Compare commits

...

21 Commits

Author SHA1 Message Date
Valtteri Karesto
a2a6596cc5 Prevent pasting decimals 2022-06-22 12:16:36 +03:00
Valtteri Karesto
37208ce97e fixes #201 2022-06-22 12:03:43 +03:00
Valtteri Karesto
bf4042926d Merge pull request #218 from XRPLF/feat/ui-fixes
Fixes #213 and fixes #200
2022-06-22 11:41:31 +03:00
Valtteri Karesto
3ccc1c16ac Fixed deploy 2022-06-22 11:32:07 +03:00
Valtteri Karesto
135f0c91a1 Fixes #213 and fixes #200 2022-06-22 11:06:15 +03:00
Valtteri Karesto
8f5786e242 Merge pull request #216 from XRPLF/feat/change-default-optimization
fixes #214 change default optimization
2022-06-22 09:56:15 +03:00
Valtteri Karesto
810eb4ca27 Add new default to compileCode as well 2022-06-22 09:52:47 +03:00
Valtteri Karesto
e6574f9f12 fixes #214 change default optimization 2022-06-22 09:47:30 +03:00
Valtteri Karesto
1a6726fabf Merge pull request #212 from XRPLF/feat/improve-supp-js
Improve supplementary JS feature
2022-06-21 11:28:42 +03:00
Valtteri Karesto
89f8671217 Clear log should now work 2022-06-21 10:53:52 +03:00
Valtteri Karesto
fb5259221b Changed color of starting running 2022-06-21 09:43:29 +03:00
Valtteri Karesto
fd17f59616 Show LogBoxForScrips if js file active 2022-06-20 23:54:56 +03:00
Valtteri Karesto
91bbc7ea61 Catch template errors, add better labels, styling 2022-06-20 23:54:33 +03:00
Valtteri Karesto
783d832c6d Remove export for unused component 2022-06-20 23:53:32 +03:00
Valtteri Karesto
698ca376e7 Add showbuttons prop to LogBoxForScripts 2022-06-20 23:53:15 +03:00
Valtteri Karesto
bfd9e21ab8 Remove unused component 2022-06-20 23:52:45 +03:00
Valtteri Karesto
e46411f245 Rename template helpers 2022-06-20 14:53:30 +03:00
Valtteri Karesto
08447c6b29 Add support for select parameters 2022-06-20 14:16:16 +03:00
Valtteri Karesto
9216cc6bf7 When downloading zip, include wasm if it exists 2022-06-20 11:01:13 +03:00
Valtteri Karesto
5108b08e39 Do not show scripts panel if no supplementary scripts 2022-06-20 10:40:47 +03:00
Valtteri Karesto
6c46a4f809 Merge pull request #211 from XRPLF/feat/user-provided-scripts
Feat/user provided scripts
2022-06-20 10:16:06 +03:00
14 changed files with 324 additions and 189 deletions

View File

