nandi/frqpublic Fork 0
e2b0e6b
Commits
Clone
git clone https://git.rickub.com/nandi/frq.git
git clone ssh://git@rickub.com/nandi/frq.git

Host key fingerprint (ed25519): SHA256:iycHnxEyq0Q7uyVpB7JlznP0G7JrTPXLYRcAU5CSLhc — verify it before your first connect.

Build the APK, out of ClojureDart and Flutter

The shared half compiles under a second compiler, which was the thing worth
proving. `clojure -M:cljd compile` turns common/frq/{clock,store,io}.cljc and
flutter/src/frq/{main,io/dart}.cljd into 698 lines of Dart, and Flutter's
Gradle build packs it into an APK for all three ABIs. It installs and runs:
the clock and the saved session on screen, read through the same namespaces
`just tui` reads them through.

Two things had to give first.

frq.clock was not as portable as moving it to common/ implied. It reached for
Math/floorDiv and Math/floorMod, which are Java and have no equivalent under
ClojureDart — so the seam that exists for the filesystem was needed one scale
down, and floor-div is now eight lines of arithmetic. Checked against
java.time.LocalDate for every day from 1901 to 2052 and against Math/floorDiv
across the range, both zero mismatches. This is the shape of the rest of the
port: what breaks is never the language, it is the host underneath it.

And frq.main was written from the docs rather than from the compiler, so it
had cljd.flutter's nesting wrong — slot names are forms in a chain, not
arguments inside the widget, and MaterialApp takes .home where Center takes
.child. It also faked the await with a :watch over a Future; main is ^:async
now and awaits path_provider before installing the host, which is what the
docstring claimed all along.

The build is impure and stays that way. Gradle fetches its own dependencies
and installs build-tools and a platform into ANDROID_HOME, so it can neither
run in a sandbox nor write to the store; nix supplies the toolchain and the
recipe copies the SDK somewhere writable. No ndkVersion, because setting it
makes Gradle fetch an NDK for native code that does not exist here. ios/,
macos/, windows/ and web/ are deleted — android/ and linux/ are the targets.

