From 4285303c8155dd91be7dcbb865d5e8f7cb0e1c71 Mon Sep 17 00:00:00 2001 From: かっこかり <67428053+kakkokari-gtyih@users.noreply.github.com> Date: Tue, 30 Dec 2025 14:32:40 +0900 Subject: fix(frontend): follow-up of #17033 (#17047) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * wip * fix * ref -> reactive * tweak throttle threshold * tweak throttle threshold * rss設定にはmanualSaveを使用するように * Update MkWidgetSettingsDialog.vue --------- Co-authored-by: syuilo <4439005+syuilo@users.noreply.github.com> --- packages/frontend/src/utility/form.ts | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'packages/frontend/src/utility') diff --git a/packages/frontend/src/utility/form.ts b/packages/frontend/src/utility/form.ts index cb4a227f67..fe89333285 100644 --- a/packages/frontend/src/utility/form.ts +++ b/packages/frontend/src/utility/form.ts @@ -25,6 +25,7 @@ export interface StringFormItem extends FormItemBase { required?: boolean; multiline?: boolean; treatAsMfm?: boolean; + manualSave?: boolean; } export interface NumberFormItem extends FormItemBase { @@ -33,6 +34,7 @@ export interface NumberFormItem extends FormItemBase { description?: string; required?: boolean; step?: number; + manualSave?: boolean; } export interface BooleanFormItem extends FormItemBase { @@ -145,3 +147,11 @@ type GetItemType = export type GetFormResultType = { [P in keyof F]: GetItemType; }; + +export function getDefaultFormValues(form: F): GetFormResultType { + const result = {} as GetFormResultType; + for (const key of Object.keys(form) as (keyof F)[]) { + result[key] = form[key].default as GetItemType; + } + return result; +} -- cgit v1.2.3-freya From a1ba403f9ae4b08107a10203997f7a790370e2a0 Mon Sep 17 00:00:00 2001 From: かっこかり <67428053+kakkokari-gtyih@users.noreply.github.com> Date: Fri, 2 Jan 2026 21:38:53 +0900 Subject: fix(frontend): ログインダイアログが表示されたあとの処理がおかしくなる問題を修正 (#17038) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * fix(frontend): ログインダイアログが表示されたあとの処理がおかしくなる問題を修正 * Update Changelog --- CHANGELOG.md | 1 + .../frontend/src/components/MkFollowButton.vue | 8 +++++- packages/frontend/src/components/MkNote.vue | 30 ++++++++++++++-------- .../frontend/src/components/MkNoteDetailed.vue | 25 ++++++++++++------ packages/frontend/src/components/MkPoll.vue | 3 ++- packages/frontend/src/os.ts | 5 ++-- packages/frontend/src/pages/flash/flash.vue | 10 +++++--- packages/frontend/src/pages/reversi/index.vue | 8 +++--- packages/frontend/src/utility/please-login.ts | 6 ++--- 9 files changed, 64 insertions(+), 32 deletions(-) (limited to 'packages/frontend/src/utility') diff --git a/CHANGELOG.md b/CHANGELOG.md index 88f3981473..e22dfba72a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,6 +13,7 @@ - Enhance: ウィジェットの表示設定をプレビューを見ながら行えるように - Enhance: ウィジェットの設定項目のラベルの多言語対応 - Fix: ドライブクリーナーでファイルを削除しても画面に反映されない問題を修正 #16061 +- Fix: 非ログイン時にログインを求めるダイアログが表示された後にダイアログのぼかしが解除されず操作不能になることがある問題を修正 - Fix: ドライブのソートが「登録日(昇順)」の場合に正しく動作しない問題を修正 ### Server diff --git a/packages/frontend/src/components/MkFollowButton.vue b/packages/frontend/src/components/MkFollowButton.vue index ba21fe82e4..72a24411c1 100644 --- a/packages/frontend/src/components/MkFollowButton.vue +++ b/packages/frontend/src/components/MkFollowButton.vue @@ -81,7 +81,13 @@ function onFollowChange(user: Misskey.entities.UserDetailed) { } async function onClick() { - pleaseLogin({ openOnRemote: { type: 'web', path: `/@${props.user.username}@${props.user.host ?? host}` } }); + const isLoggedIn = await pleaseLogin({ + openOnRemote: { + type: 'web', + path: `/@${props.user.username}@${props.user.host ?? host}`, + }, + }); + if (!isLoggedIn) return; wait.value = true; diff --git a/packages/frontend/src/components/MkNote.vue b/packages/frontend/src/components/MkNote.vue index a7299d2961..56def64d3d 100644 --- a/packages/frontend/src/components/MkNote.vue +++ b/packages/frontend/src/components/MkNote.vue @@ -468,8 +468,12 @@ if (!props.mock) { } } -function renote() { - pleaseLogin({ openOnRemote: pleaseLoginContext.value }); +async function renote() { + if (props.mock) return; + + const isLoggedIn = await pleaseLogin({ openOnRemote: pleaseLoginContext.value }); + if (!isLoggedIn) return; + showMovedDialog(); const { menu } = getRenoteMenu({ note: note, renoteButton, mock: props.mock }); @@ -478,11 +482,12 @@ function renote() { subscribeManuallyToNoteCapture(); } -function reply(): void { - pleaseLogin({ openOnRemote: pleaseLoginContext.value }); - if (props.mock) { - return; - } +async function reply() { + if (props.mock) return; + + const isLoggedIn = await pleaseLogin({ openOnRemote: pleaseLoginContext.value }); + if (!isLoggedIn) return; + os.post({ reply: appearNote, channel: appearNote.channel, @@ -491,8 +496,10 @@ function reply(): void { }); } -function react(): void { - pleaseLogin({ openOnRemote: pleaseLoginContext.value }); +async function react() { + const isLoggedIn = await pleaseLogin({ openOnRemote: pleaseLoginContext.value }); + if (!isLoggedIn) return; + showMovedDialog(); if (appearNote.reactionAcceptance === 'likeOnly') { sound.playMisskeySfx('reaction'); @@ -621,10 +628,12 @@ async function clip(): Promise { os.popupMenu(await getNoteClipMenu({ note: note, currentClip: currentClip?.value }), clipButton.value).then(focus); } -function showRenoteMenu(): void { +async function showRenoteMenu() { if (props.mock) { return; } + const isLoggedIn = await pleaseLogin({ openOnRemote: pleaseLoginContext.value }); + if (!isLoggedIn) return; function getUnrenote(): MenuItem { return { @@ -649,7 +658,6 @@ function showRenoteMenu(): void { }; if (isMyRenote) { - pleaseLogin({ openOnRemote: pleaseLoginContext.value }); os.popupMenu([ renoteDetailsMenu, getCopyNoteLinkMenu(note, i18n.ts.copyLinkRenote), diff --git a/packages/frontend/src/components/MkNoteDetailed.vue b/packages/frontend/src/components/MkNoteDetailed.vue index 47bf365877..febf909f42 100644 --- a/packages/frontend/src/components/MkNoteDetailed.vue +++ b/packages/frontend/src/components/MkNoteDetailed.vue @@ -448,8 +448,10 @@ if (appearNote.reactionAcceptance === 'likeOnly') { }); } -function renote() { - pleaseLogin({ openOnRemote: pleaseLoginContext.value }); +async function renote() { + const isLoggedIn = await pleaseLogin({ openOnRemote: pleaseLoginContext.value }); + if (!isLoggedIn) return; + showMovedDialog(); const { menu } = getRenoteMenu({ note: note, renoteButton }); @@ -459,8 +461,10 @@ function renote() { subscribeManuallyToNoteCapture(); } -function reply(): void { - pleaseLogin({ openOnRemote: pleaseLoginContext.value }); +async function reply() { + const isLoggedIn = await pleaseLogin({ openOnRemote: pleaseLoginContext.value }); + if (!isLoggedIn) return; + showMovedDialog(); os.post({ reply: appearNote, @@ -470,8 +474,10 @@ function reply(): void { }); } -function react(): void { - pleaseLogin({ openOnRemote: pleaseLoginContext.value }); +async function react() { + const isLoggedIn = await pleaseLogin({ openOnRemote: pleaseLoginContext.value }); + if (!isLoggedIn) return; + showMovedDialog(); if (appearNote.reactionAcceptance === 'likeOnly') { sound.playMisskeySfx('reaction'); @@ -569,9 +575,12 @@ async function clip(): Promise { os.popupMenu(await getNoteClipMenu({ note: note }), clipButton.value).then(focus); } -function showRenoteMenu(): void { +async function showRenoteMenu() { if (!isMyRenote) return; - pleaseLogin({ openOnRemote: pleaseLoginContext.value }); + + const isLoggedIn = await pleaseLogin({ openOnRemote: pleaseLoginContext.value }); + if (!isLoggedIn) return; + os.popupMenu([{ text: i18n.ts.unrenote, icon: 'ti ti-trash', diff --git a/packages/frontend/src/components/MkPoll.vue b/packages/frontend/src/components/MkPoll.vue index 305e9b5c4f..31567d2b84 100644 --- a/packages/frontend/src/components/MkPoll.vue +++ b/packages/frontend/src/components/MkPoll.vue @@ -90,7 +90,8 @@ const pleaseLoginContext = computed(() => ({ const vote = async (id: number) => { if (props.readOnly || closed.value || isVoted.value) return; - pleaseLogin({ openOnRemote: pleaseLoginContext.value }); + const isLoggedIn = await pleaseLogin({ openOnRemote: pleaseLoginContext.value }); + if (!isLoggedIn) return; const { canceled } = await os.confirm({ type: 'question', diff --git a/packages/frontend/src/os.ts b/packages/frontend/src/os.ts index aafa1c4b21..59ed3dc948 100644 --- a/packages/frontend/src/os.ts +++ b/packages/frontend/src/os.ts @@ -709,8 +709,8 @@ export function contextMenu(items: MenuItem[], ev: MouseEvent): Promise { })); } -export function post(props: PostFormProps = {}): Promise { - pleaseLogin({ +export async function post(props: PostFormProps = {}): Promise { + const isLoggedIn = await pleaseLogin({ openOnRemote: (props.initialText || props.initialNote ? { type: 'share', params: { @@ -720,6 +720,7 @@ export function post(props: PostFormProps = {}): Promise { }, } : undefined), }); + if (!isLoggedIn) return; showMovedDialog(); return new Promise(resolve => { diff --git a/packages/frontend/src/pages/flash/flash.vue b/packages/frontend/src/pages/flash/flash.vue index efc9ee014f..f5e51dc72f 100644 --- a/packages/frontend/src/pages/flash/flash.vue +++ b/packages/frontend/src/pages/flash/flash.vue @@ -151,9 +151,11 @@ function shareWithNote() { }); } -function like() { +async function like() { if (!flash.value) return; - pleaseLogin(); + + const isLoggedIn = await pleaseLogin(); + if (!isLoggedIn) return; os.apiWithDialog('flash/like', { flashId: flash.value.id, @@ -165,7 +167,9 @@ function like() { async function unlike() { if (!flash.value) return; - pleaseLogin(); + + const isLoggedIn = await pleaseLogin(); + if (!isLoggedIn) return; const confirm = await os.confirm({ type: 'warning', diff --git a/packages/frontend/src/pages/reversi/index.vue b/packages/frontend/src/pages/reversi/index.vue index 0ae374649d..8438943126 100644 --- a/packages/frontend/src/pages/reversi/index.vue +++ b/packages/frontend/src/pages/reversi/index.vue @@ -197,7 +197,8 @@ async function matchHeatbeat() { } async function matchUser() { - pleaseLogin(); + const isLoggedIn = await pleaseLogin(); + if (!isLoggedIn) return; const user = await os.selectUser({ includeSelf: false, localOnly: true }); if (user == null) return; @@ -207,8 +208,9 @@ async function matchUser() { matchHeatbeat(); } -function matchAny(ev: MouseEvent) { - pleaseLogin(); +async function matchAny(ev: MouseEvent) { + const isLoggedIn = await pleaseLogin(); + if (!isLoggedIn) return; os.popupMenu([{ text: i18n.ts._reversi.allowIrregularRules, diff --git a/packages/frontend/src/utility/please-login.ts b/packages/frontend/src/utility/please-login.ts index 737e7d7c6e..8120a8d1af 100644 --- a/packages/frontend/src/utility/please-login.ts +++ b/packages/frontend/src/utility/please-login.ts @@ -48,8 +48,8 @@ export async function pleaseLogin(opts: { path?: string; message?: string; openOnRemote?: OpenOnRemoteOptions; -} = {}) { - if ($i) return; +} = {}): Promise { + if ($i != null) return true; let _openOnRemote: OpenOnRemoteOptions | undefined = undefined; @@ -71,5 +71,5 @@ export async function pleaseLogin(opts: { closed: () => dispose(), }); - throw new Error('signin required'); + return false; } -- cgit v1.2.3-freya From 9c225384541192bbd83da94ac2f6c09ade3a25e8 Mon Sep 17 00:00:00 2001 From: かっこかり <67428053+kakkokari-gtyih@users.noreply.github.com> Date: Fri, 2 Jan 2026 21:41:32 +0900 Subject: fix(frontend): ファイルタブのセンシティブメディアを開く際に確認ダイアログを出す設定が適用されない問題を修正 (#17019) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * fix(frontend): ファイルタブのセンシティブメディアを開く際に確認ダイアログを出す設定が適用されない問題を修正 * Update Changelog * refactor * Update Changelog --- CHANGELOG.md | 1 + packages/frontend/src/components/MkMediaAudio.vue | 12 +++----- packages/frontend/src/components/MkMediaBanner.vue | 15 ++++------ packages/frontend/src/components/MkMediaImage.vue | 13 ++++----- packages/frontend/src/components/MkMediaVideo.vue | 11 +++----- .../frontend/src/components/MkNoteMediaGrid.vue | 28 +++++++++++++----- packages/frontend/src/utility/sensitive-file.ts | 33 ++++++++++++++++++++++ 7 files changed, 73 insertions(+), 40 deletions(-) create mode 100644 packages/frontend/src/utility/sensitive-file.ts (limited to 'packages/frontend/src/utility') diff --git a/CHANGELOG.md b/CHANGELOG.md index e22dfba72a..669e6778ff 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,6 +15,7 @@ - Fix: ドライブクリーナーでファイルを削除しても画面に反映されない問題を修正 #16061 - Fix: 非ログイン時にログインを求めるダイアログが表示された後にダイアログのぼかしが解除されず操作不能になることがある問題を修正 - Fix: ドライブのソートが「登録日(昇順)」の場合に正しく動作しない問題を修正 +- Fix: ファイルタブのセンシティブメディアを開く際に確認ダイアログを出す設定が適用されない問題を修正 ### Server - Enhance: OAuthのクライアント情報取得(Client Information Discovery)において、IndieWeb Living Standard 11 July 2024で定義されているJSONドキュメント形式に対応しました diff --git a/packages/frontend/src/components/MkMediaAudio.vue b/packages/frontend/src/components/MkMediaAudio.vue index e3bb39549f..efcbf26a29 100644 --- a/packages/frontend/src/components/MkMediaAudio.vue +++ b/packages/frontend/src/components/MkMediaAudio.vue @@ -100,6 +100,7 @@ import { hms } from '@/filters/hms.js'; import MkMediaRange from '@/components/MkMediaRange.vue'; import { $i, iAmModerator } from '@/i.js'; import { prefer } from '@/preferences.js'; +import { canRevealFile, shouldHideFileByDefault } from '@/utility/sensitive-file.js'; const props = defineProps<{ audio: Misskey.entities.DriveFile; @@ -154,16 +155,11 @@ function hasFocus() { const playerEl = useTemplateRef('playerEl'); const audioEl = useTemplateRef('audioEl'); -// eslint-disable-next-line vue/no-setup-props-reactivity-loss -const hide = ref((prefer.s.nsfw === 'force' || prefer.s.dataSaver.media) ? true : (props.audio.isSensitive && prefer.s.nsfw !== 'ignore')); +const hide = ref(shouldHideFileByDefault(props.audio)); async function reveal() { - if (props.audio.isSensitive && prefer.s.confirmWhenRevealingSensitiveMedia) { - const { canceled } = await os.confirm({ - type: 'question', - text: i18n.ts.sensitiveMediaRevealConfirm, - }); - if (canceled) return; + if (!(await canRevealFile(props.audio))) { + return; } hide.value = false; diff --git a/packages/frontend/src/components/MkMediaBanner.vue b/packages/frontend/src/components/MkMediaBanner.vue index 7730e01a9f..fd86b61b87 100644 --- a/packages/frontend/src/components/MkMediaBanner.vue +++ b/packages/frontend/src/components/MkMediaBanner.vue @@ -6,7 +6,7 @@ SPDX-License-Identifier: AGPL-3.0-only