@bobfrankston/rmfmail 1.2.317 → 1.2.319

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 (34) hide show
  1. package/.commitmsg +15 -34
  2. package/.llm/trusted-lists.md +2 -0
  3. package/client/app.bundle.js +47 -4
  4. package/client/app.bundle.js.map +2 -2
  5. package/client/components/calendar-sidebar.js +54 -3
  6. package/client/components/calendar-sidebar.js.map +1 -1
  7. package/client/components/calendar-sidebar.ts +49 -3
  8. package/client/compose/compose.bundle.js +23 -0
  9. package/client/compose/compose.bundle.js.map +2 -2
  10. package/client/compose/editor.js +40 -0
  11. package/client/compose/editor.js.map +1 -1
  12. package/client/compose/editor.ts +37 -0
  13. package/npmchanges.md +62 -0
  14. package/package.json +5 -5
  15. package/packages/mailx-imap/package-lock.json +2 -2
  16. package/packages/mailx-imap/package.json +1 -1
  17. package/packages/mailx-service/google-sync.d.ts +5 -0
  18. package/packages/mailx-service/google-sync.d.ts.map +1 -1
  19. package/packages/mailx-service/google-sync.js +1 -0
  20. package/packages/mailx-service/google-sync.js.map +1 -1
  21. package/packages/mailx-service/google-sync.ts +6 -0
  22. package/packages/mailx-service/index.d.ts +4 -0
  23. package/packages/mailx-service/index.d.ts.map +1 -1
  24. package/packages/mailx-service/index.js +19 -8
  25. package/packages/mailx-service/index.js.map +1 -1
  26. package/packages/mailx-service/index.ts +23 -8
  27. package/packages/mailx-service/package.json +1 -1
  28. package/packages/mailx-settings/package.json +1 -1
  29. package/packages/mailx-store/package.json +1 -1
  30. package/packages/mailx-store-web/package.json +1 -1
  31. package/packages/mailx-types/mailx-api.d.ts +2 -0
  32. package/packages/mailx-types/mailx-api.d.ts.map +1 -1
  33. package/packages/mailx-types/mailx-api.ts +2 -1
  34. package/packages/mailx-types/package.json +1 -1
package/.commitmsg CHANGED
@@ -1,37 +1,18 @@
1
- Calendar sidebar: New event saves here, the list follows the date, Refresh pulls
1
+ Compose: typing after a pasted link no longer extends the link
2
2
 
3
- Four from Bob 2026-09-10, all in the calendar sidebar.
3
+ Bob 2026-09-10: "there is still a problem in typing after pasting a link.
4
+ It extends the link text rather than acting as regular text."
4
5
 
5
- "Add an event puts me into Google Calendar. It should just save the event
6
- because I can easily edit it later." The New event dialog now saves each
7
- extracted event as a local row through createCalendarEvent the IPC and
8
- the store-sync push to Google existed since the two-way cache and nothing
9
- called them and the sidebar shows it at once; Google gets it from the
10
- queue. The status line names what was saved. "Create as text" (AI parse
11
- failed) becomes an all-day event today titled with the text. Wall-clock
12
- times in a named zone are converted properly (wallClockToMs), so a "9am
13
- Kuala Lumpur" invite stays 9am there. buildGoogleEventUrl, the authuser
14
- work from v1.2.316 and the post-create refresh timers are gone with the
15
- page they served.
6
+ TinyMCE (his editor) turns a pasted URL into an anchor through its smart
7
+ paste and leaves the caret INSIDE the anchor at the end of its text, so
8
+ every character typed next became more link text while the target stayed
9
+ the pasted URL a link that no longer says what it does. Same when the
10
+ clipboard carries an anchor copied from a page. New
11
+ stepCaretOutOfPastedLink in client/compose/editor.ts: one tick after a
12
+ paste, if the caret is collapsed at the very end of an anchor, it is set
13
+ to just after the anchor; a caret mid-link or outside any link is left
14
+ alone. Contained in mailx's TinyMCE wiring; rmf-tiny untouched.
16
15
 
