Extract common part of GalleryList and Favorites (#338)
* Extract common part of GalleryList and Favorites * Scroll to top after refreshing
This commit is contained in:
1 parent
dd06d82cd9
commit
fec2c39364
4 files changed
+368
-346
No files matched your search
@@ -35,6 +35,7 @@ data class ListUrlBuilder(
|
||||
var mode: Int = MODE_NORMAL,
|
||||
private var mPrev: String? = null,
|
||||
var mNext: String? = null,
|
||||
// Reset to null after initial loading
|
||||
var mJumpTo: String? = null,
|
||||
var category: Int = EhUtils.NONE,
|
||||
private var mKeyword: String? = null,
|
||||
@@ -48,6 +49,23 @@ data class ListUrlBuilder(
|
||||
var isOnlySearchCovers: Boolean = false,
|
||||
) : Parcelable {
|
||||
|
||||
fun reset() {
|
||||
mode = MODE_NORMAL
|
||||
mPrev = null
|
||||
mNext = null
|
||||
mJumpTo = null
|
||||
this.category = EhUtils.NONE
|
||||
mKeyword = null
|
||||
advanceSearch = -1
|
||||
minRating = -1
|
||||
pageFrom = -1
|
||||
pageTo = -1
|
||||
imagePath = null
|
||||
isUseSimilarityScan = false
|
||||
isOnlySearchCovers = false
|
||||
hash = null
|
||||
}
|
||||
|
||||
fun setIndex(index: String?, isNext: Boolean = true) {
|
||||
mNext = index?.takeIf { isNext }
|
||||
mPrev = index?.takeUnless { isNext }
|
||||
@@ -63,7 +81,8 @@ data class ListUrlBuilder(
|
||||
mKeyword = keyword
|
||||
}
|
||||
|
||||
constructor(q: QuickSearch) : this() {
|
||||
fun set(q: QuickSearch) {
|
||||
reset()
|
||||
mode = q.mode
|
||||
this.category = q.category
|
||||
mKeyword = q.keyword
|
||||
@@ -355,9 +374,7 @@ data class ListUrlBuilder(
|
||||
buildString {
|
||||
append(EhUrl.HOST_E)
|
||||
append("toplist.php?tl=")
|
||||
mKeyword.orEmpty().let {
|
||||
append(encodeUTF8(it))
|
||||
}
|
||||
append(mKeyword!!)
|
||||
mJumpTo?.let {
|
||||
append("&p=").append(it)
|
||||
}
|
||||
|
||||
@@ -5,24 +5,13 @@ import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.compose.foundation.clickable
|
||||
import androidx.compose.foundation.layout.Arrangement
|
||||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.PaddingValues
|
||||
import androidx.compose.foundation.layout.WindowInsets
|
||||
import androidx.compose.foundation.layout.WindowInsetsSides
|
||||
import androidx.compose.foundation.layout.calculateEndPadding
|
||||
import androidx.compose.foundation.layout.calculateStartPadding
|
||||
import androidx.compose.foundation.layout.fillMaxSize
|
||||
import androidx.compose.foundation.layout.height
|
||||
import androidx.compose.foundation.layout.only
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.size
|
||||
import androidx.compose.foundation.layout.systemBars
|
||||
import androidx.compose.foundation.layout.widthIn
|
||||
import androidx.compose.foundation.layout.windowInsetsPadding
|
||||
import androidx.compose.foundation.lazy.grid.GridCells
|
||||
import androidx.compose.foundation.lazy.staggeredgrid.StaggeredGridCells
|
||||
import androidx.compose.foundation.rememberScrollState
|
||||
import androidx.compose.foundation.text2.input.rememberTextFieldState
|
||||
import androidx.compose.foundation.verticalScroll
|
||||
@@ -34,13 +23,10 @@ import androidx.compose.material.icons.filled.DoneAll
|
||||
import androidx.compose.material.icons.filled.Download
|
||||
import androidx.compose.material.icons.filled.Refresh
|
||||
import androidx.compose.material.icons.outlined.FolderSpecial
|
||||
import androidx.compose.material3.CircularProgressIndicator
|
||||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.material3.IconButton
|
||||
import androidx.compose.material3.ListItem
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.ShapeDefaults
|
||||
import androidx.compose.material3.Surface
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.material3.TopAppBar
|
||||
import androidx.compose.material3.pulltorefresh.rememberPullToRefreshState
|
||||
@@ -56,19 +42,13 @@ import androidx.compose.runtime.remember
|
||||
import androidx.compose.runtime.rememberCoroutineScope
|
||||
import androidx.compose.runtime.saveable.rememberSaveable
|
||||
import androidx.compose.runtime.setValue
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.draw.clip
|
||||
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.LocalContext
|
||||
import androidx.compose.ui.platform.LocalLayoutDirection
|
||||
import androidx.compose.ui.res.dimensionResource
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.text.style.TextAlign
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.core.os.bundleOf
|
||||
import androidx.lifecycle.viewModelScope
|
||||
import androidx.navigation.NavController
|
||||
@@ -80,8 +60,6 @@ import androidx.paging.PagingSource
|
||||
import androidx.paging.PagingState
|
||||
import androidx.paging.cachedIn
|
||||
import androidx.paging.compose.collectAsLazyPagingItems
|
||||
import androidx.paging.compose.itemContentType
|
||||
import androidx.paging.compose.itemKey
|
||||
import com.google.android.material.datepicker.CalendarConstraints
|
||||
import com.google.android.material.datepicker.CompositeDateValidator
|
||||
import com.google.android.material.datepicker.DateValidatorPointBackward
|
||||
@@ -96,18 +74,14 @@ import com.hippo.ehviewer.client.data.BaseGalleryInfo
|
||||
import com.hippo.ehviewer.client.data.FavListUrlBuilder
|
||||
import com.hippo.ehviewer.collectAsState
|
||||
import com.hippo.ehviewer.icons.EhIcons
|
||||
import com.hippo.ehviewer.icons.big.SadAndroid
|
||||
import com.hippo.ehviewer.icons.filled.GoTo
|
||||
import com.hippo.ehviewer.ui.MainActivity
|
||||
import com.hippo.ehviewer.ui.main.FabLayout
|
||||
import com.hippo.ehviewer.ui.main.GalleryInfoGridItem
|
||||
import com.hippo.ehviewer.ui.main.GalleryInfoListItem
|
||||
import com.hippo.ehviewer.ui.startDownload
|
||||
import com.hippo.ehviewer.ui.tools.FastScrollLazyVerticalGrid
|
||||
import com.hippo.ehviewer.ui.tools.FastScrollLazyVerticalStaggeredGrid
|
||||
import com.hippo.ehviewer.ui.tools.LocalDialogState
|
||||
import com.hippo.ehviewer.ui.tools.rememberInVM
|
||||
import com.hippo.ehviewer.util.ExceptionUtils
|
||||
import com.hippo.ehviewer.util.findActivity
|
||||
import com.hippo.ehviewer.util.mapToLongArray
|
||||
import com.ramcosta.composedestinations.annotation.Destination
|
||||
@@ -248,12 +222,6 @@ fun FavouritesScreen(navigator: NavController) {
|
||||
data.loadState.refresh is LoadState.NotLoading
|
||||
}
|
||||
|
||||
if (refreshState.isRefreshing) {
|
||||
LaunchedEffect(Unit) {
|
||||
refresh()
|
||||
}
|
||||
}
|
||||
|
||||
val searchBarConnection = remember {
|
||||
object : NestedScrollConnection {
|
||||
override fun onPostScroll(consumed: Offset, available: Offset, source: NestedScrollSource): Offset {
|
||||
@@ -262,7 +230,6 @@ fun FavouritesScreen(navigator: NavController) {
|
||||
}
|
||||
}
|
||||
}
|
||||
val combinedModifier = Modifier.nestedScroll(searchBarConnection).nestedScroll(refreshState.nestedScrollConnection)
|
||||
|
||||
var expanded by remember { mutableStateOf(false) }
|
||||
var hidden by remember { mutableStateOf(false) }
|
||||
@@ -288,167 +255,73 @@ fun FavouritesScreen(navigator: NavController) {
|
||||
}
|
||||
},
|
||||
) {
|
||||
val layoutDirection = LocalLayoutDirection.current
|
||||
val marginH = dimensionResource(id = R.dimen.gallery_list_margin_h)
|
||||
val marginV = dimensionResource(id = R.dimen.gallery_list_margin_v)
|
||||
val realPadding = PaddingValues(
|
||||
top = it.calculateTopPadding() + marginV,
|
||||
bottom = it.calculateBottomPadding() + marginV,
|
||||
start = it.calculateStartPadding(layoutDirection) + marginH,
|
||||
end = it.calculateEndPadding(layoutDirection) + marginH,
|
||||
)
|
||||
val listMode by Settings.listMode.collectAsState()
|
||||
Box(modifier = Modifier.fillMaxSize()) {
|
||||
if (listMode == 0) {
|
||||
val height by collectListThumbSizeAsState()
|
||||
val showPages = Settings.showGalleryPages
|
||||
val columnWidth by collectDetailSizeAsState()
|
||||
FastScrollLazyVerticalGrid(
|
||||
columns = GridCells.Adaptive(columnWidth),
|
||||
modifier = combinedModifier,
|
||||
contentPadding = realPadding,
|
||||
verticalArrangement = Arrangement.spacedBy(dimensionResource(R.dimen.gallery_list_interval)),
|
||||
horizontalArrangement = Arrangement.spacedBy(dimensionResource(R.dimen.gallery_list_interval)),
|
||||
) {
|
||||
items(
|
||||
count = data.itemCount,
|
||||
key = data.itemKey(key = { item -> item.gid }),
|
||||
contentType = data.itemContentType(),
|
||||
) { index ->
|
||||
val info = data[index]
|
||||
if (info != null) {
|
||||
val checked = info.gid in checkedInfoMap
|
||||
CheckableItem(checked = checked) {
|
||||
GalleryInfoListItem(
|
||||
onClick = {
|
||||
if (selectMode) {
|
||||
if (checked) {
|
||||
checkedInfoMap.remove(info.gid)
|
||||
} else {
|
||||
checkedInfoMap[info.gid] = info
|
||||
}
|
||||
} else {
|
||||
navigator.navAnimated(
|
||||
R.id.galleryDetailScene,
|
||||
bundleOf(GalleryDetailScene.KEY_ARGS to GalleryInfoArgs(info)),
|
||||
)
|
||||
}
|
||||
},
|
||||
onLongClick = {
|
||||
selectMode = true
|
||||
checkedInfoMap[info.gid] = info
|
||||
},
|
||||
info = info,
|
||||
isInFavScene = true,
|
||||
showPages = showPages,
|
||||
modifier = Modifier.height(height),
|
||||
val height by collectListThumbSizeAsState()
|
||||
val showPages = Settings.showGalleryPages
|
||||
GalleryList(
|
||||
data = data,
|
||||
contentModifier = Modifier.nestedScroll(searchBarConnection),
|
||||
contentPadding = it,
|
||||
listMode = listMode,
|
||||
detailItemContent = { info ->
|
||||
val checked = info.gid in checkedInfoMap
|
||||
CheckableItem(checked = checked) {
|
||||
GalleryInfoListItem(
|
||||
onClick = {
|
||||
if (selectMode) {
|
||||
if (checked) {
|
||||
checkedInfoMap.remove(info.gid)
|
||||
} else {
|
||||
checkedInfoMap[info.gid] = info
|
||||
}
|
||||
} else {
|
||||
navigator.navAnimated(
|
||||
R.id.galleryDetailScene,
|
||||
bundleOf(GalleryDetailScene.KEY_ARGS to GalleryInfoArgs(info)),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
onLongClick = {
|
||||
selectMode = true
|
||||
checkedInfoMap[info.gid] = info
|
||||
},
|
||||
info = info,
|
||||
isInFavScene = true,
|
||||
showPages = showPages,
|
||||
modifier = Modifier.height(height),
|
||||
)
|
||||
}
|
||||
} else {
|
||||
val gridInterval = dimensionResource(R.dimen.gallery_grid_interval)
|
||||
val thumbWidth by Settings.thumbSizeDp.collectAsState()
|
||||
FastScrollLazyVerticalStaggeredGrid(
|
||||
columns = StaggeredGridCells.Adaptive(thumbWidth.dp),
|
||||
modifier = combinedModifier,
|
||||
verticalItemSpacing = gridInterval,
|
||||
horizontalArrangement = Arrangement.spacedBy(gridInterval),
|
||||
contentPadding = realPadding,
|
||||
) {
|
||||
items(
|
||||
count = data.itemCount,
|
||||
key = data.itemKey(key = { item -> item.gid }),
|
||||
contentType = data.itemContentType(),
|
||||
) { index ->
|
||||
val info = data[index]
|
||||
if (info != null) {
|
||||
val checked = info.gid in checkedInfoMap
|
||||
CheckableItem(checked = checked) {
|
||||
GalleryInfoGridItem(
|
||||
onClick = {
|
||||
if (selectMode) {
|
||||
if (checked) {
|
||||
checkedInfoMap.remove(info.gid)
|
||||
} else {
|
||||
checkedInfoMap[info.gid] = info
|
||||
}
|
||||
} else {
|
||||
navigator.navAnimated(
|
||||
R.id.galleryDetailScene,
|
||||
bundleOf(GalleryDetailScene.KEY_ARGS to GalleryInfoArgs(info)),
|
||||
)
|
||||
}
|
||||
},
|
||||
onLongClick = {
|
||||
selectMode = true
|
||||
checkedInfoMap[info.gid] = info
|
||||
},
|
||||
info = info,
|
||||
},
|
||||
thumbItemContent = { info ->
|
||||
val checked = info.gid in checkedInfoMap
|
||||
CheckableItem(checked = checked) {
|
||||
GalleryInfoGridItem(
|
||||
onClick = {
|
||||
if (selectMode) {
|
||||
if (checked) {
|
||||
checkedInfoMap.remove(info.gid)
|
||||
} else {
|
||||
checkedInfoMap[info.gid] = info
|
||||
}
|
||||
} else {
|
||||
navigator.navAnimated(
|
||||
R.id.galleryDetailScene,
|
||||
bundleOf(GalleryDetailScene.KEY_ARGS to GalleryInfoArgs(info)),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
onLongClick = {
|
||||
selectMode = true
|
||||
checkedInfoMap[info.gid] = info
|
||||
},
|
||||
info = info,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
var refreshing by remember { mutableStateOf(false) }
|
||||
when (val state = data.loadState.refresh) {
|
||||
is LoadState.Loading -> if (!refreshState.isRefreshing) {
|
||||
Surface {
|
||||
Box(
|
||||
modifier = Modifier.fillMaxSize(),
|
||||
contentAlignment = Alignment.Center,
|
||||
) {
|
||||
CircularProgressIndicator()
|
||||
}
|
||||
}
|
||||
} else {
|
||||
refreshing = true
|
||||
}
|
||||
is LoadState.Error -> {
|
||||
Surface {
|
||||
Box(
|
||||
modifier = Modifier.fillMaxSize(),
|
||||
contentAlignment = Alignment.Center,
|
||||
) {
|
||||
Column(
|
||||
modifier = Modifier.widthIn(max = 228.dp)
|
||||
.clip(ShapeDefaults.Small).clickable { data.retry() },
|
||||
horizontalAlignment = Alignment.CenterHorizontally,
|
||||
) {
|
||||
Icon(
|
||||
imageVector = EhIcons.Big.Default.SadAndroid,
|
||||
contentDescription = null,
|
||||
modifier = Modifier.padding(16.dp).size(120.dp),
|
||||
tint = MaterialTheme.colorScheme.tertiary,
|
||||
)
|
||||
Text(
|
||||
text = ExceptionUtils.getReadableString(state.error),
|
||||
style = MaterialTheme.typography.bodyLarge,
|
||||
textAlign = TextAlign.Center,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
SideEffect {
|
||||
if (refreshing) {
|
||||
refreshState.endRefresh()
|
||||
refreshing = false
|
||||
}
|
||||
}
|
||||
}
|
||||
is LoadState.NotLoading -> SideEffect {
|
||||
// Don't use `refreshState.isRefreshing` here because recomposition may happen
|
||||
// before loading state changes
|
||||
if (refreshing) {
|
||||
refreshState.endRefresh()
|
||||
refreshing = false
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
refreshState = refreshState,
|
||||
onRefresh = { refresh() },
|
||||
navigator = navigator,
|
||||
)
|
||||
}
|
||||
|
||||
// Explicitly reallocate fabBuilder lambda to recompose secondary fab
|
||||
|
||||
@@ -0,0 +1,223 @@
|
||||
package com.hippo.ehviewer.ui.scene
|
||||
|
||||
import androidx.compose.foundation.clickable
|
||||
import androidx.compose.foundation.layout.Arrangement
|
||||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.PaddingValues
|
||||
import androidx.compose.foundation.layout.calculateEndPadding
|
||||
import androidx.compose.foundation.layout.calculateStartPadding
|
||||
import androidx.compose.foundation.layout.fillMaxSize
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.size
|
||||
import androidx.compose.foundation.layout.widthIn
|
||||
import androidx.compose.foundation.lazy.grid.GridCells
|
||||
import androidx.compose.foundation.lazy.grid.LazyGridItemScope
|
||||
import androidx.compose.foundation.lazy.grid.LazyGridState
|
||||
import androidx.compose.foundation.lazy.grid.rememberLazyGridState
|
||||
import androidx.compose.foundation.lazy.staggeredgrid.LazyStaggeredGridItemScope
|
||||
import androidx.compose.foundation.lazy.staggeredgrid.LazyStaggeredGridState
|
||||
import androidx.compose.foundation.lazy.staggeredgrid.StaggeredGridCells
|
||||
import androidx.compose.foundation.lazy.staggeredgrid.rememberLazyStaggeredGridState
|
||||
import androidx.compose.material3.CircularProgressIndicator
|
||||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.ShapeDefaults
|
||||
import androidx.compose.material3.Surface
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.material3.pulltorefresh.PullToRefreshState
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.LaunchedEffect
|
||||
import androidx.compose.runtime.SideEffect
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.runtime.setValue
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.draw.clip
|
||||
import androidx.compose.ui.input.nestedscroll.nestedScroll
|
||||
import androidx.compose.ui.platform.LocalLayoutDirection
|
||||
import androidx.compose.ui.res.dimensionResource
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.text.style.TextAlign
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.core.os.bundleOf
|
||||
import androidx.navigation.NavController
|
||||
import androidx.paging.LoadState
|
||||
import androidx.paging.compose.LazyPagingItems
|
||||
import androidx.paging.compose.itemContentType
|
||||
import androidx.paging.compose.itemKey
|
||||
import com.hippo.ehviewer.R
|
||||
import com.hippo.ehviewer.Settings
|
||||
import com.hippo.ehviewer.client.EhUrl
|
||||
import com.hippo.ehviewer.client.data.BaseGalleryInfo
|
||||
import com.hippo.ehviewer.client.exception.CloudflareBypassException
|
||||
import com.hippo.ehviewer.collectAsState
|
||||
import com.hippo.ehviewer.icons.EhIcons
|
||||
import com.hippo.ehviewer.icons.big.SadAndroid
|
||||
import com.hippo.ehviewer.ui.WebViewActivity
|
||||
import com.hippo.ehviewer.ui.tools.FastScrollLazyVerticalGrid
|
||||
import com.hippo.ehviewer.ui.tools.FastScrollLazyVerticalStaggeredGrid
|
||||
import com.hippo.ehviewer.ui.tools.LocalDialogState
|
||||
import com.hippo.ehviewer.util.ExceptionUtils
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
|
||||
@Composable
|
||||
fun GalleryList(
|
||||
modifier: Modifier = Modifier,
|
||||
data: LazyPagingItems<BaseGalleryInfo>,
|
||||
contentModifier: Modifier = Modifier,
|
||||
contentPadding: PaddingValues = PaddingValues(0.dp),
|
||||
listMode: Int = 0,
|
||||
detailListState: LazyGridState = rememberLazyGridState(),
|
||||
detailItemContent: @Composable (LazyGridItemScope.(BaseGalleryInfo) -> Unit),
|
||||
thumbListState: LazyStaggeredGridState = rememberLazyStaggeredGridState(),
|
||||
thumbItemContent: @Composable (LazyStaggeredGridItemScope.(BaseGalleryInfo) -> Unit) = {},
|
||||
refreshState: PullToRefreshState? = null,
|
||||
onRefresh: suspend CoroutineScope.() -> Unit = {},
|
||||
navigator: NavController? = null,
|
||||
) {
|
||||
val layoutDirection = LocalLayoutDirection.current
|
||||
val marginH = dimensionResource(id = R.dimen.gallery_list_margin_h)
|
||||
val marginV = dimensionResource(id = R.dimen.gallery_list_margin_v)
|
||||
val realPadding = PaddingValues(
|
||||
top = contentPadding.calculateTopPadding() + marginV,
|
||||
bottom = contentPadding.calculateBottomPadding() + marginV,
|
||||
start = contentPadding.calculateStartPadding(layoutDirection) + marginH,
|
||||
end = contentPadding.calculateEndPadding(layoutDirection) + marginH,
|
||||
)
|
||||
val combinedModifier = if (refreshState != null) {
|
||||
contentModifier.nestedScroll(refreshState.nestedScrollConnection)
|
||||
} else {
|
||||
contentModifier
|
||||
}
|
||||
Box(modifier = modifier.fillMaxSize()) {
|
||||
if (listMode == 0) {
|
||||
val columnWidth by collectDetailSizeAsState()
|
||||
FastScrollLazyVerticalGrid(
|
||||
columns = GridCells.Adaptive(columnWidth),
|
||||
modifier = combinedModifier,
|
||||
state = detailListState,
|
||||
contentPadding = realPadding,
|
||||
verticalArrangement = Arrangement.spacedBy(dimensionResource(R.dimen.gallery_list_interval)),
|
||||
horizontalArrangement = Arrangement.spacedBy(dimensionResource(R.dimen.gallery_list_interval)),
|
||||
) {
|
||||
items(
|
||||
count = data.itemCount,
|
||||
key = data.itemKey(key = { item -> item.gid }),
|
||||
contentType = data.itemContentType(),
|
||||
) { index ->
|
||||
val info = data[index]
|
||||
if (info != null) {
|
||||
detailItemContent(info)
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
val gridInterval = dimensionResource(R.dimen.gallery_grid_interval)
|
||||
val thumbWidth by Settings.thumbSizeDp.collectAsState()
|
||||
FastScrollLazyVerticalStaggeredGrid(
|
||||
columns = StaggeredGridCells.Adaptive(thumbWidth.dp),
|
||||
modifier = combinedModifier,
|
||||
state = thumbListState,
|
||||
verticalItemSpacing = gridInterval,
|
||||
horizontalArrangement = Arrangement.spacedBy(gridInterval),
|
||||
contentPadding = realPadding,
|
||||
) {
|
||||
items(
|
||||
count = data.itemCount,
|
||||
key = data.itemKey(key = { item -> item.gid }),
|
||||
contentType = data.itemContentType(),
|
||||
) { index ->
|
||||
val info = data[index]
|
||||
if (info != null) {
|
||||
thumbItemContent(info)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (refreshState != null) {
|
||||
if (refreshState.isRefreshing) {
|
||||
LaunchedEffect(Unit) {
|
||||
onRefresh()
|
||||
}
|
||||
}
|
||||
|
||||
val dialogState = LocalDialogState.current
|
||||
var refreshing by remember { mutableStateOf(false) }
|
||||
when (val state = data.loadState.refresh) {
|
||||
is LoadState.Loading -> if (!refreshState.isRefreshing) {
|
||||
LaunchedEffect(Unit) {
|
||||
if (listMode == 0) {
|
||||
detailListState.scrollToItem(0)
|
||||
} else {
|
||||
thumbListState.scrollToItem(0)
|
||||
}
|
||||
}
|
||||
Surface {
|
||||
Box(
|
||||
modifier = Modifier.fillMaxSize(),
|
||||
contentAlignment = Alignment.Center,
|
||||
) {
|
||||
CircularProgressIndicator()
|
||||
}
|
||||
}
|
||||
} else {
|
||||
refreshing = true
|
||||
}
|
||||
|
||||
is LoadState.Error -> {
|
||||
Surface {
|
||||
LaunchedEffect(state) {
|
||||
if (state.error.cause is CloudflareBypassException) {
|
||||
dialogState.awaitPermissionOrCancel(title = R.string.cloudflare_bypass_failed) {
|
||||
Text(text = stringResource(id = R.string.open_in_webview))
|
||||
}
|
||||
navigator?.navAnimated(R.id.webView, bundleOf(WebViewActivity.KEY_URL to EhUrl.host))
|
||||
}
|
||||
}
|
||||
Box(
|
||||
modifier = Modifier.fillMaxSize(),
|
||||
contentAlignment = Alignment.Center,
|
||||
) {
|
||||
Column(
|
||||
modifier = Modifier.widthIn(max = 228.dp)
|
||||
.clip(ShapeDefaults.Small).clickable { data.retry() },
|
||||
horizontalAlignment = Alignment.CenterHorizontally,
|
||||
) {
|
||||
Icon(
|
||||
imageVector = EhIcons.Big.Default.SadAndroid,
|
||||
contentDescription = null,
|
||||
modifier = Modifier.padding(16.dp).size(120.dp),
|
||||
tint = MaterialTheme.colorScheme.tertiary,
|
||||
)
|
||||
Text(
|
||||
text = ExceptionUtils.getReadableString(state.error),
|
||||
style = MaterialTheme.typography.bodyLarge,
|
||||
textAlign = TextAlign.Center,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
SideEffect {
|
||||
if (refreshing) {
|
||||
refreshState.endRefresh()
|
||||
refreshing = false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
is LoadState.NotLoading -> SideEffect {
|
||||
// Don't use `refreshState.isRefreshing` here because recomposition may happen
|
||||
// before loading state changes
|
||||
if (refreshing) {
|
||||
refreshState.endRefresh()
|
||||
refreshing = false
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -13,10 +13,8 @@ import androidx.compose.animation.AnimatedVisibility
|
||||
import androidx.compose.animation.core.animateDpAsState
|
||||
import androidx.compose.animation.core.tween
|
||||
import androidx.compose.foundation.clickable
|
||||
import androidx.compose.foundation.layout.Arrangement
|
||||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.PaddingValues
|
||||
import androidx.compose.foundation.layout.WindowInsets
|
||||
import androidx.compose.foundation.layout.WindowInsetsSides
|
||||
import androidx.compose.foundation.layout.asPaddingValues
|
||||
@@ -28,16 +26,12 @@ import androidx.compose.foundation.layout.height
|
||||
import androidx.compose.foundation.layout.imePadding
|
||||
import androidx.compose.foundation.layout.only
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.size
|
||||
import androidx.compose.foundation.layout.systemBars
|
||||
import androidx.compose.foundation.layout.widthIn
|
||||
import androidx.compose.foundation.layout.windowInsetsPadding
|
||||
import androidx.compose.foundation.lazy.LazyColumn
|
||||
import androidx.compose.foundation.lazy.grid.GridCells
|
||||
import androidx.compose.foundation.lazy.grid.rememberLazyGridState
|
||||
import androidx.compose.foundation.lazy.items
|
||||
import androidx.compose.foundation.lazy.rememberLazyListState
|
||||
import androidx.compose.foundation.lazy.staggeredgrid.StaggeredGridCells
|
||||
import androidx.compose.foundation.lazy.staggeredgrid.rememberLazyStaggeredGridState
|
||||
import androidx.compose.foundation.rememberScrollState
|
||||
import androidx.compose.foundation.text2.input.rememberTextFieldState
|
||||
@@ -52,7 +46,6 @@ import androidx.compose.material.icons.filled.Refresh
|
||||
import androidx.compose.material.icons.filled.Reorder
|
||||
import androidx.compose.material.icons.filled.Translate
|
||||
import androidx.compose.material.icons.outlined.Bookmarks
|
||||
import androidx.compose.material3.CircularProgressIndicator
|
||||
import androidx.compose.material3.DismissDirection
|
||||
import androidx.compose.material3.DismissValue
|
||||
import androidx.compose.material3.ElevatedCard
|
||||
@@ -63,7 +56,6 @@ import androidx.compose.material3.LeadingIconTab
|
||||
import androidx.compose.material3.ListItem
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.PrimaryTabRow
|
||||
import androidx.compose.material3.ShapeDefaults
|
||||
import androidx.compose.material3.SnackbarHost
|
||||
import androidx.compose.material3.SnackbarHostState
|
||||
import androidx.compose.material3.SwipeToDismissBox
|
||||
@@ -76,7 +68,6 @@ import androidx.compose.material3.windowsizeclass.calculateWindowSizeClass
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.CompositionLocalProvider
|
||||
import androidx.compose.runtime.LaunchedEffect
|
||||
import androidx.compose.runtime.SideEffect
|
||||
import androidx.compose.runtime.Stable
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.mutableIntStateOf
|
||||
@@ -89,7 +80,6 @@ import androidx.compose.runtime.setValue
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.draw.alpha
|
||||
import androidx.compose.ui.draw.clip
|
||||
import androidx.compose.ui.draw.rotate
|
||||
import androidx.compose.ui.draw.scale
|
||||
import androidx.compose.ui.geometry.Offset
|
||||
@@ -104,7 +94,6 @@ import androidx.compose.ui.res.dimensionResource
|
||||
import androidx.compose.ui.res.stringArrayResource
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.text.font.FontWeight
|
||||
import androidx.compose.ui.text.style.TextAlign
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.util.fastAny
|
||||
import androidx.compose.ui.util.fastForEach
|
||||
@@ -120,8 +109,6 @@ import androidx.paging.PagingSource
|
||||
import androidx.paging.PagingState
|
||||
import androidx.paging.cachedIn
|
||||
import androidx.paging.compose.collectAsLazyPagingItems
|
||||
import androidx.paging.compose.itemContentType
|
||||
import androidx.paging.compose.itemKey
|
||||
import com.google.android.material.datepicker.CalendarConstraints
|
||||
import com.google.android.material.datepicker.CalendarConstraints.DateValidator
|
||||
import com.google.android.material.datepicker.CompositeDateValidator
|
||||
@@ -133,7 +120,6 @@ import com.hippo.ehviewer.R
|
||||
import com.hippo.ehviewer.Settings
|
||||
import com.hippo.ehviewer.client.EhEngine
|
||||
import com.hippo.ehviewer.client.EhTagDatabase
|
||||
import com.hippo.ehviewer.client.EhUrl
|
||||
import com.hippo.ehviewer.client.EhUtils
|
||||
import com.hippo.ehviewer.client.data.BaseGalleryInfo
|
||||
import com.hippo.ehviewer.client.data.ListUrlBuilder
|
||||
@@ -144,17 +130,14 @@ import com.hippo.ehviewer.client.data.ListUrlBuilder.Companion.MODE_TAG
|
||||
import com.hippo.ehviewer.client.data.ListUrlBuilder.Companion.MODE_TOPLIST
|
||||
import com.hippo.ehviewer.client.data.ListUrlBuilder.Companion.MODE_UPLOADER
|
||||
import com.hippo.ehviewer.client.data.ListUrlBuilder.Companion.MODE_WHATS_HOT
|
||||
import com.hippo.ehviewer.client.exception.CloudflareBypassException
|
||||
import com.hippo.ehviewer.client.parser.GalleryDetailUrlParser
|
||||
import com.hippo.ehviewer.client.parser.GalleryPageUrlParser
|
||||
import com.hippo.ehviewer.collectAsState
|
||||
import com.hippo.ehviewer.dao.QuickSearch
|
||||
import com.hippo.ehviewer.icons.EhIcons
|
||||
import com.hippo.ehviewer.icons.big.SadAndroid
|
||||
import com.hippo.ehviewer.icons.filled.GoTo
|
||||
import com.hippo.ehviewer.image.Image.Companion.decodeBitmap
|
||||
import com.hippo.ehviewer.ui.MainActivity
|
||||
import com.hippo.ehviewer.ui.WebViewActivity
|
||||
import com.hippo.ehviewer.ui.doGalleryInfoAction
|
||||
import com.hippo.ehviewer.ui.legacy.BaseDialogBuilder
|
||||
import com.hippo.ehviewer.ui.legacy.FAB_ANIMATE_TIME
|
||||
@@ -167,15 +150,12 @@ import com.hippo.ehviewer.ui.main.NormalSearch
|
||||
import com.hippo.ehviewer.ui.main.SearchAdvanced
|
||||
import com.hippo.ehviewer.ui.scene.GalleryListFragment.Companion.toStartArgs
|
||||
import com.hippo.ehviewer.ui.tools.Deferred
|
||||
import com.hippo.ehviewer.ui.tools.FastScrollLazyVerticalGrid
|
||||
import com.hippo.ehviewer.ui.tools.FastScrollLazyVerticalStaggeredGrid
|
||||
import com.hippo.ehviewer.ui.tools.LocalDialogState
|
||||
import com.hippo.ehviewer.ui.tools.LocalTouchSlopProvider
|
||||
import com.hippo.ehviewer.ui.tools.animateFloatMergePredictiveBackAsState
|
||||
import com.hippo.ehviewer.ui.tools.observed
|
||||
import com.hippo.ehviewer.ui.tools.rememberInVM
|
||||
import com.hippo.ehviewer.util.AppConfig
|
||||
import com.hippo.ehviewer.util.ExceptionUtils
|
||||
import com.hippo.ehviewer.util.findActivity
|
||||
import com.hippo.ehviewer.util.getParcelableCompat
|
||||
import com.hippo.ehviewer.util.isAtLeastOMR1
|
||||
@@ -248,7 +228,7 @@ fun GalleryListScreen(lub: ListUrlBuilder, navigator: NavController) {
|
||||
val exHint = stringResource(R.string.gallery_list_search_bar_hint_exhentai)
|
||||
val searchBarHint = remember { if (EhUtils.isExHentai) exHint else ehHint }
|
||||
val suitableTitle = getSuitableTitleForUrlBuilder(urlBuilder)
|
||||
val data = rememberInVM(urlBuilder) {
|
||||
val data = rememberInVM {
|
||||
Pager(PagingConfig(25)) {
|
||||
object : PagingSource<String, BaseGalleryInfo>() {
|
||||
override fun getRefreshKey(state: PagingState<String, BaseGalleryInfo>): String? = null
|
||||
@@ -264,6 +244,7 @@ fun GalleryListScreen(lub: ListUrlBuilder, navigator: NavController) {
|
||||
}.onFailure {
|
||||
return@withIOContext LoadResult.Error(it)
|
||||
}.onSuccess {
|
||||
urlBuilder.mJumpTo = null
|
||||
return@withIOContext LoadResult.Page(it.galleryInfoList, prev?.toString(), next?.toString())
|
||||
}
|
||||
}
|
||||
@@ -331,7 +312,8 @@ fun GalleryListScreen(lub: ListUrlBuilder, navigator: NavController) {
|
||||
ListItem(
|
||||
modifier = Modifier.clickable {
|
||||
Settings.recentToplist = keyword
|
||||
urlBuilder = ListUrlBuilder(MODE_TOPLIST, mKeyword = keyword)
|
||||
urlBuilder.keyword = keyword
|
||||
data.refresh()
|
||||
showSearchLayout = false
|
||||
coroutineScope.launch { sheetState.close() }
|
||||
},
|
||||
@@ -485,9 +467,10 @@ fun GalleryListScreen(lub: ListUrlBuilder, navigator: NavController) {
|
||||
ListItem(
|
||||
modifier = Modifier.clickable {
|
||||
if (urlBuilder.mode == MODE_WHATS_HOT) {
|
||||
navigator.navAnimated(R.id.galleryListScene, ListUrlBuilder(item).toStartArgs())
|
||||
navigator.navAnimated(R.id.galleryListScene, ListUrlBuilder().apply { set(item) }.toStartArgs())
|
||||
} else {
|
||||
urlBuilder = ListUrlBuilder(item)
|
||||
urlBuilder.set(item)
|
||||
data.refresh()
|
||||
}
|
||||
showSearchLayout = false
|
||||
coroutineScope.launch { sheetState.close() }
|
||||
@@ -556,14 +539,6 @@ fun GalleryListScreen(lub: ListUrlBuilder, navigator: NavController) {
|
||||
data.loadState.refresh is LoadState.NotLoading
|
||||
}
|
||||
|
||||
if (refreshState.isRefreshing) {
|
||||
LaunchedEffect(Unit) {
|
||||
urlBuilder.setIndex(null, true)
|
||||
urlBuilder.mJumpTo = null
|
||||
data.refresh()
|
||||
}
|
||||
}
|
||||
|
||||
var hidden by remember { mutableStateOf(false) }
|
||||
val searchBarConnection = remember {
|
||||
val slop = ViewConfiguration.get(context).scaledTouchSlop
|
||||
@@ -580,7 +555,6 @@ fun GalleryListScreen(lub: ListUrlBuilder, navigator: NavController) {
|
||||
}
|
||||
}
|
||||
}
|
||||
val combinedModifier = Modifier.nestedScroll(searchBarConnection).nestedScroll(refreshState.nestedScrollConnection)
|
||||
|
||||
val openGalleryKeyword = stringResource(R.string.gallery_list_search_bar_open_gallery)
|
||||
abstract class UrlSuggestion : Suggestion() {
|
||||
@@ -679,7 +653,10 @@ fun GalleryListScreen(lub: ListUrlBuilder, navigator: NavController) {
|
||||
delay(300)
|
||||
withUIContext { navigator.navAnimated(R.id.galleryListScene, builder.toStartArgs()) }
|
||||
}
|
||||
else -> urlBuilder = builder
|
||||
else -> {
|
||||
urlBuilder = builder
|
||||
data.refresh()
|
||||
}
|
||||
}
|
||||
showSearchLayout = false
|
||||
},
|
||||
@@ -711,19 +688,12 @@ fun GalleryListScreen(lub: ListUrlBuilder, navigator: NavController) {
|
||||
val layoutDirection = LocalLayoutDirection.current
|
||||
val marginH = dimensionResource(id = R.dimen.gallery_list_margin_h)
|
||||
val marginV = dimensionResource(id = R.dimen.gallery_list_margin_v)
|
||||
val realPadding = PaddingValues(
|
||||
top = paddingValues.calculateTopPadding() + marginV,
|
||||
bottom = paddingValues.calculateBottomPadding() + marginV,
|
||||
start = paddingValues.calculateStartPadding(layoutDirection) + marginH,
|
||||
end = paddingValues.calculateEndPadding(layoutDirection) + marginH,
|
||||
)
|
||||
|
||||
Column(
|
||||
modifier = Modifier.imePadding().verticalScroll(rememberScrollState())
|
||||
.padding(
|
||||
top = realPadding.calculateTopPadding(),
|
||||
start = realPadding.calculateStartPadding(layoutDirection),
|
||||
end = realPadding.calculateEndPadding(layoutDirection),
|
||||
top = paddingValues.calculateTopPadding() + marginV,
|
||||
start = paddingValues.calculateStartPadding(layoutDirection) + marginH,
|
||||
end = paddingValues.calculateEndPadding(layoutDirection) + marginH,
|
||||
bottom = 8.dp,
|
||||
)
|
||||
.windowInsetsPadding(WindowInsets.systemBars.only(WindowInsetsSides.Bottom))
|
||||
@@ -820,118 +790,58 @@ fun GalleryListScreen(lub: ListUrlBuilder, navigator: NavController) {
|
||||
}
|
||||
}
|
||||
|
||||
Box(modifier = Modifier.fillMaxSize().scale(animatedSearchLayout).alpha(animatedSearchLayout)) {
|
||||
when (val loadState = data.loadState.refresh) {
|
||||
is LoadState.Loading -> if (data.itemCount == 0) {
|
||||
CircularProgressIndicator(modifier = Modifier.align(Alignment.Center))
|
||||
}
|
||||
is LoadState.Error -> {
|
||||
LaunchedEffect(loadState) {
|
||||
if (loadState.error.cause is CloudflareBypassException) {
|
||||
dialogState.awaitPermissionOrCancel(title = R.string.cloudflare_bypass_failed) {
|
||||
Text(text = stringResource(id = R.string.open_in_webview))
|
||||
}
|
||||
withUIContext { navigator.navAnimated(R.id.webView, bundleOf(WebViewActivity.KEY_URL to EhUrl.host)) }
|
||||
}
|
||||
}
|
||||
Column(
|
||||
modifier = Modifier.align(Alignment.Center).widthIn(max = 228.dp)
|
||||
.clip(ShapeDefaults.Small).clickable { data.retry() },
|
||||
horizontalAlignment = Alignment.CenterHorizontally,
|
||||
) {
|
||||
Icon(
|
||||
imageVector = EhIcons.Big.Default.SadAndroid,
|
||||
contentDescription = null,
|
||||
modifier = Modifier.padding(16.dp).size(120.dp),
|
||||
tint = MaterialTheme.colorScheme.tertiary,
|
||||
val height by collectListThumbSizeAsState()
|
||||
val showPages = Settings.showGalleryPages
|
||||
GalleryList(
|
||||
modifier = Modifier.scale(animatedSearchLayout).alpha(animatedSearchLayout),
|
||||
data = data,
|
||||
contentModifier = Modifier.nestedScroll(searchBarConnection),
|
||||
contentPadding = paddingValues,
|
||||
listMode = listMode,
|
||||
detailListState = listState,
|
||||
detailItemContent = { info ->
|
||||
GalleryInfoListItem(
|
||||
onClick = {
|
||||
navigator.navAnimated(
|
||||
R.id.galleryDetailScene,
|
||||
bundleOf(GalleryDetailScene.KEY_ARGS to GalleryInfoArgs(info)),
|
||||
)
|
||||
Text(
|
||||
text = ExceptionUtils.getReadableString(loadState.error),
|
||||
style = MaterialTheme.typography.bodyLarge,
|
||||
textAlign = TextAlign.Center,
|
||||
},
|
||||
onLongClick = {
|
||||
coroutineScope.launch {
|
||||
dialogState.doGalleryInfoAction(info, context)
|
||||
}
|
||||
},
|
||||
info = info,
|
||||
isInFavScene = false,
|
||||
showPages = showPages,
|
||||
modifier = Modifier.height(height),
|
||||
)
|
||||
},
|
||||
thumbListState = gridState,
|
||||
thumbItemContent = { info ->
|
||||
GalleryInfoGridItem(
|
||||
onClick = {
|
||||
navigator.navAnimated(
|
||||
R.id.galleryDetailScene,
|
||||
bundleOf(GalleryDetailScene.KEY_ARGS to GalleryInfoArgs(info)),
|
||||
)
|
||||
}
|
||||
}
|
||||
is LoadState.NotLoading -> SideEffect {
|
||||
refreshState.endRefresh()
|
||||
}
|
||||
}
|
||||
if (listMode == 0) {
|
||||
val height by collectListThumbSizeAsState()
|
||||
val showPages = Settings.showGalleryPages
|
||||
val columnWidth by collectDetailSizeAsState()
|
||||
FastScrollLazyVerticalGrid(
|
||||
columns = GridCells.Adaptive(columnWidth),
|
||||
modifier = combinedModifier,
|
||||
state = listState,
|
||||
contentPadding = realPadding,
|
||||
verticalArrangement = Arrangement.spacedBy(dimensionResource(R.dimen.gallery_list_interval)),
|
||||
horizontalArrangement = Arrangement.spacedBy(dimensionResource(R.dimen.gallery_list_interval)),
|
||||
) {
|
||||
items(
|
||||
count = data.itemCount,
|
||||
key = data.itemKey(key = { item -> item.gid }),
|
||||
contentType = data.itemContentType(),
|
||||
) { index ->
|
||||
val info = data[index]
|
||||
if (info != null) {
|
||||
GalleryInfoListItem(
|
||||
onClick = {
|
||||
navigator.navAnimated(
|
||||
R.id.galleryDetailScene,
|
||||
bundleOf(GalleryDetailScene.KEY_ARGS to GalleryInfoArgs(info)),
|
||||
)
|
||||
},
|
||||
onLongClick = {
|
||||
coroutineScope.launch {
|
||||
dialogState.doGalleryInfoAction(info, context)
|
||||
}
|
||||
},
|
||||
info = info,
|
||||
isInFavScene = false,
|
||||
showPages = showPages,
|
||||
modifier = Modifier.height(height),
|
||||
)
|
||||
},
|
||||
onLongClick = {
|
||||
coroutineScope.launch {
|
||||
dialogState.doGalleryInfoAction(info, context)
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
val gridInterval = dimensionResource(R.dimen.gallery_grid_interval)
|
||||
val thumbWidth by Settings.thumbSizeDp.collectAsState()
|
||||
FastScrollLazyVerticalStaggeredGrid(
|
||||
columns = StaggeredGridCells.Adaptive(thumbWidth.dp),
|
||||
modifier = combinedModifier,
|
||||
state = gridState,
|
||||
verticalItemSpacing = gridInterval,
|
||||
horizontalArrangement = Arrangement.spacedBy(gridInterval),
|
||||
contentPadding = realPadding,
|
||||
) {
|
||||
items(
|
||||
count = data.itemCount,
|
||||
key = data.itemKey(key = { item -> item.gid }),
|
||||
contentType = data.itemContentType(),
|
||||
) { index ->
|
||||
val info = data[index]
|
||||
if (info != null) {
|
||||
GalleryInfoGridItem(
|
||||
onClick = {
|
||||
navigator.navAnimated(
|
||||
R.id.galleryDetailScene,
|
||||
bundleOf(GalleryDetailScene.KEY_ARGS to GalleryInfoArgs(info)),
|
||||
)
|
||||
},
|
||||
onLongClick = {
|
||||
coroutineScope.launch {
|
||||
dialogState.doGalleryInfoAction(info, context)
|
||||
}
|
||||
},
|
||||
info = info,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
info = info,
|
||||
)
|
||||
},
|
||||
refreshState = refreshState,
|
||||
onRefresh = {
|
||||
urlBuilder.setIndex(null)
|
||||
data.refresh()
|
||||
},
|
||||
navigator = navigator,
|
||||
)
|
||||
}
|
||||
|
||||
val gotoTitle = stringResource(R.string.go_to)
|
||||
@@ -944,8 +854,7 @@ fun GalleryListScreen(lub: ListUrlBuilder, navigator: NavController) {
|
||||
autoCancel = true,
|
||||
) {
|
||||
onClick(Icons.Default.Refresh) {
|
||||
urlBuilder.setIndex(null, true)
|
||||
urlBuilder.mJumpTo = null
|
||||
urlBuilder.setIndex(null)
|
||||
data.refresh()
|
||||
}
|
||||
if (urlBuilder.mode != MODE_WHATS_HOT) {
|
||||
|
||||
Reference in new issue
Block a user