diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 0ab668f39..209ff44e0 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -182,6 +182,7 @@ dependencies { implementation(compose.accompanist.flowlayout) implementation(compose.accompanist.permissions) implementation(compose.accompanist.themeadapter) + implementation(compose.accompanist.systemuicontroller) implementation(androidx.paging.runtime) implementation(androidx.paging.compose) diff --git a/app/src/main/java/eu/kanade/presentation/components/AppBar.kt b/app/src/main/java/eu/kanade/presentation/components/AppBar.kt index 440f597fa..f94513bb7 100644 --- a/app/src/main/java/eu/kanade/presentation/components/AppBar.kt +++ b/app/src/main/java/eu/kanade/presentation/components/AppBar.kt @@ -63,9 +63,6 @@ fun AppBar( actionModeCounter: Int = 0, onCancelActionMode: () -> Unit = {}, actionModeActions: @Composable RowScope.() -> Unit = {}, - // Banners - downloadedOnlyMode: Boolean = false, - incognitoMode: Boolean = false, scrollBehavior: TopAppBarScrollBehavior? = null, ) { @@ -93,8 +90,6 @@ fun AppBar( }, isActionMode = isActionMode, onCancelActionMode = onCancelActionMode, - downloadedOnlyMode = downloadedOnlyMode, - incognitoMode = incognitoMode, scrollBehavior = scrollBehavior, ) } @@ -112,9 +107,6 @@ fun AppBar( // Action mode isActionMode: Boolean = false, onCancelActionMode: () -> Unit = {}, - // Banners - downloadedOnlyMode: Boolean = false, - incognitoMode: Boolean = false, scrollBehavior: TopAppBarScrollBehavior? = null, ) { @@ -150,8 +142,6 @@ fun AppBar( ), scrollBehavior = scrollBehavior, ) - - AppStateBanners(downloadedOnlyMode, incognitoMode) } } @@ -236,8 +226,6 @@ fun SearchToolbar( onSearch: (String) -> Unit = {}, onClickCloseSearch: () -> Unit = { onChangeSearchQuery(null) }, actions: @Composable RowScope.() -> Unit = {}, - incognitoMode: Boolean = false, - downloadedOnlyMode: Boolean = false, scrollBehavior: TopAppBarScrollBehavior? = null, visualTransformation: VisualTransformation = VisualTransformation.None, interactionSource: MutableInteractionSource = remember { MutableInteractionSource() }, @@ -326,8 +314,6 @@ fun SearchToolbar( key("actions") { actions() } }, isActionMode = false, - downloadedOnlyMode = downloadedOnlyMode, - incognitoMode = incognitoMode, scrollBehavior = scrollBehavior, ) LaunchedEffect(searchClickCount) { diff --git a/app/src/main/java/eu/kanade/presentation/components/Banners.kt b/app/src/main/java/eu/kanade/presentation/components/Banners.kt index 3bb503b4d..d455b943d 100644 --- a/app/src/main/java/eu/kanade/presentation/components/Banners.kt +++ b/app/src/main/java/eu/kanade/presentation/components/Banners.kt @@ -3,8 +3,13 @@ package eu.kanade.presentation.components import androidx.annotation.StringRes import androidx.compose.foundation.background import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.WindowInsets +import androidx.compose.foundation.layout.WindowInsetsSides import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.only import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.systemBars +import androidx.compose.foundation.layout.windowInsetsPadding import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Text import androidx.compose.runtime.Composable @@ -37,24 +42,34 @@ fun AppStateBanners( incognitoMode: Boolean, modifier: Modifier = Modifier, ) { + val insets = WindowInsets.systemBars.only(WindowInsetsSides.Top + WindowInsetsSides.Horizontal) Column(modifier = modifier) { if (downloadedOnlyMode) { - DownloadedOnlyModeBanner() + DownloadedOnlyModeBanner( + modifier = Modifier.windowInsetsPadding(insets), + ) } if (incognitoMode) { - IncognitoModeBanner() + IncognitoModeBanner( + modifier = if (!downloadedOnlyMode) { + Modifier.windowInsetsPadding(insets) + } else { + Modifier + }, + ) } } } @Composable -private fun DownloadedOnlyModeBanner() { +private fun DownloadedOnlyModeBanner(modifier: Modifier = Modifier) { Text( text = stringResource(R.string.label_downloaded_only), modifier = Modifier .background(color = MaterialTheme.colorScheme.tertiary) .fillMaxWidth() - .padding(4.dp), + .padding(4.dp) + .then(modifier), color = MaterialTheme.colorScheme.onTertiary, textAlign = TextAlign.Center, style = MaterialTheme.typography.labelMedium, @@ -62,13 +77,14 @@ private fun DownloadedOnlyModeBanner() { } @Composable -private fun IncognitoModeBanner() { +private fun IncognitoModeBanner(modifier: Modifier = Modifier) { Text( text = stringResource(R.string.pref_incognito_mode), modifier = Modifier .background(color = MaterialTheme.colorScheme.primary) .fillMaxWidth() - .padding(4.dp), + .padding(4.dp) + .then(modifier), color = MaterialTheme.colorScheme.onPrimary, textAlign = TextAlign.Center, style = MaterialTheme.typography.labelMedium, diff --git a/app/src/main/java/eu/kanade/presentation/components/TabbedScreen.kt b/app/src/main/java/eu/kanade/presentation/components/TabbedScreen.kt index fe03d10a5..4cc8d5145 100644 --- a/app/src/main/java/eu/kanade/presentation/components/TabbedScreen.kt +++ b/app/src/main/java/eu/kanade/presentation/components/TabbedScreen.kt @@ -29,8 +29,6 @@ fun TabbedScreen( startIndex: Int? = null, searchQuery: String? = null, onChangeSearchQuery: (String?) -> Unit = {}, - incognitoMode: Boolean, - downloadedOnlyMode: Boolean, ) { val scope = rememberCoroutineScope() val state = rememberPagerState() @@ -78,8 +76,6 @@ fun TabbedScreen( } } - AppStateBanners(downloadedOnlyMode, incognitoMode) - HorizontalPager( count = tabs.size, modifier = Modifier.fillMaxSize(), diff --git a/app/src/main/java/eu/kanade/presentation/history/HistoryScreen.kt b/app/src/main/java/eu/kanade/presentation/history/HistoryScreen.kt index 0bb873bc8..34643ca2e 100644 --- a/app/src/main/java/eu/kanade/presentation/history/HistoryScreen.kt +++ b/app/src/main/java/eu/kanade/presentation/history/HistoryScreen.kt @@ -26,8 +26,6 @@ import java.util.Date fun HistoryScreen( state: HistoryState, snackbarHostState: SnackbarHostState, - incognitoMode: Boolean, - downloadedOnlyMode: Boolean, onSearchQueryChange: (String?) -> Unit, onClickCover: (mangaId: Long) -> Unit, onClickResume: (mangaId: Long, chapterId: Long) -> Unit, @@ -47,8 +45,6 @@ fun HistoryScreen( ) } }, - downloadedOnlyMode = downloadedOnlyMode, - incognitoMode = incognitoMode, scrollBehavior = scrollBehavior, ) }, diff --git a/app/src/main/java/eu/kanade/presentation/library/components/LibraryContent.kt b/app/src/main/java/eu/kanade/presentation/library/components/LibraryContent.kt index a5d80d6a7..28ce0bdac 100644 --- a/app/src/main/java/eu/kanade/presentation/library/components/LibraryContent.kt +++ b/app/src/main/java/eu/kanade/presentation/library/components/LibraryContent.kt @@ -45,8 +45,6 @@ fun LibraryContent( getDisplayModeForPage: @Composable (Int) -> LibraryDisplayMode, getColumnsForOrientation: (Boolean) -> PreferenceMutableState, getLibraryForPage: (Int) -> List, - isDownloadOnly: Boolean, - isIncognitoMode: Boolean, ) { Column( modifier = Modifier.padding( @@ -65,8 +63,6 @@ fun LibraryContent( LibraryTabs( categories = categories, currentPageIndex = pagerState.currentPage, - isDownloadOnly = isDownloadOnly, - isIncognitoMode = isIncognitoMode, getNumberOfMangaForCategory = getNumberOfMangaForCategory, ) { scope.launch { pagerState.animateScrollToPage(it) } } } diff --git a/app/src/main/java/eu/kanade/presentation/library/components/LibraryTabs.kt b/app/src/main/java/eu/kanade/presentation/library/components/LibraryTabs.kt index d2344d0d2..c5ed121c1 100644 --- a/app/src/main/java/eu/kanade/presentation/library/components/LibraryTabs.kt +++ b/app/src/main/java/eu/kanade/presentation/library/components/LibraryTabs.kt @@ -8,7 +8,6 @@ import androidx.compose.runtime.Composable import androidx.compose.ui.unit.dp import eu.kanade.domain.category.model.Category import eu.kanade.presentation.category.visualName -import eu.kanade.presentation.components.AppStateBanners import eu.kanade.presentation.components.Divider import eu.kanade.presentation.components.TabIndicator import eu.kanade.presentation.components.TabText @@ -17,8 +16,6 @@ import eu.kanade.presentation.components.TabText fun LibraryTabs( categories: List, currentPageIndex: Int, - isDownloadOnly: Boolean, - isIncognitoMode: Boolean, getNumberOfMangaForCategory: (Category) -> Int?, onTabItemClick: (Int) -> Unit, ) { @@ -47,7 +44,5 @@ fun LibraryTabs( } Divider() - - AppStateBanners(isDownloadOnly, isIncognitoMode) } } diff --git a/app/src/main/java/eu/kanade/presentation/library/components/LibraryToolbar.kt b/app/src/main/java/eu/kanade/presentation/library/components/LibraryToolbar.kt index c96fc62c6..cd7a7ff9b 100644 --- a/app/src/main/java/eu/kanade/presentation/library/components/LibraryToolbar.kt +++ b/app/src/main/java/eu/kanade/presentation/library/components/LibraryToolbar.kt @@ -32,8 +32,6 @@ fun LibraryToolbar( hasActiveFilters: Boolean, selectedCount: Int, title: LibraryToolbarTitle, - incognitoMode: Boolean, - downloadedOnlyMode: Boolean, onClickUnselectAll: () -> Unit, onClickSelectAll: () -> Unit, onClickInvertSelection: () -> Unit, @@ -46,8 +44,6 @@ fun LibraryToolbar( ) = when { selectedCount > 0 -> LibrarySelectionToolbar( selectedCount = selectedCount, - incognitoMode = incognitoMode, - downloadedOnlyMode = downloadedOnlyMode, onClickUnselectAll = onClickUnselectAll, onClickSelectAll = onClickSelectAll, onClickInvertSelection = onClickInvertSelection, @@ -55,8 +51,6 @@ fun LibraryToolbar( else -> LibraryRegularToolbar( title = title, hasFilters = hasActiveFilters, - incognitoMode = incognitoMode, - downloadedOnlyMode = downloadedOnlyMode, searchQuery = searchQuery, onSearchQueryChange = onSearchQueryChange, onClickFilter = onClickFilter, @@ -70,8 +64,6 @@ fun LibraryToolbar( fun LibraryRegularToolbar( title: LibraryToolbarTitle, hasFilters: Boolean, - incognitoMode: Boolean, - downloadedOnlyMode: Boolean, searchQuery: String?, onSearchQueryChange: (String?) -> Unit, onClickFilter: () -> Unit, @@ -123,8 +115,6 @@ fun LibraryRegularToolbar( ) } }, - incognitoMode = incognitoMode, - downloadedOnlyMode = downloadedOnlyMode, scrollBehavior = scrollBehavior, ) } @@ -132,8 +122,6 @@ fun LibraryRegularToolbar( @Composable fun LibrarySelectionToolbar( selectedCount: Int, - incognitoMode: Boolean, - downloadedOnlyMode: Boolean, onClickUnselectAll: () -> Unit, onClickSelectAll: () -> Unit, onClickInvertSelection: () -> Unit, @@ -150,8 +138,6 @@ fun LibrarySelectionToolbar( }, isActionMode = true, onCancelActionMode = onClickUnselectAll, - incognitoMode = incognitoMode, - downloadedOnlyMode = downloadedOnlyMode, ) } diff --git a/app/src/main/java/eu/kanade/presentation/manga/MangaScreen.kt b/app/src/main/java/eu/kanade/presentation/manga/MangaScreen.kt index 0bc451dea..f77d19bb9 100644 --- a/app/src/main/java/eu/kanade/presentation/manga/MangaScreen.kt +++ b/app/src/main/java/eu/kanade/presentation/manga/MangaScreen.kt @@ -238,8 +238,6 @@ private fun MangaScreenSmallImpl( titleAlphaProvider = { animatedTitleAlpha }, backgroundAlphaProvider = { animatedBgAlpha }, hasFilters = state.manga.chaptersFiltered(), - incognitoMode = state.isIncognitoMode, - downloadedOnlyMode = state.isDownloadedOnlyMode, onBackClicked = internalOnBackPressed, onClickFilter = onFilterClicked, onClickShare = onShareClicked, @@ -450,8 +448,6 @@ fun MangaScreenLargeImpl( titleAlphaProvider = { if (chapters.fastAny { it.selected }) 1f else 0f }, backgroundAlphaProvider = { 1f }, hasFilters = state.manga.chaptersFiltered(), - incognitoMode = state.isIncognitoMode, - downloadedOnlyMode = state.isDownloadedOnlyMode, onBackClicked = internalOnBackPressed, onClickFilter = onFilterButtonClicked, onClickShare = onShareClicked, diff --git a/app/src/main/java/eu/kanade/presentation/manga/components/MangaToolbar.kt b/app/src/main/java/eu/kanade/presentation/manga/components/MangaToolbar.kt index 52be85e7e..85171df81 100644 --- a/app/src/main/java/eu/kanade/presentation/manga/components/MangaToolbar.kt +++ b/app/src/main/java/eu/kanade/presentation/manga/components/MangaToolbar.kt @@ -26,7 +26,6 @@ import androidx.compose.ui.draw.alpha import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.unit.dp -import eu.kanade.presentation.components.AppStateBanners import eu.kanade.presentation.components.DownloadDropdownMenu import eu.kanade.presentation.components.OverflowMenu import eu.kanade.presentation.manga.DownloadAction @@ -40,8 +39,6 @@ fun MangaToolbar( titleAlphaProvider: () -> Float, backgroundAlphaProvider: () -> Float = titleAlphaProvider, hasFilters: Boolean, - incognitoMode: Boolean, - downloadedOnlyMode: Boolean, onBackClicked: () -> Unit, onClickFilter: () -> Unit, onClickShare: (() -> Unit)?, @@ -151,7 +148,5 @@ fun MangaToolbar( .copy(alpha = if (isActionMode) 1f else backgroundAlphaProvider()), ), ) - - AppStateBanners(downloadedOnlyMode, incognitoMode) } } diff --git a/app/src/main/java/eu/kanade/presentation/more/MoreScreen.kt b/app/src/main/java/eu/kanade/presentation/more/MoreScreen.kt index 81961e234..8af4f2ef0 100644 --- a/app/src/main/java/eu/kanade/presentation/more/MoreScreen.kt +++ b/app/src/main/java/eu/kanade/presentation/more/MoreScreen.kt @@ -1,7 +1,13 @@ package eu.kanade.presentation.more import androidx.compose.foundation.clickable -import androidx.compose.foundation.layout.systemBarsPadding +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.WindowInsets +import androidx.compose.foundation.layout.WindowInsetsSides +import androidx.compose.foundation.layout.only +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.systemBars +import androidx.compose.foundation.layout.windowInsetsPadding import androidx.compose.material.icons.Icons import androidx.compose.material.icons.outlined.CloudOff import androidx.compose.material.icons.outlined.GetApp @@ -18,8 +24,8 @@ import androidx.compose.ui.platform.LocalUriHandler import androidx.compose.ui.res.pluralStringResource import androidx.compose.ui.res.stringResource import androidx.compose.ui.res.vectorResource -import eu.kanade.presentation.components.AppStateBanners import eu.kanade.presentation.components.Divider +import eu.kanade.presentation.components.Scaffold import eu.kanade.presentation.components.ScrollbarLazyColumn import eu.kanade.presentation.components.WarningBanner import eu.kanade.presentation.more.settings.widget.SwitchPreferenceWidget @@ -45,125 +51,125 @@ fun MoreScreen( ) { val uriHandler = LocalUriHandler.current - ScrollbarLazyColumn( - modifier = Modifier.systemBarsPadding(), - ) { - if (isFDroid) { + Scaffold( + topBar = { + Column( + modifier = Modifier.windowInsetsPadding( + WindowInsets.systemBars.only(WindowInsetsSides.Top + WindowInsetsSides.Horizontal), + ), + ) { + if (isFDroid) { + WarningBanner( + textRes = R.string.fdroid_warning, + modifier = Modifier.clickable { + uriHandler.openUri("https://tachiyomi.org/help/faq/#how-do-i-migrate-from-the-f-droid-version") + }, + ) + } + } + }, + ) { contentPadding -> + ScrollbarLazyColumn( + modifier = Modifier.padding(contentPadding), + ) { item { - WarningBanner( - textRes = R.string.fdroid_warning, - modifier = Modifier.clickable { - uriHandler.openUri("https://tachiyomi.org/help/faq/#how-do-i-migrate-from-the-f-droid-version") + LogoHeader() + } + item { + SwitchPreferenceWidget( + title = stringResource(R.string.label_downloaded_only), + subtitle = stringResource(R.string.downloaded_only_summary), + icon = Icons.Outlined.CloudOff, + checked = downloadedOnly, + onCheckedChanged = onDownloadedOnlyChange, + ) + } + item { + SwitchPreferenceWidget( + title = stringResource(R.string.pref_incognito_mode), + subtitle = stringResource(R.string.pref_incognito_mode_summary), + icon = ImageVector.vectorResource(R.drawable.ic_glasses_24dp), + checked = incognitoMode, + onCheckedChanged = onIncognitoModeChange, + ) + } + + item { Divider() } + + item { + val downloadQueueState = downloadQueueStateProvider() + TextPreferenceWidget( + title = stringResource(R.string.label_download_queue), + subtitle = when (downloadQueueState) { + DownloadQueueState.Stopped -> null + is DownloadQueueState.Paused -> { + val pending = downloadQueueState.pending + if (pending == 0) { + stringResource(R.string.paused) + } else { + "${stringResource(R.string.paused)} • ${ + pluralStringResource( + id = R.plurals.download_queue_summary, + count = pending, + pending, + ) + }" + } + } + is DownloadQueueState.Downloading -> { + val pending = downloadQueueState.pending + pluralStringResource(id = R.plurals.download_queue_summary, count = pending, pending) + } }, + icon = Icons.Outlined.GetApp, + onPreferenceClick = onClickDownloadQueue, + ) + } + item { + TextPreferenceWidget( + title = stringResource(R.string.categories), + icon = Icons.Outlined.Label, + onPreferenceClick = onClickCategories, + ) + } + item { + TextPreferenceWidget( + title = stringResource(R.string.label_stats), + icon = Icons.Outlined.QueryStats, + onPreferenceClick = onClickStats, + ) + } + item { + TextPreferenceWidget( + title = stringResource(R.string.label_backup), + icon = Icons.Outlined.SettingsBackupRestore, + onPreferenceClick = onClickBackupAndRestore, + ) + } + + item { Divider() } + + item { + TextPreferenceWidget( + title = stringResource(R.string.label_settings), + icon = Icons.Outlined.Settings, + onPreferenceClick = onClickSettings, + ) + } + item { + TextPreferenceWidget( + title = stringResource(R.string.pref_category_about), + icon = Icons.Outlined.Info, + onPreferenceClick = onClickAbout, + ) + } + item { + TextPreferenceWidget( + title = stringResource(R.string.label_help), + icon = Icons.Outlined.HelpOutline, + onPreferenceClick = { uriHandler.openUri(Constants.URL_HELP) }, ) } } - - item { - LogoHeader() - } - - item { - AppStateBanners( - downloadedOnlyMode = downloadedOnly, - incognitoMode = incognitoMode, - ) - } - - item { - SwitchPreferenceWidget( - title = stringResource(R.string.label_downloaded_only), - subtitle = stringResource(R.string.downloaded_only_summary), - icon = Icons.Outlined.CloudOff, - checked = downloadedOnly, - onCheckedChanged = onDownloadedOnlyChange, - ) - } - item { - SwitchPreferenceWidget( - title = stringResource(R.string.pref_incognito_mode), - subtitle = stringResource(R.string.pref_incognito_mode_summary), - icon = ImageVector.vectorResource(R.drawable.ic_glasses_24dp), - checked = incognitoMode, - onCheckedChanged = onIncognitoModeChange, - ) - } - - item { Divider() } - - item { - val downloadQueueState = downloadQueueStateProvider() - TextPreferenceWidget( - title = stringResource(R.string.label_download_queue), - subtitle = when (downloadQueueState) { - DownloadQueueState.Stopped -> null - is DownloadQueueState.Paused -> { - val pending = downloadQueueState.pending - if (pending == 0) { - stringResource(R.string.paused) - } else { - "${stringResource(R.string.paused)} • ${ - pluralStringResource( - id = R.plurals.download_queue_summary, - count = pending, - pending, - ) - }" - } - } - is DownloadQueueState.Downloading -> { - val pending = downloadQueueState.pending - pluralStringResource(id = R.plurals.download_queue_summary, count = pending, pending) - } - }, - icon = Icons.Outlined.GetApp, - onPreferenceClick = onClickDownloadQueue, - ) - } - item { - TextPreferenceWidget( - title = stringResource(R.string.categories), - icon = Icons.Outlined.Label, - onPreferenceClick = onClickCategories, - ) - } - item { - TextPreferenceWidget( - title = stringResource(R.string.label_stats), - icon = Icons.Outlined.QueryStats, - onPreferenceClick = onClickStats, - ) - } - item { - TextPreferenceWidget( - title = stringResource(R.string.label_backup), - icon = Icons.Outlined.SettingsBackupRestore, - onPreferenceClick = onClickBackupAndRestore, - ) - } - - item { Divider() } - - item { - TextPreferenceWidget( - title = stringResource(R.string.label_settings), - icon = Icons.Outlined.Settings, - onPreferenceClick = onClickSettings, - ) - } - item { - TextPreferenceWidget( - title = stringResource(R.string.pref_category_about), - icon = Icons.Outlined.Info, - onPreferenceClick = onClickAbout, - ) - } - item { - TextPreferenceWidget( - title = stringResource(R.string.label_help), - icon = Icons.Outlined.HelpOutline, - onPreferenceClick = { uriHandler.openUri(Constants.URL_HELP) }, - ) - } } } diff --git a/app/src/main/java/eu/kanade/presentation/updates/UpdatesScreen.kt b/app/src/main/java/eu/kanade/presentation/updates/UpdatesScreen.kt index 8d9c6e09f..1d7d0f4c1 100644 --- a/app/src/main/java/eu/kanade/presentation/updates/UpdatesScreen.kt +++ b/app/src/main/java/eu/kanade/presentation/updates/UpdatesScreen.kt @@ -43,8 +43,6 @@ import kotlin.time.Duration.Companion.seconds fun UpdateScreen( state: UpdatesState, snackbarHostState: SnackbarHostState, - incognitoMode: Boolean, - downloadedOnlyMode: Boolean, lastUpdated: Long, relativeTime: Int, onClickCover: (UpdatesItem) -> Unit, @@ -65,8 +63,6 @@ fun UpdateScreen( Scaffold( topBar = { scrollBehavior -> UpdatesAppBar( - incognitoMode = incognitoMode, - downloadedOnlyMode = downloadedOnlyMode, onUpdateLibrary = { onUpdateLibrary() }, actionModeCounter = state.selected.size, onSelectAll = { onSelectAll(true) }, @@ -136,8 +132,6 @@ fun UpdateScreen( @Composable private fun UpdatesAppBar( modifier: Modifier = Modifier, - incognitoMode: Boolean, - downloadedOnlyMode: Boolean, onUpdateLibrary: () -> Unit, // For action mode actionModeCounter: Int, @@ -173,8 +167,6 @@ private fun UpdatesAppBar( ) } }, - downloadedOnlyMode = downloadedOnlyMode, - incognitoMode = incognitoMode, scrollBehavior = scrollBehavior, ) } diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/browse/BrowseTab.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/browse/BrowseTab.kt index 5c73f6d68..1883654f4 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/browse/BrowseTab.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/browse/BrowseTab.kt @@ -9,13 +9,9 @@ import androidx.compose.runtime.collectAsState import androidx.compose.runtime.getValue import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.res.stringResource -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.navigator.tab.LocalTabNavigator import cafe.adriel.voyager.navigator.tab.TabOptions -import eu.kanade.core.prefs.asState -import eu.kanade.domain.base.BasePreferences import eu.kanade.presentation.components.TabbedScreen import eu.kanade.presentation.util.Tab import eu.kanade.tachiyomi.R @@ -25,8 +21,6 @@ import eu.kanade.tachiyomi.ui.browse.migration.sources.migrateSourceTab import eu.kanade.tachiyomi.ui.browse.source.sourcesTab import eu.kanade.tachiyomi.ui.main.MainActivity import eu.kanade.tachiyomi.util.storage.DiskUtil -import uy.kohesive.injekt.Injekt -import uy.kohesive.injekt.api.get data class BrowseTab( private val toExtensions: Boolean = false, @@ -47,7 +41,6 @@ data class BrowseTab( @Composable override fun Content() { val context = LocalContext.current - val screenModel = rememberScreenModel { BrowseScreenModel() } // Hoisted for extensions tab's search bar val extensionsScreenModel = rememberScreenModel { ExtensionsScreenModel() } @@ -63,8 +56,6 @@ data class BrowseTab( startIndex = 1.takeIf { toExtensions }, searchQuery = extensionsQuery, onChangeSearchQuery = extensionsScreenModel::search, - incognitoMode = screenModel.isIncognitoMode, - downloadedOnlyMode = screenModel.isDownloadOnly, ) // For local source @@ -75,10 +66,3 @@ data class BrowseTab( } } } - -private class BrowseScreenModel( - preferences: BasePreferences = Injekt.get(), -) : ScreenModel { - val isDownloadOnly: Boolean by preferences.downloadedOnly().asState(coroutineScope) - val isIncognitoMode: Boolean by preferences.incognitoMode().asState(coroutineScope) -} diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/browse/BrowseSourceScreen.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/browse/BrowseSourceScreen.kt index fc6ae5ea0..ec1d9af2c 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/browse/BrowseSourceScreen.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/browse/BrowseSourceScreen.kt @@ -43,7 +43,6 @@ import eu.kanade.domain.source.interactor.GetRemoteManga import eu.kanade.presentation.browse.BrowseSourceContent import eu.kanade.presentation.browse.components.BrowseSourceToolbar import eu.kanade.presentation.browse.components.RemoveMangaDialog -import eu.kanade.presentation.components.AppStateBanners import eu.kanade.presentation.components.ChangeCategoryDialog import eu.kanade.presentation.components.Divider import eu.kanade.presentation.components.DuplicateMangaDialog @@ -167,8 +166,6 @@ data class BrowseSourceScreen( } Divider() - - AppStateBanners(screenModel.isDownloadOnly, screenModel.isIncognitoMode) } }, snackbarHost = { SnackbarHost(hostState = snackbarHostState) }, diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/browse/BrowseSourceScreenModel.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/browse/BrowseSourceScreenModel.kt index 86a97bfc8..5fddb309b 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/browse/BrowseSourceScreenModel.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/browse/BrowseSourceScreenModel.kt @@ -17,7 +17,6 @@ import eu.davidea.flexibleadapter.items.IFlexible import eu.kanade.core.prefs.CheckboxState import eu.kanade.core.prefs.asState import eu.kanade.core.prefs.mapAsCheckboxState -import eu.kanade.domain.base.BasePreferences import eu.kanade.domain.category.interactor.GetCategories import eu.kanade.domain.category.interactor.SetMangaCategories import eu.kanade.domain.category.model.Category @@ -82,7 +81,6 @@ class BrowseSourceScreenModel( private val sourceId: Long, searchQuery: String?, private val sourceManager: SourceManager = Injekt.get(), - preferences: BasePreferences = Injekt.get(), sourcePreferences: SourcePreferences = Injekt.get(), private val libraryPreferences: LibraryPreferences = Injekt.get(), private val coverCache: CoverCache = Injekt.get(), @@ -103,9 +101,6 @@ class BrowseSourceScreenModel( var displayMode by sourcePreferences.sourceDisplayMode().asState(coroutineScope) - val isDownloadOnly: Boolean by preferences.downloadedOnly().asState(coroutineScope) - val isIncognitoMode: Boolean by preferences.incognitoMode().asState(coroutineScope) - val source = sourceManager.get(sourceId) as CatalogueSource /** diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/history/HistoryScreenModel.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/history/HistoryScreenModel.kt index e549eed14..0a97d662c 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/history/HistoryScreenModel.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/history/HistoryScreenModel.kt @@ -1,12 +1,9 @@ package eu.kanade.tachiyomi.ui.history import androidx.compose.runtime.Immutable -import androidx.compose.runtime.getValue import cafe.adriel.voyager.core.model.StateScreenModel import cafe.adriel.voyager.core.model.coroutineScope -import eu.kanade.core.prefs.asState import eu.kanade.core.util.insertSeparators -import eu.kanade.domain.base.BasePreferences import eu.kanade.domain.chapter.model.Chapter import eu.kanade.domain.history.interactor.GetHistory import eu.kanade.domain.history.interactor.GetNextChapters @@ -37,15 +34,11 @@ class HistoryScreenModel( private val getHistory: GetHistory = Injekt.get(), private val getNextChapters: GetNextChapters = Injekt.get(), private val removeHistory: RemoveHistory = Injekt.get(), - preferences: BasePreferences = Injekt.get(), ) : StateScreenModel(HistoryState()) { private val _events: Channel = Channel(Channel.UNLIMITED) val events: Flow = _events.receiveAsFlow() - val isDownloadOnly: Boolean by preferences.downloadedOnly().asState(coroutineScope) - val isIncognitoMode: Boolean by preferences.incognitoMode().asState(coroutineScope) - init { coroutineScope.launch { state.map { it.searchQuery } diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/history/HistoryTab.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/history/HistoryTab.kt index 2685c60a3..f08d5dbd8 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/history/HistoryTab.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/history/HistoryTab.kt @@ -62,8 +62,6 @@ object HistoryTab : Tab { HistoryScreen( state = state, snackbarHostState = snackbarHostState, - incognitoMode = screenModel.isIncognitoMode, - downloadedOnlyMode = screenModel.isDownloadOnly, onSearchQueryChange = screenModel::updateSearchQuery, onClickCover = { navigator.push(MangaScreen(it)) }, onClickResume = screenModel::getNextChapterForManga, diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryScreenModel.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryScreenModel.kt index 27f2ccc3e..29ca0a6ff 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryScreenModel.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryScreenModel.kt @@ -89,9 +89,6 @@ class LibraryScreenModel( var activeCategoryIndex: Int by libraryPreferences.lastUsedCategory().asState(coroutineScope) - val isDownloadOnly: Boolean by preferences.downloadedOnly().asState(coroutineScope) - val isIncognitoMode: Boolean by preferences.incognitoMode().asState(coroutineScope) - init { coroutineScope.launchIO { combine( diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryTab.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryTab.kt index b7c37c9bb..b9860d842 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryTab.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryTab.kt @@ -112,8 +112,6 @@ object LibraryTab : Tab { hasActiveFilters = state.hasActiveFilters, selectedCount = state.selection.size, title = title, - incognitoMode = !tabVisible && screenModel.isIncognitoMode, - downloadedOnlyMode = !tabVisible && screenModel.isDownloadOnly, onClickUnselectAll = screenModel::clearSelection, onClickSelectAll = { screenModel.selectAll(screenModel.activeCategoryIndex) }, onClickInvertSelection = { screenModel.invertSelection(screenModel.activeCategoryIndex) }, @@ -197,10 +195,7 @@ object LibraryTab : Tab { getNumberOfMangaForCategory = { state.getMangaCountForCategory(it) }, getDisplayModeForPage = { state.categories[it].display }, getColumnsForOrientation = { screenModel.getColumnsPreferenceForCurrentOrientation(it) }, - getLibraryForPage = { state.getLibraryItemsByPage(it) }, - isDownloadOnly = screenModel.isDownloadOnly, - isIncognitoMode = screenModel.isIncognitoMode, - ) + ) { state.getLibraryItemsByPage(it) } } } } diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/main/MainActivity.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/main/MainActivity.kt index becb5507d..772c66b2d 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/main/MainActivity.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/main/MainActivity.kt @@ -10,6 +10,12 @@ import android.view.View import android.view.Window import android.widget.Toast import androidx.activity.compose.BackHandler +import androidx.compose.foundation.isSystemInDarkTheme +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.WindowInsets +import androidx.compose.foundation.layout.consumeWindowInsets +import androidx.compose.foundation.layout.statusBars import androidx.compose.material3.AlertDialog import androidx.compose.material3.Text import androidx.compose.material3.TextButton @@ -20,6 +26,7 @@ import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember import androidx.compose.runtime.rememberCoroutineScope import androidx.compose.runtime.setValue +import androidx.compose.ui.Modifier import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.res.stringResource import androidx.core.animation.doOnEnd @@ -36,12 +43,14 @@ import cafe.adriel.voyager.navigator.Navigator import cafe.adriel.voyager.navigator.NavigatorDisposeBehavior import cafe.adriel.voyager.navigator.currentOrThrow import cafe.adriel.voyager.transitions.ScreenTransition +import com.google.accompanist.systemuicontroller.rememberSystemUiController import com.google.android.material.transition.platform.MaterialContainerTransformSharedElementCallback import eu.kanade.domain.base.BasePreferences import eu.kanade.domain.category.model.Category import eu.kanade.domain.library.service.LibraryPreferences import eu.kanade.domain.source.service.SourcePreferences import eu.kanade.domain.ui.UiPreferences +import eu.kanade.presentation.components.AppStateBanners import eu.kanade.presentation.util.Transition import eu.kanade.presentation.util.collectAsState import eu.kanade.tachiyomi.BuildConfig @@ -142,47 +151,73 @@ class MainActivity : BaseActivity() { .launchIn(lifecycleScope) setComposeContent { - Navigator( - screen = HomeScreen, - disposeBehavior = NavigatorDisposeBehavior(disposeNestedNavigators = false, disposeSteps = true), - ) { navigator -> - if (navigator.size == 1) { - ConfirmExit() + val incognito by preferences.incognitoMode().collectAsState() + val download by preferences.downloadedOnly().collectAsState() + Column { + AppStateBanners( + downloadedOnlyMode = download, + incognitoMode = incognito, + ) + val systemUiController = rememberSystemUiController() + val active = incognito || download + val useDarkIcons = if (isSystemInDarkTheme()) active else !active + LaunchedEffect(systemUiController, useDarkIcons) { + systemUiController.setStatusBarColor( + color = androidx.compose.ui.graphics.Color.Transparent, + darkIcons = useDarkIcons, + ) } - LaunchedEffect(navigator) { - this@MainActivity.navigator = navigator - - if (savedInstanceState == null) { - // Set start screen - handleIntentAction(intent) - - // Reset Incognito Mode on relaunch - preferences.incognitoMode().set(false) + Navigator( + screen = HomeScreen, + disposeBehavior = NavigatorDisposeBehavior(disposeNestedNavigators = false, disposeSteps = true), + ) { navigator -> + if (navigator.size == 1) { + ConfirmExit() } - } - // Shows current screen - ScreenTransition(navigator = navigator, transition = { Transition.OneWayFade }) + LaunchedEffect(navigator) { + this@MainActivity.navigator = navigator - // Pop source-related screens when incognito mode is turned off - LaunchedEffect(Unit) { - preferences.incognitoMode().changes() - .drop(1) - .onEach { - if (!it) { - val currentScreen = navigator.lastItem - if (currentScreen is BrowseSourceScreen || - (currentScreen is MangaScreen && currentScreen.fromSource) - ) { - navigator.popUntilRoot() + if (savedInstanceState == null) { + // Set start screen + handleIntentAction(intent) + + // Reset Incognito Mode on relaunch + preferences.incognitoMode().set(false) + } + } + + // Consume insets already used by app state banners + val boxModifier = if (incognito || download) { + Modifier.consumeWindowInsets(WindowInsets.statusBars) + } else { + Modifier + } + Box(modifier = boxModifier) { + // Shows current screen + ScreenTransition(navigator = navigator, transition = { Transition.OneWayFade }) + } + + // Pop source-related screens when incognito mode is turned off + LaunchedEffect(Unit) { + preferences.incognitoMode().changes() + .drop(1) + .onEach { + if (!it) { + val currentScreen = navigator.lastItem + if (currentScreen is BrowseSourceScreen || + (currentScreen is MangaScreen && currentScreen.fromSource) + ) { + navigator.popUntilRoot() + } } } - } - .launchIn(this) - } + .launchIn(this) + } - CheckForUpdate() + CheckForUpdate() + } } var showChangelog by remember { mutableStateOf(didMigration && !BuildConfig.DEBUG) } diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/manga/MangaScreenModel.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/manga/MangaScreenModel.kt index 56f95419e..9ba65edbd 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/manga/MangaScreenModel.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/manga/MangaScreenModel.kt @@ -10,7 +10,6 @@ import eu.kanade.core.prefs.CheckboxState import eu.kanade.core.prefs.mapAsCheckboxState import eu.kanade.core.util.addOrRemove import eu.kanade.data.chapter.NoChaptersException -import eu.kanade.domain.base.BasePreferences import eu.kanade.domain.category.interactor.GetCategories import eu.kanade.domain.category.interactor.SetMangaCategories import eu.kanade.domain.category.model.Category @@ -53,7 +52,6 @@ import eu.kanade.tachiyomi.util.lang.launchNonCancellable import eu.kanade.tachiyomi.util.lang.toRelativeString import eu.kanade.tachiyomi.util.lang.withIOContext import eu.kanade.tachiyomi.util.lang.withUIContext -import eu.kanade.tachiyomi.util.preference.asHotFlow import eu.kanade.tachiyomi.util.removeCovers import eu.kanade.tachiyomi.util.shouldDownloadNewChapters import eu.kanade.tachiyomi.util.system.logcat @@ -64,7 +62,6 @@ import kotlinx.coroutines.flow.collectLatest import kotlinx.coroutines.flow.combine import kotlinx.coroutines.flow.distinctUntilChanged import kotlinx.coroutines.flow.filter -import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.map import kotlinx.coroutines.flow.update import kotlinx.coroutines.isActive @@ -81,7 +78,6 @@ class MangaInfoScreenModel( val context: Context, val mangaId: Long, private val isFromSource: Boolean, - basePreferences: BasePreferences = Injekt.get(), private val downloadPreferences: DownloadPreferences = Injekt.get(), private val libraryPreferences: LibraryPreferences = Injekt.get(), private val uiPreferences: UiPreferences = Injekt.get(), @@ -130,17 +126,6 @@ class MangaInfoScreenModel( mutableState.update { if (it is MangaScreenState.Success) func(it) else it } } - private var incognitoMode = false - set(value) { - updateSuccessState { it.copy(isIncognitoMode = value) } - field = value - } - private var downloadedOnlyMode = false - set(value) { - updateSuccessState { it.copy(isDownloadedOnlyMode = value) } - field = value - } - init { val toChapterItemsParams: List.(manga: Manga) -> List = { manga -> toChapterItems( @@ -189,8 +174,6 @@ class MangaInfoScreenModel( isFromSource = isFromSource, chapters = chapters, isRefreshingData = needRefreshInfo || needRefreshChapter, - isIncognitoMode = incognitoMode, - isDownloadedOnlyMode = downloadedOnlyMode, dialog = null, ) } @@ -210,14 +193,6 @@ class MangaInfoScreenModel( // Initial loading finished updateSuccessState { it.copy(isRefreshingData = false) } } - - basePreferences.incognitoMode() - .asHotFlow { incognitoMode = it } - .launchIn(coroutineScope) - - basePreferences.downloadedOnly() - .asHotFlow { downloadedOnlyMode = it } - .launchIn(coroutineScope) } fun fetchAllFromSource(manualFetch: Boolean = true) { @@ -1037,8 +1012,6 @@ sealed class MangaScreenState { val chapters: List, val trackItems: List = emptyList(), val isRefreshingData: Boolean = false, - val isIncognitoMode: Boolean = false, - val isDownloadedOnlyMode: Boolean = false, val dialog: MangaInfoScreenModel.Dialog? = null, ) : MangaScreenState() { diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/updates/UpdatesScreenModel.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/updates/UpdatesScreenModel.kt index c5de15e0f..b67f0dc53 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/updates/UpdatesScreenModel.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/updates/UpdatesScreenModel.kt @@ -11,7 +11,6 @@ import cafe.adriel.voyager.core.model.coroutineScope import eu.kanade.core.prefs.asState import eu.kanade.core.util.addOrRemove import eu.kanade.core.util.insertSeparators -import eu.kanade.domain.base.BasePreferences import eu.kanade.domain.chapter.interactor.GetChapter import eu.kanade.domain.chapter.interactor.SetReadStatus import eu.kanade.domain.chapter.interactor.UpdateChapter @@ -62,16 +61,12 @@ class UpdatesScreenModel( private val getChapter: GetChapter = Injekt.get(), private val libraryPreferences: LibraryPreferences = Injekt.get(), val snackbarHostState: SnackbarHostState = SnackbarHostState(), - basePreferences: BasePreferences = Injekt.get(), uiPreferences: UiPreferences = Injekt.get(), ) : StateScreenModel(UpdatesState()) { private val _events: Channel = Channel(Int.MAX_VALUE) val events: Flow = _events.receiveAsFlow() - val isDownloadOnly: Boolean by basePreferences.downloadedOnly().asState(coroutineScope) - val isIncognitoMode: Boolean by basePreferences.incognitoMode().asState(coroutineScope) - val lastUpdated by libraryPreferences.libraryUpdateLastTimestamp().asState(coroutineScope) val relativeTime: Int by uiPreferences.relativeTime().asState(coroutineScope) diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/updates/UpdatesTab.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/updates/UpdatesTab.kt index 3f0248891..78a44dd23 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/updates/UpdatesTab.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/updates/UpdatesTab.kt @@ -56,8 +56,6 @@ object UpdatesTab : Tab { UpdateScreen( state = state, snackbarHostState = screenModel.snackbarHostState, - incognitoMode = screenModel.isIncognitoMode, - downloadedOnlyMode = screenModel.isDownloadOnly, lastUpdated = screenModel.lastUpdated, relativeTime = screenModel.relativeTime, onClickCover = { item -> navigator.push(MangaScreen(item.update.mangaId)) }, diff --git a/gradle/compose.versions.toml b/gradle/compose.versions.toml index 631fee582..f4d3e6850 100644 --- a/gradle/compose.versions.toml +++ b/gradle/compose.versions.toml @@ -23,4 +23,5 @@ material-core = { module = "androidx.compose.material:material", version = "1.4. accompanist-webview = { module = "com.google.accompanist:accompanist-webview", version.ref = "accompanist" } accompanist-flowlayout = { module = "com.google.accompanist:accompanist-flowlayout", version.ref = "accompanist" } accompanist-permissions = { module = "com.google.accompanist:accompanist-permissions", version.ref = "accompanist" } -accompanist-themeadapter = { module = "com.google.accompanist:accompanist-themeadapter-material3", version.ref = "accompanist" } \ No newline at end of file +accompanist-themeadapter = { module = "com.google.accompanist:accompanist-themeadapter-material3", version.ref = "accompanist" } +accompanist-systemuicontroller = { module = "com.google.accompanist:accompanist-systemuicontroller", version.ref = "accompanist" }