File tree to act more like VS Code's file tree (#4392)

* File tree acts as VS Code's file tree

* Adjust test for new expectations

* Remove screenshot

* Actually remove this screenshot

* A snapshot a day keeps the bugs away! 📷🐛 (OS: ubuntu-latest-8-cores)

* A snapshot a day keeps the bugs away! 📷🐛 (OS: ubuntu-latest-8-cores)

* A snapshot a day keeps the bugs away! 📷🐛 (OS: ubuntu-latest-8-cores)

* A snapshot a day keeps the bugs away! 📷🐛 (OS: windows-latest-8-cores)

* A snapshot a day keeps the bugs away! 📷🐛 (OS: windows-latest-8-cores)

* A snapshot a day keeps the bugs away! 📷🐛 (OS: ubuntu-latest-8-cores)

* A snapshot a day keeps the bugs away! 📷🐛 (OS: windows-latest-8-cores)

* A snapshot a day keeps the bugs away! 📷🐛 (OS: windows-latest-8-cores)

---------

Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
This commit is contained in:
49fl
2024-11-06 14:32:06 -05:00
committed by GitHub
parent efd1f288b9
commit 4a4400e979
50 changed files with 473 additions and 229 deletions

View File

@ -2,11 +2,17 @@ import { IconDefinition, faBugSlash } from '@fortawesome/free-solid-svg-icons'
import { KclEditorMenu } from 'components/ModelingSidebar/ModelingPanes/KclEditorMenu'
import { CustomIconName } from 'components/CustomIcon'
import { KclEditorPane } from 'components/ModelingSidebar/ModelingPanes/KclEditorPane'
import { ModelingPaneHeader } from 'components/ModelingSidebar/ModelingPane'
import { MouseEventHandler, ReactNode } from 'react'
import { MemoryPane, MemoryPaneMenu } from './MemoryPane'
import { LogsPane } from './LoggingPanes'
import { DebugPane } from './DebugPane'
import { FileTreeInner, FileTreeMenu, FileTreeRoot } from 'components/FileTree'
import {
FileTreeInner,
FileTreeMenu,
FileTreeRoot,
useFileTreeOperations,
} from 'components/FileTree'
import { useKclContext } from 'lang/KclProvider'
import { editorManager } from 'lib/singletons'
import { ContextFrom } from 'xstate'
@ -38,20 +44,19 @@ interface PaneCallbackProps {
export type SidebarPane = {
id: SidebarType
title: ReactNode
sidebarName?: string
sidebarName: string
icon: CustomIconName | IconDefinition
keybinding: string
Content: ReactNode | React.FC
Menu?: ReactNode | React.FC
Content: React.FC<{ id: SidebarType; onClose: () => void }>
hide?: boolean | ((props: PaneCallbackProps) => boolean)
showBadge?: BadgeInfo
}
export type SidebarAction = {
id: string
title: ReactNode
sidebarName: string
icon: CustomIconName
title: ReactNode
iconClassName?: string // Just until we get rid of FontAwesome icons
keybinding: string
action: () => void
@ -59,14 +64,30 @@ export type SidebarAction = {
disable?: () => string | undefined
}
// For now a lot of icons are the same but the reality is they could totally
// be different, like an icon based on some data for the pane, or the icon
// changes to be a spinning loader on loading.
export const sidebarPanes: SidebarPane[] = [
{
id: 'code',
title: 'KCL Code',
icon: 'code',
Content: KclEditorPane,
sidebarName: 'KCL Code',
Content: (props: { id: SidebarType; onClose: () => void }) => {
return (
<>
<ModelingPaneHeader
id={props.id}
icon="code"
title="KCL Code"
Menu={<KclEditorMenu />}
onClose={props.onClose}
/>
<KclEditorPane />
</>
)
},
keybinding: 'Shift + C',
Menu: KclEditorMenu,
showBadge: {
value: ({ kclContext }) => {
return kclContext.errors.length
@ -79,34 +100,96 @@ export const sidebarPanes: SidebarPane[] = [
},
{
id: 'files',
title: <FileTreeRoot />,
sidebarName: 'Project Files',
icon: 'folder',
Content: FileTreeInner,
sidebarName: 'Project Files',
Content: (props: { id: SidebarType; onClose: () => void }) => {
const { createFile, createFolder, newTreeEntry } = useFileTreeOperations()
return (
<>
<ModelingPaneHeader
id={props.id}
icon="folder"
title={<FileTreeRoot />}
Menu={
<FileTreeMenu
onCreateFile={() => createFile({ dryRun: true })}
onCreateFolder={() => createFolder({ dryRun: true })}
/>
}
onClose={props.onClose}
/>
<FileTreeInner
onCreateFile={(name: string) => createFile({ dryRun: false, name })}
onCreateFolder={(name: string) =>
createFolder({ dryRun: false, name })
}
newTreeEntry={newTreeEntry}
/>
</>
)
},
keybinding: 'Shift + F',
Menu: FileTreeMenu,
hide: ({ platform }) => platform === 'web',
},
{
id: 'variables',
title: 'Variables',
icon: 'make-variable',
Content: MemoryPane,
Menu: MemoryPaneMenu,
sidebarName: 'Variables',
Content: (props: { id: SidebarType; onClose: () => void }) => {
return (
<>
<ModelingPaneHeader
id={props.id}
icon="make-variable"
title="Variables"
Menu={<MemoryPaneMenu />}
onClose={props.onClose}
/>
<MemoryPane />
</>
)
},
keybinding: 'Shift + V',
},
{
id: 'logs',
title: 'Logs',
icon: 'logs',
Content: LogsPane,
sidebarName: 'Logs',
Content: (props: { id: SidebarType; onClose: () => void }) => {
return (
<>
<ModelingPaneHeader
id={props.id}
icon="logs"
title="Logs"
Menu={null}
onClose={props.onClose}
/>
<LogsPane />
</>
)
},
keybinding: 'Shift + L',
},
{
id: 'debug',
title: 'Debug',
icon: faBugSlash,
Content: DebugPane,
sidebarName: 'Debug',
Content: (props: { id: SidebarType; onClose: () => void }) => {
return (
<>
<ModelingPaneHeader
id={props.id}
icon={faBugSlash}
title="Debug"
Menu={null}
onClose={props.onClose}
/>
<DebugPane />
</>
)
},
keybinding: 'Shift + D',
hide: ({ settings }) => !settings.modeling.showDebugPanel.current,
},