- FolderPicker: uses webkitRelativePath so paths like docs/report.pdf are preserved; adds "include subfolders" checkbox (default on) - FileBrowser: virtual directory tree with breadcrumb navigation, sort by name/size, search filter, folders shown before files - Protocol: browse sends path alongside name; get uses path as key - FileEntry type gains optional path field Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
59 lines
1.9 KiB
TypeScript
59 lines
1.9 KiB
TypeScript
import { useRef, useState } from 'react'
|
|
import { useWaste } from '../store'
|
|
|
|
export function FolderPicker() {
|
|
const { setSharedFiles, activeNetworkId, sharedFilesByNetwork } = useWaste()
|
|
const inputRef = useRef<HTMLInputElement>(null)
|
|
const [includeSubfolders, setIncludeSubfolders] = useState(true)
|
|
|
|
const current = activeNetworkId ? sharedFilesByNetwork[activeNetworkId] : undefined
|
|
const label = current && current.size > 0
|
|
? `${current.size} file${current.size !== 1 ? 's' : ''} shared`
|
|
: null
|
|
|
|
function onChange(e: React.ChangeEvent<HTMLInputElement>) {
|
|
const fileList = e.target.files
|
|
if (!fileList || fileList.length === 0) return
|
|
const map = new Map<string, File>()
|
|
for (let i = 0; i < fileList.length; i++) {
|
|
const f = fileList[i]
|
|
const rel = (f as File & { webkitRelativePath?: string }).webkitRelativePath
|
|
// Strip the root folder name prefix (first path segment) so paths are relative to the picked folder
|
|
const path = rel ? rel.split('/').slice(1).join('/') : f.name
|
|
if (!includeSubfolders && path.includes('/')) continue
|
|
map.set(path, f)
|
|
}
|
|
setSharedFiles(map)
|
|
e.target.value = ''
|
|
}
|
|
|
|
return (
|
|
<div className="folder-picker">
|
|
<input
|
|
ref={inputRef}
|
|
type="file"
|
|
// @ts-expect-error webkitdirectory is non-standard
|
|
webkitdirectory=""
|
|
multiple
|
|
style={{ display: 'none' }}
|
|
onChange={onChange}
|
|
/>
|
|
<button
|
|
className="folder-picker-btn"
|
|
onClick={() => inputRef.current?.click()}
|
|
title="Share a folder with peers on this network"
|
|
>
|
|
{label ?? '+ Share folder'}
|
|
</button>
|
|
<label className="folder-picker-subfolders">
|
|
<input
|
|
type="checkbox"
|
|
checked={includeSubfolders}
|
|
onChange={e => setIncludeSubfolders(e.target.checked)}
|
|
/>
|
|
include subfolders
|
|
</label>
|
|
</div>
|
|
)
|
|
}
|