@uppy/dashboard: My Device button respects fileManagerSelectionType (#6258)

Fixes #6256

## Problem

When `fileManagerSelectionType` is set to `'folders'`, clicking the **My
Device** tab/button
still opens the file picker instead of the folder picker.

The inline "browse" link in the tagline correctly respects the setting,
but
`renderMyDeviceAcquirer` in `AddFiles.tsx` always called
`triggerFileInputClick`
regardless of the `fileManagerSelectionType` prop.

## Solution

`renderMyDeviceAcquirer` now reads `fileManagerSelectionType` and calls
`triggerFolderInputClick` when set to `'folders'`, or
`triggerFileInputClick`
for `'files'` and `'both'`.

For `'both'` mode, the button defaults to file selection because a
single
HTML `<input>` cannot handle both files and folders simultaneously
(`webkitdirectory` is all-or-nothing). The folder picker remains
accessible
via the tagline's "browse folders" link.

---------

Co-authored-by: Prakash <qxprakash@gmail.com>
This commit is contained in:
Enver 2026-04-24 13:30:02 +03:00 committed by GitHub
parent 71a34b9b37
commit b9253f797a
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 115 additions and 1 deletions

View file

@ -0,0 +1,5 @@
---
"@uppy/dashboard": patch
---
fix "My Device" button in dashboard, it now respects the fileManagerSelectionType.

View file

@ -106,6 +106,13 @@ class AddFiles extends Component<AddFilesProps> {
}
private renderMyDeviceAcquirer = () => {
// Cannot select both files and folders at once (webkitdirectory is all-or-nothing),
// so in 'both' mode the folder picker remains accessible via the tagline browse link.
const triggerMyDeviceInputClick =
this.props.fileManagerSelectionType === 'folders'
? this.triggerFolderInputClick
: this.triggerFileInputClick
return (
<div
className="uppy-DashboardTab"
@ -118,7 +125,7 @@ class AddFiles extends Component<AddFilesProps> {
role="tab"
tabIndex={0}
data-uppy-super-focusable
onClick={this.triggerFileInputClick}
onClick={triggerMyDeviceInputClick}
>
<div className="uppy-DashboardTab-inner">
<svg

View file

@ -153,4 +153,106 @@ describe('Dashboard', () => {
core.destroy()
})
describe('My Device acquirer respects fileManagerSelectionType', () => {
// `showNativePhotoCameraButton: true` is used to force the My Device tab
// to render — Dashboard hides it when it would be the only entry in the list
// (see `hasOnlyMyDevice` in AddFiles.tsx).
const mountDashboard = (
fileManagerSelectionType: 'files' | 'folders' | 'both',
) => {
document.body.innerHTML = ''
const core = new Core()
core.use(DashboardPlugin, {
inline: true,
target: 'body',
fileManagerSelectionType,
showNativePhotoCameraButton: true,
})
return core
}
const getInputs = () => {
const fileInput = document.querySelector<HTMLInputElement>(
'.uppy-Dashboard-input:not([webkitdirectory])',
)!
const folderInput = document.querySelector<HTMLInputElement>(
'.uppy-Dashboard-input[webkitdirectory]',
)!
return { fileInput, folderInput }
}
const clickMyDeviceTab = () => {
const tab = document.querySelector<HTMLButtonElement>(
'[data-uppy-acquirer-id="MyDevice"] button[role="tab"]',
)!
tab.click()
}
it('triggers the folder input when set to "folders"', () => {
const core = mountDashboard('folders')
const { fileInput, folderInput } = getInputs()
let fileClicked = false
let folderClicked = false
fileInput.addEventListener('click', () => {
fileClicked = true
})
folderInput.addEventListener('click', () => {
folderClicked = true
})
clickMyDeviceTab()
expect(folderClicked).toBe(true)
expect(fileClicked).toBe(false)
core.destroy()
})
it('triggers the file input when set to "files"', () => {
const core = mountDashboard('files')
const { fileInput, folderInput } = getInputs()
let fileClicked = false
let folderClicked = false
fileInput.addEventListener('click', () => {
fileClicked = true
})
folderInput.addEventListener('click', () => {
folderClicked = true
})
clickMyDeviceTab()
expect(fileClicked).toBe(true)
expect(folderClicked).toBe(false)
core.destroy()
})
// `both` mode intentionally falls back to the file picker because a single
// HTML <input> cannot be webkitdirectory and not at the same time. The
// folder picker remains reachable via the tagline "browse folders" link.
it('falls back to the file input when set to "both"', () => {
const core = mountDashboard('both')
const { fileInput, folderInput } = getInputs()
let fileClicked = false
let folderClicked = false
fileInput.addEventListener('click', () => {
fileClicked = true
})
folderInput.addEventListener('click', () => {
folderClicked = true
})
clickMyDeviceTab()
expect(fileClicked).toBe(true)
expect(folderClicked).toBe(false)
core.destroy()
})
})
})