125 lines
4.4 KiB
Kotlin
Executable File
125 lines
4.4 KiB
Kotlin
Executable File
package de.harheimertc
|
|
|
|
import android.Manifest
|
|
import android.content.Intent
|
|
import android.os.Build
|
|
import android.os.Bundle
|
|
import androidx.activity.ComponentActivity
|
|
import androidx.activity.result.contract.ActivityResultContracts
|
|
import androidx.activity.compose.setContent
|
|
import androidx.compose.runtime.Composable
|
|
import androidx.compose.runtime.LaunchedEffect
|
|
import androidx.compose.runtime.mutableStateOf
|
|
import androidx.compose.ui.tooling.preview.Preview
|
|
import androidx.navigation.compose.rememberNavController
|
|
import de.harheimertc.ui.navigation.NavGraph
|
|
import de.harheimertc.ui.navigation.Destinations
|
|
import de.harheimertc.notifications.HarheimerNotifications
|
|
import de.harheimertc.ui.theme.HarheimerTheme
|
|
import androidx.hilt.navigation.compose.hiltViewModel
|
|
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<String?>(null)
|
|
|
|
private val notificationPermissionLauncher = registerForActivityResult(
|
|
ActivityResultContracts.RequestPermission(),
|
|
) { granted ->
|
|
Log.i("NOTIFICATIONS", "POST_NOTIFICATIONS granted=$granted")
|
|
}
|
|
|
|
override fun onCreate(savedInstanceState: Bundle?) {
|
|
super.onCreate(savedInstanceState)
|
|
requestNotificationPermissionIfNeeded()
|
|
notificationRoute.value = extractNotificationRoute(intent)
|
|
setContent {
|
|
App(
|
|
notificationRoute = notificationRoute.value,
|
|
onNotificationRouteConsumed = { notificationRoute.value = null },
|
|
)
|
|
}
|
|
}
|
|
|
|
override fun onNewIntent(intent: Intent) {
|
|
super.onNewIntent(intent)
|
|
setIntent(intent)
|
|
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() }
|
|
|
|
private fun requestNotificationPermissionIfNeeded() {
|
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU && !HarheimerNotifications.hasNotificationPermission(this)) {
|
|
notificationPermissionLauncher.launch(Manifest.permission.POST_NOTIFICATIONS)
|
|
}
|
|
}
|
|
|
|
companion object {
|
|
const val EXTRA_NOTIFICATION_TYPE = "de.harheimertc.extra.NOTIFICATION_TYPE"
|
|
const val EXTRA_NOTIFICATION_ROUTE = "de.harheimertc.extra.NOTIFICATION_ROUTE"
|
|
const val EXTRA_NEWS_ID = "de.harheimertc.extra.NEWS_ID"
|
|
}
|
|
}
|
|
|
|
@Composable
|
|
fun App(
|
|
notificationRoute: String? = null,
|
|
onNotificationRouteConsumed: () -> Unit = {},
|
|
) {
|
|
HarheimerTheme {
|
|
val navController = rememberNavController()
|
|
val ctx = LocalContext.current
|
|
val activity = ctx as? ComponentActivity
|
|
Log.i("HILT_FACTORY", "defaultViewModelProviderFactory=${activity?.defaultViewModelProviderFactory?.javaClass?.name}")
|
|
val navigationViewModel: NavigationViewModel = hiltViewModel()
|
|
LaunchedEffect(notificationRoute) {
|
|
val route = notificationRoute?.takeIf { it.isNotBlank() } ?: return@LaunchedEffect
|
|
navController.navigate(route) {
|
|
launchSingleTop = true
|
|
popUpTo(Destinations.Home.route)
|
|
}
|
|
onNotificationRouteConsumed()
|
|
}
|
|
NavGraph(navController = navController, navigationViewModelParam = navigationViewModel)
|
|
}
|
|
}
|
|
|
|
@Preview
|
|
@Composable
|
|
fun PreviewMain() {
|
|
App()
|
|
}
|