react-os-shell 0.7.4 → 0.8.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 +9 -32
- package/dist/{Minesweeper-N73MSPJV.js → Minesweeper-M6HIJYPL.js} +3 -3
- package/dist/{Minesweeper-N73MSPJV.js.map → Minesweeper-M6HIJYPL.js.map} +1 -1
- package/dist/{PomodoroTimer-YTV5Z6AC.js → PomodoroTimer-5K55K26A.js} +3 -3
- package/dist/{PomodoroTimer-YTV5Z6AC.js.map → PomodoroTimer-5K55K26A.js.map} +1 -1
- package/dist/{TodoList-PI4SGVGI.js → TodoList-26N6ZTLN.js} +4 -3
- package/dist/TodoList-26N6ZTLN.js.map +1 -0
- package/dist/apps/index.d.ts +1 -8
- package/dist/apps/index.js +4 -11
- package/dist/apps/index.js.map +1 -1
- package/dist/chunk-QTJ2CHJX.js +174 -0
- package/dist/chunk-QTJ2CHJX.js.map +1 -0
- package/dist/{chunk-NSU7OHPC.js → chunk-Y4QYGQKS.js} +3 -11
- package/dist/chunk-Y4QYGQKS.js.map +1 -0
- package/dist/index.d.ts +45 -58
- package/dist/index.js +12 -271
- package/dist/index.js.map +1 -1
- package/package.json +3 -10
- package/dist/Calendar-KCZQJ5CY.js +0 -598
- package/dist/Calendar-KCZQJ5CY.js.map +0 -1
- package/dist/Email-ZUDCRZKB.js +0 -475
- package/dist/Email-ZUDCRZKB.js.map +0 -1
- package/dist/TodoList-PI4SGVGI.js.map +0 -1
- package/dist/chunk-25L4DIKH.js +0 -90
- package/dist/chunk-25L4DIKH.js.map +0 -1
- package/dist/chunk-NSU7OHPC.js.map +0 -1
- package/dist/chunk-PDFQNHW7.js +0 -24
- package/dist/chunk-PDFQNHW7.js.map +0 -1
- package/dist/chunk-VBFB3ZIN.js +0 -129
- package/dist/chunk-VBFB3ZIN.js.map +0 -1
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/apps/Calendar.tsx"],"names":[],"mappings":"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","file":"Calendar-KCZQJ5CY.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"]}
|
package/dist/Email-ZUDCRZKB.js
DELETED
|
@@ -1,475 +0,0 @@
|
|
|
1
|
-
import { setEmailUnreadCount } from './chunk-PDFQNHW7.js';
|
|
2
|
-
import { useMailAuth, getMailClient } from './chunk-VBFB3ZIN.js';
|
|
3
|
-
import { formatDate, formatDateTime } from './chunk-NSU7OHPC.js';
|
|
4
|
-
import { toast_default } from './chunk-WIJ45SYD.js';
|
|
5
|
-
import { Modal, ModalActions } from './chunk-3T6SQ4UO.js';
|
|
6
|
-
import './chunk-UBN4IUDE.js';
|
|
7
|
-
import './chunk-ZF6AYO4G.js';
|
|
8
|
-
import { useState, useMemo, useCallback, useEffect, useRef } from 'react';
|
|
9
|
-
import { jsx, jsxs } from 'react/jsx-runtime';
|
|
10
|
-
|
|
11
|
-
var SMART_VIEWS = [
|
|
12
|
-
{ key: "__inbox__", label: "Inbox", icon: "\u{1F4E5}" },
|
|
13
|
-
{ key: "__starred__", label: "Starred", icon: "\u2B50" },
|
|
14
|
-
{ key: "__unread__", label: "Unread", icon: "\u25CF" },
|
|
15
|
-
{ key: "__drafts__", label: "Drafts", icon: "\u{1F4DD}" },
|
|
16
|
-
{ key: "__sent__", label: "Sent", icon: "\u{1F4E4}" },
|
|
17
|
-
{ key: "__trash__", label: "Trash", icon: "\u{1F5D1}" },
|
|
18
|
-
{ key: "__junk__", label: "Spam", icon: "\u26A0" }
|
|
19
|
-
];
|
|
20
|
-
function resolveSmartView(key, folders) {
|
|
21
|
-
if (key === "__inbox__") return folders.find((f) => f.specialUse === "inbox")?.path || "INBOX";
|
|
22
|
-
if (key === "__sent__") return folders.find((f) => f.specialUse === "sent")?.path || "Sent";
|
|
23
|
-
if (key === "__drafts__") return folders.find((f) => f.specialUse === "drafts")?.path || "Drafts";
|
|
24
|
-
if (key === "__trash__") return folders.find((f) => f.specialUse === "trash")?.path || "Trash";
|
|
25
|
-
if (key === "__junk__") return folders.find((f) => f.specialUse === "junk")?.path || "Junk";
|
|
26
|
-
return key;
|
|
27
|
-
}
|
|
28
|
-
function Email() {
|
|
29
|
-
const { isConnected, serverReachable } = useMailAuth();
|
|
30
|
-
const [folders, setFolders] = useState([]);
|
|
31
|
-
const [selectedKey, setSelectedKey] = useState("__inbox__");
|
|
32
|
-
const [messages, setMessages] = useState([]);
|
|
33
|
-
const [selectedUid, setSelectedUid] = useState(null);
|
|
34
|
-
const [detail, setDetail] = useState(null);
|
|
35
|
-
const [loadingFolders, setLoadingFolders] = useState(false);
|
|
36
|
-
const [loadingList, setLoadingList] = useState(false);
|
|
37
|
-
const [loadingDetail, setLoadingDetail] = useState(false);
|
|
38
|
-
const [composeOpen, setComposeOpen] = useState(false);
|
|
39
|
-
const [composeDraft, setComposeDraft] = useState(null);
|
|
40
|
-
const [serverError, setServerError] = useState(null);
|
|
41
|
-
const selectedFolderPath = useMemo(() => resolveSmartView(selectedKey, folders), [selectedKey, folders]);
|
|
42
|
-
const refreshFolders = useCallback(async () => {
|
|
43
|
-
if (!isConnected) return;
|
|
44
|
-
setLoadingFolders(true);
|
|
45
|
-
setServerError(null);
|
|
46
|
-
try {
|
|
47
|
-
const res = await getMailClient().get("/api/mail/folders");
|
|
48
|
-
setFolders(res.data.folders);
|
|
49
|
-
} catch (err) {
|
|
50
|
-
setServerError(extractError(err));
|
|
51
|
-
} finally {
|
|
52
|
-
setLoadingFolders(false);
|
|
53
|
-
}
|
|
54
|
-
}, [isConnected]);
|
|
55
|
-
const refreshList = useCallback(async () => {
|
|
56
|
-
if (!isConnected) return;
|
|
57
|
-
setLoadingList(true);
|
|
58
|
-
setServerError(null);
|
|
59
|
-
try {
|
|
60
|
-
const res = await getMailClient().get("/api/mail/messages", {
|
|
61
|
-
params: { folder: selectedFolderPath, page: 0, pageSize: 50 }
|
|
62
|
-
});
|
|
63
|
-
setMessages(res.data.messages);
|
|
64
|
-
} catch (err) {
|
|
65
|
-
setServerError(extractError(err));
|
|
66
|
-
} finally {
|
|
67
|
-
setLoadingList(false);
|
|
68
|
-
}
|
|
69
|
-
}, [isConnected, selectedFolderPath]);
|
|
70
|
-
useEffect(() => {
|
|
71
|
-
refreshFolders();
|
|
72
|
-
}, [refreshFolders]);
|
|
73
|
-
useEffect(() => {
|
|
74
|
-
refreshList();
|
|
75
|
-
setDetail(null);
|
|
76
|
-
setSelectedUid(null);
|
|
77
|
-
}, [refreshList]);
|
|
78
|
-
const unreadPollRef = useRef(null);
|
|
79
|
-
useEffect(() => {
|
|
80
|
-
if (!isConnected) return;
|
|
81
|
-
async function tick() {
|
|
82
|
-
try {
|
|
83
|
-
const res = await getMailClient().get("/api/mail/unread-counts");
|
|
84
|
-
const inboxFolder = folders.find((f) => f.specialUse === "inbox")?.path || "INBOX";
|
|
85
|
-
setEmailUnreadCount(res.data.counts[inboxFolder] || 0);
|
|
86
|
-
setFolders(
|
|
87
|
-
(prev) => prev.map((f) => ({ ...f, unreadCount: res.data.counts[f.path] ?? f.unreadCount }))
|
|
88
|
-
);
|
|
89
|
-
} catch {
|
|
90
|
-
}
|
|
91
|
-
}
|
|
92
|
-
tick();
|
|
93
|
-
unreadPollRef.current = window.setInterval(tick, 3e4);
|
|
94
|
-
return () => {
|
|
95
|
-
if (unreadPollRef.current) window.clearInterval(unreadPollRef.current);
|
|
96
|
-
};
|
|
97
|
-
}, [isConnected, folders]);
|
|
98
|
-
const openMessage = useCallback(async (item) => {
|
|
99
|
-
setSelectedUid(item.uid);
|
|
100
|
-
setLoadingDetail(true);
|
|
101
|
-
try {
|
|
102
|
-
const res = await getMailClient().get(
|
|
103
|
-
`/api/mail/messages/${encodeURIComponent(selectedFolderPath)}/${item.uid}`
|
|
104
|
-
);
|
|
105
|
-
setDetail(res.data);
|
|
106
|
-
if (!item.flags.includes("\\Seen")) {
|
|
107
|
-
await getMailClient().post(
|
|
108
|
-
`/api/mail/messages/${encodeURIComponent(selectedFolderPath)}/${item.uid}/flags`,
|
|
109
|
-
{ add: ["\\Seen"] }
|
|
110
|
-
);
|
|
111
|
-
setMessages(
|
|
112
|
-
(prev) => prev.map((m) => m.uid === item.uid ? { ...m, flags: [...m.flags, "\\Seen"] } : m)
|
|
113
|
-
);
|
|
114
|
-
}
|
|
115
|
-
} catch (err) {
|
|
116
|
-
toast_default.error(extractError(err));
|
|
117
|
-
} finally {
|
|
118
|
-
setLoadingDetail(false);
|
|
119
|
-
}
|
|
120
|
-
}, [selectedFolderPath]);
|
|
121
|
-
const toggleStar = useCallback(async (item) => {
|
|
122
|
-
const isFlagged = item.flags.includes("\\Flagged");
|
|
123
|
-
try {
|
|
124
|
-
await getMailClient().post(
|
|
125
|
-
`/api/mail/messages/${encodeURIComponent(selectedFolderPath)}/${item.uid}/flags`,
|
|
126
|
-
isFlagged ? { remove: ["\\Flagged"] } : { add: ["\\Flagged"] }
|
|
127
|
-
);
|
|
128
|
-
setMessages(
|
|
129
|
-
(prev) => prev.map(
|
|
130
|
-
(m) => m.uid === item.uid ? {
|
|
131
|
-
...m,
|
|
132
|
-
flags: isFlagged ? m.flags.filter((f) => f !== "\\Flagged") : [...m.flags, "\\Flagged"]
|
|
133
|
-
} : m
|
|
134
|
-
)
|
|
135
|
-
);
|
|
136
|
-
} catch (err) {
|
|
137
|
-
toast_default.error(extractError(err));
|
|
138
|
-
}
|
|
139
|
-
}, [selectedFolderPath]);
|
|
140
|
-
const trashMessage = useCallback(async (uid) => {
|
|
141
|
-
try {
|
|
142
|
-
await getMailClient().delete(`/api/mail/messages/${encodeURIComponent(selectedFolderPath)}/${uid}`);
|
|
143
|
-
setMessages((prev) => prev.filter((m) => m.uid !== uid));
|
|
144
|
-
if (selectedUid === uid) {
|
|
145
|
-
setDetail(null);
|
|
146
|
-
setSelectedUid(null);
|
|
147
|
-
}
|
|
148
|
-
} catch (err) {
|
|
149
|
-
toast_default.error(extractError(err));
|
|
150
|
-
}
|
|
151
|
-
}, [selectedFolderPath, selectedUid]);
|
|
152
|
-
function openCompose(initial) {
|
|
153
|
-
setComposeDraft(initial ?? { to: "", cc: "", subject: "", body: "" });
|
|
154
|
-
setComposeOpen(true);
|
|
155
|
-
}
|
|
156
|
-
if (serverReachable === false) {
|
|
157
|
-
return /* @__PURE__ */ jsx(
|
|
158
|
-
EmptyState,
|
|
159
|
-
{
|
|
160
|
-
title: "Mail server unreachable",
|
|
161
|
-
body: "The bridge server is not responding. Start it with `npm run server:dev`, then retry.",
|
|
162
|
-
action: /* @__PURE__ */ jsx("button", { onClick: () => window.location.reload(), className: "px-4 py-2 bg-gray-900 text-white rounded text-sm", children: "Retry" })
|
|
163
|
-
}
|
|
164
|
-
);
|
|
165
|
-
}
|
|
166
|
-
if (!isConnected) {
|
|
167
|
-
return /* @__PURE__ */ jsx(
|
|
168
|
-
EmptyState,
|
|
169
|
-
{
|
|
170
|
-
title: "Connect your mail account",
|
|
171
|
-
body: "Open the Mail & Calendar button in the taskbar to connect via IMAP/SMTP/CalDAV."
|
|
172
|
-
}
|
|
173
|
-
);
|
|
174
|
-
}
|
|
175
|
-
return /* @__PURE__ */ jsxs("div", { className: "flex h-full text-sm", children: [
|
|
176
|
-
/* @__PURE__ */ jsxs("aside", { className: "w-56 shrink-0 border-r border-gray-200 overflow-y-auto bg-gray-50/60", children: [
|
|
177
|
-
/* @__PURE__ */ jsx("div", { className: "p-3", children: /* @__PURE__ */ jsx(
|
|
178
|
-
"button",
|
|
179
|
-
{
|
|
180
|
-
onClick: () => openCompose(),
|
|
181
|
-
className: "w-full bg-gray-900 text-white rounded-lg px-3 py-2 text-sm font-medium hover:bg-gray-800",
|
|
182
|
-
children: "Compose"
|
|
183
|
-
}
|
|
184
|
-
) }),
|
|
185
|
-
/* @__PURE__ */ jsx("div", { className: "px-2", children: SMART_VIEWS.map((view) => {
|
|
186
|
-
const folder = view.key === "__inbox__" ? folders.find((f) => f.specialUse === "inbox") : view.key === "__sent__" ? folders.find((f) => f.specialUse === "sent") : view.key === "__drafts__" ? folders.find((f) => f.specialUse === "drafts") : view.key === "__trash__" ? folders.find((f) => f.specialUse === "trash") : view.key === "__junk__" ? folders.find((f) => f.specialUse === "junk") : null;
|
|
187
|
-
const unread = folder?.unreadCount ?? 0;
|
|
188
|
-
const active = selectedKey === view.key;
|
|
189
|
-
return /* @__PURE__ */ jsxs(
|
|
190
|
-
"button",
|
|
191
|
-
{
|
|
192
|
-
onClick: () => setSelectedKey(view.key),
|
|
193
|
-
className: `w-full flex items-center gap-2 px-2 py-1.5 rounded text-left text-sm ${active ? "bg-gray-200 font-medium" : "hover:bg-gray-100"}`,
|
|
194
|
-
children: [
|
|
195
|
-
/* @__PURE__ */ jsx("span", { className: "w-5 text-center text-base leading-none", children: view.icon }),
|
|
196
|
-
/* @__PURE__ */ jsx("span", { className: "flex-1 truncate", children: view.label }),
|
|
197
|
-
unread > 0 && /* @__PURE__ */ jsx("span", { className: "text-[10px] bg-blue-500 text-white rounded-full px-1.5", children: unread })
|
|
198
|
-
]
|
|
199
|
-
},
|
|
200
|
-
view.key
|
|
201
|
-
);
|
|
202
|
-
}) }),
|
|
203
|
-
/* @__PURE__ */ jsx("div", { className: "px-3 mt-4 mb-1 text-[10px] uppercase tracking-wider text-gray-500", children: "Folders" }),
|
|
204
|
-
/* @__PURE__ */ jsx("div", { className: "px-2 pb-3", children: folders.filter((f) => !f.specialUse || f.specialUse === "archive" || f.specialUse === "flagged").filter((f) => f.path.toUpperCase() !== "INBOX").map((f) => {
|
|
205
|
-
const active = selectedKey === f.path;
|
|
206
|
-
return /* @__PURE__ */ jsxs(
|
|
207
|
-
"button",
|
|
208
|
-
{
|
|
209
|
-
onClick: () => setSelectedKey(f.path),
|
|
210
|
-
className: `w-full flex items-center gap-2 px-2 py-1.5 rounded text-left text-sm ${active ? "bg-gray-200 font-medium" : "hover:bg-gray-100"}`,
|
|
211
|
-
title: f.path,
|
|
212
|
-
children: [
|
|
213
|
-
/* @__PURE__ */ jsx("span", { className: "w-5 text-center text-base leading-none", children: "\u{1F4C1}" }),
|
|
214
|
-
/* @__PURE__ */ jsx("span", { className: "flex-1 truncate", children: f.name }),
|
|
215
|
-
f.unreadCount > 0 && /* @__PURE__ */ jsx("span", { className: "text-[10px] bg-gray-300 text-gray-800 rounded-full px-1.5", children: f.unreadCount })
|
|
216
|
-
]
|
|
217
|
-
},
|
|
218
|
-
f.path
|
|
219
|
-
);
|
|
220
|
-
}) })
|
|
221
|
-
] }),
|
|
222
|
-
/* @__PURE__ */ jsxs("section", { className: "w-80 shrink-0 border-r border-gray-200 flex flex-col", children: [
|
|
223
|
-
/* @__PURE__ */ jsxs("header", { className: "px-3 py-2 border-b border-gray-200 flex items-center justify-between", children: [
|
|
224
|
-
/* @__PURE__ */ jsx("h2", { className: "text-sm font-semibold", children: SMART_VIEWS.find((v) => v.key === selectedKey)?.label || selectedKey }),
|
|
225
|
-
/* @__PURE__ */ jsx(
|
|
226
|
-
"button",
|
|
227
|
-
{
|
|
228
|
-
onClick: () => {
|
|
229
|
-
refreshList();
|
|
230
|
-
refreshFolders();
|
|
231
|
-
},
|
|
232
|
-
className: "text-xs text-gray-600 hover:text-gray-900",
|
|
233
|
-
disabled: loadingList || loadingFolders,
|
|
234
|
-
children: loadingList || loadingFolders ? "\u2026" : "Refresh"
|
|
235
|
-
}
|
|
236
|
-
)
|
|
237
|
-
] }),
|
|
238
|
-
/* @__PURE__ */ jsx("div", { className: "flex-1 overflow-y-auto", children: loadingList && messages.length === 0 ? /* @__PURE__ */ jsx("div", { className: "p-4 text-center text-xs text-gray-500", children: "Loading\u2026" }) : messages.length === 0 ? /* @__PURE__ */ jsx("div", { className: "p-4 text-center text-xs text-gray-500", children: "No messages" }) : messages.map((msg) => /* @__PURE__ */ jsx(
|
|
239
|
-
MessageRow,
|
|
240
|
-
{
|
|
241
|
-
msg,
|
|
242
|
-
active: selectedUid === msg.uid,
|
|
243
|
-
onOpen: () => openMessage(msg),
|
|
244
|
-
onStar: () => toggleStar(msg)
|
|
245
|
-
},
|
|
246
|
-
msg.uid
|
|
247
|
-
)) })
|
|
248
|
-
] }),
|
|
249
|
-
/* @__PURE__ */ jsx("section", { className: "flex-1 overflow-y-auto", children: detail ? /* @__PURE__ */ jsx(
|
|
250
|
-
MessageDetailView,
|
|
251
|
-
{
|
|
252
|
-
detail,
|
|
253
|
-
folderPath: selectedFolderPath,
|
|
254
|
-
loading: loadingDetail,
|
|
255
|
-
onReply: () => openCompose({
|
|
256
|
-
to: detail.from.address,
|
|
257
|
-
cc: "",
|
|
258
|
-
subject: detail.subject.startsWith("Re:") ? detail.subject : `Re: ${detail.subject}`,
|
|
259
|
-
body: "",
|
|
260
|
-
inReplyTo: detail.threadId,
|
|
261
|
-
references: detail.references
|
|
262
|
-
}),
|
|
263
|
-
onTrash: () => trashMessage(detail.uid)
|
|
264
|
-
}
|
|
265
|
-
) : /* @__PURE__ */ jsx("div", { className: "h-full grid place-items-center text-xs text-gray-400", children: "Select a message" }) }),
|
|
266
|
-
composeOpen && composeDraft && /* @__PURE__ */ jsx(
|
|
267
|
-
ComposeModal,
|
|
268
|
-
{
|
|
269
|
-
open: composeOpen,
|
|
270
|
-
initial: composeDraft,
|
|
271
|
-
onClose: () => setComposeOpen(false),
|
|
272
|
-
onSent: () => {
|
|
273
|
-
setComposeOpen(false);
|
|
274
|
-
toast_default.success("Message sent");
|
|
275
|
-
refreshList();
|
|
276
|
-
}
|
|
277
|
-
}
|
|
278
|
-
),
|
|
279
|
-
serverError && /* @__PURE__ */ jsx("div", { className: "absolute bottom-3 left-1/2 -translate-x-1/2 bg-red-50 border border-red-200 text-red-800 px-3 py-1 text-xs rounded", children: serverError })
|
|
280
|
-
] });
|
|
281
|
-
}
|
|
282
|
-
function MessageRow({ msg, active, onOpen, onStar }) {
|
|
283
|
-
const unread = !msg.flags.includes("\\Seen");
|
|
284
|
-
const starred = msg.flags.includes("\\Flagged");
|
|
285
|
-
return /* @__PURE__ */ jsxs(
|
|
286
|
-
"div",
|
|
287
|
-
{
|
|
288
|
-
onClick: onOpen,
|
|
289
|
-
className: `px-3 py-2 border-b border-gray-100 cursor-pointer ${active ? "bg-blue-50" : "hover:bg-gray-50"}`,
|
|
290
|
-
children: [
|
|
291
|
-
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 mb-0.5", children: [
|
|
292
|
-
/* @__PURE__ */ jsx(
|
|
293
|
-
"button",
|
|
294
|
-
{
|
|
295
|
-
onClick: (e) => {
|
|
296
|
-
e.stopPropagation();
|
|
297
|
-
onStar();
|
|
298
|
-
},
|
|
299
|
-
className: `text-xs ${starred ? "text-yellow-500" : "text-gray-300 hover:text-gray-500"}`,
|
|
300
|
-
title: starred ? "Unstar" : "Star",
|
|
301
|
-
children: "\u2605"
|
|
302
|
-
}
|
|
303
|
-
),
|
|
304
|
-
/* @__PURE__ */ jsx("p", { className: `text-xs flex-1 truncate ${unread ? "font-semibold text-gray-900" : "text-gray-700"}`, children: msg.from.name || msg.from.address }),
|
|
305
|
-
/* @__PURE__ */ jsx("span", { className: "text-[10px] text-gray-400 shrink-0", children: formatDate(msg.date) })
|
|
306
|
-
] }),
|
|
307
|
-
/* @__PURE__ */ jsx("p", { className: `text-xs truncate ${unread ? "font-medium text-gray-900" : "text-gray-600"}`, children: msg.subject || "(no subject)" }),
|
|
308
|
-
msg.hasAttachments && /* @__PURE__ */ jsx("span", { className: "text-[10px] text-gray-400", children: "\u{1F4CE} attachment" })
|
|
309
|
-
]
|
|
310
|
-
}
|
|
311
|
-
);
|
|
312
|
-
}
|
|
313
|
-
function MessageDetailView({
|
|
314
|
-
detail,
|
|
315
|
-
folderPath,
|
|
316
|
-
loading,
|
|
317
|
-
onReply,
|
|
318
|
-
onTrash
|
|
319
|
-
}) {
|
|
320
|
-
const baseUrl = `/api/mail/messages/${encodeURIComponent(folderPath)}/${detail.uid}/attachments`;
|
|
321
|
-
return /* @__PURE__ */ jsxs("div", { children: [
|
|
322
|
-
/* @__PURE__ */ jsxs("header", { className: "px-6 py-4 border-b border-gray-200", children: [
|
|
323
|
-
/* @__PURE__ */ jsx("h1", { className: "text-lg font-semibold mb-2", children: detail.subject || "(no subject)" }),
|
|
324
|
-
/* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between text-xs text-gray-600", children: [
|
|
325
|
-
/* @__PURE__ */ jsxs("div", { children: [
|
|
326
|
-
/* @__PURE__ */ jsxs("div", { children: [
|
|
327
|
-
/* @__PURE__ */ jsx("strong", { children: detail.from.name || detail.from.address }),
|
|
328
|
-
" <",
|
|
329
|
-
detail.from.address,
|
|
330
|
-
">"
|
|
331
|
-
] }),
|
|
332
|
-
/* @__PURE__ */ jsxs("div", { children: [
|
|
333
|
-
"to ",
|
|
334
|
-
detail.to.map((t) => t.address).join(", ")
|
|
335
|
-
] }),
|
|
336
|
-
detail.cc.length > 0 && /* @__PURE__ */ jsxs("div", { children: [
|
|
337
|
-
"cc ",
|
|
338
|
-
detail.cc.map((t) => t.address).join(", ")
|
|
339
|
-
] }),
|
|
340
|
-
/* @__PURE__ */ jsx("div", { className: "text-gray-400 mt-1", children: formatDateTime(detail.date) })
|
|
341
|
-
] }),
|
|
342
|
-
/* @__PURE__ */ jsxs("div", { className: "flex gap-2", children: [
|
|
343
|
-
/* @__PURE__ */ jsx("button", { onClick: onReply, className: "px-3 py-1 text-xs border border-gray-300 rounded hover:bg-gray-50", children: "Reply" }),
|
|
344
|
-
/* @__PURE__ */ jsx("button", { onClick: onTrash, className: "px-3 py-1 text-xs border border-red-200 text-red-700 rounded hover:bg-red-50", children: "Trash" })
|
|
345
|
-
] })
|
|
346
|
-
] })
|
|
347
|
-
] }),
|
|
348
|
-
/* @__PURE__ */ jsx("article", { className: "px-6 py-4", children: loading ? /* @__PURE__ */ jsx("div", { className: "text-xs text-gray-500", children: "Loading\u2026" }) : detail.html ? /* @__PURE__ */ jsx("div", { className: "prose prose-sm max-w-none", dangerouslySetInnerHTML: { __html: detail.html } }) : /* @__PURE__ */ jsx("pre", { className: "whitespace-pre-wrap text-sm font-sans", children: detail.text || "(empty)" }) }),
|
|
349
|
-
detail.attachments.length > 0 && /* @__PURE__ */ jsxs("section", { className: "px-6 pb-6", children: [
|
|
350
|
-
/* @__PURE__ */ jsx("h3", { className: "text-xs font-semibold text-gray-700 mb-2", children: "Attachments" }),
|
|
351
|
-
/* @__PURE__ */ jsx("div", { className: "grid grid-cols-2 gap-2", children: detail.attachments.map((att) => /* @__PURE__ */ jsxs(
|
|
352
|
-
"a",
|
|
353
|
-
{
|
|
354
|
-
href: `${getMailClient().defaults.baseURL}${baseUrl}/${encodeURIComponent(att.partId)}`,
|
|
355
|
-
target: "_blank",
|
|
356
|
-
rel: "noreferrer",
|
|
357
|
-
className: "flex items-center gap-2 border border-gray-200 rounded px-3 py-2 text-xs hover:bg-gray-50",
|
|
358
|
-
children: [
|
|
359
|
-
/* @__PURE__ */ jsx("span", { children: "\u{1F4CE}" }),
|
|
360
|
-
/* @__PURE__ */ jsx("span", { className: "flex-1 truncate", children: att.filename }),
|
|
361
|
-
/* @__PURE__ */ jsxs("span", { className: "text-gray-400", children: [
|
|
362
|
-
(att.size / 1024).toFixed(1),
|
|
363
|
-
"KB"
|
|
364
|
-
] })
|
|
365
|
-
]
|
|
366
|
-
},
|
|
367
|
-
att.partId
|
|
368
|
-
)) })
|
|
369
|
-
] })
|
|
370
|
-
] });
|
|
371
|
-
}
|
|
372
|
-
function ComposeModal({
|
|
373
|
-
open,
|
|
374
|
-
initial,
|
|
375
|
-
onClose,
|
|
376
|
-
onSent
|
|
377
|
-
}) {
|
|
378
|
-
const [draft, setDraft] = useState(initial);
|
|
379
|
-
const [sending, setSending] = useState(false);
|
|
380
|
-
async function send() {
|
|
381
|
-
setSending(true);
|
|
382
|
-
try {
|
|
383
|
-
const toList = draft.to.split(",").map((s) => s.trim()).filter(Boolean);
|
|
384
|
-
const ccList = draft.cc.split(",").map((s) => s.trim()).filter(Boolean);
|
|
385
|
-
if (toList.length === 0) {
|
|
386
|
-
toast_default.error("At least one recipient required");
|
|
387
|
-
return;
|
|
388
|
-
}
|
|
389
|
-
await getMailClient().post("/api/mail/send", {
|
|
390
|
-
to: toList,
|
|
391
|
-
cc: ccList.length ? ccList : void 0,
|
|
392
|
-
subject: draft.subject,
|
|
393
|
-
text: draft.body,
|
|
394
|
-
inReplyTo: draft.inReplyTo,
|
|
395
|
-
references: draft.references,
|
|
396
|
-
saveToSent: true
|
|
397
|
-
});
|
|
398
|
-
onSent();
|
|
399
|
-
} catch (err) {
|
|
400
|
-
toast_default.error(extractError(err));
|
|
401
|
-
} finally {
|
|
402
|
-
setSending(false);
|
|
403
|
-
}
|
|
404
|
-
}
|
|
405
|
-
return /* @__PURE__ */ jsxs(Modal, { open, onClose, title: "New message", size: "lg", children: [
|
|
406
|
-
/* @__PURE__ */ jsxs("div", { className: "space-y-3", children: [
|
|
407
|
-
/* @__PURE__ */ jsx(
|
|
408
|
-
"input",
|
|
409
|
-
{
|
|
410
|
-
type: "text",
|
|
411
|
-
placeholder: "To",
|
|
412
|
-
value: draft.to,
|
|
413
|
-
onChange: (e) => setDraft({ ...draft, to: e.target.value }),
|
|
414
|
-
className: "w-full border border-gray-300 rounded px-3 py-2 text-sm"
|
|
415
|
-
}
|
|
416
|
-
),
|
|
417
|
-
/* @__PURE__ */ jsx(
|
|
418
|
-
"input",
|
|
419
|
-
{
|
|
420
|
-
type: "text",
|
|
421
|
-
placeholder: "Cc (optional)",
|
|
422
|
-
value: draft.cc,
|
|
423
|
-
onChange: (e) => setDraft({ ...draft, cc: e.target.value }),
|
|
424
|
-
className: "w-full border border-gray-300 rounded px-3 py-2 text-sm"
|
|
425
|
-
}
|
|
426
|
-
),
|
|
427
|
-
/* @__PURE__ */ jsx(
|
|
428
|
-
"input",
|
|
429
|
-
{
|
|
430
|
-
type: "text",
|
|
431
|
-
placeholder: "Subject",
|
|
432
|
-
value: draft.subject,
|
|
433
|
-
onChange: (e) => setDraft({ ...draft, subject: e.target.value }),
|
|
434
|
-
className: "w-full border border-gray-300 rounded px-3 py-2 text-sm"
|
|
435
|
-
}
|
|
436
|
-
),
|
|
437
|
-
/* @__PURE__ */ jsx(
|
|
438
|
-
"textarea",
|
|
439
|
-
{
|
|
440
|
-
rows: 12,
|
|
441
|
-
placeholder: "Write your message\u2026",
|
|
442
|
-
value: draft.body,
|
|
443
|
-
onChange: (e) => setDraft({ ...draft, body: e.target.value }),
|
|
444
|
-
className: "w-full border border-gray-300 rounded px-3 py-2 text-sm font-mono"
|
|
445
|
-
}
|
|
446
|
-
)
|
|
447
|
-
] }),
|
|
448
|
-
/* @__PURE__ */ jsx(ModalActions, { children: /* @__PURE__ */ jsx(
|
|
449
|
-
"button",
|
|
450
|
-
{
|
|
451
|
-
onClick: send,
|
|
452
|
-
disabled: sending,
|
|
453
|
-
className: "bg-gray-900 text-white rounded-lg px-5 py-2 text-sm font-medium hover:bg-gray-800 disabled:opacity-50",
|
|
454
|
-
children: sending ? "Sending\u2026" : "Send"
|
|
455
|
-
}
|
|
456
|
-
) })
|
|
457
|
-
] });
|
|
458
|
-
}
|
|
459
|
-
function EmptyState({ title, body, action }) {
|
|
460
|
-
return /* @__PURE__ */ jsx("div", { className: "h-full grid place-items-center p-8 text-center", children: /* @__PURE__ */ jsxs("div", { className: "max-w-sm", children: [
|
|
461
|
-
/* @__PURE__ */ jsx("h2", { className: "text-lg font-semibold text-gray-900 mb-1", children: title }),
|
|
462
|
-
/* @__PURE__ */ jsx("p", { className: "text-sm text-gray-600", children: body }),
|
|
463
|
-
action && /* @__PURE__ */ jsx("div", { className: "mt-4", children: action })
|
|
464
|
-
] }) });
|
|
465
|
-
}
|
|
466
|
-
function extractError(err) {
|
|
467
|
-
const response = err.response;
|
|
468
|
-
if (response?.data?.error) return response.data.error;
|
|
469
|
-
if (err instanceof Error) return err.message;
|
|
470
|
-
return "Unknown error";
|
|
471
|
-
}
|
|
472
|
-
|
|
473
|
-
export { Email as default };
|
|
474
|
-
//# sourceMappingURL=Email-ZUDCRZKB.js.map
|
|
475
|
-
//# sourceMappingURL=Email-ZUDCRZKB.js.map
|