Signed with ~/.android/debug.keystore, like every debug build. The jolt APK's
key was generated inside its own derivation and never written down, so the
first install over it needed an uninstall — Android will not update a package
across a signature change. Release signing is still the template's TODO.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
nandi committed 2026-09-11T17:54:43-07:00 Browse files
e2b0e6b parent: 7070931
modified common/frq/clock.cljc +17 -3
@@ -35,6 +35,20 @@
3535 days (+ (* era 146097) doe -719468)]
3636 (* 1000 (+ (* days 86400) (* h 3600) (* mi 60) s)))))
3737
38+(defn- floor-div
39+ "`quot` rounds toward zero and this rounds down, which for a day number
40+ before 1970 is a different day.
41+
42+ Written out rather than taken from the host: `Math/floorDiv` is Java, and
43+ this namespace is compiled by ClojureDart too, where there is no Math class
44+ to call into. The same reason `frq.io` exists, one scale down."
45+ [a b]
46+ (let [q (quot a b)
47+ r (rem a b)]
48+ (if (or (zero? r) (= (neg? r) (neg? b))) q (dec q))))
49+
50+(defn- floor-mod [a b] (- a (* b (floor-div a b))))
51+
3852 (defn- civil-from-days
3953 "`[y m d]` for a day number since the epoch — Hinnant's algorithm the other
4054 way round, which is the direction `parse-time-tag` does not go.
@@ -45,7 +59,7 @@
4559 eleven lines and the same on both platforms."
4660 [days]
4761 (let [z (+ days 719468)
48- era (Math/floorDiv (long z) 146097)
62+ era (floor-div z 146097)
4963 doe (- z (* era 146097))
5064 yoe (quot (+ (- doe (quot doe 1460)) (quot doe 36524) (- (quot doe 146096))) 365)
5165 y (+ yoe (* era 400))
@@ -62,8 +76,8 @@
6276 [ms]
6377 (let [secs (quot ms 1000)
6478 secs (+ secs (io/local-offset-seconds secs))
65- days (Math/floorDiv (long secs) 86400)
66- sod (Math/floorMod (long secs) 86400)
79+ days (floor-div secs 86400)
80+ sod (floor-mod secs 86400)
6781 [y m d] (civil-from-days days)]
6882 [(str y "-" (pad2 m) "-" (pad2 d))
6983 (quot sod 3600)
@@ -35,6 +35,20 @@
35 days (+ (* era 146097) doe -719468)]35 days (+ (* era 146097) doe -719468)]
36 (* 1000 (+ (* days 86400) (* h 3600) (* mi 60) s)))))36 (* 1000 (+ (* days 86400) (* h 3600) (* mi 60) s)))))
37 37
38+(defn- floor-div
39+ "`quot` rounds toward zero and this rounds down, which for a day number
40+ before 1970 is a different day.
41+
42+ Written out rather than taken from the host: `Math/floorDiv` is Java, and
43+ this namespace is compiled by ClojureDart too, where there is no Math class
44+ to call into. The same reason `frq.io` exists, one scale down."
45+ [a b]
46+ (let [q (quot a b)
47+ r (rem a b)]
48+ (if (or (zero? r) (= (neg? r) (neg? b))) q (dec q))))
49+
50+(defn- floor-mod [a b] (- a (* b (floor-div a b))))
51+
38 (defn- civil-from-days52 (defn- civil-from-days
39 "`[y m d]` for a day number since the epoch — Hinnant's algorithm the other53 "`[y m d]` for a day number since the epoch — Hinnant's algorithm the other
40 way round, which is the direction `parse-time-tag` does not go.54 way round, which is the direction `parse-time-tag` does not go.
@@ -45,7 +59,7 @@
45 eleven lines and the same on both platforms."59 eleven lines and the same on both platforms."
46 [days]60 [days]
47 (let [z (+ days 719468)61 (let [z (+ days 719468)
48- era (Math/floorDiv (long z) 146097)62+ era (floor-div z 146097)
49 doe (- z (* era 146097))63 doe (- z (* era 146097))
50 yoe (quot (+ (- doe (quot doe 1460)) (quot doe 36524) (- (quot doe 146096))) 365)64 yoe (quot (+ (- doe (quot doe 1460)) (quot doe 36524) (- (quot doe 146096))) 365)
51 y (+ yoe (* era 400))65 y (+ yoe (* era 400))
@@ -62,8 +76,8 @@
62 [ms]76 [ms]
63 (let [secs (quot ms 1000)77 (let [secs (quot ms 1000)
64 secs (+ secs (io/local-offset-seconds secs))78 secs (+ secs (io/local-offset-seconds secs))
65- days (Math/floorDiv (long secs) 86400)79+ days (floor-div secs 86400)
66- sod (Math/floorMod (long secs) 86400)80+ sod (floor-mod secs 86400)
67 [y m d] (civil-from-days days)]81 [y m d] (civil-from-days days)]
68 [(str y "-" (pad2 m) "-" (pad2 d))82 [(str y "-" (pad2 m) "-" (pad2 d))
69 (quot sod 3600)83 (quot sod 3600)
added flutter/.gitattributes +3 -0
new file mode 100644
@@ -0,0 +1,3 @@
1+
2+# Syntax highlighting for ClojureDart files
3+*.cljd linguist-language=Clojure
new file mode 100644
@@ -0,0 +1,3 @@
1+
2+# Syntax highlighting for ClojureDart files
3+*.cljd linguist-language=Clojure
added flutter/.gitignore +25 -0
new file mode 100644
@@ -0,0 +1,25 @@
1+# Generated Dart. `clojure -M:cljd compile` writes it from src/ and ../common,
2+# and it is derived from files that are in git — so it is not.
3+lib/cljd-out/
4+
5+# Flutter's own working directories.
6+build/
7+.dart_tool/
8+.flutter-plugins
9+.flutter-plugins-dependencies
10+
11+# Where `just apk` keeps the writable Android SDK and Flutter's config. The
12+# SDK is a copy of the one nix builds, 151 MB of it, because Gradle installs
13+# build-tools and a platform into ANDROID_HOME and cannot write to the store.
14+.home/
15+
16+# Written by the build with absolute paths to the store — `just apk` rewrites
17+# it on every run, so a committed one would only ever be someone else's.
18+android/local.properties
19+
20+# ClojureDart's and tools.deps' own caches.
21+.clojuredart/
22+.cpcache/
23+
24+# Editor scaffolding `cljd init` leaves behind.
25+.idea/
new file mode 100644
@@ -0,0 +1,25 @@
1+# Generated Dart. `clojure -M:cljd compile` writes it from src/ and ../common,
2+# and it is derived from files that are in git — so it is not.
3+lib/cljd-out/
4+
5+# Flutter's own working directories.
6+build/
7+.dart_tool/
8+.flutter-plugins
9+.flutter-plugins-dependencies
10+
11+# Where `just apk` keeps the writable Android SDK and Flutter's config. The
12+# SDK is a copy of the one nix builds, 151 MB of it, because Gradle installs
13+# build-tools and a platform into ANDROID_HOME and cannot write to the store.
14+.home/
15+
16+# Written by the build with absolute paths to the store — `just apk` rewrites
17+# it on every run, so a committed one would only ever be someone else's.
18+android/local.properties
19+
20+# ClojureDart's and tools.deps' own caches.
21+.clojuredart/
22+.cpcache/
23+
24+# Editor scaffolding `cljd init` leaves behind.
25+.idea/
added flutter/.metadata +45 -0
new file mode 100644
@@ -0,0 +1,45 @@
1+# This file tracks properties of this Flutter project.
2+# Used by Flutter tool to assess capabilities and perform upgrades etc.
3+#
4+# This file should be version controlled and should not be manually edited.
5+
6+version:
7+ revision: "nixpkgs000000000000000000000000000000000"
8+ channel: "stable"
9+
10+project_type: app
11+
12+# Tracks metadata for the flutter migrate command
13+migration:
14+ platforms:
15+ - platform: root
16+ create_revision: nixpkgs000000000000000000000000000000000
17+ base_revision: nixpkgs000000000000000000000000000000000
18+ - platform: android
19+ create_revision: nixpkgs000000000000000000000000000000000
20+ base_revision: nixpkgs000000000000000000000000000000000
21+ - platform: ios
22+ create_revision: nixpkgs000000000000000000000000000000000
23+ base_revision: nixpkgs000000000000000000000000000000000
24+ - platform: linux
25+ create_revision: nixpkgs000000000000000000000000000000000
26+ base_revision: nixpkgs000000000000000000000000000000000
27+ - platform: macos
28+ create_revision: nixpkgs000000000000000000000000000000000
29+ base_revision: nixpkgs000000000000000000000000000000000
30+ - platform: web
31+ create_revision: nixpkgs000000000000000000000000000000000
32+ base_revision: nixpkgs000000000000000000000000000000000
33+ - platform: windows
34+ create_revision: nixpkgs000000000000000000000000000000000
35+ base_revision: nixpkgs000000000000000000000000000000000
36+
37+ # User provided section
38+
39+ # List of Local paths (relative to this file) that should be
40+ # ignored by the migrate tool.
41+ #
42+ # Files that are not part of the templates will be ignored by default.
43+ unmanaged_files:
44+ - 'lib/main.dart'
45+ - 'ios/Runner.xcodeproj/project.pbxproj'
new file mode 100644
@@ -0,0 +1,45 @@
1+# This file tracks properties of this Flutter project.
2+# Used by Flutter tool to assess capabilities and perform upgrades etc.
3+#
4+# This file should be version controlled and should not be manually edited.
5+
6+version:
7+ revision: "nixpkgs000000000000000000000000000000000"
8+ channel: "stable"
9+
10+project_type: app
11+
12+# Tracks metadata for the flutter migrate command
13+migration:
14+ platforms:
15+ - platform: root
16+ create_revision: nixpkgs000000000000000000000000000000000
17+ base_revision: nixpkgs000000000000000000000000000000000
18+ - platform: android
19+ create_revision: nixpkgs000000000000000000000000000000000
20+ base_revision: nixpkgs000000000000000000000000000000000
21+ - platform: ios
22+ create_revision: nixpkgs000000000000000000000000000000000
23+ base_revision: nixpkgs000000000000000000000000000000000
24+ - platform: linux
25+ create_revision: nixpkgs000000000000000000000000000000000
26+ base_revision: nixpkgs000000000000000000000000000000000
27+ - platform: macos
28+ create_revision: nixpkgs000000000000000000000000000000000
29+ base_revision: nixpkgs000000000000000000000000000000000
30+ - platform: web
31+ create_revision: nixpkgs000000000000000000000000000000000
32+ base_revision: nixpkgs000000000000000000000000000000000
33+ - platform: windows
34+ create_revision: nixpkgs000000000000000000000000000000000
35+ base_revision: nixpkgs000000000000000000000000000000000
36+
37+ # User provided section
38+
39+ # List of Local paths (relative to this file) that should be
40+ # ignored by the migrate tool.
41+ #
42+ # Files that are not part of the templates will be ignored by default.
43+ unmanaged_files:
44+ - 'lib/main.dart'
45+ - 'ios/Runner.xcodeproj/project.pbxproj'
modified flutter/README.md +37 -14
@@ -74,17 +74,40 @@ desktop-only), and the media plane — `moq/`, `codec/`, `capture/`, `av/`, abou
7474 `dart:ffi` does not conjure V4L2; that half wants Flutter's camera and audio
7575 plugins and is its own project.
7676
77-## To make this real
78-
79-1. Pin `tensegritics/clojuredart` in `deps.edn` — it says `PIN-ME`.
80-2. Get a Flutter SDK and the cljd toolchain into the flake. Neither is there.
81-3. `clj -M:cljd init`, then `clj -M:cljd flutter`. (There is no `release`
82- subcommand — a release build is `clj -M:cljd compile` followed by
83- `flutter build`.)
84-4. `frq.io.dart` is written from the docs and has never been compiled. Expect
85- its interop to be wrong in detail.
86-
87-There is no other APK to fall back on. The jolt one — `nix/android.nix`, the
88-`android/` manifest and Java glue, the `.#apk` outputs and `just apk` — is
89-gone, along with the jvui and Vidya backends it painted through. Until step 2
90-exists, frq has no Android build at all, and that is the honest state.
77+## Building it
78+
79+```bash
80+just apk # the debug APK
81+just apk install # and onto a connected device
82+just apk run # and launched
83+just apk log # logcat
84+```
85+
86+Impure on purpose. Gradle resolves its own dependencies over the network and
87+installs build-tools and a platform into `ANDROID_HOME` as it goes, so it can
88+neither run in a sandbox nor write to the store. What nix gives is the
89+toolchain — clojure, a JDK, Flutter, and an SDK composed by androidenv — and
90+the recipe copies that SDK to `flutter/.home` for Gradle to finish off. That
91+copy and everything Gradle leaves behind are gitignored.
92+
93+Two things the Flutter template wanted that are deliberately not here. There is
94+no `ndkVersion` in `android/app/build.gradle.kts`: setting it makes Gradle
95+fetch that exact NDK, and there is no native code to need one — the app is
96+Dart, and path_provider is platform channels rather than JNI. And `ios/`,
97+`macos/`, `windows/`, `web/` are deleted; `android/` and `linux/` are the
98+targets.
99+
100+It is signed with `~/.android/debug.keystore`, through the template's
101+`signingConfig = signingConfigs.getByName("debug")` — which release builds also
102+use, so `flutter build apk --release` is not shippable until a real
103+`signingConfigs.release` is wired up. The jolt APK's key was generated inside
104+its own nix derivation and never written anywhere, which is why the first
105+install over it needed an uninstall: Android will not update a package across a
106+signature change.
107+
108+## What it paints
109+
110+`frq.main` is a socket, not the client: the clock and the saved session, read
111+through exactly the `common/` namespaces the desktop reads them through. That
112+is the whole point of it — proof the shared half compiles and runs under a
113+second compiler. The screens are still to be written.
@@ -74,17 +74,40 @@ desktop-only), and the media plane — `moq/`, `codec/`, `capture/`, `av/`, abou
74 `dart:ffi` does not conjure V4L2; that half wants Flutter's camera and audio74 `dart:ffi` does not conjure V4L2; that half wants Flutter's camera and audio
75 plugins and is its own project.75 plugins and is its own project.
76 76
77-## To make this real77+## Building it
78-78+
79-1. Pin `tensegritics/clojuredart` in `deps.edn` — it says `PIN-ME`.79+```bash
80-2. Get a Flutter SDK and the cljd toolchain into the flake. Neither is there.80+just apk # the debug APK
81-3. `clj -M:cljd init`, then `clj -M:cljd flutter`. (There is no `release`81+just apk install # and onto a connected device
82- subcommand — a release build is `clj -M:cljd compile` followed by82+just apk run # and launched
83- `flutter build`.)83+just apk log # logcat
84-4. `frq.io.dart` is written from the docs and has never been compiled. Expect84+```
85- its interop to be wrong in detail.85+
86-86+Impure on purpose. Gradle resolves its own dependencies over the network and
87-There is no other APK to fall back on. The jolt one — `nix/android.nix`, the87+installs build-tools and a platform into `ANDROID_HOME` as it goes, so it can
88-`android/` manifest and Java glue, the `.#apk` outputs and `just apk` — is88+neither run in a sandbox nor write to the store. What nix gives is the
89-gone, along with the jvui and Vidya backends it painted through. Until step 289+toolchain — clojure, a JDK, Flutter, and an SDK composed by androidenv — and
90-exists, frq has no Android build at all, and that is the honest state.90+the recipe copies that SDK to `flutter/.home` for Gradle to finish off. That
91+copy and everything Gradle leaves behind are gitignored.
92+
93+Two things the Flutter template wanted that are deliberately not here. There is
94+no `ndkVersion` in `android/app/build.gradle.kts`: setting it makes Gradle
95+fetch that exact NDK, and there is no native code to need one — the app is
96+Dart, and path_provider is platform channels rather than JNI. And `ios/`,
97+`macos/`, `windows/`, `web/` are deleted; `android/` and `linux/` are the
98+targets.
99+
100+It is signed with `~/.android/debug.keystore`, through the template's
101+`signingConfig = signingConfigs.getByName("debug")` — which release builds also
102+use, so `flutter build apk --release` is not shippable until a real
103+`signingConfigs.release` is wired up. The jolt APK's key was generated inside
104+its own nix derivation and never written anywhere, which is why the first
105+install over it needed an uninstall: Android will not update a package across a
106+signature change.
107+
108+## What it paints
109+
110+`frq.main` is a socket, not the client: the clock and the saved session, read
111+through exactly the `common/` namespaces the desktop reads them through. That
112+is the whole point of it — proof the shared half compiles and runs under a
113+second compiler. The screens are still to be written.
added flutter/analysis_options.yaml +38 -0
new file mode 100644
@@ -0,0 +1,38 @@
1+# This file configures the analyzer, which statically analyzes Dart code to
2+# check for errors, warnings, and lints.
3+#
4+# The issues identified by the analyzer are surfaced in the UI of Dart-enabled
5+# IDEs (https://dart.dev/tools#ides-and-editors). The analyzer can also be
6+# invoked from the command line by running `flutter analyze`.
7+
8+# The following line activates a set of recommended lints for Flutter apps,
9+# packages, and plugins designed to encourage good coding practices.
10+include: package:flutter_lints/flutter.yaml
11+
12+analyzer:
13+ exclude:
14+ - build/**
15+ - android/**
16+ - ios/**
17+ - web/**
18+ - windows/**
19+ - macos/**
20+ - linux/**
21+
22+linter:
23+ # The lint rules applied to this project can be customized in the
24+ # section below to disable rules from the `package:flutter_lints/flutter.yaml`
25+ # included above or to enable additional rules. A list of all available lints
26+ # and their documentation is published at https://dart.dev/lints.
27+ #
28+ # Instead of disabling a lint rule for the entire project in the
29+ # section below, it can also be suppressed for a single line of code
30+ # or a specific dart file by using the `// ignore: name_of_lint` and
31+ # `// ignore_for_file: name_of_lint` syntax on the line or in the file
32+ # producing the lint.
33+ rules:
34+ # avoid_print: false # Uncomment to disable the `avoid_print` rule
35+ # prefer_single_quotes: true # Uncomment to enable the `prefer_single_quotes` rule
36+
37+# Additional information about this file can be found at
38+# https://dart.dev/guides/language/analysis-options
new file mode 100644
@@ -0,0 +1,38 @@
1+# This file configures the analyzer, which statically analyzes Dart code to
2+# check for errors, warnings, and lints.
3+#
4+# The issues identified by the analyzer are surfaced in the UI of Dart-enabled
5+# IDEs (https://dart.dev/tools#ides-and-editors). The analyzer can also be
6+# invoked from the command line by running `flutter analyze`.
7+
8+# The following line activates a set of recommended lints for Flutter apps,
9+# packages, and plugins designed to encourage good coding practices.
10+include: package:flutter_lints/flutter.yaml
11+
12+analyzer:
13+ exclude:
14+ - build/**
15+ - android/**
16+ - ios/**
17+ - web/**
18+ - windows/**
19+ - macos/**
20+ - linux/**
21+
22+linter:
23+ # The lint rules applied to this project can be customized in the
24+ # section below to disable rules from the `package:flutter_lints/flutter.yaml`
25+ # included above or to enable additional rules. A list of all available lints
26+ # and their documentation is published at https://dart.dev/lints.
27+ #
28+ # Instead of disabling a lint rule for the entire project in the
29+ # section below, it can also be suppressed for a single line of code
30+ # or a specific dart file by using the `// ignore: name_of_lint` and
31+ # `// ignore_for_file: name_of_lint` syntax on the line or in the file
32+ # producing the lint.
33+ rules:
34+ # avoid_print: false # Uncomment to disable the `avoid_print` rule
35+ # prefer_single_quotes: true # Uncomment to enable the `prefer_single_quotes` rule
36+
37+# Additional information about this file can be found at
38+# https://dart.dev/guides/language/analysis-options
added flutter/android/.gitignore +14 -0
new file mode 100644
@@ -0,0 +1,14 @@
1+gradle-wrapper.jar
2+/.gradle
3+/captures/
4+/gradlew
5+/gradlew.bat
6+/local.properties
7+GeneratedPluginRegistrant.java
8+.cxx/
9+
10+# Remember to never publicly share your keystore.
11+# See https://flutter.dev/to/reference-keystore
12+key.properties
13+**/*.keystore
14+**/*.jks
new file mode 100644
@@ -0,0 +1,14 @@
1+gradle-wrapper.jar
2+/.gradle
3+/captures/
4+/gradlew
5+/gradlew.bat
6+/local.properties
7+GeneratedPluginRegistrant.java
8+.cxx/
9+
10+# Remember to never publicly share your keystore.
11+# See https://flutter.dev/to/reference-keystore
12+key.properties
13+**/*.keystore
14+**/*.jks
added flutter/android/app/build.gradle.kts +53 -0
new file mode 100644
@@ -0,0 +1,53 @@
1+plugins {
2+ id("com.android.application")
3+ // The Flutter Gradle Plugin must be applied after the Android and Kotlin Gradle plugins.
4+ id("dev.flutter.flutter-gradle-plugin")
5+}
6+
7+android {
8+ namespace = "uk.nandi.frq"
9+ compileSdk = flutter.compileSdkVersion
10+ // No ndkVersion. The Flutter template sets it, and setting it makes Gradle
11+ // ask sdkmanager to install that exact NDK — which fails against a Nix
12+ // store it cannot write to. Nothing here has native code to build: the
13+ // app is Dart compiled from ClojureDart, and path_provider is platform
14+ // channels rather than JNI. See flutter/README.md.
15+
16+ compileOptions {
17+ sourceCompatibility = JavaVersion.VERSION_17
18+ targetCompatibility = JavaVersion.VERSION_17
19+ }
20+
21+ defaultConfig {
22+ // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html).
23+ applicationId = "uk.nandi.frq"
24+ // You can update the following values to match your application needs.
25+ // For more information, see: https://flutter.dev/to/review-gradle-config.
26+ minSdk = flutter.minSdkVersion
27+ targetSdk = flutter.targetSdkVersion
28+ // Uses the version code from pubspec.yaml. When using split APKs, 1000 * ABI_VERSION
29+ // is added automatically by Flutter. (https://developer.android.com/studio/build/configure-apk-splits#configure-APK-versions)
30+ // You can force using the value of versionCode by specifying the `-P force-version-code-ignoring-abi=true`
31+ // flag during build.
32+ versionCode = flutter.versionCode
33+ versionName = flutter.versionName
34+ }
35+
36+ buildTypes {
37+ release {
38+ // TODO: Add your own signing config for the release build.
39+ // Signing with the debug keys for now, so `flutter run --release` works.
40+ signingConfig = signingConfigs.getByName("debug")
41+ }
42+ }
43+}
44+
45+kotlin {
46+ compilerOptions {
47+ jvmTarget = org.jetbrains.kotlin.gradle.dsl.JvmTarget.JVM_17
48+ }
49+}
50+
51+flutter {
52+ source = "../.."
53+}
new file mode 100644
@@ -0,0 +1,53 @@
1+plugins {
2+ id("com.android.application")
3+ // The Flutter Gradle Plugin must be applied after the Android and Kotlin Gradle plugins.
4+ id("dev.flutter.flutter-gradle-plugin")
5+}
6+
7+android {
8+ namespace = "uk.nandi.frq"
9+ compileSdk = flutter.compileSdkVersion
10+ // No ndkVersion. The Flutter template sets it, and setting it makes Gradle
11+ // ask sdkmanager to install that exact NDK — which fails against a Nix
12+ // store it cannot write to. Nothing here has native code to build: the
13+ // app is Dart compiled from ClojureDart, and path_provider is platform
14+ // channels rather than JNI. See flutter/README.md.
15+
16+ compileOptions {
17+ sourceCompatibility = JavaVersion.VERSION_17
18+ targetCompatibility = JavaVersion.VERSION_17
19+ }
20+
21+ defaultConfig {
22+ // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html).
23+ applicationId = "uk.nandi.frq"
24+ // You can update the following values to match your application needs.
25+ // For more information, see: https://flutter.dev/to/review-gradle-config.
26+ minSdk = flutter.minSdkVersion
27+ targetSdk = flutter.targetSdkVersion
28+ // Uses the version code from pubspec.yaml. When using split APKs, 1000 * ABI_VERSION
29+ // is added automatically by Flutter. (https://developer.android.com/studio/build/configure-apk-splits#configure-APK-versions)
30+ // You can force using the value of versionCode by specifying the `-P force-version-code-ignoring-abi=true`
31+ // flag during build.
32+ versionCode = flutter.versionCode
33+ versionName = flutter.versionName
34+ }
35+
36+ buildTypes {
37+ release {
38+ // TODO: Add your own signing config for the release build.
39+ // Signing with the debug keys for now, so `flutter run --release` works.
40+ signingConfig = signingConfigs.getByName("debug")
41+ }
42+ }
43+}
44+
45+kotlin {
46+ compilerOptions {
47+ jvmTarget = org.jetbrains.kotlin.gradle.dsl.JvmTarget.JVM_17
48+ }
49+}
50+
51+flutter {
52+ source = "../.."
53+}
added flutter/android/app/src/debug/AndroidManifest.xml +7 -0
new file mode 100644
@@ -0,0 +1,7 @@
1+<manifest xmlns:android="http://schemas.android.com/apk/res/android">
2+ <!-- The INTERNET permission is required for development. Specifically,
3+ the Flutter tool needs it to communicate with the running application
4+ to allow setting breakpoints, to provide hot reload, etc.
5+ -->
6+ <uses-permission android:name="android.permission.INTERNET"/>
7+</manifest>
new file mode 100644
@@ -0,0 +1,7 @@
1+<manifest xmlns:android="http://schemas.android.com/apk/res/android">
2+ <!-- The INTERNET permission is required for development. Specifically,
3+ the Flutter tool needs it to communicate with the running application
4+ to allow setting breakpoints, to provide hot reload, etc.
5+ -->
6+ <uses-permission android:name="android.permission.INTERNET"/>
7+</manifest>
added flutter/android/app/src/main/AndroidManifest.xml +45 -0
new file mode 100644
@@ -0,0 +1,45 @@
1+<manifest xmlns:android="http://schemas.android.com/apk/res/android">
2+ <application
3+ android:label="frq"
4+ android:name="${applicationName}"
5+ android:icon="@mipmap/ic_launcher">
6+ <activity
7+ android:name=".MainActivity"
8+ android:exported="true"
9+ android:launchMode="singleTop"
10+ android:taskAffinity=""
11+ android:theme="@style/LaunchTheme"
12+ android:configChanges="orientation|keyboardHidden|keyboard|screenSize|smallestScreenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode"
13+ android:hardwareAccelerated="true"
14+ android:windowSoftInputMode="adjustResize">
15+ <!-- Specifies an Android theme to apply to this Activity as soon as
16+ the Android process has started. This theme is visible to the user
17+ while the Flutter UI initializes. After that, this theme continues
18+ to determine the Window background behind the Flutter UI. -->
19+ <meta-data
20+ android:name="io.flutter.embedding.android.NormalTheme"
21+ android:resource="@style/NormalTheme"
22+ />
23+ <intent-filter>
24+ <action android:name="android.intent.action.MAIN"/>
25+ <category android:name="android.intent.category.LAUNCHER"/>
26+ </intent-filter>
27+ </activity>
28+ <!-- Don't delete the meta-data below.
29+ This is used by the Flutter tool to generate GeneratedPluginRegistrant.java -->
30+ <meta-data
31+ android:name="flutterEmbedding"
32+ android:value="2" />
33+ </application>
34+ <!-- Required to query activities that can process text, see:
35+ https://developer.android.com/training/package-visibility and
36+ https://developer.android.com/reference/android/content/Intent#ACTION_PROCESS_TEXT.
37+
38+ In particular, this is used by the Flutter engine in io.flutter.plugin.text.ProcessTextPlugin. -->
39+ <queries>
40+ <intent>
41+ <action android:name="android.intent.action.PROCESS_TEXT"/>
42+ <data android:mimeType="text/plain"/>
43+ </intent>
44+ </queries>
45+</manifest>
new file mode 100644
@@ -0,0 +1,45 @@
1+<manifest xmlns:android="http://schemas.android.com/apk/res/android">
2+ <application
3+ android:label="frq"
4+ android:name="${applicationName}"
5+ android:icon="@mipmap/ic_launcher">
6+ <activity
7+ android:name=".MainActivity"
8+ android:exported="true"
9+ android:launchMode="singleTop"
10+ android:taskAffinity=""
11+ android:theme="@style/LaunchTheme"
12+ android:configChanges="orientation|keyboardHidden|keyboard|screenSize|smallestScreenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode"
13+ android:hardwareAccelerated="true"
14+ android:windowSoftInputMode="adjustResize">
15+ <!-- Specifies an Android theme to apply to this Activity as soon as
16+ the Android process has started. This theme is visible to the user
17+ while the Flutter UI initializes. After that, this theme continues
18+ to determine the Window background behind the Flutter UI. -->
19+ <meta-data
20+ android:name="io.flutter.embedding.android.NormalTheme"
21+ android:resource="@style/NormalTheme"
22+ />
23+ <intent-filter>
24+ <action android:name="android.intent.action.MAIN"/>
25+ <category android:name="android.intent.category.LAUNCHER"/>
26+ </intent-filter>
27+ </activity>
28+ <!-- Don't delete the meta-data below.
29+ This is used by the Flutter tool to generate GeneratedPluginRegistrant.java -->
30+ <meta-data
31+ android:name="flutterEmbedding"
32+ android:value="2" />
33+ </application>
34+ <!-- Required to query activities that can process text, see:
35+ https://developer.android.com/training/package-visibility and
36+ https://developer.android.com/reference/android/content/Intent#ACTION_PROCESS_TEXT.
37+
38+ In particular, this is used by the Flutter engine in io.flutter.plugin.text.ProcessTextPlugin. -->
39+ <queries>
40+ <intent>
41+ <action android:name="android.intent.action.PROCESS_TEXT"/>
42+ <data android:mimeType="text/plain"/>
43+ </intent>
44+ </queries>
45+</manifest>
added flutter/android/app/src/main/kotlin/uk/nandi/frq/MainActivity.kt +5 -0
new file mode 100644
@@ -0,0 +1,5 @@
1+package uk.nandi.frq
2+
3+import io.flutter.embedding.android.FlutterActivity
4+
5+class MainActivity : FlutterActivity()
new file mode 100644
@@ -0,0 +1,5 @@
1+package uk.nandi.frq
2+
3+import io.flutter.embedding.android.FlutterActivity
4+
5+class MainActivity : FlutterActivity()
added flutter/android/app/src/main/res/drawable-v21/launch_background.xml +12 -0
new file mode 100644
@@ -0,0 +1,12 @@
1+<?xml version="1.0" encoding="utf-8"?>
2+<!-- Modify this file to customize your launch splash screen -->
3+<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
4+ <item android:drawable="?android:colorBackground" />
5+
6+ <!-- You can insert your own image assets here -->
7+ <!-- <item>
8+ <bitmap
9+ android:gravity="center"
10+ android:src="@mipmap/launch_image" />
11+ </item> -->
12+</layer-list>
new file mode 100644
@@ -0,0 +1,12 @@
1+<?xml version="1.0" encoding="utf-8"?>
2+<!-- Modify this file to customize your launch splash screen -->
3+<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
4+ <item android:drawable="?android:colorBackground" />
5+
6+ <!-- You can insert your own image assets here -->
7+ <!-- <item>
8+ <bitmap
9+ android:gravity="center"
10+ android:src="@mipmap/launch_image" />
11+ </item> -->
12+</layer-list>
added flutter/android/app/src/main/res/drawable/launch_background.xml +12 -0
new file mode 100644
@@ -0,0 +1,12 @@
1+<?xml version="1.0" encoding="utf-8"?>
2+<!-- Modify this file to customize your launch splash screen -->
3+<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
4+ <item android:drawable="@android:color/white" />
5+
6+ <!-- You can insert your own image assets here -->
7+ <!-- <item>
8+ <bitmap
9+ android:gravity="center"
10+ android:src="@mipmap/launch_image" />
11+ </item> -->
12+</layer-list>
new file mode 100644
@@ -0,0 +1,12 @@
1+<?xml version="1.0" encoding="utf-8"?>
2+<!-- Modify this file to customize your launch splash screen -->
3+<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
4+ <item android:drawable="@android:color/white" />
5+
6+ <!-- You can insert your own image assets here -->
7+ <!-- <item>
8+ <bitmap
9+ android:gravity="center"
10+ android:src="@mipmap/launch_image" />
11+ </item> -->
12+</layer-list>
added flutter/android/app/src/main/res/mipmap-hdpi/ic_launcher.png +0 -0
new file mode 100644
Binary files /dev/null and b/flutter/android/app/src/main/res/mipmap-hdpi/ic_launcher.png differ
new file mode 100644
Binary files /dev/null and b/flutter/android/app/src/main/res/mipmap-hdpi/ic_launcher.png differBinary files /dev/null and b/flutter/android/app/src/main/res/mipmap-hdpi/ic_launcher.png differ
added flutter/android/app/src/main/res/mipmap-mdpi/ic_launcher.png +0 -0
new file mode 100644
Binary files /dev/null and b/flutter/android/app/src/main/res/mipmap-mdpi/ic_launcher.png differ
new file mode 100644
Binary files /dev/null and b/flutter/android/app/src/main/res/mipmap-mdpi/ic_launcher.png differBinary files /dev/null and b/flutter/android/app/src/main/res/mipmap-mdpi/ic_launcher.png differ
added flutter/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png +0 -0
new file mode 100644
Binary files /dev/null and b/flutter/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png differ
new file mode 100644
Binary files /dev/null and b/flutter/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png differBinary files /dev/null and b/flutter/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png differ
added flutter/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png +0 -0
new file mode 100644
Binary files /dev/null and b/flutter/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png differ
new file mode 100644
Binary files /dev/null and b/flutter/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png differBinary files /dev/null and b/flutter/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png differ
added flutter/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png +0 -0
new file mode 100644
Binary files /dev/null and b/flutter/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png differ
new file mode 100644
Binary files /dev/null and b/flutter/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png differBinary files /dev/null and b/flutter/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png differ
added flutter/android/app/src/main/res/values-night/styles.xml +18 -0
new file mode 100644
@@ -0,0 +1,18 @@
1+<?xml version="1.0" encoding="utf-8"?>
2+<resources>
3+ <!-- Theme applied to the Android Window while the process is starting when the OS's Dark Mode setting is on -->
4+ <style name="LaunchTheme" parent="@android:style/Theme.Black.NoTitleBar">
5+ <!-- Show a splash screen on the activity. Automatically removed when
6+ the Flutter engine draws its first frame -->
7+ <item name="android:windowBackground">@drawable/launch_background</item>
8+ </style>
9+ <!-- Theme applied to the Android Window as soon as the process has started.
10+ This theme determines the color of the Android Window while your
11+ Flutter UI initializes, as well as behind your Flutter UI while its
12+ running.
13+
14+ This Theme is only used starting with V2 of Flutter's Android embedding. -->
15+ <style name="NormalTheme" parent="@android:style/Theme.Black.NoTitleBar">
16+ <item name="android:windowBackground">?android:colorBackground</item>
17+ </style>
18+</resources>
new file mode 100644
@@ -0,0 +1,18 @@
1+<?xml version="1.0" encoding="utf-8"?>
2+<resources>
3+ <!-- Theme applied to the Android Window while the process is starting when the OS's Dark Mode setting is on -->
4+ <style name="LaunchTheme" parent="@android:style/Theme.Black.NoTitleBar">
5+ <!-- Show a splash screen on the activity. Automatically removed when
6+ the Flutter engine draws its first frame -->
7+ <item name="android:windowBackground">@drawable/launch_background</item>
8+ </style>
9+ <!-- Theme applied to the Android Window as soon as the process has started.
10+ This theme determines the color of the Android Window while your
11+ Flutter UI initializes, as well as behind your Flutter UI while its
12+ running.
13+
14+ This Theme is only used starting with V2 of Flutter's Android embedding. -->
15+ <style name="NormalTheme" parent="@android:style/Theme.Black.NoTitleBar">
16+ <item name="android:windowBackground">?android:colorBackground</item>
17+ </style>
18+</resources>
added flutter/android/app/src/main/res/values/styles.xml +18 -0
new file mode 100644
@@ -0,0 +1,18 @@
1+<?xml version="1.0" encoding="utf-8"?>
2+<resources>
3+ <!-- Theme applied to the Android Window while the process is starting when the OS's Dark Mode setting is off -->
4+ <style name="LaunchTheme" parent="@android:style/Theme.Light.NoTitleBar">
5+ <!-- Show a splash screen on the activity. Automatically removed when
6+ the Flutter engine draws its first frame -->
7+ <item name="android:windowBackground">@drawable/launch_background</item>
8+ </style>
9+ <!-- Theme applied to the Android Window as soon as the process has started.
10+ This theme determines the color of the Android Window while your
11+ Flutter UI initializes, as well as behind your Flutter UI while its
12+ running.
13+
14+ This Theme is only used starting with V2 of Flutter's Android embedding. -->
15+ <style name="NormalTheme" parent="@android:style/Theme.Light.NoTitleBar">
16+ <item name="android:windowBackground">?android:colorBackground</item>
17+ </style>
18+</resources>
new file mode 100644
@@ -0,0 +1,18 @@
1+<?xml version="1.0" encoding="utf-8"?>
2+<resources>
3+ <!-- Theme applied to the Android Window while the process is starting when the OS's Dark Mode setting is off -->
4+ <style name="LaunchTheme" parent="@android:style/Theme.Light.NoTitleBar">
5+ <!-- Show a splash screen on the activity. Automatically removed when
6+ the Flutter engine draws its first frame -->
7+ <item name="android:windowBackground">@drawable/launch_background</item>
8+ </style>
9+ <!-- Theme applied to the Android Window as soon as the process has started.
10+ This theme determines the color of the Android Window while your
11+ Flutter UI initializes, as well as behind your Flutter UI while its
12+ running.
13+
14+ This Theme is only used starting with V2 of Flutter's Android embedding. -->
15+ <style name="NormalTheme" parent="@android:style/Theme.Light.NoTitleBar">
16+ <item name="android:windowBackground">?android:colorBackground</item>
17+ </style>
18+</resources>
added flutter/android/app/src/profile/AndroidManifest.xml +7 -0
new file mode 100644
@@ -0,0 +1,7 @@
1+<manifest xmlns:android="http://schemas.android.com/apk/res/android">
2+ <!-- The INTERNET permission is required for development. Specifically,
3+ the Flutter tool needs it to communicate with the running application
4+ to allow setting breakpoints, to provide hot reload, etc.
5+ -->
6+ <uses-permission android:name="android.permission.INTERNET"/>
7+</manifest>
new file mode 100644
@@ -0,0 +1,7 @@
1+<manifest xmlns:android="http://schemas.android.com/apk/res/android">
2+ <!-- The INTERNET permission is required for development. Specifically,
3+ the Flutter tool needs it to communicate with the running application
4+ to allow setting breakpoints, to provide hot reload, etc.
5+ -->
6+ <uses-permission android:name="android.permission.INTERNET"/>
7+</manifest>
added flutter/android/build.gradle.kts +24 -0
new file mode 100644
@@ -0,0 +1,24 @@
1+allprojects {
2+ repositories {
3+ google()
4+ mavenCentral()
5+ }
6+}
7+
8+val newBuildDir: Directory =
9+ rootProject.layout.buildDirectory
10+ .dir("../../build")
11+ .get()
12+rootProject.layout.buildDirectory.value(newBuildDir)
13+
14+subprojects {
15+ val newSubprojectBuildDir: Directory = newBuildDir.dir(project.name)
16+ project.layout.buildDirectory.value(newSubprojectBuildDir)
17+}
18+subprojects {
19+ project.evaluationDependsOn(":app")
20+}
21+
22+tasks.register<Delete>("clean") {
23+ delete(rootProject.layout.buildDirectory)
24+}
new file mode 100644
@@ -0,0 +1,24 @@
1+allprojects {
2+ repositories {
3+ google()
4+ mavenCentral()
5+ }
6+}
7+
8+val newBuildDir: Directory =
9+ rootProject.layout.buildDirectory
10+ .dir("../../build")
11+ .get()
12+rootProject.layout.buildDirectory.value(newBuildDir)
13+
14+subprojects {
15+ val newSubprojectBuildDir: Directory = newBuildDir.dir(project.name)
16+ project.layout.buildDirectory.value(newSubprojectBuildDir)
17+}
18+subprojects {
19+ project.evaluationDependsOn(":app")
20+}
21+
22+tasks.register<Delete>("clean") {
23+ delete(rootProject.layout.buildDirectory)
24+}
added flutter/android/cljd_flutter_android.iml +29 -0
new file mode 100644
@@ -0,0 +1,29 @@
1+<?xml version="1.0" encoding="UTF-8"?>
2+<module type="JAVA_MODULE" version="4">
3+ <component name="FacetManager">
4+ <facet type="android" name="Android">
5+ <configuration>
6+ <option name="ALLOW_USER_CONFIGURATION" value="false" />
7+ <option name="GEN_FOLDER_RELATIVE_PATH_APT" value="/gen" />
8+ <option name="GEN_FOLDER_RELATIVE_PATH_AIDL" value="/gen" />
9+ <option name="MANIFEST_FILE_RELATIVE_PATH" value="/app/src/main/AndroidManifest.xml" />
10+ <option name="RES_FOLDER_RELATIVE_PATH" value="/app/src/main/res" />
11+ <option name="ASSETS_FOLDER_RELATIVE_PATH" value="/app/src/main/assets" />
12+ <option name="LIBS_FOLDER_RELATIVE_PATH" value="/app/src/main/libs" />
13+ <option name="PROGUARD_LOGS_FOLDER_RELATIVE_PATH" value="/app/src/main/proguard_logs" />
14+ </configuration>
15+ </facet>
16+ </component>
17+ <component name="NewModuleRootManager" inherit-compiler-output="true">
18+ <exclude-output />
19+ <content url="file://$MODULE_DIR$">
20+ <sourceFolder url="file://$MODULE_DIR$/app/src/main/java" isTestSource="false" />
21+ <sourceFolder url="file://$MODULE_DIR$/app/src/main/kotlin" isTestSource="false" />
22+ <sourceFolder url="file://$MODULE_DIR$/gen" isTestSource="false" generated="true" />
23+ </content>
24+ <orderEntry type="jdk" jdkName="Android API 24 Platform" jdkType="Android SDK" />
25+ <orderEntry type="sourceFolder" forTests="false" />
26+ <orderEntry type="library" name="Flutter for Android" level="project" />
27+ <orderEntry type="library" name="KotlinJavaRuntime" level="project" />
28+ </component>
29+</module>
new file mode 100644
@@ -0,0 +1,29 @@
1+<?xml version="1.0" encoding="UTF-8"?>
2+<module type="JAVA_MODULE" version="4">
3+ <component name="FacetManager">
4+ <facet type="android" name="Android">
5+ <configuration>
6+ <option name="ALLOW_USER_CONFIGURATION" value="false" />
7+ <option name="GEN_FOLDER_RELATIVE_PATH_APT" value="/gen" />
8+ <option name="GEN_FOLDER_RELATIVE_PATH_AIDL" value="/gen" />
9+ <option name="MANIFEST_FILE_RELATIVE_PATH" value="/app/src/main/AndroidManifest.xml" />
10+ <option name="RES_FOLDER_RELATIVE_PATH" value="/app/src/main/res" />
11+ <option name="ASSETS_FOLDER_RELATIVE_PATH" value="/app/src/main/assets" />
12+ <option name="LIBS_FOLDER_RELATIVE_PATH" value="/app/src/main/libs" />
13+ <option name="PROGUARD_LOGS_FOLDER_RELATIVE_PATH" value="/app/src/main/proguard_logs" />
14+ </configuration>
15+ </facet>
16+ </component>
17+ <component name="NewModuleRootManager" inherit-compiler-output="true">
18+ <exclude-output />
19+ <content url="file://$MODULE_DIR$">
20+ <sourceFolder url="file://$MODULE_DIR$/app/src/main/java" isTestSource="false" />
21+ <sourceFolder url="file://$MODULE_DIR$/app/src/main/kotlin" isTestSource="false" />
22+ <sourceFolder url="file://$MODULE_DIR$/gen" isTestSource="false" generated="true" />
23+ </content>
24+ <orderEntry type="jdk" jdkName="Android API 24 Platform" jdkType="Android SDK" />
25+ <orderEntry type="sourceFolder" forTests="false" />
26+ <orderEntry type="library" name="Flutter for Android" level="project" />
27+ <orderEntry type="library" name="KotlinJavaRuntime" level="project" />
28+ </component>
29+</module>
added flutter/android/gradle.properties +6 -0
new file mode 100644
@@ -0,0 +1,6 @@
1+org.gradle.jvmargs=-Xmx8G -XX:MaxMetaspaceSize=4G -XX:ReservedCodeCacheSize=512m -XX:+HeapDumpOnOutOfMemoryError
2+android.useAndroidX=true
3+# This newDsl flag was added by the Flutter template
4+android.newDsl=false
5+# This builtInKotlin flag was added by the Flutter template
6+android.builtInKotlin=false
new file mode 100644
@@ -0,0 +1,6 @@
1+org.gradle.jvmargs=-Xmx8G -XX:MaxMetaspaceSize=4G -XX:ReservedCodeCacheSize=512m -XX:+HeapDumpOnOutOfMemoryError
2+android.useAndroidX=true
3+# This newDsl flag was added by the Flutter template
4+android.newDsl=false
5+# This builtInKotlin flag was added by the Flutter template
6+android.builtInKotlin=false
added flutter/android/gradle/wrapper/gradle-wrapper.properties +5 -0
new file mode 100644
@@ -0,0 +1,5 @@
1+distributionBase=GRADLE_USER_HOME
2+distributionPath=wrapper/dists
3+zipStoreBase=GRADLE_USER_HOME
4+zipStorePath=wrapper/dists
5+distributionUrl=https\://services.gradle.org/distributions/gradle-9.3.1-all.zip
new file mode 100644
@@ -0,0 +1,5 @@
1+distributionBase=GRADLE_USER_HOME
2+distributionPath=wrapper/dists
3+zipStoreBase=GRADLE_USER_HOME
4+zipStorePath=wrapper/dists
5+distributionUrl=https\://services.gradle.org/distributions/gradle-9.3.1-all.zip
added flutter/android/settings.gradle.kts +26 -0
new file mode 100644
@@ -0,0 +1,26 @@
1+pluginManagement {
2+ val flutterSdkPath =
3+ run {
4+ val properties = java.util.Properties()
5+ file("local.properties").inputStream().use { properties.load(it) }
6+ val flutterSdkPath = properties.getProperty("flutter.sdk")
7+ require(flutterSdkPath != null) { "flutter.sdk not set in local.properties" }
8+ flutterSdkPath
9+ }
10+
11+ includeBuild("$flutterSdkPath/packages/flutter_tools/gradle")
12+
13+ repositories {
14+ google()
15+ mavenCentral()
16+ gradlePluginPortal()
17+ }
18+}
19+
20+plugins {
21+ id("dev.flutter.flutter-plugin-loader") version "1.0.0"
22+ id("com.android.application") version "9.1.0" apply false
23+ id("org.jetbrains.kotlin.android") version "2.4.0" apply false
24+}
25+
26+include(":app")
new file mode 100644
@@ -0,0 +1,26 @@
1+pluginManagement {
2+ val flutterSdkPath =
3+ run {
4+ val properties = java.util.Properties()
5+ file("local.properties").inputStream().use { properties.load(it) }
6+ val flutterSdkPath = properties.getProperty("flutter.sdk")
7+ require(flutterSdkPath != null) { "flutter.sdk not set in local.properties" }
8+ flutterSdkPath
9+ }
10+
11+ includeBuild("$flutterSdkPath/packages/flutter_tools/gradle")
12+
13+ repositories {
14+ google()
15+ mavenCentral()
16+ gradlePluginPortal()
17+ }
18+}
19+
20+plugins {
21+ id("dev.flutter.flutter-plugin-loader") version "1.0.0"
22+ id("com.android.application") version "9.1.0" apply false
23+ id("org.jetbrains.kotlin.android") version "2.4.0" apply false
24+}
25+
26+include(":app")
modified flutter/deps.edn +3 -2
@@ -8,8 +8,9 @@
88
99 :deps {tensegritics/clojuredart
1010 {:git/url "https://github.com/Tensegritics/ClojureDart.git"
11- ;; UNPINNED. Nothing builds this yet — see flutter/README.md.
12- :git/sha "PIN-ME"}}
11+ ;; ClojureDart HEAD as of 2026-09-12. It has no releases; a sha is
12+ ;; the only pin there is.
13+ :git/sha "dfa7a0c83e0902aae23df992ded3fb7f8b577bc6"}}
1314
1415 :aliases {:cljd {:main-opts ["-m" "cljd.build"]}}
1516
@@ -8,8 +8,9 @@
8 8
9 :deps {tensegritics/clojuredart9 :deps {tensegritics/clojuredart
10 {:git/url "https://github.com/Tensegritics/ClojureDart.git"10 {:git/url "https://github.com/Tensegritics/ClojureDart.git"
11- ;; UNPINNED. Nothing builds this yet — see flutter/README.md.11+ ;; ClojureDart HEAD as of 2026-09-12. It has no releases; a sha is
12- :git/sha "PIN-ME"}}12+ ;; the only pin there is.
13+ :git/sha "dfa7a0c83e0902aae23df992ded3fb7f8b577bc6"}}
13 14
14 :aliases {:cljd {:main-opts ["-m" "cljd.build"]}}15 :aliases {:cljd {:main-opts ["-m" "cljd.build"]}}
15 16
added flutter/lib/main.dart +1 -0
new file mode 100644
@@ -0,0 +1 @@
1+export "cljd-out/frq/main.dart" show main;
new file mode 100644
@@ -0,0 +1 @@
1+export "cljd-out/frq/main.dart" show main;
added flutter/linux/.gitignore +1 -0
new file mode 100644
@@ -0,0 +1 @@
1+flutter/ephemeral
new file mode 100644
@@ -0,0 +1 @@
1+flutter/ephemeral
added flutter/linux/CMakeLists.txt +128 -0
new file mode 100644
@@ -0,0 +1,128 @@
1+# Project-level configuration.
2+cmake_minimum_required(VERSION 3.13)
3+project(runner LANGUAGES CXX)
4+
5+# The name of the executable created for the application. Change this to change
6+# the on-disk name of your application.
7+set(BINARY_NAME "cljd_flutter")
8+# The unique GTK application identifier for this application. See:
9+# https://wiki.gnome.org/HowDoI/ChooseApplicationID
10+set(APPLICATION_ID "com.example.cljd_flutter")
11+
12+# Explicitly opt in to modern CMake behaviors to avoid warnings with recent
13+# versions of CMake.
14+cmake_policy(SET CMP0063 NEW)
15+
16+# Load bundled libraries from the lib/ directory relative to the binary.
17+set(CMAKE_INSTALL_RPATH "$ORIGIN/lib")
18+
19+# Root filesystem for cross-building.
20+if(FLUTTER_TARGET_PLATFORM_SYSROOT)
21+ set(CMAKE_SYSROOT ${FLUTTER_TARGET_PLATFORM_SYSROOT})
22+ set(CMAKE_FIND_ROOT_PATH ${CMAKE_SYSROOT})
23+ set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
24+ set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY)
25+ set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
26+ set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
27+endif()
28+
29+# Define build configuration options.
30+if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES)
31+ set(CMAKE_BUILD_TYPE "Debug" CACHE
32+ STRING "Flutter build mode" FORCE)
33+ set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS
34+ "Debug" "Profile" "Release")
35+endif()
36+
37+# Compilation settings that should be applied to most targets.
38+#
39+# Be cautious about adding new options here, as plugins use this function by
40+# default. In most cases, you should add new options to specific targets instead
41+# of modifying this function.
42+function(APPLY_STANDARD_SETTINGS TARGET)
43+ target_compile_features(${TARGET} PUBLIC cxx_std_14)
44+ target_compile_options(${TARGET} PRIVATE -Wall -Werror)
45+ target_compile_options(${TARGET} PRIVATE "$<$<NOT:$<CONFIG:Debug>>:-O3>")
46+ target_compile_definitions(${TARGET} PRIVATE "$<$<NOT:$<CONFIG:Debug>>:NDEBUG>")
47+endfunction()
48+
49+# Flutter library and tool build rules.
50+set(FLUTTER_MANAGED_DIR "${CMAKE_CURRENT_SOURCE_DIR}/flutter")
51+add_subdirectory(${FLUTTER_MANAGED_DIR})
52+
53+# System-level dependencies.
54+find_package(PkgConfig REQUIRED)
55+pkg_check_modules(GTK REQUIRED IMPORTED_TARGET gtk+-3.0)
56+
57+# Application build; see runner/CMakeLists.txt.
58+add_subdirectory("runner")
59+
60+# Run the Flutter tool portions of the build. This must not be removed.
61+add_dependencies(${BINARY_NAME} flutter_assemble)
62+
63+# Only the install-generated bundle's copy of the executable will launch
64+# correctly, since the resources must in the right relative locations. To avoid
65+# people trying to run the unbundled copy, put it in a subdirectory instead of
66+# the default top-level location.
67+set_target_properties(${BINARY_NAME}
68+ PROPERTIES
69+ RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/intermediates_do_not_run"
70+)
71+
72+
73+# Generated plugin build rules, which manage building the plugins and adding
74+# them to the application.
75+include(flutter/generated_plugins.cmake)
76+
77+
78+# === Installation ===
79+# By default, "installing" just makes a relocatable bundle in the build
80+# directory.
81+set(BUILD_BUNDLE_DIR "${PROJECT_BINARY_DIR}/bundle")
82+if(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT)
83+ set(CMAKE_INSTALL_PREFIX "${BUILD_BUNDLE_DIR}" CACHE PATH "..." FORCE)
84+endif()
85+
86+# Start with a clean build bundle directory every time.
87+install(CODE "
88+ file(REMOVE_RECURSE \"${BUILD_BUNDLE_DIR}/\")
89+ " COMPONENT Runtime)
90+
91+set(INSTALL_BUNDLE_DATA_DIR "${CMAKE_INSTALL_PREFIX}/data")
92+set(INSTALL_BUNDLE_LIB_DIR "${CMAKE_INSTALL_PREFIX}/lib")
93+
94+install(TARGETS ${BINARY_NAME} RUNTIME DESTINATION "${CMAKE_INSTALL_PREFIX}"
95+ COMPONENT Runtime)
96+
97+install(FILES "${FLUTTER_ICU_DATA_FILE}" DESTINATION "${INSTALL_BUNDLE_DATA_DIR}"
98+ COMPONENT Runtime)
99+
100+install(FILES "${FLUTTER_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}"
101+ COMPONENT Runtime)
102+
103+foreach(bundled_library ${PLUGIN_BUNDLED_LIBRARIES})
104+ install(FILES "${bundled_library}"
105+ DESTINATION "${INSTALL_BUNDLE_LIB_DIR}"
106+ COMPONENT Runtime)
107+endforeach(bundled_library)
108+
109+# Copy the native assets provided by the build.dart from all packages.
110+set(NATIVE_ASSETS_DIR "${PROJECT_BUILD_DIR}native_assets/linux/")
111+install(DIRECTORY "${NATIVE_ASSETS_DIR}"
112+ DESTINATION "${INSTALL_BUNDLE_LIB_DIR}"
113+ COMPONENT Runtime)
114+
115+# Fully re-copy the assets directory on each build to avoid having stale files
116+# from a previous install.
117+set(FLUTTER_ASSET_DIR_NAME "flutter_assets")
118+install(CODE "
119+ file(REMOVE_RECURSE \"${INSTALL_BUNDLE_DATA_DIR}/${FLUTTER_ASSET_DIR_NAME}\")
120+ " COMPONENT Runtime)
121+install(DIRECTORY "${PROJECT_BUILD_DIR}/${FLUTTER_ASSET_DIR_NAME}"
122+ DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" COMPONENT Runtime)
123+
124+# Install the AOT library on non-Debug builds only.
125+if(NOT CMAKE_BUILD_TYPE MATCHES "Debug")
126+ install(FILES "${AOT_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}"
127+ COMPONENT Runtime)
128+endif()
new file mode 100644
@@ -0,0 +1,128 @@
1+# Project-level configuration.
2+cmake_minimum_required(VERSION 3.13)
3+project(runner LANGUAGES CXX)
4+
5+# The name of the executable created for the application. Change this to change
6+# the on-disk name of your application.
7+set(BINARY_NAME "cljd_flutter")
8+# The unique GTK application identifier for this application. See:
9+# https://wiki.gnome.org/HowDoI/ChooseApplicationID
10+set(APPLICATION_ID "com.example.cljd_flutter")
11+
12+# Explicitly opt in to modern CMake behaviors to avoid warnings with recent
13+# versions of CMake.
14+cmake_policy(SET CMP0063 NEW)
15+
16+# Load bundled libraries from the lib/ directory relative to the binary.
17+set(CMAKE_INSTALL_RPATH "$ORIGIN/lib")
18+
19+# Root filesystem for cross-building.
20+if(FLUTTER_TARGET_PLATFORM_SYSROOT)
21+ set(CMAKE_SYSROOT ${FLUTTER_TARGET_PLATFORM_SYSROOT})
22+ set(CMAKE_FIND_ROOT_PATH ${CMAKE_SYSROOT})
23+ set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
24+ set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY)
25+ set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
26+ set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
27+endif()
28+
29+# Define build configuration options.
30+if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES)
31+ set(CMAKE_BUILD_TYPE "Debug" CACHE
32+ STRING "Flutter build mode" FORCE)
33+ set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS
34+ "Debug" "Profile" "Release")
35+endif()
36+
37+# Compilation settings that should be applied to most targets.
38+#
39+# Be cautious about adding new options here, as plugins use this function by
40+# default. In most cases, you should add new options to specific targets instead
41+# of modifying this function.
42+function(APPLY_STANDARD_SETTINGS TARGET)
43+ target_compile_features(${TARGET} PUBLIC cxx_std_14)
44+ target_compile_options(${TARGET} PRIVATE -Wall -Werror)
45+ target_compile_options(${TARGET} PRIVATE "$<$<NOT:$<CONFIG:Debug>>:-O3>")
46+ target_compile_definitions(${TARGET} PRIVATE "$<$<NOT:$<CONFIG:Debug>>:NDEBUG>")
47+endfunction()
48+
49+# Flutter library and tool build rules.
50+set(FLUTTER_MANAGED_DIR "${CMAKE_CURRENT_SOURCE_DIR}/flutter")
51+add_subdirectory(${FLUTTER_MANAGED_DIR})
52+
53+# System-level dependencies.
54+find_package(PkgConfig REQUIRED)
55+pkg_check_modules(GTK REQUIRED IMPORTED_TARGET gtk+-3.0)
56+
57+# Application build; see runner/CMakeLists.txt.
58+add_subdirectory("runner")
59+
60+# Run the Flutter tool portions of the build. This must not be removed.
61+add_dependencies(${BINARY_NAME} flutter_assemble)
62+
63+# Only the install-generated bundle's copy of the executable will launch
64+# correctly, since the resources must in the right relative locations. To avoid
65+# people trying to run the unbundled copy, put it in a subdirectory instead of
66+# the default top-level location.
67+set_target_properties(${BINARY_NAME}
68+ PROPERTIES
69+ RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/intermediates_do_not_run"
70+)
71+
72+
73+# Generated plugin build rules, which manage building the plugins and adding
74+# them to the application.
75+include(flutter/generated_plugins.cmake)
76+
77+
78+# === Installation ===
79+# By default, "installing" just makes a relocatable bundle in the build
80+# directory.
81+set(BUILD_BUNDLE_DIR "${PROJECT_BINARY_DIR}/bundle")
82+if(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT)
83+ set(CMAKE_INSTALL_PREFIX "${BUILD_BUNDLE_DIR}" CACHE PATH "..." FORCE)
84+endif()
85+
86+# Start with a clean build bundle directory every time.
87+install(CODE "
88+ file(REMOVE_RECURSE \"${BUILD_BUNDLE_DIR}/\")
89+ " COMPONENT Runtime)
90+
91+set(INSTALL_BUNDLE_DATA_DIR "${CMAKE_INSTALL_PREFIX}/data")
92+set(INSTALL_BUNDLE_LIB_DIR "${CMAKE_INSTALL_PREFIX}/lib")
93+
94+install(TARGETS ${BINARY_NAME} RUNTIME DESTINATION "${CMAKE_INSTALL_PREFIX}"
95+ COMPONENT Runtime)
96+
97+install(FILES "${FLUTTER_ICU_DATA_FILE}" DESTINATION "${INSTALL_BUNDLE_DATA_DIR}"
98+ COMPONENT Runtime)
99+
100+install(FILES "${FLUTTER_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}"
101+ COMPONENT Runtime)
102+
103+foreach(bundled_library ${PLUGIN_BUNDLED_LIBRARIES})
104+ install(FILES "${bundled_library}"
105+ DESTINATION "${INSTALL_BUNDLE_LIB_DIR}"
106+ COMPONENT Runtime)
107+endforeach(bundled_library)
108+
109+# Copy the native assets provided by the build.dart from all packages.
110+set(NATIVE_ASSETS_DIR "${PROJECT_BUILD_DIR}native_assets/linux/")
111+install(DIRECTORY "${NATIVE_ASSETS_DIR}"
112+ DESTINATION "${INSTALL_BUNDLE_LIB_DIR}"
113+ COMPONENT Runtime)
114+
115+# Fully re-copy the assets directory on each build to avoid having stale files
116+# from a previous install.
117+set(FLUTTER_ASSET_DIR_NAME "flutter_assets")
118+install(CODE "
119+ file(REMOVE_RECURSE \"${INSTALL_BUNDLE_DATA_DIR}/${FLUTTER_ASSET_DIR_NAME}\")
120+ " COMPONENT Runtime)
121+install(DIRECTORY "${PROJECT_BUILD_DIR}/${FLUTTER_ASSET_DIR_NAME}"
122+ DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" COMPONENT Runtime)
123+
124+# Install the AOT library on non-Debug builds only.
125+if(NOT CMAKE_BUILD_TYPE MATCHES "Debug")
126+ install(FILES "${AOT_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}"
127+ COMPONENT Runtime)
128+endif()
added flutter/linux/flutter/CMakeLists.txt +88 -0
new file mode 100644
@@ -0,0 +1,88 @@
1+# This file controls Flutter-level build steps. It should not be edited.
2+cmake_minimum_required(VERSION 3.10)
3+
4+set(EPHEMERAL_DIR "${CMAKE_CURRENT_SOURCE_DIR}/ephemeral")
5+
6+# Configuration provided via flutter tool.
7+include(${EPHEMERAL_DIR}/generated_config.cmake)
8+
9+# TODO: Move the rest of this into files in ephemeral. See
10+# https://github.com/flutter/flutter/issues/57146.
11+
12+# Serves the same purpose as list(TRANSFORM ... PREPEND ...),
13+# which isn't available in 3.10.
14+function(list_prepend LIST_NAME PREFIX)
15+ set(NEW_LIST "")
16+ foreach(element ${${LIST_NAME}})
17+ list(APPEND NEW_LIST "${PREFIX}${element}")
18+ endforeach(element)
19+ set(${LIST_NAME} "${NEW_LIST}" PARENT_SCOPE)
20+endfunction()
21+
22+# === Flutter Library ===
23+# System-level dependencies.
24+find_package(PkgConfig REQUIRED)
25+pkg_check_modules(GTK REQUIRED IMPORTED_TARGET gtk+-3.0)
26+pkg_check_modules(GLIB REQUIRED IMPORTED_TARGET glib-2.0)
27+pkg_check_modules(GIO REQUIRED IMPORTED_TARGET gio-2.0)
28+
29+set(FLUTTER_LIBRARY "${EPHEMERAL_DIR}/libflutter_linux_gtk.so")
30+
31+# Published to parent scope for install step.
32+set(FLUTTER_LIBRARY ${FLUTTER_LIBRARY} PARENT_SCOPE)
33+set(FLUTTER_ICU_DATA_FILE "${EPHEMERAL_DIR}/icudtl.dat" PARENT_SCOPE)
34+set(PROJECT_BUILD_DIR "${PROJECT_DIR}/build/" PARENT_SCOPE)
35+set(AOT_LIBRARY "${PROJECT_DIR}/build/lib/libapp.so" PARENT_SCOPE)
36+
37+list(APPEND FLUTTER_LIBRARY_HEADERS
38+ "fl_basic_message_channel.h"
39+ "fl_binary_codec.h"
40+ "fl_binary_messenger.h"
41+ "fl_dart_project.h"
42+ "fl_engine.h"
43+ "fl_json_message_codec.h"
44+ "fl_json_method_codec.h"
45+ "fl_message_codec.h"
46+ "fl_method_call.h"
47+ "fl_method_channel.h"
48+ "fl_method_codec.h"
49+ "fl_method_response.h"
50+ "fl_plugin_registrar.h"
51+ "fl_plugin_registry.h"
52+ "fl_standard_message_codec.h"
53+ "fl_standard_method_codec.h"
54+ "fl_string_codec.h"
55+ "fl_value.h"
56+ "fl_view.h"
57+ "flutter_linux.h"
58+)
59+list_prepend(FLUTTER_LIBRARY_HEADERS "${EPHEMERAL_DIR}/flutter_linux/")
60+add_library(flutter INTERFACE)
61+target_include_directories(flutter INTERFACE
62+ "${EPHEMERAL_DIR}"
63+)
64+target_link_libraries(flutter INTERFACE "${FLUTTER_LIBRARY}")
65+target_link_libraries(flutter INTERFACE
66+ PkgConfig::GTK
67+ PkgConfig::GLIB
68+ PkgConfig::GIO
69+)
70+add_dependencies(flutter flutter_assemble)
71+
72+# === Flutter tool backend ===
73+# _phony_ is a non-existent file to force this command to run every time,
74+# since currently there's no way to get a full input/output list from the
75+# flutter tool.
76+add_custom_command(
77+ OUTPUT ${FLUTTER_LIBRARY} ${FLUTTER_LIBRARY_HEADERS}
78+ ${CMAKE_CURRENT_BINARY_DIR}/_phony_
79+ COMMAND ${CMAKE_COMMAND} -E env
80+ ${FLUTTER_TOOL_ENVIRONMENT}
81+ "${FLUTTER_ROOT}/packages/flutter_tools/bin/tool_backend.sh"
82+ ${FLUTTER_TARGET_PLATFORM} ${CMAKE_BUILD_TYPE}
83+ VERBATIM
84+)
85+add_custom_target(flutter_assemble DEPENDS
86+ "${FLUTTER_LIBRARY}"
87+ ${FLUTTER_LIBRARY_HEADERS}
88+)
new file mode 100644
@@ -0,0 +1,88 @@
1+# This file controls Flutter-level build steps. It should not be edited.
2+cmake_minimum_required(VERSION 3.10)
3+
4+set(EPHEMERAL_DIR "${CMAKE_CURRENT_SOURCE_DIR}/ephemeral")
5+
6+# Configuration provided via flutter tool.
7+include(${EPHEMERAL_DIR}/generated_config.cmake)
8+
9+# TODO: Move the rest of this into files in ephemeral. See
10+# https://github.com/flutter/flutter/issues/57146.
11+
12+# Serves the same purpose as list(TRANSFORM ... PREPEND ...),
13+# which isn't available in 3.10.
14+function(list_prepend LIST_NAME PREFIX)
15+ set(NEW_LIST "")
16+ foreach(element ${${LIST_NAME}})
17+ list(APPEND NEW_LIST "${PREFIX}${element}")
18+ endforeach(element)
19+ set(${LIST_NAME} "${NEW_LIST}" PARENT_SCOPE)
20+endfunction()
21+
22+# === Flutter Library ===
23+# System-level dependencies.
24+find_package(PkgConfig REQUIRED)
25+pkg_check_modules(GTK REQUIRED IMPORTED_TARGET gtk+-3.0)
26+pkg_check_modules(GLIB REQUIRED IMPORTED_TARGET glib-2.0)
27+pkg_check_modules(GIO REQUIRED IMPORTED_TARGET gio-2.0)
28+
29+set(FLUTTER_LIBRARY "${EPHEMERAL_DIR}/libflutter_linux_gtk.so")
30+
31+# Published to parent scope for install step.
32+set(FLUTTER_LIBRARY ${FLUTTER_LIBRARY} PARENT_SCOPE)
33+set(FLUTTER_ICU_DATA_FILE "${EPHEMERAL_DIR}/icudtl.dat" PARENT_SCOPE)
34+set(PROJECT_BUILD_DIR "${PROJECT_DIR}/build/" PARENT_SCOPE)
35+set(AOT_LIBRARY "${PROJECT_DIR}/build/lib/libapp.so" PARENT_SCOPE)
36+
37+list(APPEND FLUTTER_LIBRARY_HEADERS
38+ "fl_basic_message_channel.h"
39+ "fl_binary_codec.h"
40+ "fl_binary_messenger.h"
41+ "fl_dart_project.h"
42+ "fl_engine.h"
43+ "fl_json_message_codec.h"
44+ "fl_json_method_codec.h"
45+ "fl_message_codec.h"
46+ "fl_method_call.h"
47+ "fl_method_channel.h"
48+ "fl_method_codec.h"
49+ "fl_method_response.h"
50+ "fl_plugin_registrar.h"
51+ "fl_plugin_registry.h"
52+ "fl_standard_message_codec.h"
53+ "fl_standard_method_codec.h"
54+ "fl_string_codec.h"
55+ "fl_value.h"
56+ "fl_view.h"
57+ "flutter_linux.h"
58+)
59+list_prepend(FLUTTER_LIBRARY_HEADERS "${EPHEMERAL_DIR}/flutter_linux/")
60+add_library(flutter INTERFACE)
61+target_include_directories(flutter INTERFACE
62+ "${EPHEMERAL_DIR}"
63+)
64+target_link_libraries(flutter INTERFACE "${FLUTTER_LIBRARY}")
65+target_link_libraries(flutter INTERFACE
66+ PkgConfig::GTK
67+ PkgConfig::GLIB
68+ PkgConfig::GIO
69+)
70+add_dependencies(flutter flutter_assemble)
71+
72+# === Flutter tool backend ===
73+# _phony_ is a non-existent file to force this command to run every time,
74+# since currently there's no way to get a full input/output list from the
75+# flutter tool.
76+add_custom_command(
77+ OUTPUT ${FLUTTER_LIBRARY} ${FLUTTER_LIBRARY_HEADERS}
78+ ${CMAKE_CURRENT_BINARY_DIR}/_phony_
79+ COMMAND ${CMAKE_COMMAND} -E env
80+ ${FLUTTER_TOOL_ENVIRONMENT}
81+ "${FLUTTER_ROOT}/packages/flutter_tools/bin/tool_backend.sh"
82+ ${FLUTTER_TARGET_PLATFORM} ${CMAKE_BUILD_TYPE}
83+ VERBATIM
84+)
85+add_custom_target(flutter_assemble DEPENDS
86+ "${FLUTTER_LIBRARY}"
87+ ${FLUTTER_LIBRARY_HEADERS}
88+)
added flutter/linux/flutter/generated_plugin_registrant.cc +11 -0
new file mode 100644
@@ -0,0 +1,11 @@
1+//
2+// Generated file. Do not edit.
3+//
4+
5+// clang-format off
6+
7+#include "generated_plugin_registrant.h"
8+
9+
10+void fl_register_plugins(FlPluginRegistry* registry) {
11+}
new file mode 100644
@@ -0,0 +1,11 @@
1+//
2+// Generated file. Do not edit.
3+//
4+
5+// clang-format off
6+
7+#include "generated_plugin_registrant.h"
8+
9+
10+void fl_register_plugins(FlPluginRegistry* registry) {
11+}
added flutter/linux/flutter/generated_plugin_registrant.h +15 -0
new file mode 100644
@@ -0,0 +1,15 @@
1+//
2+// Generated file. Do not edit.
3+//
4+
5+// clang-format off
6+
7+#ifndef GENERATED_PLUGIN_REGISTRANT_
8+#define GENERATED_PLUGIN_REGISTRANT_
9+
10+#include <flutter_linux/flutter_linux.h>
11+
12+// Registers Flutter plugins.
13+void fl_register_plugins(FlPluginRegistry* registry);
14+
15+#endif // GENERATED_PLUGIN_REGISTRANT_
new file mode 100644
@@ -0,0 +1,15 @@
1+//
2+// Generated file. Do not edit.
3+//
4+
5+// clang-format off
6+
7+#ifndef GENERATED_PLUGIN_REGISTRANT_
8+#define GENERATED_PLUGIN_REGISTRANT_
9+
10+#include <flutter_linux/flutter_linux.h>
11+
12+// Registers Flutter plugins.
13+void fl_register_plugins(FlPluginRegistry* registry);
14+
15+#endif // GENERATED_PLUGIN_REGISTRANT_
added flutter/linux/flutter/generated_plugins.cmake +24 -0
new file mode 100644
@@ -0,0 +1,24 @@
1+#
2+# Generated file, do not edit.
3+#
4+
5+list(APPEND FLUTTER_PLUGIN_LIST
6+)
7+
8+list(APPEND FLUTTER_FFI_PLUGIN_LIST
9+ jni
10+)
11+
12+set(PLUGIN_BUNDLED_LIBRARIES)
13+
14+foreach(plugin ${FLUTTER_PLUGIN_LIST})
15+ add_subdirectory(flutter/ephemeral/.plugin_symlinks/${plugin}/linux plugins/${plugin})
16+ target_link_libraries(${BINARY_NAME} PRIVATE ${plugin}_plugin)
17+ list(APPEND PLUGIN_BUNDLED_LIBRARIES $<TARGET_FILE:${plugin}_plugin>)
18+ list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${plugin}_bundled_libraries})
19+endforeach(plugin)
20+
21+foreach(ffi_plugin ${FLUTTER_FFI_PLUGIN_LIST})
22+ add_subdirectory(flutter/ephemeral/.plugin_symlinks/${ffi_plugin}/linux plugins/${ffi_plugin})
23+ list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${ffi_plugin}_bundled_libraries})
24+endforeach(ffi_plugin)
new file mode 100644
@@ -0,0 +1,24 @@
1+#
2+# Generated file, do not edit.
3+#
4+
5+list(APPEND FLUTTER_PLUGIN_LIST
6+)
7+
8+list(APPEND FLUTTER_FFI_PLUGIN_LIST
9+ jni
10+)
11+
12+set(PLUGIN_BUNDLED_LIBRARIES)
13+
14+foreach(plugin ${FLUTTER_PLUGIN_LIST})
15+ add_subdirectory(flutter/ephemeral/.plugin_symlinks/${plugin}/linux plugins/${plugin})
16+ target_link_libraries(${BINARY_NAME} PRIVATE ${plugin}_plugin)
17+ list(APPEND PLUGIN_BUNDLED_LIBRARIES $<TARGET_FILE:${plugin}_plugin>)
18+ list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${plugin}_bundled_libraries})
19+endforeach(plugin)
20+
21+foreach(ffi_plugin ${FLUTTER_FFI_PLUGIN_LIST})
22+ add_subdirectory(flutter/ephemeral/.plugin_symlinks/${ffi_plugin}/linux plugins/${ffi_plugin})
23+ list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${ffi_plugin}_bundled_libraries})
24+endforeach(ffi_plugin)
added flutter/linux/runner/CMakeLists.txt +26 -0
new file mode 100644
@@ -0,0 +1,26 @@
1+cmake_minimum_required(VERSION 3.13)
2+project(runner LANGUAGES CXX)
3+
4+# Define the application target. To change its name, change BINARY_NAME in the
5+# top-level CMakeLists.txt, not the value here, or `flutter run` will no longer
6+# work.
7+#
8+# Any new source files that you add to the application should be added here.
9+add_executable(${BINARY_NAME}
10+ "main.cc"
11+ "my_application.cc"
12+ "${FLUTTER_MANAGED_DIR}/generated_plugin_registrant.cc"
13+)
14+
15+# Apply the standard set of build settings. This can be removed for applications
16+# that need different build settings.
17+apply_standard_settings(${BINARY_NAME})
18+
19+# Add preprocessor definitions for the application ID.
20+add_definitions(-DAPPLICATION_ID="${APPLICATION_ID}")
21+
22+# Add dependency libraries. Add any application-specific dependencies here.
23+target_link_libraries(${BINARY_NAME} PRIVATE flutter)
24+target_link_libraries(${BINARY_NAME} PRIVATE PkgConfig::GTK)
25+
26+target_include_directories(${BINARY_NAME} PRIVATE "${CMAKE_SOURCE_DIR}")
new file mode 100644
@@ -0,0 +1,26 @@
1+cmake_minimum_required(VERSION 3.13)
2+project(runner LANGUAGES CXX)
3+
4+# Define the application target. To change its name, change BINARY_NAME in the
5+# top-level CMakeLists.txt, not the value here, or `flutter run` will no longer
6+# work.
7+#
8+# Any new source files that you add to the application should be added here.
9+add_executable(${BINARY_NAME}
10+ "main.cc"
11+ "my_application.cc"
12+ "${FLUTTER_MANAGED_DIR}/generated_plugin_registrant.cc"
13+)
14+
15+# Apply the standard set of build settings. This can be removed for applications
16+# that need different build settings.
17+apply_standard_settings(${BINARY_NAME})
18+
19+# Add preprocessor definitions for the application ID.
20+add_definitions(-DAPPLICATION_ID="${APPLICATION_ID}")
21+
22+# Add dependency libraries. Add any application-specific dependencies here.
23+target_link_libraries(${BINARY_NAME} PRIVATE flutter)
24+target_link_libraries(${BINARY_NAME} PRIVATE PkgConfig::GTK)
25+
26+target_include_directories(${BINARY_NAME} PRIVATE "${CMAKE_SOURCE_DIR}")
added flutter/linux/runner/main.cc +6 -0
new file mode 100644
@@ -0,0 +1,6 @@
1+#include "my_application.h"
2+
3+int main(int argc, char** argv) {
4+ g_autoptr(MyApplication) app = my_application_new();
5+ return g_application_run(G_APPLICATION(app), argc, argv);
6+}
new file mode 100644
@@ -0,0 +1,6 @@
1+#include "my_application.h"
2+
3+int main(int argc, char** argv) {
4+ g_autoptr(MyApplication) app = my_application_new();
5+ return g_application_run(G_APPLICATION(app), argc, argv);
6+}
added flutter/linux/runner/my_application.cc +148 -0
new file mode 100644
@@ -0,0 +1,148 @@
1+#include "my_application.h"
2+
3+#include <flutter_linux/flutter_linux.h>
4+#ifdef GDK_WINDOWING_X11
5+#include <gdk/gdkx.h>
6+#endif
7+
8+#include "flutter/generated_plugin_registrant.h"
9+
10+struct _MyApplication {
11+ GtkApplication parent_instance;
12+ char** dart_entrypoint_arguments;
13+};
14+
15+G_DEFINE_TYPE(MyApplication, my_application, GTK_TYPE_APPLICATION)
16+
17+// Called when first Flutter frame received.
18+static void first_frame_cb(MyApplication* self, FlView* view) {
19+ gtk_widget_show(gtk_widget_get_toplevel(GTK_WIDGET(view)));
20+}
21+
22+// Implements GApplication::activate.
23+static void my_application_activate(GApplication* application) {
24+ MyApplication* self = MY_APPLICATION(application);
25+ GtkWindow* window =
26+ GTK_WINDOW(gtk_application_window_new(GTK_APPLICATION(application)));
27+
28+ // Use a header bar when running in GNOME as this is the common style used
29+ // by applications and is the setup most users will be using (e.g. Ubuntu
30+ // desktop).
31+ // If running on X and not using GNOME then just use a traditional title bar
32+ // in case the window manager does more exotic layout, e.g. tiling.
33+ // If running on Wayland assume the header bar will work (may need changing
34+ // if future cases occur).
35+ gboolean use_header_bar = TRUE;
36+#ifdef GDK_WINDOWING_X11
37+ GdkScreen* screen = gtk_window_get_screen(window);
38+ if (GDK_IS_X11_SCREEN(screen)) {
39+ const gchar* wm_name = gdk_x11_screen_get_window_manager_name(screen);
40+ if (g_strcmp0(wm_name, "GNOME Shell") != 0) {
41+ use_header_bar = FALSE;
42+ }
43+ }
44+#endif
45+ if (use_header_bar) {
46+ GtkHeaderBar* header_bar = GTK_HEADER_BAR(gtk_header_bar_new());
47+ gtk_widget_show(GTK_WIDGET(header_bar));
48+ gtk_header_bar_set_title(header_bar, "cljd_flutter");
49+ gtk_header_bar_set_show_close_button(header_bar, TRUE);
50+ gtk_window_set_titlebar(window, GTK_WIDGET(header_bar));
51+ } else {
52+ gtk_window_set_title(window, "cljd_flutter");
53+ }
54+
55+ gtk_window_set_default_size(window, 1280, 720);
56+
57+ g_autoptr(FlDartProject) project = fl_dart_project_new();
58+ fl_dart_project_set_dart_entrypoint_arguments(
59+ project, self->dart_entrypoint_arguments);
60+
61+ FlView* view = fl_view_new(project);
62+ GdkRGBA background_color;
63+ // Background defaults to black, override it here if necessary, e.g. #00000000
64+ // for transparent.
65+ gdk_rgba_parse(&background_color, "#000000");
66+ fl_view_set_background_color(view, &background_color);
67+ gtk_widget_show(GTK_WIDGET(view));
68+ gtk_container_add(GTK_CONTAINER(window), GTK_WIDGET(view));
69+
70+ // Show the window when Flutter renders.
71+ // Requires the view to be realized so we can start rendering.
72+ g_signal_connect_swapped(view, "first-frame", G_CALLBACK(first_frame_cb),
73+ self);
74+ gtk_widget_realize(GTK_WIDGET(view));
75+
76+ fl_register_plugins(FL_PLUGIN_REGISTRY(view));
77+
78+ gtk_widget_grab_focus(GTK_WIDGET(view));
79+}
80+
81+// Implements GApplication::local_command_line.
82+static gboolean my_application_local_command_line(GApplication* application,
83+ gchar*** arguments,
84+ int* exit_status) {
85+ MyApplication* self = MY_APPLICATION(application);
86+ // Strip out the first argument as it is the binary name.
87+ self->dart_entrypoint_arguments = g_strdupv(*arguments + 1);
88+
89+ g_autoptr(GError) error = nullptr;
90+ if (!g_application_register(application, nullptr, &error)) {
91+ g_warning("Failed to register: %s", error->message);
92+ *exit_status = 1;
93+ return TRUE;
94+ }
95+
96+ g_application_activate(application);
97+ *exit_status = 0;
98+
99+ return TRUE;
100+}
101+
102+// Implements GApplication::startup.
103+static void my_application_startup(GApplication* application) {
104+ // MyApplication* self = MY_APPLICATION(object);
105+
106+ // Perform any actions required at application startup.
107+
108+ G_APPLICATION_CLASS(my_application_parent_class)->startup(application);
109+}
110+
111+// Implements GApplication::shutdown.
112+static void my_application_shutdown(GApplication* application) {
113+ // MyApplication* self = MY_APPLICATION(object);
114+
115+ // Perform any actions required at application shutdown.
116+
117+ G_APPLICATION_CLASS(my_application_parent_class)->shutdown(application);
118+}
119+
120+// Implements GObject::dispose.
121+static void my_application_dispose(GObject* object) {
122+ MyApplication* self = MY_APPLICATION(object);
123+ g_clear_pointer(&self->dart_entrypoint_arguments, g_strfreev);
124+ G_OBJECT_CLASS(my_application_parent_class)->dispose(object);
125+}
126+
127+static void my_application_class_init(MyApplicationClass* klass) {
128+ G_APPLICATION_CLASS(klass)->activate = my_application_activate;
129+ G_APPLICATION_CLASS(klass)->local_command_line =
130+ my_application_local_command_line;
131+ G_APPLICATION_CLASS(klass)->startup = my_application_startup;
132+ G_APPLICATION_CLASS(klass)->shutdown = my_application_shutdown;
133+ G_OBJECT_CLASS(klass)->dispose = my_application_dispose;
134+}
135+
136+static void my_application_init(MyApplication* self) {}
137+
138+MyApplication* my_application_new() {
139+ // Set the program name to the application ID, which helps various systems
140+ // like GTK and desktop environments map this running application to its
141+ // corresponding .desktop file. This ensures better integration by allowing
142+ // the application to be recognized beyond its binary name.
143+ g_set_prgname(APPLICATION_ID);
144+
145+ return MY_APPLICATION(g_object_new(my_application_get_type(),
146+ "application-id", APPLICATION_ID, "flags",
147+ G_APPLICATION_NON_UNIQUE, nullptr));
148+}
new file mode 100644
@@ -0,0 +1,148 @@
1+#include "my_application.h"
2+
3+#include <flutter_linux/flutter_linux.h>
4+#ifdef GDK_WINDOWING_X11
5+#include <gdk/gdkx.h>
6+#endif
7+
8+#include "flutter/generated_plugin_registrant.h"
9+
10+struct _MyApplication {
11+ GtkApplication parent_instance;
12+ char** dart_entrypoint_arguments;
13+};
14+
15+G_DEFINE_TYPE(MyApplication, my_application, GTK_TYPE_APPLICATION)
16+
17+// Called when first Flutter frame received.
18+static void first_frame_cb(MyApplication* self, FlView* view) {
19+ gtk_widget_show(gtk_widget_get_toplevel(GTK_WIDGET(view)));
20+}
21+
22+// Implements GApplication::activate.
23+static void my_application_activate(GApplication* application) {
24+ MyApplication* self = MY_APPLICATION(application);
25+ GtkWindow* window =
26+ GTK_WINDOW(gtk_application_window_new(GTK_APPLICATION(application)));
27+
28+ // Use a header bar when running in GNOME as this is the common style used
29+ // by applications and is the setup most users will be using (e.g. Ubuntu
30+ // desktop).
31+ // If running on X and not using GNOME then just use a traditional title bar
32+ // in case the window manager does more exotic layout, e.g. tiling.
33+ // If running on Wayland assume the header bar will work (may need changing
34+ // if future cases occur).
35+ gboolean use_header_bar = TRUE;
36+#ifdef GDK_WINDOWING_X11
37+ GdkScreen* screen = gtk_window_get_screen(window);
38+ if (GDK_IS_X11_SCREEN(screen)) {
39+ const gchar* wm_name = gdk_x11_screen_get_window_manager_name(screen);
40+ if (g_strcmp0(wm_name, "GNOME Shell") != 0) {
41+ use_header_bar = FALSE;
42+ }
43+ }
44+#endif
45+ if (use_header_bar) {
46+ GtkHeaderBar* header_bar = GTK_HEADER_BAR(gtk_header_bar_new());
47+ gtk_widget_show(GTK_WIDGET(header_bar));
48+ gtk_header_bar_set_title(header_bar, "cljd_flutter");
49+ gtk_header_bar_set_show_close_button(header_bar, TRUE);
50+ gtk_window_set_titlebar(window, GTK_WIDGET(header_bar));
51+ } else {
52+ gtk_window_set_title(window, "cljd_flutter");
53+ }
54+
55+ gtk_window_set_default_size(window, 1280, 720);
56+
57+ g_autoptr(FlDartProject) project = fl_dart_project_new();
58+ fl_dart_project_set_dart_entrypoint_arguments(
59+ project, self->dart_entrypoint_arguments);
60+
61+ FlView* view = fl_view_new(project);
62+ GdkRGBA background_color;
63+ // Background defaults to black, override it here if necessary, e.g. #00000000
64+ // for transparent.
65+ gdk_rgba_parse(&background_color, "#000000");
66+ fl_view_set_background_color(view, &background_color);
67+ gtk_widget_show(GTK_WIDGET(view));
68+ gtk_container_add(GTK_CONTAINER(window), GTK_WIDGET(view));
69+
70+ // Show the window when Flutter renders.
71+ // Requires the view to be realized so we can start rendering.
72+ g_signal_connect_swapped(view, "first-frame", G_CALLBACK(first_frame_cb),
73+ self);
74+ gtk_widget_realize(GTK_WIDGET(view));
75+
76+ fl_register_plugins(FL_PLUGIN_REGISTRY(view));
77+
78+ gtk_widget_grab_focus(GTK_WIDGET(view));
79+}
80+
81+// Implements GApplication::local_command_line.
82+static gboolean my_application_local_command_line(GApplication* application,
83+ gchar*** arguments,
84+ int* exit_status) {
85+ MyApplication* self = MY_APPLICATION(application);
86+ // Strip out the first argument as it is the binary name.
87+ self->dart_entrypoint_arguments = g_strdupv(*arguments + 1);
88+
89+ g_autoptr(GError) error = nullptr;
90+ if (!g_application_register(application, nullptr, &error)) {
91+ g_warning("Failed to register: %s", error->message);
92+ *exit_status = 1;
93+ return TRUE;
94+ }
95+
96+ g_application_activate(application);
97+ *exit_status = 0;
98+
99+ return TRUE;
100+}
101+
102+// Implements GApplication::startup.
103+static void my_application_startup(GApplication* application) {
104+ // MyApplication* self = MY_APPLICATION(object);
105+
106+ // Perform any actions required at application startup.
107+
108+ G_APPLICATION_CLASS(my_application_parent_class)->startup(application);
109+}
110+
111+// Implements GApplication::shutdown.
112+static void my_application_shutdown(GApplication* application) {
113+ // MyApplication* self = MY_APPLICATION(object);
114+
115+ // Perform any actions required at application shutdown.
116+
117+ G_APPLICATION_CLASS(my_application_parent_class)->shutdown(application);
118+}
119+
120+// Implements GObject::dispose.
121+static void my_application_dispose(GObject* object) {
122+ MyApplication* self = MY_APPLICATION(object);
123+ g_clear_pointer(&self->dart_entrypoint_arguments, g_strfreev);
124+ G_OBJECT_CLASS(my_application_parent_class)->dispose(object);
125+}
126+
127+static void my_application_class_init(MyApplicationClass* klass) {
128+ G_APPLICATION_CLASS(klass)->activate = my_application_activate;
129+ G_APPLICATION_CLASS(klass)->local_command_line =
130+ my_application_local_command_line;
131+ G_APPLICATION_CLASS(klass)->startup = my_application_startup;
132+ G_APPLICATION_CLASS(klass)->shutdown = my_application_shutdown;
133+ G_OBJECT_CLASS(klass)->dispose = my_application_dispose;
134+}
135+
136+static void my_application_init(MyApplication* self) {}
137+
138+MyApplication* my_application_new() {
139+ // Set the program name to the application ID, which helps various systems
140+ // like GTK and desktop environments map this running application to its
141+ // corresponding .desktop file. This ensures better integration by allowing
142+ // the application to be recognized beyond its binary name.
143+ g_set_prgname(APPLICATION_ID);
144+
145+ return MY_APPLICATION(g_object_new(my_application_get_type(),
146+ "application-id", APPLICATION_ID, "flags",
147+ G_APPLICATION_NON_UNIQUE, nullptr));
148+}
added flutter/linux/runner/my_application.h +21 -0
new file mode 100644
@@ -0,0 +1,21 @@
1+#ifndef FLUTTER_MY_APPLICATION_H_
2+#define FLUTTER_MY_APPLICATION_H_
3+
4+#include <gtk/gtk.h>
5+
6+G_DECLARE_FINAL_TYPE(MyApplication,
7+ my_application,
8+ MY,
9+ APPLICATION,
10+ GtkApplication)
11+
12+/**
13+ * my_application_new:
14+ *
15+ * Creates a new Flutter-based application.
16+ *
17+ * Returns: a new #MyApplication.
18+ */
19+MyApplication* my_application_new();
20+
21+#endif // FLUTTER_MY_APPLICATION_H_
new file mode 100644
@@ -0,0 +1,21 @@
1+#ifndef FLUTTER_MY_APPLICATION_H_
2+#define FLUTTER_MY_APPLICATION_H_
3+
4+#include <gtk/gtk.h>
5+
6+G_DECLARE_FINAL_TYPE(MyApplication,
7+ my_application,
8+ MY,
9+ APPLICATION,
10+ GtkApplication)
11+
12+/**
13+ * my_application_new:
14+ *
15+ * Creates a new Flutter-based application.
16+ *
17+ * Returns: a new #MyApplication.
18+ */
19+MyApplication* my_application_new();
20+
21+#endif // FLUTTER_MY_APPLICATION_H_
added flutter/pubspec.lock +405 -0
new file mode 100644
@@ -0,0 +1,405 @@
1+# Generated by pub
2+# See https://dart.dev/tools/pub/glossary#lockfile
3+packages:
4+ args:
5+ dependency: transitive
6+ description:
7+ name: args
8+ sha256: d0481093c50b1da8910eb0bb301626d4d8eb7284aa739614d2b394ee09e3ea04
9+ url: "https://pub.dev"
10+ source: hosted
11+ version: "2.7.0"
12+ async:
13+ dependency: transitive
14+ description:
15+ name: async
16+ sha256: e2eb0491ba5ddb6177742d2da23904574082139b07c1e33b8503b9f46f3e1a37
17+ url: "https://pub.dev"
18+ source: hosted
19+ version: "2.13.1"
20+ boolean_selector:
21+ dependency: transitive
22+ description:
23+ name: boolean_selector
24+ sha256: "8aab1771e1243a5063b8b0ff68042d67334e3feab9e95b9490f9a6ebf73b42ea"
25+ url: "https://pub.dev"
26+ source: hosted
27+ version: "2.1.2"
28+ characters:
29+ dependency: transitive
30+ description:
31+ name: characters
32+ sha256: faf38497bda5ead2a8c7615f4f7939df04333478bf32e4173fcb06d428b5716b
33+ url: "https://pub.dev"
34+ source: hosted
35+ version: "1.4.1"
36+ clock:
37+ dependency: transitive
38+ description:
39+ name: clock
40+ sha256: e51d50bca3217c9a9fa2b41a30e4a38971133f5f9ec7a3d57bae095007f1d28e
41+ url: "https://pub.dev"
42+ source: hosted
43+ version: "1.1.3"
44+ code_assets:
45+ dependency: transitive
46+ description:
47+ name: code_assets
48+ sha256: bf394f466ba9205f1812a0433b392d6af280f155f56651eda7c18cc32ed493b8
49+ url: "https://pub.dev"
50+ source: hosted
51+ version: "1.2.1"
52+ collection:
53+ dependency: transitive
54+ description:
55+ name: collection
56+ sha256: "2f5709ae4d3d59dd8f7cd309b4e023046b57d8a6c82130785d2b0e5868084e76"
57+ url: "https://pub.dev"
58+ source: hosted
59+ version: "1.19.1"
60+ crypto:
61+ dependency: transitive
62+ description:
63+ name: crypto
64+ sha256: c8ea0233063ba03258fbcf2ca4d6dadfefe14f02fab57702265467a19f27fadf
65+ url: "https://pub.dev"
66+ source: hosted
67+ version: "3.0.7"
68+ cupertino_icons:
69+ dependency: "direct main"
70+ description:
71+ name: cupertino_icons
72+ sha256: "41e005c33bd814be4d3096aff55b1908d419fde52ca656c8c47719ec745873cd"
73+ url: "https://pub.dev"
74+ source: hosted
75+ version: "1.0.9"
76+ fake_async:
77+ dependency: transitive
78+ description:
79+ name: fake_async
80+ sha256: "5368f224a74523e8d2e7399ea1638b37aecfca824a3cc4dfdf77bf1fa905ac44"
81+ url: "https://pub.dev"
82+ source: hosted
83+ version: "1.3.3"
84+ ffi:
85+ dependency: transitive
86+ description:
87+ name: ffi
88+ sha256: "6d7fd89431262d8f3125e81b50d3847a091d846eafcd4fdb88dd06f36d705a45"
89+ url: "https://pub.dev"
90+ source: hosted
91+ version: "2.2.0"
92+ flutter:
93+ dependency: "direct main"
94+ description: flutter
95+ source: sdk
96+ version: "0.0.0"
97+ flutter_lints:
98+ dependency: "direct dev"
99+ description:
100+ name: flutter_lints
101+ sha256: "3105dc8492f6183fb076ccf1f351ac3d60564bff92e20bfc4af9cc1651f4e7e1"
102+ url: "https://pub.dev"
103+ source: hosted
104+ version: "6.0.0"
105+ flutter_test:
106+ dependency: "direct dev"
107+ description: flutter
108+ source: sdk
109+ version: "0.0.0"
110+ hooks:
111+ dependency: transitive
112+ description:
113+ name: hooks
114+ sha256: "9a62a50b50b769a737bc0a8ff381f333529df3ab746b2f6b02e83760231455ba"
115+ url: "https://pub.dev"
116+ source: hosted
117+ version: "2.0.2"
118+ jni:
119+ dependency: transitive
120+ description:
121+ name: jni
122+ sha256: f038e58b4dc2c9037f50e233175086337e0b305e356d28211bf55f21c504cbd3
123+ url: "https://pub.dev"
124+ source: hosted
125+ version: "1.0.3"
126+ jni_flutter:
127+ dependency: transitive
128+ description:
129+ name: jni_flutter
130+ sha256: b2310cdd4c18c65c081ab141a41efa94aa26c65431803703ece51996f174f351
131+ url: "https://pub.dev"
132+ source: hosted
133+ version: "1.0.3"
134+ jni_util:
135+ dependency: transitive
136+ description:
137+ name: jni_util
138+ sha256: "1ba86da04a5f2bf18fde2edb235587e70c5b0fc5bd4ba955f46b00942c3fc35f"
139+ url: "https://pub.dev"
140+ source: hosted
141+ version: "1.0.0"
142+ leak_tracker:
143+ dependency: transitive
144+ description:
145+ name: leak_tracker
146+ sha256: "33e2e26bdd85a0112ec15400c8cbffea70d0f9c3407491f672a2fad47915e2de"
147+ url: "https://pub.dev"
148+ source: hosted
149+ version: "11.0.2"
150+ leak_tracker_flutter_testing:
151+ dependency: transitive
152+ description:
153+ name: leak_tracker_flutter_testing
154+ sha256: "1dbc140bb5a23c75ea9c4811222756104fbcd1a27173f0c34ca01e16bea473c1"
155+ url: "https://pub.dev"
156+ source: hosted
157+ version: "3.0.10"
158+ leak_tracker_testing:
159+ dependency: transitive
160+ description:
161+ name: leak_tracker_testing
162+ sha256: "8d5a2d49f4a66b49744b23b018848400d23e54caf9463f4eb20df3eb8acb2eb1"
163+ url: "https://pub.dev"
164+ source: hosted
165+ version: "3.0.2"
166+ lints:
167+ dependency: transitive
168+ description:
169+ name: lints
170+ sha256: "12f842a479589fea194fe5c5a3095abc7be0c1f2ddfa9a0e76aed1dbd26a87df"
171+ url: "https://pub.dev"
172+ source: hosted
173+ version: "6.1.0"
174+ logging:
175+ dependency: transitive
176+ description:
177+ name: logging
178+ sha256: c8245ada5f1717ed44271ed1c26b8ce85ca3228fd2ffdb75468ab01979309d61
179+ url: "https://pub.dev"
180+ source: hosted
181+ version: "1.3.0"
182+ matcher:
183+ dependency: transitive
184+ description:
185+ name: matcher
186+ sha256: "31bd099b47c10cd1aeb55146a2d46ce0277630ecef3f7dae54ad7873f36696cd"
187+ url: "https://pub.dev"
188+ source: hosted
189+ version: "0.12.20"
190+ material_color_utilities:
191+ dependency: transitive
192+ description:
193+ name: material_color_utilities
194+ sha256: "9c337007e82b1889149c82ed242ed1cb24a66044e30979c44912381e9be4c48b"
195+ url: "https://pub.dev"
196+ source: hosted
197+ version: "0.13.0"
198+ meta:
199+ dependency: transitive
200+ description:
201+ name: meta
202+ sha256: c82594181e3312f3d0695fc95aaaf7758d75b8d4ae2bbecf223b9fd5109a059d
203+ url: "https://pub.dev"
204+ source: hosted
205+ version: "1.18.3"
206+ objective_c:
207+ dependency: transitive
208+ description:
209+ name: objective_c
210+ sha256: b7fb95a6d9a4f009edd63dc5ac69f07420b23a16161c6dd8660290b59c602e8e
211+ url: "https://pub.dev"
212+ source: hosted
213+ version: "9.5.0"
214+ package_config:
215+ dependency: transitive
216+ description:
217+ name: package_config
218+ sha256: ffcf4cf3d6c0b74ac43708d9f56625506e8a68aa935abe9d267a7330f320eb5d
219+ url: "https://pub.dev"
220+ source: hosted
221+ version: "3.0.0"
222+ path:
223+ dependency: transitive
224+ description:
225+ name: path
226+ sha256: "75cca69d1490965be98c73ceaea117e8a04dd21217b37b292c9ddbec0d955bc5"
227+ url: "https://pub.dev"
228+ source: hosted
229+ version: "1.9.1"
230+ path_provider:
231+ dependency: "direct main"
232+ description:
233+ name: path_provider
234+ sha256: a7f4874f987173da295a61c181b8ee71dab59b332a486b391babf26a1b884825
235+ url: "https://pub.dev"
236+ source: hosted
237+ version: "2.1.6"
238+ path_provider_android:
239+ dependency: transitive
240+ description:
241+ name: path_provider_android
242+ sha256: "69cbd515a62b94d32a7944f086b2f82b4ac40a1d45bebfc00813a430ab2dabcd"
243+ url: "https://pub.dev"
244+ source: hosted
245+ version: "2.3.1"
246+ path_provider_foundation:
247+ dependency: transitive
248+ description:
249+ name: path_provider_foundation
250+ sha256: "2a376b7d6392d80cd3705782d2caa734ca4727776db0b6ec36ef3f1855197699"
251+ url: "https://pub.dev"
252+ source: hosted
253+ version: "2.6.0"
254+ path_provider_linux:
255+ dependency: transitive
256+ description:
257+ name: path_provider_linux
258+ sha256: "58c2005f147315b11e9b4a7bc889cd5203e250cba8e3f012dae259b4972b5c16"
259+ url: "https://pub.dev"
260+ source: hosted
261+ version: "2.2.2"
262+ path_provider_platform_interface:
263+ dependency: transitive
264+ description:
265+ name: path_provider_platform_interface
266+ sha256: "484838772624c3a4b94f1e44a3e19897fee738f2d5c4ce448443b0417f7c9dda"
267+ url: "https://pub.dev"
268+ source: hosted
269+ version: "2.1.3"
270+ path_provider_windows:
271+ dependency: transitive
272+ description:
273+ name: path_provider_windows
274+ sha256: bd6f00dbd873bfb70d0761682da2b3a2c2fccc2b9e84c495821639601d81afe7
275+ url: "https://pub.dev"
276+ source: hosted
277+ version: "2.3.0"
278+ platform:
279+ dependency: transitive
280+ description:
281+ name: platform
282+ sha256: a36d119c13416516a7b5913fbe8af8531e11633d784c550b2125f76c758524ec
283+ url: "https://pub.dev"
284+ source: hosted
285+ version: "3.2.0"
286+ plugin_platform_interface:
287+ dependency: transitive
288+ description:
289+ name: plugin_platform_interface
290+ sha256: "4820fbfdb9478b1ebae27888254d445073732dae3d6ea81f0b7e06d5dedc3f02"
291+ url: "https://pub.dev"
292+ source: hosted
293+ version: "2.1.8"
294+ pub_semver:
295+ dependency: transitive
296+ description:
297+ name: pub_semver
298+ sha256: "261236774e8b1d69cfc6b9eabbc96c40f25e7a2d6b171f3385d4f65d5734fb24"
299+ url: "https://pub.dev"
300+ source: hosted
301+ version: "2.2.1"
302+ record_use:
303+ dependency: transitive
304+ description:
305+ name: record_use
306+ sha256: "2551bd8eecfe95d14ae75f6021ad0248be5c27f138c2ec12fcb52b500b3ba1ed"
307+ url: "https://pub.dev"
308+ source: hosted
309+ version: "0.6.0"
310+ sky_engine:
311+ dependency: transitive
312+ description: flutter
313+ source: sdk
314+ version: "0.0.0"
315+ source_span:
316+ dependency: transitive
317+ description:
318+ name: source_span
319+ sha256: "56a02f1f4cd1a2d96303c0144c93bd6d909eea6bee6bf5a0e0b685edbd4c47ab"
320+ url: "https://pub.dev"
321+ source: hosted
322+ version: "1.10.2"
323+ stack_trace:
324+ dependency: transitive
325+ description:
326+ name: stack_trace
327+ sha256: "277654b3034d17ac6f9f1cb5595db011b1d5d41e8806866db28e0abaa101c490"
328+ url: "https://pub.dev"
329+ source: hosted
330+ version: "1.12.2"
331+ stream_channel:
332+ dependency: transitive
333+ description:
334+ name: stream_channel
335+ sha256: "969e04c80b8bcdf826f8f16579c7b14d780458bd97f56d107d3950fdbeef059d"
336+ url: "https://pub.dev"
337+ source: hosted
338+ version: "2.1.4"
339+ string_scanner:
340+ dependency: transitive
341+ description:
342+ name: string_scanner
343+ sha256: "921cd31725b72fe181906c6a94d987c78e3b98c2e205b397ea399d4054872b43"
344+ url: "https://pub.dev"
345+ source: hosted
346+ version: "1.4.1"
347+ term_glyph:
348+ dependency: transitive
349+ description:
350+ name: term_glyph
351+ sha256: "7f554798625ea768a7518313e58f83891c7f5024f88e46e7182a4558850a4b8e"
352+ url: "https://pub.dev"
353+ source: hosted
354+ version: "1.2.2"
355+ test_api:
356+ dependency: transitive
357+ description:
358+ name: test_api
359+ sha256: "2a122cbe059f8b610d3a5415f42e255b6c17b1f21eee1d960f31080237fb4f11"
360+ url: "https://pub.dev"
361+ source: hosted
362+ version: "0.7.12"
363+ typed_data:
364+ dependency: transitive
365+ description:
366+ name: typed_data
367+ sha256: f9049c039ebfeb4cf7a7104a675823cd72dba8297f264b6637062516699fa006
368+ url: "https://pub.dev"
369+ source: hosted
370+ version: "1.4.0"
371+ vector_math:
372+ dependency: transitive
373+ description:
374+ name: vector_math
375+ sha256: "1d774bbdf6b72a0b12122fc1560c9c2d2a67db5a4a4cc2bd8a5c990ab20e3188"
376+ url: "https://pub.dev"
377+ source: hosted
378+ version: "2.4.0"
379+ vm_service:
380+ dependency: transitive
381+ description:
382+ name: vm_service
383+ sha256: "5f37239c4851efcef929cea7824e76df7f2f0970aef85d66bbc430afa40e72f0"
384+ url: "https://pub.dev"
385+ source: hosted
386+ version: "15.3.0"
387+ xdg_directories:
388+ dependency: transitive
389+ description:
390+ name: xdg_directories
391+ sha256: "7a3f37b05d989967cdddcbb571f1ea834867ae2faa29725fd085180e0883aa15"
392+ url: "https://pub.dev"
393+ source: hosted
394+ version: "1.1.0"
395+ yaml:
396+ dependency: transitive
397+ description:
398+ name: yaml
399+ sha256: f67cdd8e07d3c6329146aaef1ba043542b3134c12489f553ca9a7435d1068aea
400+ url: "https://pub.dev"
401+ source: hosted
402+ version: "3.1.4"
403+sdks:
404+ dart: ">=3.13.0 <4.0.0"
405+ flutter: ">=3.38.4"
new file mode 100644
@@ -0,0 +1,405 @@
1+# Generated by pub
2+# See https://dart.dev/tools/pub/glossary#lockfile
3+packages:
4+ args:
5+ dependency: transitive
6+ description:
7+ name: args
8+ sha256: d0481093c50b1da8910eb0bb301626d4d8eb7284aa739614d2b394ee09e3ea04
9+ url: "https://pub.dev"
10+ source: hosted
11+ version: "2.7.0"
12+ async:
13+ dependency: transitive
14+ description:
15+ name: async
16+ sha256: e2eb0491ba5ddb6177742d2da23904574082139b07c1e33b8503b9f46f3e1a37
17+ url: "https://pub.dev"
18+ source: hosted
19+ version: "2.13.1"
20+ boolean_selector:
21+ dependency: transitive
22+ description:
23+ name: boolean_selector
24+ sha256: "8aab1771e1243a5063b8b0ff68042d67334e3feab9e95b9490f9a6ebf73b42ea"
25+ url: "https://pub.dev"
26+ source: hosted
27+ version: "2.1.2"
28+ characters:
29+ dependency: transitive
30+ description:
31+ name: characters
32+ sha256: faf38497bda5ead2a8c7615f4f7939df04333478bf32e4173fcb06d428b5716b
33+ url: "https://pub.dev"
34+ source: hosted
35+ version: "1.4.1"
36+ clock:
37+ dependency: transitive
38+ description:
39+ name: clock
40+ sha256: e51d50bca3217c9a9fa2b41a30e4a38971133f5f9ec7a3d57bae095007f1d28e
41+ url: "https://pub.dev"
42+ source: hosted
43+ version: "1.1.3"
44+ code_assets:
45+ dependency: transitive
46+ description:
47+ name: code_assets
48+ sha256: bf394f466ba9205f1812a0433b392d6af280f155f56651eda7c18cc32ed493b8
49+ url: "https://pub.dev"
50+ source: hosted
51+ version: "1.2.1"
52+ collection:
53+ dependency: transitive
54+ description:
55+ name: collection
56+ sha256: "2f5709ae4d3d59dd8f7cd309b4e023046b57d8a6c82130785d2b0e5868084e76"
57+ url: "https://pub.dev"
58+ source: hosted
59+ version: "1.19.1"
60+ crypto:
61+ dependency: transitive
62+ description:
63+ name: crypto
64+ sha256: c8ea0233063ba03258fbcf2ca4d6dadfefe14f02fab57702265467a19f27fadf
65+ url: "https://pub.dev"
66+ source: hosted
67+ version: "3.0.7"
68+ cupertino_icons:
69+ dependency: "direct main"
70+ description:
71+ name: cupertino_icons
72+ sha256: "41e005c33bd814be4d3096aff55b1908d419fde52ca656c8c47719ec745873cd"
73+ url: "https://pub.dev"
74+ source: hosted
75+ version: "1.0.9"
76+ fake_async:
77+ dependency: transitive
78+ description:
79+ name: fake_async
80+ sha256: "5368f224a74523e8d2e7399ea1638b37aecfca824a3cc4dfdf77bf1fa905ac44"
81+ url: "https://pub.dev"
82+ source: hosted
83+ version: "1.3.3"
84+ ffi:
85+ dependency: transitive
86+ description:
87+ name: ffi
88+ sha256: "6d7fd89431262d8f3125e81b50d3847a091d846eafcd4fdb88dd06f36d705a45"
89+ url: "https://pub.dev"
90+ source: hosted
91+ version: "2.2.0"
92+ flutter:
93+ dependency: "direct main"
94+ description: flutter
95+ source: sdk
96+ version: "0.0.0"
97+ flutter_lints:
98+ dependency: "direct dev"
99+ description:
100+ name: flutter_lints
101+ sha256: "3105dc8492f6183fb076ccf1f351ac3d60564bff92e20bfc4af9cc1651f4e7e1"
102+ url: "https://pub.dev"
103+ source: hosted
104+ version: "6.0.0"
105+ flutter_test:
106+ dependency: "direct dev"
107+ description: flutter
108+ source: sdk
109+ version: "0.0.0"
110+ hooks:
111+ dependency: transitive
112+ description:
113+ name: hooks
114+ sha256: "9a62a50b50b769a737bc0a8ff381f333529df3ab746b2f6b02e83760231455ba"
115+ url: "https://pub.dev"
116+ source: hosted
117+ version: "2.0.2"
118+ jni:
119+ dependency: transitive
120+ description:
121+ name: jni
122+ sha256: f038e58b4dc2c9037f50e233175086337e0b305e356d28211bf55f21c504cbd3
123+ url: "https://pub.dev"
124+ source: hosted
125+ version: "1.0.3"
126+ jni_flutter:
127+ dependency: transitive
128+ description:
129+ name: jni_flutter
130+ sha256: b2310cdd4c18c65c081ab141a41efa94aa26c65431803703ece51996f174f351
131+ url: "https://pub.dev"
132+ source: hosted
133+ version: "1.0.3"
134+ jni_util:
135+ dependency: transitive
136+ description:
137+ name: jni_util
138+ sha256: "1ba86da04a5f2bf18fde2edb235587e70c5b0fc5bd4ba955f46b00942c3fc35f"
139+ url: "https://pub.dev"
140+ source: hosted
141+ version: "1.0.0"
142+ leak_tracker:
143+ dependency: transitive
144+ description:
145+ name: leak_tracker
146+ sha256: "33e2e26bdd85a0112ec15400c8cbffea70d0f9c3407491f672a2fad47915e2de"
147+ url: "https://pub.dev"
148+ source: hosted
149+ version: "11.0.2"
150+ leak_tracker_flutter_testing:
151+ dependency: transitive
152+ description:
153+ name: leak_tracker_flutter_testing
154+ sha256: "1dbc140bb5a23c75ea9c4811222756104fbcd1a27173f0c34ca01e16bea473c1"
155+ url: "https://pub.dev"
156+ source: hosted
157+ version: "3.0.10"
158+ leak_tracker_testing:
159+ dependency: transitive
160+ description:
161+ name: leak_tracker_testing
162+ sha256: "8d5a2d49f4a66b49744b23b018848400d23e54caf9463f4eb20df3eb8acb2eb1"
163+ url: "https://pub.dev"
164+ source: hosted
165+ version: "3.0.2"
166+ lints:
167+ dependency: transitive
168+ description:
169+ name: lints
170+ sha256: "12f842a479589fea194fe5c5a3095abc7be0c1f2ddfa9a0e76aed1dbd26a87df"
171+ url: "https://pub.dev"
172+ source: hosted
173+ version: "6.1.0"
174+ logging:
175+ dependency: transitive
176+ description:
177+ name: logging
178+ sha256: c8245ada5f1717ed44271ed1c26b8ce85ca3228fd2ffdb75468ab01979309d61
179+ url: "https://pub.dev"
180+ source: hosted
181+ version: "1.3.0"
182+ matcher:
183+ dependency: transitive
184+ description:
185+ name: matcher
186+ sha256: "31bd099b47c10cd1aeb55146a2d46ce0277630ecef3f7dae54ad7873f36696cd"
187+ url: "https://pub.dev"
188+ source: hosted
189+ version: "0.12.20"
190+ material_color_utilities:
191+ dependency: transitive
192+ description:
193+ name: material_color_utilities
194+ sha256: "9c337007e82b1889149c82ed242ed1cb24a66044e30979c44912381e9be4c48b"
195+ url: "https://pub.dev"
196+ source: hosted
197+ version: "0.13.0"
198+ meta:
199+ dependency: transitive
200+ description:
201+ name: meta
202+ sha256: c82594181e3312f3d0695fc95aaaf7758d75b8d4ae2bbecf223b9fd5109a059d
203+ url: "https://pub.dev"
204+ source: hosted
205+ version: "1.18.3"
206+ objective_c:
207+ dependency: transitive
208+ description:
209+ name: objective_c
210+ sha256: b7fb95a6d9a4f009edd63dc5ac69f07420b23a16161c6dd8660290b59c602e8e
211+ url: "https://pub.dev"
212+ source: hosted
213+ version: "9.5.0"
214+ package_config:
215+ dependency: transitive
216+ description:
217+ name: package_config
218+ sha256: ffcf4cf3d6c0b74ac43708d9f56625506e8a68aa935abe9d267a7330f320eb5d
219+ url: "https://pub.dev"
220+ source: hosted
221+ version: "3.0.0"
222+ path:
223+ dependency: transitive
224+ description:
225+ name: path
226+ sha256: "75cca69d1490965be98c73ceaea117e8a04dd21217b37b292c9ddbec0d955bc5"
227+ url: "https://pub.dev"
228+ source: hosted
229+ version: "1.9.1"
230+ path_provider:
231+ dependency: "direct main"
232+ description:
233+ name: path_provider
234+ sha256: a7f4874f987173da295a61c181b8ee71dab59b332a486b391babf26a1b884825
235+ url: "https://pub.dev"
236+ source: hosted
237+ version: "2.1.6"
238+ path_provider_android:
239+ dependency: transitive
240+ description:
241+ name: path_provider_android
242+ sha256: "69cbd515a62b94d32a7944f086b2f82b4ac40a1d45bebfc00813a430ab2dabcd"
243+ url: "https://pub.dev"
244+ source: hosted
245+ version: "2.3.1"
246+ path_provider_foundation:
247+ dependency: transitive
248+ description:
249+ name: path_provider_foundation
250+ sha256: "2a376b7d6392d80cd3705782d2caa734ca4727776db0b6ec36ef3f1855197699"
251+ url: "https://pub.dev"
252+ source: hosted
253+ version: "2.6.0"
254+ path_provider_linux:
255+ dependency: transitive
256+ description:
257+ name: path_provider_linux
258+ sha256: "58c2005f147315b11e9b4a7bc889cd5203e250cba8e3f012dae259b4972b5c16"
259+ url: "https://pub.dev"
260+ source: hosted
261+ version: "2.2.2"
262+ path_provider_platform_interface:
263+ dependency: transitive
264+ description:
265+ name: path_provider_platform_interface
266+ sha256: "484838772624c3a4b94f1e44a3e19897fee738f2d5c4ce448443b0417f7c9dda"
267+ url: "https://pub.dev"
268+ source: hosted
269+ version: "2.1.3"
270+ path_provider_windows:
271+ dependency: transitive
272+ description:
273+ name: path_provider_windows
274+ sha256: bd6f00dbd873bfb70d0761682da2b3a2c2fccc2b9e84c495821639601d81afe7
275+ url: "https://pub.dev"
276+ source: hosted
277+ version: "2.3.0"
278+ platform:
279+ dependency: transitive
280+ description:
281+ name: platform
282+ sha256: a36d119c13416516a7b5913fbe8af8531e11633d784c550b2125f76c758524ec
283+ url: "https://pub.dev"
284+ source: hosted
285+ version: "3.2.0"
286+ plugin_platform_interface:
287+ dependency: transitive
288+ description:
289+ name: plugin_platform_interface
290+ sha256: "4820fbfdb9478b1ebae27888254d445073732dae3d6ea81f0b7e06d5dedc3f02"
291+ url: "https://pub.dev"
292+ source: hosted
293+ version: "2.1.8"
294+ pub_semver:
295+ dependency: transitive
296+ description:
297+ name: pub_semver
298+ sha256: "261236774e8b1d69cfc6b9eabbc96c40f25e7a2d6b171f3385d4f65d5734fb24"
299+ url: "https://pub.dev"
300+ source: hosted
301+ version: "2.2.1"
302+ record_use:
303+ dependency: transitive
304+ description:
305+ name: record_use
306+ sha256: "2551bd8eecfe95d14ae75f6021ad0248be5c27f138c2ec12fcb52b500b3ba1ed"
307+ url: "https://pub.dev"
308+ source: hosted
309+ version: "0.6.0"
310+ sky_engine:
311+ dependency: transitive
312+ description: flutter
313+ source: sdk
314+ version: "0.0.0"
315+ source_span:
316+ dependency: transitive
317+ description:
318+ name: source_span
319+ sha256: "56a02f1f4cd1a2d96303c0144c93bd6d909eea6bee6bf5a0e0b685edbd4c47ab"
320+ url: "https://pub.dev"
321+ source: hosted
322+ version: "1.10.2"
323+ stack_trace:
324+ dependency: transitive
325+ description:
326+ name: stack_trace
327+ sha256: "277654b3034d17ac6f9f1cb5595db011b1d5d41e8806866db28e0abaa101c490"
328+ url: "https://pub.dev"
329+ source: hosted
330+ version: "1.12.2"
331+ stream_channel:
332+ dependency: transitive
333+ description:
334+ name: stream_channel
335+ sha256: "969e04c80b8bcdf826f8f16579c7b14d780458bd97f56d107d3950fdbeef059d"
336+ url: "https://pub.dev"
337+ source: hosted
338+ version: "2.1.4"
339+ string_scanner:
340+ dependency: transitive
341+ description:
342+ name: string_scanner
343+ sha256: "921cd31725b72fe181906c6a94d987c78e3b98c2e205b397ea399d4054872b43"
344+ url: "https://pub.dev"
345+ source: hosted
346+ version: "1.4.1"
347+ term_glyph:
348+ dependency: transitive
349+ description:
350+ name: term_glyph
351+ sha256: "7f554798625ea768a7518313e58f83891c7f5024f88e46e7182a4558850a4b8e"
352+ url: "https://pub.dev"
353+ source: hosted
354+ version: "1.2.2"
355+ test_api:
356+ dependency: transitive
357+ description:
358+ name: test_api
359+ sha256: "2a122cbe059f8b610d3a5415f42e255b6c17b1f21eee1d960f31080237fb4f11"
360+ url: "https://pub.dev"
361+ source: hosted
362+ version: "0.7.12"
363+ typed_data:
364+ dependency: transitive
365+ description:
366+ name: typed_data
367+ sha256: f9049c039ebfeb4cf7a7104a675823cd72dba8297f264b6637062516699fa006
368+ url: "https://pub.dev"
369+ source: hosted
370+ version: "1.4.0"
371+ vector_math:
372+ dependency: transitive
373+ description:
374+ name: vector_math
375+ sha256: "1d774bbdf6b72a0b12122fc1560c9c2d2a67db5a4a4cc2bd8a5c990ab20e3188"
376+ url: "https://pub.dev"
377+ source: hosted
378+ version: "2.4.0"
379+ vm_service:
380+ dependency: transitive
381+ description:
382+ name: vm_service
383+ sha256: "5f37239c4851efcef929cea7824e76df7f2f0970aef85d66bbc430afa40e72f0"
384+ url: "https://pub.dev"
385+ source: hosted
386+ version: "15.3.0"
387+ xdg_directories:
388+ dependency: transitive
389+ description:
390+ name: xdg_directories
391+ sha256: "7a3f37b05d989967cdddcbb571f1ea834867ae2faa29725fd085180e0883aa15"
392+ url: "https://pub.dev"
393+ source: hosted
394+ version: "1.1.0"
395+ yaml:
396+ dependency: transitive
397+ description:
398+ name: yaml
399+ sha256: f67cdd8e07d3c6329146aaef1ba043542b3134c12489f553ca9a7435d1068aea
400+ url: "https://pub.dev"
401+ source: hosted
402+ version: "3.1.4"
403+sdks:
404+ dart: ">=3.13.0 <4.0.0"
405+ flutter: ">=3.38.4"
added flutter/pubspec.yaml +90 -0
new file mode 100644
@@ -0,0 +1,90 @@
1+name: cljd_flutter
2+description: "A new Flutter project."
3+# The following line prevents the package from being accidentally published to
4+# pub.dev using `flutter pub publish`. This is preferred for private packages.
5+publish_to: 'none' # Remove this line if you wish to publish to pub.dev
6+
7+# The following defines the version and build number for your application.
8+# A version number is three numbers separated by dots, like 1.2.43
9+# followed by an optional build number separated by a +.
10+# Both the version and the builder number may be overridden in flutter
11+# build by specifying --build-name and --build-number, respectively.
12+# In Android, build-name is used as versionName while build-number used as versionCode.
13+# Read more about Android versioning at https://developer.android.com/studio/publish/versioning
14+# In iOS, build-name is used as CFBundleShortVersionString while build-number is used as CFBundleVersion.
15+# Read more about iOS versioning at
16+# https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html
17+# In Windows, build-name is used as the major, minor, and patch parts
18+# of the product and file versions while build-number is used as the build suffix.
19+version: 1.0.0+1
20+
21+environment:
22+ sdk: ^3.13.0
23+
24+# Dependencies specify other packages that your package needs in order to work.
25+# To automatically upgrade your package dependencies to the latest versions
26+# consider running `flutter pub upgrade --major-versions`. Alternatively,
27+# dependencies can be manually updated by changing the version numbers below to
28+# the latest version available on pub.dev. To see which dependencies have newer
29+# versions available, run `flutter pub outdated`.
30+dependencies:
31+ flutter:
32+ sdk: flutter
33+
34+ # The following adds the Cupertino Icons font to your application.
35+ # Use with the CupertinoIcons class for iOS style icons.
36+ cupertino_icons: ^1.0.8
37+ path_provider: ^2.1.6
38+
39+dev_dependencies:
40+ flutter_test:
41+ sdk: flutter
42+
43+ # The "flutter_lints" package below contains a set of recommended lints to
44+ # encourage good coding practices. The lint set provided by the package is
45+ # activated in the `analysis_options.yaml` file located at the root of your
46+ # package. See that file for information about deactivating specific lint
47+ # rules and activating additional ones.
48+ flutter_lints: ^6.0.0
49+
50+# For information on the generic Dart part of this file, see the
51+# following page: https://dart.dev/tools/pub/pubspec
52+
53+# The following section is specific to Flutter packages.
54+flutter:
55+
56+ # The following line ensures that the Material Icons font is
57+ # included with your application, so that you can use the icons in
58+ # the material Icons class.
59+ uses-material-design: true
60+
61+ # To add assets to your application, add an assets section, like this:
62+ # assets:
63+ # - images/a_dot_burr.jpeg
64+ # - images/a_dot_ham.jpeg
65+
66+ # An image asset can refer to one or more resolution-specific "variants", see
67+ # https://flutter.dev/to/resolution-aware-images
68+
69+ # For details regarding adding assets from package dependencies, see
70+ # https://flutter.dev/to/asset-from-package
71+
72+ # To add custom fonts to your application, add a fonts section here,
73+ # in this "flutter" section. Each entry in this list should have a
74+ # "family" key with the font family name, and a "fonts" key with a
75+ # list giving the asset and other descriptors for the font. For
76+ # example:
77+ # fonts:
78+ # - family: Schyler
79+ # fonts:
80+ # - asset: fonts/Schyler-Regular.ttf
81+ # - asset: fonts/Schyler-Italic.ttf
82+ # style: italic
83+ # - family: Trajan Pro
84+ # fonts:
85+ # - asset: fonts/TrajanPro.ttf
86+ # - asset: fonts/TrajanPro_Bold.ttf
87+ # weight: 700
88+ #
89+ # For details regarding fonts from package dependencies,
90+ # see https://flutter.dev/to/font-from-package
new file mode 100644
@@ -0,0 +1,90 @@
1+name: cljd_flutter
2+description: "A new Flutter project."
3+# The following line prevents the package from being accidentally published to
4+# pub.dev using `flutter pub publish`. This is preferred for private packages.
5+publish_to: 'none' # Remove this line if you wish to publish to pub.dev
6+
7+# The following defines the version and build number for your application.
8+# A version number is three numbers separated by dots, like 1.2.43
9+# followed by an optional build number separated by a +.
10+# Both the version and the builder number may be overridden in flutter
11+# build by specifying --build-name and --build-number, respectively.
12+# In Android, build-name is used as versionName while build-number used as versionCode.
13+# Read more about Android versioning at https://developer.android.com/studio/publish/versioning
14+# In iOS, build-name is used as CFBundleShortVersionString while build-number is used as CFBundleVersion.
15+# Read more about iOS versioning at
16+# https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html
17+# In Windows, build-name is used as the major, minor, and patch parts
18+# of the product and file versions while build-number is used as the build suffix.
19+version: 1.0.0+1
20+
21+environment:
22+ sdk: ^3.13.0
23+
24+# Dependencies specify other packages that your package needs in order to work.
25+# To automatically upgrade your package dependencies to the latest versions
26+# consider running `flutter pub upgrade --major-versions`. Alternatively,
27+# dependencies can be manually updated by changing the version numbers below to
28+# the latest version available on pub.dev. To see which dependencies have newer
29+# versions available, run `flutter pub outdated`.
30+dependencies:
31+ flutter:
32+ sdk: flutter
33+
34+ # The following adds the Cupertino Icons font to your application.
35+ # Use with the CupertinoIcons class for iOS style icons.
36+ cupertino_icons: ^1.0.8
37+ path_provider: ^2.1.6
38+
39+dev_dependencies:
40+ flutter_test:
41+ sdk: flutter
42+
43+ # The "flutter_lints" package below contains a set of recommended lints to
44+ # encourage good coding practices. The lint set provided by the package is
45+ # activated in the `analysis_options.yaml` file located at the root of your
46+ # package. See that file for information about deactivating specific lint
47+ # rules and activating additional ones.
48+ flutter_lints: ^6.0.0
49+
50+# For information on the generic Dart part of this file, see the
51+# following page: https://dart.dev/tools/pub/pubspec
52+
53+# The following section is specific to Flutter packages.
54+flutter:
55+
56+ # The following line ensures that the Material Icons font is
57+ # included with your application, so that you can use the icons in
58+ # the material Icons class.
59+ uses-material-design: true
60+
61+ # To add assets to your application, add an assets section, like this:
62+ # assets:
63+ # - images/a_dot_burr.jpeg
64+ # - images/a_dot_ham.jpeg
65+
66+ # An image asset can refer to one or more resolution-specific "variants", see
67+ # https://flutter.dev/to/resolution-aware-images
68+
69+ # For details regarding adding assets from package dependencies, see
70+ # https://flutter.dev/to/asset-from-package
71+
72+ # To add custom fonts to your application, add a fonts section here,
73+ # in this "flutter" section. Each entry in this list should have a
74+ # "family" key with the font family name, and a "fonts" key with a
75+ # list giving the asset and other descriptors for the font. For
76+ # example:
77+ # fonts:
78+ # - family: Schyler
79+ # fonts:
80+ # - asset: fonts/Schyler-Regular.ttf
81+ # - asset: fonts/Schyler-Italic.ttf
82+ # style: italic
83+ # - family: Trajan Pro
84+ # fonts:
85+ # - asset: fonts/TrajanPro.ttf
86+ # - asset: fonts/TrajanPro_Bold.ttf
87+ # weight: 700
88+ #
89+ # For details regarding fonts from package dependencies,
90+ # see https://flutter.dev/to/font-from-package
modified flutter/src/frq/main.cljd +25 -21
@@ -1,15 +1,21 @@
11 (ns frq.main
2- "The Flutter entry point: what `frq.app` is to the jolt half.
2+ "The Flutter entry point: what `frq.cosmic` is to the jolt half.
33
44 Two jobs, and the first one is why `frq.io.dart` cannot install itself the
55 way `frq.io.jolt` does: the app's storage directory arrives from
6- path_provider as a Future, so it is awaited here and handed over before
7- anything under ../common runs.
6+ path_provider as a Future, so `main` is async, awaits it, and installs the
7+ host before a widget is built. Everything under ../common asks `frq.io` for
8+ the filesystem, so nothing shared can run until that has happened.
9+
10+ `ensureInitialized` first, and not as a formality: path_provider is a
11+ platform channel, and a channel used before the binding exists throws.
812
913 The screens themselves are not written. `frq.app` is 1,834 lines of hiccup
1014 over glimmer's widget tags, and glimmer is not here Flutter brings its own
1115 reconciler, so those screens are a rewrite against cljd.flutter rather than a
12- port. This file is the socket they plug into."
16+ port. What this paints is the proof the shared half is alive under a second
17+ compiler: the clock and the saved session, read through exactly the
18+ namespaces the desktop reads them through."
1319 (:require ["package:flutter/material.dart" :as m]
1420 ["package:path_provider/path_provider.dart" :as pp]
1521 [cljd.flutter :as f]
@@ -17,20 +23,18 @@
1723 [frq.clock :as clock]
1824 [frq.store :as store]))
1925
20-(defn main []
21- (f/run
22- (f/widget
23- :watch [dir (.then (pp/getApplicationSupportDirectory)
24- (fn [d] (.-path d)))]
25- (m/MaterialApp)
26- (m/Scaffold)
27- (m/Center)
28- ;; Proof the shared half is alive under a second compiler, and nothing
29- ;; more: install the host, then read the clock and the saved session
30- ;; through exactly the namespaces the desktop reads them through.
31- (do (host/install! dir)
32- (m/Text (str "frq\n"
33- (clock/clock-time (clock/now-ms)) "\n"
34- (if-let [s (store/load-session)]
35- (str "signed in as " (:handle s))
36- "no saved session")))))))
26+(defn ^:async main []
27+ (m/WidgetsFlutterBinding.ensureInitialized)
28+ (let [dir (.-path (await (pp/getApplicationSupportDirectory)))]
29+ (host/install! dir)
30+ (f/run
31+ (m/MaterialApp .title "frq")
32+ .home
33+ (m/Scaffold .appBar (m/AppBar .title (m/Text "frq")))
34+ .body
35+ m/Center
36+ (m/Text (str "frq\n"
37+ (clock/clock-time (clock/now-ms)) "\n"
38+ (if-let [s (store/load-session)]
39+ (str "signed in as " (:handle s))
40+ "no saved session"))))))
@@ -1,15 +1,21 @@
1 (ns frq.main1 (ns frq.main
2- "The Flutter entry point: what `frq.app` is to the jolt half.2+ "The Flutter entry point: what `frq.cosmic` is to the jolt half.
3 3
4 Two jobs, and the first one is why `frq.io.dart` cannot install itself the4 Two jobs, and the first one is why `frq.io.dart` cannot install itself the
5 way `frq.io.jolt` does: the app's storage directory arrives from5 way `frq.io.jolt` does: the app's storage directory arrives from
6- path_provider as a Future, so it is awaited here and handed over before6+ path_provider as a Future, so `main` is async, awaits it, and installs the
7- anything under ../common runs.7+ host before a widget is built. Everything under ../common asks `frq.io` for
8+ the filesystem, so nothing shared can run until that has happened.
9+
10+ `ensureInitialized` first, and not as a formality: path_provider is a
11+ platform channel, and a channel used before the binding exists throws.
8 12
9 The screens themselves are not written. `frq.app` is 1,834 lines of hiccup13 The screens themselves are not written. `frq.app` is 1,834 lines of hiccup
10 over glimmer's widget tags, and glimmer is not here Flutter brings its own14 over glimmer's widget tags, and glimmer is not here Flutter brings its own
11 reconciler, so those screens are a rewrite against cljd.flutter rather than a15 reconciler, so those screens are a rewrite against cljd.flutter rather than a
12- port. This file is the socket they plug into."16+ port. What this paints is the proof the shared half is alive under a second
17+ compiler: the clock and the saved session, read through exactly the
18+ namespaces the desktop reads them through."
13 (:require ["package:flutter/material.dart" :as m]19 (:require ["package:flutter/material.dart" :as m]
14 ["package:path_provider/path_provider.dart" :as pp]20 ["package:path_provider/path_provider.dart" :as pp]
15 [cljd.flutter :as f]21 [cljd.flutter :as f]
@@ -17,20 +23,18 @@
17 [frq.clock :as clock]23 [frq.clock :as clock]
18 [frq.store :as store]))24 [frq.store :as store]))
19 25
20-(defn main []26+(defn ^:async main []
21- (f/run27+ (m/WidgetsFlutterBinding.ensureInitialized)
22- (f/widget28+ (let [dir (.-path (await (pp/getApplicationSupportDirectory)))]
23- :watch [dir (.then (pp/getApplicationSupportDirectory)29+ (host/install! dir)
24- (fn [d] (.-path d)))]30+ (f/run
25- (m/MaterialApp)31+ (m/MaterialApp .title "frq")
26- (m/Scaffold)32+ .home
27- (m/Center)33+ (m/Scaffold .appBar (m/AppBar .title (m/Text "frq")))
28- ;; Proof the shared half is alive under a second compiler, and nothing34+ .body
29- ;; more: install the host, then read the clock and the saved session35+ m/Center
30- ;; through exactly the namespaces the desktop reads them through.36+ (m/Text (str "frq\n"
31- (do (host/install! dir)37+ (clock/clock-time (clock/now-ms)) "\n"
32- (m/Text (str "frq\n"38+ (if-let [s (store/load-session)]
33- (clock/clock-time (clock/now-ms)) "\n"39+ (str "signed in as " (:handle s))
34- (if-let [s (store/load-session)]40+ "no saved session"))))))
35- (str "signed in as " (:handle s))
36- "no saved session")))))))
modified justfile +60 -0
@@ -32,6 +32,66 @@ jobs := env("FRQ_MAX_JOBS", "0")
3232 default:
3333 @just --list
3434
35+# The APK: ClojureDart compiled to Dart, then Flutter's Gradle build.
36+#
37+# Impure on purpose, and worth saying why rather than leaving it to be
38+# discovered. Gradle resolves its own dependencies over the network and
39+# installs build-tools and a platform into ANDROID_HOME as it goes, so it
40+# cannot run in a sandbox and cannot write to the store. What nix gives here
41+# is the toolchain — clojure, a JDK, Flutter, and an SDK composed by
42+# androidenv — and the recipe copies that SDK somewhere writable
43+# (flutter/.home) for Gradle to finish off. That copy and everything Gradle
44+# leaves behind are gitignored.
45+#
46+# No ndkVersion in android/app/build.gradle.kts, for the same reason: the
47+# Flutter template sets it, setting it makes Gradle fetch that exact NDK, and
48+# there is no native code here to need one.
49+#
50+# just apk build the debug APK
51+# just apk install build it and put it on a connected device
52+# just apk run install and launch
53+# just apk log logcat, filtered to this app
54+apk action="build":
55+ #!/usr/bin/env bash
56+ set -euo pipefail
57+ cd "{{justfile_directory()}}/flutter"
58+
59+ sdk="$(nix build --impure --no-link --print-out-paths \
60+ --expr 'let pkgs = import (builtins.getFlake "github:NixOS/nixpkgs/nixos-unstable") { system = "x86_64-linux"; config = { allowUnfree = true; android_sdk.accept_license = true; }; }; in (pkgs.androidenv.composeAndroidPackages { cmdLineToolsVersion = "13.0"; buildToolsVersions = [ "34.0.0" ]; platformVersions = [ "35" "34" ]; includeNDK = false; }).androidsdk')/libexec/android-sdk"
61+
62+ export HOME="$PWD/.home"
63+ export ANDROID_HOME="$HOME/android-sdk"
64+ export ANDROID_SDK_ROOT="$ANDROID_HOME"
65+ mkdir -p "$HOME"
66+
67+ # Gradle writes into ANDROID_HOME, so it is a copy rather than the store
68+ # path. Made once and kept: re-copying would throw away the build-tools
69+ # and platform Gradle installed into it on the last run.
70+ if [ ! -d "$ANDROID_HOME" ]; then
71+ cp -r "$sdk" "$ANDROID_HOME"
72+ chmod -R u+w "$ANDROID_HOME"
73+ fi
74+
75+ flutter="nix shell nixpkgs#clojure nixpkgs#jdk17 nixpkgs#flutter --command"
76+
77+ $flutter clojure -M:cljd compile
78+
79+ # Rewritten every run: it carries absolute store paths, and the flutter
80+ # one moves whenever nixpkgs does.
81+ $flutter flutter config --android-sdk "$ANDROID_HOME" >/dev/null
82+
83+ apk=build/app/outputs/flutter-apk/app-debug.apk
84+ adb="${ADB:-$ANDROID_HOME/platform-tools/adb}"
85+
86+ case "{{action}}" in
87+ build) $flutter flutter build apk --debug ;;
88+ install) $flutter flutter build apk --debug && "$adb" install -r "$apk" ;;
89+ run) $flutter flutter build apk --debug && "$adb" install -r "$apk" \
90+ && "$adb" shell monkey -p uk.nandi.frq -c android.intent.category.LAUNCHER 1 ;;
91+ log) "$adb" logcat -s flutter ;;
92+ *) echo "usage: just apk [build|install|run|log]" >&2; exit 1 ;;
93+ esac
94+
3595 # Two halves, and the split is the point. The frq source is the files on disk,
3696 # uncommitted edits and all. Everything under it — jolt, glimmer, glimmer-cosmic
3797 # and the native objects — is the flake's, built rather than fetched.
@@ -32,6 +32,66 @@ jobs := env("FRQ_MAX_JOBS", "0")
32 default:32 default:
33 @just --list33 @just --list
34 34
35+# The APK: ClojureDart compiled to Dart, then Flutter's Gradle build.
36+#
37+# Impure on purpose, and worth saying why rather than leaving it to be
38+# discovered. Gradle resolves its own dependencies over the network and
39+# installs build-tools and a platform into ANDROID_HOME as it goes, so it
40+# cannot run in a sandbox and cannot write to the store. What nix gives here
41+# is the toolchain — clojure, a JDK, Flutter, and an SDK composed by
42+# androidenv — and the recipe copies that SDK somewhere writable
43+# (flutter/.home) for Gradle to finish off. That copy and everything Gradle
44+# leaves behind are gitignored.
45+#
46+# No ndkVersion in android/app/build.gradle.kts, for the same reason: the
47+# Flutter template sets it, setting it makes Gradle fetch that exact NDK, and
48+# there is no native code here to need one.
49+#
50+# just apk build the debug APK
51+# just apk install build it and put it on a connected device
52+# just apk run install and launch
53+# just apk log logcat, filtered to this app
54+apk action="build":
55+ #!/usr/bin/env bash
56+ set -euo pipefail
57+ cd "{{justfile_directory()}}/flutter"
58+
59+ sdk="$(nix build --impure --no-link --print-out-paths \
60+ --expr 'let pkgs = import (builtins.getFlake "github:NixOS/nixpkgs/nixos-unstable") { system = "x86_64-linux"; config = { allowUnfree = true; android_sdk.accept_license = true; }; }; in (pkgs.androidenv.composeAndroidPackages { cmdLineToolsVersion = "13.0"; buildToolsVersions = [ "34.0.0" ]; platformVersions = [ "35" "34" ]; includeNDK = false; }).androidsdk')/libexec/android-sdk"
61+
62+ export HOME="$PWD/.home"
63+ export ANDROID_HOME="$HOME/android-sdk"
64+ export ANDROID_SDK_ROOT="$ANDROID_HOME"
65+ mkdir -p "$HOME"
66+
67+ # Gradle writes into ANDROID_HOME, so it is a copy rather than the store
68+ # path. Made once and kept: re-copying would throw away the build-tools
69+ # and platform Gradle installed into it on the last run.
70+ if [ ! -d "$ANDROID_HOME" ]; then
71+ cp -r "$sdk" "$ANDROID_HOME"
72+ chmod -R u+w "$ANDROID_HOME"
73+ fi
74+
75+ flutter="nix shell nixpkgs#clojure nixpkgs#jdk17 nixpkgs#flutter --command"
76+
77+ $flutter clojure -M:cljd compile
78+
79+ # Rewritten every run: it carries absolute store paths, and the flutter
80+ # one moves whenever nixpkgs does.
81+ $flutter flutter config --android-sdk "$ANDROID_HOME" >/dev/null
82+
83+ apk=build/app/outputs/flutter-apk/app-debug.apk
84+ adb="${ADB:-$ANDROID_HOME/platform-tools/adb}"
85+
86+ case "{{action}}" in
87+ build) $flutter flutter build apk --debug ;;
88+ install) $flutter flutter build apk --debug && "$adb" install -r "$apk" ;;
89+ run) $flutter flutter build apk --debug && "$adb" install -r "$apk" \
90+ && "$adb" shell monkey -p uk.nandi.frq -c android.intent.category.LAUNCHER 1 ;;
91+ log) "$adb" logcat -s flutter ;;
92+ *) echo "usage: just apk [build|install|run|log]" >&2; exit 1 ;;
93+ esac
94+
35 # Two halves, and the split is the point. The frq source is the files on disk,95 # Two halves, and the split is the point. The frq source is the files on disk,
36 # uncommitted edits and all. Everything under it — jolt, glimmer, glimmer-cosmic96 # uncommitted edits and all. Everything under it — jolt, glimmer, glimmer-cosmic
37 # and the native objects — is the flake's, built rather than fetched.97 # and the native objects — is the flake's, built rather than fetched.