feat: add calendar hover preview settings and functionality
This commit is contained in:
@@ -69,7 +69,7 @@ export default function CalendarPage() {
|
|||||||
setSelectedDate, setViewMode, toggleCalendarVisibility, updateCalendar,
|
setSelectedDate, setViewMode, toggleCalendarVisibility, updateCalendar,
|
||||||
refreshAllSubscriptions,
|
refreshAllSubscriptions,
|
||||||
} = useCalendarStore();
|
} = useCalendarStore();
|
||||||
const { firstDayOfWeek, timeFormat, showWeekNumbers, enableCalendarTasks, showTasksOnCalendar } = useSettingsStore();
|
const { firstDayOfWeek, timeFormat, showWeekNumbers, enableCalendarTasks, showTasksOnCalendar, calendarHoverPreview } = useSettingsStore();
|
||||||
const taskStore = useTaskStore();
|
const taskStore = useTaskStore();
|
||||||
const fetchTasksFn = useTaskStore(state => state.fetchTasks);
|
const fetchTasksFn = useTaskStore(state => state.fetchTasks);
|
||||||
const { identities } = useIdentityStore();
|
const { identities } = useIdentityStore();
|
||||||
@@ -338,18 +338,26 @@ export default function CalendarPage() {
|
|||||||
|
|
||||||
const handleHoverEvent = useCallback((event: CalendarEvent, anchorRect: DOMRect) => {
|
const handleHoverEvent = useCallback((event: CalendarEvent, anchorRect: DOMRect) => {
|
||||||
if (isMobile) return;
|
if (isMobile) return;
|
||||||
|
if (calendarHoverPreview === 'off') return;
|
||||||
if (hoverTimerRef.current) { clearTimeout(hoverTimerRef.current); hoverTimerRef.current = null; }
|
if (hoverTimerRef.current) { clearTimeout(hoverTimerRef.current); hoverTimerRef.current = null; }
|
||||||
// Don't show hover popover if the sidebar is already open for this event
|
// Don't show hover popover if the sidebar is already open for this event
|
||||||
if (showEventModal && editEvent?.id === event.id) return;
|
if (showEventModal && editEvent?.id === event.id) return;
|
||||||
setDetailEvent(event);
|
if (calendarHoverPreview === 'delay-500ms' || calendarHoverPreview === 'delay-1s' || calendarHoverPreview === 'delay-2s') {
|
||||||
setDetailAnchorRect(anchorRect);
|
const ms = calendarHoverPreview === 'delay-500ms' ? 500 : calendarHoverPreview === 'delay-1s' ? 1000 : 2000;
|
||||||
}, [isMobile, showEventModal, editEvent]);
|
hoverTimerRef.current = setTimeout(() => {
|
||||||
|
setDetailEvent(event);
|
||||||
|
setDetailAnchorRect(anchorRect);
|
||||||
|
}, ms);
|
||||||
|
} else {
|
||||||
|
setDetailEvent(event);
|
||||||
|
setDetailAnchorRect(anchorRect);
|
||||||
|
}
|
||||||
|
}, [isMobile, calendarHoverPreview, showEventModal, editEvent]);
|
||||||
|
|
||||||
const handleHoverLeave = useCallback(() => {
|
const handleHoverLeave = useCallback(() => {
|
||||||
hoverTimerRef.current = setTimeout(() => {
|
if (hoverTimerRef.current) { clearTimeout(hoverTimerRef.current); hoverTimerRef.current = null; }
|
||||||
setDetailEvent(null);
|
setDetailEvent(null);
|
||||||
setDetailAnchorRect(null);
|
setDetailAnchorRect(null);
|
||||||
}, 200);
|
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
const handleEditFromDetail = useCallback(() => {
|
const handleEditFromDetail = useCallback(() => {
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ export function CalendarSettings() {
|
|||||||
showWeekNumbers,
|
showWeekNumbers,
|
||||||
enableCalendarTasks,
|
enableCalendarTasks,
|
||||||
showTasksOnCalendar,
|
showTasksOnCalendar,
|
||||||
|
calendarHoverPreview,
|
||||||
updateSetting,
|
updateSetting,
|
||||||
} = useSettingsStore();
|
} = useSettingsStore();
|
||||||
const { isFeatureEnabled } = usePolicyStore();
|
const { isFeatureEnabled } = usePolicyStore();
|
||||||
@@ -80,6 +81,23 @@ export function CalendarSettings() {
|
|||||||
/>
|
/>
|
||||||
</SettingItem>
|
</SettingItem>
|
||||||
|
|
||||||
|
<SettingItem
|
||||||
|
label={t('hover_preview')}
|
||||||
|
description={t('hover_preview_desc')}
|
||||||
|
>
|
||||||
|
<Select
|
||||||
|
value={calendarHoverPreview}
|
||||||
|
onChange={(value) => updateSetting('calendarHoverPreview', value as 'off' | 'instant' | 'delay-500ms' | 'delay-1s' | 'delay-2s')}
|
||||||
|
options={[
|
||||||
|
{ value: 'instant', label: t('hover_preview_instant') },
|
||||||
|
{ value: 'delay-500ms', label: t('hover_preview_delay_500ms') },
|
||||||
|
{ value: 'delay-1s', label: t('hover_preview_delay_1s') },
|
||||||
|
{ value: 'delay-2s', label: t('hover_preview_delay_2s') },
|
||||||
|
{ value: 'off', label: t('hover_preview_off') },
|
||||||
|
]}
|
||||||
|
/>
|
||||||
|
</SettingItem>
|
||||||
|
|
||||||
{isFeatureEnabled('calendarTasksEnabled') && (
|
{isFeatureEnabled('calendarTasksEnabled') && (
|
||||||
<>
|
<>
|
||||||
<SettingItem
|
<SettingItem
|
||||||
|
|||||||
@@ -1981,7 +1981,14 @@
|
|||||||
"enable_tasks": "Enable tasks",
|
"enable_tasks": "Enable tasks",
|
||||||
"enable_tasks_desc": "Show a tasks view in the calendar for managing to-dos",
|
"enable_tasks_desc": "Show a tasks view in the calendar for managing to-dos",
|
||||||
"show_tasks_on_calendar": "Show tasks on calendar",
|
"show_tasks_on_calendar": "Show tasks on calendar",
|
||||||
"show_tasks_on_calendar_desc": "Display task chips on the day and week calendar views"
|
"show_tasks_on_calendar_desc": "Display task chips on the day and week calendar views",
|
||||||
|
"hover_preview": "Event hover preview",
|
||||||
|
"hover_preview_desc": "Show a detail popover when hovering over calendar events",
|
||||||
|
"hover_preview_instant": "Instant",
|
||||||
|
"hover_preview_delay_500ms": "0.5-second delay",
|
||||||
|
"hover_preview_delay_1s": "1-second delay",
|
||||||
|
"hover_preview_delay_2s": "2-second delay",
|
||||||
|
"hover_preview_off": "Disabled"
|
||||||
},
|
},
|
||||||
"days": {
|
"days": {
|
||||||
"monday": "Monday",
|
"monday": "Monday",
|
||||||
|
|||||||
@@ -34,6 +34,7 @@ export type AttachmentPosition = 'beside-sender' | 'below-header';
|
|||||||
export type ToolbarPosition = 'top' | 'below-subject';
|
export type ToolbarPosition = 'top' | 'below-subject';
|
||||||
export type ArchiveMode = 'single' | 'year' | 'month';
|
export type ArchiveMode = 'single' | 'year' | 'month';
|
||||||
export type MailLayout = 'split' | 'focus';
|
export type MailLayout = 'split' | 'focus';
|
||||||
|
export type CalendarHoverPreview = 'off' | 'instant' | 'delay-500ms' | 'delay-1s' | 'delay-2s';
|
||||||
|
|
||||||
export type HoverAction = 'delete' | 'star' | 'markRead' | 'archive' | 'tag' | 'spam';
|
export type HoverAction = 'delete' | 'star' | 'markRead' | 'archive' | 'tag' | 'spam';
|
||||||
export type HoverActionsMode = 'inline' | 'floating';
|
export type HoverActionsMode = 'inline' | 'floating';
|
||||||
@@ -134,6 +135,7 @@ interface SettingsState {
|
|||||||
// Calendar
|
// Calendar
|
||||||
showTimeInMonthView: boolean;
|
showTimeInMonthView: boolean;
|
||||||
showWeekNumbers: boolean;
|
showWeekNumbers: boolean;
|
||||||
|
calendarHoverPreview: CalendarHoverPreview;
|
||||||
|
|
||||||
// Calendar Tasks
|
// Calendar Tasks
|
||||||
enableCalendarTasks: boolean;
|
enableCalendarTasks: boolean;
|
||||||
@@ -257,6 +259,7 @@ const DEFAULT_SETTINGS = {
|
|||||||
// Calendar
|
// Calendar
|
||||||
showTimeInMonthView: false,
|
showTimeInMonthView: false,
|
||||||
showWeekNumbers: false,
|
showWeekNumbers: false,
|
||||||
|
calendarHoverPreview: 'delay-500ms' as CalendarHoverPreview,
|
||||||
|
|
||||||
// Calendar Tasks
|
// Calendar Tasks
|
||||||
enableCalendarTasks: false,
|
enableCalendarTasks: false,
|
||||||
@@ -370,6 +373,7 @@ export const useSettingsStore = create<SettingsState>()(
|
|||||||
expandedFilterView: state.expandedFilterView,
|
expandedFilterView: state.expandedFilterView,
|
||||||
showTimeInMonthView: state.showTimeInMonthView,
|
showTimeInMonthView: state.showTimeInMonthView,
|
||||||
showWeekNumbers: state.showWeekNumbers,
|
showWeekNumbers: state.showWeekNumbers,
|
||||||
|
calendarHoverPreview: state.calendarHoverPreview,
|
||||||
toolbarPosition: state.toolbarPosition,
|
toolbarPosition: state.toolbarPosition,
|
||||||
hideAccountSwitcher: state.hideAccountSwitcher,
|
hideAccountSwitcher: state.hideAccountSwitcher,
|
||||||
showRailAccountList: state.showRailAccountList,
|
showRailAccountList: state.showRailAccountList,
|
||||||
|
|||||||
Reference in New Issue
Block a user