From 45f909ef33056ac8f429d2a1707d1d7da96d2970 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E3=81=8B=E3=81=A3=E3=81=93=E3=81=8B=E3=82=8A?= <67428053+kakkokari-gtyih@users.noreply.github.com> Date: Tue, 30 Jul 2024 14:42:46 +0900 Subject: [PATCH] =?UTF-8?q?enhance(frontend):=20=E3=83=89=E3=83=A9?= =?UTF-8?q?=E3=82=A4=E3=83=96=E3=81=AE=E3=83=95=E3=82=A1=E3=82=A4=E3=83=AB?= =?UTF-8?q?=E3=83=BB=E3=83=95=E3=82=A9=E3=83=AB=E3=83=80=E3=82=92=E3=83=89?= =?UTF-8?q?=E3=83=A9=E3=83=83=E3=82=B0=E3=81=97=E3=81=AA=E3=81=8F=E3=81=A6?= =?UTF-8?q?=E3=82=82=E7=A7=BB=E5=8B=95=E3=81=A7=E3=81=8D=E3=82=8B=E3=82=88?= =?UTF-8?q?=E3=81=86=E3=81=AB=20(#14318)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * feat(drive): ファイルをフォルダに移動するメニューを実装 (cherry picked from commit b89c2af6945c6a9f9f10e83f54d2bcf0f240b0b4) * tweak ui * Update Changelog * ファイル詳細からも移動できるように * feat(drive) フォルダのネストを移動するメニューを実装 (cherry picked from commit 8a7d710c6acb83f50c83f050bd1423c764d60a99) * Update Changelog * Update Changelog * lint * tweak ui --------- Co-authored-by: nafu-at Co-authored-by: syuilo <4439005+syuilo@users.noreply.github.com> --- CHANGELOG.md | 2 + .../src/components/MkDrive.folder.vue | 70 ++++++++++++++++--- packages/frontend/src/components/MkDrive.vue | 6 ++ .../frontend/src/pages/drive.file.info.vue | 43 ++++++++++-- .../src/scripts/get-drive-file-menu.ts | 13 ++++ 5 files changed, 117 insertions(+), 17 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f3ea5ca2d..0be36a2cb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -25,6 +25,8 @@ - Enhance: AiScriptを0.19.0にアップデート - Enhance: Allow negative delay for MFM animation elements (`tada`, `jelly`, `twitch`, `shake`, `spin`, `jump`, `bounce`, `rainbow`) - Enhance: センシティブなメディアを開く際に確認ダイアログを出せるように +- Enhance: ドライブのファイル・フォルダをドラッグしなくても移動できるように + (Cherry-picked from https://github.com/nafu-at/misskey/commit/b89c2af6945c6a9f9f10e83f54d2bcf0f240b0b4, https://github.com/nafu-at/misskey/commit/8a7d710c6acb83f50c83f050bd1423c764d60a99) - Enhance: デッキのアンテナ・リスト選択画面からそれぞれを新規作成できるように - Fix: `/about#federation` ページなどで各インスタンスのチャートが表示されなくなっていた問題を修正 - Fix: ユーザーページの追加情報のラベルを投稿者のサーバーの絵文字で表示する (#13968) diff --git a/packages/frontend/src/components/MkDrive.folder.vue b/packages/frontend/src/components/MkDrive.folder.vue index c940596cd..d6dfaf34e 100644 --- a/packages/frontend/src/components/MkDrive.folder.vue +++ b/packages/frontend/src/components/MkDrive.folder.vue @@ -27,7 +27,9 @@ SPDX-License-Identifier: AGPL-3.0-only

{{ i18n.ts.uploadFolder }}

- + @@ -53,6 +55,7 @@ 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: 'removeFile', v: Misskey.entities.DriveFile['id']): void; @@ -68,7 +71,11 @@ const isDragging = ref(false); const title = computed(() => props.folder.name); function checkboxClicked() { - emit('chosen', props.folder); + if (props.isSelected) { + emit('unchose', props.folder); + } else { + emit('chosen', props.folder); + } } function onClick() { @@ -222,6 +229,17 @@ function rename() { }); } +function move() { + os.selectDriveFolder(false).then(folder => { + if (folder[0] && folder[0].id === props.folder.id) return; + + misskeyApi('drive/folders/update', { + folderId: props.folder.id, + parentId: folder[0] ? folder[0].id : null, + }); + }); +} + function deleteFolder() { misskeyApi('drive/folders/delete', { folderId: props.folder.id, @@ -267,6 +285,10 @@ function onContextmenu(ev: MouseEvent) { text: i18n.ts.rename, icon: 'ti ti-forms', action: rename, + }, { + text: i18n.ts.move, + icon: 'ti ti ti-folder-symlink', + action: move, }, { type: 'divider' }, { text: i18n.ts.delete, icon: 'ti ti-trash', @@ -310,17 +332,43 @@ function onContextmenu(ev: MouseEvent) { } } -.checkbox { +.checkboxWrapper { position: absolute; - bottom: 8px; - right: 8px; - width: 16px; - height: 16px; - background: #fff; - border: solid 1px #000; + border-radius: 50%; + bottom: 2px; + right: 2px; + padding: 8px; + box-sizing: border-box; - &.checked { - background: var(--accent); + > .checkbox { + position: relative; + width: 18px; + height: 18px; + background: #fff; + border: solid 2px var(--divider); + border-radius: 4px; + box-sizing: border-box; + + &.checked { + border-color: var(--accent); + background: var(--accent); + + &::after { + content: "\ea5e"; + font-family: 'tabler-icons'; + position: absolute; + top: 50%; + left: 50%; + transform: translate(-50%, -50%); + color: #fff; + font-size: 12px; + line-height: 22px; + } + } + } + + &:hover { + background: var(--accentedBg); } } diff --git a/packages/frontend/src/components/MkDrive.vue b/packages/frontend/src/components/MkDrive.vue index a9717b4fb..dbb491706 100644 --- a/packages/frontend/src/components/MkDrive.vue +++ b/packages/frontend/src/components/MkDrive.vue @@ -52,6 +52,7 @@ SPDX-License-Identifier: AGPL-3.0-only :selectMode="select === 'folder'" :isSelected="selectedFolders.some(x => x.id === f.id)" @chosen="chooseFolder" + @unchose="unchoseFolder" @move="move" @upload="upload" @removeFile="removeFile" @@ -428,6 +429,11 @@ function chooseFolder(folderToChoose: Misskey.entities.DriveFolder) { } } +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']) { if (!target) { goRoot(); diff --git a/packages/frontend/src/pages/drive.file.info.vue b/packages/frontend/src/pages/drive.file.info.vue index a774412f8..3026d00a2 100644 --- a/packages/frontend/src/pages/drive.file.info.vue +++ b/packages/frontend/src/pages/drive.file.info.vue @@ -37,11 +37,17 @@ SPDX-License-Identifier: AGPL-3.0-only -
- + @@ -90,6 +96,18 @@ const props = defineProps<{ const fetching = ref(true); const file = ref(); +const folderHierarchy = computed(() => { + if (!file.value) return [i18n.ts.drive]; + const folderNames = [i18n.ts.drive]; + + function get(folder: Misskey.entities.DriveFolder) { + if (folder.parent) get(folder.parent); + folderNames.push(folder.name); + } + + if (file.value.folder) get(file.value.folder); + return folderNames; +}); const isImage = computed(() => file.value?.type.startsWith('image/')); async function fetch() { @@ -122,6 +140,19 @@ function crop() { }); } +function move() { + if (!file.value) return; + + os.selectDriveFolder(false).then(folder => { + misskeyApi('drive/files/update', { + fileId: file.value.id, + folderId: folder[0] ? folder[0].id : null, + }).then(async () => { + await fetch(); + }); + }); +} + function toggleSensitive() { if (!file.value) return; @@ -282,14 +313,14 @@ onMounted(async () => { padding: .5rem 1rem; } -.fileAltEditBtn { +.kvEditBtn { text-align: start; display: block; width: 100%; padding: .5rem 1rem; border-radius: var(--radius); - .fileAltEditIcon { + .kvEditIcon { display: inline-block; color: transparent; visibility: hidden; @@ -300,7 +331,7 @@ onMounted(async () => { color: var(--accent); background-color: var(--accentedBg); - .fileAltEditIcon { + .kvEditIcon { color: var(--accent); visibility: visible; } diff --git a/packages/frontend/src/scripts/get-drive-file-menu.ts b/packages/frontend/src/scripts/get-drive-file-menu.ts index 7c6c4b4db..108648d64 100644 --- a/packages/frontend/src/scripts/get-drive-file-menu.ts +++ b/packages/frontend/src/scripts/get-drive-file-menu.ts @@ -41,6 +41,15 @@ function describe(file: Misskey.entities.DriveFile) { }); } +function move(file: Misskey.entities.DriveFile) { + os.selectDriveFolder(false).then(folder => { + misskeyApi('drive/files/update', { + fileId: file.id, + folderId: folder[0] ? folder[0].id : null, + }); + }); +} + function toggleSensitive(file: Misskey.entities.DriveFile) { misskeyApi('drive/files/update', { fileId: file.id, @@ -88,6 +97,10 @@ export function getDriveFileMenu(file: Misskey.entities.DriveFile, folder?: Miss text: i18n.ts.rename, icon: 'ti ti-forms', action: () => rename(file), + }, { + text: i18n.ts.move, + icon: 'ti ti-folder-symlink', + action: () => move(file), }, { text: file.isSensitive ? i18n.ts.unmarkAsSensitive : i18n.ts.markAsSensitive, icon: file.isSensitive ? 'ti ti-eye' : 'ti ti-eye-exclamation',