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:
parent
70dff5ef5f
commit
13db6c1a7a
@ -17,8 +17,6 @@ import androidx.compose.material.icons.outlined.PlaylistAdd
|
|||||||
import androidx.compose.material.icons.outlined.Settings
|
import androidx.compose.material.icons.outlined.Settings
|
||||||
import androidx.compose.material.icons.outlined.SettingsBackupRestore
|
import androidx.compose.material.icons.outlined.SettingsBackupRestore
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.collectAsState
|
|
||||||
import androidx.compose.runtime.getValue
|
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.graphics.vector.ImageVector
|
import androidx.compose.ui.graphics.vector.ImageVector
|
||||||
import androidx.compose.ui.platform.LocalUriHandler
|
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.R
|
||||||
import eu.kanade.tachiyomi.ui.more.DownloadQueueState
|
import eu.kanade.tachiyomi.ui.more.DownloadQueueState
|
||||||
import eu.kanade.tachiyomi.ui.more.MoreController
|
import eu.kanade.tachiyomi.ui.more.MoreController
|
||||||
import eu.kanade.tachiyomi.ui.more.MorePresenter
|
|
||||||
import eu.kanade.tachiyomi.widget.TachiyomiBottomNavigationView
|
import eu.kanade.tachiyomi.widget.TachiyomiBottomNavigationView
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun MoreScreen(
|
fun MoreScreen(
|
||||||
presenter: MorePresenter,
|
downloadQueueStateProvider: () -> DownloadQueueState,
|
||||||
|
downloadedOnly: Boolean,
|
||||||
|
onDownloadedOnlyChange: (Boolean) -> Unit,
|
||||||
|
incognitoMode: Boolean,
|
||||||
|
onIncognitoModeChange: (Boolean) -> Unit,
|
||||||
isFDroid: Boolean,
|
isFDroid: Boolean,
|
||||||
|
// SY -->
|
||||||
|
showNavUpdates: Boolean,
|
||||||
|
showNavHistory: Boolean,
|
||||||
|
// SY <--
|
||||||
onClickDownloadQueue: () -> Unit,
|
onClickDownloadQueue: () -> Unit,
|
||||||
onClickCategories: () -> Unit,
|
onClickCategories: () -> Unit,
|
||||||
onClickBackupAndRestore: () -> Unit,
|
onClickBackupAndRestore: () -> Unit,
|
||||||
@ -51,7 +56,6 @@ fun MoreScreen(
|
|||||||
onClickHistory: () -> Unit,
|
onClickHistory: () -> Unit,
|
||||||
) {
|
) {
|
||||||
val uriHandler = LocalUriHandler.current
|
val uriHandler = LocalUriHandler.current
|
||||||
val downloadQueueState by presenter.downloadQueueState.collectAsState()
|
|
||||||
|
|
||||||
ScrollbarLazyColumn(
|
ScrollbarLazyColumn(
|
||||||
modifier = Modifier.statusBarsPadding(),
|
modifier = Modifier.statusBarsPadding(),
|
||||||
@ -76,8 +80,8 @@ fun MoreScreen(
|
|||||||
|
|
||||||
item {
|
item {
|
||||||
AppStateBanners(
|
AppStateBanners(
|
||||||
downloadedOnlyMode = presenter.downloadedOnly.value,
|
downloadedOnlyMode = downloadedOnly,
|
||||||
incognitoMode = presenter.incognitoMode.value,
|
incognitoMode = incognitoMode,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -86,8 +90,8 @@ fun MoreScreen(
|
|||||||
title = stringResource(R.string.label_downloaded_only),
|
title = stringResource(R.string.label_downloaded_only),
|
||||||
subtitle = stringResource(R.string.downloaded_only_summary),
|
subtitle = stringResource(R.string.downloaded_only_summary),
|
||||||
icon = Icons.Outlined.CloudOff,
|
icon = Icons.Outlined.CloudOff,
|
||||||
checked = presenter.downloadedOnly.value,
|
checked = downloadedOnly,
|
||||||
onCheckedChanged = { presenter.downloadedOnly.value = it },
|
onCheckedChanged = onDownloadedOnlyChange,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
item {
|
item {
|
||||||
@ -95,15 +99,15 @@ fun MoreScreen(
|
|||||||
title = stringResource(R.string.pref_incognito_mode),
|
title = stringResource(R.string.pref_incognito_mode),
|
||||||
subtitle = stringResource(R.string.pref_incognito_mode_summary),
|
subtitle = stringResource(R.string.pref_incognito_mode_summary),
|
||||||
icon = ImageVector.vectorResource(R.drawable.ic_glasses_24dp),
|
icon = ImageVector.vectorResource(R.drawable.ic_glasses_24dp),
|
||||||
checked = presenter.incognitoMode.value,
|
checked = incognitoMode,
|
||||||
onCheckedChanged = { presenter.incognitoMode.value = it },
|
onCheckedChanged = onIncognitoModeChange,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
item { Divider() }
|
item { Divider() }
|
||||||
|
|
||||||
// SY -->
|
// SY -->
|
||||||
if (!presenter.showNavUpdates.value) {
|
if (!showNavUpdates) {
|
||||||
item {
|
item {
|
||||||
TextPreferenceWidget(
|
TextPreferenceWidget(
|
||||||
title = stringResource(R.string.label_recent_updates),
|
title = stringResource(R.string.label_recent_updates),
|
||||||
@ -112,7 +116,7 @@ fun MoreScreen(
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!presenter.showNavHistory.value) {
|
if (!showNavHistory) {
|
||||||
item {
|
item {
|
||||||
TextPreferenceWidget(
|
TextPreferenceWidget(
|
||||||
title = stringResource(R.string.label_recent_manga),
|
title = stringResource(R.string.label_recent_manga),
|
||||||
@ -124,12 +128,13 @@ fun MoreScreen(
|
|||||||
// SY <--
|
// SY <--
|
||||||
|
|
||||||
item {
|
item {
|
||||||
|
val downloadQueueState = downloadQueueStateProvider()
|
||||||
TextPreferenceWidget(
|
TextPreferenceWidget(
|
||||||
title = stringResource(R.string.label_download_queue),
|
title = stringResource(R.string.label_download_queue),
|
||||||
subtitle = when (downloadQueueState) {
|
subtitle = when (downloadQueueState) {
|
||||||
DownloadQueueState.Stopped -> null
|
DownloadQueueState.Stopped -> null
|
||||||
is DownloadQueueState.Paused -> {
|
is DownloadQueueState.Paused -> {
|
||||||
val pending = (downloadQueueState as DownloadQueueState.Paused).pending
|
val pending = downloadQueueState.pending
|
||||||
if (pending == 0) {
|
if (pending == 0) {
|
||||||
stringResource(R.string.paused)
|
stringResource(R.string.paused)
|
||||||
} else {
|
} else {
|
||||||
@ -143,7 +148,7 @@ fun MoreScreen(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
is DownloadQueueState.Downloading -> {
|
is DownloadQueueState.Downloading -> {
|
||||||
val pending = (downloadQueueState as DownloadQueueState.Downloading).pending
|
val pending = downloadQueueState.pending
|
||||||
pluralStringResource(id = R.plurals.download_queue_summary, count = pending, pending)
|
pluralStringResource(id = R.plurals.download_queue_summary, count = pending, pending)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -1,40 +1,15 @@
|
|||||||
package eu.kanade.tachiyomi.ui.more
|
package eu.kanade.tachiyomi.ui.more
|
||||||
|
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import eu.kanade.presentation.more.MoreScreen
|
import cafe.adriel.voyager.navigator.Navigator
|
||||||
import eu.kanade.tachiyomi.ui.base.controller.FullComposeController
|
import eu.kanade.tachiyomi.ui.base.controller.BasicFullComposeController
|
||||||
import eu.kanade.tachiyomi.ui.base.controller.RootController
|
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 :
|
class MoreController : BasicFullComposeController(), RootController {
|
||||||
FullComposeController<MorePresenter>(),
|
|
||||||
RootController {
|
|
||||||
|
|
||||||
override fun createPresenter() = MorePresenter()
|
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
override fun ComposeContent() {
|
override fun ComposeContent() {
|
||||||
MoreScreen(
|
Navigator(screen = 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 <--
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
|
@ -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()
|
|
||||||
}
|
|
112
app/src/main/java/eu/kanade/tachiyomi/ui/more/MoreScreen.kt
Normal file
112
app/src/main/java/eu/kanade/tachiyomi/ui/more/MoreScreen.kt
Normal 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()
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user