@@ -512,6 +512,7 @@ const ImportAccountDialog = () => {
<Input <Input
name="secret" name="secret"
type="password" type="password"
autoComplete="new-password"
value={value} value={value}
onChange={(e) => setValue(e.target.value)} onChange={(e) => setValue(e.target.value)}
/> />

View File

@@ -34,7 +34,9 @@ const DeployEditor = () => {
const [showContent, setShowContent] = useState(false); const [showContent, setShowContent] = useState(false);
const activeFile = snap.files[snap.active]; const activeFile = snap.files[snap.active]?.compiledContent
? snap.files[snap.active]
: snap.files.filter((file) => file.compiledContent)[0];
const compiledSize = activeFile?.compiledContent?.byteLength || 0; const compiledSize = activeFile?.compiledContent?.byteLength || 0;
const color = const color =
compiledSize > FILESIZE_BREAKPOINTS[1] compiledSize > FILESIZE_BREAKPOINTS[1]
@@ -60,12 +62,21 @@ const DeployEditor = () => {
{activeFile?.lastCompiled && ( {activeFile?.lastCompiled && (
<ReactTimeAgo date={activeFile.lastCompiled} locale="en-US" /> <ReactTimeAgo date={activeFile.lastCompiled} locale="en-US" />
)} )}
{activeFile.compiledContent?.byteLength && ( {activeFile.compiledContent?.byteLength && (
<Text css={{ ml: "$2", color }}> <Text css={{ ml: "$2", color }}>
({filesize(activeFile.compiledContent.byteLength)}) ({filesize(activeFile.compiledContent.byteLength)})
</Text> </Text>
)} )}
</Flex> </Flex>
{activeFile.compiledContent?.byteLength &&
activeFile.compiledContent?.byteLength >= 64000 && (
<Flex css={{ flexDirection: "column", py: "$3", pb: "$1" }}>
<Text css={{ ml: "$2", color: "$error" }}>
File size is larger than 64kB, cannot set hook!
</Text>
</Flex>
)}
<Button variant="link" onClick={() => setShowContent(true)}> <Button variant="link" onClick={() => setShowContent(true)}>
View as WAT-file View as WAT-file
</Button> </Button>
@@ -119,8 +130,8 @@ const DeployEditor = () => {
className="hooks-editor" className="hooks-editor"
defaultLanguage={"wat"} defaultLanguage={"wat"}
language={"wat"} language={"wat"}
path={`file://tmp/c/${snap.files?.[snap.active]?.name}.wat`} path={`file://tmp/c/${activeFile?.name}.wat`}
value={snap.files?.[snap.active]?.compiledWatContent || ""} value={activeFile?.compiledWatContent || ""}
beforeMount={(monaco) => { beforeMount={(monaco) => {
monaco.languages.register({ id: "wat" }); monaco.languages.register({ id: "wat" });
monaco.languages.setLanguageConfiguration("wat", wat.config); monaco.languages.setLanguageConfiguration("wat", wat.config);

View File

@@ -1,103 +0,0 @@
import React, { useRef, useLayoutEffect } from "react";
import { useSnapshot } from "valtio";
import { Play, Prohibit } from "phosphor-react";
import useStayScrolled from "react-stay-scrolled";
import Container from "./Container";
import Box from "./Box";
import LogText from "./LogText";
import { compileCode } from "../state/actions";
import state from "../state";
import Button from "./Button";
import Heading from "./Heading";
const Footer = () => {
const snap = useSnapshot(state);
const logRef = useRef<HTMLPreElement>(null);
const { stayScrolled /*, scrollBottom*/ } = useStayScrolled(logRef);
useLayoutEffect(() => {
stayScrolled();
}, [snap.logs, stayScrolled]);
return (
<Box
as="footer"
css={{
display: "flex",
borderTop: "1px solid $mauve6",
background: "$mauve1",
position: "relative",
}}
>
<Container css={{ py: "$3", flexShrink: 1 }}>
<Heading
as="h3"
css={{ fontWeight: 300, m: 0, fontSize: "11px", color: "$mauve9" }}
>
DEVELOPMENT LOG
</Heading>
<Button
ghost
size="xs"
css={{
position: "absolute",
right: "$3",
top: "$2",
color: "$mauve10",
}}
onClick={() => {
state.logs = [];
}}
>
<Prohibit size="14px" />
</Button>
<Box
as="pre"
ref={logRef}
css={{
display: "flex",
flexDirection: "column",
width: "100%",
height: "160px",
fontSize: "13px",
fontWeight: "$body",
fontFamily: "$monospace",
overflowY: "auto",
wordWrap: "break-word",
py: 3,
}}
>
{snap.logs?.map((log, index) => (
<Box as="span" key={log.type + index}>
<LogText capitalize variant={log.type}>
{log.type}:{" "}
</LogText>
<LogText>{log.message}</LogText>
</Box>
))}
</Box>
<Button
variant="primary"
uppercase
disabled={!snap.files.length}
isLoading={snap.compiling}
onClick={() => compileCode(snap.active)}
css={{
position: "absolute",
bottom: "$4",
left: "$4",
alignItems: "center",
display: "flex",
cursor: "pointer",
}}
>
<Play weight="bold" size="16px" />
Compile to Wasm
</Button>
</Container>
</Box>
);
};
export default Footer;

View File

@@ -25,6 +25,7 @@ interface ILogBox {
logs: ILog[]; logs: ILog[];
renderNav?: () => ReactNode; renderNav?: () => ReactNode;
enhanced?: boolean; enhanced?: boolean;
showButtons?: boolean;
} }
const LogBox: FC<ILogBox> = ({ const LogBox: FC<ILogBox> = ({
@@ -34,6 +35,7 @@ const LogBox: FC<ILogBox> = ({
children, children,
renderNav, renderNav,
enhanced, enhanced,
showButtons = true,
}) => { }) => {
const logRef = useRef<HTMLPreElement>(null); const logRef = useRef<HTMLPreElement>(null);
const { stayScrolled /*, scrollBottom*/ } = useStayScrolled(logRef); const { stayScrolled /*, scrollBottom*/ } = useStayScrolled(logRef);
@@ -86,13 +88,15 @@ const LogBox: FC<ILogBox> = ({
> >
<FileJs size="15px" /> <Text css={{ lineHeight: 1 }}>{title}</Text> <FileJs size="15px" /> <Text css={{ lineHeight: 1 }}>{title}</Text>
</Heading> </Heading>
<Flex css={{ gap: "$3" }}> {showButtons && (
{snap.files <Flex css={{ gap: "$3" }}>
.filter((f) => f.name.endsWith(".js")) {snap.files
.map((file) => ( .filter((f) => f.name.endsWith(".js"))
<RunScript file={file} key={file.name} /> .map((file) => (
))} <RunScript file={file} key={file.name} />
</Flex> ))}
</Flex>
)}
<Flex css={{ ml: "auto", gap: "$3", marginRight: "$3" }}> <Flex css={{ ml: "auto", gap: "$3", marginRight: "$3" }}>
{clearLog && ( {clearLog && (
<Button ghost size="xs" onClick={clearLog}> <Button ghost size="xs" onClick={clearLog}>

View File

@@ -1,6 +1,6 @@
import Handlebars from "handlebars"; import * as Handlebars from "handlebars";
import { Play, X } from "phosphor-react"; import { Play, X } from "phosphor-react";
import { useEffect, useState } from "react"; import { useCallback, useEffect, useState } from "react";
import state, { IFile, ILog } from "../../state"; import state, { IFile, ILog } from "../../state";
import Button from "../Button"; import Button from "../Button";
import Box from "../Box"; import Box from "../Box";
@@ -16,6 +16,15 @@ import {
} from "../Dialog"; } from "../Dialog";
import Flex from "../Flex"; import Flex from "../Flex";
import { useSnapshot } from "valtio"; import { useSnapshot } from "valtio";
import Select from "../Select";
import { saveFile } from "../../state/actions/saveFile";
Handlebars.registerHelper(
"customize_input",
function (/* dynamic arguments */) {
return new Handlebars.SafeString(arguments[0]);
}
);
const generateHtmlTemplate = (code: string) => { const generateHtmlTemplate = (code: string) => {
return ` return `
@@ -48,7 +57,7 @@ const generateHtmlTemplate = (code: string) => {
} }
</script> </script>
<script type="module"> <script type="module">
${code} ${code}
</script> </script>
</head> </head>
<body> <body>
@@ -56,22 +65,87 @@ const generateHtmlTemplate = (code: string) => {
</html> </html>
`; `;
}; };
const RunScript: React.FC<{ file: IFile }> = ({ file }) => {
type Fields = Record<
string,
{
key: string;
value: string;
label?: string;
type?: string;
attach?: "account_secret" | "account_address" | string;
}
>;
const RunScript: React.FC<{ file: IFile }> = ({ file: { content, name } }) => {
const snap = useSnapshot(state); const snap = useSnapshot(state);
const parsed = Handlebars.parse(file.content); const [templateError, setTemplateError] = useState("");
const names = parsed.body const getFieldValues = useCallback(() => {
.filter((i) => i.type === "MustacheStatement") try {
// @ts-expect-error const parsed = Handlebars.parse(content);
.map((block) => block?.path?.original); const names = parsed.body
const defaultState: Record<string, string> = {}; .filter((i) => i.type === "MustacheStatement")
names.forEach((name) => (defaultState[name] = "")); .map((block) => {
const [fields, setFields] = useState<Record<string, string>>(defaultState); // @ts-expect-error
const type = block.hash?.pairs?.find((i) => i.key == "type");
// @ts-expect-error
const attach = block.hash?.pairs?.find((i) => i.key == "attach");
// @ts-expect-error
const label = block.hash?.pairs?.find((i) => i.key == "label");
const key =
// @ts-expect-error
block?.path?.original === "customize_input"
? // @ts-expect-error
block?.params?.[0].original
: // @ts-expect-error
block?.path?.original;
return {
key,
label: label?.value?.original || key,
attach: attach?.value?.original,
type: type?.value?.original,
value: "",
};
});
const defaultState: Fields = {};
if (names) {
names.forEach((field) => (defaultState[field.key] = field));
}
setTemplateError("");
return defaultState;
} catch (err) {
console.log(err);
setTemplateError("Could not parse template");
return undefined;
}
}, [content]);
// const defaultFieldValues = getFieldValues();
const [fields, setFields] = useState<Fields>({});
const [iFrameCode, setIframeCode] = useState(""); const [iFrameCode, setIframeCode] = useState("");
const [isDialogOpen, setIsDialogOpen] = useState(false); const [isDialogOpen, setIsDialogOpen] = useState(false);
const runScript = () => { const runScript = () => {
const template = Handlebars.compile(file.content); const fieldsToSend: Record<string, string> = {};
const code = template(fields); Object.entries(fields).map(([key, obj]) => {
setIframeCode(generateHtmlTemplate(code)); fieldsToSend[key] = obj.value;
});
const template = Handlebars.compile(content, { strict: false });
try {
const code = template(fieldsToSend);
setIframeCode(generateHtmlTemplate(code));
state.scriptLogs = [
...snap.scriptLogs,
{ type: "success", message: "Started running..." },
];
} catch (err) {
state.scriptLogs = [
...snap.scriptLogs,
// @ts-expect-error
{ type: "error", message: err?.message || "Could not parse template" },
];
}
}; };
useEffect(() => { useEffect(() => {
@@ -88,6 +162,18 @@ const RunScript: React.FC<{ file: IFile }> = ({ file }) => {
return () => window.removeEventListener("message", handleEvent); return () => window.removeEventListener("message", handleEvent);
}, [snap.scriptLogs]); }, [snap.scriptLogs]);
useEffect(() => {
const newDefaultState = getFieldValues();
setFields(newDefaultState || {});
}, [content, setFields, getFieldValues]);
const options = snap.accounts?.map((acc) => ({
label: acc.name,
secret: acc.secret,
address: acc.address,
value: acc.address,
}));
return ( return (
<> <>
<Dialog open={isDialogOpen} onOpenChange={setIsDialogOpen}> <Dialog open={isDialogOpen} onOpenChange={setIsDialogOpen}>
@@ -95,18 +181,28 @@ const RunScript: React.FC<{ file: IFile }> = ({ file }) => {
<Button <Button
variant="primary" variant="primary"
onClick={() => { onClick={() => {
saveFile(false);
setIframeCode(""); setIframeCode("");
}} }}
> >
{file.name} <Play weight="bold" size="16px" /> <Play weight="bold" size="16px" /> {name}
</Button> </Button>
</DialogTrigger> </DialogTrigger>
<DialogContent> <DialogContent>
<DialogTitle>Run {file.name} script</DialogTitle> <DialogTitle>Run {name} script</DialogTitle>
<DialogDescription> <DialogDescription>
You are about to run scripts provided by the developer of the hook, You are about to run scripts provided by the developer of the hook,
make sure you know what you are doing. make sure you know what you are doing.
<br /> <br />
{templateError && (
<Box
as="span"
css={{ display: "block", color: "$error", mt: "$3" }}
>
Error occured while parsing template, modify script and try
again!
</Box>
)}
<br /> <br />
{Object.keys(fields).length > 0 {Object.keys(fields).length > 0
? `You also need to fill in following parameters to run the script` ? `You also need to fill in following parameters to run the script`
@@ -115,15 +211,52 @@ const RunScript: React.FC<{ file: IFile }> = ({ file }) => {
<Stack css={{ width: "100%" }}> <Stack css={{ width: "100%" }}>
{Object.keys(fields).map((key) => ( {Object.keys(fields).map((key) => (
<Box key={key} css={{ width: "100%" }}> <Box key={key} css={{ width: "100%" }}>
<label>{key}</label> <label>
<Input {fields[key]?.label || key}{" "}
type="text" {fields[key].attach === "account_secret" &&
value={fields[key]} `(Script uses account secret)`}
css={{ mt: "$1" }} </label>
onChange={(e) => {fields[key].attach === "account_secret" ||
setFields({ ...fields, [key]: e.target.value }) fields[key].attach === "account_address" ? (
} <Select
/> css={{ mt: "$1" }}
options={options}
onChange={(val: any) => {
setFields({
...fields,
[key]: {
...fields[key],
value:
fields[key].attach === "account_secret"
? val.secret
: val.address,
},
});
}}
value={options.find(
(opt) =>
opt.address === fields[key].value ||
opt.secret === fields[key].value
)}
/>
) : (
<Input
type={fields[key].type || "text"}
value={
typeof fields[key].value !== "string"
? // @ts-expect-error
fields[key].value.value
: fields[key].value
}
css={{ mt: "$1" }}
onChange={(e) => {
setFields({
...fields,
[key]: { ...fields[key], value: e.target.value },
});
}}
/>
)}
</Box> </Box>
))} ))}
<Flex <Flex
@@ -135,10 +268,9 @@ const RunScript: React.FC<{ file: IFile }> = ({ file }) => {
<Button <Button
variant="primary" variant="primary"
isDisabled={ isDisabled={
Object.entries(fields).length > 0 && (Object.entries(fields).length > 0 &&
Object.entries(fields).every( Object.entries(fields).some(([key, obj]) => !obj.value)) ||
([key, value]: [string, string]) => !value Boolean(templateError)
)
} }
onClick={() => { onClick={() => {
state.scriptLogs = []; state.scriptLogs = [];

View File

@@ -140,6 +140,16 @@ export const SetHookDialog: React.FC<{ accountAddress: string }> = React.memo(
return null; return null;
} }
const tooLargeFile = () => {
const activeFile = snap.files[snap.active].compiledContent
? snap.files[snap.active]
: snap.files.filter((file) => file.compiledContent)[0];
return Boolean(
activeFile?.compiledContent?.byteLength &&
activeFile?.compiledContent?.byteLength >= 64000
);
};
const onSubmit: SubmitHandler<SetHookData> = async (data) => { const onSubmit: SubmitHandler<SetHookData> = async (data) => {
const currAccount = state.accounts.find( const currAccount = state.accounts.find(
(acc) => acc.address === account.address (acc) => acc.address === account.address
@@ -164,7 +174,8 @@ export const SetHookDialog: React.FC<{ accountAddress: string }> = React.memo(
variant={"secondary"} variant={"secondary"}
disabled={ disabled={
account.isLoading || account.isLoading ||
!snap.files.filter((file) => file.compiledWatContent).length !snap.files.filter((file) => file.compiledWatContent).length ||
tooLargeFile()
} }
> >
Set Hook Set Hook

View File

@@ -38,22 +38,22 @@ export const TxUI: FC<UIProps> = ({
txFields, txFields,
} = txState; } = txState;
const transactionsOptions = transactionsData.map(tx => ({ const transactionsOptions = transactionsData.map((tx) => ({
value: tx.TransactionType, value: tx.TransactionType,
label: tx.TransactionType, label: tx.TransactionType,
})); }));
const accountOptions: SelectOption[] = accounts.map(acc => ({ const accountOptions: SelectOption[] = accounts.map((acc) => ({
label: acc.name, label: acc.name,
value: acc.address, value: acc.address,
})); }));
const destAccountOptions: SelectOption[] = accounts const destAccountOptions: SelectOption[] = accounts
.map(acc => ({ .map((acc) => ({
label: acc.name, label: acc.name,
value: acc.address, value: acc.address,
})) }))
.filter(acc => acc.value !== selectedAccount?.value); .filter((acc) => acc.value !== selectedAccount?.value);
const [feeLoading, setFeeLoading] = useState(false); const [feeLoading, setFeeLoading] = useState(false);
@@ -108,15 +108,15 @@ export const TxUI: FC<UIProps> = ({
const specialFields = ["TransactionType", "Account", "Destination"]; const specialFields = ["TransactionType", "Account", "Destination"];
const otherFields = Object.keys(txFields).filter( const otherFields = Object.keys(txFields).filter(
k => !specialFields.includes(k) (k) => !specialFields.includes(k)
) as [keyof TxFields]; ) as [keyof TxFields];
const switchToJson = () => const switchToJson = () =>
setState({ editorSavedValue: null, viewType: "json" }); setState({ editorSavedValue: null, viewType: "json" });
useEffect(() => { useEffect(() => {
const defaultOption = transactionsOptions.find( const defaultOption = transactionsOptions.find(
tt => tt.value === "Payment" (tt) => tt.value === "Payment"
); );
if (defaultOption) { if (defaultOption) {
handleChangeTxType(defaultOption); handleChangeTxType(defaultOption);
@@ -204,7 +204,7 @@ export const TxUI: FC<UIProps> = ({
/> />
</Flex> </Flex>
)} )}
{otherFields.map(field => { {otherFields.map((field) => {
let _value = txFields[field]; let _value = txFields[field];
let value: string | undefined; let value: string | undefined;
@@ -253,13 +253,39 @@ export const TxUI: FC<UIProps> = ({
/> />
) : ( ) : (
<Input <Input
type={isFee ? "number" : "text"}
value={value} value={value}
onChange={e => { onChange={(e) => {
handleSetField(field, e.target.value); if (isFee) {
const val = e.target.value
.replaceAll(".", "")
.replaceAll(",", "");
handleSetField(field, val);
} else {
handleSetField(field, e.target.value);
}
}} }}
onKeyPress={
isFee
? (e) => {
if (e.key === "." || e.key === ",") {
e.preventDefault();
}
}
: undefined
}
css={{ css={{
width: "70%", width: "70%",
flex: "inherit", flex: "inherit",
"-moz-appearance": "textfield",
"&::-webkit-outer-spin-button": {
"-webkit-appearance": "none",
margin: 0,
},
"&::-webkit-inner-spin-button ": {
"-webkit-appearance": "none",
margin: 0,
},
}} }}
/> />
)} )}

View File

@@ -12,6 +12,5 @@ export { default as Box } from "./Box";
export { default as Button } from "./Button"; export { default as Button } from "./Button";
export { default as Pre } from "./Pre"; export { default as Pre } from "./Pre";
export { default as ButtonGroup } from "./ButtonGroup"; export { default as ButtonGroup } from "./ButtonGroup";
export { default as DeployFooter } from "./DeployFooter";
export * from "./Dialog"; export * from "./Dialog";
export * from "./DropdownMenu"; export * from "./DropdownMenu";

View File

@@ -8,7 +8,9 @@ import { useSnapshot } from "valtio";
import { ButtonGroup, Flex } from "../../components"; import { ButtonGroup, Flex } from "../../components";
import Box from "../../components/Box"; import Box from "../../components/Box";
import Button from "../../components/Button"; import Button from "../../components/Button";
import LogBoxForScripts from "../../components/LogBoxForScripts";
import Popover from "../../components/Popover"; import Popover from "../../components/Popover";
import RunScript from "../../components/RunScript";
import state from "../../state"; import state from "../../state";
import { compileCode } from "../../state/actions"; import { compileCode } from "../../state/actions";
import { getSplit, saveSplit } from "../../state/actions/persistSplits"; import { getSplit, saveSplit } from "../../state/actions/persistSplits";
@@ -196,20 +198,61 @@ const Home: NextPage = () => {
</Flex> </Flex>
</Hotkeys> </Hotkeys>
)} )}
{snap.files[snap.active]?.name?.split(".")?.[1]?.toLowerCase() ===
"js" && (
<Hotkeys
keyName="command+b,ctrl+b"
onKeyDown={() =>
!snap.compiling && snap.files.length && compileCode(snap.active)
}
>
<Flex
css={{
position: "absolute",
bottom: "$4",
left: "$4",
alignItems: "center",
display: "flex",
cursor: "pointer",
gap: "$2",
}}
>
<RunScript file={snap.files[snap.active]} />
</Flex>
</Hotkeys>
)}
</main> </main>
<Box <Flex css={{ width: "100%" }}>
css={{ <Flex
display: "flex", css={{
background: "$mauve1", flex: 1,
position: "relative", background: "$mauve1",
}} position: "relative",
> borderRight: "1px solid $mauve8",
<LogBox }}
title="Development Log" >
clearLog={() => (state.logs = [])} <LogBox
logs={snap.logs} title="Development Log"
/> clearLog={() => (state.logs = [])}
</Box> logs={snap.logs}
/>
</Flex>
{snap.files[snap.active]?.name?.split(".")?.[1]?.toLowerCase() ===
"js" && (
<Flex
css={{
flex: 1,
}}
>
<LogBoxForScripts
showButtons={false}
title="Script Log"
logs={snap.scriptLogs}
clearLog={() => (state.scriptLogs = [])}
/>
</Flex>
)}
</Flex>
</Split> </Split>
); );
}; };

View File

@@ -32,11 +32,15 @@ const Test = () => {
if (!showComponent) { if (!showComponent) {
return null; return null;
} }
const hasScripts =
snap.files.filter((f) => f.name.endsWith(".js")).length > 0;
return ( return (
<Container css={{ px: 0 }}> <Container css={{ px: 0 }}>
<Split <Split
direction="vertical" direction="vertical"
sizes={getSplit("testVertical") || [50, 20, 30]} sizes={
getSplit("testVertical") || (hasScripts ? [50, 20, 30] : [50, 50])
}
gutterSize={4} gutterSize={4}
gutterAlign="center" gutterAlign="center"
style={{ height: "calc(100vh - 60px)" }} style={{ height: "calc(100vh - 60px)" }}
@@ -91,16 +95,22 @@ const Test = () => {
</Box> </Box>
</Split> </Split>
</Flex> </Flex>
<Flex {hasScripts && (
as="div" <Flex
css={{ as="div"
borderTop: "1px solid $mauve6", css={{
background: "$mauve1", borderTop: "1px solid $mauve6",
flexDirection: "column", background: "$mauve1",
}} flexDirection: "column",
> }}
<LogBoxForScripts title="Helper scripts" logs={snap.scriptLogs} /> >
</Flex> <LogBoxForScripts
title="Helper scripts"
logs={snap.scriptLogs}
clearLog={() => (state.scriptLogs = [])}
/>
</Flex>
)}
<Flex> <Flex>
<Split <Split
direction="horizontal" direction="horizontal"

View File

@@ -39,7 +39,7 @@ export const compileCode = async (activeId: number) => {
files: [ files: [
{ {
type: "c", type: "c",
options: state.compileOptions.optimizationLevel || '-O0', options: state.compileOptions.optimizationLevel || '-O2',
name: state.files[activeId].name, name: state.files[activeId].name,
src: state.files[activeId].content, src: state.files[activeId].content,
}, },

View File

@@ -54,15 +54,15 @@ export const prepareDeployHookTx = async (
account: IAccount & { name?: string }, account: IAccount & { name?: string },
data: SetHookData data: SetHookData
) => { ) => {
if ( const activeFile = state.files[state.active]?.compiledContent
!state.files || ? state.files[state.active]
state.files.length === 0 || : state.files.filter((file) => file.compiledContent)[0];
!state.files?.[state.active]?.compiledContent
) { if (!state.files || state.files.length === 0) {
return; return;
} }
if (!state.files?.[state.active]?.compiledContent) { if (!activeFile?.compiledContent) {
return; return;
} }
if (!state.client) { if (!state.client) {
@@ -99,7 +99,7 @@ export const prepareDeployHookTx = async (
{ {
Hook: { Hook: {
CreateCode: arrayBufferToHex( CreateCode: arrayBufferToHex(
state.files?.[state.active]?.compiledContent activeFile?.compiledContent
).toUpperCase(), ).toUpperCase(),
HookOn: calculateHookOn(hookOnValues), HookOn: calculateHookOn(hookOnValues),
HookNamespace, HookNamespace,

View File

@@ -8,7 +8,8 @@ export const downloadAsZip = async () => {
state.zipLoading = true state.zipLoading = true
// TODO do something about file/gist loading state // TODO do something about file/gist loading state
const files = state.files.map(({ name, content }) => ({ name, content })); const files = state.files.map(({ name, content }) => ({ name, content }));
const zipped = await createZip(files); const wasmFiles = state.files.filter(i => i.compiledContent).map(({ name, compiledContent }) => ({ name: `${name}.wasm`, content: compiledContent }));
const zipped = await createZip([...files, ...wasmFiles]);
const zipFileName = guessZipFileName(files); const zipFileName = guessZipFileName(files);
zipped.saveFile(zipFileName); zipped.saveFile(zipFileName);
} catch (error) { } catch (error) {

View File

@@ -114,7 +114,7 @@ let initialState: IState = {
mainModalShowed: false, mainModalShowed: false,
accounts: [], accounts: [],
compileOptions: { compileOptions: {
optimizationLevel: '-O0', optimizationLevel: '-O2',
strip: true strip: true
} }
}; };