react-os-shell 0.2.67 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +35 -15
- package/dist/{Browser-OH3E6TIZ.js → Browser-H5KDP5OH.js} +3 -3
- package/dist/{Browser-OH3E6TIZ.js.map → Browser-H5KDP5OH.js.map} +1 -1
- package/dist/{Calculator-DBSWD2RM.js → Calculator-QQ7NF53Q.js} +4 -4
- package/dist/{Calculator-DBSWD2RM.js.map → Calculator-QQ7NF53Q.js.map} +1 -1
- package/dist/{Calendar-5S3MOTVB.js → Calendar-J6L7FGHS.js} +175 -108
- package/dist/Calendar-J6L7FGHS.js.map +1 -0
- package/dist/{CurrencyConverter-TDAW7VME.js → CurrencyConverter-YHOGBUPH.js} +4 -4
- package/dist/{CurrencyConverter-TDAW7VME.js.map → CurrencyConverter-YHOGBUPH.js.map} +1 -1
- package/dist/{Documents-R4DZLBJU.js → Documents-6DYALASM.js} +3 -3
- package/dist/{Documents-R4DZLBJU.js.map → Documents-6DYALASM.js.map} +1 -1
- package/dist/Email-U2U5Z4DL.js +475 -0
- package/dist/Email-U2U5Z4DL.js.map +1 -0
- package/dist/Files-T62M4V5I.js +11 -0
- package/dist/{Files-XD7SWQSG.js.map → Files-T62M4V5I.js.map} +1 -1
- package/dist/{Minesweeper-YWYMJQN6.js → Minesweeper-S2JHXYLX.js} +3 -3
- package/dist/{Minesweeper-YWYMJQN6.js.map → Minesweeper-S2JHXYLX.js.map} +1 -1
- package/dist/{Notepad-F3BJYZJL.js → Notepad-2YF7X3XO.js} +3 -3
- package/dist/{Notepad-F3BJYZJL.js.map → Notepad-2YF7X3XO.js.map} +1 -1
- package/dist/{PomodoroTimer-VLPDNV7W.js → PomodoroTimer-3J7Z3NVQ.js} +4 -4
- package/dist/{PomodoroTimer-VLPDNV7W.js.map → PomodoroTimer-3J7Z3NVQ.js.map} +1 -1
- package/dist/Preview-WM6ZP5PZ.js +8 -0
- package/dist/{Preview-XOCYZM4T.js.map → Preview-WM6ZP5PZ.js.map} +1 -1
- package/dist/Spreadsheet-ZIE2SXAF.js +6 -0
- package/dist/{Spreadsheet-7NEC5RBR.js.map → Spreadsheet-ZIE2SXAF.js.map} +1 -1
- package/dist/{TodoList-7JZ2SLDI.js → TodoList-QGXCDEIE.js} +18 -204
- package/dist/TodoList-QGXCDEIE.js.map +1 -0
- package/dist/{Weather-HLXHNBM4.js → Weather-2GFPSZ5V.js} +4 -4
- package/dist/{Weather-HLXHNBM4.js.map → Weather-2GFPSZ5V.js.map} +1 -1
- package/dist/{WorldClock-HIWKHF6U.js → WorldClock-P4JR5I6X.js} +4 -4
- package/dist/{WorldClock-HIWKHF6U.js.map → WorldClock-P4JR5I6X.js.map} +1 -1
- package/dist/apps/index.d.ts +2 -5
- package/dist/apps/index.js +23 -26
- package/dist/apps/index.js.map +1 -1
- package/dist/chunk-57B3WALN.js +114 -0
- package/dist/chunk-57B3WALN.js.map +1 -0
- package/dist/{chunk-GAC6D4LN.js → chunk-62FC2FHC.js} +94 -23
- package/dist/chunk-62FC2FHC.js.map +1 -0
- package/dist/{chunk-HAUVCQNK.js → chunk-ATQVRDDQ.js} +3 -3
- package/dist/{chunk-HAUVCQNK.js.map → chunk-ATQVRDDQ.js.map} +1 -1
- package/dist/{chunk-GP4Y3VCB.js → chunk-KMGWSDEI.js} +480 -4
- package/dist/chunk-KMGWSDEI.js.map +1 -0
- package/dist/{chunk-KFRHMW57.js → chunk-O6FJZAFM.js} +3 -3
- package/dist/{chunk-KFRHMW57.js.map → chunk-O6FJZAFM.js.map} +1 -1
- package/dist/{chunk-VG5ZM3QD.js → chunk-SEV7UXGN.js} +4 -4
- package/dist/{chunk-VG5ZM3QD.js.map → chunk-SEV7UXGN.js.map} +1 -1
- package/dist/{chunk-EXYMMWOS.js → chunk-ZBRFMK3E.js} +4 -4
- package/dist/{chunk-EXYMMWOS.js.map → chunk-ZBRFMK3E.js.map} +1 -1
- package/dist/index.d.ts +55 -1
- package/dist/index.js +242 -136
- package/dist/index.js.map +1 -1
- package/package.json +10 -3
- package/dist/Calendar-5S3MOTVB.js.map +0 -1
- package/dist/Email-OAQ76CET.js +0 -1883
- package/dist/Email-OAQ76CET.js.map +0 -1
- package/dist/Files-XD7SWQSG.js +0 -12
- package/dist/GeminiChat-XTEBZIVK.js +0 -184
- package/dist/GeminiChat-XTEBZIVK.js.map +0 -1
- package/dist/Preview-XOCYZM4T.js +0 -8
- package/dist/Spreadsheet-7NEC5RBR.js +0 -7
- package/dist/TodoList-7JZ2SLDI.js.map +0 -1
- package/dist/chunk-5VXRBUEH.js +0 -104
- package/dist/chunk-5VXRBUEH.js.map +0 -1
- package/dist/chunk-62EP7CNW.js +0 -485
- package/dist/chunk-62EP7CNW.js.map +0 -1
- package/dist/chunk-GAC6D4LN.js.map +0 -1
- package/dist/chunk-GP4Y3VCB.js.map +0 -1
- package/dist/chunk-MVWEL34Y.js +0 -209
- package/dist/chunk-MVWEL34Y.js.map +0 -1
|
@@ -1,9 +1,8 @@
|
|
|
1
|
-
import { isDemoMode, getDemoCalendarEvents } from './chunk-5VXRBUEH.js';
|
|
2
1
|
import { useTodoTasks } from './chunk-25L4DIKH.js';
|
|
3
|
-
import {
|
|
2
|
+
import { useMailAuth, getMailClient } from './chunk-57B3WALN.js';
|
|
4
3
|
import { useShellPrefs } from './chunk-36VM54SC.js';
|
|
5
4
|
import { toast_default } from './chunk-WIJ45SYD.js';
|
|
6
|
-
import { Modal, ModalActions } from './chunk-
|
|
5
|
+
import { Modal, ModalActions } from './chunk-62FC2FHC.js';
|
|
7
6
|
import './chunk-PLGHQ7QW.js';
|
|
8
7
|
import './chunk-SSA762W5.js';
|
|
9
8
|
import { useState, useMemo, useEffect, useCallback } from 'react';
|
|
@@ -58,15 +57,42 @@ function getWeekDays(date) {
|
|
|
58
57
|
}
|
|
59
58
|
return days;
|
|
60
59
|
}
|
|
60
|
+
function davToLocal(ev, calendarId) {
|
|
61
|
+
const startIso = ev.start;
|
|
62
|
+
const endIso = ev.end;
|
|
63
|
+
const startDate = startIso.slice(0, 10);
|
|
64
|
+
const startTime = ev.allDay ? void 0 : startIso.slice(11, 16);
|
|
65
|
+
const endTime = ev.allDay ? void 0 : endIso.slice(11, 16);
|
|
66
|
+
return {
|
|
67
|
+
id: `caldav-${calendarId}-${ev.uid}`,
|
|
68
|
+
title: ev.summary || "(No title)",
|
|
69
|
+
date: startDate,
|
|
70
|
+
start_time: startTime,
|
|
71
|
+
end_time: endTime,
|
|
72
|
+
color: "blue",
|
|
73
|
+
all_day: ev.allDay,
|
|
74
|
+
description: ev.description || void 0,
|
|
75
|
+
_caldav: { calendarId, eventUid: ev.uid, etag: ev.etag }
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
function toDavInput(evt) {
|
|
79
|
+
const start = evt.all_day ? evt.date : `${evt.date}T${evt.start_time || "09:00"}:00`;
|
|
80
|
+
const end = evt.all_day ? evt.date : `${evt.date}T${evt.end_time || "10:00"}:00`;
|
|
81
|
+
return {
|
|
82
|
+
summary: evt.title,
|
|
83
|
+
description: evt.description,
|
|
84
|
+
start: new Date(start).toISOString(),
|
|
85
|
+
end: new Date(end).toISOString(),
|
|
86
|
+
allDay: !!evt.all_day
|
|
87
|
+
};
|
|
88
|
+
}
|
|
61
89
|
function Calendar() {
|
|
62
90
|
const { prefs, save } = useShellPrefs();
|
|
63
|
-
const
|
|
91
|
+
const { isConnected, capabilities } = useMailAuth();
|
|
92
|
+
const caldavEnabled = isConnected && capabilities?.caldav === true;
|
|
64
93
|
const localEvents = prefs.calendar_events || [];
|
|
65
|
-
const [
|
|
66
|
-
const
|
|
67
|
-
() => isDemoMode() && !google.isConnected ? getDemoCalendarEvents() : [],
|
|
68
|
-
[google.isConnected]
|
|
69
|
-
);
|
|
94
|
+
const [calendars, setCalendars] = useState([]);
|
|
95
|
+
const [caldavEvents, setCaldavEvents] = useState([]);
|
|
70
96
|
const { tasks: todoTasks, toggleDone: toggleTodoDone } = useTodoTasks();
|
|
71
97
|
const todoEvents = useMemo(
|
|
72
98
|
() => todoTasks.filter((t) => !!t.dueDate).map((t) => ({
|
|
@@ -74,8 +100,6 @@ function Calendar() {
|
|
|
74
100
|
title: t.name,
|
|
75
101
|
date: t.dueDate,
|
|
76
102
|
color: "gray",
|
|
77
|
-
// Marker fields consumed by MonthView / WeekView to render a
|
|
78
|
-
// checkbox affordance instead of the regular event button.
|
|
79
103
|
_todo: true,
|
|
80
104
|
_todoId: t.id,
|
|
81
105
|
_done: t.done
|
|
@@ -83,63 +107,115 @@ function Calendar() {
|
|
|
83
107
|
[todoTasks]
|
|
84
108
|
);
|
|
85
109
|
const events = useMemo(
|
|
86
|
-
() => [...localEvents, ...
|
|
87
|
-
[localEvents,
|
|
110
|
+
() => [...localEvents, ...caldavEvents, ...todoEvents],
|
|
111
|
+
[localEvents, caldavEvents, todoEvents]
|
|
88
112
|
);
|
|
89
113
|
const today = /* @__PURE__ */ new Date();
|
|
90
114
|
const [currentDate, setCurrentDate] = useState(new Date(today.getFullYear(), today.getMonth(), 1));
|
|
91
|
-
useEffect(() => {
|
|
92
|
-
const token = getGoogleAccessToken();
|
|
93
|
-
if (!token) {
|
|
94
|
-
setGoogleEvents([]);
|
|
95
|
-
return;
|
|
96
|
-
}
|
|
97
|
-
const year = currentDate.getFullYear();
|
|
98
|
-
const month = currentDate.getMonth();
|
|
99
|
-
const timeMin = new Date(year, month - 1, 1).toISOString();
|
|
100
|
-
const timeMax = new Date(year, month + 2, 0).toISOString();
|
|
101
|
-
fetch(`https://www.googleapis.com/calendar/v3/calendars/primary/events?timeMin=${timeMin}&timeMax=${timeMax}&maxResults=250&singleEvents=true&orderBy=startTime`, {
|
|
102
|
-
headers: { Authorization: `Bearer ${token}` }
|
|
103
|
-
}).then((r) => r.ok ? r.json() : null).then((data) => {
|
|
104
|
-
if (!data?.items) return;
|
|
105
|
-
const mapped = data.items.map((item) => {
|
|
106
|
-
const isAllDay = !!item.start?.date;
|
|
107
|
-
const startDate = isAllDay ? item.start.date : item.start?.dateTime?.split("T")[0];
|
|
108
|
-
const startTime = isAllDay ? void 0 : item.start?.dateTime?.split("T")[1]?.slice(0, 5);
|
|
109
|
-
const endTime = isAllDay ? void 0 : item.end?.dateTime?.split("T")[1]?.slice(0, 5);
|
|
110
|
-
return {
|
|
111
|
-
id: `gcal-${item.id}`,
|
|
112
|
-
title: item.summary || "(No title)",
|
|
113
|
-
date: startDate,
|
|
114
|
-
start_time: startTime,
|
|
115
|
-
end_time: endTime,
|
|
116
|
-
color: "blue",
|
|
117
|
-
all_day: isAllDay,
|
|
118
|
-
description: item.description,
|
|
119
|
-
_google: true
|
|
120
|
-
};
|
|
121
|
-
});
|
|
122
|
-
setGoogleEvents(mapped);
|
|
123
|
-
}).catch(() => setGoogleEvents([]));
|
|
124
|
-
}, [currentDate]);
|
|
125
115
|
const [view, setView] = useState("month");
|
|
126
116
|
const [editingEvent, setEditingEvent] = useState(null);
|
|
127
117
|
const [newEventDate, setNewEventDate] = useState(null);
|
|
118
|
+
useEffect(() => {
|
|
119
|
+
if (!caldavEnabled) {
|
|
120
|
+
setCalendars([]);
|
|
121
|
+
return;
|
|
122
|
+
}
|
|
123
|
+
getMailClient().get("/api/calendar/calendars").then((r) => setCalendars(r.data.calendars)).catch(() => setCalendars([]));
|
|
124
|
+
}, [caldavEnabled]);
|
|
125
|
+
useEffect(() => {
|
|
126
|
+
if (!caldavEnabled || calendars.length === 0) {
|
|
127
|
+
setCaldavEvents([]);
|
|
128
|
+
return;
|
|
129
|
+
}
|
|
130
|
+
const y = currentDate.getFullYear();
|
|
131
|
+
const m = currentDate.getMonth();
|
|
132
|
+
const start = new Date(y, m - 1, 1).toISOString();
|
|
133
|
+
const end = new Date(y, m + 2, 0).toISOString();
|
|
134
|
+
let cancelled = false;
|
|
135
|
+
Promise.all(
|
|
136
|
+
calendars.map(
|
|
137
|
+
(cal) => getMailClient().get(`/api/calendar/calendars/${encodeURIComponent(cal.id)}/events`, {
|
|
138
|
+
params: { start, end }
|
|
139
|
+
}).then((r) => r.data.events.map((e) => davToLocal(e, cal.id))).catch(() => [])
|
|
140
|
+
)
|
|
141
|
+
).then((perCalendar) => {
|
|
142
|
+
if (cancelled) return;
|
|
143
|
+
setCaldavEvents(perCalendar.flat());
|
|
144
|
+
});
|
|
145
|
+
return () => {
|
|
146
|
+
cancelled = true;
|
|
147
|
+
};
|
|
148
|
+
}, [caldavEnabled, calendars, currentDate]);
|
|
128
149
|
const saveLocalEvents = useCallback((updated) => {
|
|
129
150
|
save({ calendar_events: updated });
|
|
130
151
|
}, [save]);
|
|
131
|
-
const saveEvent = (evt) => {
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
152
|
+
const saveEvent = async (evt, targetCalendarId) => {
|
|
153
|
+
if (evt._caldav) {
|
|
154
|
+
try {
|
|
155
|
+
const input = toDavInput(evt);
|
|
156
|
+
const res = await getMailClient().put(
|
|
157
|
+
`/api/calendar/calendars/${encodeURIComponent(evt._caldav.calendarId)}/events/${encodeURIComponent(evt._caldav.eventUid)}`,
|
|
158
|
+
input,
|
|
159
|
+
{ headers: { "If-Match": evt._caldav.etag } }
|
|
160
|
+
);
|
|
161
|
+
setCaldavEvents((prev) => prev.map(
|
|
162
|
+
(e) => e.id === evt.id ? { ...evt, _caldav: { ...evt._caldav, etag: res.data.etag } } : e
|
|
163
|
+
));
|
|
164
|
+
toast_default.success("Event updated");
|
|
165
|
+
} catch (err) {
|
|
166
|
+
const status = err?.response?.status;
|
|
167
|
+
if (status === 409) {
|
|
168
|
+
toast_default.error("Event was modified elsewhere \u2014 refresh to see latest");
|
|
169
|
+
} else {
|
|
170
|
+
toast_default.error(extractError(err));
|
|
171
|
+
}
|
|
172
|
+
return;
|
|
173
|
+
}
|
|
174
|
+
} else if (targetCalendarId) {
|
|
175
|
+
try {
|
|
176
|
+
const input = toDavInput(evt);
|
|
177
|
+
const res = await getMailClient().post(
|
|
178
|
+
`/api/calendar/calendars/${encodeURIComponent(targetCalendarId)}/events`,
|
|
179
|
+
input
|
|
180
|
+
);
|
|
181
|
+
const newEvt = {
|
|
182
|
+
...evt,
|
|
183
|
+
id: `caldav-${targetCalendarId}-${res.data.uid}`,
|
|
184
|
+
_caldav: { calendarId: targetCalendarId, eventUid: res.data.uid, etag: res.data.etag }
|
|
185
|
+
};
|
|
186
|
+
setCaldavEvents((prev) => [...prev, newEvt]);
|
|
187
|
+
toast_default.success("Event created");
|
|
188
|
+
} catch (err) {
|
|
189
|
+
toast_default.error(extractError(err));
|
|
190
|
+
return;
|
|
191
|
+
}
|
|
135
192
|
} else {
|
|
136
|
-
|
|
193
|
+
const existing = localEvents.find((e) => e.id === evt.id);
|
|
194
|
+
if (existing) {
|
|
195
|
+
saveLocalEvents(localEvents.map((e) => e.id === evt.id ? evt : e));
|
|
196
|
+
} else {
|
|
197
|
+
saveLocalEvents([...localEvents, evt]);
|
|
198
|
+
}
|
|
137
199
|
}
|
|
138
200
|
setEditingEvent(null);
|
|
139
201
|
setNewEventDate(null);
|
|
140
202
|
};
|
|
141
|
-
const deleteEvent = (
|
|
142
|
-
|
|
203
|
+
const deleteEvent = async (evt) => {
|
|
204
|
+
if (evt._caldav) {
|
|
205
|
+
try {
|
|
206
|
+
await getMailClient().delete(
|
|
207
|
+
`/api/calendar/calendars/${encodeURIComponent(evt._caldav.calendarId)}/events/${encodeURIComponent(evt._caldav.eventUid)}`,
|
|
208
|
+
{ headers: { "If-Match": evt._caldav.etag } }
|
|
209
|
+
);
|
|
210
|
+
setCaldavEvents((prev) => prev.filter((e) => e.id !== evt.id));
|
|
211
|
+
toast_default.success("Event deleted");
|
|
212
|
+
} catch (err) {
|
|
213
|
+
toast_default.error(extractError(err));
|
|
214
|
+
return;
|
|
215
|
+
}
|
|
216
|
+
} else {
|
|
217
|
+
saveLocalEvents(localEvents.filter((e) => e.id !== evt.id));
|
|
218
|
+
}
|
|
143
219
|
setEditingEvent(null);
|
|
144
220
|
};
|
|
145
221
|
const goToday = () => setCurrentDate(new Date(today.getFullYear(), today.getMonth(), 1));
|
|
@@ -196,45 +272,15 @@ function Calendar() {
|
|
|
196
272
|
/* @__PURE__ */ jsx("h2", { className: "text-sm font-semibold text-gray-900", children: monthLabel })
|
|
197
273
|
] }),
|
|
198
274
|
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
|
|
199
|
-
|
|
200
|
-
"
|
|
275
|
+
/* @__PURE__ */ jsx(
|
|
276
|
+
"span",
|
|
201
277
|
{
|
|
202
|
-
onClick: () => window.dispatchEvent(new Event("open-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
children:
|
|
206
|
-
google.user?.picture ? /* @__PURE__ */ jsx("img", { src: google.user.picture, alt: "", className: "h-6 w-6 rounded-full" }) : /* @__PURE__ */ jsx("div", { className: "h-6 w-6 rounded-full bg-gray-200" }),
|
|
207
|
-
/* @__PURE__ */ jsxs("div", { className: "text-left", children: [
|
|
208
|
-
/* @__PURE__ */ jsx("p", { className: "text-[11px] font-medium text-gray-900", children: google.user?.name }),
|
|
209
|
-
/* @__PURE__ */ jsx("p", { className: "text-[10px] text-gray-500", children: google.user?.email })
|
|
210
|
-
] })
|
|
211
|
-
]
|
|
212
|
-
}
|
|
213
|
-
) : /* @__PURE__ */ jsxs(
|
|
214
|
-
"button",
|
|
215
|
-
{
|
|
216
|
-
onClick: () => {
|
|
217
|
-
if (!google.hasClientId) {
|
|
218
|
-
const id = prompt("Enter your Google OAuth Client ID\n\nCreate one at console.cloud.google.com > APIs > Credentials > OAuth 2.0 Client ID (Web application)");
|
|
219
|
-
if (id?.trim()) google.setClientId(id.trim());
|
|
220
|
-
return;
|
|
221
|
-
}
|
|
222
|
-
google.connect();
|
|
223
|
-
},
|
|
224
|
-
disabled: google.loading,
|
|
225
|
-
className: "inline-flex items-center gap-1.5 border border-gray-300 bg-white rounded-md px-2 py-1 text-[10px] font-medium text-gray-600 hover:bg-gray-50 transition-colors disabled:opacity-50",
|
|
226
|
-
children: [
|
|
227
|
-
/* @__PURE__ */ jsxs("svg", { className: "h-3.5 w-3.5", viewBox: "0 0 24 24", children: [
|
|
228
|
-
/* @__PURE__ */ jsx("path", { d: "M22.56 12.25c0-.78-.07-1.53-.2-2.25H12v4.26h5.92a5.06 5.06 0 01-2.2 3.32v2.77h3.57c2.08-1.92 3.28-4.74 3.28-8.1z", fill: "#4285F4" }),
|
|
229
|
-
/* @__PURE__ */ jsx("path", { d: "M12 23c2.97 0 5.46-.98 7.28-2.66l-3.57-2.77c-.98.66-2.23 1.06-3.71 1.06-2.86 0-5.29-1.93-6.16-4.53H2.18v2.84C3.99 20.53 7.7 23 12 23z", fill: "#34A853" }),
|
|
230
|
-
/* @__PURE__ */ jsx("path", { d: "M5.84 14.09c-.22-.66-.35-1.36-.35-2.09s.13-1.43.35-2.09V7.07H2.18C1.43 8.55 1 10.22 1 12s.43 3.45 1.18 4.93l2.85-2.22.81-.62z", fill: "#FBBC05" }),
|
|
231
|
-
/* @__PURE__ */ jsx("path", { d: "M12 5.38c1.62 0 3.06.56 4.21 1.64l3.15-3.15C17.45 2.09 14.97 1 12 1 7.7 1 3.99 3.47 2.18 7.07l3.66 2.84c.87-2.6 3.3-4.53 6.16-4.53z", fill: "#EA4335" })
|
|
232
|
-
] }),
|
|
233
|
-
google.loading ? "Connecting..." : "Connect Google Calendar"
|
|
234
|
-
]
|
|
278
|
+
onClick: () => window.dispatchEvent(new Event("open-mail-connect")),
|
|
279
|
+
className: "text-[11px] text-gray-600 cursor-pointer hover:text-gray-900",
|
|
280
|
+
title: "Open mail & calendar settings",
|
|
281
|
+
children: caldavEnabled ? `CalDAV \xB7 ${calendars.length} calendar${calendars.length === 1 ? "" : "s"}` : "CalDAV not connected"
|
|
235
282
|
}
|
|
236
283
|
),
|
|
237
|
-
google.error && /* @__PURE__ */ jsx("span", { className: "text-[10px] text-red-500", children: google.error }),
|
|
238
284
|
/* @__PURE__ */ jsx("div", { className: "w-px h-4 bg-gray-200" }),
|
|
239
285
|
/* @__PURE__ */ jsx("div", { className: "flex gap-1", children: ["year", "month", "week"].map((v) => /* @__PURE__ */ jsx(
|
|
240
286
|
"button",
|
|
@@ -286,8 +332,9 @@ function Calendar() {
|
|
|
286
332
|
{
|
|
287
333
|
event: editingEvent,
|
|
288
334
|
isNew: !!newEventDate,
|
|
335
|
+
calendars,
|
|
289
336
|
onSave: saveEvent,
|
|
290
|
-
onDelete: deleteEvent,
|
|
337
|
+
onDelete: () => deleteEvent(editingEvent),
|
|
291
338
|
onClose: () => {
|
|
292
339
|
setEditingEvent(null);
|
|
293
340
|
setNewEventDate(null);
|
|
@@ -296,21 +343,26 @@ function Calendar() {
|
|
|
296
343
|
)
|
|
297
344
|
] });
|
|
298
345
|
}
|
|
346
|
+
function extractError(err) {
|
|
347
|
+
const r = err?.response?.data?.error;
|
|
348
|
+
if (r) return r;
|
|
349
|
+
if (err instanceof Error) return err.message;
|
|
350
|
+
return "Unknown error";
|
|
351
|
+
}
|
|
299
352
|
function DayEventBadge({ evt, onEventClick, onToggleTodo, compact = false }) {
|
|
300
|
-
|
|
301
|
-
if (e._todo && e._todoId) {
|
|
353
|
+
if (evt._todo && evt._todoId) {
|
|
302
354
|
return compact ? /* @__PURE__ */ jsxs(
|
|
303
355
|
"button",
|
|
304
356
|
{
|
|
305
357
|
onClick: (ev) => {
|
|
306
358
|
ev.stopPropagation();
|
|
307
|
-
onToggleTodo(
|
|
359
|
+
onToggleTodo(evt._todoId);
|
|
308
360
|
},
|
|
309
|
-
title:
|
|
310
|
-
className: `w-full text-left flex items-center gap-1 truncate rounded px-1 py-0.5 text-[10px] leading-tight font-medium hover:bg-gray-100 transition-colors ${
|
|
361
|
+
title: evt.title,
|
|
362
|
+
className: `w-full text-left flex items-center gap-1 truncate rounded px-1 py-0.5 text-[10px] leading-tight font-medium hover:bg-gray-100 transition-colors ${evt._done ? "text-gray-400" : "text-gray-700"}`,
|
|
311
363
|
children: [
|
|
312
|
-
/* @__PURE__ */ jsx("span", { className: "shrink-0", children:
|
|
313
|
-
/* @__PURE__ */ jsx("span", { className: `truncate ${
|
|
364
|
+
/* @__PURE__ */ jsx("span", { className: "shrink-0", children: evt._done ? "\u2611" : "\u2610" }),
|
|
365
|
+
/* @__PURE__ */ jsx("span", { className: `truncate ${evt._done ? "line-through" : ""}`, children: evt.title || "Task" })
|
|
314
366
|
]
|
|
315
367
|
}
|
|
316
368
|
) : /* @__PURE__ */ jsxs(
|
|
@@ -318,12 +370,12 @@ function DayEventBadge({ evt, onEventClick, onToggleTodo, compact = false }) {
|
|
|
318
370
|
{
|
|
319
371
|
onClick: (ev) => {
|
|
320
372
|
ev.stopPropagation();
|
|
321
|
-
onToggleTodo(
|
|
373
|
+
onToggleTodo(evt._todoId);
|
|
322
374
|
},
|
|
323
|
-
className: `w-full text-left flex items-center gap-2 rounded-md px-2 py-1.5 hover:bg-gray-100 transition-colors ${
|
|
375
|
+
className: `w-full text-left flex items-center gap-2 rounded-md px-2 py-1.5 hover:bg-gray-100 transition-colors ${evt._done ? "text-gray-400" : "text-gray-700"}`,
|
|
324
376
|
children: [
|
|
325
|
-
/* @__PURE__ */ jsx("span", { className: "shrink-0 text-base leading-none", children:
|
|
326
|
-
/* @__PURE__ */ jsx("span", { className: `text-xs font-medium truncate ${
|
|
377
|
+
/* @__PURE__ */ jsx("span", { className: "shrink-0 text-base leading-none", children: evt._done ? "\u2611" : "\u2610" }),
|
|
378
|
+
/* @__PURE__ */ jsx("span", { className: `text-xs font-medium truncate ${evt._done ? "line-through" : ""}`, children: evt.title || "Task" })
|
|
327
379
|
]
|
|
328
380
|
}
|
|
329
381
|
);
|
|
@@ -456,7 +508,7 @@ function WeekView({ currentDate, eventsByDate, today, onDayClick, onEventClick,
|
|
|
456
508
|
}) })
|
|
457
509
|
] });
|
|
458
510
|
}
|
|
459
|
-
function EventEditor({ event, isNew, onSave, onDelete, onClose }) {
|
|
511
|
+
function EventEditor({ event, isNew, calendars, onSave, onDelete, onClose }) {
|
|
460
512
|
const [title, setTitle] = useState(event.title);
|
|
461
513
|
const [date, setDate] = useState(event.date);
|
|
462
514
|
const [startTime, setStartTime] = useState(event.start_time || "09:00");
|
|
@@ -464,12 +516,14 @@ function EventEditor({ event, isNew, onSave, onDelete, onClose }) {
|
|
|
464
516
|
const [color, setColor] = useState(event.color);
|
|
465
517
|
const [allDay, setAllDay] = useState(event.all_day ?? false);
|
|
466
518
|
const [description, setDescription] = useState(event.description || "");
|
|
519
|
+
const isFromCaldav = !!event._caldav;
|
|
520
|
+
const [target, setTarget] = useState(isFromCaldav ? event._caldav.calendarId : "local");
|
|
467
521
|
const handleSave = () => {
|
|
468
522
|
if (!title.trim()) {
|
|
469
523
|
toast_default.error("Event title is required.");
|
|
470
524
|
return;
|
|
471
525
|
}
|
|
472
|
-
|
|
526
|
+
const updated = {
|
|
473
527
|
...event,
|
|
474
528
|
title: title.trim(),
|
|
475
529
|
date,
|
|
@@ -478,7 +532,9 @@ function EventEditor({ event, isNew, onSave, onDelete, onClose }) {
|
|
|
478
532
|
color,
|
|
479
533
|
all_day: allDay,
|
|
480
534
|
description: description.trim() || void 0
|
|
481
|
-
}
|
|
535
|
+
};
|
|
536
|
+
const targetCal = !isFromCaldav && target !== "local" ? target : void 0;
|
|
537
|
+
onSave(updated, targetCal);
|
|
482
538
|
};
|
|
483
539
|
const inp = "block w-full rounded-md border border-gray-300 px-3 py-2 shadow-sm focus:border-blue-500 focus:ring-blue-500 sm:text-sm";
|
|
484
540
|
return /* @__PURE__ */ jsxs(Modal, { open: true, onClose, title: isNew ? "New Event" : "Edit Event", size: "sm", children: [
|
|
@@ -505,6 +561,17 @@ function EventEditor({ event, isNew, onSave, onDelete, onClose }) {
|
|
|
505
561
|
/* @__PURE__ */ jsx("input", { type: "time", value: endTime, onChange: (e) => setEndTime(e.target.value), className: inp })
|
|
506
562
|
] })
|
|
507
563
|
] }),
|
|
564
|
+
isNew && calendars.length > 0 && /* @__PURE__ */ jsxs("div", { children: [
|
|
565
|
+
/* @__PURE__ */ jsx("label", { className: "block text-sm font-medium text-gray-700 mb-1", children: "Save to" }),
|
|
566
|
+
/* @__PURE__ */ jsxs("select", { value: target, onChange: (e) => setTarget(e.target.value), className: inp, children: [
|
|
567
|
+
/* @__PURE__ */ jsx("option", { value: "local", children: "Local (this device only)" }),
|
|
568
|
+
calendars.map((c) => /* @__PURE__ */ jsx("option", { value: c.id, children: c.displayName }, c.id))
|
|
569
|
+
] })
|
|
570
|
+
] }),
|
|
571
|
+
isFromCaldav && /* @__PURE__ */ jsxs("p", { className: "text-[11px] text-gray-500", children: [
|
|
572
|
+
"From ",
|
|
573
|
+
calendars.find((c) => c.id === event._caldav?.calendarId)?.displayName || "CalDAV"
|
|
574
|
+
] }),
|
|
508
575
|
/* @__PURE__ */ jsxs("div", { children: [
|
|
509
576
|
/* @__PURE__ */ jsx("label", { className: "block text-sm font-medium text-gray-700 mb-1", children: "Color" }),
|
|
510
577
|
/* @__PURE__ */ jsx("div", { className: "flex gap-2", children: COLORS.map((c) => /* @__PURE__ */ jsx(
|
|
@@ -521,11 +588,11 @@ function EventEditor({ event, isNew, onSave, onDelete, onClose }) {
|
|
|
521
588
|
/* @__PURE__ */ jsx("textarea", { value: description, onChange: (e) => setDescription(e.target.value), rows: 2, className: inp, placeholder: "Optional notes..." })
|
|
522
589
|
] })
|
|
523
590
|
] }),
|
|
524
|
-
!isNew && /* @__PURE__ */ jsx(ModalActions, { position: "left", children: /* @__PURE__ */ jsx("button", { onClick:
|
|
591
|
+
!isNew && /* @__PURE__ */ jsx(ModalActions, { position: "left", children: /* @__PURE__ */ jsx("button", { onClick: onDelete, className: "text-sm text-red-600 hover:text-red-800 font-medium", children: "Delete" }) }),
|
|
525
592
|
/* @__PURE__ */ jsx(ModalActions, { children: /* @__PURE__ */ jsx("button", { onClick: handleSave, className: "bg-blue-600 text-white px-4 py-2 text-sm font-medium rounded-lg hover:bg-blue-700", children: isNew ? "Create" : "Save" }) })
|
|
526
593
|
] });
|
|
527
594
|
}
|
|
528
595
|
|
|
529
596
|
export { Calendar as default };
|
|
530
|
-
//# sourceMappingURL=Calendar-
|
|
531
|
-
//# sourceMappingURL=Calendar-
|
|
597
|
+
//# sourceMappingURL=Calendar-J6L7FGHS.js.map
|
|
598
|
+
//# sourceMappingURL=Calendar-J6L7FGHS.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/apps/Calendar.tsx"],"names":[],"mappings":"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","file":"Calendar-J6L7FGHS.js","sourcesContent":["import { useState, useMemo, useCallback, useEffect } from 'react';\nimport Modal, { ModalActions } from '../shell/Modal';\nimport toast from '../shell/toast';\nimport useMailAuth from '../hooks/useMailAuth';\nimport { getMailClient } from '../api/mailClient';\nimport { useShellPrefs } from '../shell/ShellPrefs';\nimport { useTodoTasks } from './_todoStore';\n\n// ── Types ──\ninterface CalDavMeta {\n calendarId: string;\n eventUid: string;\n etag: string;\n}\n\ninterface CalendarEvent {\n id: string;\n title: string;\n date: string; // YYYY-MM-DD\n start_time?: string;\n end_time?: string;\n color: string;\n description?: string;\n all_day?: boolean;\n // Internal markers (not persisted in useShellPrefs for non-local events):\n _caldav?: CalDavMeta;\n _todo?: boolean;\n _todoId?: string;\n _done?: boolean;\n}\n\ninterface DavCalendar {\n id: string;\n displayName: string;\n color: string | null;\n ctag: string;\n readOnly: boolean;\n}\n\ninterface DavEvent {\n uid: string;\n etag: string;\n url: string;\n summary: string;\n description: string | null;\n location: string | null;\n start: string;\n end: string;\n allDay: boolean;\n recurrence: string | null;\n status: string;\n}\n\ntype ViewMode = 'year' | 'month' | 'week';\n\nconst COLORS = [\n { key: 'blue', bg: 'bg-blue-500', light: 'bg-blue-100 text-blue-800', dot: 'bg-blue-500' },\n { key: 'green', bg: 'bg-green-500', light: 'bg-green-100 text-green-800', dot: 'bg-green-500' },\n { key: 'red', bg: 'bg-red-500', light: 'bg-red-100 text-red-800', dot: 'bg-red-500' },\n { key: 'purple', bg: 'bg-purple-500', light: 'bg-purple-100 text-purple-800', dot: 'bg-purple-500' },\n { key: 'orange', bg: 'bg-orange-500', light: 'bg-orange-100 text-orange-800', dot: 'bg-orange-500' },\n { key: 'pink', bg: 'bg-pink-500', light: 'bg-pink-100 text-pink-800', dot: 'bg-pink-500' },\n { key: 'yellow', bg: 'bg-yellow-500', light: 'bg-yellow-100 text-yellow-800', dot: 'bg-yellow-500' },\n { key: 'gray', bg: 'bg-gray-500', light: 'bg-gray-100 text-gray-800', dot: 'bg-gray-500' },\n];\n\nfunction getColor(key: string) {\n return COLORS.find(c => c.key === key) || COLORS[0];\n}\n\nconst DAYS = ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'];\n\nfunction pad(n: number) { return String(n).padStart(2, '0'); }\nfunction toDateStr(d: Date) { return `${d.getFullYear()}-${pad(d.getMonth() + 1)}-${pad(d.getDate())}`; }\n\nfunction getMonthDays(year: number, month: number) {\n const first = new Date(year, month, 1);\n const startDay = first.getDay();\n const daysInMonth = new Date(year, month + 1, 0).getDate();\n const prevDays = new Date(year, month, 0).getDate();\n\n const cells: { date: Date; isCurrentMonth: boolean }[] = [];\n for (let i = startDay - 1; i >= 0; i--) {\n cells.push({ date: new Date(year, month - 1, prevDays - i), isCurrentMonth: false });\n }\n for (let d = 1; d <= daysInMonth; d++) {\n cells.push({ date: new Date(year, month, d), isCurrentMonth: true });\n }\n const remaining = 42 - cells.length;\n for (let d = 1; d <= remaining; d++) {\n cells.push({ date: new Date(year, month + 1, d), isCurrentMonth: false });\n }\n return cells;\n}\n\nfunction getWeekDays(date: Date) {\n const start = new Date(date);\n start.setDate(start.getDate() - start.getDay());\n const days: Date[] = [];\n for (let i = 0; i < 7; i++) {\n const d = new Date(start);\n d.setDate(d.getDate() + i);\n days.push(d);\n }\n return days;\n}\n\nfunction davToLocal(ev: DavEvent, calendarId: string): CalendarEvent {\n const startIso = ev.start;\n const endIso = ev.end;\n const startDate = startIso.slice(0, 10);\n const startTime = ev.allDay ? undefined : startIso.slice(11, 16);\n const endTime = ev.allDay ? undefined : endIso.slice(11, 16);\n return {\n id: `caldav-${calendarId}-${ev.uid}`,\n title: ev.summary || '(No title)',\n date: startDate,\n start_time: startTime,\n end_time: endTime,\n color: 'blue',\n all_day: ev.allDay,\n description: ev.description || undefined,\n _caldav: { calendarId, eventUid: ev.uid, etag: ev.etag },\n };\n}\n\nfunction toDavInput(evt: CalendarEvent): {\n summary: string;\n description?: string;\n start: string;\n end: string;\n allDay: boolean;\n} {\n const start = evt.all_day\n ? evt.date\n : `${evt.date}T${evt.start_time || '09:00'}:00`;\n const end = evt.all_day\n ? evt.date\n : `${evt.date}T${evt.end_time || '10:00'}:00`;\n return {\n summary: evt.title,\n description: evt.description,\n start: new Date(start).toISOString(),\n end: new Date(end).toISOString(),\n allDay: !!evt.all_day,\n };\n}\n\n// ── Main Component ──\nexport default function Calendar() {\n const { prefs, save } = useShellPrefs();\n const { isConnected, capabilities } = useMailAuth();\n const caldavEnabled = isConnected && capabilities?.caldav === true;\n const localEvents: CalendarEvent[] = prefs.calendar_events || [];\n\n const [calendars, setCalendars] = useState<DavCalendar[]>([]);\n const [caldavEvents, setCaldavEvents] = useState<CalendarEvent[]>([]);\n\n const { tasks: todoTasks, toggleDone: toggleTodoDone } = useTodoTasks();\n const todoEvents = useMemo<CalendarEvent[]>(\n () => todoTasks\n .filter(t => !!t.dueDate)\n .map(t => ({\n id: `todo-${t.id}`,\n title: t.name,\n date: t.dueDate!,\n color: 'gray',\n _todo: true,\n _todoId: t.id,\n _done: t.done,\n })),\n [todoTasks],\n );\n\n const events = useMemo(\n () => [...localEvents, ...caldavEvents, ...todoEvents],\n [localEvents, caldavEvents, todoEvents],\n );\n\n const today = new Date();\n const [currentDate, setCurrentDate] = useState(new Date(today.getFullYear(), today.getMonth(), 1));\n const [view, setView] = useState<ViewMode>('month');\n const [editingEvent, setEditingEvent] = useState<CalendarEvent | null>(null);\n const [newEventDate, setNewEventDate] = useState<string | null>(null);\n\n // Fetch calendars once when CalDAV becomes available\n useEffect(() => {\n if (!caldavEnabled) { setCalendars([]); return; }\n getMailClient()\n .get<{ calendars: DavCalendar[] }>('/api/calendar/calendars')\n .then(r => setCalendars(r.data.calendars))\n .catch(() => setCalendars([]));\n }, [caldavEnabled]);\n\n // Fetch events when current date changes (a 3-month window for prefetch)\n useEffect(() => {\n if (!caldavEnabled || calendars.length === 0) { setCaldavEvents([]); return; }\n const y = currentDate.getFullYear();\n const m = currentDate.getMonth();\n const start = new Date(y, m - 1, 1).toISOString();\n const end = new Date(y, m + 2, 0).toISOString();\n\n let cancelled = false;\n Promise.all(\n calendars.map(cal =>\n getMailClient()\n .get<{ events: DavEvent[] }>(`/api/calendar/calendars/${encodeURIComponent(cal.id)}/events`, {\n params: { start, end },\n })\n .then(r => r.data.events.map(e => davToLocal(e, cal.id)))\n .catch(() => [] as CalendarEvent[]),\n ),\n ).then(perCalendar => {\n if (cancelled) return;\n setCaldavEvents(perCalendar.flat());\n });\n return () => { cancelled = true; };\n }, [caldavEnabled, calendars, currentDate]);\n\n const saveLocalEvents = useCallback((updated: CalendarEvent[]) => {\n save({ calendar_events: updated });\n }, [save]);\n\n const saveEvent = async (evt: CalendarEvent, targetCalendarId?: string) => {\n // Editing an existing CalDAV event\n if (evt._caldav) {\n try {\n const input = toDavInput(evt);\n const res = await getMailClient().put<{ uid: string; etag: string }>(\n `/api/calendar/calendars/${encodeURIComponent(evt._caldav.calendarId)}/events/${encodeURIComponent(evt._caldav.eventUid)}`,\n input,\n { headers: { 'If-Match': evt._caldav.etag } },\n );\n setCaldavEvents(prev => prev.map(e =>\n e.id === evt.id\n ? { ...evt, _caldav: { ...evt._caldav!, etag: res.data.etag } }\n : e\n ));\n toast.success('Event updated');\n } catch (err) {\n const status = (err as { response?: { status?: number } })?.response?.status;\n if (status === 409) {\n toast.error('Event was modified elsewhere — refresh to see latest');\n } else {\n toast.error(extractError(err));\n }\n return;\n }\n } else if (targetCalendarId) {\n // New CalDAV event\n try {\n const input = toDavInput(evt);\n const res = await getMailClient().post<{ uid: string; etag: string; url: string }>(\n `/api/calendar/calendars/${encodeURIComponent(targetCalendarId)}/events`,\n input,\n );\n const newEvt: CalendarEvent = {\n ...evt,\n id: `caldav-${targetCalendarId}-${res.data.uid}`,\n _caldav: { calendarId: targetCalendarId, eventUid: res.data.uid, etag: res.data.etag },\n };\n setCaldavEvents(prev => [...prev, newEvt]);\n toast.success('Event created');\n } catch (err) {\n toast.error(extractError(err));\n return;\n }\n } else {\n // Local event\n const existing = localEvents.find(e => e.id === evt.id);\n if (existing) {\n saveLocalEvents(localEvents.map(e => e.id === evt.id ? evt : e));\n } else {\n saveLocalEvents([...localEvents, evt]);\n }\n }\n setEditingEvent(null);\n setNewEventDate(null);\n };\n\n const deleteEvent = async (evt: CalendarEvent) => {\n if (evt._caldav) {\n try {\n await getMailClient().delete(\n `/api/calendar/calendars/${encodeURIComponent(evt._caldav.calendarId)}/events/${encodeURIComponent(evt._caldav.eventUid)}`,\n { headers: { 'If-Match': evt._caldav.etag } },\n );\n setCaldavEvents(prev => prev.filter(e => e.id !== evt.id));\n toast.success('Event deleted');\n } catch (err) {\n toast.error(extractError(err));\n return;\n }\n } else {\n saveLocalEvents(localEvents.filter(e => e.id !== evt.id));\n }\n setEditingEvent(null);\n };\n\n // ── Navigation ──\n const goToday = () => setCurrentDate(new Date(today.getFullYear(), today.getMonth(), 1));\n const goPrev = () => {\n if (view === 'year') setCurrentDate(new Date(currentDate.getFullYear() - 1, currentDate.getMonth(), 1));\n else if (view === 'month') setCurrentDate(new Date(currentDate.getFullYear(), currentDate.getMonth() - 1, 1));\n else {\n const d = new Date(currentDate);\n d.setDate(d.getDate() - 7);\n setCurrentDate(d);\n }\n };\n const goNext = () => {\n if (view === 'year') setCurrentDate(new Date(currentDate.getFullYear() + 1, currentDate.getMonth(), 1));\n else if (view === 'month') setCurrentDate(new Date(currentDate.getFullYear(), currentDate.getMonth() + 1, 1));\n else {\n const d = new Date(currentDate);\n d.setDate(d.getDate() + 7);\n setCurrentDate(d);\n }\n };\n\n const monthLabel = view === 'year'\n ? String(currentDate.getFullYear())\n : currentDate.toLocaleDateString(undefined, { month: 'long', year: 'numeric' });\n\n const eventsByDate = useMemo(() => {\n const map: Record<string, CalendarEvent[]> = {};\n events.forEach(e => {\n if (!map[e.date]) map[e.date] = [];\n map[e.date].push(e);\n });\n for (const key of Object.keys(map)) {\n map[key].sort((a, b) => (a.start_time || '').localeCompare(b.start_time || ''));\n }\n return map;\n }, [events]);\n\n const handleDayClick = (dateStr: string) => {\n setNewEventDate(dateStr);\n setEditingEvent({\n id: `evt-${Date.now()}-${Math.random().toString(36).slice(2, 5)}`,\n title: '',\n date: dateStr,\n start_time: '09:00',\n end_time: '10:00',\n color: 'blue',\n all_day: false,\n });\n };\n\n return (\n <div className=\"flex flex-col h-full\">\n <div className=\"flex items-center justify-between px-4 py-2 border-b border-gray-200 shrink-0\">\n <div className=\"flex items-center gap-3\">\n <button onClick={goToday} className=\"px-2.5 py-1 text-xs font-medium rounded-md border border-gray-300 text-gray-700 hover:bg-gray-50\">Today</button>\n <div className=\"flex items-center gap-1\">\n <button onClick={goPrev} className=\"p-1 rounded hover:bg-gray-100\">\n <svg className=\"h-4 w-4 text-gray-600\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" strokeWidth={2}><path strokeLinecap=\"round\" strokeLinejoin=\"round\" d=\"M15.75 19.5L8.25 12l7.5-7.5\" /></svg>\n </button>\n <button onClick={goNext} className=\"p-1 rounded hover:bg-gray-100\">\n <svg className=\"h-4 w-4 text-gray-600\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" strokeWidth={2}><path strokeLinecap=\"round\" strokeLinejoin=\"round\" d=\"M8.25 4.5l7.5 7.5-7.5 7.5\" /></svg>\n </button>\n </div>\n <h2 className=\"text-sm font-semibold text-gray-900\">{monthLabel}</h2>\n </div>\n <div className=\"flex items-center gap-2\">\n <span\n onClick={() => window.dispatchEvent(new Event('open-mail-connect'))}\n className=\"text-[11px] text-gray-600 cursor-pointer hover:text-gray-900\"\n title=\"Open mail & calendar settings\"\n >\n {caldavEnabled\n ? `CalDAV · ${calendars.length} calendar${calendars.length === 1 ? '' : 's'}`\n : 'CalDAV not connected'}\n </span>\n <div className=\"w-px h-4 bg-gray-200\" />\n <div className=\"flex gap-1\">\n {(['year', 'month', 'week'] as const).map(v => (\n <button key={v} onClick={() => setView(v)}\n className={`px-3 py-1 text-xs font-medium rounded-md transition-colors ${view === v ? 'bg-blue-600 text-white' : 'bg-white border border-gray-300 text-gray-600 hover:bg-gray-50'}`}>\n {v.charAt(0).toUpperCase() + v.slice(1)}\n </button>\n ))}\n </div>\n </div>\n </div>\n\n <div className=\"flex-1 overflow-hidden\">\n {view === 'year' ? (\n <YearView\n year={currentDate.getFullYear()}\n eventsByDate={eventsByDate}\n today={toDateStr(today)}\n onPickMonth={(m) => { setCurrentDate(new Date(currentDate.getFullYear(), m, 1)); setView('month'); }}\n onDayClick={handleDayClick}\n />\n ) : view === 'month' ? (\n <MonthView\n year={currentDate.getFullYear()}\n month={currentDate.getMonth()}\n eventsByDate={eventsByDate}\n today={toDateStr(today)}\n onDayClick={handleDayClick}\n onEventClick={setEditingEvent}\n onToggleTodo={toggleTodoDone}\n />\n ) : (\n <WeekView\n currentDate={currentDate}\n eventsByDate={eventsByDate}\n today={toDateStr(today)}\n onDayClick={handleDayClick}\n onEventClick={setEditingEvent}\n onToggleTodo={toggleTodoDone}\n />\n )}\n </div>\n\n {editingEvent && (\n <EventEditor\n event={editingEvent}\n isNew={!!newEventDate}\n calendars={calendars}\n onSave={saveEvent}\n onDelete={() => deleteEvent(editingEvent)}\n onClose={() => { setEditingEvent(null); setNewEventDate(null); }}\n />\n )}\n </div>\n );\n}\n\nfunction extractError(err: unknown): string {\n const r = (err as { response?: { data?: { error?: string } } })?.response?.data?.error;\n if (r) return r;\n if (err instanceof Error) return err.message;\n return 'Unknown error';\n}\n\nfunction DayEventBadge({ evt, onEventClick, onToggleTodo, compact = false }: {\n evt: CalendarEvent;\n onEventClick: (e: CalendarEvent) => void;\n onToggleTodo: (id: string) => void;\n compact?: boolean;\n}) {\n if (evt._todo && evt._todoId) {\n return compact ? (\n <button onClick={(ev) => { ev.stopPropagation(); onToggleTodo(evt._todoId!); }}\n title={evt.title}\n className={`w-full text-left flex items-center gap-1 truncate rounded px-1 py-0.5 text-[10px] leading-tight font-medium hover:bg-gray-100 transition-colors ${evt._done ? 'text-gray-400' : 'text-gray-700'}`}>\n <span className=\"shrink-0\">{evt._done ? '☑' : '☐'}</span>\n <span className={`truncate ${evt._done ? 'line-through' : ''}`}>{evt.title || 'Task'}</span>\n </button>\n ) : (\n <button onClick={(ev) => { ev.stopPropagation(); onToggleTodo(evt._todoId!); }}\n className={`w-full text-left flex items-center gap-2 rounded-md px-2 py-1.5 hover:bg-gray-100 transition-colors ${evt._done ? 'text-gray-400' : 'text-gray-700'}`}>\n <span className=\"shrink-0 text-base leading-none\">{evt._done ? '☑' : '☐'}</span>\n <span className={`text-xs font-medium truncate ${evt._done ? 'line-through' : ''}`}>{evt.title || 'Task'}</span>\n </button>\n );\n }\n const c = getColor(evt.color);\n return compact ? (\n <button onClick={(ev) => { ev.stopPropagation(); onEventClick(evt); }}\n className={`w-full text-left truncate rounded px-1 py-0.5 text-[10px] leading-tight font-medium ${c.light} hover:opacity-80 transition-opacity`}>\n {!evt.all_day && evt.start_time && <span className=\"text-[9px] opacity-70 mr-0.5\">{evt.start_time}</span>}\n {evt.title || 'Untitled'}\n </button>\n ) : (\n <button onClick={(ev) => { ev.stopPropagation(); onEventClick(evt); }}\n className={`w-full text-left rounded-md px-2 py-1.5 ${c.light} hover:opacity-80 transition-opacity`}>\n <p className=\"text-xs font-medium truncate\">{evt.title || 'Untitled'}</p>\n {!evt.all_day && evt.start_time && (\n <p className=\"text-[10px] opacity-70\">{evt.start_time}{evt.end_time ? ` - ${evt.end_time}` : ''}</p>\n )}\n </button>\n );\n}\n\nfunction MonthView({ year, month, eventsByDate, today, onDayClick, onEventClick, onToggleTodo }: {\n year: number; month: number; eventsByDate: Record<string, CalendarEvent[]>;\n today: string; onDayClick: (d: string) => void; onEventClick: (e: CalendarEvent) => void;\n onToggleTodo: (id: string) => void;\n}) {\n const cells = useMemo(() => getMonthDays(year, month), [year, month]);\n\n return (\n <div className=\"h-full flex flex-col\">\n <div className=\"grid grid-cols-7 border-b border-gray-200\">\n {DAYS.map(d => (\n <div key={d} className=\"px-2 py-1.5 text-[10px] font-semibold text-gray-500 uppercase text-center\">{d}</div>\n ))}\n </div>\n <div className=\"grid grid-cols-7 flex-1 auto-rows-fr\">\n {cells.map((cell, i) => {\n const dateStr = toDateStr(cell.date);\n const isToday = dateStr === today;\n const dayEvents = eventsByDate[dateStr] || [];\n return (\n <div key={i}\n onClick={() => onDayClick(dateStr)}\n className={`border-b border-r border-gray-100 px-1 py-0.5 cursor-pointer hover:bg-blue-50/50 transition-colors overflow-hidden ${!cell.isCurrentMonth ? 'bg-gray-50/50' : ''}`}\n >\n <div className={`text-[11px] font-medium mb-0.5 w-5 h-5 flex items-center justify-center rounded-full ${isToday ? 'bg-blue-600 text-white' : cell.isCurrentMonth ? 'text-gray-900' : 'text-gray-400'}`}>\n {cell.date.getDate()}\n </div>\n <div className=\"space-y-0.5\">\n {dayEvents.slice(0, 3).map(evt => <DayEventBadge key={evt.id} evt={evt} onEventClick={onEventClick} onToggleTodo={onToggleTodo} compact />)}\n {dayEvents.length > 3 && (\n <p className=\"text-[9px] text-gray-400 pl-1\">+{dayEvents.length - 3} more</p>\n )}\n </div>\n </div>\n );\n })}\n </div>\n </div>\n );\n}\n\nfunction YearView({ year, eventsByDate, today, onPickMonth, onDayClick }: {\n year: number;\n eventsByDate: Record<string, CalendarEvent[]>;\n today: string;\n onPickMonth: (month: number) => void;\n onDayClick: (dateStr: string) => void;\n}) {\n const monthShort = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'];\n const dowShort = ['S', 'M', 'T', 'W', 'T', 'F', 'S'];\n\n return (\n <div className=\"h-full overflow-y-auto p-4\">\n <div className=\"grid grid-cols-2 sm:grid-cols-3 lg:grid-cols-4 gap-x-6 gap-y-5 max-w-5xl mx-auto\">\n {monthShort.map((label, m) => {\n const cells = getMonthDays(year, m);\n return (\n <div key={m} className=\"flex flex-col\">\n <button onClick={() => onPickMonth(m)}\n className=\"self-start text-[13px] font-semibold text-blue-600 hover:text-blue-800 mb-1 px-1 -ml-1 rounded transition-colors\">\n {label}\n </button>\n <div className=\"grid grid-cols-7 mb-0.5\">\n {dowShort.map((d, i) => (\n <div key={i} className=\"text-[9px] font-medium text-gray-400 text-center\">{d}</div>\n ))}\n </div>\n <div className=\"grid grid-cols-7\">\n {cells.map((cell, i) => {\n const dateStr = toDateStr(cell.date);\n const isToday = dateStr === today;\n const hasEvents = !!eventsByDate[dateStr]?.length;\n return (\n <button key={i}\n onClick={(e) => { e.stopPropagation(); onDayClick(dateStr); }}\n className=\"relative h-6 flex items-center justify-center group\"\n tabIndex={cell.isCurrentMonth ? 0 : -1}>\n <span className={`text-[10px] tabular-nums leading-none flex items-center justify-center w-5 h-5 rounded-full transition-colors\n ${isToday\n ? 'bg-blue-600 text-white font-semibold'\n : cell.isCurrentMonth\n ? 'text-gray-700 group-hover:bg-blue-100'\n : 'text-gray-300'}`}>\n {cell.date.getDate()}\n </span>\n {hasEvents && cell.isCurrentMonth && !isToday && (\n <span className=\"absolute bottom-0 left-1/2 -translate-x-1/2 w-1 h-1 rounded-full bg-blue-500\" />\n )}\n </button>\n );\n })}\n </div>\n </div>\n );\n })}\n </div>\n </div>\n );\n}\n\nfunction WeekView({ currentDate, eventsByDate, today, onDayClick, onEventClick, onToggleTodo }: {\n currentDate: Date; eventsByDate: Record<string, CalendarEvent[]>;\n today: string; onDayClick: (d: string) => void; onEventClick: (e: CalendarEvent) => void;\n onToggleTodo: (id: string) => void;\n}) {\n const days = useMemo(() => getWeekDays(currentDate), [currentDate]);\n\n return (\n <div className=\"h-full flex flex-col\">\n <div className=\"grid grid-cols-7 border-b border-gray-200\">\n {days.map(d => {\n const dateStr = toDateStr(d);\n const isToday = dateStr === today;\n return (\n <div key={dateStr} className=\"px-2 py-2 text-center\">\n <p className=\"text-[10px] font-medium text-gray-500 uppercase\">{DAYS[d.getDay()]}</p>\n <p className={`text-lg font-semibold mt-0.5 ${isToday ? 'text-blue-600' : 'text-gray-900'}`}>{d.getDate()}</p>\n </div>\n );\n })}\n </div>\n <div className=\"grid grid-cols-7 flex-1 overflow-y-auto\">\n {days.map(d => {\n const dateStr = toDateStr(d);\n const dayEvents = eventsByDate[dateStr] || [];\n return (\n <div key={dateStr}\n onClick={() => onDayClick(dateStr)}\n className=\"border-r border-gray-100 px-1.5 py-2 cursor-pointer hover:bg-blue-50/30 transition-colors min-h-[200px]\">\n <div className=\"space-y-1\">\n {dayEvents.map(evt => <DayEventBadge key={evt.id} evt={evt} onEventClick={onEventClick} onToggleTodo={onToggleTodo} />)}\n </div>\n </div>\n );\n })}\n </div>\n </div>\n );\n}\n\nfunction EventEditor({ event, isNew, calendars, onSave, onDelete, onClose }: {\n event: CalendarEvent;\n isNew: boolean;\n calendars: DavCalendar[];\n onSave: (e: CalendarEvent, targetCalendarId?: string) => void;\n onDelete: () => void;\n onClose: () => void;\n}) {\n const [title, setTitle] = useState(event.title);\n const [date, setDate] = useState(event.date);\n const [startTime, setStartTime] = useState(event.start_time || '09:00');\n const [endTime, setEndTime] = useState(event.end_time || '10:00');\n const [color, setColor] = useState(event.color);\n const [allDay, setAllDay] = useState(event.all_day ?? false);\n const [description, setDescription] = useState(event.description || '');\n const isFromCaldav = !!event._caldav;\n const [target, setTarget] = useState<string>(isFromCaldav ? event._caldav!.calendarId : 'local');\n\n const handleSave = () => {\n if (!title.trim()) { toast.error('Event title is required.'); return; }\n const updated: CalendarEvent = {\n ...event,\n title: title.trim(),\n date,\n start_time: allDay ? undefined : startTime,\n end_time: allDay ? undefined : endTime,\n color,\n all_day: allDay,\n description: description.trim() || undefined,\n };\n const targetCal = !isFromCaldav && target !== 'local' ? target : undefined;\n onSave(updated, targetCal);\n };\n\n const inp = 'block w-full rounded-md border border-gray-300 px-3 py-2 shadow-sm focus:border-blue-500 focus:ring-blue-500 sm:text-sm';\n\n return (\n <Modal open onClose={onClose} title={isNew ? 'New Event' : 'Edit Event'} size=\"sm\">\n <div className=\"space-y-4\">\n <div>\n <label className=\"block text-sm font-medium text-gray-700 mb-1\">Title *</label>\n <input value={title} onChange={e => setTitle(e.target.value)} className={inp} placeholder=\"Event title\" autoFocus />\n </div>\n <div>\n <label className=\"block text-sm font-medium text-gray-700 mb-1\">Date</label>\n <input type=\"date\" value={date} onChange={e => setDate(e.target.value)} className={inp} />\n </div>\n <label className=\"flex items-center gap-2 cursor-pointer\">\n <input type=\"checkbox\" checked={allDay} onChange={e => setAllDay(e.target.checked)} className=\"h-4 w-4 rounded border-gray-300 text-blue-600\" />\n <span className=\"text-sm text-gray-700\">All day</span>\n </label>\n {!allDay && (\n <div className=\"grid grid-cols-2 gap-3\">\n <div>\n <label className=\"block text-sm font-medium text-gray-700 mb-1\">Start</label>\n <input type=\"time\" value={startTime} onChange={e => setStartTime(e.target.value)} className={inp} />\n </div>\n <div>\n <label className=\"block text-sm font-medium text-gray-700 mb-1\">End</label>\n <input type=\"time\" value={endTime} onChange={e => setEndTime(e.target.value)} className={inp} />\n </div>\n </div>\n )}\n {(isNew && calendars.length > 0) && (\n <div>\n <label className=\"block text-sm font-medium text-gray-700 mb-1\">Save to</label>\n <select value={target} onChange={e => setTarget(e.target.value)} className={inp}>\n <option value=\"local\">Local (this device only)</option>\n {calendars.map(c => (\n <option key={c.id} value={c.id}>{c.displayName}</option>\n ))}\n </select>\n </div>\n )}\n {isFromCaldav && (\n <p className=\"text-[11px] text-gray-500\">\n From {calendars.find(c => c.id === event._caldav?.calendarId)?.displayName || 'CalDAV'}\n </p>\n )}\n <div>\n <label className=\"block text-sm font-medium text-gray-700 mb-1\">Color</label>\n <div className=\"flex gap-2\">\n {COLORS.map(c => (\n <button key={c.key} onClick={() => setColor(c.key)}\n className={`w-6 h-6 rounded-full ${c.bg} border-2 transition-all ${color === c.key ? 'border-gray-700 scale-110' : 'border-transparent hover:border-gray-400'}`} />\n ))}\n </div>\n </div>\n <div>\n <label className=\"block text-sm font-medium text-gray-700 mb-1\">Description</label>\n <textarea value={description} onChange={e => setDescription(e.target.value)} rows={2} className={inp} placeholder=\"Optional notes...\" />\n </div>\n </div>\n\n {!isNew && (\n <ModalActions position=\"left\">\n <button onClick={onDelete} className=\"text-sm text-red-600 hover:text-red-800 font-medium\">Delete</button>\n </ModalActions>\n )}\n <ModalActions>\n <button onClick={handleSave} className=\"bg-blue-600 text-white px-4 py-2 text-sm font-medium rounded-lg hover:bg-blue-700\">\n {isNew ? 'Create' : 'Save'}\n </button>\n </ModalActions>\n </Modal>\n );\n}\n"]}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { loadAppearance, WidgetSettingsModal } from './chunk-
|
|
2
|
-
import { useWidgetSettings } from './chunk-
|
|
1
|
+
import { loadAppearance, WidgetSettingsModal } from './chunk-O6FJZAFM.js';
|
|
2
|
+
import { useWidgetSettings } from './chunk-62FC2FHC.js';
|
|
3
3
|
import './chunk-PLGHQ7QW.js';
|
|
4
4
|
import './chunk-SSA762W5.js';
|
|
5
5
|
import { useState, useCallback, useEffect } from 'react';
|
|
@@ -226,5 +226,5 @@ function CurrencyConverter() {
|
|
|
226
226
|
}
|
|
227
227
|
|
|
228
228
|
export { CurrencyConverter as default };
|
|
229
|
-
//# sourceMappingURL=CurrencyConverter-
|
|
230
|
-
//# sourceMappingURL=CurrencyConverter-
|
|
229
|
+
//# sourceMappingURL=CurrencyConverter-YHOGBUPH.js.map
|
|
230
|
+
//# sourceMappingURL=CurrencyConverter-YHOGBUPH.js.map
|