Skip to content

Commit

Permalink
fix: collisions between examples, projects and projects examples (#31)
Browse files Browse the repository at this point in the history
  • Loading branch information
lajbel authored Sep 30, 2024
1 parent e58c9f9 commit d28c348
Show file tree
Hide file tree
Showing 16 changed files with 237 additions and 296 deletions.
4 changes: 2 additions & 2 deletions src/components/Config/ConfigDialog.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,10 @@ import ConfigInput from "./ConfigInput";

const ConfigDialog = () => {
const {
getProjectMode,
getKAPLAYConfig,
updateKAPLAYConfig,
syncKAPLAYFile,
getProject,
} = useProject();
const {
update,
Expand Down Expand Up @@ -81,7 +81,7 @@ const ConfigDialog = () => {
<h2 className="text-xl">KAPLAY Configuration</h2>
</header>
<main>
{getProjectMode() === "project"
{getProject().mode === "pj"
? (
<>
<ConfigGroup title="screen & perf">
Expand Down
87 changes: 28 additions & 59 deletions src/components/Editor/MonacoEditor.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,66 +3,53 @@ import type { editor } from "monaco-editor";
import { type FC } from "react";
import { useEditor } from "../../hooks/useEditor";
import { useProject } from "../../hooks/useProject";
import { decompressCode } from "../../util/compressCode";
import { debug } from "../../util/logs";
import { configMonaco } from "./monacoConfig";

type Props = {
onMount?: () => void;
};

const IMPORT_CODE_ALERT =
"Are you sure you want to open this example? This will permanently replace your current project. You can export your current project to save it.";

const MonacoEditor: FC<Props> = (props) => {
const { updateFile, replaceProject, addFile, getFile } = useProject();
const {
setEditor,
run,
update,
currentFile,
setMonaco,
updateImageDecorations,
setGylphDecorations,
getCurrentFile,
} = useEditor();
const { updateFile, getFile } = useProject();
const { run, update, updateImageDecorations, getRuntime } = useEditor();

const handleEditorBeforeMount = (monaco: Monaco) => {
configMonaco(monaco);

const codeUrl = new URL(window.location.href).searchParams.get("code");
if (!codeUrl) return;

if (confirm(IMPORT_CODE_ALERT)) {
replaceProject({
files: new Map(),
assets: new Map(),
kaplayConfig: {},
version: "2.0.0",
mode: "example",
});

const code = decompressCode(codeUrl);

addFile({
name: "main.js",
value: code,
kind: "main",
language: "javascript",
path: "main.js",
});
}
};

const handleEditorMount = (
editor: editor.IStandaloneCodeEditor,
monaco: Monaco,
) => {
setEditor(editor);
setMonaco(monaco);
getRuntime().editor = editor;
getRuntime().monaco = monaco;
const currentFile = getRuntime().currentFile;

props.onMount?.();
editor.setValue(getFile(currentFile)?.value ?? "");

editor.onDidChangeModelContent((ev) => {
if (ev.isFlush) {
// set value

updateImageDecorations();
} else {
const currentProjectFile = getFile(getRuntime().currentFile);
if (!currentProjectFile) {
return debug(0, "Current file not found");
}

debug(
0,
"Due to text editor change, updating file",
currentProjectFile.path,
);

updateFile(currentProjectFile.path, editor.getValue());
}
});

// Editor Shortcuts
editor.addAction({
id: "run-game",
Expand All @@ -88,32 +75,16 @@ const MonacoEditor: FC<Props> = (props) => {
});

let decorations = editor.createDecorationsCollection([]);
setGylphDecorations(decorations);
getRuntime().gylphDecorations = decorations;

run();
};

const handleEditorChange = (value: string | undefined) => {
const currentProjectFile = getFile(getCurrentFile());
if (!currentProjectFile) return debug(0, "Current file not found");

debug(
0,
"Due to editor change, updating file",
currentProjectFile.path,
);

updateFile(currentProjectFile.path, value ?? "");
updateImageDecorations();
};

return (
<Editor
defaultLanguage="javascript"
defaultValue={getFile(currentFile)?.value}
beforeMount={handleEditorBeforeMount}
onMount={handleEditorMount}
onChange={handleEditorChange}
theme="kaplayrk"
language="javascript"
options={{
Expand All @@ -126,6 +97,4 @@ const MonacoEditor: FC<Props> = (props) => {
);
};

MonacoEditor.displayName = "MonacoEditor";

export default MonacoEditor;
7 changes: 5 additions & 2 deletions src/components/ExamplesBrowser/ExampleEntry.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { assets } from "@kaplayjs/crew";
import type { FC } from "react";
import type { Example } from "../../data/examples";
import { useEditor } from "../../hooks/useEditor";
import { useProject } from "../../hooks/useProject";
import { cn } from "../../util/cn";

type Props = {
Expand All @@ -17,7 +18,8 @@ const imagesPerDifficulty: Record<string, string> = {
};

export const ExampleEntry: FC<Props> = ({ example, isProject }) => {
const { loadExample } = useEditor();
const { loadDefaultExample } = useProject();
const { loadProject } = useEditor();

const handleClick = () => {
const dialog = document.querySelector<HTMLDialogElement>(
Expand All @@ -27,8 +29,9 @@ export const ExampleEntry: FC<Props> = ({ example, isProject }) => {
dialog?.close();

if (isProject) {
loadProject(example.name);
} else {
loadExample(example.index);
loadDefaultExample(example.index);
}
};

Expand Down
15 changes: 9 additions & 6 deletions src/components/ExamplesBrowser/ExamplesBrowser.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import * as Tabs from "@radix-ui/react-tabs";
import { examples } from "../../data/examples";
import { examples, type Tag } from "../../data/examples";
import { ExampleEntry } from "./ExampleEntry";
import "./ExamplesBrowser.css";
import { assets } from "@kaplayjs/crew";
Expand Down Expand Up @@ -37,7 +37,7 @@ export const ExamplesBrowser = () => {
/>
</header>

<Tabs.Root className="overflow-auto">
<Tabs.Root className="overflow-auto" defaultValue="Projects">
<TabsList>
<TabTrigger
label="Projects"
Expand All @@ -57,13 +57,16 @@ export const ExamplesBrowser = () => {
<ExampleEntry
example={{
description: null,
formatedName: project.replace(
"pj-",
"",
),
formatedName: project.slice(3),
name: project,
index: "0",
tags: [
...project.startsWith("pj-")
? ["project"] as Tag[]
: ["example"] as Tag[],
],
}}
isProject
key={project}
/>
))}
Expand Down
4 changes: 2 additions & 2 deletions src/components/FileTree/FileTree.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,14 @@ import FileFolder from "./FileFolder";

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

return (
<div className="flex flex-col p-2 gap-2">
{getProjectMode() === "project" && (
{getProject().mode === "pj" && (
<>
<FileFolder level={1} title="Scenes">
{getFilesByFolder("scenes").length === 0
Expand Down
7 changes: 1 addition & 6 deletions src/components/Playground/GameView.tsx
Original file line number Diff line number Diff line change
@@ -1,18 +1,13 @@
import { type FC } from "react";
import { useEditor } from "../../hooks/useEditor";

type GameViewProps = {
onLoad?: () => void;
};

const GameView: FC<GameViewProps> = ({ onLoad }) => {
const {
setIframe,
} = useEditor();

return (
<iframe
ref={setIframe}
id="game-view"
tabIndex={0}
onLoad={onLoad}
style={{
Expand Down
9 changes: 4 additions & 5 deletions src/components/Playground/Playground.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ import GameView from "./GameView";
const Playground = () => {
const {
project,
getProjectMode,
getProject,
createNewProject,
} = useProject();
const [loadingProject, setLoadingProject] = useState<boolean>(true);
Expand All @@ -32,7 +32,7 @@ const Playground = () => {
useEffect(() => {
if (project.files.size > 0) setLoadingProject(false);
else {
createNewProject();
createNewProject("pj");
}
}, [project]);

Expand All @@ -57,7 +57,7 @@ const Playground = () => {
<Allotment.Pane
snap
minSize={200}
visible={getProjectMode() === "project"}
visible={getProject().mode === "pj"}
>
<FileTree />
</Allotment.Pane>
Expand All @@ -70,8 +70,7 @@ const Playground = () => {
</Allotment.Pane>
<Allotment.Pane
snap
visible={getProjectMode()
=== "project"}
visible={getProject().mode === "pj"}
>
<Assets />
</Allotment.Pane>
Expand Down
24 changes: 17 additions & 7 deletions src/components/Toolbar/ExampleList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,16 @@ import { useEditor } from "../../hooks/useEditor";
import { useProject } from "../../hooks/useProject";

const ExampleList: FC = () => {
const { getSavedProjects } = useProject();
const { loadExample, loadProject } = useEditor();
const { getSavedProjects, loadDefaultExample } = useProject();
const { loadProject } = useEditor();

const handleExampleChange = (ev: ChangeEvent<HTMLSelectElement>) => {
const exampleIndex = ev.target.selectedOptions[0].getAttribute(
"data-example",
"data-def-example",
);

if (exampleIndex) {
loadExample(exampleIndex);
loadDefaultExample(exampleIndex);
} else {
loadProject(ev.target.value);
}
Expand All @@ -30,16 +30,26 @@ const ExampleList: FC = () => {
Projects
</option>

{getSavedProjects().map((project) => (
<option key={project} value={project} data-project>
{getSavedProjects("pj").map((project) => (
<option key={project} value={project}>
{project.replace("pj-", "")}
</option>
))}

<option className="text-md" disabled value="none">
User Examples
</option>

{getSavedProjects("ex").map((project) => (
<option key={project} value={project}>
{project.replace("ex-", "")}
</option>
))}

<option className="text-md" disabled>KAPLAY Examples</option>

{examples.map((example) => (
<option key={example.name} data-example={example.index}>
<option key={example.name} data-def-example={example.index}>
{example.name}
</option>
))}
Expand Down
26 changes: 12 additions & 14 deletions src/components/Toolbar/ProjectStatus.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,35 +2,33 @@ import { assets } from "@kaplayjs/crew";
import { useProject } from "../../hooks/useProject";

const ProjectStatus = () => {
const {
getProjectMode,
project,
saveProject,
getProjectName,
setProjectName,
isProjectSaved,
} = useProject();
const { saveProject, getProject, setProject, projectIsSaved } =
useProject();

const handleSaveProject = () => {
saveProject(getProjectName());
saveProject(getProject().name);
};

const handleEditName = () => {
const projectName = prompt("Project name");
const projectName = prompt("New project name?");
if (!projectName) return;

setProjectName(projectName);
setProject({ name: projectName });
};

if (getProject().isDefault) return;

return (
<div className="flex flex-row gap-2">
<div className="uppercase | badge badge-lg badge-primary">
{getProjectMode() === "project" ? "PJ" : "EX"}
{getProject().mode}
</div>

<div>
{project.name || "Untitled Project"}
{!isProjectSaved(getProjectName()) && <span>*</span>}
{getProject().name}
{!projectIsSaved(getProject().name, getProject().mode) && (
<span>*</span>
)}
</div>

<button
Expand Down
Loading

0 comments on commit d28c348

Please sign in to comment.