diff --git a/apps/mail/app/globals.css b/apps/mail/app/globals.css index 5f135cc01..cd83a8e65 100644 --- a/apps/mail/app/globals.css +++ b/apps/mail/app/globals.css @@ -48,7 +48,7 @@ --sidebar-accent-foreground: 240 5.9% 10%; --sidebar-border: 220 13% 91%; --sidebar-ring: 217.2 91.2% 59.8%; - --icon-color: black; + --icon-color: currentColor; } .dark { diff --git a/apps/mail/components/icons/icons.tsx b/apps/mail/components/icons/icons.tsx index 2fec9694c..0d369e34b 100644 --- a/apps/mail/components/icons/icons.tsx +++ b/apps/mail/components/icons/icons.tsx @@ -425,8 +425,8 @@ export const ExclamationCircle = ({ className }: { className?: string }) => ( fillRule="evenodd" clipRule="evenodd" d="M7 13.5C10.5899 13.5 13.5 10.5899 13.5 7C13.5 3.41015 10.5899 0.5 7 0.5C3.41015 0.5 0.5 3.41015 0.5 7C0.5 10.5899 3.41015 13.5 7 13.5ZM7 3.28571C7.38463 3.28571 7.69643 3.59752 7.69643 3.98214V6.76786C7.69643 7.15248 7.38463 7.46429 7 7.46429C6.61537 7.46429 6.30357 7.15248 6.30357 6.76786V3.98214C6.30357 3.59752 6.61537 3.28571 7 3.28571ZM7 10.7143C7.51284 10.7143 7.92857 10.2986 7.92857 9.78571C7.92857 9.27288 7.51284 8.85714 7 8.85714C6.48716 8.85714 6.07143 9.27288 6.07143 9.78571C6.07143 10.2986 6.48716 10.7143 7 10.7143Z" - fill="var(--icon-color)" - fillOpacity="0.5" + // fill="var(--icon-color)" + // fillOpacity="0.5" /> ); @@ -1763,12 +1763,18 @@ export const Printer = ({ className }: { className?: string }) => ( ); export const OldPhone = ({ className }: { className?: string }) => ( - + - ); diff --git a/apps/mail/components/mail/mail-list.tsx b/apps/mail/components/mail/mail-list.tsx index cb1cf7cca..e485791e6 100644 --- a/apps/mail/components/mail/mail-list.tsx +++ b/apps/mail/components/mail/mail-list.tsx @@ -271,7 +271,13 @@ const Thread = memo( className="h-6 w-6 [&_svg]:size-3.5" onClick={handleToggleImportant} > - + { - enableScope('mail-list'); - }} - onMouseLeave={() => { - disableScope('mail-list'); - }} > <> {isLoading ? ( @@ -945,7 +945,7 @@ function getLabelIcon(label: string) { switch (normalizedLabel) { case 'starred': - return ; + return ; default: return null; } diff --git a/apps/mail/components/mail/mail.tsx b/apps/mail/components/mail/mail.tsx index a33257a91..0195a8d2e 100644 --- a/apps/mail/components/mail/mail.tsx +++ b/apps/mail/components/mail/mail.tsx @@ -432,6 +432,15 @@ export function MailLayout() { disableScope('mail-list'); }; }, [threadId, enableScope, disableScope]); + + const handleMailListMouseEnter = useCallback(() => { + enableScope('mail-list'); + }, [enableScope]); + + const handleMailListMouseLeave = useCallback(() => { + disableScope('mail-list'); + }, [disableScope]); + const [, setActiveReplyId] = useQueryState('activeReplyId'); // Add mailto protocol handler registration @@ -472,6 +481,8 @@ export function MailLayout() { `bg-panelLight dark:bg-panelDark mb-1 w-fit shadow-sm md:rounded-2xl md:border md:border-[#E7E7E7] lg:flex lg:shadow-sm dark:border-[#252525]`, isDesktop && threadId && 'hidden lg:block', )} + onMouseEnter={handleMailListMouseEnter} + onMouseLeave={handleMailListMouseLeave} >
Promise; undo: () => void; + toastId?: string | number; }; export function useOptimisticActions() { @@ -41,6 +42,7 @@ export function useOptimisticActions() { const pendingActionsRef = useRef>(new Map()); const pendingActionsByTypeRef = useRef>>(new Map()); + const lastActionIdRef = useRef(null); const generatePendingActionId = () => `pending_${Date.now()}_${Math.random().toString(36).substring(2, 9)}`; @@ -406,6 +408,24 @@ export function useOptimisticActions() { ], ); + const undoLastAction = useCallback(() => { + if (!lastActionIdRef.current) return; + + const lastAction = pendingActionsRef.current.get(lastActionIdRef.current); + if (!lastAction) return; + + lastAction.undo(); + + pendingActionsRef.current.delete(lastActionIdRef.current); + pendingActionsByTypeRef.current.get(lastAction.type)?.delete(lastActionIdRef.current); + + if (lastAction.toastId) { + toast.dismiss(lastAction.toastId); + } + + lastActionIdRef.current = null; + }, []); + return { optimisticMarkAsRead, optimisticMarkAsUnread, @@ -413,5 +433,6 @@ export function useOptimisticActions() { optimisticMoveThreadsTo, optimisticDeleteThreads, optimisticToggleImportant, + undoLastAction, }; } diff --git a/apps/mail/lib/hotkeys/global-hotkeys.tsx b/apps/mail/lib/hotkeys/global-hotkeys.tsx index faea2cc6c..524bdbc34 100644 --- a/apps/mail/lib/hotkeys/global-hotkeys.tsx +++ b/apps/mail/lib/hotkeys/global-hotkeys.tsx @@ -1,4 +1,5 @@ import { useCommandPalette } from '@/components/context/command-palette-context'; +import { useOptimisticActions } from '@/hooks/use-optimistic-actions'; import { keyboardShortcuts } from '@/config/shortcuts'; import { useVoice } from '@/providers/voice-provider'; import { useShortcuts } from './use-hotkey-utils'; @@ -7,6 +8,7 @@ import { useQueryState } from 'nuqs'; export function GlobalHotkeys() { const [composeOpen, setComposeOpen] = useQueryState('isComposeOpen'); const { openModal, clearAllFilters } = useCommandPalette(); + const { undoLastAction } = useOptimisticActions(); const { startConversation } = useVoice(); const scope = 'global'; @@ -17,6 +19,9 @@ export function GlobalHotkeys() { newEmail: () => setComposeOpen('true'), commandPalette: () => openModal(), clearAllFilters: () => clearAllFilters(), + undoLastAction: () => { + undoLastAction(); + }, }; const globalShortcuts = keyboardShortcuts.filter((shortcut) => shortcut.scope === scope);