17
- "It is still showing me yesterday's calendar." The view date was fixed
18
- when the module loaded and never moved. It now follows the calendar date
19
- unless the reader has stepped to another day with ‹ › (Today clears
20
- that), and re-renders at local midnight.
21
-
22
- "Still showing…" had a second cause: the Refresh button said "from
23
- Google" and only re-read local rows — the daemon's 5-minute throttle made
24
- it a no-op most of the time. It now calls refreshCalendarNow (v1.2.316)
25
- and reports when nothing was pulled and why. The window's focus does the
26
- same, so an edit made in Google Calendar shows on coming back to rmfmail.
27
-
28
- "How do I edit the calendar list? Perhaps more tooltip help would be
29
- useful?" Every control in the sidebar header now says what it does and
30
- what it does not: the calendar rows say that unticking hides a calendar
31
- here while the list itself is the calendars selected in Google Calendar;
32
- the ‹ › buttons say the list then stays on that day; New event says it
33
- saves and how to edit. Event rows: click opens the event in Google
34
- Calendar to edit; a just-saved row says it is syncing and cannot be
35
- opened there yet; right-click offers Edit "‹title›" in Google Calendar
36
- and Delete "‹title›" (local-first, queued to Google), with confirmAt at
37
- the pointer.
16
+ The Quill branch has the same shape (insertText with a link format, then
17
+ setSelection at its end) and is not changed here untested, and not the
18
+ editor in use.
@@ -62,3 +62,5 @@ tests/trust.test.ts, .commitmsg, TODO.md C165, root version 1.2.311. Then rebuil
62
62
  buildGoogleEventUrl/authuser/post-create timers removed. viewPinned + followToday + midnight rollover.
63
63
  Refresh button + window focus call refreshCalendarNow. Tooltips on all sidebar controls; event rows:
64
64
  click = edit in Google, right-click = Delete "<title>" (deleteCalendarEvent). Publishing as v1.2.317.
65
+ - v1.2.318: New event Calendar picker (writable calendars via accessRole from listCalendars). Store-sync drain now passes calendarId to create/update/delete (was always "primary" — shared-calendar edits 404'd forever). Google: create/subscribe/share calendars on calendar.google.com; rmfmail lists the ones selected there.
66
+ - v1.2.319: TinyMCE smart-paste left the caret INSIDE the pasted <a>; stepCaretOutOfPastedLink in client/compose/editor.ts moves it after the anchor one tick after paste. Quill path has the same shape (insertText link + setSelection) — untouched, Bob uses TinyMCE.
@@ -6684,6 +6684,9 @@ function armMidnightRollover() {
6684
6684
  armMidnightRollover();
6685
6685
  }, next.getTime() - now.getTime());
6686
6686
  }
