Use Voyager between supported screens in Extension package (#8616)
- Minor state behavior changes
This commit is contained in:
parent
758d223776
commit
db35ba53b1
6 changed files with 29 additions and 63 deletions
|
@ -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())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -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) },
|
||||||
)
|
)
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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))
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -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()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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 {
|
.catch { throwable ->
|
||||||
it.copy(
|
logcat(LogPriority.ERROR, throwable)
|
||||||
sources = sources,
|
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
|
||||||
}
|
}
|
||||||
|
|
Reference in a new issue