@bobfrankston/rmfmail 1.2.232 → 1.2.233

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.
Files changed (146) hide show
  1. package/client/android-bootstrap.bundle.js +164 -152
  2. package/client/android-bootstrap.bundle.js.map +4 -4
  3. package/client/app.bundle.js +10 -104
  4. package/client/app.bundle.js.map +4 -4
  5. package/client/components/message-list.js +0 -60
  6. package/client/components/message-list.js.map +1 -1
  7. package/client/components/message-list.ts +0 -56
  8. package/client/compose/compose.bundle.js +1 -12
  9. package/client/compose/compose.bundle.js.map +2 -2
  10. package/client/compose/compose.html +0 -8
  11. package/client/compose/ghost-text.js +0 -8
  12. package/client/compose/ghost-text.js.map +1 -1
  13. package/client/compose/ghost-text.ts +0 -6
  14. package/client/compose/spellcheck-core.js +0 -1
  15. package/client/compose/spellcheck-core.js.map +1 -1
  16. package/client/compose/spellcheck-core.ts +0 -1
  17. package/client/index.html +0 -8
  18. package/client/lib/local-service.js +0 -73
  19. package/client/lib/local-service.js.map +1 -1
  20. package/client/lib/local-service.ts +0 -71
  21. package/client/lib/local-store.js +0 -3
  22. package/client/lib/local-store.js.map +1 -1
  23. package/client/lib/local-store.ts +0 -4
  24. package/package.json +1 -3
  25. package/packages/mailx-host/index.d.ts +0 -1
  26. package/packages/mailx-host/index.d.ts.map +1 -1
  27. package/packages/mailx-host/index.js +0 -1
  28. package/packages/mailx-host/index.js.map +1 -1
  29. package/packages/mailx-host/index.ts +0 -1
  30. package/packages/mailx-host/package.json +1 -1
  31. package/packages/mailx-service/index.d.ts.map +1 -1
  32. package/packages/mailx-service/index.js +36 -139
  33. package/packages/mailx-service/index.js.map +1 -1
  34. package/packages/mailx-service/index.ts +36 -148
  35. package/packages/mailx-settings/cloud.d.ts +0 -5
  36. package/packages/mailx-settings/cloud.d.ts.map +1 -1
  37. package/packages/mailx-settings/cloud.js +0 -16
  38. package/packages/mailx-settings/cloud.js.map +1 -1
  39. package/packages/mailx-settings/cloud.ts +0 -12
  40. package/packages/mailx-settings/index.d.ts +0 -3
  41. package/packages/mailx-settings/index.d.ts.map +1 -1
  42. package/packages/mailx-settings/index.js +0 -5
  43. package/packages/mailx-settings/index.js.map +1 -1
  44. package/packages/mailx-settings/index.ts +0 -7
  45. package/packages/mailx-store-web/main-thread-host.d.ts +1 -1
  46. package/packages/mailx-store-web/main-thread-host.d.ts.map +1 -1
  47. package/packages/mailx-store-web/main-thread-host.js +1 -38
  48. package/packages/mailx-store-web/main-thread-host.js.map +1 -1
  49. package/packages/mailx-store-web/main-thread-host.ts +0 -42
  50. package/packages/mailx-store-web/package.json +1 -1
  51. package/packages/mailx-store-web/web-service.d.ts.map +1 -1
  52. package/packages/mailx-store-web/web-service.js +28 -114
  53. package/packages/mailx-store-web/web-service.js.map +1 -1
  54. package/packages/mailx-store-web/web-service.ts +28 -124
  55. package/packages/mailx-store-web/web-settings.d.ts +0 -4
  56. package/packages/mailx-store-web/web-settings.d.ts.map +1 -1
  57. package/packages/mailx-store-web/web-settings.js +0 -29
  58. package/packages/mailx-store-web/web-settings.js.map +1 -1
  59. package/packages/mailx-store-web/web-settings.ts +0 -24
  60. package/packages/mailx-types/index.d.ts +2 -0
  61. package/packages/mailx-types/index.d.ts.map +1 -1
  62. package/packages/mailx-types/index.js +1 -0
  63. package/packages/mailx-types/index.js.map +1 -1
  64. package/packages/mailx-types/index.ts +2 -0
  65. package/packages/mailx-types/mime-build.d.ts +74 -0
  66. package/packages/mailx-types/mime-build.d.ts.map +1 -0
  67. package/packages/mailx-types/mime-build.js +160 -0
  68. package/packages/mailx-types/mime-build.js.map +1 -0
  69. package/packages/mailx-types/mime-build.ts +217 -0
  70. package/packages/mailx-types/package.json +1 -1
  71. package/packages/mailx-types/test/mime-build.test.mjs +200 -0
  72. package/client/components/calendar.js +0 -220
  73. package/client/components/calendar.js.map +0 -1
  74. package/client/components/calendar.ts +0 -213
  75. package/client/components/tasks.js +0 -261
  76. package/client/components/tasks.js.map +0 -1
  77. package/client/components/tasks.ts +0 -234
  78. package/packages/mailx-compose/.gitattributes +0 -10
  79. package/packages/mailx-compose/index.d.ts +0 -21
  80. package/packages/mailx-compose/index.d.ts.map +0 -1
  81. package/packages/mailx-compose/index.js +0 -66
  82. package/packages/mailx-compose/index.js.map +0 -1
  83. package/packages/mailx-compose/index.ts +0 -91
  84. package/packages/mailx-compose/package.json +0 -18
  85. package/packages/mailx-compose/tsconfig.json +0 -9
  86. package/packages/mailx-core/index.d.ts +0 -142
  87. package/packages/mailx-core/index.d.ts.map +0 -1
  88. package/packages/mailx-core/index.js +0 -430
  89. package/packages/mailx-core/index.js.map +0 -1
  90. package/packages/mailx-core/index.ts +0 -450
  91. package/packages/mailx-core/ipc.d.ts +0 -13
  92. package/packages/mailx-core/ipc.d.ts.map +0 -1
  93. package/packages/mailx-core/ipc.js +0 -56
  94. package/packages/mailx-core/ipc.js.map +0 -1
  95. package/packages/mailx-core/ipc.ts +0 -62
  96. package/packages/mailx-core/package.json +0 -18
  97. package/packages/mailx-core/tsconfig.json +0 -9
  98. package/packages/mailx-send/.gitattributes +0 -10
  99. package/packages/mailx-send/README.md +0 -217
  100. package/packages/mailx-send/cli-queue.d.ts +0 -11
  101. package/packages/mailx-send/cli-queue.d.ts.map +0 -1
  102. package/packages/mailx-send/cli-queue.js +0 -59
  103. package/packages/mailx-send/cli-queue.js.map +0 -1
  104. package/packages/mailx-send/cli-queue.ts +0 -62
  105. package/packages/mailx-send/cli-send.d.ts +0 -17
  106. package/packages/mailx-send/cli-send.d.ts.map +0 -1
  107. package/packages/mailx-send/cli-send.js +0 -75
  108. package/packages/mailx-send/cli-send.js.map +0 -1
  109. package/packages/mailx-send/cli-send.ts +0 -83
  110. package/packages/mailx-send/cli.d.ts +0 -22
  111. package/packages/mailx-send/cli.d.ts.map +0 -1
  112. package/packages/mailx-send/cli.js +0 -115
  113. package/packages/mailx-send/cli.js.map +0 -1
  114. package/packages/mailx-send/cli.ts +0 -126
  115. package/packages/mailx-send/index.d.ts +0 -77
  116. package/packages/mailx-send/index.d.ts.map +0 -1
  117. package/packages/mailx-send/index.js +0 -269
  118. package/packages/mailx-send/index.js.map +0 -1
  119. package/packages/mailx-send/index.ts +0 -338
  120. package/packages/mailx-send/mailsend/README.md +0 -133
  121. package/packages/mailx-send/mailsend/cli.d.ts +0 -12
  122. package/packages/mailx-send/mailsend/cli.d.ts.map +0 -1
  123. package/packages/mailx-send/mailsend/cli.js +0 -70
  124. package/packages/mailx-send/mailsend/cli.js.map +0 -1
  125. package/packages/mailx-send/mailsend/cli.ts +0 -81
  126. package/packages/mailx-send/mailsend/index.d.ts +0 -77
  127. package/packages/mailx-send/mailsend/index.d.ts.map +0 -1
  128. package/packages/mailx-send/mailsend/index.js +0 -264
  129. package/packages/mailx-send/mailsend/index.js.map +0 -1
  130. package/packages/mailx-send/mailsend/index.ts +0 -336
  131. package/packages/mailx-send/mailsend/package-lock.json +0 -65
  132. package/packages/mailx-send/mailsend/package.json +0 -26
  133. package/packages/mailx-send/mailsend/tsconfig.json +0 -21
  134. package/packages/mailx-send/package-lock.json +0 -65
  135. package/packages/mailx-send/package.json +0 -37
  136. package/packages/mailx-send/tsconfig.json +0 -21
  137. package/packages/mailx-server/.gitattributes +0 -10
  138. package/packages/mailx-server/index.d.ts +0 -8
  139. package/packages/mailx-server/index.d.ts.map +0 -1
  140. package/packages/mailx-server/index.js +0 -412
  141. package/packages/mailx-server/index.js.map +0 -1
  142. package/packages/mailx-server/index.ts +0 -445
  143. package/packages/mailx-server/package.json +0 -28
  144. package/packages/mailx-server/tsconfig.json +0 -9
  145. package/packages/mailx-server/tsconfig.tsbuildinfo +0 -1
  146. /package/packages/mailx-imap/{node_modules.npmglobalize-stash-40260 → node_modules.npmglobalize-stash-40004}/.package-lock.json +0 -0
@@ -1,213 +0,0 @@
1
- /**
2
- * Calendar pane — Thunderbird Lightning "Today Pane" style.
3
- *
4
- * Phase-1 scope (this commit): a usable mini-month + upcoming-events list
5
- * sourced from a local-only event store. Google Calendar sync is a separate
6
- * step (oauthsupport scope is already wired; the dispatcher branch + provider
7
- * are owed). UI lands first so the data layer can be slotted in without
8
- * UX rework.
9
- */
10
-
11
- interface CalEvent {
12
- id: string;
13
- title: string;
14
- start: number; // ms since epoch
15
- end: number;
16
- allDay?: boolean;
17
- location?: string;
18
- notes?: string;
19
- source?: "local" | "google";
20
- }
21
-
22
- const LOCAL_STORE_KEY = "mailx-cal-events-v1";
23
- let isOpen = false;
24
-
25
- function loadEvents(): CalEvent[] {
26
- try {
27
- const raw = localStorage.getItem(LOCAL_STORE_KEY);
28
- if (!raw) return [];
29
- const arr = JSON.parse(raw);
30
- return Array.isArray(arr) ? arr : [];
31
- } catch { return []; }
32
- }
33
- function saveEvents(events: CalEvent[]): void {
34
- try { localStorage.setItem(LOCAL_STORE_KEY, JSON.stringify(events)); } catch { /* */ }
35
- }
36
-
37
- export async function openCalendar(): Promise<void> {
38
- if (isOpen) return;
39
- isOpen = true;
40
-
41
- const backdrop = document.createElement("div");
42
- backdrop.className = "mailx-modal-backdrop";
43
- const panel = document.createElement("div");
44
- panel.className = "mailx-modal mailx-modal-wide";
45
- panel.innerHTML = `
46
- <div class="mailx-modal-title">
47
- <span class="mailx-modal-title-text">Calendar</span>
48
- <button type="button" class="mailx-modal-close" id="cal-close" title="Close (Esc)" aria-label="Close">&times;</button>
49
- </div>
50
- <div class="cal-grid">
51
- <div class="cal-month" id="cal-month"></div>
52
- <div class="cal-upcoming">
53
- <div class="cal-section-title">Upcoming</div>
54
- <div id="cal-events"></div>
55
- <button type="button" class="mailx-modal-btn mailx-modal-btn-primary" id="cal-new" style="margin-top:12px;">+ New event</button>
56
- </div>
57
- </div>
58
- <div class="mailx-modal-buttons">
59
- <span class="mailx-modal-spacer"></span>
60
- <span class="cal-source-note">Local-only · Google Calendar sync pending</span>
61
- <button type="button" class="mailx-modal-btn" data-action="close">Close</button>
62
- </div>`;
63
- backdrop.appendChild(panel);
64
- document.body.appendChild(backdrop);
65
-
66
- const monthEl = panel.querySelector<HTMLElement>("#cal-month")!;
67
- const eventsEl = panel.querySelector<HTMLElement>("#cal-events")!;
68
-
69
- let viewYear = new Date().getFullYear();
70
- let viewMonth = new Date().getMonth();
71
- let selectedDay = new Date();
72
- let events = loadEvents();
73
-
74
- const renderMonth = () => {
75
- const first = new Date(viewYear, viewMonth, 1);
76
- const lastDay = new Date(viewYear, viewMonth + 1, 0).getDate();
77
- const firstWeekday = first.getDay();
78
- const monthName = first.toLocaleDateString(undefined, { month: "long", year: "numeric" });
79
- const today = new Date();
80
- const isToday = (y: number, m: number, d: number) =>
81
- y === today.getFullYear() && m === today.getMonth() && d === today.getDate();
82
- const eventsByDay = new Map<string, CalEvent[]>();
83
- for (const e of events) {
84
- const d = new Date(e.start);
85
- const k = `${d.getFullYear()}-${d.getMonth()}-${d.getDate()}`;
86
- const arr = eventsByDay.get(k) || [];
87
- arr.push(e);
88
- eventsByDay.set(k, arr);
89
- }
90
- let html = `
91
- <div class="cal-nav">
92
- <button type="button" class="cal-nav-btn" data-nav="prev">‹</button>
93
- <span class="cal-nav-title">${monthName}</span>
94
- <button type="button" class="cal-nav-btn" data-nav="today">Today</button>
95
- <button type="button" class="cal-nav-btn" data-nav="next">›</button>
96
- </div>
97
- <div class="cal-month-grid">
98
- ${["S","M","T","W","T","F","S"].map(d => `<span class="cal-dow">${d}</span>`).join("")}`;
99
- for (let i = 0; i < firstWeekday; i++) html += `<span class="cal-day cal-day-blank"></span>`;
100
- for (let d = 1; d <= lastDay; d++) {
101
- const k = `${viewYear}-${viewMonth}-${d}`;
102
- const hasEv = eventsByDay.has(k);
103
- const sel = selectedDay.getFullYear() === viewYear && selectedDay.getMonth() === viewMonth && selectedDay.getDate() === d;
104
- const cls = ["cal-day"];
105
- if (isToday(viewYear, viewMonth, d)) cls.push("cal-day-today");
106
- if (sel) cls.push("cal-day-selected");
107
- if (hasEv) cls.push("cal-day-has-event");
108
- html += `<button type="button" class="${cls.join(" ")}" data-day="${d}">${d}</button>`;
109
- }
110
- html += `</div>`;
111
- monthEl.innerHTML = html;
112
- monthEl.querySelectorAll<HTMLButtonElement>("[data-day]").forEach(b => {
113
- b.addEventListener("click", () => {
114
- selectedDay = new Date(viewYear, viewMonth, +b.dataset.day!);
115
- renderMonth();
116
- renderEvents();
117
- });
118
- });
119
- monthEl.querySelectorAll<HTMLButtonElement>(".cal-nav-btn").forEach(b => {
120
- b.addEventListener("click", () => {
121
- const nav = b.dataset.nav;
122
- if (nav === "prev") {
123
- if (--viewMonth < 0) { viewMonth = 11; viewYear--; }
124
- } else if (nav === "next") {
125
- if (++viewMonth > 11) { viewMonth = 0; viewYear++; }
126
- } else if (nav === "today") {
127
- const t = new Date();
128
- viewYear = t.getFullYear(); viewMonth = t.getMonth(); selectedDay = t;
129
- }
130
- renderMonth();
131
- renderEvents();
132
- });
133
- });
134
- };
135
-
136
- const renderEvents = () => {
137
- const dayStart = new Date(selectedDay.getFullYear(), selectedDay.getMonth(), selectedDay.getDate()).getTime();
138
- const horizon = dayStart + 30 * 86400_000;
139
- const upcoming = events
140
- .filter(e => e.start >= dayStart && e.start < horizon)
141
- .sort((a, b) => a.start - b.start);
142
- if (upcoming.length === 0) {
143
- eventsEl.innerHTML = `<div class="cal-empty">No events in the next 30 days from ${selectedDay.toLocaleDateString()}.</div>`;
144
- return;
145
- }
146
- const fmt = (e: CalEvent) => {
147
- const d = new Date(e.start);
148
- const date = d.toLocaleDateString(undefined, { weekday: "short", month: "short", day: "numeric" });
149
- const time = e.allDay ? "all day" : d.toLocaleTimeString(undefined, { hour: "numeric", minute: "2-digit" });
150
- return `${date} · ${time}`;
151
- };
152
- eventsEl.innerHTML = upcoming.map(e => `
153
- <div class="cal-event" data-id="${e.id}">
154
- <div class="cal-event-time">${fmt(e)}</div>
155
- <div class="cal-event-title">${escapeHtml(e.title)}</div>
156
- ${e.location ? `<div class="cal-event-loc">${escapeHtml(e.location)}</div>` : ""}
157
- <button type="button" class="cal-event-del" title="Delete">×</button>
158
- </div>`).join("");
159
- eventsEl.querySelectorAll<HTMLElement>(".cal-event").forEach(row => {
160
- row.querySelector(".cal-event-del")?.addEventListener("click", () => {
161
- const id = row.dataset.id!;
162
- events = events.filter(e => e.id !== id);
163
- saveEvents(events);
164
- renderEvents();
165
- renderMonth();
166
- });
167
- });
168
- };
169
-
170
- panel.querySelector<HTMLButtonElement>("#cal-new")?.addEventListener("click", () => {
171
- const title = prompt("Event title:");
172
- if (!title) return;
173
- const dateStr = prompt(
174
- "Date and time (YYYY-MM-DD HH:MM, or YYYY-MM-DD for all-day):",
175
- // Local date components — toISOString() is the UTC date, which
176
- // pre-fills the wrong day for users east of UTC.
177
- `${selectedDay.getFullYear()}-${String(selectedDay.getMonth() + 1).padStart(2, "0")}-${String(selectedDay.getDate()).padStart(2, "0")} 09:00`
178
- );
179
- if (!dateStr) return;
180
- const allDay = !/\d{1,2}:\d{2}/.test(dateStr);
181
- const start = Date.parse(dateStr.replace(" ", "T"));
182
- if (isNaN(start)) { alert("Couldn't parse that date."); return; }
183
- const ev: CalEvent = {
184
- id: `cal-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`,
185
- title, start, end: start + (allDay ? 86400_000 : 3600_000),
186
- allDay, source: "local",
187
- };
188
- events.push(ev);
189
- saveEvents(events);
190
- renderMonth();
191
- renderEvents();
192
- });
193
-
194
- const close = () => {
195
- backdrop.remove();
196
- document.removeEventListener("keydown", onKey, true);
197
- isOpen = false;
198
- };
199
- const onKey = (e: KeyboardEvent) => {
200
- if (e.key === "Escape") { e.stopPropagation(); e.preventDefault(); close(); }
201
- };
202
- document.addEventListener("keydown", onKey, true);
203
- panel.querySelector<HTMLButtonElement>("#cal-close")!.addEventListener("click", close);
204
- panel.querySelector<HTMLButtonElement>('[data-action="close"]')!.addEventListener("click", close);
205
- backdrop.addEventListener("mousedown", (e) => { if (e.target === backdrop) close(); });
206
-
207
- renderMonth();
208
- renderEvents();
209
- }
210
-
211
- function escapeHtml(s: string): string {
212
- return s.replace(/[&<>"']/g, c => ({ "&": "&amp;", "<": "&lt;", ">": "&gt;", "\"": "&quot;", "'": "&#39;" }[c]!));
213
- }
@@ -1,261 +0,0 @@
1
- /**
2
- * Tasks pane — goal is "better than Thunderbird" on tasks.
3
- *
4
- * Phase-1 features (this commit):
5
- * - Local-only task store with priority, due-date, snooze, tags, notes
6
- * - Inline edit, drag-to-reorder by priority, mark complete with strikethrough
7
- * - Filter by status (active/completed/all), tag, due-soon
8
- * - "Snooze until" (defer-to-date) — Thunderbird Lightning has nothing here
9
- * - Quick add from email subject (composeInit-style, hooked from message viewer
10
- * right-click later)
11
- *
12
- * Phase-2 (later):
13
- * - Google Tasks sync (oauthsupport scope ready)
14
- * - CalDAV VTODO interop
15
- * - Task-from-email contextmenu
16
- * - Reminders that share the calendar/mail alarm subsystem
17
- */
18
- const STORE_KEY = "mailx-tasks-v1";
19
- let isOpen = false;
20
- function loadTasks() {
21
- try {
22
- const raw = localStorage.getItem(STORE_KEY);
23
- if (!raw)
24
- return [];
25
- const arr = JSON.parse(raw);
26
- return Array.isArray(arr) ? arr : [];
27
- }
28
- catch {
29
- return [];
30
- }
31
- }
32
- function saveTasks(tasks) {
33
- try {
34
- localStorage.setItem(STORE_KEY, JSON.stringify(tasks));
35
- }
36
- catch { /* */ }
37
- }
38
- export async function openTasks() {
39
- if (isOpen)
40
- return;
41
- isOpen = true;
42
- const backdrop = document.createElement("div");
43
- backdrop.className = "mailx-modal-backdrop";
44
- const panel = document.createElement("div");
45
- panel.className = "mailx-modal mailx-modal-wide";
46
- panel.innerHTML = `
47
- <div class="mailx-modal-title">
48
- <span class="mailx-modal-title-text">Tasks</span>
49
- <button type="button" class="mailx-modal-close" id="tk-close" title="Close (Esc)" aria-label="Close">&times;</button>
50
- </div>
51
- <div class="tk-toolbar">
52
- <input type="text" id="tk-quickadd" class="mailx-modal-input" placeholder="Add task — Enter to commit, prefix !!=high !=med ?=low, @tag, due:YYYY-MM-DD" autocomplete="off">
53
- </div>
54
- <div class="tk-filters">
55
- <button type="button" class="tk-filter-btn" data-filter="active">Active</button>
56
- <button type="button" class="tk-filter-btn" data-filter="due-soon">Due soon</button>
57
- <button type="button" class="tk-filter-btn" data-filter="completed">Completed</button>
58
- <button type="button" class="tk-filter-btn" data-filter="all">All</button>
59
- <span class="tk-spacer"></span>
60
- <span id="tk-count" class="tk-count"></span>
61
- </div>
62
- <div class="tk-list" id="tk-list"></div>
63
- <div class="mailx-modal-buttons">
64
- <span class="mailx-modal-spacer"></span>
65
- <span class="cal-source-note">Local-only · Google Tasks sync pending</span>
66
- <button type="button" class="mailx-modal-btn" data-action="close">Close</button>
67
- </div>`;
68
- backdrop.appendChild(panel);
69
- document.body.appendChild(backdrop);
70
- const quickAdd = panel.querySelector("#tk-quickadd");
71
- const listEl = panel.querySelector("#tk-list");
72
- const countEl = panel.querySelector("#tk-count");
73
- let tasks = loadTasks();
74
- let filter = "active";
75
- const setFilter = (f) => {
76
- filter = f;
77
- panel.querySelectorAll(".tk-filter-btn").forEach(b => b.classList.toggle("tk-filter-active", b.dataset.filter === f));
78
- render();
79
- };
80
- panel.querySelectorAll(".tk-filter-btn").forEach(b => b.addEventListener("click", () => setFilter(b.dataset.filter)));
81
- setFilter("active");
82
- const parseQuickAdd = (line) => {
83
- const t = {
84
- id: `tk-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`,
85
- title: "", priority: 0, createdAt: Date.now(),
86
- };
87
- const tags = [];
88
- const words = line.split(/\s+/);
89
- const titleParts = [];
90
- for (const w of words) {
91
- if (w === "!!") {
92
- t.priority = 3;
93
- continue;
94
- }
95
- if (w === "!") {
96
- t.priority = 2;
97
- continue;
98
- }
99
- if (w === "?") {
100
- t.priority = 1;
101
- continue;
102
- }
103
- if (w.startsWith("@") && w.length > 1) {
104
- tags.push(w.slice(1));
105
- continue;
106
- }
107
- const dueMatch = w.match(/^due:(\S+)$/i);
108
- if (dueMatch) {
109
- const parsed = Date.parse(dueMatch[1]);
110
- if (!isNaN(parsed))
111
- t.due = parsed;
112
- continue;
113
- }
114
- titleParts.push(w);
115
- }
116
- t.title = titleParts.join(" ").trim();
117
- if (tags.length)
118
- t.tags = tags;
119
- return t;
120
- };
121
- quickAdd.addEventListener("keydown", (e) => {
122
- if (e.key !== "Enter")
123
- return;
124
- const v = quickAdd.value.trim();
125
- if (!v)
126
- return;
127
- const t = parseQuickAdd(v);
128
- if (!t.title) {
129
- alert("Task needs a title.");
130
- return;
131
- }
132
- tasks.push(t);
133
- saveTasks(tasks);
134
- quickAdd.value = "";
135
- render();
136
- });
137
- const render = () => {
138
- const now = Date.now();
139
- let visible = tasks.slice();
140
- if (filter === "active")
141
- visible = visible.filter(t => !t.completed && (!t.snoozeUntil || t.snoozeUntil <= now));
142
- else if (filter === "completed")
143
- visible = visible.filter(t => !!t.completed);
144
- else if (filter === "due-soon")
145
- visible = visible.filter(t => !t.completed && t.due && t.due <= now + 7 * 86400_000);
146
- // Sort: priority desc, then due asc (none last), then created asc.
147
- visible.sort((a, b) => {
148
- if ((b.priority || 0) !== (a.priority || 0))
149
- return (b.priority || 0) - (a.priority || 0);
150
- const ad = a.due || Number.MAX_SAFE_INTEGER;
151
- const bd = b.due || Number.MAX_SAFE_INTEGER;
152
- if (ad !== bd)
153
- return ad - bd;
154
- return a.createdAt - b.createdAt;
155
- });
156
- countEl.textContent = `${visible.length} of ${tasks.length}`;
157
- if (visible.length === 0) {
158
- listEl.innerHTML = `<div class="tk-empty">Nothing matches the ${filter} filter.</div>`;
159
- return;
160
- }
161
- const dueLabel = (ms) => {
162
- if (!ms)
163
- return "";
164
- const d = new Date(ms);
165
- const today = new Date();
166
- today.setHours(0, 0, 0, 0);
167
- const dt = new Date(ms);
168
- dt.setHours(0, 0, 0, 0);
169
- const days = Math.round((dt.getTime() - today.getTime()) / 86400_000);
170
- if (days < 0)
171
- return `${-days}d overdue`;
172
- if (days === 0)
173
- return "today";
174
- if (days === 1)
175
- return "tomorrow";
176
- if (days < 7)
177
- return `${days}d`;
178
- return d.toLocaleDateString();
179
- };
180
- const prioLabel = (p) => p === 3 ? "‼" : p === 2 ? "!" : p === 1 ? "·" : "";
181
- listEl.innerHTML = visible.map(t => `
182
- <div class="tk-row${t.completed ? " tk-done" : ""}" data-id="${t.id}">
183
- <input type="checkbox" class="tk-check" ${t.completed ? "checked" : ""}>
184
- <span class="tk-prio tk-prio-${t.priority}">${prioLabel(t.priority)}</span>
185
- <span class="tk-title" contenteditable="plaintext-only">${escapeHtml(t.title)}</span>
186
- ${t.tags?.length ? `<span class="tk-tags">${t.tags.map(x => `#${escapeHtml(x)}`).join(" ")}</span>` : ""}
187
- <span class="tk-due${t.due && t.due < now && !t.completed ? " tk-overdue" : ""}">${dueLabel(t.due)}</span>
188
- <button type="button" class="tk-snooze" title="Snooze 1d / 1w (right-click)">⏰</button>
189
- <button type="button" class="tk-del" title="Delete">×</button>
190
- </div>`).join("");
191
- listEl.querySelectorAll(".tk-row").forEach(row => {
192
- const id = row.dataset.id;
193
- const t = tasks.find(x => x.id === id);
194
- row.querySelector(".tk-check").addEventListener("change", (e) => {
195
- const ck = e.target;
196
- t.completed = ck.checked ? Date.now() : undefined;
197
- saveTasks(tasks);
198
- render();
199
- });
200
- row.querySelector(".tk-del").addEventListener("click", () => {
201
- if (!confirm(`Delete task "${t.title}"?`))
202
- return;
203
- tasks = tasks.filter(x => x.id !== id);
204
- saveTasks(tasks);
205
- render();
206
- });
207
- row.querySelector(".tk-snooze").addEventListener("click", () => {
208
- t.snoozeUntil = Date.now() + 86400_000; // 1d
209
- saveTasks(tasks);
210
- render();
211
- });
212
- row.querySelector(".tk-snooze").addEventListener("contextmenu", (e) => {
213
- e.preventDefault();
214
- t.snoozeUntil = Date.now() + 7 * 86400_000; // 1w
215
- saveTasks(tasks);
216
- render();
217
- });
218
- const titleEl = row.querySelector(".tk-title");
219
- titleEl.addEventListener("blur", () => {
220
- const v = (titleEl.textContent || "").trim();
221
- if (v && v !== t.title) {
222
- t.title = v;
223
- saveTasks(tasks);
224
- }
225
- });
226
- titleEl.addEventListener("keydown", (e) => {
227
- if (e.key === "Enter") {
228
- e.preventDefault();
229
- titleEl.blur();
230
- }
231
- });
232
- });
233
- };
234
- const close = () => {
235
- backdrop.remove();
236
- document.removeEventListener("keydown", onKey, true);
237
- isOpen = false;
238
- };
239
- // Esc always closes. Earlier guard blocked Esc when focus was in the
240
- // quickadd input, which made the panel feel stuck — user hits Esc to
241
- // dismiss and nothing happens. Blur-on-Esc before close is the right
242
- // behavior: the close handler is idempotent and the input loses focus
243
- // when the backdrop goes away anyway.
244
- const onKey = (e) => {
245
- if (e.key === "Escape") {
246
- e.stopPropagation();
247
- e.preventDefault();
248
- close();
249
- }
250
- };
251
- document.addEventListener("keydown", onKey, true);
252
- panel.querySelector("#tk-close").addEventListener("click", close);
253
- panel.querySelector('[data-action="close"]').addEventListener("click", close);
254
- backdrop.addEventListener("mousedown", (e) => { if (e.target === backdrop)
255
- close(); });
256
- quickAdd.focus();
257
- }
258
- function escapeHtml(s) {
259
- return s.replace(/[&<>"']/g, c => ({ "&": "&amp;", "<": "&lt;", ">": "&gt;", "\"": "&quot;", "'": "&#39;" }[c]));
260
- }
261
- //# sourceMappingURL=tasks.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"tasks.js","sourceRoot":"","sources":["tasks.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAcH,MAAM,SAAS,GAAG,gBAAgB,CAAC;AACnC,IAAI,MAAM,GAAG,KAAK,CAAC;AAEnB,SAAS,SAAS;IACd,IAAI,CAAC;QACD,MAAM,GAAG,GAAG,YAAY,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;QAC5C,IAAI,CAAC,GAAG;YAAE,OAAO,EAAE,CAAC;QACpB,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;QAC5B,OAAO,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC;IACzC,CAAC;IAAC,MAAM,CAAC;QAAC,OAAO,EAAE,CAAC;IAAC,CAAC;AAC1B,CAAC;AACD,SAAS,SAAS,CAAC,KAAa;IAC5B,IAAI,CAAC;QAAC,YAAY,CAAC,OAAO,CAAC,SAAS,EAAE,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC,CAAC;IAAC,CAAC;IAAC,MAAM,CAAC,CAAC,KAAK,CAAC,CAAC;AACnF,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,SAAS;IAC3B,IAAI,MAAM;QAAE,OAAO;IACnB,MAAM,GAAG,IAAI,CAAC;IAEd,MAAM,QAAQ,GAAG,QAAQ,CAAC,aAAa,CAAC,KAAK,CAAC,CAAC;IAC/C,QAAQ,CAAC,SAAS,GAAG,sBAAsB,CAAC;IAC5C,MAAM,KAAK,GAAG,QAAQ,CAAC,aAAa,CAAC,KAAK,CAAC,CAAC;IAC5C,KAAK,CAAC,SAAS,GAAG,8BAA8B,CAAC;IACjD,KAAK,CAAC,SAAS,GAAG;;;;;;;;;;;;;;;;;;;;;eAqBP,CAAC;IACZ,QAAQ,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC;IAC5B,QAAQ,CAAC,IAAI,CAAC,WAAW,CAAC,QAAQ,CAAC,CAAC;IAEpC,MAAM,QAAQ,GAAG,KAAK,CAAC,aAAa,CAAmB,cAAc,CAAE,CAAC;IACxE,MAAM,MAAM,GAAG,KAAK,CAAC,aAAa,CAAc,UAAU,CAAE,CAAC;IAC7D,MAAM,OAAO,GAAG,KAAK,CAAC,aAAa,CAAc,WAAW,CAAE,CAAC;IAE/D,IAAI,KAAK,GAAG,SAAS,EAAE,CAAC;IACxB,IAAI,MAAM,GAAgD,QAAQ,CAAC;IAEnE,MAAM,SAAS,GAAG,CAAC,CAAgB,EAAE,EAAE;QACnC,MAAM,GAAG,CAAC,CAAC;QACX,KAAK,CAAC,gBAAgB,CAAoB,gBAAgB,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CACpE,CAAC,CAAC,SAAS,CAAC,MAAM,CAAC,kBAAkB,EAAE,CAAC,CAAC,OAAO,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC;QACpE,MAAM,EAAE,CAAC;IACb,CAAC,CAAC;IACF,KAAK,CAAC,gBAAgB,CAAoB,gBAAgB,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CACpE,CAAC,CAAC,gBAAgB,CAAC,OAAO,EAAE,GAAG,EAAE,CAAC,SAAS,CAAC,CAAC,CAAC,OAAO,CAAC,MAAuB,CAAC,CAAC,CAAC,CAAC;IACrF,SAAS,CAAC,QAAQ,CAAC,CAAC;IAEpB,MAAM,aAAa,GAAG,CAAC,IAAY,EAAQ,EAAE;QACzC,MAAM,CAAC,GAAS;YACZ,EAAE,EAAE,MAAM,IAAI,CAAC,GAAG,EAAE,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE;YAChE,KAAK,EAAE,EAAE,EAAE,QAAQ,EAAE,CAAC,EAAE,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE;SAChD,CAAC;QACF,MAAM,IAAI,GAAa,EAAE,CAAC;QAC1B,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;QAChC,MAAM,UAAU,GAAa,EAAE,CAAC;QAChC,KAAK,MAAM,CAAC,IAAI,KAAK,EAAE,CAAC;YACpB,IAAI,CAAC,KAAK,IAAI,EAAE,CAAC;gBAAC,CAAC,CAAC,QAAQ,GAAG,CAAC,CAAC;gBAAC,SAAS;YAAC,CAAC;YAC7C,IAAI,CAAC,KAAK,GAAG,EAAE,CAAC;gBAAC,CAAC,CAAC,QAAQ,GAAG,CAAC,CAAC;gBAAC,SAAS;YAAC,CAAC;YAC5C,IAAI,CAAC,KAAK,GAAG,EAAE,CAAC;gBAAC,CAAC,CAAC,QAAQ,GAAG,CAAC,CAAC;gBAAC,SAAS;YAAC,CAAC;YAC5C,IAAI,CAAC,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;gBAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;gBAAC,SAAS;YAAC,CAAC;YAC3E,MAAM,QAAQ,GAAG,CAAC,CAAC,KAAK,CAAC,cAAc,CAAC,CAAC;YACzC,IAAI,QAAQ,EAAE,CAAC;gBACX,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC;gBACvC,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC;oBAAE,CAAC,CAAC,GAAG,GAAG,MAAM,CAAC;gBACnC,SAAS;YACb,CAAC;YACD,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QACvB,CAAC;QACD,CAAC,CAAC,KAAK,GAAG,UAAU,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC;QACtC,IAAI,IAAI,CAAC,MAAM;YAAE,CAAC,CAAC,IAAI,GAAG,IAAI,CAAC;QAC/B,OAAO,CAAC,CAAC;IACb,CAAC,CAAC;IAEF,QAAQ,CAAC,gBAAgB,CAAC,SAAS,EAAE,CAAC,CAAC,EAAE,EAAE;QACvC,IAAI,CAAC,CAAC,GAAG,KAAK,OAAO;YAAE,OAAO;QAC9B,MAAM,CAAC,GAAG,QAAQ,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC;QAChC,IAAI,CAAC,CAAC;YAAE,OAAO;QACf,MAAM,CAAC,GAAG,aAAa,CAAC,CAAC,CAAC,CAAC;QAC3B,IAAI,CAAC,CAAC,CAAC,KAAK,EAAE,CAAC;YAAC,KAAK,CAAC,qBAAqB,CAAC,CAAC;YAAC,OAAO;QAAC,CAAC;QACvD,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QACd,SAAS,CAAC,KAAK,CAAC,CAAC;QACjB,QAAQ,CAAC,KAAK,GAAG,EAAE,CAAC;QACpB,MAAM,EAAE,CAAC;IACb,CAAC,CAAC,CAAC;IAEH,MAAM,MAAM,GAAG,GAAG,EAAE;QAChB,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QACvB,IAAI,OAAO,GAAG,KAAK,CAAC,KAAK,EAAE,CAAC;QAC5B,IAAI,MAAM,KAAK,QAAQ;YAAE,OAAO,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,SAAS,IAAI,CAAC,CAAC,CAAC,CAAC,WAAW,IAAI,CAAC,CAAC,WAAW,IAAI,GAAG,CAAC,CAAC,CAAC;aAC5G,IAAI,MAAM,KAAK,WAAW;YAAE,OAAO,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC;aACzE,IAAI,MAAM,KAAK,UAAU;YAAE,OAAO,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,SAAS,IAAI,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC,GAAG,IAAI,GAAG,GAAG,CAAC,GAAG,SAAS,CAAC,CAAC;QACrH,mEAAmE;QACnE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE;YAClB,IAAI,CAAC,CAAC,CAAC,QAAQ,IAAI,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,QAAQ,IAAI,CAAC,CAAC;gBAAE,OAAO,CAAC,CAAC,CAAC,QAAQ,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,QAAQ,IAAI,CAAC,CAAC,CAAC;YAC1F,MAAM,EAAE,GAAG,CAAC,CAAC,GAAG,IAAI,MAAM,CAAC,gBAAgB,CAAC;YAC5C,MAAM,EAAE,GAAG,CAAC,CAAC,GAAG,IAAI,MAAM,CAAC,gBAAgB,CAAC;YAC5C,IAAI,EAAE,KAAK,EAAE;gBAAE,OAAO,EAAE,GAAG,EAAE,CAAC;YAC9B,OAAO,CAAC,CAAC,SAAS,GAAG,CAAC,CAAC,SAAS,CAAC;QACrC,CAAC,CAAC,CAAC;QACH,OAAO,CAAC,WAAW,GAAG,GAAG,OAAO,CAAC,MAAM,OAAO,KAAK,CAAC,MAAM,EAAE,CAAC;QAC7D,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACvB,MAAM,CAAC,SAAS,GAAG,6CAA6C,MAAM,gBAAgB,CAAC;YACvF,OAAO;QACX,CAAC;QACD,MAAM,QAAQ,GAAG,CAAC,EAAW,EAAU,EAAE;YACrC,IAAI,CAAC,EAAE;gBAAE,OAAO,EAAE,CAAC;YACnB,MAAM,CAAC,GAAG,IAAI,IAAI,CAAC,EAAE,CAAC,CAAC;YACvB,MAAM,KAAK,GAAG,IAAI,IAAI,EAAE,CAAC;YAAC,KAAK,CAAC,QAAQ,CAAC,CAAC,EAAC,CAAC,EAAC,CAAC,EAAC,CAAC,CAAC,CAAC;YAClD,MAAM,EAAE,GAAG,IAAI,IAAI,CAAC,EAAE,CAAC,CAAC;YAAC,EAAE,CAAC,QAAQ,CAAC,CAAC,EAAC,CAAC,EAAC,CAAC,EAAC,CAAC,CAAC,CAAC;YAC9C,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,OAAO,EAAE,GAAG,KAAK,CAAC,OAAO,EAAE,CAAC,GAAG,SAAS,CAAC,CAAC;YACtE,IAAI,IAAI,GAAG,CAAC;gBAAE,OAAO,GAAG,CAAC,IAAI,WAAW,CAAC;YACzC,IAAI,IAAI,KAAK,CAAC;gBAAE,OAAO,OAAO,CAAC;YAC/B,IAAI,IAAI,KAAK,CAAC;gBAAE,OAAO,UAAU,CAAC;YAClC,IAAI,IAAI,GAAG,CAAC;gBAAE,OAAO,GAAG,IAAI,GAAG,CAAC;YAChC,OAAO,CAAC,CAAC,kBAAkB,EAAE,CAAC;QAClC,CAAC,CAAC;QACF,MAAM,SAAS,GAAG,CAAC,CAAS,EAAU,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC;QAC5F,MAAM,CAAC,SAAS,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC;gCACZ,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,EAAE,cAAc,CAAC,CAAC,EAAE;0DACrB,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE;+CACvC,CAAC,CAAC,QAAQ,KAAK,SAAS,CAAC,CAAC,CAAC,QAAQ,CAAC;0EACT,UAAU,CAAC,CAAC,CAAC,KAAK,CAAC;kBAC3E,CAAC,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC,CAAC,yBAAyB,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,IAAI,UAAU,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE;qCACnF,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC,GAAG,GAAG,GAAG,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,EAAE,KAAK,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC;;;mBAG/F,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QACtB,MAAM,CAAC,gBAAgB,CAAc,SAAS,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE;YAC1D,MAAM,EAAE,GAAG,GAAG,CAAC,OAAO,CAAC,EAAG,CAAC;YAC3B,MAAM,CAAC,GAAG,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,CAAE,CAAC;YACxC,GAAG,CAAC,aAAa,CAAmB,WAAW,CAAE,CAAC,gBAAgB,CAAC,QAAQ,EAAE,CAAC,CAAC,EAAE,EAAE;gBAC/E,MAAM,EAAE,GAAG,CAAC,CAAC,MAA0B,CAAC;gBACxC,CAAC,CAAC,SAAS,GAAG,EAAE,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC;gBAClD,SAAS,CAAC,KAAK,CAAC,CAAC;gBAAC,MAAM,EAAE,CAAC;YAC/B,CAAC,CAAC,CAAC;YACH,GAAG,CAAC,aAAa,CAAoB,SAAS,CAAE,CAAC,gBAAgB,CAAC,OAAO,EAAE,GAAG,EAAE;gBAC5E,IAAI,CAAC,OAAO,CAAC,gBAAgB,CAAC,CAAC,KAAK,IAAI,CAAC;oBAAE,OAAO;gBAClD,KAAK,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC;gBACvC,SAAS,CAAC,KAAK,CAAC,CAAC;gBAAC,MAAM,EAAE,CAAC;YAC/B,CAAC,CAAC,CAAC;YACH,GAAG,CAAC,aAAa,CAAoB,YAAY,CAAE,CAAC,gBAAgB,CAAC,OAAO,EAAE,GAAG,EAAE;gBAC/E,CAAC,CAAC,WAAW,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,SAAS,CAAC,CAAC,KAAK;gBAC7C,SAAS,CAAC,KAAK,CAAC,CAAC;gBAAC,MAAM,EAAE,CAAC;YAC/B,CAAC,CAAC,CAAC;YACH,GAAG,CAAC,aAAa,CAAoB,YAAY,CAAE,CAAC,gBAAgB,CAAC,aAAa,EAAE,CAAC,CAAC,EAAE,EAAE;gBACtF,CAAC,CAAC,cAAc,EAAE,CAAC;gBACnB,CAAC,CAAC,WAAW,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,CAAC,GAAG,SAAS,CAAC,CAAC,KAAK;gBACjD,SAAS,CAAC,KAAK,CAAC,CAAC;gBAAC,MAAM,EAAE,CAAC;YAC/B,CAAC,CAAC,CAAC;YACH,MAAM,OAAO,GAAG,GAAG,CAAC,aAAa,CAAc,WAAW,CAAE,CAAC;YAC7D,OAAO,CAAC,gBAAgB,CAAC,MAAM,EAAE,GAAG,EAAE;gBAClC,MAAM,CAAC,GAAG,CAAC,OAAO,CAAC,WAAW,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;gBAC7C,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,KAAK,EAAE,CAAC;oBAAC,CAAC,CAAC,KAAK,GAAG,CAAC,CAAC;oBAAC,SAAS,CAAC,KAAK,CAAC,CAAC;gBAAC,CAAC;YAC9D,CAAC,CAAC,CAAC;YACH,OAAO,CAAC,gBAAgB,CAAC,SAAS,EAAE,CAAC,CAAC,EAAE,EAAE;gBACtC,IAAI,CAAC,CAAC,GAAG,KAAK,OAAO,EAAE,CAAC;oBAAC,CAAC,CAAC,cAAc,EAAE,CAAC;oBAAC,OAAO,CAAC,IAAI,EAAE,CAAC;gBAAC,CAAC;YAClE,CAAC,CAAC,CAAC;QACP,CAAC,CAAC,CAAC;IACP,CAAC,CAAC;IAEF,MAAM,KAAK,GAAG,GAAG,EAAE;QACf,QAAQ,CAAC,MAAM,EAAE,CAAC;QAClB,QAAQ,CAAC,mBAAmB,CAAC,SAAS,EAAE,KAAK,EAAE,IAAI,CAAC,CAAC;QACrD,MAAM,GAAG,KAAK,CAAC;IACnB,CAAC,CAAC;IACF,qEAAqE;IACrE,qEAAqE;IACrE,qEAAqE;IACrE,sEAAsE;IACtE,sCAAsC;IACtC,MAAM,KAAK,GAAG,CAAC,CAAgB,EAAE,EAAE;QAC/B,IAAI,CAAC,CAAC,GAAG,KAAK,QAAQ,EAAE,CAAC;YACrB,CAAC,CAAC,eAAe,EAAE,CAAC;YAAC,CAAC,CAAC,cAAc,EAAE,CAAC;YAAC,KAAK,EAAE,CAAC;QACrD,CAAC;IACL,CAAC,CAAC;IACF,QAAQ,CAAC,gBAAgB,CAAC,SAAS,EAAE,KAAK,EAAE,IAAI,CAAC,CAAC;IAClD,KAAK,CAAC,aAAa,CAAoB,WAAW,CAAE,CAAC,gBAAgB,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC;IACtF,KAAK,CAAC,aAAa,CAAoB,uBAAuB,CAAE,CAAC,gBAAgB,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC;IAClG,QAAQ,CAAC,gBAAgB,CAAC,WAAW,EAAE,CAAC,CAAC,EAAE,EAAE,GAAG,IAAI,CAAC,CAAC,MAAM,KAAK,QAAQ;QAAE,KAAK,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;IAEvF,QAAQ,CAAC,KAAK,EAAE,CAAC;AACrB,CAAC;AAED,SAAS,UAAU,CAAC,CAAS;IACzB,OAAO,CAAC,CAAC,OAAO,CAAC,UAAU,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,GAAG,EAAE,OAAO,EAAE,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,QAAQ,EAAE,GAAG,EAAE,OAAO,EAAE,CAAC,CAAC,CAAE,CAAC,CAAC,CAAC;AACtH,CAAC"}