@bobfrankston/mailx 1.0.286 → 1.0.288
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 +16 -4
- package/client/components/folder-tree.js +19 -9
- package/package.json +3 -3
package/bin/mailx.js
CHANGED
|
@@ -661,9 +661,17 @@ async function runTest() {
|
|
|
661
661
|
console.log("Test complete. Check your inbox for the test message(s).");
|
|
662
662
|
process.exit(0);
|
|
663
663
|
}
|
|
664
|
-
/** Register this client on GDrive — writes/updates clients.jsonc with device info
|
|
664
|
+
/** Register this client on GDrive — writes/updates clients.jsonc with device info.
|
|
665
|
+
* Best-effort: silently skips when cloud isn't ready (fresh install, expired
|
|
666
|
+
* token). The scary "No cloud configured" banner must NOT fire for this. */
|
|
665
667
|
async function registerClient(settings) {
|
|
666
|
-
const { cloudRead, cloudWrite } = await import("@bobfrankston/mailx-settings");
|
|
668
|
+
const { cloudRead, cloudWrite, getStorageInfo } = await import("@bobfrankston/mailx-settings");
|
|
669
|
+
// Check if cloud is actually ready before attempting a write — cloudWrite
|
|
670
|
+
// calls setCloudError which pushes an error banner to the UI. We'd rather
|
|
671
|
+
// silently skip than show "No cloud configured" at startup.
|
|
672
|
+
const info = getStorageInfo();
|
|
673
|
+
if (info.mode === "local" || !info.provider || info.provider === "local")
|
|
674
|
+
return;
|
|
667
675
|
// Device ID: stable per machine, stored locally
|
|
668
676
|
const deviceIdPath = path.join(os.homedir(), ".mailx", "device-id");
|
|
669
677
|
let deviceId;
|
|
@@ -1017,8 +1025,12 @@ async function main() {
|
|
|
1017
1025
|
catch (e) {
|
|
1018
1026
|
console.error(` [name-resolve] init failed: ${e.message}`);
|
|
1019
1027
|
}
|
|
1020
|
-
// Register this client device on GDrive (fire-and-forget)
|
|
1021
|
-
|
|
1028
|
+
// Register this client device on GDrive (fire-and-forget).
|
|
1029
|
+
// Skip when no accounts — cloud isn't configured yet on fresh installs,
|
|
1030
|
+
// so the write fails with "No cloud configured" and flashes a scary banner.
|
|
1031
|
+
if (settings.accounts.length > 0) {
|
|
1032
|
+
registerClient(settings).catch(() => { });
|
|
1033
|
+
}
|
|
1022
1034
|
// Start sync in background — don't block. Kick off IDLE watchers once the
|
|
1023
1035
|
// initial sync finishes so IMAP accounts get instant-push new-mail (the
|
|
1024
1036
|
// 5-min STATUS poll is only a safety net).
|
|
@@ -449,20 +449,20 @@ async function loadFolderTree(container) {
|
|
|
449
449
|
<div id="setup-cloud-status"></div>
|
|
450
450
|
<p id="setup-form-intro">${introText}</p>
|
|
451
451
|
<form id="setup-form" style="margin-top:1rem;${formDisplay}">
|
|
452
|
-
<label style="display:block;margin-bottom:0.5rem">
|
|
453
|
-
Your name <span id="setup-name-hint" style="color:var(--color-text-muted);font-size:0.85rem">(optional — auto-detected from Google)</span>
|
|
454
|
-
<input id="setup-name" type="text" placeholder="Your Name (leave blank to use Google profile)" style="display:block;width:100%;padding:0.5rem;margin-top:0.25rem;background:var(--color-bg-surface);color:var(--color-text);border:1px solid var(--color-border);border-radius:4px">
|
|
455
|
-
</label>
|
|
456
452
|
<label style="display:block;margin-bottom:0.5rem">
|
|
457
453
|
Email address
|
|
458
454
|
<input id="setup-email" type="email" placeholder="you@gmail.com" required style="display:block;width:100%;padding:0.5rem;margin-top:0.25rem;background:var(--color-bg-surface);color:var(--color-text);border:1px solid var(--color-border);border-radius:4px">
|
|
459
455
|
</label>
|
|
460
|
-
<label id="setup-
|
|
461
|
-
|
|
456
|
+
<label id="setup-name-row" style="display:none;margin-bottom:0.5rem">
|
|
457
|
+
Your name <span style="color:var(--color-text-muted);font-size:0.85rem">(optional — auto-detected from Google)</span>
|
|
458
|
+
<input id="setup-name" type="text" placeholder="Your Name (leave blank to use Google profile)" style="display:block;width:100%;padding:0.5rem;margin-top:0.25rem;background:var(--color-bg-surface);color:var(--color-text);border:1px solid var(--color-border);border-radius:4px">
|
|
459
|
+
</label>
|
|
460
|
+
<label id="setup-password-row" style="display:none;margin-bottom:0.5rem">
|
|
461
|
+
Password
|
|
462
462
|
<input id="setup-password" type="password" placeholder="password" style="display:block;width:100%;padding:0.5rem;margin-top:0.25rem;background:var(--color-bg-surface);color:var(--color-text);border:1px solid var(--color-border);border-radius:4px">
|
|
463
463
|
<div id="setup-app-password-help" style="display:none;margin-top:0.25rem;font-size:0.8rem;color:var(--color-text-muted)"></div>
|
|
464
464
|
</label>
|
|
465
|
-
<button type="submit" style="margin-top:1rem;padding:0.5rem 2rem;background:var(--color-accent);color:#fff;border:none;border-radius:4px;cursor:pointer;font-size:1rem">Add Account</button>
|
|
465
|
+
<button id="setup-submit" type="submit" style="display:none;margin-top:1rem;padding:0.5rem 2rem;background:var(--color-accent);color:#fff;border:none;border-radius:4px;cursor:pointer;font-size:1rem">Add Account</button>
|
|
466
466
|
<div id="setup-status" style="margin-top:1rem;color:var(--color-text-muted)"></div>
|
|
467
467
|
</form>
|
|
468
468
|
<details style="margin-top:2rem;color:var(--color-text-muted)">
|
|
@@ -483,11 +483,21 @@ async function loadFolderTree(container) {
|
|
|
483
483
|
"icloud.com": "Use an app-specific password: appleid.apple.com → Sign-In and Security → App-Specific Passwords",
|
|
484
484
|
};
|
|
485
485
|
emailInput?.addEventListener("input", () => {
|
|
486
|
-
const
|
|
486
|
+
const email = emailInput.value.trim();
|
|
487
|
+
const domain = email.split("@")[1]?.toLowerCase() || "";
|
|
488
|
+
const hasAt = email.includes("@") && domain.length > 0;
|
|
487
489
|
const isOAuth = ["gmail.com", "googlemail.com", "outlook.com", "hotmail.com", "live.com"].includes(domain);
|
|
490
|
+
// Progressive reveal: email first, then name + submit,
|
|
491
|
+
// password only for non-OAuth providers.
|
|
492
|
+
const nameRow = document.getElementById("setup-name-row");
|
|
488
493
|
const pwRow = document.getElementById("setup-password-row");
|
|
494
|
+
const submitBtn = document.getElementById("setup-submit");
|
|
495
|
+
if (nameRow)
|
|
496
|
+
nameRow.style.display = hasAt ? "block" : "none";
|
|
489
497
|
if (pwRow)
|
|
490
|
-
pwRow.style.display = isOAuth ? "
|
|
498
|
+
pwRow.style.display = hasAt && !isOAuth ? "block" : "none";
|
|
499
|
+
if (submitBtn)
|
|
500
|
+
submitBtn.style.display = hasAt ? "block" : "none";
|
|
491
501
|
const helpEl = document.getElementById("setup-app-password-help");
|
|
492
502
|
if (helpEl) {
|
|
493
503
|
const help = APP_PASSWORD_HELP[domain];
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bobfrankston/mailx",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.288",
|
|
4
4
|
"description": "Local-first email client with IMAP sync and standalone native app",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "bin/mailx.js",
|
|
@@ -24,7 +24,7 @@
|
|
|
24
24
|
"@bobfrankston/iflow-node": "^0.1.7",
|
|
25
25
|
"@bobfrankston/miscinfo": "^1.0.8",
|
|
26
26
|
"@bobfrankston/oauthsupport": "^1.0.24",
|
|
27
|
-
"@bobfrankston/msger": "^0.1.
|
|
27
|
+
"@bobfrankston/msger": "^0.1.324",
|
|
28
28
|
"@capacitor/android": "^8.3.0",
|
|
29
29
|
"@capacitor/cli": "^8.3.0",
|
|
30
30
|
"@capacitor/core": "^8.3.0",
|
|
@@ -86,7 +86,7 @@
|
|
|
86
86
|
"@bobfrankston/iflow-node": "^0.1.7",
|
|
87
87
|
"@bobfrankston/miscinfo": "^1.0.8",
|
|
88
88
|
"@bobfrankston/oauthsupport": "^1.0.24",
|
|
89
|
-
"@bobfrankston/msger": "^0.1.
|
|
89
|
+
"@bobfrankston/msger": "^0.1.324",
|
|
90
90
|
"@capacitor/android": "^8.3.0",
|
|
91
91
|
"@capacitor/cli": "^8.3.0",
|
|
92
92
|
"@capacitor/core": "^8.3.0",
|