From c3453833747bfe79eb5462ea6c06683c6965f982 Mon Sep 17 00:00:00 2001 From: mattyatea Date: Fri, 6 Oct 2023 08:01:42 +0900 Subject: [PATCH] =?UTF-8?q?=E3=83=89=E3=83=A9=E3=82=A4=E3=83=96=E3=81=A7?= =?UTF-8?q?=E8=A4=87=E6=95=B0=E9=81=B8=E6=8A=9E=E3=81=A7=E3=81=8D=E3=82=8B?= =?UTF-8?q?=E3=82=88=E3=81=86=E3=81=AB=E3=81=97=E3=81=9F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- locales/index.d.ts | 4 + locales/ja-JP.yml | 4 + package.json | 3 +- .../src/components/MkDrive.folder.vue | 152 +++++++-- .../src/components/MkDrive.navFolder.vue | 18 +- packages/frontend/src/components/MkDrive.vue | 312 ++++++++++++------ 6 files changed, 370 insertions(+), 123 deletions(-) diff --git a/locales/index.d.ts b/locales/index.d.ts index 47e542d4e3..e254f2e9f2 100644 --- a/locales/index.d.ts +++ b/locales/index.d.ts @@ -79,6 +79,10 @@ export interface Locale { "files": string; "download": string; "driveFileDeleteConfirm": string; + "driveFilesDeleteConfirm": string; + "driveFilesSensitiveonConfirm": string; + "driveFilesSensitiveoffConfirm": string; + "driveFolderDeleteConfirm": string; "unfollowConfirm": string; "exportRequested": string; "importRequested": string; diff --git a/locales/ja-JP.yml b/locales/ja-JP.yml index ed24aa9e85..c332fd9bf6 100644 --- a/locales/ja-JP.yml +++ b/locales/ja-JP.yml @@ -76,6 +76,10 @@ export: "エクスポート" files: "ファイル" download: "ダウンロード" driveFileDeleteConfirm: "ファイル「{name}」を削除しますか?このファイルを使用した一部のコンテンツも削除されます。" +driveFilesDeleteConfirm: "{name}つのファイルを削除しますか?このファイルを使用した一部のコンテンツも削除されます。" +driveFilesSensitiveonConfirm: "{name}つのファイルをセンシティブにしますか?" +driveFilesSensitiveoffConfirm: "{name}つのファイルのセンシティブを解除しますか?" +driveFolderDeleteConfirm: "フォルダ「{name}」を削除しますか?このフォルダの中に存在するファイルを使用した一部のコンテンツも削除されます。" unfollowConfirm: "{name}のフォローを解除しますか?" exportRequested: "エクスポートをリクエストしました。これには時間がかかる場合があります。エクスポートが終わると、「ドライブ」に追加されます。" importRequested: "インポートをリクエストしました。これには時間がかかる場合があります。" diff --git a/package.json b/package.json index af11e8e66e..0a7efa9f5e 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "misskey", - "version": "2023.9.3-prismisskey.2", + "version": "2023.9.3-prismisskey.3", "codename": "nasubi", "repository": { "type": "git", @@ -18,6 +18,7 @@ "build-assets": "node ./scripts/build-assets.mjs", "build": "pnpm build-pre && pnpm -r build && pnpm build-assets", "build-storybook": "pnpm --filter frontend build-storybook", + "build-and-start": "pnpm build && pnpm start", "start": "pnpm check:connect && cd packages/backend && node ./built/boot/entry.js", "start:test": "cd packages/backend && cross-env NODE_ENV=test node ./built/boot/entry.js", "init": "pnpm migrate", diff --git a/packages/frontend/src/components/MkDrive.folder.vue b/packages/frontend/src/components/MkDrive.folder.vue index 5322664664..f13cdb61a8 100644 --- a/packages/frontend/src/components/MkDrive.folder.vue +++ b/packages/frontend/src/components/MkDrive.folder.vue @@ -44,6 +44,7 @@ const props = withDefaults(defineProps<{ folder: Misskey.entities.DriveFolder; isSelected?: boolean; selectMode?: boolean; + selectedFiles?: string[]; }>(), { isSelected: false, selectMode: false, @@ -143,10 +144,19 @@ function onDrop(ev: DragEvent) { if (driveFile != null && driveFile !== '') { const file = JSON.parse(driveFile); emit('removeFile', file.id); - os.api('drive/files/update', { - fileId: file.id, - folderId: props.folder.id, - }); + if (props.selectedFiles.length > 0) { + props.selectedFiles.forEach((e)=>{ + os.api('drive/files/update', { + fileId: e.id, + folderId: props.folder.id, + }); + }) + }else{ + os.api('drive/files/update', { + fileId: file.id, + folderId: props.folder.id, + }); + } } //#endregion @@ -221,30 +231,120 @@ function rename() { } function deleteFolder() { - os.api('drive/folders/delete', { - folderId: props.folder.id, - }).then(() => { - if (defaultStore.state.uploadFolder === props.folder.id) { - defaultStore.set('uploadFolder', null); - } - }).catch(err => { - switch (err.id) { - case 'b0fc8a17-963c-405d-bfbc-859a487295e1': - os.alert({ - type: 'error', - title: i18n.ts.unableToDelete, - text: i18n.ts.hasChildFilesOrFolders, - }); - break; - default: - os.alert({ - type: 'error', - text: i18n.ts.unableToDelete, - }); - } - }); + os.api('drive/folders/show', { + folderId: props.folder.id, + }).then(async (r) => { + + if (r.foldersCount > 0) { + await os.alert({ + type: 'error', + title: i18n.ts.unableToDelete, + text: 'フォルダ内にフォルダが存在するため、削除できません。 \n フォルダ内のフォルダを削除してから試してみてください。', + }); + } + + if (r.filesCount > 0) { + + const {canceled} = await os.confirm({ + type: 'warning', + text: i18n.t('driveFolderDeleteConfirm', {name: props.folder.name}), + }); + + if (canceled) return; + + let allResults = []; + let Result = await os.api('drive/files', {folderId: props.folder.id, limit: 31}); + allResults = allResults.concat(Result) + while (Result.length >= 31) { + const untilId = Result[Result.length - 1].id; + Result = await os.api('drive/files', { folderId: props.folder.id, limit: 31, untilId }); + allResults = allResults.concat(Result); // pushをconcatに変更 + } + allResults.forEach((r,i)=>{ + os.api('drive/files/delete',{fileId: r.id}) + }) + + + os.api('drive/folders/show', { + folderId: props.folder.id, + }).then(async (r) =>{ + if (r.filesCount > 0) { + + let allResults = []; + let Result = await os.api('drive/files', {folderId: props.folder.id, limit: 31}); + allResults = allResults.concat(Result) + while (Result.length >= 31) { + const untilId = Result[Result.length - 1].id; + Result = await os.api('drive/files', { folderId: props.folder.id, limit: 31, untilId }); + allResults = allResults.concat(Result); + } + allResults.forEach((r,i)=>{ + os.api('drive/files/delete',{fileId: r.id}) + }) + + os.api('drive/folders/delete', { + folderId: props.folder.id, + }).then(() => { + if (defaultStore.state.uploadFolder === props.folder.id) { + defaultStore.set('uploadFolder', null); + } + }).catch(err => { + switch (err.id) { + case 'b0fc8a17-963c-405d-bfbc-859a487295e1': + os.alert({ + type: 'error', + title: i18n.ts.unableToDelete, + text: i18n.ts.hasChildFilesOrFolders, + }); + break; + default: + os.alert({ + type: 'error', + text: i18n.ts.unableToDelete, + }); + } + }); + + os.api('drive/folders/delete', { + folderId: props.folder.id, + }) + }else{ + os.api('drive/folders/delete', { + folderId: props.folder.id, + }) + } + }) + + } else { + + await os.api('drive/folders/delete', { + folderId: props.folder.id, + }).then(() => { + if (defaultStore.state.uploadFolder === props.folder.id) { + defaultStore.set('uploadFolder', null); + } + }).catch(err => { + switch (err.id) { + case 'b0fc8a17-963c-405d-bfbc-859a487295e1': + os.alert({ + type: 'error', + title: i18n.ts.unableToDelete, + text: i18n.ts.hasChildFilesOrFolders, + }); + break; + default: + os.alert({ + type: 'error', + text: i18n.ts.unableToDelete, + }); + } + }); + } + }) + } + function setAsUploadFolder() { defaultStore.set('uploadFolder', props.folder.id); } diff --git a/packages/frontend/src/components/MkDrive.navFolder.vue b/packages/frontend/src/components/MkDrive.navFolder.vue index 59458ad568..f3c4374997 100644 --- a/packages/frontend/src/components/MkDrive.navFolder.vue +++ b/packages/frontend/src/components/MkDrive.navFolder.vue @@ -26,6 +26,7 @@ import { i18n } from '@/i18n.js'; const props = defineProps<{ folder?: Misskey.entities.DriveFolder; parentFolder: Misskey.entities.DriveFolder | null; + selectedFiles: string[]; }>(); const emit = defineEmits<{ @@ -112,10 +113,19 @@ function onDrop(ev: DragEvent) { if (driveFile != null && driveFile !== '') { const file = JSON.parse(driveFile); emit('removeFile', file.id); - os.api('drive/files/update', { - fileId: file.id, - folderId: props.folder ? props.folder.id : null, - }); + if (props.selectedFiles.length > 0) { + props.selectedFiles.forEach((e) => { + os.api('drive/files/update', { + fileId: e.id, + folderId: props.folder ? props.folder.id : null, + }); + }); + } else { + os.api('drive/files/update', { + fileId: file.id, + folderId: props.folder ? props.folder.id : null, + }); + } } //#endregion diff --git a/packages/frontend/src/components/MkDrive.vue b/packages/frontend/src/components/MkDrive.vue index 648e4c4e3d..6d15142d3d 100644 --- a/packages/frontend/src/components/MkDrive.vue +++ b/packages/frontend/src/components/MkDrive.vue @@ -10,6 +10,7 @@ SPDX-License-Identifier: AGPL-3.0-only - + {{ folder.name }} - + + + ({{ number(selectedFiles.length) }}) + + + + +
{{ i18n.t('empty-draghover') }}
-
{{ i18n.ts.emptyDrive }}
{{ i18n.t('empty-drive-description') }}
+
+ {{ + i18n.ts.emptyDrive + }}
{{ i18n.t('empty-drive-description') }} +
{{ i18n.ts.emptyFolder }}
- + @@ -107,23 +130,24 @@ import { defaultStore } from '@/store.js'; import { i18n } from '@/i18n.js'; import { uploadFile, uploads } from '@/scripts/upload.js'; import { claimAchievement } from '@/scripts/achievements.js'; +import number from "@/filters/number.js"; const props = withDefaults(defineProps<{ - initialFolder?: Misskey.entities.DriveFolder; - type?: string; - multiple?: boolean; - select?: 'file' | 'folder' | null; + initialFolder?: Misskey.entities.DriveFolder; + type?: string; + multiple?: boolean; + select?: 'file' | 'folder' | null; }>(), { multiple: false, select: null, }); const emit = defineEmits<{ - (ev: 'selected', v: Misskey.entities.DriveFile | Misskey.entities.DriveFolder): void; - (ev: 'change-selection', v: Misskey.entities.DriveFile[] | Misskey.entities.DriveFolder[]): void; - (ev: 'move-root'): void; - (ev: 'cd', v: Misskey.entities.DriveFolder | null): void; - (ev: 'open-folder', v: Misskey.entities.DriveFolder): void; + (ev: 'selected', v: Misskey.entities.DriveFile | Misskey.entities.DriveFolder): void; + (ev: 'change-selection', v: Misskey.entities.DriveFile[] | Misskey.entities.DriveFolder[]): void; + (ev: 'move-root'): void; + (ev: 'cd', v: Misskey.entities.DriveFolder | null): void; + (ev: 'open-folder', v: Misskey.entities.DriveFolder): void; }>(); const loadMoreFiles = shallowRef>(); @@ -140,6 +164,8 @@ const selectedFolders = ref([]); const uploadings = uploads; const connection = useStream().useChannel('drive'); const keepOriginal = ref(defaultStore.state.keepOriginalUploading); // 外部渡しが多いので$refは使わないほうがよい +const multiple = ref(props.multiple || false); +const select = ref(props.select || null); // ドロップされようとしているか const draghover = ref(false); @@ -390,7 +416,7 @@ function upload(file: File, folderToUpload?: Misskey.entities.DriveFolder | null function chooseFile(file: Misskey.entities.DriveFile) { const isAlreadySelected = selectedFiles.value.some(f => f.id === file.id); - if (props.multiple) { + if (multiple.value) { if (isAlreadySelected) { selectedFiles.value = selectedFiles.value.filter(f => f.id !== file.id); } else { @@ -409,7 +435,7 @@ function chooseFile(file: Misskey.entities.DriveFile) { function chooseFolder(folderToChoose: Misskey.entities.DriveFolder) { const isAlreadySelected = selectedFolders.value.some(f => f.id === folderToChoose.id); - if (props.multiple) { + if (multiple.value) { if (isAlreadySelected) { selectedFolders.value = selectedFolders.value.filter(f => f.id !== folderToChoose.id); } else { @@ -496,6 +522,7 @@ function removeFolder(folderToRemove: Misskey.entities.DriveFolder | string) { function removeFile(file: Misskey.entities.DriveFile | string) { const fileId = typeof file === 'object' ? file.id : file; files.value = files.value.filter(f => f.id !== fileId); + selectedFiles.value = selectedFiles.value.filter(f => f.id !== fileId); } function appendFile(file: Misskey.entities.DriveFile) { @@ -505,6 +532,7 @@ function appendFile(file: Misskey.entities.DriveFile) { function appendFolder(folderToAppend: Misskey.entities.DriveFolder) { addFolder(folderToAppend); } + /* function prependFile(file: Misskey.entities.DriveFile) { addFile(file, true); @@ -621,31 +649,128 @@ function getMenu() { }, { text: i18n.ts.upload, icon: 'ti ti-upload', - action: () => { selectLocalFile(); }, + action: () => { + selectLocalFile(); + }, }, { text: i18n.ts.fromUrl, icon: 'ti ti-link', - action: () => { urlUpload(); }, + action: () => { + urlUpload(); + }, }, null, { text: folder.value ? folder.value.name : i18n.ts.drive, type: 'label', }, folder.value ? { text: i18n.ts.renameFolder, icon: 'ti ti-forms', - action: () => { renameFolder(folder.value); }, + action: () => { + renameFolder(folder.value); + }, } : undefined, folder.value ? { text: i18n.ts.deleteFolder, icon: 'ti ti-trash', - action: () => { deleteFolder(folder.value as Misskey.entities.DriveFolder); }, + action: () => { + deleteFolder(folder.value as Misskey.entities.DriveFolder); + }, } : undefined, { text: i18n.ts.createFolder, icon: 'ti ti-folder-plus', - action: () => { createFolder(); }, + action: () => { + createFolder(); + }, }]; } +async function isSensitive(Files, isSensitive: boolean) { + const { canceled } = await os.confirm({ + type: 'warning', + text: i18n.t(isSensitive ? 'driveFilesSensitiveonConfirm' : 'driveFilesSensitiveoffConfirm', { name: Files.length }), + }); + + if (canceled) return; + Files.forEach((file) => { + os.api('drive/files/update', { + fileId: file.id, + isSensitive, + }); + }); +} + +async function fileDelete(Files) { + const { canceled } = await os.confirm({ + type: 'warning', + text: i18n.t('driveFilesDeleteConfirm', { name: Files.length }), + }); + + if (canceled) return; + Files.forEach((file) => { + os.api('drive/files/delete', { + fileId: file.id, + }); + }); +} + +function getFilesMenu(Files) { + return [{ + text: i18n.ts.createNoteFromTheFile, + icon: 'ti ti-pencil', + action: () => { + if (Files.length >= 16) { + os.confirm({ + type: 'warning', + text: '16ファイル以上添付しようとしています', + }); + return; + } else { + os.post({ + initialFiles: [...Files], + }); + } + }, + }, { + text: i18n.ts.unmarkAsSensitive, + icon: 'ti ti-eye', + action: () => { + isSensitive(Files, false); + }, + }, { + text: i18n.ts.markAsSensitive, + icon: 'ti ti-eye-exclamation', + action: () => { + isSensitive(Files, true); + }, + }, { + text: i18n.ts.delete, + icon: 'ti ti-trash', + danger: true, + action: () => { + fileDelete(Files); + }, + }]; +} + +function filesSelect() { + multiple.value = !multiple.value; + select.value = (select.value === null) ? 'file' : null; + selectedFiles.value = []; +} + +function filesAllSelect() { + if (selectedFiles.value.length === 0) { + selectedFiles.value = files.value; + } else { + selectedFiles.value = []; + } +} + function showMenu(ev: MouseEvent) { - os.popupMenu(getMenu(), (ev.currentTarget ?? ev.target ?? undefined) as HTMLElement | undefined); + console.log(selectedFiles.value.length); + if (selectedFiles.value.length === 0) { + os.popupMenu(getMenu(), (ev.currentTarget ?? ev.target ?? undefined) as HTMLElement | undefined); + } else { + os.popupMenu(getFilesMenu(selectedFiles.value), (ev.currentTarget ?? ev.target ?? undefined) as HTMLElement | undefined); + } } function onContextmenu(ev: MouseEvent) { @@ -689,114 +814,117 @@ onBeforeUnmount(() => {