@bobfrankston/rmfmail 1.2.318 → 1.2.320

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/.commitmsg CHANGED
@@ -1,19 +1,14 @@
1
- New event: choose the calendar; pushes go to the event's own calendar
1
+ Compose (Quill): typing after a pasted or edited link is plain text
2
2
 
3
- Bob 2026-09-10: "when creating an event I should be able to specify
4
- which calendar. I want to start making more use of shared calendars."
3
+ Bob 2026-09-10: "you can risk the change for Quill since it is a known
4
+ bug and I can test it" the Quill counterpart of v1.2.319's TinyMCE fix.
5
5
 
6
- The New event dialog gains a Calendar picker listing the calendars
7
- Google says the reader can write to (accessRole owner or writer, now
8
- carried by listCalendars getCalendars), personal first, shown only
9
- when there is more than one; the last choice is remembered per machine.
10
- The status line names the calendar the event went to.
11
-
12
- Underneath, a real bug: the store-sync drain dropped calendarId and sent
13
- every create, update and delete to "primary". A create could not land
14
- anywhere else, and an update or delete of an event on a shared calendar
15
- was a 404 retried on every poll. createCalendarEventLocal takes
16
- calendarId, the row and the queue payload carry it, update/delete
17
- payloads carry the row's, and the drain passes it to all three Google
18
- calls. Rows pulled before today already hold the id the pull recorded.
19
- mailx-types 0.1.95, mailx-service 0.1.37.
6
+ Quill carries the format of the character before the caret into what is
7
+ typed next, so every place that inserted a linked run and then set the
8
+ caret at its end (the five paste paths — single-anchor clipboard, URL in
9
+ an HTML clipboard, plain URL with and without a selection and both
10
+ branches of the Edit-link dialog) left the next keystrokes extending the
11
+ link. One hoisted placeCaretAfterLink(index) in createQuillEditor now
12
+ does setSelection + format("link", false) for all seven sites; format()
13
+ on a collapsed selection sets the cursor format, which is how the
14
+ toolbar's own toggle-then-type works. Untested on Quill Bob tests.
@@ -63,3 +63,5 @@ tests/trust.test.ts, .commitmsg, TODO.md C165, root version 1.2.311. Then rebuil
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
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.
67
+ - v1.2.320: Quill counterpart — placeCaretAfterLink(index) = setSelection + format("link", false) at 5 paste sites + 2 Edit-link dialog sites. Untested; Bob will switch editor to test.
@@ -4671,10 +4671,10 @@ function createQuillEditor(container2) {
4671
4671
  if (linkRange.length) {
4672
4672
  quill.deleteText(linkRange.index, linkRange.length);
4673
4673
  quill.insertText(linkRange.index, newText, { link: result.url });
4674
- quill.setSelection(linkRange.index + newText.length, 0);
4674
+ placeCaretAfterLink(linkRange.index + newText.length);
4675
4675
  } else {
4676
4676
  quill.insertText(linkRange.index, newText, { link: result.url });
4677
- quill.setSelection(linkRange.index + newText.length, 0);
4677
+ placeCaretAfterLink(linkRange.index + newText.length);
4678
4678
  }
4679
4679
  };
4680
4680
  const extraBindings = {
@@ -4978,7 +4978,7 @@ function createQuillEditor(container2) {
4978
4978
  q.deleteText(range.index, range.length);
4979
4979
  }
4980
4980
  q.insertText(range.index, text, { link: href });
4981
- q.setSelection(range.index + text.length, 0);
4981
+ placeCaretAfterLink(range.index + text.length);
4982
4982
  return;
4983
4983
  }
4984
4984
  }
@@ -4991,10 +4991,10 @@ function createQuillEditor(container2) {
4991
4991
  const url = normalizeUrl(textOnly);
4992
4992
  if (range.length > 0) {
4993
4993
  q.formatText(range.index, range.length, "link", url);
4994
- q.setSelection(range.index + range.length, 0);
4994
+ placeCaretAfterLink(range.index + range.length);
4995
4995
  } else {
4996
4996
  q.insertText(range.index, textOnly, { link: url });
4997
- q.setSelection(range.index + textOnly.length, 0);
4997
+ placeCaretAfterLink(range.index + textOnly.length);
4998
4998
  }
4999
4999
  return;
5000
5000
  }
@@ -5010,10 +5010,10 @@ function createQuillEditor(container2) {
5010
5010
  const url = normalizeUrl(plain);
5011
5011
  if (range.length > 0) {
5012
5012
  q.formatText(range.index, range.length, "link", url);
5013
- q.setSelection(range.index + range.length, 0);
5013
+ placeCaretAfterLink(range.index + range.length);
5014
5014
  } else {
5015
5015
  q.insertText(range.index, plain.trim(), { link: url });
5016
- q.setSelection(range.index + plain.trim().length, 0);
5016
+ placeCaretAfterLink(range.index + plain.trim().length);
5017
5017
  }
5018
5018
  return;
5019
5019
  }
@@ -5033,6 +5033,10 @@ function createQuillEditor(container2) {
5033
5033
  q.clipboard.dangerouslyPasteHTML(range.index, markdownToEmailHtml(plain));
5034
5034
  }
5035
5035
  }, true);
5036
+ function placeCaretAfterLink(index) {
5037
+ q.setSelection(index, 0);
5038
+ q.format("link", false);
5039
+ }
5036
5040
  q.on("text-change", (delta, _old, source) => {
5037
5041
  if (source !== "user")
5038
5042
  return;
@@ -5320,11 +5324,34 @@ async function createTinyMceEditor2(container2, opts = {}) {
5320
5324
  const body = native?.getBody?.();
5321
5325
  if (native && body) {
5322
5326
  wireMarkdownPaste(body, (html) => native.insertContent(html));
5327
+ stepCaretOutOfPastedLink(native);
5323
5328
  }
5324
5329
  } catch {
5325
5330
  }
5326
5331
  return ed;
5327
5332
  }
5333
+ function stepCaretOutOfPastedLink(native) {
5334
+ native.on("paste", () => {
5335
+ setTimeout(() => {
5336
+ try {
5337
+ const rng = native.selection.getRng();
5338
+ if (!rng || !rng.collapsed)
5339
+ return;
5340
+ const node = native.selection.getNode();
5341
+ const a = node?.closest?.("a[href]");
5342
+ if (!a)
5343
+ return;
5344
+ const rest = rng.cloneRange();
5345
+ rest.setEnd(a, a.childNodes.length);
5346
+ if (rest.toString().trim())
5347
+ return;
5348
+ native.selection.setCursorLocation(a.parentNode, native.dom.nodeIndex(a) + 1);
5349
+ } catch (e) {
5350
+ console.warn("[editor] could not move the caret past the pasted link:", e?.message || e);
5351
+ }
5352
+ }, 0);
5353
+ });
5354
+ }
5328
5355
 
5329
5356
  // client/compose/compose.ts
5330
5357
  init_api_client();