@bobfrankston/rmfmail 1.2.100 → 1.2.101
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/TODO.md +1 -0
- package/client/app.bundle.js +27 -0
- package/client/app.bundle.js.map +2 -2
- package/client/app.js +38 -0
- package/client/app.js.map +1 -1
- package/client/app.ts +33 -0
- package/client/index.html +1 -0
- package/client/styles/components.css +50 -0
- package/docs/preferences.md +1 -0
- package/package.json +5 -5
- package/packages/mailx-settings/docs/preferences.md +1 -0
package/client/app.ts
CHANGED
|
@@ -3900,6 +3900,7 @@ function openShortcutsDialog(): void {
|
|
|
3900
3900
|
const viewBtn = document.getElementById("btn-view");
|
|
3901
3901
|
const viewDropdown = document.getElementById("view-dropdown");
|
|
3902
3902
|
const optTwoLine = document.getElementById("opt-two-line") as HTMLInputElement;
|
|
3903
|
+
const optEleanor = document.getElementById("opt-eleanor") as HTMLInputElement;
|
|
3903
3904
|
const optPreview = document.getElementById("opt-preview") as HTMLInputElement;
|
|
3904
3905
|
const optSnippet = document.getElementById("opt-snippet") as HTMLInputElement;
|
|
3905
3906
|
const optFlagStars = document.getElementById("opt-flag-stars") as HTMLInputElement;
|
|
@@ -4065,6 +4066,7 @@ document.addEventListener("keydown", (e) => {
|
|
|
4065
4066
|
|
|
4066
4067
|
// Restore saved view settings
|
|
4067
4068
|
const savedTwoLine = localStorage.getItem("mailx-two-line") === "true";
|
|
4069
|
+
const savedEleanor = localStorage.getItem("mailx-eleanor-view") === "true";
|
|
4068
4070
|
const savedPreview = localStorage.getItem("mailx-preview") !== "false"; // default true
|
|
4069
4071
|
const savedSnippet = localStorage.getItem("mailx-snippet") !== "false"; // default true
|
|
4070
4072
|
const savedFlagStars = localStorage.getItem("mailx-flag-stars") !== "false"; // default true (show)
|
|
@@ -4078,6 +4080,7 @@ const savedFlagged = false;
|
|
|
4078
4080
|
try { localStorage.removeItem("mailx-flagged"); } catch { /* private mode */ }
|
|
4079
4081
|
const savedFolderCounts = localStorage.getItem("mailx-folder-counts") === "true";
|
|
4080
4082
|
if (optTwoLine) optTwoLine.checked = savedTwoLine;
|
|
4083
|
+
if (optEleanor) optEleanor.checked = savedEleanor;
|
|
4081
4084
|
if (optPreview) optPreview.checked = savedPreview;
|
|
4082
4085
|
if (optSnippet) optSnippet.checked = savedSnippet;
|
|
4083
4086
|
if (optFlagStars) optFlagStars.checked = savedFlagStars;
|
|
@@ -4085,6 +4088,7 @@ if (optThreaded) optThreaded.checked = savedThreaded;
|
|
|
4085
4088
|
if (optFlagged) optFlagged.checked = savedFlagged;
|
|
4086
4089
|
if (optFolderCounts) optFolderCounts.checked = savedFolderCounts;
|
|
4087
4090
|
if (savedTwoLine) document.getElementById("message-list")?.classList.add("two-line");
|
|
4091
|
+
if (savedEleanor) document.getElementById("message-list")?.classList.add("eleanor-view");
|
|
4088
4092
|
if (!savedPreview) document.querySelector(".main-area")?.classList.add("no-preview");
|
|
4089
4093
|
if (!savedSnippet) document.getElementById("message-list")?.classList.add("no-snippets");
|
|
4090
4094
|
if (!savedFlagStars) document.getElementById("message-list")?.classList.add("no-empty-stars");
|
|
@@ -4282,6 +4286,35 @@ optTwoLine?.addEventListener("change", () => {
|
|
|
4282
4286
|
localStorage.setItem("mailx-two-line", String(optTwoLine.checked));
|
|
4283
4287
|
});
|
|
4284
4288
|
|
|
4289
|
+
// Eleanor view toggle — Thunderbird-classic one-line summary list
|
|
4290
|
+
// (★ | Subject | From | Date, whitespace, monochrome). Pure CSS class;
|
|
4291
|
+
// the row markup is unchanged. TODO.md: generalize into per-column view
|
|
4292
|
+
// control instead of a named preset.
|
|
4293
|
+
function applyEleanorView(on: boolean): void {
|
|
4294
|
+
document.getElementById("message-list")?.classList.toggle("eleanor-view", on);
|
|
4295
|
+
if (optEleanor) optEleanor.checked = on;
|
|
4296
|
+
try { localStorage.setItem("mailx-eleanor-view", String(on)); } catch { /* private mode */ }
|
|
4297
|
+
}
|
|
4298
|
+
optEleanor?.addEventListener("change", () => {
|
|
4299
|
+
applyEleanorView(optEleanor.checked);
|
|
4300
|
+
// Mirror to preferences.jsonc (ui.eleanorView) so the choice follows the
|
|
4301
|
+
// shared config across machines; localStorage stays the synchronous
|
|
4302
|
+
// first-paint cache, same split as the editor setting.
|
|
4303
|
+
getSettings().then((settings: any) => {
|
|
4304
|
+
settings.ui = { ...settings.ui, eleanorView: optEleanor.checked };
|
|
4305
|
+
saveSettings(settings);
|
|
4306
|
+
}).catch(() => {});
|
|
4307
|
+
});
|
|
4308
|
+
// A ui.eleanorView value in preferences.jsonc wins over the local cache once
|
|
4309
|
+
// it arrives — so the view can be enabled by editing the shared config file
|
|
4310
|
+
// directly, without touching the View menu on that machine.
|
|
4311
|
+
getSettings().then((s: any) => {
|
|
4312
|
+
const pref = s.ui?.eleanorView;
|
|
4313
|
+
if (typeof pref === "boolean" && pref !== (localStorage.getItem("mailx-eleanor-view") === "true")) {
|
|
4314
|
+
applyEleanorView(pref);
|
|
4315
|
+
}
|
|
4316
|
+
}).catch(() => { /* offline boot — keep the localStorage value */ });
|
|
4317
|
+
|
|
4285
4318
|
// Preview pane toggle
|
|
4286
4319
|
optPreview?.addEventListener("change", () => {
|
|
4287
4320
|
const main = document.querySelector(".main-area");
|
package/client/index.html
CHANGED
|
@@ -717,6 +717,7 @@
|
|
|
717
717
|
<button class="tb-btn" id="btn-view">View</button>
|
|
718
718
|
<div class="tb-menu-dropdown" id="view-dropdown" hidden>
|
|
719
719
|
<label class="tb-menu-item" title="Stack From + Subject on two lines per row, date to the right — denser on narrow windows"><input type="checkbox" id="opt-two-line"> Two-line view</label>
|
|
720
|
+
<label class="tb-menu-item" title="Thunderbird-classic summary list: one line per message — ★, Subject, From, Date — extra whitespace, no row tinting"><input type="checkbox" id="opt-eleanor"> Eleanor view</label>
|
|
720
721
|
<label class="tb-menu-item" title="Show the reading pane to the right of the message list"><input type="checkbox" id="opt-preview" checked> Preview pane</label>
|
|
721
722
|
<label class="tb-menu-item" title="Show a short body-text preview (first ~80 chars) beneath each row's subject"><input type="checkbox" id="opt-snippet" checked> Preview snippets</label>
|
|
722
723
|
<label class="tb-menu-item" title="Show the grey ☆ on every row. Uncheck to hide empty stars — flagged ★ rows keep their gold star, and a row's ☆ reappears on hover so you can still click to flag."><input type="checkbox" id="opt-flag-stars" checked> Flag stars</label>
|
|
@@ -538,6 +538,56 @@ button.tb-menu-item { background: none; border: none; color: inherit; width: 100
|
|
|
538
538
|
font-size: var(--font-size-sm);
|
|
539
539
|
}
|
|
540
540
|
|
|
541
|
+
/* ── Eleanor view ──────────────────────────────────────────────────────
|
|
542
|
+
Thunderbird-classic summary list: one line per message in table order
|
|
543
|
+
★ | Subject | From | Date — no avatar, no snippet, no row tinting,
|
|
544
|
+
generous row padding. Named for its first user; TODO.md tracks
|
|
545
|
+
generalizing it into proper per-column view control.
|
|
546
|
+
:not(.two-line) — below 600px the ResizeObserver forces two-line,
|
|
547
|
+
which must keep winning there; a one-line table is unusable that
|
|
548
|
+
narrow anyway. The monochrome rules below apply in both cases. */
|
|
549
|
+
.message-list.eleanor-view:not(.two-line) {
|
|
550
|
+
/* flag | subject | from | date */
|
|
551
|
+
grid-template-columns: 1.7em minmax(0, 1fr) minmax(140px, 220px) auto;
|
|
552
|
+
column-gap: var(--gap-md);
|
|
553
|
+
}
|
|
554
|
+
.message-list.eleanor-view:not(.two-line) .ml-row {
|
|
555
|
+
grid-template-rows: auto;
|
|
556
|
+
padding-top: 9px;
|
|
557
|
+
padding-bottom: 9px;
|
|
558
|
+
line-height: 1.5;
|
|
559
|
+
}
|
|
560
|
+
.message-list.eleanor-view:not(.two-line) .ml-avatar { display: none; }
|
|
561
|
+
.message-list.eleanor-view:not(.two-line) .ml-flag { grid-column: 1; grid-row: 1; font-size: 1.15em; }
|
|
562
|
+
.message-list.eleanor-view:not(.two-line) .ml-subject {
|
|
563
|
+
grid-column: 2; grid-row: 1;
|
|
564
|
+
white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
|
|
565
|
+
}
|
|
566
|
+
.message-list.eleanor-view:not(.two-line) .ml-from { grid-column: 3; grid-row: 1; }
|
|
567
|
+
.message-list.eleanor-view:not(.two-line) .ml-date { grid-column: 4; grid-row: 1; padding-right: var(--gap-md); }
|
|
568
|
+
/* Sortable header follows the remapped column order. */
|
|
569
|
+
.message-list.eleanor-view:not(.two-line) .ml-col-avatar { display: none; }
|
|
570
|
+
.message-list.eleanor-view:not(.two-line) .ml-col-flag { grid-column: 1; }
|
|
571
|
+
.message-list.eleanor-view:not(.two-line) .ml-col-subject { grid-column: 2; grid-row: 1; }
|
|
572
|
+
.message-list.eleanor-view:not(.two-line) .ml-col-from { grid-column: 3; grid-row: 1; }
|
|
573
|
+
.message-list.eleanor-view:not(.two-line) .ml-col-date { grid-column: 4; grid-row: 1; }
|
|
574
|
+
/* Single clean line: no body snippet after the subject. */
|
|
575
|
+
.message-list.eleanor-view .ml-preview { display: none; }
|
|
576
|
+
/* Monochrome: unread speaks through weight alone; flagged rows keep the
|
|
577
|
+
gold ★ glyph but lose the row wash; priority loses bar + tint. The
|
|
578
|
+
selected-row background stays — that's selection, not decoration. */
|
|
579
|
+
.message-list.eleanor-view .ml-row.unread { color: var(--color-text); }
|
|
580
|
+
.message-list.eleanor-view .ml-row.flagged:not(.selected) { background: transparent; }
|
|
581
|
+
.message-list.eleanor-view .ml-row.priority:not(.selected) {
|
|
582
|
+
border-left: none;
|
|
583
|
+
padding-left: var(--gap-sm);
|
|
584
|
+
background: transparent;
|
|
585
|
+
}
|
|
586
|
+
.message-list.eleanor-view .ml-row.priority.unread .ml-from { color: inherit; }
|
|
587
|
+
/* The teal downloaded / hollow not-downloaded dot before the date is
|
|
588
|
+
coloring too — off in this view. */
|
|
589
|
+
.message-list.eleanor-view .ml-row .ml-date::before { display: none; }
|
|
590
|
+
|
|
541
591
|
.ml-row.filter-hidden { display: none; }
|
|
542
592
|
|
|
543
593
|
.ml-header {
|
package/docs/preferences.md
CHANGED
|
@@ -13,6 +13,7 @@
|
|
|
13
13
|
"ui": {
|
|
14
14
|
"theme": "system", // "system" | "light" | "dark"
|
|
15
15
|
"twoLine": false, // two-line message-list rows
|
|
16
|
+
"eleanorView": false, // one-line ★|Subject|From|Date list (Thunderbird-classic)
|
|
16
17
|
"previewPane": true,
|
|
17
18
|
"previewSnippets": true,
|
|
18
19
|
"threaded": false,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bobfrankston/rmfmail",
|
|
3
|
-
"version": "1.2.
|
|
3
|
+
"version": "1.2.101",
|
|
4
4
|
"description": "Local-first email client with IMAP sync and standalone native app",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "bin/mailx.js",
|
|
@@ -35,8 +35,8 @@
|
|
|
35
35
|
"dependencies": {
|
|
36
36
|
"@bobfrankston/iflow-direct": "^0.1.56",
|
|
37
37
|
"@bobfrankston/mailx-host": "^0.1.13",
|
|
38
|
-
"@bobfrankston/mailx-imap": "^0.1.
|
|
39
|
-
"@bobfrankston/mailx-store-web": "^0.1.
|
|
38
|
+
"@bobfrankston/mailx-imap": "^0.1.112",
|
|
39
|
+
"@bobfrankston/mailx-store-web": "^0.1.35",
|
|
40
40
|
"@bobfrankston/mailx-sync": "^0.1.27",
|
|
41
41
|
"@bobfrankston/miscinfo": "^1.0.13",
|
|
42
42
|
"@bobfrankston/msger": "^0.1.388",
|
|
@@ -113,8 +113,8 @@
|
|
|
113
113
|
"dependencies": {
|
|
114
114
|
"@bobfrankston/iflow-direct": "^0.1.56",
|
|
115
115
|
"@bobfrankston/mailx-host": "^0.1.13",
|
|
116
|
-
"@bobfrankston/mailx-imap": "^0.1.
|
|
117
|
-
"@bobfrankston/mailx-store-web": "^0.1.
|
|
116
|
+
"@bobfrankston/mailx-imap": "^0.1.112",
|
|
117
|
+
"@bobfrankston/mailx-store-web": "^0.1.35",
|
|
118
118
|
"@bobfrankston/mailx-sync": "^0.1.27",
|
|
119
119
|
"@bobfrankston/miscinfo": "^1.0.13",
|
|
120
120
|
"@bobfrankston/msger": "^0.1.388",
|
|
@@ -13,6 +13,7 @@
|
|
|
13
13
|
"ui": {
|
|
14
14
|
"theme": "system", // "system" | "light" | "dark"
|
|
15
15
|
"twoLine": false, // two-line message-list rows
|
|
16
|
+
"eleanorView": false, // one-line ★|Subject|From|Date list (Thunderbird-classic)
|
|
16
17
|
"previewPane": true,
|
|
17
18
|
"previewSnippets": true,
|
|
18
19
|
"threaded": false,
|