@bobfrankston/mailx 1.0.446 → 1.0.448
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/lib/message-state.js +35 -5
- package/package.json +1 -1
- package/rebuild.cmd +2 -2
- package/#build-apk.cmd.asv# +0 -4
|
@@ -27,13 +27,18 @@ function notify(change) {
|
|
|
27
27
|
catch { /* don't let one subscriber break others */ }
|
|
28
28
|
}
|
|
29
29
|
}
|
|
30
|
-
/** Replace the entire message list (folder load, search, unified inbox)
|
|
30
|
+
/** Replace the entire message list (folder load, search, unified inbox).
|
|
31
|
+
* Selection stays even when the previously-selected message isn't in
|
|
32
|
+
* the new list — that case happens whenever a periodic sync re-fetches
|
|
33
|
+
* page 1 of the unified inbox and a row the user opened earlier has
|
|
34
|
+
* scrolled off, or when the same row's accountId/uid pair changes
|
|
35
|
+
* shape after dedup. Yanking the viewer mid-read was a user-reported
|
|
36
|
+
* surprise (2026-04-30: "I was reading a message but now it just
|
|
37
|
+
* jumped to Select a message to read"). The viewer keeps the message
|
|
38
|
+
* it has; it'll only clear when the user explicitly clicks elsewhere
|
|
39
|
+
* or the message is removed via removeMessages (real delete/move). */
|
|
31
40
|
export function setMessages(msgs) {
|
|
32
41
|
messages = msgs;
|
|
33
|
-
// If the previously selected message is no longer in the list, deselect
|
|
34
|
-
if (selected && !messages.find(m => m.uid === selected.uid && m.accountId === selected.accountId)) {
|
|
35
|
-
selected = null;
|
|
36
|
-
}
|
|
37
42
|
notify("messages");
|
|
38
43
|
}
|
|
39
44
|
/** Get current messages */
|
|
@@ -52,6 +57,10 @@ export function getSelected() {
|
|
|
52
57
|
/**
|
|
53
58
|
* Remove messages from the list (after move or delete).
|
|
54
59
|
* If the selected message is removed, auto-selects the next message or null.
|
|
60
|
+
* Decrements dupeCount on any remaining messages that shared a Message-ID
|
|
61
|
+
* with one of the removed rows — so the unified-inbox ⇆ marker disappears
|
|
62
|
+
* when one half of a duplicate pair is deleted, instead of pointing at a
|
|
63
|
+
* sibling that no longer exists.
|
|
55
64
|
*/
|
|
56
65
|
export function removeMessages(uids) {
|
|
57
66
|
const removeSet = new Set(uids.map(u => `${u.accountId}:${u.uid}`));
|
|
@@ -60,7 +69,28 @@ export function removeMessages(uids) {
|
|
|
60
69
|
selectedIdx = messages.findIndex(m => m.uid === selected.uid && m.accountId === selected.accountId);
|
|
61
70
|
}
|
|
62
71
|
const wasSelectedRemoved = selected && removeSet.has(`${selected.accountId}:${selected.uid}`);
|
|
72
|
+
// Capture Message-IDs of the rows about to leave, so we can fix up the
|
|
73
|
+
// dupeCount on any remaining siblings. Only IDs that were in the list
|
|
74
|
+
// and had a non-empty messageId count — empty IDs would match every
|
|
75
|
+
// headerless row and falsely "merge" them.
|
|
76
|
+
const removedIds = new Set();
|
|
77
|
+
for (const m of messages) {
|
|
78
|
+
if (removeSet.has(`${m.accountId}:${m.uid}`) && m.messageId) {
|
|
79
|
+
removedIds.add(m.messageId);
|
|
80
|
+
}
|
|
81
|
+
}
|
|
63
82
|
messages = messages.filter(m => !removeSet.has(`${m.accountId}:${m.uid}`));
|
|
83
|
+
// Sibling dupeCount adjustment. dupeCount is server-recomputed on the
|
|
84
|
+
// next getUnifiedInbox fetch, but we don't want to wait for that —
|
|
85
|
+
// user just deleted, the marker should drop now. Decrement once per
|
|
86
|
+
// remaining message whose messageId matches a removed one.
|
|
87
|
+
if (removedIds.size > 0) {
|
|
88
|
+
for (const m of messages) {
|
|
89
|
+
if (m.messageId && removedIds.has(m.messageId) && typeof m.dupeCount === "number") {
|
|
90
|
+
m.dupeCount = Math.max(0, m.dupeCount - 1);
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
}
|
|
64
94
|
if (wasSelectedRemoved) {
|
|
65
95
|
// Auto-select next message (same index, or last, or null)
|
|
66
96
|
if (messages.length > 0) {
|
package/package.json
CHANGED
package/rebuild.cmd
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
@echo off
|
|
2
|
-
REM
|
|
2
|
+
REM -------------------------------------------------------------------------
|
|
3
3
|
REM rebuild.cmd — one-shot release: npmglobalize + APK.
|
|
4
4
|
REM Runs the desktop release workflow (npmglobalize commits, tags, bumps,
|
|
5
5
|
REM publishes the npm package) and, only if that succeeds, rebuilds the
|
|
6
6
|
REM Android MAUI APK + copies it into download/apks/ + updates versions.json.
|
|
7
7
|
REM Anything non-zero from npmglobalize aborts before the APK stage — no
|
|
8
8
|
REM point building an APK against a failed publish.
|
|
9
|
-
REM
|
|
9
|
+
REM -------------------------------------------------------------------------
|
|
10
10
|
|
|
11
11
|
cls
|
|
12
12
|
setlocal
|
package/#build-apk.cmd.asv#
DELETED