1 parent
2ac1566eca
commit
1bb398acd1
32 files changed
+907
-136
No files matched your search
@@ -70,18 +70,43 @@ function updateNotificationPermissionStatus() {
|
||||
status.textContent = !("Notification" in window) ? "Browser permission: unsupported" : `Browser permission: ${Notification.permission}`;
|
||||
}
|
||||
|
||||
async function loadNotificationPreferences() {
|
||||
function notificationPreferencesForAccount(accountId) {
|
||||
if (accountId && state.notificationPrefsByAccount.has(accountId)) return state.notificationPrefsByAccount.get(accountId);
|
||||
if (accountId === state.accountId) return state.notificationPrefs;
|
||||
return { enabled: true, sound: false, folders: ["INBOX"], dnd_enabled: false, dnd_start: "22:00", dnd_end: "07:00" };
|
||||
}
|
||||
|
||||
async function loadNotificationPreferencesForAccount(accountId, { silent = true } = {}) {
|
||||
if (!accountId) return null;
|
||||
try {
|
||||
const prefs = await request("/settings/notifications", { method: "GET" });
|
||||
state.notificationPrefs = { ...state.notificationPrefs, ...prefs };
|
||||
$("#notify-enabled").checked = Boolean(prefs.enabled);
|
||||
$("#notify-sound").checked = Boolean(prefs.sound);
|
||||
$("#notify-dnd-enabled").checked = Boolean(prefs.dnd_enabled);
|
||||
$("#notify-dnd-start").value = prefs.dnd_start || "22:00";
|
||||
$("#notify-dnd-end").value = prefs.dnd_end || "07:00";
|
||||
renderNotificationFolders(prefs.folders || ["INBOX"]);
|
||||
updateNotificationPermissionStatus();
|
||||
} catch (error) { toast(error.message, "error"); }
|
||||
const prefs = await request("/settings/notifications", { method: "GET", accountId });
|
||||
const normalized = { ...notificationPreferencesForAccount(accountId), ...prefs };
|
||||
state.notificationPrefsByAccount.set(accountId, normalized);
|
||||
if (accountId === state.accountId) state.notificationPrefs = normalized;
|
||||
return normalized;
|
||||
} catch (error) {
|
||||
if (!silent) toast(error.message, "error");
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
async function loadCombinedNotificationPreferences() {
|
||||
if (!multiAccountEnabled()) return;
|
||||
const accountIds = [...state.notificationAccountIds].filter((accountId) => accountId !== state.accountId && state.accounts.some((account) => account.id === accountId));
|
||||
await Promise.all(accountIds.map((accountId) => loadNotificationPreferencesForAccount(accountId)));
|
||||
}
|
||||
|
||||
async function loadNotificationPreferences() {
|
||||
const prefs = await loadNotificationPreferencesForAccount(state.accountId, { silent: false });
|
||||
if (!prefs) return;
|
||||
$("#notify-enabled").checked = Boolean(prefs.enabled);
|
||||
$("#notify-sound").checked = Boolean(prefs.sound);
|
||||
$("#notify-dnd-enabled").checked = Boolean(prefs.dnd_enabled);
|
||||
$("#notify-dnd-start").value = prefs.dnd_start || "22:00";
|
||||
$("#notify-dnd-end").value = prefs.dnd_end || "07:00";
|
||||
renderNotificationFolders(prefs.folders || ["INBOX"]);
|
||||
updateNotificationPermissionStatus();
|
||||
await loadCombinedNotificationPreferences();
|
||||
}
|
||||
|
||||
function renderNotificationFolders(selected) {
|
||||
@@ -105,6 +130,7 @@ async function saveNotificationPreferences() {
|
||||
if ($("#notify-enabled").checked && "Notification" in window && Notification.permission === "default") await requestNotificationPermission();
|
||||
const prefs = await request("/settings/notifications", { method: "PUT", body: JSON.stringify({ enabled: $("#notify-enabled").checked, sound: $("#notify-sound").checked, folders, dnd_enabled: $("#notify-dnd-enabled").checked, dnd_start: $("#notify-dnd-start").value || "22:00", dnd_end: $("#notify-dnd-end").value || "07:00" }) });
|
||||
state.notificationPrefs = { ...state.notificationPrefs, ...prefs };
|
||||
if (state.accountId) state.notificationPrefsByAccount.set(state.accountId, state.notificationPrefs);
|
||||
updateNotificationPermissionStatus();
|
||||
toast("Notification settings saved");
|
||||
} catch (error) { toast(error.message, "error"); }
|
||||
@@ -163,10 +189,14 @@ function playNotificationSound() {
|
||||
function renderSyncActivityIndicator() {
|
||||
const indicator = $("#indexing-indicator");
|
||||
if (!indicator) return;
|
||||
const busy = Boolean(state.indexingActive || state.imapSyncActive);
|
||||
const busy = Boolean(state.messageLoadPending > 0 || state.indexingActive || state.imapSyncActive);
|
||||
indicator.classList.toggle("hidden", !busy);
|
||||
indicator.classList.toggle("active", busy);
|
||||
const parts = [];
|
||||
if (state.messageLoadPending > 0) {
|
||||
const folder = state.folder ? ` · ${state.folder}` : "";
|
||||
parts.push(`Loading messages${folder}`);
|
||||
}
|
||||
if (state.imapSyncActive || state.imapSyncPending > 0) {
|
||||
const folder = state.imapSyncFolder ? ` · ${state.imapSyncFolder}` : "";
|
||||
const pending = state.imapSyncPending > 0 ? ` · ${state.imapSyncPending} headers pending in task` : "";
|
||||
@@ -190,6 +220,16 @@ function setIndexingIndicator(active, pending = 0) {
|
||||
renderSyncActivityIndicator();
|
||||
}
|
||||
|
||||
function beginMessageLoadActivity() {
|
||||
state.messageLoadPending = Math.max(0, Number(state.messageLoadPending) || 0) + 1;
|
||||
renderSyncActivityIndicator();
|
||||
}
|
||||
|
||||
function endMessageLoadActivity() {
|
||||
state.messageLoadPending = Math.max(0, (Number(state.messageLoadPending) || 0) - 1);
|
||||
renderSyncActivityIndicator();
|
||||
}
|
||||
|
||||
function setImapSyncIndicator(active, folder = null, pending = 0) {
|
||||
state.imapSyncActive = Boolean(active);
|
||||
state.imapSyncFolder = folder || null;
|
||||
@@ -318,7 +358,7 @@ async function openRealtimeNotificationTarget(accountId, data) {
|
||||
}
|
||||
|
||||
function notifyNewMail(data, accountId) {
|
||||
const prefs = state.notificationPrefs || {};
|
||||
const prefs = notificationPreferencesForAccount(accountId) || {};
|
||||
if (!prefs.enabled || dndActive(prefs)) return;
|
||||
const folders = prefs.folders || [];
|
||||
if (folders.length && !folders.includes(data.folder)) return;
|
||||
@@ -505,7 +545,8 @@ function connectRealtime() {
|
||||
clearTimeout(state.wsRetryTimer);
|
||||
state.wsRetryTimer = null;
|
||||
const protocol = location.protocol === "https:" ? "wss:" : "ws:";
|
||||
const socket = new WebSocket(`${protocol}//${location.host}${BASE}/api/ws`);
|
||||
const accountQuery = state.accountId ? `?account_id=${encodeURIComponent(state.accountId)}` : "";
|
||||
const socket = new WebSocket(`${protocol}//${location.host}${BASE}/api/ws${accountQuery}`);
|
||||
state.ws = socket;
|
||||
socket.onopen = () => {
|
||||
if (state.ws !== socket) return;
|
||||
@@ -533,7 +574,7 @@ function connectRealtime() {
|
||||
if (event.type === "NewMessages") {
|
||||
const data = event.data || {};
|
||||
const duplicate = isDuplicateNewMailNotification(data, payload.accountId);
|
||||
if (!duplicate && !realtimeNewMailNotificationsSuppressed(data, payload.accountId)) {
|
||||
if (!duplicate && notificationAccountEnabled(payload.accountId) && !realtimeNewMailNotificationsSuppressed(data, payload.accountId)) {
|
||||
toastNewMail(data, payload.accountId);
|
||||
notifyNewMail(data, payload.accountId);
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user