diff --git a/components/src/file_utils.ts b/components/src/file_utils.ts index bf4cf39e4..9df6d7bf1 100644 --- a/components/src/file_utils.ts +++ b/components/src/file_utils.ts @@ -42,3 +42,40 @@ export function sortFiles(files: Stats[]) { } }); } + +export async function cloneTree( + sourceFs: FileSystem, + targetFs: FileSystem, + dir = "/", + pathTransform: (path: string) => string, + overwrite = false, +) { + const sourceDir = dir == "/" ? "" : dir; + const targetDir = pathTransform(sourceDir); + + const sourceItems = await sourceFs.scandir(dir); + + targetFs.mkdir(targetDir); + const targetItems = new Set( + (await targetFs.scandir(targetDir)).map((stat) => stat.name), + ); + + for (const item of sourceItems) { + if (item.isFile()) { + if (overwrite || !targetItems.has(item.name)) { + await targetFs.writeFile( + `${targetDir}/${item.name}`, + await sourceFs.readFile(`${sourceDir}/${item.name}`), + ); + } + } else { + await cloneTree( + sourceFs, + targetFs, + `${sourceDir}/${item.name}`, + pathTransform, + overwrite, + ); + } + } +} diff --git a/components/src/stores/base.context.ts b/components/src/stores/base.context.ts index 6b591c32f..10fda269e 100644 --- a/components/src/stores/base.context.ts +++ b/components/src/stores/base.context.ts @@ -11,6 +11,7 @@ import { useState, } from "react"; import { useDialog } from "../dialog.js"; +import { cloneTree } from "../file_utils.js"; import { FileSystemAccessFileSystemAdapter, openNand2TetrisDirectory, @@ -49,8 +50,14 @@ export function useBaseContext(): BaseContext { new FileSystemAccessFileSystemAdapter(handle), ); if (createFiles) { - const loaders = await import("@nand2tetris/projects/loader.js"); - await loaders.createFiles(newFs); + if (root) { + const loaders = await import("@nand2tetris/projects/loader.js"); + await loaders.createFiles(newFs); + } else { + await cloneTree(fs, newFs, "/projects", (path: string) => + path.replace("/projects", "/").replace(/\/0*(\d+)/, "$1"), + ); + } } setFs(newFs); setRoot(handle.name); @@ -106,6 +113,9 @@ export function useBaseContext(): BaseContext { async (force = false, createFiles = false) => { if (!canUpgradeFs || (root && !force)) return; const handler = await openNand2TetrisDirectory(); + if (root) { + await removeLocalAdapterFromIndexedDB(); + } const adapter = await createAndStoreLocalAdapterInIndexedDB(handler); await setLocalFs(adapter, createFiles); }, diff --git a/components/src/stores/chip.store.ts b/components/src/stores/chip.store.ts index 3f8481e6f..740dbe5f0 100644 --- a/components/src/stores/chip.store.ts +++ b/components/src/stores/chip.store.ts @@ -309,6 +309,8 @@ export function makeChipStore( if (hdlProjects.length > 0) { await actions.setProject(sortedNames[0]); + } else { + dispatch.current({ action: "setChips", payload: [] }); } dispatch.current({ action: "clearChip" }); diff --git a/projects/src/full.ts b/projects/src/full.ts index 08a272572..e3b35a8d6 100644 --- a/projects/src/full.ts +++ b/projects/src/full.ts @@ -72,7 +72,7 @@ export const resetTests = async (fs: FileSystem, projects?: number[]) => { }; export const createFiles = async (fs: FileSystem) => { - await reset(fs, ProjectFiles); + await reset(fs, ProjectFiles, "/", false); }; export const Assignments = { diff --git a/projects/src/reset.ts b/projects/src/reset.ts index f423de30a..6f54f996e 100644 --- a/projects/src/reset.ts +++ b/projects/src/reset.ts @@ -19,11 +19,19 @@ export async function resetBySuffix( } } -export async function reset(fs: FileSystem, tree: Tree, base?: string) { +export async function reset( + fs: FileSystem, + tree: Tree, + base?: string, + override = true, +) { + const items = (await fs.scandir(base ?? "/")).map((item) => item.name); for (const [key, value] of Object.entries(tree)) { const path = `${base ? `${base}/` : ""}${key}`; if (typeof value === "string") { - await fs.writeFile(path, value); + if (override || !items.includes(key)) { + await fs.writeFile(path, value); + } } else { await fs.mkdir(path); await reset(fs, value as Tree, path); diff --git a/web/src/shell/settings.tsx b/web/src/shell/settings.tsx index 4317e9ef6..11abc1d04 100644 --- a/web/src/shell/settings.tsx +++ b/web/src/shell/settings.tsx @@ -10,7 +10,6 @@ import "../pico/button-group.scss"; import "../pico/property.scss"; import { TrackingDisclosure } from "../tracking"; import { getVersion, setVersion } from "../versions"; -// import { useDialog } from "./dialog"; const showUpgradeFs = true;