Skip to content
This repository has been archived by the owner on Apr 25, 2023. It is now read-only.

Commit

Permalink
fix: plugin editor changes do not take effect until run button is cli…
Browse files Browse the repository at this point in the history
…cked (#274)

* fix: plugin editor changes do not take effect until Run button is clicked

* fix

* update

* fix

* fix
  • Loading branch information
rot1024 committed Jul 12, 2022
1 parent b9db10e commit 39fdb21
Show file tree
Hide file tree
Showing 2 changed files with 288 additions and 313 deletions.
279 changes: 161 additions & 118 deletions src/components/molecules/PluginEditor/hooks.ts
@@ -1,174 +1,217 @@
import fileDownload from "js-file-download";
import { useState, useMemo, ChangeEvent, useEffect, useCallback } from "react";
import { useState, useMemo, useCallback } from "react";
import useFileInput from "use-file-input";

import type {
Widget,
WidgetAlignSystem,
WidgetZone,
WidgetSection,
} from "@reearth/components/molecules/Visualizer";
import type { WidgetZone, WidgetSection, Layer } from "@reearth/components/molecules/Visualizer";

export type Position = { section: string; area: string };

const originalSourceCode = `
reearth.ui.show(
\`<style>
body {
margin: 0;
}
#wrapper {
background: #232226;
height: 100%;
color: white;
border: 3px dotted red;
border-radius: 5px;
padding: 20px 0;
}
const defaultSourceCode = `
reearth.ui.show(\`
<style>
body {
margin: 0;
}
#wrapper {
background: #232226;
height: 100%;
color: white;
border: 3px dotted red;
border-radius: 5px;
padding: 20px 0;
}
</style>
<div id="wrapper">
<h2 style="text-align: center; margin: 0;">Hello2 World</h2>
<h2 style="text-align: center; margin: 0;">Hello World</h2>
</div>
\`
, { visible: true });
\`);
`.trim();

const defaultPosition = {
section: "left",
area: "top",
};

const defaultFileName = "untitled.js";

export default () => {
const [mode, setMode] = useState("widget");
const [showInfobox, setShowInfobox] = useState(false);
const [infoboxSize, setInfoboxSize] = useState<"small" | "medium" | "large">("small");
const [showAlignSystem, setShowAlignSystem] = useState(false);
const [currentPosition, setCurrentPosition] = useState<Position>(defaultPosition);
const [alignSystem, setAlignSystem] = useState<WidgetAlignSystem | undefined>();
const [sourceCode, setSourceCode] = useState<{ fileName?: string; body?: string }>({
fileName: "untitled.js",
body: originalSourceCode,
});
const [hardSourceCode, setHardSourceCode] = useState<{ fileName?: string; body: string }>({
fileName: "untitled.js",
body: originalSourceCode,
});
const [executableSourceCode, setExecutableSourceCode] = useState(defaultSourceCode);
const [fileName, setFileName] = useState(defaultFileName);
const [sourceCode, setSourceCode] = useState<string | undefined>(defaultSourceCode);

const rootLayer: Layer<any, any> = useMemo(
() => ({
id: "",
children: [
{
id: "pluginprimitive",
pluginId: "reearth",
extensionId: "marker",
isVisible: true,
property: {
default: {
location: { lat: 0, lng: 139 },
height: 0,
},
},
infobox: showInfobox
? {
property: {
default: {
title: "Cool info",
bgcolor: "#56051fff",
size: infoboxSize,
},
},
blocks: [
...(mode === "block"
? [
{
id: "xxx",
__REEARTH_SOURCECODE: executableSourceCode,
} as any,
]
: []),
{
id: "yyy",
pluginId: "plugins",
extensionId: "block",
property: {
location: { lat: 0, lng: 139 },
},
},
],
}
: undefined,
},
],
}),
[infoboxSize, mode, showInfobox, executableSourceCode],
);

const widgets = useMemo(() => {
if (mode !== "widget") return {};

const widget = [
{
id: "xxx",
// extended: true,
__REEARTH_SOURCECODE: executableSourceCode,
},
];
const alignment =
currentPosition.section === "center" || currentPosition.area === "middle"
? "centered"
: "start";
const newSection: WidgetSection = {
top: {
widgets: currentPosition.area === "top" ? widget : undefined,
align: alignment,
},
middle: {
widgets: currentPosition.area === "middle" ? widget : undefined,
align: alignment,
},
bottom: {
widgets: currentPosition.area === "bottom" ? widget : undefined,
align: alignment,
},
};

const positions: { [key: string]: Position }[] = [
{
LeftTop: { section: "left", area: "top" },
LeftMiddle: { section: "left", area: "middle" },
LeftBottom: { section: "left", area: "bottom" },
},
{
CenterTop: { section: "center", area: "top" },
CenterBottom: { section: "center", area: "bottom" },
},
{
RightTop: { section: "right", area: "top" },
RightMiddle: { section: "right", area: "middle" },
RightBottom: { section: "right", area: "bottom" },
},
];

const handleFileDownload = (body?: string, filename?: string) => {
if (!body) return;
fileDownload(body, filename ?? "untitled.js");
};
const newZone: WidgetZone = {
left: {
...(currentPosition.section === "left" ? newSection : undefined),
},
center: {
...(currentPosition.section === "center" ? newSection : undefined),
},
right: {
...(currentPosition.section === "right" ? newSection : undefined),
},
};
return { alignSystem: { outer: newZone } };
}, [currentPosition.area, currentPosition.section, executableSourceCode, mode]);

const handleAlignSystemUpdate = (widget: Widget, newLoc: Position) => {
setAlignSystem(() => {
const alignment =
newLoc.section === "center" || newLoc.area === "middle" ? "centered" : "start";
const newSection: WidgetSection = {
top: {
widgets: newLoc.area === "top" ? [widget] : undefined,
align: alignment,
},
middle: {
widgets: newLoc.area === "middle" ? [widget] : undefined,
align: alignment,
},
bottom: {
widgets: newLoc.area === "bottom" ? [widget] : undefined,
align: alignment,
},
};
const handleRun = useCallback(() => {
setExecutableSourceCode(sourceCode ?? "");
}, [setExecutableSourceCode, sourceCode]);

const newZone: WidgetZone = {
left: {
...(newLoc.section === "left" ? newSection : undefined),
},
center: {
...(newLoc.section === "center" ? newSection : undefined),
},
right: {
...(newLoc.section === "right" ? newSection : undefined),
},
};
setCurrentPosition(newLoc);
return { outer: newZone };
});
};
const handleAlignSystemToggle = () => {
setShowAlignSystem(!showAlignSystem);
const handleDownload = () => {
if (!sourceCode) return;
fileDownload(sourceCode, fileName);
};

const handleAlignSystemToggle = useCallback(() => {
setShowAlignSystem(s => !s);
}, []);

const handleInfoboxToggle = () => {
setShowInfobox(!showInfobox);
};

const handleFileOpen = async (e: ChangeEvent<HTMLInputElement>) => {
e.preventDefault();
const file = e.currentTarget.files?.[0];
const handleOpen = useFileInput(files => {
const file = files?.[0];
if (!file) return;
const reader = new FileReader();

reader.onload = async e2 => {
const body = e2?.target?.result;
if (typeof body != "string") return;
setSourceCode({ fileName: file.name, body });
setHardSourceCode({ fileName: file.name, body });
setFileName(file.name);
setSourceCode(body);
};
reader.readAsText(file);
};

const widget = useMemo(() => {
return {
id: "xxx",
// extended: true,
__REEARTH_SOURCECODE: sourceCode.body,
};
}, [sourceCode.body]);
});

const handleFileReset = useCallback(() => {
const handleReset = useCallback(() => {
if (confirm("Are you sure you want to reset?")) {
setSourceCode(hardSourceCode);
handleAlignSystemUpdate(widget, defaultPosition);
setFileName(defaultFileName);
setCurrentPosition(defaultPosition);
setSourceCode(defaultSourceCode);
setExecutableSourceCode(defaultSourceCode);
}
}, [widget, hardSourceCode]);

useEffect(() => {
handleAlignSystemUpdate(widget, currentPosition);
}, [widget]); // eslint-disable-line react-hooks/exhaustive-deps
}, []);

return {
sourceCode,
widget,
rootLayer,
currentPosition,
positions,
mode,
alignSystem,
widgets,
infoboxSize,
showAlignSystem,
showInfobox,
setSourceCode,
setMode,
setInfoboxSize,
handleFileOpen,
handleFileDownload,
handleFileReset,
handleOpen,
handleDownload,
handleReset,
handleAlignSystemToggle,
handleAlignSystemUpdate,
setCurrentPosition,
handleInfoboxToggle,
handleRun,
};
};

export const positions: { [key: string]: Position }[] = [
{
LeftTop: { section: "left", area: "top" },
LeftMiddle: { section: "left", area: "middle" },
LeftBottom: { section: "left", area: "bottom" },
},
{
CenterTop: { section: "center", area: "top" },
CenterBottom: { section: "center", area: "bottom" },
},
{
RightTop: { section: "right", area: "top" },
RightMiddle: { section: "right", area: "middle" },
RightBottom: { section: "right", area: "bottom" },
},
];

0 comments on commit 39fdb21

Please sign in to comment.