@bobfrankston/mailx-imap 0.1.36 → 0.1.38
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/index.js +51 -6
- package/package.json +9 -9
package/index.js
CHANGED
|
@@ -3140,6 +3140,26 @@ export class ImapManager extends EventEmitter {
|
|
|
3140
3140
|
}
|
|
3141
3141
|
}
|
|
3142
3142
|
const uid = typeof result === "number" ? result : result?.uid || null;
|
|
3143
|
+
// Insert a local DB row + body file immediately so the user's
|
|
3144
|
+
// Drafts folder shows the draft without waiting for the next
|
|
3145
|
+
// full Drafts sync. Bob 2026-05-12: "I started a reply which
|
|
3146
|
+
// I saved as a draft somewhere but I can't find it by looking
|
|
3147
|
+
// in drafts nor by searching." The IMAP APPEND just returned,
|
|
3148
|
+
// so we have both the source bytes and the real server UID —
|
|
3149
|
+
// same pattern copyToSent uses. recalcFolderCounts +
|
|
3150
|
+
// folderCountsChanged inside insertLocalRowFromSource bump
|
|
3151
|
+
// the Drafts badge as well.
|
|
3152
|
+
if (uid !== null && uid > 0) {
|
|
3153
|
+
try {
|
|
3154
|
+
const sourceStr = typeof rawMessage === "string"
|
|
3155
|
+
? rawMessage
|
|
3156
|
+
: rawMessage.toString("utf-8");
|
|
3157
|
+
await this.insertLocalRowFromSource(accountId, drafts, uid, sourceStr, ["\\Draft", "\\Seen"]);
|
|
3158
|
+
}
|
|
3159
|
+
catch (e) {
|
|
3160
|
+
console.error(` [drafts] local-insert after APPEND failed: ${e?.message || e}`);
|
|
3161
|
+
}
|
|
3162
|
+
}
|
|
3143
3163
|
return uid;
|
|
3144
3164
|
});
|
|
3145
3165
|
}
|
|
@@ -3152,6 +3172,34 @@ export class ImapManager extends EventEmitter {
|
|
|
3152
3172
|
return;
|
|
3153
3173
|
if (!draftUid && !draftId)
|
|
3154
3174
|
return;
|
|
3175
|
+
// Local-first: drop the draft from the local DB FIRST so the user's
|
|
3176
|
+
// Drafts view reflects the Send click instantly. The IMAP delete is
|
|
3177
|
+
// queued for the background reconciler. Without this, the draft
|
|
3178
|
+
// stayed visible in Drafts until the IMAP round-trip completed (or
|
|
3179
|
+
// forever if it failed) — Bob 2026-05-12: "when I send a letter you
|
|
3180
|
+
// seem to still leave it in draft so I don't know if it has been
|
|
3181
|
+
// sent or not. Once you hand it off it must leave draft."
|
|
3182
|
+
let localDeletedUid = 0;
|
|
3183
|
+
if (draftUid) {
|
|
3184
|
+
const existing = this.db.getMessageByUid(accountId, draftUid, drafts.id);
|
|
3185
|
+
if (existing) {
|
|
3186
|
+
this.unlinkBodyFile(accountId, draftUid, drafts.id).catch(() => { });
|
|
3187
|
+
this.db.deleteMessage(accountId, draftUid, "user sent the message (draft cleanup)", "mailx-imap deleteDraft (local)");
|
|
3188
|
+
localDeletedUid = draftUid;
|
|
3189
|
+
}
|
|
3190
|
+
}
|
|
3191
|
+
if (draftId && !localDeletedUid) {
|
|
3192
|
+
// Look up any local draft rows by X-Mailx-Draft-ID. The DB
|
|
3193
|
+
// doesn't index that header directly, but locally-saved drafts
|
|
3194
|
+
// share a stable header set; rely on the UID path 99% of the
|
|
3195
|
+
// time. This branch covers the "draft was saved on another
|
|
3196
|
+
// device, came in via sync, no UID known yet" edge case — for
|
|
3197
|
+
// now the IMAP path below handles it.
|
|
3198
|
+
}
|
|
3199
|
+
if (localDeletedUid > 0) {
|
|
3200
|
+
this.db.recalcFolderCounts(drafts.id);
|
|
3201
|
+
this.emit("folderCountsChanged", accountId, {});
|
|
3202
|
+
}
|
|
3155
3203
|
let succeeded = false;
|
|
3156
3204
|
try {
|
|
3157
3205
|
await this.withConnection(accountId, async (client) => {
|
|
@@ -3190,12 +3238,9 @@ export class ImapManager extends EventEmitter {
|
|
|
3190
3238
|
console.error(` [drafts] withConnection failed for ${accountId}: ${e?.message || e}`);
|
|
3191
3239
|
}
|
|
3192
3240
|
// Reliable cleanup: if the inline attempt didn't actually delete the
|
|
3193
|
-
// draft, queue a sync_action so the regular
|
|
3194
|
-
// retries it later.
|
|
3195
|
-
//
|
|
3196
|
-
// Only the UID path can be queued — searchByHeader retries on every
|
|
3197
|
-
// future call anyway, and queuing a header-lookup isn't a real
|
|
3198
|
-
// sync_action shape.
|
|
3241
|
+
// draft on the server, queue a sync_action so the regular
|
|
3242
|
+
// processSyncActions loop retries it later. The local row is already
|
|
3243
|
+
// gone (above), so the user doesn't see stale UI either way.
|
|
3199
3244
|
if (!succeeded && draftUid) {
|
|
3200
3245
|
console.log(` [drafts] Queueing sync_action for retry: delete UID ${draftUid} in ${drafts.path}`);
|
|
3201
3246
|
this.db.queueSyncAction(accountId, "delete", draftUid, drafts.id);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bobfrankston/mailx-imap",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.38",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"types": "index.d.ts",
|
|
@@ -9,10 +9,10 @@
|
|
|
9
9
|
},
|
|
10
10
|
"license": "ISC",
|
|
11
11
|
"dependencies": {
|
|
12
|
-
"@bobfrankston/mailx-types": "^0.1.
|
|
13
|
-
"@bobfrankston/mailx-settings": "^0.1.
|
|
14
|
-
"@bobfrankston/mailx-store": "^0.1.
|
|
15
|
-
"@bobfrankston/iflow-direct": "^0.1.
|
|
12
|
+
"@bobfrankston/mailx-types": "^0.1.11",
|
|
13
|
+
"@bobfrankston/mailx-settings": "^0.1.16",
|
|
14
|
+
"@bobfrankston/mailx-store": "^0.1.19",
|
|
15
|
+
"@bobfrankston/iflow-direct": "^0.1.41",
|
|
16
16
|
"@bobfrankston/tcp-transport": "^0.1.6",
|
|
17
17
|
"@bobfrankston/smtp-direct": "^0.1.8",
|
|
18
18
|
"@bobfrankston/mailx-sync": "^0.1.16",
|
|
@@ -37,10 +37,10 @@
|
|
|
37
37
|
},
|
|
38
38
|
".transformedSnapshot": {
|
|
39
39
|
"dependencies": {
|
|
40
|
-
"@bobfrankston/mailx-types": "^0.1.
|
|
41
|
-
"@bobfrankston/mailx-settings": "^0.1.
|
|
42
|
-
"@bobfrankston/mailx-store": "^0.1.
|
|
43
|
-
"@bobfrankston/iflow-direct": "^0.1.
|
|
40
|
+
"@bobfrankston/mailx-types": "^0.1.11",
|
|
41
|
+
"@bobfrankston/mailx-settings": "^0.1.16",
|
|
42
|
+
"@bobfrankston/mailx-store": "^0.1.19",
|
|
43
|
+
"@bobfrankston/iflow-direct": "^0.1.41",
|
|
44
44
|
"@bobfrankston/tcp-transport": "^0.1.6",
|
|
45
45
|
"@bobfrankston/smtp-direct": "^0.1.8",
|
|
46
46
|
"@bobfrankston/mailx-sync": "^0.1.16",
|