deploy-android is working.
This commit is contained in:
@@ -0,0 +1,30 @@
|
||||
# This file tracks properties of this Flutter project.
|
||||
# Used by Flutter tool to assess capabilities and perform upgrades etc.
|
||||
#
|
||||
# This file should be version controlled and should not be manually edited.
|
||||
|
||||
version:
|
||||
revision: "db50e20168db8fee486b9abf32fc912de3bc5b6a"
|
||||
channel: "stable"
|
||||
|
||||
project_type: app
|
||||
|
||||
# Tracks metadata for the flutter migrate command
|
||||
migration:
|
||||
platforms:
|
||||
- platform: root
|
||||
create_revision: db50e20168db8fee486b9abf32fc912de3bc5b6a
|
||||
base_revision: db50e20168db8fee486b9abf32fc912de3bc5b6a
|
||||
- platform: android
|
||||
create_revision: db50e20168db8fee486b9abf32fc912de3bc5b6a
|
||||
base_revision: db50e20168db8fee486b9abf32fc912de3bc5b6a
|
||||
|
||||
# User provided section
|
||||
|
||||
# List of Local paths (relative to this file) that should be
|
||||
# ignored by the migrate tool.
|
||||
#
|
||||
# Files that are not part of the templates will be ignored by default.
|
||||
unmanaged_files:
|
||||
- 'lib/main.dart'
|
||||
- 'ios/Runner.xcodeproj/project.pbxproj'
|
||||
+47
@@ -0,0 +1,47 @@
|
||||
# DB Sync Status
|
||||
|
||||
This document covers the mail-to-database sync layer only, not the UI.
|
||||
|
||||
## Implemented features
|
||||
|
||||
### IMAP
|
||||
|
||||
- Background sync starts automatically for IMAP accounts.
|
||||
- Mailbox lists and mailbox counters are synced into the local database.
|
||||
- Email headers, flags, and attachment metadata are pulled from IMAP into the local database.
|
||||
- Email bodies are fetched on demand and cached locally.
|
||||
- User-triggered changes are sent to the server immediately: seen, flagged, move, delete, and send.
|
||||
- Sent messages are appended to the Sent folder after SMTP delivery.
|
||||
- Sync retries use exponential backoff after failures.
|
||||
|
||||
### JMAP
|
||||
|
||||
- JMAP accounts can be stored in the database.
|
||||
- JMAP endpoint discovery is implemented.
|
||||
- JMAP connection testing is implemented.
|
||||
|
||||
## Missing features
|
||||
|
||||
### IMAP
|
||||
|
||||
- No general outbound DB-to-IMAP sync queue for arbitrary local database changes.
|
||||
- Background sync currently refreshes only INBOX, not all folders.
|
||||
- No persisted sync log or audit trail in the database.
|
||||
- No explicit conflict-resolution strategy such as revisions, merge rules, or retryable pending operations.
|
||||
- No full reconciliation for remote deletions, mailbox removals, or stale local rows.
|
||||
- No incremental sync checkpoints such as last synced UID, MODSEQ, or similar state.
|
||||
- No durable offline-first sync state tracking.
|
||||
|
||||
### JMAP
|
||||
|
||||
- No JMAP mailbox sync into the local database.
|
||||
- No JMAP email sync into the local database.
|
||||
- No DB-to-JMAP change propagation.
|
||||
- No background JMAP sync worker.
|
||||
- No JMAP conflict handling.
|
||||
- No JMAP sync log in the database.
|
||||
|
||||
## Current summary
|
||||
|
||||
- IMAP: partially implemented and already usable, but not full bidirectional sync.
|
||||
- JMAP: account setup exists, but actual sync is still missing.
|
||||
+26
-2
@@ -89,11 +89,35 @@ tasks:
|
||||
cmds:
|
||||
- fvm flutter build linux --debug --no-pub
|
||||
|
||||
_android-sdk-check:
|
||||
internal: true
|
||||
run: once
|
||||
preconditions:
|
||||
- sh: test -d "${ANDROID_HOME:-$HOME/Android/Sdk}"
|
||||
msg: |
|
||||
Android SDK not found. Install it with:
|
||||
wget https://dl.google.com/android/repository/commandlinetools-linux-11076708_latest.zip -O /tmp/cmdtools.zip
|
||||
mkdir -p ~/Android/Sdk/cmdline-tools
|
||||
unzip /tmp/cmdtools.zip -d ~/Android/Sdk/cmdline-tools
|
||||
mv ~/Android/Sdk/cmdline-tools/cmdline-tools ~/Android/Sdk/cmdline-tools/latest
|
||||
~/Android/Sdk/cmdline-tools/latest/bin/sdkmanager "platform-tools" "build-tools;34.0.0" "platforms;android-34"
|
||||
- sh: ls "${ANDROID_HOME:-$HOME/Android/Sdk}/platforms/" 2>/dev/null | grep -qE '^android-([3-9][4-9]|[4-9][0-9]|[1-9][0-9]{2,})$'
|
||||
msg: |
|
||||
Android platform 34 or higher not found. Install it with:
|
||||
${ANDROID_HOME:-$HOME/Android/Sdk}/cmdline-tools/latest/bin/sdkmanager "build-tools;34.0.0" "platforms;android-34"
|
||||
|
||||
build-android:
|
||||
desc: Build a release APK (output in build/app/outputs/flutter-apk/)
|
||||
deps: [_nix-check, _pub-get]
|
||||
deps: [_nix-check, _android-sdk-check, _pub-get]
|
||||
cmds:
|
||||
- fvm flutter build apk --release --no-pub
|
||||
- ANDROID_HOME=${ANDROID_HOME:-$HOME/Android/Sdk} fvm flutter build apk --release --no-pub
|
||||
|
||||
deploy-android:
|
||||
desc: Build release APK and upload via scp to $ANDROID_APK_SCP_USER@$ANDROID_APK_SCP_HOST:$ANDROID_APK_SCP_PATH
|
||||
deps: [build-android]
|
||||
dotenv: [".env"]
|
||||
cmds:
|
||||
- scripts/deploy_android.sh
|
||||
|
||||
run:
|
||||
desc: Run the app on Linux desktop
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
gradle-wrapper.jar
|
||||
/.gradle
|
||||
/captures/
|
||||
/gradlew
|
||||
/gradlew.bat
|
||||
/local.properties
|
||||
GeneratedPluginRegistrant.java
|
||||
.cxx/
|
||||
|
||||
# Remember to never publicly share your keystore.
|
||||
# See https://flutter.dev/to/reference-keystore
|
||||
key.properties
|
||||
**/*.keystore
|
||||
**/*.jks
|
||||
@@ -0,0 +1,53 @@
|
||||
plugins {
|
||||
id("com.android.application")
|
||||
id("kotlin-android")
|
||||
// The Flutter Gradle Plugin must be applied after the Android and Kotlin Gradle plugins.
|
||||
id("dev.flutter.flutter-gradle-plugin")
|
||||
}
|
||||
|
||||
android {
|
||||
namespace = "com.example.sharedinbox"
|
||||
compileSdk = flutter.compileSdkVersion
|
||||
ndkVersion = flutter.ndkVersion
|
||||
|
||||
compileOptions {
|
||||
sourceCompatibility = JavaVersion.VERSION_17
|
||||
targetCompatibility = JavaVersion.VERSION_17
|
||||
}
|
||||
|
||||
kotlinOptions {
|
||||
jvmTarget = JavaVersion.VERSION_17.toString()
|
||||
}
|
||||
|
||||
defaultConfig {
|
||||
// TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html).
|
||||
applicationId = "com.example.sharedinbox"
|
||||
// You can update the following values to match your application needs.
|
||||
// For more information, see: https://flutter.dev/to/review-gradle-config.
|
||||
minSdk = flutter.minSdkVersion
|
||||
targetSdk = flutter.targetSdkVersion
|
||||
versionCode = flutter.versionCode
|
||||
versionName = flutter.versionName
|
||||
}
|
||||
|
||||
buildTypes {
|
||||
release {
|
||||
// TODO: Add your own signing config for the release build.
|
||||
// Signing with the debug keys for now, so `flutter run --release` works.
|
||||
signingConfig = signingConfigs.getByName("debug")
|
||||
proguardFiles(getDefaultProguardFile("proguard-android-optimize.txt"), "proguard-rules.pro")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
flutter {
|
||||
source = "../.."
|
||||
}
|
||||
|
||||
dependencies {
|
||||
// integration_test is a dev dependency; the Flutter plugin loader adds it as
|
||||
// debugImplementation only, but GeneratedPluginRegistrant.java (in src/main)
|
||||
// references its class in all variants. Make it available for release compilation
|
||||
// without bundling it in the APK.
|
||||
releaseCompileOnly(project(":integration_test"))
|
||||
}
|
||||
Vendored
+4
@@ -0,0 +1,4 @@
|
||||
# integration_test is a dev dependency; its plugin class is referenced in
|
||||
# GeneratedPluginRegistrant.java but not bundled in release. Suppress R8 warnings
|
||||
# for its transitive Guava dependency.
|
||||
-dontwarn com.google.common.util.concurrent.SettableFuture
|
||||
@@ -0,0 +1,7 @@
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<!-- The INTERNET permission is required for development. Specifically,
|
||||
the Flutter tool needs it to communicate with the running application
|
||||
to allow setting breakpoints, to provide hot reload, etc.
|
||||
-->
|
||||
<uses-permission android:name="android.permission.INTERNET"/>
|
||||
</manifest>
|
||||
@@ -0,0 +1,45 @@
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<application
|
||||
android:label="sharedinbox"
|
||||
android:name="${applicationName}"
|
||||
android:icon="@mipmap/ic_launcher">
|
||||
<activity
|
||||
android:name=".MainActivity"
|
||||
android:exported="true"
|
||||
android:launchMode="singleTop"
|
||||
android:taskAffinity=""
|
||||
android:theme="@style/LaunchTheme"
|
||||
android:configChanges="orientation|keyboardHidden|keyboard|screenSize|smallestScreenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode"
|
||||
android:hardwareAccelerated="true"
|
||||
android:windowSoftInputMode="adjustResize">
|
||||
<!-- Specifies an Android theme to apply to this Activity as soon as
|
||||
the Android process has started. This theme is visible to the user
|
||||
while the Flutter UI initializes. After that, this theme continues
|
||||
to determine the Window background behind the Flutter UI. -->
|
||||
<meta-data
|
||||
android:name="io.flutter.embedding.android.NormalTheme"
|
||||
android:resource="@style/NormalTheme"
|
||||
/>
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN"/>
|
||||
<category android:name="android.intent.category.LAUNCHER"/>
|
||||
</intent-filter>
|
||||
</activity>
|
||||
<!-- Don't delete the meta-data below.
|
||||
This is used by the Flutter tool to generate GeneratedPluginRegistrant.java -->
|
||||
<meta-data
|
||||
android:name="flutterEmbedding"
|
||||
android:value="2" />
|
||||
</application>
|
||||
<!-- Required to query activities that can process text, see:
|
||||
https://developer.android.com/training/package-visibility and
|
||||
https://developer.android.com/reference/android/content/Intent#ACTION_PROCESS_TEXT.
|
||||
|
||||
In particular, this is used by the Flutter engine in io.flutter.plugin.text.ProcessTextPlugin. -->
|
||||
<queries>
|
||||
<intent>
|
||||
<action android:name="android.intent.action.PROCESS_TEXT"/>
|
||||
<data android:mimeType="text/plain"/>
|
||||
</intent>
|
||||
</queries>
|
||||
</manifest>
|
||||
@@ -0,0 +1,5 @@
|
||||
package com.example.sharedinbox
|
||||
|
||||
import io.flutter.embedding.android.FlutterActivity
|
||||
|
||||
class MainActivity : FlutterActivity()
|
||||
@@ -0,0 +1,12 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Modify this file to customize your launch splash screen -->
|
||||
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<item android:drawable="?android:colorBackground" />
|
||||
|
||||
<!-- You can insert your own image assets here -->
|
||||
<!-- <item>
|
||||
<bitmap
|
||||
android:gravity="center"
|
||||
android:src="@mipmap/launch_image" />
|
||||
</item> -->
|
||||
</layer-list>
|
||||
@@ -0,0 +1,12 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Modify this file to customize your launch splash screen -->
|
||||
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<item android:drawable="@android:color/white" />
|
||||
|
||||
<!-- You can insert your own image assets here -->
|
||||
<!-- <item>
|
||||
<bitmap
|
||||
android:gravity="center"
|
||||
android:src="@mipmap/launch_image" />
|
||||
</item> -->
|
||||
</layer-list>
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 544 B |
Binary file not shown.
|
After Width: | Height: | Size: 442 B |
Binary file not shown.
|
After Width: | Height: | Size: 721 B |
Binary file not shown.
|
After Width: | Height: | Size: 1.0 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 1.4 KiB |
@@ -0,0 +1,18 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<!-- Theme applied to the Android Window while the process is starting when the OS's Dark Mode setting is on -->
|
||||
<style name="LaunchTheme" parent="@android:style/Theme.Black.NoTitleBar">
|
||||
<!-- Show a splash screen on the activity. Automatically removed when
|
||||
the Flutter engine draws its first frame -->
|
||||
<item name="android:windowBackground">@drawable/launch_background</item>
|
||||
</style>
|
||||
<!-- Theme applied to the Android Window as soon as the process has started.
|
||||
This theme determines the color of the Android Window while your
|
||||
Flutter UI initializes, as well as behind your Flutter UI while its
|
||||
running.
|
||||
|
||||
This Theme is only used starting with V2 of Flutter's Android embedding. -->
|
||||
<style name="NormalTheme" parent="@android:style/Theme.Black.NoTitleBar">
|
||||
<item name="android:windowBackground">?android:colorBackground</item>
|
||||
</style>
|
||||
</resources>
|
||||
@@ -0,0 +1,18 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<!-- Theme applied to the Android Window while the process is starting when the OS's Dark Mode setting is off -->
|
||||
<style name="LaunchTheme" parent="@android:style/Theme.Light.NoTitleBar">
|
||||
<!-- Show a splash screen on the activity. Automatically removed when
|
||||
the Flutter engine draws its first frame -->
|
||||
<item name="android:windowBackground">@drawable/launch_background</item>
|
||||
</style>
|
||||
<!-- Theme applied to the Android Window as soon as the process has started.
|
||||
This theme determines the color of the Android Window while your
|
||||
Flutter UI initializes, as well as behind your Flutter UI while its
|
||||
running.
|
||||
|
||||
This Theme is only used starting with V2 of Flutter's Android embedding. -->
|
||||
<style name="NormalTheme" parent="@android:style/Theme.Light.NoTitleBar">
|
||||
<item name="android:windowBackground">?android:colorBackground</item>
|
||||
</style>
|
||||
</resources>
|
||||
@@ -0,0 +1,7 @@
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<!-- The INTERNET permission is required for development. Specifically,
|
||||
the Flutter tool needs it to communicate with the running application
|
||||
to allow setting breakpoints, to provide hot reload, etc.
|
||||
-->
|
||||
<uses-permission android:name="android.permission.INTERNET"/>
|
||||
</manifest>
|
||||
@@ -0,0 +1,24 @@
|
||||
allprojects {
|
||||
repositories {
|
||||
google()
|
||||
mavenCentral()
|
||||
}
|
||||
}
|
||||
|
||||
val newBuildDir: Directory =
|
||||
rootProject.layout.buildDirectory
|
||||
.dir("../../build")
|
||||
.get()
|
||||
rootProject.layout.buildDirectory.value(newBuildDir)
|
||||
|
||||
subprojects {
|
||||
val newSubprojectBuildDir: Directory = newBuildDir.dir(project.name)
|
||||
project.layout.buildDirectory.value(newSubprojectBuildDir)
|
||||
}
|
||||
subprojects {
|
||||
project.evaluationDependsOn(":app")
|
||||
}
|
||||
|
||||
tasks.register<Delete>("clean") {
|
||||
delete(rootProject.layout.buildDirectory)
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
org.gradle.jvmargs=-Xmx8G -XX:MaxMetaspaceSize=4G -XX:ReservedCodeCacheSize=512m -XX:+HeapDumpOnOutOfMemoryError
|
||||
android.useAndroidX=true
|
||||
@@ -0,0 +1,5 @@
|
||||
distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
zipStorePath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-8.14-all.zip
|
||||
@@ -0,0 +1,26 @@
|
||||
pluginManagement {
|
||||
val flutterSdkPath =
|
||||
run {
|
||||
val properties = java.util.Properties()
|
||||
file("local.properties").inputStream().use { properties.load(it) }
|
||||
val flutterSdkPath = properties.getProperty("flutter.sdk")
|
||||
require(flutterSdkPath != null) { "flutter.sdk not set in local.properties" }
|
||||
flutterSdkPath
|
||||
}
|
||||
|
||||
includeBuild("$flutterSdkPath/packages/flutter_tools/gradle")
|
||||
|
||||
repositories {
|
||||
google()
|
||||
mavenCentral()
|
||||
gradlePluginPortal()
|
||||
}
|
||||
}
|
||||
|
||||
plugins {
|
||||
id("dev.flutter.flutter-plugin-loader") version "1.0.0"
|
||||
id("com.android.application") version "8.11.1" apply false
|
||||
id("org.jetbrains.kotlin.android") version "2.2.20" apply false
|
||||
}
|
||||
|
||||
include(":app")
|
||||
@@ -13,6 +13,9 @@
|
||||
in {
|
||||
devShells.default = pkgs.mkShell {
|
||||
buildInputs = with pkgs; [
|
||||
# Java JDK — required by Gradle for Android builds
|
||||
jdk17
|
||||
|
||||
# Task runner
|
||||
go-task
|
||||
|
||||
|
||||
Executable
+10
@@ -0,0 +1,10 @@
|
||||
#!/usr/bin/env bash
|
||||
# Bash Strict Mode: https://github.com/guettli/bash-strict-mode
|
||||
trap 'echo -e "\n🤷 🚨 🔥 Warning: A command has failed. Exiting the script. Line was ($0:$LINENO): $(sed -n "${LINENO}p" "$0" 2>/dev/null || true) 🔥 🚨 🤷 "; exit 3' ERR
|
||||
set -Eeuo pipefail
|
||||
|
||||
: "${ANDROID_APK_SCP_HOST:?ANDROID_APK_SCP_HOST is not set (add it to .env)}"
|
||||
: "${ANDROID_APK_SCP_USER:?ANDROID_APK_SCP_USER is not set (add it to .env)}"
|
||||
: "${ANDROID_APK_SCP_PATH:?ANDROID_APK_SCP_PATH is not set (add it to .env)}"
|
||||
|
||||
scp -C build/app/outputs/flutter-apk/app-release.apk "${ANDROID_APK_SCP_USER}@${ANDROID_APK_SCP_HOST}:${ANDROID_APK_SCP_PATH}"
|
||||
Reference in New Issue
Block a user