feat: persist view style and start-on preference per device
viewStyle, showTimeGrid, and startDayOffset now also write to a device cookie so each device remembers its own view independently. Cookie wins over DB on load, giving phone/desktop their own default view without losing the cross-device DB fallback. - DEVICE_ALSO_COOKIE_KEYS: viewStyle, showTimeGrid, startDayOffset - saveSetting writes cookie for these in addition to DB - viewStyle and showTimeGrid lazy-init from cookie on first render - Both fetchProfile and fetchUserInfo apply cookie overrides last v1.94.1
This commit is contained in:
parent
0b40974b88
commit
075ccdba04
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "my-weekly-todo-list",
|
"name": "my-weekly-todo-list",
|
||||||
"version": "1.94.0",
|
"version": "1.94.1",
|
||||||
"description": "A web-based weekly task management application that organizes to-dos and calendar events in a single, intuitive weekly view",
|
"description": "A web-based weekly task management application that organizes to-dos and calendar events in a single, intuitive weekly view",
|
||||||
"main": "index.js",
|
"main": "index.js",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
|
|||||||
@ -117,6 +117,9 @@ const DEVICE_SETTINGS_KEYS = ["viewDays", "cellDuration", "startHour", "endHour"
|
|||||||
const DEVICE_VIEW_SETTINGS_KEYS = ["showSomeday", "showAllDayEvents", "showTaskCheckboxes", "showProjectIcons", "weatherEnabled"] as const;
|
const DEVICE_VIEW_SETTINGS_KEYS = ["showSomeday", "showAllDayEvents", "showTaskCheckboxes", "showProjectIcons", "weatherEnabled"] as const;
|
||||||
type DeviceViewSettingKey = typeof DEVICE_VIEW_SETTINGS_KEYS[number];
|
type DeviceViewSettingKey = typeof DEVICE_VIEW_SETTINGS_KEYS[number];
|
||||||
|
|
||||||
|
// Settings that save to DB (cross-device default) AND to cookie (device override wins on load)
|
||||||
|
const DEVICE_ALSO_COOKIE_KEYS = ["viewStyle", "showTimeGrid", "startDayOffset"];
|
||||||
|
|
||||||
function getCookie(name: string): string | null {
|
function getCookie(name: string): string | null {
|
||||||
if (typeof document === "undefined") return null;
|
if (typeof document === "undefined") return null;
|
||||||
const match = document.cookie.match(new RegExp(`(?:^|; )${name}=([^;]*)`));
|
const match = document.cookie.match(new RegExp(`(?:^|; )${name}=([^;]*)`));
|
||||||
@ -999,7 +1002,10 @@ export default function WeeklyView() {
|
|||||||
};
|
};
|
||||||
const [cellDuration, setCellDuration] = useState<CellDuration>(30);
|
const [cellDuration, setCellDuration] = useState<CellDuration>(30);
|
||||||
const [draggedTask, setDraggedTask] = useState<Task | null>(null);
|
const [draggedTask, setDraggedTask] = useState<Task | null>(null);
|
||||||
const [showTimeGrid, setShowTimeGrid] = useState(true);
|
const [showTimeGrid, setShowTimeGrid] = useState<boolean>(() => {
|
||||||
|
const c = getCookie("setting_showTimeGrid");
|
||||||
|
return c !== null ? c === "true" : true;
|
||||||
|
});
|
||||||
const [slideDirection, setSlideDirection] = useState<"next" | "prev" | null>(
|
const [slideDirection, setSlideDirection] = useState<"next" | "prev" | null>(
|
||||||
null,
|
null,
|
||||||
);
|
);
|
||||||
@ -1018,7 +1024,10 @@ export default function WeeklyView() {
|
|||||||
listId?: string;
|
listId?: string;
|
||||||
slotIdx?: number;
|
slotIdx?: number;
|
||||||
} | null>(null);
|
} | null>(null);
|
||||||
const [viewStyle, setViewStyle] = useState<ViewStyle>("simple");
|
const [viewStyle, setViewStyle] = useState<ViewStyle>(() => {
|
||||||
|
const c = getCookie("setting_viewStyle");
|
||||||
|
return (c as ViewStyle) || "simple";
|
||||||
|
});
|
||||||
|
|
||||||
// Per-view settings: overrides that apply only to a specific view
|
// Per-view settings: overrides that apply only to a specific view
|
||||||
type PerViewOverrides = {
|
type PerViewOverrides = {
|
||||||
@ -1407,6 +1416,12 @@ export default function WeeklyView() {
|
|||||||
if (_cStart) setStartHour(Number(_cStart));
|
if (_cStart) setStartHour(Number(_cStart));
|
||||||
const _cEnd = getCookie("setting_endHour");
|
const _cEnd = getCookie("setting_endHour");
|
||||||
if (_cEnd) setEndHour(Number(_cEnd));
|
if (_cEnd) setEndHour(Number(_cEnd));
|
||||||
|
const _cVS = getCookie("setting_viewStyle");
|
||||||
|
if (_cVS) { setViewStyle(_cVS as ViewStyle); setProfile((p: any) => ({ ...p, viewStyle: _cVS })); }
|
||||||
|
const _cTG = getCookie("setting_showTimeGrid");
|
||||||
|
if (_cTG !== null) { const v = _cTG === "true"; setShowTimeGrid(v); setProfile((p: any) => ({ ...p, showTimeGrid: v })); }
|
||||||
|
const _cSDO = getCookie("setting_startDayOffset");
|
||||||
|
if (_cSDO !== null) setProfile((p: any) => ({ ...p, startDayOffset: Number(_cSDO) }));
|
||||||
|
|
||||||
// Show onboarding wizard for new users
|
// Show onboarding wizard for new users
|
||||||
if (profileData.hasCompletedOnboarding === false) {
|
if (profileData.hasCompletedOnboarding === false) {
|
||||||
@ -2271,6 +2286,10 @@ export default function WeeklyView() {
|
|||||||
setCookie(`setting_${key}`, String(value));
|
setCookie(`setting_${key}`, String(value));
|
||||||
return; // Don't write to DB — that would overwrite other devices
|
return; // Don't write to DB — that would overwrite other devices
|
||||||
}
|
}
|
||||||
|
// Also persist to device cookie so this device remembers its own preference on reload
|
||||||
|
if (DEVICE_ALSO_COOKIE_KEYS.includes(key)) {
|
||||||
|
setCookie(`setting_${key}`, String(value));
|
||||||
|
}
|
||||||
// Keep profile object in sync so the debounced auto-save never sends stale values
|
// Keep profile object in sync so the debounced auto-save never sends stale values
|
||||||
setProfile((p: any) => ({ ...p, [key]: value }));
|
setProfile((p: any) => ({ ...p, [key]: value }));
|
||||||
try {
|
try {
|
||||||
@ -2499,6 +2518,21 @@ export default function WeeklyView() {
|
|||||||
setCellDuration(data.user.cellDuration as CellDuration);
|
setCellDuration(data.user.cellDuration as CellDuration);
|
||||||
if (data.user.viewStyle)
|
if (data.user.viewStyle)
|
||||||
setViewStyle(data.user.viewStyle as ViewStyle);
|
setViewStyle(data.user.viewStyle as ViewStyle);
|
||||||
|
|
||||||
|
// Cookie overrides for settings that are also device-local
|
||||||
|
const _cVS2 = getCookie("setting_viewStyle");
|
||||||
|
if (_cVS2) { setViewStyle(_cVS2 as ViewStyle); setProfile((p: any) => ({ ...p, viewStyle: _cVS2, showTimeGrid: _cVS2 === "simple" || _cVS2 === "calendar" })); }
|
||||||
|
const _cTG2 = getCookie("setting_showTimeGrid");
|
||||||
|
if (_cTG2 !== null) setShowTimeGrid(_cTG2 === "true");
|
||||||
|
const _cSDO2 = getCookie("setting_startDayOffset");
|
||||||
|
if (_cSDO2 !== null) {
|
||||||
|
const offset = Number(_cSDO2);
|
||||||
|
setProfile((p: any) => ({ ...p, startDayOffset: offset }));
|
||||||
|
if (offset !== 0) {
|
||||||
|
const d = new Date(); d.setHours(0, 0, 0, 0); d.setDate(d.getDate() + offset);
|
||||||
|
setCurrentWeekStart(d);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user