fix: update support page content without page refresh
This commit is contained in:
@@ -1,6 +1,11 @@
|
|||||||
import { writable } from "svelte/store";
|
import { writable } from "svelte/store";
|
||||||
|
|
||||||
export function createAdminSupportStore({ api, onToast, at }) {
|
export function createAdminSupportStore({ api, onToast, at }) {
|
||||||
|
const OPEN_TICKET_POLL_MS = 3_000;
|
||||||
|
const STATS_POLL_MS = 30_000;
|
||||||
|
const HIDDEN_POLL_MS = 300_000;
|
||||||
|
const ERROR_POLL_MS = 90_000;
|
||||||
|
|
||||||
const state = writable({
|
const state = writable({
|
||||||
tickets: [],
|
tickets: [],
|
||||||
stats: { active: 0, closed: 0, open: 0, awaiting_admin: 0, total_unread_admin: 0 },
|
stats: { active: 0, closed: 0, open: 0, awaiting_admin: 0, total_unread_admin: 0 },
|
||||||
@@ -21,13 +26,35 @@ export function createAdminSupportStore({ api, onToast, at }) {
|
|||||||
composerInternalNote: false,
|
composerInternalNote: false,
|
||||||
});
|
});
|
||||||
|
|
||||||
let pollTimer = null;
|
let statsPollTimer = null;
|
||||||
|
let ticketPollTimer = null;
|
||||||
|
let ticketPollInFlight = false;
|
||||||
|
let visibilityHandler = null;
|
||||||
|
let resumeHandler = null;
|
||||||
let active = "stats";
|
let active = "stats";
|
||||||
|
|
||||||
function setActive(section) {
|
function setActive(section) {
|
||||||
active = section;
|
active = section;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function getSnapshot() {
|
||||||
|
let snapshot;
|
||||||
|
const unsubscribe = state.subscribe((s) => {
|
||||||
|
snapshot = s;
|
||||||
|
});
|
||||||
|
unsubscribe();
|
||||||
|
return snapshot;
|
||||||
|
}
|
||||||
|
|
||||||
|
function currentOpenedTicketId() {
|
||||||
|
return getSnapshot()?.openedTicketId || null;
|
||||||
|
}
|
||||||
|
|
||||||
|
function lastMessageId(messages) {
|
||||||
|
const list = Array.isArray(messages) ? messages : [];
|
||||||
|
return Number(list.at(-1)?.message_id || 0);
|
||||||
|
}
|
||||||
|
|
||||||
function pushTicketPath(ticketId) {
|
function pushTicketPath(ticketId) {
|
||||||
if (typeof window === "undefined" || window.location.protocol === "file:") return;
|
if (typeof window === "undefined" || window.location.protocol === "file:") return;
|
||||||
if (active !== "support") return;
|
if (active !== "support") return;
|
||||||
@@ -46,13 +73,11 @@ export function createAdminSupportStore({ api, onToast, at }) {
|
|||||||
if (res?.ok) state.update((s) => ({ ...s, stats: res.stats || s.stats }));
|
if (res?.ok) state.update((s) => ({ ...s, stats: res.stats || s.stats }));
|
||||||
}
|
}
|
||||||
|
|
||||||
async function loadList() {
|
async function loadList(options = {}) {
|
||||||
state.update((s) => ({ ...s, loading: true }));
|
const silent = options.silent === true;
|
||||||
|
if (!silent) state.update((s) => ({ ...s, loading: true }));
|
||||||
let filters;
|
let filters;
|
||||||
state.update((s) => {
|
filters = getSnapshot()?.filters;
|
||||||
filters = s.filters;
|
|
||||||
return s;
|
|
||||||
});
|
|
||||||
try {
|
try {
|
||||||
const params = new URLSearchParams({ limit: "50", offset: "0" });
|
const params = new URLSearchParams({ limit: "50", offset: "0" });
|
||||||
for (const [key, value] of Object.entries(filters || {})) {
|
for (const [key, value] of Object.entries(filters || {})) {
|
||||||
@@ -62,10 +87,45 @@ export function createAdminSupportStore({ api, onToast, at }) {
|
|||||||
if (res?.ok) state.update((s) => ({ ...s, tickets: res.tickets || [] }));
|
if (res?.ok) state.update((s) => ({ ...s, tickets: res.tickets || [] }));
|
||||||
else if (res?.error) onToast(res.message || res.error);
|
else if (res?.error) onToast(res.message || res.error);
|
||||||
} finally {
|
} finally {
|
||||||
state.update((s) => ({ ...s, loading: false }));
|
if (!silent) state.update((s) => ({ ...s, loading: false }));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function refreshCurrentTicket(ticketId) {
|
||||||
|
const id = Number(ticketId);
|
||||||
|
if (!id) return null;
|
||||||
|
const res = await api(`/admin/support/tickets/${id}`);
|
||||||
|
if (!res?.ok) return res;
|
||||||
|
|
||||||
|
let shouldRefreshList = false;
|
||||||
|
let shouldMarkRead = false;
|
||||||
|
state.update((s) => {
|
||||||
|
if (s.openedTicketId !== id) return s;
|
||||||
|
const nextMessages = res.messages || [];
|
||||||
|
shouldRefreshList =
|
||||||
|
lastMessageId(nextMessages) !== lastMessageId(s.messages) ||
|
||||||
|
res.ticket?.status !== s.openedTicket?.status ||
|
||||||
|
Number(res.ticket?.unread_admin_count || 0) !==
|
||||||
|
Number(s.openedTicket?.unread_admin_count || 0);
|
||||||
|
shouldMarkRead = Number(res.ticket?.unread_admin_count || 0) > 0;
|
||||||
|
return {
|
||||||
|
...s,
|
||||||
|
openedTicket: res.ticket,
|
||||||
|
messages: nextMessages,
|
||||||
|
userSnapshot: res.user_snapshot || null,
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
if (currentOpenedTicketId() !== id) return res;
|
||||||
|
if (shouldMarkRead) {
|
||||||
|
await api(`/admin/support/tickets/${id}/read`, { method: "POST", body: "{}" });
|
||||||
|
await loadStats();
|
||||||
|
shouldRefreshList = true;
|
||||||
|
}
|
||||||
|
if (shouldRefreshList) await loadList({ silent: true });
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
async function openTicket(ticketId, opts = {}) {
|
async function openTicket(ticketId, opts = {}) {
|
||||||
const id = Number(ticketId);
|
const id = Number(ticketId);
|
||||||
if (!id) return;
|
if (!id) return;
|
||||||
@@ -81,17 +141,25 @@ export function createAdminSupportStore({ api, onToast, at }) {
|
|||||||
try {
|
try {
|
||||||
const res = await api(`/admin/support/tickets/${id}`);
|
const res = await api(`/admin/support/tickets/${id}`);
|
||||||
if (res?.ok) {
|
if (res?.ok) {
|
||||||
state.update((s) => ({
|
state.update((s) =>
|
||||||
...s,
|
s.openedTicketId === id
|
||||||
openedTicket: res.ticket,
|
? {
|
||||||
messages: res.messages || [],
|
...s,
|
||||||
userSnapshot: res.user_snapshot || null,
|
openedTicket: res.ticket,
|
||||||
}));
|
messages: res.messages || [],
|
||||||
await api(`/admin/support/tickets/${id}/read`, { method: "POST", body: "{}" });
|
userSnapshot: res.user_snapshot || null,
|
||||||
await loadStats();
|
}
|
||||||
|
: s
|
||||||
|
);
|
||||||
|
if (currentOpenedTicketId() === id) {
|
||||||
|
await api(`/admin/support/tickets/${id}/read`, { method: "POST", body: "{}" });
|
||||||
|
await loadStats();
|
||||||
|
await loadList({ silent: true });
|
||||||
|
scheduleTicketPoll(OPEN_TICKET_POLL_MS);
|
||||||
|
}
|
||||||
} else onToast(res?.message || res?.error || "not_found");
|
} else onToast(res?.message || res?.error || "not_found");
|
||||||
} finally {
|
} finally {
|
||||||
state.update((s) => ({ ...s, detailLoading: false }));
|
state.update((s) => (s.openedTicketId === id ? { ...s, detailLoading: false } : s));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -103,6 +171,7 @@ export function createAdminSupportStore({ api, onToast, at }) {
|
|||||||
messages: [],
|
messages: [],
|
||||||
userSnapshot: null,
|
userSnapshot: null,
|
||||||
}));
|
}));
|
||||||
|
clearTicketPollTimer();
|
||||||
if (!opts.skipPush) pushTicketPath(null);
|
if (!opts.skipPush) pushTicketPath(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -114,7 +183,10 @@ export function createAdminSupportStore({ api, onToast, at }) {
|
|||||||
internal = s.composerInternalNote;
|
internal = s.composerInternalNote;
|
||||||
return { ...s, sending: true };
|
return { ...s, sending: true };
|
||||||
});
|
});
|
||||||
if (!current) return;
|
if (!current) {
|
||||||
|
state.update((s) => ({ ...s, sending: false }));
|
||||||
|
return;
|
||||||
|
}
|
||||||
try {
|
try {
|
||||||
const res = await api(`/admin/support/tickets/${current}/messages`, {
|
const res = await api(`/admin/support/tickets/${current}/messages`, {
|
||||||
method: "POST",
|
method: "POST",
|
||||||
@@ -183,17 +255,99 @@ export function createAdminSupportStore({ api, onToast, at }) {
|
|||||||
loadList();
|
loadList();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function clearTicketPollTimer() {
|
||||||
|
if (!ticketPollTimer || typeof window === "undefined") return;
|
||||||
|
window.clearTimeout(ticketPollTimer);
|
||||||
|
ticketPollTimer = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
function scheduleTicketPoll(delayMs = OPEN_TICKET_POLL_MS) {
|
||||||
|
if (typeof window === "undefined") return;
|
||||||
|
clearTicketPollTimer();
|
||||||
|
if (!currentOpenedTicketId()) return;
|
||||||
|
ticketPollTimer = window.setTimeout(runTicketPoll, Math.max(0, Number(delayMs) || 0));
|
||||||
|
}
|
||||||
|
|
||||||
|
async function runTicketPoll() {
|
||||||
|
ticketPollTimer = null;
|
||||||
|
if (typeof document !== "undefined" && document.visibilityState !== "visible") {
|
||||||
|
scheduleTicketPoll(HIDDEN_POLL_MS);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const ticketId = currentOpenedTicketId();
|
||||||
|
if (!ticketId) return;
|
||||||
|
if (ticketPollInFlight) {
|
||||||
|
scheduleTicketPoll(OPEN_TICKET_POLL_MS);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ticketPollInFlight = true;
|
||||||
|
let failed = false;
|
||||||
|
try {
|
||||||
|
const res = await refreshCurrentTicket(ticketId);
|
||||||
|
if (res?.error) failed = true;
|
||||||
|
} catch (_error) {
|
||||||
|
failed = true;
|
||||||
|
} finally {
|
||||||
|
ticketPollInFlight = false;
|
||||||
|
if (currentOpenedTicketId()) {
|
||||||
|
scheduleTicketPoll(failed ? ERROR_POLL_MS : OPEN_TICKET_POLL_MS);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function ensureRealtimeListeners() {
|
||||||
|
if (typeof window === "undefined") return;
|
||||||
|
if (!visibilityHandler && typeof document !== "undefined") {
|
||||||
|
visibilityHandler = () => {
|
||||||
|
if (document.visibilityState === "visible") {
|
||||||
|
loadStats();
|
||||||
|
scheduleTicketPoll(0);
|
||||||
|
} else {
|
||||||
|
scheduleTicketPoll(HIDDEN_POLL_MS);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
document.addEventListener("visibilitychange", visibilityHandler);
|
||||||
|
}
|
||||||
|
if (!resumeHandler) {
|
||||||
|
resumeHandler = () => {
|
||||||
|
if (typeof document !== "undefined" && document.visibilityState === "hidden") return;
|
||||||
|
loadStats();
|
||||||
|
scheduleTicketPoll(0);
|
||||||
|
};
|
||||||
|
window.addEventListener("focus", resumeHandler);
|
||||||
|
window.addEventListener("pageshow", resumeHandler);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function stopRealtimeListeners() {
|
||||||
|
if (visibilityHandler && typeof document !== "undefined") {
|
||||||
|
document.removeEventListener("visibilitychange", visibilityHandler);
|
||||||
|
visibilityHandler = null;
|
||||||
|
}
|
||||||
|
if (resumeHandler && typeof window !== "undefined") {
|
||||||
|
window.removeEventListener("focus", resumeHandler);
|
||||||
|
window.removeEventListener("pageshow", resumeHandler);
|
||||||
|
resumeHandler = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function startStatsPolling() {
|
function startStatsPolling() {
|
||||||
if (pollTimer || typeof window === "undefined") return;
|
if (typeof window === "undefined") return;
|
||||||
|
ensureRealtimeListeners();
|
||||||
|
if (statsPollTimer) return;
|
||||||
loadStats();
|
loadStats();
|
||||||
pollTimer = window.setInterval(() => {
|
statsPollTimer = window.setInterval(() => {
|
||||||
if (document.visibilityState === "visible") loadStats();
|
if (document.visibilityState === "visible") loadStats();
|
||||||
}, 30000);
|
}, STATS_POLL_MS);
|
||||||
}
|
}
|
||||||
|
|
||||||
function stopStatsPolling() {
|
function stopStatsPolling() {
|
||||||
if (pollTimer) window.clearInterval(pollTimer);
|
if (statsPollTimer) window.clearInterval(statsPollTimer);
|
||||||
pollTimer = null;
|
statsPollTimer = null;
|
||||||
|
clearTicketPollTimer();
|
||||||
|
ticketPollInFlight = false;
|
||||||
|
stopRealtimeListeners();
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
|||||||
@@ -1,7 +1,8 @@
|
|||||||
import { writable } from "svelte/store";
|
import { writable } from "svelte/store";
|
||||||
|
|
||||||
export function createSupportStore({ api, t, showToast }) {
|
export function createSupportStore({ api, t, showToast }) {
|
||||||
const ACTIVE_POLL_MS = 15_000;
|
const OPEN_TICKET_POLL_MS = 3_000;
|
||||||
|
const ACTIVE_POLL_MS = 8_000;
|
||||||
const BACKGROUND_POLL_MS = 45_000;
|
const BACKGROUND_POLL_MS = 45_000;
|
||||||
const IDLE_POLL_MS = 120_000;
|
const IDLE_POLL_MS = 120_000;
|
||||||
const PAUSED_POLL_MS = 300_000;
|
const PAUSED_POLL_MS = 300_000;
|
||||||
@@ -34,6 +35,7 @@ export function createSupportStore({ api, t, showToast }) {
|
|||||||
let emptyUnreadPolls = 0;
|
let emptyUnreadPolls = 0;
|
||||||
let lastUnreadCount = 0;
|
let lastUnreadCount = 0;
|
||||||
let visibilityHandler = null;
|
let visibilityHandler = null;
|
||||||
|
let resumeHandler = null;
|
||||||
let listRequestSeq = 0;
|
let listRequestSeq = 0;
|
||||||
let listPromise = null;
|
let listPromise = null;
|
||||||
let listPromiseKey = "";
|
let listPromiseKey = "";
|
||||||
@@ -55,6 +57,19 @@ export function createSupportStore({ api, t, showToast }) {
|
|||||||
return BACKGROUND_POLL_MS;
|
return BACKGROUND_POLL_MS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function getSnapshot() {
|
||||||
|
let snapshot;
|
||||||
|
const unsubscribe = state.subscribe((s) => {
|
||||||
|
snapshot = s;
|
||||||
|
});
|
||||||
|
unsubscribe();
|
||||||
|
return snapshot;
|
||||||
|
}
|
||||||
|
|
||||||
|
function activePollDelay() {
|
||||||
|
return currentOpenedTicketId() ? OPEN_TICKET_POLL_MS : ACTIVE_POLL_MS;
|
||||||
|
}
|
||||||
|
|
||||||
function clearPollTimer() {
|
function clearPollTimer() {
|
||||||
if (!pollTimer) return;
|
if (!pollTimer) return;
|
||||||
if (typeof window !== "undefined") window.clearTimeout(pollTimer);
|
if (typeof window !== "undefined") window.clearTimeout(pollTimer);
|
||||||
@@ -68,12 +83,7 @@ export function createSupportStore({ api, t, showToast }) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function currentOpenedTicketId() {
|
function currentOpenedTicketId() {
|
||||||
let opened = null;
|
return getSnapshot()?.openedTicketId || null;
|
||||||
state.update((s) => {
|
|
||||||
opened = s.openedTicketId;
|
|
||||||
return s;
|
|
||||||
});
|
|
||||||
return opened;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function hydrateUnread(value) {
|
function hydrateUnread(value) {
|
||||||
@@ -138,12 +148,18 @@ export function createSupportStore({ api, t, showToast }) {
|
|||||||
try {
|
try {
|
||||||
const res = await api(`/support/tickets/${id}`);
|
const res = await api(`/support/tickets/${id}`);
|
||||||
if (res?.ok) {
|
if (res?.ok) {
|
||||||
state.update((s) => ({
|
state.update((s) =>
|
||||||
...s,
|
s.openedTicketId === id
|
||||||
openedTicket: res.ticket,
|
? {
|
||||||
messages: res.messages || [],
|
...s,
|
||||||
}));
|
openedTicket: res.ticket,
|
||||||
await markRead(id);
|
messages: res.messages || [],
|
||||||
|
}
|
||||||
|
: s
|
||||||
|
);
|
||||||
|
if (currentOpenedTicketId() === id && Number(res.ticket?.unread_user_count || 0) > 0) {
|
||||||
|
await markRead(id, { silent: true });
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return res;
|
return res;
|
||||||
} catch {
|
} catch {
|
||||||
@@ -194,17 +210,22 @@ export function createSupportStore({ api, t, showToast }) {
|
|||||||
try {
|
try {
|
||||||
const res = await api(`/support/tickets/${id}`);
|
const res = await api(`/support/tickets/${id}`);
|
||||||
if (res?.ok) {
|
if (res?.ok) {
|
||||||
state.update((s) => ({
|
state.update((s) =>
|
||||||
...s,
|
s.openedTicketId === id
|
||||||
openedTicket: res.ticket,
|
? {
|
||||||
messages: res.messages || [],
|
...s,
|
||||||
}));
|
openedTicket: res.ticket,
|
||||||
await markRead(id);
|
messages: res.messages || [],
|
||||||
|
}
|
||||||
|
: s
|
||||||
|
);
|
||||||
|
if (currentOpenedTicketId() === id) await markRead(id);
|
||||||
} else {
|
} else {
|
||||||
showToast(res?.message || res?.error || "not_found");
|
showToast(res?.message || res?.error || "not_found");
|
||||||
}
|
}
|
||||||
} finally {
|
} finally {
|
||||||
state.update((s) => ({ ...s, detailLoading: false }));
|
state.update((s) => (s.openedTicketId === id ? { ...s, detailLoading: false } : s));
|
||||||
|
if (pollingEnabled) schedulePoll(activePollDelay());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -227,7 +248,10 @@ export function createSupportStore({ api, t, showToast }) {
|
|||||||
ticketId = s.openedTicketId;
|
ticketId = s.openedTicketId;
|
||||||
return { ...s, sending: true };
|
return { ...s, sending: true };
|
||||||
});
|
});
|
||||||
if (!ticketId) return;
|
if (!ticketId) {
|
||||||
|
state.update((s) => ({ ...s, sending: false }));
|
||||||
|
return;
|
||||||
|
}
|
||||||
try {
|
try {
|
||||||
const res = await api(`/support/tickets/${ticketId}/messages`, {
|
const res = await api(`/support/tickets/${ticketId}/messages`, {
|
||||||
method: "POST",
|
method: "POST",
|
||||||
@@ -248,20 +272,15 @@ export function createSupportStore({ api, t, showToast }) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async function markRead(ticketId = null) {
|
async function markRead(ticketId = null, options = {}) {
|
||||||
const id =
|
const id =
|
||||||
ticketId ||
|
ticketId ||
|
||||||
(() => {
|
(() => {
|
||||||
let current = null;
|
return currentOpenedTicketId();
|
||||||
state.update((s) => {
|
|
||||||
current = s.openedTicketId;
|
|
||||||
return s;
|
|
||||||
});
|
|
||||||
return current;
|
|
||||||
})();
|
})();
|
||||||
if (!id) return;
|
if (!id) return;
|
||||||
await api(`/support/tickets/${id}/read`, { method: "POST", body: "{}" });
|
await api(`/support/tickets/${id}/read`, { method: "POST", body: "{}" });
|
||||||
await refreshUnread();
|
await refreshUnread({ silent: options.silent === true });
|
||||||
}
|
}
|
||||||
|
|
||||||
async function refreshUnread(options = {}) {
|
async function refreshUnread(options = {}) {
|
||||||
@@ -318,7 +337,9 @@ export function createSupportStore({ api, t, showToast }) {
|
|||||||
failed = true;
|
failed = true;
|
||||||
} finally {
|
} finally {
|
||||||
pollInFlight = false;
|
pollInFlight = false;
|
||||||
if (pollingEnabled) schedulePoll(failed ? ERROR_POLL_MS : nextPollDelay());
|
if (pollingEnabled) {
|
||||||
|
schedulePoll(failed ? ERROR_POLL_MS : supportActive ? activePollDelay() : nextPollDelay());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -327,7 +348,7 @@ export function createSupportStore({ api, t, showToast }) {
|
|||||||
if (supportActive === next) return;
|
if (supportActive === next) return;
|
||||||
supportActive = next;
|
supportActive = next;
|
||||||
if (supportActive) emptyUnreadPolls = 0;
|
if (supportActive) emptyUnreadPolls = 0;
|
||||||
if (pollingEnabled) schedulePoll(supportActive ? ACTIVE_POLL_MS : nextPollDelay());
|
if (pollingEnabled) schedulePoll(supportActive ? 0 : nextPollDelay());
|
||||||
}
|
}
|
||||||
|
|
||||||
function startPolling(options = {}) {
|
function startPolling(options = {}) {
|
||||||
@@ -348,10 +369,20 @@ export function createSupportStore({ api, t, showToast }) {
|
|||||||
};
|
};
|
||||||
document.addEventListener("visibilitychange", visibilityHandler);
|
document.addEventListener("visibilitychange", visibilityHandler);
|
||||||
}
|
}
|
||||||
|
if (!resumeHandler) {
|
||||||
|
resumeHandler = () => {
|
||||||
|
if (!pollingEnabled) return;
|
||||||
|
if (typeof document !== "undefined" && document.visibilityState === "hidden") return;
|
||||||
|
emptyUnreadPolls = 0;
|
||||||
|
schedulePoll(0);
|
||||||
|
};
|
||||||
|
window.addEventListener("focus", resumeHandler);
|
||||||
|
window.addEventListener("pageshow", resumeHandler);
|
||||||
|
}
|
||||||
if (!pollTimer && !pollInFlight) {
|
if (!pollTimer && !pollInFlight) {
|
||||||
schedulePoll(supportActive ? ACTIVE_POLL_MS : nextPollDelay());
|
schedulePoll(supportActive ? 0 : nextPollDelay());
|
||||||
} else if (supportActive) {
|
} else if (supportActive) {
|
||||||
schedulePoll(ACTIVE_POLL_MS);
|
schedulePoll(activePollDelay());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -361,6 +392,13 @@ export function createSupportStore({ api, t, showToast }) {
|
|||||||
visibilityHandler = null;
|
visibilityHandler = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function stopResumeListeners() {
|
||||||
|
if (!resumeHandler || typeof window === "undefined") return;
|
||||||
|
window.removeEventListener("focus", resumeHandler);
|
||||||
|
window.removeEventListener("pageshow", resumeHandler);
|
||||||
|
resumeHandler = null;
|
||||||
|
}
|
||||||
|
|
||||||
function closePolling() {
|
function closePolling() {
|
||||||
pollingEnabled = false;
|
pollingEnabled = false;
|
||||||
supportActive = false;
|
supportActive = false;
|
||||||
@@ -368,6 +406,7 @@ export function createSupportStore({ api, t, showToast }) {
|
|||||||
emptyUnreadPolls = 0;
|
emptyUnreadPolls = 0;
|
||||||
clearPollTimer();
|
clearPollTimer();
|
||||||
stopVisibilityListener();
|
stopVisibilityListener();
|
||||||
|
stopResumeListeners();
|
||||||
state.update((s) => (s.polling ? { ...s, polling: false } : s));
|
state.update((s) => (s.polling ? { ...s, polling: false } : s));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user