Compare commits

..

5 Commits

Author SHA1 Message Date
muzam
7db07e3f92 Merge branch 'main' into feat/controlled-dialog 2021-12-14 21:29:31 +05:30
Valtteri Karesto
6ad7c67672 hotfix: fixes faucet url 2021-12-14 16:36:37 +02:00
Valtteri Karesto
10f279a6b4 Merge pull request #33 from eqlabs/feat/add-language-client
Add example of language server
2021-12-14 16:17:16 +02:00
muzam
792c093cfd Input filename validation and default extension. 2021-12-14 16:43:43 +05:30
muzam
a11a641608 New file dialog confirms on pressing Enter. 2021-12-14 15:33:39 +05:30
5 changed files with 111 additions and 103 deletions

View File

@@ -70,7 +70,7 @@ const StyledTitle = styled(DialogPrimitive.Title, {
});
const StyledDescription = styled(DialogPrimitive.Description, {
margin: "10px 0 20px",
margin: "10px 0 10px",
color: "$mauve11",
fontSize: 15,
lineHeight: 1.5,

View File

@@ -1,4 +1,4 @@
import React, { useState, useEffect } from "react";
import React, { useState, useEffect, useCallback } from "react";
import {
Plus,
Share,
@@ -26,11 +26,7 @@ import NewWindow from "react-new-window";
import { signOut, useSession } from "next-auth/react";
import { useSnapshot } from "valtio";
import {
createNewFile,
syncToGist,
updateEditorSettings,
} from "../state/actions";
import { createNewFile, syncToGist, updateEditorSettings } from "../state/actions";
import state from "../state";
import Box from "./Box";
import Button from "./Button";
@@ -46,6 +42,7 @@ import {
import Flex from "./Flex";
import Stack from "./Stack";
import Input from "./Input";
import Text from "./Text";
import toast from "react-hot-toast";
import {
AlertDialog,
@@ -55,11 +52,22 @@ import {
AlertDialogCancel,
AlertDialogAction,
} from "./AlertDialog";
import { styled } from "../stitches.config";
const DEFAULT_EXTENSION = ".c";
const ErrorText = styled(Text, {
color: "$red9",
mt: "$1",
display: "block",
});
const EditorNavigation = ({ showWat }: { showWat?: boolean }) => {
const snap = useSnapshot(state);
const [createNewAlertOpen, setCreateNewAlertOpen] = useState(false);
const [editorSettingsOpen, setEditorSettingsOpen] = useState(false);
const [isNewfileDialogOpen, setIsNewfileDialogOpen] = useState(false);
const [newfileError, setNewfileError] = useState<string | null>(null);
const [filename, setFilename] = useState("");
const { data: session, status } = useSession();
const [popup, setPopUp] = useState(false);
@@ -69,6 +77,36 @@ const EditorNavigation = ({ showWat }: { showWat?: boolean }) => {
setPopUp(false);
}
}, [session, popup]);
// when filename changes, reset error
useEffect(() => {
setNewfileError(null);
}, [filename, setNewfileError]);
const validateFilename = useCallback(
(filename: string): { error: string | null } => {
if (snap.files.find(file => file.name === filename)) {
return { error: "Filename already exists." };
}
// More checks in future
return { error: null };
},
[snap.files]
);
const handleConfirm = useCallback(() => {
// add default extension in case omitted
let _filename = filename.includes(".") ? filename : filename + DEFAULT_EXTENSION;
const chk = validateFilename(_filename);
if (chk.error) {
setNewfileError(`Error: ${chk.error}`);
return;
}
setIsNewfileDialogOpen(false);
createNewFile(_filename);
setFilename("");
}, [filename, setIsNewfileDialogOpen, setFilename, validateFilename]);
const files = snap.files;
return (
<Flex css={{ flexShrink: 0, gap: "$0" }}>
@@ -101,9 +139,7 @@ const EditorNavigation = ({ showWat }: { showWat?: boolean }) => {
return (
<Button
size="sm"
outline={
showWat ? snap.activeWat !== index : snap.active !== index
}
outline={showWat ? snap.activeWat !== index : snap.active !== index}
onClick={() => (state.active = index)}
key={file.name + index}
css={{
@@ -138,8 +174,7 @@ const EditorNavigation = ({ showWat }: { showWat?: boolean }) => {
// If deleted file is behind active tab
// we keep the current state otherwise
// select previous file on the list
state.active =
index > snap.active ? snap.active : snap.active - 1;
state.active = index > snap.active ? snap.active : snap.active - 1;
}}
>
<X size="9px" weight="bold" />
@@ -149,15 +184,10 @@ const EditorNavigation = ({ showWat }: { showWat?: boolean }) => {
);
})}
{!showWat && (
<Dialog>
<Dialog open={isNewfileDialogOpen} onOpenChange={setIsNewfileDialogOpen}>
<DialogTrigger asChild>
<Button
ghost
size="sm"
css={{ alignItems: "center", px: "$2", mr: "$3" }}
>
<Plus size="16px" />{" "}
{snap.files.length === 0 && "Add new file"}
<Button ghost size="sm" css={{ alignItems: "center", px: "$2", mr: "$3" }}>
<Plus size="16px" /> {snap.files.length === 0 && "Add new file"}
</Button>
</DialogTrigger>
<DialogContent>
@@ -166,8 +196,14 @@ const EditorNavigation = ({ showWat }: { showWat?: boolean }) => {
<label>Filename</label>
<Input
value={filename}
onChange={(e) => setFilename(e.target.value)}
onChange={e => setFilename(e.target.value)}
onKeyPress={e => {
if (e.key === "Enter") {
handleConfirm();
}
}}
/>
<ErrorText>{newfileError}</ErrorText>
</DialogDescription>
<Flex
@@ -180,18 +216,12 @@ const EditorNavigation = ({ showWat }: { showWat?: boolean }) => {
<DialogClose asChild>
<Button outline>Cancel</Button>
</DialogClose>
<DialogClose asChild>
<Button
variant="primary"
onClick={() => {
createNewFile(filename);
// reset
setFilename("");
}}
>
Create file
</Button>
</DialogClose>
<Button
variant="primary"
onClick={handleConfirm}
>
Create file
</Button>
</Flex>
<DialogClose asChild>
<Box css={{ position: "absolute", top: "$3", right: "$3" }}>
@@ -211,9 +241,7 @@ const EditorNavigation = ({ showWat }: { showWat?: boolean }) => {
zIndex: 1,
}}
>
<Container
css={{ width: "unset", display: "flex", alignItems: "center" }}
>
<Container css={{ width: "unset", display: "flex", alignItems: "center" }}>
{status === "authenticated" ? (
<DropdownMenu>
<DropdownMenuTrigger asChild>
@@ -246,15 +274,10 @@ const EditorNavigation = ({ showWat }: { showWat?: boolean }) => {
</DropdownMenuTrigger>
<DropdownMenuContent>
<DropdownMenuItem disabled onClick={() => signOut()}>
<User size="16px" /> {session?.user?.username} (
{session?.user.name})
<User size="16px" /> {session?.user?.username} ({session?.user.name})
</DropdownMenuItem>
<DropdownMenuItem
onClick={() =>
window.open(
`http://gist.github.com/${session?.user.username}`
)
}
onClick={() => window.open(`http://gist.github.com/${session?.user.username}`)}
>
<ArrowSquareOut size="16px" />
Go to your Gist
@@ -268,12 +291,7 @@ const EditorNavigation = ({ showWat }: { showWat?: boolean }) => {
</DropdownMenuContent>
</DropdownMenu>
) : (
<Button
outline
size="sm"
css={{ mr: "$3" }}
onClick={() => setPopUp(true)}
>
<Button outline size="sm" css={{ mr: "$3" }} onClick={() => setPopUp(true)}>
<GithubLogo size="16px" /> Login
</Button>
)}
@@ -320,9 +338,7 @@ const EditorNavigation = ({ showWat }: { showWat?: boolean }) => {
size="sm"
css={{ alignItems: "center" }}
onClick={() => {
navigator.clipboard.writeText(
`${window.location.origin}/develop/${snap.gistId}`
);
navigator.clipboard.writeText(`${window.location.origin}/develop/${snap.gistId}`);
toast.success("Copied share link to clipboard!");
}}
>
@@ -367,9 +383,7 @@ const EditorNavigation = ({ showWat }: { showWat?: boolean }) => {
Copy share link to clipboard
</DropdownMenuItem>
<DropdownMenuItem
disabled={
session?.user.username !== snap.gistOwner || !snap.gistId
}
disabled={session?.user.username !== snap.gistOwner || !snap.gistId}
onClick={() => {
syncToGist(session);
}}
@@ -395,21 +409,15 @@ const EditorNavigation = ({ showWat }: { showWat?: boolean }) => {
</DropdownMenu>
</Stack>
{popup && !session ? (
<NewWindow center="parent" url="/sign-in" />
) : null}
{popup && !session ? <NewWindow center="parent" url="/sign-in" /> : null}
</Container>
</Flex>
<AlertDialog
open={createNewAlertOpen}
onOpenChange={(value) => setCreateNewAlertOpen(value)}
>
<AlertDialog open={createNewAlertOpen} onOpenChange={value => setCreateNewAlertOpen(value)}>
<AlertDialogContent>
<AlertDialogTitle>Are you sure?</AlertDialogTitle>
<AlertDialogDescription>
This action will create new <strong>public</strong> Github Gist from
your current saved files. You can delete gist anytime from your
GitHub Gists page.
This action will create new <strong>public</strong> Github Gist from your current saved
files. You can delete gist anytime from your GitHub Gists page.
</AlertDialogDescription>
<Flex css={{ justifyContent: "flex-end", gap: "$3" }}>
<AlertDialogCancel asChild>
@@ -443,8 +451,8 @@ const EditorNavigation = ({ showWat }: { showWat?: boolean }) => {
type="number"
min="1"
value={editorSettings.tabSize}
onChange={(e) =>
setEditorSettings((curr) => ({
onChange={e =>
setEditorSettings(curr => ({
...curr,
tabSize: Number(e.target.value),
}))
@@ -454,18 +462,12 @@ const EditorNavigation = ({ showWat }: { showWat?: boolean }) => {
<Flex css={{ marginTop: 25, justifyContent: "flex-end", gap: "$3" }}>
<DialogClose asChild>
<Button
outline
onClick={() => updateEditorSettings(editorSettings)}
>
<Button outline onClick={() => updateEditorSettings(editorSettings)}>
Cancel
</Button>
</DialogClose>
<DialogClose asChild>
<Button
variant="primary"
onClick={() => updateEditorSettings(editorSettings)}
>
<Button variant="primary" onClick={() => updateEditorSettings(editorSettings)}>
Save changes
</Button>
</DialogClose>

View File

@@ -45,7 +45,7 @@
"vscode-uri": "^3.0.2",
"wabt": "1.0.16",
"xrpl-accountlib": "^1.2.3",
"xrpl-client": "^1.9.2"
"xrpl-client": "^1.9.3"
},
"devDependencies": {
"@types/dinero.js": "^1.9.0",

View File

@@ -1,3 +1,4 @@
import Router from "next/router";
import toast from "react-hot-toast";
import state, { FaucetAccountRes } from '../index';
@@ -31,30 +32,35 @@ export const addFaucetAccount = async (showToast: boolean = false) => {
if (state.accounts.length > 4) {
return toast.error("You can only have maximum 5 accounts");
}
const toastId = showToast ? toast.loading("Creating account") : "";
const res = await fetch(`${process.env.NEXT_PUBLIC_SITE_URL}/api/faucet`, {
method: "POST",
});
const json: FaucetAccountRes | { error: string } = await res.json();
if ("error" in json) {
if (showToast) {
return toast.error(json.error, { id: toastId });
} else {
return;
}
} else {
if (showToast) {
toast.success("New account created", { id: toastId });
}
state.accounts.push({
name: names[state.accounts.length],
xrp: (json.xrp || 0 * 1000000).toString(),
address: json.address,
secret: json.secret,
sequence: 1,
hooks: [],
isLoading: false,
if (typeof window !== 'undefined') {
const toastId = showToast ? toast.loading("Creating account") : "";
console.log(Router)
const res = await fetch(`${window.location.origin}/api/faucet`, {
method: "POST",
});
const json: FaucetAccountRes | { error: string } = await res.json();
if ("error" in json) {
if (showToast) {
return toast.error(json.error, { id: toastId });
} else {
return;
}
} else {
if (showToast) {
toast.success("New account created", { id: toastId });
}
state.accounts.push({
name: names[state.accounts.length],
xrp: (json.xrp || 0 * 1000000).toString(),
address: json.address,
secret: json.secret,
sequence: 1,
hooks: [],
isLoading: false,
});
}
}
};

View File

@@ -4642,10 +4642,10 @@ xrpl-accountlib@^1.2.3:
xrpl-secret-numbers "^0.3.3"
xrpl-sign-keypairs "^2.0.0"
xrpl-client@^1.9.2:
version "1.9.2"
resolved "https://registry.yarnpkg.com/xrpl-client/-/xrpl-client-1.9.2.tgz#c018510b050e678e09b8640533a57c50d4e586e9"
integrity sha512-foFrFqfYxpkj8La9k1G9ZJEbVOHJpvIIt0koNaw/3nlTUUnbyTENtr112CnHEh+z2JMqJxBB9JpmZavGDhMlKg==
xrpl-client@^1.9.3:
version "1.9.3"
resolved "https://registry.yarnpkg.com/xrpl-client/-/xrpl-client-1.9.3.tgz#1f2c17f7677d271a854e74d6035d6334cacf1629"
integrity sha512-TouyBeXuDXZWvO+4HrlvfrVtoXXyi9ny4+vpZoMCd2EbljsdFFTU6ujAqu81BvujkathKMTHiB81cR1bTL8ypw==
dependencies:
debug "^4.1.1"
websocket "^1.0.34"