Voyager on More tab (#8498)

(cherry picked from commit 340357d158762a0b01b09092688ef6bce784b1c0)

# Conflicts:
#	app/src/main/java/eu/kanade/tachiyomi/ui/more/MoreController.kt
#	app/src/main/java/eu/kanade/tachiyomi/ui/more/MorePresenter.kt
This commit is contained in:
Ivan Iskandar 2022-11-11 10:08:18 +07:00 committed by Jobobby04
parent 70dff5ef5f
commit 13db6c1a7a
4 changed files with 136 additions and 107 deletions

View File

@ -17,8 +17,6 @@ import androidx.compose.material.icons.outlined.PlaylistAdd
import androidx.compose.material.icons.outlined.Settings
import androidx.compose.material.icons.outlined.SettingsBackupRestore
import androidx.compose.runtime.Composable
import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.getValue
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.vector.ImageVector
import androidx.compose.ui.platform.LocalUriHandler
@ -34,13 +32,20 @@ import eu.kanade.presentation.more.settings.widget.TextPreferenceWidget
import eu.kanade.tachiyomi.R
import eu.kanade.tachiyomi.ui.more.DownloadQueueState
import eu.kanade.tachiyomi.ui.more.MoreController
import eu.kanade.tachiyomi.ui.more.MorePresenter
import eu.kanade.tachiyomi.widget.TachiyomiBottomNavigationView
@Composable
fun MoreScreen(
presenter: MorePresenter,
downloadQueueStateProvider: () -> DownloadQueueState,
downloadedOnly: Boolean,
onDownloadedOnlyChange: (Boolean) -> Unit,
incognitoMode: Boolean,
onIncognitoModeChange: (Boolean) -> Unit,
isFDroid: Boolean,
// SY -->
showNavUpdates: Boolean,
showNavHistory: Boolean,
// SY <--
onClickDownloadQueue: () -> Unit,
onClickCategories: () -> Unit,
onClickBackupAndRestore: () -> Unit,
@ -51,7 +56,6 @@ fun MoreScreen(
onClickHistory: () -> Unit,
) {
val uriHandler = LocalUriHandler.current
val downloadQueueState by presenter.downloadQueueState.collectAsState()
ScrollbarLazyColumn(
modifier = Modifier.statusBarsPadding(),
@ -76,8 +80,8 @@ fun MoreScreen(
item {
AppStateBanners(
downloadedOnlyMode = presenter.downloadedOnly.value,
incognitoMode = presenter.incognitoMode.value,
downloadedOnlyMode = downloadedOnly,
incognitoMode = incognitoMode,
)
}
@ -86,8 +90,8 @@ fun MoreScreen(
title = stringResource(R.string.label_downloaded_only),
subtitle = stringResource(R.string.downloaded_only_summary),
icon = Icons.Outlined.CloudOff,
checked = presenter.downloadedOnly.value,
onCheckedChanged = { presenter.downloadedOnly.value = it },
checked = downloadedOnly,
onCheckedChanged = onDownloadedOnlyChange,
)
}
item {
@ -95,15 +99,15 @@ fun MoreScreen(
title = stringResource(R.string.pref_incognito_mode),
subtitle = stringResource(R.string.pref_incognito_mode_summary),
icon = ImageVector.vectorResource(R.drawable.ic_glasses_24dp),
checked = presenter.incognitoMode.value,
onCheckedChanged = { presenter.incognitoMode.value = it },
checked = incognitoMode,
onCheckedChanged = onIncognitoModeChange,
)
}
item { Divider() }
// SY -->
if (!presenter.showNavUpdates.value) {
if (!showNavUpdates) {
item {
TextPreferenceWidget(
title = stringResource(R.string.label_recent_updates),
@ -112,7 +116,7 @@ fun MoreScreen(
)
}
}
if (!presenter.showNavHistory.value) {
if (!showNavHistory) {
item {
TextPreferenceWidget(
title = stringResource(R.string.label_recent_manga),
@ -124,12 +128,13 @@ fun MoreScreen(
// SY <--
item {
val downloadQueueState = downloadQueueStateProvider()
TextPreferenceWidget(
title = stringResource(R.string.label_download_queue),
subtitle = when (downloadQueueState) {
DownloadQueueState.Stopped -> null
is DownloadQueueState.Paused -> {
val pending = (downloadQueueState as DownloadQueueState.Paused).pending
val pending = downloadQueueState.pending
if (pending == 0) {
stringResource(R.string.paused)
} else {
@ -143,7 +148,7 @@ fun MoreScreen(
}
}
is DownloadQueueState.Downloading -> {
val pending = (downloadQueueState as DownloadQueueState.Downloading).pending
val pending = downloadQueueState.pending
pluralStringResource(id = R.plurals.download_queue_summary, count = pending, pending)
}
},

View File

@ -1,40 +1,15 @@
package eu.kanade.tachiyomi.ui.more
import androidx.compose.runtime.Composable
import eu.kanade.presentation.more.MoreScreen
import eu.kanade.tachiyomi.ui.base.controller.FullComposeController
import cafe.adriel.voyager.navigator.Navigator
import eu.kanade.tachiyomi.ui.base.controller.BasicFullComposeController
import eu.kanade.tachiyomi.ui.base.controller.RootController
import eu.kanade.tachiyomi.ui.base.controller.pushController
import eu.kanade.tachiyomi.ui.category.CategoryController
import eu.kanade.tachiyomi.ui.download.DownloadController
import eu.kanade.tachiyomi.ui.history.HistoryController
import eu.kanade.tachiyomi.ui.setting.SettingsMainController
import eu.kanade.tachiyomi.ui.updates.UpdatesController
import eu.kanade.tachiyomi.util.system.isInstalledFromFDroid
import exh.ui.batchadd.BatchAddController
class MoreController :
FullComposeController<MorePresenter>(),
RootController {
override fun createPresenter() = MorePresenter()
class MoreController : BasicFullComposeController(), RootController {
@Composable
override fun ComposeContent() {
MoreScreen(
presenter = presenter,
isFDroid = activity?.isInstalledFromFDroid() ?: false,
onClickDownloadQueue = { router.pushController(DownloadController()) },
onClickCategories = { router.pushController(CategoryController()) },
onClickBackupAndRestore = { router.pushController(SettingsMainController.toBackupScreen()) },
onClickSettings = { router.pushController(SettingsMainController()) },
onClickAbout = { router.pushController(SettingsMainController.toAboutScreen()) },
// SY -->
onClickBatchAdd = { router.pushController(BatchAddController()) },
onClickUpdates = { router.pushController(UpdatesController()) },
onClickHistory = { router.pushController(HistoryController()) },
// SY <--
)
Navigator(screen = MoreScreen)
}
companion object {

View File

@ -1,63 +0,0 @@
package eu.kanade.tachiyomi.ui.more
import android.os.Bundle
import eu.kanade.domain.base.BasePreferences
import eu.kanade.domain.ui.UiPreferences
import eu.kanade.tachiyomi.data.download.DownloadManager
import eu.kanade.tachiyomi.data.download.DownloadService
import eu.kanade.tachiyomi.ui.base.presenter.BasePresenter
import eu.kanade.tachiyomi.util.lang.launchIO
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.flow.collectLatest
import kotlinx.coroutines.flow.combine
import uy.kohesive.injekt.Injekt
import uy.kohesive.injekt.api.get
class MorePresenter(
private val downloadManager: DownloadManager = Injekt.get(),
preferences: BasePreferences = Injekt.get(),
// SY -->
uiPreferences: UiPreferences = Injekt.get(),
// SY <--
) : BasePresenter<MoreController>() {
val downloadedOnly = preferences.downloadedOnly().asState()
val incognitoMode = preferences.incognitoMode().asState()
// SY -->
val showNavUpdates = uiPreferences.showNavUpdates().asState()
val showNavHistory = uiPreferences.showNavHistory().asState()
// SY <--
private var _state: MutableStateFlow<DownloadQueueState> = MutableStateFlow(DownloadQueueState.Stopped)
val downloadQueueState: StateFlow<DownloadQueueState> = _state.asStateFlow()
override fun onCreate(savedState: Bundle?) {
super.onCreate(savedState)
// Handle running/paused status change and queue progress updating
presenterScope.launchIO {
combine(
DownloadService.isRunning,
downloadManager.queue.updatedFlow(),
) { isRunning, downloadQueue -> Pair(isRunning, downloadQueue.size) }
.collectLatest { (isDownloading, downloadQueueSize) ->
val pendingDownloadExists = downloadQueueSize != 0
_state.value = when {
!pendingDownloadExists -> DownloadQueueState.Stopped
!isDownloading && !pendingDownloadExists -> DownloadQueueState.Paused(0)
!isDownloading && pendingDownloadExists -> DownloadQueueState.Paused(downloadQueueSize)
else -> DownloadQueueState.Downloading(downloadQueueSize)
}
}
}
}
}
sealed class DownloadQueueState {
object Stopped : DownloadQueueState()
data class Paused(val pending: Int) : DownloadQueueState()
data class Downloading(val pending: Int) : DownloadQueueState()
}

View File

@ -0,0 +1,112 @@
package eu.kanade.tachiyomi.ui.more
import androidx.compose.runtime.Composable
import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.getValue
import androidx.compose.runtime.setValue
import androidx.compose.ui.platform.LocalContext
import cafe.adriel.voyager.core.model.ScreenModel
import cafe.adriel.voyager.core.model.coroutineScope
import cafe.adriel.voyager.core.model.rememberScreenModel
import cafe.adriel.voyager.core.screen.Screen
import cafe.adriel.voyager.navigator.currentOrThrow
import eu.kanade.core.prefs.asState
import eu.kanade.domain.base.BasePreferences
import eu.kanade.domain.ui.UiPreferences
import eu.kanade.presentation.more.MoreScreen
import eu.kanade.presentation.util.LocalRouter
import eu.kanade.tachiyomi.data.download.DownloadManager
import eu.kanade.tachiyomi.data.download.DownloadService
import eu.kanade.tachiyomi.ui.base.controller.pushController
import eu.kanade.tachiyomi.ui.category.CategoryController
import eu.kanade.tachiyomi.ui.download.DownloadController
import eu.kanade.tachiyomi.ui.history.HistoryController
import eu.kanade.tachiyomi.ui.setting.SettingsMainController
import eu.kanade.tachiyomi.ui.updates.UpdatesController
import eu.kanade.tachiyomi.util.lang.launchIO
import eu.kanade.tachiyomi.util.system.isInstalledFromFDroid
import exh.ui.batchadd.BatchAddController
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.flow.collectLatest
import kotlinx.coroutines.flow.combine
import uy.kohesive.injekt.Injekt
import uy.kohesive.injekt.api.get
object MoreScreen : Screen {
@Composable
override fun Content() {
val router = LocalRouter.currentOrThrow
val context = LocalContext.current
val screenModel = rememberScreenModel { MoreScreenModel() }
val downloadQueueState by screenModel.downloadQueueState.collectAsState()
MoreScreen(
downloadQueueStateProvider = { downloadQueueState },
downloadedOnly = screenModel.downloadedOnly,
onDownloadedOnlyChange = { screenModel.downloadedOnly = it },
incognitoMode = screenModel.incognitoMode,
onIncognitoModeChange = { screenModel.incognitoMode = it },
isFDroid = context.isInstalledFromFDroid(),
// SY -->
showNavUpdates = screenModel.showNavUpdates,
showNavHistory = screenModel.showNavHistory,
// SY <--
onClickDownloadQueue = { router.pushController(DownloadController()) },
onClickCategories = { router.pushController(CategoryController()) },
onClickBackupAndRestore = { router.pushController(SettingsMainController.toBackupScreen()) },
onClickSettings = { router.pushController(SettingsMainController()) },
onClickAbout = { router.pushController(SettingsMainController.toAboutScreen()) },
// SY -->
onClickBatchAdd = { router.pushController(BatchAddController()) },
onClickUpdates = { router.pushController(UpdatesController()) },
onClickHistory = { router.pushController(HistoryController()) },
// SY <--
)
}
}
private class MoreScreenModel(
private val downloadManager: DownloadManager = Injekt.get(),
preferences: BasePreferences = Injekt.get(),
// SY -->
uiPreferences: UiPreferences = Injekt.get(),
// SY <--
) : ScreenModel {
var downloadedOnly by preferences.downloadedOnly().asState(coroutineScope)
var incognitoMode by preferences.incognitoMode().asState(coroutineScope)
// SY -->
val showNavUpdates by uiPreferences.showNavUpdates().asState(coroutineScope)
val showNavHistory by uiPreferences.showNavHistory().asState(coroutineScope)
// SY <--
private var _state: MutableStateFlow<DownloadQueueState> = MutableStateFlow(DownloadQueueState.Stopped)
val downloadQueueState: StateFlow<DownloadQueueState> = _state.asStateFlow()
init {
// Handle running/paused status change and queue progress updating
coroutineScope.launchIO {
combine(
DownloadService.isRunning,
downloadManager.queue.updatedFlow(),
) { isRunning, downloadQueue -> Pair(isRunning, downloadQueue.size) }
.collectLatest { (isDownloading, downloadQueueSize) ->
val pendingDownloadExists = downloadQueueSize != 0
_state.value = when {
!pendingDownloadExists -> DownloadQueueState.Stopped
!isDownloading && !pendingDownloadExists -> DownloadQueueState.Paused(0)
!isDownloading && pendingDownloadExists -> DownloadQueueState.Paused(downloadQueueSize)
else -> DownloadQueueState.Downloading(downloadQueueSize)
}
}
}
}
}
sealed class DownloadQueueState {
object Stopped : DownloadQueueState()
data class Paused(val pending: Int) : DownloadQueueState()
data class Downloading(val pending: Int) : DownloadQueueState()
}