feat: require double click for sensitive images
This commit is contained in:
parent
8bd86ce456
commit
7d4383c449
6 changed files with 83 additions and 10 deletions
|
@ -616,7 +616,7 @@ addedRelays: "추가된 릴레이"
|
||||||
serviceworkerInfo: "푸시 알림을 수행하려면 활성화해야 합니다."
|
serviceworkerInfo: "푸시 알림을 수행하려면 활성화해야 합니다."
|
||||||
deletedNote: "삭제된 노트"
|
deletedNote: "삭제된 노트"
|
||||||
invisibleNote: "비공개 노트"
|
invisibleNote: "비공개 노트"
|
||||||
enableInfiniteScroll: "자동으로 더 보기"
|
enableInfiniteScroll: "스크롤해서 더 보기"
|
||||||
visibility: "공개 범위"
|
visibility: "공개 범위"
|
||||||
poll: "투표"
|
poll: "투표"
|
||||||
useCw: "내용 숨기기"
|
useCw: "내용 숨기기"
|
||||||
|
@ -1227,7 +1227,7 @@ overwriteContentConfirm: "현재 내용을 덮어쓰기 합니다. 계속 진행
|
||||||
seasonalScreenEffect: "계절에 따른 효과 보이기"
|
seasonalScreenEffect: "계절에 따른 효과 보이기"
|
||||||
decorate: "장식하기"
|
decorate: "장식하기"
|
||||||
addMfmFunction: "장식 추가하기"
|
addMfmFunction: "장식 추가하기"
|
||||||
enableQuickAddMfmFunction: "상급자용 MFM 선택기 표시하기"
|
enableQuickAddMfmFunction: "상급자용 MFM 선택기 표시"
|
||||||
bubbleGame: "버블 게임"
|
bubbleGame: "버블 게임"
|
||||||
sfx: "효과음"
|
sfx: "효과음"
|
||||||
soundWillBePlayed: "소리가 재생됩니다"
|
soundWillBePlayed: "소리가 재생됩니다"
|
||||||
|
@ -1242,7 +1242,7 @@ backToTitle: "타이틀로 가기"
|
||||||
hemisphere: "거주 지역"
|
hemisphere: "거주 지역"
|
||||||
withSensitive: "민감한 파일이 포함된 노트 보기"
|
withSensitive: "민감한 파일이 포함된 노트 보기"
|
||||||
userSaysSomethingSensitive: "{name} 같은 민감한 파일이 포함된 글"
|
userSaysSomethingSensitive: "{name} 같은 민감한 파일이 포함된 글"
|
||||||
enableHorizontalSwipe: "스와이프하여 탭 전환"
|
enableHorizontalSwipe: "밀어서 탭 간 전환하기"
|
||||||
loading: "불러오는 중"
|
loading: "불러오는 중"
|
||||||
surrender: "그만두기"
|
surrender: "그만두기"
|
||||||
gameRetry: "다시 시도"
|
gameRetry: "다시 시도"
|
||||||
|
@ -1252,6 +1252,8 @@ useBackupCode: "백업 코드 사용"
|
||||||
launchApp: "앱 실행"
|
launchApp: "앱 실행"
|
||||||
useNativeUIForVideoAudioPlayer: "브라우저 UI에서 미디어 재생"
|
useNativeUIForVideoAudioPlayer: "브라우저 UI에서 미디어 재생"
|
||||||
here: "여기"
|
here: "여기"
|
||||||
|
hideMutedNotes: "단어 뮤트된 노트를 완전히 숨기기"
|
||||||
|
alwaysConfirmFollow: "팔로우할 때 항상 확인하기"
|
||||||
credits: "엔딩 크레딧"
|
credits: "엔딩 크레딧"
|
||||||
timeWillCome: "언젠가 이 칸에 당신의 이름이 쓰여지는 날이 올까요?"
|
timeWillCome: "언젠가 이 칸에 당신의 이름이 쓰여지는 날이 올까요?"
|
||||||
thankYou: "오스카는 당신과 함께 서핑할 것입니다. 언제까지고."
|
thankYou: "오스카는 당신과 함께 서핑할 것입니다. 언제까지고."
|
||||||
|
|
|
@ -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="showHiddenContent">
|
<div v-else-if="media.isSensitive && hide" :class="$style.sensitive" @click="showHiddenContent" @dblclick="showHiddenContentDouble">
|
||||||
<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>
|
||||||
|
@ -30,6 +30,7 @@ import { i18n } from '@/i18n.js';
|
||||||
import MkMediaAudio from '@/components/MkMediaAudio.vue';
|
import MkMediaAudio from '@/components/MkMediaAudio.vue';
|
||||||
import { pleaseLogin } from '@/scripts/please-login.js';
|
import { pleaseLogin } from '@/scripts/please-login.js';
|
||||||
import { $i } from '@/account.js';
|
import { $i } from '@/account.js';
|
||||||
|
import { defaultStore } from '@/store.js';
|
||||||
|
|
||||||
const props = withDefaults(defineProps<{
|
const props = withDefaults(defineProps<{
|
||||||
media: Misskey.entities.DriveFile;
|
media: Misskey.entities.DriveFile;
|
||||||
|
@ -40,6 +41,25 @@ const audioEl = shallowRef<HTMLAudioElement>();
|
||||||
const hide = ref(true);
|
const hide = ref(true);
|
||||||
|
|
||||||
function showHiddenContent(ev: MouseEvent) {
|
function showHiddenContent(ev: MouseEvent) {
|
||||||
|
if (defaultStore.state.sensitiveDoubleClickRequired) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (props.media.isSensitive && !$i) {
|
||||||
|
ev.preventDefault();
|
||||||
|
ev.stopPropagation();
|
||||||
|
pleaseLogin();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hide.value) {
|
||||||
|
ev.preventDefault();
|
||||||
|
ev.stopPropagation();
|
||||||
|
hide.value = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function showHiddenContentDouble(ev: MouseEvent) {
|
||||||
if (props.media.isSensitive && !$i) {
|
if (props.media.isSensitive && !$i) {
|
||||||
ev.preventDefault();
|
ev.preventDefault();
|
||||||
ev.stopPropagation();
|
ev.stopPropagation();
|
||||||
|
|
|
@ -4,7 +4,7 @@ SPDX-License-Identifier: AGPL-3.0-only
|
||||||
-->
|
-->
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div :class="[hide ? $style.hidden : $style.visible, (image.isSensitive && defaultStore.state.highlightSensitiveMedia) && $style.sensitive]" :style="darkMode ? '--c: rgb(255 255 255 / 2%);' : '--c: rgb(0 0 0 / 2%);'" @click="showHiddenContent">
|
<div :class="[hide ? $style.hidden : $style.visible, (image.isSensitive && defaultStore.state.highlightSensitiveMedia) && $style.sensitive]" :style="darkMode ? '--c: rgb(255 255 255 / 2%);' : '--c: rgb(0 0 0 / 2%);'" @click="showHiddenContent" @dblclick="showHiddenContentDouble">
|
||||||
<component
|
<component
|
||||||
:is="(image.isSensitive && !$i) || disableImageLink ? 'div' : 'a'"
|
:is="(image.isSensitive && !$i) || disableImageLink ? 'div' : 'a'"
|
||||||
v-bind="(image.isSensitive && !$i) || disableImageLink ? {
|
v-bind="(image.isSensitive && !$i) || disableImageLink ? {
|
||||||
|
@ -135,6 +135,29 @@ function showHiddenContent(ev: MouseEvent) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (defaultStore.state.sensitiveDoubleClickRequired) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (props.image.isSensitive && !$i) {
|
||||||
|
ev.preventDefault();
|
||||||
|
ev.stopPropagation();
|
||||||
|
pleaseLogin();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hide.value) {
|
||||||
|
ev.preventDefault();
|
||||||
|
ev.stopPropagation();
|
||||||
|
hide.value = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function showHiddenContentDouble(ev: MouseEvent) {
|
||||||
|
if (!props.controls) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (props.image.isSensitive && !$i) {
|
if (props.image.isSensitive && !$i) {
|
||||||
ev.preventDefault();
|
ev.preventDefault();
|
||||||
ev.stopPropagation();
|
ev.stopPropagation();
|
||||||
|
|
|
@ -18,7 +18,7 @@ SPDX-License-Identifier: AGPL-3.0-only
|
||||||
@contextmenu.stop
|
@contextmenu.stop
|
||||||
@keydown.stop
|
@keydown.stop
|
||||||
>
|
>
|
||||||
<button v-if="hide" :class="$style.hidden" @click="showHiddenContent">
|
<button v-if="hide" :class="$style.hidden" @click="showHiddenContent" @dblclick="showHiddenContentDouble">
|
||||||
<div :class="$style.hiddenTextWrapper">
|
<div :class="$style.hiddenTextWrapper">
|
||||||
<b v-if="video.isSensitive" style="display: block;"><i class="ti ti-eye-exclamation"></i> {{ i18n.ts.sensitive }}{{ defaultStore.state.dataSaver.media ? ` (${i18n.ts.video}${video.size ? ' ' + bytes(video.size) : ''})` : '' }}</b>
|
<b v-if="video.isSensitive" style="display: block;"><i class="ti ti-eye-exclamation"></i> {{ i18n.ts.sensitive }}{{ defaultStore.state.dataSaver.media ? ` (${i18n.ts.video}${video.size ? ' ' + bytes(video.size) : ''})` : '' }}</b>
|
||||||
<b v-else style="display: block;"><i class="ti ti-movie"></i> {{ defaultStore.state.dataSaver.media && video.size ? bytes(video.size) : i18n.ts.video }}</b>
|
<b v-else style="display: block;"><i class="ti ti-movie"></i> {{ defaultStore.state.dataSaver.media && video.size ? bytes(video.size) : i18n.ts.video }}</b>
|
||||||
|
@ -255,6 +255,25 @@ function showMenu(ev: MouseEvent) {
|
||||||
}
|
}
|
||||||
|
|
||||||
function showHiddenContent(ev: MouseEvent) {
|
function showHiddenContent(ev: MouseEvent) {
|
||||||
|
if (defaultStore.state.sensitiveDoubleClickRequired) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (props.video.isSensitive && !$i) {
|
||||||
|
ev.preventDefault();
|
||||||
|
ev.stopPropagation();
|
||||||
|
pleaseLogin();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hide.value) {
|
||||||
|
ev.preventDefault();
|
||||||
|
ev.stopPropagation();
|
||||||
|
hide.value = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function showHiddenContentDouble(ev: MouseEvent) {
|
||||||
if (props.video.isSensitive && !$i) {
|
if (props.video.isSensitive && !$i) {
|
||||||
ev.preventDefault();
|
ev.preventDefault();
|
||||||
ev.stopPropagation();
|
ev.stopPropagation();
|
||||||
|
|
|
@ -170,6 +170,7 @@ SPDX-License-Identifier: AGPL-3.0-only
|
||||||
<MkSwitch v-model="disableStreamingTimeline">{{ i18n.ts.disableStreamingTimeline }}</MkSwitch>
|
<MkSwitch v-model="disableStreamingTimeline">{{ i18n.ts.disableStreamingTimeline }}</MkSwitch>
|
||||||
<MkSwitch v-model="enableHorizontalSwipe">{{ i18n.ts.enableHorizontalSwipe }}</MkSwitch>
|
<MkSwitch v-model="enableHorizontalSwipe">{{ i18n.ts.enableHorizontalSwipe }}</MkSwitch>
|
||||||
<MkSwitch v-model="alwaysConfirmFollow">{{ i18n.ts.alwaysConfirmFollow }}</MkSwitch>
|
<MkSwitch v-model="alwaysConfirmFollow">{{ i18n.ts.alwaysConfirmFollow }}</MkSwitch>
|
||||||
|
<MkSwitch v-model="sensitiveDoubleClickRequired">{{ i18n.ts.sensitiveDoubleClickRequired }}</MkSwitch>
|
||||||
</div>
|
</div>
|
||||||
<MkSelect v-model="serverDisconnectedBehavior">
|
<MkSelect v-model="serverDisconnectedBehavior">
|
||||||
<template #label>{{ i18n.ts.whenServerDisconnected }}</template>
|
<template #label>{{ i18n.ts.whenServerDisconnected }}</template>
|
||||||
|
|
|
@ -80,10 +80,6 @@ export const defaultStore = markRaw(new Storage('base', {
|
||||||
where: 'account',
|
where: 'account',
|
||||||
default: true,
|
default: true,
|
||||||
},
|
},
|
||||||
hideDirectMessages: {
|
|
||||||
where: 'deviceAccount',
|
|
||||||
default: false,
|
|
||||||
},
|
|
||||||
showFullAcct: {
|
showFullAcct: {
|
||||||
where: 'account',
|
where: 'account',
|
||||||
default: false,
|
default: false,
|
||||||
|
@ -160,6 +156,14 @@ export const defaultStore = markRaw(new Storage('base', {
|
||||||
where: 'deviceAccount',
|
where: 'deviceAccount',
|
||||||
default: false,
|
default: false,
|
||||||
},
|
},
|
||||||
|
hideSensitiveInformation: {
|
||||||
|
where: 'device',
|
||||||
|
default: false,
|
||||||
|
},
|
||||||
|
hideDirectMessages: {
|
||||||
|
where: 'device',
|
||||||
|
default: false,
|
||||||
|
},
|
||||||
showPreview: {
|
showPreview: {
|
||||||
where: 'device',
|
where: 'device',
|
||||||
default: false,
|
default: false,
|
||||||
|
@ -218,6 +222,10 @@ export const defaultStore = markRaw(new Storage('base', {
|
||||||
where: 'device',
|
where: 'device',
|
||||||
default: true,
|
default: true,
|
||||||
},
|
},
|
||||||
|
sensitiveDoubleClickRequired: {
|
||||||
|
where: 'device',
|
||||||
|
default: false,
|
||||||
|
},
|
||||||
animation: {
|
animation: {
|
||||||
where: 'device',
|
where: 'device',
|
||||||
default: !window.matchMedia('(prefers-reduced-motion)').matches,
|
default: !window.matchMedia('(prefers-reduced-motion)').matches,
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue