Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement and Enhance File Move Functionality (Closes #943) #2341

Open
wants to merge 4 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions public/locales/ar/app.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
"close": "أغلق",
"copy": "نسخ",
"create": "إنشاء ",
"move": "تحريك",
"remove": "إزالة",
"download": "تحميل",
"edit": "تعديل",
Expand Down
1 change: 1 addition & 0 deletions public/locales/ca/app.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
"copy": "Copia",
"create": "Crea",
"remove": "Treu",
"move": "Mou",
"download": "Descarrega",
"edit": "Edita",
"import": "Importa",
Expand Down
1 change: 1 addition & 0 deletions public/locales/cs/app.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
"close": "Zavřít",
"copy": "Zkopírovat",
"create": "Vytvořit",
"move": "Přesunout",
"remove": "Odstranit",
"download": "Stáhnout",
"edit": "Upravit",
Expand Down
1 change: 1 addition & 0 deletions public/locales/de/app.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
"change": "Ändern",
"clear": "Löschen",
"close": "Schließen",
"move": "Verschieben",
"copy": "Kopieren",
"create": "Erstellen",
"remove": "Entfernen",
Expand Down
1 change: 1 addition & 0 deletions public/locales/en/app.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
"copy": "Copy",
"create": "Create",
"remove": "Remove",
"move": "Move",
"download": "Download",
"edit": "Edit",
"import": "Import",
Expand Down
7 changes: 7 additions & 0 deletions public/locales/en/files.json
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,13 @@
"descriptionFile": "Choose a new name for this file.",
"descriptionFolder": "Choose a new name for this folder."
},
"moveModal": {
"titleFiles": "{count, plural, one {Move file} other {Move {count} files}}",
"titleFolder": "Move folder",
"descriptionFiles": "{count, plural, one {Choose a new location for this file.} other {Choose a new location for these {count} files.}}",
"descriptionFolder": "Choose a new location for this folder.",
"directoryCreationInfo": "If the directory does not exist, it will be created automatically"
},
"removeModal": {
"titleItem": "{count, plural, one {Remove item? {name}} other {Remove {count} items?}}",
"titleFolder": "{count, plural, one {Remove folder? {name}} other {Remove {count} folders?}}",
Expand Down
1 change: 1 addition & 0 deletions public/locales/es/app.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
"change": "Cambio",
"clear": "Limpiar",
"close": "Cerrar",
"move": "Mover",
"copy": "Copiar",
"create": "Crear",
"remove": "Eliminar",
Expand Down
1 change: 1 addition & 0 deletions public/locales/fi/app.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
"close": "Sulje",
"copy": "Kopioi",
"create": "Luo",
"move": "Siirrä",
"remove": "Poista",
"download": "Lataa",
"edit": "Muokkaa",
Expand Down
1 change: 1 addition & 0 deletions public/locales/fr/app.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
"cancel": "Annuler",
"change": "Modifier",
"clear": "Effacer",
"move": "Déplacer",
"close": "Fermer",
"copy": "Copier",
"create": "Créer",
Expand Down
1 change: 1 addition & 0 deletions public/locales/hu/app.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
"clear": "Törlés",
"close": "Bezárás",
"copy": "Másolás",
"move": "Áthelyezés",
"create": "Létrehozás",
"remove": "Remove",
"download": "Letölt",
Expand Down
1 change: 1 addition & 0 deletions public/locales/id/app.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
"change": "Mengubah",
"clear": "Bersihkan",
"close": "Tutup",
"move": "Pindahkan",
"copy": "Salin",
"create": "Buat",
"remove": "Hapus",
Expand Down
1 change: 1 addition & 0 deletions public/locales/it/app.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
"cancel": "Annulla",
"change": "Cambia",
"clear": "Svuota",
"move": "Sposta",
"close": "Chiudi",
"copy": "Copia",
"create": "Crea",
Expand Down
1 change: 1 addition & 0 deletions public/locales/ja-JP/app.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
"change": "変更",
"clear": "クリア",
"close": "閉じる",
"move": "移動",
"copy": "コピー",
"create": "作成",
"remove": "削除",
Expand Down
1 change: 1 addition & 0 deletions public/locales/ko-KR/app.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
"copy": "Copy",
"create": "Create",
"remove": "Remove",
"move": "Move",
"download": "Download",
"edit": "Edit",
"import": "Import",
Expand Down
1 change: 1 addition & 0 deletions public/locales/pl/app.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
"create": "Utwórz",
"remove": "Usuń",
"download": "Pobierz",
"move": "Przenieś",
"edit": "Edytuj",
"import": "Import",
"inspect": "Analizuj",
Expand Down
1 change: 1 addition & 0 deletions public/locales/ru/app.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
"create": "Создать",
"remove": "Удалить",
"download": "Загрузить",
"move": "Переместить",
"edit": "Изменить",
"import": "Импорт",
"inspect": "Проверить",
Expand Down
1 change: 1 addition & 0 deletions public/locales/tr/app.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
"create": "Oluştur",
"remove": "Kaldır",
"download": "İndir",
"move": "Taşı",
"edit": "Düzenle",
"import": "İçe aktar",
"inspect": "İncele",
Expand Down
1 change: 1 addition & 0 deletions public/locales/ur/app.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
"copy": "نقل کریں",
"create": "تشکیل دیں",
"remove": "Remove",
"move": "پیچھے کریں",
"download": "ڈاؤنلوڈ کریں",
"edit": "ترمیم کریں",
"import": "درآمد کریں",
Expand Down
1 change: 1 addition & 0 deletions public/locales/zh-CN/app.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
"copy": "复制",
"create": "创建",
"remove": "移除",
"move": "移动",
"download": "下载",
"edit": "编辑",
"import": "导入",
Expand Down
1 change: 1 addition & 0 deletions public/locales/zh-TW/app.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
"remove": "移除",
"download": "下載",
"edit": "編輯",
"move": "移動",
"import": "匯入",
"inspect": "檢查",
"more": "更多",
Expand Down
51 changes: 51 additions & 0 deletions src/bundles/files/actions.js
Original file line number Diff line number Diff line change
Expand Up @@ -185,6 +185,57 @@ const actions = () => ({
}
},

/**
* Fetches directory contents with optimized performance
* @param {string} path - Directory path to fetch
*/
doFetchDirectory: (path) => perform(ACTIONS.DIRECTORY_FETCH, async (ipfs) => {
if (!ipfs) {
throw new Error('IPFS is not available')
}

try {
const resolvedPath = path.startsWith('/ipns') ? await last(ipfs.name.resolve(path)) : path

const stats = await stat(ipfs, resolvedPath)

if (stats.type !== 'directory') {
return {
path,
type: stats.type,
content: []
}
}

const entries = []
for await (const entry of ipfs.ls(stats.cid)) {
if (entry.type === 'dir') {
entries.push({
name: entry.name,
type: entry.type,
path: entry.path,
size: entry.size,
cid: entry.cid
})
}
}

entries.sort((a, b) => a.name.localeCompare(b.name))

return {
path,
type: 'directory',
content: entries
}
} catch (err) {
return {
path,
type: 'unknown',
content: []
}
}
}),

/**
* Fetches conten for the currently selected path. And updates
* `state.pageContent` on succesful completion.
Expand Down
4 changes: 3 additions & 1 deletion src/bundles/files/consts.js
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,9 @@ export const ACTIONS = {
/** @type {'FILES_WRITE_UPDATED'} */
WRITE_UPDATED: ('FILES_WRITE_UPDATED'),
/** @type {'FILES_UPDATE_SORT'} */
UPDATE_SORT: ('FILES_UPDATE_SORT')
UPDATE_SORT: ('FILES_UPDATE_SORT'),
/** @type {'FILES_DIRECTORY_FETCH'} */
DIRECTORY_FETCH: ('FILES_DIRECTORY_FETCH')
}

