fix: moved path into the file entry
This commit is contained in:
@ -5,7 +5,6 @@ import {
|
||||
type FileExplorerRow,
|
||||
type FileExplorerRender,
|
||||
type FileExplorerRowContextMenuProps,
|
||||
constructPath,
|
||||
} from '@src/components/Explorer/utils'
|
||||
import { ContextMenu, ContextMenuItem } from '@src/components/ContextMenu'
|
||||
import { useRef } from 'react'
|
||||
@ -59,19 +58,18 @@ const Spacer = (level: number) => {
|
||||
export const FileExplorer = ({
|
||||
rowsToRender,
|
||||
selectedRow,
|
||||
renamingRow,
|
||||
}: {
|
||||
rowsToRender: FileExplorerRow[]
|
||||
selectedRow: FileExplorerEntry | null
|
||||
renamingRow: FileExplorerRow | null
|
||||
}) => {
|
||||
// Local state for selection and what is opened
|
||||
// diff this against new Project value that comes in
|
||||
return (
|
||||
<div role="presentation" className="p-px">
|
||||
{rowsToRender.map((row, index, original) => {
|
||||
const key = constructPath({
|
||||
parentPath: row.parentPath,
|
||||
name: row.name,
|
||||
})
|
||||
const key = row.key
|
||||
const renderRow: FileExplorerRender = {
|
||||
...row,
|
||||
domIndex: index,
|
||||
@ -82,6 +80,7 @@ export const FileExplorer = ({
|
||||
key={key}
|
||||
row={renderRow}
|
||||
selectedRow={selectedRow}
|
||||
renamingRow={renamingRow}
|
||||
></FileExplorerRowElement>
|
||||
)
|
||||
})}
|
||||
@ -89,6 +88,115 @@ export const FileExplorer = ({
|
||||
)
|
||||
}
|
||||
|
||||
function FileExplorerRowContextMenu({
|
||||
itemRef,
|
||||
onRename,
|
||||
onDelete,
|
||||
onClone,
|
||||
onOpenInNewWindow,
|
||||
callback,
|
||||
}: FileExplorerRowContextMenuProps) {
|
||||
const platform = usePlatform()
|
||||
const metaKey = platform === 'macos' ? '⌘' : 'Ctrl'
|
||||
return (
|
||||
<ContextMenu
|
||||
menuTargetElement={itemRef}
|
||||
callback={callback}
|
||||
items={[
|
||||
<ContextMenuItem
|
||||
data-testid="context-menu-rename"
|
||||
onClick={onRename}
|
||||
hotkey="Enter"
|
||||
>
|
||||
Rename
|
||||
</ContextMenuItem>,
|
||||
<ContextMenuItem
|
||||
data-testid="context-menu-delete"
|
||||
onClick={onDelete}
|
||||
hotkey={metaKey + ' + Del'}
|
||||
>
|
||||
Delete
|
||||
</ContextMenuItem>,
|
||||
<ContextMenuItem
|
||||
data-testid="context-menu-clone"
|
||||
onClick={onClone}
|
||||
hotkey=""
|
||||
>
|
||||
Clone
|
||||
</ContextMenuItem>,
|
||||
<ContextMenuItem
|
||||
data-testid="context-menu-open-in-new-window"
|
||||
onClick={onOpenInNewWindow}
|
||||
>
|
||||
Open in new window
|
||||
</ContextMenuItem>,
|
||||
]}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
function RenameForm({
|
||||
row,
|
||||
onSubmit,
|
||||
}: {
|
||||
row: FileExplorerRender
|
||||
onSubmit: () => void
|
||||
}) {
|
||||
const inputRef = useRef<HTMLInputElement>(null)
|
||||
|
||||
function handleRenameSubmit(e: React.KeyboardEvent<HTMLElement>) {
|
||||
if (e.key !== 'Enter') {
|
||||
return
|
||||
}
|
||||
|
||||
// TODO: Do the renaming
|
||||
// newName: inputRef.current?.value || fileOrDir.name || '',
|
||||
|
||||
// To get out of the renaming state, without this the current file is still in renaming mode
|
||||
onSubmit()
|
||||
}
|
||||
|
||||
function handleKeyDown(e: React.KeyboardEvent<HTMLInputElement>) {
|
||||
if (e.key === 'Escape') {
|
||||
e.stopPropagation()
|
||||
onSubmit()
|
||||
} else if (e.key === 'Enter') {
|
||||
// This is needed to prevent events to bubble up and the form to be submitted.
|
||||
// (Alternatively the form could be changed into a div.)
|
||||
// Bug without this:
|
||||
// - open a parent folder (close and open if it's already open)
|
||||
// - right click -> rename one of its children
|
||||
// - give new name and press enter
|
||||
// -> new name is not applied, old name is reverted
|
||||
e.preventDefault()
|
||||
e.stopPropagation()
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<form onKeyUp={handleRenameSubmit}>
|
||||
<label>
|
||||
<span className="sr-only">Rename file</span>
|
||||
<input
|
||||
data-testid="file-rename-field"
|
||||
ref={inputRef}
|
||||
type="text"
|
||||
autoFocus
|
||||
autoCapitalize="off"
|
||||
autoCorrect="off"
|
||||
placeholder={row.name}
|
||||
className="w-full py-1 bg-transparent text-chalkboard-100 placeholder:text-chalkboard-70 dark:text-chalkboard-10 dark:placeholder:text-chalkboard-50 focus:outline-none focus:ring-0"
|
||||
onKeyDown={handleKeyDown}
|
||||
onBlur={onSubmit}
|
||||
/>
|
||||
</label>
|
||||
<button className="sr-only" type="submit">
|
||||
Submit
|
||||
</button>
|
||||
</form>
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Making div soup!
|
||||
* A row is a folder or a file.
|
||||
@ -96,9 +204,11 @@ export const FileExplorer = ({
|
||||
export const FileExplorerRowElement = ({
|
||||
row,
|
||||
selectedRow,
|
||||
renamingRow
|
||||
}: {
|
||||
row: FileExplorerRender
|
||||
selectedRow: FileExplorerEntry | null
|
||||
renamingRow: FileExplorerRow | null
|
||||
domLength: number
|
||||
}) => {
|
||||
const isSelected =
|
||||
@ -163,50 +273,3 @@ export const FileExplorerRowElement = ({
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
function FileExplorerRowContextMenu({
|
||||
itemRef,
|
||||
onRename,
|
||||
onDelete,
|
||||
onClone,
|
||||
onOpenInNewWindow,
|
||||
callback,
|
||||
}: FileExplorerRowContextMenuProps) {
|
||||
const platform = usePlatform()
|
||||
const metaKey = platform === 'macos' ? '⌘' : 'Ctrl'
|
||||
return (
|
||||
<ContextMenu
|
||||
menuTargetElement={itemRef}
|
||||
callback={callback}
|
||||
items={[
|
||||
<ContextMenuItem
|
||||
data-testid="context-menu-rename"
|
||||
onClick={onRename}
|
||||
hotkey="Enter"
|
||||
>
|
||||
Rename
|
||||
</ContextMenuItem>,
|
||||
<ContextMenuItem
|
||||
data-testid="context-menu-delete"
|
||||
onClick={onDelete}
|
||||
hotkey={metaKey + ' + Del'}
|
||||
>
|
||||
Delete
|
||||
</ContextMenuItem>,
|
||||
<ContextMenuItem
|
||||
data-testid="context-menu-clone"
|
||||
onClick={onClone}
|
||||
hotkey=""
|
||||
>
|
||||
Clone
|
||||
</ContextMenuItem>,
|
||||
<ContextMenuItem
|
||||
data-testid="context-menu-open-in-new-window"
|
||||
onClick={onOpenInNewWindow}
|
||||
>
|
||||
Open in new window
|
||||
</ContextMenuItem>,
|
||||
]}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
@ -23,11 +23,7 @@ const isFileExplorerEntryOpened = (
|
||||
rows: { [key: string]: boolean },
|
||||
entry: FileExplorerEntry
|
||||
): boolean => {
|
||||
const key = constructPath({
|
||||
parentPath: entry.parentPath,
|
||||
name: entry.name,
|
||||
})
|
||||
return rows[key]
|
||||
return rows[entry.key]
|
||||
}
|
||||
|
||||
/**
|
||||
@ -52,6 +48,8 @@ export const ProjectExplorer = ({
|
||||
// -1 is the parent container, -2 is nothing is selected
|
||||
const [activeIndex, setActiveIndex] = useState<number>(NOTHING_IS_SELECTED)
|
||||
const [rowsToRender, setRowsToRender] = useState<FileExplorerRow[]>([])
|
||||
const [renamingRow, setRenamingRow] = useState<FileExplorerRow | null>(null)
|
||||
|
||||
const fileExplorerContainer = useRef(null)
|
||||
const openedRowsRef = useRef(openedRows)
|
||||
const rowsToRenderRef = useRef(rowsToRender)
|
||||
@ -75,10 +73,7 @@ export const ProjectExplorer = ({
|
||||
*/
|
||||
const onRowClickCallback = (file: FileExplorerEntry, domIndex: number) => {
|
||||
const newOpenedRows = { ...openedRowsRef.current }
|
||||
const key = constructPath({
|
||||
parentPath: file.parentPath,
|
||||
name: file.name,
|
||||
})
|
||||
const key = file.key
|
||||
const value = openedRowsRef.current[key]
|
||||
newOpenedRows[key] = !value
|
||||
setOpenedRows(newOpenedRows)
|
||||
@ -127,7 +122,7 @@ export const ProjectExplorer = ({
|
||||
|
||||
const isOpen =
|
||||
openedRows[
|
||||
constructPath({ parentPath: child.parentPath, name: child.name })
|
||||
child.key
|
||||
]
|
||||
const render =
|
||||
(openedRows[child.parentPath] || project.name === child.parentPath) &&
|
||||
@ -155,10 +150,7 @@ export const ProjectExplorer = ({
|
||||
},
|
||||
rowOpen: () => {
|
||||
const newOpenedRows = { ...openedRowsRef.current }
|
||||
const key = constructPath({
|
||||
parentPath: child.parentPath,
|
||||
name: child.name,
|
||||
})
|
||||
const key = child.key
|
||||
newOpenedRows[key] = true
|
||||
setOpenedRows(newOpenedRows)
|
||||
},
|
||||
@ -182,6 +174,7 @@ export const ProjectExplorer = ({
|
||||
requestedRowsToRender.forEach((r, index) => {
|
||||
r.rowContextMenu = () => {
|
||||
setActiveIndex(index)
|
||||
setRenamingRow(r)
|
||||
}
|
||||
})
|
||||
|
||||
@ -219,10 +212,7 @@ export const ProjectExplorer = ({
|
||||
} else if (shouldCheckOpened && isEntryOpened) {
|
||||
// close
|
||||
const newOpenedRows = { ...openedRowsRef.current }
|
||||
const key = constructPath({
|
||||
parentPath: focusedEntry.parentPath,
|
||||
name: focusedEntry.name,
|
||||
})
|
||||
const key = focusedEntry.key
|
||||
const value = openedRowsRef.current[key]
|
||||
newOpenedRows[key] = !value
|
||||
setOpenedRows(newOpenedRows)
|
||||
@ -234,10 +224,7 @@ export const ProjectExplorer = ({
|
||||
} else if (shouldCheckOpened && !isEntryOpened) {
|
||||
// open!
|
||||
const newOpenedRows = { ...openedRowsRef.current }
|
||||
const key = constructPath({
|
||||
parentPath: focusedEntry.parentPath,
|
||||
name: focusedEntry.name,
|
||||
})
|
||||
const key = focusedEntry.key
|
||||
const value = openedRowsRef.current[key]
|
||||
newOpenedRows[key] = !value
|
||||
setOpenedRows(newOpenedRows)
|
||||
@ -265,10 +252,7 @@ export const ProjectExplorer = ({
|
||||
if (activeIndexRef.current >= STARTING_INDEX_TO_SELECT) {
|
||||
// open close folder
|
||||
const newOpenedRows = { ...openedRowsRef.current }
|
||||
const key = constructPath({
|
||||
parentPath: focusedEntry.parentPath,
|
||||
name: focusedEntry.name,
|
||||
})
|
||||
const key = focusedEntry.key
|
||||
const value = openedRowsRef.current[key]
|
||||
newOpenedRows[key] = !value
|
||||
setOpenedRows(newOpenedRows)
|
||||
|
||||
@ -7,6 +7,7 @@ export interface FileExplorerEntry extends FileEntry {
|
||||
parentPath: string
|
||||
level: number
|
||||
index: number
|
||||
key: string
|
||||
}
|
||||
|
||||
export interface FileExplorerRow extends FileExplorerEntry {
|
||||
@ -70,6 +71,10 @@ const flattenProjectHelper = (
|
||||
parentPath,
|
||||
level,
|
||||
index,
|
||||
key: constructPath({
|
||||
parentPath,
|
||||
name: f.name
|
||||
})
|
||||
}
|
||||
// keep track of the file once within the recursive list that will be built up
|
||||
list.push(content)
|
||||
|
||||
Reference in New Issue
Block a user