From d30837665a4cb3063ca67a5d17b201a244a3c371 Mon Sep 17 00:00:00 2001 From: tarsin Date: Thu, 4 May 2023 17:38:17 +0800 Subject: [PATCH] Introduce coroutine bounded dialog --- .../hippo/ehviewer/ui/scene/HistoryScene.kt | 31 +++---- .../com/hippo/ehviewer/ui/widget/Dialog.kt | 82 +++++++++++++++++++ 2 files changed, 95 insertions(+), 18 deletions(-) create mode 100644 app/src/main/java/com/hippo/ehviewer/ui/widget/Dialog.kt diff --git a/app/src/main/java/com/hippo/ehviewer/ui/scene/HistoryScene.kt b/app/src/main/java/com/hippo/ehviewer/ui/scene/HistoryScene.kt index 1538ab4b3..4d1658c04 100644 --- a/app/src/main/java/com/hippo/ehviewer/ui/scene/HistoryScene.kt +++ b/app/src/main/java/com/hippo/ehviewer/ui/scene/HistoryScene.kt @@ -15,7 +15,6 @@ */ package com.hippo.ehviewer.ui.scene -import android.annotation.SuppressLint import android.content.DialogInterface import android.content.Intent import android.os.Bundle @@ -76,6 +75,7 @@ import com.hippo.ehviewer.ui.removeFromFavorites import com.hippo.ehviewer.ui.widget.Deferred import com.hippo.ehviewer.ui.widget.LazyColumnWithScrollBar import com.hippo.ehviewer.ui.widget.ListInfoCard +import com.hippo.ehviewer.ui.widget.rememberDialogState import com.hippo.ehviewer.ui.widget.setMD3Content import eu.kanade.tachiyomi.ui.reader.ReaderActivity import eu.kanade.tachiyomi.util.lang.launchIO @@ -91,6 +91,8 @@ class HistoryScene : BaseScene() { ): 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)) { EhDB.historyLazyList }.flow.cachedIn(lifecycleScope) }.collectAsLazyPagingItems() @@ -105,7 +107,16 @@ class HistoryScene : BaseScene() { } }, actions = { - IconButton(onClick = ::showClearAllDialog) { + IconButton(onClick = { + coroutineScope.launchIO { + val clear = dialogState.show( + confirmText = R.string.clear_all, + dismissText = android.R.string.cancel, + text = R.string.clear_all_history, + ) + if (clear) EhDB.clearHistoryInfo() + } + }) { Icon(imageVector = Icons.Default.ClearAll, contentDescription = null) } }, @@ -189,22 +200,6 @@ class HistoryScene : BaseScene() { toggleDrawer(GravityCompat.START) } - @SuppressLint("NotifyDataSetChanged") - private fun showClearAllDialog() { - BaseDialogBuilder(requireContext()) - .setMessage(R.string.clear_all_history) - .setPositiveButton(R.string.clear_all) { _: DialogInterface?, which: Int -> - if (DialogInterface.BUTTON_POSITIVE != which) { - return@setPositiveButton - } - lifecycleScope.launchIO { - EhDB.clearHistoryInfo() - } - } - .setNegativeButton(android.R.string.cancel, null) - .show() - } - private fun onItemClick(gi: GalleryInfo) { val args = Bundle() args.putString(GalleryDetailScene.KEY_ACTION, GalleryDetailScene.ACTION_GALLERY_INFO) diff --git a/app/src/main/java/com/hippo/ehviewer/ui/widget/Dialog.kt b/app/src/main/java/com/hippo/ehviewer/ui/widget/Dialog.kt new file mode 100644 index 000000000..d75bc119b --- /dev/null +++ b/app/src/main/java/com/hippo/ehviewer/ui/widget/Dialog.kt @@ -0,0 +1,82 @@ +package com.hippo.ehviewer.ui.widget + +import androidx.annotation.StringRes +import androidx.compose.material3.AlertDialog +import androidx.compose.material3.Text +import androidx.compose.material3.TextButton +import androidx.compose.runtime.Composable +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember +import androidx.compose.runtime.setValue +import androidx.compose.ui.res.stringResource +import kotlinx.coroutines.suspendCancellableCoroutine +import kotlin.coroutines.resume + +interface DialogScope { + fun dismiss() +} + +class DialogState : DialogScope { + private var content: (@Composable () -> Unit)? by mutableStateOf(null) + + @Composable + fun Handler() = content?.invoke() + + override fun dismiss() { + content = null + } + + suspend fun show(block: @Composable DialogScope.() -> Unit) { + suspendCancellableCoroutine { + content = { + AlertDialog(onDismissRequest = { dismiss() }, confirmButton = { /*TODO*/ }) + block() + } + } + } + + suspend fun show( + @StringRes confirmText: Int? = null, + @StringRes dismissText: Int? = null, + @StringRes title: Int? = null, + @StringRes text: Int? = null, + ): Boolean { + return suspendCancellableCoroutine { cont -> + cont.invokeOnCancellation { dismiss() } + content = { + AlertDialog( + onDismissRequest = { + dismiss() + cont.resume(false) + }, + confirmButton = { + TextButton(onClick = { + dismiss() + cont.resume(true) + }) { + Text(text = stringResource(id = confirmText ?: android.R.string.ok)) + } + }, + dismissButton = dismissText?.let { + { + TextButton(onClick = { + dismiss() + cont.resume(false) + }) { + Text(text = stringResource(id = dismissText)) + } + } + }, + title = title?.let { { Text(text = stringResource(id = title)) } }, + text = text?.let { { Text(text = stringResource(id = text)) } }, + ) + } + } + } +} + +@Composable +fun rememberDialogState(): DialogState { + return remember { DialogState() } +}