export const SORTING = {
Expand Down
9 changes: 6 additions & 3 deletions src/files/FilesPage.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import FilesList from './files-list/FilesList.js'
import { getJoyrideLocales } from '../helpers/i8n.js'

// Icons
import Modals, { DELETE, NEW_FOLDER, SHARE, RENAME, ADD_BY_PATH, BULK_CID_IMPORT, CLI_TUTOR_MODE, PINNING, PUBLISH } from './modals/Modals.js'
import Modals, { DELETE, NEW_FOLDER, SHARE, RENAME, ADD_BY_PATH, BULK_CID_IMPORT, CLI_TUTOR_MODE, PINNING, PUBLISH, MOVE } from './modals/Modals.js'
import Header from './header/Header.js'
import FileImportStatus from './file-import-status/FileImportStatus.js'
import { useExplore } from 'ipld-explorer-components/providers'
Expand All @@ -24,7 +24,7 @@ const FilesPage = ({
doFetchPinningServices, doFilesFetch, doPinsFetch, doFilesSizeGet, doFilesDownloadLink, doFilesDownloadCarLink, doFilesWrite, doFilesBulkCidImport, doFilesAddPath, doUpdateHash,
doFilesUpdateSorting, doFilesNavigateTo, doFilesMove, doSetCliOptions, doFetchRemotePins, remotePins, pendingPins, failedPins,
ipfsProvider, ipfsConnected, doFilesMakeDir, doFilesShareLink, doFilesDelete, doSetPinning, onRemotePinClick, doPublishIpnsKey,
files, filesPathInfo, pinningServices, toursEnabled, handleJoyrideCallback, isCliTutorModeEnabled, cliOptions, t
files, filesPathInfo, doFetchDirectory, pinningServices, toursEnabled, handleJoyrideCallback, isCliTutorModeEnabled, cliOptions, t
}) => {
const { doExploreUserProvidedPath } = useExplore()
const contextMenuRef = useRef()
Expand Down Expand Up @@ -150,13 +150,13 @@ const FilesPage = ({
onShare={(files) => showModal(SHARE, files)}
onRename={(files) => showModal(RENAME, files)}
onRemove={(files) => showModal(DELETE, files)}
onMove={(files) => showModal(MOVE, files)}
onSetPinning={(files) => showModal(PINNING, files)}
onInspect={onInspect}
onRemotePinClick={onRemotePinClick}
onDownload={onDownload}
onAddFiles={onAddFiles}
onNavigate={doFilesNavigateTo}
onMove={doFilesMove}
handleContextMenuClick={handleContextMenu} />
)
}
Expand Down Expand Up @@ -227,6 +227,7 @@ const FilesPage = ({

<Modals
done={hideModal}
mainFiles={files}
root={files ? files.path : null}
onMove={doFilesMove}
onMakeDir={doFilesMakeDir}
Expand All @@ -235,6 +236,7 @@ const FilesPage = ({
onAddByPath={onAddByPath}
onBulkCidImport={onBulkCidImport}
onPinningSet={doSetPinning}
onFetchDirectory={doFetchDirectory}
onPublish={doPublishIpnsKey}
cliOptions={cliOptions}
{ ...modals } />
Expand Down Expand Up @@ -293,6 +295,7 @@ export default connect(
'selectIsCliTutorModalOpen',
'doOpenCliTutorModal',
'doSetCliOptions',
'doFetchDirectory',
'selectCliOptions',
'doSetPinning',
'doPublishIpnsKey',
Expand Down
55 changes: 45 additions & 10 deletions src/files/breadcrumbs/Breadcrumbs.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import React, { useEffect, useState, useRef, useMemo } from 'react'
import classNames from 'classnames'
import PropTypes from 'prop-types'
import { basename, join } from 'path'
import { connect } from 'redux-bundler-react'
import { withTranslation } from 'react-i18next'
import { useDrop } from 'react-dnd'
Expand All @@ -14,21 +13,57 @@ import './Breadcrumbs.css'
const DropableBreadcrumb = ({ index, link, immutable, onAddFiles, onMove, onClick, onContextMenuHandle, getPathInfo, checkIfPinned }) => {
const [{ isOver }, drop] = useDrop({
accept: [NativeTypes.FILE, 'FILE'],
drop: async ({ files, filesPromise, path: filePath }) => {
if (files) {
drop: async (_, monitor) => {
const item = monitor.getItem()

if (item.files) {
(async () => {
const files = await filesPromise
onAddFiles(await normalizeFiles(files), link.path)
const files = await item.filesPromise
onAddFiles(normalizeFiles(files), link.path)
})()
} else {
const src = filePath
const dst = join(link.path, basename(filePath))

try { await onMove(src, dst) } catch (e) { console.error(e) }
const src = item.path

try {
const selectedFiles = Array.isArray(item.selectedFiles) ? item.selectedFiles : []
const isDraggedFileSelected = selectedFiles.length > 0 && selectedFiles.some(file => file.path === src)

if (isDraggedFileSelected) {
const moveOperations = selectedFiles.map(file => {
const fileName = file.path.split('/').pop()
const destinationPath = `${link.path}/${fileName}`
return [file.path, destinationPath]
})
for (const [src, dst] of moveOperations) {
try {
await onMove(src, dst)
} catch (err) {
console.error('Failed to move file:', { src, dst, error: err })
}
}
} else {
const fileName = src.split('/').pop()
const destinationPath = `${link.path}/${fileName}`
await onMove(src, destinationPath)
}
} catch (err) {
console.error('Error during file move operation:', err)
}
}
},
canDrop: (_, monitor) => {
const item = monitor.getItem()
if (!item) return false

if (item.path === link.path) return false

if (item.parentPath === link.path) return false

return true
},
collect: (monitor) => ({
isOver: monitor.isOver()
isOver: monitor.isOver(),
canDrop: monitor.canDrop()
})
})

Expand Down
Loading