From 27c016378143379a5bbefb4f192882e8f6b51d63 Mon Sep 17 00:00:00 2001 From: thecodrr Date: Sun, 27 Sep 2020 15:35:11 +0500 Subject: [PATCH] feat: improve UI of all dialogs --- apps/web/src/common/selectionoptions.js | 8 +- .../components/dialogs/add-notebook-dialog.js | 20 +- apps/web/src/components/dialogs/confirm.js | 65 +++++- apps/web/src/components/dialogs/dialog.js | 152 ++++++------ .../src/components/dialogs/exportdialog.js | 61 +++-- .../web/src/components/dialogs/logindialog.js | 39 +++- .../components/dialogs/move-note-dialog.js | 216 +++++++++--------- .../src/components/dialogs/password-dialog.js | 19 +- .../src/components/dialogs/signupdialog.js | 29 ++- .../web/src/components/dialogs/topicdialog.js | 5 +- apps/web/src/components/icons/index.js | 5 +- apps/web/src/components/note/index.js | 38 +-- apps/web/src/components/notebook/index.js | 8 +- apps/web/src/components/topic/index.js | 24 +- apps/web/src/components/trash-item/index.js | 25 +- apps/web/src/theme/font/fontsize.js | 2 +- apps/web/src/views/notebooks.js | 2 +- apps/web/src/views/topics.js | 2 +- apps/web/src/views/trash.js | 24 +- 19 files changed, 447 insertions(+), 297 deletions(-) diff --git a/apps/web/src/common/selectionoptions.js b/apps/web/src/common/selectionoptions.js index b7ae05e1f..f23d89cf4 100644 --- a/apps/web/src/common/selectionoptions.js +++ b/apps/web/src/common/selectionoptions.js @@ -6,7 +6,7 @@ import { store as editorStore } from "../stores/editor-store"; import { store as trashStore } from "../stores/trash-store"; import { db } from "./index"; import { showMoveNoteDialog } from "../components/dialogs/movenotedialog"; -import { confirm } from "../components/dialogs/confirm"; +import { confirm, showDeleteConfirmation } from "../components/dialogs/confirm"; function createOption(key, icon, onClick) { return { @@ -26,12 +26,10 @@ function createOptions(options = []) { const DeleteOption = createOption("deleteOption", Icon.Trash, async function ( state ) { - if ( - !(await confirm(Icon.Trash, "Delete", "Are you sure you want to proceed?")) - ) - return; const item = state.selectedItems[0]; + if (!(await showDeleteConfirmation(item.type, true))) return; + var isAnyNoteOpened = false; const items = state.selectedItems.map((item) => { if (item.id === editorStore.get().session.id) isAnyNoteOpened = true; diff --git a/apps/web/src/components/dialogs/add-notebook-dialog.js b/apps/web/src/components/dialogs/add-notebook-dialog.js index b5370ad00..2651f5b54 100644 --- a/apps/web/src/components/dialogs/add-notebook-dialog.js +++ b/apps/web/src/components/dialogs/add-notebook-dialog.js @@ -1,5 +1,5 @@ import React from "react"; -import { Flex, Box, Text, Button as RebassButton } from "rebass"; +import { Flex, Box, Button as RebassButton } from "rebass"; import { Input } from "@rebass/forms"; import * as Icon from "../icons"; import Dialog, { showDialog } from "./dialog"; @@ -86,10 +86,13 @@ class AddNotebookDialog extends React.Component { return ( { props.onDone({ title: this.title, @@ -104,7 +107,7 @@ class AddNotebookDialog extends React.Component { }} negativeButton={{ text: "Cancel", onClick: props.close }} > - + (this.title = e.target.value)} @@ -112,19 +115,16 @@ class AddNotebookDialog extends React.Component { defaultValue={this.title} /> (this.description = e.target.value)} placeholder="Enter description (optional)" defaultValue={this.description} /> - - Topics (optional): - {this.state.topics.map( @@ -164,7 +164,7 @@ class AddNotebookDialog extends React.Component { /> this.performActionOnTopic(index)} diff --git a/apps/web/src/components/dialogs/confirm.js b/apps/web/src/components/dialogs/confirm.js index 5e66a7a0c..3a66e02a3 100644 --- a/apps/web/src/components/dialogs/confirm.js +++ b/apps/web/src/components/dialogs/confirm.js @@ -1,6 +1,7 @@ import React from "react"; import { Box, Text } from "rebass"; import Dialog, { showDialog } from "./dialog"; +import * as Icon from "../icons"; function Confirm(props) { return ( @@ -8,14 +9,15 @@ function Confirm(props) { isOpen={true} title={props.title} icon={props.icon} + description={props.subtitle} positiveButton={{ - text: "Yes", + text: props.yesText, onClick: props.onYes, }} - negativeButton={{ text: "No", onClick: props.onNo }} + negativeButton={{ text: props.noText, onClick: props.onNo }} > - - + + {props.message} @@ -23,14 +25,67 @@ function Confirm(props) { ); } -export function confirm(icon, title, message) { +export function confirm(icon, { title, subtitle, message, yesText, noText }) { return showDialog((perform) => ( perform(false)} onYes={() => perform(true)} /> )); } + +/** + * + * @param {"note"|"notebook"} type + */ +export function showDeleteConfirmation(type, multi = false) { + let noun = type === "note" ? "Note" : "Notebook"; + if (multi) noun += "s"; + let lowerCaseNoun = noun.toLowerCase(); + + let [firstPronoun, secondPronoun] = multi + ? ["these", "they"] + : ["this", "it"]; + + return confirm(Icon.Trash, { + title: `Delete ${noun}`, + subtitle: `Are you sure you want to delete ${firstPronoun} ${lowerCaseNoun}?`, + message: ( + + The {lowerCaseNoun} will be{" "} + + kept in your Trash for 7 days + {" "} + after which {secondPronoun} will be permanently removed. + + ), + yesText: `Delete ${lowerCaseNoun}`, + noText: "Cancel", + }); +} + +export function showMultiDeleteConfirmation(type) { + let noun = type === "note" ? "Notes" : "Notebooks"; + + return confirm(Icon.Trash, { + title: `Delete these ${noun}`, + subtitle: `Are you sure you want to delete these ${type}s?`, + message: ( + + These {type}s will be{" "} + + kept in your Trash for 7 days + {" "} + after which they will be permanently removed. + + ), + yesText: `Delete these ${type}s`, + noText: "Cancel", + }); +} diff --git a/apps/web/src/components/dialogs/dialog.js b/apps/web/src/components/dialogs/dialog.js index 280507e22..270b8d127 100644 --- a/apps/web/src/components/dialogs/dialog.js +++ b/apps/web/src/components/dialogs/dialog.js @@ -5,85 +5,91 @@ import ThemeProvider from "../theme-provider"; import * as Icon from "../icons"; import Modal from "react-modal"; import useMobile from "../../utils/use-mobile"; +import { useTheme } from "emotion-theming"; function Dialog(props) { const isMobile = useMobile(); + const theme = useTheme(); return ( - - {(theme) => ( - + + - - - - - {props.title} - - - {props.children} - - {props.positiveButton && ( - - {props.positiveButton.loading ? ( - - ) : ( - props.positiveButton.text || "OK" - )} - + + + {props.title} + + + {props.description} + + + {props.children} + + {props.positiveButton && ( + + {props.positiveButton.loading ? ( + + ) : ( + props.positiveButton.text || "OK" )} - - {props.negativeButton && ( - - {props.negativeButton.text || "Cancel"} - - )} - - - - )} - + + )} + {props.negativeButton && ( + + {props.negativeButton.text || "Cancel"} + + )} + + {props.footer} + + ); } export default Dialog; @@ -97,7 +103,7 @@ export function showDialog(dialog) { if (root) { return new Promise((resolve) => { const PropDialog = dialog(perform.bind(this, resolve)); - ReactDOM.render(PropDialog, root); + ReactDOM.render({PropDialog}, root); }); } return Promise.reject("No element with id 'dialogContainer'"); diff --git a/apps/web/src/components/dialogs/exportdialog.js b/apps/web/src/components/dialogs/exportdialog.js index adaa5bfaf..b4e5ed706 100644 --- a/apps/web/src/components/dialogs/exportdialog.js +++ b/apps/web/src/components/dialogs/exportdialog.js @@ -1,5 +1,5 @@ import React from "react"; -import { Flex, Button, Text, Box } from "rebass"; +import { Flex, Button, Text } from "rebass"; import { db } from "../../common"; import download from "../../utils/download"; import { showToast } from "../../utils/toast"; @@ -12,38 +12,33 @@ function ExportDialog(props) { isOpen={true} title={props.title} icon={props.icon} - negativeButton={{ onClick: props.onClose, text: "Cancel" }} + description="You can export your note to Markdown, HTML, or Text." + buttonsAlignment="center" + negativeButton={{ + onClick: props.onClose, + text: "I don't want to export anymore", + }} > - - - Please choose a format to export the note into: - - - - - - - + + + + + ); } @@ -51,7 +46,7 @@ function ExportDialog(props) { export function showExportDialog(noteId) { return showDialog((perform) => ( perform(false)} exportNote={async (format) => { diff --git a/apps/web/src/components/dialogs/logindialog.js b/apps/web/src/components/dialogs/logindialog.js index a69966950..750cda712 100644 --- a/apps/web/src/components/dialogs/logindialog.js +++ b/apps/web/src/components/dialogs/logindialog.js @@ -1,5 +1,5 @@ import React, { useState } from "react"; -import { Box, Button, Text } from "rebass"; +import { Flex, Button, Text } from "rebass"; import Input from "../inputs"; import * as Icon from "../icons"; import Dialog, { showDialog } from "./dialog"; @@ -18,19 +18,38 @@ function LoginDialog(props) { return ( submit(setError, form, login, onClose), }} + buttonsAlignment="center" + footer={ + <> + + Don't have an account? + + + + } > - { if (e.key === "Enter") submit(setError, form, login, onClose); }} @@ -39,11 +58,11 @@ function LoginDialog(props) { - {error && {error}} - + {/* */} + ); } diff --git a/apps/web/src/components/dialogs/move-note-dialog.js b/apps/web/src/components/dialogs/move-note-dialog.js index d45ac5a72..49e779fc4 100644 --- a/apps/web/src/components/dialogs/move-note-dialog.js +++ b/apps/web/src/components/dialogs/move-note-dialog.js @@ -1,5 +1,5 @@ import React from "react"; -import { Flex, Box, Text } from "rebass"; +import { Flex, Box, Text, Button } from "rebass"; import { Input } from "@rebass/forms"; import * as Icon from "../icons"; import { db } from "../../common"; @@ -14,73 +14,32 @@ class MoveDialog extends React.Component { selectedNotebook; selectedTopic; state = { - items: db.notebooks.all, - type: "notebooks", - title: "Notebooks", - mode: "read", + currentOpenedIndex: -1, + notebooks: db.notebooks.all, }; render() { - const { items, type, title, mode } = this.state; + const { notebooks, currentOpenedIndex } = this.state; const props = this.props; return ( { - try { - const notebook = { - id: this.selectedNotebook.id, - topic: this.selectedTopic, - }; - const note = db.notes.note(props.noteIds[0]).data; - await db.notes.move(notebook, ...props.noteIds); - showNotesMovedToast(note, props.noteIds, notebook); - props.onMove(); - } catch (e) { - showToast("error", e.message); - console.error(e); - } finally { - props.onClose(); - } - }, - disabled: type !== "notes", + title={"Add Note to Notebook"} + description={"Organize your notes by adding them to notebooks."} + icon={Icon.Move} + buttonsAlignment="center" + negativeButton={{ + text: "Get me out of here", + onClick: props.onClose, }} - negativeButton={{ text: "Cancel", onClick: props.onClose }} > - - - { - let item = this.history.pop(); - this.setState({ ...item }); - }} - sx={{ - display: this.history.length ? "block" : "none", - ":hover": { color: "primary" }, - marginRight: 2, - }} - > - - - {title} - - { + + Notebooks + - (this._inputRef = ref)} sx={{ display: mode === "write" ? "block" : "none" }} my={1} @@ -123,7 +78,7 @@ class MoveDialog extends React.Component { this.setState({ mode: "read" }); } }} - /> + /> */} - {items.length ? ( - items.map((item) => { - return ( - { + {notebooks.map((notebook, index) => ( + { this.history.push({ title, items, @@ -169,31 +115,59 @@ class MoveDialog extends React.Component { }); this.selectedTopic = item.title; } - }} - > - - {item.title} - - {item.totalNotes !== undefined && ( - - {item.totalNotes + " Notes"} - - )} - - ); - }) - ) : ( - - Nothing here - - )} + + this.setState({ + currentOpenedIndex: + this.state.currentOpenedIndex === index ? -1 : index, + }) + } + /> + + {notebook.topics.map((topic) => ( + { + try { + const nb = { + id: notebook.id, + topic: topic.id, + }; + const note = db.notes.note(props.noteIds[0]).data; + await db.notes.move(nb, ...props.noteIds); + showNotesMovedToast(note, props.noteIds, nb); + props.onMove(); + } catch (e) { + showToast("error", e.message); + console.error(e); + } finally { + props.onClose(); + } + }} + indent={1} + icon={Icon.Topic} + title={topic.title} + totalNotes={topic.totalNotes} + action={ + + Move here + + } + /> + ))} + + + ))} @@ -210,3 +184,35 @@ export function showMoveNoteDialog(noteIds) { /> )); } + +function Item(props) { + const { icon: Icon, indent = 0, title, totalNotes, onClick, action } = props; + return ( + + + + + {title} + + + {action || ( + + {totalNotes + " Notes"} + + )} + + ); +} diff --git a/apps/web/src/components/dialogs/password-dialog.js b/apps/web/src/components/dialogs/password-dialog.js index 94c704e3e..e36fe908c 100644 --- a/apps/web/src/components/dialogs/password-dialog.js +++ b/apps/web/src/components/dialogs/password-dialog.js @@ -20,6 +20,7 @@ function PasswordDialog(props) { ( perform(false)} diff --git a/apps/web/src/components/dialogs/signupdialog.js b/apps/web/src/components/dialogs/signupdialog.js index 37d015379..6441d0152 100644 --- a/apps/web/src/components/dialogs/signupdialog.js +++ b/apps/web/src/components/dialogs/signupdialog.js @@ -1,5 +1,5 @@ import React, { useState } from "react"; -import { Text, Box } from "rebass"; +import { Text, Box, Button } from "rebass"; import Input from "../inputs"; import * as Icon from "../icons"; import Dialog, { showDialog } from "./dialog"; @@ -8,6 +8,7 @@ import EmailInput from "../inputs/email"; import PasswordInput from "../inputs/password"; import Dropper from "../dropper"; import { useStore } from "../../stores/user-store"; +import { showLogInDialog } from "./logindialog"; const form = { error: true }; function SignUpDialog(props) { @@ -19,19 +20,35 @@ function SignUpDialog(props) { return ( submit(setError, form, signup, onClose), }} + footer={ + <> + + Already have an account? + + + + } > { if (e.key === "Enter") submit(setError, form, signup, onClose); }} diff --git a/apps/web/src/components/dialogs/topicdialog.js b/apps/web/src/components/dialogs/topicdialog.js index c0af3ab0a..2ea0633e8 100644 --- a/apps/web/src/components/dialogs/topicdialog.js +++ b/apps/web/src/components/dialogs/topicdialog.js @@ -13,9 +13,10 @@ function TopicDialog(props) { { props.onYes(ref.current.value); }, @@ -37,7 +38,7 @@ function TopicDialog(props) { export function showTopicDialog(notebook) { return showDialog((perform) => ( { perform(false); diff --git a/apps/web/src/components/icons/index.js b/apps/web/src/components/icons/index.js index e48145209..0ea9db641 100644 --- a/apps/web/src/components/icons/index.js +++ b/apps/web/src/components/icons/index.js @@ -38,7 +38,7 @@ export const Plus = createIcon(Icons.mdiPlus); export const Minus = createIcon(Icons.mdiMinus); export const Notebook = createIcon(Icons.mdiBookOutline); export const ArrowLeft = createIcon(Icons.mdiArrowLeft); -export const Move = createIcon(Icons.mdiArrowAll); +export const Move = createIcon(Icons.mdiBookPlusMultipleOutline); export const Topic = createIcon(Icons.mdiFormatTitle); export const Alert = createIcon(Icons.mdiAlert); export const Vault = createIcon(Icons.mdiShieldOutline); @@ -54,6 +54,7 @@ export const Trash = createIcon(Icons.mdiTrashCanOutline); export const Search = createIcon(Icons.mdiMagnify); export const Menu = createIcon(Icons.mdiMenu); export const Login = createIcon(Icons.mdiLoginVariant); +export const Signup = createIcon(Icons.mdiAccountPlusOutline); export const Logout = createIcon(Icons.mdiLogoutVariant); export const FocusMode = createIcon(Icons.mdiFullscreen); export const NormalMode = createIcon(Icons.mdiFullscreenExit); @@ -62,7 +63,7 @@ export const Home = createIcon(Icons.mdiHomeOutline); export const Restore = createIcon(Icons.mdiRecycle); export const Sync = createIcon(Icons.mdiSync); export const Loading = createIcon(Icons.mdiLoading, true); -export const Export = createIcon(Icons.mdiExport); +export const Export = createIcon(Icons.mdiExportVariant); export const AddToNotebook = createIcon(Icons.mdiBookPlusMultipleOutline); /** Properties Icons */ diff --git a/apps/web/src/components/note/index.js b/apps/web/src/components/note/index.js index fe4df9bc5..cf2e10da1 100644 --- a/apps/web/src/components/note/index.js +++ b/apps/web/src/components/note/index.js @@ -3,7 +3,7 @@ import { Flex, Box, Text } from "rebass"; import * as Icon from "../icons"; import TimeAgo from "timeago-react"; import ListItem from "../list-item"; -import { confirm } from "../dialogs/confirm"; +import { confirm, showDeleteConfirmation } from "../dialogs/confirm"; import { showMoveNoteDialog } from "../dialogs/movenotedialog"; import { store, useStore } from "../../stores/note-store"; import { store as editorStore } from "../../stores/editor-store"; @@ -65,17 +65,31 @@ function menuItems(note, context) { }, { visible: context?.type === "topic", - title: "Remove", + title: "Remove from topic", onClick: async () => { - confirm( - Icon.Topic, - "Remove from Topic", - "Are you sure you want to remove this note?" - ).then(async (res) => { + confirm(Icon.Topic, { + title: "Remove Note from Topic", + subtitle: "Are you sure you want to remove the note from this topic?", + yesText: "Remove note", + noText: "Cancel", + message: ( + + + This action does not delete the note. + {" "} + The note will only be removed from this notebook. You will still + be able to{" "} + + access it from Home and other places. + + + ), + }).then(async (res) => { if (res) { + console.log(context); await db.notebooks - .notebook(context.notebook.id) - .topics.topic(context.value) + .notebook(context.value.id) + .topics.topic(context.value.topic) .delete(note.id); store.setContext(context); } @@ -95,11 +109,7 @@ function menuItems(note, context) { }); if (!res) return; } - confirm( - Icon.Trash, - "Delete", - "Are you sure you want to delete this note?" - ).then(async (res) => { + showDeleteConfirmation("note").then(async (res) => { if (res) { await store.delete(note.id).then(() => showItemDeletedToast(note)); } diff --git a/apps/web/src/components/notebook/index.js b/apps/web/src/components/notebook/index.js index 80f5d0841..ea9e25cc1 100644 --- a/apps/web/src/components/notebook/index.js +++ b/apps/web/src/components/notebook/index.js @@ -4,7 +4,7 @@ import ListItem from "../list-item"; import { store } from "../../stores/notebook-store"; import * as Icon from "../icons"; import { showEditNoteDialog } from "../dialogs/addnotebookdialog"; -import { confirm } from "../dialogs/confirm"; +import { confirm, showDeleteConfirmation } from "../dialogs/confirm"; import { showItemDeletedToast, showUnpinnedToast } from "../../common/toasts"; const pin = async (notebook, index) => { await store.pin(notebook, index); @@ -24,11 +24,7 @@ function menuItems(notebook, index) { title: "Delete", color: "red", onClick: () => { - confirm( - Icon.Trash, - "Delete Notebook", - "Are you sure you want to delete this notebook?" - ).then(async (res) => { + showDeleteConfirmation("notebook").then(async (res) => { if (res) { await store .delete(notebook.id, index) diff --git a/apps/web/src/components/topic/index.js b/apps/web/src/components/topic/index.js index b5f14fdae..a98a36b24 100644 --- a/apps/web/src/components/topic/index.js +++ b/apps/web/src/components/topic/index.js @@ -5,6 +5,7 @@ import { confirm } from "../dialogs/confirm"; import * as Icon from "../icons"; import { db } from "../../common"; import { store } from "../../stores/notebook-store"; +import { Text } from "rebass"; const menuItems = (item) => [ { @@ -19,11 +20,24 @@ const menuItems = (item) => [ visible: item.title !== "General", color: "red", onClick: () => { - confirm( - Icon.Trash, - "Delete Topic", - "Are you sure you want to delete this topic?" - ).then(async (res) => { + confirm(Icon.Trash, { + title: "Delete topic", + subtitle: "Are you sure you want to delete this topic?", + yesText: "Delete topic", + noText: "Cancel", + message: ( + <> + This action is{" "} + + IRREVERSIBLE + + . Deleting this topic{" "} + + will not delete the notes contained in it. + + + ), + }).then(async (res) => { if (res) { await db.notebooks.notebook(item.notebookId).topics.delete(item.id); store.setSelectedNotebookTopics(item.notebookId); diff --git a/apps/web/src/components/trash-item/index.js b/apps/web/src/components/trash-item/index.js index 422501169..9df0af3b6 100644 --- a/apps/web/src/components/trash-item/index.js +++ b/apps/web/src/components/trash-item/index.js @@ -25,11 +25,24 @@ function menuItems(item, index) { title: "Delete", color: "red", onClick: () => { - confirm( - Icon.Trash, - "Delete", - `Are you sure you want to permanently delete this item?` - ).then(async (res) => { + confirm(Icon.Trash, { + title: `Permanently Delete ${toTitleCase(item.itemType)}`, + subtitle: `Are you sure you want to permanently delete this ${item.itemType}?`, + yesText: `Delete ${item.itemType}`, + noText: "Cancel", + message: ( + <> + This action is{" "} + + IRREVERSIBLE + + . You will{" "} + + not be able to recover this {item.itemType}. + + + ), + }).then(async (res) => { if (res) { await store.delete(item.id, index); showPermanentDeleteToast(item, index); @@ -54,7 +67,7 @@ function TrashItem({ item, index }) { - {toTitleCase(item.type)} + {toTitleCase(item.itemType)} } menuData={item} diff --git a/apps/web/src/theme/font/fontsize.js b/apps/web/src/theme/font/fontsize.js index ab38affc1..db764207a 100644 --- a/apps/web/src/theme/font/fontsize.js +++ b/apps/web/src/theme/font/fontsize.js @@ -7,7 +7,7 @@ class FontSizeFactory { subtitle: 16 * scaleFactor, body: 16 * scaleFactor, menu: 14 * scaleFactor, - subBody: 11 * scaleFactor, + subBody: 12 * scaleFactor, }; } } diff --git a/apps/web/src/views/notebooks.js b/apps/web/src/views/notebooks.js index c676a0a5f..b9a947959 100644 --- a/apps/web/src/views/notebooks.js +++ b/apps/web/src/views/notebooks.js @@ -36,7 +36,7 @@ const routes = { } diff --git a/apps/web/src/views/topics.js b/apps/web/src/views/topics.js index 7171731ed..17377f3b1 100644 --- a/apps/web/src/views/topics.js +++ b/apps/web/src/views/topics.js @@ -31,7 +31,7 @@ function Topics(props) { context={{ notebookId }} placeholder={Flex} button={{ - content: "Add more topics", + content: "Create a new topic", onClick: async () => { await showTopicDialog(notebookId); }, diff --git a/apps/web/src/views/trash.js b/apps/web/src/views/trash.js index a76997c58..95f5ae292 100644 --- a/apps/web/src/views/trash.js +++ b/apps/web/src/views/trash.js @@ -5,6 +5,7 @@ import { confirm } from "../components/dialogs/confirm"; import { useStore, store } from "../stores/trash-store"; import TrashPlaceholder from "../components/placeholders/trash-placeholder"; import { showToast } from "../utils/toast"; +import { Text } from "rebass"; function Trash() { useEffect(() => store.refresh(), []); @@ -19,11 +20,24 @@ function Trash() { content: "Clear Trash", icon: Icon.Trash, onClick: function () { - confirm( - Icon.Trash, - "Clear", - `This action is irreversible. Are you sure you want to proceed?` - ).then(async (res) => { + confirm(Icon.Trash, { + title: "Clear Trash", + subtitle: "Are you sure you want to clear all the trash?", + yesText: "Clear trash", + noText: "Cancel", + message: ( + <> + This action is{" "} + + IRREVERSIBLE + + . You will{" "} + + not be able to recover any of these items. + + + ), + }).then(async (res) => { if (res) { try { await clearTrash();