From a3c2dbbfb59cf95f1f3972e0e08dde50a66b7829 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Acid=20Chicken=20=28=E7=A1=AB=E9=85=B8=E9=B6=8F=29?= Date: Tue, 19 Jul 2022 17:09:21 +0900 Subject: [PATCH 01/47] fix(server): make sure `getFileInfo` doesn't fail if `detectSensitivity` ever fails (#9020) --- packages/backend/src/misc/get-file-info.ts | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/packages/backend/src/misc/get-file-info.ts b/packages/backend/src/misc/get-file-info.ts index 42061fcf8..1c988b248 100644 --- a/packages/backend/src/misc/get-file-info.ts +++ b/packages/backend/src/misc/get-file-info.ts @@ -101,13 +101,17 @@ export async function getFileInfo(path: string, opts: { let porn = false; if (!opts.skipSensitiveDetection) { - [sensitive, porn] = await detectSensitivity( + await detectSensitivity( path, type.mime, opts.sensitiveThreshold ?? 0.5, opts.sensitiveThresholdForPorn ?? 0.75, opts.enableSensitiveMediaDetectionForVideos ?? false, - ); + ).then(value => { + [sensitive, porn] = value; + }, error => { + warnings.push(`detectSensitivity failed: ${error}`); + }); } return { From 7dd381bb5cddde6b83b2d7c1c8639503ff8965dc Mon Sep 17 00:00:00 2001 From: syuilo Date: Tue, 19 Jul 2022 17:10:21 +0900 Subject: [PATCH 02/47] Update CHANGELOG.md --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 114481357..c8926cb6d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,6 +15,7 @@ You should also include the user name that made the change. - Client: UIのブラッシュアップ @syuilo ### Bugfixes +- Server: ファイルのアップロードに失敗することがある問題を修正 @acid-chicken - Client: リアクションピッカーがアプリ内ウィンドウの後ろに表示されてしまう問題を修正 @syuilo - Client: ユーザー情報の取得の再試行を修正する @xianonn From 5b8d960b9fdfba46b707d768e9cf321270ae5c05 Mon Sep 17 00:00:00 2001 From: syuilo Date: Tue, 19 Jul 2022 17:13:24 +0900 Subject: [PATCH 03/47] fix(client): tweak mfm-cheat-sheet --- CHANGELOG.md | 3 +- locales/ja-JP.yml | 2 + packages/client/src/pages/mfm-cheat-sheet.vue | 643 +++++++++--------- 3 files changed, 332 insertions(+), 316 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c8926cb6d..0c6423149 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -17,7 +17,8 @@ You should also include the user name that made the change. ### Bugfixes - Server: ファイルのアップロードに失敗することがある問題を修正 @acid-chicken - Client: リアクションピッカーがアプリ内ウィンドウの後ろに表示されてしまう問題を修正 @syuilo -- Client: ユーザー情報の取得の再試行を修正する @xianonn +- Client: ユーザー情報の取得の再試行を修正 @xianonn +- Client: MFMチートシートの挙動を修正 @syuilo ## 12.117.0 (2022/07/18) diff --git a/locales/ja-JP.yml b/locales/ja-JP.yml index e071b4bda..0c4a7c723 100644 --- a/locales/ja-JP.yml +++ b/locales/ja-JP.yml @@ -1038,6 +1038,8 @@ _mfm: sparkleDescription: "キラキラしたパーティクルのエフェクトを追加します。" rotate: "回転" rotateDescription: "指定した角度で回転させます。" + plain: "プレーン" + plainDescription: "内側の構文を全て無効にします。" _instanceTicker: none: "表示しない" diff --git a/packages/client/src/pages/mfm-cheat-sheet.vue b/packages/client/src/pages/mfm-cheat-sheet.vue index 3315479ab..0b5dae996 100644 --- a/packages/client/src/pages/mfm-cheat-sheet.vue +++ b/packages/client/src/pages/mfm-cheat-sheet.vue @@ -1,301 +1,313 @@ @@ -306,35 +318,36 @@ import { definePageMetadata } from '@/scripts/page-metadata'; import { i18n } from '@/i18n'; import { instance } from '@/instance'; -const preview_mention = '@example'; -const preview_hashtag = '#test'; -const preview_url = 'https://example.com'; -const preview_link = `[${i18n.ts._mfm.dummy}](https://example.com)`; -const preview_emoji = instance.emojis.length ? `:${instance.emojis[0].name}:` : ':emojiname:'; -const preview_bold = `**${i18n.ts._mfm.dummy}**`; -const preview_small = `${i18n.ts._mfm.dummy}`; -const preview_center = `
${i18n.ts._mfm.dummy}
`; -const preview_inlineCode = '`<: "Hello, world!"`'; -const preview_blockCode = '```\n~ (#i, 100) {\n\t<: ? ((i % 15) = 0) "FizzBuzz"\n\t\t.? ((i % 3) = 0) "Fizz"\n\t\t.? ((i % 5) = 0) "Buzz"\n\t\t. i\n}\n```'; -const preview_inlineMath = '\\(x= \\frac{-b\' \\pm \\sqrt{(b\')^2-ac}}{a}\\)'; -const preview_quote = `> ${i18n.ts._mfm.dummy}`; -const preview_search = `${i18n.ts._mfm.dummy} 検索`; -const preview_jelly = '$[jelly 🍮] $[jelly.speed=5s 🍮]'; -const preview_tada = '$[tada 🍮] $[tada.speed=5s 🍮]'; -const preview_jump = '$[jump 🍮] $[jump.speed=5s 🍮]'; -const preview_bounce = '$[bounce 🍮] $[bounce.speed=5s 🍮]'; -const preview_shake = '$[shake 🍮] $[shake.speed=5s 🍮]'; -const preview_twitch = '$[twitch 🍮] $[twitch.speed=5s 🍮]'; -const preview_spin = '$[spin 🍮] $[spin.left 🍮] $[spin.alternate 🍮]\n$[spin.x 🍮] $[spin.x,left 🍮] $[spin.x,alternate 🍮]\n$[spin.y 🍮] $[spin.y,left 🍮] $[spin.y,alternate 🍮]\n\n$[spin.speed=5s 🍮]'; -const preview_flip = `$[flip ${i18n.ts._mfm.dummy}]\n$[flip.v ${i18n.ts._mfm.dummy}]\n$[flip.h,v ${i18n.ts._mfm.dummy}]`; -const preview_font = `$[font.serif ${i18n.ts._mfm.dummy}]\n$[font.monospace ${i18n.ts._mfm.dummy}]\n$[font.cursive ${i18n.ts._mfm.dummy}]\n$[font.fantasy ${i18n.ts._mfm.dummy}]`; -const preview_x2 = '$[x2 🍮]'; -const preview_x3 = '$[x3 🍮]'; -const preview_x4 = '$[x4 🍮]'; -const preview_blur = `$[blur ${i18n.ts._mfm.dummy}]`; -const preview_rainbow = '$[rainbow 🍮] $[rainbow.speed=5s 🍮]'; -const preview_sparkle = '$[sparkle 🍮]'; -const preview_rotate = '$[rotate 🍮]'; +let preview_mention = $ref('@example'); +let preview_hashtag = $ref('#test'); +let preview_url = $ref('https://example.com'); +let preview_link = $ref(`[${i18n.ts._mfm.dummy}](https://example.com)`); +let preview_emoji = $ref(instance.emojis.length ? `:${instance.emojis[0].name}:` : ':emojiname:'); +let preview_bold = $ref(`**${i18n.ts._mfm.dummy}**`); +let preview_small = $ref(`${i18n.ts._mfm.dummy}`); +let preview_center = $ref(`
${i18n.ts._mfm.dummy}
`); +let preview_inlineCode = $ref('`<: "Hello, world!"`'); +let preview_blockCode = $ref('```\n~ (#i, 100) {\n\t<: ? ((i % 15) = 0) "FizzBuzz"\n\t\t.? ((i % 3) = 0) "Fizz"\n\t\t.? ((i % 5) = 0) "Buzz"\n\t\t. i\n}\n```'); +let preview_inlineMath = $ref('\\(x= \\frac{-b\' \\pm \\sqrt{(b\')^2-ac}}{a}\\)'); +let preview_quote = $ref(`> ${i18n.ts._mfm.dummy}`); +let preview_search = $ref(`${i18n.ts._mfm.dummy} 検索`); +let preview_jelly = $ref('$[jelly 🍮] $[jelly.speed=5s 🍮]'); +let preview_tada = $ref('$[tada 🍮] $[tada.speed=5s 🍮]'); +let preview_jump = $ref('$[jump 🍮] $[jump.speed=5s 🍮]'); +let preview_bounce = $ref('$[bounce 🍮] $[bounce.speed=5s 🍮]'); +let preview_shake = $ref('$[shake 🍮] $[shake.speed=5s 🍮]'); +let preview_twitch = $ref('$[twitch 🍮] $[twitch.speed=5s 🍮]'); +let preview_spin = $ref('$[spin 🍮] $[spin.left 🍮] $[spin.alternate 🍮]\n$[spin.x 🍮] $[spin.x,left 🍮] $[spin.x,alternate 🍮]\n$[spin.y 🍮] $[spin.y,left 🍮] $[spin.y,alternate 🍮]\n\n$[spin.speed=5s 🍮]'); +let preview_flip = $ref(`$[flip ${i18n.ts._mfm.dummy}]\n$[flip.v ${i18n.ts._mfm.dummy}]\n$[flip.h,v ${i18n.ts._mfm.dummy}]`); +let preview_font = $ref(`$[font.serif ${i18n.ts._mfm.dummy}]\n$[font.monospace ${i18n.ts._mfm.dummy}]\n$[font.cursive ${i18n.ts._mfm.dummy}]\n$[font.fantasy ${i18n.ts._mfm.dummy}]`); +let preview_x2 = $ref('$[x2 🍮]'); +let preview_x3 = $ref('$[x3 🍮]'); +let preview_x4 = $ref('$[x4 🍮]'); +let preview_blur = $ref(`$[blur ${i18n.ts._mfm.dummy}]`); +let preview_rainbow = $ref('$[rainbow 🍮] $[rainbow.speed=5s 🍮]'); +let preview_sparkle = $ref('$[sparkle 🍮]'); +let preview_rotate = $ref('$[rotate 🍮]'); +let preview_plain = $ref('**bold** @mention #hashtag `code` $[x2 🍮]'); definePageMetadata({ title: i18n.ts._mfm.cheatSheet, From 4769cd420b03703078417eaec8b7b7222a264d2d Mon Sep 17 00:00:00 2001 From: syuilo Date: Tue, 19 Jul 2022 17:21:03 +0900 Subject: [PATCH 04/47] =?UTF-8?q?fix(client):=20=E3=80=8C=E3=82=A4?= =?UTF-8?q?=E3=83=B3=E3=82=B9=E3=82=BF=E3=83=B3=E3=82=B9=E3=81=8B=E3=82=89?= =?UTF-8?q?=E3=81=AE=E3=81=8A=E7=9F=A5=E3=82=89=E3=81=9B=E3=82=92=E5=8F=97?= =?UTF-8?q?=E3=81=91=E5=8F=96=E3=82=8B=E3=80=8D=E3=81=AE=E8=A8=AD=E5=AE=9A?= =?UTF-8?q?=E3=82=92=E5=A4=89=E6=9B=B4=E3=81=A7=E3=81=8D=E3=81=AA=E3=81=84?= =?UTF-8?q?=E5=95=8F=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 Fix #8474 --- CHANGELOG.md | 1 + packages/client/src/pages/settings/email.vue | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0c6423149..c337e13df 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -19,6 +19,7 @@ You should also include the user name that made the change. - Client: リアクションピッカーがアプリ内ウィンドウの後ろに表示されてしまう問題を修正 @syuilo - Client: ユーザー情報の取得の再試行を修正 @xianonn - Client: MFMチートシートの挙動を修正 @syuilo +- Client: 「インスタンスからのお知らせを受け取る」の設定を変更できない問題を修正 @syuilo ## 12.117.0 (2022/07/18) diff --git a/packages/client/src/pages/settings/email.vue b/packages/client/src/pages/settings/email.vue index e575af6d6..9d2afd6a6 100644 --- a/packages/client/src/pages/settings/email.vue +++ b/packages/client/src/pages/settings/email.vue @@ -10,7 +10,7 @@ - + {{ $ts.receiveAnnouncementFromInstance }} From c3c74c098d160d94af78bdf029b8f999432adc63 Mon Sep 17 00:00:00 2001 From: syuilo Date: Tue, 19 Jul 2022 17:21:30 +0900 Subject: [PATCH 05/47] New translations ja-JP.yml (Slovak) (#9014) --- locales/sk-SK.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/locales/sk-SK.yml b/locales/sk-SK.yml index 2ac0a8566..4fbdc1cb1 100644 --- a/locales/sk-SK.yml +++ b/locales/sk-SK.yml @@ -885,6 +885,7 @@ enableAutoSensitiveDescription: "Ak je zapnuté, príznak NSFW sa na médiách a activeEmailValidationDescription: "Dôkladnejšie overí e-mailovú adresu používateľa tým, že zistí, či ide o vyradenú e-mailovú adresu a či sa s ňou dá skutočne komunikovať. Ak nie je začiarknuté, e-mailová adresa sa kontroluje len ako text." navbar: "Navigačný panel" account: "Účty" +move: "Pohyb" _sensitiveMediaDetection: description: "Strojové učenie sa použije na automatickú detekciu citlivých médií na účely ich moderovania. Mierne sa zvýši zaťaženie servera." sensitivity: "Citlivosť detekcie" @@ -1691,6 +1692,7 @@ _deck: alwaysShowMainColumn: "Vždy zobraziť v hlavnom stĺpci" columnAlign: "Zarovnať stĺpce" addColumn: "Pridať stĺpec" + configureColumn: "Nastavenie stĺpcov" swapLeft: "Vymeniť vľavo" swapRight: "Vymeniť vpravo" swapUp: "Vymeniť hore" From b495f6cffff7a9a41cc72bd11417d7b9d79e0f27 Mon Sep 17 00:00:00 2001 From: syuilo Date: Tue, 19 Jul 2022 17:22:24 +0900 Subject: [PATCH 06/47] 12.117.1 --- CHANGELOG.md | 2 +- package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c337e13df..59c748fb6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,7 +9,7 @@ You should also include the user name that made the change. --> -## 12.x.x (unreleased) +## 12.117.1 (2022/07/19) ### Improvements - Client: UIのブラッシュアップ @syuilo diff --git a/package.json b/package.json index 2699b7dc9..cabb9f8f9 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "misskey", - "version": "12.117.0", + "version": "12.117.1", "codename": "indigo", "repository": { "type": "git", From 17afbc3c46f7bd11351b5775f08356e598d60110 Mon Sep 17 00:00:00 2001 From: syuilo Date: Tue, 19 Jul 2022 21:36:33 +0900 Subject: [PATCH 07/47] enhance(client): suspense Fix #8817 --- CHANGELOG.md | 7 +++++++ packages/client/src/components/global/router-view.vue | 8 +++++++- 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 59c748fb6..4fd6ff231 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,13 @@ You should also include the user name that made the change. --> +## 12.x.x (unreleased) + +### Improvements + +### Bugfixes +- Client: 一度作ったwebhookの設定画面を開こうとするとページがフリーズする @syuilo + ## 12.117.1 (2022/07/19) ### Improvements diff --git a/packages/client/src/components/global/router-view.vue b/packages/client/src/components/global/router-view.vue index fca2371f0..cd1e78019 100644 --- a/packages/client/src/components/global/router-view.vue +++ b/packages/client/src/components/global/router-view.vue @@ -1,6 +1,12 @@ From 66f1aaf5f7ba793500123320ac723b5c3fbe80d6 Mon Sep 17 00:00:00 2001 From: syuilo Date: Wed, 20 Jul 2022 19:59:27 +0900 Subject: [PATCH 08/47] =?UTF-8?q?enhance(client):=20=E3=83=8D=E3=82=B9?= =?UTF-8?q?=E3=83=88=E3=81=97=E3=81=9F=E3=83=AB=E3=83=BC=E3=83=86=E3=82=A3?= =?UTF-8?q?=E3=83=B3=E3=82=B0=E3=81=AB=E5=AF=BE=E5=BF=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/components/global/router-view.vue | 38 +++- .../client/src/components/page-window.vue | 2 +- packages/client/src/nirax.ts | 190 +++++++++++------- packages/client/src/pages/_empty_.vue | 7 + packages/client/src/pages/admin/index.vue | 99 +++------ packages/client/src/pages/settings/index.vue | 144 ++++--------- ....statusbar.vue => statusbar.statusbar.vue} | 0 .../{statusbars.vue => statusbar.vue} | 2 +- packages/client/src/router.ts | 174 +++++++++++++++- 9 files changed, 391 insertions(+), 265 deletions(-) create mode 100644 packages/client/src/pages/_empty_.vue rename packages/client/src/pages/settings/{statusbars.statusbar.vue => statusbar.statusbar.vue} (100%) rename packages/client/src/pages/settings/{statusbars.vue => statusbar.vue} (96%) diff --git a/packages/client/src/components/global/router-view.vue b/packages/client/src/components/global/router-view.vue index cd1e78019..1d841e050 100644 --- a/packages/client/src/components/global/router-view.vue +++ b/packages/client/src/components/global/router-view.vue @@ -11,8 +11,8 @@ diff --git a/packages/client/src/components/page-window.vue b/packages/client/src/components/page-window.vue index 98140b95c..43d75b0cf 100644 --- a/packages/client/src/components/page-window.vue +++ b/packages/client/src/components/page-window.vue @@ -114,7 +114,7 @@ function menu(ev) { function back() { history.pop(); - router.change(history[history.length - 1].path, history[history.length - 1].key); + router.replace(history[history.length - 1].path, history[history.length - 1].key); } function close() { diff --git a/packages/client/src/nirax.ts b/packages/client/src/nirax.ts index 4ba1fe70f..0ee39bf47 100644 --- a/packages/client/src/nirax.ts +++ b/packages/client/src/nirax.ts @@ -13,6 +13,7 @@ type RouteDef = { name?: string; hash?: string; globalCacheKey?: string; + children?: RouteDef[]; }; type ParsedPath = (string | { @@ -22,6 +23,8 @@ type ParsedPath = (string | { optional?: boolean; })[]; +export type Resolved = { route: RouteDef; props: Map; child?: Resolved; }; + function parsePath(path: string): ParsedPath { const res = [] as ParsedPath; @@ -51,8 +54,11 @@ export class Router extends EventEmitter<{ change: (ctx: { beforePath: string; path: string; - route: RouteDef | null; - props: Map | null; + resolved: Resolved; + key: string; + }) => void; + replace: (ctx: { + path: string; key: string; }) => void; push: (ctx: { @@ -65,12 +71,12 @@ export class Router extends EventEmitter<{ same: () => void; }> { private routes: RouteDef[]; + public current: Resolved; + public currentRef: ShallowRef = shallowRef(); + public currentRoute: ShallowRef = shallowRef(); private currentPath: string; - private currentComponent: Component | null = null; - private currentProps: Map | null = null; private currentKey = Date.now().toString(); - public currentRoute: ShallowRef = shallowRef(null); public navHook: ((path: string, flag?: any) => boolean) | null = null; constructor(routes: Router['routes'], currentPath: Router['currentPath']) { @@ -78,10 +84,10 @@ export class Router extends EventEmitter<{ this.routes = routes; this.currentPath = currentPath; - this.navigate(currentPath, null, true); + this.navigate(currentPath, null, false); } - public resolve(path: string): { route: RouteDef; props: Map; } | null { + public resolve(path: string): Resolved | null { let queryString: string | null = null; let hash: string | null = null; if (path[0] === '/') path = path.substring(1); @@ -96,77 +102,108 @@ export class Router extends EventEmitter<{ if (_DEV_) console.log('Routing: ', path, queryString); - const _parts = path.split('/').filter(part => part.length !== 0); + function check(routes: RouteDef[], _parts: string[]): Resolved | null { + forEachRouteLoop: + for (const route of routes) { + let parts = [ ..._parts ]; + const props = new Map(); - forEachRouteLoop: - for (const route of this.routes) { - let parts = [ ..._parts ]; - const props = new Map(); - - pathMatchLoop: - for (const p of parsePath(route.path)) { - if (typeof p === 'string') { - if (p === parts[0]) { - parts.shift(); - } else { - continue forEachRouteLoop; - } - } else { - if (parts[0] == null && !p.optional) { - continue forEachRouteLoop; - } - if (p.wildcard) { - if (parts.length !== 0) { - props.set(p.name, safeURIDecode(parts.join('/'))); - parts = []; - } - break pathMatchLoop; - } else { - if (p.startsWith) { - if (parts[0] == null || !parts[0].startsWith(p.startsWith)) continue forEachRouteLoop; - - props.set(p.name, safeURIDecode(parts[0].substring(p.startsWith.length))); + pathMatchLoop: + for (const p of parsePath(route.path)) { + if (typeof p === 'string') { + if (p === parts[0]) { parts.shift(); } else { - if (parts[0]) { - props.set(p.name, safeURIDecode(parts[0])); + continue forEachRouteLoop; + } + } else { + if (parts[0] == null && !p.optional) { + continue forEachRouteLoop; + } + if (p.wildcard) { + if (parts.length !== 0) { + props.set(p.name, safeURIDecode(parts.join('/'))); + parts = []; + } + break pathMatchLoop; + } else { + if (p.startsWith) { + if (parts[0] == null || !parts[0].startsWith(p.startsWith)) continue forEachRouteLoop; + + props.set(p.name, safeURIDecode(parts[0].substring(p.startsWith.length))); + parts.shift(); + } else { + if (parts[0]) { + props.set(p.name, safeURIDecode(parts[0])); + } + parts.shift(); } - parts.shift(); } } } - } - if (parts.length !== 0) continue forEachRouteLoop; + if (parts.length === 0) { + if (route.children) { + const child = check(route.children, []); + if (child) { + return { + route, + props, + child, + }; + } else { + continue forEachRouteLoop; + } + } - if (route.hash != null && hash != null) { - props.set(route.hash, safeURIDecode(hash)); - } - - if (route.query != null && queryString != null) { - const queryObject = [...new URLSearchParams(queryString).entries()] - .reduce((obj, entry) => ({ ...obj, [entry[0]]: entry[1] }), {}); - - for (const q in route.query) { - const as = route.query[q]; - if (queryObject[q]) { - props.set(as, safeURIDecode(queryObject[q])); + if (route.hash != null && hash != null) { + props.set(route.hash, safeURIDecode(hash)); + } + + if (route.query != null && queryString != null) { + const queryObject = [...new URLSearchParams(queryString).entries()] + .reduce((obj, entry) => ({ ...obj, [entry[0]]: entry[1] }), {}); + + for (const q in route.query) { + const as = route.query[q]; + if (queryObject[q]) { + props.set(as, safeURIDecode(queryObject[q])); + } + } + } + + return { + route, + props, + }; + } else { + if (route.children) { + const child = check(route.children, parts); + if (child) { + return { + route, + props, + child, + }; + } else { + continue forEachRouteLoop; + } + } else { + continue forEachRouteLoop; } } } - return { - route, - props, - }; + return null; } - return null; + const _parts = path.split('/').filter(part => part.length !== 0); + + return check(this.routes, _parts); } - private navigate(path: string, key: string | null | undefined, initial = false) { + private navigate(path: string, key: string | null | undefined, emitChange = true) { const beforePath = this.currentPath; - const beforeRoute = this.currentRoute.value; this.currentPath = path; const res = this.resolve(this.currentPath); @@ -181,28 +218,21 @@ export class Router extends EventEmitter<{ const isSamePath = beforePath === path; if (isSamePath && key == null) key = this.currentKey; - this.currentComponent = res.route.component; - this.currentProps = res.props; + this.current = res; + this.currentRef.value = res; this.currentRoute.value = res.route; - this.currentKey = this.currentRoute.value.globalCacheKey ?? key ?? Date.now().toString(); + this.currentKey = res.route.globalCacheKey ?? key ?? path; - if (!initial) { + if (emitChange) { this.emit('change', { beforePath, path, - route: this.currentRoute.value, - props: this.currentProps, + resolved: res, key: this.currentKey, }); } - } - public getCurrentComponent() { - return this.currentComponent; - } - - public getCurrentProps() { - return this.currentProps; + return res; } public getCurrentPath() { @@ -223,17 +253,23 @@ export class Router extends EventEmitter<{ const cancel = this.navHook(path, flag); if (cancel) return; } - this.navigate(path, null); + const res = this.navigate(path, null); this.emit('push', { beforePath, path, - route: this.currentRoute.value, - props: this.currentProps, + route: res.route, + props: res.props, key: this.currentKey, }); } - public change(path: string, key?: string | null) { + public replace(path: string, key?: string | null, emitEvent = true) { this.navigate(path, key); + if (emitEvent) { + this.emit('replace', { + path, + key: this.currentKey, + }); + } } } diff --git a/packages/client/src/pages/_empty_.vue b/packages/client/src/pages/_empty_.vue new file mode 100644 index 000000000..000b6decc --- /dev/null +++ b/packages/client/src/pages/_empty_.vue @@ -0,0 +1,7 @@ + + + diff --git a/packages/client/src/pages/admin/index.vue b/packages/client/src/pages/admin/index.vue index d82880c34..2ff55d351 100644 --- a/packages/client/src/pages/admin/index.vue +++ b/packages/client/src/pages/admin/index.vue @@ -1,6 +1,6 @@ @@ -44,15 +44,10 @@ const indexInfo = { hideHeader: true, }; -const props = defineProps<{ - initialPage?: string, -}>(); - provide('shouldOmitHeaderTitle', false); let INFO = $ref(indexInfo); let childInfo = $ref(null); -let page = $ref(props.initialPage); let narrow = $ref(false); let view = $ref(null); let el = $ref(null); @@ -61,6 +56,7 @@ let noMaintainerInformation = isEmpty(instance.maintainerName) || isEmpty(instan let noBotProtection = !instance.disableRegistration && !instance.enableHcaptcha && !instance.enableRecaptcha; let noEmailServer = !instance.enableEmail; let thereIsUnresolvedAbuseReport = $ref(false); +let currentPage = $computed(() => router.currentRef.value.child); os.api('admin/abuse-user-reports', { state: 'unresolved', @@ -94,47 +90,47 @@ const menuDef = $computed(() => [{ icon: 'fas fa-tachometer-alt', text: i18n.ts.dashboard, to: '/admin/overview', - active: props.initialPage === 'overview', + active: currentPage?.route.name === 'overview', }, { icon: 'fas fa-users', text: i18n.ts.users, to: '/admin/users', - active: props.initialPage === 'users', + active: currentPage?.route.name === 'users', }, { icon: 'fas fa-laugh', text: i18n.ts.customEmojis, to: '/admin/emojis', - active: props.initialPage === 'emojis', + active: currentPage?.route.name === 'emojis', }, { icon: 'fas fa-globe', text: i18n.ts.federation, to: '/about#federation', - active: props.initialPage === 'federation', + active: currentPage?.route.name === 'federation', }, { icon: 'fas fa-clipboard-list', text: i18n.ts.jobQueue, to: '/admin/queue', - active: props.initialPage === 'queue', + active: currentPage?.route.name === 'queue', }, { icon: 'fas fa-cloud', text: i18n.ts.files, to: '/admin/files', - active: props.initialPage === 'files', + active: currentPage?.route.name === 'files', }, { icon: 'fas fa-broadcast-tower', text: i18n.ts.announcements, to: '/admin/announcements', - active: props.initialPage === 'announcements', + active: currentPage?.route.name === 'announcements', }, { icon: 'fas fa-audio-description', text: i18n.ts.ads, to: '/admin/ads', - active: props.initialPage === 'ads', + active: currentPage?.route.name === 'ads', }, { icon: 'fas fa-exclamation-circle', text: i18n.ts.abuseReports, to: '/admin/abuses', - active: props.initialPage === 'abuses', + active: currentPage?.route.name === 'abuses', }], }, { title: i18n.ts.settings, @@ -142,47 +138,47 @@ const menuDef = $computed(() => [{ icon: 'fas fa-cog', text: i18n.ts.general, to: '/admin/settings', - active: props.initialPage === 'settings', + active: currentPage?.route.name === 'settings', }, { icon: 'fas fa-envelope', text: i18n.ts.emailServer, to: '/admin/email-settings', - active: props.initialPage === 'email-settings', + active: currentPage?.route.name === 'email-settings', }, { icon: 'fas fa-cloud', text: i18n.ts.objectStorage, to: '/admin/object-storage', - active: props.initialPage === 'object-storage', + active: currentPage?.route.name === 'object-storage', }, { icon: 'fas fa-lock', text: i18n.ts.security, to: '/admin/security', - active: props.initialPage === 'security', + active: currentPage?.route.name === 'security', }, { icon: 'fas fa-globe', text: i18n.ts.relays, to: '/admin/relays', - active: props.initialPage === 'relays', + active: currentPage?.route.name === 'relays', }, { icon: 'fas fa-share-alt', text: i18n.ts.integration, to: '/admin/integrations', - active: props.initialPage === 'integrations', + active: currentPage?.route.name === 'integrations', }, { icon: 'fas fa-ban', text: i18n.ts.instanceBlocking, to: '/admin/instance-block', - active: props.initialPage === 'instance-block', + active: currentPage?.route.name === 'instance-block', }, { icon: 'fas fa-ghost', text: i18n.ts.proxyAccount, to: '/admin/proxy-account', - active: props.initialPage === 'proxy-account', + active: currentPage?.route.name === 'proxy-account', }, { icon: 'fas fa-cogs', text: i18n.ts.other, to: '/admin/other-settings', - active: props.initialPage === 'other-settings', + active: currentPage?.route.name === 'other-settings', }], }, { title: i18n.ts.info, @@ -190,55 +186,12 @@ const menuDef = $computed(() => [{ icon: 'fas fa-database', text: i18n.ts.database, to: '/admin/database', - active: props.initialPage === 'database', + active: currentPage?.route.name === 'database', }], }]); -const component = $computed(() => { - if (props.initialPage == null) return null; - switch (props.initialPage) { - case 'overview': return defineAsyncComponent(() => import('./overview.vue')); - case 'users': return defineAsyncComponent(() => import('./users.vue')); - case 'emojis': return defineAsyncComponent(() => import('./emojis.vue')); - //case 'federation': return defineAsyncComponent(() => import('../federation.vue')); - case 'queue': return defineAsyncComponent(() => import('./queue.vue')); - case 'files': return defineAsyncComponent(() => import('./files.vue')); - case 'announcements': return defineAsyncComponent(() => import('./announcements.vue')); - case 'ads': return defineAsyncComponent(() => import('./ads.vue')); - case 'database': return defineAsyncComponent(() => import('./database.vue')); - case 'abuses': return defineAsyncComponent(() => import('./abuses.vue')); - case 'settings': return defineAsyncComponent(() => import('./settings.vue')); - case 'email-settings': return defineAsyncComponent(() => import('./email-settings.vue')); - case 'object-storage': return defineAsyncComponent(() => import('./object-storage.vue')); - case 'security': return defineAsyncComponent(() => import('./security.vue')); - case 'relays': return defineAsyncComponent(() => import('./relays.vue')); - case 'integrations': return defineAsyncComponent(() => import('./integrations.vue')); - case 'instance-block': return defineAsyncComponent(() => import('./instance-block.vue')); - case 'proxy-account': return defineAsyncComponent(() => import('./proxy-account.vue')); - case 'other-settings': return defineAsyncComponent(() => import('./other-settings.vue')); - } -}); - -watch(component, () => { - pageProps = {}; - - nextTick(() => { - scroll(el, { top: 0 }); - }); -}, { immediate: true }); - -watch(() => props.initialPage, () => { - if (props.initialPage == null && !narrow) { - router.push('/admin/overview'); - } else { - if (props.initialPage == null) { - INFO = indexInfo; - } - } -}); - watch(narrow, () => { - if (props.initialPage == null && !narrow) { + if (currentPage?.route.name == null && !narrow) { router.push('/admin/overview'); } }); @@ -247,7 +200,7 @@ onMounted(() => { ro.observe(el); narrow = el.offsetWidth < NARROW_THRESHOLD; - if (props.initialPage == null && !narrow) { + if (currentPage?.route.name == null && !narrow) { router.push('/admin/overview'); } }); diff --git a/packages/client/src/pages/settings/index.vue b/packages/client/src/pages/settings/index.vue index 8b1cc6c12..8964333b3 100644 --- a/packages/client/src/pages/settings/index.vue +++ b/packages/client/src/pages/settings/index.vue @@ -4,15 +4,15 @@
-