Merge branch 'develop' of https://github.com/misskey-dev/misskey into develop

This commit is contained in:
syuilo 2023-02-13 15:28:10 +09:00
commit 30f600e03e
6 changed files with 43 additions and 32 deletions

View file

@ -83,7 +83,7 @@ const announcements = {
limit: 10, limit: 10,
}; };
const isTimelineAvailable = instance.policies.ltlAvailable || instance.policies.gtlAvailable; const isTimelineAvailable = $ref(instance.policies?.ltlAvailable || instance.policies?.gtlAvailable);
let showMenu = $ref(false); let showMenu = $ref(false);
let isDesktop = $ref(window.innerWidth >= DESKTOP_THRESHOLD); let isDesktop = $ref(window.innerWidth >= DESKTOP_THRESHOLD);

7
packages/sw/src/@types/global.d.ts vendored Normal file
View file

@ -0,0 +1,7 @@
type FIXME = any;
declare const _LANGS_: string[][];
declare const _VERSION_: string;
declare const _ENV_: string;
declare const _DEV_: boolean;
declare const _PERF_PREFIX_: string;

View file

@ -30,7 +30,7 @@ export async function createNotification<K extends keyof pushNotificationDataMap
} }
} }
async function composeNotification<K extends keyof pushNotificationDataMap>(data: pushNotificationDataMap[K]): Promise<[string, NotificationOptions] | null> { async function composeNotification(data: pushNotificationDataMap[keyof pushNotificationDataMap]): Promise<[string, NotificationOptions] | null> {
if (!swLang.i18n) swLang.fetchLocale(); if (!swLang.i18n) swLang.fetchLocale();
const i18n = await swLang.i18n as I18n<any>; const i18n = await swLang.i18n as I18n<any>;
const { t } = i18n; const { t } = i18n;
@ -66,7 +66,7 @@ async function composeNotification<K extends keyof pushNotificationDataMap>(data
case 'mention': case 'mention':
return [t('_notification.youGotMention', { name: getUserName(data.body.user) }), { return [t('_notification.youGotMention', { name: getUserName(data.body.user) }), {
body: data.body.note.text || '', body: data.body.note.text ?? '',
icon: data.body.user.avatarUrl, icon: data.body.user.avatarUrl,
badge: iconUrl('at'), badge: iconUrl('at'),
data, data,
@ -80,7 +80,7 @@ async function composeNotification<K extends keyof pushNotificationDataMap>(data
case 'reply': case 'reply':
return [t('_notification.youGotReply', { name: getUserName(data.body.user) }), { return [t('_notification.youGotReply', { name: getUserName(data.body.user) }), {
body: data.body.note.text || '', body: data.body.note.text ?? '',
icon: data.body.user.avatarUrl, icon: data.body.user.avatarUrl,
badge: iconUrl('arrow-back-up'), badge: iconUrl('arrow-back-up'),
data, data,
@ -94,7 +94,7 @@ async function composeNotification<K extends keyof pushNotificationDataMap>(data
case 'renote': case 'renote':
return [t('_notification.youRenoted', { name: getUserName(data.body.user) }), { return [t('_notification.youRenoted', { name: getUserName(data.body.user) }), {
body: data.body.note.text || '', body: data.body.note.text ?? '',
icon: data.body.user.avatarUrl, icon: data.body.user.avatarUrl,
badge: iconUrl('repeat'), badge: iconUrl('repeat'),
data, data,
@ -108,7 +108,7 @@ async function composeNotification<K extends keyof pushNotificationDataMap>(data
case 'quote': case 'quote':
return [t('_notification.youGotQuote', { name: getUserName(data.body.user) }), { return [t('_notification.youGotQuote', { name: getUserName(data.body.user) }), {
body: data.body.note.text || '', body: data.body.note.text ?? '',
icon: data.body.user.avatarUrl, icon: data.body.user.avatarUrl,
badge: iconUrl('quote'), badge: iconUrl('quote'),
data, data,
@ -162,7 +162,7 @@ async function composeNotification<K extends keyof pushNotificationDataMap>(data
} }
return [`${reaction} ${getUserName(data.body.user)}`, { return [`${reaction} ${getUserName(data.body.user)}`, {
body: data.body.note.text || '', body: data.body.note.text ?? '',
icon: data.body.user.avatarUrl, icon: data.body.user.avatarUrl,
badge, badge,
data, data,
@ -227,9 +227,9 @@ async function composeNotification<K extends keyof pushNotificationDataMap>(data
}]; }];
case 'app': case 'app':
return [data.body.header || data.body.body, { return [data.body.header ?? data.body.body, {
body: data.body.header && data.body.body, body: data.body.header ? data.body.body : '',
icon: data.body.icon, icon: data.body.icon ?? undefined,
data, data,
}]; }];
@ -246,7 +246,7 @@ async function composeNotification<K extends keyof pushNotificationDataMap>(data
renotify: true, renotify: true,
}]; }];
} }
return [t('_notification.youGotMessagingMessageFromGroup', { name: data.body.group.name }), { return [t('_notification.youGotMessagingMessageFromGroup', { name: data.body.group?.name ?? '' }), {
icon: data.body.user.avatarUrl, icon: data.body.user.avatarUrl,
badge: iconUrl('messages'), badge: iconUrl('messages'),
tag: `messaging:group:${data.body.groupId}`, tag: `messaging:group:${data.body.groupId}`,
@ -255,7 +255,7 @@ async function composeNotification<K extends keyof pushNotificationDataMap>(data
}]; }];
case 'unreadAntennaNote': case 'unreadAntennaNote':
return [t('_notification.unreadAntennaNote', { name: data.body.antenna.name }), { return [t('_notification.unreadAntennaNote', { name: data.body.antenna.name }), {
body: `${getUserName(data.body.note.user)}: ${data.body.note.text || ''}`, body: `${getUserName(data.body.note.user)}: ${data.body.note.text ?? ''}`,
icon: data.body.note.user.avatarUrl, icon: data.body.note.user.avatarUrl,
badge: iconUrl('antenna'), badge: iconUrl('antenna'),
tag: `antenna:${data.body.antenna.id}`, tag: `antenna:${data.body.antenna.id}`,
@ -272,7 +272,7 @@ export async function createEmptyNotification() {
if (!swLang.i18n) swLang.fetchLocale(); if (!swLang.i18n) swLang.fetchLocale();
const i18n = await swLang.i18n as I18n<any>; const i18n = await swLang.i18n as I18n<any>;
const { t } = i18n; const { t } = i18n;
await self.registration.showNotification( await self.registration.showNotification(
t('_notification.emptyPushNotificationMessage'), t('_notification.emptyPushNotificationMessage'),
{ {

View file

@ -1,3 +1,7 @@
export default function(user: { name?: string | null, username: string }): string { export default function(user: { name?: string | null, username: string }): string {
// Show username if name is empty.
// XXX: typescript-eslint has no configuration to allow using `||` against string.
// https://github.com/typescript-eslint/typescript-eslint/issues/4906
// eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing
return user.name || user.username; return user.name || user.username;
} }

View file

@ -28,7 +28,7 @@ class SwNotificationReadManager {
} }
// プッシュ通知の既読をサーバーに送信 // プッシュ通知の既読をサーバーに送信
public async read<K extends keyof pushNotificationDataMap>(data: pushNotificationDataMap[K]) { public async read(data: pushNotificationDataMap[keyof pushNotificationDataMap]) {
if (data.type !== 'notification' || !(data.userId in this.accounts)) return; if (data.type !== 'notification' || !(data.userId in this.accounts)) return;
const account = this.accounts[data.userId]; const account = this.accounts[data.userId];

View file

@ -5,11 +5,11 @@ import { pushNotificationDataMap } from '@/types';
import * as swos from '@/scripts/operations'; import * as swos from '@/scripts/operations';
import { acct as getAcct } from '@/filters/user'; import { acct as getAcct } from '@/filters/user';
self.addEventListener('install', ev => { globalThis.addEventListener('install', ev => {
ev.waitUntil(self.skipWaiting()); //ev.waitUntil(self.skipWaiting());
}); });
self.addEventListener('activate', ev => { globalThis.addEventListener('activate', ev => {
ev.waitUntil( ev.waitUntil(
caches.keys() caches.keys()
.then(cacheNames => Promise.all( .then(cacheNames => Promise.all(
@ -21,7 +21,7 @@ self.addEventListener('activate', ev => {
); );
}); });
self.addEventListener('fetch', ev => { globalThis.addEventListener('fetch', ev => {
let isHTMLRequest = false; let isHTMLRequest = false;
if (ev.request.headers.get('sec-fetch-dest') === 'document') { if (ev.request.headers.get('sec-fetch-dest') === 'document') {
isHTMLRequest = true; isHTMLRequest = true;
@ -38,13 +38,13 @@ self.addEventListener('fetch', ev => {
); );
}); });
self.addEventListener('push', ev => { globalThis.addEventListener('push', ev => {
// クライアント取得 // クライアント取得
ev.waitUntil(self.clients.matchAll({ ev.waitUntil(self.clients.matchAll({
includeUncontrolled: true, includeUncontrolled: true,
type: 'window' type: 'window'
}).then(async <K extends keyof pushNotificationDataMap>(clients: readonly WindowClient[]) => { }).then(async (clients: readonly WindowClient[]) => {
const data: pushNotificationDataMap[K] = ev.data?.json(); const data: pushNotificationDataMap[keyof pushNotificationDataMap] = ev.data?.json();
switch (data.type) { switch (data.type) {
// case 'driveFileCreated': // case 'driveFileCreated':
@ -104,17 +104,17 @@ self.addEventListener('push', ev => {
})); }));
}); });
self.addEventListener('notificationclick', <K extends keyof pushNotificationDataMap>(ev: ServiceWorkerGlobalScopeEventMap['notificationclick']) => { globalThis.addEventListener('notificationclick', (ev: ServiceWorkerGlobalScopeEventMap['notificationclick']) => {
ev.waitUntil((async () => { ev.waitUntil((async () => {
if (_DEV_) { if (_DEV_) {
console.log('notificationclick', ev.action, ev.notification.data); console.log('notificationclick', ev.action, ev.notification.data);
} }
const { action, notification } = ev; const { action, notification } = ev;
const data: pushNotificationDataMap[K] = notification.data; const data: pushNotificationDataMap[keyof pushNotificationDataMap] = notification.data;
const { userId: loginId } = data; const { userId: loginId } = data;
let client: WindowClient | null = null; let client: WindowClient | null = null;
switch (data.type) { switch (data.type) {
case 'notification': case 'notification':
switch (action) { switch (action) {
@ -180,27 +180,27 @@ self.addEventListener('notificationclick', <K extends keyof pushNotificationData
case 'unreadAntennaNote': case 'unreadAntennaNote':
client = await swos.openAntenna(data.body.antenna.id, loginId); client = await swos.openAntenna(data.body.antenna.id, loginId);
} }
if (client) { if (client) {
client.focus(); client.focus();
} }
if (data.type === 'notification') { if (data.type === 'notification') {
swNotificationRead.then(that => that.read(data)); swNotificationRead.then(that => that.read(data));
} }
notification.close(); notification.close();
})()); })());
}); });
self.addEventListener('notificationclose', <K extends keyof pushNotificationDataMap>(ev: ServiceWorkerGlobalScopeEventMap['notificationclose']) => { globalThis.addEventListener('notificationclose', (ev: ServiceWorkerGlobalScopeEventMap['notificationclose']) => {
const data: pushNotificationDataMap[K] = ev.notification.data; const data: pushNotificationDataMap[keyof pushNotificationDataMap] = ev.notification.data;
if (data.type === 'notification') { if (data.type === 'notification') {
swNotificationRead.then(that => that.read(data)); swNotificationRead.then(that => that.read(data));
} }
}); });
self.addEventListener('message', (ev: ServiceWorkerGlobalScopeEventMap['message']) => { globalThis.addEventListener('message', (ev: ServiceWorkerGlobalScopeEventMap['message']) => {
ev.waitUntil((async () => { ev.waitUntil((async () => {
switch (ev.data) { switch (ev.data) {
case 'clear': case 'clear':
@ -211,11 +211,11 @@ self.addEventListener('message', (ev: ServiceWorkerGlobalScopeEventMap['message'
)); ));
return; // TODO return; // TODO
} }
if (typeof ev.data === 'object') { if (typeof ev.data === 'object') {
// E.g. '[object Array]' → 'array' // E.g. '[object Array]' → 'array'
const otype = Object.prototype.toString.call(ev.data).slice(8, -1).toLowerCase(); const otype = Object.prototype.toString.call(ev.data).slice(8, -1).toLowerCase();
if (otype === 'object') { if (otype === 'object') {
if (ev.data.msg === 'initialize') { if (ev.data.msg === 'initialize') {
swLang.setLang(ev.data.lang); swLang.setLang(ev.data.lang);