devbox setup, dep upgrades, lint fixes, Android build fixes

- Add devbox.json pinning Flutter 3.35.7, Android SDK (Nix flake),
  openjdk17, just, openssl
- Add android/nix-android-sdk/ Nix flake + flake.lock + Android Studio
  config script
- Add justfile with build/get/upgrade/icons/analyze/rebuild recipes
- flutter pub upgrade --major-versions: file_picker ^11, google_fonts ^8,
  permission_handler ^12, share_plus ^12, flutter_lints ^6 (+71 transitive)
- Fix file_picker v11 API: FilePicker.platform → FilePicker.getDirectoryPath()
- Fix all 37 analyzer issues: deprecated APIs (window, WillPopScope, Share,
  SvgPicture color), async BuildContext guards, key constructors, private
  createState() return types, unused locals, print → debugPrint, etc.
- Hook _handleCommand into onSubmitted for : prefix commands
- Android: Gradle 8.3→8.11.1, AGP 8.2.2→8.9.1, KGP 1.8.22→2.2.20,
  compileSdk/targetSdk 34→36, namespace auto-derivation for library modules,
  kotlin.compiler.execution.strategy=in-process

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
randogoth 2026-06-19 17:08:29 +03:00
parent 9dbd638fa8
commit fc6c69db24
19 changed files with 1287 additions and 383 deletions

8
android/app/build.gradle Normal file → Executable file
View file

