Cleanup ComposeFragment

This commit is contained in:
tarsin committed 2023-07-09 15:28:29 +08:00
1 parent 662fc6859b
commit a3237a024e
2 files changed
+194 -200

No files matched your search

@@ -2,7 +2,6 @@ package com.hippo.ehviewer.ui.scene
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
@@ -70,107 +69,105 @@ import moe.tarsin.coroutines.runSuspendCatching
import my.nanihadesuka.compose.LazyGridScrollbar
class GalleryPreviewScreen : Fragment() {
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View {
return ComposeView(inflater.context).apply {
setMD3Content {
val galleryDetail = remember { requireArguments().getParcelableCompat<GalleryDetail>(KEY_GALLERY_DETAIL)!! }
val context = LocalContext.current
fun onPreviewCLick(index: Int) = context.navToReader(galleryDetail, index)
var toNextPage by rememberSaveable { mutableStateOf(requireArguments().getBoolean(KEY_NEXT_PAGE)) }
val scrollBehaviour = TopAppBarDefaults.pinnedScrollBehavior()
val columnCount = calculateSuitableSpanCount()
val state = rememberLazyGridState()
val dialogState = rememberDialogState()
dialogState.Handler()
val coroutineScope = rememberCoroutineScope { Dispatchers.IO }
val pages = galleryDetail.pages
val pgSize = galleryDetail.previewList.size
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?) = ComposeView(inflater.context).apply {
setMD3Content {
val galleryDetail = remember { requireArguments().getParcelableCompat<GalleryDetail>(KEY_GALLERY_DETAIL)!! }
val context = LocalContext.current
fun onPreviewCLick(index: Int) = context.navToReader(galleryDetail, index)
var toNextPage by rememberSaveable { mutableStateOf(requireArguments().getBoolean(KEY_NEXT_PAGE)) }
val scrollBehaviour = TopAppBarDefaults.pinnedScrollBehavior()
val columnCount = calculateSuitableSpanCount()
val state = rememberLazyGridState()
val dialogState = rememberDialogState()
dialogState.Handler()
val coroutineScope = rememberCoroutineScope { Dispatchers.IO }
val pages = galleryDetail.pages
val pgSize = galleryDetail.previewList.size
LaunchedEffect(Unit) {
if (toNextPage) state.scrollToItem(pgSize)
toNextPage = false
}
LaunchedEffect(Unit) {
if (toNextPage) state.scrollToItem(pgSize)
toNextPage = false
}
suspend fun getPreviewListByPage(page: Int) = galleryDetail.run {
val url = EhUrl.getGalleryDetailUrl(gid, token, page, false)
val result = EhEngine.getPreviewList(url)
if (Settings.preloadThumbAggressively) {
coroutineScope.launch {
context.run { result.first.first.forEach { imageLoader.enqueue(imageRequest(it) { justDownload() }) } }
}
suspend fun getPreviewListByPage(page: Int) = galleryDetail.run {
val url = EhUrl.getGalleryDetailUrl(gid, token, page, false)
val result = EhEngine.getPreviewList(url)
if (Settings.preloadThumbAggressively) {
coroutineScope.launch {
context.run { result.first.first.forEach { imageLoader.enqueue(imageRequest(it) { justDownload() }) } }
}
result.first.first
}
result.first.first
}
val previewPagesMap = rememberMemorized { galleryDetail.previewList.associateBy { it.position } as MutableMap }
val data = remember {
Pager(PagingConfig(pageSize = pgSize, initialLoadSize = pgSize, jumpThreshold = 2 * pgSize)) {
object : PagingSource<Int, GalleryPreview>() {
override fun getRefreshKey(state: PagingState<Int, GalleryPreview>) = state.getClippedRefreshKey()
override suspend fun load(params: LoadParams<Int>): LoadResult<Int, GalleryPreview> {
val key = params.key ?: 0
val up = getOffset(params, key, pages)
val end = (up + getLimit(params, key) - 1).coerceAtMost(pages - 1)
runSuspendCatching {
(up..end).filterNot { it in previewPagesMap }.map { it / pgSize }.toSet()
.parMap(Dispatchers.IO) { getPreviewListByPage(it) }
.forEach { previews -> previews.forEach { previewPagesMap[it.position] = it } }
}.onFailure {
return LoadResult.Error(it)
}
val r = (up..end).map { requireNotNull(previewPagesMap[it]) }
val prevK = if (up <= 0 || r.isEmpty()) null else up
val nextK = if (end == pages - 1) null else end + 1
return LoadResult.Page(r, prevK, nextK, up, pages - end - 1)
val previewPagesMap = rememberMemorized { galleryDetail.previewList.associateBy { it.position } as MutableMap }
val data = remember {
Pager(PagingConfig(pageSize = pgSize, initialLoadSize = pgSize, jumpThreshold = 2 * pgSize)) {
object : PagingSource<Int, GalleryPreview>() {
override fun getRefreshKey(state: PagingState<Int, GalleryPreview>) = state.getClippedRefreshKey()
override suspend fun load(params: LoadParams<Int>): LoadResult<Int, GalleryPreview> {
val key = params.key ?: 0
val up = getOffset(params, key, pages)
val end = (up + getLimit(params, key) - 1).coerceAtMost(pages - 1)
runSuspendCatching {
(up..end).filterNot { it in previewPagesMap }.map { it / pgSize }.toSet()
.parMap(Dispatchers.IO) { getPreviewListByPage(it) }
.forEach { previews -> previews.forEach { previewPagesMap[it.position] = it } }
}.onFailure {
return LoadResult.Error(it)
}
override val jumpingSupported = true
val r = (up..end).map { requireNotNull(previewPagesMap[it]) }
val prevK = if (up <= 0 || r.isEmpty()) null else up
val nextK = if (end == pages - 1) null else end + 1
return LoadResult.Page(r, prevK, nextK, up, pages - end - 1)
}
}.flow.cachedIn(lifecycleScope)
}.collectAsLazyPagingItems()
override val jumpingSupported = true
}
}.flow.cachedIn(lifecycleScope)
}.collectAsLazyPagingItems()
Scaffold(
topBar = {
TopAppBar(
title = { Text(stringResource(R.string.gallery_previews)) },
navigationIcon = {
IconButton(onClick = { findNavController().popBackStack() }) {
Icon(imageVector = Icons.Default.ArrowBack, contentDescription = null)
Scaffold(
topBar = {
TopAppBar(
title = { Text(stringResource(R.string.gallery_previews)) },
navigationIcon = {
IconButton(onClick = { findNavController().popBackStack() }) {
Icon(imageVector = Icons.Default.ArrowBack, contentDescription = null)
}
},
scrollBehavior = scrollBehaviour,
)
},
) { paddingValues ->
Box {
LazyVerticalGrid(
columns = GridCells.Fixed(columnCount),
modifier = Modifier.nestedScroll(scrollBehaviour.nestedScrollConnection).padding(horizontal = dimensionResource(id = R.dimen.gallery_list_margin_h), vertical = dimensionResource(id = R.dimen.gallery_list_margin_v)),
state = state,
contentPadding = paddingValues,
horizontalArrangement = Arrangement.spacedBy(4.dp),
verticalArrangement = Arrangement.spacedBy(4.dp),
) {
items(
count = data.itemCount,
key = data.itemKey(key = { item -> item.position }),
contentType = data.itemContentType(),
) { index ->
val item = data[index]
if (item != null) {
EhPreviewItem(item) {
onPreviewCLick(item.position)
}
},
scrollBehavior = scrollBehaviour,
)
},
) { paddingValues ->
Box {
LazyVerticalGrid(
columns = GridCells.Fixed(columnCount),
modifier = Modifier.nestedScroll(scrollBehaviour.nestedScrollConnection).padding(horizontal = dimensionResource(id = R.dimen.gallery_list_margin_h), vertical = dimensionResource(id = R.dimen.gallery_list_margin_v)),
state = state,
contentPadding = paddingValues,
horizontalArrangement = Arrangement.spacedBy(4.dp),
verticalArrangement = Arrangement.spacedBy(4.dp),
) {
items(
count = data.itemCount,
key = data.itemKey(key = { item -> item.position }),
contentType = data.itemContentType(),
) { index ->
val item = data[index]
if (item != null) {
EhPreviewItem(item) {
onPreviewCLick(item.position)
}
} else {
EhPreviewItemPlaceholder(index) {
onPreviewCLick(index)
}
} else {
EhPreviewItemPlaceholder(index) {
onPreviewCLick(index)
}
}
}
}
Box(modifier = Modifier.padding(paddingValues = paddingValues)) {
LazyGridScrollbar(listState = state)
}
}
Box(modifier = Modifier.padding(paddingValues = paddingValues)) {
LazyGridScrollbar(listState = state)
}
}
}
@@ -17,7 +17,6 @@ package com.hippo.ehviewer.ui.scene
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.compose.foundation.Image
import androidx.compose.foundation.layout.Arrangement
@@ -75,122 +74,120 @@ import kotlinx.coroutines.delay
import my.nanihadesuka.compose.LazyColumnScrollbar
class HistoryScene : BaseScene() {
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View {
return ComposeView(inflater.context).apply {
setMD3Content {
val dialogState = rememberDialogState()
dialogState.Handler()
val coroutineScope = rememberCoroutineScope()
val scrollBehavior = TopAppBarDefaults.pinnedScrollBehavior()
val historyData = remember { Pager(PagingConfig(20, jumpThreshold = 40)) { EhDB.historyLazyList }.flow.cachedIn(lifecycleScope) }.collectAsLazyPagingItems()
Scaffold(
modifier = Modifier.nestedScroll(scrollBehavior.nestedScrollConnection),
topBar = {
TopAppBar(
title = { Text(text = stringResource(id = R.string.history)) },
navigationIcon = {
IconButton(onClick = { toggleDrawer(GravityCompat.START) }) {
Icon(imageVector = Icons.Default.Menu, contentDescription = null)
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?) = ComposeView(inflater.context).apply {
setMD3Content {
val dialogState = rememberDialogState()
dialogState.Handler()
val coroutineScope = rememberCoroutineScope()
val scrollBehavior = TopAppBarDefaults.pinnedScrollBehavior()
val historyData = remember { Pager(PagingConfig(20, jumpThreshold = 40)) { EhDB.historyLazyList }.flow.cachedIn(lifecycleScope) }.collectAsLazyPagingItems()
Scaffold(
modifier = Modifier.nestedScroll(scrollBehavior.nestedScrollConnection),
topBar = {
TopAppBar(
title = { Text(text = stringResource(id = R.string.history)) },
navigationIcon = {
IconButton(onClick = { toggleDrawer(GravityCompat.START) }) {
Icon(imageVector = Icons.Default.Menu, contentDescription = null)
}
},
actions = {
IconButton(onClick = {
coroutineScope.launchIO {
val clear = dialogState.show(
confirmText = R.string.clear_all,
dismissText = android.R.string.cancel,
text = { Text(text = stringResource(id = R.string.clear_all_history)) },
)
if (clear) EhDB.clearHistoryInfo()
}
},
actions = {
IconButton(onClick = {
coroutineScope.launchIO {
val clear = dialogState.show(
confirmText = R.string.clear_all,
dismissText = android.R.string.cancel,
text = { Text(text = stringResource(id = R.string.clear_all_history)) },
)
if (clear) EhDB.clearHistoryInfo()
}
}) {
Icon(imageVector = Icons.Default.ClearAll, contentDescription = null)
}
},
scrollBehavior = scrollBehavior,
)
},
) { paddingValues ->
val state = rememberLazyListState()
Box {
val cardHeight = remember { (3 * listThumbSize * 3).pxToDp.dp }
LazyColumn(
modifier = Modifier.padding(horizontal = dimensionResource(id = R.dimen.gallery_list_margin_h), vertical = dimensionResource(id = R.dimen.gallery_list_margin_v)),
state = state,
contentPadding = paddingValues,
verticalArrangement = Arrangement.spacedBy(dimensionResource(R.dimen.gallery_list_interval)),
) {
items(
count = historyData.itemCount,
key = historyData.itemKey(key = { item -> item.gid }),
contentType = historyData.itemContentType(),
) { index ->
val info = historyData[index]
// TODO: item delete & add animation
// Bug tracker: https://issuetracker.google.com/issues/150812265
info?.let {
val dismissState = rememberDismissState(
confirmValueChange = {
if (it == DismissValue.DismissedToStart) {
}) {
Icon(imageVector = Icons.Default.ClearAll, contentDescription = null)
}
},
scrollBehavior = scrollBehavior,
)
},
) { paddingValues ->
val state = rememberLazyListState()
Box {
val cardHeight = remember { (3 * listThumbSize * 3).pxToDp.dp }
LazyColumn(
modifier = Modifier.padding(horizontal = dimensionResource(id = R.dimen.gallery_list_margin_h), vertical = dimensionResource(id = R.dimen.gallery_list_margin_v)),
state = state,
contentPadding = paddingValues,
verticalArrangement = Arrangement.spacedBy(dimensionResource(R.dimen.gallery_list_interval)),
) {
items(
count = historyData.itemCount,
key = historyData.itemKey(key = { item -> item.gid }),
contentType = historyData.itemContentType(),
) { index ->
val info = historyData[index]
// TODO: item delete & add animation
// Bug tracker: https://issuetracker.google.com/issues/150812265
info?.let {
val dismissState = rememberDismissState(
confirmValueChange = {
if (it == DismissValue.DismissedToStart) {
coroutineScope.launchIO {
EhDB.deleteHistoryInfo(info)
}
}
true
},
)
SwipeToDismiss(
state = dismissState,
background = {},
dismissContent = {
// TODO: item delete & add animation
// Bug tracker: https://issuetracker.google.com/issues/150812265
GalleryInfoListItem(
onClick = {
navAnimated(
R.id.galleryDetailScene,
bundleOf(
GalleryDetailScene.KEY_ACTION to GalleryDetailScene.ACTION_GALLERY_INFO,
GalleryDetailScene.KEY_GALLERY_INFO to it,
),
)
},
onLongClick = {
coroutineScope.launchIO {
EhDB.deleteHistoryInfo(info)
dialogState.doGalleryInfoAction(info, context)
}
}
true
},
)
SwipeToDismiss(
state = dismissState,
background = {},
dismissContent = {
// TODO: item delete & add animation
// Bug tracker: https://issuetracker.google.com/issues/150812265
GalleryInfoListItem(
onClick = {
navAnimated(
R.id.galleryDetailScene,
bundleOf(
GalleryDetailScene.KEY_ACTION to GalleryDetailScene.ACTION_GALLERY_INFO,
GalleryDetailScene.KEY_GALLERY_INFO to it,
),
)
},
onLongClick = {
coroutineScope.launchIO {
dialogState.doGalleryInfoAction(info, context)
}
},
info = it,
modifier = Modifier.height(cardHeight),
)
},
directions = setOf(DismissDirection.EndToStart),
)
}
},
info = it,
modifier = Modifier.height(cardHeight),
)
},
directions = setOf(DismissDirection.EndToStart),
)
}
}
Box(modifier = Modifier.padding(paddingValues = paddingValues)) {
LazyColumnScrollbar(listState = state)
}
}
Deferred({ delay(200) }) {
if (historyData.itemCount == 0) {
Column(
modifier = Modifier.padding(paddingValues).fillMaxSize(),
verticalArrangement = Arrangement.Center,
horizontalAlignment = Alignment.CenterHorizontally,
) {
Image(
painter = painterResource(id = R.drawable.big_history),
contentDescription = null,
Modifier.padding(16.dp),
)
Text(
text = stringResource(id = R.string.no_history),
style = MaterialTheme.typography.headlineMedium,
)
}
Box(modifier = Modifier.padding(paddingValues = paddingValues)) {
LazyColumnScrollbar(listState = state)
}
}
Deferred({ delay(200) }) {
if (historyData.itemCount == 0) {
Column(
modifier = Modifier.padding(paddingValues).fillMaxSize(),
verticalArrangement = Arrangement.Center,
horizontalAlignment = Alignment.CenterHorizontally,
) {
Image(
painter = painterResource(id = R.drawable.big_history),
contentDescription = null,
Modifier.padding(16.dp),
)
Text(
text = stringResource(id = R.string.no_history),
style = MaterialTheme.typography.headlineMedium,
)
}
}
}