fix(frontend): ファイルタブのセンシティブメディアを開く際に確認ダイアログを出す設定が適用されない問題を修正 (#17019)
* fix(frontend): ファイルタブのセンシティブメディアを開く際に確認ダイアログを出す設定が適用されない問題を修正 * Update Changelog * refactor * Update Changelog
This commit is contained in:
parent
a1ba403f9a
commit
9c22538454
|
|
@ -15,6 +15,7 @@
|
||||||
- Fix: ドライブクリーナーでファイルを削除しても画面に反映されない問題を修正 #16061
|
- Fix: ドライブクリーナーでファイルを削除しても画面に反映されない問題を修正 #16061
|
||||||
- Fix: 非ログイン時にログインを求めるダイアログが表示された後にダイアログのぼかしが解除されず操作不能になることがある問題を修正
|
- Fix: 非ログイン時にログインを求めるダイアログが表示された後にダイアログのぼかしが解除されず操作不能になることがある問題を修正
|
||||||
- Fix: ドライブのソートが「登録日(昇順)」の場合に正しく動作しない問題を修正
|
- Fix: ドライブのソートが「登録日(昇順)」の場合に正しく動作しない問題を修正
|
||||||
|
- Fix: ファイルタブのセンシティブメディアを開く際に確認ダイアログを出す設定が適用されない問題を修正
|
||||||
|
|
||||||
### Server
|
### Server
|
||||||
- Enhance: OAuthのクライアント情報取得(Client Information Discovery)において、IndieWeb Living Standard 11 July 2024で定義されているJSONドキュメント形式に対応しました
|
- Enhance: OAuthのクライアント情報取得(Client Information Discovery)において、IndieWeb Living Standard 11 July 2024で定義されているJSONドキュメント形式に対応しました
|
||||||
|
|
|
||||||
|
|
@ -100,6 +100,7 @@ import { hms } from '@/filters/hms.js';
|
||||||
import MkMediaRange from '@/components/MkMediaRange.vue';
|
import MkMediaRange from '@/components/MkMediaRange.vue';
|
||||||
import { $i, iAmModerator } from '@/i.js';
|
import { $i, iAmModerator } from '@/i.js';
|
||||||
import { prefer } from '@/preferences.js';
|
import { prefer } from '@/preferences.js';
|
||||||
|
import { canRevealFile, shouldHideFileByDefault } from '@/utility/sensitive-file.js';
|
||||||
|
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
audio: Misskey.entities.DriveFile;
|
audio: Misskey.entities.DriveFile;
|
||||||
|
|
@ -154,16 +155,11 @@ function hasFocus() {
|
||||||
const playerEl = useTemplateRef('playerEl');
|
const playerEl = useTemplateRef('playerEl');
|
||||||
const audioEl = useTemplateRef('audioEl');
|
const audioEl = useTemplateRef('audioEl');
|
||||||
|
|
||||||
// eslint-disable-next-line vue/no-setup-props-reactivity-loss
|
const hide = ref(shouldHideFileByDefault(props.audio));
|
||||||
const hide = ref((prefer.s.nsfw === 'force' || prefer.s.dataSaver.media) ? true : (props.audio.isSensitive && prefer.s.nsfw !== 'ignore'));
|
|
||||||
|
|
||||||
async function reveal() {
|
async function reveal() {
|
||||||
if (props.audio.isSensitive && prefer.s.confirmWhenRevealingSensitiveMedia) {
|
if (!(await canRevealFile(props.audio))) {
|
||||||
const { canceled } = await os.confirm({
|
return;
|
||||||
type: 'question',
|
|
||||||
text: i18n.ts.sensitiveMediaRevealConfirm,
|
|
||||||
});
|
|
||||||
if (canceled) return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
hide.value = false;
|
hide.value = false;
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,7 @@ SPDX-License-Identifier: AGPL-3.0-only
|
||||||
<template>
|
<template>
|
||||||
<div :class="$style.root">
|
<div :class="$style.root">
|
||||||
<MkMediaAudio v-if="media.type.startsWith('audio') && media.type !== 'audio/midi'" :audio="media"/>
|
<MkMediaAudio v-if="media.type.startsWith('audio') && media.type !== 'audio/midi'" :audio="media"/>
|
||||||
<div v-else-if="media.isSensitive && hide" :class="$style.sensitive" @click="reveal">
|
<div v-else-if="hide" :class="$style.sensitive" @click="reveal">
|
||||||
<span style="font-size: 1.6em;"><i class="ti ti-alert-triangle"></i></span>
|
<span style="font-size: 1.6em;"><i class="ti ti-alert-triangle"></i></span>
|
||||||
<b>{{ i18n.ts.sensitive }}</b>
|
<b>{{ i18n.ts.sensitive }}</b>
|
||||||
<span>{{ i18n.ts.clickToShow }}</span>
|
<span>{{ i18n.ts.clickToShow }}</span>
|
||||||
|
|
@ -27,23 +27,18 @@ SPDX-License-Identifier: AGPL-3.0-only
|
||||||
import { ref } from 'vue';
|
import { ref } from 'vue';
|
||||||
import * as Misskey from 'misskey-js';
|
import * as Misskey from 'misskey-js';
|
||||||
import { i18n } from '@/i18n.js';
|
import { i18n } from '@/i18n.js';
|
||||||
import * as os from '@/os.js';
|
|
||||||
import MkMediaAudio from '@/components/MkMediaAudio.vue';
|
import MkMediaAudio from '@/components/MkMediaAudio.vue';
|
||||||
import { prefer } from '@/preferences.js';
|
import { shouldHideFileByDefault, canRevealFile } from '@/utility/sensitive-file.js';
|
||||||
|
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
media: Misskey.entities.DriveFile;
|
media: Misskey.entities.DriveFile;
|
||||||
}>();
|
}>();
|
||||||
|
|
||||||
const hide = ref(true);
|
const hide = ref(shouldHideFileByDefault(props.media));
|
||||||
|
|
||||||
async function reveal() {
|
async function reveal() {
|
||||||
if (props.media.isSensitive && prefer.s.confirmWhenRevealingSensitiveMedia) {
|
if (!(await canRevealFile(props.media))) {
|
||||||
const { canceled } = await os.confirm({
|
return;
|
||||||
type: 'question',
|
|
||||||
text: i18n.ts.sensitiveMediaRevealConfirm,
|
|
||||||
});
|
|
||||||
if (canceled) return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
hide.value = false;
|
hide.value = false;
|
||||||
|
|
|
||||||
|
|
@ -77,6 +77,7 @@ import { i18n } from '@/i18n.js';
|
||||||
import * as os from '@/os.js';
|
import * as os from '@/os.js';
|
||||||
import { $i, iAmModerator } from '@/i.js';
|
import { $i, iAmModerator } from '@/i.js';
|
||||||
import { prefer } from '@/preferences.js';
|
import { prefer } from '@/preferences.js';
|
||||||
|
import { shouldHideFileByDefault, canRevealFile } from '@/utility/sensitive-file.js';
|
||||||
|
|
||||||
const props = withDefaults(defineProps<{
|
const props = withDefaults(defineProps<{
|
||||||
image: Misskey.entities.DriveFile;
|
image: Misskey.entities.DriveFile;
|
||||||
|
|
@ -106,12 +107,8 @@ async function reveal(ev: MouseEvent) {
|
||||||
|
|
||||||
if (hide.value) {
|
if (hide.value) {
|
||||||
ev.stopPropagation();
|
ev.stopPropagation();
|
||||||
if (props.image.isSensitive && prefer.s.confirmWhenRevealingSensitiveMedia) {
|
if (!(await canRevealFile(props.image))) {
|
||||||
const { canceled } = await os.confirm({
|
return;
|
||||||
type: 'question',
|
|
||||||
text: i18n.ts.sensitiveMediaRevealConfirm,
|
|
||||||
});
|
|
||||||
if (canceled) return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
hide.value = false;
|
hide.value = false;
|
||||||
|
|
@ -119,8 +116,8 @@ async function reveal(ev: MouseEvent) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Plugin:register_note_view_interruptor を使って書き換えられる可能性があるためwatchする
|
// Plugin:register_note_view_interruptor を使って書き換えられる可能性があるためwatchする
|
||||||
watch(() => props.image, () => {
|
watch(() => props.image, (newImage) => {
|
||||||
hide.value = (prefer.s.nsfw === 'force' || prefer.s.dataSaver.media) ? true : (props.image.isSensitive && prefer.s.nsfw !== 'ignore');
|
hide.value = shouldHideFileByDefault(newImage);
|
||||||
}, {
|
}, {
|
||||||
deep: true,
|
deep: true,
|
||||||
immediate: true,
|
immediate: true,
|
||||||
|
|
|
||||||
|
|
@ -124,6 +124,7 @@ import hasAudio from '@/utility/media-has-audio.js';
|
||||||
import MkMediaRange from '@/components/MkMediaRange.vue';
|
import MkMediaRange from '@/components/MkMediaRange.vue';
|
||||||
import { $i, iAmModerator } from '@/i.js';
|
import { $i, iAmModerator } from '@/i.js';
|
||||||
import { prefer } from '@/preferences.js';
|
import { prefer } from '@/preferences.js';
|
||||||
|
import { shouldHideFileByDefault, canRevealFile } from '@/utility/sensitive-file.js';
|
||||||
|
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
video: Misskey.entities.DriveFile;
|
video: Misskey.entities.DriveFile;
|
||||||
|
|
@ -176,15 +177,11 @@ function hasFocus() {
|
||||||
}
|
}
|
||||||
|
|
||||||
// eslint-disable-next-line vue/no-setup-props-reactivity-loss
|
// eslint-disable-next-line vue/no-setup-props-reactivity-loss
|
||||||
const hide = ref((prefer.s.nsfw === 'force' || prefer.s.dataSaver.media) ? true : (props.video.isSensitive && prefer.s.nsfw !== 'ignore'));
|
const hide = ref(shouldHideFileByDefault(props.video));
|
||||||
|
|
||||||
async function reveal() {
|
async function reveal() {
|
||||||
if (props.video.isSensitive && prefer.s.confirmWhenRevealingSensitiveMedia) {
|
if (!(await canRevealFile(props.video))) {
|
||||||
const { canceled } = await os.confirm({
|
return;
|
||||||
type: 'question',
|
|
||||||
text: i18n.ts.sensitiveMediaRevealConfirm,
|
|
||||||
});
|
|
||||||
if (canceled) return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
hide.value = false;
|
hide.value = false;
|
||||||
|
|
|
||||||
|
|
@ -6,14 +6,9 @@ SPDX-License-Identifier: AGPL-3.0-only
|
||||||
<template>
|
<template>
|
||||||
<template v-for="file in note.files">
|
<template v-for="file in note.files">
|
||||||
<div
|
<div
|
||||||
v-if="(((
|
v-if="isHiding(file)"
|
||||||
(prefer.s.nsfw === 'force' || file.isSensitive) &&
|
|
||||||
prefer.s.nsfw !== 'ignore'
|
|
||||||
) || (prefer.s.dataSaver.media && file.type.startsWith('image/'))) &&
|
|
||||||
!showingFiles.has(file.id)
|
|
||||||
)"
|
|
||||||
:class="[$style.filePreview, { [$style.square]: square }]"
|
:class="[$style.filePreview, { [$style.square]: square }]"
|
||||||
@click="showingFiles.add(file.id)"
|
@click="reveal(file)"
|
||||||
>
|
>
|
||||||
<MkDriveFileThumbnail
|
<MkDriveFileThumbnail
|
||||||
:file="file"
|
:file="file"
|
||||||
|
|
@ -49,6 +44,7 @@ import * as Misskey from 'misskey-js';
|
||||||
import { notePage } from '@/filters/note.js';
|
import { notePage } from '@/filters/note.js';
|
||||||
import { i18n } from '@/i18n.js';
|
import { i18n } from '@/i18n.js';
|
||||||
import { prefer } from '@/preferences.js';
|
import { prefer } from '@/preferences.js';
|
||||||
|
import { shouldHideFileByDefault, canRevealFile } from '@/utility/sensitive-file.js';
|
||||||
import bytes from '@/filters/bytes.js';
|
import bytes from '@/filters/bytes.js';
|
||||||
|
|
||||||
import MkDriveFileThumbnail from '@/components/MkDriveFileThumbnail.vue';
|
import MkDriveFileThumbnail from '@/components/MkDriveFileThumbnail.vue';
|
||||||
|
|
@ -59,6 +55,24 @@ defineProps<{
|
||||||
}>();
|
}>();
|
||||||
|
|
||||||
const showingFiles = ref<Set<string>>(new Set());
|
const showingFiles = ref<Set<string>>(new Set());
|
||||||
|
|
||||||
|
function isHiding(file: Misskey.entities.DriveFile) {
|
||||||
|
if (shouldHideFileByDefault(file) && !showingFiles.value.has(file.id)) {
|
||||||
|
if (!file.isSensitive && !file.type.startsWith('image/')) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
async function reveal(file: Misskey.entities.DriveFile) {
|
||||||
|
if (!(await canRevealFile(file))) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
showingFiles.value.add(file.id);
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss" module>
|
<style lang="scss" module>
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,33 @@
|
||||||
|
/*
|
||||||
|
* SPDX-FileCopyrightText: syuilo and misskey-project
|
||||||
|
* SPDX-License-Identifier: AGPL-3.0-only
|
||||||
|
*/
|
||||||
|
|
||||||
|
import * as Misskey from 'misskey-js';
|
||||||
|
import * as os from '@/os.js';
|
||||||
|
import { prefer } from '@/preferences.js';
|
||||||
|
import { i18n } from '@/i18n.js';
|
||||||
|
|
||||||
|
export function shouldHideFileByDefault(file: Misskey.entities.DriveFile): boolean {
|
||||||
|
if (prefer.s.nsfw === 'force' || prefer.s.dataSaver.media) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (file.isSensitive && prefer.s.nsfw !== 'ignore') {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function canRevealFile(file: Misskey.entities.DriveFile): Promise<boolean> {
|
||||||
|
if (file.isSensitive && prefer.s.confirmWhenRevealingSensitiveMedia) {
|
||||||
|
const { canceled } = await os.confirm({
|
||||||
|
type: 'question',
|
||||||
|
text: i18n.ts.sensitiveMediaRevealConfirm,
|
||||||
|
});
|
||||||
|
if (canceled) return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue