Refactor select item dialog API to take List<T>

This commit is contained in:
FooIbar committed 2024-02-08 12:39:04 +08:00
1 parent c444a3b435
commit a3e7b6ef43
7 files changed
+97 -93

No files matched your search

@@ -155,12 +155,14 @@ suspend fun DialogState.startDownload(
} else {
// Let use chose label
val list = DownloadManager.labelList
val items = arrayOf(
getString(R.string.default_download_label_name),
*list.map { it.label }.toTypedArray(),
)
val items = buildList {
add(getString(R.string.default_download_label_name))
list.forEach {
add(it.label)
}
}
val (selected, checked) = showSelectItemWithCheckBox(
*items,
items,
title = R.string.download,
checkBoxText = R.string.remember_download_label,
)
@@ -195,15 +197,17 @@ suspend fun DialogState.modifyFavorites(galleryInfo: BaseGalleryInfo): Boolean {
val localFav = getFavoriteIcon(localFavorited) to appCtx.getString(R.string.local_favorites)
val cloudFav = Settings.favCat.mapIndexed { index, name ->
getFavoriteIcon(galleryInfo.favoriteSlot == index) to name
}.toTypedArray()
val items = if (isFavorited) {
val remove = Icons.Default.HeartBroken to appCtx.getString(R.string.remove_from_favourites)
arrayOf(remove, localFav, *cloudFav)
} else {
arrayOf(localFav, *cloudFav)
}
val items = buildList {
if (isFavorited) {
val remove = Icons.Default.HeartBroken to appCtx.getString(R.string.remove_from_favourites)
add(remove)
}
add(localFav)
addAll(cloudFav)
}
val (slot, note) = showSelectItemWithIconAndTextField(
*items,
items,
title = R.string.add_favorites_dialog_title,
hint = R.string.favorite_note,
maxChar = MAX_FAVNOTE_CHAR,
@@ -279,23 +283,26 @@ fun Context.navToReader(info: BaseGalleryInfo, page: Int = -1) {
suspend fun DialogState.doGalleryInfoAction(info: BaseGalleryInfo, context: Context) {
val downloaded = DownloadManager.getDownloadState(info.gid) != DownloadInfo.STATE_INVALID
val favourite = info.favoriteSlot != NOT_FAVORITED
val selected = if (!downloaded) {
showSelectItemWithIcon(
Icons.AutoMirrored.Default.MenuBook to R.string.read,
Icons.Default.Download to R.string.download,
if (!favourite) Icons.Default.Favorite to R.string.add_to_favourites else Icons.Default.HeartBroken to R.string.remove_from_favourites,
title = EhUtils.getSuitableTitle(info),
)
} else {
showSelectItemWithIcon(
Icons.AutoMirrored.Default.MenuBook to R.string.read,
Icons.Default.Delete to R.string.delete_downloads,
if (!favourite) Icons.Default.Favorite to R.string.add_to_favourites else Icons.Default.HeartBroken to R.string.remove_from_favourites,
Icons.AutoMirrored.Default.DriveFileMove to R.string.download_move_dialog_title,
title = EhUtils.getSuitableTitle(info),
)
val favorited = info.favoriteSlot != NOT_FAVORITED
val items = buildList {
add(Icons.AutoMirrored.Default.MenuBook to R.string.read)
val download = if (downloaded) {
Icons.Default.Delete to R.string.delete_downloads
} else {
Icons.Default.Download to R.string.download
}
add(download)
val favorite = if (favorited) {
Icons.Default.HeartBroken to R.string.remove_from_favourites
} else {
Icons.Default.Favorite to R.string.add_to_favourites
}
add(favorite)
if (downloaded) {
add(Icons.AutoMirrored.Default.DriveFileMove to R.string.download_move_dialog_title)
}
}
val selected = showSelectItemWithIcon(items, EhUtils.getSuitableTitle(info))
with(context.findActivity<MainActivity>()) {
when (selected) {
0 -> navToReader(info)
@@ -307,7 +314,7 @@ suspend fun DialogState.doGalleryInfoAction(info: BaseGalleryInfo, context: Cont
}
}
2 -> if (favourite) {
2 -> if (favorited) {
runSuspendCatching {
removeFromFavorites(info)
showTip(R.string.remove_from_favorite_success)
@@ -397,18 +404,28 @@ suspend fun DialogState.confirmRemoveDownloadRange(list: Collection<DownloadInfo
suspend fun DialogState.showMoveDownloadLabel(info: GalleryInfo) {
val defaultLabel = appCtx.getString(R.string.default_download_label_name)
val labels = DownloadManager.labelList.map { it.label }.toTypedArray()
val selected = showSelectItem(defaultLabel, *labels, title = R.string.download_move_dialog_title)
val labels = buildList {
add(defaultLabel)
DownloadManager.labelList.forEach {
add(it.label)
}
}
val selected = showSelectItem(labels, R.string.download_move_dialog_title)
val downloadInfo = DownloadManager.getDownloadInfo(info.gid) ?: return
val label = if (selected == 0) null else labels[selected - 1]
val label = if (selected == 0) null else labels[selected]
withUIContext { DownloadManager.changeLabel(listOf(downloadInfo), label) }
}
suspend fun DialogState.showMoveDownloadLabelList(list: Collection<DownloadInfo>): String? {
val defaultLabel = appCtx.getString(R.string.default_download_label_name)
val labels = DownloadManager.labelList.map { it.label }.toTypedArray()
val selected = showSelectItem(defaultLabel, *labels, title = R.string.download_move_dialog_title)
val label = if (selected == 0) null else labels[selected - 1]
val labels = buildList {
add(defaultLabel)
DownloadManager.labelList.forEach {
add(it.label)
}
}
val selected = showSelectItem(labels, R.string.download_move_dialog_title)
val label = if (selected == 0) null else labels[selected]
withUIContext { DownloadManager.changeLabel(list, label) }
return label
}
@@ -88,7 +88,7 @@ fun SearchFilter(
it
}
}
}.toTypedArray()
}
}
Row(
modifier = Modifier.horizontalScroll(rememberScrollState()).padding(horizontal = 16.dp, vertical = 8.dp),
@@ -100,7 +100,11 @@ fun SearchFilter(
selected = languageFilter != -1,
onClick = {
scope.launch {
languageFilter = dialogState.showSingleChoice(any, *languages, selected = languageFilter + 1) - 1
val items = buildList {
add(any)
addAll(languages)
}
languageFilter = dialogState.showSingleChoice(items, languageFilter + 1) - 1
}
},
label = {
@@ -201,7 +205,7 @@ fun SearchFilter(
selected = advancedOption.minRating != 0,
onClick = {
scope.launch {
val selected = dialogState.showSingleChoice(*minRatingItems, selected = minRatingIndex)
val selected = dialogState.showSingleChoice(minRatingItems.toList(), minRatingIndex)
onAdvancedOptionChanged(advancedOption.copy(minRating = if (selected == 0) 0 else selected + 1))
}
},
@@ -347,7 +347,7 @@ fun DownloadsScreen(navigator: DestinationsNavigator) {
onClick = {
expanded = false
coroutineScope.launch {
filterType = dialogState.showSingleChoice(*states, selected = filterType + 1) - 1
filterType = dialogState.showSingleChoice(states.toList(), filterType + 1) - 1
}
},
)
@@ -371,12 +371,13 @@ fun FavouritesScreen(navigator: DestinationsNavigator) {
}
onClick(Icons.AutoMirrored.Default.DriveFileMove) {
// First is local favorite, the other 10 is cloud favorite
val array = if (EhCookieStore.hasSignedIn()) {
arrayOf(localFavName, *Settings.favCat)
} else {
arrayOf(localFavName)
val items = buildList {
add(localFavName)
if (EhCookieStore.hasSignedIn()) {
addAll(Settings.favCat)
}
}
val index = dialogState.showSelectItem(*array, title = R.string.move_favorites_dialog_title)
val index = dialogState.showSelectItem(items, R.string.move_favorites_dialog_title)
val srcCat = urlBuilder.favCat
val dstCat = if (index == 0) FavListUrlBuilder.FAV_CAT_LOCAL else index - 1
val info = checkedInfoMap.run { toMap().values.also { clear() } }
@@ -536,16 +536,13 @@ fun GalleryDetailScreen(args: GalleryDetailScreenArgs, navigator: DestinationsNa
}
suspend fun showNewerVersionDialog() {
val items = galleryDetail.newerVersions.map {
context.getString(
R.string.newer_version_title,
it.title,
it.posted,
) to {
navigator.navigate(GalleryDetailScreenDestination(TokenArgs(it.gid, it.token!!)))
}
}.toTypedArray()
val navAction = dialogState.showSelectItem(*items)
withUIContext { navAction.invoke() }
context.getString(R.string.newer_version_title, it.title, it.posted)
}
val selected = dialogState.showSelectItem(items)
val info = galleryDetail.newerVersions[selected]
withUIContext {
navigator.navigate(GalleryDetailScreenDestination(GalleryInfoArgs(info)))
}
}
Spacer(modifier = Modifier.size(dimensionResource(id = R.dimen.keyline_margin)))
if (galleryDetail.newerVersions.isNotEmpty()) {
@@ -233,12 +233,14 @@ fun EhScreen(navigator: DestinationsNavigator) {
summary = summary,
) {
coroutineScope.launch {
defaultFavSlot = dialogState.showSelectItem(
disabled,
localFav,
*Settings.favCat.takeIf { signin } ?: emptyArray(),
title = R.string.default_favorites_collection,
) - 2
val items = buildList {
add(disabled)
add(localFav)
if (signin) {
addAll(Settings.favCat)
}
}
defaultFavSlot = dialogState.showSelectItem(items, R.string.default_favorites_collection) - 2
}
}
SimpleMenuPreferenceInt(
@@ -405,7 +405,7 @@ class DialogState {
}
suspend fun showSingleChoice(
vararg items: String,
items: List<String>,
selected: Int,
): Int = showNoButton {
Column(modifier = Modifier.verticalScroll(rememberScrollState()).padding(vertical = 8.dp)) {
@@ -423,17 +423,9 @@ class DialogState {
}
suspend fun showSelectItem(
vararg items: String?,
@StringRes title: Int,
) = showSelectItem(
*items.filterNotNull().mapIndexed { a, b -> b to a }.toTypedArray(),
title = title,
)
suspend fun <R> showSelectItem(
vararg items: Pair<String, R>,
items: List<String>,
@StringRes title: Int? = null,
): R = showNoButton {
): Int = showNoButton {
Column(modifier = Modifier.padding(vertical = 8.dp)) {
if (title != null) {
Text(
@@ -443,11 +435,11 @@ class DialogState {
)
}
LazyColumn {
items(items) { (text, item) ->
itemsIndexed(items) { index, text ->
CompositionLocalProvider(LocalContentColor provides MaterialTheme.colorScheme.tertiary) {
Text(
text = text,
modifier = Modifier.clickable { dismissWith(item) }.fillMaxWidth()
modifier = Modifier.clickable { dismissWith(index) }.fillMaxWidth()
.padding(horizontal = 24.dp, vertical = 16.dp),
style = MaterialTheme.typography.titleMedium,
)
@@ -460,26 +452,17 @@ class DialogState {
suspend inline fun showSelectActions(
@StringRes title: Int? = null,
builder: ActionScope.() -> Unit,
) = showSelectItem(
*buildList { builder(ActionScope { action, that -> add(action to that) }) }.toTypedArray(),
title = title,
).invoke()
) {
val (items, actions) = buildList { builder(ActionScope { action, that -> add(action to that) }) }.unzip()
val selected = showSelectItem(items, title)
actions[selected].invoke()
}
suspend fun showSelectItemWithCheckBox(
vararg items: String?,
items: List<String>,
@StringRes title: Int,
@StringRes checkBoxText: Int,
) = showSelectItemWithCheckBox(
*items.filterNotNull().mapIndexed { a, b -> b to a }.toTypedArray(),
title = title,
checkBoxText = checkBoxText,
)
private suspend fun <R> showSelectItemWithCheckBox(
vararg items: Pair<String, R>,
@StringRes title: Int,
@StringRes checkBoxText: Int,
): Pair<R, Boolean> = showNoButton {
): Pair<Int, Boolean> = showNoButton {
var checked by remember { mutableStateOf(false) }
Column(modifier = Modifier.padding(vertical = 8.dp)) {
Text(
@@ -488,11 +471,11 @@ class DialogState {
style = MaterialTheme.typography.headlineSmall,
)
LazyColumn {
items(items) { (text, item) ->
itemsIndexed(items) { index, text ->
CompositionLocalProvider(LocalContentColor provides MaterialTheme.colorScheme.tertiary) {
Text(
text = text,
modifier = Modifier.clickable { dismissWith(item to checked) }.fillMaxWidth()
modifier = Modifier.clickable { dismissWith(index to checked) }.fillMaxWidth()
.padding(horizontal = 24.dp, vertical = 16.dp),
style = MaterialTheme.typography.titleMedium,
)
@@ -509,7 +492,7 @@ class DialogState {
}
suspend fun showSelectItemWithIcon(
vararg items: Pair<ImageVector, Int>,
items: List<Pair<ImageVector, Int>>,
title: String,
): Int = showNoButton {
LazyColumn {
@@ -531,7 +514,7 @@ class DialogState {
}
suspend fun showSelectItemWithIconAndTextField(
vararg items: Pair<ImageVector, String>,
items: List<Pair<ImageVector, String>>,
@StringRes title: Int,
@StringRes hint: Int,
maxChar: Int,