fix: fixing bug with enter with project loader name ref

This commit is contained in:
Kevin
2025-06-24 11:44:03 -05:00
parent ebf1ec5f49
commit b733722886
3 changed files with 55 additions and 36 deletions

View File

@ -5,8 +5,7 @@ import {
type FileExplorerRow,
type FileExplorerRender,
type FileExplorerRowContextMenuProps,
FILE_PLACEHOLDER_NAME,
FOLDER_PLACEHOLDER_NAME,
isRowFake,
} from '@src/components/Explorer/utils'
import { ContextMenu, ContextMenuItem } from '@src/components/ContextMenu'
import { useRef } from 'react'
@ -16,11 +15,14 @@ export const StatusDot = () => {
}
/**
* Implement a dynamic spacer with rem to offset the row
* in the tree based on the level within the tree
* level 0 to level N
* A dynamic spacer that will add spaces based on the level it is in the tree
* @param level supported be from 0 to N
* @returns
*/
const Spacer = (level: number) => {
if (level < 0) {
return <div>Do not pass a number less than 0.</div>
}
const containerRemSpacing = `${level}rem`
return level === 0 ? (
<div></div>
@ -50,10 +52,7 @@ const Spacer = (level: number) => {
* Render all the rows of the file explorer in linear layout in the DOM.
* each row is rendered one after another in the same parent DOM element
* rows will have aria support to understand the linear div soup layout
*
* what is opened and selected outside of this logic level.
*
* Pure functional renderer, state is stored outside this component.
*/
export const FileExplorer = ({
rowsToRender,
@ -66,8 +65,6 @@ export const FileExplorer = ({
contextMenuRow: FileExplorerRow | null
isRenaming: boolean
}) => {
// Local state for selection and what is opened
// diff this against new Project value that comes in
return (
<div role="presentation" className="relative">
{rowsToRender.map((row, index, original) => {
@ -91,11 +88,17 @@ export const FileExplorer = ({
)
}
/**
* TODO Support more context menu callback functions
* cut
* paste
* copy
*
*/
function FileExplorerRowContextMenu({
itemRef,
onRename,
onDelete,
onClone,
onOpenInNewWindow,
callback,
}: FileExplorerRowContextMenuProps) {
@ -134,10 +137,6 @@ function RenameForm({
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(e)
}
@ -158,12 +157,7 @@ function RenameForm({
e.stopPropagation()
}
}
const hidePlaceHolderIfFakeRow =
row.name === FOLDER_PLACEHOLDER_NAME || row.name === FILE_PLACEHOLDER_NAME
? ''
: row.name
const formattedPlaceHolder = isRowFake(row) ? '' : row.name
return (
<form onKeyUp={handleRenameSubmit}>
<label>
@ -175,7 +169,7 @@ function RenameForm({
autoFocus
autoCapitalize="off"
autoCorrect="off"
placeholder={hidePlaceHolderIfFakeRow}
placeholder={formattedPlaceHolder}
className="p-1 overflow-hidden whitespace-nowrap text-ellipsis py-1 bg-transparent outline outline-primary -outline-offset-4 text-chalkboard-100 placeholder:text-chalkboard-70 dark:text-chalkboard-10 dark:placeholder:text-chalkboard-50 focus:ring-0"
onKeyDown={handleKeyDown}
onBlur={onSubmit}
@ -203,11 +197,10 @@ export const FileExplorerRowElement = ({
contextMenuRow: FileExplorerEntry | null
isRenaming: boolean
}) => {
const rowElementRef = useRef(null)
const isSelected =
row.name === selectedRow?.name && row.parentPath === selectedRow?.parentPath
const isIndexActive = row.domIndex === row.activeIndex
const rowElementRef = useRef(null)
const isContextMenuRow = contextMenuRow?.key === row.key
const isMyRowRenaming = isContextMenuRow && isRenaming
@ -236,17 +229,18 @@ export const FileExplorerRowElement = ({
}}
draggable="true"
onDragOver={(event) => {
if (!row.isOpen && row.isFolder) {
// on drag over, open!
row.onOpen()
}
event.preventDefault()
// TODO
// if (!row.isOpen && row.isFolder) {
// // on drag over, open!
// row.onOpen()
// }
// event.preventDefault()
}}
onDragStart={(event) => {
// console.log(event.target.innerText, 'onDragStart')
// TODO console.log(event.target.innerText, 'onDragStart')
}}
onDrop={(event) => {
// console.log(event.target.innerText, 'onDrop')
// TODO console.log(event.target.innerText, 'onDrop')
}}
>
<div style={{ width: '0.5rem' }}></div>
@ -277,7 +271,6 @@ export const FileExplorerRowElement = ({
onDelete={() => {
row.onDelete()
}}
onClone={() => {}}
onOpenInNewWindow={() => {
row.onOpenInNewWindow()
}}

View File

@ -4,6 +4,10 @@ import { sortFilesAndDirectories } from '@src/lib/desktopFS'
import type { FileEntry } from '@src/lib/project'
import { desktopSafePathJoin, joinOSPaths } from '@src/lib/paths'
/**
* Remap FileEntry data into another data structure for the Project Explorer
* This will be transformed into a DOM one called FileExplorerRow
*/
export interface FileExplorerEntry extends FileEntry {
parentPath: string
level: number
@ -11,6 +15,9 @@ export interface FileExplorerEntry extends FileEntry {
key: string
}
/**
* Pass this to the FileExplorer to render
*/
export interface FileExplorerRow extends FileExplorerEntry {
icon: CustomIconName
name: string
@ -36,6 +43,9 @@ export interface FileExplorerRow extends FileExplorerEntry {
onRenameEnd: (e: React.KeyboardEvent<HTMLElement> | null) => void
}
/**
* Last conversion for linear rendering of DOM elements, we need the index.
*/
export interface FileExplorerRender extends FileExplorerRow {
domIndex: number
domLength: number
@ -45,11 +55,14 @@ export interface FileExplorerRowContextMenuProps {
itemRef: React.RefObject<HTMLElement>
onRename: () => void
onDelete: () => void
onClone: () => void
onOpenInNewWindow: () => void
callback: () => void
}
/**
* Create a key that can be used for a hash table for opened rows
* this is also used for key={} in React.
*/
export const constructPath = ({
parentPath,
name,
@ -162,6 +175,14 @@ export const addPlaceHoldersForNewFileAndFolder = (
children.push(placeHolderFileEntry)
}
export const isRowFake = (
row: FileExplorerRender | FileExplorerRow | FileExplorerEntry
): boolean => {
return (
row.name === FOLDER_PLACEHOLDER_NAME || row.name === FILE_PLACEHOLDER_NAME
)
}
// Used for focused which is different from the selection when you mouse click.
export const NOTHING_IS_SELECTED: number = -2
export const CONTAINER_IS_SELECTED: number = -1

View File

@ -4,6 +4,7 @@ import {
useEffect,
type MouseEventHandler,
type ReactNode,
useRef,
} from 'react'
import type { ContextFrom } from 'xstate'
@ -145,10 +146,13 @@ export const sidebarPanes: SidebarPane[] = [
Content: (props: { id: SidebarType; onClose: () => void }) => {
const projects = useFolders()
const loaderData = useRouteLoaderData(PATHS.FILE) as IndexLoaderData
const projectNameRef = useRef(loaderData.project?.name)
const [theProject, setTheProject] = useState<Project | null>(null)
const { project, file } = loaderData
const settings = useSettings()
useEffect(() => {
projectNameRef.current = loaderData?.project?.name
// Have no idea why the project loader data doesn't have the children from the ls on disk
// That means it is a different object or cached incorrectly?
if (!project || !file) {
@ -186,14 +190,15 @@ export const sidebarPanes: SidebarPane[] = [
// Only open the file if it is a kcl file.
if (
loaderData?.project?.name &&
projectNameRef.current &&
entry.children == null &&
entry.path.endsWith(FILE_EXT)
) {
systemIOActor.send({
type: SystemIOMachineEvents.navigateToFile,
data: {
requestedProjectName: loaderData?.project?.name,
requestedProjectName: projectNameRef.current,
requestedFileName: requestedFileName,
},
})