Skip to content

Commit

Permalink
chore: simplified folders
Browse files Browse the repository at this point in the history
  • Loading branch information
lajbel committed Oct 15, 2024
1 parent 20fd96c commit 8713d95
Show file tree
Hide file tree
Showing 9 changed files with 241 additions and 126 deletions.
96 changes: 82 additions & 14 deletions src/components/FileTree/FileEntry.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { cn } from "../../util/cn";
import { removeExtension } from "../../util/removeExtensions";
import "./FileEntry.css";
import { useEditor } from "../../hooks/useEditor";
import { debug } from "../../util/logs";

type Props = {
file: File;
Expand All @@ -18,8 +19,28 @@ const logoByKind = {
assets: assets.assetbrew.outlined,
};

const FileEntry: FC<Props> = ({ file }) => {
const { removeFile } = useProject();
const FileButton: FC<{
onClick: MouseEventHandler;
icon: keyof typeof assets;
rotate?: 0 | 90 | 180 | 270;
}> = (props) => {
return (
<button
className="btn btn-ghost btn-xs rounded-sm px-1"
onClick={props.onClick}
>
<img
src={assets[props.icon].outlined}
alt="Delete"
className="h-4 data-[rotation=90]:rotate-90 data-[rotation=180]:rotate-180 data-[rotation=270]:-rotate-90"
data-rotation={props.rotate}
/>
</button>
);
};

export const FileEntry: FC<Props> = ({ file }) => {
const { removeFile, project, setProject } = useProject();
const { getRuntime, setCurrentFile } = useEditor();

const handleClick: MouseEventHandler = () => {
Expand All @@ -39,6 +60,56 @@ const FileEntry: FC<Props> = ({ file }) => {
}
};

const handleMoveUp: MouseEventHandler = (e) => {
e.stopPropagation();

// order the map with the file one step up
const files = project.files;
const order = Array.from(files.keys());
const index = order.indexOf(file.path);

if (index === 0) return;

const newOrder = [...order];
newOrder.splice(index, 1);

newOrder.splice(index - 1, 0, file.path);

const newFiles = new Map(
newOrder.map((path) => [path, files.get(path)!]),
);

setProject({
...project,
files: newFiles,
});
};

const handleMoveDown: MouseEventHandler = (e) => {
e.stopPropagation();

// order the map with the file one step down
const files = project.files;
const order = Array.from(files.keys());
const index = order.indexOf(file.path);

if (index === order.length - 1) return;

const newOrder = [...order];
newOrder.splice(index, 1);

newOrder.splice(index + 1, 0, file.path);

const newFiles = new Map(
newOrder.map((path) => [path, files.get(path)!]),
);

setProject({
...project,
files: newFiles,
});
};

return (
<div
className={cn(
Expand All @@ -51,20 +122,19 @@ const FileEntry: FC<Props> = ({ file }) => {
onClick={handleClick}
data-file-kind={file.kind}
>
<span className="text-left truncate w-[50%]">
<span className="text-left truncate w-[50%] flex-1">
{removeExtension(file.name)}
</span>
<div role="toolbar" className="file-actions hidden">
<button
className="btn btn-ghost btn-xs rounded-sm px-1"
<FileButton
onClick={handleDelete}
>
<img
src={assets.trash.outlined}
alt="Delete"
className="h-4"
/>
</button>
icon="trash"
/>
<FileButton
onClick={handleMoveUp}
icon="arrow"
rotate={270}
/>
</div>
<img
src={logoByKind[file.kind]}
Expand All @@ -74,5 +144,3 @@ const FileEntry: FC<Props> = ({ file }) => {
</div>
);
};

export default FileEntry;
82 changes: 82 additions & 0 deletions src/components/FileTree/FileFold.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
import { assets } from "@kaplayjs/crew";
import { type FC, type PropsWithChildren, useMemo, useState } from "react";
import { cn } from "../../util/cn";
import { FileToolbar } from "./FileToolbar";
import "./FileFolder.css";
import { useProject } from "../../hooks/useProject";
import type { FileFolder, FileKind } from "../../stores/storage/files";
import { FileEntry } from "./FileEntry";

type Props = PropsWithChildren<{
level: 0 | 1 | 2;
title?: string;
toolbar?: boolean;
/** Kind of files on Folder */
kind?: FileKind;
/** Folder */
folder: FileFolder;
}>;

const paddingLevels = {
0: "pl-0",
1: "pl-4",
2: "pl-8",
};

export const FileFold: FC<Props> = (props) => {
const [folded, setFolded] = useState(false);
const { getFilesByFolder } = useProject();
const files = useMemo(() => getFilesByFolder(props.folder), [props.folder]);

return (
<div className="mb-2">
<div className="flex justify-between">
{props.title && (
<h2 className="text-lg font-medium">{props.title}</h2>
)}

{(props.toolbar && props.kind) && (
<FileToolbar
kind={props.kind}
>
<button
className="btn btn-ghost btn-xs rounded-sm px-1"
onClick={() => setFolded(!folded)}
>
<img
src={assets.arrow.outlined}
alt={folded ? "Open folder" : "Close folder"}
data-folded={folded}
className="folded-icon | h-4"
/>
</button>
</FileToolbar>
)}
</div>

<ul
className={cn(paddingLevels[props.level], {
"hidden": folded,
})}
>
{files.length === 0
? (
<li className="text-gray-500 text-xs">
Create an {props.folder} to start
</li>
)
: (
files.map((file) => {
return (
<li key={file.name}>
<FileEntry
file={file}
/>
</li>
);
})
)}
</ul>
</div>
);
};
56 changes: 0 additions & 56 deletions src/components/FileTree/FileFolder.tsx

This file was deleted.

24 changes: 14 additions & 10 deletions src/components/FileTree/FileToolbar.tsx
Original file line number Diff line number Diff line change
@@ -1,20 +1,26 @@
import { assets } from "@kaplayjs/crew";
import type { FC, PropsWithChildren } from "react";
import { useProject } from "../../hooks/useProject";
import { type FileKind, folderByKind } from "../../stores/storage/files";

const FileToolbar: FC<PropsWithChildren> = ({ children }) => {
const { addFile } = useProject();
type Props = PropsWithChildren<{
kind: FileKind;
}>;

export const FileToolbar: FC<Props> = (props) => {
const { addFile, getFile } = useProject();

const handleAddFile = () => {
const sceneName = prompt("Scene name");
if (!sceneName) return;
const fileName = prompt("File name");
if (!fileName) return;
if (getFile(`${folderByKind[props.kind]}/${fileName}.js`)) return;

addFile({
name: sceneName + ".js",
name: fileName + ".js",
kind: "scene",
value: `scene("${sceneName}", () => {\n\n});`,
value: `scene("${fileName}", () => {\n\n});`,
language: "javascript",
path: `scenes/${sceneName}.js`,
path: `${folderByKind[props.kind]}/${fileName}.js`,
});
};

Expand All @@ -31,9 +37,7 @@ const FileToolbar: FC<PropsWithChildren> = ({ children }) => {
/>
</button>

{children}
{props.children}
</div>
);
};

export default FileToolbar;
58 changes: 15 additions & 43 deletions src/components/FileTree/FileTree.tsx
Original file line number Diff line number Diff line change
@@ -1,48 +1,20 @@
import { useProject } from "../../hooks/useProject";
import FileEntry from "./FileEntry";
import FileFolder from "./FileFolder";
import { View } from "../UI/View";
import { FileFold } from "./FileFold";

export const FileTree = () => {
const {
getFile,
getFilesByFolder,
getProject,
} = useProject();

return (
<div className="flex flex-col p-2 gap-2">
{getProject().mode === "pj" && (
<>
<FileFolder level={1} title="Scenes">
{getFilesByFolder("scenes").length === 0
? (
<li className="text-gray-500 text-xs">
No scenes yet
</li>
)
: (
getFilesByFolder("scenes").map((file) => {
return (
<li key={file.name}>
<FileEntry
file={file}
/>
</li>
);
})
)}
</FileFolder>
<FileFolder level={0} toolbar={false}>
<li>
<>
<FileEntry file={getFile("main.js")!} />
<FileEntry file={getFile("kaplay.js")!} />
<FileEntry file={getFile("assets.js")!} />
</>
</li>
</FileFolder>
</>
)}
</div>
<View direction={"column"} padding={2} gap={2}>
<FileFold
level={1}
title="Scenes"
folder="scenes"
kind="scene"
toolbar
/>
<FileFold
folder="root"
level={0}
/>
</View>
);
};
3 changes: 2 additions & 1 deletion src/components/Playground/WorkspaceExample.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { Allotment } from "allotment";
import type { FC } from "react";
import { cn } from "../../util/cn";
import { MonacoEditor } from "../Editor/MonacoEditor";
import { Toolbar } from "../Toolbar";
import ExampleList from "../Toolbar/ExampleList";
import ToolbarToolsMenu from "../Toolbar/ToolbarToolsMenu";
import { GameView } from "./GameView";
Expand All @@ -21,7 +22,7 @@ export const WorkspaceExample: FC<Props> = (props) => {
})}
>
<header className="h-[4%] flex">
<ToolbarToolsMenu />
{props.isPortrait && <ToolbarToolsMenu /> || <Toolbar />}
</header>

<main className="h-[92%] lg:h-[96%] overflow-hidden">
Expand Down
Loading

0 comments on commit 8713d95

Please sign in to comment.