package eu.kanade.presentation.util import androidx.compose.animation.AnimatedContent import androidx.compose.animation.AnimatedContentTransitionScope import androidx.compose.animation.ContentTransform import androidx.compose.runtime.Composable import androidx.compose.runtime.ProvidableCompositionLocal import androidx.compose.runtime.staticCompositionLocalOf import androidx.compose.ui.Modifier import cafe.adriel.voyager.core.model.ScreenModel import cafe.adriel.voyager.core.model.ScreenModelStore import cafe.adriel.voyager.core.screen.Screen import cafe.adriel.voyager.core.screen.ScreenKey import cafe.adriel.voyager.core.screen.uniqueScreenKey import cafe.adriel.voyager.core.stack.StackEvent import cafe.adriel.voyager.navigator.Navigator import cafe.adriel.voyager.transitions.ScreenTransitionContent import kotlinx.coroutines.CoroutineName import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.SupervisorJob import kotlinx.coroutines.cancel import kotlinx.coroutines.plus import soup.compose.material.motion.animation.materialSharedAxisX import soup.compose.material.motion.animation.rememberSlideDistance /** * For invoking back press to the parent activity */ val LocalBackPress: ProvidableCompositionLocal<(() -> Unit)?> = staticCompositionLocalOf { null } interface Tab : cafe.adriel.voyager.navigator.tab.Tab { suspend fun onReselect(navigator: Navigator) {} } abstract class Screen : Screen { override val key: ScreenKey = uniqueScreenKey } /** * A variant of ScreenModel.coroutineScope except with the IO dispatcher instead of the * main dispatcher. */ val ScreenModel.ioCoroutineScope: CoroutineScope get() = ScreenModelStore.getOrPutDependency( screenModel = this, name = "ScreenModelIoCoroutineScope", factory = { key -> CoroutineScope(Dispatchers.IO + SupervisorJob()) + CoroutineName(key) }, onDispose = { scope -> scope.cancel() }, ) interface AssistContentScreen { fun onProvideAssistUrl(): String? } @Composable fun DefaultNavigatorScreenTransition(navigator: Navigator) { val slideDistance = rememberSlideDistance() ScreenTransition( navigator = navigator, transition = { materialSharedAxisX( forward = navigator.lastEvent != StackEvent.Pop, slideDistance = slideDistance, ) }, ) } @Composable fun ScreenTransition( navigator: Navigator, transition: AnimatedContentTransitionScope.() -> ContentTransform, modifier: Modifier = Modifier, content: ScreenTransitionContent = { it.Content() }, ) { AnimatedContent( targetState = navigator.lastItem, transitionSpec = transition, modifier = modifier, label = "ScreenTransition", ) { screen -> navigator.saveableState("transition", screen) { content(screen) } } }