diff --git a/locales/ja-JP.yml b/locales/ja-JP.yml index bb1c41d866..598a320045 100644 --- a/locales/ja-JP.yml +++ b/locales/ja-JP.yml @@ -1568,6 +1568,8 @@ _notification: youReceivedFollowRequest: "フォローリクエストが来ました" yourFollowRequestAccepted: "フォローリクエストが承認されました" youWereInvitedToGroup: "{userName}があなたをグループに招待しました" + readAllNotifications: "通知はすべて既読です" + readAllMessagingMessages: "チャットはすべて既読です" _types: all: "すべて" diff --git a/src/client/init.ts b/src/client/init.ts index e3441976e3..27cca0eb42 100644 --- a/src/client/init.ts +++ b/src/client/init.ts @@ -56,7 +56,7 @@ import { router } from '@/router'; import { applyTheme } from '@/scripts/theme'; import { isDeviceDarkmode } from '@/scripts/is-device-darkmode'; import { i18n } from '@/i18n'; -import { api, stream, isMobile, dialog, post } from '@/os'; +import { stream, isMobile, dialog, post } from '@/os'; import * as sound from '@/scripts/sound'; import { $i, refreshAccount, login, updateAccount, signout } from '@/account'; import { defaultStore, ColdDeviceStorage } from '@/store'; @@ -68,7 +68,6 @@ import { initializeSw } from '@/scripts/initialize-sw'; import { reloadChannel } from '@/scripts/unison-reload'; import { deleteLoginId } from '@/scripts/login-id'; import { getAccountFromId } from '@/scripts/get-account-from-id'; -import { SwMessage } from '@/sw/types'; console.info(`Misskey v${version}`); @@ -240,33 +239,6 @@ components(app); await router.isReady(); -//#region Listen message from SW -navigator.serviceWorker.addEventListener('message', ev => { - if (_DEV_) { - console.log('sw msg', ev.data); - } - - const data = ev.data as SwMessage; - if (data.type !== 'order') return; - - if (data.loginId !== $i?.id) { - return getAccountFromId(data.loginId).then(account => { - if (!account) return; - return login(account.token, data.url); - }); - } - - switch (data.order) { - case 'post': - return post(data.options); - case 'push': - return router.push(data.url); - default: - return; - } -}); -//#endregion - //document.body.innerHTML = '
'; app.mount('body'); @@ -415,22 +387,3 @@ if ($i) { signout(); }); } - -/** - * Convert the URL safe base64 string to a Uint8Array - * @param base64String base64 string - */ -function urlBase64ToUint8Array(base64String: string): Uint8Array { - const padding = '='.repeat((4 - base64String.length % 4) % 4); - const base64 = (base64String + padding) - .replace(/-/g, '+') - .replace(/_/g, '/'); - - const rawData = window.atob(base64); - const outputArray = new Uint8Array(rawData.length); - - for (let i = 0; i < rawData.length; ++i) { - outputArray[i] = rawData.charCodeAt(i); - } - return outputArray; -} diff --git a/src/client/sw/create-notification.ts b/src/client/sw/create-notification.ts index 1519ce48f3..921e92e0cc 100644 --- a/src/client/sw/create-notification.ts +++ b/src/client/sw/create-notification.ts @@ -169,14 +169,42 @@ async function composeNotification(data: pushNotificationData): Promise<[string, icon: body.user.avatarUrl, tag: `messaging:user:${body.userId}`, data, + renotify: true, }]; } return [t('_notification.youGotMessagingMessageFromGroup', { name: body.group.name }), { icon: body.user.avatarUrl, tag: `messaging:group:${body.groupId}`, data, + renotify: true, }]; default: return null; } } + +export async function createAllReadNotification(type: 'notifications' | 'messagingMessages') { + const n = await composeAllReadNotification(type); + if (n) return self.registration.showNotification(...n); +} + +async function composeAllReadNotification(type: string): Promise<[string, NotificationOptions] | null | undefined> { + if (!swLang.i18n) swLang.fetchLocale(); + const i18n = await swLang.i18n as I18n; + const { t } = i18n; + + if (type === 'notifications') { + return [t('readAllNotifications'), { + silent: true, + tag: 'user_visible_auto_notification', + }]; + } + if (type === 'messagingMessages') { + return [t('readAllMessagingMessages'), { + silent: true, + tag: 'user_visible_auto_notification', + }]; + } + + return; +} diff --git a/src/client/sw/operations.ts b/src/client/sw/operations.ts index bf6434d5ea..a6b5afe765 100644 --- a/src/client/sw/operations.ts +++ b/src/client/sw/operations.ts @@ -61,7 +61,12 @@ export async function openPost(options: any, loginId: string) { export async function openClient(order: swMessageOrderType, url: string, loginId: string, query: any = {}) { const client = await self.clients.matchAll({ type: 'window' - }).then(clients => clients.length > 0 ? clients[0] as WindowClient : null); + }).then(clients => { + for (const c of clients) { + if (c.url.indexOf('?zen') < 0) return c; + } + return null; + }); if (client) { client.postMessage({ type: 'order', ...query, order, loginId, url } as SwMessage); diff --git a/src/client/sw/sw.ts b/src/client/sw/sw.ts index a2fbcf3c22..eb78571998 100644 --- a/src/client/sw/sw.ts +++ b/src/client/sw/sw.ts @@ -38,6 +38,14 @@ self.addEventListener('fetch', ev => { //#region When: Caught Notification self.addEventListener('push', ev => { + setTimeout(async () => { + console.log('to'); + for (const n of await self.registration.getNotifications({ tag: 'user_visible_auto_notification' })) { + console.log(close) + n.close(); + } + }, 5000); + // クライアント取得 ev.waitUntil(self.clients.matchAll({ includeUncontrolled: true, diff --git a/src/client/ui/_common_/common.vue b/src/client/ui/_common_/common.vue index e5cdaca235..8709f5a686 100644 --- a/src/client/ui/_common_/common.vue +++ b/src/client/ui/_common_/common.vue @@ -14,10 +14,15 @@