6687
+ function writableCalendars(list) {
6688
+ return list.filter((c) => c.accessRole === "owner" || c.accessRole === "writer").sort((a, b) => (a.primary ? 0 : 1) - (b.primary ? 0 : 1) || a.name.localeCompare(b.name));
6689
+ }
6687
6690
  function calendarKind(id, primary) {
6688
6691
  if (primary)
6689
6692
  return "personal";
@@ -7193,6 +7196,38 @@ function openNewEventDialog() {
7193
7196
  ta.placeholder = "Lunch with John tomorrow at noon at Joe's Pizza";
7194
7197
  const status = document.createElement("div");
7195
7198
  status.style.cssText = "min-height:1.2em;font-size:0.85em;color:var(--color-text-muted);";
7199
+ const calRow = document.createElement("label");
7200
+ calRow.style.cssText = "display:flex;align-items:center;gap:8px;font-size:0.9em;";
7201
+ calRow.title = "The calendar this event is saved to. Only calendars you can write to are listed; to add or share a calendar, do that in Google Calendar and press Refresh.";
7202
+ const calSelect = document.createElement("select");
7203
+ calSelect.style.cssText = "flex:1;font:inherit;padding:4px;";
7204
+ calRow.append("Calendar", calSelect);
7205
+ calRow.hidden = true;
7206
+ const fillCalendars = (list) => {
7207
+ const writable = writableCalendars(list);
7208
+ calSelect.innerHTML = "";
7209
+ let last = "";
7210
+ try {
7211
+ last = localStorage.getItem(LAST_CALENDAR_PREF) || "";
7212
+ } catch {
7213
+ }
7214
+ for (const c of writable) {
7215
+ const opt = document.createElement("option");
7216
+ opt.value = c.id;
7217
+ opt.textContent = c.primary ? `${c.name} (personal)` : c.name;
7218
+ if (c.id === last || !last && c.primary)
7219
+ opt.selected = true;
7220
+ calSelect.append(opt);
7221
+ }
7222
+ calRow.hidden = writable.length < 2;
7223
+ };
7224
+ if (calendarList.length)
7225
+ fillCalendars(calendarList);
7226
+ else
7227
+ getCalendars().then((list) => {
7228
+ calendarList = list;
7229
+ fillCalendars(calendarList);
7230
+ }).catch((e) => console.warn("[calendar] calendar list for the picker failed:", e?.message || e));
7196
7231
  const btnRow = document.createElement("div");
7197
7232
  btnRow.style.cssText = "display:flex;gap:8px;justify-content:flex-end;";
7198
7233
  const cancelBtn = document.createElement("button");
@@ -7202,7 +7237,7 @@ function openNewEventDialog() {
7202
7237
  createBtn.textContent = "Create";
7203
7238
  createBtn.style.cssText = "padding:6px 14px;font-weight:500;";
7204
7239
  btnRow.append(cancelBtn, createBtn);
7205
- panel.append(heading, hint, ta, status, btnRow);
7240
+ panel.append(heading, hint, ta, calRow, status, btnRow);
7206
7241
  backdrop.append(panel);
7207
7242
  document.body.append(backdrop);
7208
7243
  setTimeout(() => ta.focus(), 0);
@@ -7260,8 +7295,14 @@ function openNewEventDialog() {
7260
7295
  }
7261
7296
  const targets = events.length ? events : [null];
7262
7297
  const saved = [];
7298
+ const calendarId = calSelect.value || "primary";
7299
+ const calendarName = calSelect.selectedOptions[0]?.textContent || "";
7300
+ try {
7301
+ localStorage.setItem(LAST_CALENDAR_PREF, calendarId);
7302
+ } catch {
7303
+ }
7263
7304
  for (const ev of targets) {
7264
- const row = eventToLocalRow(ev, text);
7305
+ const row = { ...eventToLocalRow(ev, text), calendarId };
7265
7306
  try {
7266
7307
  await createCalendarEvent(row);
7267
7308
  saved.push(row.title);
@@ -7274,8 +7315,9 @@ function openNewEventDialog() {
7274
7315
  }
7275
7316
  close();
7276
7317
  const st = document.getElementById("status-sync");
7318
+ const where = calendarName && !calRow.hidden ? ` to ${calendarName}` : "";
7277
7319
  if (st)
7278
- st.textContent = saved.length === 1 ? `Saved event: ${saved[0]}` : `Saved ${saved.length} events: ${saved.join("; ")}`;
7320
+ st.textContent = saved.length === 1 ? `Saved event${where}: ${saved[0]}` : `Saved ${saved.length} events${where}: ${saved.join("; ")}`;
7279
7321
  await refresh();
7280
7322
  });
7281
7323
  }
@@ -7520,7 +7562,7 @@ function initCalendarSidebar() {
7520
7562
  }
7521
7563
  }
7522
7564
  }
7523
- var SIDEBAR_PREF, SHOW_RECURRING_PREF, SHOW_DONE_PREF, HORIZON_DAYS_PREF, HORIZON_DEFAULT_DAYS, HOLIDAY_HORIZON_MS, viewYear, viewMonth, viewDay, viewPinned, lastEvents, lastOverdueTasks, calById, calendarList, hiddenCalendars, selectedTaskUuids, TASK_DELETE_NOTE;
7565
+ var SIDEBAR_PREF, SHOW_RECURRING_PREF, SHOW_DONE_PREF, HORIZON_DAYS_PREF, HORIZON_DEFAULT_DAYS, HOLIDAY_HORIZON_MS, viewYear, viewMonth, viewDay, viewPinned, lastEvents, lastOverdueTasks, LAST_CALENDAR_PREF, calById, calendarList, hiddenCalendars, selectedTaskUuids, TASK_DELETE_NOTE;
7524
7566
  var init_calendar_sidebar = __esm({
7525
7567
  "client/components/calendar-sidebar.js"() {
7526
7568
  "use strict";
@@ -7538,6 +7580,7 @@ var init_calendar_sidebar = __esm({
7538
7580
  viewPinned = false;
7539
7581
  lastEvents = [];
7540
7582
  lastOverdueTasks = [];
7583
+ LAST_CALENDAR_PREF = "mailx.calendar.lastCreateCalendar";
7541
7584
  calById = /* @__PURE__ */ new Map();
7542
7585
  calendarList = [];
7543
7586
  hiddenCalendars = /* @__PURE__ */ new Set();