fix: reload the entire file list after adding or deleting files
This commit is contained in:
parent
062e8d9226
commit
07d3802baa
@ -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))
|
||||
})
|
||||
)
|
||||
|
@ -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}
|
||||
|
@ -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}
|
||||
</>
|
||||
|
@ -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 })
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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
|
||||
|
Loading…
x
Reference in New Issue
Block a user