@ -6,10 +6,10 @@ plugins {
} }
android { android {
namespace = "com.example.muzzlevelocity" namespace = "vision.flux.muzzlevelocity"
compileSdk = flutter.compileSdkVersion compileSdk = flutter.compileSdkVersion
ndkVersion = flutter.ndkVersion ndkVersion = flutter.ndkVersion
compileSdkVersion 34 compileSdkVersion 36
compileOptions { compileOptions {
sourceCompatibility = JavaVersion.VERSION_1_8 sourceCompatibility = JavaVersion.VERSION_1_8
@ -22,14 +22,14 @@ android {
defaultConfig { defaultConfig {
// TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html). // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html).
applicationId = "com.example.muzzlevelocity" applicationId = "vision.flux.muzzlevelocity"
// You can update the following values to match your application needs. // You can update the following values to match your application needs.
// For more information, see: https://flutter.dev/to/review-gradle-config. // For more information, see: https://flutter.dev/to/review-gradle-config.
minSdk = flutter.minSdkVersion minSdk = flutter.minSdkVersion
targetSdk = flutter.targetSdkVersion targetSdk = flutter.targetSdkVersion
versionCode = flutter.versionCode versionCode = flutter.versionCode
versionName = flutter.versionName versionName = flutter.versionName
targetSdkVersion 34 targetSdkVersion 36
} }
buildTypes { buildTypes {

32
android/build.gradle Normal file → Executable file
View file

@ -7,10 +7,36 @@ allprojects {
rootProject.buildDir = "../build" rootProject.buildDir = "../build"
subprojects { subprojects {
afterEvaluate { project ->
if (project.hasProperty("android")) {
project.android {
compileSdkVersion 36
}
}
}
project.buildDir = "${rootProject.buildDir}/${project.name}" project.buildDir = "${rootProject.buildDir}/${project.name}"
} project.evaluationDependsOn(':app')
subprojects {
project.evaluationDependsOn(":app") plugins.withId('com.android.library') {
extensions.configure(com.android.build.gradle.LibraryExtension) { android ->
def manifestFile = android.sourceSets.main.manifest.srcFile
def packageName = null
if (manifestFile.exists()) {
def manifestContent = new XmlParser().parse(file(manifestFile))
packageName = manifestContent.@package
}
if (!android.hasProperty("namespace") || android.namespace == null || android.namespace.isEmpty()) {
if (packageName) {
println ">> Derived Namespace for: '${project.name}' to '${packageName}'"
android.namespace = packageName
} else {
def defaultNamespace = "com.example.${project.name}"
println "?? Made up Namespace for: '${project.name}' to '${defaultNamespace}'"
android.namespace = defaultNamespace
}
}
}
}
} }
tasks.register("clean", Delete) { tasks.register("clean", Delete) {

2
android/gradle.properties Normal file → Executable file
View file

@ -1,3 +1,5 @@
org.gradle.jvmargs=-Xmx4G -XX:MaxMetaspaceSize=2G -XX:+HeapDumpOnOutOfMemoryError org.gradle.jvmargs=-Xmx4G -XX:MaxMetaspaceSize=2G -XX:+HeapDumpOnOutOfMemoryError
android.useAndroidX=true android.useAndroidX=true
android.enableJetifier=true android.enableJetifier=true
kotlin.incremental=false
kotlin.compiler.execution.strategy=in-process

2
android/gradle/wrapper/gradle-wrapper.properties vendored Normal file → Executable file
View file

@ -2,4 +2,4 @@ distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-8.3-all.zip distributionUrl=https\://services.gradle.org/distributions/gradle-8.11.1-all.zip

View file

@ -0,0 +1,59 @@
#!/usr/bin/env bash
set -euo pipefail
SCRIPT_DIR="$(cd -- "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
PROJECT_DIR="$(cd -- "$SCRIPT_DIR/../.." && pwd)"
IDEA_DIR="$PROJECT_DIR/.idea"
LIBRARIES_DIR="$IDEA_DIR/libraries"
FLUTTER_SDK="$PROJECT_DIR/.devbox/nix/profile/default"
DART_SDK="$FLUTTER_SDK/bin/cache/dart-sdk"
mkdir -p "$IDEA_DIR"
if [ ! -x "$FLUTTER_SDK/bin/flutter" ]; then
echo "Flutter not found at $FLUTTER_SDK/bin/flutter. Run devbox install to download it." >&2
exit 1
fi
if [ ! -d "$DART_SDK" ]; then
echo "Dart SDK not found at $DART_SDK. Run flutter doctor to populate the cache." >&2
exit 1
fi
mkdir -p "$LIBRARIES_DIR"
cat > "$IDEA_DIR/flutter.xml" <<'EOF'
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="FlutterSdkSettings">
<option name="FLUTTER_SDK_PATH" value="$PROJECT_DIR$/.devbox/nix/profile/default" />
</component>
</project>
EOF
cat > "$IDEA_DIR/dart.xml" <<'EOF'
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="DartSdkGlobalLibSettings">
<option name="dartSdkPath" value="$PROJECT_DIR$/.devbox/nix/profile/default/bin/cache/dart-sdk" />
</component>
</project>
EOF
dart_libs=$(find "$DART_SDK/lib" -maxdepth 1 -mindepth 1 -type d -printf '%f\n' | sort)
tmp_file=$(mktemp)
{
echo '<component name="libraryTable">'
echo ' <library name="Dart SDK">'
echo ' <CLASSES>'
for lib in $dart_libs; do
printf ' <root url="file://$PROJECT_DIR$/.devbox/nix/profile/default/bin/cache/dart-sdk/lib/%s" />\n' "$lib"
done
echo ' </CLASSES>'
echo ' <JAVADOC />'
echo ' <SOURCES />'
echo ' </library>'
echo '</component>'
} > "$tmp_file"
mv "$tmp_file" "$LIBRARIES_DIR/Dart_SDK.xml"
echo "Android Studio configured. Flutter SDK: $FLUTTER_SDK"

136
android/nix-android-sdk/flake.lock generated Normal file
View file

@ -0,0 +1,136 @@
{
"nodes": {
"android-nixpkgs": {
"inputs": {
"devshell": "devshell",
"flake-utils": "flake-utils",
"nixpkgs": "nixpkgs"
},
"locked": {
"lastModified": 1768249546,
"narHash": "sha256-cpNxcSNveCBSDmocYlPrayaP8CX8ik0SKR4aNbrxOqA=",
"owner": "tadfisher",
"repo": "android-nixpkgs",
"rev": "001ffcb40e86888d38acf7b851f9a1bfac7d3a81",
"type": "github"
},
"original": {
"owner": "tadfisher",
"ref": "stable",
"repo": "android-nixpkgs",
"type": "github"
}
},
"devshell": {
"inputs": {
"nixpkgs": [
"android-nixpkgs",
"nixpkgs"
]
},
"locked": {
"lastModified": 1764011051,
"narHash": "sha256-M7SZyPZiqZUR/EiiBJnmyUbOi5oE/03tCeFrTiUZchI=",
"owner": "numtide",
"repo": "devshell",
"rev": "17ed8d9744ebe70424659b0ef74ad6d41fc87071",
"type": "github"
},
"original": {
"owner": "numtide",
"repo": "devshell",
"type": "github"
}
},
"flake-utils": {
"inputs": {
"systems": "systems"
},
"locked": {
"lastModified": 1731533236,
"narHash": "sha256-l0KFg5HjrsfsO/JpG+r7fRrqm12kzFHyUHqHCVpMMbI=",
"owner": "numtide",
"repo": "flake-utils",
"rev": "11707dc2f618dd54ca8739b309ec4fc024de578b",
"type": "github"
},
"original": {
"owner": "numtide",
"repo": "flake-utils",
"type": "github"
}
},
"flake-utils_2": {
"inputs": {
"systems": "systems_2"
},
"locked": {
"lastModified": 1731533236,
"narHash": "sha256-l0KFg5HjrsfsO/JpG+r7fRrqm12kzFHyUHqHCVpMMbI=",
"owner": "numtide",
"repo": "flake-utils",
"rev": "11707dc2f618dd54ca8739b309ec4fc024de578b",
"type": "github"
},
"original": {
"owner": "numtide",
"repo": "flake-utils",
"type": "github"
}
},
"nixpkgs": {
"locked": {
"lastModified": 1768127708,
"narHash": "sha256-1Sm77VfZh3mU0F5OqKABNLWxOuDeHIlcFjsXeeiPazs=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "ffbc9f8cbaacfb331b6017d5a5abb21a492c9a38",
"type": "github"
},
"original": {
"owner": "NixOS",
"ref": "nixos-unstable",
"repo": "nixpkgs",
"type": "github"
}
},
"root": {
"inputs": {
"android-nixpkgs": "android-nixpkgs",
"flake-utils": "flake-utils_2"
}
},
"systems": {
"locked": {
"lastModified": 1681028828,
"narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
"owner": "nix-systems",
"repo": "default",
"rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
"type": "github"
},
"original": {
"owner": "nix-systems",
"repo": "default",
"type": "github"
}
},
"systems_2": {
"locked": {
"lastModified": 1681028828,
"narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
"owner": "nix-systems",
"repo": "default",
"rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
"type": "github"
},
"original": {
"owner": "nix-systems",
"repo": "default",
"type": "github"
}
}
},
"root": "root",
"version": 7
}

View file

@ -0,0 +1,27 @@
{
description = "A Flake for the Android SDK";
inputs = {
flake-utils.url = "github:numtide/flake-utils";
android-nixpkgs.url = "github:tadfisher/android-nixpkgs/stable";
};
outputs = { self, flake-utils, android-nixpkgs }:
flake-utils.lib.eachSystem ["x86_64-linux" "x86_64-darwin" "aarch64-darwin"] (system: {
packages.android-sdk = android-nixpkgs.sdk."${system}" (sdkPkgs: with sdkPkgs; [
cmdline-tools-latest
build-tools-33-0-0
build-tools-34-0-0
build-tools-35-0-0
build-tools-36-1-0
cmake-3-22-1
platform-tools
platforms-android-33
platforms-android-34
platforms-android-35
platforms-android-36
emulator
ndk-27-0-12077973
]);
});
}

4
android/settings.gradle Normal file → Executable file
View file

@ -18,8 +18,8 @@ pluginManagement {
plugins { plugins {
id "dev.flutter.flutter-plugin-loader" version "1.0.0" id "dev.flutter.flutter-plugin-loader" version "1.0.0"
id "com.android.application" version "8.2.2" apply false id "com.android.application" version "8.9.1" apply false
id "org.jetbrains.kotlin.android" version "1.8.22" apply false id "org.jetbrains.kotlin.android" version "2.2.20" apply false
} }
include ":app" include ":app"

32
devbox.json Normal file
View file

@ -0,0 +1,32 @@
{
"$schema": "https://raw.githubusercontent.com/jetify-com/devbox/main/packages/devbox.schema.json",
"packages": [
"nixpkgs#git",
"path:./android/nix-android-sdk#android-sdk",
"nixpkgs#android-tools",
"nixpkgs#openjdk17",
"just@latest",
"openssl@latest",
"flutter@3.35.7-sdk-links"
],
"env": {
"ANDROID_SDK_ROOT": "$DEVBOX_PACKAGES_DIR/share/android-sdk",
"ANDROID_HOME": "$DEVBOX_PACKAGES_DIR/share/android-sdk"
},
"nix_config": {
"allow-unfree": "true"
},
"shell": {
"init_hook": [
"flutter --version",
"if command -v android >/dev/null 2>&1; then export ANDROID_HOME=$(command -v android | sed -E 's|(.*libexec/android-sdk).*|\\1|'); fi",
"if [ -n \"$ANDROID_HOME\" ]; then export PATH=$ANDROID_HOME/cmdline-tools/latest/bin:$PATH; fi"
],
"scripts": {
"doctor": "flutter doctor -v",
"link-android-tools": "if [ -n \"$ANDROID_HOME\" ] && [ ! -d \"$ANDROID_HOME/cmdline-tools/latest\" ] && [ -d \"$ANDROID_HOME/cmdline-tools/8.0\" ]; then ln -s \"$ANDROID_HOME/cmdline-tools/8.0\" \"$ANDROID_HOME/cmdline-tools/latest\"; fi",
"studio-config": "./android/nix-android-sdk/android-studio-devbox-config.sh",
"studio": "PROJECT_DIR=${DEVBOX_PROJECT_ROOT:-$(pwd)}; if command -v android-studio >/dev/null 2>&1; then android-studio \"$PROJECT_DIR\" >/dev/null 2>&1 &\nelif [ -x \"$HOME/.local/share/JetBrains/Toolbox/apps/android-studio/bin/studio.sh\" ]; then \"$HOME/.local/share/JetBrains/Toolbox/apps/android-studio/bin/studio.sh\" \"$PROJECT_DIR\" >/dev/null 2>&1 &\nelse echo \"Android Studio not found. Install it via JetBrains Toolbox.\" >&2; exit 1; fi"
}
}
}

277
devbox.lock Normal file
View file

@ -0,0 +1,277 @@
{
"lockfile_version": "1",
"packages": {
"flutter@3.35.7-sdk-links": {
"last_modified": "2025-11-05T16:44:39Z",
"resolved": "github:NixOS/nixpkgs/ffcdcf99d65c61956d882df249a9be53e5902ea5#flutter",
"source": "devbox-search",
"version": "3.35.7-sdk-links",
"systems": {
"aarch64-darwin": {
"outputs": [
{
"name": "out",
"path": "/nix/store/jkk73gnffwqw9mhcsk1ajiwnws9jlczm-flutter-wrapped-3.35.7-sdk-links",
"default": true
}
],
"store_path": "/nix/store/jkk73gnffwqw9mhcsk1ajiwnws9jlczm-flutter-wrapped-3.35.7-sdk-links"
},
"aarch64-linux": {
"outputs": [
{
"name": "out",
"path": "/nix/store/h5cfzbsnsjcb8kj2m3426bc7hp084fqa-flutter-wrapped-3.35.7-sdk-links",
"default": true
}
],
"store_path": "/nix/store/h5cfzbsnsjcb8kj2m3426bc7hp084fqa-flutter-wrapped-3.35.7-sdk-links"
},
"x86_64-darwin": {
"outputs": [
{
"name": "out",
"path": "/nix/store/a6ckgh19iwmswmdhxrcilf7p6zzmqr8g-flutter-wrapped-3.35.7-sdk-links",
"default": true
}
],
"store_path": "/nix/store/a6ckgh19iwmswmdhxrcilf7p6zzmqr8g-flutter-wrapped-3.35.7-sdk-links"
},
"x86_64-linux": {
"outputs": [
{
"name": "out",
"path": "/nix/store/5hdc6vzas1kp7hkc1r8j14sdplfy954z-flutter-wrapped-3.35.7-sdk-links",
"default": true
}
],
"store_path": "/nix/store/5hdc6vzas1kp7hkc1r8j14sdplfy954z-flutter-wrapped-3.35.7-sdk-links"
}
}
},
"github:NixOS/nixpkgs/nixpkgs-unstable": {
"last_modified": "2026-06-16T10:57:20Z",
"resolved": "github:NixOS/nixpkgs/3e41b24abd260e8f71dbe2f5737d24122f972158?lastModified=1781607440&narHash=sha256-rxO%2Buc%2FKFbSJp%2BpgyXRuAX6QlG9hJdnt0BXpEQRXY%2BU%3D"
},
"just@latest": {
"last_modified": "2026-05-21T08:15:18Z",
"resolved": "github:NixOS/nixpkgs/4a29d733e8a7d5b824c3d8c958a946a9867b3eb2#just",
"source": "devbox-search",
"version": "1.51.0",
"systems": {
"aarch64-darwin": {
"outputs": [
{
"name": "out",
"path": "/nix/store/18ml04rix1526kmcv5fcir6n7cb8lxyf-just-1.51.0",
"default": true
},
{
"name": "man",
"path": "/nix/store/48iac05gjz4kjpx605hcgn95an8ary9q-just-1.51.0-man",
"default": true
},
{
"name": "doc",
"path": "/nix/store/d0n7b7xd2miyja6m2nlzc2szj0gqzgxb-just-1.51.0-doc"
}
],
"store_path": "/nix/store/18ml04rix1526kmcv5fcir6n7cb8lxyf-just-1.51.0"
},
"aarch64-linux": {
"outputs": [
{
"name": "out",
"path": "/nix/store/6q8i59br2gzxnqax4dz3g1fmkwp2mfs2-just-1.51.0",
"default": true
},
{
"name": "man",
"path": "/nix/store/8ygmlmpxmggc2wqbkz1yhf7fz5nwg084-just-1.51.0-man",
"default": true
},
{
"name": "doc",
"path": "/nix/store/ppj3c78k6x3bql77f3mgrjjrxb2jjc0q-just-1.51.0-doc"
}
],
"store_path": "/nix/store/6q8i59br2gzxnqax4dz3g1fmkwp2mfs2-just-1.51.0"
},
"x86_64-darwin": {
"outputs": [
{
"name": "out",
"path": "/nix/store/7ppiil9ycr565vqgbc18x4rpgbfgcnzy-just-1.51.0",
"default": true
},
{
"name": "man",
"path": "/nix/store/144wqvh3s441y05xvzn8m16rhcqbki7d-just-1.51.0-man",
"default": true
},
{
"name": "doc",
"path": "/nix/store/x5g644hwbjdlij9w37gwgg1z1h4b6qqk-just-1.51.0-doc"
}
],
"store_path": "/nix/store/7ppiil9ycr565vqgbc18x4rpgbfgcnzy-just-1.51.0"
},
"x86_64-linux": {
"outputs": [
{
"name": "out",
"path": "/nix/store/3j32zmchv9wd60qng1mm04yj07wf04i8-just-1.51.0",
"default": true
},
{
"name": "man",
"path": "/nix/store/p04vig0h2hj7hg5vgd74n5nphlcy23l8-just-1.51.0-man",
"default": true
},
{
"name": "doc",
"path": "/nix/store/r800x8xppg70s00hw3h6x9cxpd6nh06y-just-1.51.0-doc"
}
],
"store_path": "/nix/store/3j32zmchv9wd60qng1mm04yj07wf04i8-just-1.51.0"
}
}
},
"nixpkgs#android-tools": {
"last_modified": "1970-01-01T00:00:00Z",
"resolved": "path:/nix/store/fm3z9r7r90yh8l7ai6cn6gsrp6h27ira-source?narHash=sha256-ypxFOeDz%2BCqADEQNL72haqGjvZQdBR5Vc7pyx2JDttI%3D#android-tools"
},
"nixpkgs#git": {
"last_modified": "1970-01-01T00:00:00Z",
"resolved": "path:/nix/store/fm3z9r7r90yh8l7ai6cn6gsrp6h27ira-source?narHash=sha256-ypxFOeDz%2BCqADEQNL72haqGjvZQdBR5Vc7pyx2JDttI%3D#git"
},
"nixpkgs#openjdk17": {
"last_modified": "1970-01-01T00:00:00Z",
"resolved": "path:/nix/store/fm3z9r7r90yh8l7ai6cn6gsrp6h27ira-source?narHash=sha256-ypxFOeDz%2BCqADEQNL72haqGjvZQdBR5Vc7pyx2JDttI%3D#openjdk17"
},
"openssl@latest": {
"last_modified": "2025-12-05T06:24:47Z",
"resolved": "github:NixOS/nixpkgs/42e29df35be6ef54091d3a3b4e97056ce0a98ce8#openssl",
"source": "devbox-search",
"version": "3.6.0",
"systems": {
"aarch64-darwin": {
"outputs": [
{
"name": "bin",
"path": "/nix/store/z9prisxci5h5lsk3rdknd4jzq7k9q13d-openssl-3.6.0-bin",
"default": true
},
{
"name": "man",
"path": "/nix/store/ii9mnzr3i92mgk9dkgg65739mavd0j6f-openssl-3.6.0-man",
"default": true
},
{
"name": "dev",
"path": "/nix/store/h0qgqik0mk0wn7rmm2kk3grfi1wzly74-openssl-3.6.0-dev"
},
{
"name": "doc",
"path": "/nix/store/yx3ip21fdaaxpjn5fbir02mqnaw9cm4f-openssl-3.6.0-doc"
},
{
"name": "out",
"path": "/nix/store/3z54dgks2mz3dhwddj158sdibll8xmq5-openssl-3.6.0"
}
],
"store_path": "/nix/store/z9prisxci5h5lsk3rdknd4jzq7k9q13d-openssl-3.6.0-bin"
},
"aarch64-linux": {
"outputs": [
{
"name": "bin",
"path": "/nix/store/wb6q44n9kcb5acmaa4rgqsajadx1fhhl-openssl-3.6.0-bin",
"default": true
},
{
"name": "man",
"path": "/nix/store/c9n1alb7ypzjvzd47m16fiwfczz23qs3-openssl-3.6.0-man",
"default": true
},
{
"name": "debug",
"path": "/nix/store/ci6d4k1sj4bnr892lsrqqmjiihqsk0bl-openssl-3.6.0-debug"
},
{
"name": "dev",
"path": "/nix/store/pq8b7fb3282g68pmk14mbyi20qn6chid-openssl-3.6.0-dev"
},
{
"name": "doc",
"path": "/nix/store/vaplp6w56dyz38986bgkf0pbg3r486b2-openssl-3.6.0-doc"
},
{
"name": "out",
"path": "/nix/store/nj50gkyx813dxvfmsg1q8m330hmf3h86-openssl-3.6.0"
}
],
"store_path": "/nix/store/wb6q44n9kcb5acmaa4rgqsajadx1fhhl-openssl-3.6.0-bin"
},
"x86_64-darwin": {
"outputs": [
{
"name": "bin",
"path": "/nix/store/m3xwn9n0jypwjgi256idfzs979g30j29-openssl-3.6.0-bin",
"default": true
},
{
"name": "man",
"path": "/nix/store/hw43f3y1vl7ydrd4samnwnrwqqwkpisv-openssl-3.6.0-man",
"default": true
},
{
"name": "dev",
"path": "/nix/store/dirjrfjk8jgsbdpslgb51cav6qaxn2vm-openssl-3.6.0-dev"
},
{
"name": "doc",
"path": "/nix/store/va1zhkz0nfmycvd0h239hi4w40qgaxcx-openssl-3.6.0-doc"
},
{
"name": "out",
"path": "/nix/store/q9a4wssx24xsy28w8kifdqizc01fh7sc-openssl-3.6.0"
}
],
"store_path": "/nix/store/m3xwn9n0jypwjgi256idfzs979g30j29-openssl-3.6.0-bin"
},
"x86_64-linux": {
"outputs": [
{
"name": "bin",
"path": "/nix/store/k0gl1zc7f5hk87lylxwbipb0b870bcmk-openssl-3.6.0-bin",
"default": true
},
{
"name": "man",
"path": "/nix/store/a9jdl6xq9fc98ykpvqmc9kf0b0j9y8wh-openssl-3.6.0-man",
"default": true
},
{
"name": "debug",
"path": "/nix/store/sqv8kbdgfxlr2d6nysr8c2715qpsi6f5-openssl-3.6.0-debug"
},
{
"name": "dev",
"path": "/nix/store/ydrckgnllgg8nmhdwni81h7xhcpnrlhd-openssl-3.6.0-dev"
},
{
"name": "doc",
"path": "/nix/store/cgp9ig35iwicfb9spcrgyg2m5dmlcgrv-openssl-3.6.0-doc"
},
{
"name": "out",
"path": "/nix/store/61i74yjkj9p1qphfl7018ja4sdwkipx0-openssl-3.6.0"
}
],
"store_path": "/nix/store/k0gl1zc7f5hk87lylxwbipb0b870bcmk-openssl-3.6.0-bin"
}
}
}
}
}

17
justfile Normal file
View file

@ -0,0 +1,17 @@
build:
flutter build apk --release
get:
flutter pub get
upgrade:
flutter clean && flutter pub upgrade
icons:
flutter pub run flutter_launcher_icons
analyze:
flutter analyze
rebuild:
flutter clean && flutter pub upgrade && flutter pub run flutter_launcher_icons

2
lib/codefield.dart Normal file → Executable file
View file

@ -24,7 +24,7 @@ class WrappedCodeField extends StatefulWidget {
}); });
@override @override
_WrappedCodeFieldState createState() => _WrappedCodeFieldState(); State<WrappedCodeField> createState() => _WrappedCodeFieldState();
} }
class _WrappedCodeFieldState extends State<WrappedCodeField> { class _WrappedCodeFieldState extends State<WrappedCodeField> {

8
lib/main.dart Normal file → Executable file
View file

@ -14,12 +14,14 @@ void main() async {
final license = await rootBundle.loadString('google_fonts/OFL.txt'); final license = await rootBundle.loadString('google_fonts/OFL.txt');
yield LicenseEntryWithLineBreaks(['google_fonts'], license); yield LicenseEntryWithLineBreaks(['google_fonts'], license);
}); });
runApp(MuzzleVelocityApp()); runApp(const MuzzleVelocityApp());
} }
class MuzzleVelocityApp extends StatefulWidget { class MuzzleVelocityApp extends StatefulWidget {
const MuzzleVelocityApp({super.key});
@override @override
_MuzzleVelocityAppState createState() => _MuzzleVelocityAppState(); State<MuzzleVelocityApp> createState() => _MuzzleVelocityAppState();
} }
class _MuzzleVelocityAppState extends State<MuzzleVelocityApp> { class _MuzzleVelocityAppState extends State<MuzzleVelocityApp> {
@ -31,7 +33,7 @@ class _MuzzleVelocityAppState extends State<MuzzleVelocityApp> {
super.initState(); super.initState();
// Ensure the correct theme mode is set on startup // Ensure the correct theme mode is set on startup
_themeMode = _themeMode =
WidgetsBinding.instance.window.platformBrightness == Brightness.dark WidgetsBinding.instance.platformDispatcher.platformBrightness == Brightness.dark
? ThemeMode.dark ? ThemeMode.dark
: ThemeMode.light; : ThemeMode.light;
} }

56
lib/note_editor.dart Normal file → Executable file
View file

@ -6,6 +6,7 @@ import 'package:flutter_markdown_latex/flutter_markdown_latex.dart';
import 'package:flutter_svg/svg.dart'; import 'package:flutter_svg/svg.dart';
import 'package:markdown/markdown.dart' as md; import 'package:markdown/markdown.dart' as md;
import 'package:shared_preferences/shared_preferences.dart'; import 'package:shared_preferences/shared_preferences.dart';
import 'package:share_plus/share_plus.dart';
import 'themes/day.dart'; import 'themes/day.dart';
import 'themes/night.dart'; import 'themes/night.dart';
import 'themes/markdown.dart'; import 'themes/markdown.dart';
@ -16,13 +17,15 @@ class NoteEditorScreen extends StatefulWidget {
final String? notesDirectoryPath; // Add this final String? notesDirectoryPath; // Add this
final bool isDarkMode; final bool isDarkMode;
NoteEditorScreen( const NoteEditorScreen({
{required this.note, super.key,
required this.isDarkMode, required this.note,
required this.notesDirectoryPath}); required this.isDarkMode,
required this.notesDirectoryPath,
});
@override @override
_NoteEditorScreenState createState() => _NoteEditorScreenState(); State<NoteEditorScreen> createState() => _NoteEditorScreenState();
} }
class _NoteEditorScreenState extends State<NoteEditorScreen> { class _NoteEditorScreenState extends State<NoteEditorScreen> {
@ -59,7 +62,7 @@ class _NoteEditorScreenState extends State<NoteEditorScreen> {
try { try {
_initialContent = await widget.note.readAsString(); _initialContent = await widget.note.readAsString();
} catch (e) { } catch (e) {
print("❌ Failed to read file: ${widget.note.path}"); debugPrint("❌ Failed to read file: ${widget.note.path}");
_initialContent = ""; _initialContent = "";
} }
@ -86,9 +89,18 @@ class _NoteEditorScreenState extends State<NoteEditorScreen> {
await widget.note.writeAsString(_controller.text); await widget.note.writeAsString(_controller.text);
_initialContent = _controller.text; // Update initial state _initialContent = _controller.text; // Update initial state
print("✅ Note saved successfully"); debugPrint("✅ Note saved successfully");
} catch (e) { } catch (e) {
print("❌ Error saving note: ${widget.note.path}"); debugPrint("❌ Error saving note: ${widget.note.path}");
}
}
void _shareNote() {
if (_controller.text.isNotEmpty) {
SharePlus.instance.share(ShareParams(
text: _controller.text,
subject: widget.note.uri.pathSegments.last,
));
} }
} }
@ -108,7 +120,7 @@ class _NoteEditorScreenState extends State<NoteEditorScreen> {
TextButton( TextButton(
onPressed: () async { onPressed: () async {
await _saveNote(); await _saveNote();
Navigator.of(context).pop(true); // Save and exit if (context.mounted) Navigator.of(context).pop(true);
}, },
child: Text("Save"), child: Text("Save"),
), ),
@ -137,8 +149,13 @@ class _NoteEditorScreenState extends State<NoteEditorScreen> {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return WillPopScope( return PopScope(
onWillPop: _onWillPop, canPop: false,
onPopInvokedWithResult: (bool didPop, Object? result) async {
if (didPop) return;
final bool shouldPop = await _onWillPop();
if (shouldPop && context.mounted) Navigator.of(context).pop();
},
child: Scaffold( child: Scaffold(
appBar: AppBar( appBar: AppBar(
title: Text(widget.note.uri.pathSegments.last.replaceAll('.md', '')), title: Text(widget.note.uri.pathSegments.last.replaceAll('.md', '')),
@ -146,7 +163,7 @@ class _NoteEditorScreenState extends State<NoteEditorScreen> {
icon: Icon(Icons.arrow_back), icon: Icon(Icons.arrow_back),
onPressed: () async { onPressed: () async {
if (await _onWillPop()) { if (await _onWillPop()) {
Navigator.pop(context); if (context.mounted) Navigator.pop(context);
} }
}, },
), ),
@ -157,10 +174,13 @@ class _NoteEditorScreenState extends State<NoteEditorScreen> {
icon: SvgPicture.asset( icon: SvgPicture.asset(
"assets/blaster.svg", "assets/blaster.svg",
width: 30, width: 30,
color: Colors.orange, colorFilter: const ColorFilter.mode(Colors.orange, BlendMode.srcIn),
), ),
onSelected: (String value) { onSelected: (String value) {
switch (value) { switch (value) {
case 'Share': // New case for sharing
_shareNote();
break;
case 'Save': case 'Save':
_saveNote(); _saveNote();
break; break;
@ -175,6 +195,14 @@ class _NoteEditorScreenState extends State<NoteEditorScreen> {
} }
}, },
itemBuilder: (BuildContext context) => [ itemBuilder: (BuildContext context) => [
PopupMenuItem<String>( // Share button
value: 'Share',
child: ListTile(
leading: Icon(Icons.share_outlined),
title: Text("Share"),
),
),
PopupMenuDivider(),
PopupMenuItem<String>( PopupMenuItem<String>(
value: 'Save', value: 'Save',
child: ListTile( child: ListTile(
@ -193,6 +221,7 @@ class _NoteEditorScreenState extends State<NoteEditorScreen> {
: "Enable Autosave"), : "Enable Autosave"),
), ),
), ),
PopupMenuDivider(),
PopupMenuItem<String>( PopupMenuItem<String>(
enabled: false, enabled: false,
child: Column( child: Column(
@ -219,6 +248,7 @@ class _NoteEditorScreenState extends State<NoteEditorScreen> {
], ],
), ),
), ),
PopupMenuDivider(),
PopupMenuItem<String>( PopupMenuItem<String>(
value: 'Toggle Preview', value: 'Toggle Preview',
child: ListTile( child: ListTile(

375
lib/note_list.dart Normal file → Executable file
View file

@ -19,7 +19,8 @@ class NoteListScreen extends StatefulWidget {
final bool isDarkMode; final bool isDarkMode;
final bool showTags; final bool showTags;
NoteListScreen({ const NoteListScreen({
super.key,
required this.toggleTheme, required this.toggleTheme,
required this.toggleTags, required this.toggleTags,
required this.isDarkMode, required this.isDarkMode,
@ -27,11 +28,12 @@ class NoteListScreen extends StatefulWidget {
}); });
@override @override
_NoteListScreenState createState() => _NoteListScreenState(); State<NoteListScreen> createState() => _NoteListScreenState();
} }
class _NoteListScreenState extends State<NoteListScreen> { class _NoteListScreenState extends State<NoteListScreen> {
TextEditingController searchController = TextEditingController(); TextEditingController searchController = TextEditingController();
final FocusNode searchFocusNode = FocusNode();
List<File> notes = []; List<File> notes = [];
List<File> filteredNotes = []; List<File> filteredNotes = [];
List<File> _visibleNotes = []; List<File> _visibleNotes = [];
@ -52,6 +54,9 @@ class _NoteListScreenState extends State<NoteListScreen> {
searchController.addListener(() { searchController.addListener(() {
_debouncedFilterNotes(); _debouncedFilterNotes();
}); });
WidgetsBinding.instance.addPostFrameCallback((_) {
FocusScope.of(context).requestFocus(searchFocusNode);
});
} }
void _debouncedFilterNotes() { void _debouncedFilterNotes() {
@ -95,16 +100,16 @@ class _NoteListScreenState extends State<NoteListScreen> {
Future<void> _requestStoragePermission() async { Future<void> _requestStoragePermission() async {
if (Platform.isAndroid) { if (Platform.isAndroid) {
if (await Permission.storage.request().isGranted) { if (await Permission.storage.request().isGranted) {
print("✅ Basic storage permission granted."); debugPrint("✅ Basic storage permission granted.");
return; return;
} }
if (await Permission.manageExternalStorage.request().isGranted) { if (await Permission.manageExternalStorage.request().isGranted) {
print("✅ Full file access granted."); debugPrint("✅ Full file access granted.");
return; return;
} }
print("❌ Storage permission denied. Opening settings..."); debugPrint("❌ Storage permission denied. Opening settings...");
await openAppSettings(); // Open settings if denied await openAppSettings(); // Open settings if denied
} }
} }
@ -116,12 +121,46 @@ class _NoteListScreenState extends State<NoteListScreen> {
setState(() { setState(() {
defaultDir = dir.path; defaultDir = dir.path;
_useExternalEditor = prefs.getBool('use_external_editor') ?? false; _useExternalEditor = prefs.getBool('use_external_editor') ?? false;
_includeSubdirectories = prefs.getBool('include_subdirectories') ?? true; // Load setting _includeSubdirectories = prefs.getBool('include_subdirectories') ?? true;
}); });
notesDirectoryPath = prefs.getString('notes_directory') ?? defaultDir;
// 🚀 Check if it's the first start OR if the directory is empty
final directory = Directory(notesDirectoryPath!);
if (prefs.getBool('initialized') == null ||
!directory.listSync().any((entity) => entity is File && entity.path.endsWith('.md'))) {
await _createDefaultNotes();
await prefs.setBool('initialized', true);
}
await _loadNotes(); await _loadNotes();
} }
Future<void> _createDefaultNotes() async {
final quickStartNote = File(path.join(notesDirectoryPath!, "QuickStart.md"));
if (!quickStartNote.existsSync()) {
quickStartNote.writeAsStringSync("""
# Quick Start Guide
Welcome to *Muzzle Velocity*.
This is your fast and minimal note-taking app.
1. Create Notes quickly: just type a title in the search bar and press enter.
2. 🔍 Type keywords to filter notes instantly.
3. 💻 Type commands like :help to get more information.
4. 🏷 Use hashtags like #quickstart, context tags like @help, or project tags like +muzzle in your notes for categorization.
5. 🔫 Tap the blaster at the top right for more settings or to clear the search field.
*Muzzle Velocity* is built for speed and simplicity! 🚀
Happy note taking!
""");
}
}
void _toggleIncludeSubdirectories(bool value) { void _toggleIncludeSubdirectories(bool value) {
setState(() { setState(() {
_includeSubdirectories = value; _includeSubdirectories = value;
@ -157,7 +196,7 @@ class _NoteListScreenState extends State<NoteListScreen> {
setState(() { setState(() {
notesDirectoryPath = defaultDir; // Reset to default directory notesDirectoryPath = defaultDir; // Reset to default directory
}); });
Navigator.pop(context); // Close dialog if (context.mounted) Navigator.pop(context);
_loadNotes(); // Reload notes from the default directory _loadNotes(); // Reload notes from the default directory
}, },
child: Text("Use Default"), child: Text("Use Default"),
@ -165,7 +204,7 @@ class _NoteListScreenState extends State<NoteListScreen> {
TextButton( TextButton(
onPressed: () async { onPressed: () async {
await _requestStoragePermission(); await _requestStoragePermission();
Navigator.pop(context); // Close the current dialog if (context.mounted) Navigator.pop(context);
await _selectNotesDirectory(); // Allow user to pick a folder await _selectNotesDirectory(); // Allow user to pick a folder
}, },
child: Text("Choose Folder"), child: Text("Choose Folder"),
@ -177,7 +216,7 @@ class _NoteListScreenState extends State<NoteListScreen> {
} }
Future<void> _selectNotesDirectory() async { Future<void> _selectNotesDirectory() async {
String? selectedDirectory = await FilePicker.platform.getDirectoryPath(); String? selectedDirectory = await FilePicker.getDirectoryPath();
if (selectedDirectory != null) { if (selectedDirectory != null) {
final prefs = await SharedPreferences.getInstance(); final prefs = await SharedPreferences.getInstance();
await prefs.setString( await prefs.setString(
@ -206,7 +245,7 @@ class _NoteListScreenState extends State<NoteListScreen> {
final entries = dir.listSync(recursive: _includeSubdirectories); final entries = dir.listSync(recursive: _includeSubdirectories);
for (var entry in entries) { for (var entry in entries) {
if (entry is File && entry.path.endsWith('.md')) { if (entry is File && _isValidNoteFile(entry)) {
if (path.basename(path.dirname(entry.path)) == "trash") { if (path.basename(path.dirname(entry.path)) == "trash") {
continue; continue;
@ -268,6 +307,11 @@ class _NoteListScreenState extends State<NoteListScreen> {
return sortedTags.toSet(); // Convert back to a set after sorting return sortedTags.toSet(); // Convert back to a set after sorting
} }
bool _isValidNoteFile(File file) {
final validExtensions = ['.md', '.txt', '.markdown'];
return validExtensions.any((ext) => file.path.toLowerCase().endsWith(ext));
}
void _filterNotes() { void _filterNotes() {
final query = searchController.text.trim().toLowerCase(); final query = searchController.text.trim().toLowerCase();
@ -351,6 +395,15 @@ class _NoteListScreenState extends State<NoteListScreen> {
String notePath = title.trim(); String notePath = title.trim();
String? subfolder; String? subfolder;
String safeTitle; String safeTitle;
String extension = '.md'; // Default extension
// Check if user specified an extension manually
if (title.contains('.')) {
final ext = path.extension(title);
if (['.txt', '.markdown', '.md'].contains(ext)) {
extension = ext;
}
}
if (notePath.startsWith('/')) { if (notePath.startsWith('/')) {
final parts = notePath.split('/'); final parts = notePath.split('/');
@ -358,21 +411,21 @@ class _NoteListScreenState extends State<NoteListScreen> {
if (parts.length > 1) { if (parts.length > 1) {
subfolder = parts.sublist(0, parts.length - 1).join('/'); subfolder = parts.sublist(0, parts.length - 1).join('/');
} }
safeTitle = _sanitizeFilename(parts.last); safeTitle = _sanitizeFilename(parts.last.replaceAll(extension, '')); // Remove extension from input
} else { } else {
safeTitle = _sanitizeFilename(title); safeTitle = _sanitizeFilename(title.replaceAll(extension, ''));
} }
// Construct the final file path // Construct the final file path
String fullPath = subfolder != null String fullPath = subfolder != null
? path.join(notesDirectoryPath!, subfolder, '$safeTitle.md') ? path.join(notesDirectoryPath!, subfolder, '$safeTitle$extension')
: path.join(notesDirectoryPath!, '$safeTitle.md'); : path.join(notesDirectoryPath!, '$safeTitle$extension');
final newNote = File(fullPath); final newNote = File(fullPath);
// Prevent duplicate note creation // Prevent duplicate note creation
if (notes.any((note) => note.path == newNote.path)) { if (notes.any((note) => note.path == newNote.path)) {
print("❌ Note already exists at: $fullPath"); debugPrint("❌ Note already exists at: $fullPath");
return; return;
} }
@ -416,7 +469,7 @@ class _NoteListScreenState extends State<NoteListScreen> {
if (notePath.startsWith('/')) { if (notePath.startsWith('/')) {
final parts = notePath.split('/'); final parts = notePath.split('/');
parts.removeWhere((element) => element.isEmpty); // Remove empty elements parts.removeWhere((element) => element.isEmpty);
if (parts.length > 1) { if (parts.length > 1) {
subfolder = parts.sublist(0, parts.length - 1).join('/'); subfolder = parts.sublist(0, parts.length - 1).join('/');
} }
@ -425,12 +478,18 @@ class _NoteListScreenState extends State<NoteListScreen> {
safeTitle = _sanitizeFilename(title); safeTitle = _sanitizeFilename(title);
} }
// Construct the expected file path // Allow multiple file extensions
String fullPath = subfolder != null for (var ext in ['.md', '.txt', '.markdown']) {
? path.join(notesDirectoryPath!, subfolder, '$safeTitle.md') String fullPath = subfolder != null
: path.join(notesDirectoryPath!, '$safeTitle.md'); ? path.join(notesDirectoryPath!, subfolder, '$safeTitle$ext')
: path.join(notesDirectoryPath!, '$safeTitle$ext');
return !notes.any((note) => note.path == fullPath); if (notes.any((note) => note.path == fullPath)) {
return false; // A note with this name already exists
}
}
return true;
} }
String _sanitizeFilename(String title) { String _sanitizeFilename(String title) {
@ -508,7 +567,7 @@ class _NoteListScreenState extends State<NoteListScreen> {
_deleteEmptyParentFolders(folder.parent); // Recursively check parent _deleteEmptyParentFolders(folder.parent); // Recursively check parent
} }
} catch (e) { } catch (e) {
print("❌ Error deleting empty folder: $e"); debugPrint("❌ Error deleting empty folder: $e");
} }
} }
@ -577,13 +636,14 @@ class _NoteListScreenState extends State<NoteListScreen> {
break; break;
case ':help': case ':help':
_showInfoPage(context, "Help", helpContent); _showInfoPage(context, "Help", helpContent);
break;
default: default:
return; // Do nothing for unrecognized commands return; // Do nothing for unrecognized commands
} }
searchController.clear(); searchController.clear();
} }
_showInfoPage(BuildContext context, String title, String content) { void _showInfoPage(BuildContext context, String title, String content) {
Navigator.push( Navigator.push(
context, context,
MaterialPageRoute( MaterialPageRoute(
@ -603,6 +663,7 @@ class _NoteListScreenState extends State<NoteListScreen> {
title: Padding( title: Padding(
padding: EdgeInsets.symmetric(horizontal: 10), padding: EdgeInsets.symmetric(horizontal: 10),
child: TextField( child: TextField(
focusNode: searchFocusNode,
enableInteractiveSelection: true, enableInteractiveSelection: true,
autocorrect: false, autocorrect: false,
textInputAction: TextInputAction.done, textInputAction: TextInputAction.done,
@ -615,10 +676,11 @@ class _NoteListScreenState extends State<NoteListScreen> {
style: GoogleFonts.ibmPlexMono(color: Colors.grey[300]), style: GoogleFonts.ibmPlexMono(color: Colors.grey[300]),
onSubmitted: (text) { onSubmitted: (text) {
final trimmedText = text.trim(); final trimmedText = text.trim();
if (trimmedText.isNotEmpty && _isNewNote(trimmedText)) { if (trimmedText.startsWith(':')) {
_handleCommand(trimmedText);
} else if (trimmedText.isNotEmpty && _isNewNote(trimmedText)) {
_createNewNote(trimmedText); _createNewNote(trimmedText);
searchController searchController.clear();
.clear(); // Clears the search field after creation
} }
}, },
), ),
@ -626,137 +688,145 @@ class _NoteListScreenState extends State<NoteListScreen> {
actions: [ actions: [
Padding( Padding(
padding: EdgeInsets.symmetric(horizontal: 15), padding: EdgeInsets.symmetric(horizontal: 15),
child: PopupMenuButton<String>( child: GestureDetector(
icon: SvgPicture.asset( onTap: () {
"assets/blaster.svg", if (searchController.text.isNotEmpty) {
width: 30, searchController.clear();
color: Colors.orange, }
),
onSelected: (String value) {
switch (value) {
case 'Toggle Tags':
widget.toggleTags();
break;
case 'Toggle Theme':
setState(() {
widget.toggleTheme(!widget.isDarkMode);
});
break;
case 'External Editor':
_toggleExternalEditor(!_useExternalEditor);
break;
case 'Select Folder':
_showDirectoryChoiceDialog(
notesDirectoryPath ?? ''); // Re-trigger popup
break;
case 'Empty Trash':
_confirmEmptyTrash();
break;
case 'Help':
_showInfoPage(context, "Help", helpContent);
break;
case 'About':
_showInfoPage(context, "About", aboutContent);
break;
}
}, },
itemBuilder: (BuildContext context) => [ child: PopupMenuButton<String>(
PopupMenuItem<String>( enabled: searchController.text.isEmpty,
value: 'Toggle Tags', icon: SvgPicture.asset(
child: ListTile( "assets/blaster.svg",
leading: width: 30,
Icon(widget.showTags ? Icons.short_text : Icons.tag), colorFilter: const ColorFilter.mode(Colors.orange, BlendMode.srcIn),
title: Text(widget.showTags ? 'Hide Tags' : 'Show Tags'),
),
), ),
PopupMenuItem<String>( onSelected: (String value) {
value: 'Toggle Theme', switch (value) {
child: ListTile( case 'Toggle Tags':
leading: Icon( widget.toggleTags();
Theme.of(context).brightness == Brightness.dark break;
? Icons.light_mode case 'Toggle Theme':
: Icons.dark_mode, setState(() {
), widget.toggleTheme(!widget.isDarkMode);
title: Text( });
Theme.of(context).brightness == Brightness.dark break;
? 'Switch to Light Mode' case 'External Editor':
: 'Switch to Dark Mode', _toggleExternalEditor(!_useExternalEditor);
break;
case 'Select Folder':
_showDirectoryChoiceDialog(
notesDirectoryPath ?? ''); // Re-trigger popup
break;
case 'Empty Trash':
_confirmEmptyTrash();
break;
case 'Help':
_showInfoPage(context, "Help", helpContent);
break;
case 'About':
_showInfoPage(context, "About", aboutContent);
break;
}
},
itemBuilder: (BuildContext context) => [
PopupMenuItem<String>(
value: 'Toggle Tags',
child: ListTile(
leading:
Icon(widget.showTags ? Icons.short_text : Icons.tag),
title: Text(widget.showTags ? 'Hide Tags' : 'Show Tags'),
), ),
), ),
), PopupMenuItem<String>(
PopupMenuItem<String>( value: 'Toggle Theme',
value: 'Include Subdirectories', child: ListTile(
child: ListTile( leading: Icon(
leading: Icon(_includeSubdirectories ? Icons.file_copy_outlined : Icons.folder_copy_outlined), Theme.of(context).brightness == Brightness.dark
title: Text(_includeSubdirectories ? 'Exclude Subdirectories' : 'Include Subdirectories'), ? Icons.light_mode
onTap: () { : Icons.dark_mode,
_toggleIncludeSubdirectories(!_includeSubdirectories); ),
Navigator.pop(context); // Close menu after toggle title: Text(
}, Theme.of(context).brightness == Brightness.dark
), ? 'Switch to Light Mode'
), : 'Switch to Dark Mode',
PopupMenuItem<String>( ),
value: 'Include File Content',
child: ListTile(
leading: Icon(
_includeFileContent ? Icons.highlight_off : Icons.file_open_outlined,
),
title: Text(
_includeFileContent ? 'Exclude File Content' : 'Include File Content',
),
onTap: () {
_toggleIncludeFileContent(!_includeFileContent);
Navigator.pop(context);
},
),
),
PopupMenuItem<String>(
value: 'External Editor',
child: ListTile(
leading: Icon(
_useExternalEditor
? Icons.open_in_new_off
: Icons.open_in_new,
),
title: Text(
!_useExternalEditor
? 'Use External Editor'
: 'Use Internal Editor',
), ),
), ),
), PopupMenuItem<String>(
PopupMenuItem<String>( value: 'Include Subdirectories',
value: 'Select Folder', child: ListTile(
child: ListTile( leading: Icon(_includeSubdirectories ? Icons.file_copy_outlined : Icons.folder_copy_outlined),
leading: Icon(Icons.folder_shared_outlined), title: Text(_includeSubdirectories ? 'Exclude Subdirectories' : 'Search Subdirectories'),
title: Text('Set Notes Directory'), onTap: () {
_toggleIncludeSubdirectories(!_includeSubdirectories);
Navigator.pop(context); // Close menu after toggle
},
),
), ),
), PopupMenuItem<String>(
PopupMenuDivider(), value: 'Include File Content',
PopupMenuItem<String>( child: ListTile(
value: 'Empty Trash', leading: Icon(
child: ListTile( _includeFileContent ? Icons.highlight_off : Icons.file_open_outlined,
leading: Icon(Icons.delete, color: Colors.redAccent), ),
title: Text('Empty Trash', title: Text(
style: TextStyle(color: Colors.redAccent)), _includeFileContent ? 'Exclude File Content' : 'Search File Content',
),
onTap: () {
_toggleIncludeFileContent(!_includeFileContent);
Navigator.pop(context);
},
),
), ),
), PopupMenuItem<String>(
PopupMenuDivider(), value: 'External Editor',
PopupMenuItem<String>( child: ListTile(
value: 'Help', leading: Icon(
child: ListTile( _useExternalEditor
leading: Icon(Icons.help_outline), ? Icons.open_in_new_off
title: Text('Help'), : Icons.open_in_new,
),
title: Text(
!_useExternalEditor
? 'Use External Editor'
: 'Use Internal Editor',
),
),
), ),
), PopupMenuItem<String>(
PopupMenuItem<String>( value: 'Select Folder',
value: 'About', child: ListTile(
child: ListTile( leading: Icon(Icons.folder_shared_outlined),
leading: Icon(Icons.info_outline), title: Text('Set Notes Directory'),
title: Text('About'), ),
), ),
), PopupMenuDivider(),
], PopupMenuItem<String>(
value: 'Empty Trash',
child: ListTile(
leading: Icon(Icons.delete, color: Colors.redAccent),
title: Text('Empty Trash',
style: TextStyle(color: Colors.redAccent)),
),
),
PopupMenuDivider(),
PopupMenuItem<String>(
value: 'Help',
child: ListTile(
leading: Icon(Icons.help_outline),
title: Text('Help'),
),
),
PopupMenuItem<String>(
value: 'About',
child: ListTile(
leading: Icon(Icons.info_outline),
title: Text('About'),
),
),
],
),
), ),
), ),
], ],
@ -783,11 +853,6 @@ class _NoteListScreenState extends State<NoteListScreen> {
} }
final noteFile = filteredNotes[index]; final noteFile = filteredNotes[index];
final noteContent = _includeFileContent ? noteFile.readAsStringSync() : ""; // Read content only if needed
final tagSpans = _formatTags(noteContent).isNotEmpty
? _formatTags(noteContent)
: [TextSpan(text: '')];
return Dismissible( return Dismissible(
key: Key(noteFile.path), key: Key(noteFile.path),
direction: DismissDirection.endToStart, direction: DismissDirection.endToStart,
@ -836,7 +901,7 @@ class _NoteListScreenState extends State<NoteListScreen> {
if (result.stdout.toString().trim().isNotEmpty) { if (result.stdout.toString().trim().isNotEmpty) {
await Process.run('xdg-open', [noteFile.path]); await Process.run('xdg-open', [noteFile.path]);
} else { } else {
print("❌ `xdg-open` is not available."); debugPrint("❌ `xdg-open` is not available.");
} }
} else if (Platform.isAndroid) { } else if (Platform.isAndroid) {
await _requestStoragePermission(); await _requestStoragePermission();
@ -844,10 +909,10 @@ class _NoteListScreenState extends State<NoteListScreen> {
noteFile.path, noteFile.path,
type: "text/markdown", type: "text/markdown",
); );
print("✅ OpenFilex result: ${result.type}, message: ${result.message}"); debugPrint("✅ OpenFilex result: ${result.type}, message: ${result.message}");
} }
} catch (e) { } catch (e) {
print("❌ Failed to open external editor: $e"); debugPrint("❌ Failed to open external editor: $e");
} }
} else { } else {
await Navigator.push( await Navigator.push(

3
lib/read_only.dart Normal file → Executable file
View file

@ -10,7 +10,8 @@ class ReadOnlyPage extends StatelessWidget {
final String content; final String content;
final bool isDarkMode; final bool isDarkMode;
ReadOnlyPage({ const ReadOnlyPage({
super.key,
required this.title, required this.title,
required this.content, required this.content,
required this.isDarkMode, required this.isDarkMode,

273
lib/themes/markdown.dart Normal file → Executable file
View file

@ -1,61 +1,218 @@
import 'package:highlight/highlight.dart'; import 'package:highlight/highlight.dart';
final markdown = Mode(refs: {}, aliases: [ final markdown = Mode(
"md", refs: {},
"mkdown", aliases: [
"mkd" "md",
], contains: [ "mkdown",
Mode(className: "section", variants: [ "mkd"
Mode(begin: "^#\\s{1,6}", end: "\$"), ],
Mode(begin: "^.+?\\n[=-]{2,}\$") contains: [
]), // Headers (with distinct classes for each level)
Mode(begin: "<", end: ">", subLanguage: ["xml"], relevance: 0), Mode(
Mode(className: "bullet", begin: "^\\s*([*+-]|(\\d+\\.))\\s+"), className: "header",
Mode(className: "strong", begin: "[*_]{2}.+?[*_]{2}"), variants: [
// Level 1 header (#)
Mode(
className: "header-h1",
begin: "^#\\s+",
end: "\$"
),
// Level 2 header (##)
Mode(
className: "header-h2",
begin: "^##\\s+",
end: "\$"
),
// Level 3 header (###)
Mode(
className: "header-h3",
begin: "^###\\s+",
end: "\$"
),
// Level 4 header (####)
Mode(
className: "header-h4",
begin: "^####\\s+",
end: "\$"
),
// Level 5 header (#####)
Mode(
className: "header-h5",
begin: "^#####\\s+",
end: "\$"
),
// Level 6 header (######)
Mode(
className: "header-h6",
begin: "^######\\s+",
end: "\$"
),
// Underlined headers (=== and ---)
Mode(
className: "header-underline",
begin: "^.+?\\n[=-]{2,}\$"
)
]
),
// HTML tags
Mode(
begin: "<",
end: ">",
subLanguage: ["xml"],
relevance: 0
),
// Lists
Mode(
className: "list",
begin: "^\\s*([*+-]|(\\d+\\.))\\s+"
),
// Bold text
Mode(
className: "bold",
begin: "[*_]{2}.+?[*_]{2}"
),
// Italic text
Mode(
className: "italic",
variants: [
Mode(begin: "\\*.+?\\*"),
Mode(begin: "_.+?_", relevance: 0)
]
),
// Blockquotes
Mode(
className: "blockquote",
begin: "^>\\s+",
end: "\$"
),
// Code blocks and inline code
Mode(
className: "code",
variants: [
Mode(begin: "^```\\w*\\s*\$", end: "^```[ ]*\$"), // Fenced code blocks
Mode(begin: "`.+?`"), // Inline code
Mode(begin: "^( {4}|\\t)", end: "\$", relevance: 0) // Indented code blocks
]
),
// Horizontal rules
Mode(
className: "horizontal-rule",
begin: "^[-\\*]{3,}",
end: "\$"
),
// Links and images
Mode(
begin: "\\[.+?\\][\\(\\[].*?[\\)\\]]",
returnBegin: true,
contains: [
Mode(
className: "link-text",
begin: "\\[",
end: "\\]",
excludeBegin: true,
returnEnd: true,
relevance: 0
),
Mode(
className: "link-url",
begin: "\\]\\(",
end: "\\)",
excludeBegin: true,
excludeEnd: true
),
Mode(
className: "link-reference",
begin: "\\]\\[",
end: "\\]",
excludeBegin: true,
excludeEnd: true
)
],
relevance: 10
),
// Reference-style links
Mode(
begin: "^\\[[^\\n]+\\]:",
returnBegin: true,
contains: [
Mode(
className: "link-reference",
begin: "\\[",
end: "\\]",
excludeBegin: true,
excludeEnd: true
),
Mode(
className: "link-url",
begin: ":\\s*",
end: "\$",
excludeBegin: true
)
]
),
// Strikethrough text
Mode(
className: "strikethrough",
begin: "~~.+?~~"
),
// Tables
Mode(
className: "table",
begin: "^\\|.+?\\|",
end: "\$",
contains: [
Mode(
className: "table-header",
begin: "^\\|",
end: "\\|",
contains: [
Mode(
className: "table-cell",
begin: "[^|]+",
end: "\$"
)
]
),
Mode(
className: "table-row",
begin: "^\\|",
end: "\\|",
contains: [
Mode(
className: "table-cell",
begin: "[^|]+",
end: "\$"
)
]
)
]
),
// Task lists
Mode(
className: "task-list",
begin: "^\\s*-\\s*\\[\\s*[xX ]?\\s*\\]\\s+"
),
Mode( Mode(
className: "emphasis", className: "link-reference",
variants: [Mode(begin: "\\*.+?\\*"), Mode(begin: "_.+?_", relevance: 0)]), begin: "\\[",
Mode(className: "quote", begin: "^>\\s+", end: "\$"), end: "\\]",
Mode(className: "code", variants: [ excludeBegin: true,
Mode(begin: "^```\\w*\\s*\$", end: "^```[ ]*\$"), excludeEnd: true
Mode(begin: "`.+?`"), ),
Mode(begin: "^( {4}|\\t)", end: "\$", relevance: 0)
]),
Mode(begin: "^[-\\*]{3,}", end: "\$"),
Mode(
begin: "\\[.+?\\][\\(\\[].*?[\\)\\]]",
returnBegin: true,
contains: [
Mode(
className: "string",
begin: "\\[",
end: "\\]",
excludeBegin: true,
returnEnd: true,
relevance: 0),
Mode(
className: "link",
begin: "\\]\\(",
end: "\\)",
excludeBegin: true,
excludeEnd: true),
Mode(
className: "symbol",
begin: "\\]\\[",
end: "\\]",
excludeBegin: true,
excludeEnd: true)
],
relevance: 10),
Mode(begin: "^\\[[^\\n]+\\]:", returnBegin: true, contains: [
Mode(
className: "symbol",
begin: "\\[",
end: "\\]",
excludeBegin: true,
excludeEnd: true),
Mode(className: "link", begin: ":\\s*", end: "\$", excludeBegin: true)
]),
// Custom Tag Highlighting // Custom Tag Highlighting
Mode( Mode(
@ -71,11 +228,11 @@ final markdown = Mode(refs: {}, aliases: [
begin: "(?<=\\s|^)@[a-zA-Z0-9_]+", begin: "(?<=\\s|^)@[a-zA-Z0-9_]+",
relevance: 10), // Yellow relevance: 10), // Yellow
Mode( Mode(
className: "keyword", className: "command",
begin: "(?<=\\s|^):[a-zA-Z0-9_]+", begin: "(?<=\\s|^):[a-zA-Z0-9_]+",
relevance: 10), relevance: 10),
Mode( Mode(
className: "variable", className: "link-url",
begin: "(?<=\\s|^)\/[a-zA-Z0-9_\/]+", begin: "(?<=\\s|^)/[a-zA-Z0-9_/]+",
relevance: 10), // Yellow relevance: 10), // Yellow
]); ]);

348
pubspec.lock Normal file → Executable file
View file

@ -5,26 +5,26 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: archive name: archive
sha256: "528579c7e4579719f04b21eeeeddfd73a18b31dabc22766893b7d1be7f49b967" sha256: a96e8b390886ee8abb49b7bd3ac8df6f451c621619f52a26e815fdcf568959ff
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "4.0.3" version: "4.0.9"
args: args:
dependency: transitive dependency: transitive
description: description:
name: args name: args
sha256: bf9f5caeea8d8fe6721a9c358dd8a5c1947b27f1cfaa18b39c301273594919e6 sha256: d0481093c50b1da8910eb0bb301626d4d8eb7284aa739614d2b394ee09e3ea04
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "2.6.0" version: "2.7.0"
async: async:
dependency: transitive dependency: transitive
description: description:
name: async name: async
sha256: "947bfcf187f74dbc5e146c9eb9c0f10c9f8b30743e341481c1e2ed3ecc18c20c" sha256: e2eb0491ba5ddb6177742d2da23904574082139b07c1e33b8503b9f46f3e1a37
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "2.11.0" version: "2.13.1"
autotrie: autotrie:
dependency: transitive dependency: transitive
description: description:
@ -37,18 +37,18 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: boolean_selector name: boolean_selector
sha256: "6cfb5af12253eaf2b368f07bacc5a80d1301a071c73360d746b7f2e32d762c66" sha256: "8aab1771e1243a5063b8b0ff68042d67334e3feab9e95b9490f9a6ebf73b42ea"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "2.1.1" version: "2.1.2"
characters: characters:
dependency: transitive dependency: transitive
description: description:
name: characters name: characters
sha256: "04a925763edad70e8443c99234dc3328f442e811f1d8fd1a72f1c8ad0f69a605" sha256: f71061c654a3380576a52b451dd5532377954cf9dbd272a78fc8479606670803
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "1.3.0" version: "1.4.0"
charcode: charcode:
dependency: transitive dependency: transitive
description: description:
@ -61,10 +61,10 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: checked_yaml name: checked_yaml
sha256: feb6bed21949061731a7a75fc5d2aa727cf160b91af9a3e464c5e3a32e28b5ff sha256: "959525d3162f249993882720d52b7e0c833978df229be20702b33d48d91de70f"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "2.0.3" version: "2.0.4"
cli_util: cli_util:
dependency: transitive dependency: transitive
description: description:
@ -77,66 +77,74 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: clock name: clock
sha256: cb6d7f03e1de671e34607e909a7213e31d7752be4fb66a86d29fe1eb14bfb5cf sha256: fddb70d9b5277016c77a80201021d40a2247104d9f4aa7bab7157b7e3f05b84b
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "1.1.1" version: "1.1.2"
collection: collection:
dependency: transitive dependency: transitive
description: description:
name: collection name: collection
sha256: a1ace0a119f20aabc852d165077c036cd864315bd99b7eaa10a60100341941bf sha256: "2f5709ae4d3d59dd8f7cd309b4e023046b57d8a6c82130785d2b0e5868084e76"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "1.19.0" version: "1.19.1"
cross_file: cross_file:
dependency: transitive dependency: transitive
description: description:
name: cross_file name: cross_file
sha256: "7caf6a750a0c04effbb52a676dce9a4a592e10ad35c34d6d2d0e4811160d5670" sha256: "28bb3ae56f117b5aec029d702a90f57d285cd975c3c5c281eaca38dbc47c5937"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "0.3.4+2" version: "0.3.5+2"
crypto: crypto:
dependency: transitive dependency: transitive
description: description:
name: crypto name: crypto
sha256: "1e445881f28f22d6140f181e07737b22f1e099a5e1ff94b0af2f9e4a463f4855" sha256: c8ea0233063ba03258fbcf2ca4d6dadfefe14f02fab57702265467a19f27fadf
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "3.0.6" version: "3.0.7"
cupertino_icons: cupertino_icons:
dependency: "direct main" dependency: "direct main"
description: description:
name: cupertino_icons name: cupertino_icons
sha256: ba631d1c7f7bef6b729a622b7b752645a2d076dba9976925b8f25725a30e1ee6 sha256: "41e005c33bd814be4d3096aff55b1908d419fde52ca656c8c47719ec745873cd"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "1.0.8" version: "1.0.9"
dbus:
dependency: transitive
description:
name: dbus
sha256: "0ce9b0a839e6dee59a37a623d2fc26a35bbbe6404213e419b0d6411023d62645"
url: "https://pub.dev"
source: hosted
version: "0.7.14"
equatable: equatable:
dependency: transitive dependency: transitive
description: description:
name: equatable name: equatable
sha256: "567c64b3cb4cf82397aac55f4f0cbd3ca20d77c6c03bedbc4ceaddc08904aef7" sha256: "3e0141505477fd8ad55d6eb4e7776d3fe8430be8e497ccb1521370c3f21a3e2b"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "2.0.7" version: "2.0.8"
fake_async: fake_async:
dependency: transitive dependency: transitive
description: description:
name: fake_async name: fake_async
sha256: "511392330127add0b769b75a987850d136345d9227c6b94c96a04cf4a391bf78" sha256: "5368f224a74523e8d2e7399ea1638b37aecfca824a3cc4dfdf77bf1fa905ac44"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "1.3.1" version: "1.3.3"
ffi: ffi:
dependency: transitive dependency: transitive
description: description:
name: ffi name: ffi
sha256: "16ed7b077ef01ad6170a3d0c57caa4a112a38d7a2ed5602e0aca9ca6f3d98da6" sha256: "6d7fd89431262d8f3125e81b50d3847a091d846eafcd4fdb88dd06f36d705a45"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "2.1.3" version: "2.2.0"
file: file:
dependency: transitive dependency: transitive
description: description:
@ -149,10 +157,18 @@ packages:
dependency: "direct main" dependency: "direct main"
description: description:
name: file_picker name: file_picker
sha256: "6f6bfa8797f296965bdc3e1f702574ab49a540c19b9237b401e7c2b25dfe594c" sha256: f13a03000d942e476bc1ff0a736d2e9de711d2f89a95cd4c1d88f861c3348387
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "9.0.0" version: "11.0.2"
fixnum:
dependency: transitive
description:
name: fixnum
sha256: b6dc7065e46c974bc7c5f143080a6764ec7a4be6da1285ececdc37be96de53be
url: "https://pub.dev"
source: hosted
version: "1.1.1"
flutter: flutter:
dependency: "direct main" dependency: "direct main"
description: flutter description: flutter
@ -162,10 +178,10 @@ packages:
dependency: "direct main" dependency: "direct main"
description: description:
name: flutter_code_editor name: flutter_code_editor
sha256: "505ad56dcc8a7be4b782c8113574571bc4b9723499b0c1f385b3e2c3fae11f5d" sha256: "9af48ba8e3558b6ea4bb98b84c5eb1649702acf53e61a84d88383eeb79b239b0"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "0.3.2" version: "0.3.5"
flutter_highlight: flutter_highlight:
dependency: "direct main" dependency: "direct main"
description: description:
@ -178,26 +194,26 @@ packages:
dependency: "direct main" dependency: "direct main"
description: description:
name: flutter_launcher_icons name: flutter_launcher_icons
sha256: bfa04787c85d80ecb3f8777bde5fc10c3de809240c48fa061a2c2bf15ea5211c sha256: "10f13781741a2e3972126fae08393d3c4e01fa4cd7473326b94b72cf594195e7"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "0.14.3" version: "0.14.4"
flutter_lints: flutter_lints:
dependency: "direct dev" dependency: "direct dev"
description: description:
name: flutter_lints name: flutter_lints
sha256: "5398f14efa795ffb7a33e9b6a08798b26a180edac4ad7db3f231e40f82ce11e1" sha256: "3105dc8492f6183fb076ccf1f351ac3d60564bff92e20bfc4af9cc1651f4e7e1"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "5.0.0" version: "6.0.0"
flutter_markdown: flutter_markdown:
dependency: "direct main" dependency: "direct main"
description: description:
name: flutter_markdown name: flutter_markdown
sha256: e7bbc718adc9476aa14cfddc1ef048d2e21e4e8f18311aaac723266db9f9e7b5 sha256: "08fb8315236099ff8e90cb87bb2b935e0a724a3af1623000a9cec930468e0f27"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "0.7.6+2" version: "0.7.7+1"
flutter_markdown_latex: flutter_markdown_latex:
dependency: "direct main" dependency: "direct main"
description: description:
@ -210,26 +226,26 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: flutter_math_fork name: flutter_math_fork
sha256: "284bab89b2fbf1bc3a0baf13d011c1dd324d004e35d177626b77f2fc056366ac" sha256: "6d5f2f1aa57ae539ffb0a04bb39d2da67af74601d685a161aff7ce5bda5fa407"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "0.7.3" version: "0.7.4"
flutter_plugin_android_lifecycle: flutter_plugin_android_lifecycle:
dependency: transitive dependency: transitive
description: description:
name: flutter_plugin_android_lifecycle name: flutter_plugin_android_lifecycle
sha256: "615a505aef59b151b46bbeef55b36ce2b6ed299d160c51d84281946f0aa0ce0e" sha256: "38d1c268de9097ff59cf0e844ac38759fc78f76836d37edad06fa21e182055a0"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "2.0.24" version: "2.0.34"
flutter_svg: flutter_svg:
dependency: "direct main" dependency: "direct main"
description: description:
name: flutter_svg name: flutter_svg
sha256: c200fd79c918a40c5cd50ea0877fa13f81bdaf6f0a5d3dbcc2a13e3285d6aa1b sha256: "35882981abcbfb8c15b286f0cd690ff25bac12d95eff3e25ee207f37d4c42e7f"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "2.0.17" version: "2.3.0"
flutter_test: flutter_test:
dependency: "direct dev" dependency: "direct dev"
description: flutter description: flutter
@ -244,10 +260,10 @@ packages:
dependency: "direct main" dependency: "direct main"
description: description:
name: google_fonts name: google_fonts
sha256: b1ac0fe2832c9cc95e5e88b57d627c5e68c223b9657f4b96e1487aa9098c7b82 sha256: "4e9391085e524954a51e3625b7c9c7e9851dc3f376603208bb45c24b9a66255d"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "6.2.1" version: "8.1.0"
highlight: highlight:
dependency: "direct main" dependency: "direct main"
description: description:
@ -268,10 +284,10 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: http name: http
sha256: fe7ab022b76f3034adc518fb6ea04a82387620e19977665ea18d30a1cf43442f sha256: "87721a4a50b19c7f1d49001e51409bddc46303966ce89a65af4f4e6004896412"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "1.3.0" version: "1.6.0"
http_parser: http_parser:
dependency: transitive dependency: transitive
description: description:
@ -284,42 +300,58 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: image name: image
sha256: "13d3349ace88f12f4a0d175eb5c12dcdd39d35c4c109a8a13dfeb6d0bd9e31c3" sha256: f9881ff4998044947ec38d098bc7c8316ae1186fa786eddffdb867b9bc94dfce
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "4.5.3" version: "4.8.0"
jni:
dependency: transitive
description:
name: jni
sha256: c2230682d5bc2362c1c9e8d3c7f406d9cbba23ab3f2e203a025dd47e0fb2e68f
url: "https://pub.dev"
source: hosted
version: "1.0.0"
jni_flutter:
dependency: transitive
description:
name: jni_flutter
sha256: "8b59e590786050b1cd866677dddaf76b1ade5e7bc751abe04b86e84d379d3ba6"
url: "https://pub.dev"
source: hosted
version: "1.0.1"
json_annotation: json_annotation:
dependency: transitive dependency: transitive
description: description:
name: json_annotation name: json_annotation
sha256: "1ce844379ca14835a50d2f019a3099f419082cfdd231cd86a142af94dd5c6bb1" sha256: "2a743920d81b7910627f68ee2c9ac1fc0bfee32b9fc3403587d7c6791ca12f80"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "4.9.0" version: "4.12.0"
leak_tracker: leak_tracker:
dependency: transitive dependency: transitive
description: description:
name: leak_tracker name: leak_tracker
sha256: "7bb2830ebd849694d1ec25bf1f44582d6ac531a57a365a803a6034ff751d2d06" sha256: "33e2e26bdd85a0112ec15400c8cbffea70d0f9c3407491f672a2fad47915e2de"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "10.0.7" version: "11.0.2"
leak_tracker_flutter_testing: leak_tracker_flutter_testing:
dependency: transitive dependency: transitive
description: description:
name: leak_tracker_flutter_testing name: leak_tracker_flutter_testing
sha256: "9491a714cca3667b60b5c420da8217e6de0d1ba7a5ec322fab01758f6998f379" sha256: "1dbc140bb5a23c75ea9c4811222756104fbcd1a27173f0c34ca01e16bea473c1"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "3.0.8" version: "3.0.10"
leak_tracker_testing: leak_tracker_testing:
dependency: transitive dependency: transitive
description: description:
name: leak_tracker_testing name: leak_tracker_testing
sha256: "6ba465d5d76e67ddf503e1161d1f4a6bc42306f9d66ca1e8f079a47290fb06d3" sha256: "8d5a2d49f4a66b49744b23b018848400d23e54caf9463f4eb20df3eb8acb2eb1"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "3.0.1" version: "3.0.2"
linked_scroll_controller: linked_scroll_controller:
dependency: transitive dependency: transitive
description: description:
@ -332,26 +364,26 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: lints name: lints
sha256: c35bb79562d980e9a453fc715854e1ed39e24e7d0297a880ef54e17f9874a9d7 sha256: "12f842a479589fea194fe5c5a3095abc7be0c1f2ddfa9a0e76aed1dbd26a87df"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "5.1.1" version: "6.1.0"
markdown: markdown:
dependency: "direct main" dependency: "direct main"
description: description:
name: markdown name: markdown
sha256: "935e23e1ff3bc02d390bad4d4be001208ee92cc217cb5b5a6c19bc14aaa318c1" sha256: ee85086ad7698b42522c6ad42fe195f1b9898e4d974a1af4576c1a3a176cada9
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "7.3.0" version: "7.3.1"
matcher: matcher:
dependency: transitive dependency: transitive
description: description:
name: matcher name: matcher
sha256: d2323aa2060500f906aa31a895b4030b6da3ebdcc5619d14ce1aada65cd161cb sha256: dc58c723c3c24bf8d3e2d3ad3f2f9d7bd9cf43ec6feaa64181775e60190153f2
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "0.12.16+1" version: "0.12.17"
material_color_utilities: material_color_utilities:
dependency: transitive dependency: transitive
description: description:
@ -364,18 +396,26 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: meta name: meta
sha256: bdb68674043280c3428e9ec998512fb681678676b3c54e773629ffe74419f8c7 sha256: e3641ec5d63ebf0d9b41bd43201a66e3fc79a65db5f61fc181f04cd27aab950c
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "1.15.0" version: "1.16.0"
mime:
dependency: transitive
description:
name: mime
sha256: "41a20518f0cb1256669420fdba0cd90d21561e560ac240f26ef8322e45bb7ed6"
url: "https://pub.dev"
source: hosted
version: "2.0.0"
mocktail: mocktail:
dependency: transitive dependency: transitive
description: description:
name: mocktail name: mocktail
sha256: "890df3f9688106f25755f26b1c60589a92b3ab91a22b8b224947ad041bf172d8" sha256: "5e1bf53cc7baa8062a33b84424deb61513858ea05c601b8509e683815b5914aa"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "1.0.4" version: "1.0.5"
nested: nested:
dependency: transitive dependency: transitive
description: description:
@ -388,18 +428,26 @@ packages:
dependency: "direct main" dependency: "direct main"
description: description:
name: open_filex name: open_filex
sha256: dcb7bd3d32db8db5260253a62f1564c02c2c8df64bc0187cd213f65f827519bd sha256: "9976da61b6a72302cf3b1efbce259200cd40232643a467aac7370addf94d6900"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "4.6.0" version: "4.7.0"
package_config:
dependency: transitive
description:
name: package_config
sha256: f096c55ebb7deb7e384101542bfba8c52696c1b56fca2eb62827989ef2353bbc
url: "https://pub.dev"
source: hosted
version: "2.2.0"
path: path:
dependency: "direct main" dependency: "direct main"
description: description:
name: path name: path
sha256: "087ce49c3f0dc39180befefc60fdb4acd8f8620e5682fe2476afd0b3688bb4af" sha256: "75cca69d1490965be98c73ceaea117e8a04dd21217b37b292c9ddbec0d955bc5"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "1.9.0" version: "1.9.1"
path_parsing: path_parsing:
dependency: transitive dependency: transitive
description: description:
@ -420,18 +468,18 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: path_provider_android name: path_provider_android
sha256: "4adf4fd5423ec60a29506c76581bc05854c55e3a0b72d35bb28d661c9686edf2" sha256: "69cbd515a62b94d32a7944f086b2f82b4ac40a1d45bebfc00813a430ab2dabcd"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "2.2.15" version: "2.3.1"
path_provider_foundation: path_provider_foundation:
dependency: transitive dependency: transitive
description: description:
name: path_provider_foundation name: path_provider_foundation
sha256: "4843174df4d288f5e29185bd6e72a6fbdf5a4a4602717eed565497429f179942" sha256: "6d13aece7b3f5c5a9731eaf553ff9dcbc2eff41087fd2df587fd0fed9a3eb0c4"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "2.4.1" version: "2.5.1"
path_provider_linux: path_provider_linux:
dependency: transitive dependency: transitive
description: description:
@ -460,26 +508,26 @@ packages:
dependency: "direct main" dependency: "direct main"
description: description:
name: permission_handler name: permission_handler
sha256: "59adad729136f01ea9e35a48f5d1395e25cba6cea552249ddbe9cf950f5d7849" sha256: fe54465bcc62a4564c6e4db337bbaded6c0c0fa6e10487414436d163114784f6
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "11.4.0" version: "12.0.3"
permission_handler_android: permission_handler_android:
dependency: transitive dependency: transitive
description: description:
name: permission_handler_android name: permission_handler_android
sha256: d3971dcdd76182a0c198c096b5db2f0884b0d4196723d21a866fc4cdea057ebc sha256: "1e3bc410ca1bf84662104b100eb126e066cb55791b7451307f9708d4007350e6"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "12.1.0" version: "13.0.1"
permission_handler_apple: permission_handler_apple:
dependency: transitive dependency: transitive
description: description:
name: permission_handler_apple name: permission_handler_apple
sha256: f84a188e79a35c687c132a0a0556c254747a08561e99ab933f12f6ca71ef3c98 sha256: "79dfa1df734798aa3cfdad166d3a3698c206d8813de13516ea1071b5d7e2f420"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "9.4.6" version: "9.4.10"
permission_handler_html: permission_handler_html:
dependency: transitive dependency: transitive
description: description:
@ -508,10 +556,10 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: petitparser name: petitparser
sha256: c15605cd28af66339f8eb6fbe0e541bfe2d1b72d5825efc6598f3e0a31b9ad27 sha256: "91bd59303e9f769f108f8df05e371341b15d59e995e6806aefab827b58336675"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "6.0.2" version: "7.0.2"
platform: platform:
dependency: transitive dependency: transitive
description: description:
@ -532,18 +580,18 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: posix name: posix
sha256: a0117dc2167805aa9125b82eee515cc891819bac2f538c83646d355b16f58b9a sha256: "185ef7606574f789b40f289c233efa52e96dead518aed988e040a10737febb07"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "6.0.1" version: "6.5.0"
provider: provider:
dependency: transitive dependency: transitive
description: description:
name: provider name: provider
sha256: c8a055ee5ce3fd98d6fc872478b03823ffdb448699c6ebdbbc71d59b596fd48c sha256: "4e82183fa20e5ca25703ead7e05de9e4cceed1fbd1eadc1ac3cb6f565a09f272"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "6.1.2" version: "6.1.5+1"
scrollable_positioned_list: scrollable_positioned_list:
dependency: transitive dependency: transitive
description: description:
@ -552,30 +600,46 @@ packages:
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "0.3.8" version: "0.3.8"
share_plus:
dependency: "direct main"
description:
name: share_plus
sha256: "223873d106614442ea6f20db5a038685cc5b32a2fba81cdecaefbbae0523f7fa"
url: "https://pub.dev"
source: hosted
version: "12.0.2"
share_plus_platform_interface:
dependency: transitive
description:
name: share_plus_platform_interface
sha256: "88023e53a13429bd65d8e85e11a9b484f49d4c190abbd96c7932b74d6927cc9a"
url: "https://pub.dev"
source: hosted
version: "6.1.0"
shared_preferences: shared_preferences:
dependency: "direct main" dependency: "direct main"
description: description:
name: shared_preferences name: shared_preferences
sha256: "846849e3e9b68f3ef4b60c60cf4b3e02e9321bc7f4d8c4692cf87ffa82fc8a3a" sha256: c3025c5534b01739267eb7d76959bbc25a6d10f6988e1c2a3036940133dd10bf
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "2.5.2" version: "2.5.5"
shared_preferences_android: shared_preferences_android:
dependency: transitive dependency: transitive
description: description:
name: shared_preferences_android name: shared_preferences_android
sha256: a768fc8ede5f0c8e6150476e14f38e2417c0864ca36bb4582be8e21925a03c22 sha256: e8d4762b1e2e8578fc4d0fd548cebf24afd24f49719c08974df92834565e2c53
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "2.4.6" version: "2.4.23"
shared_preferences_foundation: shared_preferences_foundation:
dependency: transitive dependency: transitive
description: description:
name: shared_preferences_foundation name: shared_preferences_foundation
sha256: "6a52cfcdaeac77cad8c97b539ff688ccfc458c007b4db12be584fbe5c0e49e03" sha256: "4e7eaffc2b17ba398759f1151415869a34771ba11ebbccd1b0145472a619a64f"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "2.5.4" version: "2.5.6"
shared_preferences_linux: shared_preferences_linux:
dependency: transitive dependency: transitive
description: description:
@ -588,10 +652,10 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: shared_preferences_platform_interface name: shared_preferences_platform_interface
sha256: "57cbf196c486bc2cf1f02b85784932c6094376284b3ad5779d1b1c6c6a816b80" sha256: "649dc798a33931919ea356c4305c2d1f81619ea6e92244070b520187b5140ef9"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "2.4.1" version: "2.4.2"
shared_preferences_web: shared_preferences_web:
dependency: transitive dependency: transitive
description: description:
@ -617,50 +681,50 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: source_span name: source_span
sha256: "53e943d4206a5e30df338fd4c6e7a077e02254531b138a15aec3bd143c1a8b3c" sha256: "56a02f1f4cd1a2d96303c0144c93bd6d909eea6bee6bf5a0e0b685edbd4c47ab"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "1.10.0" version: "1.10.2"
stack_trace: stack_trace:
dependency: transitive dependency: transitive
description: description:
name: stack_trace name: stack_trace
sha256: "9f47fd3630d76be3ab26f0ee06d213679aa425996925ff3feffdec504931c377" sha256: "8b27215b45d22309b5cddda1aa2b19bdfec9df0e765f2de506401c071d38d1b1"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "1.12.0" version: "1.12.1"
stream_channel: stream_channel:
dependency: transitive dependency: transitive
description: description:
name: stream_channel name: stream_channel
sha256: ba2aa5d8cc609d96bbb2899c28934f9e1af5cddbd60a827822ea467161eb54e7 sha256: "969e04c80b8bcdf826f8f16579c7b14d780458bd97f56d107d3950fdbeef059d"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "2.1.2" version: "2.1.4"
string_scanner: string_scanner:
dependency: transitive dependency: transitive
description: description:
name: string_scanner name: string_scanner
sha256: "688af5ed3402a4bde5b3a6c15fd768dbf2621a614950b17f04626c431ab3c4c3" sha256: "921cd31725b72fe181906c6a94d987c78e3b98c2e205b397ea399d4054872b43"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "1.3.0" version: "1.4.1"
term_glyph: term_glyph:
dependency: transitive dependency: transitive
description: description:
name: term_glyph name: term_glyph
sha256: a29248a84fbb7c79282b40b8c72a1209db169a2e0542bce341da992fe1bc7e84 sha256: "7f554798625ea768a7518313e58f83891c7f5024f88e46e7182a4558850a4b8e"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "1.2.1" version: "1.2.2"
test_api: test_api:
dependency: transitive dependency: transitive
description: description:
name: test_api name: test_api
sha256: "664d3a9a64782fcdeb83ce9c6b39e78fd2971d4e37827b9b06c3aa1edc5e760c" sha256: "522f00f556e73044315fa4585ec3270f1808a4b186c936e612cab0b565ff1e00"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "0.7.3" version: "0.7.6"
tuple: tuple:
dependency: transitive dependency: transitive
description: description:
@ -681,42 +745,42 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: url_launcher name: url_launcher
sha256: "9d06212b1362abc2f0f0d78e6f09f726608c74e3b9462e8368bb03314aa8d603" sha256: f6a7e5c4835bb4e3026a04793a4199ca2d14c739ec378fdfe23fc8075d0439f8
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "6.3.1" version: "6.3.2"
url_launcher_android: url_launcher_android:
dependency: transitive dependency: transitive
description: description:
name: url_launcher_android name: url_launcher_android
sha256: "6fc2f56536ee873eeb867ad176ae15f304ccccc357848b351f6f0d8d4a40d193" sha256: "3bb000251e55d4a209aa0e2e563309dc9bb2befea2295fd0cec1f51760aac572"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "6.3.14" version: "6.3.29"
url_launcher_ios: url_launcher_ios:
dependency: transitive dependency: transitive
description: description:
name: url_launcher_ios name: url_launcher_ios
sha256: "16a513b6c12bb419304e72ea0ae2ab4fed569920d1c7cb850263fe3acc824626" sha256: cfde38aa257dae62ffe79c87fab20165dfdf6988c1d31b58ebf59b9106062aad
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "6.3.2" version: "6.3.6"
url_launcher_linux: url_launcher_linux:
dependency: transitive dependency: transitive
description: description:
name: url_launcher_linux name: url_launcher_linux
sha256: "4e9ba368772369e3e08f231d2301b4ef72b9ff87c31192ef471b380ef29a4935" sha256: d5e14138b3bc193a0f63c10a53c94b91d399df0512b1f29b94a043db7482384a
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "3.2.1" version: "3.2.2"
url_launcher_macos: url_launcher_macos:
dependency: transitive dependency: transitive
description: description:
name: url_launcher_macos name: url_launcher_macos
sha256: "17ba2000b847f334f16626a574c702b196723af2a289e7a93ffcb79acff855c2" sha256: "368adf46f71ad3c21b8f06614adb38346f193f3a59ba8fe9a2fd74133070ba18"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "3.2.2" version: "3.2.5"
url_launcher_platform_interface: url_launcher_platform_interface:
dependency: transitive dependency: transitive
description: description:
@ -729,26 +793,34 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: url_launcher_web name: url_launcher_web
sha256: "3ba963161bd0fe395917ba881d320b9c4f6dd3c4a233da62ab18a5025c85f1e9" sha256: "4bd2b7b4dc4d4d0b94e5babfffbca8eac1a126c7f3d6ecbc1a11013faa3abba2"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "2.4.0" version: "2.4.1"
url_launcher_windows: url_launcher_windows:
dependency: transitive dependency: transitive
description: description:
name: url_launcher_windows name: url_launcher_windows
sha256: "3284b6d2ac454cf34f114e1d3319866fdd1e19cdc329999057e44ffe936cfa77" sha256: "712c70ab1b99744ff066053cbe3e80c73332b38d46e5e945c98689b2e66fc15f"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "3.1.4" version: "3.1.5"
uuid:
dependency: transitive
description:
name: uuid
sha256: "1fef9e8e11e2991bb773070d4656b7bd5d850967a2456cfc83cf47925ba79489"
url: "https://pub.dev"
source: hosted
version: "4.5.3"
vector_graphics: vector_graphics:
dependency: transitive dependency: transitive
description: description:
name: vector_graphics name: vector_graphics
sha256: "44cc7104ff32563122a929e4620cf3efd584194eec6d1d913eb5ba593dbcf6de" sha256: "2306c03da2ba81724afeb589c351ebbc0aa7d86005925be8f8735856dbe5e42d"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "1.1.18" version: "1.2.2"
vector_graphics_codec: vector_graphics_codec:
dependency: transitive dependency: transitive
description: description:
@ -761,42 +833,42 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: vector_graphics_compiler name: vector_graphics_compiler
sha256: "1b4b9e706a10294258727674a340ae0d6e64a7231980f9f9a3d12e4b42407aad" sha256: b9b3f391857781aa96acacef96066f2f49b4cd03cf9fce3ca4d8da2ef5ea129e
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "1.1.16" version: "1.2.3"
vector_math: vector_math:
dependency: transitive dependency: transitive
description: description:
name: vector_math name: vector_math
sha256: "80b3257d1492ce4d091729e3a67a60407d227c27241d6927be0130c98e741803" sha256: d530bd74fea330e6e364cda7a85019c434070188383e1cd8d9777ee586914c5b
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "2.1.4" version: "2.2.0"
vm_service: vm_service:
dependency: transitive dependency: transitive
description: description:
name: vm_service name: vm_service
sha256: f6be3ed8bd01289b34d679c2b62226f63c0e69f9fd2e50a6b3c1c729a961041b sha256: "0016aef94fc66495ac78af5859181e3f3bf2026bd8eecc72b9565601e19ab360"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "14.3.0" version: "15.2.0"
web: web:
dependency: transitive dependency: transitive
description: description:
name: web name: web
sha256: cd3543bd5798f6ad290ea73d210f423502e71900302dde696f8bff84bf89a1cb sha256: "868d88a33d8a87b18ffc05f9f030ba328ffefba92d6c127917a2ba740f9cfe4a"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "1.1.0" version: "1.1.1"
win32: win32:
dependency: transitive dependency: transitive
description: description:
name: win32 name: win32
sha256: daf97c9d80197ed7b619040e86c8ab9a9dad285e7671ee7390f9180cc828a51e sha256: d7cb55e04cd34096cd3a79b3330245f54cb96a370a1c27adb3c84b917de8b08e
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "5.10.1" version: "5.15.0"
xdg_directories: xdg_directories:
dependency: transitive dependency: transitive
description: description:
@ -809,10 +881,10 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: xml name: xml
sha256: b015a8ad1c488f66851d762d3090a21c600e479dc75e68328c52774040cf9226 sha256: "971043b3a0d3da28727e40ed3e0b5d18b742fa5a68665cca88e74b7876d5e025"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "6.5.0" version: "6.6.1"
yaml: yaml:
dependency: transitive dependency: transitive
description: description:
@ -822,5 +894,5 @@ packages:
source: hosted source: hosted
version: "3.1.3" version: "3.1.3"
sdks: sdks:
dart: ">=3.6.0 <4.0.0" dart: ">=3.9.0 <4.0.0"
flutter: ">=3.27.0" flutter: ">=3.35.6"

9
pubspec.yaml Normal file → Executable file
View file

@ -10,26 +10,27 @@ dependencies:
flutter: flutter:
sdk: flutter sdk: flutter
cupertino_icons: ^1.0.8 cupertino_icons: ^1.0.8
file_picker: ^9.0.0 file_picker: ^11.0.2
flutter_highlight: ^0.7.0 flutter_highlight: ^0.7.0
flutter_code_editor: ^0.3.2 flutter_code_editor: ^0.3.2
flutter_markdown: ^0.7.6+2 flutter_markdown: ^0.7.6+2
flutter_markdown_latex: ^0.3.4 flutter_markdown_latex: ^0.3.4
google_fonts: ^6.2.1 google_fonts: ^8.1.0
markdown: ^7.3.0 markdown: ^7.3.0
path: ^1.9.0 path: ^1.9.0
path_provider: ^2.1.5 path_provider: ^2.1.5
permission_handler: ^11.4.0 permission_handler: ^12.0.3
shared_preferences: ^2.5.2 shared_preferences: ^2.5.2
highlight: ^0.7.0 highlight: ^0.7.0
open_filex: ^4.6.0 open_filex: ^4.6.0
flutter_svg: ^2.0.17 flutter_svg: ^2.0.17
flutter_launcher_icons: ^0.14.3 flutter_launcher_icons: ^0.14.3
share_plus: ^12.0.2
dev_dependencies: dev_dependencies:
flutter_test: flutter_test:
sdk: flutter sdk: flutter
flutter_lints: ^5.0.0 flutter_lints: ^6.0.0
flutter: flutter:
uses-material-design: true uses-material-design: true