@bobfrankston/rmfmail 1.2.170 → 1.2.171
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/client/android-bootstrap.bundle.js +91 -40
- package/client/android-bootstrap.bundle.js.map +2 -2
- package/package.json +3 -3
- package/packages/mailx-store-web/package.json +1 -1
- package/packages/mailx-store-web/web-service.d.ts.map +1 -1
- package/packages/mailx-store-web/web-service.js +33 -28
- package/packages/mailx-store-web/web-service.js.map +1 -1
- package/packages/mailx-store-web/web-service.ts +23 -23
- package/packages/mailx-store-web/web-settings.d.ts +12 -1
- package/packages/mailx-store-web/web-settings.d.ts.map +1 -1
- package/packages/mailx-store-web/web-settings.js +81 -15
- package/packages/mailx-store-web/web-settings.js.map +1 -1
- package/packages/mailx-store-web/web-settings.ts +79 -19
- /package/packages/mailx-imap/{node_modules.npmglobalize-stash-41184 → node_modules.npmglobalize-stash-3252}/.package-lock.json +0 -0
|
@@ -2588,7 +2588,8 @@ __export(web_settings_exports, {
|
|
|
2588
2588
|
savePreferences: () => savePreferences,
|
|
2589
2589
|
saveSettings: () => saveSettings,
|
|
2590
2590
|
setGDriveFolderId: () => setGDriveFolderId,
|
|
2591
|
-
setGDriveTokenProvider: () => setGDriveTokenProvider
|
|
2591
|
+
setGDriveTokenProvider: () => setGDriveTokenProvider,
|
|
2592
|
+
updateAllowlist: () => updateAllowlist
|
|
2592
2593
|
});
|
|
2593
2594
|
function openSettingsDb() {
|
|
2594
2595
|
return new Promise((resolve, reject) => {
|
|
@@ -2665,17 +2666,28 @@ async function cloudStat(filename) {
|
|
|
2665
2666
|
return null;
|
|
2666
2667
|
}
|
|
2667
2668
|
}
|
|
2669
|
+
async function gDriveFindFile(filename, token) {
|
|
2670
|
+
const q = encodeURIComponent(`name='${filename}' and '${gDriveFolderId}' in parents and trashed=false`);
|
|
2671
|
+
const res = await globalThis.fetch(`https://www.googleapis.com/drive/v3/files?q=${q}&fields=files(id,modifiedTime,ownedByMe,capabilities(canEdit))`, { headers: { "Authorization": `Bearer ${token}` } });
|
|
2672
|
+
if (!res.ok)
|
|
2673
|
+
return null;
|
|
2674
|
+
const files = (await res.json()).files || [];
|
|
2675
|
+
if (files.length === 0)
|
|
2676
|
+
return null;
|
|
2677
|
+
if (files.length > 1) {
|
|
2678
|
+
console.warn(`[settings] ${filename}: ${files.length} same-named files in the shared folder \u2014 using own/newest. Clean the duplicates (owners differ?).`);
|
|
2679
|
+
files.sort((a, b) => (b.ownedByMe === true ? 1 : 0) - (a.ownedByMe === true ? 1 : 0) || String(b.modifiedTime).localeCompare(String(a.modifiedTime)));
|
|
2680
|
+
}
|
|
2681
|
+
const f = files[0];
|
|
2682
|
+
return { id: f.id, modifiedTime: f.modifiedTime || "", ownedByMe: f.ownedByMe === true, capabilitiesCanEdit: f.capabilities?.canEdit !== false };
|
|
2683
|
+
}
|
|
2668
2684
|
async function gDriveRead(filename) {
|
|
2669
2685
|
if (!tokenProvider || !gDriveFolderId)
|
|
2670
2686
|
return null;
|
|
2671
2687
|
try {
|
|
2672
2688
|
const token = await tokenProvider();
|
|
2673
|
-
const
|
|
2674
|
-
const
|
|
2675
|
-
if (!listRes.ok)
|
|
2676
|
-
return null;
|
|
2677
|
-
const listData = await listRes.json();
|
|
2678
|
-
const fileId = listData.files?.[0]?.id;
|
|
2689
|
+
const found = await gDriveFindFile(filename, token);
|
|
2690
|
+
const fileId = found?.id;
|
|
2679
2691
|
if (!fileId)
|
|
2680
2692
|
return null;
|
|
2681
2693
|
const res = await globalThis.fetch(`https://www.googleapis.com/drive/v3/files/${fileId}?alt=media`, { headers: { "Authorization": `Bearer ${token}` } });
|
|
@@ -2692,13 +2704,13 @@ async function gDriveWrite(filename, content) {
|
|
|
2692
2704
|
return false;
|
|
2693
2705
|
try {
|
|
2694
2706
|
const token = await tokenProvider();
|
|
2695
|
-
const
|
|
2696
|
-
const
|
|
2697
|
-
if (!listRes.ok)
|
|
2698
|
-
return false;
|
|
2699
|
-
const listData = await listRes.json();
|
|
2700
|
-
const fileId = listData.files?.[0]?.id;
|
|
2707
|
+
const found = await gDriveFindFile(filename, token);
|
|
2708
|
+
const fileId = found?.id;
|
|
2701
2709
|
if (fileId) {
|
|
2710
|
+
if (!found.capabilitiesCanEdit) {
|
|
2711
|
+
console.error(`[settings] ${filename}: existing shared file is not editable by this account \u2014 NOT creating a duplicate. Change kept locally.`);
|
|
2712
|
+
return false;
|
|
2713
|
+
}
|
|
2702
2714
|
const res = await globalThis.fetch(`https://www.googleapis.com/upload/drive/v3/files/${fileId}?uploadType=media`, {
|
|
2703
2715
|
method: "PATCH",
|
|
2704
2716
|
headers: {
|
|
@@ -2707,6 +2719,8 @@ async function gDriveWrite(filename, content) {
|
|
|
2707
2719
|
},
|
|
2708
2720
|
body: content
|
|
2709
2721
|
});
|
|
2722
|
+
if (!res.ok)
|
|
2723
|
+
console.error(`[settings] ${filename}: cloud update failed (${res.status})`);
|
|
2710
2724
|
return res.ok;
|
|
2711
2725
|
} else {
|
|
2712
2726
|
const metadata = JSON.stringify({
|
|
@@ -2948,9 +2962,43 @@ async function loadAllowlist() {
|
|
|
2948
2962
|
}
|
|
2949
2963
|
return { ...DEFAULT_ALLOWLIST };
|
|
2950
2964
|
}
|
|
2965
|
+
function allowlistEntryCount(l) {
|
|
2966
|
+
return ALLOWLIST_KEYS.reduce((n, k) => n + (Array.isArray(l?.[k]) ? l[k].length : 0), 0);
|
|
2967
|
+
}
|
|
2968
|
+
async function updateAllowlist(mutate) {
|
|
2969
|
+
let base = null;
|
|
2970
|
+
try {
|
|
2971
|
+
const fresh = await gDriveRead("allowlist.jsonc");
|
|
2972
|
+
if (fresh) {
|
|
2973
|
+
await idbWrite("allowlist.jsonc", fresh);
|
|
2974
|
+
try {
|
|
2975
|
+
base = parseJsonc(fresh);
|
|
2976
|
+
} catch {
|
|
2977
|
+
}
|
|
2978
|
+
}
|
|
2979
|
+
} catch {
|
|
2980
|
+
}
|
|
2981
|
+
if (!base)
|
|
2982
|
+
base = await loadAllowlist();
|
|
2983
|
+
const out = mutate(base) || base;
|
|
2984
|
+
await saveAllowlist(out);
|
|
2985
|
+
return out;
|
|
2986
|
+
}
|
|
2951
2987
|
async function saveAllowlist(list) {
|
|
2952
2988
|
const content = JSON.stringify(list, null, 2);
|
|
2953
2989
|
await idbWrite("allowlist.jsonc", content);
|
|
2990
|
+
try {
|
|
2991
|
+
const cloudRaw = await gDriveRead("allowlist.jsonc");
|
|
2992
|
+
if (cloudRaw) {
|
|
2993
|
+
const cloudCount = allowlistEntryCount(parseJsonc(cloudRaw));
|
|
2994
|
+
const newCount = allowlistEntryCount(list);
|
|
2995
|
+
if (cloudCount > 10 && newCount < cloudCount / 2) {
|
|
2996
|
+
console.error(`[settings] REFUSING allowlist cloud write: ${cloudCount} \u2192 ${newCount} entries (stale/default base \u2014 see 2026-07-23 wipe). Local cache updated only.`);
|
|
2997
|
+
return;
|
|
2998
|
+
}
|
|
2999
|
+
}
|
|
3000
|
+
} catch {
|
|
3001
|
+
}
|
|
2954
3002
|
await gDriveWrite("allowlist.jsonc", content);
|
|
2955
3003
|
}
|
|
2956
3004
|
async function loadAutocomplete() {
|
|
@@ -3020,7 +3068,7 @@ async function loadDeviceState() {
|
|
|
3020
3068
|
}
|
|
3021
3069
|
return {};
|
|
3022
3070
|
}
|
|
3023
|
-
var IDB_NAME2, IDB_VERSION, STORE_NAME2, gDriveFolderId, gDriveFolderName, gDriveFolderPath, gDriveFolderOwner, tokenProvider, PROVIDERS, DEFAULT_PREFERENCES, DEFAULT_ALLOWLIST, SHARED_REFRESH_MS, __lastSharedRefresh, DEVICE_ID_KEY;
|
|
3071
|
+
var IDB_NAME2, IDB_VERSION, STORE_NAME2, gDriveFolderId, gDriveFolderName, gDriveFolderPath, gDriveFolderOwner, tokenProvider, PROVIDERS, DEFAULT_PREFERENCES, DEFAULT_ALLOWLIST, SHARED_REFRESH_MS, __lastSharedRefresh, ALLOWLIST_KEYS, DEVICE_ID_KEY;
|
|
3024
3072
|
var init_web_settings = __esm({
|
|
3025
3073
|
"packages/mailx-store-web/web-settings.js"() {
|
|
3026
3074
|
"use strict";
|
|
@@ -3097,6 +3145,7 @@ var init_web_settings = __esm({
|
|
|
3097
3145
|
};
|
|
3098
3146
|
SHARED_REFRESH_MS = 5 * 6e4;
|
|
3099
3147
|
__lastSharedRefresh = /* @__PURE__ */ new Map();
|
|
3148
|
+
ALLOWLIST_KEYS = ["senders", "domains", "recipients", "flaggedSenders", "flaggedDomains"];
|
|
3100
3149
|
DEVICE_ID_KEY = "mailx-device-id";
|
|
3101
3150
|
}
|
|
3102
3151
|
});
|
|
@@ -5939,23 +5988,24 @@ var WebMailxService = class _WebMailxService {
|
|
|
5939
5988
|
* flaggedSenders / flaggedDomains in allowlist.jsonc, which syncs
|
|
5940
5989
|
* back to the cloud copy. */
|
|
5941
5990
|
async flagSenderOrDomain(type, value) {
|
|
5942
|
-
const list = await loadAllowlist();
|
|
5943
|
-
const key = type === "sender" ? "flaggedSenders" : "flaggedDomains";
|
|
5944
|
-
const arr = Array.isArray(list[key]) ? list[key] : [];
|
|
5945
5991
|
const v = (value || "").trim().toLowerCase();
|
|
5946
5992
|
if (!v)
|
|
5947
5993
|
return { flagged: false };
|
|
5948
|
-
|
|
5949
|
-
|
|
5950
|
-
|
|
5951
|
-
arr.
|
|
5952
|
-
|
|
5953
|
-
|
|
5954
|
-
|
|
5955
|
-
|
|
5956
|
-
|
|
5957
|
-
|
|
5958
|
-
|
|
5994
|
+
let flagged = false;
|
|
5995
|
+
await updateAllowlist((list) => {
|
|
5996
|
+
const key = type === "sender" ? "flaggedSenders" : "flaggedDomains";
|
|
5997
|
+
const arr = Array.isArray(list[key]) ? list[key] : [];
|
|
5998
|
+
const idx = arr.findIndex((x) => (x || "").toLowerCase() === v);
|
|
5999
|
+
if (idx >= 0) {
|
|
6000
|
+
arr.splice(idx, 1);
|
|
6001
|
+
flagged = false;
|
|
6002
|
+
} else {
|
|
6003
|
+
arr.push(v);
|
|
6004
|
+
flagged = true;
|
|
6005
|
+
}
|
|
6006
|
+
list[key] = arr;
|
|
6007
|
+
return list;
|
|
6008
|
+
});
|
|
5959
6009
|
return { flagged };
|
|
5960
6010
|
}
|
|
5961
6011
|
async updateFlags(accountId, uid, flags) {
|
|
@@ -5964,18 +6014,19 @@ var WebMailxService = class _WebMailxService {
|
|
|
5964
6014
|
}
|
|
5965
6015
|
// ── Remote content allow-list ──
|
|
5966
6016
|
async allowRemoteContent(type, value) {
|
|
5967
|
-
|
|
5968
|
-
|
|
5969
|
-
|
|
5970
|
-
|
|
5971
|
-
|
|
5972
|
-
|
|
5973
|
-
|
|
5974
|
-
|
|
5975
|
-
|
|
5976
|
-
|
|
5977
|
-
|
|
5978
|
-
|
|
6017
|
+
await updateAllowlist((list) => {
|
|
6018
|
+
if (type === "sender" && !list.senders.includes(value))
|
|
6019
|
+
list.senders.push(value);
|
|
6020
|
+
else if (type === "domain" && !list.domains.includes(value))
|
|
6021
|
+
list.domains.push(value);
|
|
6022
|
+
else if (type === "recipient") {
|
|
6023
|
+
if (!list.recipients)
|
|
6024
|
+
list.recipients = [];
|
|
6025
|
+
if (!list.recipients.includes(value))
|
|
6026
|
+
list.recipients.push(value);
|
|
6027
|
+
}
|
|
6028
|
+
return list;
|
|
6029
|
+
});
|
|
5979
6030
|
}
|
|
5980
6031
|
// ── Search ──
|
|
5981
6032
|
async search(q, page = 1, pageSize = 50, scope = "all", accountId, folderId) {
|