From 76b2fc7e0f41922203dffcf6fbe182443233c94e Mon Sep 17 00:00:00 2001 From: Ishaan Dey Date: Sat, 27 Apr 2024 11:08:19 -0400 Subject: [PATCH] start file rename logic --- frontend/components/editor/index.tsx | 23 ++++++++++-- frontend/components/editor/sidebar/file.tsx | 37 ++++++++++++++++--- frontend/components/editor/sidebar/folder.tsx | 4 +- frontend/components/editor/sidebar/index.tsx | 4 +- frontend/components/editor/sidebar/types.ts | 4 ++ frontend/components/ui/tab.tsx | 17 +++++++-- 6 files changed, 73 insertions(+), 16 deletions(-) diff --git a/frontend/components/editor/index.tsx b/frontend/components/editor/index.tsx index 0be779e..ce18f1b 100644 --- a/frontend/components/editor/index.tsx +++ b/frontend/components/editor/index.tsx @@ -13,13 +13,14 @@ import { import { ChevronLeft, ChevronRight, + FileJson, RotateCw, TerminalSquare, } from "lucide-react" import Tab from "../ui/tab" import Sidebar from "./sidebar" import { useClerk } from "@clerk/nextjs" -import { TFile, TFileData, TFolder } from "./sidebar/types" +import { TFile, TFileData, TFolder, TTab } from "./sidebar/types" import { io } from "socket.io-client" import { set } from "zod" @@ -41,7 +42,7 @@ export default function CodeEditor({ const [files, setFiles] = useState<(TFolder | TFile)[]>([]) const [editorLanguage, setEditorLanguage] = useState("plaintext") const [activeFile, setActiveFile] = useState(null) - const [tabs, setTabs] = useState([]) + const [tabs, setTabs] = useState([]) const [activeId, setActiveId] = useState(null) const socket = io( @@ -81,7 +82,7 @@ export default function CodeEditor({ const clerk = useClerk() - const selectFile = (tab: TFile) => { + const selectFile = (tab: TTab) => { setTabs((prev) => { const exists = prev.find((t) => t.id === tab.id) if (exists) { @@ -115,6 +116,13 @@ export default function CodeEditor({ setTabs((prev) => prev.filter((t) => t.id !== tab.id)) } + const handleFileNameChange = (id: string, newName: string) => { + socket.emit("renameFile", id, newName) + setTabs((prev) => + prev.map((tab) => (tab.id === id ? { ...tab, name: newName } : tab)) + ) + } + return ( <> @@ -129,6 +137,7 @@ export default function CodeEditor({ {tabs.map((tab) => ( { selectFile(tab) @@ -143,6 +152,7 @@ export default function CodeEditor({ {activeId === null ? ( <>
+ No file selected.
@@ -152,6 +162,13 @@ export default function CodeEditor({ // defaultLanguage="typescript" language={editorLanguage} onMount={handleEditorMount} + onChange={(value) => { + setTabs((prev) => + prev.map((tab) => + tab.id === activeId ? { ...tab, saved: false } : tab + ) + ) + }} options={{ minimap: { enabled: false, diff --git a/frontend/components/editor/sidebar/file.tsx b/frontend/components/editor/sidebar/file.tsx index e7a4e62..e6ad7b0 100644 --- a/frontend/components/editor/sidebar/file.tsx +++ b/frontend/components/editor/sidebar/file.tsx @@ -2,21 +2,32 @@ import Image from "next/image" import { getIconForFile } from "vscode-icons-js" -import { TFile } from "./types" -import { useEffect, useState } from "react" +import { TFile, TTab } from "./types" +import { useEffect, useRef, useState } from "react" export default function SidebarFile({ data, selectFile, }: { data: TFile - selectFile: (file: TFile) => void + selectFile: (file: TTab) => void }) { const [imgSrc, setImgSrc] = useState(`/icons/${getIconForFile(data.name)}`) + const [editing, setEditing] = useState(false) + const inputRef = useRef(null) + + useEffect(() => { + if (editing) { + inputRef.current?.focus() + } + }, [editing]) return ( ) } diff --git a/frontend/components/editor/sidebar/folder.tsx b/frontend/components/editor/sidebar/folder.tsx index d4bdc74..a275acd 100644 --- a/frontend/components/editor/sidebar/folder.tsx +++ b/frontend/components/editor/sidebar/folder.tsx @@ -3,7 +3,7 @@ import Image from "next/image" import { useState } from "react" import { getIconForFolder, getIconForOpenFolder } from "vscode-icons-js" -import { TFile, TFolder } from "./types" +import { TFile, TFolder, TTab } from "./types" import SidebarFile from "./file" export default function SidebarFolder({ @@ -11,7 +11,7 @@ export default function SidebarFolder({ selectFile, }: { data: TFolder - selectFile: (file: TFile) => void + selectFile: (file: TTab) => void }) { const [isOpen, setIsOpen] = useState(false) const folder = isOpen diff --git a/frontend/components/editor/sidebar/index.tsx b/frontend/components/editor/sidebar/index.tsx index 535a702..c72c343 100644 --- a/frontend/components/editor/sidebar/index.tsx +++ b/frontend/components/editor/sidebar/index.tsx @@ -3,7 +3,7 @@ import { FilePlus, FolderPlus, Loader2, Search } from "lucide-react" import SidebarFile from "./file" import SidebarFolder from "./folder" -import { TFile, TFolder } from "./types" +import { TFile, TFolder, TTab } from "./types" // Note: add renaming validation: // In general: must not contain / or \ or whitespace, not empty, no duplicates @@ -15,7 +15,7 @@ export default function Sidebar({ selectFile, }: { files: (TFile | TFolder)[] - selectFile: (tab: TFile) => void + selectFile: (tab: TTab) => void }) { return (
diff --git a/frontend/components/editor/sidebar/types.ts b/frontend/components/editor/sidebar/types.ts index cfb6ca0..5ce1f4e 100644 --- a/frontend/components/editor/sidebar/types.ts +++ b/frontend/components/editor/sidebar/types.ts @@ -11,6 +11,10 @@ export type TFile = { name: string } +export type TTab = TFile & { + saved: boolean +} + export type TFileData = { id: string data: string diff --git a/frontend/components/ui/tab.tsx b/frontend/components/ui/tab.tsx index 1c42244..f288df4 100644 --- a/frontend/components/ui/tab.tsx +++ b/frontend/components/ui/tab.tsx @@ -6,11 +6,13 @@ import { useEffect } from "react" export default function Tab({ children, - selected, + saved = true, + selected = false, onClick, onClose, }: { children: React.ReactNode + saved?: boolean selected?: boolean onClick?: () => void onClose?: () => void @@ -20,7 +22,7 @@ export default function Tab({ onClick={onClick ?? undefined} size="sm" variant={"secondary"} - className={`group font-normal select-none ${ + className={`font-normal select-none ${ selected ? "bg-neutral-700 hover:bg-neutral-600 text-foreground" : "text-muted-foreground" @@ -37,9 +39,16 @@ export default function Tab({ } : undefined } - className="h-5 w-5 ml-0.5 flex items-center justify-center translate-x-1 transition-colors bg-transparent hover:bg-muted-foreground/25 cursor-pointer rounded-sm" + className="h-5 w-5 ml-0.5 group flex items-center justify-center translate-x-1 transition-colors bg-transparent hover:bg-muted-foreground/25 cursor-pointer rounded-sm" > - + {saved ? ( + + ) : ( + <> + +
+ + )}
)