Use Voyager between supported screens in Extension package (#8616)

- Minor state behavior changes
This commit is contained in:
Andreas 2022-11-26 15:14:11 +01:00 committed by GitHub
parent 758d223776
commit db35ba53b1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 29 additions and 63 deletions

View File

@ -1,17 +0,0 @@
package eu.kanade.tachiyomi.ui.browse.extension
import androidx.compose.runtime.Composable
import androidx.compose.runtime.CompositionLocalProvider
import cafe.adriel.voyager.navigator.Navigator
import eu.kanade.presentation.util.LocalRouter
import eu.kanade.tachiyomi.ui.base.controller.BasicFullComposeController
class ExtensionFilterController : BasicFullComposeController() {
@Composable
override fun ComposeContent() {
CompositionLocalProvider(LocalRouter provides router) {
Navigator(screen = ExtensionFilterScreen())
}
}
}

View File

@ -7,10 +7,10 @@ import androidx.compose.runtime.getValue
import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.platform.LocalContext
import cafe.adriel.voyager.core.model.rememberScreenModel import cafe.adriel.voyager.core.model.rememberScreenModel
import cafe.adriel.voyager.core.screen.Screen import cafe.adriel.voyager.core.screen.Screen
import cafe.adriel.voyager.navigator.LocalNavigator
import cafe.adriel.voyager.navigator.currentOrThrow import cafe.adriel.voyager.navigator.currentOrThrow
import eu.kanade.presentation.browse.ExtensionFilterScreen import eu.kanade.presentation.browse.ExtensionFilterScreen
import eu.kanade.presentation.components.LoadingScreen import eu.kanade.presentation.components.LoadingScreen
import eu.kanade.presentation.util.LocalRouter
import eu.kanade.tachiyomi.R import eu.kanade.tachiyomi.R
import eu.kanade.tachiyomi.util.system.toast import eu.kanade.tachiyomi.util.system.toast
import kotlinx.coroutines.flow.collectLatest import kotlinx.coroutines.flow.collectLatest
@ -20,7 +20,7 @@ class ExtensionFilterScreen : Screen {
@Composable @Composable
override fun Content() { override fun Content() {
val context = LocalContext.current val context = LocalContext.current
val router = LocalRouter.currentOrThrow val navigator = LocalNavigator.currentOrThrow
val screenModel = rememberScreenModel { ExtensionFilterScreenModel() } val screenModel = rememberScreenModel { ExtensionFilterScreenModel() }
val state by screenModel.state.collectAsState() val state by screenModel.state.collectAsState()
@ -32,7 +32,7 @@ class ExtensionFilterScreen : Screen {
val successState = state as ExtensionFilterState.Success val successState = state as ExtensionFilterState.Success
ExtensionFilterScreen( ExtensionFilterScreen(
navigateUp = router::popCurrentController, navigateUp = navigator::pop,
state = successState, state = successState,
onClickToggle = { screenModel.toggle(it) }, onClickToggle = { screenModel.toggle(it) },
) )

View File

@ -6,21 +6,20 @@ import androidx.compose.runtime.Composable
import androidx.compose.runtime.collectAsState import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.getValue import androidx.compose.runtime.getValue
import androidx.compose.ui.res.stringResource import androidx.compose.ui.res.stringResource
import cafe.adriel.voyager.navigator.LocalNavigator
import cafe.adriel.voyager.navigator.currentOrThrow import cafe.adriel.voyager.navigator.currentOrThrow
import eu.kanade.presentation.browse.ExtensionScreen import eu.kanade.presentation.browse.ExtensionScreen
import eu.kanade.presentation.components.AppBar import eu.kanade.presentation.components.AppBar
import eu.kanade.presentation.components.TabContent import eu.kanade.presentation.components.TabContent
import eu.kanade.presentation.util.LocalRouter
import eu.kanade.tachiyomi.R import eu.kanade.tachiyomi.R
import eu.kanade.tachiyomi.extension.model.Extension import eu.kanade.tachiyomi.extension.model.Extension
import eu.kanade.tachiyomi.ui.base.controller.pushController import eu.kanade.tachiyomi.ui.browse.extension.details.ExtensionDetailsScreen
import eu.kanade.tachiyomi.ui.browse.extension.details.ExtensionDetailsController
@Composable @Composable
fun extensionsTab( fun extensionsTab(
extensionsScreenModel: ExtensionsScreenModel, extensionsScreenModel: ExtensionsScreenModel,
): TabContent { ): TabContent {
val router = LocalRouter.currentOrThrow val navigator = LocalNavigator.currentOrThrow
val state by extensionsScreenModel.state.collectAsState() val state by extensionsScreenModel.state.collectAsState()
return TabContent( return TabContent(
@ -31,7 +30,7 @@ fun extensionsTab(
AppBar.Action( AppBar.Action(
title = stringResource(R.string.action_filter), title = stringResource(R.string.action_filter),
icon = Icons.Outlined.Translate, icon = Icons.Outlined.Translate,
onClick = { router.pushController(ExtensionFilterController()) }, onClick = { navigator.push(ExtensionFilterScreen()) },
), ),
), ),
content = { contentPadding, _ -> content = { contentPadding, _ ->
@ -47,7 +46,7 @@ fun extensionsTab(
onClickItemCancel = extensionsScreenModel::cancelInstallUpdateExtension, onClickItemCancel = extensionsScreenModel::cancelInstallUpdateExtension,
onClickUpdateAll = extensionsScreenModel::updateAllExtensions, onClickUpdateAll = extensionsScreenModel::updateAllExtensions,
onInstallExtension = extensionsScreenModel::installExtension, onInstallExtension = extensionsScreenModel::installExtension,
onOpenExtension = { router.pushController(ExtensionDetailsController(it.pkgName)) }, onOpenExtension = { navigator.push(ExtensionDetailsScreen(it.pkgName)) },
onTrustExtension = { extensionsScreenModel.trustSignature(it.signatureHash) }, onTrustExtension = { extensionsScreenModel.trustSignature(it.signatureHash) },
onUninstallExtension = { extensionsScreenModel.uninstallExtension(it.pkgName) }, onUninstallExtension = { extensionsScreenModel.uninstallExtension(it.pkgName) },
onUpdateExtension = extensionsScreenModel::updateExtension, onUpdateExtension = extensionsScreenModel::updateExtension,

View File

@ -1,26 +0,0 @@
package eu.kanade.tachiyomi.ui.browse.extension.details
import android.os.Bundle
import androidx.compose.runtime.Composable
import androidx.core.os.bundleOf
import cafe.adriel.voyager.navigator.Navigator
import eu.kanade.presentation.browse.ExtensionDetailsScreen
import eu.kanade.tachiyomi.ui.base.controller.BasicFullComposeController
private const val PKGNAME_KEY = "pkg_name"
class ExtensionDetailsController : BasicFullComposeController {
@Suppress("unused")
constructor(bundle: Bundle) : this(bundle.getString(PKGNAME_KEY)!!)
constructor(pkgName: String) : super(bundleOf(PKGNAME_KEY to pkgName))
val pkgName: String
get() = args.getString(PKGNAME_KEY)!!
@Composable
override fun ComposeContent() {
Navigator(screen = ExtensionDetailsScreen(pkgName = pkgName))
}
}

View File

@ -8,6 +8,7 @@ import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.platform.LocalUriHandler import androidx.compose.ui.platform.LocalUriHandler
import cafe.adriel.voyager.core.model.rememberScreenModel import cafe.adriel.voyager.core.model.rememberScreenModel
import cafe.adriel.voyager.core.screen.Screen import cafe.adriel.voyager.core.screen.Screen
import cafe.adriel.voyager.navigator.LocalNavigator
import cafe.adriel.voyager.navigator.currentOrThrow import cafe.adriel.voyager.navigator.currentOrThrow
import eu.kanade.presentation.browse.ExtensionDetailsScreen import eu.kanade.presentation.browse.ExtensionDetailsScreen
import eu.kanade.presentation.components.LoadingScreen import eu.kanade.presentation.components.LoadingScreen
@ -15,7 +16,7 @@ import eu.kanade.presentation.util.LocalRouter
import eu.kanade.tachiyomi.ui.base.controller.pushController import eu.kanade.tachiyomi.ui.base.controller.pushController
import kotlinx.coroutines.flow.collectLatest import kotlinx.coroutines.flow.collectLatest
class ExtensionDetailsScreen( data class ExtensionDetailsScreen(
private val pkgName: String, private val pkgName: String,
) : Screen { ) : Screen {
@ -30,11 +31,12 @@ class ExtensionDetailsScreen(
return return
} }
val navigator = LocalNavigator.currentOrThrow
val router = LocalRouter.currentOrThrow val router = LocalRouter.currentOrThrow
val uriHandler = LocalUriHandler.current val uriHandler = LocalUriHandler.current
ExtensionDetailsScreen( ExtensionDetailsScreen(
navigateUp = router::popCurrentController, navigateUp = navigator::pop,
state = state, state = state,
onClickSourcePreferences = { router.pushController(SourcePreferencesController(it)) }, onClickSourcePreferences = { router.pushController(SourcePreferencesController(it)) },
onClickWhatsNew = { uriHandler.openUri(screenModel.getChangelogUrl()) }, onClickWhatsNew = { uriHandler.openUri(screenModel.getChangelogUrl()) },
@ -49,7 +51,7 @@ class ExtensionDetailsScreen(
LaunchedEffect(Unit) { LaunchedEffect(Unit) {
screenModel.events.collectLatest { event -> screenModel.events.collectLatest { event ->
if (event is ExtensionDetailsEvent.Uninstalled) { if (event is ExtensionDetailsEvent.Uninstalled) {
router.popCurrentController() navigator.pop()
} }
} }
} }

View File

@ -1,6 +1,7 @@
package eu.kanade.tachiyomi.ui.browse.extension.details package eu.kanade.tachiyomi.ui.browse.extension.details
import android.content.Context import android.content.Context
import androidx.compose.runtime.Immutable
import cafe.adriel.voyager.core.model.StateScreenModel import cafe.adriel.voyager.core.model.StateScreenModel
import cafe.adriel.voyager.core.model.coroutineScope import cafe.adriel.voyager.core.model.coroutineScope
import eu.kanade.domain.extension.interactor.ExtensionSourceItem import eu.kanade.domain.extension.interactor.ExtensionSourceItem
@ -14,11 +15,13 @@ import eu.kanade.tachiyomi.util.system.LocaleHelper
import eu.kanade.tachiyomi.util.system.logcat import eu.kanade.tachiyomi.util.system.logcat
import kotlinx.coroutines.channels.Channel import kotlinx.coroutines.channels.Channel
import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.catch
import kotlinx.coroutines.flow.collectLatest import kotlinx.coroutines.flow.collectLatest
import kotlinx.coroutines.flow.map import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.receiveAsFlow import kotlinx.coroutines.flow.receiveAsFlow
import kotlinx.coroutines.flow.update import kotlinx.coroutines.flow.update
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import logcat.LogPriority
import okhttp3.HttpUrl.Companion.toHttpUrl import okhttp3.HttpUrl.Companion.toHttpUrl
import uy.kohesive.injekt.Injekt import uy.kohesive.injekt.Injekt
import uy.kohesive.injekt.api.get import uy.kohesive.injekt.api.get
@ -69,12 +72,13 @@ class ExtensionDetailsScreenModel(
}, },
), ),
) )
}.collectLatest { sources ->
mutableState.update {
it.copy(
sources = sources,
)
} }
.catch { throwable ->
logcat(LogPriority.ERROR, throwable)
mutableState.update { it.copy(_sources = emptyList()) }
}
.collectLatest { sources ->
mutableState.update { it.copy(_sources = sources) }
} }
} }
} }
@ -157,11 +161,15 @@ sealed class ExtensionDetailsEvent {
object Uninstalled : ExtensionDetailsEvent() object Uninstalled : ExtensionDetailsEvent()
} }
@Immutable
data class ExtensionDetailsState( data class ExtensionDetailsState(
val extension: Extension.Installed? = null, val extension: Extension.Installed? = null,
val sources: List<ExtensionSourceItem> = emptyList(), private val _sources: List<ExtensionSourceItem>? = null,
) { ) {
val sources: List<ExtensionSourceItem>
get() = _sources ?: emptyList()
val isLoading: Boolean val isLoading: Boolean
get() = sources.isEmpty() get() = extension == null || _sources == null
} }