M8: app integration — navigation, :data bindings in both variants, FCM adapter, push notifications, hardening
:app binds every :core:model interface to :data in debug and release (AppDataModule, D-085); the debug fakes module is gone. NavHost over all feature screens with the session gate (S-1, S-2, S-18), bottom destinations from each screen's own bar, result snackbars, deep links (kvitt://invite and the /i/<CODE> landing link) and notification taps. :adapter:fcm maps payload v1 to PushEvent and registers by Firebase Installation ID (firebase-messaging 26, D-087). Push work runs in WorkManager: expedited sync waited up to 20 s, then the notification from local data or the generic text. WorkManager uses KvittWorkerFactory, Coil uses :data's ImageLoader, SyncTriggers on start and foreground, update check in release only. Network security configs (debug cleartext, D-086; pinned-root variant), release signing from local.properties, notification permission after the first sync. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01TQd3pEP9UeN2uifbHknQ7B
This commit is contained in:
@@ -1,11 +1,25 @@
|
||||
// :app — MainActivity, Application, Hilt wiring; navigation, bindings, deep links and notifications arrive with M8.
|
||||
// :app — MainActivity, Application, Hilt wiring (every :core:model interface bound to :data, D-041 and D-085),
|
||||
// navigation and deep links, push handling and notifications, network security and release signing (SPEC §6.2, M8).
|
||||
import java.util.Properties
|
||||
|
||||
plugins {
|
||||
id("kvitt.android.application")
|
||||
id("kvitt.android.compose")
|
||||
id("kvitt.android.hilt")
|
||||
alias(libs.plugins.google.services)
|
||||
alias(libs.plugins.roborazzi)
|
||||
}
|
||||
|
||||
// SPEC §10.6: release signing from android/local.properties (git-ignored); without the keys the release build is unsigned.
|
||||
val localProperties = Properties().apply {
|
||||
val file = rootProject.file("local.properties")
|
||||
if (file.isFile) file.inputStream().use { load(it) }
|
||||
}
|
||||
val releaseStoreFile: String? = localProperties.getProperty("kvitt.release.storeFile")
|
||||
|
||||
// SPEC §10.5.3: the pinned Caddy root replaces the system anchors for icehack.asuscomm.com only when this is true.
|
||||
val pinnedRoot = providers.gradleProperty("kvitt.tls.pinnedRoot").orElse("false").get().toBoolean()
|
||||
|
||||
android {
|
||||
namespace = "se.hagstedt.kvitt"
|
||||
defaultConfig {
|
||||
@@ -18,10 +32,28 @@ android {
|
||||
buildFeatures {
|
||||
buildConfig = true
|
||||
}
|
||||
signingConfigs {
|
||||
if (releaseStoreFile != null) {
|
||||
create("release") {
|
||||
storeFile = file(releaseStoreFile)
|
||||
storePassword = localProperties.getProperty("kvitt.release.storePassword")
|
||||
keyAlias = localProperties.getProperty("kvitt.release.keyAlias")
|
||||
keyPassword = localProperties.getProperty("kvitt.release.keyPassword")
|
||||
}
|
||||
}
|
||||
}
|
||||
buildTypes {
|
||||
debug {
|
||||
applicationIdSuffix = ".debug"
|
||||
}
|
||||
release {
|
||||
if (releaseStoreFile != null) signingConfig = signingConfigs.getByName("release")
|
||||
}
|
||||
}
|
||||
sourceSets {
|
||||
// The pinned-root network security config (and the committed kvitt_root_ca.crt in src/release/res/raw) only
|
||||
// when kvitt.tls.pinnedRoot=true; otherwise src/main's system-anchors config applies.
|
||||
if (pinnedRoot) getByName("release").res.directories.add("src/releasePinnedRoot/res")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -42,14 +74,24 @@ dependencies {
|
||||
implementation(project(":feature:settle"))
|
||||
implementation(project(":feature:analytics"))
|
||||
implementation(project(":feature:settings"))
|
||||
debugImplementation(project(":core:fakes"))
|
||||
testImplementation(project(":core:fakes"))
|
||||
|
||||
implementation(libs.androidx.core.ktx)
|
||||
implementation(libs.androidx.activity.compose)
|
||||
implementation(libs.androidx.navigation.compose)
|
||||
implementation(libs.androidx.hilt.lifecycle.viewmodel.compose)
|
||||
implementation(libs.androidx.lifecycle.runtime.compose)
|
||||
implementation(libs.androidx.lifecycle.viewmodel.compose)
|
||||
implementation(libs.androidx.lifecycle.process)
|
||||
implementation(libs.androidx.work.runtime.ktx)
|
||||
implementation(libs.kotlinx.coroutines.core)
|
||||
implementation(libs.kotlinx.datetime)
|
||||
implementation(libs.coil)
|
||||
implementation(libs.coil.compose)
|
||||
|
||||
debugImplementation(libs.androidx.compose.ui.test.manifest)
|
||||
testImplementation(libs.androidx.compose.ui.test.junit4)
|
||||
testImplementation(libs.kotlinx.coroutines.test)
|
||||
testImplementation(libs.robolectric)
|
||||
testImplementation(libs.roborazzi)
|
||||
testImplementation(libs.roborazzi.compose)
|
||||
|
||||
Reference in New Issue
Block a user