@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/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 {
@@ -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.100",
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.111",
39
- "@bobfrankston/mailx-store-web": "^0.1.34",
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.111",
117
- "@bobfrankston/mailx-store-web": "^0.1.34",
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,