From e78110a5cd7891f89682a9c58a4a3648d6940205 Mon Sep 17 00:00:00 2001 From: syuilo <4439005+syuilo@users.noreply.github.com> Date: Mon, 19 Aug 2024 13:13:32 +0900 Subject: [PATCH 01/25] refactor --- packages/frontend/src/themes/_dark.json5 | 1 - packages/frontend/src/themes/_light.json5 | 1 - packages/frontend/src/ui/_common_/navbar-for-mobile.vue | 6 ++++-- packages/frontend/src/ui/_common_/navbar.vue | 9 +++++---- 4 files changed, 9 insertions(+), 8 deletions(-) diff --git a/packages/frontend/src/themes/_dark.json5 b/packages/frontend/src/themes/_dark.json5 index c82a956868..a310fb716f 100644 --- a/packages/frontend/src/themes/_dark.json5 +++ b/packages/frontend/src/themes/_dark.json5 @@ -89,7 +89,6 @@ X11: 'rgba(0, 0, 0, 0.3)', X12: 'rgba(255, 255, 255, 0.1)', X13: 'rgba(255, 255, 255, 0.15)', - X14: ':alpha<0.5<@navBg', X15: ':alpha<0<@panel', X16: ':alpha<0.7<@panel', X17: ':alpha<0.8<@bg', diff --git a/packages/frontend/src/themes/_light.json5 b/packages/frontend/src/themes/_light.json5 index 63bc030916..827a935a0b 100644 --- a/packages/frontend/src/themes/_light.json5 +++ b/packages/frontend/src/themes/_light.json5 @@ -89,7 +89,6 @@ X11: 'rgba(0, 0, 0, 0.1)', X12: 'rgba(0, 0, 0, 0.1)', X13: 'rgba(0, 0, 0, 0.15)', - X14: ':alpha<0.5<@navBg', X15: ':alpha<0<@panel', X16: ':alpha<0.7<@panel', X17: ':alpha<0.8<@bg', diff --git a/packages/frontend/src/ui/_common_/navbar-for-mobile.vue b/packages/frontend/src/ui/_common_/navbar-for-mobile.vue index 87e9e45e63..e80d5fd399 100644 --- a/packages/frontend/src/ui/_common_/navbar-for-mobile.vue +++ b/packages/frontend/src/ui/_common_/navbar-for-mobile.vue @@ -82,6 +82,8 @@ function more() { diff --git a/packages/frontend/src/pages/settings/avatar-decoration.dialog.vue b/packages/frontend/src/pages/settings/avatar-decoration.dialog.vue index ce1d4e48d8..1938b8d48d 100644 --- a/packages/frontend/src/pages/settings/avatar-decoration.dialog.vue +++ b/packages/frontend/src/pages/settings/avatar-decoration.dialog.vue @@ -96,6 +96,7 @@ const decorationsForPreview = computed(() => { flipH: flipH.value, offsetX: offsetX.value, offsetY: offsetY.value, + blink: true, }; const decorations = [...$i.avatarDecorations]; if (props.usingIndex != null) { From 21a3095eb0d0ce8f385b4450f371c2160ea18b12 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E3=81=8B=E3=81=A3=E3=81=93=E3=81=8B=E3=82=8A?= <67428053+kakkokari-gtyih@users.noreply.github.com> Date: Tue, 20 Aug 2024 12:39:01 +0900 Subject: [PATCH 05/25] fix button translation (#14444) that Japanese string exactly matches that i18n key (cherry picked from commit a408d32bb72ada9a4ad6bd1afe6e3fadb9b403db) Co-authored-by: dakkar --- packages/frontend/src/pages/admin/abuses.vue | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/frontend/src/pages/admin/abuses.vue b/packages/frontend/src/pages/admin/abuses.vue index 9a9fa472a5..0b9847fed3 100644 --- a/packages/frontend/src/pages/admin/abuses.vue +++ b/packages/frontend/src/pages/admin/abuses.vue @@ -9,7 +9,7 @@ SPDX-License-Identifier: AGPL-3.0-only
- {{ "通知設定" }} + {{ i18n.ts.notificationSetting }}
From 043ab1f69b78af5caea47644a2878cae3cdbe141 Mon Sep 17 00:00:00 2001 From: atsuchan <83960488+atsu1125@users.noreply.github.com> Date: Tue, 20 Aug 2024 13:49:42 +0900 Subject: [PATCH 06/25] fix(backend): Fix chart generation non-matching blockedHosts (#14441) --- packages/backend/src/core/chart/charts/federation.ts | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/packages/backend/src/core/chart/charts/federation.ts b/packages/backend/src/core/chart/charts/federation.ts index c2329a2f73..f40a26495d 100644 --- a/packages/backend/src/core/chart/charts/federation.ts +++ b/packages/backend/src/core/chart/charts/federation.ts @@ -65,21 +65,21 @@ export default class FederationChart extends Chart { // eslint-di this.followingsRepository.createQueryBuilder('following') .select('COUNT(DISTINCT following.followeeHost)') .where('following.followeeHost IS NOT NULL') - .andWhere(meta.blockedHosts.length === 0 ? '1=1' : 'following.followeeHost NOT ILIKE ANY(ARRAY[:...blocked])', { blocked: meta.blockedHosts.flatMap(x => [x, `%.${x}`]) }) + .andWhere(meta.blockedHosts.length === 0 ? '1=1' : 'following.followeeHost NOT ILIKE ALL(ARRAY[:...blocked])', { blocked: meta.blockedHosts.flatMap(x => [x, `%.${x}`]) }) .andWhere(`following.followeeHost NOT IN (${ suspendedInstancesQuery.getQuery() })`) .getRawOne() .then(x => parseInt(x.count, 10)), this.followingsRepository.createQueryBuilder('following') .select('COUNT(DISTINCT following.followerHost)') .where('following.followerHost IS NOT NULL') - .andWhere(meta.blockedHosts.length === 0 ? '1=1' : 'following.followerHost NOT ILIKE ANY(ARRAY[:...blocked])', { blocked: meta.blockedHosts.flatMap(x => [x, `%.${x}`]) }) + .andWhere(meta.blockedHosts.length === 0 ? '1=1' : 'following.followerHost NOT ILIKE ALL(ARRAY[:...blocked])', { blocked: meta.blockedHosts.flatMap(x => [x, `%.${x}`]) }) .andWhere(`following.followerHost NOT IN (${ suspendedInstancesQuery.getQuery() })`) .getRawOne() .then(x => parseInt(x.count, 10)), this.followingsRepository.createQueryBuilder('following') .select('COUNT(DISTINCT following.followeeHost)') .where('following.followeeHost IS NOT NULL') - .andWhere(meta.blockedHosts.length === 0 ? '1=1' : 'following.followeeHost NOT ILIKE ANY(ARRAY[:...blocked])', { blocked: meta.blockedHosts.flatMap(x => [x, `%.${x}`]) }) + .andWhere(meta.blockedHosts.length === 0 ? '1=1' : 'following.followeeHost NOT ILIKE ALL(ARRAY[:...blocked])', { blocked: meta.blockedHosts.flatMap(x => [x, `%.${x}`]) }) .andWhere(`following.followeeHost NOT IN (${ suspendedInstancesQuery.getQuery() })`) .andWhere(`following.followeeHost IN (${ pubsubSubQuery.getQuery() })`) .setParameters(pubsubSubQuery.getParameters()) @@ -88,7 +88,7 @@ export default class FederationChart extends Chart { // eslint-di this.instancesRepository.createQueryBuilder('instance') .select('COUNT(instance.id)') .where(`instance.host IN (${ subInstancesQuery.getQuery() })`) - .andWhere(meta.blockedHosts.length === 0 ? '1=1' : 'instance.host NOT ILIKE ANY(ARRAY[:...blocked])', { blocked: meta.blockedHosts.flatMap(x => [x, `%.${x}`]) }) + .andWhere(meta.blockedHosts.length === 0 ? '1=1' : 'instance.host NOT ILIKE ALL(ARRAY[:...blocked])', { blocked: meta.blockedHosts.flatMap(x => [x, `%.${x}`]) }) .andWhere('instance.suspensionState = \'none\'') .andWhere('instance.isNotResponding = false') .getRawOne() @@ -96,7 +96,7 @@ export default class FederationChart extends Chart { // eslint-di this.instancesRepository.createQueryBuilder('instance') .select('COUNT(instance.id)') .where(`instance.host IN (${ pubInstancesQuery.getQuery() })`) - .andWhere(meta.blockedHosts.length === 0 ? '1=1' : 'instance.host NOT ILIKE ANY(ARRAY[:...blocked])', { blocked: meta.blockedHosts.flatMap(x => [x, `%.${x}`]) }) + .andWhere(meta.blockedHosts.length === 0 ? '1=1' : 'instance.host NOT ILIKE ALL(ARRAY[:...blocked])', { blocked: meta.blockedHosts.flatMap(x => [x, `%.${x}`]) }) .andWhere('instance.suspensionState = \'none\'') .andWhere('instance.isNotResponding = false') .getRawOne() From 1008fa32a059f4c66c17a2ab77c3d5595d998233 Mon Sep 17 00:00:00 2001 From: syuilo <4439005+syuilo@users.noreply.github.com> Date: Thu, 22 Aug 2024 14:03:11 +0900 Subject: [PATCH 07/25] better boot error screen --- packages/backend/src/server/web/boot.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/backend/src/server/web/boot.js b/packages/backend/src/server/web/boot.js index 4275dc9527..5e52360456 100644 --- a/packages/backend/src/server/web/boot.js +++ b/packages/backend/src/server/web/boot.js @@ -176,10 +176,10 @@ Reload / リロード

The following actions may solve the problem. / 以下を行うと解決する可能性があります。

-

Clear the browser cache / ブラウザのキャッシュをクリアする

Update your os and browser / ブラウザおよびOSを最新バージョンに更新する

Disable an adblocker / アドブロッカーを無効にする

-

(Tor Browser) Set dom.webaudio.enabled to true / dom.webaudio.enabledをtrueに設定する

+

Clear the browser cache / ブラウザのキャッシュをクリアする

+

(Tor Browser) Set dom.webaudio.enabled to true / dom.webaudio.enabledをtrueに設定する

Other options / その他のオプション @@ -212,7 +212,7 @@ ERROR CODE: ${code} - ${JSON.stringify(details)}`; + ${details.toString()} ${JSON.stringify(details)}`; errorsElement.appendChild(detailsElement); addStyle(` * { From f85aa7b6415eaf61d213deb370f598f603f3fe9b Mon Sep 17 00:00:00 2001 From: syuilo <4439005+syuilo@users.noreply.github.com> Date: Fri, 23 Aug 2024 16:29:05 +0900 Subject: [PATCH 08/25] =?UTF-8?q?fix(backend):=20=E3=83=95=E3=82=A1?= =?UTF-8?q?=E3=82=A4=E3=83=AB=E3=81=8C=E3=82=B5=E3=82=A4=E3=82=BA=E3=81=AE?= =?UTF-8?q?=E5=88=B6=E9=99=90=E3=82=92=E8=B6=85=E3=81=88=E3=81=A6=E3=82=A2?= =?UTF-8?q?=E3=83=83=E3=83=97=E3=83=AD=E3=83=BC=E3=83=89=E3=81=95=E3=82=8C?= =?UTF-8?q?=E3=81=9F=E9=9A=9B=E3=81=AB=E3=82=A8=E3=83=A9=E3=83=BC=E3=82=92?= =?UTF-8?q?=E8=BF=94=E3=81=95=E3=81=AA=E3=81=8B=E3=81=A3=E3=81=9F=E5=95=8F?= =?UTF-8?q?=E9=A1=8C=E3=82=92=E4=BF=AE=E6=AD=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CHANGELOG.md | 2 +- packages/backend/src/server/api/ApiCallService.ts | 10 +++++++++- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index da204c9198..ad070cc981 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,7 +7,7 @@ - ### Server -- +- ファイルがサイズの制限を超えてアップロードされた際にエラーを返さなかった問題を修正 ## 2024.8.0 diff --git a/packages/backend/src/server/api/ApiCallService.ts b/packages/backend/src/server/api/ApiCallService.ts index 47f64f6609..ea852d590d 100644 --- a/packages/backend/src/server/api/ApiCallService.ts +++ b/packages/backend/src/server/api/ApiCallService.ts @@ -199,9 +199,17 @@ export class ApiCallService implements OnApplicationShutdown { return; } - const [path] = await createTemp(); + const [path, cleanup] = await createTemp(); await stream.pipeline(multipartData.file, fs.createWriteStream(path)); + // ファイルサイズが制限を超えていた場合 + if (multipartData.file.truncated) { + cleanup(); + reply.code(413); + reply.send(); + return; + } + const fields = {} as Record; for (const [k, v] of Object.entries(multipartData.fields)) { fields[k] = typeof v === 'object' && 'value' in v ? v.value : undefined; From 2f009f7d49e2468da6950c7ff8448565b095df38 Mon Sep 17 00:00:00 2001 From: syuilo <4439005+syuilo@users.noreply.github.com> Date: Fri, 23 Aug 2024 16:31:16 +0900 Subject: [PATCH 09/25] add note --- packages/backend/src/server/api/ApiCallService.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/backend/src/server/api/ApiCallService.ts b/packages/backend/src/server/api/ApiCallService.ts index ea852d590d..f95c272757 100644 --- a/packages/backend/src/server/api/ApiCallService.ts +++ b/packages/backend/src/server/api/ApiCallService.ts @@ -203,6 +203,7 @@ export class ApiCallService implements OnApplicationShutdown { await stream.pipeline(multipartData.file, fs.createWriteStream(path)); // ファイルサイズが制限を超えていた場合 + // なお truncated はストリームを読み切ってからでないと機能しないため、stream.pipeline より後にある必要がある if (multipartData.file.truncated) { cleanup(); reply.code(413); From 8032a4e12ad0425b3a2b4d7a857f12de656a718d Mon Sep 17 00:00:00 2001 From: syuilo <4439005+syuilo@users.noreply.github.com> Date: Fri, 23 Aug 2024 16:40:11 +0900 Subject: [PATCH 10/25] =?UTF-8?q?enhance(frontend):=20=E3=82=B5=E3=82=A4?= =?UTF-8?q?=E3=82=BA=E5=88=B6=E9=99=90=E3=82=92=E8=B6=85=E9=81=8E=E3=81=99?= =?UTF-8?q?=E3=82=8B=E3=83=95=E3=82=A1=E3=82=A4=E3=83=AB=E3=82=92=E3=82=A2?= =?UTF-8?q?=E3=83=83=E3=83=97=E3=83=AD=E3=83=BC=E3=83=89=E3=81=97=E3=82=88?= =?UTF-8?q?=E3=81=86=E3=81=A8=E3=81=97=E3=81=9F=E9=9A=9B=E3=81=AB=E3=82=A8?= =?UTF-8?q?=E3=83=A9=E3=83=BC=E3=82=92=E5=87=BA=E3=81=99=E3=82=88=E3=81=86?= =?UTF-8?q?=E3=81=AB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CHANGELOG.md | 2 +- packages/backend/src/config.ts | 4 ++-- packages/backend/src/core/DownloadService.ts | 2 +- .../backend/src/core/entities/MetaEntityService.ts | 1 + packages/backend/src/models/json-schema/meta.ts | 4 ++++ packages/backend/src/server/api/ApiServerService.ts | 2 +- packages/frontend/src/scripts/upload.ts | 10 ++++++++++ packages/misskey-js/src/autogen/types.ts | 1 + 8 files changed, 21 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ad070cc981..6359033c1b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,7 +4,7 @@ - ### Client -- +- サイズ制限を超過するファイルをアップロードしようとした際にエラーを出すように ### Server - ファイルがサイズの制限を超えてアップロードされた際にエラーを返さなかった問題を修正 diff --git a/packages/backend/src/config.ts b/packages/backend/src/config.ts index 3e5a1e81cd..cff0194780 100644 --- a/packages/backend/src/config.ts +++ b/packages/backend/src/config.ts @@ -133,7 +133,7 @@ export type Config = { proxySmtp: string | undefined; proxyBypassHosts: string[] | undefined; allowedPrivateNetworks: string[] | undefined; - maxFileSize: number | undefined; + maxFileSize: number; clusterLimit: number | undefined; id: string; outgoingAddress: string | undefined; @@ -250,7 +250,7 @@ export function loadConfig(): Config { proxySmtp: config.proxySmtp, proxyBypassHosts: config.proxyBypassHosts, allowedPrivateNetworks: config.allowedPrivateNetworks, - maxFileSize: config.maxFileSize, + maxFileSize: config.maxFileSize ?? 262144000, clusterLimit: config.clusterLimit, outgoingAddress: config.outgoingAddress, outgoingAddressFamily: config.outgoingAddressFamily, diff --git a/packages/backend/src/core/DownloadService.ts b/packages/backend/src/core/DownloadService.ts index 21ae798f9f..93f4a38246 100644 --- a/packages/backend/src/core/DownloadService.ts +++ b/packages/backend/src/core/DownloadService.ts @@ -42,7 +42,7 @@ export class DownloadService { const timeout = 30 * 1000; const operationTimeout = 60 * 1000; - const maxSize = this.config.maxFileSize ?? 262144000; + const maxSize = this.config.maxFileSize; const urlObj = new URL(url); let filename = urlObj.pathname.split('/').pop() ?? 'untitled'; diff --git a/packages/backend/src/core/entities/MetaEntityService.ts b/packages/backend/src/core/entities/MetaEntityService.ts index 44ec0d6a7b..f4b1e302d0 100644 --- a/packages/backend/src/core/entities/MetaEntityService.ts +++ b/packages/backend/src/core/entities/MetaEntityService.ts @@ -129,6 +129,7 @@ export class MetaEntityService { mediaProxy: this.config.mediaProxy, enableUrlPreview: instance.urlPreviewEnabled, noteSearchableScope: (this.config.meilisearch == null || this.config.meilisearch.scope !== 'local') ? 'global' : 'local', + maxFileSize: this.config.maxFileSize, }; return packed; diff --git a/packages/backend/src/models/json-schema/meta.ts b/packages/backend/src/models/json-schema/meta.ts index 3bcf9cac92..99feeaa7d7 100644 --- a/packages/backend/src/models/json-schema/meta.ts +++ b/packages/backend/src/models/json-schema/meta.ts @@ -253,6 +253,10 @@ export const packedMetaLiteSchema = { optional: false, nullable: false, default: 'local', }, + maxFileSize: { + type: 'number', + optional: false, nullable: false, + }, }, } as const; diff --git a/packages/backend/src/server/api/ApiServerService.ts b/packages/backend/src/server/api/ApiServerService.ts index 4a5935f930..13cbdfc3be 100644 --- a/packages/backend/src/server/api/ApiServerService.ts +++ b/packages/backend/src/server/api/ApiServerService.ts @@ -49,7 +49,7 @@ export class ApiServerService { fastify.register(multipart, { limits: { - fileSize: this.config.maxFileSize ?? 262144000, + fileSize: this.config.maxFileSize, files: 1, }, }); diff --git a/packages/frontend/src/scripts/upload.ts b/packages/frontend/src/scripts/upload.ts index 3e947183c9..abb0e1e677 100644 --- a/packages/frontend/src/scripts/upload.ts +++ b/packages/frontend/src/scripts/upload.ts @@ -13,6 +13,7 @@ import { apiUrl } from '@/config.js'; import { $i } from '@/account.js'; import { alert } from '@/os.js'; import { i18n } from '@/i18n.js'; +import { instance } from '@/instance.js'; type Uploading = { id: string; @@ -39,6 +40,15 @@ export function uploadFile( if (folder && typeof folder === 'object') folder = folder.id; + if (file.size > instance.maxFileSize) { + alert({ + type: 'error', + title: i18n.ts.failedToUpload, + text: i18n.ts.cannotUploadBecauseExceedsFileSizeLimit, + }); + return Promise.reject(); + } + return new Promise((resolve, reject) => { const id = uuid(); diff --git a/packages/misskey-js/src/autogen/types.ts b/packages/misskey-js/src/autogen/types.ts index 6d2f787767..0c50825203 100644 --- a/packages/misskey-js/src/autogen/types.ts +++ b/packages/misskey-js/src/autogen/types.ts @@ -4947,6 +4947,7 @@ export type components = { * @enum {string} */ noteSearchableScope: 'local' | 'global'; + maxFileSize: number; }; MetaDetailedOnly: { features?: { From 44f62160cb4b876f415b48b0574592f87bea9b3d Mon Sep 17 00:00:00 2001 From: syuilo <4439005+syuilo@users.noreply.github.com> Date: Sat, 24 Aug 2024 16:59:17 +0900 Subject: [PATCH 11/25] enhance(frontend): error message i18n --- locales/index.d.ts | 4 ++++ locales/ja-JP.yml | 1 + packages/frontend/src/scripts/get-note-menu.ts | 5 +++++ 3 files changed, 10 insertions(+) diff --git a/locales/index.d.ts b/locales/index.d.ts index 75e1703b4a..9fd3441ab1 100644 --- a/locales/index.d.ts +++ b/locales/index.d.ts @@ -5068,6 +5068,10 @@ export interface Locale extends ILocale { * 作成したアンテナ */ "createdAntennas": string; + /** + * これ以上このクリップにノートを追加できません。 + */ + "clipNoteLimitExceeded": string; "_delivery": { /** * 配信状態 diff --git a/locales/ja-JP.yml b/locales/ja-JP.yml index 98e3cbfa41..587b67d987 100644 --- a/locales/ja-JP.yml +++ b/locales/ja-JP.yml @@ -1263,6 +1263,7 @@ confirmWhenRevealingSensitiveMedia: "センシティブなメディアを表示 sensitiveMediaRevealConfirm: "センシティブなメディアです。表示しますか?" createdLists: "作成したリスト" createdAntennas: "作成したアンテナ" +clipNoteLimitExceeded: "これ以上このクリップにノートを追加できません。" _delivery: status: "配信状態" diff --git a/packages/frontend/src/scripts/get-note-menu.ts b/packages/frontend/src/scripts/get-note-menu.ts index 2563b0baf3..b5d7350a41 100644 --- a/packages/frontend/src/scripts/get-note-menu.ts +++ b/packages/frontend/src/scripts/get-note-menu.ts @@ -66,6 +66,11 @@ export async function getNoteClipMenu(props: { }); if (props.currentClip?.id === clip.id) props.isDeleted.value = true; } + } else if (err.id === 'f0dba960-ff73-4615-8df4-d6ac5d9dc118') { + os.alert({ + type: 'error', + text: i18n.ts.clipNoteLimitExceeded, + }); } else { os.alert({ type: 'error', From 255c8bd1b9a35b36f33b2e524a7146de106d387e Mon Sep 17 00:00:00 2001 From: Kisaragi <48310258+KisaragiEffective@users.noreply.github.com> Date: Mon, 26 Aug 2024 15:55:38 +0900 Subject: [PATCH 12/25] =?UTF-8?q?fix:=20=E6=8A=95=E7=A8=BF=E3=83=95?= =?UTF-8?q?=E3=82=A9=E3=83=BC=E3=83=A0=E3=81=AE=E5=AD=97=E6=95=B0=E4=B8=8A?= =?UTF-8?q?=E9=99=90=E8=A8=88=E7=AE=97=E3=82=92=E5=AE=9F=E9=9A=9B=E3=81=AE?= =?UTF-8?q?=E6=8A=95=E7=A8=BF=E5=86=85=E5=AE=B9=E3=81=AB=E5=90=88=E3=82=8F?= =?UTF-8?q?=E3=81=9B=E3=82=8B=20(#14466)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/frontend/src/components/MkPostForm.vue | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/frontend/src/components/MkPostForm.vue b/packages/frontend/src/components/MkPostForm.vue index f0826fcf4e..df251d9192 100644 --- a/packages/frontend/src/components/MkPostForm.vue +++ b/packages/frontend/src/components/MkPostForm.vue @@ -245,7 +245,7 @@ const submitText = computed((): string => { }); const textLength = computed((): number => { - return (text.value + imeText.value).trim().length; + return (text.value + imeText.value).length; }); const maxTextLength = computed((): number => { From 36dff6688323485fa0d47a74b6db1b7b8d393325 Mon Sep 17 00:00:00 2001 From: syuilo <4439005+syuilo@users.noreply.github.com> Date: Tue, 27 Aug 2024 20:36:43 +0900 Subject: [PATCH 13/25] refactor --- packages/backend/src/server/web/boot.js | 6 +++--- packages/frontend/src/_boot_.ts | 2 ++ packages/frontend/src/_dev_boot_.ts | 5 ----- 3 files changed, 5 insertions(+), 8 deletions(-) diff --git a/packages/backend/src/server/web/boot.js b/packages/backend/src/server/web/boot.js index 5e52360456..5283596316 100644 --- a/packages/backend/src/server/web/boot.js +++ b/packages/backend/src/server/web/boot.js @@ -166,7 +166,7 @@ if (!errorsElement) { document.body.innerHTML = ` - + @@ -178,7 +178,7 @@

The following actions may solve the problem. / 以下を行うと解決する可能性があります。

Update your os and browser / ブラウザおよびOSを最新バージョンに更新する

Disable an adblocker / アドブロッカーを無効にする

-

Clear the browser cache / ブラウザのキャッシュをクリアする

+

Clear the browser cache / ブラウザのキャッシュをクリアする

(Tor Browser) Set dom.webaudio.enabled to true / dom.webaudio.enabledをtrueに設定する

Other options / その他のオプション @@ -320,6 +320,6 @@ #errorInfo { width: 50%; } - }`) + }`); } })(); diff --git a/packages/frontend/src/_boot_.ts b/packages/frontend/src/_boot_.ts index 875353f8a4..13a97e433c 100644 --- a/packages/frontend/src/_boot_.ts +++ b/packages/frontend/src/_boot_.ts @@ -6,6 +6,8 @@ // https://vitejs.dev/config/build-options.html#build-modulepreload import 'vite/modulepreload-polyfill'; +import '@tabler/icons-webfont/dist/tabler-icons.scss'; + import '@/style.scss'; import { mainBoot } from '@/boot/main-boot.js'; import { subBoot } from '@/boot/sub-boot.js'; diff --git a/packages/frontend/src/_dev_boot_.ts b/packages/frontend/src/_dev_boot_.ts index 7c6e537fbc..1601f247d7 100644 --- a/packages/frontend/src/_dev_boot_.ts +++ b/packages/frontend/src/_dev_boot_.ts @@ -3,11 +3,6 @@ * SPDX-License-Identifier: AGPL-3.0-only */ -// devモードで起動される際(index.htmlを使うとき)はrouterが暴発してしまってうまく読み込めない。 -// よって、devモードとして起動されるときはビルド時に組み込む形としておく。 -// (pnpm start時はpugファイルの中で静的リソースとして読み込むようになっており、この問題は起こっていない) -import '@tabler/icons-webfont/dist/tabler-icons.scss'; - await main(); import('@/_boot_.js'); From b6fdd7195725d09ab30245ac174d0ea04ef550ae Mon Sep 17 00:00:00 2001 From: syuilo <4439005+syuilo@users.noreply.github.com> Date: Tue, 27 Aug 2024 20:40:11 +0900 Subject: [PATCH 14/25] =?UTF-8?q?=E6=B6=88=E3=81=97=E5=BF=98=E3=82=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/backend/src/server/web/views/base.pug | 2 -- 1 file changed, 2 deletions(-) diff --git a/packages/backend/src/server/web/views/base.pug b/packages/backend/src/server/web/views/base.pug index 151b7bca6c..da6d1eafd3 100644 --- a/packages/backend/src/server/web/views/base.pug +++ b/packages/backend/src/server/web/views/base.pug @@ -36,8 +36,6 @@ html link(rel='prefetch' href=serverErrorImageUrl) link(rel='prefetch' href=infoImageUrl) link(rel='prefetch' href=notFoundImageUrl) - //- https://github.com/misskey-dev/misskey/issues/9842 - link(rel='stylesheet' href='/assets/tabler-icons/tabler-icons.min.css?v3.3.0') link(rel='modulepreload' href=`/vite/${clientEntry.file}`) if !config.clientManifestExists From 3e85052754b1c86e3c3b16d2e29b5aef6db04ccf Mon Sep 17 00:00:00 2001 From: zyoshoka <107108195+zyoshoka@users.noreply.github.com> Date: Thu, 29 Aug 2024 18:57:44 +0900 Subject: [PATCH 15/25] fix(backend): correct `app`-type notification schema (#14471) --- packages/backend/src/models/Notification.ts | 2 +- packages/backend/src/models/json-schema/notification.ts | 4 ++-- packages/misskey-js/src/autogen/types.ts | 8 ++++---- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/packages/backend/src/models/Notification.ts b/packages/backend/src/models/Notification.ts index df88b99636..87d8c16cb3 100644 --- a/packages/backend/src/models/Notification.ts +++ b/packages/backend/src/models/Notification.ts @@ -85,7 +85,7 @@ export type MiNotification = { /** * アプリ通知のbody */ - customBody: string | null; + customBody: string; /** * アプリ通知のheader diff --git a/packages/backend/src/models/json-schema/notification.ts b/packages/backend/src/models/json-schema/notification.ts index b4c4442758..6f5fb8247b 100644 --- a/packages/backend/src/models/json-schema/notification.ts +++ b/packages/backend/src/models/json-schema/notification.ts @@ -311,11 +311,11 @@ export const packedNotificationSchema = { }, header: { type: 'string', - optional: false, nullable: false, + optional: false, nullable: true, }, icon: { type: 'string', - optional: false, nullable: false, + optional: false, nullable: true, }, }, }, { diff --git a/packages/misskey-js/src/autogen/types.ts b/packages/misskey-js/src/autogen/types.ts index 0c50825203..3f866a9ab3 100644 --- a/packages/misskey-js/src/autogen/types.ts +++ b/packages/misskey-js/src/autogen/types.ts @@ -4253,7 +4253,7 @@ export type components = { /** @enum {string} */ type: 'achievementEarned'; achievement: string; - } | { + } | ({ /** Format: id */ id: string; /** Format: date-time */ @@ -4261,9 +4261,9 @@ export type components = { /** @enum {string} */ type: 'app'; body: string; - header: string; - icon: string; - } | { + header: string | null; + icon: string | null; + }) | { /** Format: id */ id: string; /** Format: date-time */ From 06855f769f1fe8c84fc3bbef615dac0a9fd2cf7b Mon Sep 17 00:00:00 2001 From: zyoshoka <107108195+zyoshoka@users.noreply.github.com> Date: Fri, 30 Aug 2024 10:58:11 +0900 Subject: [PATCH 16/25] refactor(sw): use fully typed locales (#14470) * refactor(sw): use fully typed locales * fix(backend): enumerate achievement notification type --- .../src/models/json-schema/notification.ts | 2 + packages/frontend/src/scripts/i18n.ts | 49 ----------------- packages/frontend/test/i18n.test.ts | 52 +++++++++++++++++++ packages/misskey-js/src/autogen/types.ts | 7 +-- .../sw/src/scripts/create-notification.ts | 50 +++++++++--------- packages/sw/src/scripts/i18n.ts | 37 ------------- packages/sw/src/scripts/lang.ts | 5 +- packages/sw/src/sw.ts | 7 +-- 8 files changed, 89 insertions(+), 120 deletions(-) create mode 100644 packages/frontend/test/i18n.test.ts delete mode 100644 packages/sw/src/scripts/i18n.ts diff --git a/packages/backend/src/models/json-schema/notification.ts b/packages/backend/src/models/json-schema/notification.ts index 6f5fb8247b..b05ec8b762 100644 --- a/packages/backend/src/models/json-schema/notification.ts +++ b/packages/backend/src/models/json-schema/notification.ts @@ -3,6 +3,7 @@ * SPDX-License-Identifier: AGPL-3.0-only */ +import { ACHIEVEMENT_TYPES } from '@/core/AchievementService.js'; import { notificationTypes } from '@/types.js'; const baseSchema = { @@ -294,6 +295,7 @@ export const packedNotificationSchema = { achievement: { type: 'string', optional: false, nullable: false, + enum: ACHIEVEMENT_TYPES, }, }, }, { diff --git a/packages/frontend/src/scripts/i18n.ts b/packages/frontend/src/scripts/i18n.ts index c2f44a33cc..b258a2a678 100644 --- a/packages/frontend/src/scripts/i18n.ts +++ b/packages/frontend/src/scripts/i18n.ts @@ -137,7 +137,6 @@ export class I18n { return this.tsxCache = new Proxy(this.locale, new Handler()) as unknown as Tsx; } - // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition if (this.tsxCache) { return this.tsxCache; } @@ -244,51 +243,3 @@ export class I18n { return str; } } - -if (import.meta.vitest) { - const { describe, expect, it } = import.meta.vitest; - - describe('i18n', () => { - it('t', () => { - const i18n = new I18n({ - foo: 'foo', - bar: { - baz: 'baz', - qux: 'qux {0}' as unknown as ParameterizedString<'0'>, - quux: 'quux {0} {1}' as unknown as ParameterizedString<'0' | '1'>, - }, - }); - - expect(i18n.t('foo')).toBe('foo'); - expect(i18n.t('bar.baz')).toBe('baz'); - expect(i18n.tsx.bar.qux({ 0: 'hoge' })).toBe('qux hoge'); - expect(i18n.tsx.bar.quux({ 0: 'hoge', 1: 'fuga' })).toBe('quux hoge fuga'); - }); - it('ts', () => { - const i18n = new I18n({ - foo: 'foo', - bar: { - baz: 'baz', - qux: 'qux {0}' as unknown as ParameterizedString<'0'>, - quux: 'quux {0} {1}' as unknown as ParameterizedString<'0' | '1'>, - }, - }); - - expect(i18n.ts.foo).toBe('foo'); - expect(i18n.ts.bar.baz).toBe('baz'); - }); - it('tsx', () => { - const i18n = new I18n({ - foo: 'foo', - bar: { - baz: 'baz', - qux: 'qux {0}' as unknown as ParameterizedString<'0'>, - quux: 'quux {0} {1}' as unknown as ParameterizedString<'0' | '1'>, - }, - }); - - expect(i18n.tsx.bar.qux({ 0: 'hoge' })).toBe('qux hoge'); - expect(i18n.tsx.bar.quux({ 0: 'hoge', 1: 'fuga' })).toBe('quux hoge fuga'); - }); - }); -} diff --git a/packages/frontend/test/i18n.test.ts b/packages/frontend/test/i18n.test.ts new file mode 100644 index 0000000000..e1cab1f15f --- /dev/null +++ b/packages/frontend/test/i18n.test.ts @@ -0,0 +1,52 @@ +/* + * SPDX-FileCopyrightText: syuilo and misskey-project + * SPDX-License-Identifier: AGPL-3.0-only + */ + +import { describe, expect, it } from 'vitest'; +import { I18n } from '@/scripts/i18n.js'; +import { ParameterizedString } from '../../../locales/index.js'; + +describe('i18n', () => { + it('t', () => { + const i18n = new I18n({ + foo: 'foo', + bar: { + baz: 'baz', + qux: 'qux {0}' as unknown as ParameterizedString<'0'>, + quux: 'quux {0} {1}' as unknown as ParameterizedString<'0' | '1'>, + }, + }); + + expect(i18n.t('foo')).toBe('foo'); + expect(i18n.t('bar.baz')).toBe('baz'); + expect(i18n.tsx.bar.qux({ 0: 'hoge' })).toBe('qux hoge'); + expect(i18n.tsx.bar.quux({ 0: 'hoge', 1: 'fuga' })).toBe('quux hoge fuga'); + }); + it('ts', () => { + const i18n = new I18n({ + foo: 'foo', + bar: { + baz: 'baz', + qux: 'qux {0}' as unknown as ParameterizedString<'0'>, + quux: 'quux {0} {1}' as unknown as ParameterizedString<'0' | '1'>, + }, + }); + + expect(i18n.ts.foo).toBe('foo'); + expect(i18n.ts.bar.baz).toBe('baz'); + }); + it('tsx', () => { + const i18n = new I18n({ + foo: 'foo', + bar: { + baz: 'baz', + qux: 'qux {0}' as unknown as ParameterizedString<'0'>, + quux: 'quux {0} {1}' as unknown as ParameterizedString<'0' | '1'>, + }, + }); + + expect(i18n.tsx.bar.qux({ 0: 'hoge' })).toBe('qux hoge'); + expect(i18n.tsx.bar.quux({ 0: 'hoge', 1: 'fuga' })).toBe('quux hoge fuga'); + }); +}); diff --git a/packages/misskey-js/src/autogen/types.ts b/packages/misskey-js/src/autogen/types.ts index 3f866a9ab3..37f1bf2d38 100644 --- a/packages/misskey-js/src/autogen/types.ts +++ b/packages/misskey-js/src/autogen/types.ts @@ -4245,15 +4245,16 @@ export type components = { /** @enum {string} */ type: 'roleAssigned'; role: components['schemas']['Role']; - } | { + } | ({ /** Format: id */ id: string; /** Format: date-time */ createdAt: string; /** @enum {string} */ type: 'achievementEarned'; - achievement: string; - } | ({ + /** @enum {string} */ + achievement: 'notes1' | 'notes10' | 'notes100' | 'notes500' | 'notes1000' | 'notes5000' | 'notes10000' | 'notes20000' | 'notes30000' | 'notes40000' | 'notes50000' | 'notes60000' | 'notes70000' | 'notes80000' | 'notes90000' | 'notes100000' | 'login3' | 'login7' | 'login15' | 'login30' | 'login60' | 'login100' | 'login200' | 'login300' | 'login400' | 'login500' | 'login600' | 'login700' | 'login800' | 'login900' | 'login1000' | 'passedSinceAccountCreated1' | 'passedSinceAccountCreated2' | 'passedSinceAccountCreated3' | 'loggedInOnBirthday' | 'loggedInOnNewYearsDay' | 'noteClipped1' | 'noteFavorited1' | 'myNoteFavorited1' | 'profileFilled' | 'markedAsCat' | 'following1' | 'following10' | 'following50' | 'following100' | 'following300' | 'followers1' | 'followers10' | 'followers50' | 'followers100' | 'followers300' | 'followers500' | 'followers1000' | 'collectAchievements30' | 'viewAchievements3min' | 'iLoveMisskey' | 'foundTreasure' | 'client30min' | 'client60min' | 'noteDeletedWithin1min' | 'postedAtLateNight' | 'postedAt0min0sec' | 'selfQuote' | 'htl20npm' | 'viewInstanceChart' | 'outputHelloWorldOnScratchpad' | 'open3windows' | 'driveFolderCircularReference' | 'reactWithoutRead' | 'clickedClickHere' | 'justPlainLucky' | 'setNameToSyuilo' | 'cookieClicked' | 'brainDiver' | 'smashTestNotificationButton' | 'tutorialCompleted' | 'bubbleGameExplodingHead' | 'bubbleGameDoubleExplodingHead'; + }) | ({ /** Format: id */ id: string; /** Format: date-time */ diff --git a/packages/sw/src/scripts/create-notification.ts b/packages/sw/src/scripts/create-notification.ts index 7d28d8a694..02d9b07767 100644 --- a/packages/sw/src/scripts/create-notification.ts +++ b/packages/sw/src/scripts/create-notification.ts @@ -41,11 +41,10 @@ export async function createNotification { const i18n = await (swLang.i18n ?? swLang.fetchLocale()); - const { t } = i18n; switch (data.type) { /* case 'driveFileCreated': // TODO (Server Side) - return [t('_notification.fileUploaded'), { + return [i18n.ts._notification.fileUploaded, { body: body.name, icon: body.url, data @@ -58,7 +57,7 @@ async function composeNotification(data: PushNotificationDataMap[keyof PushNotif const account = await getAccountFromId(data.userId); if (!account) return null; const userDetail = await cli.request('users/show', { userId: data.body.userId }, account.token); - return [t('_notification.youWereFollowed'), { + return [i18n.ts._notification.youWereFollowed, { body: getUserName(data.body.user), icon: data.body.user.avatarUrl, badge: iconUrl('user-plus'), @@ -66,14 +65,14 @@ async function composeNotification(data: PushNotificationDataMap[keyof PushNotif actions: userDetail.isFollowing ? [] : [ { action: 'follow', - title: t('_notification._actions.followBack'), + title: i18n.ts._notification._actions.followBack, }, ], }]; } case 'mention': - return [t('_notification.youGotMention', { name: getUserName(data.body.user) }), { + return [i18n.tsx._notification.youGotMention({ name: getUserName(data.body.user) }), { body: data.body.note.text ?? '', icon: data.body.user.avatarUrl, badge: iconUrl('at'), @@ -81,13 +80,13 @@ async function composeNotification(data: PushNotificationDataMap[keyof PushNotif actions: [ { action: 'reply', - title: t('_notification._actions.reply'), + title: i18n.ts._notification._actions.reply, }, ], }]; case 'reply': - return [t('_notification.youGotReply', { name: getUserName(data.body.user) }), { + return [i18n.tsx._notification.youGotReply({ name: getUserName(data.body.user) }), { body: data.body.note.text ?? '', icon: data.body.user.avatarUrl, badge: iconUrl('arrow-back-up'), @@ -95,13 +94,13 @@ async function composeNotification(data: PushNotificationDataMap[keyof PushNotif actions: [ { action: 'reply', - title: t('_notification._actions.reply'), + title: i18n.ts._notification._actions.reply, }, ], }]; case 'renote': - return [t('_notification.youRenoted', { name: getUserName(data.body.user) }), { + return [i18n.tsx._notification.youRenoted({ name: getUserName(data.body.user) }), { body: data.body.note.text ?? '', icon: data.body.user.avatarUrl, badge: iconUrl('repeat'), @@ -115,7 +114,7 @@ async function composeNotification(data: PushNotificationDataMap[keyof PushNotif }]; case 'quote': - return [t('_notification.youGotQuote', { name: getUserName(data.body.user) }), { + return [i18n.tsx._notification.youGotQuote({ name: getUserName(data.body.user) }), { body: data.body.note.text ?? '', icon: data.body.user.avatarUrl, badge: iconUrl('quote'), @@ -123,19 +122,19 @@ async function composeNotification(data: PushNotificationDataMap[keyof PushNotif actions: [ { action: 'reply', - title: t('_notification._actions.reply'), + title: i18n.ts._notification._actions.reply, }, ...((data.body.note.visibility === 'public' || data.body.note.visibility === 'home') ? [ { action: 'renote', - title: t('_notification._actions.renote'), + title: i18n.ts._notification._actions.renote, }, ] : []), ], }]; case 'note': - return [t('_notification.newNote') + ': ' + getUserName(data.body.user), { + return [i18n.ts._notification.newNote + ': ' + getUserName(data.body.user), { body: data.body.note.text ?? '', icon: data.body.user.avatarUrl, data, @@ -178,7 +177,7 @@ async function composeNotification(data: PushNotificationDataMap[keyof PushNotif } case 'receiveFollowRequest': - return [t('_notification.youReceivedFollowRequest'), { + return [i18n.ts._notification.youReceivedFollowRequest, { body: getUserName(data.body.user), icon: data.body.user.avatarUrl, badge: iconUrl('user-plus'), @@ -186,17 +185,17 @@ async function composeNotification(data: PushNotificationDataMap[keyof PushNotif actions: [ { action: 'accept', - title: t('accept'), + title: i18n.ts.accept, }, { action: 'reject', - title: t('reject'), + title: i18n.ts.reject, }, ], }]; case 'followRequestAccepted': - return [t('_notification.yourFollowRequestAccepted'), { + return [i18n.ts._notification.yourFollowRequestAccepted, { body: getUserName(data.body.user), icon: data.body.user.avatarUrl, badge: iconUrl('circle-check'), @@ -204,15 +203,15 @@ async function composeNotification(data: PushNotificationDataMap[keyof PushNotif }]; case 'achievementEarned': - return [t('_notification.achievementEarned'), { - body: t(`_achievements._types._${data.body.achievement}.title`), + return [i18n.ts._notification.achievementEarned, { + body: i18n.ts._achievements._types[`_${data.body.achievement}`].title, badge: iconUrl('medal'), data, tag: `achievement:${data.body.achievement}`, }]; case 'pollEnded': - return [t('_notification.pollEnded'), { + return [i18n.ts._notification.pollEnded, { body: data.body.note.text ?? '', badge: iconUrl('chart-arrows'), data, @@ -226,8 +225,8 @@ async function composeNotification(data: PushNotificationDataMap[keyof PushNotif }]; case 'test': - return [t('_notification.testNotification'), { - body: t('_notification.notificationWillBeDisplayedLikeThis'), + return [i18n.ts._notification.testNotification, { + body: i18n.ts._notification.notificationWillBeDisplayedLikeThis, badge: iconUrl('bell'), data, }]; @@ -236,7 +235,7 @@ async function composeNotification(data: PushNotificationDataMap[keyof PushNotif return null; } case 'unreadAntennaNote': - return [t('_notification.unreadAntennaNote', { name: data.body.antenna.name }), { + return [i18n.tsx._notification.unreadAntennaNote({ name: data.body.antenna.name }), { body: `${getUserName(data.body.note.user)}: ${data.body.note.text ?? ''}`, icon: data.body.note.user.avatarUrl, badge: iconUrl('antenna'), @@ -252,7 +251,6 @@ async function composeNotification(data: PushNotificationDataMap[keyof PushNotif export async function createEmptyNotification(): Promise { return new Promise(async res => { const i18n = await (swLang.i18n ?? swLang.fetchLocale()); - const { t } = i18n; await globalThis.registration.showNotification( (new URL(origin)).host, @@ -264,11 +262,11 @@ export async function createEmptyNotification(): Promise { actions: [ { action: 'markAllAsRead', - title: t('markAllAsRead'), + title: i18n.ts.markAllAsRead, }, { action: 'settings', - title: t('notificationSettings'), + title: i18n.ts.notificationSettings, }, ], data: {}, diff --git a/packages/sw/src/scripts/i18n.ts b/packages/sw/src/scripts/i18n.ts deleted file mode 100644 index 77b955dbe8..0000000000 --- a/packages/sw/src/scripts/i18n.ts +++ /dev/null @@ -1,37 +0,0 @@ -/* - * SPDX-FileCopyrightText: syuilo and misskey-project - * SPDX-License-Identifier: AGPL-3.0-only - */ - -export type Locale = { [key: string]: string | Locale }; - -export class I18n { - public ts: T; - - constructor(locale: T) { - this.ts = locale; - - //#region BIND - this.t = this.t.bind(this); - //#endregion - } - - // string にしているのは、ドット区切りでのパス指定を許可するため - // なるべくこのメソッド使うよりもlocale直接参照の方がvueのキャッシュ効いてパフォーマンスが良いかも - public t(key: string, args?: Record): string { - try { - let str = key.split('.').reduce((o, i) => o[i], this.ts); - if (typeof str !== 'string') throw new Error(); - - if (args) { - for (const [k, v] of Object.entries(args)) { - str = str.replace(`{${k}}`, v); - } - } - return str; - } catch (err) { - console.warn(`missing localization '${key}'`); - return key; - } - } -} diff --git a/packages/sw/src/scripts/lang.ts b/packages/sw/src/scripts/lang.ts index 6fccedd746..0db4cc6381 100644 --- a/packages/sw/src/scripts/lang.ts +++ b/packages/sw/src/scripts/lang.ts @@ -7,7 +7,8 @@ * Language manager for SW */ import { get, set } from 'idb-keyval'; -import { I18n, type Locale } from '@/scripts/i18n.js'; +import { I18n } from '../../../frontend/src/scripts/i18n.js'; +import type { Locale } from '../../../../locales/index.js'; class SwLang { public cacheName = `mk-cache-${_VERSION_}`; @@ -23,7 +24,7 @@ class SwLang { return this.fetchLocale(); } - public i18n: Promise | null = null; + public i18n: Promise> | null = null; public fetchLocale(): Promise> { return (this.i18n = this._fetch()); diff --git a/packages/sw/src/sw.ts b/packages/sw/src/sw.ts index cc79d88713..7a0010992e 100644 --- a/packages/sw/src/sw.ts +++ b/packages/sw/src/sw.ts @@ -6,7 +6,8 @@ import { get } from 'idb-keyval'; import * as Misskey from 'misskey-js'; import type { PushNotificationDataMap } from '@/types.js'; -import type { I18n, Locale } from '@/scripts/i18n.js'; +import type { I18n } from '../../frontend/src/scripts/i18n.js'; +import type { Locale } from '../../../locales/index.js'; import { createEmptyNotification, createNotification } from '@/scripts/create-notification.js'; import { swLang } from '@/scripts/lang.js'; import * as swos from '@/scripts/operations.js'; @@ -30,8 +31,8 @@ globalThis.addEventListener('activate', ev => { async function offlineContentHTML() { const i18n = await (swLang.i18n ?? swLang.fetchLocale()) as Partial>; const messages = { - title: i18n.ts?._offlineScreen?.title ?? 'Offline - Could not connect to server', - header: i18n.ts?._offlineScreen?.header ?? 'Could not connect to server', + title: i18n.ts?._offlineScreen.title ?? 'Offline - Could not connect to server', + header: i18n.ts?._offlineScreen.header ?? 'Could not connect to server', reload: i18n.ts?.reload ?? 'Reload', }; From 7fe303505961c764561b93e3c34b9e8e83d70698 Mon Sep 17 00:00:00 2001 From: zyoshoka <107108195+zyoshoka@users.noreply.github.com> Date: Fri, 30 Aug 2024 10:58:59 +0900 Subject: [PATCH 17/25] fix(backend): use `prefixItems` in `admin/queue/*-delayed` endpoint schema (#14468) * fix(backend): represent tuples with `prefixItems` * refactor(frontend): fix type errors * fix(backend): add `prefixItems` in `SchemaType` * fix(backend): add `unevaluatedItems: false` to disallow extra items * refactor(frontend): consolidate `'deliver' | 'queue'` type def into `queue.vue` * fix(backend): add `unevaluatedItems` in `SchemaType` --- packages/backend/src/misc/json-schema.ts | 9 ++++++ .../endpoints/admin/queue/deliver-delayed.ts | 19 ++++++------ .../endpoints/admin/queue/inbox-delayed.ts | 19 ++++++------ .../src/pages/admin/overview.queue.vue | 20 +++++++------ .../frontend/src/pages/admin/queue.chart.vue | 30 +++++++++---------- packages/frontend/src/pages/admin/queue.vue | 6 ++-- packages/misskey-js/src/autogen/types.ts | 4 +-- 7 files changed, 59 insertions(+), 48 deletions(-) diff --git a/packages/backend/src/misc/json-schema.ts b/packages/backend/src/misc/json-schema.ts index a721b8663c..040e36228c 100644 --- a/packages/backend/src/misc/json-schema.ts +++ b/packages/backend/src/misc/json-schema.ts @@ -144,7 +144,9 @@ export interface Schema extends OfSchema { readonly type?: TypeStringef; readonly nullable?: boolean; readonly optional?: boolean; + readonly prefixItems?: ReadonlyArray; readonly items?: Schema; + readonly unevaluatedItems?: Schema | boolean; readonly properties?: Obj; readonly required?: ReadonlyArray, string>>; readonly description?: string; @@ -198,6 +200,7 @@ type UnionSchemaType = X //type UnionObjectSchemaType = X extends any ? ObjectSchemaType : never; type UnionObjType = a[number]> = X extends any ? ObjType : never; type ArrayUnion = T extends any ? Array : never; +type ArrayToTuple> = { [K in keyof X]: SchemaType }; type ObjectSchemaTypeDef

= p['ref'] extends keyof typeof refs ? Packed : @@ -232,6 +235,12 @@ export type SchemaTypeDef

= p['items']['allOf'] extends ReadonlyArray ? UnionToIntersection>>[] : never ) : + p['prefixItems'] extends ReadonlyArray ? ( + p['items'] extends NonNullable ? [...ArrayToTuple, ...SchemaType[]] : + p['items'] extends false ? ArrayToTuple : + p['unevaluatedItems'] extends false ? ArrayToTuple : + [...ArrayToTuple, ...unknown[]] + ) : p['items'] extends NonNullable ? SchemaType[] : any[] ) : diff --git a/packages/backend/src/server/api/endpoints/admin/queue/deliver-delayed.ts b/packages/backend/src/server/api/endpoints/admin/queue/deliver-delayed.ts index 7a3410ffa7..f3e440b4cb 100644 --- a/packages/backend/src/server/api/endpoints/admin/queue/deliver-delayed.ts +++ b/packages/backend/src/server/api/endpoints/admin/queue/deliver-delayed.ts @@ -21,16 +21,15 @@ export const meta = { items: { type: 'array', optional: false, nullable: false, - items: { - anyOf: [ - { - type: 'string', - }, - { - type: 'number', - }, - ], - }, + prefixItems: [ + { + type: 'string', + }, + { + type: 'number', + }, + ], + unevaluatedItems: false, }, example: [[ 'example.com', diff --git a/packages/backend/src/server/api/endpoints/admin/queue/inbox-delayed.ts b/packages/backend/src/server/api/endpoints/admin/queue/inbox-delayed.ts index 305ae1af1d..e7589cba81 100644 --- a/packages/backend/src/server/api/endpoints/admin/queue/inbox-delayed.ts +++ b/packages/backend/src/server/api/endpoints/admin/queue/inbox-delayed.ts @@ -21,16 +21,15 @@ export const meta = { items: { type: 'array', optional: false, nullable: false, - items: { - anyOf: [ - { - type: 'string', - }, - { - type: 'number', - }, - ], - }, + prefixItems: [ + { + type: 'string', + }, + { + type: 'number', + }, + ], + unevaluatedItems: false, }, example: [[ 'example.com', diff --git a/packages/frontend/src/pages/admin/overview.queue.vue b/packages/frontend/src/pages/admin/overview.queue.vue index c7478f252a..fb190f5325 100644 --- a/packages/frontend/src/pages/admin/overview.queue.vue +++ b/packages/frontend/src/pages/admin/overview.queue.vue @@ -36,7 +36,9 @@ SPDX-License-Identifier: AGPL-3.0-only + + From cdb0566c5b823f0ce4ecc493bd459cb726431be2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E3=81=8B=E3=81=A3=E3=81=93=E3=81=8B=E3=82=8A?= <67428053+kakkokari-gtyih@users.noreply.github.com> Date: Fri, 6 Sep 2024 16:12:14 +0900 Subject: [PATCH 23/25] =?UTF-8?q?refactor(frontend):=20scss=20deprecated?= =?UTF-8?q?=20=E8=AD=A6=E5=91=8A=E3=81=AB=E5=AF=BE=E5=BF=9C=20(#14513)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../frontend/src/components/MkModalWindow.vue | 6 +++--- packages/frontend/src/components/MkSuperMenu.vue | 6 +++--- packages/frontend/src/components/MkWindow.vue | 8 ++++---- .../frontend/src/pages/admin/overview.users.vue | 8 ++++---- packages/frontend/src/pages/page.vue | 3 +-- packages/frontend/src/style.scss | 8 ++++---- packages/frontend/src/ui/_common_/statusbars.vue | 16 ++++++++-------- packages/frontend/src/ui/deck/column.vue | 6 +++--- 8 files changed, 30 insertions(+), 31 deletions(-) diff --git a/packages/frontend/src/components/MkModalWindow.vue b/packages/frontend/src/components/MkModalWindow.vue index c3c7812036..f26959888b 100644 --- a/packages/frontend/src/components/MkModalWindow.vue +++ b/packages/frontend/src/components/MkModalWindow.vue @@ -94,12 +94,12 @@ defineExpose({ --root-margin: 24px; + --headerHeight: 46px; + --headerHeightNarrow: 42px; + @media (max-width: 500px) { --root-margin: 16px; } - - --headerHeight: 46px; - --headerHeightNarrow: 42px; } .header { diff --git a/packages/frontend/src/components/MkSuperMenu.vue b/packages/frontend/src/components/MkSuperMenu.vue index 1a880170be..3746ffd8f3 100644 --- a/packages/frontend/src/components/MkSuperMenu.vue +++ b/packages/frontend/src/components/MkSuperMenu.vue @@ -100,14 +100,14 @@ defineProps<{ &.grid { > .group { + margin-left: 0; + margin-right: 0; + & + .group { padding-top: 0; border-top: none; } - margin-left: 0; - margin-right: 0; - > .title { font-size: 1em; opacity: 0.7; diff --git a/packages/frontend/src/components/MkWindow.vue b/packages/frontend/src/components/MkWindow.vue index 303e49de00..26ba598498 100644 --- a/packages/frontend/src/components/MkWindow.vue +++ b/packages/frontend/src/components/MkWindow.vue @@ -508,10 +508,6 @@ defineExpose({ .header { --height: 39px; - &.mini { - --height: 32px; - } - display: flex; position: relative; z-index: 1; @@ -524,6 +520,10 @@ defineExpose({ //border-bottom: solid 1px var(--divider); font-size: 90%; font-weight: bold; + + &.mini { + --height: 32px; + } } .headerButton { diff --git a/packages/frontend/src/pages/admin/overview.users.vue b/packages/frontend/src/pages/admin/overview.users.vue index 408be88d47..a7dd4c0a48 100644 --- a/packages/frontend/src/pages/admin/overview.users.vue +++ b/packages/frontend/src/pages/admin/overview.users.vue @@ -47,14 +47,14 @@ useInterval(fetch, 1000 * 60, { .root { &:global { > .users { - .chart-move { - transition: transform 1s ease; - } - display: grid; grid-template-columns: repeat(auto-fill, minmax(200px, 1fr)); grid-gap: 12px; + .chart-move { + transition: transform 1s ease; + } + > .user:hover { text-decoration: none; } diff --git a/packages/frontend/src/pages/page.vue b/packages/frontend/src/pages/page.vue index cb1ce9b918..7ae61236e8 100644 --- a/packages/frontend/src/pages/page.vue +++ b/packages/frontend/src/pages/page.vue @@ -433,13 +433,12 @@ definePageMetadata(() => ({ .pageBannerTitleUser { --height: 32px; flex-shrink: 0; + line-height: var(--height); .avatar { height: var(--height); width: var(--height); } - - line-height: var(--height); } .pageBannerTitleSubActions { diff --git a/packages/frontend/src/style.scss b/packages/frontend/src/style.scss index 44ef740a2e..caaf9fca6f 100644 --- a/packages/frontend/src/style.scss +++ b/packages/frontend/src/style.scss @@ -17,10 +17,6 @@ --minBottomSpacingMobile: calc(72px + max(12px, env(safe-area-inset-bottom, 0px))); --minBottomSpacing: var(--minBottomSpacingMobile); - @media (max-width: 500px) { - --margin: var(--marginHalf); - } - //--ad: rgb(255 169 0 / 10%); --eventFollow: #36aed2; --eventRenote: #36d298; @@ -29,6 +25,10 @@ --eventReaction: #e99a0b; --eventAchievement: #cb9a11; --eventOther: #88a6b7; + + @media (max-width: 500px) { + --margin: var(--marginHalf); + } } ::selection { diff --git a/packages/frontend/src/ui/_common_/statusbars.vue b/packages/frontend/src/ui/_common_/statusbars.vue index 872c69810c..690366307b 100644 --- a/packages/frontend/src/ui/_common_/statusbars.vue +++ b/packages/frontend/src/ui/_common_/statusbars.vue @@ -40,6 +40,14 @@ const XUserList = defineAsyncComponent(() => import('./statusbar-user-list.vue') --nameMargin: 10px; font-size: 0.85em; + display: flex; + vertical-align: bottom; + width: 100%; + line-height: var(--height); + height: var(--height); + overflow: clip; + contain: strict; + &.verySmall { --nameMargin: 7px; --height: 16px; @@ -64,14 +72,6 @@ const XUserList = defineAsyncComponent(() => import('./statusbar-user-list.vue') font-size: 0.9em; } - display: flex; - vertical-align: bottom; - width: 100%; - line-height: var(--height); - height: var(--height); - overflow: clip; - contain: strict; - &.black { background: #000; color: #fff; diff --git a/packages/frontend/src/ui/deck/column.vue b/packages/frontend/src/ui/deck/column.vue index e96402d13b..893301122e 100644 --- a/packages/frontend/src/ui/deck/column.vue +++ b/packages/frontend/src/ui/deck/column.vue @@ -324,11 +324,11 @@ function onDrop(ev) { > .body { background: transparent !important; + scrollbar-color: var(--scrollbarHandle) transparent; &::-webkit-scrollbar-track { background: transparent; } - scrollbar-color: var(--scrollbarHandle) transparent; } } @@ -338,11 +338,11 @@ function onDrop(ev) { > .body { background: var(--bg) !important; overflow-y: scroll !important; + scrollbar-color: var(--scrollbarHandle) transparent; &::-webkit-scrollbar-track { background: inherit; } - scrollbar-color: var(--scrollbarHandle) transparent; } } } @@ -423,10 +423,10 @@ function onDrop(ev) { box-sizing: border-box; container-type: size; background-color: var(--bg); + scrollbar-color: var(--scrollbarHandle) var(--panel); &::-webkit-scrollbar-track { background: var(--panel); } - scrollbar-color: var(--scrollbarHandle) var(--panel); } From 8d19bdbb65c79e2425bf5c73fd8b6310670a8c10 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E3=81=8B=E3=81=A3=E3=81=93=E3=81=8B=E3=82=8A?= <67428053+kakkokari-gtyih@users.noreply.github.com> Date: Fri, 6 Sep 2024 17:22:45 +0900 Subject: [PATCH 24/25] =?UTF-8?q?fix(misskey-js):=20content-type=E3=81=AFa?= =?UTF-8?q?pplication/json=E3=81=A7=E3=81=AA=E3=81=84=E3=82=82=E3=81=AE?= =?UTF-8?q?=E3=81=AE=E3=81=BF=E3=82=92=E8=A8=98=E9=8C=B2=E3=81=99=E3=82=8B?= =?UTF-8?q?=E3=82=88=E3=81=86=E3=81=AB=20(#14508)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../misskey-js/generator/src/generator.ts | 21 +- packages/misskey-js/src/api.ts | 9 +- packages/misskey-js/src/autogen/endpoint.ts | 385 +----------------- 3 files changed, 22 insertions(+), 393 deletions(-) diff --git a/packages/misskey-js/generator/src/generator.ts b/packages/misskey-js/generator/src/generator.ts index 4ae00a4522..88f2ae9ee9 100644 --- a/packages/misskey-js/generator/src/generator.ts +++ b/packages/misskey-js/generator/src/generator.ts @@ -96,15 +96,11 @@ async function generateEndpoints( endpoint.request = req; const reqType = new EndpointReqMediaType(path, req); - endpointReqMediaTypesSet.add(reqType.getMediaType()); - endpointReqMediaTypes.push(reqType); - } else { - endpointReqMediaTypesSet.add('application/json'); - endpointReqMediaTypes.push(new EndpointReqMediaType(path, undefined, 'application/json')); + if (reqType.getMediaType() !== 'application/json') { + endpointReqMediaTypesSet.add(reqType.getMediaType()); + endpointReqMediaTypes.push(reqType); + } } - } else { - endpointReqMediaTypesSet.add('application/json'); - endpointReqMediaTypes.push(new EndpointReqMediaType(path, undefined, 'application/json')); } if (operation.responses && isResponseObject(operation.responses['200']) && operation.responses['200'].content) { @@ -158,16 +154,19 @@ async function generateEndpoints( endpointOutputLine.push(''); function generateEndpointReqMediaTypesType() { - return `Record `'${t}'`).join(' | ')}>`; + return `{ [K in keyof Endpoints]?: ${[...endpointReqMediaTypesSet].map((t) => `'${t}'`).join(' | ')}; }`; } - endpointOutputLine.push(`export const endpointReqTypes: ${generateEndpointReqMediaTypesType()} = {`); + endpointOutputLine.push(`/** + * NOTE: The content-type for all endpoints not listed here is application/json. + */`); + endpointOutputLine.push('export const endpointReqTypes = {'); endpointOutputLine.push( ...endpointReqMediaTypes.map(it => '\t' + it.toLine()), ); - endpointOutputLine.push('};'); + endpointOutputLine.push(`} as const satisfies ${generateEndpointReqMediaTypesType()};`); endpointOutputLine.push(''); await writeFile(endpointOutputPath, endpointOutputLine.join('\n')); diff --git a/packages/misskey-js/src/api.ts b/packages/misskey-js/src/api.ts index ea1df57f3d..659a29a221 100644 --- a/packages/misskey-js/src/api.ts +++ b/packages/misskey-js/src/api.ts @@ -56,6 +56,10 @@ export class APIClient { return obj !== null && typeof obj === 'object' && !Array.isArray(obj); } + private assertSpecialEpReqType(ep: keyof Endpoints): ep is keyof typeof endpointReqTypes { + return ep in endpointReqTypes; + } + public request( endpoint: E, params: P = {} as P, @@ -63,9 +67,10 @@ export class APIClient { ): Promise> { return new Promise((resolve, reject) => { let mediaType = 'application/json'; - if (endpoint in endpointReqTypes) { + if (this.assertSpecialEpReqType(endpoint) && endpointReqTypes[endpoint] != null) { mediaType = endpointReqTypes[endpoint]; } + let payload: FormData | string = '{}'; if (mediaType === 'application/json') { @@ -100,7 +105,7 @@ export class APIClient { method: 'POST', body: payload, headers: { - 'Content-Type': endpointReqTypes[endpoint], + 'Content-Type': mediaType, }, credentials: 'omit', cache: 'no-cache', diff --git a/packages/misskey-js/src/autogen/endpoint.ts b/packages/misskey-js/src/autogen/endpoint.ts index be41951e4d..8fbdbbb629 100644 --- a/packages/misskey-js/src/autogen/endpoint.ts +++ b/packages/misskey-js/src/autogen/endpoint.ts @@ -955,384 +955,9 @@ export type Endpoints = { 'reversi/verify': { req: ReversiVerifyRequest; res: ReversiVerifyResponse }; } -export const endpointReqTypes: Record = { - 'admin/meta': 'application/json', - 'admin/abuse-user-reports': 'application/json', - 'admin/abuse-report/notification-recipient/list': 'application/json', - 'admin/abuse-report/notification-recipient/show': 'application/json', - 'admin/abuse-report/notification-recipient/create': 'application/json', - 'admin/abuse-report/notification-recipient/update': 'application/json', - 'admin/abuse-report/notification-recipient/delete': 'application/json', - 'admin/accounts/create': 'application/json', - 'admin/accounts/delete': 'application/json', - 'admin/accounts/find-by-email': 'application/json', - 'admin/ad/create': 'application/json', - 'admin/ad/delete': 'application/json', - 'admin/ad/list': 'application/json', - 'admin/ad/update': 'application/json', - 'admin/announcements/create': 'application/json', - 'admin/announcements/delete': 'application/json', - 'admin/announcements/list': 'application/json', - 'admin/announcements/update': 'application/json', - 'admin/avatar-decorations/create': 'application/json', - 'admin/avatar-decorations/delete': 'application/json', - 'admin/avatar-decorations/list': 'application/json', - 'admin/avatar-decorations/update': 'application/json', - 'admin/delete-all-files-of-a-user': 'application/json', - 'admin/unset-user-avatar': 'application/json', - 'admin/unset-user-banner': 'application/json', - 'admin/drive/clean-remote-files': 'application/json', - 'admin/drive/cleanup': 'application/json', - 'admin/drive/files': 'application/json', - 'admin/drive/show-file': 'application/json', - 'admin/emoji/add-aliases-bulk': 'application/json', - 'admin/emoji/add': 'application/json', - 'admin/emoji/copy': 'application/json', - 'admin/emoji/delete-bulk': 'application/json', - 'admin/emoji/delete': 'application/json', - 'admin/emoji/import-zip': 'application/json', - 'admin/emoji/list-remote': 'application/json', - 'admin/emoji/list': 'application/json', - 'admin/emoji/remove-aliases-bulk': 'application/json', - 'admin/emoji/set-aliases-bulk': 'application/json', - 'admin/emoji/set-category-bulk': 'application/json', - 'admin/emoji/set-license-bulk': 'application/json', - 'admin/emoji/update': 'application/json', - 'admin/federation/delete-all-files': 'application/json', - 'admin/federation/refresh-remote-instance-metadata': 'application/json', - 'admin/federation/remove-all-following': 'application/json', - 'admin/federation/update-instance': 'application/json', - 'admin/get-index-stats': 'application/json', - 'admin/get-table-stats': 'application/json', - 'admin/get-user-ips': 'application/json', - 'admin/invite/create': 'application/json', - 'admin/invite/list': 'application/json', - 'admin/promo/create': 'application/json', - 'admin/queue/clear': 'application/json', - 'admin/queue/deliver-delayed': 'application/json', - 'admin/queue/inbox-delayed': 'application/json', - 'admin/queue/promote': 'application/json', - 'admin/queue/stats': 'application/json', - 'admin/relays/add': 'application/json', - 'admin/relays/list': 'application/json', - 'admin/relays/remove': 'application/json', - 'admin/reset-password': 'application/json', - 'admin/resolve-abuse-user-report': 'application/json', - 'admin/send-email': 'application/json', - 'admin/server-info': 'application/json', - 'admin/show-moderation-logs': 'application/json', - 'admin/show-user': 'application/json', - 'admin/show-users': 'application/json', - 'admin/suspend-user': 'application/json', - 'admin/unsuspend-user': 'application/json', - 'admin/update-meta': 'application/json', - 'admin/delete-account': 'application/json', - 'admin/update-user-note': 'application/json', - 'admin/roles/create': 'application/json', - 'admin/roles/delete': 'application/json', - 'admin/roles/list': 'application/json', - 'admin/roles/show': 'application/json', - 'admin/roles/update': 'application/json', - 'admin/roles/assign': 'application/json', - 'admin/roles/unassign': 'application/json', - 'admin/roles/update-default-policies': 'application/json', - 'admin/roles/users': 'application/json', - 'admin/system-webhook/create': 'application/json', - 'admin/system-webhook/delete': 'application/json', - 'admin/system-webhook/list': 'application/json', - 'admin/system-webhook/show': 'application/json', - 'admin/system-webhook/update': 'application/json', - 'announcements': 'application/json', - 'announcements/show': 'application/json', - 'antennas/create': 'application/json', - 'antennas/delete': 'application/json', - 'antennas/list': 'application/json', - 'antennas/notes': 'application/json', - 'antennas/show': 'application/json', - 'antennas/update': 'application/json', - 'ap/get': 'application/json', - 'ap/show': 'application/json', - 'app/create': 'application/json', - 'app/show': 'application/json', - 'auth/accept': 'application/json', - 'auth/session/generate': 'application/json', - 'auth/session/show': 'application/json', - 'auth/session/userkey': 'application/json', - 'blocking/create': 'application/json', - 'blocking/delete': 'application/json', - 'blocking/list': 'application/json', - 'channels/create': 'application/json', - 'channels/featured': 'application/json', - 'channels/follow': 'application/json', - 'channels/followed': 'application/json', - 'channels/owned': 'application/json', - 'channels/show': 'application/json', - 'channels/timeline': 'application/json', - 'channels/unfollow': 'application/json', - 'channels/update': 'application/json', - 'channels/favorite': 'application/json', - 'channels/unfavorite': 'application/json', - 'channels/my-favorites': 'application/json', - 'channels/search': 'application/json', - 'charts/active-users': 'application/json', - 'charts/ap-request': 'application/json', - 'charts/drive': 'application/json', - 'charts/federation': 'application/json', - 'charts/instance': 'application/json', - 'charts/notes': 'application/json', - 'charts/user/drive': 'application/json', - 'charts/user/following': 'application/json', - 'charts/user/notes': 'application/json', - 'charts/user/pv': 'application/json', - 'charts/user/reactions': 'application/json', - 'charts/users': 'application/json', - 'clips/add-note': 'application/json', - 'clips/remove-note': 'application/json', - 'clips/create': 'application/json', - 'clips/delete': 'application/json', - 'clips/list': 'application/json', - 'clips/notes': 'application/json', - 'clips/show': 'application/json', - 'clips/update': 'application/json', - 'clips/favorite': 'application/json', - 'clips/unfavorite': 'application/json', - 'clips/my-favorites': 'application/json', - 'drive': 'application/json', - 'drive/files': 'application/json', - 'drive/files/attached-notes': 'application/json', - 'drive/files/check-existence': 'application/json', +/** + * NOTE: The content-type for all endpoints not listed here is application/json. + */ +export const endpointReqTypes = { 'drive/files/create': 'multipart/form-data', - 'drive/files/delete': 'application/json', - 'drive/files/find-by-hash': 'application/json', - 'drive/files/find': 'application/json', - 'drive/files/show': 'application/json', - 'drive/files/update': 'application/json', - 'drive/files/upload-from-url': 'application/json', - 'drive/folders': 'application/json', - 'drive/folders/create': 'application/json', - 'drive/folders/delete': 'application/json', - 'drive/folders/find': 'application/json', - 'drive/folders/show': 'application/json', - 'drive/folders/update': 'application/json', - 'drive/stream': 'application/json', - 'email-address/available': 'application/json', - 'endpoint': 'application/json', - 'endpoints': 'application/json', - 'export-custom-emojis': 'application/json', - 'federation/followers': 'application/json', - 'federation/following': 'application/json', - 'federation/instances': 'application/json', - 'federation/show-instance': 'application/json', - 'federation/update-remote-user': 'application/json', - 'federation/users': 'application/json', - 'federation/stats': 'application/json', - 'following/create': 'application/json', - 'following/delete': 'application/json', - 'following/update': 'application/json', - 'following/update-all': 'application/json', - 'following/invalidate': 'application/json', - 'following/requests/accept': 'application/json', - 'following/requests/cancel': 'application/json', - 'following/requests/list': 'application/json', - 'following/requests/reject': 'application/json', - 'gallery/featured': 'application/json', - 'gallery/popular': 'application/json', - 'gallery/posts': 'application/json', - 'gallery/posts/create': 'application/json', - 'gallery/posts/delete': 'application/json', - 'gallery/posts/like': 'application/json', - 'gallery/posts/show': 'application/json', - 'gallery/posts/unlike': 'application/json', - 'gallery/posts/update': 'application/json', - 'get-online-users-count': 'application/json', - 'get-avatar-decorations': 'application/json', - 'hashtags/list': 'application/json', - 'hashtags/search': 'application/json', - 'hashtags/show': 'application/json', - 'hashtags/trend': 'application/json', - 'hashtags/users': 'application/json', - 'i': 'application/json', - 'i/2fa/done': 'application/json', - 'i/2fa/key-done': 'application/json', - 'i/2fa/password-less': 'application/json', - 'i/2fa/register-key': 'application/json', - 'i/2fa/register': 'application/json', - 'i/2fa/update-key': 'application/json', - 'i/2fa/remove-key': 'application/json', - 'i/2fa/unregister': 'application/json', - 'i/apps': 'application/json', - 'i/authorized-apps': 'application/json', - 'i/claim-achievement': 'application/json', - 'i/change-password': 'application/json', - 'i/delete-account': 'application/json', - 'i/export-blocking': 'application/json', - 'i/export-following': 'application/json', - 'i/export-mute': 'application/json', - 'i/export-notes': 'application/json', - 'i/export-clips': 'application/json', - 'i/export-favorites': 'application/json', - 'i/export-user-lists': 'application/json', - 'i/export-antennas': 'application/json', - 'i/favorites': 'application/json', - 'i/gallery/likes': 'application/json', - 'i/gallery/posts': 'application/json', - 'i/import-blocking': 'application/json', - 'i/import-following': 'application/json', - 'i/import-muting': 'application/json', - 'i/import-user-lists': 'application/json', - 'i/import-antennas': 'application/json', - 'i/notifications': 'application/json', - 'i/notifications-grouped': 'application/json', - 'i/page-likes': 'application/json', - 'i/pages': 'application/json', - 'i/pin': 'application/json', - 'i/read-all-unread-notes': 'application/json', - 'i/read-announcement': 'application/json', - 'i/regenerate-token': 'application/json', - 'i/registry/get-all': 'application/json', - 'i/registry/get-detail': 'application/json', - 'i/registry/get': 'application/json', - 'i/registry/keys-with-type': 'application/json', - 'i/registry/keys': 'application/json', - 'i/registry/remove': 'application/json', - 'i/registry/scopes-with-domain': 'application/json', - 'i/registry/set': 'application/json', - 'i/revoke-token': 'application/json', - 'i/signin-history': 'application/json', - 'i/unpin': 'application/json', - 'i/update-email': 'application/json', - 'i/update': 'application/json', - 'i/move': 'application/json', - 'i/webhooks/create': 'application/json', - 'i/webhooks/list': 'application/json', - 'i/webhooks/show': 'application/json', - 'i/webhooks/update': 'application/json', - 'i/webhooks/delete': 'application/json', - 'invite/create': 'application/json', - 'invite/delete': 'application/json', - 'invite/list': 'application/json', - 'invite/limit': 'application/json', - 'meta': 'application/json', - 'emojis': 'application/json', - 'emoji': 'application/json', - 'miauth/gen-token': 'application/json', - 'mute/create': 'application/json', - 'mute/delete': 'application/json', - 'mute/list': 'application/json', - 'renote-mute/create': 'application/json', - 'renote-mute/delete': 'application/json', - 'renote-mute/list': 'application/json', - 'my/apps': 'application/json', - 'notes': 'application/json', - 'notes/children': 'application/json', - 'notes/clips': 'application/json', - 'notes/conversation': 'application/json', - 'notes/create': 'application/json', - 'notes/delete': 'application/json', - 'notes/favorites/create': 'application/json', - 'notes/favorites/delete': 'application/json', - 'notes/featured': 'application/json', - 'notes/global-timeline': 'application/json', - 'notes/hybrid-timeline': 'application/json', - 'notes/local-timeline': 'application/json', - 'notes/mentions': 'application/json', - 'notes/polls/recommendation': 'application/json', - 'notes/polls/vote': 'application/json', - 'notes/reactions': 'application/json', - 'notes/reactions/create': 'application/json', - 'notes/reactions/delete': 'application/json', - 'notes/renotes': 'application/json', - 'notes/replies': 'application/json', - 'notes/search-by-tag': 'application/json', - 'notes/search': 'application/json', - 'notes/show': 'application/json', - 'notes/state': 'application/json', - 'notes/thread-muting/create': 'application/json', - 'notes/thread-muting/delete': 'application/json', - 'notes/timeline': 'application/json', - 'notes/translate': 'application/json', - 'notes/unrenote': 'application/json', - 'notes/user-list-timeline': 'application/json', - 'notifications/create': 'application/json', - 'notifications/flush': 'application/json', - 'notifications/mark-all-as-read': 'application/json', - 'notifications/test-notification': 'application/json', - 'page-push': 'application/json', - 'pages/create': 'application/json', - 'pages/delete': 'application/json', - 'pages/featured': 'application/json', - 'pages/like': 'application/json', - 'pages/show': 'application/json', - 'pages/unlike': 'application/json', - 'pages/update': 'application/json', - 'flash/create': 'application/json', - 'flash/delete': 'application/json', - 'flash/featured': 'application/json', - 'flash/like': 'application/json', - 'flash/show': 'application/json', - 'flash/unlike': 'application/json', - 'flash/update': 'application/json', - 'flash/my': 'application/json', - 'flash/my-likes': 'application/json', - 'ping': 'application/json', - 'pinned-users': 'application/json', - 'promo/read': 'application/json', - 'roles/list': 'application/json', - 'roles/show': 'application/json', - 'roles/users': 'application/json', - 'roles/notes': 'application/json', - 'request-reset-password': 'application/json', - 'reset-db': 'application/json', - 'reset-password': 'application/json', - 'server-info': 'application/json', - 'stats': 'application/json', - 'sw/show-registration': 'application/json', - 'sw/update-registration': 'application/json', - 'sw/register': 'application/json', - 'sw/unregister': 'application/json', - 'test': 'application/json', - 'username/available': 'application/json', - 'users': 'application/json', - 'users/clips': 'application/json', - 'users/followers': 'application/json', - 'users/following': 'application/json', - 'users/gallery/posts': 'application/json', - 'users/get-frequently-replied-users': 'application/json', - 'users/featured-notes': 'application/json', - 'users/lists/create': 'application/json', - 'users/lists/delete': 'application/json', - 'users/lists/list': 'application/json', - 'users/lists/pull': 'application/json', - 'users/lists/push': 'application/json', - 'users/lists/show': 'application/json', - 'users/lists/favorite': 'application/json', - 'users/lists/unfavorite': 'application/json', - 'users/lists/update': 'application/json', - 'users/lists/create-from-public': 'application/json', - 'users/lists/update-membership': 'application/json', - 'users/lists/get-memberships': 'application/json', - 'users/notes': 'application/json', - 'users/pages': 'application/json', - 'users/flashs': 'application/json', - 'users/reactions': 'application/json', - 'users/recommendation': 'application/json', - 'users/relation': 'application/json', - 'users/report-abuse': 'application/json', - 'users/search-by-username-and-host': 'application/json', - 'users/search': 'application/json', - 'users/show': 'application/json', - 'users/achievements': 'application/json', - 'users/update-memo': 'application/json', - 'fetch-rss': 'application/json', - 'fetch-external-resources': 'application/json', - 'retention': 'application/json', - 'bubble-game/register': 'application/json', - 'bubble-game/ranking': 'application/json', - 'reversi/cancel-match': 'application/json', - 'reversi/games': 'application/json', - 'reversi/match': 'application/json', - 'reversi/invitations': 'application/json', - 'reversi/show-game': 'application/json', - 'reversi/surrender': 'application/json', - 'reversi/verify': 'application/json', -}; +} as const satisfies { [K in keyof Endpoints]?: 'multipart/form-data'; }; From 567acea2a3a040dbde69748deb2112e3ff2b92b8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E3=81=8B=E3=81=A3=E3=81=93=E3=81=8B=E3=82=8A?= <67428053+kakkokari-gtyih@users.noreply.github.com> Date: Fri, 6 Sep 2024 17:23:40 +0900 Subject: [PATCH 25/25] =?UTF-8?q?fix(frontend):=20instance=20info=E3=83=9A?= =?UTF-8?q?=E3=83=BC=E3=82=B8=E3=81=A7=E4=B8=8D=E5=BF=85=E8=A6=81=E3=81=AA?= =?UTF-8?q?api=E3=83=AA=E3=82=AF=E3=82=A8=E3=82=B9=E3=83=88=E3=81=8C?= =?UTF-8?q?=E9=A3=9B=E3=81=B6=E3=81=AE=E3=82=92=E6=8A=91=E6=AD=A2=20(#1451?= =?UTF-8?q?5)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * fix(frontend): instance infoページで不必要なapiリクエストが飛ぶのを抑止 * fix --- packages/frontend/src/components/MkChart.vue | 50 ++++++++++--------- packages/frontend/src/pages/instance-info.vue | 25 +++++++--- 2 files changed, 43 insertions(+), 32 deletions(-) diff --git a/packages/frontend/src/components/MkChart.vue b/packages/frontend/src/components/MkChart.vue index 4b24562249..57d325b11a 100644 --- a/packages/frontend/src/components/MkChart.vue +++ b/packages/frontend/src/components/MkChart.vue @@ -13,29 +13,8 @@ SPDX-License-Identifier: AGPL-3.0-only

- + +