Server (gateway-plugin): - push.py: FCM (HTTP v1 service-account / legacy key) + ntfy backends; NtfyBackend.server_url for app discovery - adapter.py: push on offline broadcast + high-priority push when live; fcm.register; server_caps.push_ntfy_server; outbox now ALWAYS appends so a reconnecting app catches up on live-delivered frames (fixes empty chat after notification tap / activity recreation) - protocol.py / ws_server.py / outbox.py / plugin.yaml: M5 frames + env vars App (Kotlin CMP): - Protocol.kt: notification / fcm.register / sync frames + push caps - GatewayClient.kt: hello carries push creds; auto-sync on reconnect - IrisController.kt: banners, deep-link, notifyMessageIfBackgrounded (system notification on a regular reply when backgrounded) - Android: PlatformPush, AppBridge, IrisNotifications, NtfyListenerService, IrisFirebaseMessagingService, AndroidPush, AndroidSecureStore - Desktop: DesktopPush, DesktopSecureStore - build files + manifest (permissions, services, deep-links) Tests: 35-test tests/gateway/test_android.py suite passes (incl. new regression test_live_delivered_frame_still_parked_for_sync). E2E verified on device: push fire, reconnect sync, background notification, and message replay after ChatStore reset.
60 lines
2.4 KiB
Kotlin
60 lines
2.4 KiB
Kotlin
plugins {
|
|
kotlin("multiplatform")
|
|
kotlin("plugin.serialization")
|
|
id("com.android.library")
|
|
id("org.jetbrains.compose")
|
|
id("org.jetbrains.kotlin.plugin.compose")
|
|
}
|
|
|
|
val composeVersion = "1.7.3"
|
|
val coroutinesVersion = "1.9.0"
|
|
val serializationVersion = "1.7.3"
|
|
val okhttpVersion = "4.12.0"
|
|
|
|
kotlin {
|
|
androidTarget()
|
|
jvm("desktop")
|
|
|
|
sourceSets {
|
|
// Both targets are JVM-based (androidTarget + jvm("desktop")), so
|
|
// shared JVM code (File I/O, SHA-256, media cache) lives in jvmMain.
|
|
val jvmMain by creating { dependsOn(commonMain.get()) }
|
|
val androidMain by getting { dependsOn(jvmMain) }
|
|
val desktopMain by getting { dependsOn(jvmMain) }
|
|
|
|
commonMain.dependencies {
|
|
implementation("org.jetbrains.compose.runtime:runtime:$composeVersion")
|
|
implementation("org.jetbrains.compose.foundation:foundation:$composeVersion")
|
|
implementation("org.jetbrains.compose.material3:material3:$composeVersion")
|
|
implementation("org.jetbrains.compose.ui:ui:$composeVersion")
|
|
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:$coroutinesVersion")
|
|
implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:$serializationVersion")
|
|
// OkHttp is a JVM library; both targets here are JVM-based
|
|
// (androidTarget + jvm("desktop")), so it resolves on both.
|
|
implementation("com.squareup.okhttp3:okhttp:$okhttpVersion")
|
|
}
|
|
// M4: ExoPlayer (Media3) for inline audio/video playback (Android only).
|
|
androidMain.dependencies {
|
|
implementation("androidx.media3:media3-exoplayer:1.3.1")
|
|
implementation("androidx.media3:media3-ui:1.3.1")
|
|
// SAF picker (rememberLauncherForActivityResult).
|
|
implementation("androidx.activity:activity-compose:1.9.2")
|
|
// M5: FCM push (inert without a Firebase project / google-services.json;
|
|
// the ntfy listener is the fallback). The google-services plugin is
|
|
// applied conditionally in the app module.
|
|
implementation("com.google.firebase:firebase-messaging:23.1.2")
|
|
}
|
|
}
|
|
}
|
|
|
|
android {
|
|
namespace = "iris.shared"
|
|
compileSdk = 34
|
|
defaultConfig {
|
|
minSdk = 29
|
|
}
|
|
compileOptions {
|
|
sourceCompatibility = JavaVersion.VERSION_17
|
|
targetCompatibility = JavaVersion.VERSION_17
|
|
}
|
|
} |