diff --git a/app/build.gradle.kts b/app/build.gradle.kts index ef4cbe53..91e25c49 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -4,6 +4,8 @@ plugins { alias(libs.plugins.android.application) alias(libs.plugins.kotlin.parcelize) alias(libs.plugins.kotlin.compose) + alias(libs.plugins.ksp) + alias(libs.plugins.hilt) } val githubReleaseCertSha256 = providers @@ -141,7 +143,12 @@ dependencies { // Navigation implementation(libs.androidx.navigation.compose) - + + // Dependency injection + implementation(libs.hilt.android) + implementation(libs.androidx.hilt.navigation.compose) + ksp(libs.hilt.compiler) + // Permissions implementation(libs.accompanist.permissions) @@ -191,6 +198,10 @@ dependencies { implementation(libs.androidx.exifinterface) // Testing + implementation(libs.androidx.navigation3.runtime) + implementation(libs.androidx.navigation3.ui) + implementation(libs.androidx.lifecycle.viewmodel.navigation3) + testImplementation(libs.bundles.testing) androidTestImplementation(platform(libs.androidx.compose.bom)) androidTestImplementation(libs.bundles.compose.testing) diff --git a/app/gradle.lockfile b/app/gradle.lockfile index c66fac1d..bc56f3ff 100644 --- a/app/gradle.lockfile +++ b/app/gradle.lockfile @@ -93,6 +93,9 @@ androidx.emoji2:emoji2:1.4.0=debugAndroidTestLintChecksClasspath,debugAndroidTes androidx.exifinterface:exifinterface:1.4.2=debugAndroidTestCompileClasspath,debugAndroidTestLintChecksClasspath,debugCompileClasspath,debugLintChecksClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestLintChecksClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseLintChecksClasspath,releaseRuntimeClasspath androidx.fragment:fragment:1.5.4=debugAndroidTestCompileClasspath,debugAndroidTestLintChecksClasspath,debugCompileClasspath,debugLintChecksClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestLintChecksClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseLintChecksClasspath,releaseRuntimeClasspath androidx.graphics:graphics-path:1.0.1=debugAndroidTestLintChecksClasspath,debugAndroidTestRuntimeClasspath,debugLintChecksClasspath,debugRuntimeClasspath,debugUnitTestLintChecksClasspath,debugUnitTestRuntimeClasspath,releaseLintChecksClasspath,releaseRuntimeClasspath +androidx.hilt:hilt-lifecycle-viewmodel-compose:1.4.0=debugAndroidTestCompileClasspath,debugAndroidTestLintChecksClasspath,debugCompileClasspath,debugLintChecksClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestLintChecksClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseLintChecksClasspath,releaseRuntimeClasspath +androidx.hilt:hilt-lifecycle-viewmodel:1.4.0=debugAndroidTestCompileClasspath,debugAndroidTestLintChecksClasspath,debugCompileClasspath,debugLintChecksClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestLintChecksClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseLintChecksClasspath,releaseRuntimeClasspath +androidx.hilt:hilt-navigation-compose:1.4.0=debugAndroidTestCompileClasspath,debugAndroidTestLintChecksClasspath,debugCompileClasspath,debugLintChecksClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestLintChecksClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseLintChecksClasspath,releaseRuntimeClasspath androidx.interpolator:interpolator:1.0.0=debugAndroidTestCompileClasspath,debugAndroidTestLintChecksClasspath,debugAndroidTestRuntimeClasspath,debugCompileClasspath,debugLintChecksClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestLintChecksClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseLintChecksClasspath,releaseRuntimeClasspath androidx.legacy:legacy-support-core-utils:1.0.0=debugAndroidTestLintChecksClasspath,debugAndroidTestRuntimeClasspath,debugLintChecksClasspath,debugRuntimeClasspath,debugUnitTestLintChecksClasspath,debugUnitTestRuntimeClasspath,releaseLintChecksClasspath,releaseRuntimeClasspath androidx.lifecycle:lifecycle-common-java8:2.11.0=debugAndroidTestLintChecksClasspath,debugLintChecksClasspath,debugRuntimeClasspath,debugUnitTestLintChecksClasspath,debugUnitTestRuntimeClasspath,releaseLintChecksClasspath,releaseRuntimeClasspath @@ -113,21 +116,27 @@ androidx.lifecycle:lifecycle-viewmodel-android:2.11.0=debugAndroidTestCompileCla androidx.lifecycle:lifecycle-viewmodel-compose-android:2.11.0=debugAndroidTestCompileClasspath,debugAndroidTestLintChecksClasspath,debugCompileClasspath,debugLintChecksClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestLintChecksClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseLintChecksClasspath,releaseRuntimeClasspath androidx.lifecycle:lifecycle-viewmodel-compose:2.11.0=debugAndroidTestCompileClasspath,debugAndroidTestLintChecksClasspath,debugCompileClasspath,debugLintChecksClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestLintChecksClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseLintChecksClasspath,releaseRuntimeClasspath androidx.lifecycle:lifecycle-viewmodel-ktx:2.11.0=debugAndroidTestCompileClasspath,debugAndroidTestLintChecksClasspath,debugAndroidTestRuntimeClasspath,debugCompileClasspath,debugLintChecksClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestLintChecksClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseLintChecksClasspath,releaseRuntimeClasspath +androidx.lifecycle:lifecycle-viewmodel-navigation3-android:2.11.0=debugAndroidTestCompileClasspath,debugAndroidTestLintChecksClasspath,debugCompileClasspath,debugLintChecksClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestLintChecksClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseLintChecksClasspath,releaseRuntimeClasspath +androidx.lifecycle:lifecycle-viewmodel-navigation3:2.11.0=debugAndroidTestCompileClasspath,debugAndroidTestLintChecksClasspath,debugCompileClasspath,debugLintChecksClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestLintChecksClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseLintChecksClasspath,releaseRuntimeClasspath androidx.lifecycle:lifecycle-viewmodel-savedstate-android:2.11.0=debugAndroidTestCompileClasspath,debugAndroidTestLintChecksClasspath,debugAndroidTestRuntimeClasspath,debugCompileClasspath,debugLintChecksClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestLintChecksClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseLintChecksClasspath,releaseRuntimeClasspath androidx.lifecycle:lifecycle-viewmodel-savedstate:2.11.0=debugAndroidTestCompileClasspath,debugAndroidTestLintChecksClasspath,debugAndroidTestRuntimeClasspath,debugCompileClasspath,debugLintChecksClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestLintChecksClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseLintChecksClasspath,releaseRuntimeClasspath androidx.lifecycle:lifecycle-viewmodel:2.11.0=debugAndroidTestCompileClasspath,debugAndroidTestLintChecksClasspath,debugAndroidTestRuntimeClasspath,debugCompileClasspath,debugLintChecksClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestLintChecksClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseLintChecksClasspath,releaseRuntimeClasspath androidx.loader:loader:1.0.0=debugAndroidTestCompileClasspath,debugAndroidTestLintChecksClasspath,debugAndroidTestRuntimeClasspath,debugCompileClasspath,debugLintChecksClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestLintChecksClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseLintChecksClasspath,releaseRuntimeClasspath androidx.localbroadcastmanager:localbroadcastmanager:1.0.0=debugAndroidTestLintChecksClasspath,debugAndroidTestRuntimeClasspath,debugLintChecksClasspath,debugRuntimeClasspath,debugUnitTestLintChecksClasspath,debugUnitTestRuntimeClasspath,releaseLintChecksClasspath,releaseRuntimeClasspath +androidx.navigation3:navigation3-runtime-android:1.1.6=debugAndroidTestCompileClasspath,debugAndroidTestLintChecksClasspath,debugCompileClasspath,debugLintChecksClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestLintChecksClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseLintChecksClasspath,releaseRuntimeClasspath +androidx.navigation3:navigation3-runtime:1.1.6=debugAndroidTestCompileClasspath,debugAndroidTestLintChecksClasspath,debugCompileClasspath,debugLintChecksClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestLintChecksClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseLintChecksClasspath,releaseRuntimeClasspath +androidx.navigation3:navigation3-ui-android:1.1.6=debugAndroidTestCompileClasspath,debugAndroidTestLintChecksClasspath,debugCompileClasspath,debugLintChecksClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestLintChecksClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseLintChecksClasspath,releaseRuntimeClasspath +androidx.navigation3:navigation3-ui:1.1.6=debugAndroidTestCompileClasspath,debugAndroidTestLintChecksClasspath,debugCompileClasspath,debugLintChecksClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestLintChecksClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseLintChecksClasspath,releaseRuntimeClasspath androidx.navigation:navigation-common-android:2.9.8=debugAndroidTestCompileClasspath,debugAndroidTestLintChecksClasspath,debugCompileClasspath,debugLintChecksClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestLintChecksClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseLintChecksClasspath,releaseRuntimeClasspath androidx.navigation:navigation-common:2.9.8=debugAndroidTestCompileClasspath,debugAndroidTestLintChecksClasspath,debugCompileClasspath,debugLintChecksClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestLintChecksClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseLintChecksClasspath,releaseRuntimeClasspath androidx.navigation:navigation-compose-android:2.9.8=debugAndroidTestCompileClasspath,debugAndroidTestLintChecksClasspath,debugCompileClasspath,debugLintChecksClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestLintChecksClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseLintChecksClasspath,releaseRuntimeClasspath androidx.navigation:navigation-compose:2.9.8=debugAndroidTestCompileClasspath,debugAndroidTestLintChecksClasspath,debugCompileClasspath,debugLintChecksClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestLintChecksClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseLintChecksClasspath,releaseRuntimeClasspath androidx.navigation:navigation-runtime-android:2.9.8=debugAndroidTestCompileClasspath,debugAndroidTestLintChecksClasspath,debugCompileClasspath,debugLintChecksClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestLintChecksClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseLintChecksClasspath,releaseRuntimeClasspath androidx.navigation:navigation-runtime:2.9.8=debugAndroidTestCompileClasspath,debugAndroidTestLintChecksClasspath,debugCompileClasspath,debugLintChecksClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestLintChecksClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseLintChecksClasspath,releaseRuntimeClasspath -androidx.navigationevent:navigationevent-android:1.0.0=debugAndroidTestCompileClasspath,debugAndroidTestLintChecksClasspath,debugAndroidTestRuntimeClasspath,debugCompileClasspath,debugLintChecksClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestLintChecksClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseLintChecksClasspath,releaseRuntimeClasspath -androidx.navigationevent:navigationevent-compose-android:1.0.0=debugAndroidTestCompileClasspath,debugAndroidTestLintChecksClasspath,debugAndroidTestRuntimeClasspath,debugCompileClasspath,debugLintChecksClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestLintChecksClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseLintChecksClasspath,releaseRuntimeClasspath -androidx.navigationevent:navigationevent-compose:1.0.0=debugAndroidTestCompileClasspath,debugAndroidTestLintChecksClasspath,debugAndroidTestRuntimeClasspath,debugCompileClasspath,debugLintChecksClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestLintChecksClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseLintChecksClasspath,releaseRuntimeClasspath -androidx.navigationevent:navigationevent:1.0.0=debugAndroidTestCompileClasspath,debugAndroidTestLintChecksClasspath,debugAndroidTestRuntimeClasspath,debugCompileClasspath,debugLintChecksClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestLintChecksClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseLintChecksClasspath,releaseRuntimeClasspath +androidx.navigationevent:navigationevent-android:1.1.2=debugAndroidTestCompileClasspath,debugAndroidTestLintChecksClasspath,debugAndroidTestRuntimeClasspath,debugCompileClasspath,debugLintChecksClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestLintChecksClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseLintChecksClasspath,releaseRuntimeClasspath +androidx.navigationevent:navigationevent-compose-android:1.1.2=debugAndroidTestCompileClasspath,debugAndroidTestLintChecksClasspath,debugAndroidTestRuntimeClasspath,debugCompileClasspath,debugLintChecksClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestLintChecksClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseLintChecksClasspath,releaseRuntimeClasspath +androidx.navigationevent:navigationevent-compose:1.1.2=debugAndroidTestCompileClasspath,debugAndroidTestLintChecksClasspath,debugAndroidTestRuntimeClasspath,debugCompileClasspath,debugLintChecksClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestLintChecksClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseLintChecksClasspath,releaseRuntimeClasspath +androidx.navigationevent:navigationevent:1.1.2=debugAndroidTestCompileClasspath,debugAndroidTestLintChecksClasspath,debugAndroidTestRuntimeClasspath,debugCompileClasspath,debugLintChecksClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestLintChecksClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseLintChecksClasspath,releaseRuntimeClasspath androidx.print:print:1.0.0=debugAndroidTestLintChecksClasspath,debugAndroidTestRuntimeClasspath,debugLintChecksClasspath,debugRuntimeClasspath,debugUnitTestLintChecksClasspath,debugUnitTestRuntimeClasspath,releaseLintChecksClasspath,releaseRuntimeClasspath androidx.profileinstaller:profileinstaller:1.4.0=debugAndroidTestLintChecksClasspath,debugAndroidTestRuntimeClasspath,debugLintChecksClasspath,debugRuntimeClasspath,debugUnitTestLintChecksClasspath,debugUnitTestRuntimeClasspath,releaseLintChecksClasspath,releaseRuntimeClasspath androidx.resourceinspection:resourceinspection-annotation:1.0.1=debugAndroidTestLintChecksClasspath,debugLintChecksClasspath,debugRuntimeClasspath,debugUnitTestLintChecksClasspath,debugUnitTestRuntimeClasspath,releaseLintChecksClasspath,releaseRuntimeClasspath @@ -236,33 +245,46 @@ com.google.auto.service:auto-service:1.1.1=unified-test-platform-android-device- com.google.auto.value:auto-value-annotations:1.11.0=debugUnitTestCompileClasspath,debugUnitTestLintChecksClasspath,debugUnitTestRuntimeClasspath com.google.auto.value:auto-value-annotations:1.6.3=debugAndroidTestLintChecksClasspath,debugLintChecksClasspath,debugRuntimeClasspath,releaseLintChecksClasspath,releaseRuntimeClasspath com.google.auto:auto-common:1.2.1=unified-test-platform-android-device-provider-ddmlib,unified-test-platform-android-driver-instrumentation,unified-test-platform-android-test-plugin,unified-test-platform-android-test-plugin-host-additional-test-output,unified-test-platform-android-test-plugin-host-apk-installer,unified-test-platform-android-test-plugin-host-coverage,unified-test-platform-android-test-plugin-host-device-info,unified-test-platform-android-test-plugin-host-emulator-control,unified-test-platform-android-test-plugin-host-logcat,unified-test-platform-android-test-plugin-result-listener-gradle -com.google.code.findbugs:jsr305:3.0.2=androidLintTool,debugAndroidTestCompileClasspath,debugAndroidTestLintChecksClasspath,debugAndroidTestRuntimeClasspath,debugCompileClasspath,debugLintChecksClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestLintChecksClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseLintChecksClasspath,releaseRuntimeClasspath,unified-test-platform-android-device-provider-ddmlib,unified-test-platform-android-driver-instrumentation,unified-test-platform-android-test-plugin,unified-test-platform-android-test-plugin-host-additional-test-output,unified-test-platform-android-test-plugin-host-apk-installer,unified-test-platform-android-test-plugin-host-coverage,unified-test-platform-android-test-plugin-host-device-info,unified-test-platform-android-test-plugin-host-emulator-control,unified-test-platform-android-test-plugin-host-logcat,unified-test-platform-android-test-plugin-result-listener-gradle,unified-test-platform-core,unified-test-platform-gradle-work-action,unified-test-platform-launcher +com.google.code.findbugs:jsr305:3.0.2=_agp_internal_debug_kspClasspath,_agp_internal_release_kspClasspath,androidLintTool,debugAndroidTestCompileClasspath,debugAndroidTestLintChecksClasspath,debugAndroidTestRuntimeClasspath,debugCompileClasspath,debugLintChecksClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestLintChecksClasspath,debugUnitTestRuntimeClasspath,hiltAnnotationProcessorDebug,hiltAnnotationProcessorDebugAndroidTest,hiltAnnotationProcessorDebugUnitTest,hiltAnnotationProcessorRelease,kspDebugKotlinProcessorClasspath,kspReleaseKotlinProcessorClasspath,releaseCompileClasspath,releaseLintChecksClasspath,releaseRuntimeClasspath,unified-test-platform-android-device-provider-ddmlib,unified-test-platform-android-driver-instrumentation,unified-test-platform-android-test-plugin,unified-test-platform-android-test-plugin-host-additional-test-output,unified-test-platform-android-test-plugin-host-apk-installer,unified-test-platform-android-test-plugin-host-coverage,unified-test-platform-android-test-plugin-host-device-info,unified-test-platform-android-test-plugin-host-emulator-control,unified-test-platform-android-test-plugin-host-logcat,unified-test-platform-android-test-plugin-result-listener-gradle,unified-test-platform-core,unified-test-platform-gradle-work-action,unified-test-platform-launcher com.google.code.gson:gson:2.10.1=unified-test-platform-core,unified-test-platform-gradle-work-action com.google.code.gson:gson:2.11.0=androidLintTool,unified-test-platform-android-test-plugin-host-emulator-control,unified-test-platform-android-test-plugin-result-listener-gradle com.google.code.gson:gson:2.14.0=debugAndroidTestCompileClasspath,debugAndroidTestLintChecksClasspath,debugCompileClasspath,debugLintChecksClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestLintChecksClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseLintChecksClasspath,releaseRuntimeClasspath com.google.code.gson:gson:2.8.9=unified-test-platform-android-driver-instrumentation,unified-test-platform-launcher com.google.crypto.tink:tink-android:1.23.0=debugAndroidTestCompileClasspath,debugAndroidTestLintChecksClasspath,debugCompileClasspath,debugLintChecksClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestLintChecksClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseLintChecksClasspath,releaseRuntimeClasspath com.google.crypto.tink:tink:1.18.0=unified-test-platform-android-test-plugin-host-emulator-control,unified-test-platform-gradle-work-action +com.google.dagger:dagger-compiler:2.60.1=_agp_internal_debug_kspClasspath,_agp_internal_release_kspClasspath,hiltAnnotationProcessorDebug,hiltAnnotationProcessorDebugAndroidTest,hiltAnnotationProcessorDebugUnitTest,hiltAnnotationProcessorRelease,kspDebugKotlinProcessorClasspath,kspReleaseKotlinProcessorClasspath +com.google.dagger:dagger-lint-aar:2.60.1=debugAndroidTestCompileClasspath,debugAndroidTestLintChecksClasspath,debugCompileClasspath,debugLintChecksClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestLintChecksClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseLintChecksClasspath,releaseRuntimeClasspath +com.google.dagger:dagger-spi:2.60.1=_agp_internal_debug_kspClasspath,_agp_internal_release_kspClasspath,hiltAnnotationProcessorDebug,hiltAnnotationProcessorDebugAndroidTest,hiltAnnotationProcessorDebugUnitTest,hiltAnnotationProcessorRelease,kspDebugKotlinProcessorClasspath,kspReleaseKotlinProcessorClasspath com.google.dagger:dagger:2.48=unified-test-platform-android-device-provider-ddmlib,unified-test-platform-android-driver-instrumentation,unified-test-platform-android-test-plugin-host-additional-test-output,unified-test-platform-android-test-plugin-host-apk-installer,unified-test-platform-android-test-plugin-host-coverage,unified-test-platform-android-test-plugin-host-device-info,unified-test-platform-android-test-plugin-host-emulator-control,unified-test-platform-android-test-plugin-host-logcat,unified-test-platform-android-test-plugin-result-listener-gradle,unified-test-platform-core,unified-test-platform-gradle-work-action -com.google.dagger:dagger:2.59=debugAndroidTestLintChecksClasspath,debugLintChecksClasspath,debugRuntimeClasspath,debugUnitTestLintChecksClasspath,debugUnitTestRuntimeClasspath,releaseLintChecksClasspath,releaseRuntimeClasspath +com.google.dagger:dagger:2.60.1=_agp_internal_debug_kspClasspath,_agp_internal_release_kspClasspath,debugAndroidTestCompileClasspath,debugAndroidTestLintChecksClasspath,debugCompileClasspath,debugLintChecksClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestLintChecksClasspath,debugUnitTestRuntimeClasspath,hiltAnnotationProcessorDebug,hiltAnnotationProcessorDebugAndroidTest,hiltAnnotationProcessorDebugUnitTest,hiltAnnotationProcessorRelease,kspDebugKotlinProcessorClasspath,kspReleaseKotlinProcessorClasspath,releaseCompileClasspath,releaseLintChecksClasspath,releaseRuntimeClasspath +com.google.dagger:hilt-android-compiler:2.60.1=_agp_internal_debug_kspClasspath,_agp_internal_release_kspClasspath,hiltAnnotationProcessorDebug,hiltAnnotationProcessorDebugAndroidTest,hiltAnnotationProcessorDebugUnitTest,hiltAnnotationProcessorRelease,kspDebugKotlinProcessorClasspath,kspReleaseKotlinProcessorClasspath +com.google.dagger:hilt-android:2.60.1=debugAndroidTestCompileClasspath,debugAndroidTestLintChecksClasspath,debugCompileClasspath,debugLintChecksClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestLintChecksClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseLintChecksClasspath,releaseRuntimeClasspath +com.google.dagger:hilt-compiler:2.60.1=hiltAnnotationProcessorDebug,hiltAnnotationProcessorDebugAndroidTest,hiltAnnotationProcessorDebugUnitTest,hiltAnnotationProcessorRelease +com.google.dagger:hilt-core:2.60.1=debugAndroidTestCompileClasspath,debugAndroidTestLintChecksClasspath,debugCompileClasspath,debugLintChecksClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestLintChecksClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseLintChecksClasspath,releaseRuntimeClasspath +com.google.devtools.ksp:symbol-processing-api:2.3.11=kotlinCompilerPluginClasspathDebug,kotlinCompilerPluginClasspathDebugAndroidTest,kotlinCompilerPluginClasspathDebugUnitTest,kotlinCompilerPluginClasspathRelease,kspPluginClasspath,kspPluginClasspathNonEmbeddable +com.google.devtools.ksp:symbol-processing-api:2.3.7=_agp_internal_debug_kspClasspath,_agp_internal_release_kspClasspath,hiltAnnotationProcessorDebug,hiltAnnotationProcessorDebugAndroidTest,hiltAnnotationProcessorDebugUnitTest,hiltAnnotationProcessorRelease,kspDebugKotlinProcessorClasspath,kspReleaseKotlinProcessorClasspath com.google.errorprone:error_prone_annotation:2.38.0=debugUnitTestLintChecksClasspath,debugUnitTestRuntimeClasspath com.google.errorprone:error_prone_annotations:2.23.0=unified-test-platform-android-driver-instrumentation,unified-test-platform-android-test-plugin,unified-test-platform-core,unified-test-platform-launcher com.google.errorprone:error_prone_annotations:2.36.0=androidLintTool,unified-test-platform-android-device-provider-ddmlib,unified-test-platform-android-test-plugin-host-additional-test-output,unified-test-platform-android-test-plugin-host-apk-installer,unified-test-platform-android-test-plugin-host-coverage,unified-test-platform-android-test-plugin-host-device-info,unified-test-platform-android-test-plugin-host-emulator-control,unified-test-platform-android-test-plugin-host-logcat,unified-test-platform-android-test-plugin-result-listener-gradle,unified-test-platform-gradle-work-action +com.google.errorprone:error_prone_annotations:2.47.0=_agp_internal_debug_kspClasspath,_agp_internal_release_kspClasspath,hiltAnnotationProcessorDebug,hiltAnnotationProcessorDebugAndroidTest,hiltAnnotationProcessorDebugUnitTest,hiltAnnotationProcessorRelease,kspDebugKotlinProcessorClasspath,kspReleaseKotlinProcessorClasspath com.google.errorprone:error_prone_annotations:2.48.0=debugAndroidTestCompileClasspath,debugAndroidTestLintChecksClasspath,debugCompileClasspath,debugLintChecksClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestLintChecksClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseLintChecksClasspath,releaseRuntimeClasspath com.google.firebase:firebase-annotations:16.0.0=debugAndroidTestCompileClasspath,debugAndroidTestLintChecksClasspath,debugCompileClasspath,debugLintChecksClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestLintChecksClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseLintChecksClasspath,releaseRuntimeClasspath com.google.firebase:firebase-components:16.1.0=debugAndroidTestCompileClasspath,debugAndroidTestLintChecksClasspath,debugCompileClasspath,debugLintChecksClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestLintChecksClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseLintChecksClasspath,releaseRuntimeClasspath com.google.firebase:firebase-encoders-json:17.1.0=debugAndroidTestCompileClasspath,debugAndroidTestLintChecksClasspath,debugCompileClasspath,debugLintChecksClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestLintChecksClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseLintChecksClasspath,releaseRuntimeClasspath com.google.firebase:firebase-encoders:16.1.0=debugAndroidTestCompileClasspath,debugAndroidTestLintChecksClasspath,debugCompileClasspath,debugLintChecksClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestLintChecksClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseLintChecksClasspath,releaseRuntimeClasspath +com.google.googlejavaformat:google-java-format:1.33.0=_agp_internal_debug_kspClasspath,_agp_internal_release_kspClasspath,hiltAnnotationProcessorDebug,hiltAnnotationProcessorDebugAndroidTest,hiltAnnotationProcessorDebugUnitTest,hiltAnnotationProcessorRelease,kspDebugKotlinProcessorClasspath,kspReleaseKotlinProcessorClasspath com.google.guava:failureaccess:1.0.1=unified-test-platform-android-driver-instrumentation,unified-test-platform-android-test-plugin,unified-test-platform-core,unified-test-platform-launcher com.google.guava:failureaccess:1.0.2=androidLintTool,unified-test-platform-android-device-provider-ddmlib,unified-test-platform-android-test-plugin-host-additional-test-output,unified-test-platform-android-test-plugin-host-apk-installer,unified-test-platform-android-test-plugin-host-coverage,unified-test-platform-android-test-plugin-host-device-info,unified-test-platform-android-test-plugin-host-emulator-control,unified-test-platform-android-test-plugin-host-logcat,unified-test-platform-android-test-plugin-result-listener-gradle,unified-test-platform-gradle-work-action -com.google.guava:failureaccess:1.0.3=debugUnitTestCompileClasspath,debugUnitTestLintChecksClasspath,debugUnitTestRuntimeClasspath +com.google.guava:failureaccess:1.0.3=_agp_internal_debug_kspClasspath,_agp_internal_release_kspClasspath,debugUnitTestCompileClasspath,debugUnitTestLintChecksClasspath,debugUnitTestRuntimeClasspath,hiltAnnotationProcessorDebug,hiltAnnotationProcessorDebugAndroidTest,hiltAnnotationProcessorDebugUnitTest,hiltAnnotationProcessorRelease,kspDebugKotlinProcessorClasspath,kspReleaseKotlinProcessorClasspath com.google.guava:guava:32.0.1-jre=unified-test-platform-android-driver-instrumentation,unified-test-platform-android-test-plugin,unified-test-platform-core,unified-test-platform-launcher com.google.guava:guava:33.4.0-jre=androidLintTool,unified-test-platform-android-device-provider-ddmlib,unified-test-platform-android-test-plugin-host-additional-test-output,unified-test-platform-android-test-plugin-host-apk-installer,unified-test-platform-android-test-plugin-host-coverage,unified-test-platform-android-test-plugin-host-device-info,unified-test-platform-android-test-plugin-host-emulator-control,unified-test-platform-android-test-plugin-host-logcat,unified-test-platform-android-test-plugin-result-listener-gradle,unified-test-platform-gradle-work-action com.google.guava:guava:33.4.8-jre=debugUnitTestCompileClasspath,debugUnitTestLintChecksClasspath,debugUnitTestRuntimeClasspath +com.google.guava:guava:33.6.0-jre=_agp_internal_debug_kspClasspath,_agp_internal_release_kspClasspath,hiltAnnotationProcessorDebug,hiltAnnotationProcessorDebugAndroidTest,hiltAnnotationProcessorDebugUnitTest,hiltAnnotationProcessorRelease,kspDebugKotlinProcessorClasspath,kspReleaseKotlinProcessorClasspath com.google.guava:listenablefuture:1.0=debugAndroidTestCompileClasspath,debugAndroidTestLintChecksClasspath,debugAndroidTestRuntimeClasspath,debugCompileClasspath,debugLintChecksClasspath,debugRuntimeClasspath,releaseCompileClasspath,releaseLintChecksClasspath,releaseRuntimeClasspath -com.google.guava:listenablefuture:9999.0-empty-to-avoid-conflict-with-guava=androidLintTool,debugUnitTestCompileClasspath,debugUnitTestLintChecksClasspath,debugUnitTestRuntimeClasspath,unified-test-platform-android-device-provider-ddmlib,unified-test-platform-android-driver-instrumentation,unified-test-platform-android-test-plugin,unified-test-platform-android-test-plugin-host-additional-test-output,unified-test-platform-android-test-plugin-host-apk-installer,unified-test-platform-android-test-plugin-host-coverage,unified-test-platform-android-test-plugin-host-device-info,unified-test-platform-android-test-plugin-host-emulator-control,unified-test-platform-android-test-plugin-host-logcat,unified-test-platform-android-test-plugin-result-listener-gradle,unified-test-platform-core,unified-test-platform-gradle-work-action,unified-test-platform-launcher +com.google.guava:listenablefuture:9999.0-empty-to-avoid-conflict-with-guava=_agp_internal_debug_kspClasspath,_agp_internal_release_kspClasspath,androidLintTool,debugUnitTestCompileClasspath,debugUnitTestLintChecksClasspath,debugUnitTestRuntimeClasspath,hiltAnnotationProcessorDebug,hiltAnnotationProcessorDebugAndroidTest,hiltAnnotationProcessorDebugUnitTest,hiltAnnotationProcessorRelease,kspDebugKotlinProcessorClasspath,kspReleaseKotlinProcessorClasspath,unified-test-platform-android-device-provider-ddmlib,unified-test-platform-android-driver-instrumentation,unified-test-platform-android-test-plugin,unified-test-platform-android-test-plugin-host-additional-test-output,unified-test-platform-android-test-plugin-host-apk-installer,unified-test-platform-android-test-plugin-host-coverage,unified-test-platform-android-test-plugin-host-device-info,unified-test-platform-android-test-plugin-host-emulator-control,unified-test-platform-android-test-plugin-host-logcat,unified-test-platform-android-test-plugin-result-listener-gradle,unified-test-platform-core,unified-test-platform-gradle-work-action,unified-test-platform-launcher com.google.j2objc:j2objc-annotations:2.8=unified-test-platform-android-driver-instrumentation,unified-test-platform-android-test-plugin,unified-test-platform-core,unified-test-platform-launcher com.google.j2objc:j2objc-annotations:3.0.0=androidLintTool,debugUnitTestCompileClasspath,debugUnitTestLintChecksClasspath,debugUnitTestRuntimeClasspath,unified-test-platform-android-device-provider-ddmlib,unified-test-platform-android-test-plugin-host-additional-test-output,unified-test-platform-android-test-plugin-host-apk-installer,unified-test-platform-android-test-plugin-host-coverage,unified-test-platform-android-test-plugin-host-device-info,unified-test-platform-android-test-plugin-host-emulator-control,unified-test-platform-android-test-plugin-host-logcat,unified-test-platform-android-test-plugin-result-listener-gradle,unified-test-platform-gradle-work-action +com.google.j2objc:j2objc-annotations:3.1=_agp_internal_debug_kspClasspath,_agp_internal_release_kspClasspath,hiltAnnotationProcessorDebug,hiltAnnotationProcessorDebugAndroidTest,hiltAnnotationProcessorDebugUnitTest,hiltAnnotationProcessorRelease,kspDebugKotlinProcessorClasspath,kspReleaseKotlinProcessorClasspath com.google.jimfs:jimfs:1.1=androidLintTool,unified-test-platform-android-test-plugin-result-listener-gradle com.google.mlkit:barcode-scanning-common:17.0.0=debugAndroidTestCompileClasspath,debugAndroidTestLintChecksClasspath,debugCompileClasspath,debugLintChecksClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestLintChecksClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseLintChecksClasspath,releaseRuntimeClasspath com.google.mlkit:barcode-scanning:17.3.0=debugAndroidTestCompileClasspath,debugAndroidTestLintChecksClasspath,debugCompileClasspath,debugLintChecksClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestLintChecksClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseLintChecksClasspath,releaseRuntimeClasspath @@ -288,7 +310,9 @@ com.squareup.okhttp3:okhttp-android:5.4.0=debugAndroidTestCompileClasspath,debug com.squareup.okhttp3:okhttp:5.4.0=debugAndroidTestCompileClasspath,debugAndroidTestLintChecksClasspath,debugCompileClasspath,debugLintChecksClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestLintChecksClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseLintChecksClasspath,releaseRuntimeClasspath com.squareup.okio:okio-jvm:3.17.0=debugAndroidTestCompileClasspath,debugAndroidTestLintChecksClasspath,debugCompileClasspath,debugLintChecksClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestLintChecksClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseLintChecksClasspath,releaseRuntimeClasspath com.squareup.okio:okio:3.17.0=debugAndroidTestCompileClasspath,debugAndroidTestLintChecksClasspath,debugCompileClasspath,debugLintChecksClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestLintChecksClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseLintChecksClasspath,releaseRuntimeClasspath +com.squareup:javapoet:1.13.0=_agp_internal_debug_kspClasspath,_agp_internal_release_kspClasspath,hiltAnnotationProcessorDebug,hiltAnnotationProcessorDebugAndroidTest,hiltAnnotationProcessorDebugUnitTest,hiltAnnotationProcessorRelease,kspDebugKotlinProcessorClasspath,kspReleaseKotlinProcessorClasspath com.squareup:javawriter:2.1.1=debugAndroidTestLintChecksClasspath,debugAndroidTestRuntimeClasspath +com.squareup:kotlinpoet:1.11.0=_agp_internal_debug_kspClasspath,_agp_internal_release_kspClasspath,hiltAnnotationProcessorDebug,hiltAnnotationProcessorDebugAndroidTest,hiltAnnotationProcessorDebugUnitTest,hiltAnnotationProcessorRelease,kspDebugKotlinProcessorClasspath,kspReleaseKotlinProcessorClasspath com.sun.istack:istack-commons-runtime:3.0.8=androidLintTool,unified-test-platform-android-test-plugin-result-listener-gradle com.sun.xml.fastinfoset:FastInfoset:1.2.16=androidLintTool,unified-test-platform-android-test-plugin-result-listener-gradle commons-codec:commons-codec:1.17.1=androidLintTool,unified-test-platform-android-test-plugin-result-listener-gradle @@ -337,15 +361,16 @@ io.opencensus:opencensus-proto:0.2.0=unified-test-platform-core,unified-test-pla io.perfmark:perfmark-api:0.26.0=unified-test-platform-core io.perfmark:perfmark-api:0.27.0=unified-test-platform-android-test-plugin-host-emulator-control jakarta.activation:jakarta.activation-api:1.2.1=androidLintTool,unified-test-platform-android-test-plugin-result-listener-gradle -jakarta.inject:jakarta.inject-api:2.0.1=debugAndroidTestLintChecksClasspath,debugLintChecksClasspath,debugRuntimeClasspath,debugUnitTestLintChecksClasspath,debugUnitTestRuntimeClasspath,releaseLintChecksClasspath,releaseRuntimeClasspath +jakarta.inject:jakarta.inject-api:2.0.1=_agp_internal_debug_kspClasspath,_agp_internal_release_kspClasspath,debugAndroidTestCompileClasspath,debugAndroidTestLintChecksClasspath,debugCompileClasspath,debugLintChecksClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestLintChecksClasspath,debugUnitTestRuntimeClasspath,hiltAnnotationProcessorDebug,hiltAnnotationProcessorDebugAndroidTest,hiltAnnotationProcessorDebugUnitTest,hiltAnnotationProcessorRelease,kspDebugKotlinProcessorClasspath,kspReleaseKotlinProcessorClasspath,releaseCompileClasspath,releaseLintChecksClasspath,releaseRuntimeClasspath jakarta.xml.bind:jakarta.xml.bind-api:2.3.2=androidLintTool,unified-test-platform-android-test-plugin-result-listener-gradle javax.annotation:javax.annotation-api:1.3.2=debugUnitTestCompileClasspath,debugUnitTestLintChecksClasspath,debugUnitTestRuntimeClasspath,unified-test-platform-android-test-plugin-host-emulator-control -javax.inject:javax.inject:1=androidLintTool,debugAndroidTestCompileClasspath,debugAndroidTestLintChecksClasspath,debugAndroidTestRuntimeClasspath,debugCompileClasspath,debugLintChecksClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestLintChecksClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseLintChecksClasspath,releaseRuntimeClasspath,unified-test-platform-android-device-provider-ddmlib,unified-test-platform-android-driver-instrumentation,unified-test-platform-android-test-plugin-host-additional-test-output,unified-test-platform-android-test-plugin-host-apk-installer,unified-test-platform-android-test-plugin-host-coverage,unified-test-platform-android-test-plugin-host-device-info,unified-test-platform-android-test-plugin-host-emulator-control,unified-test-platform-android-test-plugin-host-logcat,unified-test-platform-android-test-plugin-result-listener-gradle,unified-test-platform-core,unified-test-platform-gradle-work-action +javax.inject:javax.inject:1=_agp_internal_debug_kspClasspath,_agp_internal_release_kspClasspath,androidLintTool,debugAndroidTestCompileClasspath,debugAndroidTestLintChecksClasspath,debugAndroidTestRuntimeClasspath,debugCompileClasspath,debugLintChecksClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestLintChecksClasspath,debugUnitTestRuntimeClasspath,hiltAnnotationProcessorDebug,hiltAnnotationProcessorDebugAndroidTest,hiltAnnotationProcessorDebugUnitTest,hiltAnnotationProcessorRelease,kspDebugKotlinProcessorClasspath,kspReleaseKotlinProcessorClasspath,releaseCompileClasspath,releaseLintChecksClasspath,releaseRuntimeClasspath,unified-test-platform-android-device-provider-ddmlib,unified-test-platform-android-driver-instrumentation,unified-test-platform-android-test-plugin-host-additional-test-output,unified-test-platform-android-test-plugin-host-apk-installer,unified-test-platform-android-test-plugin-host-coverage,unified-test-platform-android-test-plugin-host-device-info,unified-test-platform-android-test-plugin-host-emulator-control,unified-test-platform-android-test-plugin-host-logcat,unified-test-platform-android-test-plugin-result-listener-gradle,unified-test-platform-core,unified-test-platform-gradle-work-action junit:junit:4.13.2=debugAndroidTestCompileClasspath,debugAndroidTestLintChecksClasspath,debugAndroidTestRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestLintChecksClasspath,debugUnitTestRuntimeClasspath net.bytebuddy:byte-buddy-agent:1.17.7=debugUnitTestCompileClasspath,debugUnitTestLintChecksClasspath,debugUnitTestRuntimeClasspath net.bytebuddy:byte-buddy:1.17.7=debugUnitTestCompileClasspath,debugUnitTestLintChecksClasspath,debugUnitTestRuntimeClasspath net.java.dev.jna:jna-platform:5.6.0=androidLintTool,unified-test-platform-android-device-provider-ddmlib,unified-test-platform-android-test-plugin-host-additional-test-output,unified-test-platform-android-test-plugin-host-apk-installer,unified-test-platform-android-test-plugin-host-coverage,unified-test-platform-android-test-plugin-host-device-info,unified-test-platform-android-test-plugin-host-emulator-control,unified-test-platform-android-test-plugin-host-logcat,unified-test-platform-android-test-plugin-result-listener-gradle,unified-test-platform-gradle-work-action net.java.dev.jna:jna:5.6.0=androidLintTool,unified-test-platform-android-device-provider-ddmlib,unified-test-platform-android-test-plugin-host-additional-test-output,unified-test-platform-android-test-plugin-host-apk-installer,unified-test-platform-android-test-plugin-host-coverage,unified-test-platform-android-test-plugin-host-device-info,unified-test-platform-android-test-plugin-host-emulator-control,unified-test-platform-android-test-plugin-host-logcat,unified-test-platform-android-test-plugin-result-listener-gradle,unified-test-platform-gradle-work-action +net.ltgt.gradle.incap:incap:0.2=_agp_internal_debug_kspClasspath,_agp_internal_release_kspClasspath,hiltAnnotationProcessorDebug,hiltAnnotationProcessorDebugAndroidTest,hiltAnnotationProcessorDebugUnitTest,hiltAnnotationProcessorRelease,kspDebugKotlinProcessorClasspath,kspReleaseKotlinProcessorClasspath net.sf.kxml:kxml2:2.3.0=androidLintTool,unified-test-platform-android-device-provider-ddmlib,unified-test-platform-android-test-plugin-result-listener-gradle,unified-test-platform-gradle-work-action no.nordicsemi.android:ble:2.11.0=debugAndroidTestCompileClasspath,debugAndroidTestLintChecksClasspath,debugCompileClasspath,debugLintChecksClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestLintChecksClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseLintChecksClasspath,releaseRuntimeClasspath org.apache.commons:commons-compress:1.27.1=androidLintTool,unified-test-platform-android-test-plugin-result-listener-gradle @@ -357,6 +382,7 @@ org.bouncycastle:bcpkix-jdk18on:1.79=androidLintTool,unified-test-platform-andro org.bouncycastle:bcprov-jdk18on:1.79=androidLintTool,unified-test-platform-android-test-plugin-result-listener-gradle org.bouncycastle:bcprov-jdk18on:1.85=debugAndroidTestCompileClasspath,debugAndroidTestLintChecksClasspath,debugCompileClasspath,debugLintChecksClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestLintChecksClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseLintChecksClasspath,releaseRuntimeClasspath org.bouncycastle:bcutil-jdk18on:1.79=androidLintTool,unified-test-platform-android-test-plugin-result-listener-gradle +org.checkerframework:checker-compat-qual:2.5.3=_agp_internal_debug_kspClasspath,_agp_internal_release_kspClasspath,hiltAnnotationProcessorDebug,hiltAnnotationProcessorDebugAndroidTest,hiltAnnotationProcessorDebugUnitTest,hiltAnnotationProcessorRelease,kspDebugKotlinProcessorClasspath,kspReleaseKotlinProcessorClasspath org.checkerframework:checker-qual:3.33.0=unified-test-platform-android-driver-instrumentation,unified-test-platform-android-test-plugin,unified-test-platform-core,unified-test-platform-launcher org.checkerframework:checker-qual:3.43.0=androidLintTool,unified-test-platform-android-device-provider-ddmlib,unified-test-platform-android-test-plugin-host-additional-test-output,unified-test-platform-android-test-plugin-host-apk-installer,unified-test-platform-android-test-plugin-host-coverage,unified-test-platform-android-test-plugin-host-device-info,unified-test-platform-android-test-plugin-host-emulator-control,unified-test-platform-android-test-plugin-host-logcat,unified-test-platform-android-test-plugin-result-listener-gradle,unified-test-platform-gradle-work-action org.codehaus.groovy:groovy:3.0.22=androidLintTool @@ -385,9 +411,10 @@ org.jetbrains.kotlin:kotlin-daemon-client:2.4.0=kotlinAbiValidationCompatClasspa org.jetbrains.kotlin:kotlin-daemon-client:2.4.10=kotlinBuildToolsApiClasspath,kotlinCompilerClasspath org.jetbrains.kotlin:kotlin-daemon-embeddable:2.4.0=kotlinAbiValidationCompatClasspath org.jetbrains.kotlin:kotlin-daemon-embeddable:2.4.10=kotlinBuildToolsApiClasspath,kotlinCompilerClasspath,kotlinCompilerPluginClasspathDebug,kotlinCompilerPluginClasspathDebugAndroidTest,kotlinCompilerPluginClasspathDebugUnitTest,kotlinCompilerPluginClasspathRelease +org.jetbrains.kotlin:kotlin-metadata-jvm:2.3.21=_agp_internal_debug_kspClasspath,_agp_internal_release_kspClasspath,hiltAnnotationProcessorDebug,hiltAnnotationProcessorDebugAndroidTest,hiltAnnotationProcessorDebugUnitTest,hiltAnnotationProcessorRelease,kspDebugKotlinProcessorClasspath,kspReleaseKotlinProcessorClasspath org.jetbrains.kotlin:kotlin-parcelize-compiler:2.4.10=kotlinCompilerPluginClasspathDebug,kotlinCompilerPluginClasspathDebugAndroidTest,kotlinCompilerPluginClasspathDebugUnitTest,kotlinCompilerPluginClasspathRelease org.jetbrains.kotlin:kotlin-parcelize-runtime:2.4.10=debugAndroidTestCompileClasspath,debugAndroidTestLintChecksClasspath,debugAndroidTestRuntimeClasspath,debugCompileClasspath,debugLintChecksClasspath,debugRuntimeClasspath,debugRuntimeClasspathCopy,debugUnitTestCompileClasspath,debugUnitTestLintChecksClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseLintChecksClasspath,releaseRuntimeClasspath,releaseRuntimeClasspathCopy -org.jetbrains.kotlin:kotlin-reflect:1.6.10=kotlinAbiValidationCompatClasspath,kotlinBuildToolsApiClasspath,kotlinCompilerClasspath,kotlinCompilerPluginClasspathDebug,kotlinCompilerPluginClasspathDebugAndroidTest,kotlinCompilerPluginClasspathDebugUnitTest,kotlinCompilerPluginClasspathRelease +org.jetbrains.kotlin:kotlin-reflect:1.6.10=_agp_internal_debug_kspClasspath,_agp_internal_release_kspClasspath,hiltAnnotationProcessorDebug,hiltAnnotationProcessorDebugAndroidTest,hiltAnnotationProcessorDebugUnitTest,hiltAnnotationProcessorRelease,kotlinAbiValidationCompatClasspath,kotlinBuildToolsApiClasspath,kotlinCompilerClasspath,kotlinCompilerPluginClasspathDebug,kotlinCompilerPluginClasspathDebugAndroidTest,kotlinCompilerPluginClasspathDebugUnitTest,kotlinCompilerPluginClasspathRelease,kspDebugKotlinProcessorClasspath,kspReleaseKotlinProcessorClasspath org.jetbrains.kotlin:kotlin-reflect:1.8.21=unified-test-platform-android-device-provider-ddmlib,unified-test-platform-android-driver-instrumentation,unified-test-platform-android-test-plugin,unified-test-platform-android-test-plugin-host-additional-test-output,unified-test-platform-android-test-plugin-host-apk-installer,unified-test-platform-android-test-plugin-host-coverage,unified-test-platform-android-test-plugin-host-device-info,unified-test-platform-android-test-plugin-host-emulator-control,unified-test-platform-android-test-plugin-host-logcat,unified-test-platform-core,unified-test-platform-gradle-work-action,unified-test-platform-launcher org.jetbrains.kotlin:kotlin-reflect:2.1.20=debugUnitTestLintChecksClasspath,debugUnitTestRuntimeClasspath org.jetbrains.kotlin:kotlin-reflect:2.2.10=androidLintTool,unified-test-platform-android-test-plugin-result-listener-gradle @@ -397,9 +424,11 @@ org.jetbrains.kotlin:kotlin-stdlib-common:1.8.21=unified-test-platform-android-t org.jetbrains.kotlin:kotlin-stdlib-common:1.9.0=unified-test-platform-android-driver-instrumentation,unified-test-platform-launcher org.jetbrains.kotlin:kotlin-stdlib-common:2.2.10=unified-test-platform-android-device-provider-ddmlib,unified-test-platform-android-test-plugin-host-additional-test-output,unified-test-platform-android-test-plugin-host-apk-installer,unified-test-platform-android-test-plugin-host-coverage,unified-test-platform-android-test-plugin-host-device-info,unified-test-platform-android-test-plugin-host-emulator-control,unified-test-platform-android-test-plugin-host-logcat,unified-test-platform-gradle-work-action org.jetbrains.kotlin:kotlin-stdlib-common:2.4.10=debugAndroidTestLintChecksClasspath,debugLintChecksClasspath,debugRuntimeClasspath,debugUnitTestLintChecksClasspath,debugUnitTestRuntimeClasspath,releaseLintChecksClasspath,releaseRuntimeClasspath +org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.8.0=_agp_internal_debug_kspClasspath,_agp_internal_release_kspClasspath,hiltAnnotationProcessorDebug,hiltAnnotationProcessorDebugAndroidTest,hiltAnnotationProcessorDebugUnitTest,hiltAnnotationProcessorRelease,kspDebugKotlinProcessorClasspath,kspReleaseKotlinProcessorClasspath org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.8.20=unified-test-platform-android-driver-instrumentation,unified-test-platform-android-test-plugin,unified-test-platform-core,unified-test-platform-launcher org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.8.22=debugAndroidTestLintChecksClasspath,debugLintChecksClasspath,debugRuntimeClasspath,debugUnitTestLintChecksClasspath,debugUnitTestRuntimeClasspath,releaseLintChecksClasspath,releaseRuntimeClasspath org.jetbrains.kotlin:kotlin-stdlib-jdk7:2.2.10=androidLintTool,unified-test-platform-android-device-provider-ddmlib,unified-test-platform-android-test-plugin-host-additional-test-output,unified-test-platform-android-test-plugin-host-apk-installer,unified-test-platform-android-test-plugin-host-coverage,unified-test-platform-android-test-plugin-host-device-info,unified-test-platform-android-test-plugin-host-emulator-control,unified-test-platform-android-test-plugin-host-logcat,unified-test-platform-android-test-plugin-result-listener-gradle,unified-test-platform-gradle-work-action +org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.8.0=_agp_internal_debug_kspClasspath,_agp_internal_release_kspClasspath,hiltAnnotationProcessorDebug,hiltAnnotationProcessorDebugAndroidTest,hiltAnnotationProcessorDebugUnitTest,hiltAnnotationProcessorRelease,kspDebugKotlinProcessorClasspath,kspReleaseKotlinProcessorClasspath org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.8.20=unified-test-platform-android-driver-instrumentation,unified-test-platform-android-test-plugin,unified-test-platform-core,unified-test-platform-launcher org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.8.22=debugAndroidTestLintChecksClasspath,debugLintChecksClasspath,debugRuntimeClasspath,debugUnitTestLintChecksClasspath,debugUnitTestRuntimeClasspath,releaseLintChecksClasspath,releaseRuntimeClasspath org.jetbrains.kotlin:kotlin-stdlib-jdk8:2.2.10=androidLintTool,unified-test-platform-android-device-provider-ddmlib,unified-test-platform-android-test-plugin-host-additional-test-output,unified-test-platform-android-test-plugin-host-apk-installer,unified-test-platform-android-test-plugin-host-coverage,unified-test-platform-android-test-plugin-host-device-info,unified-test-platform-android-test-plugin-host-emulator-control,unified-test-platform-android-test-plugin-host-logcat,unified-test-platform-android-test-plugin-result-listener-gradle,unified-test-platform-gradle-work-action @@ -407,6 +436,8 @@ org.jetbrains.kotlin:kotlin-stdlib:1.8.21=unified-test-platform-android-test-plu org.jetbrains.kotlin:kotlin-stdlib:1.9.0=unified-test-platform-android-driver-instrumentation,unified-test-platform-launcher org.jetbrains.kotlin:kotlin-stdlib:2.2.10=androidLintTool,unified-test-platform-android-device-provider-ddmlib,unified-test-platform-android-test-plugin-host-additional-test-output,unified-test-platform-android-test-plugin-host-apk-installer,unified-test-platform-android-test-plugin-host-coverage,unified-test-platform-android-test-plugin-host-device-info,unified-test-platform-android-test-plugin-host-emulator-control,unified-test-platform-android-test-plugin-host-logcat,unified-test-platform-android-test-plugin-result-listener-gradle,unified-test-platform-gradle-work-action org.jetbrains.kotlin:kotlin-stdlib:2.2.21=composeMappingProducerClasspath +org.jetbrains.kotlin:kotlin-stdlib:2.3.20=kspPluginClasspath,kspPluginClasspathNonEmbeddable +org.jetbrains.kotlin:kotlin-stdlib:2.3.21=_agp_internal_debug_kspClasspath,_agp_internal_release_kspClasspath,hiltAnnotationProcessorDebug,hiltAnnotationProcessorDebugAndroidTest,hiltAnnotationProcessorDebugUnitTest,hiltAnnotationProcessorRelease,kspDebugKotlinProcessorClasspath,kspReleaseKotlinProcessorClasspath org.jetbrains.kotlin:kotlin-stdlib:2.4.0=kotlinAbiValidationCompatClasspath org.jetbrains.kotlin:kotlin-stdlib:2.4.10=debugAndroidTestCompileClasspath,debugAndroidTestLintChecksClasspath,debugAndroidTestRuntimeClasspath,debugCompileClasspath,debugLintChecksClasspath,debugRuntimeClasspath,debugRuntimeClasspathCopy,debugUnitTestCompileClasspath,debugUnitTestLintChecksClasspath,debugUnitTestRuntimeClasspath,kotlinBuildToolsApiClasspath,kotlinCompilerClasspath,kotlinCompilerPluginClasspathDebug,kotlinCompilerPluginClasspathDebugAndroidTest,kotlinCompilerPluginClasspathDebugUnitTest,kotlinCompilerPluginClasspathRelease,releaseCompileClasspath,releaseLintChecksClasspath,releaseRuntimeClasspath,releaseRuntimeClasspathCopy org.jetbrains.kotlin:kotlin-tooling-core:2.4.10=kotlinAbiValidationCompatClasspath,kotlinBuildToolsApiClasspath,kotlinCompilerClasspath @@ -430,9 +461,9 @@ org.jetbrains.kotlinx:kotlinx-coroutines-test:1.11.0=debugAndroidTestCompileClas org.jetbrains.kotlinx:kotlinx-serialization-bom:1.7.3=debugAndroidTestCompileClasspath,debugAndroidTestLintChecksClasspath,debugAndroidTestRuntimeClasspath,debugCompileClasspath,debugLintChecksClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestLintChecksClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseLintChecksClasspath,releaseRuntimeClasspath org.jetbrains.kotlinx:kotlinx-serialization-core-jvm:1.7.3=debugAndroidTestCompileClasspath,debugAndroidTestLintChecksClasspath,debugAndroidTestRuntimeClasspath,debugCompileClasspath,debugLintChecksClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestLintChecksClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseLintChecksClasspath,releaseRuntimeClasspath org.jetbrains.kotlinx:kotlinx-serialization-core:1.7.3=debugAndroidTestCompileClasspath,debugAndroidTestLintChecksClasspath,debugAndroidTestRuntimeClasspath,debugCompileClasspath,debugLintChecksClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestLintChecksClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseLintChecksClasspath,releaseRuntimeClasspath -org.jetbrains:annotations:13.0=composeMappingProducerClasspath,debugRuntimeClasspathCopy,kotlinAbiValidationCompatClasspath,kotlinBuildToolsApiClasspath,kotlinCompilerClasspath,kotlinCompilerPluginClasspathDebug,kotlinCompilerPluginClasspathDebugAndroidTest,kotlinCompilerPluginClasspathDebugUnitTest,kotlinCompilerPluginClasspathRelease,releaseRuntimeClasspathCopy +org.jetbrains:annotations:13.0=_agp_internal_debug_kspClasspath,_agp_internal_release_kspClasspath,composeMappingProducerClasspath,debugRuntimeClasspathCopy,hiltAnnotationProcessorDebug,hiltAnnotationProcessorDebugAndroidTest,hiltAnnotationProcessorDebugUnitTest,hiltAnnotationProcessorRelease,kotlinAbiValidationCompatClasspath,kotlinBuildToolsApiClasspath,kotlinCompilerClasspath,kotlinCompilerPluginClasspathDebug,kotlinCompilerPluginClasspathDebugAndroidTest,kotlinCompilerPluginClasspathDebugUnitTest,kotlinCompilerPluginClasspathRelease,kspDebugKotlinProcessorClasspath,kspPluginClasspath,kspPluginClasspathNonEmbeddable,kspReleaseKotlinProcessorClasspath,releaseRuntimeClasspathCopy org.jetbrains:annotations:23.0.0=androidLintTool,debugAndroidTestCompileClasspath,debugAndroidTestLintChecksClasspath,debugAndroidTestRuntimeClasspath,debugCompileClasspath,debugLintChecksClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestLintChecksClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseLintChecksClasspath,releaseRuntimeClasspath,unified-test-platform-android-device-provider-ddmlib,unified-test-platform-android-driver-instrumentation,unified-test-platform-android-test-plugin,unified-test-platform-android-test-plugin-host-additional-test-output,unified-test-platform-android-test-plugin-host-apk-installer,unified-test-platform-android-test-plugin-host-coverage,unified-test-platform-android-test-plugin-host-device-info,unified-test-platform-android-test-plugin-host-emulator-control,unified-test-platform-android-test-plugin-host-logcat,unified-test-platform-android-test-plugin-result-listener-gradle,unified-test-platform-core,unified-test-platform-gradle-work-action,unified-test-platform-launcher -org.jspecify:jspecify:1.0.0=debugAndroidTestCompileClasspath,debugAndroidTestLintChecksClasspath,debugAndroidTestRuntimeClasspath,debugCompileClasspath,debugLintChecksClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestLintChecksClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseLintChecksClasspath,releaseRuntimeClasspath +org.jspecify:jspecify:1.0.0=_agp_internal_debug_kspClasspath,_agp_internal_release_kspClasspath,debugAndroidTestCompileClasspath,debugAndroidTestLintChecksClasspath,debugAndroidTestRuntimeClasspath,debugCompileClasspath,debugLintChecksClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestLintChecksClasspath,debugUnitTestRuntimeClasspath,hiltAnnotationProcessorDebug,hiltAnnotationProcessorDebugAndroidTest,hiltAnnotationProcessorDebugUnitTest,hiltAnnotationProcessorRelease,kspDebugKotlinProcessorClasspath,kspReleaseKotlinProcessorClasspath,releaseCompileClasspath,releaseLintChecksClasspath,releaseRuntimeClasspath org.jvnet.staxex:stax-ex:1.8.1=androidLintTool,unified-test-platform-android-test-plugin-result-listener-gradle org.mockito.kotlin:mockito-kotlin:6.3.0=debugUnitTestCompileClasspath,debugUnitTestLintChecksClasspath,debugUnitTestRuntimeClasspath org.mockito:mockito-core:5.23.0=debugUnitTestCompileClasspath,debugUnitTestLintChecksClasspath,debugUnitTestRuntimeClasspath @@ -461,4 +492,4 @@ org.robolectric:shadows-framework:4.15=debugUnitTestCompileClasspath,debugUnitTe org.robolectric:utils-reflector:4.15=debugUnitTestCompileClasspath,debugUnitTestLintChecksClasspath,debugUnitTestRuntimeClasspath org.robolectric:utils:4.15=debugUnitTestCompileClasspath,debugUnitTestLintChecksClasspath,debugUnitTestRuntimeClasspath org.yaml:snakeyaml:2.4=debugUnitTestLintChecksClasspath,debugUnitTestRuntimeClasspath -empty=androidApis,androidJdkImage,androidTestUtil,coreLibraryDesugaring,debugAndroidTestAnnotationProcessorClasspath,debugAndroidTestImplementationDependenciesMetadata,debugAnnotationProcessorClasspath,debugImplementationDependenciesMetadata,debugReverseMetadataValues,debugUnitTestAnnotationProcessorClasspath,debugUnitTestImplementationDependenciesMetadata,kotlinCompilerPluginClasspath,lintChecks,lintPublish,releaseAnnotationProcessorClasspath,releaseImplementationDependenciesMetadata,releaseReverseMetadataValues +empty=_agp_internal_debugAndroidTest_kspClasspath,_agp_internal_debugUnitTest_kspClasspath,androidApis,androidJdkImage,androidTestUtil,coreLibraryDesugaring,debugAndroidTestAnnotationProcessorClasspath,debugAndroidTestImplementationDependenciesMetadata,debugAnnotationProcessorClasspath,debugImplementationDependenciesMetadata,debugReverseMetadataValues,debugUnitTestAnnotationProcessorClasspath,debugUnitTestImplementationDependenciesMetadata,hiltCompileOnlyDebug,hiltCompileOnlyDebugAndroidTest,hiltCompileOnlyDebugUnitTest,hiltCompileOnlyRelease,kotlinCompilerPluginClasspath,kspDebugAndroidTestKotlinProcessorClasspath,kspDebugUnitTestKotlinProcessorClasspath,lintChecks,lintPublish,releaseAnnotationProcessorClasspath,releaseImplementationDependenciesMetadata,releaseReverseMetadataValues diff --git a/app/src/main/java/com/bitchat/android/BitchatApplication.kt b/app/src/main/java/com/bitchat/android/BitchatApplication.kt index 7b5926ef..b4107ba3 100644 --- a/app/src/main/java/com/bitchat/android/BitchatApplication.kt +++ b/app/src/main/java/com/bitchat/android/BitchatApplication.kt @@ -4,10 +4,12 @@ import android.app.Application import com.bitchat.android.nostr.RelayDirectory import com.bitchat.android.ui.theme.ThemePreferenceManager import com.bitchat.android.net.ArtiTorManager +import dagger.hilt.android.HiltAndroidApp /** * Main application class for bitchat Android */ +@HiltAndroidApp class BitchatApplication : Application() { override fun onCreate() { diff --git a/app/src/main/java/com/bitchat/android/MainActivity.kt b/app/src/main/java/com/bitchat/android/MainActivity.kt index 6f80052a..b0e56485 100644 --- a/app/src/main/java/com/bitchat/android/MainActivity.kt +++ b/app/src/main/java/com/bitchat/android/MainActivity.kt @@ -4,7 +4,7 @@ import android.content.Intent import android.os.Build import android.os.Bundle import android.util.Log -import androidx.activity.OnBackPressedCallback +import androidx.activity.compose.BackHandler import androidx.activity.compose.setContent import androidx.activity.enableEdgeToEdge import androidx.activity.viewModels @@ -14,9 +14,7 @@ import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Scaffold import androidx.compose.runtime.* import androidx.compose.ui.Modifier -import androidx.compose.ui.platform.LocalContext import androidx.lifecycle.lifecycleScope -import androidx.lifecycle.ViewModelProvider import androidx.lifecycle.repeatOnLifecycle import androidx.lifecycle.Lifecycle import com.bitchat.android.mesh.BluetoothMeshService @@ -45,10 +43,19 @@ import com.bitchat.android.ui.OrientationAwareActivity import com.bitchat.android.ui.theme.BitchatTheme import com.bitchat.android.wifiaware.WifiAwareController import com.bitchat.android.nostr.PoWPreferenceManager +import com.bitchat.android.navigation.AppNavigator +import com.bitchat.android.navigation.BitchatNavDisplay +import com.bitchat.android.navigation.ChatRoute +import com.bitchat.android.navigation.EntryProviderInstaller +import com.bitchat.android.navigation.OnboardingRoute +import com.bitchat.android.navigation.rootRouteFor import com.bitchat.android.services.VerificationService +import dagger.hilt.android.AndroidEntryPoint +import javax.inject.Inject import kotlinx.coroutines.delay import kotlinx.coroutines.launch +@AndroidEntryPoint class MainActivity : OrientationAwareActivity() { private lateinit var permissionManager: PermissionManager @@ -62,15 +69,18 @@ class MainActivity : OrientationAwareActivity() { private lateinit var unifiedMeshService: MeshService private val mainViewModel: MainViewModel by viewModels() private var pendingMeshForegroundServiceStart = false - private val chatViewModel: ChatViewModel by viewModels { - object : ViewModelProvider.Factory { - override fun create(modelClass: Class): T { - @Suppress("UNCHECKED_CAST") - return ChatViewModel(application, meshService, unifiedMeshService) as T - } - } - } - + private val chatViewModel: ChatViewModel by viewModels() + + // Held by ActivityRetainedComponent, so the back stack outlives configuration + // changes without being rebuilt here. + @Inject + lateinit var navigator: AppNavigator + + // Watches the adapter for the whole Activity, not for as long as some + // composable happens to stay on screen. Scoping it to a destination is what + // let a Bluetooth switch-off go unnoticed once chat became its own route. + private var bluetoothStateReceiver: android.content.BroadcastReceiver? = null + private val forceFinishReceiver = object : android.content.BroadcastReceiver() { override fun onReceive(context: android.content.Context, intent: android.content.Intent) { if (intent.action == com.bitchat.android.util.AppConstants.UI.ACTION_FORCE_FINISH) { @@ -160,14 +170,78 @@ class MainActivity : OrientationAwareActivity() { modifier = Modifier.fillMaxSize(), containerColor = MaterialTheme.colorScheme.background ) { innerPadding -> - OnboardingFlowScreen(modifier = Modifier + // Only onboarding takes the scaffold insets; ChatScreen applies + // its own status, navigation and IME padding. + val onboardingModifier = Modifier .fillMaxSize() .padding(innerPadding) - ) + val onboardingState by mainViewModel.onboardingState.collectAsState() + val root = rootRouteFor(onboardingState) + + // Seeds the stack on its first run and re-roots it on every + // later crossing between onboarding and chat. Keyed on root, so + // it stays quiet between onboarding steps. resetTo rather than + // goTo: onboarding must not be reachable with Back once the app + // is in. Compares the root of the stack, not its top, so pushing + // a destination onto chat does not read as a crossing. + LaunchedEffect(root) { + if (navigator.backStack.firstOrNull() != root) { + navigator.resetTo(root) + } + } + + val entries: EntryProviderInstaller = { + entry { OnboardingFlowScreen(onboardingModifier) } + entry { ChatScreen(viewModel = chatViewModel) } + } + + // NavDisplay rejects an empty back stack and the effect above does + // not run until after this composition, so the host waits a frame + // for it. Gate on the stack itself: root is non-null immediately, + // so gating on that would compose with nothing to show. + if (navigator.backStack.isNotEmpty()) { + BitchatNavDisplay( + navigator = navigator, + entryInstallers = setOf(entries), + onExit = { finish() }, + modifier = Modifier.fillMaxSize(), + ) + } + + // Chat still drives its overlays with booleans rather than routes, + // and NavDisplay enables its own handler only while something sits + // beneath the current scene, which at the root destination is never. + // So the press has to be claimed here. Composed after NavDisplay: + // among enabled handlers the last one composed wins, so overlays + // unwind before routes pop. Called unconditionally and gated by + // enabled, because a conditional call would reorder composition. + // Removed once the overlays become routes. + val canHandleBack by chatViewModel.canHandleBack.collectAsState() + BackHandler( + enabled = navigator.backStack.lastOrNull() == ChatRoute && canHandleBack + ) { + // enabled trails the state by a dispatch and a recomposition, so a + // second quick press can arrive with nothing left to unwind. Forward + // it rather than swallowing it: pop a route if there is one, and + // otherwise leave, which is what the press would have done anyway. + if (!chatViewModel.handleBackPressed() && !navigator.goBack()) finish() + } } } } + bluetoothStateReceiver = bluetoothStatusManager.monitorBluetoothState( + context = this, + bluetoothStatusManager = bluetoothStatusManager, + onBluetoothStateChanged = { status -> + if (status == BluetoothStatus.ENABLED && + mainViewModel.onboardingState.value == OnboardingState.BLUETOOTH_CHECK + ) { + checkBluetoothAndProceed() + } + } + ) + // Collect state changes in a lifecycle-aware manner lifecycleScope.launch { repeatOnLifecycle(Lifecycle.State.STARTED) { @@ -197,7 +271,6 @@ class MainActivity : OrientationAwareActivity() { @Composable private fun OnboardingFlowScreen(modifier: Modifier = Modifier) { - val context = LocalContext.current val onboardingState by mainViewModel.onboardingState.collectAsState() val bluetoothStatus by mainViewModel.bluetoothStatus.collectAsState() val locationStatus by mainViewModel.locationStatus.collectAsState() @@ -207,27 +280,6 @@ class MainActivity : OrientationAwareActivity() { val isLocationLoading by mainViewModel.isLocationLoading.collectAsState() val isBatteryOptimizationLoading by mainViewModel.isBatteryOptimizationLoading.collectAsState() - DisposableEffect(context, bluetoothStatusManager) { - - val receiver = bluetoothStatusManager.monitorBluetoothState( - context = context, - bluetoothStatusManager = bluetoothStatusManager, - onBluetoothStateChanged = { status -> - if (status == BluetoothStatus.ENABLED && onboardingState == OnboardingState.BLUETOOTH_CHECK) { - checkBluetoothAndProceed() - } - } - ) - - onDispose { - try { - context.unregisterReceiver(receiver) - } catch (e: IllegalStateException) { - Log.w("BluetoothStatusUI", "Receiver was not registered") - } - } - } - when (onboardingState) { OnboardingState.PERMISSION_REQUESTING -> { InitializingScreen(modifier) @@ -312,27 +364,12 @@ class MainActivity : OrientationAwareActivity() { ) } - OnboardingState.CHECKING, OnboardingState.INITIALIZING, OnboardingState.COMPLETE -> { - // Set up back navigation handling for the chat screen - val backCallback = object : OnBackPressedCallback(true) { - override fun handleOnBackPressed() { - // Let ChatViewModel handle navigation state - val handled = chatViewModel.handleBackPressed() - if (!handled) { - // If ChatViewModel doesn't handle it, disable this callback - // and let the system handle it (which will exit the app) - this.isEnabled = false - onBackPressedDispatcher.onBackPressed() - this.isEnabled = true - } - } - } + // CHECKING, INITIALIZING and COMPLETE are handled by ChatRoute, so this + // composable is only ever shown for the onboarding steps themselves. + OnboardingState.CHECKING, + OnboardingState.INITIALIZING, + OnboardingState.COMPLETE -> Unit - // Add the callback - this will be automatically removed when the activity is destroyed - onBackPressedDispatcher.addCallback(this, backCallback) - ChatScreen(viewModel = chatViewModel) - } - OnboardingState.ERROR -> { InitializationErrorScreen( modifier = modifier, @@ -864,6 +901,10 @@ class MainActivity : OrientationAwareActivity() { super.onDestroy() try { unregisterReceiver(forceFinishReceiver) } catch (_: Exception) { } + bluetoothStateReceiver?.let { + try { unregisterReceiver(it) } catch (_: IllegalArgumentException) { } + } + bluetoothStateReceiver = null // Cleanup location status manager try { diff --git a/app/src/main/java/com/bitchat/android/MainViewModel.kt b/app/src/main/java/com/bitchat/android/MainViewModel.kt index 15ec6fda..aa30b6bd 100644 --- a/app/src/main/java/com/bitchat/android/MainViewModel.kt +++ b/app/src/main/java/com/bitchat/android/MainViewModel.kt @@ -5,11 +5,14 @@ import com.bitchat.android.onboarding.BluetoothStatus import com.bitchat.android.onboarding.LocationStatus import com.bitchat.android.onboarding.OnboardingState import com.bitchat.android.onboarding.BatteryOptimizationStatus +import dagger.hilt.android.lifecycle.HiltViewModel import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.asStateFlow +import javax.inject.Inject -class MainViewModel : ViewModel() { +@HiltViewModel +class MainViewModel @Inject constructor() : ViewModel() { private val _onboardingState = MutableStateFlow(OnboardingState.CHECKING) val onboardingState: StateFlow = _onboardingState.asStateFlow() diff --git a/app/src/main/java/com/bitchat/android/di/MeshModule.kt b/app/src/main/java/com/bitchat/android/di/MeshModule.kt new file mode 100644 index 00000000..2cb8453c --- /dev/null +++ b/app/src/main/java/com/bitchat/android/di/MeshModule.kt @@ -0,0 +1,36 @@ +package com.bitchat.android.di + +import android.content.Context +import com.bitchat.android.mesh.BluetoothMeshService +import com.bitchat.android.mesh.MeshService +import com.bitchat.android.service.MeshServiceHolder +import dagger.Module +import dagger.Provides +import dagger.hilt.InstallIn +import dagger.hilt.android.qualifiers.ApplicationContext +import dagger.hilt.components.SingletonComponent + +/** + * Bridges the process-wide mesh instances into the injection graph. + * + * [MeshServiceHolder] remains the single source of truth: it is shared with the + * foreground service, it synchronises creation, and it supports replacing the + * mesh service after a panic clear. These bindings are therefore deliberately + * unscoped — each injection re-reads the holder. Caching them with @Singleton + * would pin the first instance for the process lifetime and hand out a stale + * mesh service after a replacement. + */ +@Module +@InstallIn(SingletonComponent::class) +object MeshModule { + + @Provides + fun provideBluetoothMeshService( + @ApplicationContext context: Context + ): BluetoothMeshService = MeshServiceHolder.getOrCreate(context) + + @Provides + fun provideMeshService( + @ApplicationContext context: Context + ): MeshService = MeshServiceHolder.getUnifiedOrCreate(context) +} diff --git a/app/src/main/java/com/bitchat/android/hotspot/HotspotActivity.kt b/app/src/main/java/com/bitchat/android/hotspot/HotspotActivity.kt index 35d0f4ec..41b6eb80 100644 --- a/app/src/main/java/com/bitchat/android/hotspot/HotspotActivity.kt +++ b/app/src/main/java/com/bitchat/android/hotspot/HotspotActivity.kt @@ -39,6 +39,7 @@ import com.bitchat.android.R import com.bitchat.android.ui.theme.BitchatFontFamily import com.bitchat.android.ui.theme.BitchatTheme import com.bitchat.android.util.UniversalApkManager +import dagger.hilt.android.AndroidEntryPoint import com.google.accompanist.permissions.ExperimentalPermissionsApi import com.google.accompanist.permissions.rememberMultiplePermissionsState import java.io.File @@ -47,6 +48,7 @@ import java.io.File * Activity for managing Wi-Fi P2P hotspot for offline APK sharing. * Pure Compose implementation, no fragments. */ +@AndroidEntryPoint class HotspotActivity : ComponentActivity() { companion object { diff --git a/app/src/main/java/com/bitchat/android/hotspot/HotspotViewModel.kt b/app/src/main/java/com/bitchat/android/hotspot/HotspotViewModel.kt index 73f9faa4..d012ccbb 100644 --- a/app/src/main/java/com/bitchat/android/hotspot/HotspotViewModel.kt +++ b/app/src/main/java/com/bitchat/android/hotspot/HotspotViewModel.kt @@ -7,6 +7,8 @@ import android.util.Log import androidx.lifecycle.AndroidViewModel import androidx.lifecycle.viewModelScope import com.bitchat.android.wifiaware.WifiAwareController +import dagger.hilt.android.lifecycle.HiltViewModel +import javax.inject.Inject import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.asStateFlow @@ -16,7 +18,10 @@ import java.io.File /** * ViewModel for managing hotspot state and lifecycle. */ -class HotspotViewModel(application: Application) : AndroidViewModel(application) { +@HiltViewModel +class HotspotViewModel @Inject constructor( + application: Application +) : AndroidViewModel(application) { companion object { private const val TAG = "HotspotViewModel" diff --git a/app/src/main/java/com/bitchat/android/navigation/AppNavigator.kt b/app/src/main/java/com/bitchat/android/navigation/AppNavigator.kt new file mode 100644 index 00000000..723b304a --- /dev/null +++ b/app/src/main/java/com/bitchat/android/navigation/AppNavigator.kt @@ -0,0 +1,65 @@ +package com.bitchat.android.navigation + +import androidx.compose.runtime.Stable +import androidx.compose.runtime.mutableStateListOf +import androidx.compose.runtime.snapshots.SnapshotStateList +import androidx.navigation3.runtime.NavKey +import dagger.hilt.android.scopes.ActivityRetainedScoped +import javax.inject.Inject + +/** + * Single-stack navigator backed by a [SnapshotStateList] that NavDisplay observes. + * + * Scoped to [dagger.hilt.android.components.ActivityRetainedComponent], which is + * what makes the back stack survive configuration changes — there is no + * rememberNavBackStack here, and so no requirement that keys be serializable. + * + * The stack is *not* restored across process death. Nothing needs that yet: + * onboarding re-derives its state on launch. When it is needed, the move is + * kotlinx-serialization plus rememberNavBackStack, which is why keys are kept as + * plain data objects that would be trivial to annotate. + * + * Deliberately single-stack. The multi-back-stack pattern exists to serve bottom + * navigation; this app has no tabs, so it would be a map that only ever holds + * one key. + */ +@Stable +@ActivityRetainedScoped +class AppNavigator @Inject constructor() : Navigator { + + val backStack: SnapshotStateList = mutableStateListOf() + + override fun goTo(dest: NavKey) { + // A same-frame double tap pushes the same key twice. Dedup at the source + // rather than guarding every call site. + if (backStack.lastOrNull() != dest) backStack.add(dest) + } + + override fun goBack(): Boolean { + if (backStack.size <= 1) return false + backStack.removeAt(backStack.lastIndex) + return true + } + + override fun popTo(route: NavKey, inclusive: Boolean): Boolean { + val index = backStack.indexOfLast { it == route } + if (index < 0) return false + val target = if (inclusive) index else index + 1 + // Already at the requested route with inclusive = false pops nothing and + // still succeeded. + while (backStack.size > target) { + backStack.removeAt(backStack.lastIndex) + } + return true + } + + override fun replaceCurrent(dest: NavKey) { + if (backStack.isNotEmpty()) backStack.removeAt(backStack.lastIndex) + backStack.add(dest) + } + + override fun resetTo(dest: NavKey) { + backStack.clear() + backStack.add(dest) + } +} diff --git a/app/src/main/java/com/bitchat/android/navigation/AppRoutes.kt b/app/src/main/java/com/bitchat/android/navigation/AppRoutes.kt new file mode 100644 index 00000000..fcfd2342 --- /dev/null +++ b/app/src/main/java/com/bitchat/android/navigation/AppRoutes.kt @@ -0,0 +1,31 @@ +package com.bitchat.android.navigation + +import androidx.navigation3.runtime.NavKey +import com.bitchat.android.onboarding.OnboardingState + +/** + * Top-level destinations. + * + * Onboarding is one destination, not eight. Its steps are driven by permission + * results and adapter state changes rather than by the user navigating, and the + * app has never supported going back from one step to the previous one. Giving + * each step its own entry would invent a history that does not exist. + */ +data object OnboardingRoute : NavKey + +data object ChatRoute : NavKey + +/** + * The destination that should be at the root for a given onboarding state. + * + * CHECKING and INITIALIZING map to chat, matching the behaviour this replaced: + * the app shows the chat screen while it verifies its own readiness rather than + * flashing an onboarding step. + */ +fun rootRouteFor(state: OnboardingState): NavKey = when (state) { + OnboardingState.CHECKING, + OnboardingState.INITIALIZING, + OnboardingState.COMPLETE -> ChatRoute + + else -> OnboardingRoute +} diff --git a/app/src/main/java/com/bitchat/android/navigation/BitchatNavDisplay.kt b/app/src/main/java/com/bitchat/android/navigation/BitchatNavDisplay.kt new file mode 100644 index 00000000..c0009527 --- /dev/null +++ b/app/src/main/java/com/bitchat/android/navigation/BitchatNavDisplay.kt @@ -0,0 +1,44 @@ +package com.bitchat.android.navigation + +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import androidx.lifecycle.viewmodel.navigation3.rememberViewModelStoreNavEntryDecorator +import androidx.navigation3.runtime.entryProvider +import androidx.navigation3.runtime.rememberSaveableStateHolderNavEntryDecorator +import androidx.navigation3.ui.NavDisplay + +/** + * Hosts every feature's destinations. + * + * [entryInstallers] arrives as a Hilt multibinding, so adding a destination + * means adding an @IntoSet provider in the owning feature — this function never + * changes. + * + * This handles Back only between destinations, and only while there is one to + * go back to: NavDisplay enables its handler on scene.previousEntries being + * non-empty, so at the root destination it takes no press at all. A screen with + * state the back stack does not model has to claim Back itself, with a handler + * registered into the same dispatcher — androidx.activity.compose's BackHandler + * is, since activity-compose prefers the NavigationEventDispatcher when one is + * present. Among enabled handlers the last one composed wins. + */ +@Composable +fun BitchatNavDisplay( + navigator: AppNavigator, + entryInstallers: Set, + onExit: () -> Unit, + modifier: Modifier = Modifier, +) { + NavDisplay( + backStack = navigator.backStack, + modifier = modifier, + onBack = { if (!navigator.goBack()) onExit() }, + entryDecorators = listOf( + rememberSaveableStateHolderNavEntryDecorator(), + rememberViewModelStoreNavEntryDecorator(), + ), + entryProvider = entryProvider { + entryInstallers.forEach { install -> install() } + }, + ) +} diff --git a/app/src/main/java/com/bitchat/android/navigation/EntryProviderInstaller.kt b/app/src/main/java/com/bitchat/android/navigation/EntryProviderInstaller.kt new file mode 100644 index 00000000..18d86803 --- /dev/null +++ b/app/src/main/java/com/bitchat/android/navigation/EntryProviderInstaller.kt @@ -0,0 +1,12 @@ +package com.bitchat.android.navigation + +import androidx.navigation3.runtime.EntryProviderScope +import androidx.navigation3.runtime.NavKey + +/** + * One feature's contribution to the navigation graph. + * + * Features provide these into a Set via Hilt multibindings, so the host + * assembles every destination without importing any feature's internals. + */ +typealias EntryProviderInstaller = EntryProviderScope.() -> Unit diff --git a/app/src/main/java/com/bitchat/android/navigation/NavigationModule.kt b/app/src/main/java/com/bitchat/android/navigation/NavigationModule.kt new file mode 100644 index 00000000..39895808 --- /dev/null +++ b/app/src/main/java/com/bitchat/android/navigation/NavigationModule.kt @@ -0,0 +1,18 @@ +package com.bitchat.android.navigation + +import dagger.Binds +import dagger.Module +import dagger.hilt.InstallIn +import dagger.hilt.android.components.ActivityRetainedComponent + +@Module +@InstallIn(ActivityRetainedComponent::class) +abstract class NavigationModule { + + /** + * Features inject [Navigator]; only the host injects [AppNavigator] itself, + * since reading or seeding the back stack is the host's job. + */ + @Binds + abstract fun bindNavigator(impl: AppNavigator): Navigator +} diff --git a/app/src/main/java/com/bitchat/android/navigation/Navigator.kt b/app/src/main/java/com/bitchat/android/navigation/Navigator.kt new file mode 100644 index 00000000..1c66b2bb --- /dev/null +++ b/app/src/main/java/com/bitchat/android/navigation/Navigator.kt @@ -0,0 +1,27 @@ +package com.bitchat.android.navigation + +import androidx.navigation3.runtime.NavKey + +/** + * The navigation surface features are allowed to depend on. + * + * Features call this rather than touching the back stack directly, so the + * guards below live in one place instead of at every call site. + */ +interface Navigator { + + /** Push [dest], unless it is already on top. */ + fun goTo(dest: NavKey) + + /** Pop one entry. Returns false when the stack cannot go back any further. */ + fun goBack(): Boolean + + /** Pop back to [route]. Returns false when [route] is not on the stack. */ + fun popTo(route: NavKey, inclusive: Boolean = false): Boolean + + /** Swap the current top for [dest], so Back skips the screen being replaced. */ + fun replaceCurrent(dest: NavKey) + + /** Clear the stack and start again at [dest]. */ + fun resetTo(dest: NavKey) +} diff --git a/app/src/main/java/com/bitchat/android/ui/AboutSheet.kt b/app/src/main/java/com/bitchat/android/ui/AboutSheet.kt index 54ab0318..0fa6bd72 100644 --- a/app/src/main/java/com/bitchat/android/ui/AboutSheet.kt +++ b/app/src/main/java/com/bitchat/android/ui/AboutSheet.kt @@ -63,8 +63,8 @@ import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp +import androidx.hilt.navigation.compose.hiltViewModel import androidx.lifecycle.compose.collectAsStateWithLifecycle -import androidx.lifecycle.viewmodel.compose.viewModel import com.bitchat.android.ui.theme.BitchatFontFamily import com.bitchat.android.R import com.bitchat.android.core.ui.component.button.CloseButton @@ -617,7 +617,7 @@ fun AboutSheet( ) // === Prepare App for Sharing Section === - val apkViewModel: ApkDownloadViewModel = viewModel() + val apkViewModel: ApkDownloadViewModel = hiltViewModel() val apkUiState by apkViewModel.state.collectAsStateWithLifecycle() val apkStatus = apkUiState.apkStatus val releaseStatus = apkUiState.releaseStatus diff --git a/app/src/main/java/com/bitchat/android/ui/ApkDownloadViewModel.kt b/app/src/main/java/com/bitchat/android/ui/ApkDownloadViewModel.kt index 4d0c2d5b..dcc6d4af 100644 --- a/app/src/main/java/com/bitchat/android/ui/ApkDownloadViewModel.kt +++ b/app/src/main/java/com/bitchat/android/ui/ApkDownloadViewModel.kt @@ -15,6 +15,8 @@ import com.bitchat.android.util.LatestReleaseProvider import com.bitchat.android.util.ShareableApkVariant import com.bitchat.android.util.UniversalApkManager import com.bitchat.android.util.WorkManagerApkDownloader +import dagger.hilt.android.lifecycle.HiltViewModel +import javax.inject.Inject import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Job import kotlinx.coroutines.channels.Channel @@ -151,6 +153,7 @@ sealed class ApkUiEffect { * ViewModel for APK download/status/share logic following MVI pattern. * UI sends [ApkUiEvent], observes [ApkUiState], and collects [ApkUiEffect]. */ +@HiltViewModel class ApkDownloadViewModel internal constructor( application: Application, private val apkManager: UniversalApkManager, @@ -158,6 +161,11 @@ class ApkDownloadViewModel internal constructor( private val latestReleaseProvider: LatestReleaseProvider ) : AndroidViewModel(application) { + // Hilt injects through this constructor rather than the primary one: + // UniversalApkManager's collaborators are internal, and routing internal + // Kotlin types through Dagger's generated Java buys nothing here. Tests + // keep using the primary constructor to substitute fakes. + @Inject constructor(application: Application) : this( application = application, apkManager = UniversalApkManager(application), diff --git a/app/src/main/java/com/bitchat/android/ui/ChatState.kt b/app/src/main/java/com/bitchat/android/ui/ChatState.kt index f4504cc2..16210894 100644 --- a/app/src/main/java/com/bitchat/android/ui/ChatState.kt +++ b/app/src/main/java/com/bitchat/android/ui/ChatState.kt @@ -170,6 +170,26 @@ class ChatState( initialValue = false ) + // Mirrors the branches of ChatViewModel.handleBackPressed. The back handler + // is enabled from this and the press consumed by that, so they must agree. + val canHandleBack: StateFlow = combine( + _showAppInfo, + _showPasswordPrompt, + _selectedPrivateChatPeer, + _privateChatSheetPeer, + _currentChannel + ) { showAppInfo, showPasswordPrompt, privateChatPeer, privateChatSheetPeer, channel -> + showAppInfo || + showPasswordPrompt || + privateChatPeer != null || + privateChatSheetPeer != null || + channel != null + }.stateIn( + scope = scope, + started = WhileSubscribed(5_000), + initialValue = false + ) + // Getters for internal state access fun getMessagesValue() = _messages.value fun getConnectedPeersValue() = _connectedPeers.value diff --git a/app/src/main/java/com/bitchat/android/ui/ChatViewModel.kt b/app/src/main/java/com/bitchat/android/ui/ChatViewModel.kt index f40549b6..056bc9a7 100644 --- a/app/src/main/java/com/bitchat/android/ui/ChatViewModel.kt +++ b/app/src/main/java/com/bitchat/android/ui/ChatViewModel.kt @@ -7,6 +7,8 @@ import androidx.lifecycle.AndroidViewModel import androidx.lifecycle.viewModelScope import com.bitchat.android.favorites.FavoritesChangeListener import com.bitchat.android.favorites.FavoritesPersistenceService +import dagger.hilt.android.lifecycle.HiltViewModel +import javax.inject.Inject import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.MutableStateFlow @@ -53,7 +55,8 @@ private data class ConversationLiveIdentityState( * Refactored ChatViewModel - Main coordinator for bitchat functionality * Delegates specific responsibilities to specialized managers while maintaining 100% iOS compatibility */ -class ChatViewModel( +@HiltViewModel +class ChatViewModel @Inject constructor( application: Application, initialMeshService: BluetoothMeshService, initialUnifiedMeshService: MeshService @@ -387,6 +390,7 @@ class ChatViewModel( val passwordPromptChannel: StateFlow = state.passwordPromptChannel val hasUnreadChannels = state.hasUnreadChannels val hasUnreadPrivateMessages = state.hasUnreadPrivateMessages + val canHandleBack = state.canHandleBack val showCommandSuggestions: StateFlow = state.showCommandSuggestions val commandSuggestions: StateFlow> = state.commandSuggestions val showMentionSuggestions: StateFlow = state.showMentionSuggestions diff --git a/app/src/test/kotlin/com/bitchat/android/ui/ChatStateBackNavigationTest.kt b/app/src/test/kotlin/com/bitchat/android/ui/ChatStateBackNavigationTest.kt new file mode 100644 index 00000000..5c5c41de --- /dev/null +++ b/app/src/test/kotlin/com/bitchat/android/ui/ChatStateBackNavigationTest.kt @@ -0,0 +1,90 @@ +package com.bitchat.android.ui + +import kotlinx.coroutines.ExperimentalCoroutinesApi +import kotlinx.coroutines.Job +import kotlinx.coroutines.launch +import kotlinx.coroutines.test.TestScope +import kotlinx.coroutines.test.UnconfinedTestDispatcher +import org.junit.After +import org.junit.Assert.assertFalse +import org.junit.Assert.assertTrue +import org.junit.Before +import org.junit.Test + +/** + * `canHandleBack` must agree with the branches of + * [ChatViewModel.handleBackPressed]: the back handler is enabled from one and + * the press consumed by the other. + */ +@OptIn(ExperimentalCoroutinesApi::class) +class ChatStateBackNavigationTest { + + private lateinit var scope: TestScope + private lateinit var state: ChatState + private lateinit var subscription: Job + + @Before + fun setUp() { + scope = TestScope(UnconfinedTestDispatcher()) + state = ChatState(scope) + // Shared WhileSubscribed, so it only tracks its sources while collected. + subscription = scope.launch { state.canHandleBack.collect { } } + } + + @After + fun tearDown() { + subscription.cancel() + } + + @Test + fun `is false on the bare chat screen`() { + assertFalse(state.canHandleBack.value) + } + + @Test + fun `is true while the app info dialog is open`() { + state.setShowAppInfo(true) + + assertTrue(state.canHandleBack.value) + } + + @Test + fun `is true while the password prompt is open`() { + state.setShowPasswordPrompt(true) + + assertTrue(state.canHandleBack.value) + } + + @Test + fun `is true while a private chat is selected`() { + state.setSelectedPrivateChatPeer("peer-a") + + assertTrue(state.canHandleBack.value) + } + + @Test + fun `is true while the private chat sheet is open`() { + state.setPrivateChatSheetPeer("peer-a") + + assertTrue(state.canHandleBack.value) + } + + @Test + fun `is true while a channel is open`() { + state.setCurrentChannel("#bitchat") + + assertTrue(state.canHandleBack.value) + } + + @Test + fun `returns to false once the last overlay closes`() { + state.setCurrentChannel("#bitchat") + state.setShowAppInfo(true) + + state.setShowAppInfo(false) + assertTrue("the channel is still open", state.canHandleBack.value) + + state.setCurrentChannel(null) + assertFalse("nothing is left to unwind", state.canHandleBack.value) + } +} diff --git a/build.gradle.kts b/build.gradle.kts index 16bf6428..abe4f5a6 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -5,6 +5,8 @@ plugins { alias(libs.plugins.android.application) apply false alias(libs.plugins.android.library) apply false alias(libs.plugins.kotlin.compose) apply false + alias(libs.plugins.ksp) apply false + alias(libs.plugins.hilt) apply false } val resolveIdeRuntimeClasspathCopyLocks = tasks.register("resolveIdeRuntimeClasspathCopyLocks") { diff --git a/gradle.properties b/gradle.properties index e3461bd0..5ff2de48 100644 --- a/gradle.properties +++ b/gradle.properties @@ -27,8 +27,14 @@ kotlin.code.style=official # signed by an unexpected publisher. BITCHAT_GITHUB_RELEASE_CERT_SHA256=3b03fa66a5451321100792f5b55a7b4966d5c8dc10c6daa40aa95ea489531bca -# JVM heap size configuration to prevent OutOfMemoryError -org.gradle.jvmargs=-Xmx4g -XX:MaxMetaspaceSize=512m -XX:+HeapDumpOnOutOfMemoryError +# JVM heap size configuration to prevent OutOfMemoryError. +# Metaspace is 1g rather than 512m: KSP and the Hilt/Dagger annotation +# processors load a large amount of extra classes into the daemon, and at 512m +# a combined test + lint + KSP invocation across the modules exhausts it. The +# failure surfaces as ClassLoader.defineClass OutOfMemoryError in unrelated +# tasks, and can truncate gradle/verification-metadata.xml if it lands during +# a --write-verification-metadata run. +org.gradle.jvmargs=-Xmx4g -XX:MaxMetaspaceSize=1g -XX:+HeapDumpOnOutOfMemoryError # Enabled parallel sync for Gradle 9.4+ org.gradle.tooling.parallel=true diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 405f6dc3..1034a2f1 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -2,6 +2,9 @@ # Android and Kotlin agp = "9.3.1" kotlin = "2.4.10" +# KSP versions independently of Kotlin as of 2.3.0; earlier releases used a +# - scheme that had to match the Kotlin version exactly. +ksp = "2.3.11" compileSdk = "37" minSdk = "26" # API 26 for proper BLE support targetSdk = "37" @@ -19,6 +22,13 @@ compose-icons-extended = "1.7.8" # Navigation navigation-compose = "2.9.8" +# Latest stable line; the 1.2.0 branch is still alpha. 1.1.6 floors Compose at +# 1.10.0, below the 1.11.4 the BOM resolves, so it does not drag Compose forward. +navigation3 = "1.1.6" + +# Dependency injection +hilt = "2.60.1" +androidx-hilt = "1.4.0" # Accompanist accompanist-permissions = "0.37.3" @@ -76,6 +86,11 @@ mockito-core = "5.23.0" roboelectric = "4.15" # 4.16+ drops the AndroidKeyStore shim; breaks EncryptionServiceTest [libraries] +# Gradle plugin artifacts, resolved only by build-logic convention plugins +android-gradlePlugin = { module = "com.android.tools.build:gradle", version.ref = "agp" } +kotlin-gradlePlugin = { module = "org.jetbrains.kotlin:kotlin-gradle-plugin", version.ref = "kotlin" } +compose-gradlePlugin = { module = "org.jetbrains.kotlin:compose-compiler-gradle-plugin", version.ref = "kotlin" } + # AndroidX Core androidx-core-ktx = { module = "androidx.core:core-ktx", version.ref = "core-ktx" } androidx-lifecycle-process = { module = "androidx.lifecycle:lifecycle-process", version.ref = "lifecycle-runtime" } @@ -97,6 +112,14 @@ androidx-lifecycle-viewmodel-compose = { module = "androidx.lifecycle:lifecycle- # Navigation androidx-navigation-compose = { module = "androidx.navigation:navigation-compose", version.ref = "navigation-compose" } +androidx-navigation3-runtime = { module = "androidx.navigation3:navigation3-runtime", version.ref = "navigation3" } +androidx-navigation3-ui = { module = "androidx.navigation3:navigation3-ui", version.ref = "navigation3" } +androidx-lifecycle-viewmodel-navigation3 = { module = "androidx.lifecycle:lifecycle-viewmodel-navigation3", version.ref = "lifecycle-runtime" } + +# Dependency injection +hilt-android = { module = "com.google.dagger:hilt-android", version.ref = "hilt" } +hilt-compiler = { module = "com.google.dagger:hilt-android-compiler", version.ref = "hilt" } +androidx-hilt-navigation-compose = { module = "androidx.hilt:hilt-navigation-compose", version.ref = "androidx-hilt" } # Accompanist accompanist-permissions = { module = "com.google.accompanist:accompanist-permissions", version.ref = "accompanist-permissions" } @@ -166,6 +189,8 @@ android-application = { id = "com.android.application", version.ref = "agp" } android-library = { id = "com.android.library", version.ref = "agp" } kotlin-parcelize = { id = "kotlin-parcelize" } kotlin-compose = { id = "org.jetbrains.kotlin.plugin.compose", version.ref = "kotlin" } +ksp = { id = "com.google.devtools.ksp", version.ref = "ksp" } +hilt = { id = "com.google.dagger.hilt.android", version.ref = "hilt" } [bundles] compose = [ diff --git a/gradle/verification-metadata.xml b/gradle/verification-metadata.xml index 4dad1c4d..0e8701de 100644 --- a/gradle/verification-metadata.xml +++ b/gradle/verification-metadata.xml @@ -59,6 +59,11 @@ + + + + + @@ -549,6 +554,11 @@ + + + + + @@ -1282,6 +1292,30 @@ + + + + + + + + + + + + + + + + + + + + + + + + @@ -1455,6 +1489,19 @@ + + + + + + + + + + + + + @@ -1523,11 +1570,42 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -1536,11 +1614,24 @@ + + + + + + + + + + + + + @@ -1549,6 +1640,14 @@ + + + + + + + + @@ -2825,6 +2924,128 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -2879,6 +3100,14 @@ + + + + + + + + @@ -2932,6 +3161,11 @@ + + + + + @@ -2977,6 +3211,19 @@ + + + + + + + + + + + + + @@ -3030,6 +3277,14 @@ + + + + + + + + @@ -3060,6 +3315,11 @@ + + + + + @@ -3092,6 +3352,14 @@ + + + + + + + + @@ -3352,6 +3620,14 @@ + + + + + + + + @@ -3907,6 +4183,14 @@ + + + + + + + + @@ -4094,6 +4378,14 @@ + + + + + + + + @@ -4280,6 +4572,11 @@ + + + + + @@ -4485,6 +4782,14 @@ + + + + + + + + @@ -4597,6 +4902,14 @@ + + + + + + + + @@ -4647,6 +4960,14 @@ + + + + + + + + @@ -4671,6 +4992,14 @@ + + + + + + + + @@ -4766,11 +5095,21 @@ + + + + + + + + + + @@ -4781,6 +5120,11 @@ + + + + + @@ -4806,6 +5150,14 @@ + + + + + + + +