diff --git a/src/assets/fileExtensionIcons/index.tsx b/src/assets/fileExtensionIcons/index.tsx index 1953b9f1..0c684893 100644 --- a/src/assets/fileExtensionIcons/index.tsx +++ b/src/assets/fileExtensionIcons/index.tsx @@ -195,7 +195,9 @@ export function directoryColorToHex(color: DirColors | null): string { ? "#AF52DE" : color === "red" ? "#FF3B30" - : color + : color.includes("#") + ? color + : "#85BCFF" ).toLowerCase() } diff --git a/src/components/chats/index.tsx b/src/components/chats/index.tsx index 1c7d2fc1..13a00278 100644 --- a/src/components/chats/index.tsx +++ b/src/components/chats/index.tsx @@ -14,7 +14,7 @@ let didInitializeEmojisPreviously = false export const Chats = memo(() => { const isMobile = useIsMobile() - const { selectedConversation } = useChatsStore() + const { selectedConversation, setReplyMessage, setEditUUID } = useChatsStore() const [conversationParticipantsContainerOpen] = useLocalStorage( `conversationParticipantsContainerOpen:${selectedConversation?.uuid}`, true @@ -22,6 +22,9 @@ export const Chats = memo(() => { const [emojisInitialized, setEmojisInitialized] = useState(didInitializeEmojisPreviously) useMountedEffect(() => { + setReplyMessage(null) + setEditUUID("") + initEmojiMart({ data: EmojiMartData, custom: [ diff --git a/src/components/drive/list/contextMenu.tsx b/src/components/drive/list/contextMenu.tsx index 3e14172e..aa456dee 100644 --- a/src/components/drive/list/contextMenu.tsx +++ b/src/components/drive/list/contextMenu.tsx @@ -14,6 +14,8 @@ import worker from "@/lib/worker" import useRouteParent from "@/hooks/useRouteParent" import eventEmitter from "@/lib/eventEmitter" import { directoryUUIDToNameCache } from "@/cache" +import useLoadingToast from "@/hooks/useLoadingToast" +import useErrorToast from "@/hooks/useErrorToast" export const ContextMenu = memo(({ children }: { children: React.ReactNode }) => { const { setItems } = useDriveItemsStore() @@ -21,21 +23,25 @@ export const ContextMenu = memo(({ children }: { children: React.ReactNode }) => const { t } = useTranslation() const [, startTransition] = useTransition() const parent = useRouteParent() + const loadingToast = useLoadingToast() + const errorToast = useErrorToast() const createFolder = useCallback(async () => { - try { - const inputResponse = await showInputDialog({ - title: "newfolder", - continueButtonText: "create", - value: "", - autoFocusInput: true, - placeholder: "New folder" - }) + const inputResponse = await showInputDialog({ + title: "newfolder", + continueButtonText: "create", + value: "", + autoFocusInput: true, + placeholder: "New folder" + }) + + if (inputResponse.cancelled) { + return + } - if (inputResponse.cancelled) { - return - } + const toast = loadingToast() + try { const item = await worker.createDirectory({ name: inputResponse.value, parent }) directoryUUIDToNameCache.set(item.uuid, inputResponse.value) @@ -48,8 +54,17 @@ export const ContextMenu = memo(({ children }: { children: React.ReactNode }) => }) } catch (e) { console.error(e) + + const toast = errorToast((e as unknown as Error).toString()) + + toast.update({ + id: toast.id, + duration: 5000 + }) + } finally { + toast.dismiss() } - }, [setItems, parent]) + }, [setItems, parent, loadingToast, errorToast]) useEffect(() => { const createFolderTriggerListener = eventEmitter.on("createFolderTrigger", createFolder) diff --git a/src/components/drive/list/item/contextMenu/index.tsx b/src/components/drive/list/item/contextMenu/index.tsx index 7cc1799a..c6574809 100644 --- a/src/components/drive/list/item/contextMenu/index.tsx +++ b/src/components/drive/list/item/contextMenu/index.tsx @@ -26,6 +26,8 @@ import useLocation from "@/hooks/useLocation" import { HexColorPicker } from "react-colorful" import { useDebouncedCallback } from "use-debounce" import { directoryColorToHex } from "@/assets/fileExtensionIcons" +import useLoadingToast from "@/hooks/useLoadingToast" +import useErrorToast from "@/hooks/useErrorToast" export const ContextMenu = memo(({ item, children }: { item: DriveCloudItem; children: React.ReactNode }) => { const { items, setItems } = useDriveItemsStore() @@ -38,6 +40,8 @@ export const ContextMenu = memo(({ item, children }: { item: DriveCloudItem; chi useDriveSharedStore() const location = useLocation() const [directoryColor, setDirectoryColor] = useState(directoryColorToHex(item.type === "directory" ? item.color : null)) + const loadingToast = useLoadingToast() + const errorToast = useErrorToast() const selectedItems = useMemo(() => { return items.filter(item => item.selected) @@ -84,6 +88,8 @@ export const ContextMenu = memo(({ item, children }: { item: DriveCloudItem; chi return } + const toast = loadingToast() + try { const parent = await selectDriveDestination() @@ -101,8 +107,17 @@ export const ContextMenu = memo(({ item, children }: { item: DriveCloudItem; chi }) } catch (e) { console.error(e) + + const toast = errorToast((e as unknown as Error).toString()) + + toast.update({ + id: toast.id, + duration: 5000 + }) + } finally { + toast.dismiss() } - }, [selectedItems, setItems]) + }, [selectedItems, setItems, errorToast, loadingToast]) const download = useCallback(async () => { if (selectedItems.length === 0) { @@ -121,6 +136,8 @@ export const ContextMenu = memo(({ item, children }: { item: DriveCloudItem; chi return } + const toast = loadingToast() + try { const trashedUUIDs = selectedItems.map(item => item.uuid) @@ -133,14 +150,25 @@ export const ContextMenu = memo(({ item, children }: { item: DriveCloudItem; chi }) } catch (e) { console.error(e) + + const toast = errorToast((e as unknown as Error).toString()) + + toast.update({ + id: toast.id, + duration: 5000 + }) + } finally { + toast.dismiss() } - }, [selectedItems, setItems]) + }, [selectedItems, setItems, loadingToast, errorToast]) const deletePermanently = useCallback(async () => { if (selectedItems.length === 0) { return } + const toast = loadingToast() + try { const deletedUUIDs = selectedItems.map(item => item.uuid) @@ -153,14 +181,25 @@ export const ContextMenu = memo(({ item, children }: { item: DriveCloudItem; chi }) } catch (e) { console.error(e) + + const toast = errorToast((e as unknown as Error).toString()) + + toast.update({ + id: toast.id, + duration: 5000 + }) + } finally { + toast.dismiss() } - }, [selectedItems, setItems]) + }, [selectedItems, setItems, loadingToast, errorToast]) const restore = useCallback(async () => { if (selectedItems.length === 0) { return } + const toast = loadingToast() + try { const restoredUUIDs = selectedItems.map(item => item.uuid) @@ -171,8 +210,17 @@ export const ContextMenu = memo(({ item, children }: { item: DriveCloudItem; chi }) } catch (e) { console.error(e) + + const toast = errorToast((e as unknown as Error).toString()) + + toast.update({ + id: toast.id, + duration: 5000 + }) + } finally { + toast.dismiss() } - }, [selectedItems, setItems]) + }, [selectedItems, setItems, loadingToast, errorToast]) const preview = useCallback(() => { if (selectedItems.length !== 1 && previewType !== "other") { @@ -187,6 +235,8 @@ export const ContextMenu = memo(({ item, children }: { item: DriveCloudItem; chi return } + const toast = loadingToast() + try { const item = selectedItems[0] const newName = await actions.rename({ item }) @@ -196,8 +246,17 @@ export const ContextMenu = memo(({ item, children }: { item: DriveCloudItem; chi }) } catch (e) { console.error(e) + + const toast = errorToast((e as unknown as Error).toString()) + + toast.update({ + id: toast.id, + duration: 5000 + }) + } finally { + toast.dismiss() } - }, [selectedItems, setItems]) + }, [selectedItems, setItems, loadingToast, errorToast]) const toggleFavorite = useCallback( async (favorite: boolean) => { @@ -205,6 +264,8 @@ export const ContextMenu = memo(({ item, children }: { item: DriveCloudItem; chi return } + const toast = loadingToast() + try { const uuids = selectedItems.map(item => item.uuid) @@ -217,9 +278,18 @@ export const ContextMenu = memo(({ item, children }: { item: DriveCloudItem; chi }) } catch (e) { console.error(e) + + const toast = errorToast((e as unknown as Error).toString()) + + toast.update({ + id: toast.id, + duration: 5000 + }) + } finally { + toast.dismiss() } }, - [selectedItems, setItems] + [selectedItems, setItems, errorToast, loadingToast] ) const share = useCallback(async () => { @@ -227,18 +297,31 @@ export const ContextMenu = memo(({ item, children }: { item: DriveCloudItem; chi return } + const toast = loadingToast() + try { await actions.share({ selectedItems }) } catch (e) { console.error(e) + + const toast = errorToast((e as unknown as Error).toString()) + + toast.update({ + id: toast.id, + duration: 5000 + }) + } finally { + toast.dismiss() } - }, [selectedItems]) + }, [selectedItems, loadingToast, errorToast]) const changeColor = useDebouncedCallback(async (color: string) => { if (selectedItems.length !== 1) { return } + const toast = loadingToast() + try { await actions.changeColor({ uuid: selectedItems[0].uuid, color }) @@ -247,6 +330,15 @@ export const ContextMenu = memo(({ item, children }: { item: DriveCloudItem; chi }) } catch (e) { console.error(e) + + const toast = errorToast((e as unknown as Error).toString()) + + toast.update({ + id: toast.id, + duration: 5000 + }) + } finally { + toast.dismiss() } }, 1000) diff --git a/src/components/drive/list/item/contextMenu/moveTree.tsx b/src/components/drive/list/item/contextMenu/moveTree.tsx index 9675f922..7a50f3b2 100644 --- a/src/components/drive/list/item/contextMenu/moveTree.tsx +++ b/src/components/drive/list/item/contextMenu/moveTree.tsx @@ -6,9 +6,13 @@ import { Loader } from "lucide-react" import { useDriveItemsStore } from "@/stores/drive.store" import { move as moveAction } from "./actions" import { orderItemsByType } from "@/components/drive/utils" +import useErrorToast from "@/hooks/useErrorToast" +import useLoadingToast from "@/hooks/useLoadingToast" export const MoveTree = memo(({ parent, name }: { parent: string; name: string }) => { const { items, setItems } = useDriveItemsStore() + const errorToast = useErrorToast() + const loadingToast = useLoadingToast() const query = useQuery({ queryKey: ["listDirectoryOnlyDirectories", parent], @@ -44,6 +48,8 @@ export const MoveTree = memo(({ parent, name }: { parent: string; name: string } return } + const toast = loadingToast() + try { const itemsToMove = selectedItems.filter(item => item.parent !== parent) @@ -54,9 +60,18 @@ export const MoveTree = memo(({ parent, name }: { parent: string; name: string } setItems(prev => prev.filter(prevItem => !movedUUIDs.includes(prevItem.uuid))) } catch (e) { console.error(e) + + const toast = errorToast((e as unknown as Error).toString()) + + toast.update({ + id: toast.id, + duration: 5000 + }) + } finally { + toast.dismiss() } }, - [selectedItems, parent, setItems, canMove] + [selectedItems, parent, setItems, canMove, loadingToast, errorToast] ) if (!canMove) { diff --git a/src/components/mainContainer/innerSideBar/notes/note/contextMenu/index.tsx b/src/components/mainContainer/innerSideBar/notes/note/contextMenu/index.tsx index 70bee749..969f55b7 100644 --- a/src/components/mainContainer/innerSideBar/notes/note/contextMenu/index.tsx +++ b/src/components/mainContainer/innerSideBar/notes/note/contextMenu/index.tsx @@ -19,11 +19,15 @@ import { cn } from "@/lib/utils" import { useQuery } from "@tanstack/react-query" import { showSaveFilePicker } from "native-file-system-adapter" import striptags from "striptags" +import useLoadingToast from "@/hooks/useLoadingToast" +import useErrorToast from "@/hooks/useErrorToast" export const ContextMenu = memo(({ note, children }: { note: Note; children: React.ReactNode }) => { const { t } = useTranslation() const { setNotes, setSelectedNote, selectedNote, notes } = useNotesStore() const navigate = useNavigate() + const errorToast = useErrorToast() + const loadingToast = useLoadingToast() const tagsQuery = useQuery({ queryKey: ["listNotesTags"], @@ -31,6 +35,8 @@ export const ContextMenu = memo(({ note, children }: { note: Note; children: Rea }) const trash = useCallback(async () => { + const toast = loadingToast() + try { await worker.trashNote({ uuid: note.uuid }) @@ -38,22 +44,33 @@ export const ContextMenu = memo(({ note, children }: { note: Note; children: Rea setSelectedNote(prev => (prev && prev.uuid === note.uuid ? { ...prev, trash: true } : prev)) } catch (e) { console.error(e) + + const toast = errorToast((e as unknown as Error).toString()) + + toast.update({ + id: toast.id, + duration: 5000 + }) + } finally { + toast.dismiss() } - }, [note.uuid, setNotes, setSelectedNote]) + }, [note.uuid, setNotes, setSelectedNote, loadingToast, errorToast]) const deleteNote = useCallback(async () => { - try { - if ( - !(await showConfirmDialog({ - title: "delete", - continueButtonText: "delete", - continueButtonVariant: "destructive", - description: "delele" - })) - ) { - return - } + if ( + !(await showConfirmDialog({ + title: "delete", + continueButtonText: "delete", + continueButtonVariant: "destructive", + description: "delele" + })) + ) { + return + } + + const toast = loadingToast() + try { await worker.deleteNote({ uuid: note.uuid }) setNotes(prev => prev.filter(prevNote => prevNote.uuid !== note.uuid)) @@ -76,10 +93,21 @@ export const ContextMenu = memo(({ note, children }: { note: Note; children: Rea } } catch (e) { console.error(e) + + const toast = errorToast((e as unknown as Error).toString()) + + toast.update({ + id: toast.id, + duration: 5000 + }) + } finally { + toast.dismiss() } - }, [note.uuid, setNotes, setSelectedNote, notes, navigate, selectedNote?.uuid]) + }, [note.uuid, setNotes, setSelectedNote, notes, navigate, selectedNote?.uuid, errorToast, loadingToast]) const favorite = useCallback(async () => { + const toast = loadingToast() + try { await worker.favoriteNote({ uuid: note.uuid, favorite: true }) @@ -87,10 +115,21 @@ export const ContextMenu = memo(({ note, children }: { note: Note; children: Rea setSelectedNote(prev => (prev && prev.uuid === note.uuid ? { ...prev, favorite: true } : prev)) } catch (e) { console.error(e) + + const toast = errorToast((e as unknown as Error).toString()) + + toast.update({ + id: toast.id, + duration: 5000 + }) + } finally { + toast.dismiss() } - }, [note.uuid, setNotes, setSelectedNote]) + }, [note.uuid, setNotes, setSelectedNote, loadingToast, errorToast]) const unfavorite = useCallback(async () => { + const toast = loadingToast() + try { await worker.favoriteNote({ uuid: note.uuid, favorite: false }) @@ -98,10 +137,21 @@ export const ContextMenu = memo(({ note, children }: { note: Note; children: Rea setSelectedNote(prev => (prev && prev.uuid === note.uuid ? { ...prev, favorite: false } : prev)) } catch (e) { console.error(e) + + const toast = errorToast((e as unknown as Error).toString()) + + toast.update({ + id: toast.id, + duration: 5000 + }) + } finally { + toast.dismiss() } - }, [note.uuid, setNotes, setSelectedNote]) + }, [note.uuid, setNotes, setSelectedNote, loadingToast, errorToast]) const pin = useCallback(async () => { + const toast = loadingToast() + try { await worker.pinNote({ uuid: note.uuid, pin: true }) @@ -109,10 +159,21 @@ export const ContextMenu = memo(({ note, children }: { note: Note; children: Rea setSelectedNote(prev => (prev && prev.uuid === note.uuid ? { ...prev, pinned: true } : prev)) } catch (e) { console.error(e) + + const toast = errorToast((e as unknown as Error).toString()) + + toast.update({ + id: toast.id, + duration: 5000 + }) + } finally { + toast.dismiss() } - }, [note.uuid, setNotes, setSelectedNote]) + }, [note.uuid, setNotes, setSelectedNote, loadingToast, errorToast]) const unpin = useCallback(async () => { + const toast = loadingToast() + try { await worker.pinNote({ uuid: note.uuid, pin: false }) @@ -120,10 +181,21 @@ export const ContextMenu = memo(({ note, children }: { note: Note; children: Rea setSelectedNote(prev => (prev && prev.uuid === note.uuid ? { ...prev, pinned: false } : prev)) } catch (e) { console.error(e) + + const toast = errorToast((e as unknown as Error).toString()) + + toast.update({ + id: toast.id, + duration: 5000 + }) + } finally { + toast.dismiss() } - }, [note.uuid, setNotes, setSelectedNote]) + }, [note.uuid, setNotes, setSelectedNote, loadingToast, errorToast]) const duplicate = useCallback(async () => { + const toast = loadingToast() + try { const uuid = await worker.duplicateNote({ uuid: note.uuid }) const notes = await worker.listNotes() @@ -139,10 +211,21 @@ export const ContextMenu = memo(({ note, children }: { note: Note; children: Rea }) } catch (e) { console.error(e) + + const toast = errorToast((e as unknown as Error).toString()) + + toast.update({ + id: toast.id, + duration: 5000 + }) + } finally { + toast.dismiss() } - }, [note.uuid, setNotes, navigate, setSelectedNote]) + }, [note.uuid, setNotes, navigate, setSelectedNote, loadingToast, errorToast]) const restore = useCallback(async () => { + const toast = loadingToast() + try { await worker.restoreNote({ uuid: note.uuid }) @@ -150,10 +233,21 @@ export const ContextMenu = memo(({ note, children }: { note: Note; children: Rea setSelectedNote(prev => (prev && prev.uuid === note.uuid ? { ...prev, trash: false, archive: false } : prev)) } catch (e) { console.error(e) + + const toast = errorToast((e as unknown as Error).toString()) + + toast.update({ + id: toast.id, + duration: 5000 + }) + } finally { + toast.dismiss() } - }, [note.uuid, setNotes, setSelectedNote]) + }, [note.uuid, setNotes, setSelectedNote, loadingToast, errorToast]) const archive = useCallback(async () => { + const toast = loadingToast() + try { await worker.archiveNote({ uuid: note.uuid }) @@ -161,8 +255,17 @@ export const ContextMenu = memo(({ note, children }: { note: Note; children: Rea setSelectedNote(prev => (prev && prev.uuid === note.uuid ? { ...prev, archive: true } : prev)) } catch (e) { console.error(e) + + const toast = errorToast((e as unknown as Error).toString()) + + toast.update({ + id: toast.id, + duration: 5000 + }) + } finally { + toast.dismiss() } - }, [note.uuid, setNotes, setSelectedNote]) + }, [note.uuid, setNotes, setSelectedNote, loadingToast, errorToast]) const changeType = useCallback( async (type: NoteType) => { @@ -170,6 +273,8 @@ export const ContextMenu = memo(({ note, children }: { note: Note; children: Rea return } + const toast = loadingToast() + try { await worker.changeNoteType({ uuid: note.uuid, type }) @@ -177,13 +282,24 @@ export const ContextMenu = memo(({ note, children }: { note: Note; children: Rea setSelectedNote(prev => (prev && prev.uuid === note.uuid ? { ...prev, type } : prev)) } catch (e) { console.error(e) + + const toast = errorToast((e as unknown as Error).toString()) + + toast.update({ + id: toast.id, + duration: 5000 + }) + } finally { + toast.dismiss() } }, - [note.uuid, setNotes, setSelectedNote, note.type] + [note.uuid, setNotes, setSelectedNote, note.type, loadingToast, errorToast] ) const tagNote = useCallback( async (tag: NoteTag) => { + const toast = loadingToast() + try { await worker.tagNote({ uuid: note.uuid, tag: tag.uuid }) @@ -193,13 +309,24 @@ export const ContextMenu = memo(({ note, children }: { note: Note; children: Rea setSelectedNote(prev => (prev && prev.uuid === note.uuid ? { ...prev, tags: [...prev.tags, tag] } : prev)) } catch (e) { console.error(e) + + const toast = errorToast((e as unknown as Error).toString()) + + toast.update({ + id: toast.id, + duration: 5000 + }) + } finally { + toast.dismiss() } }, - [note.uuid, setNotes, setSelectedNote] + [note.uuid, setNotes, setSelectedNote, loadingToast, errorToast] ) const untagNote = useCallback( async (tag: NoteTag) => { + const toast = loadingToast() + try { await worker.tagNote({ uuid: note.uuid, tag: tag.uuid }) @@ -213,12 +340,23 @@ export const ContextMenu = memo(({ note, children }: { note: Note; children: Rea ) } catch (e) { console.error(e) + + const toast = errorToast((e as unknown as Error).toString()) + + toast.update({ + id: toast.id, + duration: 5000 + }) + } finally { + toast.dismiss() } }, - [note.uuid, setNotes, setSelectedNote] + [note.uuid, setNotes, setSelectedNote, loadingToast, errorToast] ) const exportNote = useCallback(async () => { + const toast = loadingToast() + try { let { content } = await worker.fetchNoteContent({ uuid: note.uuid }) @@ -261,8 +399,17 @@ export const ContextMenu = memo(({ note, children }: { note: Note; children: Rea writer.close() } catch (e) { console.error(e) + + const toast = errorToast((e as unknown as Error).toString()) + + toast.update({ + id: toast.id, + duration: 5000 + }) + } finally { + toast.dismiss() } - }, [note.uuid, note.title, note.type]) + }, [note.uuid, note.title, note.type, loadingToast, errorToast]) return ( diff --git a/src/components/mainContainer/innerSideBar/top/notes/tags/contextMenu.tsx b/src/components/mainContainer/innerSideBar/top/notes/tags/contextMenu.tsx index bd80b14d..cccdf47e 100644 --- a/src/components/mainContainer/innerSideBar/top/notes/tags/contextMenu.tsx +++ b/src/components/mainContainer/innerSideBar/top/notes/tags/contextMenu.tsx @@ -13,6 +13,7 @@ import { showConfirmDialog } from "@/components/dialogs/confirm" import { showInputDialog } from "@/components/dialogs/input" import { type RefetchOptions, type QueryObserverResult } from "@tanstack/react-query" import useLoadingToast from "@/hooks/useLoadingToast" +import useErrorToast from "@/hooks/useErrorToast" export const ContextMenu = memo( ({ @@ -26,6 +27,7 @@ export const ContextMenu = memo( }) => { const { t } = useTranslation() const loadingToast = useLoadingToast() + const errorToast = useErrorToast() const deleteTag = useCallback(async () => { if ( @@ -46,10 +48,17 @@ export const ContextMenu = memo( await refetch() } catch (e) { console.error(e) + + const toast = errorToast((e as unknown as Error).toString()) + + toast.update({ + id: toast.id, + duration: 5000 + }) } finally { toast.dismiss() } - }, [tag.uuid, refetch, loadingToast]) + }, [tag.uuid, refetch, loadingToast, errorToast]) const favorite = useCallback(async () => { const toast = loadingToast() @@ -62,10 +71,17 @@ export const ContextMenu = memo( await refetch() } catch (e) { console.error(e) + + const toast = errorToast((e as unknown as Error).toString()) + + toast.update({ + id: toast.id, + duration: 5000 + }) } finally { toast.dismiss() } - }, [tag.uuid, refetch, loadingToast]) + }, [tag.uuid, refetch, loadingToast, errorToast]) const unfavorite = useCallback(async () => { const toast = loadingToast() @@ -75,13 +91,21 @@ export const ContextMenu = memo( uuid: tag.uuid, favorite: false }) + await refetch() } catch (e) { console.error(e) + + const toast = errorToast((e as unknown as Error).toString()) + + toast.update({ + id: toast.id, + duration: 5000 + }) } finally { toast.dismiss() } - }, [tag.uuid, refetch, loadingToast]) + }, [tag.uuid, refetch, loadingToast, errorToast]) const rename = useCallback(async () => { const inputResponse = await showInputDialog({ @@ -103,13 +127,21 @@ export const ContextMenu = memo( uuid: tag.uuid, name: inputResponse.value.trim() }) + await refetch() } catch (e) { console.error(e) + + const toast = errorToast((e as unknown as Error).toString()) + + toast.update({ + id: toast.id, + duration: 5000 + }) } finally { toast.dismiss() } - }, [tag.uuid, refetch, loadingToast]) + }, [tag.uuid, refetch, loadingToast, errorToast]) return ( diff --git a/src/components/mainContainer/topBar/notes.tsx b/src/components/mainContainer/topBar/notes.tsx index acddaff8..c7d6f532 100644 --- a/src/components/mainContainer/topBar/notes.tsx +++ b/src/components/mainContainer/topBar/notes.tsx @@ -4,9 +4,13 @@ import { CheckCircle2, Loader, MoreVertical } from "lucide-react" import { showInputDialog } from "@/components/dialogs/input" import worker from "@/lib/worker" import ContextMenu from "../innerSideBar/notes/note/contextMenu" +import useLoadingToast from "@/hooks/useLoadingToast" +import useErrorToast from "@/hooks/useErrorToast" export const Notes = memo(() => { const { selectedNote, setSelectedNote, setNotes, synced } = useNotesStore() + const loadingToast = useLoadingToast() + const errorToast = useErrorToast() const triggerMoreIconContextMenu = useCallback( (e: React.MouseEvent | React.MouseEvent) => { @@ -30,19 +34,21 @@ export const Notes = memo(() => { return } - try { - const inputResponse = await showInputDialog({ - title: "title", - continueButtonText: "edit", - value: selectedNote.title, - autoFocusInput: true, - placeholder: "Title" - }) + const inputResponse = await showInputDialog({ + title: "title", + continueButtonText: "edit", + value: selectedNote.title, + autoFocusInput: true, + placeholder: "Title" + }) + + if (inputResponse.cancelled) { + return + } - if (inputResponse.cancelled) { - return - } + const toast = loadingToast() + try { await worker.editNoteTitle({ uuid: selectedNote.uuid, title: inputResponse.value }) setSelectedNote(prev => (prev ? { ...prev, title: inputResponse.value } : prev)) @@ -51,8 +57,17 @@ export const Notes = memo(() => { ) } catch (e) { console.error(e) + + const toast = errorToast((e as unknown as Error).toString()) + + toast.update({ + id: toast.id, + duration: 5000 + }) + } finally { + toast.dismiss() } - }, [selectedNote, setSelectedNote, setNotes]) + }, [selectedNote, setSelectedNote, setNotes, loadingToast, errorToast]) if (!selectedNote) { return null diff --git a/src/lib/worker/proxy.ts b/src/lib/worker/proxy.ts index 4f696796..f1c15acf 100644 --- a/src/lib/worker/proxy.ts +++ b/src/lib/worker/proxy.ts @@ -14,6 +14,8 @@ import { getItem } from "@/lib/localForage" export const generateThumbnailMutexes: Record = {} export const generateThumbnailSemaphore = new Semaphore(3) +const useNative = ["Blink"].includes(UAParserResult?.engine?.name ?? "Gecko") + // Setup message handler. The worker sends messages to the main thread. worker.setMessageHandler(proxy(event => eventEmitter.emit("workerMessage", event))) @@ -33,8 +35,6 @@ export async function downloadFile({ item }: { item: DriveCloudItem }): Promise< return } - const useNative = ["Blink", "WebKit"].includes(UAParserResult.engine.name ?? "Gecko") - const fileHandle = await showSaveFilePicker({ suggestedName: item.name, _preferPolyfill: !useNative @@ -64,8 +64,6 @@ export async function downloadDirectory({ linkPassword?: string linkSalt?: string }): Promise { - const useNative = ["Blink", "WebKit"].includes(UAParserResult.engine.name ?? "Gecko") - const fileHandle = await showSaveFilePicker({ suggestedName: `${name}.zip`, _preferPolyfill: !useNative @@ -90,8 +88,6 @@ export async function downloadDirectory({ * @returns {Promise} */ export async function downloadMultipleFilesAndDirectoriesAsZip({ items }: { items: DriveCloudItem[] }): Promise { - const useNative = ["Blink", "WebKit"].includes(UAParserResult.engine.name ?? "Gecko") - const fileHandle = await showSaveFilePicker({ suggestedName: `Download_${Date.now()}.zip`, _preferPolyfill: !useNative @@ -148,12 +144,14 @@ export async function generateThumbnail({ item }: { item: DriveCloudItem }): Pro // Needs to run in the main thread if (thumbnailType === "pdf") { const fromDb = await getItem(dbKey) + let blob: Blob if (fromDb) { blob = fromDb } else { const buffer = await worker.readFile({ item, emitEvents: false }) + blob = await workerLib.generatePDFThumbnail({ item, buffer }) } @@ -173,12 +171,14 @@ export async function generateThumbnail({ item }: { item: DriveCloudItem }): Pro blob = fromDb } else { const chunkedEnd = 1024 * 1024 * 8 - 1 + const buffer = await worker.readFile({ item, emitEvents: false, start: 0, end: chunkedEnd >= item.size - 1 ? item.size - 1 : chunkedEnd }) + blob = await workerLib.generateVideoThumbnail({ item, buffer }) }