fix(chat): catch-up сообщений при возврате на вкладку; fix(sw): фокус на открытой вкладке вместо навигации всех; fix(history): числа не резолвятся в имена пользователей
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
const CACHE_NAME = 'iistwin-pwa-v13';
|
||||
const CACHE_NAME = 'iistwin-pwa-v14';
|
||||
const STATIC_ASSETS = [
|
||||
'/',
|
||||
'/index.html',
|
||||
@@ -577,47 +577,55 @@ self.addEventListener('push', (event) => {
|
||||
);
|
||||
});
|
||||
|
||||
// Нормализация URL для сравнения «та же ли страница открыта»:
|
||||
// сравниваем только pathname (суффикс), игнорируем query (?tab=chat) и origin.
|
||||
// Матчим по суффиксу, чтобы ловить и org-префиксные роуты (/:org/tasks/<id>).
|
||||
function samePage(clientUrl, targetUrl) {
|
||||
try {
|
||||
const targetPath = new URL(targetUrl, self.location.origin).pathname;
|
||||
const clientPath = new URL(clientUrl, self.location.origin).pathname;
|
||||
if (clientPath === targetPath) return true;
|
||||
// суффикс: /tasks/123 или /chat/123 в конце пути
|
||||
const suffixMatch = targetPath.match(/\/(tasks|chat)\/(\d+)$/);
|
||||
if (suffixMatch && clientPath.endsWith(suffixMatch[0])) return true;
|
||||
return false;
|
||||
} catch {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// focus() штатно отклоняется по спецификации (нет transient activation, окно
|
||||
// не получило фокус и т.п.) — он ВСЕГДА в отдельном try/catch, иначе его отказ
|
||||
// роняет общий catch и цикл идёт навигировать следующую вкладку.
|
||||
async function focusClient(client) {
|
||||
try {
|
||||
if ('focus' in client) await client.focus();
|
||||
} catch (err) {
|
||||
console.log('[SW] focus() rejected (best effort):', err?.message || err);
|
||||
}
|
||||
}
|
||||
|
||||
async function openOrFocusChat(url) {
|
||||
const absoluteUrl = new URL(url, self.location.origin).href;
|
||||
console.log('[SW] openOrFocusChat:', absoluteUrl);
|
||||
|
||||
try {
|
||||
// Ищем любые окна (включая неподконтрольные) — focus работает и на них,
|
||||
// а navigate может не сработать на uncontrolled, поэтому оборачиваем в try/catch.
|
||||
const clientList = await clients.matchAll({ type: 'window', includeUncontrolled: true });
|
||||
console.log('[SW] clients found:', clientList.length);
|
||||
|
||||
// Сначала ищем клиент с уже открытым этим URL — просто фокусируем.
|
||||
// 1. Задача/чат уже открыт в какой-то вкладке — просто фокусируем её.
|
||||
for (const client of clientList) {
|
||||
try {
|
||||
if (client.url === absoluteUrl && 'focus' in client) {
|
||||
console.log('[SW] focusing existing client with same URL');
|
||||
return await client.focus();
|
||||
}
|
||||
} catch (err) {
|
||||
console.error('[SW] focus same-url client error:', err);
|
||||
if (samePage(client.url, absoluteUrl)) {
|
||||
console.log('[SW] page already open, focusing client:', client.url);
|
||||
await focusClient(client);
|
||||
return client;
|
||||
}
|
||||
}
|
||||
|
||||
// Затем пытаемся навигировать любой доступный клиент.
|
||||
for (const client of clientList) {
|
||||
try {
|
||||
if ('focus' in client) {
|
||||
console.log('[SW] navigating client to', absoluteUrl);
|
||||
await client.navigate(absoluteUrl);
|
||||
return await client.focus();
|
||||
}
|
||||
} catch (err) {
|
||||
console.error('[SW] navigate client error:', err);
|
||||
}
|
||||
}
|
||||
|
||||
// Нет подходящих клиентов — открываем новое окно/вкладку.
|
||||
// 2. Не открыта — открываем НОВУЮ вкладку, чужие не перехватываем.
|
||||
console.log('[SW] opening new window');
|
||||
const newClient = await clients.openWindow(absoluteUrl);
|
||||
if (newClient && 'focus' in newClient) {
|
||||
return await newClient.focus();
|
||||
}
|
||||
if (newClient) await focusClient(newClient);
|
||||
return newClient;
|
||||
} catch (err) {
|
||||
console.error('[SW] openOrFocusChat fatal error:', err);
|
||||
|
||||
Reference in New Issue
Block a user