From 69bbac013a5875b1ffb686e63c8896b86eacdebf Mon Sep 17 00:00:00 2001 From: syuilo <4439005+syuilo@users.noreply.github.com> Date: Tue, 26 Aug 2025 17:31:36 +0900 Subject: [PATCH] refactor --- .../src/server/api/endpoints/flash/update.ts | 4 +- packages/frontend/src/accounts.ts | 43 ++++++++++++------- packages/frontend/src/components/MkLink.vue | 4 +- packages/frontend/src/components/MkNote.vue | 2 +- .../src/components/MkNoteDetailed.vue | 5 ++- .../src/components/MkPostFormDialog.vue | 2 +- packages/frontend/src/os.ts | 4 +- .../frontend/src/pages/flash/flash-edit.vue | 11 +++-- packages/frontend/src/store.ts | 2 +- packages/frontend/src/types/menu.ts | 16 +++---- packages/frontend/src/types/post-form.ts | 9 +++- packages/frontend/src/utility/drive.ts | 2 +- .../src/utility/extract-url-from-mfm.ts | 2 +- 13 files changed, 67 insertions(+), 39 deletions(-) diff --git a/packages/backend/src/server/api/endpoints/flash/update.ts b/packages/backend/src/server/api/endpoints/flash/update.ts index e378669f0a..8696c6f6e8 100644 --- a/packages/backend/src/server/api/endpoints/flash/update.ts +++ b/packages/backend/src/server/api/endpoints/flash/update.ts @@ -73,8 +73,8 @@ export default class extends Endpoint { // eslint- updatedAt: new Date(), ...Object.fromEntries( Object.entries(ps).filter( - ([key, val]) => (key !== 'flashId') && Object.hasOwn(paramDef.properties, key) - ) + ([key, val]) => (key !== 'flashId') && Object.hasOwn(paramDef.properties, key), + ), ), }); }); diff --git a/packages/frontend/src/accounts.ts b/packages/frontend/src/accounts.ts index 3693ac3308..afa2ecb911 100644 --- a/packages/frontend/src/accounts.ts +++ b/packages/frontend/src/accounts.ts @@ -23,7 +23,7 @@ export async function getAccounts(): Promise<{ host: string; id: Misskey.entities.User['id']; username: Misskey.entities.User['username']; - user?: Misskey.entities.User | null; + user?: Misskey.entities.MeDetailed | null; token: string | null; }[]> { const tokens = store.s.accountTokens; @@ -38,7 +38,7 @@ export async function getAccounts(): Promise<{ })); } -async function addAccount(host: string, user: Misskey.entities.User, token: AccountWithToken['token']) { +async function addAccount(host: string, user: Misskey.entities.MeDetailed, token: AccountWithToken['token']) { if (!prefer.s.accounts.some(x => x[0] === host && x[1].id === user.id)) { store.set('accountTokens', { ...store.s.accountTokens, [host + '/' + user.id]: token }); store.set('accountInfos', { ...store.s.accountInfos, [host + '/' + user.id]: user }); @@ -149,9 +149,10 @@ export function updateCurrentAccountPartial(accountData: Partial { if (reason === isAccountDeleted) { - removeAccount(host, $i.id); + removeAccount(host, me.id); if (Object.keys(store.s.accountTokens).length > 0) { login(Object.values(store.s.accountTokens)[0]); } else { @@ -214,19 +215,37 @@ export async function openAccountMenu(opts: { includeCurrentAccount?: boolean; withExtraOperation: boolean; active?: Misskey.entities.User['id']; - onChoose?: (account: Misskey.entities.User) => void; + onChoose?: (account: Misskey.entities.MeDetailed) => void; }, ev: MouseEvent) { if (!$i) return; + const me = $i; - function createItem(host: string, id: Misskey.entities.User['id'], username: Misskey.entities.User['username'], account: Misskey.entities.User | null | undefined, token: string): MenuItem { + const callback = opts.onChoose; + + function createItem(host: string, id: Misskey.entities.User['id'], username: Misskey.entities.User['username'], account: Misskey.entities.MeDetailed | null | undefined, token: string | null): MenuItem { if (account) { return { type: 'user' as const, user: account, active: opts.active != null ? opts.active === id : false, action: async () => { - if (opts.onChoose) { - opts.onChoose(account); + if (callback) { + callback(account); + } else { + switchAccount(host, id); + } + }, + }; + } else if (token != null) { + return { + type: 'button' as const, + text: username, + active: opts.active != null ? opts.active === id : false, + action: async () => { + if (callback) { + fetchAccount(token, id).then(account => { + callback(account); + }); } else { switchAccount(host, id); } @@ -238,13 +257,7 @@ export async function openAccountMenu(opts: { text: username, active: opts.active != null ? opts.active === id : false, action: async () => { - if (opts.onChoose) { - fetchAccount(token, id).then(account => { - opts.onChoose(account); - }); - } else { - switchAccount(host, id); - } + // TODO }, }; } @@ -253,7 +266,7 @@ export async function openAccountMenu(opts: { const menuItems: MenuItem[] = []; // TODO: $iのホストも比較したいけど通常null - const accountItems = (await getAccounts().then(accounts => accounts.filter(x => x.id !== $i.id))).map(a => createItem(a.host, a.id, a.username, a.user, a.token)); + const accountItems = (await getAccounts().then(accounts => accounts.filter(x => x.id !== me.id))).map(a => createItem(a.host, a.id, a.username, a.user, a.token)); if (opts.withExtraOperation) { menuItems.push({ diff --git a/packages/frontend/src/components/MkLink.vue b/packages/frontend/src/components/MkLink.vue index 1959f97565..163f172f57 100644 --- a/packages/frontend/src/components/MkLink.vue +++ b/packages/frontend/src/components/MkLink.vue @@ -39,10 +39,12 @@ const el = ref(); if (isEnabledUrlPreview.value) { useTooltip(el, (showing) => { + const anchorElement = el.value instanceof HTMLElement ? el.value : el.value?.$el; + if (anchorElement == null) return; const { dispose } = os.popup(defineAsyncComponent(() => import('@/components/MkUrlPreviewPopup.vue')), { showing, url: props.url, - anchorElement: el.value instanceof HTMLElement ? el.value : el.value?.$el, + anchorElement: anchorElement, }, { closed: () => dispose(), }); diff --git a/packages/frontend/src/components/MkNote.vue b/packages/frontend/src/components/MkNote.vue index 17d4c70bfc..729bded03c 100644 --- a/packages/frontend/src/components/MkNote.vue +++ b/packages/frontend/src/components/MkNote.vue @@ -654,7 +654,7 @@ function showRenoteMenu(): void { getCopyNoteLinkMenu(note, i18n.ts.copyLinkRenote), { type: 'divider' }, getAbuseNoteMenu(note, i18n.ts.reportAbuseRenote), - ($i?.isModerator || $i?.isAdmin) ? getUnrenote() : undefined, + ...(($i?.isModerator || $i?.isAdmin) ? [getUnrenote()] : []), ], renoteTime.value); } } diff --git a/packages/frontend/src/components/MkNoteDetailed.vue b/packages/frontend/src/components/MkNoteDetailed.vue index 42e8665fe5..48fd9908bd 100644 --- a/packages/frontend/src/components/MkNoteDetailed.vue +++ b/packages/frontend/src/components/MkNoteDetailed.vue @@ -392,6 +392,9 @@ const reactionsPaginator = markRaw(new Paginator('notes/reactions', { })); useTooltip(renoteButton, async (showing) => { + const anchorElement = renoteButton.value; + if (anchorElement == null) return; + const renotes = await misskeyApi('notes/renotes', { noteId: appearNote.id, limit: 11, @@ -405,7 +408,7 @@ useTooltip(renoteButton, async (showing) => { showing, users, count: appearNote.renoteCount, - anchorElement: renoteButton.value, + anchorElement: anchorElement, }, { closed: () => dispose(), }); diff --git a/packages/frontend/src/components/MkPostFormDialog.vue b/packages/frontend/src/components/MkPostFormDialog.vue index 1f7796bd83..bf332e706e 100644 --- a/packages/frontend/src/components/MkPostFormDialog.vue +++ b/packages/frontend/src/components/MkPostFormDialog.vue @@ -57,7 +57,7 @@ async function _close() { modal.value?.close(); } -function onEsc(ev: KeyboardEvent) { +function onEsc() { _close(); } diff --git a/packages/frontend/src/os.ts b/packages/frontend/src/os.ts index 6ba3af72b9..56a2b8d269 100644 --- a/packages/frontend/src/os.ts +++ b/packages/frontend/src/os.ts @@ -684,7 +684,7 @@ export async function cropImageFile(imageFile: File | Blob, options: { }); } -export function popupMenu(items: MenuItem[], anchorElement?: HTMLElement | EventTarget | null, options?: { +export function popupMenu(items: (MenuItem | null)[], anchorElement?: HTMLElement | EventTarget | null, options?: { align?: string; width?: number; onClosing?: () => void; @@ -696,7 +696,7 @@ export function popupMenu(items: MenuItem[], anchorElement?: HTMLElement | Event let returnFocusTo = getHTMLElementOrNull(anchorElement) ?? getHTMLElementOrNull(window.document.activeElement); return new Promise(resolve => nextTick(() => { const { dispose } = popup(MkPopupMenu, { - items, + items: items.filter(x => x != null), anchorElement, width: options?.width, align: options?.align, diff --git a/packages/frontend/src/pages/flash/flash-edit.vue b/packages/frontend/src/pages/flash/flash-edit.vue index d2c2621a35..81b9d1cead 100644 --- a/packages/frontend/src/pages/flash/flash-edit.vue +++ b/packages/frontend/src/pages/flash/flash-edit.vue @@ -383,7 +383,7 @@ if (props.id) { const title = ref(flash.value?.title ?? 'New Play'); const summary = ref(flash.value?.summary ?? ''); -const permissions = ref(flash.value?.permissions ?? []); +const permissions = ref([]); // not implemented yet const visibility = ref<'private' | 'public'>(flash.value?.visibility ?? 'public'); const script = ref(flash.value?.script ?? PRESET_DEFAULT); @@ -412,9 +412,9 @@ function selectPreset(ev: MouseEvent) { } async function save() { - if (flash.value) { + if (flash.value != null) { os.apiWithDialog('flash/update', { - flashId: props.id, + flashId: flash.value.id, title: title.value, summary: summary.value, permissions: permissions.value, @@ -448,6 +448,8 @@ function show() { } async function del() { + if (flash.value == null) return; + const { canceled } = await os.confirm({ type: 'warning', text: i18n.tsx.deleteAreYouSure({ x: flash.value.title }), @@ -455,7 +457,7 @@ async function del() { if (canceled) return; await os.apiWithDialog('flash/delete', { - flashId: props.id, + flashId: flash.value.id, }); router.push('/play'); } @@ -468,6 +470,7 @@ definePage(() => ({ title: flash.value ? `${i18n.ts._play.edit}: ${flash.value.title}` : i18n.ts._play.new, })); +