Skip to content

[feature] new project explorer #7592

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 133 commits into
base: main
Choose a base branch
from

Conversation

nadr0
Copy link
Contributor

@nadr0 nadr0 commented Jun 24, 2025

closes #6878

tl;dr for review

  • A few known bugs, nothing should be a show stopper for getting this in.
  • Jest is deleted in favor of vitest, Lee's billing component works
  • FileMachine + FileTree deleted!
  • UseFileSystemWatcher in the project tree is not implemented (for now)
  • Clone on right click context menu is deleted (for now)
  • All E2E tests passed with Locator changes
    • I did rewrite a few lines of the tests to use more helper functions that I didn't realize that were there.
    • I didn't touch that much, these original tests are amazing and worked really well with my new component.

Known bugs

  • aria label indexing is off by 1 when creating a file or folder
  • status dots don't do anything in the file tree yet
  • hotkeys are not enabled
  • usefilesystem watcher not enabled
  • previous bug in main the context menu does not recompute based on the row you select, it will keep the selected row then render at a new x,y, position.
  • previous bug in main closing the pane will unmount the file tree and lose its local state
  • arrow key selection logic scrolls the window... I'd have to programmatically reimplement scroll on arrow keys :( we live in 2025 and we are still reimplementing basic browser logic in JS

Issue

  • FileMachine needs to be ported into SystemIOMachine
  • Several bugs within the current file tree (improvement ticket above)
  • Improving overall components and data storage around the file tree.

Implementation

  • Deleted jest in favorite of vitest it works...
npx vitest --mode development ./src/components/billing.test.tsx
  • npm run test:unit:components is deleted because the npm run test:unit covers this case with vitest since jest .tsx testing is in vitest now
  • Since component testing is in vitest, it gets all our eslint and typescript checks. Previously the jest codebase had its own which was different. This now formats all the component tests the same as the rest of the codebase.
  • New Project Explorer that is more functional that can be used in different parts of the application without forced business logic all the way down in the filetree. There are more callbacks and configuration.

Features

Two missing features in new file tree

  • UseFileSystemWatcher (disk watch) is removed in this version will be back.

  • Clone is deleted as well since it is implemented wrong and I want cut/copy/paste.
    Everything else should be implemented.

  • Arrow keys

    • Up selects up
    • Down selects down
    • Right opens folder
    • Left closes folder
  • Enter

    • Open or close folder
    • Open KCL file
    • Trigger import for importable files
  • New action header bar

    • Add file
    • Add folder
    • Refresh contents from disk
    • Collapse all folders
  • Sorted placeholders for new file or new folder

  • Rename

  • 3 States for Rows

    • Hover (mouse hover)
    • activeIndex (keyboard/mouse) this is the outline selection for add file, add folder etc...
    • clicked this is the background highlighted row (the last thing you clicked)
    • These all can be different! It is valid!
  • Linear layout of the DOM instead of recursive DOM structure

  • Aria support for div soup/linear layout (1 bug listed above)

  • Folder/files will have a pink dot if there is an LSP error (all parent folders to nest down to the problematic file)

Oddly specific subtle features

  • If you are on a file and refresh the application that folder path will be opened to the file you have loaded
  • You can tab select to the project explorer
  • You cannot use the keyboard events if you aren't focused in the project explorer
  • Clicking new folder/file will focus and scroll your window
  • If you have a folder closed and you hit new file or folder it will open the folder

Testing

  • All e2e tests have been updated with new Locators in playwright and the fucking tests pass!! hell yeah! I didn't rewrite any logic
  • Updated hard coded file logic to a few helper functions in the playwright codebase

Screenshot

image

Future work

  • Fix the bugs above
  • Click error status dot for LSP
  • More context menu actions

nadr0 added 30 commits June 12, 2025 15:57
@nadr0 nadr0 force-pushed the nadro/gh-6878/file-explorer-next-iteration branch from 9c7506c to ccc7ec9 Compare June 26, 2025 17:34
@nadr0 nadr0 marked this pull request as ready for review June 26, 2025 20:25
@nadr0 nadr0 requested a review from a team as a code owner June 26, 2025 20:25
@@ -87,38 +87,3 @@ jobs:
git commit -am "Look at this (photo)Graph *in the voice of Nickelback*" || true
git push
git push origin ${{ github.head_ref }}

npm-test-unit-components:
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is deleted because the billing.test.tsx is covered in vitest which is the npm run test:unit workflow. Its all one runner for multiple file types.

