From 9f0e0dc8ce9ca2a04f8bfbfb95c33a7b20288e21 Mon Sep 17 00:00:00 2001
From: Kagami Sascha Rosylight <saschanaz@outlook.com>
Date: Sun, 12 Feb 2023 16:31:37 +0100
Subject: [PATCH 1/3] refactor(sw): Fix type errors in packages/sw (#9909)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

* Fix type errors in packages/sw

* mouhitotsu

* @typesは越境しない

* Update packages/sw/src/scripts/create-notification.ts

---------

Co-authored-by: tamaina <tamaina@hotmail.co.jp>
---
 packages/sw/src/@types/global.d.ts            |  7 ++++
 .../sw/src/scripts/create-notification.ts     | 24 ++++++-------
 packages/sw/src/scripts/get-user-name.ts      |  4 +++
 packages/sw/src/scripts/notification-read.ts  |  2 +-
 packages/sw/src/sw.ts                         | 34 +++++++++----------
 5 files changed, 41 insertions(+), 30 deletions(-)
 create mode 100644 packages/sw/src/@types/global.d.ts

diff --git a/packages/sw/src/@types/global.d.ts b/packages/sw/src/@types/global.d.ts
new file mode 100644
index 0000000000..5aaef9412c
--- /dev/null
+++ b/packages/sw/src/@types/global.d.ts
@@ -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;
diff --git a/packages/sw/src/scripts/create-notification.ts b/packages/sw/src/scripts/create-notification.ts
index 6744687fcc..6e7845f667 100644
--- a/packages/sw/src/scripts/create-notification.ts
+++ b/packages/sw/src/scripts/create-notification.ts
@@ -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();
 	const i18n = await swLang.i18n as I18n<any>;
 	const { t } = i18n;
@@ -66,7 +66,7 @@ async function composeNotification<K extends keyof pushNotificationDataMap>(data
 
 				case 'mention':
 					return [t('_notification.youGotMention', { name: getUserName(data.body.user) }), {
-						body: data.body.note.text || '',
+						body: data.body.note.text ?? '',
 						icon: data.body.user.avatarUrl,
 						badge: iconUrl('at'),
 						data,
@@ -80,7 +80,7 @@ async function composeNotification<K extends keyof pushNotificationDataMap>(data
 
 				case 'reply':
 					return [t('_notification.youGotReply', { name: getUserName(data.body.user) }), {
-						body: data.body.note.text || '',
+						body: data.body.note.text ?? '',
 						icon: data.body.user.avatarUrl,
 						badge: iconUrl('arrow-back-up'),
 						data,
@@ -94,7 +94,7 @@ async function composeNotification<K extends keyof pushNotificationDataMap>(data
 
 				case 'renote':
 					return [t('_notification.youRenoted', { name: getUserName(data.body.user) }), {
-						body: data.body.note.text || '',
+						body: data.body.note.text ?? '',
 						icon: data.body.user.avatarUrl,
 						badge: iconUrl('repeat'),
 						data,
@@ -108,7 +108,7 @@ async function composeNotification<K extends keyof pushNotificationDataMap>(data
 
 				case 'quote':
 					return [t('_notification.youGotQuote', { name: getUserName(data.body.user) }), {
-						body: data.body.note.text || '',
+						body: data.body.note.text ?? '',
 						icon: data.body.user.avatarUrl,
 						badge: iconUrl('quote'),
 						data,
@@ -162,7 +162,7 @@ async function composeNotification<K extends keyof pushNotificationDataMap>(data
 					}
 
 					return [`${reaction} ${getUserName(data.body.user)}`, {
-						body: data.body.note.text || '',
+						body: data.body.note.text ?? '',
 						icon: data.body.user.avatarUrl,
 						badge,
 						data,
@@ -227,9 +227,9 @@ async function composeNotification<K extends keyof pushNotificationDataMap>(data
 					}];
 
 				case 'app':
-					return [data.body.header || data.body.body, {
-						body: data.body.header && data.body.body,
-						icon: data.body.icon,
+					return [data.body.header ?? data.body.body, {
+						body: data.body.header ? data.body.body : '',
+						icon: data.body.icon ?? undefined,
 						data,
 					}];
 
@@ -246,7 +246,7 @@ async function composeNotification<K extends keyof pushNotificationDataMap>(data
 					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,
 				badge: iconUrl('messages'),
 				tag: `messaging:group:${data.body.groupId}`,
@@ -255,7 +255,7 @@ async function composeNotification<K extends keyof pushNotificationDataMap>(data
 			}];
 		case 'unreadAntennaNote':
 			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,
 				badge: iconUrl('antenna'),
 				tag: `antenna:${data.body.antenna.id}`,
@@ -272,7 +272,7 @@ export async function createEmptyNotification() {
 		if (!swLang.i18n) swLang.fetchLocale();
 		const i18n = await swLang.i18n as I18n<any>;
 		const { t } = i18n;
-	
+
 		await self.registration.showNotification(
 			t('_notification.emptyPushNotificationMessage'),
 			{
diff --git a/packages/sw/src/scripts/get-user-name.ts b/packages/sw/src/scripts/get-user-name.ts
index d499ea0203..ccc38c298e 100644
--- a/packages/sw/src/scripts/get-user-name.ts
+++ b/packages/sw/src/scripts/get-user-name.ts
@@ -1,3 +1,7 @@
 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;
 }
diff --git a/packages/sw/src/scripts/notification-read.ts b/packages/sw/src/scripts/notification-read.ts
index 5ad748b849..3b1dde0cd5 100644
--- a/packages/sw/src/scripts/notification-read.ts
+++ b/packages/sw/src/scripts/notification-read.ts
@@ -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;
 
 		const account = this.accounts[data.userId];
diff --git a/packages/sw/src/sw.ts b/packages/sw/src/sw.ts
index d47563939a..55f881cd43 100644
--- a/packages/sw/src/sw.ts
+++ b/packages/sw/src/sw.ts
@@ -5,11 +5,11 @@ import { pushNotificationDataMap } from '@/types';
 import * as swos from '@/scripts/operations';
 import { acct as getAcct } from '@/filters/user';
 
-self.addEventListener('install', ev => {
+globalThis.addEventListener('install', ev => {
 	ev.waitUntil(self.skipWaiting());
 });
 
-self.addEventListener('activate', ev => {
+globalThis.addEventListener('activate', ev => {
 	ev.waitUntil(
 		caches.keys()
 			.then(cacheNames => Promise.all(
@@ -21,7 +21,7 @@ self.addEventListener('activate', ev => {
 	);
 });
 
-self.addEventListener('fetch', ev => {
+globalThis.addEventListener('fetch', ev => {
 	let isHTMLRequest = false;
 	if (ev.request.headers.get('sec-fetch-dest') === 'document') {
 		isHTMLRequest = true;
@@ -38,13 +38,13 @@ self.addEventListener('fetch', ev => {
 	);
 });
 
-self.addEventListener('push', ev => {
+globalThis.addEventListener('push', ev => {
 	// クライアント取得
 	ev.waitUntil(self.clients.matchAll({
 		includeUncontrolled: true,
 		type: 'window'
-	}).then(async <K extends keyof pushNotificationDataMap>(clients: readonly WindowClient[]) => {
-		const data: pushNotificationDataMap[K] = ev.data?.json();
+	}).then(async (clients: readonly WindowClient[]) => {
+		const data: pushNotificationDataMap[keyof pushNotificationDataMap] = ev.data?.json();
 
 		switch (data.type) {
 			// 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 () => {
 		if (_DEV_) {
 			console.log('notificationclick', ev.action, ev.notification.data);
 		}
-	
+
 		const { action, notification } = ev;
-		const data: pushNotificationDataMap[K] = notification.data;
+		const data: pushNotificationDataMap[keyof pushNotificationDataMap] = notification.data;
 		const { userId: loginId } = data;
 		let client: WindowClient | null = null;
-	
+
 		switch (data.type) {
 			case 'notification':
 				switch (action) {
@@ -180,27 +180,27 @@ self.addEventListener('notificationclick', <K extends keyof pushNotificationData
 			case 'unreadAntennaNote':
 				client = await swos.openAntenna(data.body.antenna.id, loginId);
 		}
-	
+
 		if (client) {
 			client.focus();
 		}
 		if (data.type === 'notification') {
 			swNotificationRead.then(that => that.read(data));
 		}
-	
+
 		notification.close();
 	})());
 });
 
-self.addEventListener('notificationclose', <K extends keyof pushNotificationDataMap>(ev: ServiceWorkerGlobalScopeEventMap['notificationclose']) => {
-	const data: pushNotificationDataMap[K] = ev.notification.data;
+globalThis.addEventListener('notificationclose', (ev: ServiceWorkerGlobalScopeEventMap['notificationclose']) => {
+	const data: pushNotificationDataMap[keyof pushNotificationDataMap] = ev.notification.data;
 
 	if (data.type === 'notification') {
 		swNotificationRead.then(that => that.read(data));
 	}
 });
 
-self.addEventListener('message', (ev: ServiceWorkerGlobalScopeEventMap['message']) => {
+globalThis.addEventListener('message', (ev: ServiceWorkerGlobalScopeEventMap['message']) => {
 	ev.waitUntil((async () => {
 		switch (ev.data) {
 			case 'clear':
@@ -211,11 +211,11 @@ self.addEventListener('message', (ev: ServiceWorkerGlobalScopeEventMap['message'
 					));
 				return; // TODO
 		}
-	
+
 		if (typeof ev.data === 'object') {
 			// E.g. '[object Array]' → 'array'
 			const otype = Object.prototype.toString.call(ev.data).slice(8, -1).toLowerCase();
-	
+
 			if (otype === 'object') {
 				if (ev.data.msg === 'initialize') {
 					swLang.setLang(ev.data.lang);

From 2f41f12aea9f3a1e0ed5da28d703a718e5de3a1a Mon Sep 17 00:00:00 2001
From: Kagami Sascha Rosylight <saschanaz@outlook.com>
Date: Sun, 12 Feb 2023 16:40:36 +0100
Subject: [PATCH 2/3] fix(client): Make `isTimelineAvailable` a reference
 (#9906)

* Make `isTimelineAvailable` a reference

* Update b.vue
---
 packages/frontend/src/ui/visitor/b.vue | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/packages/frontend/src/ui/visitor/b.vue b/packages/frontend/src/ui/visitor/b.vue
index 058a9482fa..42283fe95b 100644
--- a/packages/frontend/src/ui/visitor/b.vue
+++ b/packages/frontend/src/ui/visitor/b.vue
@@ -83,7 +83,7 @@ const announcements = {
 	limit: 10,
 };
 
-const isTimelineAvailable = instance.policies.ltlAvailable || instance.policies.gtlAvailable;
+const isTimelineAvailable = $ref(instance.policies?.ltlAvailable || instance.policies?.gtlAvailable);
 
 let showMenu = $ref(false);
 let isDesktop = $ref(window.innerWidth >= DESKTOP_THRESHOLD);

From 8d4c5deb8dc173d59975e998dc1295c698af362b Mon Sep 17 00:00:00 2001
From: tamaina <tamaina@hotmail.co.jp>
Date: Sun, 12 Feb 2023 15:48:56 +0000
Subject: [PATCH 3/3] =?UTF-8?q?perf(sw):=20skipWaiting=E3=81=97=E3=81=AA?=
 =?UTF-8?q?=E3=81=84?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 packages/sw/src/sw.ts | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/packages/sw/src/sw.ts b/packages/sw/src/sw.ts
index 55f881cd43..7bcf4d5976 100644
--- a/packages/sw/src/sw.ts
+++ b/packages/sw/src/sw.ts
@@ -6,7 +6,7 @@ import * as swos from '@/scripts/operations';
 import { acct as getAcct } from '@/filters/user';
 
 globalThis.addEventListener('install', ev => {
-	ev.waitUntil(self.skipWaiting());
+	//ev.waitUntil(self.skipWaiting());
 });
 
 globalThis.addEventListener('activate', ev => {