@bobfrankston/rmfmail 1.0.667 → 1.0.668
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/TODO.md +2 -0
- package/bin/mailx.js +114 -111
- package/bin/mailx.js.map +1 -1
- package/bin/mailx.ts +117 -95
- package/client/app.bundle.js +98 -24
- package/client/app.bundle.js.map +2 -2
- package/client/components/alarms.js +106 -29
- package/client/components/alarms.js.map +1 -1
- package/client/components/alarms.ts +109 -31
- package/client/components/calendar-sidebar.js +19 -12
- package/client/components/calendar-sidebar.js.map +1 -1
- package/client/components/calendar-sidebar.ts +21 -12
- package/client/compose/compose.bundle.js.map +1 -1
- package/client/index.html +3 -0
- package/client/lib/api-client.ts +1 -1
- package/package.json +1 -1
- package/packages/mailx-host/index.d.ts +5 -0
- package/packages/mailx-host/index.d.ts.map +1 -1
- package/packages/mailx-host/index.js +5 -0
- package/packages/mailx-host/index.js.map +1 -1
- package/packages/mailx-host/index.ts +5 -0
- package/packages/mailx-host/package.json +1 -1
- package/packages/mailx-service/index.d.ts +1 -0
- package/packages/mailx-service/index.d.ts.map +1 -1
- package/packages/mailx-service/index.js +68 -36
- package/packages/mailx-service/index.js.map +1 -1
- package/packages/mailx-service/index.ts +67 -37
|
@@ -696,7 +696,7 @@ export class MailxService {
|
|
|
696
696
|
buttons: string[];
|
|
697
697
|
size?: { width: number; height: number };
|
|
698
698
|
pos?: { x: number; y: number };
|
|
699
|
-
}): Promise<{ button: string; reason?: string }> {
|
|
699
|
+
}): Promise<{ button: string; form?: any; reason?: string }> {
|
|
700
700
|
if (!this.popupFn) return { button: "", reason: "no popup host" };
|
|
701
701
|
try {
|
|
702
702
|
const r = await this.popupFn({
|
|
@@ -723,7 +723,13 @@ export class MailxService {
|
|
|
723
723
|
// on graceful shutdown.
|
|
724
724
|
detach: false,
|
|
725
725
|
});
|
|
726
|
-
return {
|
|
726
|
+
return {
|
|
727
|
+
button: r.button || (r.dismissed ? "dismissed" : r.closed ? "closed" : ""),
|
|
728
|
+
// Pass msger's `form` field through. Used by the calendar
|
|
729
|
+
// reminder popup to send back arbitrary snooze durations
|
|
730
|
+
// (e.g. { minutes: 75 }) — see alarms.ts.
|
|
731
|
+
form: (r as any).form,
|
|
732
|
+
};
|
|
727
733
|
} catch (e: any) {
|
|
728
734
|
console.error(` [reminder] popup failed: ${e.message}`);
|
|
729
735
|
return { button: "", reason: e.message };
|
|
@@ -1116,7 +1122,15 @@ export class MailxService {
|
|
|
1116
1122
|
.catch(e => this.handleGoogleRefreshError("calendar", e));
|
|
1117
1123
|
}
|
|
1118
1124
|
}
|
|
1119
|
-
|
|
1125
|
+
const rows = this.localStore.getCalendarEvents(acctId, fromMs, toMs);
|
|
1126
|
+
// Diagnostic: separate counts for plain / recurring / holiday rows
|
|
1127
|
+
// so log inspection reveals whether the issue is fetch-side
|
|
1128
|
+
// (refresh didn't write them) vs read/render-side (they're in DB
|
|
1129
|
+
// but not appearing in the UI).
|
|
1130
|
+
const recurring = rows.filter(r => r.recurringEventId).length;
|
|
1131
|
+
const holidays = rows.filter(r => r.isHoliday).length;
|
|
1132
|
+
console.log(` [calendar] getCalendarEvents → ${rows.length} rows (${recurring} recurring, ${holidays} holiday) for window ${new Date(fromMs).toISOString().slice(0, 10)}..${new Date(toMs).toISOString().slice(0, 10)}`);
|
|
1133
|
+
return rows;
|
|
1120
1134
|
}
|
|
1121
1135
|
|
|
1122
1136
|
/** Returns true if the feature is currently in a quota-exceeded cooldown. */
|
|
@@ -1177,24 +1191,36 @@ export class MailxService {
|
|
|
1177
1191
|
const tp = await this.primaryTokenProvider("calendar");
|
|
1178
1192
|
const events = await gsync.listCalendarEvents(tp, fromMs, toMs);
|
|
1179
1193
|
console.log(` [calendar] pulled ${events.length} events from ${new Date(fromMs).toISOString().slice(0, 10)} to ${new Date(toMs).toISOString().slice(0, 10)}`);
|
|
1180
|
-
//
|
|
1181
|
-
//
|
|
1182
|
-
//
|
|
1194
|
+
// Holiday calendars (Q131 + Bob 2026-05-11 second-toggle request).
|
|
1195
|
+
// Each enabled toggle pulls a separate Google public calendar; rows
|
|
1196
|
+
// are tagged with the source `calendar_id` so toggling one off only
|
|
1197
|
+
// purges that source's rows, not the others. Future generalization
|
|
1198
|
+
// to arbitrary user-supplied calendars is filed as Q140.
|
|
1183
1199
|
const settings = loadSettings() as any;
|
|
1184
|
-
const
|
|
1185
|
-
|
|
1186
|
-
|
|
1200
|
+
const HOLIDAY_SOURCES: Array<{ enabled: boolean; calId: string; label: string }> = [
|
|
1201
|
+
{
|
|
1202
|
+
enabled: !!settings?.calendar?.showHolidays,
|
|
1203
|
+
calId: "en.usa#holiday@group.v.calendar.google.com",
|
|
1204
|
+
label: "US",
|
|
1205
|
+
},
|
|
1206
|
+
{
|
|
1207
|
+
enabled: !!settings?.calendar?.showJewishHolidays,
|
|
1208
|
+
calId: "en.jewish#holiday@group.v.calendar.google.com",
|
|
1209
|
+
label: "Jewish",
|
|
1210
|
+
},
|
|
1211
|
+
];
|
|
1212
|
+
const holidayBundles: Array<{ calId: string; events: any[] }> = [];
|
|
1213
|
+
for (const src of HOLIDAY_SOURCES) {
|
|
1214
|
+
if (!src.enabled) continue;
|
|
1187
1215
|
try {
|
|
1188
|
-
|
|
1189
|
-
|
|
1190
|
-
|
|
1216
|
+
const ev = await gsync.listCalendarEvents(tp, fromMs, toMs, src.calId);
|
|
1217
|
+
console.log(` [calendar] pulled ${ev.length} ${src.label} holiday events`);
|
|
1218
|
+
holidayBundles.push({ calId: src.calId, events: ev });
|
|
1191
1219
|
} catch (e: any) {
|
|
1192
|
-
|
|
1193
|
-
// or network; the user's primary calendar already loaded,
|
|
1194
|
-
// so we don't want to block render on holidays.
|
|
1195
|
-
console.warn(` [calendar] holiday pull failed: ${e?.message || e}`);
|
|
1220
|
+
console.warn(` [calendar] ${src.label} holiday pull failed: ${e?.message || e}`);
|
|
1196
1221
|
}
|
|
1197
1222
|
}
|
|
1223
|
+
const enabledHolidayCalIds = new Set(HOLIDAY_SOURCES.filter(s => s.enabled).map(s => s.calId));
|
|
1198
1224
|
let changed = false;
|
|
1199
1225
|
// Upsert by provider_id — dedup globally, not just within the window,
|
|
1200
1226
|
// so an event whose start moves outside the prior query range doesn't
|
|
@@ -1208,35 +1234,39 @@ export class MailxService {
|
|
|
1208
1234
|
this.db.upsertCalendarEvent({ uuid: existing?.uuid, ...local, isHoliday: false });
|
|
1209
1235
|
changed = true;
|
|
1210
1236
|
}
|
|
1211
|
-
for (const
|
|
1212
|
-
const
|
|
1213
|
-
|
|
1214
|
-
|
|
1215
|
-
|
|
1216
|
-
|
|
1217
|
-
|
|
1237
|
+
for (const bundle of holidayBundles) {
|
|
1238
|
+
for (const ev of bundle.events) {
|
|
1239
|
+
const baseLocal = gsync.calendarEventToLocal(ev, accountId);
|
|
1240
|
+
// Override calendarId so reconcile (below) can tell which
|
|
1241
|
+
// holiday source this row belongs to — toggling one source
|
|
1242
|
+
// off must not purge rows from another active source.
|
|
1243
|
+
const local = { ...baseLocal, calendarId: bundle.calId };
|
|
1244
|
+
seenProviderIds.add(ev.id);
|
|
1245
|
+
const existing = this.db.getCalendarEventByProviderId(accountId, ev.id);
|
|
1246
|
+
if (existing && calendarRowEquals(existing, local) && existing.isHoliday) continue;
|
|
1247
|
+
this.db.upsertCalendarEvent({ uuid: existing?.uuid, ...local, isHoliday: true });
|
|
1248
|
+
changed = true;
|
|
1249
|
+
}
|
|
1218
1250
|
}
|
|
1219
1251
|
// Server-side delete reconciliation: any local non-dirty row whose
|
|
1220
1252
|
// start falls in the queried window and whose provider_id wasn't
|
|
1221
|
-
// returned must have been deleted on Google.
|
|
1222
|
-
//
|
|
1223
|
-
//
|
|
1224
|
-
//
|
|
1225
|
-
// the next toggle-on refresh re-pulls them.
|
|
1253
|
+
// returned must have been deleted on Google. Holiday rows are
|
|
1254
|
+
// partitioned by `calendarId`: only purge a holiday row when its
|
|
1255
|
+
// source calendar is currently disabled. Sources that are enabled
|
|
1256
|
+
// but returned nothing for this row keep the row (transient fail).
|
|
1226
1257
|
const localWindow = this.db.getCalendarEvents(accountId, fromMs, toMs);
|
|
1227
1258
|
for (const row of localWindow) {
|
|
1228
1259
|
if (!row.providerId) continue; // local-only, never pushed
|
|
1229
1260
|
if (row.dirty) continue; // locally edited, pending push
|
|
1230
1261
|
if (seenProviderIds.has(row.providerId)) continue;
|
|
1231
|
-
if (row.isHoliday
|
|
1232
|
-
|
|
1233
|
-
|
|
1234
|
-
|
|
1235
|
-
|
|
1236
|
-
|
|
1237
|
-
|
|
1238
|
-
//
|
|
1239
|
-
// calendar fetch may have failed transiently. Keep it.
|
|
1262
|
+
if (row.isHoliday) {
|
|
1263
|
+
const fromActiveSource = enabledHolidayCalIds.has(row.calendarId || "");
|
|
1264
|
+
if (!fromActiveSource) {
|
|
1265
|
+
// Source toggled off — purge.
|
|
1266
|
+
this.db.purgeCalendarEvent(row.uuid);
|
|
1267
|
+
changed = true;
|
|
1268
|
+
}
|
|
1269
|
+
// Source enabled but row missing → transient; keep.
|
|
1240
1270
|
continue;
|
|
1241
1271
|
}
|
|
1242
1272
|
this.db.purgeCalendarEvent(row.uuid);
|