delete file ui + logic
This commit is contained in:
@ -4,11 +4,19 @@ import Image from "next/image"
|
||||
import { getIconForFile } from "vscode-icons-js"
|
||||
import { TFile, TTab } from "./types"
|
||||
import { useEffect, useRef, useState } from "react"
|
||||
import {
|
||||
ContextMenu,
|
||||
ContextMenuContent,
|
||||
ContextMenuItem,
|
||||
ContextMenuTrigger,
|
||||
} from "@/components/ui/context-menu"
|
||||
import { Loader2, Pencil, Trash2 } from "lucide-react"
|
||||
|
||||
export default function SidebarFile({
|
||||
data,
|
||||
selectFile,
|
||||
handleRename,
|
||||
handleDeleteFile,
|
||||
}: {
|
||||
data: TFile
|
||||
selectFile: (file: TTab) => void
|
||||
@ -18,16 +26,21 @@ export default function SidebarFile({
|
||||
oldName: string,
|
||||
type: "file" | "folder"
|
||||
) => boolean
|
||||
handleDeleteFile: (file: TFile) => void
|
||||
}) {
|
||||
const [imgSrc, setImgSrc] = useState(`/icons/${getIconForFile(data.name)}`)
|
||||
const [editing, setEditing] = useState(false)
|
||||
const inputRef = useRef<HTMLInputElement>(null)
|
||||
const [pendingDelete, setPendingDelete] = useState(false)
|
||||
|
||||
useEffect(() => {
|
||||
if (editing) {
|
||||
inputRef.current?.focus()
|
||||
setTimeout(() => inputRef.current?.focus(), 0)
|
||||
}
|
||||
}, [editing])
|
||||
if (!inputRef.current) {
|
||||
console.log("no input ref")
|
||||
}
|
||||
}, [editing, inputRef.current])
|
||||
|
||||
const renameFile = () => {
|
||||
const renamed = handleRename(
|
||||
@ -43,37 +56,71 @@ export default function SidebarFile({
|
||||
}
|
||||
|
||||
return (
|
||||
<button
|
||||
onClick={() => selectFile({ ...data, saved: true })}
|
||||
onDoubleClick={() => {
|
||||
setEditing(true)
|
||||
}}
|
||||
className="w-full flex items-center h-7 px-1 hover:bg-secondary rounded-sm cursor-pointer transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring"
|
||||
>
|
||||
<Image
|
||||
src={imgSrc}
|
||||
alt="File Icon"
|
||||
width={18}
|
||||
height={18}
|
||||
className="mr-2"
|
||||
onError={() => setImgSrc("/icons/default_file.svg")}
|
||||
/>
|
||||
<form
|
||||
onSubmit={(e) => {
|
||||
e.preventDefault()
|
||||
renameFile()
|
||||
<ContextMenu>
|
||||
<ContextMenuTrigger
|
||||
disabled={pendingDelete}
|
||||
onClick={() => {
|
||||
if (!editing && !pendingDelete) selectFile({ ...data, saved: true })
|
||||
}}
|
||||
// onDoubleClick={() => {
|
||||
// setEditing(true)
|
||||
// }}
|
||||
className="data-[state=open]:bg-secondary/50 w-full flex items-center h-7 px-1 hover:bg-secondary rounded-sm cursor-pointer transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring"
|
||||
>
|
||||
<input
|
||||
ref={inputRef}
|
||||
className={`bg-transparent transition-all focus-visible:outline-none focus-visible:ring-offset-2 focus-visible:ring-offset-background focus-visible:ring-2 focus-visible:ring-ring rounded-sm w-full ${
|
||||
editing ? "" : "pointer-events-none"
|
||||
}`}
|
||||
disabled={!editing}
|
||||
defaultValue={data.name}
|
||||
onBlur={() => renameFile()}
|
||||
<Image
|
||||
src={imgSrc}
|
||||
alt="File Icon"
|
||||
width={18}
|
||||
height={18}
|
||||
className="mr-2"
|
||||
onError={() => setImgSrc("/icons/default_file.svg")}
|
||||
/>
|
||||
</form>
|
||||
</button>
|
||||
{pendingDelete ? (
|
||||
<>
|
||||
<Loader2 className="text-muted-foreground w-4 h-4 animate-spin mr-2" />
|
||||
<div className="text-muted-foreground">Deleting...</div>
|
||||
</>
|
||||
) : (
|
||||
<form
|
||||
onSubmit={(e) => {
|
||||
e.preventDefault()
|
||||
renameFile()
|
||||
}}
|
||||
>
|
||||
<input
|
||||
ref={inputRef}
|
||||
className={`bg-transparent transition-all focus-visible:outline-none focus-visible:ring-offset-2 focus-visible:ring-offset-background focus-visible:ring-2 focus-visible:ring-ring rounded-sm w-full ${
|
||||
editing ? "" : "pointer-events-none"
|
||||
}`}
|
||||
disabled={!editing}
|
||||
defaultValue={data.name}
|
||||
onBlur={() => renameFile()}
|
||||
/>
|
||||
</form>
|
||||
)}
|
||||
</ContextMenuTrigger>
|
||||
<ContextMenuContent>
|
||||
<ContextMenuItem
|
||||
onClick={() => {
|
||||
console.log("rename")
|
||||
setEditing(true)
|
||||
}}
|
||||
>
|
||||
<Pencil className="w-4 h-4 mr-2" />
|
||||
Rename
|
||||
</ContextMenuItem>
|
||||
<ContextMenuItem
|
||||
disabled={pendingDelete}
|
||||
onClick={() => {
|
||||
console.log("delete")
|
||||
setPendingDelete(true)
|
||||
handleDeleteFile(data)
|
||||
}}
|
||||
>
|
||||
<Trash2 className="w-4 h-4 mr-2" />
|
||||
Delete
|
||||
</ContextMenuItem>
|
||||
</ContextMenuContent>
|
||||
</ContextMenu>
|
||||
)
|
||||
}
|
||||
|
@ -10,6 +10,8 @@ export default function SidebarFolder({
|
||||
data,
|
||||
selectFile,
|
||||
handleRename,
|
||||
handleDeleteFile,
|
||||
handleDeleteFolder,
|
||||
}: {
|
||||
data: TFolder
|
||||
selectFile: (file: TTab) => void
|
||||
@ -19,6 +21,8 @@ export default function SidebarFolder({
|
||||
oldName: string,
|
||||
type: "file" | "folder"
|
||||
) => boolean
|
||||
handleDeleteFile: (file: TFile) => void
|
||||
handleDeleteFolder: (folder: TFolder) => void
|
||||
}) {
|
||||
const [isOpen, setIsOpen] = useState(false)
|
||||
const folder = isOpen
|
||||
@ -82,6 +86,7 @@ export default function SidebarFolder({
|
||||
data={child}
|
||||
selectFile={selectFile}
|
||||
handleRename={handleRename}
|
||||
handleDeleteFile={handleDeleteFile}
|
||||
/>
|
||||
) : (
|
||||
<SidebarFolder
|
||||
@ -89,6 +94,8 @@ export default function SidebarFolder({
|
||||
data={child}
|
||||
selectFile={selectFile}
|
||||
handleRename={handleRename}
|
||||
handleDeleteFile={handleDeleteFile}
|
||||
handleDeleteFolder={handleDeleteFolder}
|
||||
/>
|
||||
)
|
||||
)}
|
||||
|
@ -12,6 +12,8 @@ export default function Sidebar({
|
||||
files,
|
||||
selectFile,
|
||||
handleRename,
|
||||
handleDeleteFile,
|
||||
handleDeleteFolder,
|
||||
socket,
|
||||
addNew,
|
||||
}: {
|
||||
@ -23,6 +25,8 @@ export default function Sidebar({
|
||||
oldName: string,
|
||||
type: "file" | "folder"
|
||||
) => boolean
|
||||
handleDeleteFile: (file: TFile) => void
|
||||
handleDeleteFolder: (folder: TFolder) => void
|
||||
socket: Socket
|
||||
addNew: (name: string, type: "file" | "folder") => void
|
||||
}) {
|
||||
@ -66,6 +70,7 @@ export default function Sidebar({
|
||||
data={child}
|
||||
selectFile={selectFile}
|
||||
handleRename={handleRename}
|
||||
handleDeleteFile={handleDeleteFile}
|
||||
/>
|
||||
) : (
|
||||
<SidebarFolder
|
||||
@ -73,6 +78,8 @@ export default function Sidebar({
|
||||
data={child}
|
||||
selectFile={selectFile}
|
||||
handleRename={handleRename}
|
||||
handleDeleteFile={handleDeleteFile}
|
||||
handleDeleteFolder={handleDeleteFolder}
|
||||
/>
|
||||
)
|
||||
)}
|
||||
|
Reference in New Issue
Block a user