From a7339c7b7b1b4ac299addac7f590dd12f0c4a670 Mon Sep 17 00:00:00 2001 From: syuilo <4439005+syuilo@users.noreply.github.com> Date: Fri, 28 Mar 2025 10:12:18 +0900 Subject: [PATCH 01/23] wip --- packages/backend/src/core/DriveService.ts | 17 +++++++- .../backend/src/server/api/endpoint-list.ts | 1 + .../api/endpoints/drive/files/move-bulk.ts | 43 +++++++++++++++++++ 3 files changed, 60 insertions(+), 1 deletion(-) create mode 100644 packages/backend/src/server/api/endpoints/drive/files/move-bulk.ts diff --git a/packages/backend/src/core/DriveService.ts b/packages/backend/src/core/DriveService.ts index 1550fe3d3c..097dfaea87 100644 --- a/packages/backend/src/core/DriveService.ts +++ b/packages/backend/src/core/DriveService.ts @@ -8,7 +8,7 @@ import * as fs from 'node:fs'; import { Inject, Injectable } from '@nestjs/common'; import sharp from 'sharp'; import { sharpBmp } from '@misskey-dev/sharp-read-bmp'; -import { IsNull } from 'typeorm'; +import { In, IsNull } from 'typeorm'; import { DeleteObjectCommandInput, PutObjectCommandInput, NoSuchKey } from '@aws-sdk/client-s3'; import { DI } from '@/di-symbols.js'; import type { DriveFilesRepository, UsersRepository, DriveFoldersRepository, UserProfilesRepository, MiMeta } from '@/models/_.js'; @@ -713,6 +713,21 @@ export class DriveService { return fileObj; } + @bindThis + public async moveFiles(fileIds: MiDriveFile['id'][], folderId: MiDriveFolder['id'] | null, userId: MiUser['id']) { + const folder = folderId ? await this.driveFoldersRepository.findOneByOrFail({ + id: folderId, + userId: userId, + }) : null; + + await this.driveFilesRepository.update({ + id: In(fileIds), + userId: userId, + }, { + folderId: folder ? folder.id : null, + }); + } + @bindThis public async deleteFile(file: MiDriveFile, isExpired = false, deleter?: MiUser) { if (file.storedInternal) { diff --git a/packages/backend/src/server/api/endpoint-list.ts b/packages/backend/src/server/api/endpoint-list.ts index 34aaef3cc7..eda7a4446d 100644 --- a/packages/backend/src/server/api/endpoint-list.ts +++ b/packages/backend/src/server/api/endpoint-list.ts @@ -169,6 +169,7 @@ export * as 'drive/files/find' from './endpoints/drive/files/find.js'; export * as 'drive/files/find-by-hash' from './endpoints/drive/files/find-by-hash.js'; export * as 'drive/files/show' from './endpoints/drive/files/show.js'; export * as 'drive/files/update' from './endpoints/drive/files/update.js'; +export * as 'drive/files/move-bulk' from './endpoints/drive/files/move-bulk.js'; export * as 'drive/files/upload-from-url' from './endpoints/drive/files/upload-from-url.js'; export * as 'drive/folders' from './endpoints/drive/folders.js'; export * as 'drive/folders/create' from './endpoints/drive/folders/create.js'; diff --git a/packages/backend/src/server/api/endpoints/drive/files/move-bulk.ts b/packages/backend/src/server/api/endpoints/drive/files/move-bulk.ts new file mode 100644 index 0000000000..79e505575b --- /dev/null +++ b/packages/backend/src/server/api/endpoints/drive/files/move-bulk.ts @@ -0,0 +1,43 @@ +/* + * SPDX-FileCopyrightText: syuilo and misskey-project + * SPDX-License-Identifier: AGPL-3.0-only + */ + +import { Inject, Injectable } from '@nestjs/common'; +import { Endpoint } from '@/server/api/endpoint-base.js'; +import { DI } from '@/di-symbols.js'; +import { DriveService } from '@/core/DriveService.js'; +import { ApiError } from '../../../error.js'; + +export const meta = { + tags: ['drive'], + + requireCredential: true, + + kind: 'write:drive', + + errors: { + }, + + res: {}, +} as const; + +export const paramDef = { + type: 'object', + properties: { + fileIds: { type: 'array', uniqueItems: true, minItems: 1, maxItems: 100, items: { type: 'string', format: 'misskey:id' } }, + folderId: { type: 'string', format: 'misskey:id', nullable: true }, + }, + required: ['fileIds'], +} as const; + +@Injectable() +export default class extends Endpoint { // eslint-disable-line import/no-default-export + constructor( + private driveService: DriveService, + ) { + super(meta, paramDef, async (ps, me) => { + await this.driveService.moveFiles(ps.fileIds, ps.folderId ?? null, me.id); + }); + } +} From 8ce2f43722f05eba925f391117fc334fcae62dd6 Mon Sep 17 00:00:00 2001 From: syuilo <4439005+syuilo@users.noreply.github.com> Date: Sat, 10 May 2025 12:56:19 +0900 Subject: [PATCH 02/23] wip --- packages/frontend/src/components/MkDrive.vue | 168 ++++++------------- 1 file changed, 53 insertions(+), 115 deletions(-) diff --git a/packages/frontend/src/components/MkDrive.vue b/packages/frontend/src/components/MkDrive.vue index a1f76ac563..d7430439f8 100644 --- a/packages/frontend/src/components/MkDrive.vue +++ b/packages/frontend/src/components/MkDrive.vue @@ -68,23 +68,27 @@ SPDX-License-Identifier: AGPL-3.0-only
{{ i18n.ts.loadMore }} -
- - -
- {{ i18n.ts.loadMore }} + +
+
+
+ {{ getSeparatorInfo(filesPaginator.items.value[i -1].createdAt, file.createdAt).prevText }} + + {{ getSeparatorInfo(filesPaginator.items.value[i -1].createdAt, file.createdAt).nextText }} +
+ +
+ {{ i18n.ts.loadMore }}
{{ i18n.ts['empty-draghover'] }}
@@ -99,7 +103,7 @@ SPDX-License-Identifier: AGPL-3.0-only diff --git a/packages/frontend/src/composables/use-pagination.ts b/packages/frontend/src/composables/use-pagination.ts index 8dd3b888db..9325caeadc 100644 --- a/packages/frontend/src/composables/use-pagination.ts +++ b/packages/frontend/src/composables/use-pagination.ts @@ -39,6 +39,7 @@ export type PagingCtx(props: { ctx: PagingCtx; + autoInit?: boolean; useShallowRef?: boolean; }) { const items = props.useShallowRef ? shallowRef([]) : ref([]); @@ -232,9 +233,11 @@ export function usePagination { - init(); - }); + if (props.autoInit !== false) { + onMounted(() => { + init(); + }); + } return { items: items as DeepReadonly>, From 293aa9512cc5bd13fc2e3d4e28f97ba27088b50e Mon Sep 17 00:00:00 2001 From: syuilo <4439005+syuilo@users.noreply.github.com> Date: Sat, 10 May 2025 14:59:50 +0900 Subject: [PATCH 05/23] Update MkDrive.vue --- packages/frontend/src/components/MkDrive.vue | 45 +++++++++++--------- 1 file changed, 26 insertions(+), 19 deletions(-) diff --git a/packages/frontend/src/components/MkDrive.vue b/packages/frontend/src/components/MkDrive.vue index d861f40f42..23a90eab52 100644 --- a/packages/frontend/src/components/MkDrive.vue +++ b/packages/frontend/src/components/MkDrive.vue @@ -142,6 +142,23 @@ const emit = defineEmits<{ (ev: 'open-folder', v: Misskey.entities.DriveFolder): void; }>(); +const folder = ref(null); +const hierarchyFolders = ref([]); +const selectedFiles = ref([]); +const selectedFolders = ref([]); +const uploadings = uploads; + +// ドロップされようとしているか +const draghover = ref(false); + +// 自身の所有するアイテムがドラッグをスタートさせたか +// (自分自身の階層にドロップできないようにするためのフラグ) +const isDragSource = ref(false); + +const fetching = ref(true); + +const sortModeSelect = ref>('+createdAt'); + const filesPaginator = usePagination({ ctx: { endpoint: 'drive/files', @@ -166,23 +183,6 @@ const foldersPaginator = usePagination({ autoInit: false, }); -const folder = ref(null); -const hierarchyFolders = ref([]); -const selectedFiles = ref([]); -const selectedFolders = ref([]); -const uploadings = uploads; - -// ドロップされようとしているか -const draghover = ref(false); - -// 自身の所有するアイテムがドラッグをスタートさせたか -// (自分自身の階層にドロップできないようにするためのフラグ) -const isDragSource = ref(false); - -const fetching = ref(true); - -const sortModeSelect = ref>('+createdAt'); - watch(folder, () => emit('cd', folder.value)); watch(sortModeSelect, () => { initialize(); @@ -627,8 +627,13 @@ function closeTip() { store.set('readDriveTip', true); } +let connection: Misskey.ChannelConnection | null = null; + onMounted(() => { - connection.on('fileCreated', onStreamDriveFileCreated); + if (store.s.realtimeMode) { + connection = useStream().useChannel('drive'); + connection.on('fileCreated', onStreamDriveFileCreated); + } if (props.initialFolder) { move(props.initialFolder); @@ -641,7 +646,9 @@ onActivated(() => { }); onBeforeUnmount(() => { - connection.dispose(); + if (connection != null) { + connection.dispose(); + } }); From f25bc9bd95bdf437f9e4535d9c0d9416b03bd506 Mon Sep 17 00:00:00 2001 From: syuilo <4439005+syuilo@users.noreply.github.com> Date: Sat, 10 May 2025 15:03:09 +0900 Subject: [PATCH 06/23] Update MkDrive.vue --- packages/frontend/src/components/MkDrive.vue | 28 ++++++++++---------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/packages/frontend/src/components/MkDrive.vue b/packages/frontend/src/components/MkDrive.vue index 23a90eab52..03b1f17c78 100644 --- a/packages/frontend/src/components/MkDrive.vue +++ b/packages/frontend/src/components/MkDrive.vue @@ -263,7 +263,7 @@ function onDrop(ev: DragEvent) { const driveFile = ev.dataTransfer.getData(_DATA_TRANSFER_DRIVE_FILE_); if (driveFile != null && driveFile !== '') { const file = JSON.parse(driveFile); - if (files.value.some(f => f.id === file.id)) return; + if (filesPaginator.items.value.some(f => f.id === file.id)) return; removeFile(file.id); misskeyApi('drive/files/update', { fileId: file.id, @@ -279,7 +279,7 @@ function onDrop(ev: DragEvent) { // 移動先が自分自身ならreject if (folder.value && droppedFolder.id === folder.value.id) return false; - if (folders.value.some(f => f.id === droppedFolder.id)) return false; + if (foldersPaginator.items.value.some(f => f.id === droppedFolder.id)) return false; removeFolder(droppedFolder.id); misskeyApi('drive/folders/update', { folderId: droppedFolder.id, @@ -463,16 +463,16 @@ function addFolder(folderToAdd: Misskey.entities.DriveFolder, unshift = false) { const current = folder.value ? folder.value.id : null; if (current !== folderToAdd.parentId) return; - if (folders.value.some(f => f.id === folderToAdd.id)) { - const exist = folders.value.map(f => f.id).indexOf(folderToAdd.id); - folders.value[exist] = folderToAdd; + if (foldersPaginator.items.value.some(f => f.id === folderToAdd.id)) { + const exist = foldersPaginator.items.value.map(f => f.id).indexOf(folderToAdd.id); + foldersPaginator.items.value[exist] = folderToAdd; return; } if (unshift) { - folders.value.unshift(folderToAdd); + foldersPaginator.items.value.unshift(folderToAdd); } else { - folders.value.push(folderToAdd); + foldersPaginator.items.value.push(folderToAdd); } } @@ -480,27 +480,27 @@ function addFile(fileToAdd: Misskey.entities.DriveFile, unshift = false) { const current = folder.value ? folder.value.id : null; if (current !== fileToAdd.folderId) return; - if (files.value.some(f => f.id === fileToAdd.id)) { - const exist = files.value.map(f => f.id).indexOf(fileToAdd.id); - files.value[exist] = fileToAdd; + if (filesPaginator.items.value.some(f => f.id === fileToAdd.id)) { + const exist = filesPaginator.items.value.map(f => f.id).indexOf(fileToAdd.id); + filesPaginator.items.value[exist] = fileToAdd; return; } if (unshift) { - files.value.unshift(fileToAdd); + filesPaginator.items.value.unshift(fileToAdd); } else { - files.value.push(fileToAdd); + filesPaginator.items.value.push(fileToAdd); } } function removeFolder(folderToRemove: Misskey.entities.DriveFolder | string) { const folderIdToRemove = typeof folderToRemove === 'object' ? folderToRemove.id : folderToRemove; - folders.value = folders.value.filter(f => f.id !== folderIdToRemove); + foldersPaginator.items.value = foldersPaginator.items.value.filter(f => f.id !== folderIdToRemove); } function removeFile(file: Misskey.entities.DriveFile | string) { const fileId = typeof file === 'object' ? file.id : file; - files.value = files.value.filter(f => f.id !== fileId); + filesPaginator.items.value = filesPaginator.items.value.filter(f => f.id !== fileId); } function appendFile(file: Misskey.entities.DriveFile) { From c98d72e6e1a439e2f00421cb6854d851c8856bcc Mon Sep 17 00:00:00 2001 From: syuilo <4439005+syuilo@users.noreply.github.com> Date: Sat, 10 May 2025 15:28:06 +0900 Subject: [PATCH 07/23] wip --- packages/frontend/src/components/MkDrive.vue | 62 ++++++++----------- .../src/utility/timeline-date-separate.ts | 62 ++++++++++++++----- 2 files changed, 74 insertions(+), 50 deletions(-) diff --git a/packages/frontend/src/components/MkDrive.vue b/packages/frontend/src/components/MkDrive.vue index 03b1f17c78..81f25f115f 100644 --- a/packages/frontend/src/components/MkDrive.vue +++ b/packages/frontend/src/components/MkDrive.vue @@ -69,25 +69,28 @@ SPDX-License-Identifier: AGPL-3.0-only {{ i18n.ts.loadMore }}
-
-
-
- {{ getSeparatorInfo(filesPaginator.items.value[i -1].createdAt, file.createdAt).prevText }} - - {{ getSeparatorInfo(filesPaginator.items.value[i -1].createdAt, file.createdAt).nextText }} +
+ + + +
+
- -
+ {{ i18n.ts.loadMore }}
@@ -121,7 +124,7 @@ import { claimAchievement } from '@/utility/achievements.js'; import { prefer } from '@/preferences.js'; import { chooseFileFromPc } from '@/utility/select-file.js'; import { store } from '@/store.js'; -import { isSeparatorNeeded, getSeparatorInfo } from '@/utility/timeline-date-separate.js'; +import { isSeparatorNeeded, getSeparatorInfo, makeDateGroupedTimelineComputedRef } from '@/utility/timeline-date-separate.js'; import { usePagination } from '@/composables/use-pagination.js'; const props = withDefaults(defineProps<{ @@ -183,6 +186,8 @@ const foldersPaginator = usePagination({ autoInit: false, }); +const filesTimeline = makeDateGroupedTimelineComputedRef(filesPaginator.items, 'month'); + watch(folder, () => emit('cd', folder.value)); watch(sortModeSelect, () => { initialize(); @@ -725,22 +730,9 @@ onBeforeUnmount(() => { .folders, .files { - display: flex; - flex-wrap: wrap; -} - -.folder, -.file { - flex-grow: 1; - width: 128px; - margin: 4px; - box-sizing: border-box; -} - -.padding { - flex-grow: 1; - pointer-events: none; - width: 128px + 8px; + display: grid; + grid-template-columns: repeat(auto-fill, minmax(140px, 1fr)); + grid-gap: 12px; } .empty { diff --git a/packages/frontend/src/utility/timeline-date-separate.ts b/packages/frontend/src/utility/timeline-date-separate.ts index 1071a80962..33ddea048b 100644 --- a/packages/frontend/src/utility/timeline-date-separate.ts +++ b/packages/frontend/src/utility/timeline-date-separate.ts @@ -4,7 +4,7 @@ */ import { computed } from 'vue'; -import type { Ref } from 'vue'; +import type { Ref, ShallowRef } from 'vue'; export function getDateText(dateInstance: Date) { const date = dateInstance.getDate(); @@ -12,19 +12,6 @@ export function getDateText(dateInstance: Date) { return `${month.toString()}/${date.toString()}`; } -export type DateSeparetedTimelineItem = { - id: string; - type: 'item'; - data: T; -} | { - id: string; - type: 'date'; - prev: Date; - prevText: string; - next: Date; - nextText: string; -}; - // TODO: いちいちDateインスタンス作成するのは無駄感あるから文字列のまま解析したい export function isSeparatorNeeded( prev: string | null, @@ -56,7 +43,20 @@ export function getSeparatorInfo( }; } -export function makeDateSeparatedTimelineComputedRef(items: Ref) { +export type DateSeparetedTimelineItem = { + id: string; + type: 'item'; + data: T; +} | { + id: string; + type: 'date'; + prev: Date; + prevText: string; + next: Date; + nextText: string; +}; + +export function makeDateSeparatedTimelineComputedRef(items: Ref | ShallowRef) { return computed[]>(() => { const tl: DateSeparetedTimelineItem[] = []; for (let i = 0; i < items.value.length; i++) { @@ -92,3 +92,35 @@ export function makeDateSeparatedTimelineComputedRef = { + date: Date; + items: T[]; +}; + +export function makeDateGroupedTimelineComputedRef(items: Ref | ShallowRef, span: 'day' | 'month' = 'day') { + return computed[]>(() => { + const tl: DateGroupedTimelineItem[] = []; + for (let i = 0; i < items.value.length; i++) { + const item = items.value[i]; + const date = new Date(item.createdAt); + const nextDate = items.value[i + 1] ? new Date(items.value[i + 1].createdAt) : null; + + if (tl.length === 0 || ( + span === 'day' && tl[tl.length - 1].date.getTime() !== date.getTime() + ) || ( + span === 'month' && ( + tl[tl.length - 1].date.getFullYear() !== date.getFullYear() || + tl[tl.length - 1].date.getMonth() !== date.getMonth() + ) + )) { + tl.push({ + date, + items: [], + }); + } + tl[tl.length - 1].items.push(item); + } + return tl; + }); +} From 796b0c3706a765fe062c87ea30506e279bd13739 Mon Sep 17 00:00:00 2001 From: syuilo <4439005+syuilo@users.noreply.github.com> Date: Sat, 10 May 2025 15:35:41 +0900 Subject: [PATCH 08/23] Update MkDrive.vue --- packages/frontend/src/components/MkDrive.vue | 122 ++++++++++--------- 1 file changed, 63 insertions(+), 59 deletions(-) diff --git a/packages/frontend/src/components/MkDrive.vue b/packages/frontend/src/components/MkDrive.vue index 81f25f115f..115f753aab 100644 --- a/packages/frontend/src/components/MkDrive.vue +++ b/packages/frontend/src/components/MkDrive.vue @@ -44,64 +44,62 @@ SPDX-License-Identifier: AGPL-3.0-only @drop.prevent.stop="onDrop" @contextmenu.stop="onContextmenu" > -
-
-
- - -
- {{ i18n.ts.loadMore }} -
- -
- - - -
- -
-
- {{ i18n.ts.loadMore }} -
- -
-
{{ i18n.ts['empty-draghover'] }}
-
{{ i18n.ts.emptyDrive }}
{{ i18n.ts['empty-drive-description'] }}
-
{{ i18n.ts.emptyFolder }}
-
+
+
+ + +
+ {{ i18n.ts.loadMore }} +
+ +
+ + + +
+ +
+
+ {{ i18n.ts.loadMore }} +
+ +
+
{{ i18n.ts['empty-draghover'] }}
+
{{ i18n.ts.emptyDrive }}
{{ i18n.ts['empty-drive-description'] }}
+
{{ i18n.ts.emptyFolder }}
-
+
@@ -712,9 +710,6 @@ onBeforeUnmount(() => { } .main { - flex: 1; - overflow: auto; - padding: var(--MI-margin); user-select: none; &.fetching { @@ -733,6 +728,15 @@ onBeforeUnmount(() => { display: grid; grid-template-columns: repeat(auto-fill, minmax(140px, 1fr)); grid-gap: 12px; + padding: var(--MI-margin); +} + +.date { + padding: 8px 16px; + font-size: 90%; + -webkit-backdrop-filter: var(--MI-blur, blur(8px)); + backdrop-filter: var(--MI-blur, blur(8px)); + background-color: color(from var(--MI_THEME-bg) srgb r g b / 0.85); } .empty { From 9d6eb954b7feb2fd87d00178f500833448f9233e Mon Sep 17 00:00:00 2001 From: syuilo <4439005+syuilo@users.noreply.github.com> Date: Sat, 10 May 2025 15:40:46 +0900 Subject: [PATCH 09/23] Update MkDrive.vue --- packages/frontend/src/components/MkDrive.vue | 46 ++++++++++---------- 1 file changed, 23 insertions(+), 23 deletions(-) diff --git a/packages/frontend/src/components/MkDrive.vue b/packages/frontend/src/components/MkDrive.vue index 115f753aab..35aed7c202 100644 --- a/packages/frontend/src/components/MkDrive.vue +++ b/packages/frontend/src/components/MkDrive.vue @@ -45,30 +45,30 @@ SPDX-License-Identifier: AGPL-3.0-only @contextmenu.stop="onContextmenu" >
-
- - -
- {{ i18n.ts.loadMore }} +
+
+ +
+ {{ i18n.ts.loadMore }}
-
+
-
-
-
-
- -
- {{ i18n.ts.loadMore }} -
- -
- - - -
- +
+
+
+
+
- - {{ i18n.ts.loadMore }} -
+ {{ i18n.ts.loadMore }} +
-
-
{{ i18n.ts['empty-draghover'] }}
-
{{ i18n.ts.emptyDrive }}
{{ i18n.ts['empty-drive-description'] }}
-
{{ i18n.ts.emptyFolder }}
+
+ + + +
+ +
+
+ {{ i18n.ts.loadMore }} +
+ +
+
{{ i18n.ts['empty-draghover'] }}
+
{{ i18n.ts.emptyDrive }}
{{ i18n.ts['empty-drive-description'] }}
+
{{ i18n.ts.emptyFolder }}
+
+ +
- -
+ +
@@ -156,6 +164,8 @@ const draghover = ref(false); // (自分自身の階層にドロップできないようにするためのフラグ) const isDragSource = ref(false); +const isEditMode = ref(false); + const fetching = ref(true); const sortModeSelect = ref>('+createdAt'); @@ -171,6 +181,7 @@ const filesPaginator = usePagination({ })), }, autoInit: false, + autoReInit: false, }); const foldersPaginator = usePagination({ @@ -182,6 +193,7 @@ const foldersPaginator = usePagination({ })), }, autoInit: false, + autoReInit: false, }); const filesTimeline = makeDateGroupedTimelineComputedRef(filesPaginator.items, 'month'); @@ -613,6 +625,11 @@ function getMenu() { text: i18n.ts.createFolder, icon: 'ti ti-folder-plus', action: () => { createFolder(); }, + }, { type: 'divider' }, { + type: 'switch', + text: i18n.ts.edit, + icon: 'ti ti-pointer', + ref: isEditMode, }); return menu; @@ -739,6 +756,14 @@ onBeforeUnmount(() => { background-color: color(from var(--MI_THEME-bg) srgb r g b / 0.85); } +.footer { + padding: 8px 16px; + font-size: 90%; + -webkit-backdrop-filter: var(--MI-blur, blur(8px)); + backdrop-filter: var(--MI-blur, blur(8px)); + background-color: color(from var(--MI_THEME-bg) srgb r g b / 0.85); +} + .empty { padding: 16px; text-align: center; diff --git a/packages/frontend/src/composables/use-pagination.ts b/packages/frontend/src/composables/use-pagination.ts index 9325caeadc..cf8543c16a 100644 --- a/packages/frontend/src/composables/use-pagination.ts +++ b/packages/frontend/src/composables/use-pagination.ts @@ -40,6 +40,7 @@ export type PagingCtx(props: { ctx: PagingCtx; autoInit?: boolean; + autoReInit?: boolean; useShallowRef?: boolean; }) { const items = props.useShallowRef ? shallowRef([]) : ref([]); @@ -50,8 +51,9 @@ export function usePagination [props.ctx.endpoint, props.ctx.params], init, { deep: true }); + if (props.autoReInit !== false) { + watch(() => [props.ctx.endpoint, props.ctx.params], init, { deep: true }); + } function getNewestId(): string | null | undefined { // 様々な要因により並び順は保証されないのでソートが必要 From 5149e1c28535885dccd26d74ffb2b120ad78e591 Mon Sep 17 00:00:00 2001 From: syuilo <4439005+syuilo@users.noreply.github.com> Date: Sat, 10 May 2025 17:08:25 +0900 Subject: [PATCH 11/23] Update MkDrive.vue --- packages/frontend/src/components/MkDrive.vue | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/packages/frontend/src/components/MkDrive.vue b/packages/frontend/src/components/MkDrive.vue index 3407805660..7c618110ad 100644 --- a/packages/frontend/src/components/MkDrive.vue +++ b/packages/frontend/src/components/MkDrive.vue @@ -83,7 +83,7 @@ SPDX-License-Identifier: AGPL-3.0-only :class="$style.file" :file="file" :folder="folder" - :selectMode="select === 'file'" + :selectMode="select === 'file' || isEditMode" :isSelected="selectedFiles.some(x => x.id === file.id)" @chosen="chooseFile" @dragstart="isDragSource = true" @@ -405,6 +405,16 @@ 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 (isEditMode.value) { + if (isAlreadySelected) { + selectedFiles.value = selectedFiles.value.filter(f => f.id !== file.id); + } else { + selectedFiles.value.push(file); + } + return; + } + if (props.multiple) { if (isAlreadySelected) { selectedFiles.value = selectedFiles.value.filter(f => f.id !== file.id); From 6d5e9506e4483b99a850fbab9874f8525dd47c4d Mon Sep 17 00:00:00 2001 From: syuilo <4439005+syuilo@users.noreply.github.com> Date: Sat, 10 May 2025 17:53:54 +0900 Subject: [PATCH 12/23] wip --- .../frontend/src/components/MkDrive.file.vue | 16 ++++++++-------- packages/frontend/src/components/MkDrive.vue | 13 ++++++++++++- 2 files changed, 20 insertions(+), 9 deletions(-) diff --git a/packages/frontend/src/components/MkDrive.file.vue b/packages/frontend/src/components/MkDrive.file.vue index 388b8b56d7..0bb97c40ed 100644 --- a/packages/frontend/src/components/MkDrive.file.vue +++ b/packages/frontend/src/components/MkDrive.file.vue @@ -114,7 +114,7 @@ function onDragend() { &:hover { background: rgba(#000, 0.05); - > .label { + .label { &::before, &::after { background: #0b65a5; @@ -132,7 +132,7 @@ function onDragend() { &:active { background: rgba(#000, 0.1); - > .label { + .label { &::before, &::after { background: #0b588c; @@ -158,19 +158,19 @@ function onDragend() { background: hsl(from var(--MI_THEME-accent) h s calc(l - 10)); } - > .label { + .label { &::before, &::after { display: none; } } - > .name { - color: #fff; + .name { + color: var(--MI_THEME-fgOnAccent); } - > .thumbnail { - color: #fff; + .thumbnail { + color: var(--MI_THEME-fgOnAccent); } } } @@ -241,7 +241,7 @@ function onDragend() { .name { display: block; margin: 8px 0 0 0; - font-size: 85%; + font-size: 82%; text-align: center; word-break: break-all; color: var(--MI_THEME-fg); diff --git a/packages/frontend/src/components/MkDrive.vue b/packages/frontend/src/components/MkDrive.vue index 7c618110ad..7a283120da 100644 --- a/packages/frontend/src/components/MkDrive.vue +++ b/packages/frontend/src/components/MkDrive.vue @@ -106,7 +106,7 @@ SPDX-License-Identifier: AGPL-3.0-only @@ -484,6 +484,17 @@ function move(target?: Misskey.entities.DriveFolder | Misskey.entities.DriveFold }); } +async function moveFilesBulk() { + if (selectedFiles.value.length === 0) return; + + const toFolder = await os.selectDriveFolder(false); + + os.apiWithDialog('drive/files/move-bulk', { + fileIds: selectedFiles.value.map(f => f.id), + folderId: toFolder[0] ? toFolder[0].id : null, + }); +} + function addFolder(folderToAdd: Misskey.entities.DriveFolder, unshift = false) { const current = folder.value ? folder.value.id : null; if (current !== folderToAdd.parentId) return; From 90ac02931736598083c30067219c45b4f461599b Mon Sep 17 00:00:00 2001 From: syuilo <4439005+syuilo@users.noreply.github.com> Date: Sat, 10 May 2025 18:18:05 +0900 Subject: [PATCH 13/23] wip --- .../src/components/MkDrive.folder.vue | 2 +- packages/frontend/src/components/MkDrive.vue | 54 +++++++++++----- ...> MkDriveFileSelectDialog.stories.impl.ts} | 2 +- ...Dialog.vue => MkDriveFileSelectDialog.vue} | 20 +++--- .../components/MkDriveFolderSelectDialog.vue | 63 +++++++++++++++++++ packages/frontend/src/os.ts | 10 ++- .../frontend/src/pages/drive.file.info.vue | 2 +- .../frontend/src/pages/settings/drive.vue | 2 +- .../src/utility/get-drive-file-menu.ts | 2 +- .../frontend/src/widgets/WidgetSlideshow.vue | 2 +- 10 files changed, 121 insertions(+), 38 deletions(-) rename packages/frontend/src/components/{MkDriveSelectDialog.stories.impl.ts => MkDriveFileSelectDialog.stories.impl.ts} (66%) rename packages/frontend/src/components/{MkDriveSelectDialog.vue => MkDriveFileSelectDialog.vue} (54%) create mode 100644 packages/frontend/src/components/MkDriveFolderSelectDialog.vue diff --git a/packages/frontend/src/components/MkDrive.folder.vue b/packages/frontend/src/components/MkDrive.folder.vue index 9c72691d21..37181f65b6 100644 --- a/packages/frontend/src/components/MkDrive.folder.vue +++ b/packages/frontend/src/components/MkDrive.folder.vue @@ -230,7 +230,7 @@ function rename() { } function move() { - os.selectDriveFolder(false).then(folder => { + os.selectDriveFolder().then(folder => { if (folder[0] && folder[0].id === props.folder.id) return; misskeyApi('drive/folders/update', { diff --git a/packages/frontend/src/components/MkDrive.vue b/packages/frontend/src/components/MkDrive.vue index 7a283120da..f215457a78 100644 --- a/packages/frontend/src/components/MkDrive.vue +++ b/packages/frontend/src/components/MkDrive.vue @@ -36,6 +36,25 @@ SPDX-License-Identifier: AGPL-3.0-only
+
+ + +
+
@@ -134,7 +153,7 @@ import { isSeparatorNeeded, getSeparatorInfo, makeDateGroupedTimelineComputedRef import { usePagination } from '@/composables/use-pagination.js'; const props = withDefaults(defineProps<{ - initialFolder?: Misskey.entities.DriveFolder; + initialFolder?: Misskey.entities.DriveFolder['id'] | null; type?: string; multiple?: boolean; select?: 'file' | 'folder' | null; @@ -144,8 +163,8 @@ const props = withDefaults(defineProps<{ }); 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: 'changeSelectedFiles', v: Misskey.entities.DriveFile[]): void; + (ev: 'changeSelectedFolders', v: (Misskey.entities.DriveFolder | null)[]): void; (ev: 'move-root'): void; (ev: 'cd', v: Misskey.entities.DriveFolder | null): void; (ev: 'open-folder', v: Misskey.entities.DriveFolder): void; @@ -153,8 +172,6 @@ const emit = defineEmits<{ const folder = ref(null); const hierarchyFolders = ref([]); -const selectedFiles = ref([]); -const selectedFolders = ref([]); const uploadings = uploads; // ドロップされようとしているか @@ -166,6 +183,18 @@ const isDragSource = ref(false); const isEditMode = ref(false); +const selectedFiles = ref([]); +const selectedFolders = ref([]); +const isRootSelected = ref(false); + +watch(selectedFiles, () => { + emit('changeSelectedFiles', selectedFiles.value); +}); + +watch([selectedFolders, isRootSelected], () => { + emit('changeSelectedFolders', isRootSelected.value ? [null, ...selectedFolders.value] : selectedFolders.value); +}); + const fetching = ref(true); const sortModeSelect = ref>('+createdAt'); @@ -403,7 +432,7 @@ function upload(file: File, folderToUpload?: Misskey.entities.DriveFolder | null }); } -function chooseFile(file: Misskey.entities.DriveFile) { +function onChooseFile(file: Misskey.entities.DriveFile) { const isAlreadySelected = selectedFiles.value.some(f => f.id === file.id); if (isEditMode.value) { @@ -421,13 +450,11 @@ function chooseFile(file: Misskey.entities.DriveFile) { } else { selectedFiles.value.push(file); } - emit('change-selection', selectedFiles.value); } else { if (isAlreadySelected) { - emit('selected', file); + //emit('selected', file); } else { selectedFiles.value = [file]; - emit('change-selection', [file]); } } } @@ -440,20 +467,17 @@ function chooseFolder(folderToChoose: Misskey.entities.DriveFolder) { } else { selectedFolders.value.push(folderToChoose); } - emit('change-selection', selectedFolders.value); } else { if (isAlreadySelected) { - emit('selected', folderToChoose); + //emit('selected', folderToChoose); } else { selectedFolders.value = [folderToChoose]; - emit('change-selection', [folderToChoose]); } } } function unchoseFolder(folderToUnchose: Misskey.entities.DriveFolder) { selectedFolders.value = selectedFolders.value.filter(f => f.id !== folderToUnchose.id); - emit('change-selection', selectedFolders.value); } function move(target?: Misskey.entities.DriveFolder | Misskey.entities.DriveFolder['id' | 'parentId']) { @@ -487,7 +511,7 @@ function move(target?: Misskey.entities.DriveFolder | Misskey.entities.DriveFold async function moveFilesBulk() { if (selectedFiles.value.length === 0) return; - const toFolder = await os.selectDriveFolder(false); + const toFolder = await os.selectDriveFolder(folder.value ? folder.value.id : null); os.apiWithDialog('drive/files/move-bulk', { fileIds: selectedFiles.value.map(f => f.id), diff --git a/packages/frontend/src/components/MkDriveSelectDialog.stories.impl.ts b/packages/frontend/src/components/MkDriveFileSelectDialog.stories.impl.ts similarity index 66% rename from packages/frontend/src/components/MkDriveSelectDialog.stories.impl.ts rename to packages/frontend/src/components/MkDriveFileSelectDialog.stories.impl.ts index fe8f705165..a5073337cd 100644 --- a/packages/frontend/src/components/MkDriveSelectDialog.stories.impl.ts +++ b/packages/frontend/src/components/MkDriveFileSelectDialog.stories.impl.ts @@ -3,5 +3,5 @@ * SPDX-License-Identifier: AGPL-3.0-only */ -import MkDriveSelectDialog from './MkDriveSelectDialog.vue'; +import MkDriveSelectDialog from './MkDriveFileSelectDialog.vue'; void MkDriveSelectDialog; diff --git a/packages/frontend/src/components/MkDriveSelectDialog.vue b/packages/frontend/src/components/MkDriveFileSelectDialog.vue similarity index 54% rename from packages/frontend/src/components/MkDriveSelectDialog.vue rename to packages/frontend/src/components/MkDriveFileSelectDialog.vue index 1b9455e3f3..9cccd4ab5e 100644 --- a/packages/frontend/src/components/MkDriveSelectDialog.vue +++ b/packages/frontend/src/components/MkDriveFileSelectDialog.vue @@ -9,43 +9,41 @@ SPDX-License-Identifier: AGPL-3.0-only :width="800" :height="500" :withOkButton="true" - :okButtonDisabled="(type === 'file') && (selected.length === 0)" + :okButtonDisabled="selected.length === 0" @click="cancel()" @close="cancel()" @ok="ok()" @closed="emit('closed')" > - + diff --git a/packages/frontend/src/components/MkDriveFolderSelectDialog.vue b/packages/frontend/src/components/MkDriveFolderSelectDialog.vue new file mode 100644 index 0000000000..adc85c49e1 --- /dev/null +++ b/packages/frontend/src/components/MkDriveFolderSelectDialog.vue @@ -0,0 +1,63 @@ + + + + + diff --git a/packages/frontend/src/os.ts b/packages/frontend/src/os.ts index d891525782..9d26242c3c 100644 --- a/packages/frontend/src/os.ts +++ b/packages/frontend/src/os.ts @@ -594,8 +594,7 @@ export async function selectUser(opts: { includeSelf?: boolean; localOnly?: bool export async function selectDriveFile(multiple: boolean): Promise { return new Promise(resolve => { - const { dispose } = popup(defineAsyncComponent(() => import('@/components/MkDriveSelectDialog.vue')), { - type: 'file', + const { dispose } = popup(defineAsyncComponent(() => import('@/components/MkDriveFileSelectDialog.vue')), { multiple, }, { done: files => { @@ -608,11 +607,10 @@ export async function selectDriveFile(multiple: boolean): Promise { +export async function selectDriveFolder(initialFolder: Misskey.entities.DriveFolder['id'] | null): Promise { return new Promise(resolve => { - const { dispose } = popup(defineAsyncComponent(() => import('@/components/MkDriveSelectDialog.vue')), { - type: 'folder', - multiple, + const { dispose } = popup(defineAsyncComponent(() => import('@/components/MkDriveFolderSelectDialog.vue')), { + initialFolder, }, { done: folders => { if (folders) { diff --git a/packages/frontend/src/pages/drive.file.info.vue b/packages/frontend/src/pages/drive.file.info.vue index 21be0b18a9..fec260be72 100644 --- a/packages/frontend/src/pages/drive.file.info.vue +++ b/packages/frontend/src/pages/drive.file.info.vue @@ -139,7 +139,7 @@ function crop() { function move() { if (!file.value) return; - os.selectDriveFolder(false).then(folder => { + os.selectDriveFolder().then(folder => { misskeyApi('drive/files/update', { fileId: file.value.id, folderId: folder[0] ? folder[0].id : null, diff --git a/packages/frontend/src/pages/settings/drive.vue b/packages/frontend/src/pages/settings/drive.vue index 2130cbc868..c4619c354d 100644 --- a/packages/frontend/src/pages/settings/drive.vue +++ b/packages/frontend/src/pages/settings/drive.vue @@ -138,7 +138,7 @@ if (prefer.s.uploadFolder) { } function chooseUploadFolder() { - os.selectDriveFolder(false).then(async folder => { + os.selectDriveFolder().then(async folder => { prefer.commit('uploadFolder', folder[0] ? folder[0].id : null); os.success(); if (prefer.s.uploadFolder) { diff --git a/packages/frontend/src/utility/get-drive-file-menu.ts b/packages/frontend/src/utility/get-drive-file-menu.ts index 3c6cbba002..a5595cb0cb 100644 --- a/packages/frontend/src/utility/get-drive-file-menu.ts +++ b/packages/frontend/src/utility/get-drive-file-menu.ts @@ -42,7 +42,7 @@ function describe(file: Misskey.entities.DriveFile) { } function move(file: Misskey.entities.DriveFile) { - os.selectDriveFolder(false).then(folder => { + os.selectDriveFolder().then(folder => { misskeyApi('drive/files/update', { fileId: file.id, folderId: folder[0] ? folder[0].id : null, diff --git a/packages/frontend/src/widgets/WidgetSlideshow.vue b/packages/frontend/src/widgets/WidgetSlideshow.vue index 2ccbb7a28f..a83e2754f6 100644 --- a/packages/frontend/src/widgets/WidgetSlideshow.vue +++ b/packages/frontend/src/widgets/WidgetSlideshow.vue @@ -93,7 +93,7 @@ const fetch = () => { }; const choose = () => { - os.selectDriveFolder(false).then(folder => { + os.selectDriveFolder().then(folder => { if (folder[0] == null) { return; } From ade38bfe2f480432be2d35af1d283f63cffbad59 Mon Sep 17 00:00:00 2001 From: syuilo <4439005+syuilo@users.noreply.github.com> Date: Sat, 10 May 2025 18:28:26 +0900 Subject: [PATCH 14/23] wip --- packages/frontend/src/components/MkDrive.vue | 6 ++- .../src/composables/use-pagination.ts | 44 +++++++++++++------ 2 files changed, 35 insertions(+), 15 deletions(-) diff --git a/packages/frontend/src/components/MkDrive.vue b/packages/frontend/src/components/MkDrive.vue index f215457a78..fdf231cd9d 100644 --- a/packages/frontend/src/components/MkDrive.vue +++ b/packages/frontend/src/components/MkDrive.vue @@ -85,7 +85,7 @@ SPDX-License-Identifier: AGPL-3.0-only @dragend="isDragSource = false" />
- {{ i18n.ts.loadMore }} + {{ i18n.ts.loadMore }}
@@ -110,7 +110,7 @@ SPDX-License-Identifier: AGPL-3.0-only />
- {{ i18n.ts.loadMore }} + {{ i18n.ts.loadMore }}
@@ -203,6 +203,7 @@ const filesPaginator = usePagination({ ctx: { endpoint: 'drive/files', limit: 30, + canFetchDetection: 'limit', params: computed(() => ({ folderId: folder.value ? folder.value.id : null, type: props.type, @@ -217,6 +218,7 @@ const foldersPaginator = usePagination({ ctx: { endpoint: 'drive/folders', limit: 30, + canFetchDetection: 'limit', params: computed(() => ({ folderId: folder.value ? folder.value.id : null, })), diff --git a/packages/frontend/src/composables/use-pagination.ts b/packages/frontend/src/composables/use-pagination.ts index cf8543c16a..b0be8255ef 100644 --- a/packages/frontend/src/composables/use-pagination.ts +++ b/packages/frontend/src/composables/use-pagination.ts @@ -35,6 +35,9 @@ export type PagingCtx(props: { @@ -95,12 +98,20 @@ export function usePagination { fetchingOlder.value = false; From 40c5cd0013c60c5581d77fa5fa77127c30487ddf Mon Sep 17 00:00:00 2001 From: syuilo <4439005+syuilo@users.noreply.github.com> Date: Sat, 10 May 2025 20:15:03 +0900 Subject: [PATCH 15/23] wip --- packages/frontend/src/components/MkDrive.vue | 9 ++++++++- packages/frontend/src/events.ts | 1 + 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/packages/frontend/src/components/MkDrive.vue b/packages/frontend/src/components/MkDrive.vue index fdf231cd9d..e4caf9aef9 100644 --- a/packages/frontend/src/components/MkDrive.vue +++ b/packages/frontend/src/components/MkDrive.vue @@ -151,6 +151,7 @@ import { chooseFileFromPc } from '@/utility/select-file.js'; import { store } from '@/store.js'; import { isSeparatorNeeded, getSeparatorInfo, makeDateGroupedTimelineComputedRef } from '@/utility/timeline-date-separate.js'; import { usePagination } from '@/composables/use-pagination.js'; +import { globalEvents, useGlobalEvent } from '@/events.js'; const props = withDefaults(defineProps<{ initialFolder?: Misskey.entities.DriveFolder['id'] | null; @@ -515,10 +516,12 @@ async function moveFilesBulk() { const toFolder = await os.selectDriveFolder(folder.value ? folder.value.id : null); - os.apiWithDialog('drive/files/move-bulk', { + await os.apiWithDialog('drive/files/move-bulk', { fileIds: selectedFiles.value.map(f => f.id), folderId: toFolder[0] ? toFolder[0].id : null, }); + + globalEvents.emit('driveFilesMoved', selectedFiles.value, toFolder[0]); } function addFolder(folderToAdd: Misskey.entities.DriveFolder, unshift = false) { @@ -694,6 +697,10 @@ function closeTip() { store.set('readDriveTip', true); } +useGlobalEvent('driveFilesMoved', (files, to) => { + // TODO +}); + let connection: Misskey.ChannelConnection | null = null; onMounted(() => { diff --git a/packages/frontend/src/events.ts b/packages/frontend/src/events.ts index 26b1881d15..83412b365a 100644 --- a/packages/frontend/src/events.ts +++ b/packages/frontend/src/events.ts @@ -13,6 +13,7 @@ type Events = { clientNotification: (notification: Misskey.entities.Notification) => void; notePosted: (note: Misskey.entities.Note) => void; noteDeleted: (noteId: Misskey.entities.Note['id']) => void; + driveFilesMoved: (files: Misskey.entities.DriveFile[], to: Misskey.entities.DriveFolder | null) => void; }; export const globalEvents = new EventEmitter(); From 4d185b49cd5d10356e87c865aa219c7b8442690c Mon Sep 17 00:00:00 2001 From: syuilo <4439005+syuilo@users.noreply.github.com> Date: Sun, 11 May 2025 09:16:16 +0900 Subject: [PATCH 16/23] Update MkDrive.vue --- packages/frontend/src/components/MkDrive.vue | 129 ++++++------------- 1 file changed, 41 insertions(+), 88 deletions(-) diff --git a/packages/frontend/src/components/MkDrive.vue b/packages/frontend/src/components/MkDrive.vue index e4caf9aef9..72d6ae32f5 100644 --- a/packages/frontend/src/components/MkDrive.vue +++ b/packages/frontend/src/components/MkDrive.vue @@ -245,7 +245,9 @@ async function initialize() { } function onStreamDriveFileCreated(file: Misskey.entities.DriveFile) { - addFile(file, true); + if (file.folderId === (folder.value?.id ?? null)) { + filesPaginator.prepend(file); + } } function onDragover(ev: DragEvent) { @@ -354,55 +356,55 @@ function onDrop(ev: DragEvent) { //#endregion } -function urlUpload() { - os.inputText({ +async function urlUpload() { + const { canceled, result: url } = await os.inputText({ title: i18n.ts.uploadFromUrl, type: 'url', placeholder: i18n.ts.uploadFromUrlDescription, - }).then(({ canceled, result: url }) => { - if (canceled || !url) return; - misskeyApi('drive/files/upload-from-url', { - url: url, - folderId: folder.value ? folder.value.id : undefined, - }); + }); + if (canceled || !url) return; - os.alert({ - title: i18n.ts.uploadFromUrlRequested, - text: i18n.ts.uploadFromUrlMayTakeTime, - }); + await os.apiWithDialog('drive/files/upload-from-url', { + url: url, + folderId: folder.value ? folder.value.id : undefined, + }); + + os.alert({ + title: i18n.ts.uploadFromUrlRequested, + text: i18n.ts.uploadFromUrlMayTakeTime, }); } -function createFolder() { - os.inputText({ +async function createFolder() { + const { canceled, result: name } = await os.inputText({ title: i18n.ts.createFolder, placeholder: i18n.ts.folderName, - }).then(({ canceled, result: name }) => { - if (canceled || name == null) return; - misskeyApi('drive/folders/create', { - name: name, - parentId: folder.value ? folder.value.id : undefined, - }).then(createdFolder => { - addFolder(createdFolder, true); - }); }); + if (canceled || name == null) return; + + const createdFolder = await os.apiWithDialog('drive/folders/create', { + name: name, + parentId: folder.value ? folder.value.id : undefined, + }); + + foldersPaginator.prepend(createdFolder); } -function renameFolder(folderToRename: Misskey.entities.DriveFolder) { - os.inputText({ +async function renameFolder(folderToRename: Misskey.entities.DriveFolder) { + const { canceled, result: name } = await os.inputText({ title: i18n.ts.renameFolder, placeholder: i18n.ts.inputNewFolderName, default: folderToRename.name, - }).then(({ canceled, result: name }) => { - if (canceled) return; - misskeyApi('drive/folders/update', { - folderId: folderToRename.id, - name: name, - }).then(updatedFolder => { - // FIXME: 画面を更新するために自分自身に移動 - move(updatedFolder); - }); }); + if (canceled) return; + + const updatedFolder = await os.apiWithDialog('drive/folders/update', { + folderId: folderToRename.id, + name: name, + }); + + // FIXME: 画面を更新するために自分自身に移動 + move(updatedFolder); } function deleteFolder(folderToDelete: Misskey.entities.DriveFolder) { @@ -431,7 +433,9 @@ function deleteFolder(folderToDelete: Misskey.entities.DriveFolder) { function upload(file: File, folderToUpload?: Misskey.entities.DriveFolder | null, keepOriginal?: boolean) { uploadFile(file, (folderToUpload && typeof folderToUpload === 'object') ? folderToUpload.id : null, undefined, keepOriginal).then(res => { - addFile(res, true); + if (res.folderId === (folder.value?.id ?? null)) { + filesPaginator.prepend(res); + } }); } @@ -524,67 +528,16 @@ async function moveFilesBulk() { globalEvents.emit('driveFilesMoved', selectedFiles.value, toFolder[0]); } -function addFolder(folderToAdd: Misskey.entities.DriveFolder, unshift = false) { - const current = folder.value ? folder.value.id : null; - if (current !== folderToAdd.parentId) return; - - if (foldersPaginator.items.value.some(f => f.id === folderToAdd.id)) { - const exist = foldersPaginator.items.value.map(f => f.id).indexOf(folderToAdd.id); - foldersPaginator.items.value[exist] = folderToAdd; - return; - } - - if (unshift) { - foldersPaginator.items.value.unshift(folderToAdd); - } else { - foldersPaginator.items.value.push(folderToAdd); - } -} - -function addFile(fileToAdd: Misskey.entities.DriveFile, unshift = false) { - const current = folder.value ? folder.value.id : null; - if (current !== fileToAdd.folderId) return; - - if (filesPaginator.items.value.some(f => f.id === fileToAdd.id)) { - const exist = filesPaginator.items.value.map(f => f.id).indexOf(fileToAdd.id); - filesPaginator.items.value[exist] = fileToAdd; - return; - } - - if (unshift) { - filesPaginator.items.value.unshift(fileToAdd); - } else { - filesPaginator.items.value.push(fileToAdd); - } -} - function removeFolder(folderToRemove: Misskey.entities.DriveFolder | string) { const folderIdToRemove = typeof folderToRemove === 'object' ? folderToRemove.id : folderToRemove; - foldersPaginator.items.value = foldersPaginator.items.value.filter(f => f.id !== folderIdToRemove); + foldersPaginator.removeItem(folderIdToRemove); } function removeFile(file: Misskey.entities.DriveFile | string) { const fileId = typeof file === 'object' ? file.id : file; - filesPaginator.items.value = filesPaginator.items.value.filter(f => f.id !== fileId); + filesPaginator.removeItem(fileId); } -function appendFile(file: Misskey.entities.DriveFile) { - addFile(file); -} - -function appendFolder(folderToAppend: Misskey.entities.DriveFolder) { - addFolder(folderToAppend); -} - -/* -function prependFile(file: Misskey.entities.DriveFile) { - addFile(file, true); -} - -function prependFolder(folderToPrepend: Misskey.entities.DriveFolder) { - addFolder(folderToPrepend, true); -} -*/ function goRoot() { // 既にrootにいるなら何もしない if (folder.value == null) return; From db09744ce87362f16907234f7598a00934e87f7d Mon Sep 17 00:00:00 2001 From: syuilo <4439005+syuilo@users.noreply.github.com> Date: Sun, 11 May 2025 09:41:15 +0900 Subject: [PATCH 17/23] wip --- packages/frontend-embed/@types/global.d.ts | 3 -- packages/frontend-embed/eslint.config.js | 3 -- packages/frontend-shared/@types/global.d.ts | 3 -- packages/frontend-shared/eslint.config.js | 3 -- packages/frontend/@types/global.d.ts | 3 -- packages/frontend/eslint.config.js | 3 -- .../frontend/src/components/MkDrive.file.vue | 7 +++-- .../src/components/MkDrive.folder.vue | 11 ++++---- .../src/components/MkDrive.navFolder.vue | 9 +++--- packages/frontend/src/components/MkDrive.vue | 28 +++++++++++++++---- .../frontend/src/components/MkPostForm.vue | 5 ++-- packages/frontend/src/consts.ts | 10 +++++++ .../frontend/src/pages/chat/room.form.vue | 5 ++-- packages/frontend/src/ui/deck/column.vue | 7 +++-- packages/frontend/vite.config.ts | 3 -- 15 files changed, 57 insertions(+), 46 deletions(-) create mode 100644 packages/frontend/src/consts.ts diff --git a/packages/frontend-embed/@types/global.d.ts b/packages/frontend-embed/@types/global.d.ts index 1025d1bedb..8a067a78ec 100644 --- a/packages/frontend-embed/@types/global.d.ts +++ b/packages/frontend-embed/@types/global.d.ts @@ -10,9 +10,6 @@ declare const _VERSION_: string; declare const _ENV_: string; declare const _DEV_: boolean; declare const _PERF_PREFIX_: string; -declare const _DATA_TRANSFER_DRIVE_FILE_: string; -declare const _DATA_TRANSFER_DRIVE_FOLDER_: string; -declare const _DATA_TRANSFER_DECK_COLUMN_: string; // for dev-mode declare const _LANGS_FULL_: string[][]; diff --git a/packages/frontend-embed/eslint.config.js b/packages/frontend-embed/eslint.config.js index 7805256fd4..2aef311e2e 100644 --- a/packages/frontend-embed/eslint.config.js +++ b/packages/frontend-embed/eslint.config.js @@ -30,9 +30,6 @@ export default [ _VERSION_: false, _ENV_: false, _PERF_PREFIX_: false, - _DATA_TRANSFER_DRIVE_FILE_: false, - _DATA_TRANSFER_DRIVE_FOLDER_: false, - _DATA_TRANSFER_DECK_COLUMN_: false, }, parser, parserOptions: { diff --git a/packages/frontend-shared/@types/global.d.ts b/packages/frontend-shared/@types/global.d.ts index 4b8d679e75..52081d07b3 100644 --- a/packages/frontend-shared/@types/global.d.ts +++ b/packages/frontend-shared/@types/global.d.ts @@ -11,9 +11,6 @@ declare const _VERSION_: string; declare const _ENV_: string; declare const _DEV_: boolean; declare const _PERF_PREFIX_: string; -declare const _DATA_TRANSFER_DRIVE_FILE_: string; -declare const _DATA_TRANSFER_DRIVE_FOLDER_: string; -declare const _DATA_TRANSFER_DECK_COLUMN_: string; // for dev-mode declare const _LANGS_FULL_: string[][]; diff --git a/packages/frontend-shared/eslint.config.js b/packages/frontend-shared/eslint.config.js index ac5c67d0b6..f6fd64153c 100644 --- a/packages/frontend-shared/eslint.config.js +++ b/packages/frontend-shared/eslint.config.js @@ -35,9 +35,6 @@ export default [ _VERSION_: false, _ENV_: false, _PERF_PREFIX_: false, - _DATA_TRANSFER_DRIVE_FILE_: false, - _DATA_TRANSFER_DRIVE_FOLDER_: false, - _DATA_TRANSFER_DECK_COLUMN_: false, }, parser, parserOptions: { diff --git a/packages/frontend/@types/global.d.ts b/packages/frontend/@types/global.d.ts index 1025d1bedb..8a067a78ec 100644 --- a/packages/frontend/@types/global.d.ts +++ b/packages/frontend/@types/global.d.ts @@ -10,9 +10,6 @@ declare const _VERSION_: string; declare const _ENV_: string; declare const _DEV_: boolean; declare const _PERF_PREFIX_: string; -declare const _DATA_TRANSFER_DRIVE_FILE_: string; -declare const _DATA_TRANSFER_DRIVE_FOLDER_: string; -declare const _DATA_TRANSFER_DECK_COLUMN_: string; // for dev-mode declare const _LANGS_FULL_: string[][]; diff --git a/packages/frontend/eslint.config.js b/packages/frontend/eslint.config.js index 1b9a9b68c0..8f835975a8 100644 --- a/packages/frontend/eslint.config.js +++ b/packages/frontend/eslint.config.js @@ -30,9 +30,6 @@ export default [ _VERSION_: false, _ENV_: false, _PERF_PREFIX_: false, - _DATA_TRANSFER_DRIVE_FILE_: false, - _DATA_TRANSFER_DRIVE_FOLDER_: false, - _DATA_TRANSFER_DECK_COLUMN_: false, }, parser, parserOptions: { diff --git a/packages/frontend/src/components/MkDrive.file.vue b/packages/frontend/src/components/MkDrive.file.vue index 0bb97c40ed..8cd28375c4 100644 --- a/packages/frontend/src/components/MkDrive.file.vue +++ b/packages/frontend/src/components/MkDrive.file.vue @@ -48,6 +48,7 @@ import { $i } from '@/i.js'; import { getDriveFileMenu } from '@/utility/get-drive-file-menu.js'; import { deviceKind } from '@/utility/device-kind.js'; import { useRouter } from '@/router.js'; +import { DATA_TRANSFER_DRIVE_FILE } from '@/consts.js'; const router = useRouter(); @@ -63,7 +64,7 @@ const props = withDefaults(defineProps<{ const emit = defineEmits<{ (ev: 'chosen', r: Misskey.entities.DriveFile): void; - (ev: 'dragstart'): void; + (ev: 'dragstart', dragEvent: DragEvent): void; (ev: 'dragend'): void; }>(); @@ -90,11 +91,11 @@ function onContextmenu(ev: MouseEvent) { function onDragstart(ev: DragEvent) { if (ev.dataTransfer) { 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)); } isDragging.value = true; - emit('dragstart'); + emit('dragstart', ev); } function onDragend() { diff --git a/packages/frontend/src/components/MkDrive.folder.vue b/packages/frontend/src/components/MkDrive.folder.vue index 37181f65b6..e4791258c8 100644 --- a/packages/frontend/src/components/MkDrive.folder.vue +++ b/packages/frontend/src/components/MkDrive.folder.vue @@ -43,6 +43,7 @@ import { i18n } from '@/i18n.js'; import { claimAchievement } from '@/utility/achievements.js'; import { copyToClipboard } from '@/utility/copy-to-clipboard.js'; import { prefer } from '@/preferences.js'; +import { DATA_TRANSFER_DRIVE_FILE, DATA_TRANSFER_DRIVE_FOLDER } from '@/consts.js'; const props = withDefaults(defineProps<{ folder: Misskey.entities.DriveFolder; @@ -101,8 +102,8 @@ function onDragover(ev: DragEvent) { } const isFile = ev.dataTransfer.items[0].kind === 'file'; - const isDriveFile = ev.dataTransfer.types[0] === _DATA_TRANSFER_DRIVE_FILE_; - const isDriveFolder = ev.dataTransfer.types[0] === _DATA_TRANSFER_DRIVE_FOLDER_; + const isDriveFile = ev.dataTransfer.types[0] === DATA_TRANSFER_DRIVE_FILE; + const isDriveFolder = ev.dataTransfer.types[0] === DATA_TRANSFER_DRIVE_FOLDER; if (isFile || isDriveFile || isDriveFolder) { switch (ev.dataTransfer.effectAllowed) { @@ -148,7 +149,7 @@ function onDrop(ev: DragEvent) { } //#region ドライブのファイル - const driveFile = ev.dataTransfer.getData(_DATA_TRANSFER_DRIVE_FILE_); + const driveFile = ev.dataTransfer.getData(DATA_TRANSFER_DRIVE_FILE); if (driveFile != null && driveFile !== '') { const file = JSON.parse(driveFile); emit('removeFile', file.id); @@ -160,7 +161,7 @@ function onDrop(ev: DragEvent) { //#endregion //#region ドライブのフォルダ - const driveFolder = ev.dataTransfer.getData(_DATA_TRANSFER_DRIVE_FOLDER_); + const driveFolder = ev.dataTransfer.getData(DATA_TRANSFER_DRIVE_FOLDER); if (driveFolder != null && driveFolder !== '') { const folder = JSON.parse(driveFolder); @@ -198,7 +199,7 @@ function onDragstart(ev: DragEvent) { if (!ev.dataTransfer) return; ev.dataTransfer.effectAllowed = 'move'; - ev.dataTransfer.setData(_DATA_TRANSFER_DRIVE_FOLDER_, JSON.stringify(props.folder)); + ev.dataTransfer.setData(DATA_TRANSFER_DRIVE_FOLDER, JSON.stringify(props.folder)); isDragging.value = true; // 親ブラウザに対して、ドラッグが開始されたフラグを立てる diff --git a/packages/frontend/src/components/MkDrive.navFolder.vue b/packages/frontend/src/components/MkDrive.navFolder.vue index 7433aea061..176aceee5a 100644 --- a/packages/frontend/src/components/MkDrive.navFolder.vue +++ b/packages/frontend/src/components/MkDrive.navFolder.vue @@ -22,6 +22,7 @@ import { ref } from 'vue'; import * as Misskey from 'misskey-js'; import { misskeyApi } from '@/utility/misskey-api.js'; import { i18n } from '@/i18n.js'; +import { DATA_TRANSFER_DRIVE_FILE, DATA_TRANSFER_DRIVE_FOLDER } from '@/consts.js'; const props = defineProps<{ folder?: Misskey.entities.DriveFolder; @@ -59,8 +60,8 @@ function onDragover(ev: DragEvent) { } const isFile = ev.dataTransfer.items[0].kind === 'file'; - const isDriveFile = ev.dataTransfer.types[0] === _DATA_TRANSFER_DRIVE_FILE_; - const isDriveFolder = ev.dataTransfer.types[0] === _DATA_TRANSFER_DRIVE_FOLDER_; + const isDriveFile = ev.dataTransfer.types[0] === DATA_TRANSFER_DRIVE_FILE; + const isDriveFolder = ev.dataTransfer.types[0] === DATA_TRANSFER_DRIVE_FOLDER; if (isFile || isDriveFile || isDriveFolder) { switch (ev.dataTransfer.effectAllowed) { @@ -108,7 +109,7 @@ function onDrop(ev: DragEvent) { } //#region ドライブのファイル - const driveFile = ev.dataTransfer.getData(_DATA_TRANSFER_DRIVE_FILE_); + const driveFile = ev.dataTransfer.getData(DATA_TRANSFER_DRIVE_FILE); if (driveFile != null && driveFile !== '') { const file = JSON.parse(driveFile); emit('removeFile', file.id); @@ -120,7 +121,7 @@ function onDrop(ev: DragEvent) { //#endregion //#region ドライブのフォルダ - const driveFolder = ev.dataTransfer.getData(_DATA_TRANSFER_DRIVE_FOLDER_); + const driveFolder = ev.dataTransfer.getData(DATA_TRANSFER_DRIVE_FOLDER); if (driveFolder != null && driveFolder !== '') { const folder = JSON.parse(driveFolder); // 移動先が自分自身ならreject diff --git a/packages/frontend/src/components/MkDrive.vue b/packages/frontend/src/components/MkDrive.vue index 72d6ae32f5..ffbe293045 100644 --- a/packages/frontend/src/components/MkDrive.vue +++ b/packages/frontend/src/components/MkDrive.vue @@ -105,7 +105,7 @@ SPDX-License-Identifier: AGPL-3.0-only :selectMode="select === 'file' || isEditMode" :isSelected="selectedFiles.some(x => x.id === file.id)" @chosen="onChooseFile" - @dragstart="isDragSource = true" + @dragstart="onFileDragstart(file, $event)" @dragend="isDragSource = false" />
@@ -152,6 +152,7 @@ import { store } from '@/store.js'; import { isSeparatorNeeded, getSeparatorInfo, makeDateGroupedTimelineComputedRef } from '@/utility/timeline-date-separate.js'; import { usePagination } from '@/composables/use-pagination.js'; import { globalEvents, useGlobalEvent } from '@/events.js'; +import { DATA_TRANSFER_DRIVE_FILE, DATA_TRANSFER_DRIVE_FILES, DATA_TRANSFER_DRIVE_FOLDER } from '@/consts.js'; const props = withDefaults(defineProps<{ initialFolder?: Misskey.entities.DriveFolder['id'] | null; @@ -250,6 +251,19 @@ function onStreamDriveFileCreated(file: Misskey.entities.DriveFile) { } } +function onFileDragstart(file: Misskey.entities.DriveFile, ev: DragEvent) { + if (isEditMode.value) { + if (!selectedFiles.value.some(f => f.id === file.id)) { + selectedFiles.value.push(file); + } + + ev.dataTransfer.effectAllowed = 'move'; + ev.dataTransfer.setData(DATA_TRANSFER_DRIVE_FILES, JSON.stringify(selectedFiles.value)); + } + + isDragSource.value = true; +} + function onDragover(ev: DragEvent) { if (!ev.dataTransfer) return; @@ -261,8 +275,8 @@ function onDragover(ev: DragEvent) { } const isFile = ev.dataTransfer.items[0].kind === 'file'; - const isDriveFile = ev.dataTransfer.types[0] === _DATA_TRANSFER_DRIVE_FILE_; - const isDriveFolder = ev.dataTransfer.types[0] === _DATA_TRANSFER_DRIVE_FOLDER_; + const isDriveFile = ev.dataTransfer.types[0] === DATA_TRANSFER_DRIVE_FILE; + const isDriveFolder = ev.dataTransfer.types[0] === DATA_TRANSFER_DRIVE_FOLDER; if (isFile || isDriveFile || isDriveFolder) { switch (ev.dataTransfer.effectAllowed) { case 'all': @@ -309,7 +323,7 @@ function onDrop(ev: DragEvent) { } //#region ドライブのファイル - const driveFile = ev.dataTransfer.getData(_DATA_TRANSFER_DRIVE_FILE_); + const driveFile = ev.dataTransfer.getData(DATA_TRANSFER_DRIVE_FILE); if (driveFile != null && driveFile !== '') { const file = JSON.parse(driveFile); if (filesPaginator.items.value.some(f => f.id === file.id)) return; @@ -322,7 +336,7 @@ function onDrop(ev: DragEvent) { //#endregion //#region ドライブのフォルダ - const driveFolder = ev.dataTransfer.getData(_DATA_TRANSFER_DRIVE_FOLDER_); + const driveFolder = ev.dataTransfer.getData(DATA_TRANSFER_DRIVE_FOLDER); if (driveFolder != null && driveFolder !== '') { const droppedFolder = JSON.parse(driveFolder); @@ -651,7 +665,9 @@ function closeTip() { } useGlobalEvent('driveFilesMoved', (files, to) => { - // TODO + if ((to?.id ?? null) === (folder.value?.id ?? null)) { + filesPaginator.unshiftItems(files); + } }); let connection: Misskey.ChannelConnection | null = null; diff --git a/packages/frontend/src/components/MkPostForm.vue b/packages/frontend/src/components/MkPostForm.vue index 5114e98494..7678d18e58 100644 --- a/packages/frontend/src/components/MkPostForm.vue +++ b/packages/frontend/src/components/MkPostForm.vue @@ -138,6 +138,7 @@ import { prefer } from '@/preferences.js'; import { getPluginHandlers } from '@/plugin.js'; import { DI } from '@/di.js'; import { globalEvents } from '@/events.js'; +import { DATA_TRANSFER_DRIVE_FILE } from '@/consts.js'; const $i = ensureSignin(); @@ -701,7 +702,7 @@ async function onPaste(ev: ClipboardEvent) { function onDragover(ev) { if (!ev.dataTransfer.items[0]) return; const isFile = ev.dataTransfer.items[0].kind === 'file'; - const isDriveFile = ev.dataTransfer.types[0] === _DATA_TRANSFER_DRIVE_FILE_; + const isDriveFile = ev.dataTransfer.types[0] === DATA_TRANSFER_DRIVE_FILE; if (isFile || isDriveFile) { ev.preventDefault(); draghover.value = true; @@ -743,7 +744,7 @@ function onDrop(ev: DragEvent): void { } //#region ドライブのファイル - const driveFile = ev.dataTransfer?.getData(_DATA_TRANSFER_DRIVE_FILE_); + const driveFile = ev.dataTransfer?.getData(DATA_TRANSFER_DRIVE_FILE); if (driveFile != null && driveFile !== '') { const file = JSON.parse(driveFile); files.value.push(file); diff --git a/packages/frontend/src/consts.ts b/packages/frontend/src/consts.ts new file mode 100644 index 0000000000..cbc3e28556 --- /dev/null +++ b/packages/frontend/src/consts.ts @@ -0,0 +1,10 @@ +/* + * SPDX-FileCopyrightText: syuilo and misskey-project + * SPDX-License-Identifier: AGPL-3.0-only + */ + +export const DATA_TRANSFER_DRIVE_FILE = 'misskey-drive-file'; +export const DATA_TRANSFER_DRIVE_FILES = 'misskey-drive-files'; +export const DATA_TRANSFER_DRIVE_FOLDER = 'misskey-drive-folder'; +export const DATA_TRANSFER_DRIVE_FOLDERS = 'misskey-drive-folders'; +export const DATA_TRANSFER_DECK_COLUMN = 'misskey-deck-column'; diff --git a/packages/frontend/src/pages/chat/room.form.vue b/packages/frontend/src/pages/chat/room.form.vue index 9389b16ce7..ea15a126a8 100644 --- a/packages/frontend/src/pages/chat/room.form.vue +++ b/packages/frontend/src/pages/chat/room.form.vue @@ -47,6 +47,7 @@ import { misskeyApi } from '@/utility/misskey-api.js'; import { prefer } from '@/preferences.js'; import { Autocomplete } from '@/utility/autocomplete.js'; import { emojiPicker } from '@/utility/emoji-picker.js'; +import { DATA_TRANSFER_DRIVE_FILE } from '@/consts.js'; const props = defineProps<{ user?: Misskey.entities.UserDetailed | null; @@ -101,7 +102,7 @@ function onDragover(ev: DragEvent) { if (!ev.dataTransfer) return; const isFile = ev.dataTransfer.items[0].kind === 'file'; - const isDriveFile = ev.dataTransfer.types[0] === _DATA_TRANSFER_DRIVE_FILE_; + const isDriveFile = ev.dataTransfer.types[0] === DATA_TRANSFER_DRIVE_FILE; if (isFile || isDriveFile) { ev.preventDefault(); switch (ev.dataTransfer.effectAllowed) { @@ -141,7 +142,7 @@ function onDrop(ev: DragEvent): void { } //#region ドライブのファイル - const driveFile = ev.dataTransfer.getData(_DATA_TRANSFER_DRIVE_FILE_); + const driveFile = ev.dataTransfer.getData(DATA_TRANSFER_DRIVE_FILE); if (driveFile != null && driveFile !== '') { file.value = JSON.parse(driveFile); ev.preventDefault(); diff --git a/packages/frontend/src/ui/deck/column.vue b/packages/frontend/src/ui/deck/column.vue index 2085c73e03..d86d1f3d08 100644 --- a/packages/frontend/src/ui/deck/column.vue +++ b/packages/frontend/src/ui/deck/column.vue @@ -51,6 +51,7 @@ import * as os from '@/os.js'; import { i18n } from '@/i18n.js'; import { prefer } from '@/preferences.js'; import { DI } from '@/di.js'; +import { DATA_TRANSFER_DECK_COLUMN } from '@/consts.js'; provide('shouldHeaderThin', true); provide('shouldOmitHeaderTitle', true); @@ -262,7 +263,7 @@ function goTop() { function onDragstart(ev) { ev.dataTransfer.effectAllowed = 'move'; - ev.dataTransfer.setData(_DATA_TRANSFER_DECK_COLUMN_, props.column.id); + ev.dataTransfer.setData(DATA_TRANSFER_DECK_COLUMN, props.column.id); // Chromeのバグで、Dragstartハンドラ内ですぐにDOMを変更する(=リアクティブなプロパティを変更する)とDragが終了してしまう // SEE: https://stackoverflow.com/questions/19639969/html5-dragend-event-firing-immediately @@ -281,7 +282,7 @@ function onDragover(ev) { // 自分自身にはドロップさせない ev.dataTransfer.dropEffect = 'none'; } else { - const isDeckColumn = ev.dataTransfer.types[0] === _DATA_TRANSFER_DECK_COLUMN_; + const isDeckColumn = ev.dataTransfer.types[0] === DATA_TRANSFER_DECK_COLUMN; ev.dataTransfer.dropEffect = isDeckColumn ? 'move' : 'none'; @@ -297,7 +298,7 @@ function onDrop(ev) { draghover.value = false; os.deckGlobalEvents.emit('column.dragEnd'); - const id = ev.dataTransfer.getData(_DATA_TRANSFER_DECK_COLUMN_); + const id = ev.dataTransfer.getData(DATA_TRANSFER_DECK_COLUMN); if (id != null && id !== '') { swapColumn(props.column.id, id); } diff --git a/packages/frontend/vite.config.ts b/packages/frontend/vite.config.ts index aa7bf24174..71c133acc8 100644 --- a/packages/frontend/vite.config.ts +++ b/packages/frontend/vite.config.ts @@ -148,9 +148,6 @@ export function getConfig(): UserConfig { _ENV_: JSON.stringify(process.env.NODE_ENV), _DEV_: process.env.NODE_ENV !== 'production', _PERF_PREFIX_: JSON.stringify('Misskey:'), - _DATA_TRANSFER_DRIVE_FILE_: JSON.stringify('mk_drive_file'), - _DATA_TRANSFER_DRIVE_FOLDER_: JSON.stringify('mk_drive_folder'), - _DATA_TRANSFER_DECK_COLUMN_: JSON.stringify('mk_deck_column'), __VUE_OPTIONS_API__: true, __VUE_PROD_DEVTOOLS__: false, }, From 4ff3cdde873217a055c5a98f63752b00334995ae Mon Sep 17 00:00:00 2001 From: syuilo <4439005+syuilo@users.noreply.github.com> Date: Sun, 11 May 2025 09:46:52 +0900 Subject: [PATCH 18/23] wip --- .../src/components/MkDrive.folder.vue | 10 ++++---- .../src/components/MkDrive.navFolder.vue | 4 ---- packages/frontend/src/components/MkDrive.vue | 24 ++++--------------- 3 files changed, 8 insertions(+), 30 deletions(-) diff --git a/packages/frontend/src/components/MkDrive.folder.vue b/packages/frontend/src/components/MkDrive.folder.vue index e4791258c8..667369072c 100644 --- a/packages/frontend/src/components/MkDrive.folder.vue +++ b/packages/frontend/src/components/MkDrive.folder.vue @@ -43,7 +43,7 @@ import { i18n } from '@/i18n.js'; import { claimAchievement } from '@/utility/achievements.js'; import { copyToClipboard } from '@/utility/copy-to-clipboard.js'; import { prefer } from '@/preferences.js'; -import { DATA_TRANSFER_DRIVE_FILE, DATA_TRANSFER_DRIVE_FOLDER } from '@/consts.js'; +import { DATA_TRANSFER_DRIVE_FILE, DATA_TRANSFER_DRIVE_FILES, DATA_TRANSFER_DRIVE_FOLDER, DATA_TRANSFER_DRIVE_FOLDERS } from '@/consts.js'; const props = withDefaults(defineProps<{ folder: Misskey.entities.DriveFolder; @@ -59,8 +59,6 @@ const emit = defineEmits<{ (ev: 'unchose', v: Misskey.entities.DriveFolder): void; (ev: 'move', v: Misskey.entities.DriveFolder): void; (ev: 'upload', file: File, folder: Misskey.entities.DriveFolder); - (ev: 'removeFile', v: Misskey.entities.DriveFile['id']): void; - (ev: 'removeFolder', v: Misskey.entities.DriveFolder['id']): void; (ev: 'dragstart'): void; (ev: 'dragend'): void; }>(); @@ -103,9 +101,11 @@ function onDragover(ev: DragEvent) { const isFile = ev.dataTransfer.items[0].kind === 'file'; const isDriveFile = ev.dataTransfer.types[0] === DATA_TRANSFER_DRIVE_FILE; + const isDriveFiles = ev.dataTransfer.types[0] === DATA_TRANSFER_DRIVE_FILES; const isDriveFolder = ev.dataTransfer.types[0] === DATA_TRANSFER_DRIVE_FOLDER; + const isDriveFolders = ev.dataTransfer.types[0] === DATA_TRANSFER_DRIVE_FOLDERS; - if (isFile || isDriveFile || isDriveFolder) { + if (isFile || isDriveFile || isDriveFolder || isDriveFiles || isDriveFolders) { switch (ev.dataTransfer.effectAllowed) { case 'all': case 'uninitialized': @@ -152,7 +152,6 @@ function onDrop(ev: DragEvent) { const driveFile = ev.dataTransfer.getData(DATA_TRANSFER_DRIVE_FILE); if (driveFile != null && driveFile !== '') { const file = JSON.parse(driveFile); - emit('removeFile', file.id); misskeyApi('drive/files/update', { fileId: file.id, folderId: props.folder.id, @@ -168,7 +167,6 @@ function onDrop(ev: DragEvent) { // 移動先が自分自身ならreject if (folder.id === props.folder.id) return; - emit('removeFolder', folder.id); misskeyApi('drive/folders/update', { folderId: folder.id, parentId: props.folder.id, diff --git a/packages/frontend/src/components/MkDrive.navFolder.vue b/packages/frontend/src/components/MkDrive.navFolder.vue index 176aceee5a..8eb2083a01 100644 --- a/packages/frontend/src/components/MkDrive.navFolder.vue +++ b/packages/frontend/src/components/MkDrive.navFolder.vue @@ -32,8 +32,6 @@ const props = defineProps<{ const emit = defineEmits<{ (ev: 'move', v?: Misskey.entities.DriveFolder): void; (ev: 'upload', file: File, folder?: Misskey.entities.DriveFolder | null): void; - (ev: 'removeFile', v: Misskey.entities.DriveFile['id']): void; - (ev: 'removeFolder', v: Misskey.entities.DriveFolder['id']): void; }>(); const hover = ref(false); @@ -112,7 +110,6 @@ function onDrop(ev: DragEvent) { const driveFile = ev.dataTransfer.getData(DATA_TRANSFER_DRIVE_FILE); if (driveFile != null && driveFile !== '') { const file = JSON.parse(driveFile); - emit('removeFile', file.id); misskeyApi('drive/files/update', { fileId: file.id, folderId: props.folder ? props.folder.id : null, @@ -126,7 +123,6 @@ function onDrop(ev: DragEvent) { const folder = JSON.parse(driveFolder); // 移動先が自分自身ならreject if (props.folder && folder.id === props.folder.id) return; - emit('removeFolder', folder.id); misskeyApi('drive/folders/update', { folderId: folder.id, parentId: props.folder ? props.folder.id : null, diff --git a/packages/frontend/src/components/MkDrive.vue b/packages/frontend/src/components/MkDrive.vue index ffbe293045..5648a1dc4c 100644 --- a/packages/frontend/src/components/MkDrive.vue +++ b/packages/frontend/src/components/MkDrive.vue @@ -13,8 +13,6 @@ SPDX-License-Identifier: AGPL-3.0-only :parentFolder="folder" @move="move" @upload="upload" - @removeFile="removeFile" - @removeFolder="removeFolder" /> @@ -79,8 +75,6 @@ SPDX-License-Identifier: AGPL-3.0-only @unchose="unchoseFolder" @move="move" @upload="upload" - @removeFile="removeFile" - @removeFolder="removeFolder" @dragstart="isDragSource = true" @dragend="isDragSource = false" /> @@ -257,8 +251,10 @@ function onFileDragstart(file: Misskey.entities.DriveFile, ev: DragEvent) { selectedFiles.value.push(file); } - ev.dataTransfer.effectAllowed = 'move'; - ev.dataTransfer.setData(DATA_TRANSFER_DRIVE_FILES, JSON.stringify(selectedFiles.value)); + if (ev.dataTransfer) { + ev.dataTransfer.effectAllowed = 'move'; + ev.dataTransfer.setData(DATA_TRANSFER_DRIVE_FILES, JSON.stringify(selectedFiles.value)); + } } isDragSource.value = true; @@ -327,7 +323,6 @@ function onDrop(ev: DragEvent) { if (driveFile != null && driveFile !== '') { const file = JSON.parse(driveFile); if (filesPaginator.items.value.some(f => f.id === file.id)) return; - removeFile(file.id); misskeyApi('drive/files/update', { fileId: file.id, folderId: folder.value ? folder.value.id : null, @@ -343,7 +338,6 @@ function onDrop(ev: DragEvent) { // 移動先が自分自身ならreject if (folder.value && droppedFolder.id === folder.value.id) return false; if (foldersPaginator.items.value.some(f => f.id === droppedFolder.id)) return false; - removeFolder(droppedFolder.id); misskeyApi('drive/folders/update', { folderId: droppedFolder.id, parentId: folder.value ? folder.value.id : null, @@ -542,16 +536,6 @@ async function moveFilesBulk() { globalEvents.emit('driveFilesMoved', selectedFiles.value, toFolder[0]); } -function removeFolder(folderToRemove: Misskey.entities.DriveFolder | string) { - const folderIdToRemove = typeof folderToRemove === 'object' ? folderToRemove.id : folderToRemove; - foldersPaginator.removeItem(folderIdToRemove); -} - -function removeFile(file: Misskey.entities.DriveFile | string) { - const fileId = typeof file === 'object' ? file.id : file; - filesPaginator.removeItem(fileId); -} - function goRoot() { // 既にrootにいるなら何もしない if (folder.value == null) return; From 9bf9b10ba4e758ff3219e7ea56ec5203693415fc Mon Sep 17 00:00:00 2001 From: syuilo <4439005+syuilo@users.noreply.github.com> Date: Sun, 11 May 2025 09:54:59 +0900 Subject: [PATCH 19/23] wip --- .../frontend/src/components/MkDrive.folder.vue | 6 ------ .../src/components/MkDrive.navFolder.vue | 15 --------------- packages/frontend/src/components/MkDrive.vue | 18 +++++++++--------- 3 files changed, 9 insertions(+), 30 deletions(-) diff --git a/packages/frontend/src/components/MkDrive.folder.vue b/packages/frontend/src/components/MkDrive.folder.vue index 667369072c..42746aa0ec 100644 --- a/packages/frontend/src/components/MkDrive.folder.vue +++ b/packages/frontend/src/components/MkDrive.folder.vue @@ -8,7 +8,6 @@ SPDX-License-Identifier: AGPL-3.0-only :class="[$style.root, { [$style.draghover]: draghover }]" draggable="true" :title="title" - @click="onClick" @contextmenu.stop="onContextmenu" @mouseover="onMouseover" @mouseout="onMouseout" @@ -57,7 +56,6 @@ const props = withDefaults(defineProps<{ const emit = defineEmits<{ (ev: 'chosen', v: Misskey.entities.DriveFolder): void; (ev: 'unchose', v: Misskey.entities.DriveFolder): void; - (ev: 'move', v: Misskey.entities.DriveFolder): void; (ev: 'upload', file: File, folder: Misskey.entities.DriveFolder); (ev: 'dragstart'): void; (ev: 'dragend'): void; @@ -77,10 +75,6 @@ function checkboxClicked() { } } -function onClick() { - emit('move', props.folder); -} - function onMouseover() { hover.value = true; } diff --git a/packages/frontend/src/components/MkDrive.navFolder.vue b/packages/frontend/src/components/MkDrive.navFolder.vue index 8eb2083a01..d44cbb6e17 100644 --- a/packages/frontend/src/components/MkDrive.navFolder.vue +++ b/packages/frontend/src/components/MkDrive.navFolder.vue @@ -6,7 +6,6 @@ SPDX-License-Identifier: AGPL-3.0-only @@ -73,7 +73,7 @@ SPDX-License-Identifier: AGPL-3.0-only :isSelected="selectedFolders.some(x => x.id === f.id)" @chosen="chooseFolder" @unchose="unchoseFolder" - @move="move" + @click="cd(f)" @upload="upload" @dragstart="isDragSource = true" @dragend="isDragSource = false" @@ -412,7 +412,7 @@ async function renameFolder(folderToRename: Misskey.entities.DriveFolder) { }); // FIXME: 画面を更新するために自分自身に移動 - move(updatedFolder); + cd(updatedFolder); } function deleteFolder(folderToDelete: Misskey.entities.DriveFolder) { @@ -420,7 +420,7 @@ function deleteFolder(folderToDelete: Misskey.entities.DriveFolder) { folderId: folderToDelete.id, }).then(() => { // 削除時に親フォルダに移動 - move(folderToDelete.parentId); + cd(folderToDelete.parentId); }).catch(err => { switch (err.id) { case 'b0fc8a17-963c-405d-bfbc-859a487295e1': @@ -495,7 +495,7 @@ function unchoseFolder(folderToUnchose: Misskey.entities.DriveFolder) { selectedFolders.value = selectedFolders.value.filter(f => f.id !== folderToUnchose.id); } -function move(target?: Misskey.entities.DriveFolder | Misskey.entities.DriveFolder['id' | 'parentId']) { +function cd(target?: Misskey.entities.DriveFolder | Misskey.entities.DriveFolder['id' | 'parentId']) { if (!target) { goRoot(); return; @@ -663,7 +663,7 @@ onMounted(() => { } if (props.initialFolder) { - move(props.initialFolder); + cd(props.initialFolder); } else { initialize(); } From e9ee571ef3595ed5e8c3ba234cbfe763ac55ed55 Mon Sep 17 00:00:00 2001 From: syuilo <4439005+syuilo@users.noreply.github.com> Date: Sun, 11 May 2025 10:58:48 +0900 Subject: [PATCH 20/23] wip --- .../src/components/MkDrive.folder.vue | 90 ++++++++++-------- .../src/components/MkDrive.navFolder.vue | 58 ++++++++---- packages/frontend/src/components/MkDrive.vue | 92 ++++++++++++------- 3 files changed, 150 insertions(+), 90 deletions(-) diff --git a/packages/frontend/src/components/MkDrive.folder.vue b/packages/frontend/src/components/MkDrive.folder.vue index 42746aa0ec..e0d3705663 100644 --- a/packages/frontend/src/components/MkDrive.folder.vue +++ b/packages/frontend/src/components/MkDrive.folder.vue @@ -43,6 +43,7 @@ import { claimAchievement } from '@/utility/achievements.js'; import { copyToClipboard } from '@/utility/copy-to-clipboard.js'; import { prefer } from '@/preferences.js'; import { DATA_TRANSFER_DRIVE_FILE, DATA_TRANSFER_DRIVE_FILES, DATA_TRANSFER_DRIVE_FOLDER, DATA_TRANSFER_DRIVE_FOLDERS } from '@/consts.js'; +import { globalEvents } from '@/events.js'; const props = withDefaults(defineProps<{ folder: Misskey.entities.DriveFolder; @@ -143,46 +144,65 @@ function onDrop(ev: DragEvent) { } //#region ドライブのファイル - const driveFile = ev.dataTransfer.getData(DATA_TRANSFER_DRIVE_FILE); - if (driveFile != null && driveFile !== '') { - const file = JSON.parse(driveFile); - misskeyApi('drive/files/update', { - fileId: file.id, - folderId: props.folder.id, - }); + { + const driveFile = ev.dataTransfer.getData(DATA_TRANSFER_DRIVE_FILE); + if (driveFile != null && driveFile !== '') { + const file = JSON.parse(driveFile); + misskeyApi('drive/files/update', { + fileId: file.id, + folderId: props.folder.id, + }); + } + } + //#endregion + + //#region ドライブのファイル(複数) + { + const driveFiles = ev.dataTransfer.getData(DATA_TRANSFER_DRIVE_FILES); + if (driveFiles != null && driveFiles !== '') { + const files = JSON.parse(driveFiles); + misskeyApi('drive/files/move-bulk', { + fileIds: files.map(f => f.id), + folderId: props.folder.id, + }).then(() => { + globalEvents.emit('driveFilesMoved', files, props.folder); + }); + } } //#endregion //#region ドライブのフォルダ - const driveFolder = ev.dataTransfer.getData(DATA_TRANSFER_DRIVE_FOLDER); - if (driveFolder != null && driveFolder !== '') { - const folder = JSON.parse(driveFolder); + { + const driveFolder = ev.dataTransfer.getData(DATA_TRANSFER_DRIVE_FOLDER); + if (driveFolder != null && driveFolder !== '') { + const folder = JSON.parse(driveFolder); - // 移動先が自分自身ならreject - if (folder.id === props.folder.id) return; + // 移動先が自分自身ならreject + if (folder.id === props.folder.id) return; - misskeyApi('drive/folders/update', { - folderId: folder.id, - parentId: props.folder.id, - }).then(() => { + misskeyApi('drive/folders/update', { + folderId: folder.id, + parentId: props.folder.id, + }).then(() => { // noop - }).catch(err => { - switch (err.code) { - case 'RECURSIVE_NESTING': - claimAchievement('driveFolderCircularReference'); - os.alert({ - type: 'error', - title: i18n.ts.unableToProcess, - text: i18n.ts.circularReferenceFolder, - }); - break; - default: - os.alert({ - type: 'error', - text: i18n.ts.somethingHappened, - }); - } - }); + }).catch(err => { + switch (err.code) { + case 'RECURSIVE_NESTING': + claimAchievement('driveFolderCircularReference'); + os.alert({ + type: 'error', + title: i18n.ts.unableToProcess, + text: i18n.ts.circularReferenceFolder, + }); + break; + default: + os.alert({ + type: 'error', + text: i18n.ts.somethingHappened, + }); + } + }); + } } //#endregion } @@ -204,10 +224,6 @@ function onDragend() { emit('dragend'); } -function go() { - emit('move', props.folder); -} - function rename() { os.inputText({ title: i18n.ts.renameFolder, diff --git a/packages/frontend/src/components/MkDrive.navFolder.vue b/packages/frontend/src/components/MkDrive.navFolder.vue index d44cbb6e17..bbd1584057 100644 --- a/packages/frontend/src/components/MkDrive.navFolder.vue +++ b/packages/frontend/src/components/MkDrive.navFolder.vue @@ -21,7 +21,8 @@ import { ref } from 'vue'; import * as Misskey from 'misskey-js'; import { misskeyApi } from '@/utility/misskey-api.js'; import { i18n } from '@/i18n.js'; -import { DATA_TRANSFER_DRIVE_FILE, DATA_TRANSFER_DRIVE_FOLDER } from '@/consts.js'; +import { DATA_TRANSFER_DRIVE_FILE, DATA_TRANSFER_DRIVE_FILES, DATA_TRANSFER_DRIVE_FOLDER, DATA_TRANSFER_DRIVE_FOLDERS } from '@/consts.js'; +import { globalEvents } from '@/events.js'; const props = defineProps<{ folder?: Misskey.entities.DriveFolder; @@ -44,9 +45,11 @@ function onDragover(ev: DragEvent) { const isFile = ev.dataTransfer.items[0].kind === 'file'; const isDriveFile = ev.dataTransfer.types[0] === DATA_TRANSFER_DRIVE_FILE; + const isDriveFiles = ev.dataTransfer.types[0] === DATA_TRANSFER_DRIVE_FILES; const isDriveFolder = ev.dataTransfer.types[0] === DATA_TRANSFER_DRIVE_FOLDER; + const isDriveFolders = ev.dataTransfer.types[0] === DATA_TRANSFER_DRIVE_FOLDERS; - if (isFile || isDriveFile || isDriveFolder) { + if (isFile || isDriveFile || isDriveFolder || isDriveFiles || isDriveFolders) { switch (ev.dataTransfer.effectAllowed) { case 'all': case 'uninitialized': @@ -92,26 +95,45 @@ function onDrop(ev: DragEvent) { } //#region ドライブのファイル - const driveFile = ev.dataTransfer.getData(DATA_TRANSFER_DRIVE_FILE); - if (driveFile != null && driveFile !== '') { - const file = JSON.parse(driveFile); - misskeyApi('drive/files/update', { - fileId: file.id, - folderId: props.folder ? props.folder.id : null, - }); + { + const driveFile = ev.dataTransfer.getData(DATA_TRANSFER_DRIVE_FILE); + if (driveFile != null && driveFile !== '') { + const file = JSON.parse(driveFile); + misskeyApi('drive/files/update', { + fileId: file.id, + folderId: props.folder ? props.folder.id : null, + }); + } + } + //#endregion + + //#region ドライブのファイル(複数) + { + const driveFiles = ev.dataTransfer.getData(DATA_TRANSFER_DRIVE_FILES); + if (driveFiles != null && driveFiles !== '') { + const files = JSON.parse(driveFiles); + misskeyApi('drive/files/move-bulk', { + fileIds: files.map(f => f.id), + folderId: props.folder ? props.folder.id : null, + }).then(() => { + globalEvents.emit('driveFilesMoved', files, props.folder ?? null); + }); + } } //#endregion //#region ドライブのフォルダ - const driveFolder = ev.dataTransfer.getData(DATA_TRANSFER_DRIVE_FOLDER); - if (driveFolder != null && driveFolder !== '') { - const folder = JSON.parse(driveFolder); - // 移動先が自分自身ならreject - if (props.folder && folder.id === props.folder.id) return; - misskeyApi('drive/folders/update', { - folderId: folder.id, - parentId: props.folder ? props.folder.id : null, - }); + { + const driveFolder = ev.dataTransfer.getData(DATA_TRANSFER_DRIVE_FOLDER); + if (driveFolder != null && driveFolder !== '') { + const folder = JSON.parse(driveFolder); + // 移動先が自分自身ならreject + if (props.folder && folder.id === props.folder.id) return; + misskeyApi('drive/folders/update', { + folderId: folder.id, + parentId: props.folder ? props.folder.id : null, + }); + } } //#endregion } diff --git a/packages/frontend/src/components/MkDrive.vue b/packages/frontend/src/components/MkDrive.vue index e42165c3bc..d6c645c6ef 100644 --- a/packages/frontend/src/components/MkDrive.vue +++ b/packages/frontend/src/components/MkDrive.vue @@ -319,47 +319,66 @@ function onDrop(ev: DragEvent) { } //#region ドライブのファイル - const driveFile = ev.dataTransfer.getData(DATA_TRANSFER_DRIVE_FILE); - if (driveFile != null && driveFile !== '') { - const file = JSON.parse(driveFile); - if (filesPaginator.items.value.some(f => f.id === file.id)) return; - misskeyApi('drive/files/update', { - fileId: file.id, - folderId: folder.value ? folder.value.id : null, - }); + { + const driveFile = ev.dataTransfer.getData(DATA_TRANSFER_DRIVE_FILE); + if (driveFile != null && driveFile !== '') { + const file = JSON.parse(driveFile); + if (filesPaginator.items.value.some(f => f.id === file.id)) return; + misskeyApi('drive/files/update', { + fileId: file.id, + folderId: folder.value ? folder.value.id : null, + }); + } + } + //#endregion + + //#region ドライブのファイル(複数) + { + const driveFiles = ev.dataTransfer.getData(DATA_TRANSFER_DRIVE_FILES); + if (driveFiles != null && driveFiles !== '') { + const files = JSON.parse(driveFiles); + misskeyApi('drive/files/move-bulk', { + fileIds: files.map(f => f.id), + folderId: folder.value ? folder.value.id : null, + }).then(() => { + globalEvents.emit('driveFilesMoved', files, folder.value); + }); + } } //#endregion //#region ドライブのフォルダ - const driveFolder = ev.dataTransfer.getData(DATA_TRANSFER_DRIVE_FOLDER); - if (driveFolder != null && driveFolder !== '') { - const droppedFolder = JSON.parse(driveFolder); + { + const driveFolder = ev.dataTransfer.getData(DATA_TRANSFER_DRIVE_FOLDER); + if (driveFolder != null && driveFolder !== '') { + const droppedFolder = JSON.parse(driveFolder); - // 移動先が自分自身ならreject - if (folder.value && droppedFolder.id === folder.value.id) return false; - if (foldersPaginator.items.value.some(f => f.id === droppedFolder.id)) return false; - misskeyApi('drive/folders/update', { - folderId: droppedFolder.id, - parentId: folder.value ? folder.value.id : null, - }).then(() => { + // 移動先が自分自身ならreject + if (folder.value && droppedFolder.id === folder.value.id) return false; + if (foldersPaginator.items.value.some(f => f.id === droppedFolder.id)) return false; + misskeyApi('drive/folders/update', { + folderId: droppedFolder.id, + parentId: folder.value ? folder.value.id : null, + }).then(() => { // noop - }).catch(err => { - switch (err.code) { - case 'RECURSIVE_NESTING': - claimAchievement('driveFolderCircularReference'); - os.alert({ - type: 'error', - title: i18n.ts.unableToProcess, - text: i18n.ts.circularReferenceFolder, - }); - break; - default: - os.alert({ - type: 'error', - text: i18n.ts.somethingHappened, - }); - } - }); + }).catch(err => { + switch (err.code) { + case 'RECURSIVE_NESTING': + claimAchievement('driveFolderCircularReference'); + os.alert({ + type: 'error', + title: i18n.ts.unableToProcess, + text: i18n.ts.circularReferenceFolder, + }); + break; + default: + os.alert({ + type: 'error', + text: i18n.ts.somethingHappened, + }); + } + }); + } } //#endregion } @@ -649,6 +668,9 @@ function closeTip() { } useGlobalEvent('driveFilesMoved', (files, to) => { + for (const f of files) { + filesPaginator.removeItem(f.id); + } if ((to?.id ?? null) === (folder.value?.id ?? null)) { filesPaginator.unshiftItems(files); } From f239e6fc62279d06144496ff82b135e8297dfaa8 Mon Sep 17 00:00:00 2001 From: syuilo <4439005+syuilo@users.noreply.github.com> Date: Sun, 11 May 2025 11:11:58 +0900 Subject: [PATCH 21/23] wip --- packages/frontend/src/components/MkDrive.folder.vue | 2 ++ packages/frontend/src/components/MkDrive.navFolder.vue | 2 ++ packages/frontend/src/components/MkDrive.vue | 2 ++ packages/frontend/src/components/MkDriveFileSelectDialog.vue | 2 +- packages/frontend/src/components/MkDriveFolderSelectDialog.vue | 2 +- 5 files changed, 8 insertions(+), 2 deletions(-) diff --git a/packages/frontend/src/components/MkDrive.folder.vue b/packages/frontend/src/components/MkDrive.folder.vue index e0d3705663..488844e77a 100644 --- a/packages/frontend/src/components/MkDrive.folder.vue +++ b/packages/frontend/src/components/MkDrive.folder.vue @@ -151,6 +151,8 @@ function onDrop(ev: DragEvent) { misskeyApi('drive/files/update', { fileId: file.id, folderId: props.folder.id, + }).then(() => { + globalEvents.emit('driveFilesMoved', [file], props.folder); }); } } diff --git a/packages/frontend/src/components/MkDrive.navFolder.vue b/packages/frontend/src/components/MkDrive.navFolder.vue index bbd1584057..6b106810cd 100644 --- a/packages/frontend/src/components/MkDrive.navFolder.vue +++ b/packages/frontend/src/components/MkDrive.navFolder.vue @@ -102,6 +102,8 @@ function onDrop(ev: DragEvent) { misskeyApi('drive/files/update', { fileId: file.id, folderId: props.folder ? props.folder.id : null, + }).then(() => { + globalEvents.emit('driveFilesMoved', [file], props.folder ?? null); }); } } diff --git a/packages/frontend/src/components/MkDrive.vue b/packages/frontend/src/components/MkDrive.vue index d6c645c6ef..6b32820a84 100644 --- a/packages/frontend/src/components/MkDrive.vue +++ b/packages/frontend/src/components/MkDrive.vue @@ -327,6 +327,8 @@ function onDrop(ev: DragEvent) { misskeyApi('drive/files/update', { fileId: file.id, folderId: folder.value ? folder.value.id : null, + }).then(() => { + globalEvents.emit('driveFilesMoved', [file], folder.value); }); } } diff --git a/packages/frontend/src/components/MkDriveFileSelectDialog.vue b/packages/frontend/src/components/MkDriveFileSelectDialog.vue index 9cccd4ab5e..50b68b3d0f 100644 --- a/packages/frontend/src/components/MkDriveFileSelectDialog.vue +++ b/packages/frontend/src/components/MkDriveFileSelectDialog.vue @@ -19,7 +19,7 @@ SPDX-License-Identifier: AGPL-3.0-only {{ multiple ? i18n.ts.selectFiles : i18n.ts.selectFile }} ({{ selected.length }}) - + diff --git a/packages/frontend/src/components/MkDriveFolderSelectDialog.vue b/packages/frontend/src/components/MkDriveFolderSelectDialog.vue index adc85c49e1..2ebab1088f 100644 --- a/packages/frontend/src/components/MkDriveFolderSelectDialog.vue +++ b/packages/frontend/src/components/MkDriveFolderSelectDialog.vue @@ -19,7 +19,7 @@ SPDX-License-Identifier: AGPL-3.0-only {{ multiple ? i18n.ts.selectFolders : i18n.ts.selectFolder }} ({{ selected.length }}) - + From cf701f389d0c4aa40b992a7ec57a832d70ffe6c6 Mon Sep 17 00:00:00 2001 From: syuilo <4439005+syuilo@users.noreply.github.com> Date: Sun, 11 May 2025 13:11:05 +0900 Subject: [PATCH 22/23] wip --- .../frontend/src/components/MkDrive.file.vue | 4 +- .../src/components/MkDrive.folder.vue | 24 ++------- .../src/components/MkDrive.navFolder.vue | 22 ++------ packages/frontend/src/components/MkDrive.vue | 54 ++++++++++--------- .../frontend/src/components/MkPostForm.vue | 17 +++--- packages/frontend/src/consts.ts | 2 - .../frontend/src/pages/chat/room.form.vue | 16 +++--- 7 files changed, 57 insertions(+), 82 deletions(-) diff --git a/packages/frontend/src/components/MkDrive.file.vue b/packages/frontend/src/components/MkDrive.file.vue index 8cd28375c4..b84badf71f 100644 --- a/packages/frontend/src/components/MkDrive.file.vue +++ b/packages/frontend/src/components/MkDrive.file.vue @@ -48,7 +48,7 @@ import { $i } from '@/i.js'; import { getDriveFileMenu } from '@/utility/get-drive-file-menu.js'; import { deviceKind } from '@/utility/device-kind.js'; import { useRouter } from '@/router.js'; -import { DATA_TRANSFER_DRIVE_FILE } from '@/consts.js'; +import { DATA_TRANSFER_DRIVE_FILES } from '@/consts.js'; const router = useRouter(); @@ -91,7 +91,7 @@ function onContextmenu(ev: MouseEvent) { function onDragstart(ev: DragEvent) { if (ev.dataTransfer) { ev.dataTransfer.effectAllowed = 'move'; - ev.dataTransfer.setData(DATA_TRANSFER_DRIVE_FILE, JSON.stringify(props.file)); + ev.dataTransfer.setData(DATA_TRANSFER_DRIVE_FILES, JSON.stringify([props.file])); } isDragging.value = true; diff --git a/packages/frontend/src/components/MkDrive.folder.vue b/packages/frontend/src/components/MkDrive.folder.vue index 488844e77a..61de77ade3 100644 --- a/packages/frontend/src/components/MkDrive.folder.vue +++ b/packages/frontend/src/components/MkDrive.folder.vue @@ -42,7 +42,7 @@ import { i18n } from '@/i18n.js'; import { claimAchievement } from '@/utility/achievements.js'; import { copyToClipboard } from '@/utility/copy-to-clipboard.js'; import { prefer } from '@/preferences.js'; -import { DATA_TRANSFER_DRIVE_FILE, DATA_TRANSFER_DRIVE_FILES, DATA_TRANSFER_DRIVE_FOLDER, DATA_TRANSFER_DRIVE_FOLDERS } from '@/consts.js'; +import { DATA_TRANSFER_DRIVE_FILES, DATA_TRANSFER_DRIVE_FOLDERS } from '@/consts.js'; import { globalEvents } from '@/events.js'; const props = withDefaults(defineProps<{ @@ -95,12 +95,10 @@ function onDragover(ev: DragEvent) { } const isFile = ev.dataTransfer.items[0].kind === 'file'; - const isDriveFile = ev.dataTransfer.types[0] === DATA_TRANSFER_DRIVE_FILE; const isDriveFiles = ev.dataTransfer.types[0] === DATA_TRANSFER_DRIVE_FILES; - const isDriveFolder = ev.dataTransfer.types[0] === DATA_TRANSFER_DRIVE_FOLDER; const isDriveFolders = ev.dataTransfer.types[0] === DATA_TRANSFER_DRIVE_FOLDERS; - if (isFile || isDriveFile || isDriveFolder || isDriveFiles || isDriveFolders) { + if (isFile || isDriveFiles || isDriveFolders) { switch (ev.dataTransfer.effectAllowed) { case 'all': case 'uninitialized': @@ -144,21 +142,6 @@ function onDrop(ev: DragEvent) { } //#region ドライブのファイル - { - const driveFile = ev.dataTransfer.getData(DATA_TRANSFER_DRIVE_FILE); - if (driveFile != null && driveFile !== '') { - const file = JSON.parse(driveFile); - misskeyApi('drive/files/update', { - fileId: file.id, - folderId: props.folder.id, - }).then(() => { - globalEvents.emit('driveFilesMoved', [file], props.folder); - }); - } - } - //#endregion - - //#region ドライブのファイル(複数) { const driveFiles = ev.dataTransfer.getData(DATA_TRANSFER_DRIVE_FILES); if (driveFiles != null && driveFiles !== '') { @@ -174,8 +157,9 @@ function onDrop(ev: DragEvent) { //#endregion //#region ドライブのフォルダ + // TODO { - const driveFolder = ev.dataTransfer.getData(DATA_TRANSFER_DRIVE_FOLDER); + const driveFolder = ev.dataTransfer.getData(DATA_TRANSFER_DRIVE_FOLDERS); if (driveFolder != null && driveFolder !== '') { const folder = JSON.parse(driveFolder); diff --git a/packages/frontend/src/components/MkDrive.navFolder.vue b/packages/frontend/src/components/MkDrive.navFolder.vue index 6b106810cd..dd7031f111 100644 --- a/packages/frontend/src/components/MkDrive.navFolder.vue +++ b/packages/frontend/src/components/MkDrive.navFolder.vue @@ -21,7 +21,7 @@ import { ref } from 'vue'; import * as Misskey from 'misskey-js'; import { misskeyApi } from '@/utility/misskey-api.js'; import { i18n } from '@/i18n.js'; -import { DATA_TRANSFER_DRIVE_FILE, DATA_TRANSFER_DRIVE_FILES, DATA_TRANSFER_DRIVE_FOLDER, DATA_TRANSFER_DRIVE_FOLDERS } from '@/consts.js'; +import { DATA_TRANSFER_DRIVE_FILES, DATA_TRANSFER_DRIVE_FOLDERS } from '@/consts.js'; import { globalEvents } from '@/events.js'; const props = defineProps<{ @@ -44,12 +44,10 @@ function onDragover(ev: DragEvent) { } const isFile = ev.dataTransfer.items[0].kind === 'file'; - const isDriveFile = ev.dataTransfer.types[0] === DATA_TRANSFER_DRIVE_FILE; const isDriveFiles = ev.dataTransfer.types[0] === DATA_TRANSFER_DRIVE_FILES; - const isDriveFolder = ev.dataTransfer.types[0] === DATA_TRANSFER_DRIVE_FOLDER; const isDriveFolders = ev.dataTransfer.types[0] === DATA_TRANSFER_DRIVE_FOLDERS; - if (isFile || isDriveFile || isDriveFolder || isDriveFiles || isDriveFolders) { + if (isFile || isDriveFiles || isDriveFolders) { switch (ev.dataTransfer.effectAllowed) { case 'all': case 'uninitialized': @@ -95,21 +93,6 @@ function onDrop(ev: DragEvent) { } //#region ドライブのファイル - { - const driveFile = ev.dataTransfer.getData(DATA_TRANSFER_DRIVE_FILE); - if (driveFile != null && driveFile !== '') { - const file = JSON.parse(driveFile); - misskeyApi('drive/files/update', { - fileId: file.id, - folderId: props.folder ? props.folder.id : null, - }).then(() => { - globalEvents.emit('driveFilesMoved', [file], props.folder ?? null); - }); - } - } - //#endregion - - //#region ドライブのファイル(複数) { const driveFiles = ev.dataTransfer.getData(DATA_TRANSFER_DRIVE_FILES); if (driveFiles != null && driveFiles !== '') { @@ -125,6 +108,7 @@ function onDrop(ev: DragEvent) { //#endregion //#region ドライブのフォルダ + // TODO { const driveFolder = ev.dataTransfer.getData(DATA_TRANSFER_DRIVE_FOLDER); if (driveFolder != null && driveFolder !== '') { diff --git a/packages/frontend/src/components/MkDrive.vue b/packages/frontend/src/components/MkDrive.vue index 6b32820a84..a0896d4b4f 100644 --- a/packages/frontend/src/components/MkDrive.vue +++ b/packages/frontend/src/components/MkDrive.vue @@ -83,14 +83,22 @@ SPDX-License-Identifier: AGPL-3.0-only
- + -
+ -
+
{{ i18n.ts.loadMore }}
@@ -126,7 +134,7 @@ SPDX-License-Identifier: AGPL-3.0-only