@@ -345,12 +337,12 @@ test.describe('when using the file tree to', () => {
await test.step('swap between small and large files', async () => {
await openDebugPanel()
// Previously created a file so we need to start back at main.kcl
await mainFile.click()
await toolbar.openFile('main.kcl')
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

toolbar.openFile does the click for me. I updated these lines to use the helper function.

const renamedFile = page.getByRole('listitem').filter({
has: page.getByRole('button', { name: newFileName + FILE_EXT }),
})
const fileToRename = u.locatorFile('fileToRename.kcl')
Copy link
Contributor Author

@nadr0 nadr0 Jun 26, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In many locations there were specific page.getByRole calls, I've moved this to helper functions that still provide the Locator but now there are two functions to maintain for folder and file. This is a lot better.

await page.keyboard.press('Enter')
})
},

cloneFile: async (name: string) => {
return test?.step(`Cloning file '${name}'`, async () => {
await page
.locator('[data-testid="file-pane-scroll-container"] button')
.locator('[data-testid="file-pane-scroll-container"] [role=treeitem]')
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The DOM element is not a button anymore, I can use role=treeitem instead. This is a reasonable change across the helper functions.

@@ -131,8 +131,7 @@
"test": "vitest --mode development",
"test:rust": "(cd rust && just test && just lint)",
"test:snapshots": "cross-env TARGET=web NODE_ENV=development playwright test --config=playwright.config.ts --grep=@snapshot --trace=on",
"test:unit": "vitest run --mode development --exclude **/jest-component-unit-tests/*",
"test:unit:components": "jest -c jest-component-unit-tests/jest.config.ts --rootDir jest-component-unit-tests/",
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

jest is blown away. npm run test:unit will cover the new component files. Vitest does all the heavy lifting!

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you!

I was definitely concerned about having two runners willy nilly.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Awesome! Please delete npm run test:unit:components from the Makefile as well.

@@ -127,8 +127,28 @@ export const ModelingMachineProvider = ({
app: { allowOrbitInSketchMode },
modeling: { defaultUnit, cameraProjection, cameraOrbit },
} = useSettings()
const { context } = useFileContext()
const { file } = useLoaderData() as IndexLoaderData
const loaderData = useLoaderData() as IndexLoaderData
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The modelingmachine needs to point to the Project which was in filemachine provider but now it is a function of systemIOMachine and your IndexLoaderData.

I only updated this code to have reference to the project for TTC workflows.

@@ -0,0 +1,175 @@
import React, { useEffect, useMemo } from 'react'
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This was the fileMachineProvider.tsx but now it is called ModelingPageProvider because it has some initialization for the modeling page. No more file machine related stuff.

This will most likely get removed in the future when more command logic gets refactored.

@@ -0,0 +1,347 @@
// @ts-nocheck
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've moved Lee's file and renamed it for vitest and added ts-nocheck because the tsc checker in the jest codebase was not the same as our monorepo one.

This is a future todo. File still passes its tests.

@@ -24,6 +24,11 @@ import {
} from '@src/machines/systemIO/utils'
import { fromPromise } from 'xstate'
import type { AppMachineContext } from '@src/lib/types'
import {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Updated SystemIOMachine to have the same workflows as the FileMachine which is now deleted. These are required for generic application workflows as well as the project explorer.

Copy link
Contributor

@Irev-Dev Irev-Dev left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Really nice work.

I'm curious about UseFileSystemWatcher not being in yet, what is the consequence of this? user's can have ZDS and vscode open at the same time?
Also "status dots don't do anything in the file tree yet" should we just hid these until they do something?

I'm also curious if you've tried opening a monsterous directory? I can imagine perf issues that are outside of the file io stuff, just even just needing a virtual list to make react happy. Not saying those kinds of optimizations need to be in or anything, just think it's worth sanity checking and having some idea of where the limit might be before we merge.

@nadr0
Copy link
Contributor Author

nadr0 commented Jun 27, 2025

I'm curious about UseFileSystemWatcher not being in yet, what is the consequence of this? user's can have ZDS and vscode open at the same time?

Users won't be able to have them open at the same time and sync. I am worried about the implementation of the watcher.

Also "status dots don't do anything in the file tree yet" should we just hid these until they do something?

No? They can click the file in the row to see that the row has an error. There isn't any extra information in the dot.

I'm also curious if you've tried opening a monsterous directory? I can imagine perf issues that are outside of the file io stuff, just even just needing a virtual list to make react happy. Not saying those kinds of optimizations need to be in or anything, just think it's worth sanity checking and having some idea of where the limit might be before we merge.

Yes there are performance issues. We have them currently in the production application. I am working through the performance issues right now. There are many problems. I'll profile them and report my findings and fixes.

@pierremtb
Copy link
Contributor

Users won't be able to have them open at the same time and sync. I am worried about the implementation of the watcher.

@nadr0 Sorry haven't caught up to the rest of the PR yet. Does that mean we'd also loose the ability to have two ZDS windows open side by side (the Open in new window introduced in #6379)? That was a workaround for v1 to be able to edit a part while viewing the assembly at the same time.

@nadr0
Copy link
Contributor Author

nadr0 commented Jun 27, 2025

Users won't be able to have them open at the same time and sync. I am worried about the implementation of the watcher.

@nadr0 Sorry haven't caught up to the rest of the PR yet. Does that mean we'd also loose the ability to have two ZDS windows open side by side (the Open in new window introduced in #6379)? That was a workaround for v1 to be able to edit a part while viewing the assembly at the same time.

Yes, useFileSystemWatcher is disabled no live update from external sources.
This would need a cleaner implementation to not degrade performance.

Having two applications opened "updates" the other one because the other application is writing to disk and then the other application sees that an external file is edited.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

File tree improvements
5 participants