fix: reload the entire file list after adding or deleting files

This commit is contained in:
James Murdza 2024-11-17 13:25:16 -05:00
parent 062e8d9226
commit 07d3802baa
5 changed files with 20 additions and 141 deletions

View File

@ -125,6 +125,19 @@ export class FileManager {
return this.files
}
private async loadLocalFiles() {
// Reload file list from the container to include template files
const result = await this.sandbox.commands.run(
`find "${this.dirName}" -type f`
) // List all files recursively
const localPaths = result.stdout.split("\n").filter((path) => path) // Split the output into an array and filter out empty strings
const relativePaths = localPaths.map((filePath) =>
path.posix.relative(this.dirName, filePath)
) // Convert absolute paths to relative paths
this.files = generateFileStructure(relativePaths)
}
// Initialize the FileManager
async initialize() {
// Download files from remote file storage
@ -146,15 +159,7 @@ export class FileManager {
})
await Promise.all(promises)
// Reload file list from the container to include template files
const result = await this.sandbox.commands.run(
`find "${this.dirName}" -type f`
) // List all files recursively
const localPaths = result.stdout.split("\n").filter((path) => path) // Split the output into an array and filter out empty strings
const relativePaths = localPaths.map((filePath) =>
path.posix.relative(this.dirName, filePath)
) // Convert absolute paths to relative paths
this.files = generateFileStructure(relativePaths)
await this.loadLocalFiles()
// Make the logged in user the owner of all project files
this.fixPermissions()
@ -221,77 +226,13 @@ export class FileManager {
// Handle file/directory creation event
if (event.type === "create") {
const folder = findFolderById(
this.files,
sandboxDirectory
) as TFolder
const isDir = await this.isDirectory(containerFilePath)
const newItem = isDir
? ({
id: sandboxFilePath,
name: event.name,
type: "folder",
children: [],
} as TFolder)
: ({
id: sandboxFilePath,
name: event.name,
type: "file",
} as TFile)
if (folder) {
// If the folder exists, add the new item (file/folder) as a child
folder.children.push(newItem)
} else {
// If folder doesn't exist, add the new item to the root
this.files.push(newItem)
}
if (!isDir) {
const fileData = await this.sandbox.files.read(
containerFilePath
)
const fileContents =
typeof fileData === "string" ? fileData : ""
this.fileData.push({
id: sandboxFilePath,
data: fileContents,
})
}
await this.loadLocalFiles()
console.log(`Create ${sandboxFilePath}`)
}
// Handle file/directory removal or rename event
else if (event.type === "remove" || event.type == "rename") {
const folder = findFolderById(
this.files,
sandboxDirectory
) as TFolder
const isDir = await this.isDirectory(containerFilePath)
const isFileMatch = (file: TFolder | TFile | TFileData) =>
file.id === sandboxFilePath ||
file.id.startsWith(containerFilePath + "/")
if (folder) {
// Remove item from its parent folder
folder.children = folder.children.filter(
(file: TFolder | TFile) => !isFileMatch(file)
)
} else {
// Remove from the root if it's not inside a folder
this.files = this.files.filter(
(file: TFolder | TFile) => !isFileMatch(file)
)
}
// Also remove any corresponding file data
this.fileData = this.fileData.filter(
(file: TFileData) => !isFileMatch(file)
)
await this.loadLocalFiles()
console.log(`Removed: ${sandboxFilePath}`)
}
@ -458,17 +399,6 @@ export class FileManager {
await this.sandbox.files.write(path.posix.join(this.dirName, id), "")
await this.fixPermissions()
this.files.push({
id,
name,
type: "file",
})
this.fileData.push({
id,
data: "",
})
await RemoteFileStorage.createFile(this.getRemoteFileId(id))
return true
@ -568,7 +498,6 @@ export class FileManager {
if (!file) return this.files
await this.sandbox.files.remove(path.posix.join(this.dirName, fileId))
this.fileData = this.fileData.filter((f) => f.id !== fileId)
await RemoteFileStorage.deleteFile(this.getRemoteFileId(fileId))
return this.updateFileStructure()
@ -583,7 +512,6 @@ export class FileManager {
await Promise.all(
files.map(async (file) => {
await this.sandbox.files.remove(path.posix.join(this.dirName, file))
this.fileData = this.fileData.filter((f) => f.id !== file)
await RemoteFileStorage.deleteFile(this.getRemoteFileId(file))
})
)

View File

@ -23,7 +23,6 @@ import { useSocket } from "@/context/SocketContext"
import { parseTSConfigToMonacoOptions } from "@/lib/tsconfig"
import { Sandbox, TFile, TFolder, TTab, User } from "@/lib/types"
import {
addNew,
cn,
debounce,
deepMerge,
@ -856,13 +855,7 @@ export default function CodeEditor({
}
const handleDeleteFile = (file: TFile) => {
socket?.emit(
"deleteFile",
{ fileId: file.id },
(response: (TFolder | TFile)[]) => {
setFiles(response)
}
)
socket?.emit("deleteFile", { fileId: file.id })
closeTab(file.id)
}
@ -878,7 +871,6 @@ export default function CodeEditor({
"deleteFolder",
{ folderId: folder.id },
(response: (TFolder | TFile)[]) => {
setFiles(response)
setDeletingFolderId("")
}
)
@ -1047,7 +1039,6 @@ export default function CodeEditor({
handleDeleteFolder={handleDeleteFolder}
socket={socket!}
setFiles={setFiles}
addNew={(name, type) => addNew(name, type, setFiles, sandboxData)}
deletingFolderId={deletingFolderId}
toggleAIChat={toggleAIChat}
isAIChatOpen={isAIChatOpen}

View File

@ -25,7 +25,6 @@ export default function Sidebar({
handleDeleteFolder,
socket,
setFiles,
addNew,
deletingFolderId,
toggleAIChat,
isAIChatOpen,
@ -43,7 +42,6 @@ export default function Sidebar({
handleDeleteFolder: (folder: TFolder) => void
socket: Socket
setFiles: (files: (TFile | TFolder)[]) => void
addNew: (name: string, type: "file" | "folder") => void
deletingFolderId: string
toggleAIChat: () => void
isAIChatOpen: boolean
@ -176,7 +174,6 @@ export default function Sidebar({
stopEditing={() => {
setCreatingNew(null)
}}
addNew={addNew}
/>
) : null}
</>

View File

@ -9,12 +9,10 @@ export default function New({
socket,
type,
stopEditing,
addNew,
}: {
socket: Socket
type: "file" | "folder"
stopEditing: () => void
addNew: (name: string, type: "file" | "folder") => void
}) {
const inputRef = useRef<HTMLInputElement>(null)
@ -25,19 +23,9 @@ export default function New({
const valid = validateName(name, "", type)
if (valid.status) {
if (type === "file") {
socket.emit(
"createFile",
{ name },
({ success }: { success: boolean }) => {
if (success) {
addNew(name, type)
}
}
)
socket.emit("createFile", { name })
} else {
socket.emit("createFolder", { name }, () => {
addNew(name, type)
})
socket.emit("createFolder", { name })
}
}
}

View File

@ -2,7 +2,7 @@ import { type ClassValue, clsx } from "clsx"
// import { toast } from "sonner"
import { twMerge } from "tailwind-merge"
import fileExtToLang from "./file-extension-to-language.json"
import { Sandbox, TFile, TFolder } from "./types"
import { TFile, TFolder } from "./types"
export function cn(...inputs: ClassValue[]) {
return twMerge(clsx(inputs))
@ -38,31 +38,6 @@ export function validateName(
return { status: true, message: "" }
}
export function addNew(
name: string,
type: "file" | "folder",
setFiles: React.Dispatch<React.SetStateAction<(TFolder | TFile)[]>>,
sandboxData: Sandbox
) {
if (type === "file") {
setFiles((prev) => [
...prev,
{ id: `projects/${sandboxData.id}/${name}`, name, type: "file" },
])
} else {
console.log("adding folder")
setFiles((prev) => [
...prev,
{
id: `projects/${sandboxData.id}/${name}`,
name,
type: "folder",
children: [],
},
])
}
}
export function debounce<T extends (...args: any[]) => void>(
func: T,
wait: number