Move app state banner to the very top (#8706)
This moves the banners to the root composable and so eliminates the need to track the app states in every screen.
This commit is contained in:
parent
a61e2799db
commit
d97eab0328
24 changed files with 217 additions and 295 deletions
|
@ -182,6 +182,7 @@ dependencies {
|
||||||
implementation(compose.accompanist.flowlayout)
|
implementation(compose.accompanist.flowlayout)
|
||||||
implementation(compose.accompanist.permissions)
|
implementation(compose.accompanist.permissions)
|
||||||
implementation(compose.accompanist.themeadapter)
|
implementation(compose.accompanist.themeadapter)
|
||||||
|
implementation(compose.accompanist.systemuicontroller)
|
||||||
|
|
||||||
implementation(androidx.paging.runtime)
|
implementation(androidx.paging.runtime)
|
||||||
implementation(androidx.paging.compose)
|
implementation(androidx.paging.compose)
|
||||||
|
|
|
@ -63,9 +63,6 @@ fun AppBar(
|
||||||
actionModeCounter: Int = 0,
|
actionModeCounter: Int = 0,
|
||||||
onCancelActionMode: () -> Unit = {},
|
onCancelActionMode: () -> Unit = {},
|
||||||
actionModeActions: @Composable RowScope.() -> Unit = {},
|
actionModeActions: @Composable RowScope.() -> Unit = {},
|
||||||
// Banners
|
|
||||||
downloadedOnlyMode: Boolean = false,
|
|
||||||
incognitoMode: Boolean = false,
|
|
||||||
|
|
||||||
scrollBehavior: TopAppBarScrollBehavior? = null,
|
scrollBehavior: TopAppBarScrollBehavior? = null,
|
||||||
) {
|
) {
|
||||||
|
@ -93,8 +90,6 @@ fun AppBar(
|
||||||
},
|
},
|
||||||
isActionMode = isActionMode,
|
isActionMode = isActionMode,
|
||||||
onCancelActionMode = onCancelActionMode,
|
onCancelActionMode = onCancelActionMode,
|
||||||
downloadedOnlyMode = downloadedOnlyMode,
|
|
||||||
incognitoMode = incognitoMode,
|
|
||||||
scrollBehavior = scrollBehavior,
|
scrollBehavior = scrollBehavior,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -112,9 +107,6 @@ fun AppBar(
|
||||||
// Action mode
|
// Action mode
|
||||||
isActionMode: Boolean = false,
|
isActionMode: Boolean = false,
|
||||||
onCancelActionMode: () -> Unit = {},
|
onCancelActionMode: () -> Unit = {},
|
||||||
// Banners
|
|
||||||
downloadedOnlyMode: Boolean = false,
|
|
||||||
incognitoMode: Boolean = false,
|
|
||||||
|
|
||||||
scrollBehavior: TopAppBarScrollBehavior? = null,
|
scrollBehavior: TopAppBarScrollBehavior? = null,
|
||||||
) {
|
) {
|
||||||
|
@ -150,8 +142,6 @@ fun AppBar(
|
||||||
),
|
),
|
||||||
scrollBehavior = scrollBehavior,
|
scrollBehavior = scrollBehavior,
|
||||||
)
|
)
|
||||||
|
|
||||||
AppStateBanners(downloadedOnlyMode, incognitoMode)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -236,8 +226,6 @@ fun SearchToolbar(
|
||||||
onSearch: (String) -> Unit = {},
|
onSearch: (String) -> Unit = {},
|
||||||
onClickCloseSearch: () -> Unit = { onChangeSearchQuery(null) },
|
onClickCloseSearch: () -> Unit = { onChangeSearchQuery(null) },
|
||||||
actions: @Composable RowScope.() -> Unit = {},
|
actions: @Composable RowScope.() -> Unit = {},
|
||||||
incognitoMode: Boolean = false,
|
|
||||||
downloadedOnlyMode: Boolean = false,
|
|
||||||
scrollBehavior: TopAppBarScrollBehavior? = null,
|
scrollBehavior: TopAppBarScrollBehavior? = null,
|
||||||
visualTransformation: VisualTransformation = VisualTransformation.None,
|
visualTransformation: VisualTransformation = VisualTransformation.None,
|
||||||
interactionSource: MutableInteractionSource = remember { MutableInteractionSource() },
|
interactionSource: MutableInteractionSource = remember { MutableInteractionSource() },
|
||||||
|
@ -326,8 +314,6 @@ fun SearchToolbar(
|
||||||
key("actions") { actions() }
|
key("actions") { actions() }
|
||||||
},
|
},
|
||||||
isActionMode = false,
|
isActionMode = false,
|
||||||
downloadedOnlyMode = downloadedOnlyMode,
|
|
||||||
incognitoMode = incognitoMode,
|
|
||||||
scrollBehavior = scrollBehavior,
|
scrollBehavior = scrollBehavior,
|
||||||
)
|
)
|
||||||
LaunchedEffect(searchClickCount) {
|
LaunchedEffect(searchClickCount) {
|
||||||
|
|
|
@ -3,8 +3,13 @@ package eu.kanade.presentation.components
|
||||||
import androidx.annotation.StringRes
|
import androidx.annotation.StringRes
|
||||||
import androidx.compose.foundation.background
|
import androidx.compose.foundation.background
|
||||||
import androidx.compose.foundation.layout.Column
|
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.fillMaxWidth
|
||||||
|
import androidx.compose.foundation.layout.only
|
||||||
import androidx.compose.foundation.layout.padding
|
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.MaterialTheme
|
||||||
import androidx.compose.material3.Text
|
import androidx.compose.material3.Text
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
|
@ -37,24 +42,34 @@ fun AppStateBanners(
|
||||||
incognitoMode: Boolean,
|
incognitoMode: Boolean,
|
||||||
modifier: Modifier = Modifier,
|
modifier: Modifier = Modifier,
|
||||||
) {
|
) {
|
||||||
|
val insets = WindowInsets.systemBars.only(WindowInsetsSides.Top + WindowInsetsSides.Horizontal)
|
||||||
Column(modifier = modifier) {
|
Column(modifier = modifier) {
|
||||||
if (downloadedOnlyMode) {
|
if (downloadedOnlyMode) {
|
||||||
DownloadedOnlyModeBanner()
|
DownloadedOnlyModeBanner(
|
||||||
|
modifier = Modifier.windowInsetsPadding(insets),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
if (incognitoMode) {
|
if (incognitoMode) {
|
||||||
IncognitoModeBanner()
|
IncognitoModeBanner(
|
||||||
|
modifier = if (!downloadedOnlyMode) {
|
||||||
|
Modifier.windowInsetsPadding(insets)
|
||||||
|
} else {
|
||||||
|
Modifier
|
||||||
|
},
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
private fun DownloadedOnlyModeBanner() {
|
private fun DownloadedOnlyModeBanner(modifier: Modifier = Modifier) {
|
||||||
Text(
|
Text(
|
||||||
text = stringResource(R.string.label_downloaded_only),
|
text = stringResource(R.string.label_downloaded_only),
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.background(color = MaterialTheme.colorScheme.tertiary)
|
.background(color = MaterialTheme.colorScheme.tertiary)
|
||||||
.fillMaxWidth()
|
.fillMaxWidth()
|
||||||
.padding(4.dp),
|
.padding(4.dp)
|
||||||
|
.then(modifier),
|
||||||
color = MaterialTheme.colorScheme.onTertiary,
|
color = MaterialTheme.colorScheme.onTertiary,
|
||||||
textAlign = TextAlign.Center,
|
textAlign = TextAlign.Center,
|
||||||
style = MaterialTheme.typography.labelMedium,
|
style = MaterialTheme.typography.labelMedium,
|
||||||
|
@ -62,13 +77,14 @@ private fun DownloadedOnlyModeBanner() {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
private fun IncognitoModeBanner() {
|
private fun IncognitoModeBanner(modifier: Modifier = Modifier) {
|
||||||
Text(
|
Text(
|
||||||
text = stringResource(R.string.pref_incognito_mode),
|
text = stringResource(R.string.pref_incognito_mode),
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.background(color = MaterialTheme.colorScheme.primary)
|
.background(color = MaterialTheme.colorScheme.primary)
|
||||||
.fillMaxWidth()
|
.fillMaxWidth()
|
||||||
.padding(4.dp),
|
.padding(4.dp)
|
||||||
|
.then(modifier),
|
||||||
color = MaterialTheme.colorScheme.onPrimary,
|
color = MaterialTheme.colorScheme.onPrimary,
|
||||||
textAlign = TextAlign.Center,
|
textAlign = TextAlign.Center,
|
||||||
style = MaterialTheme.typography.labelMedium,
|
style = MaterialTheme.typography.labelMedium,
|
||||||
|
|
|
@ -29,8 +29,6 @@ fun TabbedScreen(
|
||||||
startIndex: Int? = null,
|
startIndex: Int? = null,
|
||||||
searchQuery: String? = null,
|
searchQuery: String? = null,
|
||||||
onChangeSearchQuery: (String?) -> Unit = {},
|
onChangeSearchQuery: (String?) -> Unit = {},
|
||||||
incognitoMode: Boolean,
|
|
||||||
downloadedOnlyMode: Boolean,
|
|
||||||
) {
|
) {
|
||||||
val scope = rememberCoroutineScope()
|
val scope = rememberCoroutineScope()
|
||||||
val state = rememberPagerState()
|
val state = rememberPagerState()
|
||||||
|
@ -78,8 +76,6 @@ fun TabbedScreen(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
AppStateBanners(downloadedOnlyMode, incognitoMode)
|
|
||||||
|
|
||||||
HorizontalPager(
|
HorizontalPager(
|
||||||
count = tabs.size,
|
count = tabs.size,
|
||||||
modifier = Modifier.fillMaxSize(),
|
modifier = Modifier.fillMaxSize(),
|
||||||
|
|
|
@ -26,8 +26,6 @@ import java.util.Date
|
||||||
fun HistoryScreen(
|
fun HistoryScreen(
|
||||||
state: HistoryState,
|
state: HistoryState,
|
||||||
snackbarHostState: SnackbarHostState,
|
snackbarHostState: SnackbarHostState,
|
||||||
incognitoMode: Boolean,
|
|
||||||
downloadedOnlyMode: Boolean,
|
|
||||||
onSearchQueryChange: (String?) -> Unit,
|
onSearchQueryChange: (String?) -> Unit,
|
||||||
onClickCover: (mangaId: Long) -> Unit,
|
onClickCover: (mangaId: Long) -> Unit,
|
||||||
onClickResume: (mangaId: Long, chapterId: Long) -> Unit,
|
onClickResume: (mangaId: Long, chapterId: Long) -> Unit,
|
||||||
|
@ -47,8 +45,6 @@ fun HistoryScreen(
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
downloadedOnlyMode = downloadedOnlyMode,
|
|
||||||
incognitoMode = incognitoMode,
|
|
||||||
scrollBehavior = scrollBehavior,
|
scrollBehavior = scrollBehavior,
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
|
|
|
@ -45,8 +45,6 @@ fun LibraryContent(
|
||||||
getDisplayModeForPage: @Composable (Int) -> LibraryDisplayMode,
|
getDisplayModeForPage: @Composable (Int) -> LibraryDisplayMode,
|
||||||
getColumnsForOrientation: (Boolean) -> PreferenceMutableState<Int>,
|
getColumnsForOrientation: (Boolean) -> PreferenceMutableState<Int>,
|
||||||
getLibraryForPage: (Int) -> List<LibraryItem>,
|
getLibraryForPage: (Int) -> List<LibraryItem>,
|
||||||
isDownloadOnly: Boolean,
|
|
||||||
isIncognitoMode: Boolean,
|
|
||||||
) {
|
) {
|
||||||
Column(
|
Column(
|
||||||
modifier = Modifier.padding(
|
modifier = Modifier.padding(
|
||||||
|
@ -65,8 +63,6 @@ fun LibraryContent(
|
||||||
LibraryTabs(
|
LibraryTabs(
|
||||||
categories = categories,
|
categories = categories,
|
||||||
currentPageIndex = pagerState.currentPage,
|
currentPageIndex = pagerState.currentPage,
|
||||||
isDownloadOnly = isDownloadOnly,
|
|
||||||
isIncognitoMode = isIncognitoMode,
|
|
||||||
getNumberOfMangaForCategory = getNumberOfMangaForCategory,
|
getNumberOfMangaForCategory = getNumberOfMangaForCategory,
|
||||||
) { scope.launch { pagerState.animateScrollToPage(it) } }
|
) { scope.launch { pagerState.animateScrollToPage(it) } }
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,7 +8,6 @@ import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import eu.kanade.domain.category.model.Category
|
import eu.kanade.domain.category.model.Category
|
||||||
import eu.kanade.presentation.category.visualName
|
import eu.kanade.presentation.category.visualName
|
||||||
import eu.kanade.presentation.components.AppStateBanners
|
|
||||||
import eu.kanade.presentation.components.Divider
|
import eu.kanade.presentation.components.Divider
|
||||||
import eu.kanade.presentation.components.TabIndicator
|
import eu.kanade.presentation.components.TabIndicator
|
||||||
import eu.kanade.presentation.components.TabText
|
import eu.kanade.presentation.components.TabText
|
||||||
|
@ -17,8 +16,6 @@ import eu.kanade.presentation.components.TabText
|
||||||
fun LibraryTabs(
|
fun LibraryTabs(
|
||||||
categories: List<Category>,
|
categories: List<Category>,
|
||||||
currentPageIndex: Int,
|
currentPageIndex: Int,
|
||||||
isDownloadOnly: Boolean,
|
|
||||||
isIncognitoMode: Boolean,
|
|
||||||
getNumberOfMangaForCategory: (Category) -> Int?,
|
getNumberOfMangaForCategory: (Category) -> Int?,
|
||||||
onTabItemClick: (Int) -> Unit,
|
onTabItemClick: (Int) -> Unit,
|
||||||
) {
|
) {
|
||||||
|
@ -47,7 +44,5 @@ fun LibraryTabs(
|
||||||
}
|
}
|
||||||
|
|
||||||
Divider()
|
Divider()
|
||||||
|
|
||||||
AppStateBanners(isDownloadOnly, isIncognitoMode)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -32,8 +32,6 @@ fun LibraryToolbar(
|
||||||
hasActiveFilters: Boolean,
|
hasActiveFilters: Boolean,
|
||||||
selectedCount: Int,
|
selectedCount: Int,
|
||||||
title: LibraryToolbarTitle,
|
title: LibraryToolbarTitle,
|
||||||
incognitoMode: Boolean,
|
|
||||||
downloadedOnlyMode: Boolean,
|
|
||||||
onClickUnselectAll: () -> Unit,
|
onClickUnselectAll: () -> Unit,
|
||||||
onClickSelectAll: () -> Unit,
|
onClickSelectAll: () -> Unit,
|
||||||
onClickInvertSelection: () -> Unit,
|
onClickInvertSelection: () -> Unit,
|
||||||
|
@ -46,8 +44,6 @@ fun LibraryToolbar(
|
||||||
) = when {
|
) = when {
|
||||||
selectedCount > 0 -> LibrarySelectionToolbar(
|
selectedCount > 0 -> LibrarySelectionToolbar(
|
||||||
selectedCount = selectedCount,
|
selectedCount = selectedCount,
|
||||||
incognitoMode = incognitoMode,
|
|
||||||
downloadedOnlyMode = downloadedOnlyMode,
|
|
||||||
onClickUnselectAll = onClickUnselectAll,
|
onClickUnselectAll = onClickUnselectAll,
|
||||||
onClickSelectAll = onClickSelectAll,
|
onClickSelectAll = onClickSelectAll,
|
||||||
onClickInvertSelection = onClickInvertSelection,
|
onClickInvertSelection = onClickInvertSelection,
|
||||||
|
@ -55,8 +51,6 @@ fun LibraryToolbar(
|
||||||
else -> LibraryRegularToolbar(
|
else -> LibraryRegularToolbar(
|
||||||
title = title,
|
title = title,
|
||||||
hasFilters = hasActiveFilters,
|
hasFilters = hasActiveFilters,
|
||||||
incognitoMode = incognitoMode,
|
|
||||||
downloadedOnlyMode = downloadedOnlyMode,
|
|
||||||
searchQuery = searchQuery,
|
searchQuery = searchQuery,
|
||||||
onSearchQueryChange = onSearchQueryChange,
|
onSearchQueryChange = onSearchQueryChange,
|
||||||
onClickFilter = onClickFilter,
|
onClickFilter = onClickFilter,
|
||||||
|
@ -70,8 +64,6 @@ fun LibraryToolbar(
|
||||||
fun LibraryRegularToolbar(
|
fun LibraryRegularToolbar(
|
||||||
title: LibraryToolbarTitle,
|
title: LibraryToolbarTitle,
|
||||||
hasFilters: Boolean,
|
hasFilters: Boolean,
|
||||||
incognitoMode: Boolean,
|
|
||||||
downloadedOnlyMode: Boolean,
|
|
||||||
searchQuery: String?,
|
searchQuery: String?,
|
||||||
onSearchQueryChange: (String?) -> Unit,
|
onSearchQueryChange: (String?) -> Unit,
|
||||||
onClickFilter: () -> Unit,
|
onClickFilter: () -> Unit,
|
||||||
|
@ -123,8 +115,6 @@ fun LibraryRegularToolbar(
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
incognitoMode = incognitoMode,
|
|
||||||
downloadedOnlyMode = downloadedOnlyMode,
|
|
||||||
scrollBehavior = scrollBehavior,
|
scrollBehavior = scrollBehavior,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -132,8 +122,6 @@ fun LibraryRegularToolbar(
|
||||||
@Composable
|
@Composable
|
||||||
fun LibrarySelectionToolbar(
|
fun LibrarySelectionToolbar(
|
||||||
selectedCount: Int,
|
selectedCount: Int,
|
||||||
incognitoMode: Boolean,
|
|
||||||
downloadedOnlyMode: Boolean,
|
|
||||||
onClickUnselectAll: () -> Unit,
|
onClickUnselectAll: () -> Unit,
|
||||||
onClickSelectAll: () -> Unit,
|
onClickSelectAll: () -> Unit,
|
||||||
onClickInvertSelection: () -> Unit,
|
onClickInvertSelection: () -> Unit,
|
||||||
|
@ -150,8 +138,6 @@ fun LibrarySelectionToolbar(
|
||||||
},
|
},
|
||||||
isActionMode = true,
|
isActionMode = true,
|
||||||
onCancelActionMode = onClickUnselectAll,
|
onCancelActionMode = onClickUnselectAll,
|
||||||
incognitoMode = incognitoMode,
|
|
||||||
downloadedOnlyMode = downloadedOnlyMode,
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -238,8 +238,6 @@ private fun MangaScreenSmallImpl(
|
||||||
titleAlphaProvider = { animatedTitleAlpha },
|
titleAlphaProvider = { animatedTitleAlpha },
|
||||||
backgroundAlphaProvider = { animatedBgAlpha },
|
backgroundAlphaProvider = { animatedBgAlpha },
|
||||||
hasFilters = state.manga.chaptersFiltered(),
|
hasFilters = state.manga.chaptersFiltered(),
|
||||||
incognitoMode = state.isIncognitoMode,
|
|
||||||
downloadedOnlyMode = state.isDownloadedOnlyMode,
|
|
||||||
onBackClicked = internalOnBackPressed,
|
onBackClicked = internalOnBackPressed,
|
||||||
onClickFilter = onFilterClicked,
|
onClickFilter = onFilterClicked,
|
||||||
onClickShare = onShareClicked,
|
onClickShare = onShareClicked,
|
||||||
|
@ -450,8 +448,6 @@ fun MangaScreenLargeImpl(
|
||||||
titleAlphaProvider = { if (chapters.fastAny { it.selected }) 1f else 0f },
|
titleAlphaProvider = { if (chapters.fastAny { it.selected }) 1f else 0f },
|
||||||
backgroundAlphaProvider = { 1f },
|
backgroundAlphaProvider = { 1f },
|
||||||
hasFilters = state.manga.chaptersFiltered(),
|
hasFilters = state.manga.chaptersFiltered(),
|
||||||
incognitoMode = state.isIncognitoMode,
|
|
||||||
downloadedOnlyMode = state.isDownloadedOnlyMode,
|
|
||||||
onBackClicked = internalOnBackPressed,
|
onBackClicked = internalOnBackPressed,
|
||||||
onClickFilter = onFilterButtonClicked,
|
onClickFilter = onFilterButtonClicked,
|
||||||
onClickShare = onShareClicked,
|
onClickShare = onShareClicked,
|
||||||
|
|
|
@ -26,7 +26,6 @@ import androidx.compose.ui.draw.alpha
|
||||||
import androidx.compose.ui.res.stringResource
|
import androidx.compose.ui.res.stringResource
|
||||||
import androidx.compose.ui.text.style.TextOverflow
|
import androidx.compose.ui.text.style.TextOverflow
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import eu.kanade.presentation.components.AppStateBanners
|
|
||||||
import eu.kanade.presentation.components.DownloadDropdownMenu
|
import eu.kanade.presentation.components.DownloadDropdownMenu
|
||||||
import eu.kanade.presentation.components.OverflowMenu
|
import eu.kanade.presentation.components.OverflowMenu
|
||||||
import eu.kanade.presentation.manga.DownloadAction
|
import eu.kanade.presentation.manga.DownloadAction
|
||||||
|
@ -40,8 +39,6 @@ fun MangaToolbar(
|
||||||
titleAlphaProvider: () -> Float,
|
titleAlphaProvider: () -> Float,
|
||||||
backgroundAlphaProvider: () -> Float = titleAlphaProvider,
|
backgroundAlphaProvider: () -> Float = titleAlphaProvider,
|
||||||
hasFilters: Boolean,
|
hasFilters: Boolean,
|
||||||
incognitoMode: Boolean,
|
|
||||||
downloadedOnlyMode: Boolean,
|
|
||||||
onBackClicked: () -> Unit,
|
onBackClicked: () -> Unit,
|
||||||
onClickFilter: () -> Unit,
|
onClickFilter: () -> Unit,
|
||||||
onClickShare: (() -> Unit)?,
|
onClickShare: (() -> Unit)?,
|
||||||
|
@ -151,7 +148,5 @@ fun MangaToolbar(
|
||||||
.copy(alpha = if (isActionMode) 1f else backgroundAlphaProvider()),
|
.copy(alpha = if (isActionMode) 1f else backgroundAlphaProvider()),
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
|
||||||
AppStateBanners(downloadedOnlyMode, incognitoMode)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,13 @@
|
||||||
package eu.kanade.presentation.more
|
package eu.kanade.presentation.more
|
||||||
|
|
||||||
import androidx.compose.foundation.clickable
|
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.Icons
|
||||||
import androidx.compose.material.icons.outlined.CloudOff
|
import androidx.compose.material.icons.outlined.CloudOff
|
||||||
import androidx.compose.material.icons.outlined.GetApp
|
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.pluralStringResource
|
||||||
import androidx.compose.ui.res.stringResource
|
import androidx.compose.ui.res.stringResource
|
||||||
import androidx.compose.ui.res.vectorResource
|
import androidx.compose.ui.res.vectorResource
|
||||||
import eu.kanade.presentation.components.AppStateBanners
|
|
||||||
import eu.kanade.presentation.components.Divider
|
import eu.kanade.presentation.components.Divider
|
||||||
|
import eu.kanade.presentation.components.Scaffold
|
||||||
import eu.kanade.presentation.components.ScrollbarLazyColumn
|
import eu.kanade.presentation.components.ScrollbarLazyColumn
|
||||||
import eu.kanade.presentation.components.WarningBanner
|
import eu.kanade.presentation.components.WarningBanner
|
||||||
import eu.kanade.presentation.more.settings.widget.SwitchPreferenceWidget
|
import eu.kanade.presentation.more.settings.widget.SwitchPreferenceWidget
|
||||||
|
@ -45,125 +51,125 @@ fun MoreScreen(
|
||||||
) {
|
) {
|
||||||
val uriHandler = LocalUriHandler.current
|
val uriHandler = LocalUriHandler.current
|
||||||
|
|
||||||
ScrollbarLazyColumn(
|
Scaffold(
|
||||||
modifier = Modifier.systemBarsPadding(),
|
topBar = {
|
||||||
) {
|
Column(
|
||||||
if (isFDroid) {
|
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 {
|
item {
|
||||||
WarningBanner(
|
LogoHeader()
|
||||||
textRes = R.string.fdroid_warning,
|
}
|
||||||
modifier = Modifier.clickable {
|
item {
|
||||||
uriHandler.openUri("https://tachiyomi.org/help/faq/#how-do-i-migrate-from-the-f-droid-version")
|
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) },
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -43,8 +43,6 @@ import kotlin.time.Duration.Companion.seconds
|
||||||
fun UpdateScreen(
|
fun UpdateScreen(
|
||||||
state: UpdatesState,
|
state: UpdatesState,
|
||||||
snackbarHostState: SnackbarHostState,
|
snackbarHostState: SnackbarHostState,
|
||||||
incognitoMode: Boolean,
|
|
||||||
downloadedOnlyMode: Boolean,
|
|
||||||
lastUpdated: Long,
|
lastUpdated: Long,
|
||||||
relativeTime: Int,
|
relativeTime: Int,
|
||||||
onClickCover: (UpdatesItem) -> Unit,
|
onClickCover: (UpdatesItem) -> Unit,
|
||||||
|
@ -65,8 +63,6 @@ fun UpdateScreen(
|
||||||
Scaffold(
|
Scaffold(
|
||||||
topBar = { scrollBehavior ->
|
topBar = { scrollBehavior ->
|
||||||
UpdatesAppBar(
|
UpdatesAppBar(
|
||||||
incognitoMode = incognitoMode,
|
|
||||||
downloadedOnlyMode = downloadedOnlyMode,
|
|
||||||
onUpdateLibrary = { onUpdateLibrary() },
|
onUpdateLibrary = { onUpdateLibrary() },
|
||||||
actionModeCounter = state.selected.size,
|
actionModeCounter = state.selected.size,
|
||||||
onSelectAll = { onSelectAll(true) },
|
onSelectAll = { onSelectAll(true) },
|
||||||
|
@ -136,8 +132,6 @@ fun UpdateScreen(
|
||||||
@Composable
|
@Composable
|
||||||
private fun UpdatesAppBar(
|
private fun UpdatesAppBar(
|
||||||
modifier: Modifier = Modifier,
|
modifier: Modifier = Modifier,
|
||||||
incognitoMode: Boolean,
|
|
||||||
downloadedOnlyMode: Boolean,
|
|
||||||
onUpdateLibrary: () -> Unit,
|
onUpdateLibrary: () -> Unit,
|
||||||
// For action mode
|
// For action mode
|
||||||
actionModeCounter: Int,
|
actionModeCounter: Int,
|
||||||
|
@ -173,8 +167,6 @@ private fun UpdatesAppBar(
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
downloadedOnlyMode = downloadedOnlyMode,
|
|
||||||
incognitoMode = incognitoMode,
|
|
||||||
scrollBehavior = scrollBehavior,
|
scrollBehavior = scrollBehavior,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,13 +9,9 @@ import androidx.compose.runtime.collectAsState
|
||||||
import androidx.compose.runtime.getValue
|
import androidx.compose.runtime.getValue
|
||||||
import androidx.compose.ui.platform.LocalContext
|
import androidx.compose.ui.platform.LocalContext
|
||||||
import androidx.compose.ui.res.stringResource
|
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.core.model.rememberScreenModel
|
||||||
import cafe.adriel.voyager.navigator.tab.LocalTabNavigator
|
import cafe.adriel.voyager.navigator.tab.LocalTabNavigator
|
||||||
import cafe.adriel.voyager.navigator.tab.TabOptions
|
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.components.TabbedScreen
|
||||||
import eu.kanade.presentation.util.Tab
|
import eu.kanade.presentation.util.Tab
|
||||||
import eu.kanade.tachiyomi.R
|
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.browse.source.sourcesTab
|
||||||
import eu.kanade.tachiyomi.ui.main.MainActivity
|
import eu.kanade.tachiyomi.ui.main.MainActivity
|
||||||
import eu.kanade.tachiyomi.util.storage.DiskUtil
|
import eu.kanade.tachiyomi.util.storage.DiskUtil
|
||||||
import uy.kohesive.injekt.Injekt
|
|
||||||
import uy.kohesive.injekt.api.get
|
|
||||||
|
|
||||||
data class BrowseTab(
|
data class BrowseTab(
|
||||||
private val toExtensions: Boolean = false,
|
private val toExtensions: Boolean = false,
|
||||||
|
@ -47,7 +41,6 @@ data class BrowseTab(
|
||||||
@Composable
|
@Composable
|
||||||
override fun Content() {
|
override fun Content() {
|
||||||
val context = LocalContext.current
|
val context = LocalContext.current
|
||||||
val screenModel = rememberScreenModel { BrowseScreenModel() }
|
|
||||||
|
|
||||||
// Hoisted for extensions tab's search bar
|
// Hoisted for extensions tab's search bar
|
||||||
val extensionsScreenModel = rememberScreenModel { ExtensionsScreenModel() }
|
val extensionsScreenModel = rememberScreenModel { ExtensionsScreenModel() }
|
||||||
|
@ -63,8 +56,6 @@ data class BrowseTab(
|
||||||
startIndex = 1.takeIf { toExtensions },
|
startIndex = 1.takeIf { toExtensions },
|
||||||
searchQuery = extensionsQuery,
|
searchQuery = extensionsQuery,
|
||||||
onChangeSearchQuery = extensionsScreenModel::search,
|
onChangeSearchQuery = extensionsScreenModel::search,
|
||||||
incognitoMode = screenModel.isIncognitoMode,
|
|
||||||
downloadedOnlyMode = screenModel.isDownloadOnly,
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// For local source
|
// 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)
|
|
||||||
}
|
|
||||||
|
|
|
@ -43,7 +43,6 @@ import eu.kanade.domain.source.interactor.GetRemoteManga
|
||||||
import eu.kanade.presentation.browse.BrowseSourceContent
|
import eu.kanade.presentation.browse.BrowseSourceContent
|
||||||
import eu.kanade.presentation.browse.components.BrowseSourceToolbar
|
import eu.kanade.presentation.browse.components.BrowseSourceToolbar
|
||||||
import eu.kanade.presentation.browse.components.RemoveMangaDialog
|
import eu.kanade.presentation.browse.components.RemoveMangaDialog
|
||||||
import eu.kanade.presentation.components.AppStateBanners
|
|
||||||
import eu.kanade.presentation.components.ChangeCategoryDialog
|
import eu.kanade.presentation.components.ChangeCategoryDialog
|
||||||
import eu.kanade.presentation.components.Divider
|
import eu.kanade.presentation.components.Divider
|
||||||
import eu.kanade.presentation.components.DuplicateMangaDialog
|
import eu.kanade.presentation.components.DuplicateMangaDialog
|
||||||
|
@ -167,8 +166,6 @@ data class BrowseSourceScreen(
|
||||||
}
|
}
|
||||||
|
|
||||||
Divider()
|
Divider()
|
||||||
|
|
||||||
AppStateBanners(screenModel.isDownloadOnly, screenModel.isIncognitoMode)
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
snackbarHost = { SnackbarHost(hostState = snackbarHostState) },
|
snackbarHost = { SnackbarHost(hostState = snackbarHostState) },
|
||||||
|
|
|
@ -17,7 +17,6 @@ import eu.davidea.flexibleadapter.items.IFlexible
|
||||||
import eu.kanade.core.prefs.CheckboxState
|
import eu.kanade.core.prefs.CheckboxState
|
||||||
import eu.kanade.core.prefs.asState
|
import eu.kanade.core.prefs.asState
|
||||||
import eu.kanade.core.prefs.mapAsCheckboxState
|
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.GetCategories
|
||||||
import eu.kanade.domain.category.interactor.SetMangaCategories
|
import eu.kanade.domain.category.interactor.SetMangaCategories
|
||||||
import eu.kanade.domain.category.model.Category
|
import eu.kanade.domain.category.model.Category
|
||||||
|
@ -82,7 +81,6 @@ class BrowseSourceScreenModel(
|
||||||
private val sourceId: Long,
|
private val sourceId: Long,
|
||||||
searchQuery: String?,
|
searchQuery: String?,
|
||||||
private val sourceManager: SourceManager = Injekt.get(),
|
private val sourceManager: SourceManager = Injekt.get(),
|
||||||
preferences: BasePreferences = Injekt.get(),
|
|
||||||
sourcePreferences: SourcePreferences = Injekt.get(),
|
sourcePreferences: SourcePreferences = Injekt.get(),
|
||||||
private val libraryPreferences: LibraryPreferences = Injekt.get(),
|
private val libraryPreferences: LibraryPreferences = Injekt.get(),
|
||||||
private val coverCache: CoverCache = Injekt.get(),
|
private val coverCache: CoverCache = Injekt.get(),
|
||||||
|
@ -103,9 +101,6 @@ class BrowseSourceScreenModel(
|
||||||
|
|
||||||
var displayMode by sourcePreferences.sourceDisplayMode().asState(coroutineScope)
|
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
|
val source = sourceManager.get(sourceId) as CatalogueSource
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -1,12 +1,9 @@
|
||||||
package eu.kanade.tachiyomi.ui.history
|
package eu.kanade.tachiyomi.ui.history
|
||||||
|
|
||||||
import androidx.compose.runtime.Immutable
|
import androidx.compose.runtime.Immutable
|
||||||
import androidx.compose.runtime.getValue
|
|
||||||
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.core.prefs.asState
|
|
||||||
import eu.kanade.core.util.insertSeparators
|
import eu.kanade.core.util.insertSeparators
|
||||||
import eu.kanade.domain.base.BasePreferences
|
|
||||||
import eu.kanade.domain.chapter.model.Chapter
|
import eu.kanade.domain.chapter.model.Chapter
|
||||||
import eu.kanade.domain.history.interactor.GetHistory
|
import eu.kanade.domain.history.interactor.GetHistory
|
||||||
import eu.kanade.domain.history.interactor.GetNextChapters
|
import eu.kanade.domain.history.interactor.GetNextChapters
|
||||||
|
@ -37,15 +34,11 @@ class HistoryScreenModel(
|
||||||
private val getHistory: GetHistory = Injekt.get(),
|
private val getHistory: GetHistory = Injekt.get(),
|
||||||
private val getNextChapters: GetNextChapters = Injekt.get(),
|
private val getNextChapters: GetNextChapters = Injekt.get(),
|
||||||
private val removeHistory: RemoveHistory = Injekt.get(),
|
private val removeHistory: RemoveHistory = Injekt.get(),
|
||||||
preferences: BasePreferences = Injekt.get(),
|
|
||||||
) : StateScreenModel<HistoryState>(HistoryState()) {
|
) : StateScreenModel<HistoryState>(HistoryState()) {
|
||||||
|
|
||||||
private val _events: Channel<Event> = Channel(Channel.UNLIMITED)
|
private val _events: Channel<Event> = Channel(Channel.UNLIMITED)
|
||||||
val events: Flow<Event> = _events.receiveAsFlow()
|
val events: Flow<Event> = _events.receiveAsFlow()
|
||||||
|
|
||||||
val isDownloadOnly: Boolean by preferences.downloadedOnly().asState(coroutineScope)
|
|
||||||
val isIncognitoMode: Boolean by preferences.incognitoMode().asState(coroutineScope)
|
|
||||||
|
|
||||||
init {
|
init {
|
||||||
coroutineScope.launch {
|
coroutineScope.launch {
|
||||||
state.map { it.searchQuery }
|
state.map { it.searchQuery }
|
||||||
|
|
|
@ -62,8 +62,6 @@ object HistoryTab : Tab {
|
||||||
HistoryScreen(
|
HistoryScreen(
|
||||||
state = state,
|
state = state,
|
||||||
snackbarHostState = snackbarHostState,
|
snackbarHostState = snackbarHostState,
|
||||||
incognitoMode = screenModel.isIncognitoMode,
|
|
||||||
downloadedOnlyMode = screenModel.isDownloadOnly,
|
|
||||||
onSearchQueryChange = screenModel::updateSearchQuery,
|
onSearchQueryChange = screenModel::updateSearchQuery,
|
||||||
onClickCover = { navigator.push(MangaScreen(it)) },
|
onClickCover = { navigator.push(MangaScreen(it)) },
|
||||||
onClickResume = screenModel::getNextChapterForManga,
|
onClickResume = screenModel::getNextChapterForManga,
|
||||||
|
|
|
@ -89,9 +89,6 @@ class LibraryScreenModel(
|
||||||
|
|
||||||
var activeCategoryIndex: Int by libraryPreferences.lastUsedCategory().asState(coroutineScope)
|
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 {
|
init {
|
||||||
coroutineScope.launchIO {
|
coroutineScope.launchIO {
|
||||||
combine(
|
combine(
|
||||||
|
|
|
@ -112,8 +112,6 @@ object LibraryTab : Tab {
|
||||||
hasActiveFilters = state.hasActiveFilters,
|
hasActiveFilters = state.hasActiveFilters,
|
||||||
selectedCount = state.selection.size,
|
selectedCount = state.selection.size,
|
||||||
title = title,
|
title = title,
|
||||||
incognitoMode = !tabVisible && screenModel.isIncognitoMode,
|
|
||||||
downloadedOnlyMode = !tabVisible && screenModel.isDownloadOnly,
|
|
||||||
onClickUnselectAll = screenModel::clearSelection,
|
onClickUnselectAll = screenModel::clearSelection,
|
||||||
onClickSelectAll = { screenModel.selectAll(screenModel.activeCategoryIndex) },
|
onClickSelectAll = { screenModel.selectAll(screenModel.activeCategoryIndex) },
|
||||||
onClickInvertSelection = { screenModel.invertSelection(screenModel.activeCategoryIndex) },
|
onClickInvertSelection = { screenModel.invertSelection(screenModel.activeCategoryIndex) },
|
||||||
|
@ -197,10 +195,7 @@ object LibraryTab : Tab {
|
||||||
getNumberOfMangaForCategory = { state.getMangaCountForCategory(it) },
|
getNumberOfMangaForCategory = { state.getMangaCountForCategory(it) },
|
||||||
getDisplayModeForPage = { state.categories[it].display },
|
getDisplayModeForPage = { state.categories[it].display },
|
||||||
getColumnsForOrientation = { screenModel.getColumnsPreferenceForCurrentOrientation(it) },
|
getColumnsForOrientation = { screenModel.getColumnsPreferenceForCurrentOrientation(it) },
|
||||||
getLibraryForPage = { state.getLibraryItemsByPage(it) },
|
) { state.getLibraryItemsByPage(it) }
|
||||||
isDownloadOnly = screenModel.isDownloadOnly,
|
|
||||||
isIncognitoMode = screenModel.isIncognitoMode,
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,6 +10,12 @@ import android.view.View
|
||||||
import android.view.Window
|
import android.view.Window
|
||||||
import android.widget.Toast
|
import android.widget.Toast
|
||||||
import androidx.activity.compose.BackHandler
|
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.AlertDialog
|
||||||
import androidx.compose.material3.Text
|
import androidx.compose.material3.Text
|
||||||
import androidx.compose.material3.TextButton
|
import androidx.compose.material3.TextButton
|
||||||
|
@ -20,6 +26,7 @@ import androidx.compose.runtime.mutableStateOf
|
||||||
import androidx.compose.runtime.remember
|
import androidx.compose.runtime.remember
|
||||||
import androidx.compose.runtime.rememberCoroutineScope
|
import androidx.compose.runtime.rememberCoroutineScope
|
||||||
import androidx.compose.runtime.setValue
|
import androidx.compose.runtime.setValue
|
||||||
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.platform.LocalContext
|
import androidx.compose.ui.platform.LocalContext
|
||||||
import androidx.compose.ui.res.stringResource
|
import androidx.compose.ui.res.stringResource
|
||||||
import androidx.core.animation.doOnEnd
|
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.NavigatorDisposeBehavior
|
||||||
import cafe.adriel.voyager.navigator.currentOrThrow
|
import cafe.adriel.voyager.navigator.currentOrThrow
|
||||||
import cafe.adriel.voyager.transitions.ScreenTransition
|
import cafe.adriel.voyager.transitions.ScreenTransition
|
||||||
|
import com.google.accompanist.systemuicontroller.rememberSystemUiController
|
||||||
import com.google.android.material.transition.platform.MaterialContainerTransformSharedElementCallback
|
import com.google.android.material.transition.platform.MaterialContainerTransformSharedElementCallback
|
||||||
import eu.kanade.domain.base.BasePreferences
|
import eu.kanade.domain.base.BasePreferences
|
||||||
import eu.kanade.domain.category.model.Category
|
import eu.kanade.domain.category.model.Category
|
||||||
import eu.kanade.domain.library.service.LibraryPreferences
|
import eu.kanade.domain.library.service.LibraryPreferences
|
||||||
import eu.kanade.domain.source.service.SourcePreferences
|
import eu.kanade.domain.source.service.SourcePreferences
|
||||||
import eu.kanade.domain.ui.UiPreferences
|
import eu.kanade.domain.ui.UiPreferences
|
||||||
|
import eu.kanade.presentation.components.AppStateBanners
|
||||||
import eu.kanade.presentation.util.Transition
|
import eu.kanade.presentation.util.Transition
|
||||||
import eu.kanade.presentation.util.collectAsState
|
import eu.kanade.presentation.util.collectAsState
|
||||||
import eu.kanade.tachiyomi.BuildConfig
|
import eu.kanade.tachiyomi.BuildConfig
|
||||||
|
@ -142,47 +151,73 @@ class MainActivity : BaseActivity() {
|
||||||
.launchIn(lifecycleScope)
|
.launchIn(lifecycleScope)
|
||||||
|
|
||||||
setComposeContent {
|
setComposeContent {
|
||||||
Navigator(
|
val incognito by preferences.incognitoMode().collectAsState()
|
||||||
screen = HomeScreen,
|
val download by preferences.downloadedOnly().collectAsState()
|
||||||
disposeBehavior = NavigatorDisposeBehavior(disposeNestedNavigators = false, disposeSteps = true),
|
Column {
|
||||||
) { navigator ->
|
AppStateBanners(
|
||||||
if (navigator.size == 1) {
|
downloadedOnlyMode = download,
|
||||||
ConfirmExit()
|
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) {
|
Navigator(
|
||||||
this@MainActivity.navigator = navigator
|
screen = HomeScreen,
|
||||||
|
disposeBehavior = NavigatorDisposeBehavior(disposeNestedNavigators = false, disposeSteps = true),
|
||||||
if (savedInstanceState == null) {
|
) { navigator ->
|
||||||
// Set start screen
|
if (navigator.size == 1) {
|
||||||
handleIntentAction(intent)
|
ConfirmExit()
|
||||||
|
|
||||||
// Reset Incognito Mode on relaunch
|
|
||||||
preferences.incognitoMode().set(false)
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// Shows current screen
|
LaunchedEffect(navigator) {
|
||||||
ScreenTransition(navigator = navigator, transition = { Transition.OneWayFade })
|
this@MainActivity.navigator = navigator
|
||||||
|
|
||||||
// Pop source-related screens when incognito mode is turned off
|
if (savedInstanceState == null) {
|
||||||
LaunchedEffect(Unit) {
|
// Set start screen
|
||||||
preferences.incognitoMode().changes()
|
handleIntentAction(intent)
|
||||||
.drop(1)
|
|
||||||
.onEach {
|
// Reset Incognito Mode on relaunch
|
||||||
if (!it) {
|
preferences.incognitoMode().set(false)
|
||||||
val currentScreen = navigator.lastItem
|
}
|
||||||
if (currentScreen is BrowseSourceScreen ||
|
}
|
||||||
(currentScreen is MangaScreen && currentScreen.fromSource)
|
|
||||||
) {
|
// Consume insets already used by app state banners
|
||||||
navigator.popUntilRoot()
|
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) }
|
var showChangelog by remember { mutableStateOf(didMigration && !BuildConfig.DEBUG) }
|
||||||
|
|
|
@ -10,7 +10,6 @@ import eu.kanade.core.prefs.CheckboxState
|
||||||
import eu.kanade.core.prefs.mapAsCheckboxState
|
import eu.kanade.core.prefs.mapAsCheckboxState
|
||||||
import eu.kanade.core.util.addOrRemove
|
import eu.kanade.core.util.addOrRemove
|
||||||
import eu.kanade.data.chapter.NoChaptersException
|
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.GetCategories
|
||||||
import eu.kanade.domain.category.interactor.SetMangaCategories
|
import eu.kanade.domain.category.interactor.SetMangaCategories
|
||||||
import eu.kanade.domain.category.model.Category
|
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.toRelativeString
|
||||||
import eu.kanade.tachiyomi.util.lang.withIOContext
|
import eu.kanade.tachiyomi.util.lang.withIOContext
|
||||||
import eu.kanade.tachiyomi.util.lang.withUIContext
|
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.removeCovers
|
||||||
import eu.kanade.tachiyomi.util.shouldDownloadNewChapters
|
import eu.kanade.tachiyomi.util.shouldDownloadNewChapters
|
||||||
import eu.kanade.tachiyomi.util.system.logcat
|
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.combine
|
||||||
import kotlinx.coroutines.flow.distinctUntilChanged
|
import kotlinx.coroutines.flow.distinctUntilChanged
|
||||||
import kotlinx.coroutines.flow.filter
|
import kotlinx.coroutines.flow.filter
|
||||||
import kotlinx.coroutines.flow.launchIn
|
|
||||||
import kotlinx.coroutines.flow.map
|
import kotlinx.coroutines.flow.map
|
||||||
import kotlinx.coroutines.flow.update
|
import kotlinx.coroutines.flow.update
|
||||||
import kotlinx.coroutines.isActive
|
import kotlinx.coroutines.isActive
|
||||||
|
@ -81,7 +78,6 @@ class MangaInfoScreenModel(
|
||||||
val context: Context,
|
val context: Context,
|
||||||
val mangaId: Long,
|
val mangaId: Long,
|
||||||
private val isFromSource: Boolean,
|
private val isFromSource: Boolean,
|
||||||
basePreferences: BasePreferences = Injekt.get(),
|
|
||||||
private val downloadPreferences: DownloadPreferences = Injekt.get(),
|
private val downloadPreferences: DownloadPreferences = Injekt.get(),
|
||||||
private val libraryPreferences: LibraryPreferences = Injekt.get(),
|
private val libraryPreferences: LibraryPreferences = Injekt.get(),
|
||||||
private val uiPreferences: UiPreferences = 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 }
|
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 {
|
init {
|
||||||
val toChapterItemsParams: List<Chapter>.(manga: Manga) -> List<ChapterItem> = { manga ->
|
val toChapterItemsParams: List<Chapter>.(manga: Manga) -> List<ChapterItem> = { manga ->
|
||||||
toChapterItems(
|
toChapterItems(
|
||||||
|
@ -189,8 +174,6 @@ class MangaInfoScreenModel(
|
||||||
isFromSource = isFromSource,
|
isFromSource = isFromSource,
|
||||||
chapters = chapters,
|
chapters = chapters,
|
||||||
isRefreshingData = needRefreshInfo || needRefreshChapter,
|
isRefreshingData = needRefreshInfo || needRefreshChapter,
|
||||||
isIncognitoMode = incognitoMode,
|
|
||||||
isDownloadedOnlyMode = downloadedOnlyMode,
|
|
||||||
dialog = null,
|
dialog = null,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -210,14 +193,6 @@ class MangaInfoScreenModel(
|
||||||
// Initial loading finished
|
// Initial loading finished
|
||||||
updateSuccessState { it.copy(isRefreshingData = false) }
|
updateSuccessState { it.copy(isRefreshingData = false) }
|
||||||
}
|
}
|
||||||
|
|
||||||
basePreferences.incognitoMode()
|
|
||||||
.asHotFlow { incognitoMode = it }
|
|
||||||
.launchIn(coroutineScope)
|
|
||||||
|
|
||||||
basePreferences.downloadedOnly()
|
|
||||||
.asHotFlow { downloadedOnlyMode = it }
|
|
||||||
.launchIn(coroutineScope)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fun fetchAllFromSource(manualFetch: Boolean = true) {
|
fun fetchAllFromSource(manualFetch: Boolean = true) {
|
||||||
|
@ -1037,8 +1012,6 @@ sealed class MangaScreenState {
|
||||||
val chapters: List<ChapterItem>,
|
val chapters: List<ChapterItem>,
|
||||||
val trackItems: List<TrackItem> = emptyList(),
|
val trackItems: List<TrackItem> = emptyList(),
|
||||||
val isRefreshingData: Boolean = false,
|
val isRefreshingData: Boolean = false,
|
||||||
val isIncognitoMode: Boolean = false,
|
|
||||||
val isDownloadedOnlyMode: Boolean = false,
|
|
||||||
val dialog: MangaInfoScreenModel.Dialog? = null,
|
val dialog: MangaInfoScreenModel.Dialog? = null,
|
||||||
) : MangaScreenState() {
|
) : MangaScreenState() {
|
||||||
|
|
||||||
|
|
|
@ -11,7 +11,6 @@ import cafe.adriel.voyager.core.model.coroutineScope
|
||||||
import eu.kanade.core.prefs.asState
|
import eu.kanade.core.prefs.asState
|
||||||
import eu.kanade.core.util.addOrRemove
|
import eu.kanade.core.util.addOrRemove
|
||||||
import eu.kanade.core.util.insertSeparators
|
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.GetChapter
|
||||||
import eu.kanade.domain.chapter.interactor.SetReadStatus
|
import eu.kanade.domain.chapter.interactor.SetReadStatus
|
||||||
import eu.kanade.domain.chapter.interactor.UpdateChapter
|
import eu.kanade.domain.chapter.interactor.UpdateChapter
|
||||||
|
@ -62,16 +61,12 @@ class UpdatesScreenModel(
|
||||||
private val getChapter: GetChapter = Injekt.get(),
|
private val getChapter: GetChapter = Injekt.get(),
|
||||||
private val libraryPreferences: LibraryPreferences = Injekt.get(),
|
private val libraryPreferences: LibraryPreferences = Injekt.get(),
|
||||||
val snackbarHostState: SnackbarHostState = SnackbarHostState(),
|
val snackbarHostState: SnackbarHostState = SnackbarHostState(),
|
||||||
basePreferences: BasePreferences = Injekt.get(),
|
|
||||||
uiPreferences: UiPreferences = Injekt.get(),
|
uiPreferences: UiPreferences = Injekt.get(),
|
||||||
) : StateScreenModel<UpdatesState>(UpdatesState()) {
|
) : StateScreenModel<UpdatesState>(UpdatesState()) {
|
||||||
|
|
||||||
private val _events: Channel<Event> = Channel(Int.MAX_VALUE)
|
private val _events: Channel<Event> = Channel(Int.MAX_VALUE)
|
||||||
val events: Flow<Event> = _events.receiveAsFlow()
|
val events: Flow<Event> = _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 lastUpdated by libraryPreferences.libraryUpdateLastTimestamp().asState(coroutineScope)
|
||||||
|
|
||||||
val relativeTime: Int by uiPreferences.relativeTime().asState(coroutineScope)
|
val relativeTime: Int by uiPreferences.relativeTime().asState(coroutineScope)
|
||||||
|
|
|
@ -56,8 +56,6 @@ object UpdatesTab : Tab {
|
||||||
UpdateScreen(
|
UpdateScreen(
|
||||||
state = state,
|
state = state,
|
||||||
snackbarHostState = screenModel.snackbarHostState,
|
snackbarHostState = screenModel.snackbarHostState,
|
||||||
incognitoMode = screenModel.isIncognitoMode,
|
|
||||||
downloadedOnlyMode = screenModel.isDownloadOnly,
|
|
||||||
lastUpdated = screenModel.lastUpdated,
|
lastUpdated = screenModel.lastUpdated,
|
||||||
relativeTime = screenModel.relativeTime,
|
relativeTime = screenModel.relativeTime,
|
||||||
onClickCover = { item -> navigator.push(MangaScreen(item.update.mangaId)) },
|
onClickCover = { item -> navigator.push(MangaScreen(item.update.mangaId)) },
|
||||||
|
|
|
@ -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-webview = { module = "com.google.accompanist:accompanist-webview", version.ref = "accompanist" }
|
||||||
accompanist-flowlayout = { module = "com.google.accompanist:accompanist-flowlayout", 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-permissions = { module = "com.google.accompanist:accompanist-permissions", version.ref = "accompanist" }
|
||||||
accompanist-themeadapter = { module = "com.google.accompanist:accompanist-themeadapter-material3", version.ref = "accompanist" }
|
accompanist-themeadapter = { module = "com.google.accompanist:accompanist-themeadapter-material3", version.ref = "accompanist" }
|
||||||
|
accompanist-systemuicontroller = { module = "com.google.accompanist:accompanist-systemuicontroller", version.ref = "accompanist" }
|
||||||
|
|
Reference in a new issue