feat(app): deep links, notification launch, and night splash
Add wallenc:// URI patterns, manifest VIEW intent-filters, and NavDeepLink with handleDeepLink from MainActivity. Move FGS notification PendingIntent constants to WallencExternalLaunch. Theme splash/window background via splash_screen_background in values and values-night. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
package com.github.nullptroma.wallenc.ui
|
||||
|
||||
import android.content.Intent
|
||||
import androidx.compose.animation.core.tween
|
||||
import androidx.compose.animation.fadeIn
|
||||
import androidx.compose.animation.fadeOut
|
||||
@@ -26,7 +27,10 @@ import androidx.hilt.lifecycle.viewmodel.compose.hiltViewModel
|
||||
import androidx.navigation.compose.NavHost
|
||||
import androidx.navigation.compose.composable
|
||||
import androidx.navigation.compose.currentBackStackEntryAsState
|
||||
import androidx.navigation.navDeepLink
|
||||
import com.github.nullptroma.wallenc.ui.navigation.NavBarItemData
|
||||
import com.github.nullptroma.wallenc.ui.navigation.WallencDeepLinks
|
||||
import com.github.nullptroma.wallenc.ui.navigation.matchesWallencDeepLink
|
||||
import com.github.nullptroma.wallenc.ui.navigation.rememberNavigationState
|
||||
import com.github.nullptroma.wallenc.ui.screens.main.MainRoute
|
||||
import com.github.nullptroma.wallenc.ui.screens.main.MainScreen
|
||||
@@ -40,10 +44,16 @@ import com.github.nullptroma.wallenc.ui.theme.WallencTheme
|
||||
|
||||
|
||||
@Composable
|
||||
fun WallencUi(taskPipelineOpenRequestCount: Int = 0) {
|
||||
fun WallencUi(
|
||||
deepLinkPulse: Int = 0,
|
||||
deepLinkIntent: Intent = Intent(),
|
||||
) {
|
||||
WallencTheme {
|
||||
Surface {
|
||||
WallencNavRoot(taskPipelineOpenRequestCount = taskPipelineOpenRequestCount)
|
||||
WallencNavRoot(
|
||||
deepLinkPulse = deepLinkPulse,
|
||||
deepLinkIntent = deepLinkIntent,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -52,7 +62,8 @@ fun WallencUi(taskPipelineOpenRequestCount: Int = 0) {
|
||||
@Composable
|
||||
fun WallencNavRoot(
|
||||
viewModel: WallencViewModel = hiltViewModel(),
|
||||
taskPipelineOpenRequestCount: Int = 0,
|
||||
deepLinkPulse: Int = 0,
|
||||
deepLinkIntent: Intent = Intent(),
|
||||
) {
|
||||
val navState = rememberNavigationState()
|
||||
val mainNavState = rememberNavigationState()
|
||||
@@ -62,10 +73,10 @@ fun WallencNavRoot(
|
||||
|
||||
val topLevelRoutes = viewModel.routes
|
||||
|
||||
LaunchedEffect(taskPipelineOpenRequestCount) {
|
||||
if (taskPipelineOpenRequestCount <= 0) return@LaunchedEffect
|
||||
val route = topLevelRoutes[TaskPipelineRoute::class.qualifiedName!!] ?: return@LaunchedEffect
|
||||
navState.changeTop(route)
|
||||
LaunchedEffect(deepLinkPulse) {
|
||||
if (deepLinkPulse <= 0) return@LaunchedEffect
|
||||
if (!deepLinkIntent.matchesWallencDeepLink()) return@LaunchedEffect
|
||||
navState.navHostController.handleDeepLink(deepLinkIntent)
|
||||
}
|
||||
|
||||
val topLevelNavBarItems = remember {
|
||||
@@ -121,7 +132,11 @@ fun WallencNavRoot(
|
||||
navState.navHostController,
|
||||
startDestination = topLevelRoutes[MainRoute::class.qualifiedName]!!
|
||||
) {
|
||||
composable<MainRoute>(enterTransition = {
|
||||
composable<MainRoute>(
|
||||
deepLinks = listOf(
|
||||
navDeepLink { uriPattern = WallencDeepLinks.MAIN_URI_PATTERN },
|
||||
),
|
||||
enterTransition = {
|
||||
fadeIn(tween(200))
|
||||
}, exitTransition = {
|
||||
fadeOut(tween(200))
|
||||
@@ -132,14 +147,22 @@ fun WallencNavRoot(
|
||||
viewModel = mainViewModel
|
||||
)
|
||||
}
|
||||
composable<SettingsRoute>(enterTransition = {
|
||||
composable<SettingsRoute>(
|
||||
deepLinks = listOf(
|
||||
navDeepLink { uriPattern = WallencDeepLinks.SETTINGS_URI_PATTERN },
|
||||
),
|
||||
enterTransition = {
|
||||
fadeIn(tween(200))
|
||||
}, exitTransition = {
|
||||
fadeOut(tween(200))
|
||||
}) {
|
||||
SettingsScreen(Modifier.padding(innerPaddings), settingsViewModel)
|
||||
}
|
||||
composable<TaskPipelineRoute>(enterTransition = {
|
||||
composable<TaskPipelineRoute>(
|
||||
deepLinks = listOf(
|
||||
navDeepLink { uriPattern = WallencDeepLinks.TASKS_URI_PATTERN },
|
||||
),
|
||||
enterTransition = {
|
||||
fadeIn(tween(200))
|
||||
}, exitTransition = {
|
||||
fadeOut(tween(200))
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
package com.github.nullptroma.wallenc.ui.navigation
|
||||
|
||||
import android.content.Intent
|
||||
|
||||
/**
|
||||
* URI для входа извне приложения (уведомления, виджеты, шорткаты, другие Activity).
|
||||
*
|
||||
* Должны совпадать с `<intent-filter><data android:scheme=… android:host=…/></intent-filter>` в манифесте
|
||||
* и с [androidx.navigation.navDeepLink] на соответствующих `composable` в [androidx.navigation.compose.NavHost].
|
||||
*
|
||||
* Для публичных HTTPS-ссылок позже добавляют отдельные хосты и `android:autoVerify`.
|
||||
*/
|
||||
object WallencDeepLinks {
|
||||
const val SCHEME = "wallenc"
|
||||
|
||||
object Host {
|
||||
const val MAIN = "main"
|
||||
const val TASKS = "tasks"
|
||||
const val SETTINGS = "settings"
|
||||
}
|
||||
|
||||
const val MAIN_URI_PATTERN = "$SCHEME://${Host.MAIN}"
|
||||
const val TASKS_URI_PATTERN = "$SCHEME://${Host.TASKS}"
|
||||
const val SETTINGS_URI_PATTERN = "$SCHEME://${Host.SETTINGS}"
|
||||
}
|
||||
|
||||
/** `ACTION_VIEW` с URI нашей схемы — обрабатывается [androidx.navigation.NavController.handleDeepLink]. */
|
||||
fun Intent.matchesWallencDeepLink(): Boolean =
|
||||
action == Intent.ACTION_VIEW && data?.scheme == WallencDeepLinks.SCHEME
|
||||
Reference in New Issue
Block a user