diff --git a/packages/web/src/common/utils/shortcut/data/shortcuts.data.ts b/packages/web/src/common/utils/shortcut/data/shortcuts.data.ts index ff3953ef1..ebc9713f7 100644 --- a/packages/web/src/common/utils/shortcut/data/shortcuts.data.ts +++ b/packages/web/src/common/utils/shortcut/data/shortcuts.data.ts @@ -4,29 +4,20 @@ import { type Shortcut } from "@web/common/types/global.shortcut.types"; interface ShortcutsConfig { isHome?: boolean; - isAuthenticated?: boolean; isToday?: boolean; isNow?: boolean; currentDate?: dayjs.Dayjs; } export const getShortcuts = (config: ShortcutsConfig = {}) => { - const { - isAuthenticated = false, - isHome = false, - isToday = true, - isNow = false, - currentDate, - } = config; + const { isHome = false, isToday = true, isNow = false, currentDate } = config; const globalShortcuts: Shortcut[] = [ { k: VIEW_SHORTCUTS.now.key, label: VIEW_SHORTCUTS.now.label }, { k: VIEW_SHORTCUTS.day.key, label: VIEW_SHORTCUTS.day.label }, { k: VIEW_SHORTCUTS.week.key, label: VIEW_SHORTCUTS.week.label }, - { k: "r", label: "Edit reminder" }, - { k: "[", label: "Toggle sidebar" }, - { k: "?", label: "Toggle shortcuts" }, - { k: "z", label: isAuthenticated ? "Logout" : "Log in" }, + { k: "[", label: "Close sidebar" }, + { k: "?", label: "Show shortcuts" }, { k: "Mod+k", label: "Command Palette" }, ]; @@ -73,7 +64,8 @@ export const getShortcuts = (config: ShortcutsConfig = {}) => { } if (isNow) { nowShortcuts = [ - { k: "e", label: "Edit description" }, + { k: "e d", label: "Edit description" }, + { k: "e r", label: "Edit reminder" }, { k: "Mod+Enter", label: "Save description" }, { k: "j", label: "Previous task" }, { k: "k", label: "Next task" }, diff --git a/packages/web/src/views/Day/view/DayViewContent.tsx b/packages/web/src/views/Day/view/DayViewContent.tsx index 56c5553b2..9062cbd32 100644 --- a/packages/web/src/views/Day/view/DayViewContent.tsx +++ b/packages/web/src/views/Day/view/DayViewContent.tsx @@ -1,6 +1,5 @@ import { memo, useCallback, useMemo } from "react"; import dayjs from "@core/util/date/dayjs"; -import { useSession } from "@web/auth/compass/session/useSession"; import { useCompassRefs } from "@web/common/hooks/useCompassRefs"; import { useEventDNDActions } from "@web/common/hooks/useEventDNDActions"; import { useGridOrganization } from "@web/common/hooks/useGridOrganization"; @@ -38,7 +37,6 @@ import { Styled, StyledCalendar } from "@web/views/Week/styled"; export const DayViewContent = memo(() => { const dispatch = useAppDispatch(); const isSidebarOpen = useAppSelector(selectIsSidebarOpen); - const { authenticated } = useSession(); const selectionActions = useMainGridSelectionActions(); const { timedEventsGridRef } = useCompassRefs(); @@ -64,7 +62,6 @@ export const DayViewContent = memo(() => { const dateInView = useDateInView(); const shortcuts = getShortcuts({ currentDate: dateInView, - isAuthenticated: authenticated, }); const { diff --git a/packages/web/src/views/Now/components/TaskDescription/TaskDescription.tsx b/packages/web/src/views/Now/components/TaskDescription/TaskDescription.tsx index e9d9f8000..4eb4b1176 100644 --- a/packages/web/src/views/Now/components/TaskDescription/TaskDescription.tsx +++ b/packages/web/src/views/Now/components/TaskDescription/TaskDescription.tsx @@ -8,6 +8,7 @@ import { } from "@web/common/utils/dom/event-emitter.util"; import { Textarea } from "@web/components/Textarea"; import { TooltipWrapper } from "@web/components/Tooltip/TooltipWrapper"; +import { ShortCutLabel } from "@web/common/utils/shortcut/shortcut.util"; const MAX_DESCRIPTION_LENGTH = 255; const NEAR_LIMIT_THRESHOLD = Math.floor(MAX_DESCRIPTION_LENGTH * 0.9); // 90% of max @@ -242,7 +243,16 @@ export const TaskDescription: React.FC = ({ {value.length}/{MAX_DESCRIPTION_LENGTH} - + + + + + + + } + > { + navigate(ROOT_ROUTES.DAY); + }, [navigate]); + + const handleEditReminder = useCallback(() => { + dispatch(viewSlice.actions.updateReminder(true)); + }, [dispatch]); + useNowShortcuts({ focusedTask, availableTasks, @@ -142,6 +153,8 @@ export function NowViewProvider({ onNextTask: handleNextTask, onCompleteTask: handleCompleteTask, onToggleSidebar, + onEscape: handleEscape, + onEditReminder: handleEditReminder, }); const value: NowViewContextValue = { diff --git a/packages/web/src/views/Now/shortcuts/useNowShortcuts.test.tsx b/packages/web/src/views/Now/shortcuts/useNowShortcuts.test.tsx index 543f526b5..2c99d4197 100644 --- a/packages/web/src/views/Now/shortcuts/useNowShortcuts.test.tsx +++ b/packages/web/src/views/Now/shortcuts/useNowShortcuts.test.tsx @@ -30,7 +30,7 @@ describe("useNowShortcuts", () => { ); }); - it("uses E to focus the task description", async () => { + it("uses E D sequence to focus the task description", async () => { const onFocusDescription = mock(); compassEventEmitter.on( CompassDOMEvents.FOCUS_TASK_DESCRIPTION, @@ -39,13 +39,14 @@ describe("useNowShortcuts", () => { renderHook(() => useNowShortcuts(), { wrapper }); pressKey("e"); + pressKey("d"); await waitFor(() => { expect(onFocusDescription).toHaveBeenCalledTimes(1); }); }); - it("does not use D for the task description shortcut", async () => { + it("does not focus description when pressing D alone", async () => { const onFocusDescription = mock(); compassEventEmitter.on( CompassDOMEvents.FOCUS_TASK_DESCRIPTION, @@ -70,4 +71,27 @@ describe("useNowShortcuts", () => { expect(onToggleSidebar).toHaveBeenCalledTimes(1); }); }); + + it("navigates to day view when Escape is pressed", async () => { + const onEscape = mock(); + renderHook(() => useNowShortcuts({ onEscape }), { wrapper }); + + pressKey("Escape"); + + await waitFor(() => { + expect(onEscape).toHaveBeenCalledTimes(1); + }); + }); + + it("uses E R sequence to edit reminder", async () => { + const onEditReminder = mock(); + renderHook(() => useNowShortcuts({ onEditReminder }), { wrapper }); + + pressKey("e"); + pressKey("r"); + + await waitFor(() => { + expect(onEditReminder).toHaveBeenCalledTimes(1); + }); + }); }); diff --git a/packages/web/src/views/Now/shortcuts/useNowShortcuts.ts b/packages/web/src/views/Now/shortcuts/useNowShortcuts.ts index 2f52fb69b..96214cdd3 100644 --- a/packages/web/src/views/Now/shortcuts/useNowShortcuts.ts +++ b/packages/web/src/views/Now/shortcuts/useNowShortcuts.ts @@ -1,4 +1,5 @@ import { useCallback } from "react"; +import { useHotkeySequence } from "@tanstack/react-hotkeys"; import { ID_REMINDER_INPUT } from "@web/common/constants/web.constants"; import { useAppHotkey, useAppHotkeyUp } from "@web/common/hooks/useAppHotkey"; import { type Task } from "@web/common/types/task.types"; @@ -14,6 +15,8 @@ interface Props { onNextTask?: () => void; onCompleteTask?: () => void; onToggleSidebar?: () => void; + onEscape?: () => void; + onEditReminder?: () => void; } export function useNowShortcuts(props?: Props) { @@ -24,6 +27,8 @@ export function useNowShortcuts(props?: Props) { onNextTask, onCompleteTask, onToggleSidebar, + onEscape, + onEditReminder, } = props || {}; const handleTaskNavigation = useCallback( @@ -35,7 +40,7 @@ export function useNowShortcuts(props?: Props) { [focusedTask, availableTasks.length], ); - useAppHotkeyUp("E", () => { + useHotkeySequence(["E", "D"], () => { compassEventEmitter.emit(CompassDOMEvents.FOCUS_TASK_DESCRIPTION); }); @@ -71,4 +76,12 @@ export function useNowShortcuts(props?: Props) { useAppHotkeyUp("[", () => { onToggleSidebar?.(); }); + + useAppHotkeyUp("Escape", () => { + onEscape?.(); + }); + + useHotkeySequence(["E", "R"], () => { + onEditReminder?.(); + }); } diff --git a/packages/web/src/views/Now/view/NowView.tsx b/packages/web/src/views/Now/view/NowView.tsx index 81f3d25da..748bffe46 100644 --- a/packages/web/src/views/Now/view/NowView.tsx +++ b/packages/web/src/views/Now/view/NowView.tsx @@ -1,5 +1,4 @@ import { useEffect } from "react"; -import { useSession } from "@web/auth/compass/session/useSession"; import { usePointerPosition } from "@web/common/hooks/usePointerPosition"; import { useSidebarState } from "@web/common/hooks/useSidebarState"; import { getShortcuts } from "@web/common/utils/shortcut/data/shortcuts.data"; @@ -11,11 +10,9 @@ import { NowViewContent } from "@web/views/Now/view/NowViewContent"; import { StyledCalendar } from "@web/views/Week/styled"; export const NowView = () => { - const { authenticated } = useSession(); const { togglePointerMovementTracking } = usePointerPosition(); const { isSidebarOpen, toggleSidebar } = useSidebarState(); const { globalShortcuts, nowShortcuts } = getShortcuts({ - isAuthenticated: authenticated, isNow: true, }); diff --git a/packages/web/src/views/Week/WeekView.tsx b/packages/web/src/views/Week/WeekView.tsx index 6ef2f5244..4a44b203d 100644 --- a/packages/web/src/views/Week/WeekView.tsx +++ b/packages/web/src/views/Week/WeekView.tsx @@ -92,8 +92,8 @@ export const WeekView = () => { { k: "d", label: "Day" }, { k: "w", label: "Week" }, { k: "n", label: "Now" }, - { k: "[", label: "Toggle sidebar" }, - { k: "?", label: "Toggle shortcuts" }, + { k: "[", label: "Close sidebar" }, + { k: "?", label: "Show shortcuts" }, { k: "Mod+k", label: "Command Palette" }, ], }, diff --git a/packages/web/src/views/Week/hooks/shortcuts/useGlobalShortcuts.ts b/packages/web/src/views/Week/hooks/shortcuts/useGlobalShortcuts.ts index 4fdb9de19..9a87388ed 100644 --- a/packages/web/src/views/Week/hooks/shortcuts/useGlobalShortcuts.ts +++ b/packages/web/src/views/Week/hooks/shortcuts/useGlobalShortcuts.ts @@ -5,7 +5,6 @@ import { ROOT_ROUTES } from "@web/common/constants/routes"; import { VIEW_SHORTCUTS } from "@web/common/constants/shortcuts.constants"; import { useAppHotkey, useAppHotkeyUp } from "@web/common/hooks/useAppHotkey"; import { useAuthModal } from "@web/components/AuthModal/hooks/useAuthModal"; -import { viewSlice } from "@web/ducks/events/slices/view.slice"; import { settingsSlice } from "@web/ducks/settings/slices/settings.slice"; import { useAppDispatch } from "@web/store/store.hooks"; @@ -51,10 +50,6 @@ export function useGlobalShortcuts() { openModal("login"); }); - useAppHotkeyUp("R", () => { - dispatch(viewSlice.actions.updateReminder(true)); - }); - useAppHotkey( "Mod+K", () => {