@bobfrankston/rmfmail 1.2.223 → 1.2.225

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.
Files changed (64) hide show
  1. package/client/android-bootstrap.bundle.js +53 -6
  2. package/client/android-bootstrap.bundle.js.map +2 -2
  3. package/client/app.bundle.js +145 -62
  4. package/client/app.bundle.js.map +2 -2
  5. package/client/app.js +24 -10
  6. package/client/app.js.map +1 -1
  7. package/client/app.ts +21 -10
  8. package/client/components/address-book.js +93 -29
  9. package/client/components/address-book.js.map +1 -1
  10. package/client/components/address-book.ts +103 -24
  11. package/client/components/message-list.js +56 -15
  12. package/client/components/message-list.js.map +1 -1
  13. package/client/components/message-list.ts +55 -16
  14. package/client/components/message-viewer.js +2 -2
  15. package/client/components/message-viewer.js.map +1 -1
  16. package/client/components/message-viewer.ts +2 -2
  17. package/client/compose/compose.bundle.js +2 -2
  18. package/client/compose/compose.bundle.js.map +2 -2
  19. package/client/lib/api-client.js +2 -2
  20. package/client/lib/api-client.js.map +1 -1
  21. package/client/lib/api-client.ts +2 -2
  22. package/client/lib/mailxapi.js +2 -2
  23. package/client/lib/message-state.js +15 -4
  24. package/client/lib/message-state.js.map +1 -1
  25. package/client/lib/message-state.ts +12 -3
  26. package/client/styles/components.css +40 -0
  27. package/package.json +5 -5
  28. package/packages/mailx-imap/index.d.ts.map +1 -1
  29. package/packages/mailx-imap/index.js +32 -4
  30. package/packages/mailx-imap/index.js.map +1 -1
  31. package/packages/mailx-imap/index.ts +34 -5
  32. package/packages/mailx-imap/package-lock.json +2 -2
  33. package/packages/mailx-imap/package.json +1 -1
  34. package/packages/mailx-service/index.d.ts +1 -1
  35. package/packages/mailx-service/index.d.ts.map +1 -1
  36. package/packages/mailx-service/index.js +33 -4
  37. package/packages/mailx-service/index.js.map +1 -1
  38. package/packages/mailx-service/index.ts +28 -4
  39. package/packages/mailx-service/jsonrpc.js +1 -1
  40. package/packages/mailx-service/jsonrpc.js.map +1 -1
  41. package/packages/mailx-service/jsonrpc.ts +1 -1
  42. package/packages/mailx-service/package.json +1 -1
  43. package/packages/mailx-store/db.d.ts +30 -10
  44. package/packages/mailx-store/db.d.ts.map +1 -1
  45. package/packages/mailx-store/db.js +108 -10
  46. package/packages/mailx-store/db.js.map +1 -1
  47. package/packages/mailx-store/db.ts +126 -13
  48. package/packages/mailx-store/package.json +1 -1
  49. package/packages/mailx-store-web/android-bootstrap.d.ts.map +1 -1
  50. package/packages/mailx-store-web/android-bootstrap.js +17 -2
  51. package/packages/mailx-store-web/android-bootstrap.js.map +1 -1
  52. package/packages/mailx-store-web/android-bootstrap.ts +17 -2
  53. package/packages/mailx-store-web/db.d.ts +1 -1
  54. package/packages/mailx-store-web/db.d.ts.map +1 -1
  55. package/packages/mailx-store-web/db.js +17 -2
  56. package/packages/mailx-store-web/db.js.map +1 -1
  57. package/packages/mailx-store-web/db.ts +18 -3
  58. package/packages/mailx-store-web/package.json +1 -1
  59. package/packages/mailx-store-web/web-service.d.ts +10 -1
  60. package/packages/mailx-store-web/web-service.d.ts.map +1 -1
  61. package/packages/mailx-store-web/web-service.js +16 -1
  62. package/packages/mailx-store-web/web-service.js.map +1 -1
  63. package/packages/mailx-store-web/web-service.ts +15 -1
  64. /package/packages/mailx-imap/{node_modules.npmglobalize-stash-65000 → node_modules.npmglobalize-stash-67672}/.package-lock.json +0 -0
