From 3b65be8b91026e6aca300bfeb0ba51fd00433d48 Mon Sep 17 00:00:00 2001
From: syuilo <4439005+syuilo@users.noreply.github.com>
Date: Mon, 25 Aug 2025 20:29:26 +0900
Subject: [PATCH 01/13] clean up
---
packages/frontend/test/aiscript/ui.test.ts | 5 -----
1 file changed, 5 deletions(-)
diff --git a/packages/frontend/test/aiscript/ui.test.ts b/packages/frontend/test/aiscript/ui.test.ts
index dc4041b135..44a50aaa62 100644
--- a/packages/frontend/test/aiscript/ui.test.ts
+++ b/packages/frontend/test/aiscript/ui.test.ts
@@ -316,7 +316,6 @@ describe('AiScript UI API', () => {
describe('textInput', () => {
test.concurrent('all options', async () => {
- // https://github.com/aiscript-dev/aiscript/pull/948
const { root, get, outputs } = await exe(`
let text_input = Ui:C:textInput({
onInput: print
@@ -357,7 +356,6 @@ describe('AiScript UI API', () => {
describe('textarea', () => {
test.concurrent('all options', async () => {
- // https://github.com/aiscript-dev/aiscript/pull/948
const { root, get, outputs } = await exe(`
let textarea = Ui:C:textarea({
onInput: print
@@ -398,7 +396,6 @@ describe('AiScript UI API', () => {
describe('numberInput', () => {
test.concurrent('all options', async () => {
- // https://github.com/aiscript-dev/aiscript/pull/948
const { root, get, outputs } = await exe(`
let number_input = Ui:C:numberInput({
onInput: print
@@ -560,7 +557,6 @@ describe('AiScript UI API', () => {
describe('switch', () => {
test.concurrent('all options', async () => {
- // https://github.com/aiscript-dev/aiscript/pull/948
const { root, get, outputs } = await exe(`
let switch = Ui:C:switch({
onChange: print
@@ -601,7 +597,6 @@ describe('AiScript UI API', () => {
describe('select', () => {
test.concurrent('all options', async () => {
- // https://github.com/aiscript-dev/aiscript/pull/948
const { root, get, outputs } = await exe(`
let select = Ui:C:select({
items: [
From 44ac51f64f99acb1b953078281f4c1ed0e62d976 Mon Sep 17 00:00:00 2001
From: syuilo <4439005+syuilo@users.noreply.github.com>
Date: Mon, 25 Aug 2025 20:31:22 +0900
Subject: [PATCH 02/13] refactor: ReloadSuggest -> ReloadSuggestion
---
.../ui/_common_/{ReloadSuggest.vue => ReloadSuggestion.vue} | 0
packages/frontend/src/ui/deck.vue | 4 ++--
packages/frontend/src/ui/universal.vue | 4 ++--
3 files changed, 4 insertions(+), 4 deletions(-)
rename packages/frontend/src/ui/_common_/{ReloadSuggest.vue => ReloadSuggestion.vue} (100%)
diff --git a/packages/frontend/src/ui/_common_/ReloadSuggest.vue b/packages/frontend/src/ui/_common_/ReloadSuggestion.vue
similarity index 100%
rename from packages/frontend/src/ui/_common_/ReloadSuggest.vue
rename to packages/frontend/src/ui/_common_/ReloadSuggestion.vue
diff --git a/packages/frontend/src/ui/deck.vue b/packages/frontend/src/ui/deck.vue
index 7cd54f01ef..226981cca8 100644
--- a/packages/frontend/src/ui/deck.vue
+++ b/packages/frontend/src/ui/deck.vue
@@ -13,7 +13,7 @@ SPDX-License-Identifier: AGPL-3.0-only
-
+
@@ -90,7 +90,7 @@ import XNavbarH from '@/ui/_common_/navbar-h.vue';
import XMobileFooterMenu from '@/ui/_common_/mobile-footer-menu.vue';
import XTitlebar from '@/ui/_common_/titlebar.vue';
import XPreferenceRestore from '@/ui/_common_/PreferenceRestore.vue';
-import XReloadSuggest from '@/ui/_common_/ReloadSuggest.vue';
+import XReloadSuggestion from '@/ui/_common_/ReloadSuggestion.vue';
import * as os from '@/os.js';
import { $i } from '@/i.js';
import { i18n } from '@/i18n.js';
diff --git a/packages/frontend/src/ui/universal.vue b/packages/frontend/src/ui/universal.vue
index 7529f21ffb..727fe08989 100644
--- a/packages/frontend/src/ui/universal.vue
+++ b/packages/frontend/src/ui/universal.vue
@@ -12,7 +12,7 @@ SPDX-License-Identifier: AGPL-3.0-only
-
+
@@ -39,7 +39,7 @@ import XCommon from './_common_/common.vue';
import type { PageMetadata } from '@/page.js';
import XMobileFooterMenu from '@/ui/_common_/mobile-footer-menu.vue';
import XPreferenceRestore from '@/ui/_common_/PreferenceRestore.vue';
-import XReloadSuggest from '@/ui/_common_/ReloadSuggest.vue';
+import XReloadSuggestion from '@/ui/_common_/ReloadSuggestion.vue';
import XTitlebar from '@/ui/_common_/titlebar.vue';
import XSidebar from '@/ui/_common_/navbar.vue';
import * as os from '@/os.js';
From a874def344282b94b23dcd46041de28ec6902326 Mon Sep 17 00:00:00 2001
From: syuilo <4439005+syuilo@users.noreply.github.com>
Date: Mon, 25 Aug 2025 20:32:07 +0900
Subject: [PATCH 03/13] remove unused file
---
.../src/components/global/SearchKeyword.vue | 14 --------------
1 file changed, 14 deletions(-)
delete mode 100644 packages/frontend/src/components/global/SearchKeyword.vue
diff --git a/packages/frontend/src/components/global/SearchKeyword.vue b/packages/frontend/src/components/global/SearchKeyword.vue
deleted file mode 100644
index 27a284faf0..0000000000
--- a/packages/frontend/src/components/global/SearchKeyword.vue
+++ /dev/null
@@ -1,14 +0,0 @@
-
-
-
-
-
-
-
-
-
From 7e7dc03796ffb852056aa1720ebe897aae5ceeb9 Mon Sep 17 00:00:00 2001
From: tamaina
Date: Tue, 26 Aug 2025 07:43:59 +0900
Subject: [PATCH 04/13] =?UTF-8?q?fix(frontend):=20ap/show=E3=81=A7?=
=?UTF-8?q?=E3=83=AD=E3=83=BC=E3=82=AB=E3=83=AB=E3=83=A6=E3=83=BC=E3=82=B6?=
=?UTF-8?q?=E3=83=BC=E3=82=92=E8=A7=A3=E6=B1=BA=E3=81=97=E3=81=9F=E9=9A=9B?=
=?UTF-8?q?@username@null=E3=81=AB=E9=A3=9B=E3=81=B0=E3=81=95=E3=82=8C?=
=?UTF-8?q?=E3=82=8B=E5=95=8F=E9=A1=8C=E3=82=92=E4=BF=AE=E6=AD=A3=20(#1646?=
=?UTF-8?q?0)?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
packages/frontend/src/utility/lookup.ts | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/packages/frontend/src/utility/lookup.ts b/packages/frontend/src/utility/lookup.ts
index 47d0db125d..9baf40b731 100644
--- a/packages/frontend/src/utility/lookup.ts
+++ b/packages/frontend/src/utility/lookup.ts
@@ -8,6 +8,7 @@ import * as os from '@/os.js';
import { misskeyApi } from '@/utility/misskey-api.js';
import { i18n } from '@/i18n.js';
import { mainRouter } from '@/router.js';
+import { acct } from '@/filters/user';
export async function lookup(router?: Router) {
const _router = router ?? mainRouter;
@@ -38,7 +39,7 @@ export async function lookup(router?: Router) {
if (res.type === 'User') {
_router.push('/@:acct/:page?', {
params: {
- acct: `${res.object.username}@${res.object.host}`,
+ acct: acct(res.object),
},
});
} else if (res.type === 'Note') {
From 0c8545ec1c5ea20c79cb816135373f850429ff16 Mon Sep 17 00:00:00 2001
From: syuilo <4439005+syuilo@users.noreply.github.com>
Date: Tue, 26 Aug 2025 07:44:26 +0900
Subject: [PATCH 05/13] Update CHANGELOG.md
---
CHANGELOG.md | 1 +
1 file changed, 1 insertion(+)
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 9cceb6e432..dd9b4ff183 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -54,6 +54,7 @@
- Fix: 複数のメンションを1行に記述した場合に、サジェストが正しく表示されない問題を修正
- Fix: メンションとしての条件を満たしていても、特定の条件(`-`が含まれる場合など)で正しくサジェストされない問題を一部修正
- Fix: ユーザーの前後ノートを閲覧する機能が動作しない問題を修正
+- Fix: 照会ダイアログでap/showでローカルユーザーを解決した際@username@nullに飛ばされる問題を修正
### Server
- Feat: サーバー管理コマンド
From 506c8a259becee338f4aabb2307a5c68e6891589 Mon Sep 17 00:00:00 2001
From: syuilo <4439005+syuilo@users.noreply.github.com>
Date: Tue, 26 Aug 2025 08:50:34 +0900
Subject: [PATCH 06/13] refactor
---
.../src/pages/settings/webhook.new.vue | 2 +-
packages/frontend/src/pages/theme-editor.vue | 22 +++++++++++--------
.../src/pages/user/activity.following.vue | 2 +-
.../frontend/src/pages/user/follow-list.vue | 2 +-
packages/frontend/src/pages/user/home.vue | 10 ++++-----
packages/frontend/src/pages/user/raw.vue | 2 +-
packages/frontend/src/utility/admin-lookup.ts | 4 ++--
.../frontend/src/utility/get-note-menu.ts | 4 ++--
8 files changed, 26 insertions(+), 22 deletions(-)
diff --git a/packages/frontend/src/pages/settings/webhook.new.vue b/packages/frontend/src/pages/settings/webhook.new.vue
index e853f967cb..6c4dff5551 100644
--- a/packages/frontend/src/pages/settings/webhook.new.vue
+++ b/packages/frontend/src/pages/settings/webhook.new.vue
@@ -61,7 +61,7 @@ const event_reaction = ref(true);
const event_mention = ref(true);
async function create(): Promise {
- const events = [];
+ const events: string[] = [];
if (event_follow.value) events.push('follow');
if (event_followed.value) events.push('followed');
if (event_note.value) events.push('note');
diff --git a/packages/frontend/src/pages/theme-editor.vue b/packages/frontend/src/pages/theme-editor.vue
index d1be9e38b7..af3891ac8e 100644
--- a/packages/frontend/src/pages/theme-editor.vue
+++ b/packages/frontend/src/pages/theme-editor.vue
@@ -11,12 +11,12 @@ SPDX-License-Identifier: AGPL-3.0-only
{{ i18n.ts.backgroundColor }}
@@ -27,7 +27,7 @@ SPDX-License-Identifier: AGPL-3.0-only
{{ i18n.ts.accentColor }}
@@ -38,7 +38,7 @@ SPDX-License-Identifier: AGPL-3.0-only
{{ i18n.ts.textColor }}
@@ -75,17 +75,17 @@ SPDX-License-Identifier: AGPL-3.0-only
import { watch, ref, computed } from 'vue';
import { toUnicode } from 'punycode.js';
import tinycolor from 'tinycolor2';
-import { genId } from '@/utility/id.js';
import JSON5 from 'json5';
import lightTheme from '@@/themes/_light.json5';
import darkTheme from '@@/themes/_dark.json5';
import { host } from '@@/js/config.js';
import type { Theme } from '@/theme.js';
+import { genId } from '@/utility/id.js';
import MkButton from '@/components/MkButton.vue';
import MkCodeEditor from '@/components/MkCodeEditor.vue';
import MkTextarea from '@/components/MkTextarea.vue';
import MkFolder from '@/components/MkFolder.vue';
-import { $i } from '@/i.js';
+import { ensureSignin } from '@/i.js';
import { addTheme, applyTheme } from '@/theme.js';
import * as os from '@/os.js';
import { store } from '@/store.js';
@@ -94,6 +94,8 @@ import { useLeaveGuard } from '@/composables/use-leave-guard.js';
import { definePage } from '@/page.js';
import { prefer } from '@/preferences.js';
+const $i = ensureSignin();
+
const bgColors = [
{ color: '#f5f5f5', kind: 'light', forPreview: '#f5f5f5' },
{ color: '#f0eee9', kind: 'light', forPreview: '#f3e2b9' },
@@ -123,12 +125,15 @@ const fgColors = [
{ color: 'pink', forLight: '#84667d', forDark: '#e4d1e0', forPreview: '#b12390' },
];
-const theme = ref
>({
+const theme = ref({
+ id: genId(),
+ name: 'untitled',
+ author: `@${$i.username}@${toUnicode(host)}`,
base: 'light',
props: lightTheme.props,
});
const description = ref(null);
-const themeCode = ref(null);
+const themeCode = ref('');
const changed = ref(false);
useLeaveGuard(changed);
@@ -194,7 +199,6 @@ async function saveAs() {
theme.value.id = genId();
theme.value.name = name;
- theme.value.author = `@${$i.username}@${toUnicode(host)}`;
if (description.value) theme.value.desc = description.value;
await addTheme(theme.value);
applyTheme(theme.value);
diff --git a/packages/frontend/src/pages/user/activity.following.vue b/packages/frontend/src/pages/user/activity.following.vue
index f2a5ad8e75..2cd825f3dc 100644
--- a/packages/frontend/src/pages/user/activity.following.vue
+++ b/packages/frontend/src/pages/user/activity.following.vue
@@ -36,7 +36,7 @@ const props = defineProps<{
const chartEl = useTemplateRef('chartEl');
const legendEl = useTemplateRef('legendEl');
const now = new Date();
-let chartInstance: Chart = null;
+let chartInstance: Chart | null = null;
const chartLimit = 30;
const fetching = ref(true);
diff --git a/packages/frontend/src/pages/user/follow-list.vue b/packages/frontend/src/pages/user/follow-list.vue
index 6bb1360d42..c383b9b7bd 100644
--- a/packages/frontend/src/pages/user/follow-list.vue
+++ b/packages/frontend/src/pages/user/follow-list.vue
@@ -7,7 +7,7 @@ SPDX-License-Identifier: AGPL-3.0-only
diff --git a/packages/frontend/src/pages/user/home.vue b/packages/frontend/src/pages/user/home.vue
index ed3ae6a2aa..e10c44960a 100644
--- a/packages/frontend/src/pages/user/home.vue
+++ b/packages/frontend/src/pages/user/home.vue
@@ -25,8 +25,8 @@ SPDX-License-Identifier: AGPL-3.0-only
-
-
+
+
@@ -43,8 +43,8 @@ SPDX-License-Identifier: AGPL-3.0-only
-
-
+
+
@@ -228,7 +228,7 @@ const bannerEl = ref
(null);
const memoTextareaEl = ref(null);
const memoDraft = ref(props.user.memo);
const isEditingMemo = ref(false);
-const moderationNote = ref(props.user.moderationNote);
+const moderationNote = ref(props.user.moderationNote ?? '');
const editModerationNote = ref(false);
watch(moderationNote, async () => {
diff --git a/packages/frontend/src/pages/user/raw.vue b/packages/frontend/src/pages/user/raw.vue
index f0e675b913..145ef5dd92 100644
--- a/packages/frontend/src/pages/user/raw.vue
+++ b/packages/frontend/src/pages/user/raw.vue
@@ -48,7 +48,7 @@ import FormSection from '@/components/form/section.vue';
import MkObjectView from '@/components/MkObjectView.vue';
const props = defineProps<{
- user: Misskey.entities.User;
+ user: Misskey.entities.UserDetailed & { isModerator?: boolean; };
}>();
const moderator = computed(() => props.user.isModerator ?? false);
diff --git a/packages/frontend/src/utility/admin-lookup.ts b/packages/frontend/src/utility/admin-lookup.ts
index 7405e229fe..eccc88d8a9 100644
--- a/packages/frontend/src/utility/admin-lookup.ts
+++ b/packages/frontend/src/utility/admin-lookup.ts
@@ -12,7 +12,7 @@ export async function lookupUser() {
const { canceled, result } = await os.inputText({
title: i18n.ts.usernameOrUserId,
});
- if (canceled) return;
+ if (canceled || result == null) return;
const show = (user) => {
os.pageWindow(`/admin/user/${user.id}`);
@@ -46,7 +46,7 @@ export async function lookupUserByEmail() {
title: i18n.ts.emailAddress,
type: 'email',
});
- if (canceled) return;
+ if (canceled || result == null) return;
try {
const user = await os.apiWithDialog('admin/accounts/find-by-email', { email: result });
diff --git a/packages/frontend/src/utility/get-note-menu.ts b/packages/frontend/src/utility/get-note-menu.ts
index 11c87dc653..f7b56040cc 100644
--- a/packages/frontend/src/utility/get-note-menu.ts
+++ b/packages/frontend/src/utility/get-note-menu.ts
@@ -179,7 +179,7 @@ export function getNoteMenu(props: {
translating: Ref;
currentClip?: Misskey.entities.Clip;
}) {
- const appearNote = getAppearNote(props.note);
+ const appearNote = getAppearNote(props.note) ?? props.note;
const link = appearNote.url ?? appearNote.uri;
const cleanups = [] as (() => void)[];
@@ -554,7 +554,7 @@ export function getRenoteMenu(props: {
renoteButton: ShallowRef;
mock?: boolean;
}) {
- const appearNote = getAppearNote(props.note);
+ const appearNote = getAppearNote(props.note) ?? props.note;
const channelRenoteItems: MenuItem[] = [];
const normalRenoteItems: MenuItem[] = [];
From 120af977a9cb0af4744e590b36e829bfb140ae4a Mon Sep 17 00:00:00 2001
From: syuilo <4439005+syuilo@users.noreply.github.com>
Date: Tue, 26 Aug 2025 08:57:36 +0900
Subject: [PATCH 07/13] refactoe
---
packages/frontend/src/pages/lookup.vue | 17 +++++++----------
packages/frontend/src/pages/my-lists/index.vue | 6 +++---
packages/frontend/src/pages/my-lists/list.vue | 2 +-
packages/frontend/src/pages/notifications.vue | 4 ++--
packages/frontend/src/pages/settings/2fa.vue | 6 +++---
.../frontend/src/pages/settings/accounts.vue | 4 ++--
packages/frontend/src/pages/settings/apps.vue | 4 ++--
packages/frontend/src/pages/settings/email.vue | 2 +-
8 files changed, 21 insertions(+), 24 deletions(-)
diff --git a/packages/frontend/src/pages/lookup.vue b/packages/frontend/src/pages/lookup.vue
index d5ee0cdf97..8a1e952d85 100644
--- a/packages/frontend/src/pages/lookup.vue
+++ b/packages/frontend/src/pages/lookup.vue
@@ -29,7 +29,7 @@ import MkButton from '@/components/MkButton.vue';
const state = ref<'fetching' | 'done'>('fetching');
-function fetch() {
+function _fetch_() {
const params = new URL(window.location.href).searchParams;
// acctのほうはdeprecated
@@ -44,20 +44,18 @@ function fetch() {
if (uri.startsWith('https://')) {
promise = misskeyApi('ap/show', {
uri,
- });
-
- promise.then(res => {
+ }).then(res => {
if (res.type === 'User') {
mainRouter.replace('/@:acct/:page?', {
params: {
acct: res.host != null ? `${res.object.username}@${res.object.host}` : res.object.username,
- }
+ },
});
} else if (res.type === 'Note') {
mainRouter.replace('/notes/:noteId/:initialTab?', {
params: {
noteId: res.object.id,
- }
+ },
});
} else {
os.alert({
@@ -70,12 +68,11 @@ function fetch() {
if (uri.startsWith('acct:')) {
uri = uri.slice(5);
}
- promise = misskeyApi('users/show', Misskey.acct.parse(uri));
- promise.then(user => {
+ promise = misskeyApi('users/show', Misskey.acct.parse(uri)).then(user => {
mainRouter.replace('/@:acct/:page?', {
params: {
acct: user.host != null ? `${user.username}@${user.host}` : user.username,
- }
+ },
});
});
}
@@ -96,7 +93,7 @@ function goToMisskey(): void {
window.location.href = '/';
}
-fetch();
+_fetch_();
const headerActions = computed(() => []);
diff --git a/packages/frontend/src/pages/my-lists/index.vue b/packages/frontend/src/pages/my-lists/index.vue
index fb31cd542c..0933618f54 100644
--- a/packages/frontend/src/pages/my-lists/index.vue
+++ b/packages/frontend/src/pages/my-lists/index.vue
@@ -17,8 +17,8 @@ SPDX-License-Identifier: AGPL-3.0-only
- {{ list.name }} ({{ i18n.tsx.nUsers({ n: `${list.userIds.length}/${$i.policies['userEachUserListsLimit']}` }) }})
-
+ {{ list.name }} ({{ i18n.tsx.nUsers({ n: `${list.userIds!.length}/${$i.policies['userEachUserListsLimit']}` }) }})
+
@@ -50,7 +50,7 @@ async function create() {
const { canceled, result: name } = await os.inputText({
title: i18n.ts.enterListName,
});
- if (canceled) return;
+ if (canceled || name == null) return;
await os.apiWithDialog('users/lists/create', { name: name });
userListsCache.delete();
fetch();
diff --git a/packages/frontend/src/pages/my-lists/list.vue b/packages/frontend/src/pages/my-lists/list.vue
index 6b5a797023..eb8e26be3b 100644
--- a/packages/frontend/src/pages/my-lists/list.vue
+++ b/packages/frontend/src/pages/my-lists/list.vue
@@ -24,7 +24,7 @@ SPDX-License-Identifier: AGPL-3.0-only
{{ i18n.ts.members }}
- {{ i18n.tsx.nUsers({ n: `${list.userIds.length}/${$i.policies['userEachUserListsLimit']}` }) }}
+ {{ i18n.tsx.nUsers({ n: `${list.userIds!.length}/${$i.policies['userEachUserListsLimit']}` }) }}
{{ i18n.ts.addUser }}
diff --git a/packages/frontend/src/pages/notifications.vue b/packages/frontend/src/pages/notifications.vue
index a8c1fb654c..71c957460c 100644
--- a/packages/frontend/src/pages/notifications.vue
+++ b/packages/frontend/src/pages/notifications.vue
@@ -31,7 +31,7 @@ import { Paginator } from '@/utility/paginator.js';
const tab = ref('all');
const includeTypes = ref
(null);
-const excludeTypes = computed(() => includeTypes.value ? notificationTypes.filter(t => !includeTypes.value.includes(t)) : null);
+const excludeTypes = computed(() => includeTypes.value ? notificationTypes.filter(t => !includeTypes.value!.includes(t)) : null);
const mentionsPaginator = markRaw(new Paginator('notes/mentions', {
limit: 10,
@@ -71,7 +71,7 @@ const headerActions = computed(() => [tab.value === 'all' ? {
text: i18n.ts.markAllAsRead,
icon: 'ti ti-check',
handler: () => {
- os.apiWithDialog('notifications/mark-all-as-read');
+ os.apiWithDialog('notifications/mark-all-as-read', {});
},
} : undefined].filter(x => x !== undefined));
diff --git a/packages/frontend/src/pages/settings/2fa.vue b/packages/frontend/src/pages/settings/2fa.vue
index 1f98fab618..ca404b43c4 100644
--- a/packages/frontend/src/pages/settings/2fa.vue
+++ b/packages/frontend/src/pages/settings/2fa.vue
@@ -25,7 +25,7 @@ SPDX-License-Identifier: AGPL-3.0-only
-
+
{{ i18n.ts._2fa.renewTOTP }}
{{ i18n.ts._2fa.whyTOTPOnlyRenew }}
@@ -58,7 +58,7 @@ SPDX-License-Identifier: AGPL-3.0-only
{{ i18n.ts._2fa.registerSecurityKey }}
-
+
{{ key.name }}
@@ -72,7 +72,7 @@ SPDX-License-Identifier: AGPL-3.0-only
- updatePasswordLessLogin(v)">
+ updatePasswordLessLogin(v)">
{{ i18n.ts.passwordLessLogin }}
{{ i18n.ts.passwordLessLoginDescription }}
diff --git a/packages/frontend/src/pages/settings/accounts.vue b/packages/frontend/src/pages/settings/accounts.vue
index 2fd0a021da..26010e93eb 100644
--- a/packages/frontend/src/pages/settings/accounts.vue
+++ b/packages/frontend/src/pages/settings/accounts.vue
@@ -11,7 +11,7 @@ SPDX-License-Identifier: AGPL-3.0-only
-
+
@@ -36,7 +36,7 @@ function refreshAllAccounts() {
// TODO
}
-function menu(host: string, account: Misskey.entities.UserDetailed, ev: MouseEvent) {
+function showMenu(host: string, account: Misskey.entities.UserDetailed, ev: MouseEvent) {
let menu: MenuItem[];
menu = [{
diff --git a/packages/frontend/src/pages/settings/apps.vue b/packages/frontend/src/pages/settings/apps.vue
index 5f51a5e079..54e214241b 100644
--- a/packages/frontend/src/pages/settings/apps.vue
+++ b/packages/frontend/src/pages/settings/apps.vue
@@ -16,7 +16,7 @@ SPDX-License-Identifier: AGPL-3.0-only
{{ token.name }}
{{ token.description }}
-
+
{{ i18n.ts.delete }}
@@ -28,7 +28,7 @@ SPDX-License-Identifier: AGPL-3.0-only
{{ i18n.ts.installedDate }}
-
+
{{ i18n.ts.lastUsedDate }}
diff --git a/packages/frontend/src/pages/settings/email.vue b/packages/frontend/src/pages/settings/email.vue
index fb8f51041e..469a3c2f1c 100644
--- a/packages/frontend/src/pages/settings/email.vue
+++ b/packages/frontend/src/pages/settings/email.vue
@@ -74,7 +74,7 @@ import { instance } from '@/instance.js';
const $i = ensureSignin();
-const emailAddress = ref($i.email);
+const emailAddress = ref($i.email ?? '');
const onChangeReceiveAnnouncementEmail = (v) => {
misskeyApi('i/update', {
From 9e5c8d94bff0352bca3b15fd75a7c6ccaa1df2ff Mon Sep 17 00:00:00 2001
From: syuilo <4439005+syuilo@users.noreply.github.com>
Date: Tue, 26 Aug 2025 09:08:00 +0900
Subject: [PATCH 08/13] refactor
---
packages/frontend/src/components/MkAchievements.vue | 6 +++---
packages/frontend/src/components/MkAnimBg.vue | 2 ++
packages/frontend/src/pages/admin-file.vue | 4 ++--
packages/frontend/src/pages/announcement.vue | 6 +++---
packages/frontend/src/pages/drive.file.info.vue | 12 ++++++------
packages/frontend/src/pages/install-extensions.vue | 4 ++--
packages/frontend/src/pages/instance-info.vue | 4 ++--
packages/frontend/src/pages/my-antennas/index.vue | 6 +++---
packages/frontend/src/pages/my-lists/index.vue | 10 +++++-----
packages/frontend/src/pages/settings/index.vue | 6 +++++-
packages/frontend/src/pages/settings/profile.vue | 2 +-
.../frontend/src/pages/settings/theme.install.vue | 6 +++---
.../frontend/src/pages/settings/theme.manage.vue | 2 +-
packages/frontend/src/theme.ts | 1 +
14 files changed, 39 insertions(+), 32 deletions(-)
diff --git a/packages/frontend/src/components/MkAchievements.vue b/packages/frontend/src/components/MkAchievements.vue
index 70766634ce..3b7b59b4d3 100644
--- a/packages/frontend/src/components/MkAchievements.vue
+++ b/packages/frontend/src/components/MkAchievements.vue
@@ -71,7 +71,7 @@ const props = withDefaults(defineProps<{
const achievements = ref(null);
const lockedAchievements = computed(() => ACHIEVEMENT_TYPES.filter(x => !(achievements.value ?? []).some(a => a.name === x)));
-function fetch() {
+function _fetch_() {
misskeyApi('users/achievements', { userId: props.user.id }).then(res => {
achievements.value = [];
for (const t of ACHIEVEMENT_TYPES) {
@@ -84,11 +84,11 @@ function fetch() {
function clickHere() {
claimAchievement('clickedClickHere');
- fetch();
+ _fetch_();
}
onMounted(() => {
- fetch();
+ _fetch_();
});
diff --git a/packages/frontend/src/components/MkAnimBg.vue b/packages/frontend/src/components/MkAnimBg.vue
index 82606c9aa4..19a21f6e24 100644
--- a/packages/frontend/src/components/MkAnimBg.vue
+++ b/packages/frontend/src/components/MkAnimBg.vue
@@ -265,6 +265,8 @@ onUnmounted(() => {
if (handle) {
window.cancelAnimationFrame(handle);
}
+
+ // TODO: WebGLリソースの解放
});
diff --git a/packages/frontend/src/pages/admin-file.vue b/packages/frontend/src/pages/admin-file.vue
index 7a49ba542f..90b3ca81cf 100644
--- a/packages/frontend/src/pages/admin-file.vue
+++ b/packages/frontend/src/pages/admin-file.vue
@@ -111,13 +111,13 @@ const props = defineProps<{
fileId: string,
}>();
-async function fetch() {
+async function _fetch_() {
file.value = await misskeyApi('drive/files/show', { fileId: props.fileId });
info.value = await misskeyApi('admin/drive/show-file', { fileId: props.fileId });
isSensitive.value = file.value.isSensitive;
}
-fetch();
+_fetch_();
async function del() {
const { canceled } = await os.confirm({
diff --git a/packages/frontend/src/pages/announcement.vue b/packages/frontend/src/pages/announcement.vue
index f9b870eda1..0bcfd28f67 100644
--- a/packages/frontend/src/pages/announcement.vue
+++ b/packages/frontend/src/pages/announcement.vue
@@ -39,7 +39,7 @@ SPDX-License-Identifier: AGPL-3.0-only
{{ i18n.ts.gotIt }}
-
+
@@ -66,7 +66,7 @@ const announcement = ref
(null);
const error = ref(null);
const path = computed(() => props.announcementId);
-function fetch() {
+function _fetch_() {
announcement.value = null;
misskeyApi('announcements/show', {
announcementId: props.announcementId,
@@ -96,7 +96,7 @@ async function read(target: Misskey.entities.Announcement): Promise {
}
}
-watch(() => path.value, fetch, { immediate: true });
+watch(() => path.value, _fetch_, { immediate: true });
const headerActions = computed(() => []);
diff --git a/packages/frontend/src/pages/drive.file.info.vue b/packages/frontend/src/pages/drive.file.info.vue
index 1def215afc..79c249413a 100644
--- a/packages/frontend/src/pages/drive.file.info.vue
+++ b/packages/frontend/src/pages/drive.file.info.vue
@@ -105,7 +105,7 @@ const folderHierarchy = computed(() => {
});
const isImage = computed(() => file.value?.type.startsWith('image/'));
-async function fetch() {
+async function _fetch_() {
fetching.value = true;
file.value = await misskeyApi('drive/files/show', {
@@ -134,7 +134,7 @@ function move() {
fileId: file.value.id,
folderId: folder[0] ? folder[0].id : null,
}).then(async () => {
- await fetch();
+ await _fetch_();
});
});
}
@@ -146,7 +146,7 @@ function toggleSensitive() {
fileId: file.value.id,
isSensitive: !file.value.isSensitive,
}).then(async () => {
- await fetch();
+ await _fetch_();
}).catch(err => {
os.alert({
type: 'error',
@@ -169,7 +169,7 @@ function rename() {
fileId: file.value.id,
name: name,
}).then(async () => {
- await fetch();
+ await _fetch_();
});
});
}
@@ -186,7 +186,7 @@ async function describe() {
fileId: file.value.id,
comment: caption.length === 0 ? null : caption,
}).then(async () => {
- await fetch();
+ await _fetch_();
});
},
closed: () => dispose(),
@@ -212,7 +212,7 @@ async function deleteFile() {
}
onMounted(async () => {
- await fetch();
+ await _fetch_();
});
diff --git a/packages/frontend/src/pages/install-extensions.vue b/packages/frontend/src/pages/install-extensions.vue
index 1b3c6616cc..4b87e0da6b 100644
--- a/packages/frontend/src/pages/install-extensions.vue
+++ b/packages/frontend/src/pages/install-extensions.vue
@@ -80,7 +80,7 @@ function close_(): void {
}
}
-async function fetch() {
+async function _fetch_() {
if (!url.value || !hash.value) {
errorKV.value = {
title: i18n.ts._externalResourceInstaller._errors._invalidParams.title,
@@ -229,7 +229,7 @@ async function install() {
const urlParams = new URLSearchParams(window.location.search);
url.value = urlParams.get('url');
hash.value = urlParams.get('hash');
-fetch();
+_fetch_();
definePage(() => ({
title: i18n.ts._externalResourceInstaller.title,
diff --git a/packages/frontend/src/pages/instance-info.vue b/packages/frontend/src/pages/instance-info.vue
index 4be5fa447d..473207fe6e 100644
--- a/packages/frontend/src/pages/instance-info.vue
+++ b/packages/frontend/src/pages/instance-info.vue
@@ -198,7 +198,7 @@ if (iAmModerator) {
});
}
-async function fetch(): Promise {
+async function _fetch_(): Promise {
if (iAmAdmin) {
meta.value = await misskeyApi('admin/meta');
}
@@ -276,7 +276,7 @@ function refreshMetadata(): void {
});
}
-fetch();
+_fetch_();
const headerActions = computed(() => [{
text: `https://${props.host}`,
diff --git a/packages/frontend/src/pages/my-antennas/index.vue b/packages/frontend/src/pages/my-antennas/index.vue
index 95a3108e3a..d7625a8a1c 100644
--- a/packages/frontend/src/pages/my-antennas/index.vue
+++ b/packages/frontend/src/pages/my-antennas/index.vue
@@ -30,11 +30,11 @@ import { antennasCache } from '@/cache.js';
const antennas = computed(() => antennasCache.value.value ?? []);
-function fetch() {
+function _fetch_() {
antennasCache.fetch();
}
-fetch();
+_fetch_();
const headerActions = computed(() => [{
asFullButton: true,
@@ -42,7 +42,7 @@ const headerActions = computed(() => [{
text: i18n.ts.reload,
handler: () => {
antennasCache.delete();
- fetch();
+ _fetch_();
},
}]);
diff --git a/packages/frontend/src/pages/my-lists/index.vue b/packages/frontend/src/pages/my-lists/index.vue
index 0933618f54..43d5432f66 100644
--- a/packages/frontend/src/pages/my-lists/index.vue
+++ b/packages/frontend/src/pages/my-lists/index.vue
@@ -40,11 +40,11 @@ const $i = ensureSignin();
const items = computed(() => userListsCache.value.value ?? []);
-function fetch() {
+function _fetch_() {
userListsCache.fetch();
}
-fetch();
+_fetch_();
async function create() {
const { canceled, result: name } = await os.inputText({
@@ -53,7 +53,7 @@ async function create() {
if (canceled || name == null) return;
await os.apiWithDialog('users/lists/create', { name: name });
userListsCache.delete();
- fetch();
+ _fetch_();
}
const headerActions = computed(() => [{
@@ -62,7 +62,7 @@ const headerActions = computed(() => [{
text: i18n.ts.reload,
handler: () => {
userListsCache.delete();
- fetch();
+ _fetch_();
},
}]);
@@ -74,7 +74,7 @@ definePage(() => ({
}));
onActivated(() => {
- fetch();
+ _fetch_();
});
diff --git a/packages/frontend/src/pages/settings/index.vue b/packages/frontend/src/pages/settings/index.vue
index eda9dfde7b..250c1735be 100644
--- a/packages/frontend/src/pages/settings/index.vue
+++ b/packages/frontend/src/pages/settings/index.vue
@@ -188,6 +188,8 @@ const menuDef = computed(() => [{
}]);
onMounted(() => {
+ if (el.value == null) return; // TSを黙らすため
+
ro.observe(el.value);
narrow.value = el.value.offsetWidth < NARROW_THRESHOLD;
@@ -198,6 +200,8 @@ onMounted(() => {
});
onActivated(() => {
+ if (el.value == null) return; // TSを黙らすため
+
narrow.value = el.value.offsetWidth < NARROW_THRESHOLD;
if (!narrow.value && currentPage.value?.route.name == null) {
@@ -215,7 +219,7 @@ watch(router.currentRef, (to) => {
}
});
-const emailNotConfigured = computed(() => instance.enableEmail && ($i.email == null || !$i.emailVerified));
+const emailNotConfigured = computed(() => $i && instance.enableEmail && ($i.email == null || !$i.emailVerified));
provideMetadataReceiver((metadataGetter) => {
const info = metadataGetter();
diff --git a/packages/frontend/src/pages/settings/profile.vue b/packages/frontend/src/pages/settings/profile.vue
index e2679623ef..4816a6e33b 100644
--- a/packages/frontend/src/pages/settings/profile.vue
+++ b/packages/frontend/src/pages/settings/profile.vue
@@ -7,7 +7,7 @@ SPDX-License-Identifier: AGPL-3.0-only
-
+
{{ i18n.ts._profile.changeBanner }}
diff --git a/packages/frontend/src/pages/settings/theme.install.vue b/packages/frontend/src/pages/settings/theme.install.vue
index ac95279402..f79357c361 100644
--- a/packages/frontend/src/pages/settings/theme.install.vue
+++ b/packages/frontend/src/pages/settings/theme.install.vue
@@ -10,8 +10,8 @@ SPDX-License-Identifier: AGPL-3.0-only
- previewTheme(installThemeCode)"> {{ i18n.ts.preview }}
- install(installThemeCode)"> {{ i18n.ts.install }}
+ previewTheme(installThemeCode!)"> {{ i18n.ts.preview }}
+ install(installThemeCode!)"> {{ i18n.ts.install }}
@@ -39,7 +39,7 @@ async function install(code: string): Promise
{
});
installThemeCode.value = null;
router.push('/settings/theme');
- } catch (err) {
+ } catch (err: any) {
switch (err.message.toLowerCase()) {
case 'this theme is already installed':
os.alert({
diff --git a/packages/frontend/src/pages/settings/theme.manage.vue b/packages/frontend/src/pages/settings/theme.manage.vue
index fcd0b293e0..e972184278 100644
--- a/packages/frontend/src/pages/settings/theme.manage.vue
+++ b/packages/frontend/src/pages/settings/theme.manage.vue
@@ -25,7 +25,7 @@ SPDX-License-Identifier: AGPL-3.0-only
{{ i18n.ts._theme.code }}
- {{ i18n.ts.uninstall }}
+ {{ i18n.ts.uninstall }}
diff --git a/packages/frontend/src/theme.ts b/packages/frontend/src/theme.ts
index 036b86cff8..b715426917 100644
--- a/packages/frontend/src/theme.ts
+++ b/packages/frontend/src/theme.ts
@@ -23,6 +23,7 @@ export type Theme = {
author: string;
desc?: string;
base?: 'dark' | 'light';
+ kind?: 'dark' | 'light'; // legacy
props: Record
;
codeHighlighter?: {
base: BundledTheme;
From dbb6c71c5c7098c33824b6070b6526416d3bdd69 Mon Sep 17 00:00:00 2001
From: syuilo <4439005+syuilo@users.noreply.github.com>
Date: Tue, 26 Aug 2025 09:39:23 +0900
Subject: [PATCH 09/13] refactor
---
.../frontend/src/pages/channel-editor.vue | 37 +++++++++++--------
packages/frontend/src/pages/gallery/edit.vue | 6 +--
packages/frontend/src/pages/registry.vue | 2 +-
.../frontend/src/pages/settings/privacy.vue | 28 +++++++++-----
packages/frontend/src/pages/tag.vue | 2 +-
packages/frontend/src/utility/chart-vline.ts | 5 ++-
packages/frontend/src/utility/popout.ts | 4 +-
.../frontend/src/utility/sticky-sidebar.ts | 2 +
8 files changed, 51 insertions(+), 35 deletions(-)
diff --git a/packages/frontend/src/pages/channel-editor.vue b/packages/frontend/src/pages/channel-editor.vue
index 80dfb8e84e..ce26a26109 100644
--- a/packages/frontend/src/pages/channel-editor.vue
+++ b/packages/frontend/src/pages/channel-editor.vue
@@ -92,7 +92,7 @@ const props = defineProps<{
}>();
const channel = ref(null);
-const name = ref(null);
+const name = ref('');
const description = ref(null);
const bannerUrl = ref(null);
const bannerId = ref(null);
@@ -114,20 +114,22 @@ watch(() => bannerId.value, async () => {
async function fetchChannel() {
if (props.channelId == null) return;
- channel.value = await misskeyApi('channels/show', {
+ const result = await misskeyApi('channels/show', {
channelId: props.channelId,
});
- name.value = channel.value.name;
- description.value = channel.value.description;
- bannerId.value = channel.value.bannerId;
- bannerUrl.value = channel.value.bannerUrl;
- isSensitive.value = channel.value.isSensitive;
- pinnedNotes.value = channel.value.pinnedNoteIds.map(id => ({
+ name.value = result.name;
+ description.value = result.description;
+ bannerId.value = result.bannerId;
+ bannerUrl.value = result.bannerUrl;
+ isSensitive.value = result.isSensitive;
+ pinnedNotes.value = result.pinnedNoteIds.map(id => ({
id,
}));
- color.value = channel.value.color;
- allowRenoteToExternal.value = channel.value.allowRenoteToExternal;
+ color.value = result.color;
+ allowRenoteToExternal.value = result.allowRenoteToExternal;
+
+ channel.value = result;
}
fetchChannel();
@@ -154,15 +156,17 @@ function save() {
name: name.value,
description: description.value,
bannerId: bannerId.value,
- pinnedNoteIds: pinnedNotes.value.map(x => x.id),
color: color.value,
isSensitive: isSensitive.value,
allowRenoteToExternal: allowRenoteToExternal.value,
- };
+ } satisfies Misskey.entities.ChannelsCreateRequest;
- if (props.channelId) {
- params.channelId = props.channelId;
- os.apiWithDialog('channels/update', params);
+ if (props.channelId != null) {
+ os.apiWithDialog('channels/update', {
+ ...params,
+ channelId: props.channelId,
+ pinnedNoteIds: pinnedNotes.value.map(x => x.id),
+ });
} else {
os.apiWithDialog('channels/create', params).then(created => {
router.push('/channels/:channelId', {
@@ -175,12 +179,13 @@ function save() {
}
async function archive() {
+ if (props.channelId == null) return;
+
const { canceled } = await os.confirm({
type: 'warning',
title: i18n.tsx.channelArchiveConfirmTitle({ name: name.value }),
text: i18n.ts.channelArchiveConfirmDescription,
});
-
if (canceled) return;
misskeyApi('channels/update', {
diff --git a/packages/frontend/src/pages/gallery/edit.vue b/packages/frontend/src/pages/gallery/edit.vue
index cf0d700962..3fd462e0b9 100644
--- a/packages/frontend/src/pages/gallery/edit.vue
+++ b/packages/frontend/src/pages/gallery/edit.vue
@@ -16,7 +16,7 @@ SPDX-License-Identifier: AGPL-3.0-only
-
+
@@ -88,7 +88,7 @@ async function save() {
router.push('/gallery/:postId', {
params: {
postId: props.postId,
- }
+ },
});
} else {
const created = await os.apiWithDialog('gallery/posts/create', {
@@ -100,7 +100,7 @@ async function save() {
router.push('/gallery/:postId', {
params: {
postId: created.id,
- }
+ },
});
}
}
diff --git a/packages/frontend/src/pages/registry.vue b/packages/frontend/src/pages/registry.vue
index 3762dadd12..389438242e 100644
--- a/packages/frontend/src/pages/registry.vue
+++ b/packages/frontend/src/pages/registry.vue
@@ -9,7 +9,7 @@ SPDX-License-Identifier: AGPL-3.0-only
{{ i18n.ts._registry.createKey }}
-
+
{{ domain.domain ? domain.domain.toUpperCase() : i18n.ts.system }}
{{ scope.length === 0 ? '(root)' : scope.join('/') }}
diff --git a/packages/frontend/src/pages/settings/privacy.vue b/packages/frontend/src/pages/settings/privacy.vue
index ab012841dc..54a6c0af82 100644
--- a/packages/frontend/src/pages/settings/privacy.vue
+++ b/packages/frontend/src/pages/settings/privacy.vue
@@ -160,10 +160,18 @@ SPDX-License-Identifier: AGPL-3.0-only
{{ i18n.ts._accountSettings.makeNotesHiddenBefore }}
-
-
-
-
+
@@ -262,7 +270,7 @@ const makeNotesFollowersOnlyBefore_presets = [
const makeNotesFollowersOnlyBefore_isCustomMode = ref(
makeNotesFollowersOnlyBefore.value != null &&
makeNotesFollowersOnlyBefore.value < 0 &&
- !makeNotesFollowersOnlyBefore_presets.some((preset) => preset.value === makeNotesFollowersOnlyBefore.value)
+ !makeNotesFollowersOnlyBefore_presets.some((preset) => preset.value === makeNotesFollowersOnlyBefore.value),
);
const makeNotesFollowersOnlyBefore_selection = computed({
@@ -270,14 +278,14 @@ const makeNotesFollowersOnlyBefore_selection = computed({
set(value) {
makeNotesFollowersOnlyBefore_isCustomMode.value = value === 'custom';
if (value !== 'custom') makeNotesFollowersOnlyBefore.value = value;
- }
+ },
});
const makeNotesFollowersOnlyBefore_customMonths = computed({
get: () => makeNotesFollowersOnlyBefore.value ? Math.abs(makeNotesFollowersOnlyBefore.value) / (30 * 24 * 60 * 60) : null,
set(value) {
if (value != null && value > 0) makeNotesFollowersOnlyBefore.value = -Math.abs(Math.floor(Number(value))) * 30 * 24 * 60 * 60;
- }
+ },
});
const makeNotesHiddenBefore_type = computed(() => {
@@ -303,7 +311,7 @@ const makeNotesHiddenBefore_presets = [
const makeNotesHiddenBefore_isCustomMode = ref(
makeNotesHiddenBefore.value != null &&
makeNotesHiddenBefore.value < 0 &&
- !makeNotesHiddenBefore_presets.some((preset) => preset.value === makeNotesHiddenBefore.value)
+ !makeNotesHiddenBefore_presets.some((preset) => preset.value === makeNotesHiddenBefore.value),
);
const makeNotesHiddenBefore_selection = computed({
@@ -311,14 +319,14 @@ const makeNotesHiddenBefore_selection = computed({
set(value) {
makeNotesHiddenBefore_isCustomMode.value = value === 'custom';
if (value !== 'custom') makeNotesHiddenBefore.value = value;
- }
+ },
});
const makeNotesHiddenBefore_customMonths = computed({
get: () => makeNotesHiddenBefore.value ? Math.abs(makeNotesHiddenBefore.value) / (30 * 24 * 60 * 60) : null,
set(value) {
if (value != null && value > 0) makeNotesHiddenBefore.value = -Math.abs(Math.floor(Number(value))) * 30 * 24 * 60 * 60;
- }
+ },
});
watch([makeNotesFollowersOnlyBefore, makeNotesHiddenBefore], () => {
diff --git a/packages/frontend/src/pages/tag.vue b/packages/frontend/src/pages/tag.vue
index b5a4503b68..047e68f583 100644
--- a/packages/frontend/src/pages/tag.vue
+++ b/packages/frontend/src/pages/tag.vue
@@ -52,7 +52,7 @@ async function post() {
const headerActions = computed(() => [{
icon: 'ti ti-dots',
- label: i18n.ts.more,
+ text: i18n.ts.more,
handler: (ev: MouseEvent) => {
os.popupMenu([{
text: i18n.ts.embed,
diff --git a/packages/frontend/src/utility/chart-vline.ts b/packages/frontend/src/utility/chart-vline.ts
index 465ca591c6..2fe4bdb83b 100644
--- a/packages/frontend/src/utility/chart-vline.ts
+++ b/packages/frontend/src/utility/chart-vline.ts
@@ -8,9 +8,10 @@ import type { Plugin } from 'chart.js';
export const chartVLine = (vLineColor: string) => ({
id: 'vLine',
beforeDraw(chart, args, options) {
- if (chart.tooltip?._active?.length) {
+ const tooltip = chart.tooltip as any;
+ if (tooltip?._active?.length) {
const ctx = chart.ctx;
- const xs = chart.tooltip._active.map(a => a.element.x);
+ const xs = tooltip._active.map(a => a.element.x);
const x = xs.reduce((a, b) => a + b, 0) / xs.length;
const topY = chart.scales.y.top;
const bottomY = chart.scales.y.bottom;
diff --git a/packages/frontend/src/utility/popout.ts b/packages/frontend/src/utility/popout.ts
index 5b141222e8..7e0222c459 100644
--- a/packages/frontend/src/utility/popout.ts
+++ b/packages/frontend/src/utility/popout.ts
@@ -20,8 +20,8 @@ export function popout(path: string, w?: HTMLElement) {
} else {
const width = 400;
const height = 500;
- const x = window.top.outerHeight / 2 + window.top.screenY - (height / 2);
- const y = window.top.outerWidth / 2 + window.top.screenX - (width / 2);
+ const x = window.top == null ? 0 : window.top.outerHeight / 2 + window.top.screenY - (height / 2);
+ const y = window.top == null ? 0 : window.top.outerWidth / 2 + window.top.screenX - (width / 2);
window.open(url, url,
`width=${width}, height=${height}, top=${x}, left=${y}`);
}
diff --git a/packages/frontend/src/utility/sticky-sidebar.ts b/packages/frontend/src/utility/sticky-sidebar.ts
index 867c9b8324..435555896f 100644
--- a/packages/frontend/src/utility/sticky-sidebar.ts
+++ b/packages/frontend/src/utility/sticky-sidebar.ts
@@ -3,6 +3,7 @@
* SPDX-License-Identifier: AGPL-3.0-only
*/
+/*
export class StickySidebar {
private lastScrollTop = 0;
private container: HTMLElement;
@@ -53,3 +54,4 @@ export class StickySidebar {
this.lastScrollTop = scrollTop <= 0 ? 0 : scrollTop;
}
}
+*/
From eb9915baf880146007bf035a8fe770acee016358 Mon Sep 17 00:00:00 2001
From: syuilo <4439005+syuilo@users.noreply.github.com>
Date: Tue, 26 Aug 2025 10:56:09 +0900
Subject: [PATCH 10/13] refactor and fix
---
CHANGELOG.md | 1 +
packages/frontend/src/os.ts | 21 +-----------------
.../src/pages/settings/avatar-decoration.vue | 22 ++++++++++++++-----
.../pages/settings/drive.WatermarkItem.vue | 2 +-
4 files changed, 20 insertions(+), 26 deletions(-)
diff --git a/CHANGELOG.md b/CHANGELOG.md
index dd9b4ff183..770b37a206 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -55,6 +55,7 @@
- Fix: メンションとしての条件を満たしていても、特定の条件(`-`が含まれる場合など)で正しくサジェストされない問題を一部修正
- Fix: ユーザーの前後ノートを閲覧する機能が動作しない問題を修正
- Fix: 照会ダイアログでap/showでローカルユーザーを解決した際@username@nullに飛ばされる問題を修正
+- Fix: アイコンのデコレーションを付ける際にデコレーションが表示されなくなる問題を修正
### Server
- Feat: サーバー管理コマンド
diff --git a/packages/frontend/src/os.ts b/packages/frontend/src/os.ts
index bf0e5e1b37..6ba3af72b9 100644
--- a/packages/frontend/src/os.ts
+++ b/packages/frontend/src/os.ts
@@ -9,7 +9,7 @@ import { markRaw, ref, defineAsyncComponent, nextTick } from 'vue';
import { EventEmitter } from 'eventemitter3';
import * as Misskey from 'misskey-js';
import type { Component, Ref } from 'vue';
-import type { ComponentProps as CP } from 'vue-component-type-helpers';
+import type { ComponentEmit, ComponentProps as CP } from 'vue-component-type-helpers';
import type { Form, GetFormResultType } from '@/utility/form.js';
import type { MenuItem } from '@/types/menu.js';
import type { PostFormProps } from '@/types/post-form.js';
@@ -157,28 +157,9 @@ export function claimZIndex(priority: keyof typeof zIndexes = 'low'): number {
return zIndexes[priority];
}
-// InstanceType['$emit'] だとインターセクション型が返ってきて
-// 使い物にならないので、代わりに ['$props'] から色々省くことで emit の型を生成する
-// FIXME: 何故か *.ts ファイルからだと型がうまく取れない?ことがあるのをなんとかしたい
-type ComponentEmit = T extends new () => { $props: infer Props }
- ? [keyof Pick>] extends [never]
- ? Record // *.ts ファイルから型がうまく取れないとき用(これがないと {} になって型エラーがうるさい)
- : EmitsExtractor
- : T extends (...args: any) => any
- ? ReturnType extends { [x: string]: any; __ctx?: { [x: string]: any; props: infer Props } }
- ? [keyof Pick>] extends [never]
- ? Record
- : EmitsExtractor
- : never
- : never;
-
// props に ref を許可するようにする
type ComponentProps = { [K in keyof CP]: CP[K] | Ref[K]> };
-type EmitsExtractor = {
- [K in keyof T as K extends `onVnode${string}` ? never : K extends `on${infer E}` ? Uncapitalize : K extends string ? never : K]: T[K];
-};
-
export function popup(
component: T,
props: ComponentProps,
diff --git a/packages/frontend/src/pages/settings/avatar-decoration.vue b/packages/frontend/src/pages/settings/avatar-decoration.vue
index c58cd57c65..4b8ac9a26c 100644
--- a/packages/frontend/src/pages/settings/avatar-decoration.vue
+++ b/packages/frontend/src/pages/settings/avatar-decoration.vue
@@ -17,13 +17,13 @@ SPDX-License-Identifier: AGPL-3.0-only
@@ -50,6 +50,7 @@ SPDX-License-Identifier: AGPL-3.0-only
import { ref, defineAsyncComponent, computed } from 'vue';
import * as Misskey from 'misskey-js';
import XDecoration from './avatar-decoration.decoration.vue';
+import XDialog from './avatar-decoration.dialog.vue';
import MkButton from '@/components/MkButton.vue';
import * as os from '@/os.js';
import { misskeyApi } from '@/utility/misskey-api.js';
@@ -68,14 +69,24 @@ misskeyApi('get-avatar-decorations').then(_avatarDecorations => {
loading.value = false;
});
-async function openDecoration(avatarDecoration, index?: number) {
- const { dispose } = await os.popupAsyncWithDialog(import('./avatar-decoration.dialog.vue').then(x => x.default), {
+function openAttachedDecoration(index: number) {
+ openDecoration(avatarDecorations.value.find(d => d.id === $i.avatarDecorations[index].id) ?? { id: '', url: '', name: '?', roleIdsThatCanBeUsedThisDecoration: [] }, index);
+}
+
+async function openDecoration(avatarDecoration: {
+ id: string;
+ url: string;
+ name: string;
+ roleIdsThatCanBeUsedThisDecoration: string[];
+}, index?: number) {
+ const { dispose } = os.popup(XDialog, {
decoration: avatarDecoration,
- usingIndex: index,
+ usingIndex: index ?? null,
}, {
'attach': async (payload) => {
const decoration = {
id: avatarDecoration.id,
+ url: avatarDecoration.url,
angle: payload.angle,
flipH: payload.flipH,
offsetX: payload.offsetX,
@@ -90,6 +101,7 @@ async function openDecoration(avatarDecoration, index?: number) {
'update': async (payload) => {
const decoration = {
id: avatarDecoration.id,
+ url: avatarDecoration.url,
angle: payload.angle,
flipH: payload.flipH,
offsetX: payload.offsetX,
diff --git a/packages/frontend/src/pages/settings/drive.WatermarkItem.vue b/packages/frontend/src/pages/settings/drive.WatermarkItem.vue
index b466f35fc5..bb91d5e212 100644
--- a/packages/frontend/src/pages/settings/drive.WatermarkItem.vue
+++ b/packages/frontend/src/pages/settings/drive.WatermarkItem.vue
@@ -43,7 +43,7 @@ async function edit() {
const { dispose } = os.popup(defineAsyncComponent(() => import('@/components/MkWatermarkEditorDialog.vue')), {
preset: deepClone(props.preset),
}, {
- ok: (preset: WatermarkPreset) => {
+ ok: (preset) => {
emit('updatePreset', preset);
},
closed: () => dispose(),
From d6a1046361d3d38726f2a86588960c3614f72a9f Mon Sep 17 00:00:00 2001
From: syuilo <4439005+syuilo@users.noreply.github.com>
Date: Tue, 26 Aug 2025 13:34:41 +0900
Subject: [PATCH 11/13] refactor
---
.../entities/NoteReactionEntityService.ts | 50 +++++++++++++----
packages/backend/src/misc/json-schema.ts | 3 +-
.../src/models/json-schema/note-reaction.ts | 31 ++++++++++-
.../api/endpoints/admin/announcements/list.ts | 28 ++++++++++
.../server/api/endpoints/users/lists/show.ts | 10 ++++
.../server/api/endpoints/users/reactions.ts | 4 +-
packages/frontend/src/boot/main-boot.ts | 5 --
.../src/components/MkAchievements.vue | 2 +-
packages/frontend/src/components/MkChart.vue | 55 +++++++++++++++----
.../src/components/MkCropperDialog.vue | 44 +++++++++------
.../frontend/src/components/MkEmojiPicker.vue | 2 +-
.../src/components/MkEmojiPickerDialog.vue | 4 +-
packages/frontend/src/components/MkModal.vue | 4 +-
.../components/MkReactionsViewer.reaction.vue | 27 ++++++---
.../components/global/MkPageHeader.tabs.vue | 2 +-
packages/frontend/src/pages/admin-user.vue | 4 +-
.../frontend/src/pages/drive.file.info.vue | 24 +++++---
packages/frontend/src/pages/explore.vue | 6 --
packages/frontend/src/pages/list.vue | 1 +
packages/frontend/src/pages/note.vue | 2 +-
.../frontend/src/pages/registry.value.vue | 4 +-
.../src/pages/settings/avatar-decoration.vue | 4 +-
.../src/pages/settings/notifications.vue | 11 ++--
.../frontend/src/pages/settings/security.vue | 4 +-
.../frontend/src/pages/settings/theme.vue | 3 +-
.../src/pages/settings/webhook.edit.vue | 2 -
packages/frontend/src/pages/timeline.vue | 2 +-
.../src/pages/user/activity.following.vue | 2 +
.../src/pages/user/activity.notes.vue | 4 +-
.../frontend/src/pages/user/activity.pv.vue | 4 +-
packages/frontend/src/preferences/def.ts | 4 +-
packages/frontend/src/preferences/manager.ts | 7 ++-
.../src/ui/_common_/announcements.vue | 2 +-
packages/frontend/src/ui/_common_/common.ts | 34 ++++++++----
.../src/ui/_common_/statusbar-rss.vue | 6 +-
packages/frontend/src/ui/deck.vue | 2 +-
packages/frontend/src/utility/admin-lookup.ts | 2 +-
packages/frontend/src/utility/chart-legend.ts | 2 +-
packages/frontend/src/utility/clicker-game.ts | 16 +-----
.../frontend/src/utility/get-note-menu.ts | 2 +-
.../src/widgets/WidgetInstanceInfo.vue | 4 +-
41 files changed, 289 insertions(+), 140 deletions(-)
diff --git a/packages/backend/src/core/entities/NoteReactionEntityService.ts b/packages/backend/src/core/entities/NoteReactionEntityService.ts
index 46ec13704c..54ce4d472a 100644
--- a/packages/backend/src/core/entities/NoteReactionEntityService.ts
+++ b/packages/backend/src/core/entities/NoteReactionEntityService.ts
@@ -49,15 +49,12 @@ export class NoteReactionEntityService implements OnModuleInit {
public async pack(
src: MiNoteReaction['id'] | MiNoteReaction,
me?: { id: MiUser['id'] } | null | undefined,
- options?: {
- withNote: boolean;
- },
+ options?: object,
hints?: {
packedUser?: Packed<'UserLite'>
},
): Promise> {
const opts = Object.assign({
- withNote: false,
}, options);
const reaction = typeof src === 'object' ? src : await this.noteReactionsRepository.findOneByOrFail({ id: src });
@@ -67,9 +64,6 @@ export class NoteReactionEntityService implements OnModuleInit {
createdAt: this.idService.parse(reaction.id).date.toISOString(),
user: hints?.packedUser ?? await this.userEntityService.pack(reaction.user ?? reaction.userId, me),
type: this.reactionService.convertLegacyReaction(reaction.reaction),
- ...(opts.withNote ? {
- note: await this.noteEntityService.pack(reaction.note ?? reaction.noteId, me),
- } : {}),
};
}
@@ -77,16 +71,50 @@ export class NoteReactionEntityService implements OnModuleInit {
public async packMany(
reactions: MiNoteReaction[],
me?: { id: MiUser['id'] } | null | undefined,
- options?: {
- withNote: boolean;
- },
+ options?: object,
): Promise[]> {
const opts = Object.assign({
- withNote: false,
}, options);
const _users = reactions.map(({ user, userId }) => user ?? userId);
const _userMap = await this.userEntityService.packMany(_users, me)
.then(users => new Map(users.map(u => [u.id, u])));
return Promise.all(reactions.map(reaction => this.pack(reaction, me, opts, { packedUser: _userMap.get(reaction.userId) })));
}
+
+ @bindThis
+ public async packWithNote(
+ src: MiNoteReaction['id'] | MiNoteReaction,
+ me?: { id: MiUser['id'] } | null | undefined,
+ options?: object,
+ hints?: {
+ packedUser?: Packed<'UserLite'>
+ },
+ ): Promise> {
+ const opts = Object.assign({
+ }, options);
+
+ const reaction = typeof src === 'object' ? src : await this.noteReactionsRepository.findOneByOrFail({ id: src });
+
+ return {
+ id: reaction.id,
+ createdAt: this.idService.parse(reaction.id).date.toISOString(),
+ user: hints?.packedUser ?? await this.userEntityService.pack(reaction.user ?? reaction.userId, me),
+ type: this.reactionService.convertLegacyReaction(reaction.reaction),
+ note: await this.noteEntityService.pack(reaction.note ?? reaction.noteId, me),
+ };
+ }
+
+ @bindThis
+ public async packManyWithNote(
+ reactions: MiNoteReaction[],
+ me?: { id: MiUser['id'] } | null | undefined,
+ options?: object,
+ ): Promise[]> {
+ const opts = Object.assign({
+ }, options);
+ const _users = reactions.map(({ user, userId }) => user ?? userId);
+ const _userMap = await this.userEntityService.packMany(_users, me)
+ .then(users => new Map(users.map(u => [u.id, u])));
+ return Promise.all(reactions.map(reaction => this.packWithNote(reaction, me, opts, { packedUser: _userMap.get(reaction.userId) })));
+ }
}
diff --git a/packages/backend/src/misc/json-schema.ts b/packages/backend/src/misc/json-schema.ts
index ed47edff9b..dca92e1037 100644
--- a/packages/backend/src/misc/json-schema.ts
+++ b/packages/backend/src/misc/json-schema.ts
@@ -22,7 +22,7 @@ import { packedFollowingSchema } from '@/models/json-schema/following.js';
import { packedMutingSchema } from '@/models/json-schema/muting.js';
import { packedRenoteMutingSchema } from '@/models/json-schema/renote-muting.js';
import { packedBlockingSchema } from '@/models/json-schema/blocking.js';
-import { packedNoteReactionSchema } from '@/models/json-schema/note-reaction.js';
+import { packedNoteReactionSchema, packedNoteReactionWithNoteSchema } from '@/models/json-schema/note-reaction.js';
import { packedHashtagSchema } from '@/models/json-schema/hashtag.js';
import { packedInviteCodeSchema } from '@/models/json-schema/invite-code.js';
import { packedPageBlockSchema, packedPageSchema } from '@/models/json-schema/page.js';
@@ -92,6 +92,7 @@ export const refs = {
Note: packedNoteSchema,
NoteDraft: packedNoteDraftSchema,
NoteReaction: packedNoteReactionSchema,
+ NoteReactionWithNote: packedNoteReactionWithNoteSchema,
NoteFavorite: packedNoteFavoriteSchema,
Notification: packedNotificationSchema,
DriveFile: packedDriveFileSchema,
diff --git a/packages/backend/src/models/json-schema/note-reaction.ts b/packages/backend/src/models/json-schema/note-reaction.ts
index 95658ace1f..04c9f34232 100644
--- a/packages/backend/src/models/json-schema/note-reaction.ts
+++ b/packages/backend/src/models/json-schema/note-reaction.ts
@@ -10,7 +10,6 @@ export const packedNoteReactionSchema = {
type: 'string',
optional: false, nullable: false,
format: 'id',
- example: 'xxxxxxxxxx',
},
createdAt: {
type: 'string',
@@ -28,3 +27,33 @@ export const packedNoteReactionSchema = {
},
},
} as const;
+
+export const packedNoteReactionWithNoteSchema = {
+ type: 'object',
+ properties: {
+ id: {
+ type: 'string',
+ optional: false, nullable: false,
+ format: 'id',
+ },
+ createdAt: {
+ type: 'string',
+ optional: false, nullable: false,
+ format: 'date-time',
+ },
+ user: {
+ type: 'object',
+ optional: false, nullable: false,
+ ref: 'UserLite',
+ },
+ type: {
+ type: 'string',
+ optional: false, nullable: false,
+ },
+ note: {
+ type: 'object',
+ optional: false, nullable: false,
+ ref: 'Note',
+ },
+ },
+} as const;
diff --git a/packages/backend/src/server/api/endpoints/admin/announcements/list.ts b/packages/backend/src/server/api/endpoints/admin/announcements/list.ts
index 81a788de2b..804bd5d9b9 100644
--- a/packages/backend/src/server/api/endpoints/admin/announcements/list.ts
+++ b/packages/backend/src/server/api/endpoints/admin/announcements/list.ts
@@ -49,6 +49,34 @@ export const meta = {
type: 'string',
optional: false, nullable: false,
},
+ icon: {
+ type: 'string',
+ optional: false, nullable: true,
+ },
+ display: {
+ type: 'string',
+ optional: false, nullable: false,
+ },
+ isActive: {
+ type: 'boolean',
+ optional: false, nullable: false,
+ },
+ forExistingUsers: {
+ type: 'boolean',
+ optional: false, nullable: false,
+ },
+ silence: {
+ type: 'boolean',
+ optional: false, nullable: false,
+ },
+ needConfirmationToRead: {
+ type: 'boolean',
+ optional: false, nullable: false,
+ },
+ userId: {
+ type: 'string',
+ optional: false, nullable: true,
+ },
imageUrl: {
type: 'string',
optional: false, nullable: true,
diff --git a/packages/backend/src/server/api/endpoints/users/lists/show.ts b/packages/backend/src/server/api/endpoints/users/lists/show.ts
index 8756801fe4..ed5952d4c5 100644
--- a/packages/backend/src/server/api/endpoints/users/lists/show.ts
+++ b/packages/backend/src/server/api/endpoints/users/lists/show.ts
@@ -23,6 +23,16 @@ export const meta = {
type: 'object',
optional: false, nullable: false,
ref: 'UserList',
+ properties: {
+ likedCount: {
+ type: 'number',
+ optional: true, nullable: false,
+ },
+ isLiked: {
+ type: 'boolean',
+ optional: true, nullable: false,
+ },
+ },
},
errors: {
diff --git a/packages/backend/src/server/api/endpoints/users/reactions.ts b/packages/backend/src/server/api/endpoints/users/reactions.ts
index d6f1ecd8ed..d84a191f7a 100644
--- a/packages/backend/src/server/api/endpoints/users/reactions.ts
+++ b/packages/backend/src/server/api/endpoints/users/reactions.ts
@@ -28,7 +28,7 @@ export const meta = {
items: {
type: 'object',
optional: false, nullable: false,
- ref: 'NoteReaction',
+ ref: 'NoteReactionWithNote',
},
},
@@ -120,7 +120,7 @@ export default class extends Endpoint { // eslint-
return true;
});
- return await this.noteReactionEntityService.packMany(reactions, me, { withNote: true });
+ return await this.noteReactionEntityService.packManyWithNote(reactions, me);
});
}
}
diff --git a/packages/frontend/src/boot/main-boot.ts b/packages/frontend/src/boot/main-boot.ts
index 6ae8379801..18817d3f79 100644
--- a/packages/frontend/src/boot/main-boot.ts
+++ b/packages/frontend/src/boot/main-boot.ts
@@ -368,11 +368,6 @@ export async function mainBoot() {
});
});
- main.on('unreadAntenna', () => {
- updateCurrentAccountPartial({ hasUnreadAntenna: true });
- sound.playMisskeySfx('antenna');
- });
-
main.on('newChatMessage', () => {
updateCurrentAccountPartial({ hasUnreadChatMessages: true });
sound.playMisskeySfx('chatMessage');
diff --git a/packages/frontend/src/components/MkAchievements.vue b/packages/frontend/src/components/MkAchievements.vue
index 3b7b59b4d3..bf39c1e983 100644
--- a/packages/frontend/src/components/MkAchievements.vue
+++ b/packages/frontend/src/components/MkAchievements.vue
@@ -16,7 +16,7 @@ SPDX-License-Identifier: AGPL-3.0-only
[$style.iconFrame_platinum]: ACHIEVEMENT_BADGES[achievement.name].frame === 'platinum',
}]"
>
-
diff --git a/packages/frontend/src/components/MkChart.vue b/packages/frontend/src/components/MkChart.vue
index 4d67bba70d..c54081ad42 100644
--- a/packages/frontend/src/components/MkChart.vue
+++ b/packages/frontend/src/components/MkChart.vue
@@ -589,7 +589,10 @@ const fetchDriveFilesChart = async (): Promise => {
};
const fetchInstanceRequestsChart = async (): Promise => {
- const raw = await misskeyApiGet('charts/instance', { host: props.args?.host, limit: props.limit, span: props.span });
+ const host = props.args?.host;
+ if (host == null) return { series: [] };
+
+ const raw = await misskeyApiGet('charts/instance', { host: host, limit: props.limit, span: props.span });
return {
series: [{
name: 'In',
@@ -611,7 +614,10 @@ const fetchInstanceRequestsChart = async (): Promise => {
};
const fetchInstanceUsersChart = async (total: boolean): Promise => {
- const raw = await misskeyApiGet('charts/instance', { host: props.args?.host, limit: props.limit, span: props.span });
+ const host = props.args?.host;
+ if (host == null) return { series: [] };
+
+ const raw = await misskeyApiGet('charts/instance', { host: host, limit: props.limit, span: props.span });
return {
series: [{
name: 'Users',
@@ -626,7 +632,10 @@ const fetchInstanceUsersChart = async (total: boolean): Promise => {
- const raw = await misskeyApiGet('charts/instance', { host: props.args?.host, limit: props.limit, span: props.span });
+ const host = props.args?.host;
+ if (host == null) return { series: [] };
+
+ const raw = await misskeyApiGet('charts/instance', { host: host, limit: props.limit, span: props.span });
return {
series: [{
name: 'Notes',
@@ -641,7 +650,10 @@ const fetchInstanceNotesChart = async (total: boolean): Promise => {
- const raw = await misskeyApiGet('charts/instance', { host: props.args?.host, limit: props.limit, span: props.span });
+ const host = props.args?.host;
+ if (host == null) return { series: [] };
+
+ const raw = await misskeyApiGet('charts/instance', { host: host, limit: props.limit, span: props.span });
return {
series: [{
name: 'Following',
@@ -664,7 +676,10 @@ const fetchInstanceFfChart = async (total: boolean): Promise =
};
const fetchInstanceDriveUsageChart = async (total: boolean): Promise => {
- const raw = await misskeyApiGet('charts/instance', { host: props.args?.host, limit: props.limit, span: props.span });
+ const host = props.args?.host;
+ if (host == null) return { series: [] };
+
+ const raw = await misskeyApiGet('charts/instance', { host: host, limit: props.limit, span: props.span });
return {
bytes: true,
series: [{
@@ -680,7 +695,10 @@ const fetchInstanceDriveUsageChart = async (total: boolean): Promise => {
- const raw = await misskeyApiGet('charts/instance', { host: props.args?.host, limit: props.limit, span: props.span });
+ const host = props.args?.host;
+ if (host == null) return { series: [] };
+
+ const raw = await misskeyApiGet('charts/instance', { host: host, limit: props.limit, span: props.span });
return {
series: [{
name: 'Drive files',
@@ -695,7 +713,10 @@ const fetchInstanceDriveFilesChart = async (total: boolean): Promise => {
- const raw = await misskeyApiGet('charts/user/notes', { userId: props.args?.user?.id, limit: props.limit, span: props.span });
+ const userId = props.args?.user?.id;
+ if (userId == null) return { series: [] };
+
+ const raw = await misskeyApiGet('charts/user/notes', { userId: userId, limit: props.limit, span: props.span });
return {
series: [...(props.args?.withoutAll ? [] : [{
name: 'All',
@@ -727,7 +748,10 @@ const fetchPerUserNotesChart = async (): Promise => {
};
const fetchPerUserPvChart = async (): Promise => {
- const raw = await misskeyApiGet('charts/user/pv', { userId: props.args?.user?.id, limit: props.limit, span: props.span });
+ const userId = props.args?.user?.id;
+ if (userId == null) return { series: [] };
+
+ const raw = await misskeyApiGet('charts/user/pv', { userId: userId, limit: props.limit, span: props.span });
return {
series: [{
name: 'Unique PV (user)',
@@ -754,7 +778,10 @@ const fetchPerUserPvChart = async (): Promise => {
};
const fetchPerUserFollowingChart = async (): Promise => {
- const raw = await misskeyApiGet('charts/user/following', { userId: props.args?.user?.id, limit: props.limit, span: props.span });
+ const userId = props.args?.user?.id;
+ if (userId == null) return { series: [] };
+
+ const raw = await misskeyApiGet('charts/user/following', { userId: userId, limit: props.limit, span: props.span });
return {
series: [{
name: 'Local',
@@ -769,7 +796,10 @@ const fetchPerUserFollowingChart = async (): Promise => {
};
const fetchPerUserFollowersChart = async (): Promise => {
- const raw = await misskeyApiGet('charts/user/following', { userId: props.args?.user?.id, limit: props.limit, span: props.span });
+ const userId = props.args?.user?.id;
+ if (userId == null) return { series: [] };
+
+ const raw = await misskeyApiGet('charts/user/following', { userId: userId, limit: props.limit, span: props.span });
return {
series: [{
name: 'Local',
@@ -784,7 +814,10 @@ const fetchPerUserFollowersChart = async (): Promise => {
};
const fetchPerUserDriveChart = async (): Promise => {
- const raw = await misskeyApiGet('charts/user/drive', { userId: props.args?.user?.id, limit: props.limit, span: props.span });
+ const userId = props.args?.user?.id;
+ if (userId == null) return { series: [] };
+
+ const raw = await misskeyApiGet('charts/user/drive', { userId: userId, limit: props.limit, span: props.span });
return {
bytes: true,
series: [{
diff --git a/packages/frontend/src/components/MkCropperDialog.vue b/packages/frontend/src/components/MkCropperDialog.vue
index 7f592fba79..6c07eac47a 100644
--- a/packages/frontend/src/components/MkCropperDialog.vue
+++ b/packages/frontend/src/components/MkCropperDialog.vue
@@ -29,7 +29,7 @@ SPDX-License-Identifier: AGPL-3.0-only