chore(react/collections/calendar): bring back saving of view

This commit is contained in:
Elian Doran 2025-09-05 17:18:02 +03:00
parent d6ccd106e6
commit 10d1ec1bb2
No known key found for this signature in database
4 changed files with 28 additions and 38 deletions

View File

@ -1,12 +1,13 @@
import { useEffect, useRef } from "preact/hooks";
import { CalendarOptions, Calendar as FullCalendar, PluginDef } from "@fullcalendar/core";
import { RefObject } from "preact";
interface CalendarProps extends CalendarOptions {
calendarRef?: RefObject<FullCalendar>;
tabIndex?: number;
}
export default function Calendar({ tabIndex, ...options }: CalendarProps) {
const calendarRef = useRef<FullCalendar>();
export default function Calendar({ tabIndex, calendarRef, ...options }: CalendarProps) {
const containerRef = useRef<HTMLDivElement>(null);
useEffect(() => {
@ -15,6 +16,10 @@ export default function Calendar({ tabIndex, ...options }: CalendarProps) {
const calendar = new FullCalendar(containerRef.current, options);
calendar.render();
if (calendarRef) {
calendarRef.current = calendar;
}
return () => calendar.destroy();
}, [ containerRef, options ]);

View File

@ -1,10 +1,13 @@
import { LocaleInput, PluginDef } from "@fullcalendar/core/index.js";
import { ViewModeProps } from "../interface";
import Calendar from "./calendar";
import { useEffect, useState } from "preact/hooks";
import { useEffect, useRef, useState } from "preact/hooks";
import "./index.css";
import { useNoteLabel, useNoteLabelBoolean, useTriliumOption, useTriliumOptionInt } from "../../react/hooks";
import { useNoteLabel, useNoteLabelBoolean, useSpacedUpdate, useTriliumOption, useTriliumOptionInt } from "../../react/hooks";
import { LOCALE_IDS } from "@triliumnext/commons";
import { Calendar as FullCalendar } from "@fullcalendar/core";
import { setLabel } from "../../../services/attributes";
import { circle } from "leaflet";
interface CalendarViewData {
@ -33,18 +36,23 @@ const LOCALE_MAPPINGS: Record<LOCALE_IDS, (() => Promise<{ default: LocaleInput
};
export default function CalendarView({ note, noteIds }: ViewModeProps<CalendarViewData>) {
const calendarRef = useRef<FullCalendar>(null);
const plugins = usePlugins(false, false);
const locale = useLocale();
const [ firstDayOfWeek ] = useTriliumOptionInt("firstDayOfWeek");
const [ hideWeekends ] = useNoteLabelBoolean(note, "calendar:hideWeekends");
const [ weekNumbers ] = useNoteLabelBoolean(note, "calendar:weekNumbers");
const [ calendarView, setCalendarView ] = useNoteLabel(note, "calendar:view");
const initialView = useRef(calendarView);
const viewSpacedUpdate = useSpacedUpdate(() => setCalendarView(initialView.current));
return (plugins &&
<div className="calendar-view">
<Calendar
calendarRef={calendarRef}
plugins={plugins}
tabIndex={100}
initialView="dayGridMonth"
initialView={initialView.current && CALENDAR_VIEWS.includes(initialView.current) ? initialView.current : "dayGridMonth"}
headerToolbar={{
start: "title",
end: `${CALENDAR_VIEWS.join(",")} today prev,next`
@ -53,6 +61,12 @@ export default function CalendarView({ note, noteIds }: ViewModeProps<CalendarVi
weekends={!hideWeekends}
weekNumbers={weekNumbers}
locale={locale}
viewDidMount={({ view }) => {
if (initialView.current !== view.type) {
initialView.current = view.type;
viewSpacedUpdate.scheduleUpdate();
}
}}
/>
</div>
);

View File

@ -54,21 +54,16 @@ export function useTriliumEvents<T extends EventNames>(eventNames: T[], handler:
export function useSpacedUpdate(callback: () => void | Promise<void>, interval = 1000) {
const callbackRef = useRef(callback);
const spacedUpdateRef = useRef<SpacedUpdate>();
const spacedUpdateRef = useRef<SpacedUpdate>(new SpacedUpdate(
() => callbackRef.current(),
interval
));
// Update callback ref when it changes
useEffect(() => {
callbackRef.current = callback;
}, [callback]);
// Create SpacedUpdate instance only once
if (!spacedUpdateRef.current) {
spacedUpdateRef.current = new SpacedUpdate(
() => callbackRef.current(),
interval
);
}
// Update interval if it changes
useEffect(() => {
spacedUpdateRef.current?.setUpdateInterval(interval);

View File

@ -39,8 +39,6 @@ export default class CalendarView extends ViewMode<{}> {
private $calendarContainer: JQuery<HTMLElement>;
private calendar?: Calendar;
private isCalendarRoot: boolean;
private lastView?: string;
private debouncedSaveView?: DebouncedFunction<() => void>;
constructor(args: ViewModeArgs) {
super(args, "calendar");
@ -64,12 +62,6 @@ export default class CalendarView extends ViewMode<{}> {
eventBuilder = async (e: EventSourceFuncArg) => await this.#buildEventsForCalendar(e);
}
// Parse user's initial view, if valid.
const userInitialView = this.parentNote.getLabelValue("calendar:view");
if (userInitialView && CALENDAR_VIEWS.includes(userInitialView)) {
initialView = userInitialView;
}
const calendar = new Calendar(this.$calendarContainer[0], {
events: eventBuilder,
editable: isEditable,
@ -150,22 +142,6 @@ export default class CalendarView extends ViewMode<{}> {
}
#onDatesSet(e: DatesSetArg) {
const currentView = e.view.type;
if (currentView === this.lastView) {
return;
}
if (!this.debouncedSaveView) {
this.debouncedSaveView = debounce(() => {
if (this.lastView) {
attributes.setLabel(this.parentNote.noteId, "calendar:view", this.lastView);
}
}, 1_000);
}
this.debouncedSaveView();
this.lastView = currentView;
if (hasTouchBar) {
appContext.triggerCommand("refreshTouchBar");
}