2026-09-16 19:24:59 +02:00
|
|
|
plugins {
|
|
|
|
|
id("com.android.application")
|
|
|
|
|
// The Flutter Gradle Plugin must be applied after the Android and Kotlin Gradle plugins.
|
|
|
|
|
id("dev.flutter.flutter-gradle-plugin")
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
android {
|
2026-09-24 13:21:37 +02:00
|
|
|
namespace = "app.halkyon.learn"
|
2026-09-16 19:24:59 +02:00
|
|
|
compileSdk = flutter.compileSdkVersion
|
|
|
|
|
ndkVersion = flutter.ndkVersion
|
|
|
|
|
|
|
|
|
|
compileOptions {
|
|
|
|
|
sourceCompatibility = JavaVersion.VERSION_17
|
|
|
|
|
targetCompatibility = JavaVersion.VERSION_17
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
defaultConfig {
|
2026-09-24 13:21:37 +02:00
|
|
|
applicationId = "app.halkyon.learn"
|
2026-09-16 19:24:59 +02:00
|
|
|
// You can update the following values to match your application needs.
|
|
|
|
|
// For more information, see: https://flutter.dev/to/review-gradle-config.
|
|
|
|
|
minSdk = flutter.minSdkVersion
|
|
|
|
|
targetSdk = flutter.targetSdkVersion
|
|
|
|
|
// Uses the version code from pubspec.yaml. When using split APKs, 1000 * ABI_VERSION
|
|
|
|
|
// is added automatically by Flutter. (https://developer.android.com/studio/build/configure-apk-splits#configure-APK-versions)
|
|
|
|
|
// You can force using the value of versionCode by specifying the `-P force-version-code-ignoring-abi=true`
|
|
|
|
|
// flag during build.
|
|
|
|
|
versionCode = flutter.versionCode
|
|
|
|
|
versionName = flutter.versionName
|
|
|
|
|
}
|
|
|
|
|
|
feat: a release script for the APK and the snap
tool/release.sh builds a release on the maintainer's laptop: one APK for
every phone, from a checkout of the signed tag and signed with the app's
own key, and the snap, both connecting to learn.halkyon.eu, the project's
instance; their checksums signed with GPG; the release on code.halkyon.app
through Forgejo's API, and the snap in the Store's edge channel.
Before building it checks that main is clean and pushed, that the tag is
signed by a key deploys accept, the version and a raised build number,
the pinned Flutter, and that the keystore holds the key whose certificate
tool/release/android-certificate.sha256 names. After building it checks
the APK's signer, package, version, that it isn't debuggable and that it
names the server, and the snap's version. The key's password and the
Forgejo token are asked for at each run and never stored.
Release builds take the app's key from the environment and otherwise fall
back to the debug key, so `flutter run --release` works anywhere. The
native libraries go into the APK compressed: an APK for three
architectures was 110 MB with them stored as they are, 48 MB now. The
list of dependencies Gradle adds for Google Play is left out.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Tizian 「ティツィアーン」 <raisondetredev@pm.me>
2026-10-05 12:55:39 +02:00
|
|
|
// The app's own key signs release builds when tool/release.sh hands it over
|
|
|
|
|
// through the environment: the keystore's path and the key's alias, and the
|
|
|
|
|
// password asked for at each release, never written down. Other release builds
|
|
|
|
|
// are signed with the debug key, so `flutter run --release` works anywhere; the
|
|
|
|
|
// release script refuses to build without the app's key.
|
|
|
|
|
val releaseKeystore = System.getenv("HALKYON_ANDROID_KEYSTORE")
|
|
|
|
|
signingConfigs {
|
|
|
|
|
if (releaseKeystore != null) {
|
|
|
|
|
create("release") {
|
|
|
|
|
storeFile = file(releaseKeystore)
|
|
|
|
|
keyAlias = System.getenv("HALKYON_ANDROID_KEY_ALIAS")
|
|
|
|
|
// A PKCS #12 keystore has one password, for the store and its key.
|
|
|
|
|
storePassword = System.getenv("HALKYON_ANDROID_KEYSTORE_PASSWORD")
|
|
|
|
|
keyPassword = System.getenv("HALKYON_ANDROID_KEYSTORE_PASSWORD")
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2026-09-16 19:24:59 +02:00
|
|
|
buildTypes {
|
|
|
|
|
release {
|
feat: a release script for the APK and the snap
tool/release.sh builds a release on the maintainer's laptop: one APK for
every phone, from a checkout of the signed tag and signed with the app's
own key, and the snap, both connecting to learn.halkyon.eu, the project's
instance; their checksums signed with GPG; the release on code.halkyon.app
through Forgejo's API, and the snap in the Store's edge channel.
Before building it checks that main is clean and pushed, that the tag is
signed by a key deploys accept, the version and a raised build number,
the pinned Flutter, and that the keystore holds the key whose certificate
tool/release/android-certificate.sha256 names. After building it checks
the APK's signer, package, version, that it isn't debuggable and that it
names the server, and the snap's version. The key's password and the
Forgejo token are asked for at each run and never stored.
Release builds take the app's key from the environment and otherwise fall
back to the debug key, so `flutter run --release` works anywhere. The
native libraries go into the APK compressed: an APK for three
architectures was 110 MB with them stored as they are, 48 MB now. The
list of dependencies Gradle adds for Google Play is left out.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Tizian 「ティツィアーン」 <raisondetredev@pm.me>
2026-10-05 12:55:39 +02:00
|
|
|
signingConfig =
|
|
|
|
|
signingConfigs.findByName("release") ?: signingConfigs.getByName("debug")
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// The native libraries go into the APK compressed. One APK serves every phone, so
|
|
|
|
|
// it holds them for three architectures; stored uncompressed (the default, made
|
|
|
|
|
// for stores that send each phone its own) they made it 110 MB to download and to
|
|
|
|
|
// keep. Compressed it's about half that, and Android unpacks the phone's own
|
|
|
|
|
// libraries as it installs the app.
|
|
|
|
|
packaging {
|
|
|
|
|
jniLibs {
|
|
|
|
|
useLegacyPackaging = true
|
2026-09-16 19:24:59 +02:00
|
|
|
}
|
|
|
|
|
}
|
feat: a release script for the APK and the snap
tool/release.sh builds a release on the maintainer's laptop: one APK for
every phone, from a checkout of the signed tag and signed with the app's
own key, and the snap, both connecting to learn.halkyon.eu, the project's
instance; their checksums signed with GPG; the release on code.halkyon.app
through Forgejo's API, and the snap in the Store's edge channel.
Before building it checks that main is clean and pushed, that the tag is
signed by a key deploys accept, the version and a raised build number,
the pinned Flutter, and that the keystore holds the key whose certificate
tool/release/android-certificate.sha256 names. After building it checks
the APK's signer, package, version, that it isn't debuggable and that it
names the server, and the snap's version. The key's password and the
Forgejo token are asked for at each run and never stored.
Release builds take the app's key from the environment and otherwise fall
back to the debug key, so `flutter run --release` works anywhere. The
native libraries go into the APK compressed: an APK for three
architectures was 110 MB with them stored as they are, 48 MB now. The
list of dependencies Gradle adds for Google Play is left out.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Tizian 「ティツィアーン」 <raisondetredev@pm.me>
2026-10-05 12:55:39 +02:00
|
|
|
|
|
|
|
|
// Leaves out the list of dependencies Gradle would otherwise add to the APK,
|
|
|
|
|
// encrypted for Google Play alone; F-Droid's and others' scanners flag it.
|
|
|
|
|
dependenciesInfo {
|
|
|
|
|
includeInApk = false
|
|
|
|
|
includeInBundle = false
|
|
|
|
|
}
|
2026-09-16 19:24:59 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
kotlin {
|
|
|
|
|
compilerOptions {
|
|
|
|
|
jvmTarget = org.jetbrains.kotlin.gradle.dsl.JvmTarget.JVM_17
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
flutter {
|
|
|
|
|
source = "../.."
|
|
|
|
|
}
|
feat(app): a Pomodoro timer on Home, in the notification and in the top bar
Home has a Pomodoro timer (decided 2026-10-07, after Goodtime): the
profile it runs, chosen there while no timer is set, the time left of
the phase, and Start, Pause or Resume, Skip and Stop. While studying, a
small countdown sits in the study screen's header, and a tap pauses it
or goes on. A phase that ends leads to the next, which starts by itself
where the profile says so and otherwise waits, paused at its full
length.
Profiles follow the person to every device, in their settings (schema
4, still written as schema 3 while the profiles are as they come, so
older apps go on reading the settings): Classic, 25 minutes of focus,
5 of break and 15 after four, and 52/17 without long breaks, built in;
both can be changed, more added and deleted, from Home's card or from
Settings. A profile can start breaks and focus by themselves, and keep
the device quiet while focusing. The running timer is the device's own,
kept in the person's folder: closed and opened again, the app catches
up with the phases that ran out meanwhile.
Android: the app's own foreground service (Kotlin, specialUse, as
Goodtime does) shows an ongoing notification counting the phase down,
with Pause or Resume, Skip and Stop; on Android 16 it is a Live Update,
its progress bar the profile's cycle, each phase a segment, focus in
cobalt and breaks in copper. An exact alarm (USE_EXACT_ALARM) alerts
with sound and vibration when the phase ends, also with the app
closed, and Do Not Disturb goes on while focusing once the person
allowed it, the filter before given back afterwards. No notification
plugin: flutter_local_notifications has Live Updates only in a
prerelease that needs compileSdk 37; androidx.core 1.18, which the
build resolved already, has every API needed.
Linux, over the session bus (package:dbus, already in the build): where
the desktop shows icons in its top bar (GNOME with the AppIndicator
extension, which Ubuntu has built in; KDE) the timer counts down there,
the buttons in the icon's menu, as a StatusNotifierItem written in Dart
on the names and paths the snap's desktop plug allows; elsewhere a
notification with the buttons says until when the phase runs. An alert
with sound ends each phase while the app runs, and GNOME's banners stay
off while focusing, through gsettings. xdg-desktop-portal's Background
status, the planned fallback, serves Flatpaks only.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Tizian 「ティツィアーン」 <raisondetredev@pm.me>
2026-10-07 02:54:52 +02:00
|
|
|
|
|
|
|
|
dependencies {
|
|
|
|
|
// NotificationCompat's ProgressStyle and promoted notifications (Android 16's
|
|
|
|
|
// Live Updates) for the Pomodoro timer, from v1.17 on; the build resolves this
|
|
|
|
|
// version already. v1.19 would need compileSdk 37.
|
|
|
|
|
implementation("androidx.core:core:1.18.0")
|
|
|
|
|
}
|