shared user restrictions + cleanup console logs

This commit is contained in:
Ishaan Dey 2024-05-07 22:40:59 -07:00
parent 9d288f580d
commit 12e8051673
12 changed files with 194 additions and 174 deletions

View File

@ -94,7 +94,6 @@ export default {
const initStorageRes = await env.STORAGE.fetch(initStorageRequest); const initStorageRes = await env.STORAGE.fetch(initStorageRequest);
const initStorage = await initStorageRes.text(); const initStorage = await initStorageRes.text();
console.log("initStorage: ", initStorage);
return new Response(sb.id, { status: 200 }); return new Response(sb.id, { status: 200 });
} else { } else {

View File

@ -39,6 +39,7 @@ const io = new Server(httpServer, {
}) })
let inactivityTimeout: NodeJS.Timeout | null = null; let inactivityTimeout: NodeJS.Timeout | null = null;
let isOwnerConnected = false;
const terminals: { const terminals: {
[id: string]: { terminal: IPty; onData: IDisposable; onExit: IDisposable } [id: string]: { terminal: IPty; onData: IDisposable; onExit: IDisposable }
@ -58,7 +59,7 @@ io.use(async (socket, next) => {
const parseQuery = handshakeSchema.safeParse(q) const parseQuery = handshakeSchema.safeParse(q)
if (!parseQuery.success) { if (!parseQuery.success) {
console.log("Invalid request.") ("Invalid request.")
next(new Error("Invalid request.")) next(new Error("Invalid request."))
return return
} }
@ -68,7 +69,6 @@ io.use(async (socket, next) => {
const dbUserJSON = (await dbUser.json()) as User const dbUserJSON = (await dbUser.json()) as User
if (!dbUserJSON) { if (!dbUserJSON) {
console.log("DB error.")
next(new Error("DB error.")) next(new Error("DB error."))
return return
} }
@ -79,7 +79,6 @@ io.use(async (socket, next) => {
) )
if (!sandbox && !sharedSandboxes) { if (!sandbox && !sharedSandboxes) {
console.log("Invalid credentials.")
next(new Error("Invalid credentials.")) next(new Error("Invalid credentials."))
return return
} }
@ -103,6 +102,15 @@ io.on("connection", async (socket) => {
isOwner: boolean isOwner: boolean
} }
if (data.isOwner) {
isOwnerConnected = true
} else {
if (!isOwnerConnected) {
socket.emit("disableAccess", "The sandbox owner is not connected.")
return
}
}
const sandboxFiles = await getSandboxFiles(data.sandboxId) const sandboxFiles = await getSandboxFiles(data.sandboxId)
sandboxFiles.fileData.forEach((file) => { sandboxFiles.fileData.forEach((file) => {
const filePath = path.join(dirName, file.id) const filePath = path.join(dirName, file.id)
@ -224,12 +232,7 @@ io.on("connection", async (socket) => {
socket.on("createTerminal", (id: string, callback) => { socket.on("createTerminal", (id: string, callback) => {
console.log("creating terminal", id) console.log("creating terminal", id)
if (terminals[id]) { if (terminals[id] || Object.keys(terminals).length >= 4) {
console.log("Terminal already exists.")
return
}
if (Object.keys(terminals).length >= 4) {
console.log("Too many terminals.")
return return
} }
@ -240,9 +243,7 @@ io.on("connection", async (socket) => {
}) })
const onData = pty.onData((data) => { const onData = pty.onData((data) => {
console.log("ondata")
socket.emit("terminalResponse", { socket.emit("terminalResponse", {
// data: Buffer.from(data, "utf-8").toString("base64"),
id, id,
data, data,
}) })
@ -263,7 +264,6 @@ io.on("connection", async (socket) => {
socket.on("terminalData", (id: string, data: string) => { socket.on("terminalData", (id: string, data: string) => {
if (!terminals[id]) { if (!terminals[id]) {
console.log("terminals", terminals)
return return
} }
@ -276,7 +276,6 @@ io.on("connection", async (socket) => {
socket.on("closeTerminal", (id: string, callback) => { socket.on("closeTerminal", (id: string, callback) => {
if (!terminals[id]) { if (!terminals[id]) {
console.log("tried to close, but term does not exist. terminals", terminals)
return return
} }
@ -332,11 +331,7 @@ io.on("connection", async (socket) => {
delete terminals[t[0]] delete terminals[t[0]]
}) })
// console.log("The owner disconnected.") socket.broadcast.emit("disableAccess", "The sandbox owner has disconnected.")
socket.broadcast.emit("ownerDisconnected")
}
else {
// console.log("A shared user disconnected.")
} }
const sockets = await io.fetchSockets() const sockets = await io.fetchSockets()

View File

@ -16,7 +16,6 @@ export const getSandboxFiles = async (id: string) => {
const paths = sandboxData.objects.map((obj) => obj.key) const paths = sandboxData.objects.map((obj) => obj.key)
const processedFiles = await processFiles(paths, id) const processedFiles = await processFiles(paths, id)
// console.log("processedFiles.fileData:", processedFiles.fileData)
return processedFiles return processedFiles
} }
@ -27,7 +26,6 @@ const processFiles = async (paths: string[], id: string) => {
paths.forEach((path) => { paths.forEach((path) => {
const allParts = path.split("/") const allParts = path.split("/")
if (allParts[1] !== id) { if (allParts[1] !== id) {
console.log("invalid path!!!!")
return return
} }

View File

@ -1,22 +1,22 @@
import { User } from "@/lib/types" import { User } from "@/lib/types";
import { currentUser } from "@clerk/nextjs" import { currentUser } from "@clerk/nextjs";
import { redirect } from "next/navigation" import { redirect } from "next/navigation";
export default async function AppAuthLayout({ export default async function AppAuthLayout({
children, children,
}: { }: {
children: React.ReactNode children: React.ReactNode;
}) { }) {
const user = await currentUser() const user = await currentUser();
if (!user) { if (!user) {
redirect("/") redirect("/");
} }
const dbUser = await fetch( const dbUser = await fetch(
`https://database.ishaan1013.workers.dev/api/user?id=${user.id}` `https://database.ishaan1013.workers.dev/api/user?id=${user.id}`
) );
const dbUserJSON = (await dbUser.json()) as User const dbUserJSON = (await dbUser.json()) as User;
if (!dbUserJSON.id) { if (!dbUserJSON.id) {
const res = await fetch( const res = await fetch(
@ -32,12 +32,8 @@ export default async function AppAuthLayout({
email: user.emailAddresses[0].emailAddress, email: user.emailAddresses[0].emailAddress,
}), }),
} }
) );
console.log(res)
} else {
// user already exists in db
} }
return <>{children}</> return <>{children}</>;
} }

View File

@ -1,26 +1,25 @@
"use client" "use client";
import { Input } from "../../ui/input" import { Input } from "../../ui/input";
import { Search } from "lucide-react" import { Search } from "lucide-react";
import { useEffect, useState } from "react" import { useEffect, useState } from "react";
import { useRouter } from "next/navigation" import { useRouter } from "next/navigation";
export default function DashboardNavbarSearch() { export default function DashboardNavbarSearch() {
const [search, setSearch] = useState("") const [search, setSearch] = useState("");
const router = useRouter() const router = useRouter();
useEffect(() => { useEffect(() => {
const delayDebounceFn = setTimeout(() => { const delayDebounceFn = setTimeout(() => {
console.log("SEARCH", search)
if (search) { if (search) {
router.push(`/dashboard?q=${search}`) router.push(`/dashboard?q=${search}`);
} else { } else {
router.push(`/dashboard`) router.push(`/dashboard`);
} }
}, 300) }, 300);
return () => clearTimeout(delayDebounceFn) return () => clearTimeout(delayDebounceFn);
}, [search]) }, [search]);
return ( return (
<div className="relative h-9 w-44 flex items-center justify-start"> <div className="relative h-9 w-44 flex items-center justify-start">
@ -32,5 +31,5 @@ export default function DashboardNavbarSearch() {
className="pl-8" className="pl-8"
/> />
</div> </div>
) );
} }

View File

@ -88,7 +88,6 @@ export default function CodeEditor({
const clerk = useClerk(); const clerk = useClerk();
const room = useRoom(); const room = useRoom();
const activeTerminal = terminals.find((t) => t.id === activeTerminalId); const activeTerminal = terminals.find((t) => t.id === activeTerminalId);
console.log("activeTerminal", activeTerminal ? activeTerminal.id : "none");
// const editorRef = useRef<monaco.editor.IStandaloneCodeEditor | null>(null) // const editorRef = useRef<monaco.editor.IStandaloneCodeEditor | null>(null)
const [editorRef, setEditorRef] = const [editorRef, setEditorRef] =
@ -270,9 +269,6 @@ export default function CodeEditor({
if (e.key === "s" && (e.metaKey || e.ctrlKey)) { if (e.key === "s" && (e.metaKey || e.ctrlKey)) {
e.preventDefault(); e.preventDefault();
// const activeTab = tabs.find((t) => t.id === activeFileId)
// console.log("saving:", activeTab?.name, editorRef?.getValue())
setTabs((prev) => setTabs((prev) =>
prev.map((tab) => prev.map((tab) =>
tab.id === activeFileId ? { ...tab, saved: true } : tab tab.id === activeFileId ? { ...tab, saved: true } : tab
@ -367,7 +363,11 @@ export default function CodeEditor({
createTerminal(); createTerminal();
}; };
const onDisconnect = () => {}; const onDisconnect = () => {
console.log("disconnected");
closeAllTerminals();
};
const onLoadedEvent = (files: (TFolder | TFile)[]) => { const onLoadedEvent = (files: (TFolder | TFile)[]) => {
setFiles(files); setFiles(files);
@ -385,11 +385,19 @@ export default function CodeEditor({
if (term && term.terminal) term.terminal.write(res); if (term && term.terminal) term.terminal.write(res);
}; };
const onDisableAccess = (message: string) => {
setDisableAccess({
isDisabled: true,
message,
});
};
socket.on("connect", onConnect); socket.on("connect", onConnect);
socket.on("disconnect", onDisconnect); socket.on("disconnect", onDisconnect);
socket.on("loaded", onLoadedEvent); socket.on("loaded", onLoadedEvent);
socket.on("rateLimit", onRateLimit); socket.on("rateLimit", onRateLimit);
socket.on("terminalResponse", onTerminalResponse); socket.on("terminalResponse", onTerminalResponse);
socket.on("disableAccess", onDisableAccess);
return () => { return () => {
socket.off("connect", onConnect); socket.off("connect", onConnect);
@ -397,6 +405,7 @@ export default function CodeEditor({
socket.off("loaded", onLoadedEvent); socket.off("loaded", onLoadedEvent);
socket.off("rateLimit", onRateLimit); socket.off("rateLimit", onRateLimit);
socket.off("terminalResponse", onTerminalResponse); socket.off("terminalResponse", onTerminalResponse);
socket.off("disableAccess", onDisableAccess);
}; };
}, []); }, []);
@ -492,6 +501,13 @@ export default function CodeEditor({
}); });
}; };
const closeAllTerminals = () => {
terminals.forEach((term) => {
socket.emit("closeTerminal", term.id, () => {}); // no need to wait for response here
setTerminals((prev) => prev.filter((t) => t.id !== term.id));
});
};
const handleRename = ( const handleRename = (
id: string, id: string,
newName: string, newName: string,

View File

@ -9,7 +9,15 @@ import {
DialogTrigger, DialogTrigger,
} from "@/components/ui/dialog"; } from "@/components/ui/dialog";
import { ChevronRight, FileStack, Globe, TextCursor } from "lucide-react"; import {
ChevronRight,
FileStack,
Globe,
Loader2,
TextCursor,
} from "lucide-react";
import { useRouter } from "next/navigation";
import { useEffect } from "react";
export default function DisableAccessModal({ export default function DisableAccessModal({
open, open,
@ -20,13 +28,30 @@ export default function DisableAccessModal({
setOpen: (open: boolean) => void; setOpen: (open: boolean) => void;
message: string; message: string;
}) { }) {
const router = useRouter();
useEffect(() => {
if (open) {
const timeout = setTimeout(() => {
router.push("/dashboard");
}, 5000);
return () => clearTimeout(timeout);
}
}, []);
return ( return (
<Dialog open={open} onOpenChange={setOpen}> <Dialog open={open} onOpenChange={setOpen}>
<DialogContent> <DialogContent>
<DialogHeader> <DialogHeader>
<DialogTitle>Live Collaboration Disabled</DialogTitle> <DialogTitle>Live Collaboration Disabled</DialogTitle>
</DialogHeader> </DialogHeader>
<div className="text-sm text-muted-foreground">{message}</div> <div className="text-sm text-muted-foreground space-y-2">
<div>{message}</div>
<div className="flex items-center">
<Loader2 className="w-4 h-4 animate-spin mr-2" />
Redirecting you to dashboard...
</div>
</div>
</DialogContent> </DialogContent>
</Dialog> </Dialog>
); );

View File

@ -1,4 +1,4 @@
"use client" "use client";
import { import {
Dialog, Dialog,
@ -7,10 +7,10 @@ import {
DialogHeader, DialogHeader,
DialogTitle, DialogTitle,
DialogTrigger, DialogTrigger,
} from "@/components/ui/dialog" } from "@/components/ui/dialog";
import { z } from "zod" import { z } from "zod";
import { zodResolver } from "@hookform/resolvers/zod" import { zodResolver } from "@hookform/resolvers/zod";
import { useForm } from "react-hook-form" import { useForm } from "react-hook-form";
import { import {
Form, Form,
@ -20,41 +20,41 @@ import {
FormItem, FormItem,
FormLabel, FormLabel,
FormMessage, FormMessage,
} from "@/components/ui/form" } from "@/components/ui/form";
import { Input } from "@/components/ui/input" import { Input } from "@/components/ui/input";
import { import {
Select, Select,
SelectContent, SelectContent,
SelectItem, SelectItem,
SelectTrigger, SelectTrigger,
SelectValue, SelectValue,
} from "@/components/ui/select" } from "@/components/ui/select";
import { Loader2 } from "lucide-react" import { Loader2 } from "lucide-react";
import { useState } from "react" import { useState } from "react";
import { Sandbox } from "@/lib/types" import { Sandbox } from "@/lib/types";
import { Button } from "@/components/ui/button" import { Button } from "@/components/ui/button";
import { deleteSandbox, updateSandbox } from "@/lib/actions" import { deleteSandbox, updateSandbox } from "@/lib/actions";
import { useRouter } from "next/navigation" import { useRouter } from "next/navigation";
import { toast } from "sonner" import { toast } from "sonner";
const formSchema = z.object({ const formSchema = z.object({
name: z.string().min(1).max(16), name: z.string().min(1).max(16),
visibility: z.enum(["public", "private"]), visibility: z.enum(["public", "private"]),
}) });
export default function EditSandboxModal({ export default function EditSandboxModal({
open, open,
setOpen, setOpen,
data, data,
}: { }: {
open: boolean open: boolean;
setOpen: (open: boolean) => void setOpen: (open: boolean) => void;
data: Sandbox data: Sandbox;
}) { }) {
const [loading, setLoading] = useState(false) const [loading, setLoading] = useState(false);
const [loadingDelete, setLoadingDelete] = useState(false) const [loadingDelete, setLoadingDelete] = useState(false);
const router = useRouter() const router = useRouter();
const form = useForm<z.infer<typeof formSchema>>({ const form = useForm<z.infer<typeof formSchema>>({
resolver: zodResolver(formSchema), resolver: zodResolver(formSchema),
@ -62,24 +62,22 @@ export default function EditSandboxModal({
name: data.name, name: data.name,
visibility: data.visibility, visibility: data.visibility,
}, },
}) });
async function onSubmit(values: z.infer<typeof formSchema>) { async function onSubmit(values: z.infer<typeof formSchema>) {
console.log(values) setLoading(true);
await updateSandbox({ id: data.id, ...values });
setLoading(true) toast.success("Sandbox updated successfully");
await updateSandbox({ id: data.id, ...values })
toast.success("Sandbox updated successfully") setLoading(false);
setLoading(false)
} }
async function onDelete() { async function onDelete() {
setLoadingDelete(true) setLoadingDelete(true);
await deleteSandbox(data.id) await deleteSandbox(data.id);
router.push("/dashboard") router.push("/dashboard");
} }
return ( return (
@ -155,5 +153,5 @@ export default function EditSandboxModal({
</Button> </Button>
</DialogContent> </DialogContent>
</Dialog> </Dialog>
) );
} }

View File

@ -1,16 +1,16 @@
"use client" "use client";
import Image from "next/image" import Image from "next/image";
import { getIconForFile } from "vscode-icons-js" import { getIconForFile } from "vscode-icons-js";
import { TFile, TTab } from "@/lib/types" import { TFile, TTab } from "@/lib/types";
import { useEffect, useRef, useState } from "react" import { useEffect, useRef, useState } from "react";
import { import {
ContextMenu, ContextMenu,
ContextMenuContent, ContextMenuContent,
ContextMenuItem, ContextMenuItem,
ContextMenuTrigger, ContextMenuTrigger,
} from "@/components/ui/context-menu" } from "@/components/ui/context-menu";
import { Loader2, Pencil, Trash2 } from "lucide-react" import { Loader2, Pencil, Trash2 } from "lucide-react";
export default function SidebarFile({ export default function SidebarFile({
data, data,
@ -18,29 +18,26 @@ export default function SidebarFile({
handleRename, handleRename,
handleDeleteFile, handleDeleteFile,
}: { }: {
data: TFile data: TFile;
selectFile: (file: TTab) => void selectFile: (file: TTab) => void;
handleRename: ( handleRename: (
id: string, id: string,
newName: string, newName: string,
oldName: string, oldName: string,
type: "file" | "folder" type: "file" | "folder"
) => boolean ) => boolean;
handleDeleteFile: (file: TFile) => void handleDeleteFile: (file: TFile) => void;
}) { }) {
const [imgSrc, setImgSrc] = useState(`/icons/${getIconForFile(data.name)}`) const [imgSrc, setImgSrc] = useState(`/icons/${getIconForFile(data.name)}`);
const [editing, setEditing] = useState(false) const [editing, setEditing] = useState(false);
const inputRef = useRef<HTMLInputElement>(null) const inputRef = useRef<HTMLInputElement>(null);
const [pendingDelete, setPendingDelete] = useState(false) const [pendingDelete, setPendingDelete] = useState(false);
useEffect(() => { useEffect(() => {
if (editing) { if (editing) {
setTimeout(() => inputRef.current?.focus(), 0) setTimeout(() => inputRef.current?.focus(), 0);
} }
if (!inputRef.current) { }, [editing, inputRef.current]);
console.log("no input ref")
}
}, [editing, inputRef.current])
const renameFile = () => { const renameFile = () => {
const renamed = handleRename( const renamed = handleRename(
@ -48,19 +45,19 @@ export default function SidebarFile({
inputRef.current?.value ?? data.name, inputRef.current?.value ?? data.name,
data.name, data.name,
"file" "file"
) );
if (!renamed && inputRef.current) { if (!renamed && inputRef.current) {
inputRef.current.value = data.name inputRef.current.value = data.name;
} }
setEditing(false) setEditing(false);
} };
return ( return (
<ContextMenu> <ContextMenu>
<ContextMenuTrigger <ContextMenuTrigger
disabled={pendingDelete} disabled={pendingDelete}
onClick={() => { onClick={() => {
if (!editing && !pendingDelete) selectFile({ ...data, saved: true }) if (!editing && !pendingDelete) selectFile({ ...data, saved: true });
}} }}
// onDoubleClick={() => { // onDoubleClick={() => {
// setEditing(true) // setEditing(true)
@ -83,8 +80,8 @@ export default function SidebarFile({
) : ( ) : (
<form <form
onSubmit={(e) => { onSubmit={(e) => {
e.preventDefault() e.preventDefault();
renameFile() renameFile();
}} }}
> >
<input <input
@ -102,8 +99,8 @@ export default function SidebarFile({
<ContextMenuContent> <ContextMenuContent>
<ContextMenuItem <ContextMenuItem
onClick={() => { onClick={() => {
console.log("rename") console.log("rename");
setEditing(true) setEditing(true);
}} }}
> >
<Pencil className="w-4 h-4 mr-2" /> <Pencil className="w-4 h-4 mr-2" />
@ -112,9 +109,9 @@ export default function SidebarFile({
<ContextMenuItem <ContextMenuItem
disabled={pendingDelete} disabled={pendingDelete}
onClick={() => { onClick={() => {
console.log("delete") console.log("delete");
setPendingDelete(true) setPendingDelete(true);
handleDeleteFile(data) handleDeleteFile(data);
}} }}
> >
<Trash2 className="w-4 h-4 mr-2" /> <Trash2 className="w-4 h-4 mr-2" />
@ -122,5 +119,5 @@ export default function SidebarFile({
</ContextMenuItem> </ContextMenuItem>
</ContextMenuContent> </ContextMenuContent>
</ContextMenu> </ContextMenu>
) );
} }

View File

@ -1,17 +1,17 @@
"use client" "use client";
import Image from "next/image" import Image from "next/image";
import { useEffect, useRef, useState } from "react" import { useEffect, useRef, useState } from "react";
import { getIconForFolder, getIconForOpenFolder } from "vscode-icons-js" import { getIconForFolder, getIconForOpenFolder } from "vscode-icons-js";
import { TFile, TFolder, TTab } from "@/lib/types" import { TFile, TFolder, TTab } from "@/lib/types";
import SidebarFile from "./file" import SidebarFile from "./file";
import { import {
ContextMenu, ContextMenu,
ContextMenuContent, ContextMenuContent,
ContextMenuItem, ContextMenuItem,
ContextMenuTrigger, ContextMenuTrigger,
} from "@/components/ui/context-menu" } from "@/components/ui/context-menu";
import { Pencil, Trash2 } from "lucide-react" import { Pencil, Trash2 } from "lucide-react";
export default function SidebarFolder({ export default function SidebarFolder({
data, data,
@ -20,30 +20,30 @@ export default function SidebarFolder({
handleDeleteFile, handleDeleteFile,
handleDeleteFolder, handleDeleteFolder,
}: { }: {
data: TFolder data: TFolder;
selectFile: (file: TTab) => void selectFile: (file: TTab) => void;
handleRename: ( handleRename: (
id: string, id: string,
newName: string, newName: string,
oldName: string, oldName: string,
type: "file" | "folder" type: "file" | "folder"
) => boolean ) => boolean;
handleDeleteFile: (file: TFile) => void handleDeleteFile: (file: TFile) => void;
handleDeleteFolder: (folder: TFolder) => void handleDeleteFolder: (folder: TFolder) => void;
}) { }) {
const [isOpen, setIsOpen] = useState(false) const [isOpen, setIsOpen] = useState(false);
const folder = isOpen const folder = isOpen
? getIconForOpenFolder(data.name) ? getIconForOpenFolder(data.name)
: getIconForFolder(data.name) : getIconForFolder(data.name);
const [editing, setEditing] = useState(false) const [editing, setEditing] = useState(false);
const inputRef = useRef<HTMLInputElement>(null) const inputRef = useRef<HTMLInputElement>(null);
useEffect(() => { useEffect(() => {
if (editing) { if (editing) {
inputRef.current?.focus() inputRef.current?.focus();
} }
}, [editing]) }, [editing]);
return ( return (
<ContextMenu> <ContextMenu>
@ -60,9 +60,8 @@ export default function SidebarFolder({
/> />
<form <form
onSubmit={(e) => { onSubmit={(e) => {
e.preventDefault() e.preventDefault();
console.log("file renamed") setEditing(false);
setEditing(false)
}} }}
> >
<input <input
@ -73,8 +72,7 @@ export default function SidebarFolder({
disabled={!editing} disabled={!editing}
defaultValue={data.name} defaultValue={data.name}
onBlur={() => { onBlur={() => {
console.log("file renamed") setEditing(false);
setEditing(false)
}} }}
/> />
</form> </form>
@ -82,8 +80,7 @@ export default function SidebarFolder({
<ContextMenuContent> <ContextMenuContent>
<ContextMenuItem <ContextMenuItem
onClick={() => { onClick={() => {
console.log("rename") setEditing(true);
setEditing(true)
}} }}
> >
<Pencil className="w-4 h-4 mr-2" /> <Pencil className="w-4 h-4 mr-2" />
@ -92,7 +89,7 @@ export default function SidebarFolder({
<ContextMenuItem <ContextMenuItem
// disabled={pendingDelete} // disabled={pendingDelete}
onClick={() => { onClick={() => {
console.log("delete") console.log("delete");
// setPendingDelete(true) // setPendingDelete(true)
// handleDeleteFile(data) // handleDeleteFile(data)
}} }}
@ -129,5 +126,5 @@ export default function SidebarFolder({
</div> </div>
) : null} ) : null}
</ContextMenu> </ContextMenu>
) );
} }

View File

@ -1,14 +1,14 @@
"use client" "use client";
import { FilePlus, FolderPlus, Loader2, Search, Sparkles } from "lucide-react" import { FilePlus, FolderPlus, Loader2, Search, Sparkles } from "lucide-react";
import SidebarFile from "./file" import SidebarFile from "./file";
import SidebarFolder from "./folder" import SidebarFolder from "./folder";
import { TFile, TFolder, TTab } from "@/lib/types" import { TFile, TFolder, TTab } from "@/lib/types";
import { useState } from "react" import { useState } from "react";
import New from "./new" import New from "./new";
import { Socket } from "socket.io-client" import { Socket } from "socket.io-client";
import Button from "@/components/ui/customButton" import Button from "@/components/ui/customButton";
import { Switch } from "@/components/ui/switch" import { Switch } from "@/components/ui/switch";
export default function Sidebar({ export default function Sidebar({
files, files,
@ -21,22 +21,24 @@ export default function Sidebar({
ai, ai,
setAi, setAi,
}: { }: {
files: (TFile | TFolder)[] files: (TFile | TFolder)[];
selectFile: (tab: TTab) => void selectFile: (tab: TTab) => void;
handleRename: ( handleRename: (
id: string, id: string,
newName: string, newName: string,
oldName: string, oldName: string,
type: "file" | "folder" type: "file" | "folder"
) => boolean ) => boolean;
handleDeleteFile: (file: TFile) => void handleDeleteFile: (file: TFile) => void;
handleDeleteFolder: (folder: TFolder) => void handleDeleteFolder: (folder: TFolder) => void;
socket: Socket socket: Socket;
addNew: (name: string, type: "file" | "folder") => void addNew: (name: string, type: "file" | "folder") => void;
ai: boolean ai: boolean;
setAi: React.Dispatch<React.SetStateAction<boolean>> setAi: React.Dispatch<React.SetStateAction<boolean>>;
}) { }) {
const [creatingNew, setCreatingNew] = useState<"file" | "folder" | null>(null) const [creatingNew, setCreatingNew] = useState<"file" | "folder" | null>(
null
);
return ( return (
<div className="h-full w-56 select-none flex flex-col text-sm items-start justify-between p-2"> <div className="h-full w-56 select-none flex flex-col text-sm items-start justify-between p-2">
@ -94,8 +96,7 @@ export default function Sidebar({
socket={socket} socket={socket}
type={creatingNew} type={creatingNew}
stopEditing={() => { stopEditing={() => {
console.log("stopped editing") setCreatingNew(null);
setCreatingNew(null)
}} }}
addNew={addNew} addNew={addNew}
/> />
@ -119,5 +120,5 @@ export default function Sidebar({
<Switch checked={ai} onCheckedChange={setAi} /> <Switch checked={ai} onCheckedChange={setAi} />
</div> </div>
</div> </div>
) );
} }

View File

@ -51,7 +51,6 @@ export default function EditorTerminal({
setTerm(term); setTerm(term);
} }
const disposable = term.onData((data) => { const disposable = term.onData((data) => {
console.log("sending data", data);
socket.emit("terminalData", id, data); socket.emit("terminalData", id, data);
}); });