@bobfrankston/mailx 1.0.451 → 1.0.452
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/bin/mailx.js.map +1 -0
- package/bin/mailx.ts +1498 -0
- package/bin/postinstall.js.map +1 -0
- package/bin/postinstall.ts +41 -0
- package/bin/tsconfig.json +10 -0
- package/client/.gitattributes +10 -0
- package/client/app.js +51 -2
- package/client/app.js.map +1 -0
- package/client/app.ts +3112 -0
- package/client/components/address-book.js.map +1 -0
- package/client/components/address-book.ts +204 -0
- package/client/components/alarms.js.map +1 -0
- package/client/components/alarms.ts +276 -0
- package/client/components/calendar-sidebar.js.map +1 -0
- package/client/components/calendar-sidebar.ts +474 -0
- package/client/components/calendar.js.map +1 -0
- package/client/components/calendar.ts +211 -0
- package/client/components/context-menu.js.map +1 -0
- package/client/components/context-menu.ts +95 -0
- package/client/components/folder-picker.js.map +1 -0
- package/client/components/folder-picker.ts +127 -0
- package/client/components/folder-tree.js.map +1 -0
- package/client/components/folder-tree.ts +1069 -0
- package/client/components/message-list.js.map +1 -0
- package/client/components/message-list.ts +1129 -0
- package/client/components/message-viewer.js.map +1 -0
- package/client/components/message-viewer.ts +1257 -0
- package/client/components/outbox-view.js.map +1 -0
- package/client/components/outbox-view.ts +102 -0
- package/client/components/tasks.js.map +1 -0
- package/client/components/tasks.ts +234 -0
- package/client/compose/compose.js.map +1 -0
- package/client/compose/compose.ts +1231 -0
- package/client/compose/editor.js.map +1 -0
- package/client/compose/editor.ts +599 -0
- package/client/compose/ghost-text.js.map +1 -0
- package/client/compose/ghost-text.ts +140 -0
- package/client/index.html +1 -0
- package/client/lib/android-bootstrap.js.map +1 -0
- package/client/lib/android-bootstrap.ts +9 -0
- package/client/lib/api-client.js.map +1 -0
- package/client/lib/api-client.ts +439 -0
- package/client/lib/local-service.js.map +1 -0
- package/client/lib/local-service.ts +646 -0
- package/client/lib/local-store.js.map +1 -0
- package/client/lib/local-store.ts +283 -0
- package/client/lib/message-state.js.map +1 -0
- package/client/lib/message-state.ts +140 -0
- package/client/tsconfig.json +19 -0
- package/package.json +15 -15
- package/packages/mailx-api/.gitattributes +10 -0
- package/packages/mailx-api/index.d.ts.map +1 -0
- package/packages/mailx-api/index.js.map +1 -0
- package/packages/mailx-api/index.ts +283 -0
- package/packages/mailx-api/tsconfig.json +9 -0
- package/packages/mailx-compose/.gitattributes +10 -0
- package/packages/mailx-compose/index.d.ts.map +1 -0
- package/packages/mailx-compose/index.js.map +1 -0
- package/packages/mailx-compose/index.ts +85 -0
- package/packages/mailx-compose/tsconfig.json +9 -0
- package/packages/mailx-core/index.d.ts.map +1 -0
- package/packages/mailx-core/index.js.map +1 -0
- package/packages/mailx-core/index.ts +424 -0
- package/packages/mailx-core/ipc.d.ts.map +1 -0
- package/packages/mailx-core/ipc.js.map +1 -0
- package/packages/mailx-core/ipc.ts +62 -0
- package/packages/mailx-core/tsconfig.json +9 -0
- package/packages/mailx-host/.gitattributes +10 -0
- package/packages/mailx-host/index.d.ts.map +1 -0
- package/packages/mailx-host/index.js.map +1 -0
- package/packages/mailx-host/index.ts +38 -0
- package/packages/mailx-host/package.json +10 -2
- package/packages/mailx-host/tsconfig.json +9 -0
- package/packages/mailx-send/.gitattributes +10 -0
- package/packages/mailx-send/cli-queue.d.ts.map +1 -0
- package/packages/mailx-send/cli-queue.js.map +1 -0
- package/packages/mailx-send/cli-queue.ts +62 -0
- package/packages/mailx-send/cli-send.d.ts.map +1 -0
- package/packages/mailx-send/cli-send.js.map +1 -0
- package/packages/mailx-send/cli-send.ts +83 -0
- package/packages/mailx-send/cli.d.ts.map +1 -0
- package/packages/mailx-send/cli.js.map +1 -0
- package/packages/mailx-send/cli.ts +126 -0
- package/packages/mailx-send/index.d.ts.map +1 -0
- package/packages/mailx-send/index.js.map +1 -0
- package/packages/mailx-send/index.ts +333 -0
- package/packages/mailx-send/mailsend/cli.d.ts.map +1 -0
- package/packages/mailx-send/mailsend/cli.js.map +1 -0
- package/packages/mailx-send/mailsend/cli.ts +81 -0
- package/packages/mailx-send/mailsend/index.d.ts.map +1 -0
- package/packages/mailx-send/mailsend/index.js.map +1 -0
- package/packages/mailx-send/mailsend/index.ts +333 -0
- package/packages/mailx-send/mailsend/package-lock.json +65 -0
- package/packages/mailx-send/mailsend/tsconfig.json +21 -0
- package/packages/mailx-send/package-lock.json +65 -0
- package/packages/mailx-send/package.json +1 -1
- package/packages/mailx-send/tsconfig.json +21 -0
- package/packages/mailx-server/.gitattributes +10 -0
- package/packages/mailx-server/index.d.ts.map +1 -0
- package/packages/mailx-server/index.js.map +1 -0
- package/packages/mailx-server/index.ts +429 -0
- package/packages/mailx-server/tsconfig.json +9 -0
- package/packages/mailx-service/google-sync.d.ts.map +1 -0
- package/packages/mailx-service/google-sync.js.map +1 -0
- package/packages/mailx-service/google-sync.ts +238 -0
- package/packages/mailx-service/index.d.ts.map +1 -0
- package/packages/mailx-service/index.js.map +1 -0
- package/packages/mailx-service/index.ts +2461 -0
- package/packages/mailx-service/jsonrpc.d.ts.map +1 -0
- package/packages/mailx-service/jsonrpc.js.map +1 -0
- package/packages/mailx-service/jsonrpc.ts +268 -0
- package/packages/mailx-service/tsconfig.json +9 -0
- package/packages/mailx-settings/.gitattributes +10 -0
- package/packages/mailx-settings/cloud.d.ts.map +1 -0
- package/packages/mailx-settings/cloud.js.map +1 -0
- package/packages/mailx-settings/cloud.ts +388 -0
- package/packages/mailx-settings/index.d.ts.map +1 -0
- package/packages/mailx-settings/index.js.map +1 -0
- package/packages/mailx-settings/index.ts +892 -0
- package/packages/mailx-settings/tsconfig.json +9 -0
- package/packages/mailx-store/.gitattributes +10 -0
- package/packages/mailx-store/db.d.ts.map +1 -0
- package/packages/mailx-store/db.js.map +1 -0
- package/packages/mailx-store/db.ts +2007 -0
- package/packages/mailx-store/file-store.d.ts.map +1 -0
- package/packages/mailx-store/file-store.js.map +1 -0
- package/packages/mailx-store/file-store.ts +82 -0
- package/packages/mailx-store/index.d.ts.map +1 -0
- package/packages/mailx-store/index.js.map +1 -0
- package/packages/mailx-store/index.ts +7 -0
- package/packages/mailx-store/tsconfig.json +9 -0
- package/packages/mailx-store-web/android-bootstrap.d.ts.map +1 -0
- package/packages/mailx-store-web/android-bootstrap.js.map +1 -0
- package/packages/mailx-store-web/android-bootstrap.ts +1262 -0
- package/packages/mailx-store-web/db.d.ts.map +1 -0
- package/packages/mailx-store-web/db.js.map +1 -0
- package/packages/mailx-store-web/db.ts +756 -0
- package/packages/mailx-store-web/gmail-api-web.d.ts.map +1 -0
- package/packages/mailx-store-web/gmail-api-web.js.map +1 -0
- package/packages/mailx-store-web/gmail-api-web.ts +11 -0
- package/packages/mailx-store-web/imap-web-provider.d.ts.map +1 -0
- package/packages/mailx-store-web/imap-web-provider.js.map +1 -0
- package/packages/mailx-store-web/imap-web-provider.ts +156 -0
- package/packages/mailx-store-web/index.d.ts.map +1 -0
- package/packages/mailx-store-web/index.js.map +1 -0
- package/packages/mailx-store-web/index.ts +10 -0
- package/packages/mailx-store-web/main-thread-host.d.ts.map +1 -0
- package/packages/mailx-store-web/main-thread-host.js.map +1 -0
- package/packages/mailx-store-web/main-thread-host.ts +322 -0
- package/packages/mailx-store-web/package.json +4 -4
- package/packages/mailx-store-web/provider-types.d.ts.map +1 -0
- package/packages/mailx-store-web/provider-types.js.map +1 -0
- package/packages/mailx-store-web/provider-types.ts +7 -0
- package/packages/mailx-store-web/sync-manager.d.ts.map +1 -0
- package/packages/mailx-store-web/sync-manager.js.map +1 -0
- package/packages/mailx-store-web/sync-manager.ts +508 -0
- package/packages/mailx-store-web/tsconfig.json +10 -0
- package/packages/mailx-store-web/web-jsonrpc.d.ts.map +1 -0
- package/packages/mailx-store-web/web-jsonrpc.js.map +1 -0
- package/packages/mailx-store-web/web-jsonrpc.ts +116 -0
- package/packages/mailx-store-web/web-message-store.d.ts.map +1 -0
- package/packages/mailx-store-web/web-message-store.js.map +1 -0
- package/packages/mailx-store-web/web-message-store.ts +97 -0
- package/packages/mailx-store-web/web-service.d.ts.map +1 -0
- package/packages/mailx-store-web/web-service.js.map +1 -0
- package/packages/mailx-store-web/web-service.ts +616 -0
- package/packages/mailx-store-web/web-settings.d.ts.map +1 -0
- package/packages/mailx-store-web/web-settings.js.map +1 -0
- package/packages/mailx-store-web/web-settings.ts +522 -0
- package/packages/mailx-store-web/worker-entry.d.ts.map +1 -0
- package/packages/mailx-store-web/worker-entry.js.map +1 -0
- package/packages/mailx-store-web/worker-entry.ts +215 -0
- package/packages/mailx-store-web/worker-tcp-transport.d.ts.map +1 -0
- package/packages/mailx-store-web/worker-tcp-transport.js.map +1 -0
- package/packages/mailx-store-web/worker-tcp-transport.ts +101 -0
- package/packages/mailx-types/.gitattributes +10 -0
- package/packages/mailx-types/index.d.ts.map +1 -0
- package/packages/mailx-types/index.js.map +1 -0
- package/packages/mailx-types/index.ts +498 -0
- package/packages/mailx-types/tsconfig.json +9 -0
- package/tsconfig.base.json +2 -1
- package/tsconfig.json +9 -0
- package/build-apk.cmd +0 -3
- package/npmg.bat +0 -6
- package/packages/mailx-imap/index.d.ts +0 -442
- package/packages/mailx-imap/index.js +0 -3684
- package/packages/mailx-imap/package.json +0 -25
- package/packages/mailx-imap/providers/gmail-api.d.ts +0 -8
- package/packages/mailx-imap/providers/gmail-api.js +0 -8
- package/packages/mailx-imap/providers/types.d.ts +0 -9
- package/packages/mailx-imap/providers/types.js +0 -9
- package/packages/mailx-imap/tsconfig.tsbuildinfo +0 -1
- package/rebuild.cmd +0 -23
- package/tdview.cmd +0 -2
- package/temp.ps1 +0 -10
- package/test-smtp-direct.mjs +0 -4
- package/unbash.cmd +0 -55
- package/unwedge.cmd +0 -1
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Ghost text autocomplete — shows AI suggestions as translucent overlay at cursor.
|
|
3
|
+
* Tab accepts, Escape dismisses, any other key dismisses and re-triggers after debounce.
|
|
4
|
+
* Editor-agnostic: works with both Quill and tiptap via MailxEditor interface.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import type { MailxEditor } from "./editor.js";
|
|
8
|
+
import { autocomplete } from "../lib/api-client.js";
|
|
9
|
+
|
|
10
|
+
interface GhostTextContext {
|
|
11
|
+
getSubject: () => string;
|
|
12
|
+
getTo: () => string;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
let ghostEl: HTMLElement | null = null;
|
|
16
|
+
let currentSuggestion: string | null = null;
|
|
17
|
+
let debounceTimer: ReturnType<typeof setTimeout> | null = null;
|
|
18
|
+
let abortController: AbortController | null = null;
|
|
19
|
+
let activeEditor: MailxEditor | null = null;
|
|
20
|
+
let debounceMs = 600;
|
|
21
|
+
|
|
22
|
+
function dismiss(): void {
|
|
23
|
+
currentSuggestion = null;
|
|
24
|
+
if (ghostEl) {
|
|
25
|
+
ghostEl.remove();
|
|
26
|
+
ghostEl = null;
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
function positionGhost(editor: MailxEditor, text: string): void {
|
|
31
|
+
dismiss();
|
|
32
|
+
|
|
33
|
+
const sel = window.getSelection();
|
|
34
|
+
if (!sel || sel.rangeCount === 0 || !sel.isCollapsed) return;
|
|
35
|
+
|
|
36
|
+
const range = sel.getRangeAt(0);
|
|
37
|
+
let rect = range.getBoundingClientRect();
|
|
38
|
+
|
|
39
|
+
// Collapsed range may return zero-width rect — use a temp span to measure
|
|
40
|
+
if (rect.width === 0 && rect.height === 0) {
|
|
41
|
+
const span = document.createElement("span");
|
|
42
|
+
span.textContent = "\u200B"; // zero-width space
|
|
43
|
+
range.insertNode(span);
|
|
44
|
+
rect = span.getBoundingClientRect();
|
|
45
|
+
span.remove();
|
|
46
|
+
// Restore selection
|
|
47
|
+
sel.removeAllRanges();
|
|
48
|
+
sel.addRange(range);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
const container = editor.getScrollContainer();
|
|
52
|
+
const containerRect = container.getBoundingClientRect();
|
|
53
|
+
|
|
54
|
+
ghostEl = document.createElement("span");
|
|
55
|
+
ghostEl.className = "ghost-text";
|
|
56
|
+
ghostEl.textContent = text;
|
|
57
|
+
ghostEl.style.top = `${rect.top - containerRect.top + container.scrollTop}px`;
|
|
58
|
+
ghostEl.style.left = `${rect.left - containerRect.left + container.scrollLeft}px`;
|
|
59
|
+
container.appendChild(ghostEl);
|
|
60
|
+
|
|
61
|
+
currentSuggestion = text;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
function requestSuggestion(editor: MailxEditor, context: GhostTextContext): void {
|
|
65
|
+
// Cancel any in-flight request
|
|
66
|
+
if (abortController) {
|
|
67
|
+
abortController.abort();
|
|
68
|
+
abortController = null;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
const bodyText = editor.getText();
|
|
72
|
+
if (!bodyText || bodyText.trim().length < 3) return; // need at least a few characters
|
|
73
|
+
|
|
74
|
+
abortController = new AbortController();
|
|
75
|
+
const signal = abortController.signal;
|
|
76
|
+
|
|
77
|
+
autocomplete({
|
|
78
|
+
subject: context.getSubject(),
|
|
79
|
+
to: context.getTo(),
|
|
80
|
+
bodyText,
|
|
81
|
+
cursorOffset: bodyText.length,
|
|
82
|
+
}, signal).then((result: any) => {
|
|
83
|
+
if (signal.aborted) return;
|
|
84
|
+
if (result.suggestion) {
|
|
85
|
+
positionGhost(editor, result.suggestion);
|
|
86
|
+
}
|
|
87
|
+
}).catch((e: any) => {
|
|
88
|
+
if (e.name === "AbortError") return;
|
|
89
|
+
// Silently ignore autocomplete errors
|
|
90
|
+
});
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
export function initGhostText(editor: MailxEditor, context: GhostTextContext, options?: { debounceMs?: number }): void {
|
|
94
|
+
activeEditor = editor;
|
|
95
|
+
if (options?.debounceMs) debounceMs = options.debounceMs;
|
|
96
|
+
|
|
97
|
+
// Debounced content change → request suggestion
|
|
98
|
+
editor.onContentChange(() => {
|
|
99
|
+
dismiss();
|
|
100
|
+
if (debounceTimer) clearTimeout(debounceTimer);
|
|
101
|
+
debounceTimer = setTimeout(() => {
|
|
102
|
+
requestSuggestion(editor, context);
|
|
103
|
+
}, debounceMs);
|
|
104
|
+
});
|
|
105
|
+
|
|
106
|
+
// Key handler: Tab accepts, Escape dismisses
|
|
107
|
+
editor.onKeyDown((e: KeyboardEvent) => {
|
|
108
|
+
if (!currentSuggestion) return;
|
|
109
|
+
|
|
110
|
+
if (e.key === "Tab") {
|
|
111
|
+
e.preventDefault();
|
|
112
|
+
e.stopPropagation();
|
|
113
|
+
const text = currentSuggestion;
|
|
114
|
+
dismiss();
|
|
115
|
+
editor.insertTextAtCursor(text);
|
|
116
|
+
return;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
if (e.key === "Escape") {
|
|
120
|
+
e.preventDefault();
|
|
121
|
+
e.stopPropagation();
|
|
122
|
+
dismiss();
|
|
123
|
+
return;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
// Any other key: dismiss (new suggestion will come after debounce)
|
|
127
|
+
dismiss();
|
|
128
|
+
});
|
|
129
|
+
|
|
130
|
+
// Dismiss on blur/scroll
|
|
131
|
+
editor.root.addEventListener("blur", dismiss);
|
|
132
|
+
editor.getScrollContainer().addEventListener("scroll", dismiss);
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
export function destroyGhostText(): void {
|
|
136
|
+
dismiss();
|
|
137
|
+
if (debounceTimer) clearTimeout(debounceTimer);
|
|
138
|
+
if (abortController) abortController.abort();
|
|
139
|
+
activeEditor = null;
|
|
140
|
+
}
|
package/client/index.html
CHANGED
|
@@ -104,6 +104,7 @@
|
|
|
104
104
|
<button class="rail-btn" id="rail-tasks" title="Tasks" aria-label="Tasks">☑</button>
|
|
105
105
|
</div>
|
|
106
106
|
<div class="rail-bottom">
|
|
107
|
+
<button class="rail-btn" id="rail-view" title="View options" aria-label="View options">👁</button>
|
|
107
108
|
<button class="rail-btn" id="rail-settings" title="Settings" aria-label="Settings">⚙</button>
|
|
108
109
|
<button class="rail-btn" id="rail-theme" title="Toggle theme" aria-label="Toggle theme">◐</button>
|
|
109
110
|
<button class="rail-btn" id="rail-help" title="Help / About" aria-label="Help">?</button>
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"android-bootstrap.js","sourceRoot":"","sources":["android-bootstrap.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Stub — the real android bootstrap is in packages/mailx-store-web/android-bootstrap.ts.
|
|
3
|
+
* This file exists only because it was created during development. The Android HTML
|
|
4
|
+
* (client/android.html) loads the bootstrap from the package via import map.
|
|
5
|
+
*
|
|
6
|
+
* This file is excluded from the desktop build (not imported by anything).
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"api-client.js","sourceRoot":"","sources":["api-client.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,439 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* API client — all operations go through the IPC bridge (mailxapi).
|
|
3
|
+
* mailxapi is injected by the launcher (msger on desktop, MAUI on Android).
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
declare const mailxapi: any;
|
|
7
|
+
|
|
8
|
+
function getIpc(): any {
|
|
9
|
+
if (typeof mailxapi !== "undefined" && mailxapi?.isApp) return mailxapi;
|
|
10
|
+
if ((window as any).opener?.mailxapi?.isApp) return (window as any).opener.mailxapi;
|
|
11
|
+
// Compose iframe — check parent
|
|
12
|
+
if ((window as any).parent?.mailxapi?.isApp) return (window as any).parent.mailxapi;
|
|
13
|
+
return null;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
/** Build a proxy bridge that forwards every method call to the parent window
|
|
17
|
+
* via postMessage. Used when the compose iframe's own attempt to reach
|
|
18
|
+
* msger's IPC silently drops messages — empirically, `sendMessage` and
|
|
19
|
+
* `saveDraft` both hit this (user-visible: "Sending…" spinner forever;
|
|
20
|
+
* "Draft save failed: mailxapi timeout"). The main window's bridge is
|
|
21
|
+
* provably fine, so the iframe routes through it. */
|
|
22
|
+
function buildRelayBridge(): any {
|
|
23
|
+
const pending = new Map<string, { resolve: (v: any) => void; reject: (e: any) => void; timer: any }>();
|
|
24
|
+
window.addEventListener("message", (ev: MessageEvent) => {
|
|
25
|
+
if (!ev.data || ev.data.type !== "mailx-ipc-result" || !ev.data.id) return;
|
|
26
|
+
const entry = pending.get(ev.data.id);
|
|
27
|
+
if (!entry) return;
|
|
28
|
+
pending.delete(ev.data.id);
|
|
29
|
+
clearTimeout(entry.timer);
|
|
30
|
+
if (ev.data.ok) entry.resolve(ev.data.result);
|
|
31
|
+
else entry.reject(new Error(ev.data.error || "parent-relay ipc error"));
|
|
32
|
+
});
|
|
33
|
+
const call = (method: string, args: any[]): Promise<any> => {
|
|
34
|
+
const id = `ipc-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`;
|
|
35
|
+
return new Promise((resolve, reject) => {
|
|
36
|
+
const timer = setTimeout(() => {
|
|
37
|
+
pending.delete(id);
|
|
38
|
+
reject(new Error(`parent-relay timeout: ${method}`));
|
|
39
|
+
}, 120000);
|
|
40
|
+
pending.set(id, { resolve, reject, timer });
|
|
41
|
+
try {
|
|
42
|
+
(window.parent as any).postMessage({ type: "mailx-ipc", id, method, args }, "*");
|
|
43
|
+
} catch (e) {
|
|
44
|
+
clearTimeout(timer);
|
|
45
|
+
pending.delete(id);
|
|
46
|
+
reject(e);
|
|
47
|
+
}
|
|
48
|
+
});
|
|
49
|
+
};
|
|
50
|
+
// Proxy: any property access returns a function that forwards to parent.
|
|
51
|
+
// `isApp` / `platform` / other non-function reads return sensible defaults
|
|
52
|
+
// so existing getIpc-style checks still work.
|
|
53
|
+
return new Proxy({}, {
|
|
54
|
+
get(_t, prop: string) {
|
|
55
|
+
if (prop === "isApp") return true;
|
|
56
|
+
if (prop === "platform") return (window.parent as any)?.mailxapi?.platform || "webview2";
|
|
57
|
+
if (prop === "onEvent") {
|
|
58
|
+
// Event subscription can't be relayed simply — iframes that need
|
|
59
|
+
// events are rare. Fall back to direct parent bridge for onEvent
|
|
60
|
+
// since the subscription path doesn't hit the broken send path.
|
|
61
|
+
return (handler: any) => (window.parent as any)?.mailxapi?.onEvent?.(handler);
|
|
62
|
+
}
|
|
63
|
+
return (...args: any[]) => call(prop, args);
|
|
64
|
+
}
|
|
65
|
+
});
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
let cachedRelayBridge: any = null;
|
|
69
|
+
function ipc(): any {
|
|
70
|
+
// Direct bridge is fine for the top window (main mailx app). The iframe
|
|
71
|
+
// (compose) can't trust its own bridge resolution because msger-routed
|
|
72
|
+
// sendMessage / saveDraft IPCs disappear without trace. So when we're in
|
|
73
|
+
// a child frame with a parent bridge, go through the parent.
|
|
74
|
+
const inIframe = window.parent && window.parent !== window;
|
|
75
|
+
if (inIframe && (window.parent as any)?.mailxapi?.isApp) {
|
|
76
|
+
if (!cachedRelayBridge) cachedRelayBridge = buildRelayBridge();
|
|
77
|
+
return cachedRelayBridge;
|
|
78
|
+
}
|
|
79
|
+
const bridge = getIpc();
|
|
80
|
+
if (!bridge) throw new Error("IPC bridge not available");
|
|
81
|
+
return bridge;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
// ── Abort controller for message-list requests ──
|
|
85
|
+
|
|
86
|
+
let messageListAbort: AbortController | null = null;
|
|
87
|
+
|
|
88
|
+
export function abortMessageListRequests(): void {
|
|
89
|
+
if (messageListAbort) {
|
|
90
|
+
messageListAbort.abort();
|
|
91
|
+
messageListAbort = null;
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
// ── API Methods ──
|
|
96
|
+
|
|
97
|
+
export function getAccounts() {
|
|
98
|
+
return ipc().getAccounts();
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
export function getFolders(accountId: string) {
|
|
102
|
+
return ipc().getFolders(accountId);
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
export function getMessages(accountId: string, folderId: number, page = 1, pageSize = 50, flaggedOnly = false, sort?: string, sortDir?: string) {
|
|
106
|
+
abortMessageListRequests();
|
|
107
|
+
return ipc().getMessages(accountId, folderId, page, pageSize, sort, sortDir, undefined, flaggedOnly);
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
export function getUnifiedInbox(page = 1, pageSize = 50) {
|
|
111
|
+
abortMessageListRequests();
|
|
112
|
+
return ipc().getUnifiedInbox(page, pageSize);
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
export function searchMessages(query: string, page = 1, pageSize = 50, scope = "all", accountId = "", folderId = 0) {
|
|
116
|
+
return ipc().searchMessages(query, page, pageSize);
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
export function getMessage(accountId: string, uid: number, allowRemote = false, folderId?: number) {
|
|
120
|
+
return ipc().getMessage(accountId, uid, allowRemote, folderId);
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
export function updateFlags(accountId: string, uid: number, flags: string[]) {
|
|
124
|
+
return ipc().updateFlags(accountId, uid, flags);
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
export function triggerSync() {
|
|
128
|
+
return ipc().syncAll();
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
export function syncAccount(accountId: string) {
|
|
132
|
+
return ipc().syncAccount(accountId);
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
export function reauthenticate(accountId: string) {
|
|
136
|
+
return ipc().reauthenticate(accountId);
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
export function reauthGoogleScopes(): Promise<{ cleared: number }> {
|
|
140
|
+
return (ipc() as any).reauthGoogleScopes();
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
export function getSyncPending() {
|
|
144
|
+
return ipc().getSyncPending();
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
export function getDiagnostics(): Promise<any> {
|
|
148
|
+
return ipc().getDiagnostics?.() ?? Promise.resolve([]);
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
/** Account that supplies `feature` data (calendar / tasks / contacts).
|
|
152
|
+
* Resolution: per-feature primary flag → catch-all `primary` → first account.
|
|
153
|
+
* Pass e.g. "calendar" to honor `primaryCalendar:true` overrides; omit for
|
|
154
|
+
* back-compat single-flag behavior. */
|
|
155
|
+
export function getPrimaryAccount(feature?: string): Promise<any> {
|
|
156
|
+
return ipc().getPrimaryAccount?.(feature) ?? Promise.resolve(null);
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
// Calendar / Tasks: two-way cache. Reads return local-cached rows; writes
|
|
160
|
+
// commit locally and queue a push to Google. Service layer handles drain.
|
|
161
|
+
export function getCalendarEvents(fromMs: number, toMs: number): Promise<any[]> {
|
|
162
|
+
return ipc().getCalendarEvents?.(fromMs, toMs) ?? Promise.resolve([]);
|
|
163
|
+
}
|
|
164
|
+
export function createCalendarEvent(ev: {
|
|
165
|
+
title: string; startMs: number; endMs: number; allDay?: boolean;
|
|
166
|
+
location?: string; notes?: string;
|
|
167
|
+
}): Promise<{ uuid: string }> {
|
|
168
|
+
return ipc().createCalendarEvent?.(ev);
|
|
169
|
+
}
|
|
170
|
+
export function updateCalendarEvent(uuid: string, patch: any): Promise<{ ok: boolean }> {
|
|
171
|
+
return ipc().updateCalendarEvent?.(uuid, patch);
|
|
172
|
+
}
|
|
173
|
+
export function deleteCalendarEvent(uuid: string): Promise<{ ok: boolean }> {
|
|
174
|
+
return ipc().deleteCalendarEvent?.(uuid);
|
|
175
|
+
}
|
|
176
|
+
export function getTasks(includeCompleted = false): Promise<any[]> {
|
|
177
|
+
return ipc().getTasks?.(includeCompleted) ?? Promise.resolve([]);
|
|
178
|
+
}
|
|
179
|
+
export function createTask(t: { title: string; notes?: string; dueMs?: number }): Promise<{ uuid: string }> {
|
|
180
|
+
return ipc().createTask?.(t);
|
|
181
|
+
}
|
|
182
|
+
export function updateTask(uuid: string, patch: any): Promise<{ ok: boolean }> {
|
|
183
|
+
return ipc().updateTask?.(uuid, patch);
|
|
184
|
+
}
|
|
185
|
+
export function deleteTask(uuid: string): Promise<{ ok: boolean }> {
|
|
186
|
+
return ipc().deleteTask?.(uuid);
|
|
187
|
+
}
|
|
188
|
+
export function drainStoreSync(): Promise<{ ok: boolean }> {
|
|
189
|
+
return ipc().drainStoreSync?.();
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
/** Report the currently-viewed message as spam → appends a row to
|
|
193
|
+
* `~/.mailx/spam.csv`. Placeholder: no folder move, no flag change, no
|
|
194
|
+
* auto-delete. Training data for a smarter pass later. */
|
|
195
|
+
export function recordSpamReport(accountId: string, uid: number, folderId: number): Promise<{ ok: boolean }> {
|
|
196
|
+
return ipc().recordSpamReport?.(accountId, uid, folderId);
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
export function getOutboxStatus() {
|
|
200
|
+
return (ipc() as any).getOutboxStatus();
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
export function listQueuedOutgoing() {
|
|
204
|
+
return (ipc() as any).listQueuedOutgoing();
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
export function cancelQueuedOutgoing(p: string) {
|
|
208
|
+
return (ipc() as any).cancelQueuedOutgoing(p);
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
export function searchContacts(query: string) {
|
|
212
|
+
return ipc().searchContacts(query);
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
export function hasCcHistoryTo(email: string): Promise<{ hasCc: boolean }> {
|
|
216
|
+
return (ipc() as any).hasCcHistoryTo(email);
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
export function hasBccHistoryTo(email: string): Promise<{ hasBcc: boolean }> {
|
|
220
|
+
return (ipc() as any).hasBccHistoryTo(email);
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
export function listContacts(query: string, page = 1, pageSize = 100) {
|
|
224
|
+
return (ipc() as any).listContacts(query, page, pageSize);
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
export function upsertContact(name: string, email: string) {
|
|
228
|
+
return (ipc() as any).upsertContact(name, email);
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
export function deleteContact(email: string) {
|
|
232
|
+
return (ipc() as any).deleteContact(email);
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
export function addPreferredContact(entry: { name: string; email: string; source?: string; organization?: string }) {
|
|
236
|
+
return (ipc() as any).addPreferredContact(entry.name, entry.email, entry.source, entry.organization);
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
export function addToDenylist(email: string) {
|
|
240
|
+
return (ipc() as any).addToDenylist(email);
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
export function openLocalPath(which: "config" | "log") {
|
|
244
|
+
return (ipc() as any).openLocalPath(which);
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
export function allowRemoteContent(type: string, value: string) {
|
|
248
|
+
return ipc().allowRemoteContent(type, value);
|
|
249
|
+
}
|
|
250
|
+
export function flagSenderOrDomain(type: "sender" | "domain", value: string): Promise<{ flagged: boolean }> {
|
|
251
|
+
return (ipc() as any).flagSenderOrDomain?.(type, value) ?? Promise.resolve({ flagged: false });
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
export function deleteMessage(accountId: string, uid: number) {
|
|
255
|
+
return ipc().deleteMessage?.(accountId, uid);
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
export function deleteMessages(accountId: string, uids: number[]) {
|
|
259
|
+
if (uids.length === 1) return deleteMessage(accountId, uids[0]);
|
|
260
|
+
return ipc().deleteMessages?.(accountId, uids);
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
export function moveMessages(accountId: string, uids: number[], targetFolderId: number, targetAccountId?: string) {
|
|
264
|
+
if (uids.length === 1) return moveMessage(accountId, uids[0], targetFolderId, targetAccountId);
|
|
265
|
+
return ipc().moveMessages?.(accountId, uids, targetFolderId, targetAccountId);
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
export function markAsSpamMessages(accountId: string, uids: number[]): Promise<{ targetFolderId: number; moved: number }> {
|
|
269
|
+
return ipc().markAsSpamMessages?.(accountId, uids);
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
export function undeleteMessage(accountId: string, uid: number, folderId: number) {
|
|
273
|
+
return ipc().undeleteMessage?.(accountId, uid, folderId);
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
export function moveMessage(accountId: string, uid: number, targetFolderId: number, targetAccountId?: string) {
|
|
277
|
+
return ipc().moveMessage?.(accountId, uid, targetFolderId, targetAccountId);
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
export function restartServer() {
|
|
281
|
+
return ipc().restart?.();
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
export function markFolderRead(accountId: string, folderId: number) {
|
|
285
|
+
return ipc().markFolderRead?.(accountId, folderId);
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
export function createFolder(accountId: string, parentPath: string, name: string) {
|
|
289
|
+
return ipc().createFolder?.(accountId, parentPath, name);
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
export function renameFolder(accountId: string, folderId: number, newName: string) {
|
|
293
|
+
return ipc().renameFolder?.(accountId, folderId, newName);
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
export function deleteFolder(accountId: string, folderId: number) {
|
|
297
|
+
return ipc().deleteFolder?.(accountId, folderId);
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
export function emptyFolder(accountId: string, folderId: number) {
|
|
301
|
+
return ipc().emptyFolder?.(accountId, folderId);
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
/** Ship a named event to the Node log as `[client] <tag> <data>`. Fire and
|
|
305
|
+
* forget — never awaits, never throws, never blocks the caller. Tries two
|
|
306
|
+
* paths so a broken primary channel can't swallow the trace:
|
|
307
|
+
* 1. Direct bridge call (self / opener / parent mailxapi).
|
|
308
|
+
* 2. parent.postMessage fallback — the main window listens and relays.
|
|
309
|
+
* The fallback matters because the whole point of tracing is to diagnose
|
|
310
|
+
* a broken iframe bridge; a single-path tracer that goes through that same
|
|
311
|
+
* bridge is useless in exactly the case we need it. */
|
|
312
|
+
export function logClientEvent(tag: string, data?: any): void {
|
|
313
|
+
let delivered = false;
|
|
314
|
+
try {
|
|
315
|
+
const bridge = typeof (globalThis as any).mailxapi !== "undefined" && (globalThis as any).mailxapi?.isApp ? (globalThis as any).mailxapi
|
|
316
|
+
: (window as any).opener?.mailxapi?.isApp ? (window as any).opener.mailxapi
|
|
317
|
+
: (window as any).parent?.mailxapi?.isApp ? (window as any).parent.mailxapi
|
|
318
|
+
: null;
|
|
319
|
+
if (bridge?.logClientEvent) {
|
|
320
|
+
bridge.logClientEvent(tag, data);
|
|
321
|
+
delivered = true;
|
|
322
|
+
}
|
|
323
|
+
} catch { /* never throw from tracing */ }
|
|
324
|
+
try {
|
|
325
|
+
if (window.parent && window.parent !== window) {
|
|
326
|
+
(window.parent as any).postMessage({ type: "mailx-trace", tag, data, bridged: delivered }, "*");
|
|
327
|
+
}
|
|
328
|
+
} catch { /* */ }
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
export function sendMessage(body: any) {
|
|
332
|
+
return ipc().sendMessage?.(body);
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
export function saveDraft(body: any) {
|
|
336
|
+
return ipc().saveDraft?.(body);
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
// ── Events ──
|
|
340
|
+
|
|
341
|
+
type EventHandler = (event: any) => void;
|
|
342
|
+
const eventHandlers: EventHandler[] = [];
|
|
343
|
+
|
|
344
|
+
export function onEvent(handler: EventHandler): void {
|
|
345
|
+
eventHandlers.push(handler);
|
|
346
|
+
}
|
|
347
|
+
|
|
348
|
+
export function connectEvents(): void {
|
|
349
|
+
ipc().onEvent((event: any) => {
|
|
350
|
+
for (const h of eventHandlers) h(event);
|
|
351
|
+
});
|
|
352
|
+
}
|
|
353
|
+
|
|
354
|
+
// ── Autocomplete ──
|
|
355
|
+
|
|
356
|
+
export function autocomplete(body: { subject: string; to: string; bodyText: string; cursorOffset: number }, signal?: AbortSignal) {
|
|
357
|
+
return ipc().autocomplete?.(body);
|
|
358
|
+
}
|
|
359
|
+
|
|
360
|
+
export function getAutocompleteSettings() {
|
|
361
|
+
return ipc().getAutocompleteSettings?.();
|
|
362
|
+
}
|
|
363
|
+
|
|
364
|
+
export function saveAutocompleteSettings(settings: any) {
|
|
365
|
+
return ipc().saveAutocompleteSettings?.(settings);
|
|
366
|
+
}
|
|
367
|
+
|
|
368
|
+
export function getVersion() {
|
|
369
|
+
return ipc().getVersion();
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
export function getSettings() {
|
|
373
|
+
return ipc().getSettings();
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
export function saveSettings(settings: any) {
|
|
377
|
+
return ipc().saveSettingsData?.(settings);
|
|
378
|
+
}
|
|
379
|
+
|
|
380
|
+
export function repairAccounts() {
|
|
381
|
+
return ipc().repairAccounts?.();
|
|
382
|
+
}
|
|
383
|
+
|
|
384
|
+
export function deleteDraft(accountId: string, draftUid: number, draftId?: string) {
|
|
385
|
+
return ipc().deleteDraft?.(accountId, draftUid, draftId);
|
|
386
|
+
}
|
|
387
|
+
|
|
388
|
+
export function addContact(name: string, email: string) {
|
|
389
|
+
return ipc().addContact?.(name, email);
|
|
390
|
+
}
|
|
391
|
+
|
|
392
|
+
export function getThreadMessages(accountId: string, threadId: string) {
|
|
393
|
+
return ipc().getThreadMessages?.(accountId, threadId);
|
|
394
|
+
}
|
|
395
|
+
|
|
396
|
+
export function readJsoncFile(name: string): Promise<{ content: string | null }> {
|
|
397
|
+
return ipc().readJsoncFile?.(name);
|
|
398
|
+
}
|
|
399
|
+
export function writeJsoncFile(name: string, content: string): Promise<{ ok: boolean }> {
|
|
400
|
+
return ipc().writeJsoncFile?.(name, content);
|
|
401
|
+
}
|
|
402
|
+
export function formatJsonc(content: string): Promise<{ content: string }> {
|
|
403
|
+
return (ipc() as any).formatJsonc?.(content);
|
|
404
|
+
}
|
|
405
|
+
export function readConfigHelp(name: string): Promise<{ content: string }> {
|
|
406
|
+
return ipc().readConfigHelp?.(name) ?? Promise.resolve({ content: "" });
|
|
407
|
+
}
|
|
408
|
+
export function unsubscribeOneClick(url: string): Promise<{ ok: boolean; status: number; statusText: string }> {
|
|
409
|
+
return ipc().unsubscribeOneClick?.(url);
|
|
410
|
+
}
|
|
411
|
+
export function openInWord(editId: string, html: string): Promise<{ ok: boolean; path: string; opener: string }> {
|
|
412
|
+
return (ipc() as any).openInWord?.(editId, html) ?? Promise.resolve({ ok: false, path: "", opener: "none" });
|
|
413
|
+
}
|
|
414
|
+
export function closeWordEdit(editId: string): Promise<void> {
|
|
415
|
+
return (ipc() as any).closeWordEdit?.(editId) ?? Promise.resolve();
|
|
416
|
+
}
|
|
417
|
+
|
|
418
|
+
/** Run an AI text transform (translate / proofread / summarize). Returns
|
|
419
|
+
* empty `text` with a `reason` when the feature is disabled or the provider
|
|
420
|
+
* errors — caller should surface `reason` in a status bar, not throw. */
|
|
421
|
+
export function aiTransform(req: { action: "translate" | "proofread" | "summarize"; text: string; targetLang?: string }): Promise<{ text: string; reason?: string }> {
|
|
422
|
+
return ipc().aiTransform?.(req) ?? Promise.resolve({ text: "", reason: "AI not available in this host" });
|
|
423
|
+
}
|
|
424
|
+
|
|
425
|
+
export function setupAccount(name: string, email: string, password: string) {
|
|
426
|
+
return ipc().setupAccount?.(name, email, password);
|
|
427
|
+
}
|
|
428
|
+
|
|
429
|
+
export async function getAttachment(accountId: string, uid: number, attachmentId: number, folderId?: number): Promise<{ content: string; contentType: string; filename: string }> {
|
|
430
|
+
return ipc().getAttachment(accountId, uid, attachmentId, folderId);
|
|
431
|
+
}
|
|
432
|
+
|
|
433
|
+
export async function getDeviceAccounts(): Promise<{ email: string; name: string }[]> {
|
|
434
|
+
return ipc().getDeviceAccounts?.() ?? [];
|
|
435
|
+
}
|
|
436
|
+
|
|
437
|
+
// Legacy exports for backward compatibility
|
|
438
|
+
export const connectWebSocket = connectEvents;
|
|
439
|
+
export const onWsEvent = onEvent;
|