@bobfrankston/mailx 1.0.159 → 1.0.160

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -200,10 +200,10 @@ Under **Settings** in the toolbar:
200
200
 
201
201
  ```
202
202
  mailx Start the app (native window via IPC)
203
- mailx --server Start HTTP server mode (http://localhost:9333)
204
- mailx --no-browser Server mode without opening browser
203
+ mailx --email <addr> First-time setup with this email (skips prompt)
205
204
  mailx --verbose Show log output in terminal (default: log file only)
206
205
  mailx --import <file> Import accounts.jsonc into Google Drive
206
+ mailx --server Start HTTP server for dev/remote (http://localhost:9333)
207
207
 
208
208
  mailx -kill Kill running mailx processes + clean up WAL files
209
209
  mailx -repair Re-sync message metadata (fix garbled subjects)
package/bin/mailx.js CHANGED
@@ -35,7 +35,7 @@ const rebuildMode = hasFlag("rebuild");
35
35
  const repairMode = hasFlag("repair");
36
36
  const importMode = hasFlag("import");
37
37
  // Validate arguments
38
- const knownFlags = ["server", "no-browser", "verbose", "external", "kill", "v", "version", "setup", "add", "test", "rebuild", "repair", "native-imap", "log", "import", "email"];
38
+ const knownFlags = ["server", "no-browser", "verbose", "external", "kill", "v", "version", "setup", "add", "test", "rebuild", "repair", "native-imap", "log", "import", "email", "mail"];
39
39
  for (const arg of args) {
40
40
  const flag = arg.replace(/^--?/, "");
41
41
  if (arg.startsWith("-") && !knownFlags.includes(flag)) {
@@ -599,9 +599,11 @@ async function main() {
599
599
  if (setupMode || !hasConfig()) {
600
600
  if (!setupMode)
601
601
  console.log("No mailx configuration found.");
602
- // --email flag skips the interactive prompt
602
+ // --email (or -mail) flag skips the interactive prompt
603
603
  const emailArg = args.find(a => a.startsWith("--email="))?.split("=")[1]
604
- || (hasFlag("email") ? args[args.indexOf("--email") + 1] || args[args.indexOf("-email") + 1] : undefined);
604
+ || args.find(a => a.startsWith("-mail="))?.split("=")[1]
605
+ || (hasFlag("email") ? args[args.indexOf("--email") + 1] || args[args.indexOf("-email") + 1] : undefined)
606
+ || (hasFlag("mail") ? args[args.indexOf("--mail") + 1] || args[args.indexOf("-mail") + 1] : undefined);
605
607
  await runSetup(emailArg);
606
608
  }
607
609
  // Redirect console to log file — keep terminal clean
@@ -708,9 +710,8 @@ async function main() {
708
710
  imapManager.on("accountError", (accountId, error, hint, isOAuth) => {
709
711
  handle.send({ _event: "accountError", type: "accountError", accountId, error, hint, isOAuth });
710
712
  });
711
- // Wait for WebView2 initialization, then signal readiness
712
- await new Promise(r => setTimeout(r, 2000));
713
- handle.send({ _event: "ready", type: "ready" });
713
+ // Brief pause for WebView2 to initialize before starting IMAP (avoids stdin writes during init)
714
+ await new Promise(r => setTimeout(r, 500));
714
715
  // Register all accounts (OAuth may open browser for Gmail — event loop stays free for IPC)
715
716
  for (const account of settings.accounts) {
716
717
  if (!account.enabled)
@@ -12,9 +12,6 @@
12
12
  var _callbacks = {};
13
13
  var _callbackId = 0;
14
14
  var _eventHandlers = [];
15
- var _ready = false;
16
- var _pendingCalls = []; // buffered until server sends "ready"
17
-
18
15
  function callNode(action, params) {
19
16
  var id = String(++_callbackId);
20
17
  return new Promise(function(resolve, reject) {
@@ -24,11 +21,6 @@
24
21
  }, 120000);
25
22
  _callbacks[id] = { resolve: resolve, reject: reject, timer: timer };
26
23
  var msg = Object.assign({ _action: action, _cbid: id }, params || {});
27
- if (!_ready) {
28
- // Buffer until server is ready (early calls are lost in the pipe)
29
- _pendingCalls.push(msg);
30
- return;
31
- }
32
24
  if (window.ipc && window.ipc.postMessage) {
33
25
  window.ipc.postMessage(JSON.stringify(msg));
34
26
  } else {
@@ -39,20 +31,6 @@
39
31
  });
40
32
  }
41
33
 
42
- function flushPending() {
43
- _ready = true;
44
- var pending = _pendingCalls.splice(0);
45
- // Send diagnostic so it shows in Node.js IPC log
46
- if (window.ipc && window.ipc.postMessage) {
47
- window.ipc.postMessage(JSON.stringify({ _action: "_debug", _cbid: "0", info: "flush " + pending.length + " calls: " + pending.map(function(m) { return m._action; }).join(", ") }));
48
- }
49
- for (var i = 0; i < pending.length; i++) {
50
- if (window.ipc && window.ipc.postMessage) {
51
- window.ipc.postMessage(JSON.stringify(pending[i]));
52
- }
53
- }
54
- }
55
-
56
34
  // Called by Rust to resolve promises
57
35
  window._mailxapiResolve = function(id, value) {
58
36
  var cb = _callbacks[id];
@@ -73,11 +51,6 @@
73
51
 
74
52
  // Called by Rust to push events (new mail, sync progress, etc.)
75
53
  window._mailxapiEvent = function(event) {
76
- // "ready" signal from server — flush buffered IPC calls
77
- if (event && event.type === "ready") {
78
- flushPending();
79
- return;
80
- }
81
54
  for (var i = 0; i < _eventHandlers.length; i++) {
82
55
  try { _eventHandlers[i](event); } catch(e) { /* ignore */ }
83
56
  }
@@ -132,13 +105,47 @@
132
105
  syncAll: function() { return callNode("syncAll"); },
133
106
  getSyncPending: function() { return callNode("getSyncPending"); },
134
107
 
108
+ // Bulk operations
109
+ deleteMessages: function(accountId, uids) {
110
+ return callNode("deleteMessages", { accountId: accountId, uids: uids });
111
+ },
112
+ moveMessage: function(accountId, uid, targetFolderId, targetAccountId) {
113
+ return callNode("moveMessage", { accountId: accountId, uid: uid, targetFolderId: targetFolderId, targetAccountId: targetAccountId });
114
+ },
115
+ moveMessages: function(accountId, uids, targetFolderId) {
116
+ return callNode("moveMessages", { accountId: accountId, uids: uids, targetFolderId: targetFolderId });
117
+ },
118
+ markFolderRead: function(accountId, folderId) {
119
+ return callNode("markFolderRead", { folderId: folderId });
120
+ },
121
+ createFolder: function(accountId, parentPath, name) {
122
+ return callNode("createFolder", { accountId: accountId, parentPath: parentPath, name: name });
123
+ },
124
+ renameFolder: function(accountId, folderId, newName) {
125
+ return callNode("renameFolder", { accountId: accountId, folderId: folderId, newName: newName });
126
+ },
127
+ deleteFolder: function(accountId, folderId) {
128
+ return callNode("deleteFolder", { accountId: accountId, folderId: folderId });
129
+ },
130
+ emptyFolder: function(accountId, folderId) {
131
+ return callNode("emptyFolder", { accountId: accountId, folderId: folderId });
132
+ },
133
+
135
134
  // Settings
136
135
  allowRemoteContent: function(type, value) {
137
136
  return callNode("allowRemoteContent", { type: type, value: value });
138
137
  },
139
138
  getSettings: function() { return callNode("getSettings"); },
140
- saveSettings: function(data) { return callNode("saveSettingsData", data); },
139
+ saveSettingsData: function(data) { return callNode("saveSettingsData", data); },
141
140
  getVersion: function() { return callNode("getVersion"); },
141
+ getAutocompleteSettings: function() { return callNode("getAutocompleteSettings"); },
142
+ saveAutocompleteSettings: function(settings) { return callNode("saveAutocompleteSettings", settings); },
143
+
144
+ // Setup & Repair
145
+ setupAccount: function(name, email, password) {
146
+ return callNode("setupAccount", { name: name, email: email, password: password });
147
+ },
148
+ repairAccounts: function() { return callNode("repairAccounts"); },
142
149
 
143
150
  // Events
144
151
  onEvent: function(handler) { _eventHandlers.push(handler); },
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bobfrankston/mailx",
3
- "version": "1.0.159",
3
+ "version": "1.0.160",
4
4
  "description": "Local-first email client with IMAP sync and standalone native app",
5
5
  "type": "module",
6
6
  "main": "bin/mailx.js",
@@ -20,10 +20,10 @@
20
20
  "postinstall": "node bin/postinstall.js"
21
21
  },
22
22
  "dependencies": {
23
- "@bobfrankston/iflow": "^1.0.54",
23
+ "@bobfrankston/iflow": "^1.0.55",
24
24
  "@bobfrankston/miscinfo": "^1.0.7",
25
25
  "@bobfrankston/oauthsupport": "^1.0.20",
26
- "@bobfrankston/msger": "^0.1.209",
26
+ "@bobfrankston/msger": "^0.1.210",
27
27
  "@capacitor/android": "^8.3.0",
28
28
  "@capacitor/cli": "^8.3.0",
29
29
  "@capacitor/core": "^8.3.0",