Refactor select item dialog API to take List<T>
This commit is contained in:
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,
|
||||
|
||||
Reference in new issue
Block a user