Download script.js from Urban-Guy/Drive: direct link, hf CLI and curl.
- Browser
- Download file 40.8 kB
-
https://huggingface.co/spaces/Urban-Guy/Drive/resolve/main/script.js
- Command line
-
hf download hf://spaces/Urban-Guy/Drive/script.js
-
curl -L -o script.js https://huggingface.co/spaces/Urban-Guy/Drive/resolve/main/script.js
40.8 kB
| let currentFileId = null; | |
| let currentView = 'grid'; | |
| let uploadQueue = []; | |
| let selectedFiles = new Set(); | |
| let draggedFileId = null; | |
| let currentShareFileId = null; | |
| document.addEventListener('DOMContentLoaded', function() { | |
| setupEventListeners(); | |
| setupContextMenu(); | |
| setupDragDrop(); | |
| setupNewButton(); | |
| setupFolderDialog(); | |
| setupFileDragDrop(); | |
| setupFileSelection(); | |
| }); | |
| function setupEventListeners() { | |
| const searchInput = document.getElementById('searchInput'); | |
| if (searchInput) searchInput.addEventListener('input', handleSearch); | |
| document.addEventListener('keydown', function(e) { | |
| if (e.key === 'Escape') { | |
| closeModal(); | |
| closeFolderDialog(); | |
| closeShareDialog(); | |
| closeWebFetchDialog(); | |
| hideContextMenu(); | |
| hideNewDropdown(); | |
| clearSelection(); | |
| } | |
| }); | |
| const fileModal = document.getElementById('fileModal'); | |
| if (fileModal) fileModal.addEventListener('click', function(e) { | |
| if (e.target === fileModal) closeModal(); | |
| }); | |
| const folderModal = document.getElementById('folderModal'); | |
| if (folderModal) folderModal.addEventListener('click', function(e) { | |
| if (e.target === folderModal) closeFolderDialog(); | |
| }); | |
| const shareModal = document.getElementById('shareModal'); | |
| if (shareModal) shareModal.addEventListener('click', function(e) { | |
| if (e.target === shareModal) closeShareDialog(); | |
| }); | |
| const webFetchModal = document.getElementById('webFetchModal'); | |
| if (webFetchModal) webFetchModal.addEventListener('click', function(e) { | |
| if (e.target === webFetchModal) closeWebFetchDialog(); | |
| }); | |
| const urlInput = document.getElementById('webFetchUrlInput'); | |
| const nameInput = document.getElementById('webFetchNameInput'); | |
| if (urlInput) { | |
| urlInput.addEventListener('keypress', function(e) { | |
| if (e.key === 'Enter') downloadFromWeb(); | |
| }); | |
| } | |
| if (nameInput) { | |
| nameInput.addEventListener('keypress', function(e) { | |
| if (e.key === 'Enter') downloadFromWeb(); | |
| }); | |
| } | |
| } | |
| function setupFileSelection() { | |
| document.addEventListener('click', function(e) { | |
| if (!e.target.closest('.file-item') && !e.ctrlKey && !e.metaKey) { | |
| clearSelection(); | |
| } | |
| }); | |
| } | |
| function selectFile(event, fileId) { | |
| event.stopPropagation(); | |
| const fileItem = document.querySelector(`[data-file-id="${fileId}"]`); | |
| if (!fileItem) return; | |
| if (event.ctrlKey || event.metaKey) { | |
| if (selectedFiles.has(fileId)) { | |
| selectedFiles.delete(fileId); | |
| fileItem.classList.remove('selected'); | |
| } else { | |
| selectedFiles.add(fileId); | |
| fileItem.classList.add('selected'); | |
| } | |
| } else if (event.shiftKey && selectedFiles.size > 0) { | |
| const allFiles = Array.from(document.querySelectorAll('.file-item')); | |
| const lastSelected = Array.from(selectedFiles)[selectedFiles.size - 1]; | |
| const lastIndex = allFiles.findIndex(f => f.dataset.fileId === lastSelected); | |
| const currentIndex = allFiles.findIndex(f => f.dataset.fileId === fileId); | |
| const start = Math.min(lastIndex, currentIndex); | |
| const end = Math.max(lastIndex, currentIndex); | |
| for (let i = start; i <= end; i++) { | |
| const id = allFiles[i].dataset.fileId; | |
| selectedFiles.add(id); | |
| allFiles[i].classList.add('selected'); | |
| } | |
| } else { | |
| clearSelection(); | |
| selectedFiles.add(fileId); | |
| fileItem.classList.add('selected'); | |
| } | |
| updateSelectionUI(); | |
| } | |
| function clearSelection() { | |
| selectedFiles.clear(); | |
| document.querySelectorAll('.file-item.selected').forEach(item => { | |
| item.classList.remove('selected'); | |
| }); | |
| updateSelectionUI(); | |
| } | |
| function updateSelectionUI() { | |
| const count = selectedFiles.size; | |
| const countElement = document.getElementById('selectedCount'); | |
| const deleteBtn = document.getElementById('deleteSelectedBtn'); | |
| const shareBtn = document.getElementById('shareSelectedBtn'); | |
| if (countElement) { | |
| if (count > 0) { | |
| countElement.textContent = `${count} selected`; | |
| countElement.classList.add('show'); | |
| } else { | |
| countElement.classList.remove('show'); | |
| } | |
| } | |
| if (deleteBtn) { | |
| if (count > 0) { | |
| deleteBtn.classList.add('show'); | |
| deleteBtn.style.display = 'flex'; | |
| } else { | |
| deleteBtn.classList.remove('show'); | |
| deleteBtn.style.display = 'none'; | |
| } | |
| } | |
| if (shareBtn) { | |
| if (count > 0) { | |
| shareBtn.classList.add('show'); | |
| shareBtn.style.display = 'inline-flex'; | |
| } else { | |
| shareBtn.classList.remove('show'); | |
| shareBtn.style.display = 'none'; | |
| } | |
| } | |
| } | |
| function deleteSelectedFiles() { | |
| if (selectedFiles.size === 0) return; | |
| if (confirm(`Move ${selectedFiles.size} item(s) to trash?`)) { | |
| const fileIds = Array.from(selectedFiles); | |
| Promise.all(fileIds.map(fileId => { | |
| return fetch('trash.php', { | |
| method: 'POST', | |
| headers: {'Content-Type': 'application/x-www-form-urlencoded'}, | |
| body: 'fileId=' + fileId | |
| }).then(r => r.json()); | |
| })).then(() => { | |
| showToast(`${fileIds.length} item(s) moved to trash`); | |
| setTimeout(() => location.reload(), 500); | |
| }); | |
| } | |
| } | |
| function setupFileDragDrop() { | |
| document.querySelectorAll('.file-item').forEach(item => { | |
| item.addEventListener('dragstart', handleDragStart); | |
| item.addEventListener('dragend', handleDragEnd); | |
| if (item.classList.contains('folder-item')) { | |
| item.addEventListener('dragover', handleDragOver); | |
| item.addEventListener('dragleave', handleDragLeave); | |
| item.addEventListener('drop', handleDrop); | |
| } | |
| }); | |
| } | |
| function handleDragStart(e) { | |
| draggedFileId = this.dataset.fileId; | |
| this.classList.add('dragging'); | |
| e.dataTransfer.effectAllowed = 'move'; | |
| e.dataTransfer.setData('text/html', this.innerHTML); | |
| } | |
| function handleDragEnd(e) { | |
| this.classList.remove('dragging'); | |
| document.querySelectorAll('.folder-item').forEach(folder => { | |
| folder.classList.remove('drag-over'); | |
| }); | |
| } | |
| function handleDragOver(e) { | |
| if (e.preventDefault) e.preventDefault(); | |
| e.dataTransfer.dropEffect = 'move'; | |
| if (!this.classList.contains('dragging')) { | |
| this.classList.add('drag-over'); | |
| } | |
| return false; | |
| } | |
| function handleDragLeave(e) { | |
| this.classList.remove('drag-over'); | |
| } | |
| function handleDrop(e) { | |
| if (e.stopPropagation) e.stopPropagation(); | |
| e.preventDefault(); | |
| this.classList.remove('drag-over'); | |
| const targetFolderId = this.dataset.fileId; | |
| if (draggedFileId && draggedFileId !== targetFolderId) { | |
| moveFileToFolder(draggedFileId, targetFolderId); | |
| } | |
| return false; | |
| } | |
| function moveFileToFolder(fileId, folderId) { | |
| fetch('move_to_folder.php', { | |
| method: 'POST', | |
| headers: {'Content-Type': 'application/x-www-form-urlencoded'}, | |
| body: `fileId=${fileId}&folderId=${folderId}` | |
| }) | |
| .then(response => response.json()) | |
| .then(data => { | |
| if (data.success) { | |
| showToast('File moved to folder'); | |
| setTimeout(() => location.reload(), 500); | |
| } else { | |
| showToast('Failed to move file'); | |
| } | |
| }) | |
| .catch(error => { | |
| console.error('Error:', error); | |
| showToast('Error moving file'); | |
| }); | |
| } | |
| function setupNewButton() { | |
| const newButton = document.getElementById('newButton'); | |
| const newDropdown = document.getElementById('newDropdown'); | |
| if (newButton && newDropdown) { | |
| newButton.addEventListener('click', function(e) { | |
| e.stopPropagation(); | |
| newDropdown.classList.toggle('show'); | |
| }); | |
| document.addEventListener('click', function() { | |
| newDropdown.classList.remove('show'); | |
| }); | |
| } | |
| } | |
| function hideNewDropdown() { | |
| const newDropdown = document.getElementById('newDropdown'); | |
| if (newDropdown) newDropdown.classList.remove('show'); | |
| } | |
| function triggerFileUpload() { | |
| hideNewDropdown(); | |
| document.getElementById('fileInput').click(); | |
| } | |
| function triggerFolderUpload() { | |
| hideNewDropdown(); | |
| document.getElementById('folderInput').click(); | |
| } | |
| function setupFolderDialog() { | |
| const folderInput = document.getElementById('folderNameInput'); | |
| const createBtn = document.getElementById('createFolderBtn'); | |
| if (folderInput && createBtn) { | |
| folderInput.addEventListener('input', function() { | |
| createBtn.disabled = this.value.trim() === ''; | |
| }); | |
| folderInput.addEventListener('keypress', function(e) { | |
| if (e.key === 'Enter' && this.value.trim() !== '') createFolder(); | |
| }); | |
| } | |
| } | |
| function showFolderDialog() { | |
| hideNewDropdown(); | |
| const modal = document.getElementById('folderModal'); | |
| const input = document.getElementById('folderNameInput'); | |
| const createBtn = document.getElementById('createFolderBtn'); | |
| if (modal && input) { | |
| modal.classList.add('show'); | |
| input.value = ''; | |
| input.focus(); | |
| createBtn.disabled = true; | |
| } | |
| } | |
| function closeFolderDialog() { | |
| const modal = document.getElementById('folderModal'); | |
| if (modal) modal.classList.remove('show'); | |
| } | |
| function createFolder() { | |
| const input = document.getElementById('folderNameInput'); | |
| const folderName = input.value.trim(); | |
| if (!folderName) { | |
| showToast('Please enter a folder name'); | |
| return; | |
| } | |
| const currentFolder = window.currentFolder || 'root'; | |
| fetch('create_folder.php', { | |
| method: 'POST', | |
| headers: {'Content-Type': 'application/x-www-form-urlencoded'}, | |
| body: `folderName=${encodeURIComponent(folderName)}&parentFolder=${encodeURIComponent(currentFolder)}` | |
| }) | |
| .then(response => response.json()) | |
| .then(data => { | |
| if (data.success) { | |
| closeFolderDialog(); | |
| showToast('Folder created: ' + folderName); | |
| setTimeout(() => location.reload(), 500); | |
| } else { | |
| showToast('Failed to create folder: ' + (data.error || 'Unknown error')); | |
| } | |
| }) | |
| .catch(error => { | |
| console.error('Error:', error); | |
| showToast('Error creating folder'); | |
| }); | |
| } | |
| function setupContextMenu() { | |
| const fileItems = document.querySelectorAll('.file-item'); | |
| const mainContent = document.getElementById('mainContent'); | |
| fileItems.forEach(item => { | |
| item.addEventListener('contextmenu', function(e) { | |
| e.preventDefault(); | |
| showFileContextMenu(e, this); | |
| }); | |
| }); | |
| if (mainContent) { | |
| mainContent.addEventListener('contextmenu', function(e) { | |
| if (e.target === mainContent || e.target.classList.contains('file-grid')) { | |
| e.preventDefault(); | |
| showEmptyContextMenu(e); | |
| } | |
| }); | |
| } | |
| document.addEventListener('click', function() { | |
| hideContextMenu(); | |
| }); | |
| } | |
| function showFileContextMenu(event, fileElement) { | |
| hideContextMenu(); | |
| const menu = document.getElementById('fileContextMenu'); | |
| currentFileId = fileElement.dataset.fileId; | |
| const isStarred = fileElement.dataset.starred === 'true'; | |
| const starMenuText = document.getElementById('starMenuText'); | |
| const starMenuItem = document.getElementById('starMenuItem'); | |
| if (isStarred) { | |
| starMenuText.textContent = 'Remove from starred'; | |
| starMenuItem.querySelector('.material-icons').textContent = 'star_outline'; | |
| } else { | |
| starMenuText.textContent = 'Add to starred'; | |
| starMenuItem.querySelector('.material-icons').textContent = 'star'; | |
| } | |
| positionContextMenu(menu, event.clientX, event.clientY); | |
| menu.classList.add('show'); | |
| } | |
| function showEmptyContextMenu(event) { | |
| hideContextMenu(); | |
| const menu = document.getElementById('emptyContextMenu'); | |
| positionContextMenu(menu, event.clientX, event.clientY); | |
| menu.classList.add('show'); | |
| } | |
| function positionContextMenu(menu, x, y) { | |
| menu.style.left = x + 'px'; | |
| menu.style.top = y + 'px'; | |
| setTimeout(() => { | |
| const rect = menu.getBoundingClientRect(); | |
| if (rect.right > window.innerWidth) menu.style.left = (x - rect.width) + 'px'; | |
| if (rect.bottom > window.innerHeight) menu.style.top = (y - rect.height) + 'px'; | |
| }, 0); | |
| } | |
| function hideContextMenu() { | |
| document.querySelectorAll('.context-menu').forEach(menu => { | |
| menu.classList.remove('show'); | |
| }); | |
| } | |
| function contextMenuAction(action) { | |
| hideContextMenu(); | |
| const fileElement = document.querySelector(`[data-file-id="${currentFileId}"]`); | |
| if (!fileElement) return; | |
| const filePath = fileElement.dataset.filePath; | |
| const fileName = fileElement.dataset.fileName; | |
| const fileType = fileElement.dataset.fileType; | |
| switch(action) { | |
| case 'open': | |
| case 'preview': | |
| if (fileType === 'folder') { | |
| window.location.href = `index.php?view=my-drive&folder=${currentFileId}`; | |
| } else { | |
| openFile(filePath, fileName, fileType, currentFileId); | |
| } | |
| break; | |
| case 'download': | |
| downloadFile(filePath, fileName); | |
| break; | |
| case 'rename': | |
| renameFile(currentFileId, fileName); | |
| break; | |
| case 'copy': | |
| copyFile(currentFileId); | |
| break; | |
| case 'star': | |
| toggleStar(currentFileId); | |
| break; | |
| case 'trash': | |
| moveToTrash(currentFileId); | |
| break; | |
| case 'share': | |
| if (currentFileId) { | |
| const fileElement = document.querySelector(`[data-file-id="${currentFileId}"]`); | |
| if (fileElement) { | |
| const fileName = fileElement.dataset.fileName; | |
| hideContextMenu(); | |
| showShareDialog(currentFileId, fileName); | |
| } | |
| } | |
| break; | |
| } | |
| } | |
| function emptyContextAction(action) { | |
| hideContextMenu(); | |
| switch(action) { | |
| case 'upload': | |
| triggerFileUpload(); | |
| break; | |
| case 'folder': | |
| showFolderDialog(); | |
| break; | |
| case 'refresh': | |
| location.reload(); | |
| break; | |
| } | |
| } | |
| function setupDragDrop() { | |
| const mainContent = document.getElementById('mainContent'); | |
| const dragOverlay = document.getElementById('dragOverlay'); | |
| let dragCounter = 0; | |
| if (!mainContent || !dragOverlay) return; | |
| document.addEventListener('dragenter', function(e) { | |
| if (e.dataTransfer.types.includes('Files')) { | |
| e.preventDefault(); | |
| dragCounter++; | |
| if (dragCounter === 1) dragOverlay.classList.add('show'); | |
| } | |
| }); | |
| document.addEventListener('dragleave', function(e) { | |
| if (e.dataTransfer.types.includes('Files')) { | |
| e.preventDefault(); | |
| dragCounter--; | |
| if (dragCounter === 0) dragOverlay.classList.remove('show'); | |
| } | |
| }); | |
| document.addEventListener('dragover', function(e) { | |
| if (e.dataTransfer.types.includes('Files')) { | |
| e.preventDefault(); | |
| } | |
| }); | |
| document.addEventListener('drop', function(e) { | |
| if (e.dataTransfer.files.length > 0) { | |
| e.preventDefault(); | |
| dragCounter = 0; | |
| dragOverlay.classList.remove('show'); | |
| const files = e.dataTransfer.files; | |
| if (files.length > 0) handleFilesUpload(files); | |
| } | |
| }); | |
| } | |
| function handleFilesUpload(files) { | |
| uploadQueue = Array.from(files); | |
| showUploadProgress(); | |
| uploadFiles(); | |
| } | |
| function showUploadProgress() { | |
| const progress = document.getElementById('uploadProgress'); | |
| const statusText = document.getElementById('uploadStatusText'); | |
| const fileList = document.getElementById('uploadFileList'); | |
| if (!progress || !statusText || !fileList) return; | |
| progress.classList.add('show'); | |
| statusText.textContent = `Uploading ${uploadQueue.length} file${uploadQueue.length > 1 ? 's' : ''}`; | |
| fileList.innerHTML = ''; | |
| uploadQueue.forEach((file, index) => { | |
| const fileItem = document.createElement('div'); | |
| fileItem.className = 'upload-file-item'; | |
| fileItem.id = 'upload-file-' + index; | |
| fileItem.innerHTML = ` | |
| <span class="material-icons file-icon">insert_drive_file</span> | |
| <div class="file-info-upload"> | |
| <div class="file-name-upload">${file.name}</div> | |
| <div class="file-progress"> | |
| <div class="file-progress-fill" id="progress-${index}" style="width: 0%"></div> | |
| </div> | |
| <div class="file-status" id="status-${index}">Waiting...</div> | |
| </div> | |
| `; | |
| fileList.appendChild(fileItem); | |
| }); | |
| } | |
| function uploadFiles() { | |
| let completed = 0; | |
| let totalSize = uploadQueue.reduce((sum, file) => sum + file.size, 0); | |
| const currentFolder = window.currentFolder || 'root'; | |
| uploadQueue.forEach((file, index) => { | |
| const xhr = new XMLHttpRequest(); | |
| const formData = new FormData(); | |
| formData.append('files[]', file); | |
| formData.append('targetFolder', currentFolder); | |
| xhr.upload.addEventListener('progress', function(e) { | |
| if (e.lengthComputable) { | |
| const percent = Math.round((e.loaded / e.total) * 100); | |
| const progressBar = document.getElementById('progress-' + index); | |
| const status = document.getElementById('status-' + index); | |
| if (progressBar) progressBar.style.width = percent + '%'; | |
| if (status) { | |
| const speed = formatBytes(e.loaded / ((Date.now() - xhr.startTime) / 1000)) + '/s'; | |
| status.textContent = `${percent}% • ${speed}`; | |
| } | |
| const currentUploadedSize = uploadQueue.slice(0, index).reduce((sum, f) => sum + f.size, 0) + e.loaded; | |
| const overallPercent = Math.round((currentUploadedSize / totalSize) * 100); | |
| updateOverallProgress(overallPercent); | |
| } | |
| }); | |
| xhr.addEventListener('load', function() { | |
| completed++; | |
| const status = document.getElementById('status-' + index); | |
| if (xhr.status === 200) { | |
| if (status) { | |
| status.textContent = 'Complete'; | |
| status.classList.add('complete'); | |
| } | |
| try { | |
| const response = JSON.parse(xhr.responseText); | |
| if (response.storageUsed && response.storageQuota) { | |
| updateStorageBar(response.storageUsed, response.storageQuota); | |
| } | |
| } catch (e) {} | |
| } else { | |
| if (status) { | |
| status.textContent = 'Failed'; | |
| status.classList.add('error'); | |
| } | |
| } | |
| if (completed === uploadQueue.length) { | |
| setTimeout(() => { | |
| closeUploadProgress(); | |
| showToast('Upload complete'); | |
| location.reload(); | |
| }, 2000); | |
| } | |
| }); | |
| xhr.addEventListener('error', function() { | |
| const status = document.getElementById('status-' + index); | |
| if (status) { | |
| status.textContent = 'Failed'; | |
| status.classList.add('error'); | |
| } | |
| }); | |
| xhr.startTime = Date.now(); | |
| xhr.open('POST', 'index.php'); | |
| xhr.setRequestHeader('X-Requested-With', 'XMLHttpRequest'); | |
| xhr.send(formData); | |
| }); | |
| } | |
| function updateOverallProgress(percent) { | |
| const progressBar = document.getElementById('overallProgress'); | |
| const progressText = document.getElementById('overallProgressText'); | |
| if (progressBar) progressBar.style.width = percent + '%'; | |
| if (progressText) progressText.textContent = percent + '%'; | |
| } | |
| function closeUploadProgress() { | |
| const progress = document.getElementById('uploadProgress'); | |
| if (progress) progress.classList.remove('show'); | |
| uploadQueue = []; | |
| } | |
| function minimizeUploadProgress() { | |
| closeUploadProgress(); | |
| } | |
| function updateStorageBar(used, quota) { | |
| const percentage = (used / quota) * 100; | |
| const storageUsed = document.querySelector('.storage-used'); | |
| const storageText = document.querySelectorAll('.storage-text')[1]; | |
| if (storageUsed) { | |
| storageUsed.style.width = Math.min(percentage, 100) + '%'; | |
| if (percentage >= 95) storageUsed.style.backgroundColor = '#ea4335'; | |
| else if (percentage >= 80) storageUsed.style.backgroundColor = '#f9ab00'; | |
| else storageUsed.style.backgroundColor = '#1a73e8'; | |
| } | |
| if (storageText) { | |
| storageText.textContent = formatBytes(used) + ' of ' + formatBytes(quota) + ' used'; | |
| } | |
| } | |
| function openFile(filePath, fileName, mimeType, fileId) { | |
| fetch('update_accessed.php', { | |
| method: 'POST', | |
| headers: {'Content-Type': 'application/x-www-form-urlencoded'}, | |
| body: 'fileId=' + fileId | |
| }); | |
| const modal = document.getElementById('fileModal'); | |
| const modalTitle = document.getElementById('modalTitle'); | |
| const modalBody = document.getElementById('modalBody'); | |
| modalTitle.textContent = fileName; | |
| modalBody.innerHTML = ''; | |
| if (mimeType.startsWith('image/')) { | |
| const img = document.createElement('img'); | |
| img.src = filePath; | |
| img.alt = fileName; | |
| modalBody.appendChild(img); | |
| } else if (mimeType === 'application/pdf') { | |
| const iframe = document.createElement('iframe'); | |
| iframe.src = filePath + '#toolbar=1'; | |
| modalBody.appendChild(iframe); | |
| } else if (mimeType.startsWith('video/')) { | |
| const video = document.createElement('video'); | |
| video.src = filePath; | |
| video.controls = true; | |
| video.autoplay = false; | |
| video.style.width = '100%'; | |
| video.style.maxHeight = '70vh'; | |
| modalBody.appendChild(video); | |
| } else if (mimeType.startsWith('audio/')) { | |
| const audio = document.createElement('audio'); | |
| audio.src = filePath; | |
| audio.controls = true; | |
| modalBody.appendChild(audio); | |
| } else if (mimeType.startsWith('text/')) { | |
| fetch(filePath).then(response => response.text()).then(text => { | |
| const pre = document.createElement('pre'); | |
| pre.textContent = text; | |
| modalBody.appendChild(pre); | |
| }); | |
| } else { | |
| const container = document.createElement('div'); | |
| container.style.textAlign = 'center'; | |
| container.style.padding = '40px'; | |
| const p = document.createElement('p'); | |
| p.textContent = 'Preview not available for this file type.'; | |
| p.style.marginBottom = '20px'; | |
| const downloadBtn = document.createElement('a'); | |
| downloadBtn.href = filePath; | |
| downloadBtn.download = fileName; | |
| downloadBtn.textContent = 'Download File'; | |
| downloadBtn.className = 'button-primary'; | |
| downloadBtn.style.textDecoration = 'none'; | |
| container.appendChild(p); | |
| container.appendChild(downloadBtn); | |
| modalBody.appendChild(container); | |
| } | |
| modal.classList.add('show'); | |
| } | |
| function closeModal() { | |
| const modal = document.getElementById('fileModal'); | |
| if (modal) { | |
| modal.classList.remove('show'); | |
| const videos = modal.querySelectorAll('video'); | |
| videos.forEach(v => v.pause()); | |
| } | |
| } | |
| function downloadFile(filePath, fileName) { | |
| const link = document.createElement('a'); | |
| link.href = filePath; | |
| link.download = fileName; | |
| document.body.appendChild(link); | |
| link.click(); | |
| document.body.removeChild(link); | |
| showToast('Download started'); | |
| } | |
| function toggleStar(fileId, event) { | |
| if (event) event.stopPropagation(); | |
| fetch('star.php', { | |
| method: 'POST', | |
| headers: {'Content-Type': 'application/x-www-form-urlencoded'}, | |
| body: 'fileId=' + fileId | |
| }) | |
| .then(response => response.json()) | |
| .then(data => { | |
| if (data.success) { | |
| showToast(data.starred ? 'Added to starred' : 'Removed from starred'); | |
| setTimeout(() => location.reload(), 500); | |
| } | |
| }); | |
| } | |
| function moveToTrash(fileId) { | |
| if (confirm('Move this item to trash?')) { | |
| fetch('trash.php', { | |
| method: 'POST', | |
| headers: {'Content-Type': 'application/x-www-form-urlencoded'}, | |
| body: 'fileId=' + fileId | |
| }) | |
| .then(response => response.json()) | |
| .then(data => { | |
| if (data.success) { | |
| showToast('Moved to trash'); | |
| setTimeout(() => location.reload(), 500); | |
| } | |
| }); | |
| } | |
| } | |
| function restoreSelected() { | |
| if (selectedFiles.size === 0) { | |
| const firstFile = document.querySelector('.file-item'); | |
| if (firstFile) selectedFiles.add(firstFile.dataset.fileId); | |
| } | |
| if (selectedFiles.size === 0) return; | |
| Promise.all(Array.from(selectedFiles).map(fileId => { | |
| return fetch('restore.php', { | |
| method: 'POST', | |
| headers: {'Content-Type': 'application/x-www-form-urlencoded'}, | |
| body: 'fileId=' + fileId | |
| }).then(r => r.json()); | |
| })).then(() => { | |
| showToast('File(s) restored'); | |
| setTimeout(() => location.reload(), 500); | |
| }); | |
| } | |
| function deleteForeverSelected() { | |
| if (selectedFiles.size === 0) { | |
| const firstFile = document.querySelector('.file-item'); | |
| if (firstFile) selectedFiles.add(firstFile.dataset.fileId); | |
| } | |
| if (selectedFiles.size === 0) return; | |
| if (confirm(`Delete ${selectedFiles.size} item(s) forever? You cannot undo this action.`)) { | |
| const fileIds = Array.from(selectedFiles); | |
| fetch('delete.php', { | |
| method: 'POST', | |
| headers: {'Content-Type': 'application/x-www-form-urlencoded'}, | |
| body: 'fileIds=' + JSON.stringify(fileIds) | |
| }) | |
| .then(response => response.json()) | |
| .then(data => { | |
| if (data.success) { | |
| showToast(`${data.deletedCount} item(s) deleted forever`); | |
| setTimeout(() => location.reload(), 500); | |
| } | |
| }); | |
| } | |
| } | |
| function emptyTrash() { | |
| if (confirm('Empty trash? All items will be deleted forever. You cannot undo this action.')) { | |
| fetch('empty_trash.php', { | |
| method: 'POST' | |
| }) | |
| .then(response => response.json()) | |
| .then(data => { | |
| if (data.success) { | |
| showToast('Trash emptied'); | |
| setTimeout(() => location.reload(), 500); | |
| } | |
| }); | |
| } | |
| } | |
| function renameFile(fileId, currentName) { | |
| const newName = prompt('Rename file:', currentName); | |
| if (newName && newName !== currentName) { | |
| fetch('rename.php', { | |
| method: 'POST', | |
| headers: {'Content-Type': 'application/x-www-form-urlencoded'}, | |
| body: 'fileId=' + fileId + '&newName=' + encodeURIComponent(newName) | |
| }) | |
| .then(response => response.json()) | |
| .then(data => { | |
| if (data.success) { | |
| showToast('File renamed'); | |
| setTimeout(() => location.reload(), 500); | |
| } | |
| }); | |
| } | |
| } | |
| function copyFile(fileId) { | |
| fetch('copy.php', { | |
| method: 'POST', | |
| headers: {'Content-Type': 'application/x-www-form-urlencoded'}, | |
| body: 'fileId=' + fileId | |
| }) | |
| .then(response => response.json()) | |
| .then(data => { | |
| if (data.success) { | |
| showToast('File copied'); | |
| setTimeout(() => location.reload(), 500); | |
| } | |
| }); | |
| } | |
| function toggleView(view) { | |
| currentView = view; | |
| const gridBtn = document.getElementById('gridViewBtn'); | |
| const listBtn = document.getElementById('listViewBtn'); | |
| if (view === 'grid') { | |
| gridBtn.classList.add('active'); | |
| listBtn.classList.remove('active'); | |
| } else { | |
| listBtn.classList.add('active'); | |
| gridBtn.classList.remove('active'); | |
| } | |
| } | |
| function handleSearch(e) { | |
| const searchTerm = e.target.value.toLowerCase(); | |
| const fileItems = document.querySelectorAll('.file-item'); | |
| fileItems.forEach(item => { | |
| const fileName = item.dataset.fileName.toLowerCase(); | |
| if (fileName.includes(searchTerm)) { | |
| item.style.display = ''; | |
| } else { | |
| item.style.display = 'none'; | |
| } | |
| }); | |
| } | |
| function showToast(message) { | |
| const toast = document.getElementById('toast'); | |
| if (toast) { | |
| toast.textContent = message; | |
| toast.classList.add('show'); | |
| setTimeout(() => { | |
| toast.classList.remove('show'); | |
| }, 3000); | |
| } | |
| } | |
| function formatBytes(bytes) { | |
| if (bytes >= 1073741824) return (bytes / 1073741824).toFixed(2) + ' GB'; | |
| else if (bytes >= 1048576) return (bytes / 1048576).toFixed(2) + ' MB'; | |
| else if (bytes >= 1024) return (bytes / 1024).toFixed(2) + ' KB'; | |
| else return bytes + ' bytes'; | |
| } | |
| const fileInput = document.getElementById('fileInput'); | |
| const folderInput = document.getElementById('folderInput'); | |
| if (fileInput) { | |
| fileInput.addEventListener('change', function() { | |
| if (this.files.length > 0) handleFilesUpload(this.files); | |
| }); | |
| } | |
| if (folderInput) { | |
| folderInput.addEventListener('change', function() { | |
| if (this.files.length > 0) handleFilesUpload(this.files); | |
| }); | |
| } | |
| // ===================================================== | |
| // WEB FETCH FEATURE | |
| // ===================================================== | |
| function showWebFetchDialog() { | |
| hideNewDropdown(); | |
| const modal = document.getElementById('webFetchModal'); | |
| const urlInput = document.getElementById('webFetchUrlInput'); | |
| const nameInput = document.getElementById('webFetchNameInput'); | |
| const downloadBtn = document.getElementById('webFetchDownloadBtn'); | |
| const progress = document.getElementById('webFetchProgress'); | |
| if (modal && urlInput) { | |
| modal.classList.add('show'); | |
| urlInput.value = ''; | |
| nameInput.value = ''; | |
| urlInput.focus(); | |
| downloadBtn.disabled = false; | |
| progress.style.display = 'none'; | |
| } | |
| } | |
| function closeWebFetchDialog() { | |
| const modal = document.getElementById('webFetchModal'); | |
| if (modal) modal.classList.remove('show'); | |
| } | |
| function downloadFromWeb() { | |
| const urlInput = document.getElementById('webFetchUrlInput'); | |
| const nameInput = document.getElementById('webFetchNameInput'); | |
| const downloadBtn = document.getElementById('webFetchDownloadBtn'); | |
| const progress = document.getElementById('webFetchProgress'); | |
| const url = urlInput.value.trim(); | |
| const customName = nameInput.value.trim(); | |
| if (!url) { | |
| showToast('Please enter a URL'); | |
| urlInput.focus(); | |
| return; | |
| } | |
| try { | |
| new URL(url); | |
| } catch (e) { | |
| showToast('Invalid URL format'); | |
| urlInput.focus(); | |
| return; | |
| } | |
| const currentFolder = window.currentFolder || 'root'; | |
| downloadBtn.disabled = true; | |
| progress.style.display = 'block'; | |
| fetch('download_from_url.php', { | |
| method: 'POST', | |
| headers: {'Content-Type': 'application/x-www-form-urlencoded'}, | |
| body: `url=${encodeURIComponent(url)}&fileName=${encodeURIComponent(customName)}&targetFolder=${encodeURIComponent(currentFolder)}` | |
| }) | |
| .then(response => response.json()) | |
| .then(data => { | |
| progress.style.display = 'none'; | |
| downloadBtn.disabled = false; | |
| if (data.success) { | |
| closeWebFetchDialog(); | |
| showToast('File downloaded: ' + data.file.name); | |
| setTimeout(() => location.reload(), 1000); | |
| } else { | |
| showToast('Download failed: ' + (data.error || 'Unknown error')); | |
| } | |
| }) | |
| .catch(error => { | |
| console.error('Error:', error); | |
| progress.style.display = 'none'; | |
| downloadBtn.disabled = false; | |
| showToast('Error downloading file'); | |
| }); | |
| } | |
| // ===================================================== | |
| // SHARE FEATURE | |
| // ===================================================== | |
| function shareSelected() { | |
| const selected = document.querySelectorAll('.file-item.selected'); | |
| if (selected.length === 0) { | |
| showToast('Please select a file to share'); | |
| return; | |
| } | |
| if (selected.length > 1) { | |
| showToast('Please select only one file to share'); | |
| return; | |
| } | |
| const fileId = selected[0].dataset.fileId; | |
| const fileName = selected[0].dataset.fileName; | |
| showShareDialog(fileId, fileName); | |
| } | |
| function showShareDialog(fileId, fileName) { | |
| currentShareFileId = fileId; | |
| const modal = document.getElementById('shareModal'); | |
| const fileNameEl = document.getElementById('shareFileName'); | |
| if (modal && fileNameEl) { | |
| fileNameEl.textContent = fileName; | |
| modal.classList.add('show'); | |
| const baseUrl = window.location.origin + window.location.pathname; | |
| const shareLink = `${baseUrl}?share=${fileId}`; | |
| const shareLinkInput = document.getElementById('shareLinkInput'); | |
| const linkBox = document.getElementById('linkSharingBox'); | |
| if (shareLinkInput) { | |
| shareLinkInput.value = shareLink; | |
| } | |
| if (linkBox) { | |
| linkBox.style.display = 'block'; | |
| } | |
| } | |
| } | |
| function closeShareDialog() { | |
| const modal = document.getElementById('shareModal'); | |
| if (modal) { | |
| modal.classList.remove('show'); | |
| currentShareFileId = null; | |
| } | |
| } | |
| function updateShareAccess(accessType) { | |
| const linkSharingBox = document.getElementById('linkSharingBox'); | |
| const shareLinkInput = document.getElementById('shareLinkInput'); | |
| const shareStatusText = document.getElementById('shareStatusText'); | |
| if (accessType === 'link') { | |
| const baseUrl = window.location.origin + window.location.pathname; | |
| const shareLink = `${baseUrl}?share=${currentShareFileId}`; | |
| shareLinkInput.value = shareLink; | |
| linkSharingBox.style.display = 'block'; | |
| shareStatusText.textContent = 'Public - Anyone with the link'; | |
| fetch('update_share.php', { | |
| method: 'POST', | |
| headers: {'Content-Type': 'application/x-www-form-urlencoded'}, | |
| body: `fileId=${encodeURIComponent(currentShareFileId)}&action=enable_link` | |
| }) | |
| .then(response => response.json()) | |
| .then(data => { | |
| if (data.success) { | |
| showToast('Link sharing enabled'); | |
| setTimeout(() => location.reload(), 1000); | |
| } | |
| }) | |
| .catch(error => console.error('Error:', error)); | |
| } else { | |
| linkSharingBox.style.display = 'none'; | |
| shareStatusText.textContent = 'Private'; | |
| fetch('update_share.php', { | |
| method: 'POST', | |
| headers: {'Content-Type': 'application/x-www-form-urlencoded'}, | |
| body: `fileId=${encodeURIComponent(currentShareFileId)}&action=disable_link` | |
| }) | |
| .then(response => response.json()) | |
| .then(data => { | |
| if (data.success) { | |
| showToast('Link sharing disabled'); | |
| setTimeout(() => location.reload(), 1000); | |
| } | |
| }) | |
| .catch(error => console.error('Error:', error)); | |
| } | |
| } | |
| function copyShareLink() { | |
| const shareLinkInput = document.getElementById('shareLinkInput'); | |
| if (!shareLinkInput) return; | |
| shareLinkInput.select(); | |
| shareLinkInput.setSelectionRange(0, 99999); | |
| try { | |
| document.execCommand('copy'); | |
| showToast('Link copied to clipboard!'); | |
| } catch (err) { | |
| navigator.clipboard.writeText(shareLinkInput.value) | |
| .then(() => showToast('Link copied to clipboard!')) | |
| .catch(() => showToast('Failed to copy link')); | |
| } | |
| } | |
| function loadShareStatus(fileId) { | |
| fetch(`get_shares.php?fileId=${encodeURIComponent(fileId)}`) | |
| .then(response => response.json()) | |
| .then(data => { | |
| const restrictedRadio = document.querySelector('input[value="restricted"]'); | |
| const linkRadio = document.querySelector('input[value="link"]'); | |
| const linkSharingBox = document.getElementById('linkSharingBox'); | |
| const shareLinkInput = document.getElementById('shareLinkInput'); | |
| const shareStatusText = document.getElementById('shareStatusText'); | |
| if (data.linkSharing) { | |
| linkRadio.checked = true; | |
| const baseUrl = window.location.origin + window.location.pathname; | |
| shareLinkInput.value = `${baseUrl}?share=${fileId}`; | |
| linkSharingBox.style.display = 'block'; | |
| shareStatusText.textContent = 'Public - Anyone with the link'; | |
| } else { | |
| restrictedRadio.checked = true; | |
| linkSharingBox.style.display = 'none'; | |
| shareStatusText.textContent = 'Private'; | |
| } | |
| }) | |
| .catch(error => { | |
| console.error('Error loading share status:', error); | |
| }); | |
| } | |
| // File type to Material Icon mapping | |
| function getFileIcon(fileName, mimeType) { | |
| const extension = fileName.split('.').pop().toLowerCase(); | |
| // Image files | |
| if (mimeType.startsWith('image/')) { | |
| return 'image'; | |
| } | |
| // Video files | |
| if (mimeType.startsWith('video/')) { | |
| return 'movie'; | |
| } | |
| // Audio files | |
| if (mimeType.startsWith('audio/')) { | |
| return 'audiotrack'; | |
| } | |
| // Document files | |
| if (mimeType === 'application/pdf') { | |
| return 'picture_as_pdf'; | |
| } | |
| // Microsoft Office | |
| if (extension === 'doc' || extension === 'docx' || mimeType.includes('word')) { | |
| return 'description'; | |
| } | |
| if (extension === 'xls' || extension === 'xlsx' || mimeType.includes('excel') || mimeType.includes('spreadsheet')) { | |
| return 'table_chart'; | |
| } | |
| if (extension === 'ppt' || extension === 'pptx' || mimeType.includes('powerpoint') || mimeType.includes('presentation')) { | |
| return 'slideshow'; | |
| } | |
| // Archives | |
| if (extension === 'zip' || extension === 'rar' || extension === '7z' || extension === 'tar' || extension === 'gz') { | |
| return 'folder_zip'; | |
| } | |
| // Code files | |
| if (extension === 'html' || extension === 'css' || extension === 'js' || extension === 'php' || | |
| extension === 'py' || extension === 'java' || extension === 'cpp' || extension === 'c' || | |
| extension === 'json' || extension === 'xml' || extension === 'sql') { | |
| return 'code'; | |
| } | |
| // Text files | |
| if (mimeType.startsWith('text/') || extension === 'txt') { | |
| return 'article'; | |
| } | |
| // Executable files | |
| if (extension === 'exe' || extension === 'msi' || extension === 'app' || extension === 'deb' || extension === 'rpm') { | |
| return 'settings_applications'; | |
| } | |
| // Binary/System files | |
| if (extension === 'bin' || extension === 'dat' || extension === 'dll' || extension === 'sys' || extension === 'so') { | |
| return 'memory'; | |
| } | |
| // ISO/Disk images | |
| if (extension === 'iso' || extension === 'img' || extension === 'dmg') { | |
| return 'album'; | |
| } | |
| // Folders | |
| if (mimeType === 'folder') { | |
| return 'folder'; | |
| } | |
| // Default | |
| return 'insert_drive_file'; | |
| } | |
| // Also add this CSS for better icon styling | |
| const iconStyles = ` | |
| .file-icon-preview { | |
| width: 100%; | |
| height: 100%; | |
| display: flex; | |
| align-items: center; | |
| justify-content: center; | |
| background: #f8f9fa; | |
| } | |
| .file-icon-preview .material-icons { | |
| font-size: 64px; | |
| color: #5f6368; | |
| } | |
| /* Specific colors for file types */ | |
| .file-icon-preview.image-file .material-icons { color: #ea4335; } | |
| .file-icon-preview.video-file .material-icons { color: #ea4335; } | |
| .file-icon-preview.audio-file .material-icons { color: #fbbc04; } | |
| .file-icon-preview.pdf-file .material-icons { color: #ea4335; } | |
| .file-icon-preview.word-file .material-icons { color: #4285f4; } | |
| .file-icon-preview.excel-file .material-icons { color: #34a853; } | |
| .file-icon-preview.powerpoint-file .material-icons { color: #ea4335; } | |
| .file-icon-preview.archive-file .material-icons { color: #f9ab00; } | |
| .file-icon-preview.code-file .material-icons { color: #5f6368; } | |
| .file-icon-preview.executable-file .material-icons { color: #1a73e8; } | |
| .file-icon-preview.binary-file .material-icons { color: #5f6368; } | |
| `; |