@bobfrankston/rmfmail 1.1.231 → 1.1.233
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.
|
@@ -4115,6 +4115,26 @@ function autoGrowAddrInput(el) {
|
|
|
4115
4115
|
if (el.scrollHeight > max) el.style.overflowY = "auto";
|
|
4116
4116
|
else el.style.overflowY = "hidden";
|
|
4117
4117
|
}
|
|
4118
|
+
function parseRecipientSegment(seg) {
|
|
4119
|
+
const s = (seg || "").trim();
|
|
4120
|
+
if (!s) return null;
|
|
4121
|
+
const angled = s.match(/^\s*"?([^"<]*?)"?\s*<([^>]+)>\s*$/);
|
|
4122
|
+
if (angled && /@/.test(angled[2])) return { name: angled[1].trim(), email: angled[2].trim() };
|
|
4123
|
+
const bare = s.match(/[^\s<>,"]+@[^\s<>,"]+\.[^\s<>,"]+/);
|
|
4124
|
+
if (bare) return { name: "", email: bare[0] };
|
|
4125
|
+
return null;
|
|
4126
|
+
}
|
|
4127
|
+
function recipientAtCaret(el) {
|
|
4128
|
+
const v = el.value;
|
|
4129
|
+
const caret = el.selectionStart ?? v.length;
|
|
4130
|
+
let start = 0;
|
|
4131
|
+
for (const seg of v.split(",")) {
|
|
4132
|
+
const end = start + seg.length;
|
|
4133
|
+
if (caret >= start && caret <= end) return parseRecipientSegment(seg);
|
|
4134
|
+
start = end + 1;
|
|
4135
|
+
}
|
|
4136
|
+
return parseRecipientSegment(v.split(",").pop() || "");
|
|
4137
|
+
}
|
|
4118
4138
|
for (const el of [toInput, ccInput, bccInput]) {
|
|
4119
4139
|
el?.addEventListener("input", () => autoGrowAddrInput(el));
|
|
4120
4140
|
el?.addEventListener("keydown", (e) => {
|
|
@@ -4127,6 +4147,60 @@ for (const el of [toInput, ccInput, bccInput]) {
|
|
|
4127
4147
|
autoGrowAddrInput(el);
|
|
4128
4148
|
}
|
|
4129
4149
|
});
|
|
4150
|
+
el?.addEventListener("contextmenu", (e) => {
|
|
4151
|
+
if (!el) return;
|
|
4152
|
+
e.preventDefault();
|
|
4153
|
+
const me = e;
|
|
4154
|
+
const items = [];
|
|
4155
|
+
const addr = recipientAtCaret(el);
|
|
4156
|
+
if (addr?.email) {
|
|
4157
|
+
items.push({
|
|
4158
|
+
label: `Open in Google Contacts: ${addr.email}`,
|
|
4159
|
+
tooltip: "Add as a new contact, attach to an existing one, or merge/update \u2014 in Google's own UI.",
|
|
4160
|
+
action: () => window.open(`https://contacts.google.com/search/${encodeURIComponent(addr.name || addr.email)}`, "_blank")
|
|
4161
|
+
});
|
|
4162
|
+
items.push({ label: "Add to preferred\u2026", action: () => openAddToPreferredModal({ name: addr.name, email: addr.email, source: "" }) });
|
|
4163
|
+
items.push({ label: `Copy address: ${addr.email}`, action: () => {
|
|
4164
|
+
void navigator.clipboard.writeText(addr.email);
|
|
4165
|
+
} });
|
|
4166
|
+
items.push({ label: "", action: () => {
|
|
4167
|
+
}, separator: true });
|
|
4168
|
+
}
|
|
4169
|
+
const selText = () => el.value.slice(el.selectionStart ?? 0, el.selectionEnd ?? 0);
|
|
4170
|
+
const replaceSelection = (text) => {
|
|
4171
|
+
const s = el.selectionStart ?? el.value.length, en = el.selectionEnd ?? el.value.length;
|
|
4172
|
+
el.value = el.value.slice(0, s) + text + el.value.slice(en);
|
|
4173
|
+
el.selectionStart = el.selectionEnd = s + text.length;
|
|
4174
|
+
el.dispatchEvent(new Event("input", { bubbles: true }));
|
|
4175
|
+
};
|
|
4176
|
+
items.push({ label: "Cut", action: async () => {
|
|
4177
|
+
const t = selText();
|
|
4178
|
+
if (t) {
|
|
4179
|
+
try {
|
|
4180
|
+
await navigator.clipboard.writeText(t);
|
|
4181
|
+
} catch {
|
|
4182
|
+
}
|
|
4183
|
+
replaceSelection("");
|
|
4184
|
+
}
|
|
4185
|
+
} });
|
|
4186
|
+
items.push({ label: "Copy", action: async () => {
|
|
4187
|
+
const t = selText();
|
|
4188
|
+
if (t) {
|
|
4189
|
+
try {
|
|
4190
|
+
await navigator.clipboard.writeText(t);
|
|
4191
|
+
} catch {
|
|
4192
|
+
}
|
|
4193
|
+
}
|
|
4194
|
+
} });
|
|
4195
|
+
items.push({ label: "Paste", action: async () => {
|
|
4196
|
+
try {
|
|
4197
|
+
replaceSelection(await navigator.clipboard.readText());
|
|
4198
|
+
} catch {
|
|
4199
|
+
}
|
|
4200
|
+
} });
|
|
4201
|
+
items.push({ label: "Select all", action: () => el.select() });
|
|
4202
|
+
showContextMenu(me.clientX, me.clientY, items);
|
|
4203
|
+
});
|
|
4130
4204
|
}
|
|
4131
4205
|
var knownAccounts = [];
|
|
4132
4206
|
if (appSettings?.autocomplete?.enabled && appSettings.autocomplete.provider !== "off") {
|