Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 5 additions & 5 deletions app/src/main/kotlin/com/hippo/ehviewer/ui/main/GalleryList.kt
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import androidx.compose.foundation.lazy.staggeredgrid.rememberLazyStaggeredGridS
import androidx.compose.material3.CircularProgressIndicator
import androidx.compose.material3.Icon
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.SearchBarScrollBehavior
import androidx.compose.material3.ShapeDefaults
import androidx.compose.material3.Surface
import androidx.compose.material3.Text
Expand Down Expand Up @@ -64,6 +65,7 @@ import com.hippo.ehviewer.ui.screen.collectDetailSizeAsState
import com.hippo.ehviewer.ui.tools.FastScrollLazyVerticalGrid
import com.hippo.ehviewer.ui.tools.FastScrollLazyVerticalStaggeredGrid
import com.hippo.ehviewer.util.displayString
import kotlin.math.roundToInt
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.flow.drop
import kotlinx.coroutines.flow.first
Expand All @@ -90,10 +92,9 @@ fun GalleryList(
detailItemContent: @Composable (LazyGridItemScope.(BaseGalleryInfo) -> Unit),
thumbListState: LazyStaggeredGridState = rememberLazyStaggeredGridState(),
thumbItemContent: @Composable (LazyStaggeredGridItemScope.(BaseGalleryInfo) -> Unit),
searchBarOffsetY: () -> Int,
scrollBehavior: SearchBarScrollBehavior,
scrollToTopOnRefresh: Boolean = true,
onRefresh: () -> Unit,
onLoading: () -> Unit,
) {
val marginH = dimensionResource(id = R.dimen.gallery_list_margin_h)
val marginV = dimensionResource(id = R.dimen.gallery_list_margin_v)
Expand Down Expand Up @@ -189,7 +190,7 @@ fun GalleryList(
when (val state = data.loadState.refresh) {
is LoadState.Loading -> if (!isRefreshing && scrollToTopOnRefresh) {
LaunchedEffect(Unit) {
onLoading()
scrollBehavior.scrollOffset = 0f
}
LaunchedEffect(Unit) {
if (listMode == 0) {
Expand Down Expand Up @@ -226,8 +227,7 @@ fun GalleryList(
PullToRefreshDefaults.Indicator(
state = refreshState,
isRefreshing = isRefreshing,
modifier = Modifier.align(Alignment.TopCenter).padding(top = contentPadding.calculateTopPadding())
.offset { IntOffset(0, searchBarOffsetY()) },
modifier = with(scrollBehavior) { Modifier.align(Alignment.TopCenter).padding(top = contentPadding.calculateTopPadding()).offset { IntOffset(0, scrollBehavior.scrollOffset.roundToInt()) } },
Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
modifier = with(scrollBehavior) { Modifier.align(Alignment.TopCenter).padding(top = contentPadding.calculateTopPadding()).offset { IntOffset(0, scrollBehavior.scrollOffset.roundToInt()) } },
modifier = Modifier.align(Alignment.TopCenter).padding(top = contentPadding.calculateTopPadding()).offset { IntOffset(0, scrollBehavior.scrollOffset.roundToInt()) },

)
}
}
Expand Down
29 changes: 15 additions & 14 deletions app/src/main/kotlin/com/hippo/ehviewer/ui/screen/DownloadsScreen.kt
Original file line number Diff line number Diff line change
Expand Up @@ -48,11 +48,13 @@ import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.material3.ListItem
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.SearchBarDefaults
import androidx.compose.material3.SwipeToDismissBoxValue
import androidx.compose.material3.Text
import androidx.compose.material3.TopAppBar
import androidx.compose.material3.fork.SwipeToDismissBox
import androidx.compose.material3.fork.SwipeToDismissBoxState
import androidx.compose.material3.rememberSearchBarState
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.collectAsState
Expand Down Expand Up @@ -123,7 +125,6 @@ import com.ramcosta.composedestinations.navigation.DestinationsNavigator
import eu.kanade.tachiyomi.util.lang.launchIO
import eu.kanade.tachiyomi.util.lang.withNonCancellableContext
import eu.kanade.tachiyomi.util.lang.withUIContext
import kotlin.math.roundToInt
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
import moe.tarsin.coroutines.onEachLatest
Expand All @@ -138,15 +139,15 @@ fun AnimatedVisibilityScope.DownloadsScreen(navigator: DestinationsNavigator) =
val filterMode by Settings.downloadFilterMode.collectAsState { DownloadsFilterMode.from(it) }
var filterState by rememberSaveable { mutableStateOf(DownloadsFilterState(filterMode, Settings.recentDownloadLabel.value)) }
var invalidateKey by rememberSaveable { mutableStateOf(false) }
var searchBarExpanded by rememberSaveable { mutableStateOf(false) }
var searchBarOffsetY by remember { mutableIntStateOf(0) }
val animateItems by Settings.animateItems.collectAsState()
val searchBarState = rememberSearchBarState()
val scrollBehavior = SearchBarDefaults.enterAlwaysSearchBarScrollBehavior()

var fabExpanded by remember { mutableStateOf(false) }
var fabHidden by remember { mutableStateOf(false) }
val checkedInfoMap = remember { mutableStateMapOf<Long, DownloadInfo>() }
val selectMode by rememberUpdatedState(checkedInfoMap.isNotEmpty())
DrawerHandle(!selectMode && !searchBarExpanded)
DrawerHandle(!selectMode && !searchBarState.expanded)

val density = LocalDensity.current
val canTranslate = Settings.showTagTranslations && EhTagDatabase.isTranslatable(implicit<Context>()) && EhTagDatabase.initialized
Expand Down Expand Up @@ -210,7 +211,7 @@ fun AnimatedVisibilityScope.DownloadsScreen(navigator: DestinationsNavigator) =
}

LaunchedEffect(filterState) {
searchBarOffsetY = 0
scrollBehavior.scrollOffset = 0f
}

ProvideSideSheetContent { drawerState ->
Expand Down Expand Up @@ -442,17 +443,19 @@ fun AnimatedVisibilityScope.DownloadsScreen(navigator: DestinationsNavigator) =
}
}

SearchBarScreen(
onApplySearch = { filterState = filterState.copy(keyword = it) },
expanded = searchBarExpanded,
onExpandedChange = {
searchBarExpanded = it
LaunchedEffect(searchBarState) {
snapshotFlow { searchBarState.expanded }.collect {
fabHidden = it
if (it) checkedInfoMap.clear()
},
}
}

SearchBarScreen(
onApplySearch = { filterState = filterState.copy(keyword = it) },
searchBarState = searchBarState,
scrollBehavior = scrollBehavior,
title = title,
searchFieldHint = hint,
searchBarOffsetY = { searchBarOffsetY },
trailingIcon = {
var expanded by remember { mutableStateOf(false) }
val sideSheetState = LocalSideSheetState.current
Expand Down Expand Up @@ -522,7 +525,6 @@ fun AnimatedVisibilityScope.DownloadsScreen(navigator: DestinationsNavigator) =
val realPadding = contentPadding + PaddingValues(dimensionResource(id = R.dimen.gallery_list_margin_h), dimensionResource(id = R.dimen.gallery_list_margin_v))
val searchBarConnection = remember {
val slop = ViewConfiguration.get(implicit<Context>()).scaledTouchSlop
val topPaddingPx = with(density) { contentPadding.calculateTopPadding().roundToPx() }
object : NestedScrollConnection {
override fun onPostScroll(consumed: Offset, available: Offset, source: NestedScrollSource): Offset {
val dy = -consumed.y
Expand All @@ -531,7 +533,6 @@ fun AnimatedVisibilityScope.DownloadsScreen(navigator: DestinationsNavigator) =
} else if (dy <= -slop / 2) {
fabHidden = false
}
searchBarOffsetY = (searchBarOffsetY - dy).roundToInt().coerceIn(-topPaddingPx, 0)
return Offset.Zero // We never consume it
}
}
Expand Down
35 changes: 16 additions & 19 deletions app/src/main/kotlin/com/hippo/ehviewer/ui/screen/FavoritesScreen.kt
Original file line number Diff line number Diff line change
Expand Up @@ -27,25 +27,26 @@ import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.material3.ListItem
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.SearchBarDefaults
import androidx.compose.material3.Text
import androidx.compose.material3.TopAppBar
import androidx.compose.material3.rememberSearchBarState
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.currentRecomposeScope
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableIntStateOf
import androidx.compose.runtime.mutableStateMapOf
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.saveable.rememberSaveable
import androidx.compose.runtime.setValue
import androidx.compose.runtime.snapshotFlow
import androidx.compose.ui.Modifier
import androidx.compose.ui.geometry.Offset
import androidx.compose.ui.input.nestedscroll.NestedScrollConnection
import androidx.compose.ui.input.nestedscroll.NestedScrollSource
import androidx.compose.ui.input.nestedscroll.nestedScroll
import androidx.compose.ui.platform.LocalDensity
import androidx.compose.ui.res.stringResource
import androidx.lifecycle.viewModelScope
import androidx.paging.Pager
Expand Down Expand Up @@ -87,7 +88,6 @@ import com.ramcosta.composedestinations.annotation.RootGraph
import com.ramcosta.composedestinations.navigation.DestinationsNavigator
import eu.kanade.tachiyomi.util.lang.withIOContext
import eu.kanade.tachiyomi.util.lang.withUIContext
import kotlin.math.roundToInt
import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.launch
Expand All @@ -103,19 +103,19 @@ fun AnimatedVisibilityScope.FavouritesScreen(navigator: DestinationsNavigator) =
val cloudFavName = stringResource(R.string.cloud_favorites)
val animateItems by Settings.animateItems.collectAsState()
val hasSignedIn by Settings.hasSignedIn.collectAsState()
val searchBarState = rememberSearchBarState()
val scrollBehavior = SearchBarDefaults.enterAlwaysSearchBarScrollBehavior()

// Meta State
var urlBuilder by rememberSaveable { mutableStateOf(FavListUrlBuilder(favCat = Settings.recentFavCat)) }
var searchBarExpanded by rememberSaveable { mutableStateOf(false) }
var searchBarOffsetY by remember { mutableIntStateOf(0) }

// Derived State
val keyword = urlBuilder.keyword
val isLocalFav = urlBuilder.favCat == FavListUrlBuilder.FAV_CAT_LOCAL
val favCatName = remember(urlBuilder) {
when (val favCat = urlBuilder.favCat) {
in 0..9 -> Settings.favCat[favCat]
FavListUrlBuilder.FAV_CAT_LOCAL -> localFavName.also { searchBarOffsetY = 0 }
FavListUrlBuilder.FAV_CAT_LOCAL -> localFavName.also { scrollBehavior.scrollOffset = 0f }
else -> cloudFavName
}
}
Expand All @@ -124,7 +124,6 @@ fun AnimatedVisibilityScope.FavouritesScreen(navigator: DestinationsNavigator) =
} else {
stringResource(R.string.favorites_title_2, favCatName, keyword)
}
val density = LocalDensity.current
val localFavCountFlow = rememberInVM { EhDB.localFavCount }
val searchBarHint = stringResource(R.string.search_bar_hint, favCatName)
val data = rememberInVM(isLocalFav) {
Expand Down Expand Up @@ -230,20 +229,21 @@ fun AnimatedVisibilityScope.FavouritesScreen(navigator: DestinationsNavigator) =
var fabHidden by remember { mutableStateOf(false) }
val checkedInfoMap = remember { mutableStateMapOf<Long, BaseGalleryInfo>() }
val selectMode = checkedInfoMap.isNotEmpty()
DrawerHandle(!selectMode && !searchBarExpanded)
DrawerHandle(!selectMode && !searchBarState.expanded)
LaunchedEffect(searchBarState) {
snapshotFlow { searchBarState.expanded }.collect {
fabHidden = it
if (it) checkedInfoMap.clear()
}
}

SearchBarScreen(
onApplySearch = { refresh(FavListUrlBuilder(urlBuilder.favCat, it)) },
expanded = searchBarExpanded,
onExpandedChange = {
searchBarExpanded = it
fabHidden = it
if (it) checkedInfoMap.clear()
},
searchBarState = searchBarState,
scrollBehavior = scrollBehavior,
title = title,
searchFieldHint = searchBarHint,
tagNamespace = !isLocalFav,
searchBarOffsetY = { searchBarOffsetY },
trailingIcon = {
val sheetState = LocalSideSheetState.current
IconButton(onClick = { launch { sheetState.open() } }) {
Expand All @@ -257,7 +257,6 @@ fun AnimatedVisibilityScope.FavouritesScreen(navigator: DestinationsNavigator) =
val showPages by Settings.showGalleryPages.collectAsState()
val searchBarConnection = remember {
val slop = ViewConfiguration.get(implicit<Context>()).scaledTouchSlop
val topPaddingPx = with(density) { contentPadding.calculateTopPadding().roundToPx() }
object : NestedScrollConnection {
override fun onPostScroll(consumed: Offset, available: Offset, source: NestedScrollSource): Offset {
val dy = -consumed.y
Expand All @@ -266,7 +265,6 @@ fun AnimatedVisibilityScope.FavouritesScreen(navigator: DestinationsNavigator) =
} else if (dy <= -slop / 2) {
fabHidden = false
}
searchBarOffsetY = (searchBarOffsetY - dy).roundToInt().coerceIn(-topPaddingPx, 0)
return Offset.Zero // We never consume it
}
}
Expand Down Expand Up @@ -332,10 +330,9 @@ fun AnimatedVisibilityScope.FavouritesScreen(navigator: DestinationsNavigator) =
)
}
},
searchBarOffsetY = { searchBarOffsetY },
scrollBehavior = scrollBehavior,
scrollToTopOnRefresh = urlBuilder.favCat != FavListUrlBuilder.FAV_CAT_LOCAL,
onRefresh = { refresh() },
onLoading = { searchBarOffsetY = 0 },
)
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,11 +31,13 @@ import androidx.compose.material.icons.outlined.Bookmarks
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.material3.ListItem
import androidx.compose.material3.SearchBarDefaults
import androidx.compose.material3.SwipeToDismissBoxValue
import androidx.compose.material3.Text
import androidx.compose.material3.TopAppBar
import androidx.compose.material3.fork.SwipeToDismissBox
import androidx.compose.material3.fork.SwipeToDismissBoxState
import androidx.compose.material3.rememberSearchBarState
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.Stable
Expand Down Expand Up @@ -124,7 +126,6 @@ import com.ramcosta.composedestinations.spec.Direction
import eu.kanade.tachiyomi.util.lang.launchIO
import eu.kanade.tachiyomi.util.lang.withIOContext
import eu.kanade.tachiyomi.util.lang.withUIContext
import kotlin.math.roundToInt
import kotlin.random.Random
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
Expand Down Expand Up @@ -153,15 +154,15 @@ fun AnimatedVisibilityScope.ToplistScreen(navigator: DestinationsNavigator) = Ga
@Composable
fun AnimatedVisibilityScope.GalleryListScreen(lub: ListUrlBuilder, navigator: DestinationsNavigator) = Screen(navigator) {
val searchFieldState = rememberTextFieldState()
val searchBarState = rememberSearchBarState()
val scrollBehaviour = SearchBarDefaults.enterAlwaysSearchBarScrollBehavior()
Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
val scrollBehaviour = SearchBarDefaults.enterAlwaysSearchBarScrollBehavior()
val scrollBehavior = SearchBarDefaults.enterAlwaysSearchBarScrollBehavior()

var urlBuilder by rememberSaveable(lub) { mutableStateOf(lub) }
var searchBarExpanded by rememberSaveable { mutableStateOf(false) }
var searchBarOffsetY by remember { mutableIntStateOf(0) }
val animateItems by Settings.animateItems.collectAsState()

var category by rememberMutableStateInDataStore("SearchCategory") { EhUtils.ALL_CATEGORY }
var advancedSearchOption by rememberMutableStateInDataStore("AdvancedSearchOption") { AdvancedSearchOption() }

DrawerHandle(!searchBarExpanded)
DrawerHandle(!searchBarState.expanded)

LaunchedEffect(urlBuilder) {
if (urlBuilder.category != EhUtils.NONE) category = urlBuilder.category
Expand Down Expand Up @@ -460,6 +461,9 @@ fun AnimatedVisibilityScope.GalleryListScreen(lub: ListUrlBuilder, navigator: De

var fabExpanded by remember { mutableStateOf(false) }
var fabHidden by remember { mutableStateOf(false) }
LaunchedEffect(searchBarState) {
snapshotFlow { searchBarState.expanded }.collect { fabHidden = it }
}

val openGalleryKeyword = stringResource(R.string.gallery_list_search_bar_open_gallery)
abstract class UrlSuggestion : Suggestion() {
Expand Down Expand Up @@ -505,11 +509,6 @@ fun AnimatedVisibilityScope.GalleryListScreen(lub: ListUrlBuilder, navigator: De

SearchBarScreen(
onApplySearch = ::onApplySearch,
expanded = searchBarExpanded,
onExpandedChange = {
searchBarExpanded = it
fabHidden = it
},
title = suitableTitle,
searchFieldHint = searchBarHint,
Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
searchFieldHint = searchBarHint,
searchFieldHint = searchBarHint,
searchBarState = searchBarState,
scrollBehavior = scrollBehavior,

searchFieldState = searchFieldState,
Expand All @@ -521,7 +520,6 @@ fun AnimatedVisibilityScope.GalleryListScreen(lub: ListUrlBuilder, navigator: De
}
},
tagNamespace = true,
searchBarOffsetY = { searchBarOffsetY },
trailingIcon = {
val sheetState = LocalSideSheetState.current
IconButton(onClick = { launch { sheetState.open() } }) {
Expand All @@ -544,7 +542,6 @@ fun AnimatedVisibilityScope.GalleryListScreen(lub: ListUrlBuilder, navigator: De
val showPages by Settings.showGalleryPages.collectAsState()
val searchBarConnection = remember {
val slop = ViewConfiguration.get(implicit<Context>()).scaledTouchSlop
val topPaddingPx = with(density) { contentPadding.calculateTopPadding().roundToPx() }
object : NestedScrollConnection {
override fun onPostScroll(consumed: Offset, available: Offset, source: NestedScrollSource): Offset {
val dy = -consumed.y
Expand All @@ -553,7 +550,6 @@ fun AnimatedVisibilityScope.GalleryListScreen(lub: ListUrlBuilder, navigator: De
} else if (dy <= -slop / 2) {
fabHidden = false
}
searchBarOffsetY = (searchBarOffsetY - dy).roundToInt().coerceIn(-topPaddingPx, 0)
return Offset.Zero // We never consume it
}
}
Expand Down Expand Up @@ -582,12 +578,11 @@ fun AnimatedVisibilityScope.GalleryListScreen(lub: ListUrlBuilder, navigator: De
showPages = showPages,
)
},
searchBarOffsetY = { searchBarOffsetY },
scrollBehavior = scrollBehaviour,
onRefresh = {
urlBuilder.setRange(0)
data.refresh()
},
onLoading = { searchBarOffsetY = 0 },
)
}

Expand Down
Loading