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:
parent
9dbd638fa8
commit
fc6c69db24
19 changed files with 1287 additions and 383 deletions
8
android/app/build.gradle
Normal file → Executable file
8
android/app/build.gradle
Normal file → Executable file
|
|
@ -6,10 +6,10 @@ plugins {
|
|||
}
|
||||
|
||||
android {
|
||||
namespace = "com.example.muzzlevelocity"
|
||||
namespace = "vision.flux.muzzlevelocity"
|
||||
compileSdk = flutter.compileSdkVersion
|
||||
ndkVersion = flutter.ndkVersion
|
||||
compileSdkVersion 34
|
||||
compileSdkVersion 36
|
||||
|
||||
compileOptions {
|
||||
sourceCompatibility = JavaVersion.VERSION_1_8
|
||||
|
|
@ -22,14 +22,14 @@ android {
|
|||
|
||||
defaultConfig {
|
||||
// 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.
|
||||
// For more information, see: https://flutter.dev/to/review-gradle-config.
|
||||
minSdk = flutter.minSdkVersion
|
||||
targetSdk = flutter.targetSdkVersion
|
||||
versionCode = flutter.versionCode
|
||||
versionName = flutter.versionName
|
||||
targetSdkVersion 34
|
||||
targetSdkVersion 36
|
||||
}
|
||||
|
||||
buildTypes {
|
||||
|
|
|
|||
32
android/build.gradle
Normal file → Executable file
32
android/build.gradle
Normal file → Executable file
|
|
@ -7,10 +7,36 @@ allprojects {
|
|||
|
||||
rootProject.buildDir = "../build"
|
||||
subprojects {
|
||||
afterEvaluate { project ->
|
||||
if (project.hasProperty("android")) {
|
||||
project.android {
|
||||
compileSdkVersion 36
|
||||
}
|
||||
}
|
||||
}
|
||||
project.buildDir = "${rootProject.buildDir}/${project.name}"
|
||||
}
|
||||
subprojects {
|
||||
project.evaluationDependsOn(":app")
|
||||
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) {
|
||||
|
|
|
|||
2
android/gradle.properties
Normal file → Executable file
2
android/gradle.properties
Normal file → Executable file
|
|
@ -1,3 +1,5 @@
|
|||
org.gradle.jvmargs=-Xmx4G -XX:MaxMetaspaceSize=2G -XX:+HeapDumpOnOutOfMemoryError
|
||||
android.useAndroidX=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
2
android/gradle/wrapper/gradle-wrapper.properties
vendored
Normal file → Executable file
|
|
@ -2,4 +2,4 @@ distributionBase=GRADLE_USER_HOME
|
|||
distributionPath=wrapper/dists
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
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
|
||||
|
|
|
|||
59
android/nix-android-sdk/android-studio-devbox-config.sh
Executable file
59
android/nix-android-sdk/android-studio-devbox-config.sh
Executable 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
136
android/nix-android-sdk/flake.lock
generated
Normal 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
|
||||
}
|
||||
27
android/nix-android-sdk/flake.nix
Normal file
27
android/nix-android-sdk/flake.nix
Normal 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
4
android/settings.gradle
Normal file → Executable file
|
|
@ -18,8 +18,8 @@ pluginManagement {
|
|||
|
||||
plugins {
|
||||
id "dev.flutter.flutter-plugin-loader" version "1.0.0"
|
||||
id "com.android.application" version "8.2.2" apply false
|
||||
id "org.jetbrains.kotlin.android" version "1.8.22" apply false
|
||||
id "com.android.application" version "8.9.1" apply false
|
||||
id "org.jetbrains.kotlin.android" version "2.2.20" apply false
|
||||
}
|
||||
|
||||
include ":app"
|
||||
|
|
|
|||
32
devbox.json
Normal file
32
devbox.json
Normal 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
277
devbox.lock
Normal 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
17
justfile
Normal 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
2
lib/codefield.dart
Normal file → Executable file
|
|
@ -24,7 +24,7 @@ class WrappedCodeField extends StatefulWidget {
|
|||
});
|
||||
|
||||
@override
|
||||
_WrappedCodeFieldState createState() => _WrappedCodeFieldState();
|
||||
State<WrappedCodeField> createState() => _WrappedCodeFieldState();
|
||||
}
|
||||
|
||||
class _WrappedCodeFieldState extends State<WrappedCodeField> {
|
||||
|
|
|
|||
8
lib/main.dart
Normal file → Executable file
8
lib/main.dart
Normal file → Executable file
|
|
@ -14,12 +14,14 @@ void main() async {
|
|||
final license = await rootBundle.loadString('google_fonts/OFL.txt');
|
||||
yield LicenseEntryWithLineBreaks(['google_fonts'], license);
|
||||
});
|
||||
runApp(MuzzleVelocityApp());
|
||||
runApp(const MuzzleVelocityApp());
|
||||
}
|
||||
|
||||
class MuzzleVelocityApp extends StatefulWidget {
|
||||
const MuzzleVelocityApp({super.key});
|
||||
|
||||
@override
|
||||
_MuzzleVelocityAppState createState() => _MuzzleVelocityAppState();
|
||||
State<MuzzleVelocityApp> createState() => _MuzzleVelocityAppState();
|
||||
}
|
||||
|
||||
class _MuzzleVelocityAppState extends State<MuzzleVelocityApp> {
|
||||
|
|
@ -31,7 +33,7 @@ class _MuzzleVelocityAppState extends State<MuzzleVelocityApp> {
|
|||
super.initState();
|
||||
// Ensure the correct theme mode is set on startup
|
||||
_themeMode =
|
||||
WidgetsBinding.instance.window.platformBrightness == Brightness.dark
|
||||
WidgetsBinding.instance.platformDispatcher.platformBrightness == Brightness.dark
|
||||
? ThemeMode.dark
|
||||
: ThemeMode.light;
|
||||
}
|
||||
|
|
|
|||
56
lib/note_editor.dart
Normal file → Executable file
56
lib/note_editor.dart
Normal file → Executable file
|
|
@ -6,6 +6,7 @@ import 'package:flutter_markdown_latex/flutter_markdown_latex.dart';
|
|||
import 'package:flutter_svg/svg.dart';
|
||||
import 'package:markdown/markdown.dart' as md;
|
||||
import 'package:shared_preferences/shared_preferences.dart';
|
||||
import 'package:share_plus/share_plus.dart';
|
||||
import 'themes/day.dart';
|
||||
import 'themes/night.dart';
|
||||
import 'themes/markdown.dart';
|
||||
|
|
@ -16,13 +17,15 @@ class NoteEditorScreen extends StatefulWidget {
|
|||
final String? notesDirectoryPath; // ✅ Add this
|
||||
final bool isDarkMode;
|
||||
|
||||
NoteEditorScreen(
|
||||
{required this.note,
|
||||
required this.isDarkMode,
|
||||
required this.notesDirectoryPath});
|
||||
const NoteEditorScreen({
|
||||
super.key,
|
||||
required this.note,
|
||||
required this.isDarkMode,
|
||||
required this.notesDirectoryPath,
|
||||
});
|
||||
|
||||
@override
|
||||
_NoteEditorScreenState createState() => _NoteEditorScreenState();
|
||||
State<NoteEditorScreen> createState() => _NoteEditorScreenState();
|
||||
}
|
||||
|
||||
class _NoteEditorScreenState extends State<NoteEditorScreen> {
|
||||
|
|
@ -59,7 +62,7 @@ class _NoteEditorScreenState extends State<NoteEditorScreen> {
|
|||
try {
|
||||
_initialContent = await widget.note.readAsString();
|
||||
} catch (e) {
|
||||
print("❌ Failed to read file: ${widget.note.path}");
|
||||
debugPrint("❌ Failed to read file: ${widget.note.path}");
|
||||
_initialContent = "";
|
||||
}
|
||||
|
||||
|
|
@ -86,9 +89,18 @@ class _NoteEditorScreenState extends State<NoteEditorScreen> {
|
|||
await widget.note.writeAsString(_controller.text);
|
||||
_initialContent = _controller.text; // Update initial state
|
||||
|
||||
print("✅ Note saved successfully");
|
||||
debugPrint("✅ Note saved successfully");
|
||||
} 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(
|
||||
onPressed: () async {
|
||||
await _saveNote();
|
||||
Navigator.of(context).pop(true); // Save and exit
|
||||
if (context.mounted) Navigator.of(context).pop(true);
|
||||
},
|
||||
child: Text("Save"),
|
||||
),
|
||||
|
|
@ -137,8 +149,13 @@ class _NoteEditorScreenState extends State<NoteEditorScreen> {
|
|||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return WillPopScope(
|
||||
onWillPop: _onWillPop,
|
||||
return PopScope(
|
||||
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(
|
||||
appBar: AppBar(
|
||||
title: Text(widget.note.uri.pathSegments.last.replaceAll('.md', '')),
|
||||
|
|
@ -146,7 +163,7 @@ class _NoteEditorScreenState extends State<NoteEditorScreen> {
|
|||
icon: Icon(Icons.arrow_back),
|
||||
onPressed: () async {
|
||||
if (await _onWillPop()) {
|
||||
Navigator.pop(context);
|
||||
if (context.mounted) Navigator.pop(context);
|
||||
}
|
||||
},
|
||||
),
|
||||
|
|
@ -157,10 +174,13 @@ class _NoteEditorScreenState extends State<NoteEditorScreen> {
|
|||
icon: SvgPicture.asset(
|
||||
"assets/blaster.svg",
|
||||
width: 30,
|
||||
color: Colors.orange,
|
||||
colorFilter: const ColorFilter.mode(Colors.orange, BlendMode.srcIn),
|
||||
),
|
||||
onSelected: (String value) {
|
||||
switch (value) {
|
||||
case 'Share': // ✅ New case for sharing
|
||||
_shareNote();
|
||||
break;
|
||||
case 'Save':
|
||||
_saveNote();
|
||||
break;
|
||||
|
|
@ -175,6 +195,14 @@ class _NoteEditorScreenState extends State<NoteEditorScreen> {
|
|||
}
|
||||
},
|
||||
itemBuilder: (BuildContext context) => [
|
||||
PopupMenuItem<String>( // ✅ Share button
|
||||
value: 'Share',
|
||||
child: ListTile(
|
||||
leading: Icon(Icons.share_outlined),
|
||||
title: Text("Share"),
|
||||
),
|
||||
),
|
||||
PopupMenuDivider(),
|
||||
PopupMenuItem<String>(
|
||||
value: 'Save',
|
||||
child: ListTile(
|
||||
|
|
@ -193,6 +221,7 @@ class _NoteEditorScreenState extends State<NoteEditorScreen> {
|
|||
: "Enable Autosave"),
|
||||
),
|
||||
),
|
||||
PopupMenuDivider(),
|
||||
PopupMenuItem<String>(
|
||||
enabled: false,
|
||||
child: Column(
|
||||
|
|
@ -219,6 +248,7 @@ class _NoteEditorScreenState extends State<NoteEditorScreen> {
|
|||
],
|
||||
),
|
||||
),
|
||||
PopupMenuDivider(),
|
||||
PopupMenuItem<String>(
|
||||
value: 'Toggle Preview',
|
||||
child: ListTile(
|
||||
|
|
|
|||
375
lib/note_list.dart
Normal file → Executable file
375
lib/note_list.dart
Normal file → Executable file
|
|
@ -19,7 +19,8 @@ class NoteListScreen extends StatefulWidget {
|
|||
final bool isDarkMode;
|
||||
final bool showTags;
|
||||
|
||||
NoteListScreen({
|
||||
const NoteListScreen({
|
||||
super.key,
|
||||
required this.toggleTheme,
|
||||
required this.toggleTags,
|
||||
required this.isDarkMode,
|
||||
|
|
@ -27,11 +28,12 @@ class NoteListScreen extends StatefulWidget {
|
|||
});
|
||||
|
||||
@override
|
||||
_NoteListScreenState createState() => _NoteListScreenState();
|
||||
State<NoteListScreen> createState() => _NoteListScreenState();
|
||||
}
|
||||
|
||||
class _NoteListScreenState extends State<NoteListScreen> {
|
||||
TextEditingController searchController = TextEditingController();
|
||||
final FocusNode searchFocusNode = FocusNode();
|
||||
List<File> notes = [];
|
||||
List<File> filteredNotes = [];
|
||||
List<File> _visibleNotes = [];
|
||||
|
|
@ -52,6 +54,9 @@ class _NoteListScreenState extends State<NoteListScreen> {
|
|||
searchController.addListener(() {
|
||||
_debouncedFilterNotes();
|
||||
});
|
||||
WidgetsBinding.instance.addPostFrameCallback((_) {
|
||||
FocusScope.of(context).requestFocus(searchFocusNode);
|
||||
});
|
||||
}
|
||||
|
||||
void _debouncedFilterNotes() {
|
||||
|
|
@ -95,16 +100,16 @@ class _NoteListScreenState extends State<NoteListScreen> {
|
|||
Future<void> _requestStoragePermission() async {
|
||||
if (Platform.isAndroid) {
|
||||
if (await Permission.storage.request().isGranted) {
|
||||
print("✅ Basic storage permission granted.");
|
||||
debugPrint("✅ Basic storage permission granted.");
|
||||
return;
|
||||
}
|
||||
|
||||
if (await Permission.manageExternalStorage.request().isGranted) {
|
||||
print("✅ Full file access granted.");
|
||||
debugPrint("✅ Full file access granted.");
|
||||
return;
|
||||
}
|
||||
|
||||
print("❌ Storage permission denied. Opening settings...");
|
||||
debugPrint("❌ Storage permission denied. Opening settings...");
|
||||
await openAppSettings(); // Open settings if denied
|
||||
}
|
||||
}
|
||||
|
|
@ -116,12 +121,46 @@ class _NoteListScreenState extends State<NoteListScreen> {
|
|||
setState(() {
|
||||
defaultDir = dir.path;
|
||||
_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();
|
||||
}
|
||||
|
||||
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) {
|
||||
setState(() {
|
||||
_includeSubdirectories = value;
|
||||
|
|
@ -157,7 +196,7 @@ class _NoteListScreenState extends State<NoteListScreen> {
|
|||
setState(() {
|
||||
notesDirectoryPath = defaultDir; // Reset to default directory
|
||||
});
|
||||
Navigator.pop(context); // Close dialog
|
||||
if (context.mounted) Navigator.pop(context);
|
||||
_loadNotes(); // Reload notes from the default directory
|
||||
},
|
||||
child: Text("Use Default"),
|
||||
|
|
@ -165,7 +204,7 @@ class _NoteListScreenState extends State<NoteListScreen> {
|
|||
TextButton(
|
||||
onPressed: () async {
|
||||
await _requestStoragePermission();
|
||||
Navigator.pop(context); // Close the current dialog
|
||||
if (context.mounted) Navigator.pop(context);
|
||||
await _selectNotesDirectory(); // Allow user to pick a folder
|
||||
},
|
||||
child: Text("Choose Folder"),
|
||||
|
|
@ -177,7 +216,7 @@ class _NoteListScreenState extends State<NoteListScreen> {
|
|||
}
|
||||
|
||||
Future<void> _selectNotesDirectory() async {
|
||||
String? selectedDirectory = await FilePicker.platform.getDirectoryPath();
|
||||
String? selectedDirectory = await FilePicker.getDirectoryPath();
|
||||
if (selectedDirectory != null) {
|
||||
final prefs = await SharedPreferences.getInstance();
|
||||
await prefs.setString(
|
||||
|
|
@ -206,7 +245,7 @@ class _NoteListScreenState extends State<NoteListScreen> {
|
|||
final entries = dir.listSync(recursive: _includeSubdirectories);
|
||||
|
||||
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") {
|
||||
continue;
|
||||
|
|
@ -268,6 +307,11 @@ class _NoteListScreenState extends State<NoteListScreen> {
|
|||
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() {
|
||||
final query = searchController.text.trim().toLowerCase();
|
||||
|
||||
|
|
@ -351,6 +395,15 @@ class _NoteListScreenState extends State<NoteListScreen> {
|
|||
String notePath = title.trim();
|
||||
String? subfolder;
|
||||
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('/')) {
|
||||
final parts = notePath.split('/');
|
||||
|
|
@ -358,21 +411,21 @@ class _NoteListScreenState extends State<NoteListScreen> {
|
|||
if (parts.length > 1) {
|
||||
subfolder = parts.sublist(0, parts.length - 1).join('/');
|
||||
}
|
||||
safeTitle = _sanitizeFilename(parts.last);
|
||||
safeTitle = _sanitizeFilename(parts.last.replaceAll(extension, '')); // Remove extension from input
|
||||
} else {
|
||||
safeTitle = _sanitizeFilename(title);
|
||||
safeTitle = _sanitizeFilename(title.replaceAll(extension, ''));
|
||||
}
|
||||
|
||||
// Construct the final file path
|
||||
String fullPath = subfolder != null
|
||||
? path.join(notesDirectoryPath!, subfolder, '$safeTitle.md')
|
||||
: path.join(notesDirectoryPath!, '$safeTitle.md');
|
||||
? path.join(notesDirectoryPath!, subfolder, '$safeTitle$extension')
|
||||
: path.join(notesDirectoryPath!, '$safeTitle$extension');
|
||||
|
||||
final newNote = File(fullPath);
|
||||
|
||||
// Prevent duplicate note creation
|
||||
if (notes.any((note) => note.path == newNote.path)) {
|
||||
print("❌ Note already exists at: $fullPath");
|
||||
debugPrint("❌ Note already exists at: $fullPath");
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -416,7 +469,7 @@ class _NoteListScreenState extends State<NoteListScreen> {
|
|||
|
||||
if (notePath.startsWith('/')) {
|
||||
final parts = notePath.split('/');
|
||||
parts.removeWhere((element) => element.isEmpty); // Remove empty elements
|
||||
parts.removeWhere((element) => element.isEmpty);
|
||||
if (parts.length > 1) {
|
||||
subfolder = parts.sublist(0, parts.length - 1).join('/');
|
||||
}
|
||||
|
|
@ -425,12 +478,18 @@ class _NoteListScreenState extends State<NoteListScreen> {
|
|||
safeTitle = _sanitizeFilename(title);
|
||||
}
|
||||
|
||||
// Construct the expected file path
|
||||
String fullPath = subfolder != null
|
||||
? path.join(notesDirectoryPath!, subfolder, '$safeTitle.md')
|
||||
: path.join(notesDirectoryPath!, '$safeTitle.md');
|
||||
// ✅ Allow multiple file extensions
|
||||
for (var ext in ['.md', '.txt', '.markdown']) {
|
||||
String fullPath = subfolder != null
|
||||
? 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) {
|
||||
|
|
@ -508,7 +567,7 @@ class _NoteListScreenState extends State<NoteListScreen> {
|
|||
_deleteEmptyParentFolders(folder.parent); // Recursively check parent
|
||||
}
|
||||
} catch (e) {
|
||||
print("❌ Error deleting empty folder: $e");
|
||||
debugPrint("❌ Error deleting empty folder: $e");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -577,13 +636,14 @@ class _NoteListScreenState extends State<NoteListScreen> {
|
|||
break;
|
||||
case ':help':
|
||||
_showInfoPage(context, "Help", helpContent);
|
||||
break;
|
||||
default:
|
||||
return; // Do nothing for unrecognized commands
|
||||
}
|
||||
searchController.clear();
|
||||
}
|
||||
|
||||
_showInfoPage(BuildContext context, String title, String content) {
|
||||
void _showInfoPage(BuildContext context, String title, String content) {
|
||||
Navigator.push(
|
||||
context,
|
||||
MaterialPageRoute(
|
||||
|
|
@ -603,6 +663,7 @@ class _NoteListScreenState extends State<NoteListScreen> {
|
|||
title: Padding(
|
||||
padding: EdgeInsets.symmetric(horizontal: 10),
|
||||
child: TextField(
|
||||
focusNode: searchFocusNode,
|
||||
enableInteractiveSelection: true,
|
||||
autocorrect: false,
|
||||
textInputAction: TextInputAction.done,
|
||||
|
|
@ -615,10 +676,11 @@ class _NoteListScreenState extends State<NoteListScreen> {
|
|||
style: GoogleFonts.ibmPlexMono(color: Colors.grey[300]),
|
||||
onSubmitted: (text) {
|
||||
final trimmedText = text.trim();
|
||||
if (trimmedText.isNotEmpty && _isNewNote(trimmedText)) {
|
||||
if (trimmedText.startsWith(':')) {
|
||||
_handleCommand(trimmedText);
|
||||
} else if (trimmedText.isNotEmpty && _isNewNote(trimmedText)) {
|
||||
_createNewNote(trimmedText);
|
||||
searchController
|
||||
.clear(); // Clears the search field after creation
|
||||
searchController.clear();
|
||||
}
|
||||
},
|
||||
),
|
||||
|
|
@ -626,137 +688,145 @@ class _NoteListScreenState extends State<NoteListScreen> {
|
|||
actions: [
|
||||
Padding(
|
||||
padding: EdgeInsets.symmetric(horizontal: 15),
|
||||
child: PopupMenuButton<String>(
|
||||
icon: SvgPicture.asset(
|
||||
"assets/blaster.svg",
|
||||
width: 30,
|
||||
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;
|
||||
}
|
||||
child: GestureDetector(
|
||||
onTap: () {
|
||||
if (searchController.text.isNotEmpty) {
|
||||
searchController.clear();
|
||||
}
|
||||
},
|
||||
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'),
|
||||
),
|
||||
child: PopupMenuButton<String>(
|
||||
enabled: searchController.text.isEmpty,
|
||||
icon: SvgPicture.asset(
|
||||
"assets/blaster.svg",
|
||||
width: 30,
|
||||
colorFilter: const ColorFilter.mode(Colors.orange, BlendMode.srcIn),
|
||||
),
|
||||
PopupMenuItem<String>(
|
||||
value: 'Toggle Theme',
|
||||
child: ListTile(
|
||||
leading: Icon(
|
||||
Theme.of(context).brightness == Brightness.dark
|
||||
? Icons.light_mode
|
||||
: Icons.dark_mode,
|
||||
),
|
||||
title: Text(
|
||||
Theme.of(context).brightness == Brightness.dark
|
||||
? 'Switch to Light Mode'
|
||||
: 'Switch to Dark Mode',
|
||||
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) => [
|
||||
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>(
|
||||
value: 'Include Subdirectories',
|
||||
child: ListTile(
|
||||
leading: Icon(_includeSubdirectories ? Icons.file_copy_outlined : Icons.folder_copy_outlined),
|
||||
title: Text(_includeSubdirectories ? 'Exclude Subdirectories' : 'Include Subdirectories'),
|
||||
onTap: () {
|
||||
_toggleIncludeSubdirectories(!_includeSubdirectories);
|
||||
Navigator.pop(context); // Close menu after toggle
|
||||
},
|
||||
),
|
||||
),
|
||||
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>(
|
||||
value: 'Toggle Theme',
|
||||
child: ListTile(
|
||||
leading: Icon(
|
||||
Theme.of(context).brightness == Brightness.dark
|
||||
? Icons.light_mode
|
||||
: Icons.dark_mode,
|
||||
),
|
||||
title: Text(
|
||||
Theme.of(context).brightness == Brightness.dark
|
||||
? 'Switch to Light Mode'
|
||||
: 'Switch to Dark Mode',
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
PopupMenuItem<String>(
|
||||
value: 'Select Folder',
|
||||
child: ListTile(
|
||||
leading: Icon(Icons.folder_shared_outlined),
|
||||
title: Text('Set Notes Directory'),
|
||||
PopupMenuItem<String>(
|
||||
value: 'Include Subdirectories',
|
||||
child: ListTile(
|
||||
leading: Icon(_includeSubdirectories ? Icons.file_copy_outlined : Icons.folder_copy_outlined),
|
||||
title: Text(_includeSubdirectories ? 'Exclude Subdirectories' : 'Search Subdirectories'),
|
||||
onTap: () {
|
||||
_toggleIncludeSubdirectories(!_includeSubdirectories);
|
||||
Navigator.pop(context); // Close menu after toggle
|
||||
},
|
||||
),
|
||||
),
|
||||
),
|
||||
PopupMenuDivider(),
|
||||
PopupMenuItem<String>(
|
||||
value: 'Empty Trash',
|
||||
child: ListTile(
|
||||
leading: Icon(Icons.delete, color: Colors.redAccent),
|
||||
title: Text('Empty Trash',
|
||||
style: TextStyle(color: Colors.redAccent)),
|
||||
PopupMenuItem<String>(
|
||||
value: 'Include File Content',
|
||||
child: ListTile(
|
||||
leading: Icon(
|
||||
_includeFileContent ? Icons.highlight_off : Icons.file_open_outlined,
|
||||
),
|
||||
title: Text(
|
||||
_includeFileContent ? 'Exclude File Content' : 'Search File Content',
|
||||
),
|
||||
onTap: () {
|
||||
_toggleIncludeFileContent(!_includeFileContent);
|
||||
Navigator.pop(context);
|
||||
},
|
||||
),
|
||||
),
|
||||
),
|
||||
PopupMenuDivider(),
|
||||
PopupMenuItem<String>(
|
||||
value: 'Help',
|
||||
child: ListTile(
|
||||
leading: Icon(Icons.help_outline),
|
||||
title: Text('Help'),
|
||||
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>(
|
||||
value: 'About',
|
||||
child: ListTile(
|
||||
leading: Icon(Icons.info_outline),
|
||||
title: Text('About'),
|
||||
PopupMenuItem<String>(
|
||||
value: 'Select Folder',
|
||||
child: ListTile(
|
||||
leading: Icon(Icons.folder_shared_outlined),
|
||||
title: Text('Set Notes Directory'),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
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 noteContent = _includeFileContent ? noteFile.readAsStringSync() : ""; // ✅ Read content only if needed
|
||||
final tagSpans = _formatTags(noteContent).isNotEmpty
|
||||
? _formatTags(noteContent)
|
||||
: [TextSpan(text: '')];
|
||||
|
||||
return Dismissible(
|
||||
key: Key(noteFile.path),
|
||||
direction: DismissDirection.endToStart,
|
||||
|
|
@ -836,7 +901,7 @@ class _NoteListScreenState extends State<NoteListScreen> {
|
|||
if (result.stdout.toString().trim().isNotEmpty) {
|
||||
await Process.run('xdg-open', [noteFile.path]);
|
||||
} else {
|
||||
print("❌ `xdg-open` is not available.");
|
||||
debugPrint("❌ `xdg-open` is not available.");
|
||||
}
|
||||
} else if (Platform.isAndroid) {
|
||||
await _requestStoragePermission();
|
||||
|
|
@ -844,10 +909,10 @@ class _NoteListScreenState extends State<NoteListScreen> {
|
|||
noteFile.path,
|
||||
type: "text/markdown",
|
||||
);
|
||||
print("✅ OpenFilex result: ${result.type}, message: ${result.message}");
|
||||
debugPrint("✅ OpenFilex result: ${result.type}, message: ${result.message}");
|
||||
}
|
||||
} catch (e) {
|
||||
print("❌ Failed to open external editor: $e");
|
||||
debugPrint("❌ Failed to open external editor: $e");
|
||||
}
|
||||
} else {
|
||||
await Navigator.push(
|
||||
|
|
|
|||
3
lib/read_only.dart
Normal file → Executable file
3
lib/read_only.dart
Normal file → Executable file
|
|
@ -10,7 +10,8 @@ class ReadOnlyPage extends StatelessWidget {
|
|||
final String content;
|
||||
final bool isDarkMode;
|
||||
|
||||
ReadOnlyPage({
|
||||
const ReadOnlyPage({
|
||||
super.key,
|
||||
required this.title,
|
||||
required this.content,
|
||||
required this.isDarkMode,
|
||||
|
|
|
|||
273
lib/themes/markdown.dart
Normal file → Executable file
273
lib/themes/markdown.dart
Normal file → Executable file
|
|
@ -1,61 +1,218 @@
|
|||
import 'package:highlight/highlight.dart';
|
||||
|
||||
final markdown = Mode(refs: {}, aliases: [
|
||||
"md",
|
||||
"mkdown",
|
||||
"mkd"
|
||||
], contains: [
|
||||
Mode(className: "section", variants: [
|
||||
Mode(begin: "^#\\s{1,6}", end: "\$"),
|
||||
Mode(begin: "^.+?\\n[=-]{2,}\$")
|
||||
]),
|
||||
Mode(begin: "<", end: ">", subLanguage: ["xml"], relevance: 0),
|
||||
Mode(className: "bullet", begin: "^\\s*([*+-]|(\\d+\\.))\\s+"),
|
||||
Mode(className: "strong", begin: "[*_]{2}.+?[*_]{2}"),
|
||||
final markdown = Mode(
|
||||
refs: {},
|
||||
aliases: [
|
||||
"md",
|
||||
"mkdown",
|
||||
"mkd"
|
||||
],
|
||||
contains: [
|
||||
// Headers (with distinct classes for each level)
|
||||
Mode(
|
||||
className: "header",
|
||||
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(
|
||||
className: "emphasis",
|
||||
variants: [Mode(begin: "\\*.+?\\*"), Mode(begin: "_.+?_", relevance: 0)]),
|
||||
Mode(className: "quote", begin: "^>\\s+", end: "\$"),
|
||||
Mode(className: "code", variants: [
|
||||
Mode(begin: "^```\\w*\\s*\$", end: "^```[ ]*\$"),
|
||||
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)
|
||||
]),
|
||||
className: "link-reference",
|
||||
begin: "\\[",
|
||||
end: "\\]",
|
||||
excludeBegin: true,
|
||||
excludeEnd: true
|
||||
),
|
||||
|
||||
// Custom Tag Highlighting
|
||||
Mode(
|
||||
|
|
@ -71,11 +228,11 @@ final markdown = Mode(refs: {}, aliases: [
|
|||
begin: "(?<=\\s|^)@[a-zA-Z0-9_]+",
|
||||
relevance: 10), // Yellow
|
||||
Mode(
|
||||
className: "keyword",
|
||||
className: "command",
|
||||
begin: "(?<=\\s|^):[a-zA-Z0-9_]+",
|
||||
relevance: 10),
|
||||
Mode(
|
||||
className: "variable",
|
||||
begin: "(?<=\\s|^)\/[a-zA-Z0-9_\/]+",
|
||||
className: "link-url",
|
||||
begin: "(?<=\\s|^)/[a-zA-Z0-9_/]+",
|
||||
relevance: 10), // Yellow
|
||||
]);
|
||||
|
|
|
|||
348
pubspec.lock
Normal file → Executable file
348
pubspec.lock
Normal file → Executable file
|
|
@ -5,26 +5,26 @@ packages:
|
|||
dependency: transitive
|
||||
description:
|
||||
name: archive
|
||||
sha256: "528579c7e4579719f04b21eeeeddfd73a18b31dabc22766893b7d1be7f49b967"
|
||||
sha256: a96e8b390886ee8abb49b7bd3ac8df6f451c621619f52a26e815fdcf568959ff
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "4.0.3"
|
||||
version: "4.0.9"
|
||||
args:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: args
|
||||
sha256: bf9f5caeea8d8fe6721a9c358dd8a5c1947b27f1cfaa18b39c301273594919e6
|
||||
sha256: d0481093c50b1da8910eb0bb301626d4d8eb7284aa739614d2b394ee09e3ea04
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.6.0"
|
||||
version: "2.7.0"
|
||||
async:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: async
|
||||
sha256: "947bfcf187f74dbc5e146c9eb9c0f10c9f8b30743e341481c1e2ed3ecc18c20c"
|
||||
sha256: e2eb0491ba5ddb6177742d2da23904574082139b07c1e33b8503b9f46f3e1a37
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.11.0"
|
||||
version: "2.13.1"
|
||||
autotrie:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
|
@ -37,18 +37,18 @@ packages:
|
|||
dependency: transitive
|
||||
description:
|
||||
name: boolean_selector
|
||||
sha256: "6cfb5af12253eaf2b368f07bacc5a80d1301a071c73360d746b7f2e32d762c66"
|
||||
sha256: "8aab1771e1243a5063b8b0ff68042d67334e3feab9e95b9490f9a6ebf73b42ea"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.1.1"
|
||||
version: "2.1.2"
|
||||
characters:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: characters
|
||||
sha256: "04a925763edad70e8443c99234dc3328f442e811f1d8fd1a72f1c8ad0f69a605"
|
||||
sha256: f71061c654a3380576a52b451dd5532377954cf9dbd272a78fc8479606670803
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.3.0"
|
||||
version: "1.4.0"
|
||||
charcode:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
|
@ -61,10 +61,10 @@ packages:
|
|||
dependency: transitive
|
||||
description:
|
||||
name: checked_yaml
|
||||
sha256: feb6bed21949061731a7a75fc5d2aa727cf160b91af9a3e464c5e3a32e28b5ff
|
||||
sha256: "959525d3162f249993882720d52b7e0c833978df229be20702b33d48d91de70f"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.0.3"
|
||||
version: "2.0.4"
|
||||
cli_util:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
|
@ -77,66 +77,74 @@ packages:
|
|||
dependency: transitive
|
||||
description:
|
||||
name: clock
|
||||
sha256: cb6d7f03e1de671e34607e909a7213e31d7752be4fb66a86d29fe1eb14bfb5cf
|
||||
sha256: fddb70d9b5277016c77a80201021d40a2247104d9f4aa7bab7157b7e3f05b84b
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.1.1"
|
||||
version: "1.1.2"
|
||||
collection:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: collection
|
||||
sha256: a1ace0a119f20aabc852d165077c036cd864315bd99b7eaa10a60100341941bf
|
||||
sha256: "2f5709ae4d3d59dd8f7cd309b4e023046b57d8a6c82130785d2b0e5868084e76"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.19.0"
|
||||
version: "1.19.1"
|
||||
cross_file:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: cross_file
|
||||
sha256: "7caf6a750a0c04effbb52a676dce9a4a592e10ad35c34d6d2d0e4811160d5670"
|
||||
sha256: "28bb3ae56f117b5aec029d702a90f57d285cd975c3c5c281eaca38dbc47c5937"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.3.4+2"
|
||||
version: "0.3.5+2"
|
||||
crypto:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: crypto
|
||||
sha256: "1e445881f28f22d6140f181e07737b22f1e099a5e1ff94b0af2f9e4a463f4855"
|
||||
sha256: c8ea0233063ba03258fbcf2ca4d6dadfefe14f02fab57702265467a19f27fadf
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "3.0.6"
|
||||
version: "3.0.7"
|
||||
cupertino_icons:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: cupertino_icons
|
||||
sha256: ba631d1c7f7bef6b729a622b7b752645a2d076dba9976925b8f25725a30e1ee6
|
||||
sha256: "41e005c33bd814be4d3096aff55b1908d419fde52ca656c8c47719ec745873cd"
|
||||
url: "https://pub.dev"
|
||||
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:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: equatable
|
||||
sha256: "567c64b3cb4cf82397aac55f4f0cbd3ca20d77c6c03bedbc4ceaddc08904aef7"
|
||||
sha256: "3e0141505477fd8ad55d6eb4e7776d3fe8430be8e497ccb1521370c3f21a3e2b"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.0.7"
|
||||
version: "2.0.8"
|
||||
fake_async:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: fake_async
|
||||
sha256: "511392330127add0b769b75a987850d136345d9227c6b94c96a04cf4a391bf78"
|
||||
sha256: "5368f224a74523e8d2e7399ea1638b37aecfca824a3cc4dfdf77bf1fa905ac44"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.3.1"
|
||||
version: "1.3.3"
|
||||
ffi:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: ffi
|
||||
sha256: "16ed7b077ef01ad6170a3d0c57caa4a112a38d7a2ed5602e0aca9ca6f3d98da6"
|
||||
sha256: "6d7fd89431262d8f3125e81b50d3847a091d846eafcd4fdb88dd06f36d705a45"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.1.3"
|
||||
version: "2.2.0"
|
||||
file:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
|
@ -149,10 +157,18 @@ packages:
|
|||
dependency: "direct main"
|
||||
description:
|
||||
name: file_picker
|
||||
sha256: "6f6bfa8797f296965bdc3e1f702574ab49a540c19b9237b401e7c2b25dfe594c"
|
||||
sha256: f13a03000d942e476bc1ff0a736d2e9de711d2f89a95cd4c1d88f861c3348387
|
||||
url: "https://pub.dev"
|
||||
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:
|
||||
dependency: "direct main"
|
||||
description: flutter
|
||||
|
|
@ -162,10 +178,10 @@ packages:
|
|||
dependency: "direct main"
|
||||
description:
|
||||
name: flutter_code_editor
|
||||
sha256: "505ad56dcc8a7be4b782c8113574571bc4b9723499b0c1f385b3e2c3fae11f5d"
|
||||
sha256: "9af48ba8e3558b6ea4bb98b84c5eb1649702acf53e61a84d88383eeb79b239b0"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.3.2"
|
||||
version: "0.3.5"
|
||||
flutter_highlight:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
|
|
@ -178,26 +194,26 @@ packages:
|
|||
dependency: "direct main"
|
||||
description:
|
||||
name: flutter_launcher_icons
|
||||
sha256: bfa04787c85d80ecb3f8777bde5fc10c3de809240c48fa061a2c2bf15ea5211c
|
||||
sha256: "10f13781741a2e3972126fae08393d3c4e01fa4cd7473326b94b72cf594195e7"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.14.3"
|
||||
version: "0.14.4"
|
||||
flutter_lints:
|
||||
dependency: "direct dev"
|
||||
description:
|
||||
name: flutter_lints
|
||||
sha256: "5398f14efa795ffb7a33e9b6a08798b26a180edac4ad7db3f231e40f82ce11e1"
|
||||
sha256: "3105dc8492f6183fb076ccf1f351ac3d60564bff92e20bfc4af9cc1651f4e7e1"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "5.0.0"
|
||||
version: "6.0.0"
|
||||
flutter_markdown:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: flutter_markdown
|
||||
sha256: e7bbc718adc9476aa14cfddc1ef048d2e21e4e8f18311aaac723266db9f9e7b5
|
||||
sha256: "08fb8315236099ff8e90cb87bb2b935e0a724a3af1623000a9cec930468e0f27"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.7.6+2"
|
||||
version: "0.7.7+1"
|
||||
flutter_markdown_latex:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
|
|
@ -210,26 +226,26 @@ packages:
|
|||
dependency: transitive
|
||||
description:
|
||||
name: flutter_math_fork
|
||||
sha256: "284bab89b2fbf1bc3a0baf13d011c1dd324d004e35d177626b77f2fc056366ac"
|
||||
sha256: "6d5f2f1aa57ae539ffb0a04bb39d2da67af74601d685a161aff7ce5bda5fa407"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.7.3"
|
||||
version: "0.7.4"
|
||||
flutter_plugin_android_lifecycle:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: flutter_plugin_android_lifecycle
|
||||
sha256: "615a505aef59b151b46bbeef55b36ce2b6ed299d160c51d84281946f0aa0ce0e"
|
||||
sha256: "38d1c268de9097ff59cf0e844ac38759fc78f76836d37edad06fa21e182055a0"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.0.24"
|
||||
version: "2.0.34"
|
||||
flutter_svg:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: flutter_svg
|
||||
sha256: c200fd79c918a40c5cd50ea0877fa13f81bdaf6f0a5d3dbcc2a13e3285d6aa1b
|
||||
sha256: "35882981abcbfb8c15b286f0cd690ff25bac12d95eff3e25ee207f37d4c42e7f"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.0.17"
|
||||
version: "2.3.0"
|
||||
flutter_test:
|
||||
dependency: "direct dev"
|
||||
description: flutter
|
||||
|
|
@ -244,10 +260,10 @@ packages:
|
|||
dependency: "direct main"
|
||||
description:
|
||||
name: google_fonts
|
||||
sha256: b1ac0fe2832c9cc95e5e88b57d627c5e68c223b9657f4b96e1487aa9098c7b82
|
||||
sha256: "4e9391085e524954a51e3625b7c9c7e9851dc3f376603208bb45c24b9a66255d"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "6.2.1"
|
||||
version: "8.1.0"
|
||||
highlight:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
|
|
@ -268,10 +284,10 @@ packages:
|
|||
dependency: transitive
|
||||
description:
|
||||
name: http
|
||||
sha256: fe7ab022b76f3034adc518fb6ea04a82387620e19977665ea18d30a1cf43442f
|
||||
sha256: "87721a4a50b19c7f1d49001e51409bddc46303966ce89a65af4f4e6004896412"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.3.0"
|
||||
version: "1.6.0"
|
||||
http_parser:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
|
@ -284,42 +300,58 @@ packages:
|
|||
dependency: transitive
|
||||
description:
|
||||
name: image
|
||||
sha256: "13d3349ace88f12f4a0d175eb5c12dcdd39d35c4c109a8a13dfeb6d0bd9e31c3"
|
||||
sha256: f9881ff4998044947ec38d098bc7c8316ae1186fa786eddffdb867b9bc94dfce
|
||||
url: "https://pub.dev"
|
||||
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:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: json_annotation
|
||||
sha256: "1ce844379ca14835a50d2f019a3099f419082cfdd231cd86a142af94dd5c6bb1"
|
||||
sha256: "2a743920d81b7910627f68ee2c9ac1fc0bfee32b9fc3403587d7c6791ca12f80"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "4.9.0"
|
||||
version: "4.12.0"
|
||||
leak_tracker:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: leak_tracker
|
||||
sha256: "7bb2830ebd849694d1ec25bf1f44582d6ac531a57a365a803a6034ff751d2d06"
|
||||
sha256: "33e2e26bdd85a0112ec15400c8cbffea70d0f9c3407491f672a2fad47915e2de"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "10.0.7"
|
||||
version: "11.0.2"
|
||||
leak_tracker_flutter_testing:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: leak_tracker_flutter_testing
|
||||
sha256: "9491a714cca3667b60b5c420da8217e6de0d1ba7a5ec322fab01758f6998f379"
|
||||
sha256: "1dbc140bb5a23c75ea9c4811222756104fbcd1a27173f0c34ca01e16bea473c1"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "3.0.8"
|
||||
version: "3.0.10"
|
||||
leak_tracker_testing:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: leak_tracker_testing
|
||||
sha256: "6ba465d5d76e67ddf503e1161d1f4a6bc42306f9d66ca1e8f079a47290fb06d3"
|
||||
sha256: "8d5a2d49f4a66b49744b23b018848400d23e54caf9463f4eb20df3eb8acb2eb1"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "3.0.1"
|
||||
version: "3.0.2"
|
||||
linked_scroll_controller:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
|
@ -332,26 +364,26 @@ packages:
|
|||
dependency: transitive
|
||||
description:
|
||||
name: lints
|
||||
sha256: c35bb79562d980e9a453fc715854e1ed39e24e7d0297a880ef54e17f9874a9d7
|
||||
sha256: "12f842a479589fea194fe5c5a3095abc7be0c1f2ddfa9a0e76aed1dbd26a87df"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "5.1.1"
|
||||
version: "6.1.0"
|
||||
markdown:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: markdown
|
||||
sha256: "935e23e1ff3bc02d390bad4d4be001208ee92cc217cb5b5a6c19bc14aaa318c1"
|
||||
sha256: ee85086ad7698b42522c6ad42fe195f1b9898e4d974a1af4576c1a3a176cada9
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "7.3.0"
|
||||
version: "7.3.1"
|
||||
matcher:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: matcher
|
||||
sha256: d2323aa2060500f906aa31a895b4030b6da3ebdcc5619d14ce1aada65cd161cb
|
||||
sha256: dc58c723c3c24bf8d3e2d3ad3f2f9d7bd9cf43ec6feaa64181775e60190153f2
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.12.16+1"
|
||||
version: "0.12.17"
|
||||
material_color_utilities:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
|
@ -364,18 +396,26 @@ packages:
|
|||
dependency: transitive
|
||||
description:
|
||||
name: meta
|
||||
sha256: bdb68674043280c3428e9ec998512fb681678676b3c54e773629ffe74419f8c7
|
||||
sha256: e3641ec5d63ebf0d9b41bd43201a66e3fc79a65db5f61fc181f04cd27aab950c
|
||||
url: "https://pub.dev"
|
||||
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:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: mocktail
|
||||
sha256: "890df3f9688106f25755f26b1c60589a92b3ab91a22b8b224947ad041bf172d8"
|
||||
sha256: "5e1bf53cc7baa8062a33b84424deb61513858ea05c601b8509e683815b5914aa"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.0.4"
|
||||
version: "1.0.5"
|
||||
nested:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
|
@ -388,18 +428,26 @@ packages:
|
|||
dependency: "direct main"
|
||||
description:
|
||||
name: open_filex
|
||||
sha256: dcb7bd3d32db8db5260253a62f1564c02c2c8df64bc0187cd213f65f827519bd
|
||||
sha256: "9976da61b6a72302cf3b1efbce259200cd40232643a467aac7370addf94d6900"
|
||||
url: "https://pub.dev"
|
||||
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:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: path
|
||||
sha256: "087ce49c3f0dc39180befefc60fdb4acd8f8620e5682fe2476afd0b3688bb4af"
|
||||
sha256: "75cca69d1490965be98c73ceaea117e8a04dd21217b37b292c9ddbec0d955bc5"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.9.0"
|
||||
version: "1.9.1"
|
||||
path_parsing:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
|
@ -420,18 +468,18 @@ packages:
|
|||
dependency: transitive
|
||||
description:
|
||||
name: path_provider_android
|
||||
sha256: "4adf4fd5423ec60a29506c76581bc05854c55e3a0b72d35bb28d661c9686edf2"
|
||||
sha256: "69cbd515a62b94d32a7944f086b2f82b4ac40a1d45bebfc00813a430ab2dabcd"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.2.15"
|
||||
version: "2.3.1"
|
||||
path_provider_foundation:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: path_provider_foundation
|
||||
sha256: "4843174df4d288f5e29185bd6e72a6fbdf5a4a4602717eed565497429f179942"
|
||||
sha256: "6d13aece7b3f5c5a9731eaf553ff9dcbc2eff41087fd2df587fd0fed9a3eb0c4"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.4.1"
|
||||
version: "2.5.1"
|
||||
path_provider_linux:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
|
@ -460,26 +508,26 @@ packages:
|
|||
dependency: "direct main"
|
||||
description:
|
||||
name: permission_handler
|
||||
sha256: "59adad729136f01ea9e35a48f5d1395e25cba6cea552249ddbe9cf950f5d7849"
|
||||
sha256: fe54465bcc62a4564c6e4db337bbaded6c0c0fa6e10487414436d163114784f6
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "11.4.0"
|
||||
version: "12.0.3"
|
||||
permission_handler_android:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: permission_handler_android
|
||||
sha256: d3971dcdd76182a0c198c096b5db2f0884b0d4196723d21a866fc4cdea057ebc
|
||||
sha256: "1e3bc410ca1bf84662104b100eb126e066cb55791b7451307f9708d4007350e6"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "12.1.0"
|
||||
version: "13.0.1"
|
||||
permission_handler_apple:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: permission_handler_apple
|
||||
sha256: f84a188e79a35c687c132a0a0556c254747a08561e99ab933f12f6ca71ef3c98
|
||||
sha256: "79dfa1df734798aa3cfdad166d3a3698c206d8813de13516ea1071b5d7e2f420"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "9.4.6"
|
||||
version: "9.4.10"
|
||||
permission_handler_html:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
|
@ -508,10 +556,10 @@ packages:
|
|||
dependency: transitive
|
||||
description:
|
||||
name: petitparser
|
||||
sha256: c15605cd28af66339f8eb6fbe0e541bfe2d1b72d5825efc6598f3e0a31b9ad27
|
||||
sha256: "91bd59303e9f769f108f8df05e371341b15d59e995e6806aefab827b58336675"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "6.0.2"
|
||||
version: "7.0.2"
|
||||
platform:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
|
@ -532,18 +580,18 @@ packages:
|
|||
dependency: transitive
|
||||
description:
|
||||
name: posix
|
||||
sha256: a0117dc2167805aa9125b82eee515cc891819bac2f538c83646d355b16f58b9a
|
||||
sha256: "185ef7606574f789b40f289c233efa52e96dead518aed988e040a10737febb07"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "6.0.1"
|
||||
version: "6.5.0"
|
||||
provider:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: provider
|
||||
sha256: c8a055ee5ce3fd98d6fc872478b03823ffdb448699c6ebdbbc71d59b596fd48c
|
||||
sha256: "4e82183fa20e5ca25703ead7e05de9e4cceed1fbd1eadc1ac3cb6f565a09f272"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "6.1.2"
|
||||
version: "6.1.5+1"
|
||||
scrollable_positioned_list:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
|
@ -552,30 +600,46 @@ packages:
|
|||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
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:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: shared_preferences
|
||||
sha256: "846849e3e9b68f3ef4b60c60cf4b3e02e9321bc7f4d8c4692cf87ffa82fc8a3a"
|
||||
sha256: c3025c5534b01739267eb7d76959bbc25a6d10f6988e1c2a3036940133dd10bf
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.5.2"
|
||||
version: "2.5.5"
|
||||
shared_preferences_android:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: shared_preferences_android
|
||||
sha256: a768fc8ede5f0c8e6150476e14f38e2417c0864ca36bb4582be8e21925a03c22
|
||||
sha256: e8d4762b1e2e8578fc4d0fd548cebf24afd24f49719c08974df92834565e2c53
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.4.6"
|
||||
version: "2.4.23"
|
||||
shared_preferences_foundation:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: shared_preferences_foundation
|
||||
sha256: "6a52cfcdaeac77cad8c97b539ff688ccfc458c007b4db12be584fbe5c0e49e03"
|
||||
sha256: "4e7eaffc2b17ba398759f1151415869a34771ba11ebbccd1b0145472a619a64f"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.5.4"
|
||||
version: "2.5.6"
|
||||
shared_preferences_linux:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
|
@ -588,10 +652,10 @@ packages:
|
|||
dependency: transitive
|
||||
description:
|
||||
name: shared_preferences_platform_interface
|
||||
sha256: "57cbf196c486bc2cf1f02b85784932c6094376284b3ad5779d1b1c6c6a816b80"
|
||||
sha256: "649dc798a33931919ea356c4305c2d1f81619ea6e92244070b520187b5140ef9"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.4.1"
|
||||
version: "2.4.2"
|
||||
shared_preferences_web:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
|
@ -617,50 +681,50 @@ packages:
|
|||
dependency: transitive
|
||||
description:
|
||||
name: source_span
|
||||
sha256: "53e943d4206a5e30df338fd4c6e7a077e02254531b138a15aec3bd143c1a8b3c"
|
||||
sha256: "56a02f1f4cd1a2d96303c0144c93bd6d909eea6bee6bf5a0e0b685edbd4c47ab"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.10.0"
|
||||
version: "1.10.2"
|
||||
stack_trace:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: stack_trace
|
||||
sha256: "9f47fd3630d76be3ab26f0ee06d213679aa425996925ff3feffdec504931c377"
|
||||
sha256: "8b27215b45d22309b5cddda1aa2b19bdfec9df0e765f2de506401c071d38d1b1"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.12.0"
|
||||
version: "1.12.1"
|
||||
stream_channel:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: stream_channel
|
||||
sha256: ba2aa5d8cc609d96bbb2899c28934f9e1af5cddbd60a827822ea467161eb54e7
|
||||
sha256: "969e04c80b8bcdf826f8f16579c7b14d780458bd97f56d107d3950fdbeef059d"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.1.2"
|
||||
version: "2.1.4"
|
||||
string_scanner:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: string_scanner
|
||||
sha256: "688af5ed3402a4bde5b3a6c15fd768dbf2621a614950b17f04626c431ab3c4c3"
|
||||
sha256: "921cd31725b72fe181906c6a94d987c78e3b98c2e205b397ea399d4054872b43"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.3.0"
|
||||
version: "1.4.1"
|
||||
term_glyph:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: term_glyph
|
||||
sha256: a29248a84fbb7c79282b40b8c72a1209db169a2e0542bce341da992fe1bc7e84
|
||||
sha256: "7f554798625ea768a7518313e58f83891c7f5024f88e46e7182a4558850a4b8e"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.2.1"
|
||||
version: "1.2.2"
|
||||
test_api:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: test_api
|
||||
sha256: "664d3a9a64782fcdeb83ce9c6b39e78fd2971d4e37827b9b06c3aa1edc5e760c"
|
||||
sha256: "522f00f556e73044315fa4585ec3270f1808a4b186c936e612cab0b565ff1e00"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.7.3"
|
||||
version: "0.7.6"
|
||||
tuple:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
|
@ -681,42 +745,42 @@ packages:
|
|||
dependency: transitive
|
||||
description:
|
||||
name: url_launcher
|
||||
sha256: "9d06212b1362abc2f0f0d78e6f09f726608c74e3b9462e8368bb03314aa8d603"
|
||||
sha256: f6a7e5c4835bb4e3026a04793a4199ca2d14c739ec378fdfe23fc8075d0439f8
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "6.3.1"
|
||||
version: "6.3.2"
|
||||
url_launcher_android:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: url_launcher_android
|
||||
sha256: "6fc2f56536ee873eeb867ad176ae15f304ccccc357848b351f6f0d8d4a40d193"
|
||||
sha256: "3bb000251e55d4a209aa0e2e563309dc9bb2befea2295fd0cec1f51760aac572"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "6.3.14"
|
||||
version: "6.3.29"
|
||||
url_launcher_ios:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: url_launcher_ios
|
||||
sha256: "16a513b6c12bb419304e72ea0ae2ab4fed569920d1c7cb850263fe3acc824626"
|
||||
sha256: cfde38aa257dae62ffe79c87fab20165dfdf6988c1d31b58ebf59b9106062aad
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "6.3.2"
|
||||
version: "6.3.6"
|
||||
url_launcher_linux:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: url_launcher_linux
|
||||
sha256: "4e9ba368772369e3e08f231d2301b4ef72b9ff87c31192ef471b380ef29a4935"
|
||||
sha256: d5e14138b3bc193a0f63c10a53c94b91d399df0512b1f29b94a043db7482384a
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "3.2.1"
|
||||
version: "3.2.2"
|
||||
url_launcher_macos:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: url_launcher_macos
|
||||
sha256: "17ba2000b847f334f16626a574c702b196723af2a289e7a93ffcb79acff855c2"
|
||||
sha256: "368adf46f71ad3c21b8f06614adb38346f193f3a59ba8fe9a2fd74133070ba18"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "3.2.2"
|
||||
version: "3.2.5"
|
||||
url_launcher_platform_interface:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
|
@ -729,26 +793,34 @@ packages:
|
|||
dependency: transitive
|
||||
description:
|
||||
name: url_launcher_web
|
||||
sha256: "3ba963161bd0fe395917ba881d320b9c4f6dd3c4a233da62ab18a5025c85f1e9"
|
||||
sha256: "4bd2b7b4dc4d4d0b94e5babfffbca8eac1a126c7f3d6ecbc1a11013faa3abba2"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.4.0"
|
||||
version: "2.4.1"
|
||||
url_launcher_windows:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: url_launcher_windows
|
||||
sha256: "3284b6d2ac454cf34f114e1d3319866fdd1e19cdc329999057e44ffe936cfa77"
|
||||
sha256: "712c70ab1b99744ff066053cbe3e80c73332b38d46e5e945c98689b2e66fc15f"
|
||||
url: "https://pub.dev"
|
||||
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:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: vector_graphics
|
||||
sha256: "44cc7104ff32563122a929e4620cf3efd584194eec6d1d913eb5ba593dbcf6de"
|
||||
sha256: "2306c03da2ba81724afeb589c351ebbc0aa7d86005925be8f8735856dbe5e42d"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.1.18"
|
||||
version: "1.2.2"
|
||||
vector_graphics_codec:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
|
@ -761,42 +833,42 @@ packages:
|
|||
dependency: transitive
|
||||
description:
|
||||
name: vector_graphics_compiler
|
||||
sha256: "1b4b9e706a10294258727674a340ae0d6e64a7231980f9f9a3d12e4b42407aad"
|
||||
sha256: b9b3f391857781aa96acacef96066f2f49b4cd03cf9fce3ca4d8da2ef5ea129e
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.1.16"
|
||||
version: "1.2.3"
|
||||
vector_math:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: vector_math
|
||||
sha256: "80b3257d1492ce4d091729e3a67a60407d227c27241d6927be0130c98e741803"
|
||||
sha256: d530bd74fea330e6e364cda7a85019c434070188383e1cd8d9777ee586914c5b
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.1.4"
|
||||
version: "2.2.0"
|
||||
vm_service:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: vm_service
|
||||
sha256: f6be3ed8bd01289b34d679c2b62226f63c0e69f9fd2e50a6b3c1c729a961041b
|
||||
sha256: "0016aef94fc66495ac78af5859181e3f3bf2026bd8eecc72b9565601e19ab360"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "14.3.0"
|
||||
version: "15.2.0"
|
||||
web:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: web
|
||||
sha256: cd3543bd5798f6ad290ea73d210f423502e71900302dde696f8bff84bf89a1cb
|
||||
sha256: "868d88a33d8a87b18ffc05f9f030ba328ffefba92d6c127917a2ba740f9cfe4a"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.1.0"
|
||||
version: "1.1.1"
|
||||
win32:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: win32
|
||||
sha256: daf97c9d80197ed7b619040e86c8ab9a9dad285e7671ee7390f9180cc828a51e
|
||||
sha256: d7cb55e04cd34096cd3a79b3330245f54cb96a370a1c27adb3c84b917de8b08e
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "5.10.1"
|
||||
version: "5.15.0"
|
||||
xdg_directories:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
|
@ -809,10 +881,10 @@ packages:
|
|||
dependency: transitive
|
||||
description:
|
||||
name: xml
|
||||
sha256: b015a8ad1c488f66851d762d3090a21c600e479dc75e68328c52774040cf9226
|
||||
sha256: "971043b3a0d3da28727e40ed3e0b5d18b742fa5a68665cca88e74b7876d5e025"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "6.5.0"
|
||||
version: "6.6.1"
|
||||
yaml:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
|
@ -822,5 +894,5 @@ packages:
|
|||
source: hosted
|
||||
version: "3.1.3"
|
||||
sdks:
|
||||
dart: ">=3.6.0 <4.0.0"
|
||||
flutter: ">=3.27.0"
|
||||
dart: ">=3.9.0 <4.0.0"
|
||||
flutter: ">=3.35.6"
|
||||
|
|
|
|||
9
pubspec.yaml
Normal file → Executable file
9
pubspec.yaml
Normal file → Executable file
|
|
@ -10,26 +10,27 @@ dependencies:
|
|||
flutter:
|
||||
sdk: flutter
|
||||
cupertino_icons: ^1.0.8
|
||||
file_picker: ^9.0.0
|
||||
file_picker: ^11.0.2
|
||||
flutter_highlight: ^0.7.0
|
||||
flutter_code_editor: ^0.3.2
|
||||
flutter_markdown: ^0.7.6+2
|
||||
flutter_markdown_latex: ^0.3.4
|
||||
google_fonts: ^6.2.1
|
||||
google_fonts: ^8.1.0
|
||||
markdown: ^7.3.0
|
||||
path: ^1.9.0
|
||||
path_provider: ^2.1.5
|
||||
permission_handler: ^11.4.0
|
||||
permission_handler: ^12.0.3
|
||||
shared_preferences: ^2.5.2
|
||||
highlight: ^0.7.0
|
||||
open_filex: ^4.6.0
|
||||
flutter_svg: ^2.0.17
|
||||
flutter_launcher_icons: ^0.14.3
|
||||
share_plus: ^12.0.2
|
||||
|
||||
dev_dependencies:
|
||||
flutter_test:
|
||||
sdk: flutter
|
||||
flutter_lints: ^5.0.0
|
||||
flutter_lints: ^6.0.0
|
||||
|
||||
flutter:
|
||||
uses-material-design: true
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue