@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,234 +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
-
19
- interface Task {
20
- id: string;
21
- title: string;
22
- notes?: string;
23
- priority: 0 | 1 | 2 | 3; // 0=none, 1=low, 2=med, 3=high
24
- due?: number; // ms epoch, 0/undefined = no due
25
- snoozeUntil?: number; // ms epoch — hide from active list until this passes
26
- tags?: string[];
27
- completed?: number; // ms epoch when marked done
28
- createdAt: number;
29
- }
30
-
31
- const STORE_KEY = "mailx-tasks-v1";
32
- let isOpen = false;
33
-
34
- function loadTasks(): Task[] {
35
- try {
36
- const raw = localStorage.getItem(STORE_KEY);
37
- if (!raw) return [];
38
- const arr = JSON.parse(raw);
39
- return Array.isArray(arr) ? arr : [];
40
- } catch { return []; }
41
- }
42
- function saveTasks(tasks: Task[]): void {
43
- try { localStorage.setItem(STORE_KEY, JSON.stringify(tasks)); } catch { /* */ }
44
- }
45
-
46
- export async function openTasks(): Promise<void> {
47
- if (isOpen) return;
48
- isOpen = true;
49
-
50
- const backdrop = document.createElement("div");
51
- backdrop.className = "mailx-modal-backdrop";
52
- const panel = document.createElement("div");
53
- panel.className = "mailx-modal mailx-modal-wide";
54
- panel.innerHTML = `
55
- <div class="mailx-modal-title">
56
- <span class="mailx-modal-title-text">Tasks</span>
57
- <button type="button" class="mailx-modal-close" id="tk-close" title="Close (Esc)" aria-label="Close">&times;</button>
58
- </div>
59
- <div class="tk-toolbar">
60
- <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">
61
- </div>
62
- <div class="tk-filters">
63
- <button type="button" class="tk-filter-btn" data-filter="active">Active</button>
64
- <button type="button" class="tk-filter-btn" data-filter="due-soon">Due soon</button>
65
- <button type="button" class="tk-filter-btn" data-filter="completed">Completed</button>
66
- <button type="button" class="tk-filter-btn" data-filter="all">All</button>
67
- <span class="tk-spacer"></span>
68
- <span id="tk-count" class="tk-count"></span>
69
- </div>
70
- <div class="tk-list" id="tk-list"></div>
71
- <div class="mailx-modal-buttons">
72
- <span class="mailx-modal-spacer"></span>
73
- <span class="cal-source-note">Local-only · Google Tasks sync pending</span>
74
- <button type="button" class="mailx-modal-btn" data-action="close">Close</button>
75
- </div>`;
76
- backdrop.appendChild(panel);
77
- document.body.appendChild(backdrop);
78
-
79
- const quickAdd = panel.querySelector<HTMLInputElement>("#tk-quickadd")!;
80
- const listEl = panel.querySelector<HTMLElement>("#tk-list")!;
81
- const countEl = panel.querySelector<HTMLElement>("#tk-count")!;
82
-
83
- let tasks = loadTasks();
84
- let filter: "active" | "due-soon" | "completed" | "all" = "active";
85
-
86
- const setFilter = (f: typeof filter) => {
87
- filter = f;
88
- panel.querySelectorAll<HTMLButtonElement>(".tk-filter-btn").forEach(b =>
89
- b.classList.toggle("tk-filter-active", b.dataset.filter === f));
90
- render();
91
- };
92
- panel.querySelectorAll<HTMLButtonElement>(".tk-filter-btn").forEach(b =>
93
- b.addEventListener("click", () => setFilter(b.dataset.filter as typeof filter)));
94
- setFilter("active");
95
-
96
- const parseQuickAdd = (line: string): Task => {
97
- const t: Task = {
98
- id: `tk-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`,
99
- title: "", priority: 0, createdAt: Date.now(),
100
- };
101
- const tags: string[] = [];
102
- const words = line.split(/\s+/);
103
- const titleParts: string[] = [];
104
- for (const w of words) {
105
- if (w === "!!") { t.priority = 3; continue; }
106
- if (w === "!") { t.priority = 2; continue; }
107
- if (w === "?") { t.priority = 1; continue; }
108
- if (w.startsWith("@") && w.length > 1) { tags.push(w.slice(1)); continue; }
109
- const dueMatch = w.match(/^due:(\S+)$/i);
110
- if (dueMatch) {
111
- const parsed = Date.parse(dueMatch[1]);
112
- if (!isNaN(parsed)) t.due = parsed;
113
- continue;
114
- }
115
- titleParts.push(w);
116
- }
117
- t.title = titleParts.join(" ").trim();
118
- if (tags.length) t.tags = tags;
119
- return t;
120
- };
121
-
122
- quickAdd.addEventListener("keydown", (e) => {
123
- if (e.key !== "Enter") return;
124
- const v = quickAdd.value.trim();
125
- if (!v) return;
126
- const t = parseQuickAdd(v);
127
- if (!t.title) { alert("Task needs a title."); return; }
128
- tasks.push(t);
129
- saveTasks(tasks);
130
- quickAdd.value = "";
131
- render();
132
- });
133
-
134
- const render = () => {
135
- const now = Date.now();
136
- let visible = tasks.slice();
137
- if (filter === "active") visible = visible.filter(t => !t.completed && (!t.snoozeUntil || t.snoozeUntil <= now));
138
- else if (filter === "completed") visible = visible.filter(t => !!t.completed);
139
- else if (filter === "due-soon") visible = visible.filter(t => !t.completed && t.due && t.due <= now + 7 * 86400_000);
140
- // Sort: priority desc, then due asc (none last), then created asc.
141
- visible.sort((a, b) => {
142
- if ((b.priority || 0) !== (a.priority || 0)) return (b.priority || 0) - (a.priority || 0);
143
- const ad = a.due || Number.MAX_SAFE_INTEGER;
144
- const bd = b.due || Number.MAX_SAFE_INTEGER;
145
- if (ad !== bd) return ad - bd;
146
- return a.createdAt - b.createdAt;
147
- });
148
- countEl.textContent = `${visible.length} of ${tasks.length}`;
149
- if (visible.length === 0) {
150
- listEl.innerHTML = `<div class="tk-empty">Nothing matches the ${filter} filter.</div>`;
151
- return;
152
- }
153
- const dueLabel = (ms?: number): string => {
154
- if (!ms) return "";
155
- const d = new Date(ms);
156
- const today = new Date(); today.setHours(0,0,0,0);
157
- const dt = new Date(ms); dt.setHours(0,0,0,0);
158
- const days = Math.round((dt.getTime() - today.getTime()) / 86400_000);
159
- if (days < 0) return `${-days}d overdue`;
160
- if (days === 0) return "today";
161
- if (days === 1) return "tomorrow";
162
- if (days < 7) return `${days}d`;
163
- return d.toLocaleDateString();
164
- };
165
- const prioLabel = (p: number): string => p === 3 ? "‼" : p === 2 ? "!" : p === 1 ? "·" : "";
166
- listEl.innerHTML = visible.map(t => `
167
- <div class="tk-row${t.completed ? " tk-done" : ""}" data-id="${t.id}">
168
- <input type="checkbox" class="tk-check" ${t.completed ? "checked" : ""}>
169
- <span class="tk-prio tk-prio-${t.priority}">${prioLabel(t.priority)}</span>
170
- <span class="tk-title" contenteditable="plaintext-only">${escapeHtml(t.title)}</span>
171
- ${t.tags?.length ? `<span class="tk-tags">${t.tags.map(x => `#${escapeHtml(x)}`).join(" ")}</span>` : ""}
172
- <span class="tk-due${t.due && t.due < now && !t.completed ? " tk-overdue" : ""}">${dueLabel(t.due)}</span>
173
- <button type="button" class="tk-snooze" title="Snooze 1d / 1w (right-click)">⏰</button>
174
- <button type="button" class="tk-del" title="Delete">×</button>
175
- </div>`).join("");
176
- listEl.querySelectorAll<HTMLElement>(".tk-row").forEach(row => {
177
- const id = row.dataset.id!;
178
- const t = tasks.find(x => x.id === id)!;
179
- row.querySelector<HTMLInputElement>(".tk-check")!.addEventListener("change", (e) => {
180
- const ck = e.target as HTMLInputElement;
181
- t.completed = ck.checked ? Date.now() : undefined;
182
- saveTasks(tasks); render();
183
- });
184
- row.querySelector<HTMLButtonElement>(".tk-del")!.addEventListener("click", () => {
185
- if (!confirm(`Delete task "${t.title}"?`)) return;
186
- tasks = tasks.filter(x => x.id !== id);
187
- saveTasks(tasks); render();
188
- });
189
- row.querySelector<HTMLButtonElement>(".tk-snooze")!.addEventListener("click", () => {
190
- t.snoozeUntil = Date.now() + 86400_000; // 1d
191
- saveTasks(tasks); render();
192
- });
193
- row.querySelector<HTMLButtonElement>(".tk-snooze")!.addEventListener("contextmenu", (e) => {
194
- e.preventDefault();
195
- t.snoozeUntil = Date.now() + 7 * 86400_000; // 1w
196
- saveTasks(tasks); render();
197
- });
198
- const titleEl = row.querySelector<HTMLElement>(".tk-title")!;
199
- titleEl.addEventListener("blur", () => {
200
- const v = (titleEl.textContent || "").trim();
201
- if (v && v !== t.title) { t.title = v; saveTasks(tasks); }
202
- });
203
- titleEl.addEventListener("keydown", (e) => {
204
- if (e.key === "Enter") { e.preventDefault(); titleEl.blur(); }
205
- });
206
- });
207
- };
208
-
209
- const close = () => {
210
- backdrop.remove();
211
- document.removeEventListener("keydown", onKey, true);
212
- isOpen = false;
213
- };
214
- // Esc always closes. Earlier guard blocked Esc when focus was in the
215
- // quickadd input, which made the panel feel stuck — user hits Esc to
216
- // dismiss and nothing happens. Blur-on-Esc before close is the right
217
- // behavior: the close handler is idempotent and the input loses focus
218
- // when the backdrop goes away anyway.
219
- const onKey = (e: KeyboardEvent) => {
220
- if (e.key === "Escape") {
221
- e.stopPropagation(); e.preventDefault(); close();
222
- }
223
- };
224
- document.addEventListener("keydown", onKey, true);
225
- panel.querySelector<HTMLButtonElement>("#tk-close")!.addEventListener("click", close);
226
- panel.querySelector<HTMLButtonElement>('[data-action="close"]')!.addEventListener("click", close);
227
- backdrop.addEventListener("mousedown", (e) => { if (e.target === backdrop) close(); });
228
-
229
- quickAdd.focus();
230
- }
231
-
232
- function escapeHtml(s: string): string {
233
- return s.replace(/[&<>"']/g, c => ({ "&": "&amp;", "<": "&lt;", ">": "&gt;", "\"": "&quot;", "'": "&#39;" }[c]!));
234
- }
@@ -1,10 +0,0 @@
1
- # Force LF line endings for all text files
2
- * text=auto eol=lf
3
-
4
- # Ensure these are always LF
5
- *.ts text eol=lf
6
- *.js text eol=lf
7
- *.json text eol=lf
8
- *.md text eol=lf
9
- *.yml text eol=lf
10
- *.yaml text eol=lf
@@ -1,21 +0,0 @@
1
- /**
2
- * @bobfrankston/mailx-compose
3
- * Compose message logic — builds prefilled compose data for reply/forward.
4
- * UI lives in client/compose/; this package has the shared logic.
5
- */
6
- import type { Message, EmailAddress } from "@bobfrankston/mailx-types";
7
- export type ComposeMode = "new" | "reply" | "replyAll" | "forward";
8
- /** Data passed to the compose window via query params or postMessage */
9
- export interface ComposeInit {
10
- mode: ComposeMode;
11
- accountId: string;
12
- to: EmailAddress[];
13
- cc: EmailAddress[];
14
- subject: string;
15
- bodyHtml: string;
16
- inReplyTo: string;
17
- references: string[];
18
- }
19
- /** Build compose init data from an original message and mode */
20
- export declare function buildComposeInit(mode: ComposeMode, accountId: string, original?: Message): ComposeInit;
21
- //# sourceMappingURL=index.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,YAAY,EAAkB,MAAM,2BAA2B,CAAC;AAEvF,MAAM,MAAM,WAAW,GAAG,KAAK,GAAG,OAAO,GAAG,UAAU,GAAG,SAAS,CAAC;AAEnE,wEAAwE;AACxE,MAAM,WAAW,WAAW;IACxB,IAAI,EAAE,WAAW,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,EAAE,EAAE,YAAY,EAAE,CAAC;IACnB,EAAE,EAAE,YAAY,EAAE,CAAC;IACnB,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,EAAE,CAAC;CACxB;AAED,gEAAgE;AAChE,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,WAAW,EAAE,SAAS,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,OAAO,GAAG,WAAW,CA0CtG"}
@@ -1,66 +0,0 @@
1
- /**
2
- * @bobfrankston/mailx-compose
3
- * Compose message logic — builds prefilled compose data for reply/forward.
4
- * UI lives in client/compose/; this package has the shared logic.
5
- */
6
- /** Build compose init data from an original message and mode */
7
- export function buildComposeInit(mode, accountId, original) {
8
- const init = {
9
- mode,
10
- accountId,
11
- to: [],
12
- cc: [],
13
- subject: "",
14
- bodyHtml: "",
15
- inReplyTo: "",
16
- references: [],
17
- };
18
- if (!original)
19
- return init;
20
- const rePrefix = /^(re|fwd?):\s*/i;
21
- const cleanSubject = original.subject.replace(rePrefix, "");
22
- switch (mode) {
23
- case "reply":
24
- init.to = [original.from];
25
- init.subject = `Re: ${cleanSubject}`;
26
- init.bodyHtml = quoteBody(original);
27
- init.inReplyTo = original.messageId;
28
- init.references = [...original.references, original.messageId];
29
- break;
30
- case "replyAll":
31
- init.to = [original.from, ...original.to.filter(a => a.address !== original.from.address)];
32
- init.cc = original.cc || [];
33
- init.subject = `Re: ${cleanSubject}`;
34
- init.bodyHtml = quoteBody(original);
35
- init.inReplyTo = original.messageId;
36
- init.references = [...original.references, original.messageId];
37
- break;
38
- case "forward":
39
- init.subject = `Fwd: ${cleanSubject}`;
40
- init.bodyHtml = forwardBody(original);
41
- break;
42
- }
43
- return init;
44
- }
45
- // Plain-text quoting uses `white-space:pre-wrap` so original line breaks
46
- // survive but long lines still wrap to the viewport. `<pre>` (the prior
47
- // approach) was honest about line breaks but disabled wrapping entirely,
48
- // producing horizontal-scroll quotes that broke the compose layout.
49
- const PLAIN_QUOTE_STYLE = "white-space:pre-wrap;font-family:inherit;margin:0";
50
- function quoteBody(msg) {
51
- const date = new Date(msg.date).toLocaleString();
52
- const from = msg.from.name ? `${msg.from.name} <${msg.from.address}>` : msg.from.address;
53
- const body = msg.bodyHtml || `<div style="${PLAIN_QUOTE_STYLE}">${escapeHtml(msg.bodyText)}</div>`;
54
- return `<br><div class="reply"><p>On ${date}, ${escapeHtml(from)} wrote:</p><blockquote>${body}</blockquote></div>`;
55
- }
56
- function forwardBody(msg) {
57
- const date = new Date(msg.date).toLocaleString();
58
- const from = msg.from.name ? `${msg.from.name} <${msg.from.address}>` : msg.from.address;
59
- const to = msg.to.map(a => a.name ? `${a.name} <${a.address}>` : a.address).join(", ");
60
- const body = msg.bodyHtml || `<div style="${PLAIN_QUOTE_STYLE}">${escapeHtml(msg.bodyText)}</div>`;
61
- return `<br><div class="reply"><p>---------- Forwarded message ----------<br>From: ${escapeHtml(from)}<br>Date: ${date}<br>Subject: ${escapeHtml(msg.subject)}<br>To: ${escapeHtml(to)}</p>${body}</div>`;
62
- }
63
- function escapeHtml(s) {
64
- return s.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
65
- }
66
- //# sourceMappingURL=index.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["index.ts"],"names":[],"mappings":"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"}
@@ -1,91 +0,0 @@
1
- /**
2
- * @bobfrankston/mailx-compose
3
- * Compose message logic — builds prefilled compose data for reply/forward.
4
- * UI lives in client/compose/; this package has the shared logic.
5
- */
6
-
7
- import type { Message, EmailAddress, ComposeMessage } from "@bobfrankston/mailx-types";
8
-
9
- export type ComposeMode = "new" | "reply" | "replyAll" | "forward";
10
-
11
- /** Data passed to the compose window via query params or postMessage */
12
- export interface ComposeInit {
13
- mode: ComposeMode;
14
- accountId: string;
15
- to: EmailAddress[];
16
- cc: EmailAddress[];
17
- subject: string;
18
- bodyHtml: string;
19
- inReplyTo: string;
20
- references: string[];
21
- }
22
-
23
- /** Build compose init data from an original message and mode */
24
- export function buildComposeInit(mode: ComposeMode, accountId: string, original?: Message): ComposeInit {
25
- const init: ComposeInit = {
26
- mode,
27
- accountId,
28
- to: [],
29
- cc: [],
30
- subject: "",
31
- bodyHtml: "",
32
- inReplyTo: "",
33
- references: [],
34
- };
35
-
36
- if (!original) return init;
37
-
38
- const rePrefix = /^(re|fwd?):\s*/i;
39
- const cleanSubject = original.subject.replace(rePrefix, "");
40
-
41
- switch (mode) {
42
- case "reply":
43
- init.to = [original.from];
44
- init.subject = `Re: ${cleanSubject}`;
45
- init.bodyHtml = quoteBody(original);
46
- init.inReplyTo = original.messageId;
47
- init.references = [...original.references, original.messageId];
48
- break;
49
-
50
- case "replyAll":
51
- init.to = [original.from, ...original.to.filter(a => a.address !== original.from.address)];
52
- init.cc = original.cc || [];
53
- init.subject = `Re: ${cleanSubject}`;
54
- init.bodyHtml = quoteBody(original);
55
- init.inReplyTo = original.messageId;
56
- init.references = [...original.references, original.messageId];
57
- break;
58
-
59
- case "forward":
60
- init.subject = `Fwd: ${cleanSubject}`;
61
- init.bodyHtml = forwardBody(original);
62
- break;
63
- }
64
-
65
- return init;
66
- }
67
-
68
- // Plain-text quoting uses `white-space:pre-wrap` so original line breaks
69
- // survive but long lines still wrap to the viewport. `<pre>` (the prior
70
- // approach) was honest about line breaks but disabled wrapping entirely,
71
- // producing horizontal-scroll quotes that broke the compose layout.
72
- const PLAIN_QUOTE_STYLE = "white-space:pre-wrap;font-family:inherit;margin:0";
73
-
74
- function quoteBody(msg: Message): string {
75
- const date = new Date(msg.date).toLocaleString();
76
- const from = msg.from.name ? `${msg.from.name} <${msg.from.address}>` : msg.from.address;
77
- const body = msg.bodyHtml || `<div style="${PLAIN_QUOTE_STYLE}">${escapeHtml(msg.bodyText)}</div>`;
78
- return `<br><div class="reply"><p>On ${date}, ${escapeHtml(from)} wrote:</p><blockquote>${body}</blockquote></div>`;
79
- }
80
-
81
- function forwardBody(msg: Message): string {
82
- const date = new Date(msg.date).toLocaleString();
83
- const from = msg.from.name ? `${msg.from.name} <${msg.from.address}>` : msg.from.address;
84
- const to = msg.to.map(a => a.name ? `${a.name} <${a.address}>` : a.address).join(", ");
85
- const body = msg.bodyHtml || `<div style="${PLAIN_QUOTE_STYLE}">${escapeHtml(msg.bodyText)}</div>`;
86
- return `<br><div class="reply"><p>---------- Forwarded message ----------<br>From: ${escapeHtml(from)}<br>Date: ${date}<br>Subject: ${escapeHtml(msg.subject)}<br>To: ${escapeHtml(to)}</p>${body}</div>`;
87
- }
88
-
89
- function escapeHtml(s: string): string {
90
- return s.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
91
- }
@@ -1,18 +0,0 @@
1
- {
2
- "name": "@bobfrankston/mailx-compose",
3
- "version": "0.1.1",
4
- "type": "module",
5
- "main": "index.js",
6
- "types": "index.d.ts",
7
- "scripts": {
8
- "build": "tsc"
9
- },
10
- "license": "ISC",
11
- "dependencies": {
12
- "@bobfrankston/mailx-types": "file:../mailx-types"
13
- },
14
- "repository": {
15
- "type": "git",
16
- "url": "https://github.com/BobFrankston/mailx-compose.git"
17
- }
18
- }
@@ -1,9 +0,0 @@
1
- {
2
- "extends": "../../tsconfig.base.json",
3
- "compilerOptions": {
4
- "outDir": ".",
5
- "rootDir": "."
6
- },
7
- "include": ["*.ts"],
8
- "exclude": ["node_modules", "prev", "cruft", "tests"]
9
- }
@@ -1,142 +0,0 @@
1
- /**
2
- * @bobfrankston/mailx-core
3
- * Core mail functions — callable directly via IPC or wrapped by Express.
4
- * No HTTP, no Express, no WebSocket. Just plain async functions.
5
- */
6
- import { MailxDB } from "@bobfrankston/mailx-store";
7
- import { ImapManager } from "@bobfrankston/mailx-imap";
8
- import type { ComposeMessage } from "@bobfrankston/mailx-types";
9
- declare let db: MailxDB;
10
- declare let imapManager: ImapManager;
11
- export declare function onEvent(handler: (event: any) => void): void;
12
- export declare function initialize(transportFactory?: any): Promise<void>;
13
- export declare function shutdown(): Promise<void>;
14
- export declare function getAccounts(): {
15
- id: string;
16
- name: string;
17
- email: string;
18
- lastSync: number;
19
- }[];
20
- export declare function getFolders(params: {
21
- accountId: string;
22
- }): import("@bobfrankston/mailx-types").Folder[];
23
- export declare function getMessages(params: {
24
- accountId: string;
25
- folderId: number;
26
- page?: number;
27
- pageSize?: number;
28
- sort?: string;
29
- sortDir?: string;
30
- search?: string;
31
- flaggedOnly?: boolean;
32
- }): import("@bobfrankston/mailx-types").PagedResult<import("@bobfrankston/mailx-types").MessageEnvelope>;
33
- export declare function getUnifiedInbox(params: {
34
- page?: number;
35
- pageSize?: number;
36
- }): import("@bobfrankston/mailx-types").PagedResult<import("@bobfrankston/mailx-types").MessageEnvelope>;
37
- export declare function getMessage(params: {
38
- accountId: string;
39
- uid: number;
40
- allowRemote?: boolean;
41
- folderId?: number;
42
- }): Promise<{
43
- bodyHtml: string;
44
- bodyText: string;
45
- hasRemoteContent: boolean;
46
- remoteAllowed: boolean;
47
- attachments: any[];
48
- deliveredTo: string;
49
- returnPath: string;
50
- listUnsubscribe: string;
51
- listUnsubscribeMail: string;
52
- listUnsubscribeHttp: string;
53
- listUnsubscribeOneClick: boolean;
54
- emlPath: string;
55
- id: number;
56
- accountId: string;
57
- folderId: number;
58
- folderName?: string;
59
- uid: number;
60
- uuid?: string;
61
- messageId: string;
62
- inReplyTo: string;
63
- references: string[];
64
- threadId?: string;
65
- date: number;
66
- sentDate?: number;
67
- subject: string;
68
- from: import("@bobfrankston/mailx-types").EmailAddress;
69
- to: import("@bobfrankston/mailx-types").EmailAddress[];
70
- cc: import("@bobfrankston/mailx-types").EmailAddress[];
71
- flags: string[];
72
- size: number;
73
- hasAttachments: boolean;
74
- isReplied?: boolean;
75
- preview: string;
76
- bodyPath?: string;
77
- providerId?: string;
78
- pending?: boolean;
79
- }>;
80
- export declare function updateFlags(params: {
81
- accountId: string;
82
- uid: number;
83
- flags: string[];
84
- }): Promise<void>;
85
- export declare function deleteMessage(params: {
86
- accountId: string;
87
- uid: number;
88
- }): Promise<void>;
89
- export declare function undeleteMessage(params: {
90
- accountId: string;
91
- uid: number;
92
- folderId: number;
93
- }): Promise<void>;
94
- export declare function sendMessage(params: ComposeMessage): Promise<void>;
95
- export declare function saveDraft(params: {
96
- accountId: string;
97
- subject: string;
98
- bodyHtml: string;
99
- bodyText: string;
100
- to: string;
101
- cc: string;
102
- previousDraftUid?: number;
103
- }): Promise<number>;
104
- export declare function deleteDraft(params: {
105
- accountId: string;
106
- draftUid: number;
107
- }): Promise<void>;
108
- export declare function searchMessages(params: {
109
- query: string;
110
- page?: number;
111
- pageSize?: number;
112
- }): import("@bobfrankston/mailx-types").PagedResult<import("@bobfrankston/mailx-types").MessageEnvelope>;
113
- export declare function searchContacts(params: {
114
- query: string;
115
- }): {
116
- name: string;
117
- email: string;
118
- source: string;
119
- sources: string[];
120
- useCount: number;
121
- }[];
122
- export declare function syncAll(): Promise<void>;
123
- export declare function getSyncPending(): {
124
- pending: number;
125
- };
126
- export declare function allowRemoteContent(params: {
127
- type: string;
128
- value: string;
129
- }): Promise<void>;
130
- export declare function getSettings(): import("@bobfrankston/mailx-types").MailxSettings;
131
- export declare function saveSettingsData(data: any): void;
132
- export declare function rebuildSearchIndex(): number;
133
- export declare function seedContacts(): Promise<number>;
134
- export declare function syncGoogleContacts(): Promise<void>;
135
- export declare function getVersion(): {
136
- server: string;
137
- client: string;
138
- };
139
- /** Dispatch an action by name — used by IPC and Express wrapper */
140
- export declare function dispatch(action: string, params?: any): Promise<any>;
141
- export { db, imapManager };
142
- //# sourceMappingURL=index.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["index.ts"],"names":[],"mappings":"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"}