📜
filemanager.js
Back
📝 Javascript ⚡ Executable Ctrl+S: Save • Ctrl+R: Run • Ctrl+F: Find
// /SFTP/filemanager.js (function() { const FileManager = { id: "fileManager", label: "📁 File Manager", html: ` <div class="fm-container"> <div class="fm-toolbar"> <div class="fm-left" data-toolbar></div> <span id="fmStatus" class="fm-status">Loading...</span> </div> <div id="fmList" class="fm-list"></div> </div> `, toolbar: [ { id: "up", label: "⬅️ Up", action: "goUpDirectory" }, { id: "refresh", label: "🔄 Refresh", action: "reload" }, { id: "newfile", label: "📄 New File", action: "newFile" }, { id: "newfolder", label: "📁 New Folder", action: "newFolder" } ], currentPath: "/", async onRender(el) { this.el = el; this.renderToolbar(); // Check if driver is initialized and connected if (!window.AppStorage || !window.AppStorage.driver) { this.showError("SFTP driver not initialized. Please use Test SFTP to connect first."); return; } // Check if there's an active connection if (!window._currentSFTPConnection) { this.showError("No active SFTP connection. Please use Test SFTP to connect first."); return; } this.log(`Connected to: ${window._currentSFTPConnection.host}`); await this.loadFiles("/"); }, log(message) { console.log('[FileManager]', message); }, renderToolbar() { const bar = this.el.querySelector("[data-toolbar]"); bar.innerHTML = ""; this.toolbar.forEach(btn => { const el = document.createElement("button"); el.className = "fm-btn"; el.textContent = btn.label; el.addEventListener("click", () => this.runAction(btn.action)); bar.appendChild(el); }); }, runAction(action) { if (FileManagerActions[action]) FileManagerActions[action](this); }, async loadFiles(path = "/") { const fmList = this.el.querySelector("#fmList"); const fmStatus = this.el.querySelector("#fmStatus"); fmList.innerHTML = `<p style="color:#94a3b8;">Loading ${path}...</p>`; fmStatus.textContent = `Loading ${path}...`; this.currentPath = path; try { // Check if driver exists if (!window.AppStorage || !window.AppStorage.driver) { throw new Error("SFTP driver not initialized. Please connect first."); } // Check if connected if (!window._currentSFTPConnection) { throw new Error("No active SFTP connection. Please connect via Test SFTP first."); } this.log(`Loading files from: ${path}`); this.log(`Connection: ${window._currentSFTPConnection.host}:${window._currentSFTPConnection.port}`); // Use the SFTPDriver's list method const files = await window.AppStorage.driver.list(path); this.log(`Loaded ${files.length} files successfully`); if (!files || files.length === 0) { fmList.innerHTML = `<p style="color:#94a3b8;">No files found in ${path}</p>`; fmStatus.textContent = `Path: ${path} (0 items)`; return; } this.renderFiles(files); fmStatus.textContent = `Path: ${path} (${files.length} items)`; } catch (err) { console.error("[FileManager] Load error:", err); fmList.innerHTML = `<p style="color:#ef4444;">❌ ${err.message}</p>`; fmStatus.textContent = "Error loading files"; } }, renderFiles(files) { const fmList = this.el.querySelector("#fmList"); fmList.innerHTML = ""; if (!files || files.length === 0) { fmList.innerHTML = `<p>No files found.</p>`; return; } files.forEach(f => { const div = document.createElement("div"); div.className = "fm-item"; const deleteBtn = document.createElement("button"); deleteBtn.className = "fm-delete-btn"; deleteBtn.textContent = "🗑️"; deleteBtn.title = "Delete"; deleteBtn.addEventListener("click", (e) => { e.stopPropagation(); FileManagerActions.deleteItem(this, f); }); div.innerHTML = ` <div class="fm-name">${f.is_dir ? "📁" : "📄"} ${f.name}</div> <div class="fm-meta">${f.is_dir ? "Folder" : this.formatBytes(f.size)} • ${f.modified}</div> `; div.appendChild(deleteBtn); if (f.is_dir) { div.querySelector(".fm-name").addEventListener("click", () => { const newPath = this.currentPath.endsWith("/") ? this.currentPath + f.name : this.currentPath + "/" + f.name; this.loadFiles(newPath); }); } fmList.appendChild(div); }); }, formatBytes(bytes) { if (!bytes) return ""; if (bytes < 1024) return bytes + " B"; const units = ["KB", "MB", "GB", "TB"]; let u = -1; do { bytes /= 1024; ++u; } while (bytes >= 1024 && u < units.length - 1); return bytes.toFixed(1) + " " + units[u]; }, showError(message) { const fmList = this.el.querySelector("#fmList"); const fmStatus = this.el.querySelector("#fmStatus"); fmList.innerHTML = `<p style="color:#ef4444;">❌ ${message}</p>`; fmStatus.textContent = "Not connected"; } }; const FileManagerActions = { reload: ctx => ctx.loadFiles(ctx.currentPath), goUpDirectory: ctx => { const parts = ctx.currentPath.split("/").filter(Boolean); parts.pop(); const newPath = "/" + parts.join("/"); ctx.loadFiles(newPath || "/"); }, newFile: async ctx => { if (!window.AppStorage || !window.AppStorage.driver) { alert("❌ SFTP driver not initialized. Please connect first."); return; } const name = prompt("Enter new file name (e.g., example.txt):"); if (!name) return; const path = `${ctx.currentPath.replace(/\/$/, "")}/${name}`; try { console.log("[FileManager] =================="); console.log("[FileManager] Creating new file"); console.log("[FileManager] Filename entered:", name); console.log("[FileManager] Full path:", path); console.log("[FileManager] Current directory:", ctx.currentPath); console.log("[FileManager] Connection status:", window._currentSFTPConnection); console.log("[FileManager] =================="); // Use the driver's create method (which calls sftpnewfile.js) const result = await window.AppStorage.driver.create(path, ""); console.log("[FileManager] Create result received:", result); if (result.success) { alert(`✅ File created: ${name}`); ctx.loadFiles(ctx.currentPath); } else { alert(`❌ Failed to create file: ${result.message}`); } } catch (err) { console.error("[FileManager] Create file error:", err); console.error("[FileManager] Error stack:", err.stack); alert(`❌ Error: ${err.message}`); } }, newFolder: async ctx => { if (!window.AppStorage || !window.AppStorage.driver) { alert("❌ SFTP driver not initialized. Please connect first."); return; } const name = prompt("Enter new folder name:"); if (!name) return; const path = `${ctx.currentPath.replace(/\/$/, "")}/${name}`; try { console.log("[FileManager] Creating folder:", path); // Import the createFolder driver const { createFolder } = await import('/core/js/drivers_files/sftpmkdir.js'); const result = await createFolder(path); if (result.success) { alert(`✅ Folder created: ${name}`); ctx.loadFiles(ctx.currentPath); } else { alert(`❌ Failed to create folder: ${result.message}`); } } catch (err) { console.error("[FileManager] Create folder error:", err); alert(`❌ Error: ${err.message}`); } }, deleteItem: async (ctx, file) => { if (!window.AppStorage || !window.AppStorage.driver) { alert("❌ SFTP driver not initialized. Please connect first."); return; } const confirmMsg = file.is_dir ? `Delete folder "${file.name}" and all its contents?` : `Delete file "${file.name}"?`; if (!confirm(confirmMsg)) return; const path = `${ctx.currentPath.replace(/\/$/, "")}/${file.name}`; try { console.log("[FileManager] Deleting:", path); // Import the deleteFile driver const { deleteFile } = await import('/core/js/drivers_files/sftpdelete.js'); const result = await deleteFile(path); if (result.success) { alert(`✅ Deleted: ${file.name}`); ctx.loadFiles(ctx.currentPath); } else { alert(`❌ Failed to delete: ${result.message}`); } } catch (err) { console.error("[FileManager] Delete error:", err); alert(`❌ Error: ${err.message}`); } } }; window.AppItems = window.AppItems || []; window.AppItems.push(FileManager); console.log("[FileManager] Registered - uses AppStorage.driver for all operations"); })();