センシティブなファイルを選択できないように
This commit is contained in:
parent
fafe980315
commit
16e92e6447
|
@ -4936,6 +4936,15 @@ export interface Locale extends ILocale {
|
||||||
* 動画・音声の再生にブラウザのUIを使用する
|
* 動画・音声の再生にブラウザのUIを使用する
|
||||||
*/
|
*/
|
||||||
"useNativeUIForVideoAudioPlayer": string;
|
"useNativeUIForVideoAudioPlayer": string;
|
||||||
|
/**
|
||||||
|
* センシティブなメディアは選択できません
|
||||||
|
*/
|
||||||
|
"cannotSelectSensitiveMedia": string;
|
||||||
|
/**
|
||||||
|
* 自分でセンシティブ設定を行っていないのにこのエラーが出ている場合、自動判定によりセンシティブなメディアとされている可能性があります。
|
||||||
|
* サーバーの規則に照らして不要な場合は、ファイルのセンシティブ設定を解除してもう一度お試しください。
|
||||||
|
*/
|
||||||
|
"cannotSelectSensitiveMediaDescription": string;
|
||||||
"_bubbleGame": {
|
"_bubbleGame": {
|
||||||
/**
|
/**
|
||||||
* 遊び方
|
* 遊び方
|
||||||
|
|
|
@ -1230,6 +1230,8 @@ useTotp: "ワンタイムパスワードを使う"
|
||||||
useBackupCode: "バックアップコードを使う"
|
useBackupCode: "バックアップコードを使う"
|
||||||
launchApp: "アプリを起動"
|
launchApp: "アプリを起動"
|
||||||
useNativeUIForVideoAudioPlayer: "動画・音声の再生にブラウザのUIを使用する"
|
useNativeUIForVideoAudioPlayer: "動画・音声の再生にブラウザのUIを使用する"
|
||||||
|
cannotSelectSensitiveMedia: "センシティブなメディアは選択できません"
|
||||||
|
cannotSelectSensitiveMediaDescription: "自分でセンシティブ設定を行っていないのにこのエラーが出ている場合、自動判定によりセンシティブなメディアとされている可能性があります。\nサーバーの規則に照らして不要な場合は、ファイルのセンシティブ設定を解除してもう一度お試しください。"
|
||||||
|
|
||||||
_bubbleGame:
|
_bubbleGame:
|
||||||
howToPlay: "遊び方"
|
howToPlay: "遊び方"
|
||||||
|
|
|
@ -5,7 +5,7 @@ SPDX-License-Identifier: AGPL-3.0-only
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div
|
<div
|
||||||
:class="[$style.root, { [$style.isSelected]: isSelected }]"
|
:class="[$style.root, { [$style.isSelected]: isSelected, [$style.isDisabled]: isDisabled }]"
|
||||||
draggable="true"
|
draggable="true"
|
||||||
:title="title"
|
:title="title"
|
||||||
@click="onClick"
|
@click="onClick"
|
||||||
|
@ -55,9 +55,11 @@ const props = withDefaults(defineProps<{
|
||||||
file: Misskey.entities.DriveFile;
|
file: Misskey.entities.DriveFile;
|
||||||
folder: Misskey.entities.DriveFolder | null;
|
folder: Misskey.entities.DriveFolder | null;
|
||||||
isSelected?: boolean;
|
isSelected?: boolean;
|
||||||
|
isDisabled?: boolean;
|
||||||
selectMode?: boolean;
|
selectMode?: boolean;
|
||||||
}>(), {
|
}>(), {
|
||||||
isSelected: false,
|
isSelected: false,
|
||||||
|
isDisabled: false,
|
||||||
selectMode: false,
|
selectMode: false,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -72,6 +74,8 @@ const isDragging = ref(false);
|
||||||
const title = computed(() => `${props.file.name}\n${props.file.type} ${bytes(props.file.size)}`);
|
const title = computed(() => `${props.file.name}\n${props.file.type} ${bytes(props.file.size)}`);
|
||||||
|
|
||||||
function onClick(ev: MouseEvent) {
|
function onClick(ev: MouseEvent) {
|
||||||
|
if (props.isDisabled) return;
|
||||||
|
|
||||||
if (props.selectMode) {
|
if (props.selectMode) {
|
||||||
emit('chosen', props.file);
|
emit('chosen', props.file);
|
||||||
} else {
|
} else {
|
||||||
|
@ -88,6 +92,8 @@ function onContextmenu(ev: MouseEvent) {
|
||||||
}
|
}
|
||||||
|
|
||||||
function onDragstart(ev: DragEvent) {
|
function onDragstart(ev: DragEvent) {
|
||||||
|
if (props.isDisabled) return;
|
||||||
|
|
||||||
if (ev.dataTransfer) {
|
if (ev.dataTransfer) {
|
||||||
ev.dataTransfer.effectAllowed = 'move';
|
ev.dataTransfer.effectAllowed = 'move';
|
||||||
ev.dataTransfer.setData(_DATA_TRANSFER_DRIVE_FILE_, JSON.stringify(props.file));
|
ev.dataTransfer.setData(_DATA_TRANSFER_DRIVE_FILE_, JSON.stringify(props.file));
|
||||||
|
@ -173,6 +179,12 @@ function onDragend() {
|
||||||
color: #fff;
|
color: #fff;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&.isDisabled {
|
||||||
|
opacity: 0.5;
|
||||||
|
pointer-events: none;
|
||||||
|
cursor: not-allowed;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.label {
|
.label {
|
||||||
|
|
|
@ -73,6 +73,7 @@ SPDX-License-Identifier: AGPL-3.0-only
|
||||||
:folder="folder"
|
:folder="folder"
|
||||||
:selectMode="select === 'file'"
|
:selectMode="select === 'file'"
|
||||||
:isSelected="selectedFiles.some(x => x.id === file.id)"
|
:isSelected="selectedFiles.some(x => x.id === file.id)"
|
||||||
|
:isDisabled="excludeSensitive && file.isSensitive"
|
||||||
@chosen="chooseFile"
|
@chosen="chooseFile"
|
||||||
@dragstart="isDragSource = true"
|
@dragstart="isDragSource = true"
|
||||||
@dragend="isDragSource = false"
|
@dragend="isDragSource = false"
|
||||||
|
@ -114,9 +115,11 @@ const props = withDefaults(defineProps<{
|
||||||
initialFolder?: Misskey.entities.DriveFolder;
|
initialFolder?: Misskey.entities.DriveFolder;
|
||||||
type?: string;
|
type?: string;
|
||||||
multiple?: boolean;
|
multiple?: boolean;
|
||||||
|
excludeSensitive?: boolean;
|
||||||
select?: 'file' | 'folder' | null;
|
select?: 'file' | 'folder' | null;
|
||||||
}>(), {
|
}>(), {
|
||||||
multiple: false,
|
multiple: false,
|
||||||
|
excludeSensitive: false,
|
||||||
select: null,
|
select: null,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -19,7 +19,7 @@ SPDX-License-Identifier: AGPL-3.0-only
|
||||||
{{ multiple ? ((type === 'file') ? i18n.ts.selectFiles : i18n.ts.selectFolders) : ((type === 'file') ? i18n.ts.selectFile : i18n.ts.selectFolder) }}
|
{{ multiple ? ((type === 'file') ? i18n.ts.selectFiles : i18n.ts.selectFolders) : ((type === 'file') ? i18n.ts.selectFile : i18n.ts.selectFolder) }}
|
||||||
<span v-if="selected.length > 0" style="margin-left: 8px; opacity: 0.5;">({{ number(selected.length) }})</span>
|
<span v-if="selected.length > 0" style="margin-left: 8px; opacity: 0.5;">({{ number(selected.length) }})</span>
|
||||||
</template>
|
</template>
|
||||||
<XDrive :multiple="multiple" :select="type" @changeSelection="onChangeSelection" @selected="ok()"/>
|
<XDrive :multiple="multiple" :excludeSensitive="excludeSensitive" :select="type" @changeSelection="onChangeSelection" @selected="ok()"/>
|
||||||
</MkModalWindow>
|
</MkModalWindow>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
@ -34,6 +34,7 @@ import { i18n } from '@/i18n.js';
|
||||||
withDefaults(defineProps<{
|
withDefaults(defineProps<{
|
||||||
type?: 'file' | 'folder';
|
type?: 'file' | 'folder';
|
||||||
multiple: boolean;
|
multiple: boolean;
|
||||||
|
excludeSensitive: boolean;
|
||||||
}>(), {
|
}>(), {
|
||||||
type: 'file',
|
type: 'file',
|
||||||
});
|
});
|
||||||
|
|
|
@ -541,11 +541,12 @@ export async function selectUser(opts: { includeSelf?: boolean; localOnly?: bool
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function selectDriveFile(multiple: boolean): Promise<Misskey.entities.DriveFile[]> {
|
export async function selectDriveFile(multiple: boolean, excludeSensitive: boolean): Promise<Misskey.entities.DriveFile[]> {
|
||||||
return new Promise(resolve => {
|
return new Promise(resolve => {
|
||||||
popup(defineAsyncComponent(() => import('@/components/MkDriveSelectDialog.vue')), {
|
popup(defineAsyncComponent(() => import('@/components/MkDriveSelectDialog.vue')), {
|
||||||
type: 'file',
|
type: 'file',
|
||||||
multiple,
|
multiple,
|
||||||
|
excludeSensitive,
|
||||||
}, {
|
}, {
|
||||||
done: files => {
|
done: files => {
|
||||||
if (files) {
|
if (files) {
|
||||||
|
|
|
@ -204,7 +204,7 @@ function save() {
|
||||||
}
|
}
|
||||||
|
|
||||||
function changeAvatar(ev) {
|
function changeAvatar(ev) {
|
||||||
selectFile(ev.currentTarget ?? ev.target, i18n.ts.avatar).then(async (file) => {
|
selectFile(ev.currentTarget ?? ev.target, i18n.ts.avatar, true).then(async (file) => {
|
||||||
let originalOrCropped = file;
|
let originalOrCropped = file;
|
||||||
|
|
||||||
const { canceled } = await os.confirm({
|
const { canceled } = await os.confirm({
|
||||||
|
@ -231,7 +231,7 @@ function changeAvatar(ev) {
|
||||||
}
|
}
|
||||||
|
|
||||||
function changeBanner(ev) {
|
function changeBanner(ev) {
|
||||||
selectFile(ev.currentTarget ?? ev.target, i18n.ts.banner).then(async (file) => {
|
selectFile(ev.currentTarget ?? ev.target, i18n.ts.banner, true).then(async (file) => {
|
||||||
let originalOrCropped = file;
|
let originalOrCropped = file;
|
||||||
|
|
||||||
const { canceled } = await os.confirm({
|
const { canceled } = await os.confirm({
|
||||||
|
|
|
@ -39,9 +39,9 @@ export function chooseFileFromPc(multiple: boolean, keepOriginal = false): Promi
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
export function chooseFileFromDrive(multiple: boolean): Promise<Misskey.entities.DriveFile[]> {
|
export function chooseFileFromDrive(multiple: boolean, excludeSensitive: boolean): Promise<Misskey.entities.DriveFile[]> {
|
||||||
return new Promise((res, rej) => {
|
return new Promise((res, rej) => {
|
||||||
os.selectDriveFile(multiple).then(files => {
|
os.selectDriveFile(multiple, excludeSensitive).then(files => {
|
||||||
res(files);
|
res(files);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -80,10 +80,23 @@ export function chooseFileFromUrl(): Promise<Misskey.entities.DriveFile> {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function select(src: any, label: string | null, multiple: boolean): Promise<Misskey.entities.DriveFile[]> {
|
function select(src: any, label: string | null, multiple: boolean, excludeSensitive: boolean): Promise<Misskey.entities.DriveFile[]> {
|
||||||
return new Promise((res, rej) => {
|
return new Promise((res, rej) => {
|
||||||
const keepOriginal = ref(defaultStore.state.keepOriginalUploading);
|
const keepOriginal = ref(defaultStore.state.keepOriginalUploading);
|
||||||
|
|
||||||
|
function _resolve(files: Misskey.entities.DriveFile[]) {
|
||||||
|
if (excludeSensitive && files.some(file => file.isSensitive)) {
|
||||||
|
os.alert({
|
||||||
|
title: i18n.ts.cannotSelectSensitiveMedia,
|
||||||
|
text: i18n.ts.cannotSelectSensitiveMediaDescription,
|
||||||
|
});
|
||||||
|
rej();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
res(files);
|
||||||
|
}
|
||||||
|
|
||||||
os.popupMenu([label ? {
|
os.popupMenu([label ? {
|
||||||
text: label,
|
text: label,
|
||||||
type: 'label',
|
type: 'label',
|
||||||
|
@ -94,23 +107,23 @@ function select(src: any, label: string | null, multiple: boolean): Promise<Miss
|
||||||
}, {
|
}, {
|
||||||
text: i18n.ts.upload,
|
text: i18n.ts.upload,
|
||||||
icon: 'ti ti-upload',
|
icon: 'ti ti-upload',
|
||||||
action: () => chooseFileFromPc(multiple, keepOriginal.value).then(files => res(files)),
|
action: () => chooseFileFromPc(multiple, keepOriginal.value).then(files => _resolve(files)),
|
||||||
}, {
|
}, {
|
||||||
text: i18n.ts.fromDrive,
|
text: i18n.ts.fromDrive,
|
||||||
icon: 'ti ti-cloud',
|
icon: 'ti ti-cloud',
|
||||||
action: () => chooseFileFromDrive(multiple).then(files => res(files)),
|
action: () => chooseFileFromDrive(multiple, excludeSensitive).then(files => _resolve(files)),
|
||||||
}, {
|
}, {
|
||||||
text: i18n.ts.fromUrl,
|
text: i18n.ts.fromUrl,
|
||||||
icon: 'ti ti-link',
|
icon: 'ti ti-link',
|
||||||
action: () => chooseFileFromUrl().then(file => res([file])),
|
action: () => chooseFileFromUrl().then(file => _resolve([file])),
|
||||||
}], src);
|
}], src);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
export function selectFile(src: any, label: string | null = null): Promise<Misskey.entities.DriveFile> {
|
export function selectFile(src: any, label: string | null = null, excludeSensitive = false): Promise<Misskey.entities.DriveFile> {
|
||||||
return select(src, label, false).then(files => files[0]);
|
return select(src, label, false, excludeSensitive).then(files => files[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function selectFiles(src: any, label: string | null = null): Promise<Misskey.entities.DriveFile[]> {
|
export function selectFiles(src: any, label: string | null = null, excludeSensitive = false): Promise<Misskey.entities.DriveFile[]> {
|
||||||
return select(src, label, true);
|
return select(src, label, true, excludeSensitive);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue