@bobfrankston/mailx 1.0.433 → 1.0.434

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.js CHANGED
@@ -1238,6 +1238,24 @@ searchInput?.addEventListener("keydown", (e) => {
1238
1238
  setTitle("mailx");
1239
1239
  }
1240
1240
  });
1241
+ // Re-run the active search when the scope dropdown or "server too" checkbox
1242
+ // flips. Without this, switching all/current/server after typing the query
1243
+ // left the old result set on screen — the controls looked like they did
1244
+ // nothing. Treat the change as `immediate=true` so the user sees the new
1245
+ // scope's results without having to retype Enter; clear any client-side
1246
+ // filter-hidden flags from the prior "current folder" path so the row set
1247
+ // resets cleanly.
1248
+ function rerunActiveSearch() {
1249
+ if (!searchInput || searchInput.value.trim() === "")
1250
+ return;
1251
+ const body = document.getElementById("ml-body");
1252
+ if (body)
1253
+ body.querySelectorAll(".filter-hidden").forEach(r => r.classList.remove("filter-hidden"));
1254
+ clearTimeout(searchTimeout);
1255
+ doSearch(true);
1256
+ }
1257
+ searchScope?.addEventListener("change", rerunActiveSearch);
1258
+ document.getElementById("search-server-too")?.addEventListener("change", rerunActiveSearch);
1241
1259
  // Message state handles move/delete — no manual event listener needed
1242
1260
  // ── Folder filter ──
1243
1261
  const ftFilterInput = document.getElementById("ft-filter-input");
@@ -160,6 +160,19 @@ function selectRange(from, to) {
160
160
  for (let i = lo; i <= hi; i++)
161
161
  rows[i].classList.add("selected");
162
162
  }
163
+ /** The row to anchor a shift-click range against. `lastClickedRow` is the
164
+ * primary anchor, but it can become a detached DOM node after a list
165
+ * re-render (folder switch, sort, search reload, paging) — `selectRange`
166
+ * would then no-op. Fall back to whichever live row is `.selected` (the
167
+ * one in the viewer) before giving up. */
168
+ function resolveShiftAnchor() {
169
+ if (lastClickedRow?.isConnected)
170
+ return lastClickedRow;
171
+ const body = document.getElementById("ml-body");
172
+ if (!body)
173
+ return null;
174
+ return body.querySelector(".ml-row.selected");
175
+ }
163
176
  const timeFmt = { hour: "2-digit", minute: "2-digit", hour12: false };
164
177
  const dateFmt = { year: "numeric", month: "short", day: "numeric", hour: "2-digit", minute: "2-digit", hour12: false };
165
178
  const dateFmtSameYear = { month: "short", day: "numeric", hour: "2-digit", minute: "2-digit", hour12: false };
@@ -789,12 +802,25 @@ function appendMessages(body, accountId, items) {
789
802
  updateBulkBar();
790
803
  return;
791
804
  }
792
- if (e.shiftKey && lastClickedRow) {
793
- clearSelection();
794
- selectRange(lastClickedRow, row);
795
- lastClickedRow = row;
796
- row.classList.remove("unread");
797
- focusMessage(msgAccountId, msg);
805
+ if (e.shiftKey) {
806
+ const anchor = resolveShiftAnchor();
807
+ if (anchor) {
808
+ clearSelection();
809
+ selectRange(anchor, row);
810
+ lastClickedRow = row;
811
+ row.classList.remove("unread");
812
+ focusMessage(msgAccountId, msg);
813
+ }
814
+ else {
815
+ // No anchor available (first click of the session, or list
816
+ // was just rebuilt with no selection). Treat as a plain
817
+ // click so the user gets visible feedback rather than a
818
+ // silent no-op.
819
+ clearSelection();
820
+ focusRow(row, msgAccountId, msg);
821
+ lastClickedRow = row;
822
+ row.classList.remove("unread");
823
+ }
798
824
  }
799
825
  else if (e.ctrlKey || e.metaKey) {
800
826
  row.classList.toggle("selected");
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bobfrankston/mailx",
3
- "version": "1.0.433",
3
+ "version": "1.0.434",
4
4
  "description": "Local-first email client with IMAP sync and standalone native app",
5
5
  "type": "module",
6
6
  "main": "bin/mailx.js",