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:
@ -5,16 +5,18 @@ import { CamDebugSettings } from 'clientSideScene/ClientSideSceneComp'
|
||||
|
||||
export const DebugPane = () => {
|
||||
return (
|
||||
<section
|
||||
data-testid="debug-panel"
|
||||
className="absolute inset-0 p-2 box-border overflow-auto"
|
||||
>
|
||||
<div className="flex flex-col">
|
||||
<EngineCommands />
|
||||
<CamDebugSettings />
|
||||
<AstExplorer />
|
||||
<DebugFeatureTree />
|
||||
</div>
|
||||
</section>
|
||||
<div className="relative">
|
||||
<section
|
||||
data-testid="debug-panel"
|
||||
className="absolute inset-0 p-2 box-border overflow-auto"
|
||||
>
|
||||
<div className="flex flex-col">
|
||||
<EngineCommands />
|
||||
<CamDebugSettings />
|
||||
<AstExplorer />
|
||||
<DebugFeatureTree />
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
@ -174,27 +174,31 @@ export const KclEditorPane = () => {
|
||||
const initialCode = useRef(codeManager.code)
|
||||
|
||||
return (
|
||||
<div
|
||||
id="code-mirror-override"
|
||||
className={'absolute inset-0 ' + (cursorBlinking.current ? 'blink' : '')}
|
||||
>
|
||||
<CodeEditor
|
||||
initialDocValue={initialCode.current}
|
||||
extensions={editorExtensions}
|
||||
theme={theme}
|
||||
onCreateEditor={(_editorView) => {
|
||||
if (_editorView === null) return
|
||||
<div className="relative">
|
||||
<div
|
||||
id="code-mirror-override"
|
||||
className={
|
||||
'absolute inset-0 ' + (cursorBlinking.current ? 'blink' : '')
|
||||
}
|
||||
>
|
||||
<CodeEditor
|
||||
initialDocValue={initialCode.current}
|
||||
extensions={editorExtensions}
|
||||
theme={theme}
|
||||
onCreateEditor={(_editorView) => {
|
||||
if (_editorView === null) return
|
||||
|
||||
editorManager.setEditorView(_editorView)
|
||||
editorManager.setEditorView(_editorView)
|
||||
|
||||
// On first load of this component, ensure we show the current errors
|
||||
// in the editor.
|
||||
// Make sure we don't add them twice.
|
||||
if (diagnosticCount(_editorView.state) === 0) {
|
||||
kclManager.setDiagnosticsForCurrentErrors()
|
||||
}
|
||||
}}
|
||||
/>
|
||||
// On first load of this component, ensure we show the current errors
|
||||
// in the editor.
|
||||
// Make sure we don't add them twice.
|
||||
if (diagnosticCount(_editorView.state) === 0) {
|
||||
kclManager.setDiagnosticsForCurrentErrors()
|
||||
}
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
@ -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,
|
||||
},
|
||||
|
Reference in New Issue
Block a user