import React, { useState, useEffect, useCallback } from "react"; import { Plus, Share, DownloadSimple, Gear, X, GithubLogo, SignOut, ArrowSquareOut, CloudArrowUp, CaretDown, User, FilePlus, } from "phosphor-react"; import Image from "next/image"; import { DropdownMenu, DropdownMenuTrigger, DropdownMenuContent, DropdownMenuItem, DropdownMenuArrow, DropdownMenuSeparator, } from "./DropdownMenu"; import NewWindow from "react-new-window"; import { signOut, useSession } from "next-auth/react"; import { useSnapshot } from "valtio"; import { createNewFile, syncToGist, updateEditorSettings, downloadAsZip } from "../state/actions"; import state from "../state"; import Box from "./Box"; import Button from "./Button"; import Container from "./Container"; import { Dialog, DialogTrigger, DialogContent, DialogTitle, DialogDescription, DialogClose, } from "./Dialog"; import Flex from "./Flex"; import Stack from "./Stack"; import Input from "./Input"; import Text from "./Text"; import toast from "react-hot-toast"; import { AlertDialog, AlertDialogContent, AlertDialogTitle, AlertDialogDescription, 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(null); const [filename, setFilename] = useState(""); const { data: session, status } = useSession(); const [popup, setPopUp] = useState(false); const [editorSettings, setEditorSettings] = useState(snap.editorSettings); useEffect(() => { if (session && session.user && popup) { 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 ( {files && files.length > 0 && files.map((file, index) => { if (!file.compiledContent && showWat) { return null; } return ( ); })} {!showWat && ( Create new file setFilename(e.target.value)} onKeyPress={e => { if (e.key === "Enter") { handleConfirm(); } }} /> {newfileError} )} {status === "authenticated" ? ( User avatar signOut()}> {session?.user?.username} ({session?.user.name}) window.open(`http://gist.github.com/${session?.user.username}`)} > Go to your Gist signOut({ callbackUrl: "/" })}> Log out ) : ( )} Download as ZIP { navigator.clipboard.writeText( `${window.location.origin}/develop/${snap.gistId}` ); toast.success("Copied share link to clipboard!"); }} > Copy share link to clipboard { syncToGist(session); }} > Push to Gist { setCreateNewAlertOpen(true); }} > Create as a new Gist setEditorSettingsOpen(true)}> Editor Settings {popup && !session ? : null} setCreateNewAlertOpen(value)}> Are you sure? This action will create new public Github Gist from your current saved files. You can delete gist anytime from your GitHub Gists page. {/* */} Editor settings setEditorSettings(curr => ({ ...curr, tabSize: Number(e.target.value), })) } /> ); }; export default EditorNavigation;