Исправлен клик по push-уведомлению: открытие задачи/чата из тела, Ответить и Прочитано; controlled-clients + fallback openWindow
This commit is contained in:
@@ -1,4 +1,4 @@
|
|||||||
const CACHE_NAME = 'iistwin-pwa-v10';
|
const CACHE_NAME = 'iistwin-pwa-v11';
|
||||||
const STATIC_ASSETS = [
|
const STATIC_ASSETS = [
|
||||||
'/',
|
'/',
|
||||||
'/index.html',
|
'/index.html',
|
||||||
@@ -568,23 +568,38 @@ self.addEventListener('push', (event) => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
async function openOrFocusChat(url) {
|
async function openOrFocusChat(url) {
|
||||||
const clientList = await clients.matchAll({ type: 'window', includeUncontrolled: true });
|
// Only controlled clients can be navigated/focused reliably from a SW.
|
||||||
// Prefer a client that already has the same path (ignoring query string).
|
const clientList = await clients.matchAll({ type: 'window', includeUncontrolled: false });
|
||||||
const targetPath = url.split('?')[0];
|
const absoluteUrl = new URL(url, self.location.origin).href;
|
||||||
|
const targetPath = new URL(absoluteUrl).pathname;
|
||||||
|
|
||||||
|
// Prefer a controlled client that already has the same path (ignoring query string).
|
||||||
for (const client of clientList) {
|
for (const client of clientList) {
|
||||||
if (client.url.includes(self.location.origin) && client.url.split('?')[0] === targetPath && 'focus' in client) {
|
try {
|
||||||
await client.navigate(url);
|
const clientPath = new URL(client.url).pathname;
|
||||||
return client.focus();
|
if (clientPath === targetPath && 'focus' in client) {
|
||||||
|
await client.navigate(absoluteUrl);
|
||||||
|
return await client.focus();
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
console.error('[SW] Failed to navigate matching client:', err);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Otherwise focus any same-origin client and navigate it.
|
|
||||||
|
// Otherwise focus any controlled same-origin client and navigate it.
|
||||||
for (const client of clientList) {
|
for (const client of clientList) {
|
||||||
if (client.url.includes(self.location.origin) && 'focus' in client) {
|
try {
|
||||||
await client.navigate(url);
|
if ('focus' in client) {
|
||||||
return client.focus();
|
await client.navigate(absoluteUrl);
|
||||||
|
return await client.focus();
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
console.error('[SW] Failed to navigate client:', err);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return clients.openWindow(url);
|
|
||||||
|
// No usable client — open a new window/tab. This is always allowed in notificationclick.
|
||||||
|
return await clients.openWindow(absoluteUrl);
|
||||||
}
|
}
|
||||||
|
|
||||||
async function markNotificationRead(data) {
|
async function markNotificationRead(data) {
|
||||||
@@ -615,11 +630,18 @@ self.addEventListener('notificationclick', (event) => {
|
|||||||
const urlToOpen = data.url || '/';
|
const urlToOpen = data.url || '/';
|
||||||
|
|
||||||
if (event.action === 'read') {
|
if (event.action === 'read') {
|
||||||
event.waitUntil(markNotificationRead(data));
|
// "Прочитано": помечаем прочитанным и всё равно открываем задачу/чат, как ожидает пользователь.
|
||||||
|
event.waitUntil(
|
||||||
|
Promise.all([
|
||||||
|
navigator.clearAppBadge ? navigator.clearAppBadge() : Promise.resolve(),
|
||||||
|
markNotificationRead(data),
|
||||||
|
openOrFocusChat(urlToOpen),
|
||||||
|
])
|
||||||
|
);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 'reply' or body click: open the chat and focus an existing tab if possible.
|
// Body click or 'reply' action: open the linked task/chat and focus an existing tab if possible.
|
||||||
event.waitUntil(
|
event.waitUntil(
|
||||||
Promise.all([
|
Promise.all([
|
||||||
navigator.clearAppBadge ? navigator.clearAppBadge() : Promise.resolve(),
|
navigator.clearAppBadge ? navigator.clearAppBadge() : Promise.resolve(),
|
||||||
|
|||||||
Reference in New Issue
Block a user