@@ -5061,6 +5061,15 @@ var SCHEMA = `
5061
5061
  name TEXT DEFAULT '',
5062
5062
  email TEXT NOT NULL,
5063
5063
  organization TEXT DEFAULT '',
5064
+ -- Full contact card, mirroring mailx-store v3. Android keeps its own
5065
+ -- IndexedDB-backed store, so the columns have to be declared here too
5066
+ -- or the same Google People fields get dropped on mobile.
5067
+ phone TEXT DEFAULT '',
5068
+ title TEXT DEFAULT '',
5069
+ address TEXT DEFAULT '',
5070
+ website TEXT DEFAULT '',
5071
+ notes TEXT DEFAULT '',
5072
+ birthday TEXT DEFAULT '',
5064
5073
  last_used INTEGER DEFAULT 0,
5065
5074
  use_count INTEGER DEFAULT 0,
5066
5075
  updated_at INTEGER NOT NULL,
@@ -5508,10 +5517,23 @@ var WebMailxDB = class {
5508
5517
  * Web side mirrors mailx-store/db.ts — the Google sync calls
5509
5518
  * `recordSentAddress` first to upsert, then this to attach the
5510
5519
  * Google identity for incremental delete tracking. */
5511
- setContactGoogleId(email, googleId, organization) {
5520
+ setContactGoogleId(email, googleId, organization, card) {
5512
5521
  if (!email)
5513
5522
  return;
5514
- this.run("UPDATE contacts SET source = 'google', google_id = ?, organization = ?, updated_at = ? WHERE email = ?", [googleId, organization || "", Date.now(), email]);
5523
+ this.run(`UPDATE contacts SET source = 'google', google_id = ?, organization = ?, title = ?,
5524
+ phone = ?, address = ?, website = ?, notes = ?, birthday = ?, updated_at = ?
5525
+ WHERE email = ?`, [
5526
+ googleId,
5527
+ organization || "",
5528
+ card?.title || "",
5529
+ card?.phone || "",
5530
+ card?.address || "",
5531
+ card?.website || "",
5532
+ card?.notes || "",
5533
+ card?.birthday || "",
5534
+ Date.now(),
5535
+ email
5536
+ ]);
5515
5537
  }
5516
5538
  recordSentAddress(name, email) {
5517
5539
  if (isJunkContact(email, name))
@@ -6627,8 +6649,21 @@ ${bodyEncoded}`;
6627
6649
  return this.notImpl("openAttachment");
6628
6650
  }
6629
6651
  // Spam / abuse
6630
- async markAsSpamMessages(_accountId, _uids) {
6631
- return this.notImpl("markAsSpamMessages");
6652
+ /** Mark as spam = move to the account's \Junk folder, exactly as desktop's
6653
+ * MailxService.markAsSpamMessages does. This was a notImpl() stub, which
6654
+ * is worse than it sounds: the client optimistically removes the rows
6655
+ * from the list BEFORE calling this, then only writes the rejection to
6656
+ * the status bar. So on Android the spam button looked like it worked,
6657
+ * nothing moved on the server, and the next sync brought every message
6658
+ * straight back (Bob 2026-08-07: "attempts to delete spam but they keep
6659
+ * coming back"). moveMessages was implemented all along — spam just never
6660
+ * got wired to it. */
6661
+ async markAsSpamMessages(accountId, uids) {
6662
+ const target = this.db.getFolders(accountId).find((f) => f.specialUse === "junk");
6663
+ if (!target)
6664
+ throw new Error(`No \\Junk/\\Spam folder found for ${accountId}`);
6665
+ await this.moveMessages(accountId, uids, target.id);
6666
+ return { targetFolderId: target.id, moved: uids.length };
6632
6667
  }
6633
6668
  async recordSpamReport(_accountId, _uid, _folderId) {
6634
6669
  return this.notImpl("recordSpamReport");
@@ -11241,7 +11276,9 @@ async function syncGoogleContactsForAccount(db2, accountId, tokenProvider2) {
11241
11276
  try {
11242
11277
  do {
11243
11278
  const params = new URLSearchParams({
11244
- personFields: "names,emailAddresses,organizations,photos",
11279
+ // Full contact card — matches the desktop sync in
11280
+ // mailx-imap so mobile doesn't silently hold less.
11281
+ personFields: "names,emailAddresses,organizations,photos,phoneNumbers,addresses,urls,biographies,birthdays",
11245
11282
  pageSize: "100"
11246
11283
  });
11247
11284
  if (nextPageToken) params.set("pageToken", nextPageToken);
@@ -11273,13 +11310,23 @@ async function syncGoogleContactsForAccount(db2, accountId, tokenProvider2) {
11273
11310
  }
11274
11311
  const name = person.names?.[0]?.displayName || "";
11275
11312
  const org = person.organizations?.[0]?.name || "";
11313
+ const bd = person.birthdays?.[0]?.date;
11314
+ const pad = (n) => String(n).padStart(2, "0");
11315
+ const card = {
11316
+ title: person.organizations?.[0]?.title || "",
11317
+ phone: person.phoneNumbers?.[0]?.value || "",
11318
+ address: person.addresses?.[0]?.formattedValue || "",
11319
+ website: person.urls?.[0]?.value || "",
11320
+ notes: person.biographies?.[0]?.value || "",
11321
+ birthday: bd?.month && bd?.day ? `${bd.year ? bd.year : "-"}-${pad(bd.month)}-${pad(bd.day)}` : ""
11322
+ };
11276
11323
  for (const e of person.emailAddresses || []) {
11277
11324
  const email = e.value?.toLowerCase();
11278
11325
  if (!email) continue;
11279
11326
  const existing = db2.searchContacts(email, 1);
11280
11327
  const wasNew = !(existing.length > 0 && existing[0].email === email);
11281
11328
  db2.recordSentAddress(name, email);
11282
- db2.setContactGoogleId(email, googleId, org);
11329
+ db2.setContactGoogleId(email, googleId, org, card);
11283
11330
  if (wasNew) changed++;
11284
11331
  }
11285
11332
  }