diff --git a/android-app/app/production/release/app-production-release.aab b/android-app/app/production/release/app-production-release.aab index 7e800cb..7c2c007 100644 Binary files a/android-app/app/production/release/app-production-release.aab and b/android-app/app/production/release/app-production-release.aab differ diff --git a/android-app/app/src/main/java/de/harheimertc/MainActivity.kt b/android-app/app/src/main/java/de/harheimertc/MainActivity.kt index 03f6766..1d06d7d 100755 --- a/android-app/app/src/main/java/de/harheimertc/MainActivity.kt +++ b/android-app/app/src/main/java/de/harheimertc/MainActivity.kt @@ -21,9 +21,20 @@ import de.harheimertc.ui.navigation.NavigationViewModel import dagger.hilt.android.AndroidEntryPoint import android.util.Log import androidx.compose.ui.platform.LocalContext +import androidx.lifecycle.lifecycleScope +import de.harheimertc.repositories.AuthRepository +import de.harheimertc.repositories.PushTokenRepository +import kotlinx.coroutines.launch +import javax.inject.Inject @AndroidEntryPoint class MainActivity : ComponentActivity() { + @Inject + lateinit var authRepository: AuthRepository + + @Inject + lateinit var pushTokenRepository: PushTokenRepository + private val notificationRoute = mutableStateOf(null) private val notificationPermissionLauncher = registerForActivityResult( @@ -50,6 +61,23 @@ class MainActivity : ComponentActivity() { notificationRoute.value = extractNotificationRoute(intent) } + override fun onResume() { + super.onResume() + syncPushTokenWhenSignedIn() + } + + /** + * Server-side tokens are persistent, but re-registering the current FCM + * token is cheap and idempotent. It restores a token if server data was + * ever recovered from a backup or manually repaired. + */ + private fun syncPushTokenWhenSignedIn() { + if (authRepository.getToken().isNullOrBlank() && authRepository.getRefreshToken().isNullOrBlank()) return + lifecycleScope.launch { + pushTokenRepository.registerCurrentDevice() + } + } + private fun extractNotificationRoute(intent: Intent?): String? = intent?.getStringExtra(EXTRA_NOTIFICATION_ROUTE)?.takeIf { it.isNotBlank() } diff --git a/android-app/app/src/main/java/de/harheimertc/ui/screens/login/LoginViewModel.kt b/android-app/app/src/main/java/de/harheimertc/ui/screens/login/LoginViewModel.kt index e5cefbf..eedcf8e 100755 --- a/android-app/app/src/main/java/de/harheimertc/ui/screens/login/LoginViewModel.kt +++ b/android-app/app/src/main/java/de/harheimertc/ui/screens/login/LoginViewModel.kt @@ -6,6 +6,7 @@ import androidx.lifecycle.viewModelScope import dagger.hilt.android.lifecycle.HiltViewModel import de.harheimertc.repositories.LoginRepository import de.harheimertc.repositories.PasskeyRepository +import de.harheimertc.repositories.PushTokenRepository import de.harheimertc.ui.components.isValidEmail import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.StateFlow @@ -29,6 +30,7 @@ data class LoginUiState( class LoginViewModel @Inject constructor( private val repository: LoginRepository, private val passkeyRepository: PasskeyRepository, + private val pushTokenRepository: PushTokenRepository, ) : ViewModel() { private val _state = MutableStateFlow(LoginUiState()) val state: StateFlow = _state @@ -70,6 +72,7 @@ class LoginViewModel @Inject constructor( _state.value = current.copy(loading = true, error = null, message = null) repository.login(current.email, current.password) .onSuccess { response -> + viewModelScope.launch { pushTokenRepository.registerCurrentDevice() } _state.value = current.copy( password = "", loading = false, @@ -92,6 +95,7 @@ class LoginViewModel @Inject constructor( _state.value = current.copy(loading = true, error = null, message = null) passkeyRepository.login(context, current.email) .onSuccess { response -> + viewModelScope.launch { pushTokenRepository.registerCurrentDevice() } _state.value = current.copy( password = "", loading = false, diff --git a/android-app/gradle.properties b/android-app/gradle.properties index 2fa50ec..7d124f1 100755 --- a/android-app/gradle.properties +++ b/android-app/gradle.properties @@ -8,8 +8,8 @@ LOCAL_API_BASE_URL=https://harheimertc.tsschulz.de/ PRODUCTION_API_BASE_URL=https://harheimertc.de/ # Android app versioning for Play Store uploads -ANDROID_VERSION_CODE=33 -ANDROID_VERSION_NAME=0.9.28 +ANDROID_VERSION_CODE=34 +ANDROID_VERSION_NAME=0.9.29 # Temporary hotfix: disable R8 minification for release to avoid Retrofit generic signature stripping. RELEASE_MINIFY_ENABLED=false