From c655a303c38f778a76dc473c87466f38562c2219 Mon Sep 17 00:00:00 2001 From: DianQK Date: Sun, 29 Jan 2023 15:31:06 +0800 Subject: [PATCH] Add SuspendConfirmAlertDialog --- .../ui/component/SuspendConfirmAlertDialog.kt | 73 +++++++++++++++++ .../ruslin/ui/page/notes/NotesDrawerSheet.kt | 71 +++++------------ .../dianqk/ruslin/ui/page/notes/NotesPage.kt | 79 ++++++------------- 3 files changed, 119 insertions(+), 104 deletions(-) create mode 100644 app/src/main/java/org/dianqk/ruslin/ui/component/SuspendConfirmAlertDialog.kt diff --git a/app/src/main/java/org/dianqk/ruslin/ui/component/SuspendConfirmAlertDialog.kt b/app/src/main/java/org/dianqk/ruslin/ui/component/SuspendConfirmAlertDialog.kt new file mode 100644 index 0000000..d1ea00d --- /dev/null +++ b/app/src/main/java/org/dianqk/ruslin/ui/component/SuspendConfirmAlertDialog.kt @@ -0,0 +1,73 @@ +package org.dianqk.ruslin.ui.component + +import androidx.compose.animation.core.* +import androidx.compose.material3.AlertDialog +import androidx.compose.material3.Text +import androidx.compose.material3.TextButton +import androidx.compose.runtime.* +import androidx.compose.ui.Modifier +import androidx.compose.ui.draw.alpha +import androidx.compose.ui.res.stringResource +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.launch +import org.dianqk.ruslin.R + +@Composable +fun SuspendConfirmAlertDialog( + scope: CoroutineScope = rememberCoroutineScope(), + icon: @Composable (() -> Unit)? = null, + inProgressIcon: @Composable ((Modifier) -> Unit)? = null, + title: @Composable (() -> Unit)? = null, + text: @Composable (() -> Unit)? = null, + onDismissRequest: () -> Unit, + onConfirm: suspend () -> Unit, + onConfirmFinished: () -> Unit, +) { + var inProgress by remember { mutableStateOf(false) } + val inProgressAnimation by rememberInfiniteTransition().animateFloat( + initialValue = 1f, + targetValue = 0f, + animationSpec = infiniteRepeatable( + animation = tween(300, easing = LinearEasing) + ) + ) + AlertDialog( + onDismissRequest = { + if (!inProgress) { + onDismissRequest() + } + }, + confirmButton = { + TextButton(enabled = !inProgress, onClick = { + inProgress = true + scope.launch { + onConfirm() + inProgress = false + onConfirmFinished() + } + }) { + Text(text = stringResource(id = R.string.confirm)) + } + }, + dismissButton = { + TextButton(enabled = !inProgress, onClick = { + onDismissRequest() + }) { + Text(text = stringResource(id = R.string.cancel)) + } + }, + icon = { + if (inProgress) { + if (inProgressIcon != null) { + inProgressIcon(Modifier.alpha(inProgressAnimation)) + } + } else { + if (icon != null) { + icon() + } + } + }, + title = title, + text = text + ) +} \ No newline at end of file diff --git a/app/src/main/java/org/dianqk/ruslin/ui/page/notes/NotesDrawerSheet.kt b/app/src/main/java/org/dianqk/ruslin/ui/page/notes/NotesDrawerSheet.kt index c8400ce..3b1bb2d 100644 --- a/app/src/main/java/org/dianqk/ruslin/ui/page/notes/NotesDrawerSheet.kt +++ b/app/src/main/java/org/dianqk/ruslin/ui/page/notes/NotesDrawerSheet.kt @@ -18,7 +18,6 @@ import androidx.compose.material3.* import androidx.compose.runtime.* 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.focus.FocusRequester import androidx.compose.ui.focus.focusRequester @@ -28,11 +27,11 @@ import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.unit.dp import androidx.lifecycle.compose.collectAsStateWithLifecycle -import kotlinx.coroutines.launch import org.dianqk.ruslin.R import org.dianqk.ruslin.ui.component.CombinedClickableSurface import org.dianqk.ruslin.ui.component.OutlinedButtonWithIcon import org.dianqk.ruslin.ui.component.SubTitle +import org.dianqk.ruslin.ui.component.SuspendConfirmAlertDialog import org.dianqk.ruslin.ui.theme.Shape32 import uniffi.ruslin.FfiFolder @@ -59,7 +58,6 @@ fun NotesDrawerSheet( var openDeleteFolderAlertDialog: Folder? by remember { mutableStateOf(null) } - val scope = rememberCoroutineScope() openEditFolderDialog?.let { editFolder -> FolderDialog( @@ -80,54 +78,22 @@ fun NotesDrawerSheet( } openDeleteFolderAlertDialog?.let { deleteFolder -> - var isDeleting by remember { mutableStateOf(false) } - val deletingAnimation by rememberInfiniteTransition().animateFloat( - initialValue = 1f, - targetValue = 0f, - animationSpec = infiniteRepeatable( - animation = tween(300, easing = LinearEasing) - ) - ) - AlertDialog( - onDismissRequest = { - if (!isDeleting) { - openDeleteFolderAlertDialog = null - } - }, - confirmButton = { - TextButton(enabled = !isDeleting, onClick = { - isDeleting = true - scope.launch { - onDeleteFolder(deleteFolder.ffiFolder) - isDeleting = false - openDeleteFolderAlertDialog = null - } - }) { - Text(text = stringResource(id = R.string.confirm)) - } - }, - dismissButton = { - TextButton(enabled = !isDeleting, onClick = { - openDeleteFolderAlertDialog = null - }) { - Text(text = stringResource(id = R.string.cancel)) - } + SuspendConfirmAlertDialog( + onDismissRequest = { openDeleteFolderAlertDialog = null }, + inProgressIcon = { + Icon( + modifier = it, + imageVector = Icons.Default.DeleteSweep, + contentDescription = null, + tint = MaterialTheme.colorScheme.tertiary + ) }, icon = { - if (isDeleting) { - Icon( - modifier = Modifier.alpha(deletingAnimation), - imageVector = Icons.Default.DeleteSweep, - contentDescription = null, - tint = MaterialTheme.colorScheme.tertiary - ) - } else { - Icon( - imageVector = Icons.Default.Warning, - contentDescription = null, - tint = MaterialTheme.colorScheme.error - ) - } + Icon( + imageVector = Icons.Default.Warning, + contentDescription = null, + tint = MaterialTheme.colorScheme.error + ) }, title = { Text( @@ -139,7 +105,12 @@ fun NotesDrawerSheet( }, text = { Text(text = stringResource(id = R.string.ask_delete_folder_description)) - }) + }, + onConfirm = { + onDeleteFolder(deleteFolder.ffiFolder) + }) { + openDeleteFolderAlertDialog = null + } } if (openCreateFolderDialog) { diff --git a/app/src/main/java/org/dianqk/ruslin/ui/page/notes/NotesPage.kt b/app/src/main/java/org/dianqk/ruslin/ui/page/notes/NotesPage.kt index 2065e10..b7646a3 100644 --- a/app/src/main/java/org/dianqk/ruslin/ui/page/notes/NotesPage.kt +++ b/app/src/main/java/org/dianqk/ruslin/ui/page/notes/NotesPage.kt @@ -7,14 +7,12 @@ import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.padding import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.foundation.lazy.items -import androidx.compose.material.ExperimentalMaterialApi import androidx.compose.material.icons.Icons import androidx.compose.material.icons.filled.* import androidx.compose.material.icons.outlined.DeleteForever import androidx.compose.material3.* import androidx.compose.runtime.* import androidx.compose.ui.Modifier -import androidx.compose.ui.draw.alpha import androidx.compose.ui.draw.rotate import androidx.compose.ui.res.stringResource import androidx.compose.ui.unit.dp @@ -24,6 +22,7 @@ import kotlinx.coroutines.launch import org.dianqk.ruslin.R import org.dianqk.ruslin.ui.component.ContentEmptyState import org.dianqk.ruslin.ui.component.ContentLoadingState +import org.dianqk.ruslin.ui.component.SuspendConfirmAlertDialog @OptIn( ExperimentalMaterial3Api::class, @@ -221,59 +220,22 @@ fun NotesPage( ) if (showRemoveMultipleItemsDialog) { - val deletingAnimation by rememberInfiniteTransition().animateFloat( - initialValue = 1f, - targetValue = 0f, - animationSpec = infiniteRepeatable( - animation = tween(300, easing = LinearEasing) - ) - ) - var isDeleting by remember { mutableStateOf(false) } - - AlertDialog( - onDismissRequest = { - if (!isDeleting) { - showRemoveMultipleItemsDialog = false - } - }, - confirmButton = { - TextButton(enabled = !isDeleting, onClick = { - isDeleting = true - scope.launch { - viewModel.deleteNotes(selectedItemIds) - .onFailure { e -> - Log.d(TAG, "$e") - } - isDeleting = false - firstSelectedItemId = null - showRemoveMultipleItemsDialog = false - } - }) { - Text(text = stringResource(id = R.string.confirm)) - } - }, - dismissButton = { - TextButton(enabled = !isDeleting, onClick = { - showRemoveMultipleItemsDialog = false - }) { - Text(text = stringResource(id = R.string.cancel)) - } + SuspendConfirmAlertDialog( + onDismissRequest = { showRemoveMultipleItemsDialog = false }, + inProgressIcon = { + Icon( + modifier = it, + imageVector = Icons.Default.DeleteSweep, + contentDescription = null, + tint = MaterialTheme.colorScheme.tertiary + ) }, icon = { - if (isDeleting) { - Icon( - modifier = Modifier.alpha(deletingAnimation), - imageVector = Icons.Default.DeleteSweep, - contentDescription = null, - tint = MaterialTheme.colorScheme.tertiary - ) - } else { - Icon( - imageVector = Icons.Default.Warning, - contentDescription = null, - tint = MaterialTheme.colorScheme.error - ) - } + Icon( + imageVector = Icons.Default.Warning, + contentDescription = null, + tint = MaterialTheme.colorScheme.error + ) }, title = { Text( @@ -281,7 +243,16 @@ fun NotesPage( id = R.string.ask_delete_selected_notes ) ) - }) + }, + onConfirm = { + viewModel.deleteNotes(selectedItemIds) + .onFailure { e -> + Log.d(TAG, "$e") + } + }) { + firstSelectedItemId = null + showRemoveMultipleItemsDialog = false + } } LaunchedEffect(Unit) {