mirror of
https://github.com/mihonapp/mihon.git
synced 2024-11-10 12:47:26 +01:00
Reimplement appbar color overlay on scroll (#7663)
only on updates and history screen for now, but the required changes on app bar is there. also fix missing incognito-downloaded mode indicator on history screen
This commit is contained in:
parent
322f3a07e8
commit
737cf9898d
@ -2,11 +2,7 @@ package eu.kanade.presentation.components
|
||||
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.RowScope
|
||||
import androidx.compose.foundation.layout.WindowInsets
|
||||
import androidx.compose.foundation.layout.WindowInsetsSides
|
||||
import androidx.compose.foundation.layout.only
|
||||
import androidx.compose.foundation.layout.systemBars
|
||||
import androidx.compose.foundation.layout.windowInsetsPadding
|
||||
import androidx.compose.foundation.layout.statusBarsPadding
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.filled.ArrowBack
|
||||
import androidx.compose.material.icons.filled.Close
|
||||
@ -18,6 +14,7 @@ import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.SmallTopAppBar
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.material3.TopAppBarDefaults
|
||||
import androidx.compose.material3.TopAppBarScrollBehavior
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.derivedStateOf
|
||||
import androidx.compose.runtime.getValue
|
||||
@ -51,19 +48,63 @@ fun AppBar(
|
||||
// Banners
|
||||
downloadedOnlyMode: Boolean = false,
|
||||
incognitoMode: Boolean = false,
|
||||
|
||||
scrollBehavior: TopAppBarScrollBehavior? = null,
|
||||
) {
|
||||
val isActionMode by derivedStateOf { actionModeCounter > 0 }
|
||||
val backgroundColor = if (isActionMode) {
|
||||
TopAppBarDefaults.smallTopAppBarColors().containerColor(1f).value
|
||||
} else {
|
||||
MaterialTheme.colorScheme.surface
|
||||
}
|
||||
AppBar(
|
||||
modifier = modifier,
|
||||
titleContent = {
|
||||
if (isActionMode) {
|
||||
AppBarTitle(actionModeCounter.toString())
|
||||
} else {
|
||||
AppBarTitle(title, subtitle)
|
||||
}
|
||||
},
|
||||
navigateUp = navigateUp,
|
||||
navigationIcon = navigationIcon,
|
||||
actions = {
|
||||
if (isActionMode) {
|
||||
actionModeActions()
|
||||
} else {
|
||||
actions()
|
||||
}
|
||||
},
|
||||
isActionMode = isActionMode,
|
||||
onCancelActionMode = onCancelActionMode,
|
||||
downloadedOnlyMode = downloadedOnlyMode,
|
||||
incognitoMode = incognitoMode,
|
||||
scrollBehavior = scrollBehavior,
|
||||
)
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun AppBar(
|
||||
modifier: Modifier = Modifier,
|
||||
// Title
|
||||
titleContent: @Composable () -> Unit,
|
||||
// Up button
|
||||
navigateUp: (() -> Unit)? = null,
|
||||
navigationIcon: ImageVector = Icons.Default.ArrowBack,
|
||||
// Menu
|
||||
actions: @Composable RowScope.() -> Unit = {},
|
||||
// Action mode
|
||||
isActionMode: Boolean,
|
||||
onCancelActionMode: () -> Unit = {},
|
||||
// Banners
|
||||
downloadedOnlyMode: Boolean = false,
|
||||
incognitoMode: Boolean = false,
|
||||
|
||||
scrollBehavior: TopAppBarScrollBehavior? = null,
|
||||
) {
|
||||
val scrollFraction = if (isActionMode) 1f else scrollBehavior?.state?.overlappedFraction ?: 0f
|
||||
val backgroundColor by TopAppBarDefaults.smallTopAppBarColors().containerColor(scrollFraction)
|
||||
|
||||
Column(
|
||||
modifier = modifier.drawBehind { drawRect(backgroundColor) },
|
||||
) {
|
||||
SmallTopAppBar(
|
||||
modifier = Modifier.windowInsetsPadding(WindowInsets.systemBars.only(WindowInsetsSides.Top)),
|
||||
modifier = Modifier.statusBarsPadding(),
|
||||
navigationIcon = {
|
||||
if (isActionMode) {
|
||||
IconButton(onClick = onCancelActionMode) {
|
||||
@ -83,25 +124,14 @@ fun AppBar(
|
||||
}
|
||||
}
|
||||
},
|
||||
title = {
|
||||
if (isActionMode) {
|
||||
AppBarTitle(actionModeCounter.toString())
|
||||
} else {
|
||||
AppBarTitle(title, subtitle)
|
||||
}
|
||||
},
|
||||
actions = {
|
||||
if (isActionMode) {
|
||||
actionModeActions()
|
||||
} else {
|
||||
actions()
|
||||
}
|
||||
},
|
||||
title = titleContent,
|
||||
actions = actions,
|
||||
// Background handled by parent
|
||||
colors = TopAppBarDefaults.smallTopAppBarColors(
|
||||
containerColor = Color.Transparent,
|
||||
scrolledContainerColor = Color.Transparent,
|
||||
),
|
||||
scrollBehavior = scrollBehavior,
|
||||
)
|
||||
|
||||
if (downloadedOnlyMode) {
|
||||
|
@ -1,10 +1,18 @@
|
||||
package eu.kanade.presentation.history
|
||||
|
||||
import androidx.compose.foundation.layout.safeDrawingPadding
|
||||
import androidx.compose.foundation.layout.WindowInsets
|
||||
import androidx.compose.foundation.layout.WindowInsetsSides
|
||||
import androidx.compose.foundation.layout.asPaddingValues
|
||||
import androidx.compose.foundation.layout.navigationBars
|
||||
import androidx.compose.foundation.layout.only
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.material3.Scaffold
|
||||
import androidx.compose.material3.TopAppBarDefaults
|
||||
import androidx.compose.material3.rememberTopAppBarState
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.LaunchedEffect
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.input.nestedscroll.nestedScroll
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.paging.LoadState
|
||||
import eu.kanade.domain.history.model.HistoryWithRelations
|
||||
@ -30,10 +38,21 @@ fun HistoryScreen(
|
||||
onClickResume: (HistoryWithRelations) -> Unit,
|
||||
) {
|
||||
val context = LocalContext.current
|
||||
val insetPaddingValue = WindowInsets.navigationBars
|
||||
.only(WindowInsetsSides.Horizontal + WindowInsetsSides.Bottom)
|
||||
.asPaddingValues()
|
||||
val scrollBehavior = TopAppBarDefaults.pinnedScrollBehavior(rememberTopAppBarState())
|
||||
Scaffold(
|
||||
modifier = Modifier.safeDrawingPadding(),
|
||||
modifier = Modifier
|
||||
.padding(insetPaddingValue)
|
||||
.nestedScroll(scrollBehavior.nestedScrollConnection),
|
||||
topBar = {
|
||||
HistoryToolbar(state = presenter)
|
||||
HistoryToolbar(
|
||||
state = presenter,
|
||||
incognitoMode = presenter.isIncognitoMode,
|
||||
downloadedOnlyMode = presenter.isDownloadOnly,
|
||||
scrollBehavior = scrollBehavior,
|
||||
)
|
||||
},
|
||||
) { contentPadding ->
|
||||
val items = presenter.getLazyHistory()
|
||||
|
@ -9,8 +9,7 @@ import androidx.compose.material.icons.outlined.Search
|
||||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.material3.IconButton
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.SmallTopAppBar
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.material3.TopAppBarScrollBehavior
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.LaunchedEffect
|
||||
import androidx.compose.runtime.remember
|
||||
@ -19,6 +18,7 @@ import androidx.compose.ui.focus.FocusRequester
|
||||
import androidx.compose.ui.focus.focusRequester
|
||||
import androidx.compose.ui.graphics.SolidColor
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import eu.kanade.presentation.components.AppBar
|
||||
import eu.kanade.tachiyomi.R
|
||||
import eu.kanade.tachiyomi.ui.recent.history.HistoryPresenter
|
||||
import eu.kanade.tachiyomi.ui.recent.history.HistoryState
|
||||
@ -27,17 +27,25 @@ import kotlinx.coroutines.delay
|
||||
@Composable
|
||||
fun HistoryToolbar(
|
||||
state: HistoryState,
|
||||
scrollBehavior: TopAppBarScrollBehavior,
|
||||
incognitoMode: Boolean,
|
||||
downloadedOnlyMode: Boolean,
|
||||
) {
|
||||
if (state.searchQuery == null) {
|
||||
HistoryRegularToolbar(
|
||||
onClickSearch = { state.searchQuery = "" },
|
||||
onClickDelete = { state.dialog = HistoryPresenter.Dialog.DeleteAll },
|
||||
incognitoMode = incognitoMode,
|
||||
downloadedOnlyMode = downloadedOnlyMode,
|
||||
scrollBehavior = scrollBehavior,
|
||||
)
|
||||
} else {
|
||||
HistorySearchToolbar(
|
||||
searchQuery = state.searchQuery!!,
|
||||
onChangeSearchQuery = { state.searchQuery = it },
|
||||
onClickCloseSearch = { state.searchQuery = null },
|
||||
incognitoMode = incognitoMode,
|
||||
downloadedOnlyMode = downloadedOnlyMode,
|
||||
)
|
||||
}
|
||||
}
|
||||
@ -46,11 +54,12 @@ fun HistoryToolbar(
|
||||
fun HistoryRegularToolbar(
|
||||
onClickSearch: () -> Unit,
|
||||
onClickDelete: () -> Unit,
|
||||
incognitoMode: Boolean,
|
||||
downloadedOnlyMode: Boolean,
|
||||
scrollBehavior: TopAppBarScrollBehavior,
|
||||
) {
|
||||
SmallTopAppBar(
|
||||
title = {
|
||||
Text(text = stringResource(id = R.string.history))
|
||||
},
|
||||
AppBar(
|
||||
title = stringResource(id = R.string.history),
|
||||
actions = {
|
||||
IconButton(onClick = onClickSearch) {
|
||||
Icon(Icons.Outlined.Search, contentDescription = "search")
|
||||
@ -59,6 +68,9 @@ fun HistoryRegularToolbar(
|
||||
Icon(Icons.Outlined.DeleteSweep, contentDescription = "delete")
|
||||
}
|
||||
},
|
||||
downloadedOnlyMode = downloadedOnlyMode,
|
||||
incognitoMode = incognitoMode,
|
||||
scrollBehavior = scrollBehavior,
|
||||
)
|
||||
}
|
||||
|
||||
@ -67,15 +79,12 @@ fun HistorySearchToolbar(
|
||||
searchQuery: String,
|
||||
onChangeSearchQuery: (String) -> Unit,
|
||||
onClickCloseSearch: () -> Unit,
|
||||
incognitoMode: Boolean,
|
||||
downloadedOnlyMode: Boolean,
|
||||
) {
|
||||
val focusRequester = remember { FocusRequester.Default }
|
||||
SmallTopAppBar(
|
||||
navigationIcon = {
|
||||
IconButton(onClick = onClickCloseSearch) {
|
||||
Icon(Icons.Outlined.ArrowBack, contentDescription = "delete")
|
||||
}
|
||||
},
|
||||
title = {
|
||||
AppBar(
|
||||
titleContent = {
|
||||
BasicTextField(
|
||||
value = searchQuery,
|
||||
onValueChange = onChangeSearchQuery,
|
||||
@ -87,6 +96,11 @@ fun HistorySearchToolbar(
|
||||
cursorBrush = SolidColor(MaterialTheme.colorScheme.onBackground),
|
||||
)
|
||||
},
|
||||
navigationIcon = Icons.Outlined.ArrowBack,
|
||||
navigateUp = onClickCloseSearch,
|
||||
isActionMode = false,
|
||||
downloadedOnlyMode = downloadedOnlyMode,
|
||||
incognitoMode = incognitoMode,
|
||||
)
|
||||
LaunchedEffect(focusRequester) {
|
||||
// TODO: https://issuetracker.google.com/issues/204502668
|
||||
|
@ -11,7 +11,6 @@ import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.navigationBars
|
||||
import androidx.compose.foundation.layout.only
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.systemBars
|
||||
import androidx.compose.foundation.lazy.LazyColumn
|
||||
import androidx.compose.foundation.lazy.rememberLazyListState
|
||||
import androidx.compose.material.icons.Icons
|
||||
@ -20,9 +19,13 @@ import androidx.compose.material.icons.filled.Refresh
|
||||
import androidx.compose.material.icons.filled.SelectAll
|
||||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.material3.IconButton
|
||||
import androidx.compose.material3.TopAppBarDefaults
|
||||
import androidx.compose.material3.TopAppBarScrollBehavior
|
||||
import androidx.compose.material3.rememberTopAppBarState
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.LaunchedEffect
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.input.nestedscroll.nestedScroll
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.compose.ui.platform.LocalLayoutDirection
|
||||
import androidx.compose.ui.res.stringResource
|
||||
@ -57,7 +60,9 @@ fun UpdateScreen(
|
||||
onDownloadChapter: (List<UpdatesItem>, ChapterDownloadAction) -> Unit,
|
||||
) {
|
||||
val updatesListState = rememberLazyListState()
|
||||
val insetPaddingValue = WindowInsets.systemBars.only(WindowInsetsSides.Horizontal).asPaddingValues()
|
||||
val insetPaddingValue = WindowInsets.navigationBars
|
||||
.only(WindowInsetsSides.Horizontal + WindowInsetsSides.Bottom)
|
||||
.asPaddingValues()
|
||||
|
||||
val internalOnBackPressed = {
|
||||
if (presenter.selectionMode) {
|
||||
@ -76,9 +81,11 @@ fun UpdateScreen(
|
||||
}
|
||||
}
|
||||
|
||||
val scrollBehavior = TopAppBarDefaults.pinnedScrollBehavior(rememberTopAppBarState())
|
||||
Scaffold(
|
||||
modifier = Modifier
|
||||
.padding(insetPaddingValue),
|
||||
.padding(insetPaddingValue)
|
||||
.nestedScroll(scrollBehavior.nestedScrollConnection),
|
||||
topBar = {
|
||||
UpdatesAppBar(
|
||||
incognitoMode = presenter.isIncognitoMode,
|
||||
@ -88,6 +95,7 @@ fun UpdateScreen(
|
||||
onSelectAll = { presenter.toggleAllSelection(true) },
|
||||
onInvertSelection = { presenter.invertSelection() },
|
||||
onCancelActionMode = { presenter.toggleAllSelection(false) },
|
||||
scrollBehavior = scrollBehavior,
|
||||
)
|
||||
},
|
||||
bottomBar = {
|
||||
@ -185,6 +193,7 @@ fun UpdatesAppBar(
|
||||
onSelectAll: () -> Unit,
|
||||
onInvertSelection: () -> Unit,
|
||||
onCancelActionMode: () -> Unit,
|
||||
scrollBehavior: TopAppBarScrollBehavior,
|
||||
) {
|
||||
AppBar(
|
||||
modifier = modifier,
|
||||
@ -215,6 +224,7 @@ fun UpdatesAppBar(
|
||||
},
|
||||
downloadedOnlyMode = downloadedOnlyMode,
|
||||
incognitoMode = incognitoMode,
|
||||
scrollBehavior = scrollBehavior,
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -22,6 +22,7 @@ import eu.kanade.domain.history.interactor.RemoveHistoryByMangaId
|
||||
import eu.kanade.domain.history.model.HistoryWithRelations
|
||||
import eu.kanade.presentation.history.HistoryUiModel
|
||||
import eu.kanade.tachiyomi.R
|
||||
import eu.kanade.tachiyomi.data.preference.PreferencesHelper
|
||||
import eu.kanade.tachiyomi.ui.base.presenter.BasePresenter
|
||||
import eu.kanade.tachiyomi.util.lang.launchIO
|
||||
import eu.kanade.tachiyomi.util.lang.launchUI
|
||||
@ -45,11 +46,16 @@ class HistoryPresenter(
|
||||
private val deleteHistoryTable: DeleteHistoryTable = Injekt.get(),
|
||||
private val removeHistoryById: RemoveHistoryById = Injekt.get(),
|
||||
private val removeHistoryByMangaId: RemoveHistoryByMangaId = Injekt.get(),
|
||||
preferences: PreferencesHelper = Injekt.get(),
|
||||
) : BasePresenter<HistoryController>(), HistoryState by state {
|
||||
|
||||
private val _events: Channel<Event> = Channel(Int.MAX_VALUE)
|
||||
val events: Flow<Event> = _events.receiveAsFlow()
|
||||
|
||||
val isDownloadOnly: Boolean by preferences.downloadedOnly().asState()
|
||||
|
||||
val isIncognitoMode: Boolean by preferences.incognitoMode().asState()
|
||||
|
||||
@Composable
|
||||
fun getLazyHistory(): LazyPagingItems<HistoryUiModel> {
|
||||
val scope = rememberCoroutineScope()
|
||||
|
Loading…
Reference in New Issue
Block a user