@uppy/provider-views
Advanced tools
Comparing version 3.3.1 to 3.4.0
# @uppy/provider-views | ||
## 3.4.0 | ||
Released: 2023-07-13 | ||
Included in: Uppy v3.12.0 | ||
- @uppy/provider-views: add support for remote file paths (Mikael Finstad / #4537) | ||
- @uppy/box,@uppy/companion,@uppy/dropbox,@uppy/google-drive,@uppy/onedrive,@uppy/provider-views: Load Google Drive / OneDrive lists 5-10x faster & always load all files (Merlijn Vos / #4513) | ||
## 3.3.1 | ||
@@ -4,0 +12,0 @@ |
@@ -19,3 +19,3 @@ import { h, Fragment } from 'preact'; | ||
breadcrumbsIcon, | ||
directories | ||
breadcrumbs | ||
} = props; | ||
@@ -26,8 +26,8 @@ return h("div", { | ||
className: "uppy-Provider-breadcrumbsIcon" | ||
}, breadcrumbsIcon), directories.map((directory, i) => h(Breadcrumb, { | ||
}, breadcrumbsIcon), breadcrumbs.map((directory, i) => h(Breadcrumb, { | ||
key: directory.id, | ||
getFolder: () => getFolder(directory.id), | ||
title: i === 0 ? title : directory.title, | ||
isLast: i + 1 === directories.length | ||
getFolder: () => getFolder(directory.requestPath), | ||
title: i === 0 ? title : directory.name, | ||
isLast: i + 1 === breadcrumbs.length | ||
}))); | ||
}); |
@@ -62,3 +62,4 @@ import { h } from 'preact'; | ||
src: itemIconString, | ||
alt: alt | ||
alt: alt, | ||
loading: "lazy" | ||
}); | ||
@@ -65,0 +66,0 @@ } |
@@ -8,3 +8,3 @@ import User from "./User.js"; | ||
getFolder: props.getFolder, | ||
directories: props.directories, | ||
breadcrumbs: props.breadcrumbs, | ||
breadcrumbsIcon: props.pluginIcon && props.pluginIcon(), | ||
@@ -11,0 +11,0 @@ title: props.title |
@@ -15,3 +15,3 @@ function _classPrivateFieldLooseBase(receiver, privateKey) { if (!Object.prototype.hasOwnProperty.call(receiver, privateKey)) { throw new TypeError("attempted to use private field on non-instance"); } return receiver; } | ||
const packageJson = { | ||
"version": "3.3.1" | ||
"version": "3.4.0" | ||
}; | ||
@@ -36,6 +36,16 @@ function getOrigin() { | ||
function formatBreadcrumbs(breadcrumbs) { | ||
return breadcrumbs.slice(1).map(directory => directory.name).join('/'); | ||
} | ||
function prependPath(path, component) { | ||
if (!path) return component; | ||
return `${path}/${component}`; | ||
} | ||
/** | ||
* Class to easily generate generic views for Provider plugins | ||
*/ | ||
var _updateFilesAndFolders = /*#__PURE__*/_classPrivateFieldLooseKey("updateFilesAndFolders"); | ||
var _list = /*#__PURE__*/_classPrivateFieldLooseKey("list"); | ||
var _listFilesAndFolders = /*#__PURE__*/_classPrivateFieldLooseKey("listFilesAndFolders"); | ||
var _recursivelyListAllFiles = /*#__PURE__*/_classPrivateFieldLooseKey("recursivelyListAllFiles"); | ||
export default class ProviderView extends View { | ||
@@ -49,5 +59,11 @@ /** | ||
// set default options | ||
Object.defineProperty(this, _updateFilesAndFolders, { | ||
value: _updateFilesAndFolders2 | ||
Object.defineProperty(this, _recursivelyListAllFiles, { | ||
value: _recursivelyListAllFiles2 | ||
}); | ||
Object.defineProperty(this, _listFilesAndFolders, { | ||
value: _listFilesAndFolders2 | ||
}); | ||
Object.defineProperty(this, _list, { | ||
value: _list2 | ||
}); | ||
const defaultOptions = { | ||
@@ -57,3 +73,4 @@ viewType: 'list', | ||
showFilter: true, | ||
showBreadcrumbs: true | ||
showBreadcrumbs: true, | ||
loadAllFiles: false | ||
}; | ||
@@ -85,3 +102,3 @@ | ||
folders: [], | ||
directories: [], | ||
breadcrumbs: [], | ||
filterInput: '', | ||
@@ -98,35 +115,69 @@ isSearchVisible: false, | ||
/** | ||
* Based on folder ID, fetch a new folder and update it to state | ||
* Select a folder based on its id: fetches the folder and then updates state with its contents | ||
* TODO rename to something better like selectFolder or navigateToFolder (breaking change?) | ||
* | ||
* @param {string} id Folder id | ||
* @param {string} requestPath | ||
* the path we need to use when sending list request to companion (for some providers it's different from ID) | ||
* @param {string} name used in the UI and to build the absDirPath | ||
* @returns {Promise} Folders/files in folder | ||
*/ | ||
async getFolder(id, name) { | ||
async getFolder(requestPath, name) { | ||
const controller = new AbortController(); | ||
const cancelRequest = () => { | ||
controller.abort(); | ||
this.clearSelection(); | ||
}; | ||
this.plugin.uppy.on('dashboard:close-panel', cancelRequest); | ||
this.plugin.uppy.on('cancel-all', cancelRequest); | ||
this.setLoading(true); | ||
try { | ||
const res = await this.provider.list(id); | ||
const folders = []; | ||
const files = []; | ||
let updatedDirectories; | ||
const state = this.plugin.getPluginState(); | ||
const index = state.directories.findIndex(dir => id === dir.id); | ||
this.lastCheckbox = undefined; | ||
let { | ||
breadcrumbs | ||
} = this.plugin.getPluginState(); | ||
const index = breadcrumbs.findIndex(dir => requestPath === dir.requestPath); | ||
if (index !== -1) { | ||
updatedDirectories = state.directories.slice(0, index + 1); | ||
// means we navigated back to a known directory (already in the stack), so cut the stack off there | ||
breadcrumbs = breadcrumbs.slice(0, index + 1); | ||
} else { | ||
updatedDirectories = state.directories.concat([{ | ||
id, | ||
title: name | ||
}]); | ||
// we have navigated into a new (unknown) folder, add it to the stack | ||
breadcrumbs = [...breadcrumbs, { | ||
requestPath, | ||
name | ||
}]; | ||
} | ||
this.username = res.username || this.username; | ||
_classPrivateFieldLooseBase(this, _updateFilesAndFolders)[_updateFilesAndFolders](res, files, folders); | ||
let files = []; | ||
let folders = []; | ||
do { | ||
const { | ||
files: newFiles, | ||
folders: newFolders | ||
} = await _classPrivateFieldLooseBase(this, _listFilesAndFolders)[_listFilesAndFolders]({ | ||
requestPath, | ||
breadcrumbs, | ||
signal: controller.signal | ||
}); | ||
files = files.concat(newFiles); | ||
folders = folders.concat(newFolders); | ||
this.setLoading(this.plugin.uppy.i18n('loadedXFiles', { | ||
numFiles: files.length + folders.length | ||
})); | ||
} while (this.opts.loadAllFiles && this.nextPagePath); | ||
this.plugin.setPluginState({ | ||
directories: updatedDirectories, | ||
folders, | ||
files, | ||
breadcrumbs, | ||
filterInput: '' | ||
}); | ||
this.lastCheckbox = undefined; | ||
} catch (err) { | ||
var _err$cause; | ||
if (((_err$cause = err.cause) == null ? void 0 : _err$cause.name) === 'AbortError') { | ||
// Expected, user clicked “cancel” | ||
return; | ||
} | ||
this.handleError(err); | ||
} finally { | ||
this.setLoading(false); | ||
this.plugin.uppy.off('dashboard:close-panel', cancelRequest); | ||
this.plugin.uppy.off('cancel-all', cancelRequest); | ||
} | ||
@@ -162,3 +213,3 @@ } | ||
folders: [], | ||
directories: [], | ||
breadcrumbs: [], | ||
filterInput: '' | ||
@@ -226,12 +277,24 @@ }; | ||
async handleScroll(event) { | ||
const path = this.nextPagePath || null; | ||
if (this.shouldHandleScroll(event) && path) { | ||
const requestPath = this.nextPagePath || null; | ||
if (this.shouldHandleScroll(event) && requestPath) { | ||
this.isHandlingScroll = true; | ||
try { | ||
const response = await this.provider.list(path); | ||
const { | ||
files, | ||
folders | ||
folders, | ||
breadcrumbs | ||
} = this.plugin.getPluginState(); | ||
_classPrivateFieldLooseBase(this, _updateFilesAndFolders)[_updateFilesAndFolders](response, files, folders); | ||
const { | ||
files: newFiles, | ||
folders: newFolders | ||
} = await _classPrivateFieldLooseBase(this, _listFilesAndFolders)[_listFilesAndFolders]({ | ||
requestPath, | ||
breadcrumbs | ||
}); | ||
const combinedFiles = files.concat(newFiles); | ||
const combinedFolders = folders.concat(newFolders); | ||
this.plugin.setPluginState({ | ||
folders: combinedFolders, | ||
files: combinedFiles | ||
}); | ||
} catch (error) { | ||
@@ -244,17 +307,2 @@ this.handleError(error); | ||
} | ||
async recursivelyListAllFiles(path, queue, onFiles) { | ||
let curPath = path; | ||
while (curPath) { | ||
const res = await this.provider.list(curPath); | ||
curPath = res.nextPagePath; | ||
const files = res.items.filter(item => !item.isFolder); | ||
const folders = res.items.filter(item => item.isFolder); | ||
onFiles(files); | ||
// recursively queue call to self for each folder | ||
const promises = folders.map(async folder => queue.add(async () => this.recursivelyListAllFiles(folder.requestPath, queue, onFiles))); | ||
await Promise.all(promises); // in case we get an error | ||
} | ||
} | ||
async donePicking() { | ||
@@ -268,8 +316,13 @@ this.setLoading(true); | ||
const newFiles = []; | ||
for (const file of currentSelection) { | ||
if (file.isFolder) { | ||
const { | ||
requestPath, | ||
name | ||
} = file; | ||
for (const selectedItem of currentSelection) { | ||
const { | ||
requestPath | ||
} = selectedItem; | ||
const withRelDirPath = newItem => ({ | ||
...newItem, | ||
// calculate the file's path relative to the user's selected item's path | ||
// see https://github.com/transloadit/uppy/pull/4537#issuecomment-1614236655 | ||
relDirPath: newItem.absDirPath.replace(selectedItem.absDirPath, '').replace(/^\//, '') | ||
}); | ||
if (selectedItem.isFolder) { | ||
let isEmpty = true; | ||
@@ -289,3 +342,3 @@ let numNewFiles = 0; | ||
if (!this.plugin.uppy.checkIfFileAlreadyExists(id)) { | ||
newFiles.push(newFile); | ||
newFiles.push(withRelDirPath(newFile)); | ||
numNewFiles++; | ||
@@ -299,3 +352,9 @@ this.setLoading(this.plugin.uppy.i18n('addedNumFiles', { | ||
}; | ||
await this.recursivelyListAllFiles(requestPath, queue, onFiles); | ||
await _classPrivateFieldLooseBase(this, _recursivelyListAllFiles)[_recursivelyListAllFiles]({ | ||
requestPath, | ||
absDirPath: prependPath(selectedItem.absDirPath, selectedItem.name), | ||
relDirPath: selectedItem.name, | ||
queue, | ||
onFiles | ||
}); | ||
await queue.onIdle(); | ||
@@ -307,3 +366,3 @@ let message; | ||
message = this.plugin.uppy.i18n('folderAlreadyAdded', { | ||
folder: name | ||
folder: selectedItem.name | ||
}); | ||
@@ -316,3 +375,3 @@ } else { | ||
smart_count: numNewFiles, | ||
folder: name | ||
folder: selectedItem.name | ||
}); | ||
@@ -322,3 +381,3 @@ } | ||
} else { | ||
newFiles.push(file); | ||
newFiles.push(withRelDirPath(selectedItem)); | ||
} | ||
@@ -381,3 +440,3 @@ } | ||
getFolder: this.getFolder, | ||
directories: this.plugin.getPluginState().directories, | ||
breadcrumbs: this.plugin.getPluginState().breadcrumbs, | ||
pluginIcon: this.plugin.icon, | ||
@@ -448,5 +507,43 @@ title: this.plugin.title, | ||
} | ||
function _updateFilesAndFolders2(res, files, folders) { | ||
this.nextPagePath = res.nextPagePath; | ||
res.items.forEach(item => { | ||
async function _list2(_ref) { | ||
let { | ||
requestPath, | ||
absDirPath, | ||
signal | ||
} = _ref; | ||
const { | ||
username, | ||
nextPagePath, | ||
items | ||
} = await this.provider.list(requestPath, { | ||
signal | ||
}); | ||
this.username = username || this.username; | ||
return { | ||
items: items.map(item => ({ | ||
...item, | ||
absDirPath | ||
})), | ||
nextPagePath | ||
}; | ||
} | ||
async function _listFilesAndFolders2(_ref2) { | ||
let { | ||
requestPath, | ||
breadcrumbs, | ||
signal | ||
} = _ref2; | ||
const absDirPath = formatBreadcrumbs(breadcrumbs); | ||
const { | ||
items, | ||
nextPagePath | ||
} = await _classPrivateFieldLooseBase(this, _list)[_list]({ | ||
requestPath, | ||
absDirPath, | ||
signal | ||
}); | ||
this.nextPagePath = nextPagePath; | ||
const files = []; | ||
const folders = []; | ||
items.forEach(item => { | ||
if (item.isFolder) { | ||
@@ -458,7 +555,37 @@ folders.push(item); | ||
}); | ||
this.plugin.setPluginState({ | ||
folders, | ||
files | ||
}); | ||
return { | ||
files, | ||
folders | ||
}; | ||
} | ||
async function _recursivelyListAllFiles2(_ref3) { | ||
let { | ||
requestPath, | ||
absDirPath, | ||
relDirPath, | ||
queue, | ||
onFiles | ||
} = _ref3; | ||
let curPath = requestPath; | ||
while (curPath) { | ||
const res = await _classPrivateFieldLooseBase(this, _list)[_list]({ | ||
requestPath: curPath, | ||
absDirPath | ||
}); | ||
curPath = res.nextPagePath; | ||
const files = res.items.filter(item => !item.isFolder); | ||
const folders = res.items.filter(item => item.isFolder); | ||
onFiles(files); | ||
// recursively queue call to self for each folder | ||
const promises = folders.map(async folder => queue.add(async () => _classPrivateFieldLooseBase(this, _recursivelyListAllFiles)[_recursivelyListAllFiles]({ | ||
requestPath: folder.requestPath, | ||
absDirPath: prependPath(absDirPath, folder.name), | ||
relDirPath: prependPath(relDirPath, folder.name), | ||
queue, | ||
onFiles | ||
}))); | ||
await Promise.all(promises); // in case we get an error | ||
} | ||
} | ||
ProviderView.VERSION = packageJson.version; |
@@ -10,3 +10,3 @@ function _classPrivateFieldLooseBase(receiver, privateKey) { if (!Object.prototype.hasOwnProperty.call(receiver, privateKey)) { throw new TypeError("attempted to use private field on non-instance"); } return receiver; } | ||
const packageJson = { | ||
"version": "3.3.1" | ||
"version": "3.4.0" | ||
}; | ||
@@ -56,3 +56,3 @@ /** | ||
folders: [], | ||
directories: [], | ||
breadcrumbs: [], | ||
filterInput: '', | ||
@@ -59,0 +59,0 @@ currentSelection: [], |
@@ -174,2 +174,7 @@ import getFileType from '@uppy/utils/lib/getFileType'; | ||
} | ||
// add relativePath similar to non-remote files: https://github.com/transloadit/uppy/pull/4486#issuecomment-1579203717 | ||
if (file.relDirPath != null) tagFile.meta.relativePath = file.relDirPath ? `${file.relDirPath}/${tagFile.name}` : null; | ||
// and absolutePath (with leading slash) https://github.com/transloadit/uppy/pull/4537#issuecomment-1614236655 | ||
if (file.absDirPath != null) tagFile.meta.absolutePath = file.absDirPath ? `/${file.absDirPath}/${tagFile.name}` : `/${tagFile.name}`; | ||
return tagFile; | ||
@@ -176,0 +181,0 @@ } |
{ | ||
"name": "@uppy/provider-views", | ||
"description": "View library for Uppy remote provider plugins.", | ||
"version": "3.3.1", | ||
"version": "3.4.0", | ||
"license": "MIT", | ||
@@ -23,3 +23,3 @@ "main": "lib/index.js", | ||
"dependencies": { | ||
"@uppy/utils": "^5.4.0", | ||
"@uppy/utils": "^5.4.1", | ||
"classnames": "^2.2.6", | ||
@@ -31,4 +31,4 @@ "nanoid": "^4.0.0", | ||
"peerDependencies": { | ||
"@uppy/core": "^3.2.1" | ||
"@uppy/core": "^3.3.1" | ||
} | ||
} |
@@ -29,3 +29,3 @@ # @uppy/provider-views | ||
this.provider.fetchPreAuthToken(), | ||
this.view.getFolder('root', '/'), | ||
this.view.getFolder('root'), | ||
]) | ||
@@ -32,0 +32,0 @@ } |
@@ -21,3 +21,3 @@ import { h, Fragment } from 'preact' | ||
export default (props) => { | ||
const { getFolder, title, breadcrumbsIcon, directories } = props | ||
const { getFolder, title, breadcrumbsIcon, breadcrumbs } = props | ||
@@ -28,8 +28,8 @@ return ( | ||
{ | ||
directories.map((directory, i) => ( | ||
breadcrumbs.map((directory, i) => ( | ||
<Breadcrumb | ||
key={directory.id} | ||
getFolder={() => getFolder(directory.id)} | ||
title={i === 0 ? title : directory.title} | ||
isLast={i + 1 === directories.length} | ||
getFolder={() => getFolder(directory.requestPath)} | ||
title={i === 0 ? title : directory.name} | ||
isLast={i + 1 === breadcrumbs.length} | ||
/> | ||
@@ -36,0 +36,0 @@ )) |
@@ -41,5 +41,5 @@ import { h } from 'preact' | ||
const { alt } = props | ||
return <img src={itemIconString} alt={alt} /> | ||
return <img src={itemIconString} alt={alt} loading="lazy" /> | ||
} | ||
} | ||
} |
@@ -9,3 +9,3 @@ import User from './User.jsx' | ||
getFolder: props.getFolder, | ||
directories: props.directories, | ||
breadcrumbs: props.breadcrumbs, | ||
breadcrumbsIcon: props.pluginIcon && props.pluginIcon(), | ||
@@ -12,0 +12,0 @@ title: props.title, |
@@ -35,2 +35,11 @@ import { h } from 'preact' | ||
function formatBreadcrumbs (breadcrumbs) { | ||
return breadcrumbs.slice(1).map((directory) => directory.name).join('/') | ||
} | ||
function prependPath (path, component) { | ||
if (!path) return component | ||
return `${path}/${component}` | ||
} | ||
/** | ||
@@ -54,2 +63,3 @@ * Class to easily generate generic views for Provider plugins | ||
showBreadcrumbs: true, | ||
loadAllFiles: false, | ||
} | ||
@@ -78,3 +88,3 @@ | ||
folders: [], | ||
directories: [], | ||
breadcrumbs: [], | ||
filterInput: '', | ||
@@ -91,5 +101,26 @@ isSearchVisible: false, | ||
#updateFilesAndFolders (res, files, folders) { | ||
this.nextPagePath = res.nextPagePath | ||
res.items.forEach((item) => { | ||
async #list ({ requestPath, absDirPath, signal }) { | ||
const { username, nextPagePath, items } = await this.provider.list(requestPath, { signal }) | ||
this.username = username || this.username | ||
return { | ||
items: items.map((item) => ({ | ||
...item, | ||
absDirPath, | ||
})), | ||
nextPagePath, | ||
} | ||
} | ||
async #listFilesAndFolders ({ requestPath, breadcrumbs, signal }) { | ||
const absDirPath = formatBreadcrumbs(breadcrumbs) | ||
const { items, nextPagePath } = await this.#list({ requestPath, absDirPath, signal }) | ||
this.nextPagePath = nextPagePath | ||
const files = [] | ||
const folders = [] | ||
items.forEach((item) => { | ||
if (item.isFolder) { | ||
@@ -102,36 +133,66 @@ folders.push(item) | ||
this.plugin.setPluginState({ folders, files }) | ||
return { files, folders } | ||
} | ||
/** | ||
* Based on folder ID, fetch a new folder and update it to state | ||
* Select a folder based on its id: fetches the folder and then updates state with its contents | ||
* TODO rename to something better like selectFolder or navigateToFolder (breaking change?) | ||
* | ||
* @param {string} id Folder id | ||
* @param {string} requestPath | ||
* the path we need to use when sending list request to companion (for some providers it's different from ID) | ||
* @param {string} name used in the UI and to build the absDirPath | ||
* @returns {Promise} Folders/files in folder | ||
*/ | ||
async getFolder (id, name) { | ||
async getFolder (requestPath, name) { | ||
const controller = new AbortController() | ||
const cancelRequest = () => { | ||
controller.abort() | ||
this.clearSelection() | ||
} | ||
this.plugin.uppy.on('dashboard:close-panel', cancelRequest) | ||
this.plugin.uppy.on('cancel-all', cancelRequest) | ||
this.setLoading(true) | ||
try { | ||
const res = await this.provider.list(id) | ||
const folders = [] | ||
const files = [] | ||
let updatedDirectories | ||
this.lastCheckbox = undefined | ||
const state = this.plugin.getPluginState() | ||
const index = state.directories.findIndex((dir) => id === dir.id) | ||
let { breadcrumbs } = this.plugin.getPluginState() | ||
const index = breadcrumbs.findIndex((dir) => requestPath === dir.requestPath) | ||
if (index !== -1) { | ||
updatedDirectories = state.directories.slice(0, index + 1) | ||
// means we navigated back to a known directory (already in the stack), so cut the stack off there | ||
breadcrumbs = breadcrumbs.slice(0, index + 1) | ||
} else { | ||
updatedDirectories = state.directories.concat([{ id, title: name }]) | ||
// we have navigated into a new (unknown) folder, add it to the stack | ||
breadcrumbs = [...breadcrumbs, { requestPath, name }] | ||
} | ||
this.username = res.username || this.username | ||
this.#updateFilesAndFolders(res, files, folders) | ||
this.plugin.setPluginState({ directories: updatedDirectories, filterInput: '' }) | ||
this.lastCheckbox = undefined | ||
let files = [] | ||
let folders = [] | ||
do { | ||
const { files: newFiles, folders: newFolders } = await this.#listFilesAndFolders({ | ||
requestPath, breadcrumbs, signal: controller.signal, | ||
}) | ||
files = files.concat(newFiles) | ||
folders = folders.concat(newFolders) | ||
this.setLoading(this.plugin.uppy.i18n('loadedXFiles', { numFiles: files.length + folders.length })) | ||
} while ( | ||
this.opts.loadAllFiles && this.nextPagePath | ||
) | ||
this.plugin.setPluginState({ folders, files, breadcrumbs, filterInput: '' }) | ||
} catch (err) { | ||
if (err.cause?.name === 'AbortError') { | ||
// Expected, user clicked “cancel” | ||
return | ||
} | ||
this.handleError(err) | ||
} finally { | ||
this.setLoading(false) | ||
this.plugin.uppy.off('dashboard:close-panel', cancelRequest) | ||
this.plugin.uppy.off('cancel-all', cancelRequest) | ||
} | ||
@@ -169,3 +230,3 @@ } | ||
folders: [], | ||
directories: [], | ||
breadcrumbs: [], | ||
filterInput: '', | ||
@@ -229,12 +290,18 @@ } | ||
async handleScroll (event) { | ||
const path = this.nextPagePath || null | ||
const requestPath = this.nextPagePath || null | ||
if (this.shouldHandleScroll(event) && path) { | ||
if (this.shouldHandleScroll(event) && requestPath) { | ||
this.isHandlingScroll = true | ||
try { | ||
const response = await this.provider.list(path) | ||
const { files, folders } = this.plugin.getPluginState() | ||
const { files, folders, breadcrumbs } = this.plugin.getPluginState() | ||
this.#updateFilesAndFolders(response, files, folders) | ||
const { files: newFiles, folders: newFolders } = await this.#listFilesAndFolders({ | ||
requestPath, breadcrumbs, | ||
}) | ||
const combinedFiles = files.concat(newFiles) | ||
const combinedFolders = folders.concat(newFolders) | ||
this.plugin.setPluginState({ folders: combinedFolders, files: combinedFiles }) | ||
} catch (error) { | ||
@@ -248,7 +315,7 @@ this.handleError(error) | ||
async recursivelyListAllFiles (path, queue, onFiles) { | ||
let curPath = path | ||
async #recursivelyListAllFiles ({ requestPath, absDirPath, relDirPath, queue, onFiles }) { | ||
let curPath = requestPath | ||
while (curPath) { | ||
const res = await this.provider.list(curPath) | ||
const res = await this.#list({ requestPath: curPath, absDirPath }) | ||
curPath = res.nextPagePath | ||
@@ -263,3 +330,9 @@ | ||
const promises = folders.map(async (folder) => queue.add(async () => ( | ||
this.recursivelyListAllFiles(folder.requestPath, queue, onFiles) | ||
this.#recursivelyListAllFiles({ | ||
requestPath: folder.requestPath, | ||
absDirPath: prependPath(absDirPath, folder.name), | ||
relDirPath: prependPath(relDirPath, folder.name), | ||
queue, | ||
onFiles, | ||
}) | ||
))) | ||
@@ -278,5 +351,13 @@ await Promise.all(promises) // in case we get an error | ||
for (const file of currentSelection) { | ||
if (file.isFolder) { | ||
const { requestPath, name } = file | ||
for (const selectedItem of currentSelection) { | ||
const { requestPath } = selectedItem | ||
const withRelDirPath = (newItem) => ({ | ||
...newItem, | ||
// calculate the file's path relative to the user's selected item's path | ||
// see https://github.com/transloadit/uppy/pull/4537#issuecomment-1614236655 | ||
relDirPath: newItem.absDirPath.replace(selectedItem.absDirPath, '').replace(/^\//, ''), | ||
}) | ||
if (selectedItem.isFolder) { | ||
let isEmpty = true | ||
@@ -296,3 +377,3 @@ let numNewFiles = 0 | ||
if (!this.plugin.uppy.checkIfFileAlreadyExists(id)) { | ||
newFiles.push(newFile) | ||
newFiles.push(withRelDirPath(newFile)) | ||
numNewFiles++ | ||
@@ -305,3 +386,9 @@ this.setLoading(this.plugin.uppy.i18n('addedNumFiles', { numFiles: numNewFiles })) | ||
await this.recursivelyListAllFiles(requestPath, queue, onFiles) | ||
await this.#recursivelyListAllFiles({ | ||
requestPath, | ||
absDirPath: prependPath(selectedItem.absDirPath, selectedItem.name), | ||
relDirPath: selectedItem.name, | ||
queue, | ||
onFiles, | ||
}) | ||
await queue.onIdle() | ||
@@ -314,3 +401,3 @@ | ||
message = this.plugin.uppy.i18n('folderAlreadyAdded', { | ||
folder: name, | ||
folder: selectedItem.name, | ||
}) | ||
@@ -322,3 +409,3 @@ } else { | ||
message = this.plugin.uppy.i18n('folderAdded', { | ||
smart_count: numNewFiles, folder: name, | ||
smart_count: numNewFiles, folder: selectedItem.name, | ||
}) | ||
@@ -329,3 +416,3 @@ } | ||
} else { | ||
newFiles.push(file) | ||
newFiles.push(withRelDirPath(selectedItem)) | ||
} | ||
@@ -368,3 +455,3 @@ } | ||
getFolder: this.getFolder, | ||
directories: this.plugin.getPluginState().directories, | ||
breadcrumbs: this.plugin.getPluginState().breadcrumbs, | ||
pluginIcon: this.plugin.icon, | ||
@@ -371,0 +458,0 @@ title: this.plugin.title, |
@@ -49,3 +49,3 @@ import { h } from 'preact' | ||
folders: [], | ||
directories: [], | ||
breadcrumbs: [], | ||
filterInput: '', | ||
@@ -52,0 +52,0 @@ currentSelection: [], |
@@ -95,2 +95,7 @@ import getFileType from '@uppy/utils/lib/getFileType' | ||
// add relativePath similar to non-remote files: https://github.com/transloadit/uppy/pull/4486#issuecomment-1579203717 | ||
if (file.relDirPath != null) tagFile.meta.relativePath = file.relDirPath ? `${file.relDirPath}/${tagFile.name}` : null | ||
// and absolutePath (with leading slash) https://github.com/transloadit/uppy/pull/4537#issuecomment-1614236655 | ||
if (file.absDirPath != null) tagFile.meta.absolutePath = file.absDirPath ? `/${file.absDirPath}/${tagFile.name}` : `/${tagFile.name}` | ||
return tagFile | ||
@@ -97,0 +102,0 @@ } |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
261286
3687
Updated@uppy/utils@^5.4.1