Drive / index.php
Urban-Guy's picture
Update index.php
aa7eb29 verified
Raw History Blame Contribute Delete
66.1 kB
<?php
session_start();
function getGoogleDriveIcon($fileName, $mimeType) {
$extension = strtolower(pathinfo($fileName, PATHINFO_EXTENSION));
// FOLDERS - Google Drive green
if ($mimeType === 'folder') {
return [
'icon' => 'folder',
'color' => '#5F6368', // Google's folder gray
'bgColor' => '#ffffff',
'class' => 'folder-item'
];
}
// IMAGES - Show thumbnail
if (strpos($mimeType, 'image/') === 0) {
return [
'icon' => 'image',
'color' => '#EA4335', // Google red
'bgColor' => '#ffffff',
'class' => 'image-file',
'showThumbnail' => true
];
}
// VIDEOS - Show thumbnail with play icon
if (strpos($mimeType, 'video/') === 0) {
return [
'icon' => 'play_circle_filled',
'color' => '#EA4335', // Google red
'bgColor' => '#ffffff',
'class' => 'video-file',
'showThumbnail' => true
];
}
// AUDIO FILES
if (strpos($mimeType, 'audio/') === 0) {
return [
'icon' => 'audiotrack',
'color' => '#EA4335', // Google red
'bgColor' => '#ffffff',
'class' => 'audio-file'
];
}
// PDF FILES - Google red
if ($mimeType === 'application/pdf' || $extension === 'pdf') {
return [
'icon' => 'picture_as_pdf',
'color' => '#EA4335', // Google red
'bgColor' => '#ffffff',
'class' => 'pdf-file'
];
}
// MICROSOFT WORD / GOOGLE DOCS - Google blue
if (in_array($extension, ['doc', 'docx']) || strpos($mimeType, 'word') !== false) {
return [
'icon' => 'description',
'color' => '#4285F4', // Google Docs blue
'bgColor' => '#ffffff',
'class' => 'word-file'
];
}
// MICROSOFT EXCEL / GOOGLE SHEETS - Google green
if (in_array($extension, ['xls', 'xlsx']) || strpos($mimeType, 'excel') !== false || strpos($mimeType, 'spreadsheet') !== false) {
return [
'icon' => 'grid_on',
'color' => '#0F9D58', // Google Sheets green
'bgColor' => '#ffffff',
'class' => 'excel-file'
];
}
// MICROSOFT POWERPOINT / GOOGLE SLIDES - Google yellow
if (in_array($extension, ['ppt', 'pptx']) || strpos($mimeType, 'powerpoint') !== false || strpos($mimeType, 'presentation') !== false) {
return [
'icon' => 'slideshow',
'color' => '#FBBC04', // Google Slides yellow
'bgColor' => '#ffffff',
'class' => 'powerpoint-file'
];
}
// ARCHIVE FILES (ZIP, RAR, etc.)
if (in_array($extension, ['zip', 'rar', '7z', 'tar', 'gz', 'bz2'])) {
return [
'icon' => 'folder_zip',
'color' => '#F4B400', // Yellow
'bgColor' => '#ffffff',
'class' => 'archive-file'
];
}
// CODE FILES
if (in_array($extension, ['html', 'css', 'js', 'php', 'py', 'java', 'cpp', 'c', 'json', 'xml', 'sql', 'sh', 'bat', 'ts', 'jsx', 'tsx'])) {
return [
'icon' => 'code',
'color' => '#5F6368', // Gray
'bgColor' => '#ffffff',
'class' => 'code-file'
];
}
// TEXT FILES
if (strpos($mimeType, 'text/') === 0 || in_array($extension, ['txt', 'md', 'log'])) {
return [
'icon' => 'description',
'color' => '#5F6368', // Gray
'bgColor' => '#ffffff',
'class' => 'text-file'
];
}
// EXECUTABLE FILES (.exe, .msi, .app) ⭐ FIXES YOUR BROKEN ICON ISSUE
if (in_array($extension, ['exe', 'msi', 'app', 'deb', 'rpm', 'apk'])) {
return [
'icon' => 'insert_drive_file',
'color' => '#80868B', // Light gray (like Google Drive)
'bgColor' => '#ffffff',
'class' => 'executable-file'
];
}
// BINARY FILES (.bin, .dll, .dat) ⭐ FIXES YOUR BROKEN ICON ISSUE
if (in_array($extension, ['bin', 'dat', 'dll', 'sys', 'so', 'o'])) {
return [
'icon' => 'insert_drive_file',
'color' => '#80868B', // Light gray (like Google Drive)
'bgColor' => '#ffffff',
'class' => 'binary-file'
];
}
// DISK IMAGES (ISO, IMG, etc.)
if (in_array($extension, ['iso', 'img', 'dmg', 'vhd'])) {
return [
'icon' => 'album',
'color' => '#9334E6', // Purple
'bgColor' => '#ffffff',
'class' => 'disk-file'
];
}
// DEFAULT - Generic file (like Google Drive)
return [
'icon' => 'insert_drive_file',
'color' => '#80868B', // Light gray
'bgColor' => '#ffffff',
'class' => 'default-file'
];
}
?>
/**
* Get Google Drive-style icon and color for file types
* Returns exact Google colors and appropriate Material Icons
*/
function getGoogleDriveIcon($fileName, $mimeType) {
$extension = strtolower(pathinfo($fileName, PATHINFO_EXTENSION));
// FOLDERS
if ($mimeType === 'folder') {
return [
'icon' => 'folder',
'color' => '#5F6368',
'bgColor' => '#ffffff',
'class' => 'folder-item'
];
}
// IMAGES - Show thumbnail
if (strpos($mimeType, 'image/') === 0) {
return [
'icon' => 'image',
'color' => '#EA4335',
'bgColor' => '#ffffff',
'class' => 'image-file',
'showThumbnail' => true
];
}
// VIDEOS
if (strpos($mimeType, 'video/') === 0) {
return [
'icon' => 'play_circle_filled',
'color' => '#EA4335',
'bgColor' => '#ffffff',
'class' => 'video-file',
'showThumbnail' => true
];
}
// AUDIO FILES
if (strpos($mimeType, 'audio/') === 0) {
return [
'icon' => 'audiotrack',
'color' => '#EA4335',
'bgColor' => '#ffffff',
'class' => 'audio-file'
];
}
// PDF FILES
if ($mimeType === 'application/pdf' || $extension === 'pdf') {
return [
'icon' => 'picture_as_pdf',
'color' => '#EA4335',
'bgColor' => '#ffffff',
'class' => 'pdf-file'
];
}
// WORD DOCS
if (in_array($extension, ['doc', 'docx']) || strpos($mimeType, 'word') !== false) {
return [
'icon' => 'description',
'color' => '#4285F4',
'bgColor' => '#ffffff',
'class' => 'word-file'
];
}
// EXCEL/SHEETS
if (in_array($extension, ['xls', 'xlsx']) || strpos($mimeType, 'excel') !== false || strpos($mimeType, 'spreadsheet') !== false) {
return [
'icon' => 'grid_on',
'color' => '#0F9D58',
'bgColor' => '#ffffff',
'class' => 'excel-file'
];
}
// POWERPOINT/SLIDES
if (in_array($extension, ['ppt', 'pptx']) || strpos($mimeType, 'powerpoint') !== false || strpos($mimeType, 'presentation') !== false) {
return [
'icon' => 'slideshow',
'color' => '#FBBC04',
'bgColor' => '#ffffff',
'class' => 'powerpoint-file'
];
}
// ARCHIVES
if (in_array($extension, ['zip', 'rar', '7z', 'tar', 'gz', 'bz2'])) {
return [
'icon' => 'folder_zip',
'color' => '#F4B400',
'bgColor' => '#ffffff',
'class' => 'archive-file'
];
}
// CODE FILES
if (in_array($extension, ['html', 'css', 'js', 'php', 'py', 'java', 'cpp', 'c', 'json', 'xml', 'sql', 'sh', 'bat'])) {
return [
'icon' => 'code',
'color' => '#5F6368',
'bgColor' => '#ffffff',
'class' => 'code-file'
];
}
// TEXT FILES
if (strpos($mimeType, 'text/') === 0 || in_array($extension, ['txt', 'md', 'log'])) {
return [
'icon' => 'description',
'color' => '#5F6368',
'bgColor' => '#ffffff',
'class' => 'text-file'
];
}
// EXECUTABLE FILES (.exe, .msi, .app) ⭐ FIXES YOUR ISSUE
if (in_array($extension, ['exe', 'msi', 'app', 'deb', 'rpm', 'apk'])) {
return [
'icon' => 'insert_drive_file',
'color' => '#80868B',
'bgColor' => '#ffffff',
'class' => 'executable-file'
];
}
// BINARY FILES (.bin, .dll, .dat) ⭐ FIXES YOUR ISSUE
if (in_array($extension, ['bin', 'dat', 'dll', 'sys', 'so', 'o'])) {
return [
'icon' => 'insert_drive_file',
'color' => '#80868B',
'bgColor' => '#ffffff',
'class' => 'binary-file'
];
}
// DISK IMAGES
if (in_array($extension, ['iso', 'img', 'dmg', 'vhd'])) {
return [
'icon' => 'album',
'color' => '#9334E6',
'bgColor' => '#ffffff',
'class' => 'disk-file'
];
}
// DEFAULT
return [
'icon' => 'insert_drive_file',
'color' => '#80868B',
'bgColor' => '#ffffff',
'class' => 'default-file'
];
}
?>
<!-- Then in your file rendering section, replace the current preview code with this: -->
<?php foreach ($displayFiles as $file): ?>
<div class="file-item <?php echo $file['type'] === 'folder' ? 'folder-item' : ''; ?> <?php
$iconData = getFileIconClass($file['name'], $file['type']);
echo $iconData['class'];
?>"
data-file-id="<?php echo htmlspecialchars($file['id']); ?>"
data-file-name="<?php echo htmlspecialchars($file['name']); ?>"
data-file-path="<?php echo htmlspecialchars($file['path']); ?>"
data-file-type="<?php echo htmlspecialchars($file['type']); ?>"
data-starred="<?php echo $file['starred'] ? 'true' : 'false'; ?>"
onclick="selectFile(event, '<?php echo htmlspecialchars($file['id']); ?>')"
ondblclick="<?php
if ($file['type'] === 'folder') {
echo "window.location.href='index.php?view=my-drive&folder=" . htmlspecialchars($file['id']) . "'";
} else {
echo "openFile('" . htmlspecialchars($file['path']) . "', '" . htmlspecialchars($file['name']) . "', '" . htmlspecialchars($file['type']) . "', '" . htmlspecialchars($file['id']) . "')";
}
?>"
draggable="true">
<div class="file-preview">
<?php if ($file['type'] === 'folder'): ?>
<!-- Folder icon -->
<span class="material-icons folder-icon">folder</span>
<?php elseif (strpos($file['type'], 'image/') === 0): ?>
<!-- Image preview -->
<img src="<?php echo htmlspecialchars($file['path']); ?>" alt="<?php echo htmlspecialchars($file['name']); ?>">
<?php else: ?>
<!-- File icon for non-image files -->
<?php
$iconData = getFileIconClass($file['name'], $file['type']);
?>
<div class="file-icon-preview <?php echo $iconData['class']; ?>">
<span class="material-icons"><?php echo $iconData['icon']; ?></span>
</div>
<?php endif; ?>
<!-- Star badge -->
<?php if ($file['starred']): ?>
<span class="star-badge material-icons">star</span>
<?php endif; ?>
<!-- Shared indicator -->
<?php if (isset($file['shared']) && $file['shared']['enabled']): ?>
<span class="shared-indicator">SHARED</span>
<?php endif; ?>
<!-- Star button on hover -->
<button class="star-button" onclick="toggleStar('<?php echo htmlspecialchars($file['id']); ?>', event)">
<span class="material-icons"><?php echo $file['starred'] ? 'star' : 'star_border'; ?></span>
</button>
</div>
<div class="file-info">
<div class="file-name"><?php echo htmlspecialchars($file['name']); ?></div>
<div class="file-details">
<?php if ($file['type'] !== 'folder'): ?>
<?php echo formatFileSize($file['size']); ?> •
<?php endif; ?>
<?php echo date('M d, Y', $file['modified']); ?>
</div>
</div>
</div>
<?php
session_start();
// ===== ADD THIS ENTIRE FUNCTION HERE ===== ↓↓↓
/**
* Get Google Drive-style icon and color for file types
* Returns exact Google colors and appropriate Material Icons
*/
function getGoogleDriveIcon($fileName, $mimeType) {
$extension = strtolower(pathinfo($fileName, PATHINFO_EXTENSION));
// FOLDERS - Google Drive green
if ($mimeType === 'folder') {
return [
'icon' => 'folder',
'color' => '#5F6368', // Google's folder gray
'bgColor' => '#ffffff',
'class' => 'folder-item'
];
}
// IMAGES - Show thumbnail
if (strpos($mimeType, 'image/') === 0) {
return [
'icon' => 'image',
'color' => '#EA4335', // Google red
'bgColor' => '#ffffff',
'class' => 'image-file',
'showThumbnail' => true
];
}
// VIDEOS - Show thumbnail with play icon
if (strpos($mimeType, 'video/') === 0) {
return [
'icon' => 'play_circle_filled',
'color' => '#EA4335', // Google red
'bgColor' => '#ffffff',
'class' => 'video-file',
'showThumbnail' => true
];
}
// AUDIO FILES
if (strpos($mimeType, 'audio/') === 0) {
return [
'icon' => 'audiotrack',
'color' => '#EA4335', // Google red
'bgColor' => '#ffffff',
'class' => 'audio-file'
];
}
// PDF FILES - Google red
if ($mimeType === 'application/pdf' || $extension === 'pdf') {
return [
'icon' => 'picture_as_pdf',
'color' => '#EA4335', // Google red
'bgColor' => '#ffffff',
'class' => 'pdf-file'
];
}
// MICROSOFT WORD / GOOGLE DOCS - Google blue
if (in_array($extension, ['doc', 'docx']) || strpos($mimeType, 'word') !== false) {
return [
'icon' => 'description',
'color' => '#4285F4', // Google Docs blue
'bgColor' => '#ffffff',
'class' => 'word-file'
];
}
// MICROSOFT EXCEL / GOOGLE SHEETS - Google green
if (in_array($extension, ['xls', 'xlsx']) || strpos($mimeType, 'excel') !== false || strpos($mimeType, 'spreadsheet') !== false) {
return [
'icon' => 'grid_on',
'color' => '#0F9D58', // Google Sheets green
'bgColor' => '#ffffff',
'class' => 'excel-file'
];
}
// MICROSOFT POWERPOINT / GOOGLE SLIDES - Google yellow
if (in_array($extension, ['ppt', 'pptx']) || strpos($mimeType, 'powerpoint') !== false || strpos($mimeType, 'presentation') !== false) {
return [
'icon' => 'slideshow',
'color' => '#FBBC04', // Google Slides yellow
'bgColor' => '#ffffff',
'class' => 'powerpoint-file'
];
}
// ARCHIVE FILES (ZIP, RAR, etc.)
if (in_array($extension, ['zip', 'rar', '7z', 'tar', 'gz', 'bz2'])) {
return [
'icon' => 'folder_zip',
'color' => '#F4B400', // Yellow
'bgColor' => '#ffffff',
'class' => 'archive-file'
];
}
// CODE FILES
if (in_array($extension, ['html', 'css', 'js', 'php', 'py', 'java', 'cpp', 'c', 'json', 'xml', 'sql', 'sh', 'bat', 'ts', 'jsx', 'tsx'])) {
return [
'icon' => 'code',
'color' => '#5F6368', // Gray
'bgColor' => '#ffffff',
'class' => 'code-file'
];
}
// TEXT FILES
if (strpos($mimeType, 'text/') === 0 || in_array($extension, ['txt', 'md', 'log'])) {
return [
'icon' => 'description',
'color' => '#5F6368', // Gray
'bgColor' => '#ffffff',
'class' => 'text-file'
];
}
// EXECUTABLE FILES (.exe, .msi, .app) ⭐ FIXES YOUR BROKEN ICON ISSUE
if (in_array($extension, ['exe', 'msi', 'app', 'deb', 'rpm', 'apk'])) {
return [
'icon' => 'insert_drive_file',
'color' => '#80868B', // Light gray (like Google Drive)
'bgColor' => '#ffffff',
'class' => 'executable-file'
];
}
// BINARY FILES (.bin, .dll, .dat) ⭐ FIXES YOUR BROKEN ICON ISSUE
if (in_array($extension, ['bin', 'dat', 'dll', 'sys', 'so', 'o'])) {
return [
'icon' => 'insert_drive_file',
'color' => '#80868B', // Light gray (like Google Drive)
'bgColor' => '#ffffff',
'class' => 'binary-file'
];
}
// DISK IMAGES (ISO, IMG, etc.)
if (in_array($extension, ['iso', 'img', 'dmg', 'vhd'])) {
return [
'icon' => 'album',
'color' => '#9334E6', // Purple
'bgColor' => '#ffffff',
'class' => 'disk-file'
];
}
// DEFAULT - Generic file (like Google Drive)
return [
'icon' => 'insert_drive_file',
'color' => '#80868B', // Light gray
'bgColor' => '#ffffff',
'class' => 'default-file'
];
}
// ===== END OF FUNCTION ===== ↑↑↑
// Check if this is a shared link
if (isset($_GET['share']) && !empty($_GET['share'])) {
// ... rest of your code continues
// Check if this is a shared link
if (isset($_GET['share']) && !empty($_GET['share'])) {
$shareId = $_GET['share'];
$metadataFile = 'data/files.json';
if (file_exists($metadataFile)) {
$metadata = json_decode(file_get_contents($metadataFile), true);
if ($metadata && isset($metadata['files'])) {
foreach ($metadata['files'] as $file) {
if ($file['id'] === $shareId) {
// ALL FILES ARE PUBLIC - No checks!
$fileName = $file['name'];
$filePath = $file['path'];
$mimeType = $file['type'];
$fileSize = $file['size'];
$modifiedTime = $file['modified'];
if (file_exists($filePath)) {
if (file_exists('view_shared.php')) {
include 'view_shared.php';
exit;
}
}
die('File not found');
}
}
}
}
die('File not found in database');
}
// Create necessary directories
$dirs = ['uploads', 'data', 'trash'];
foreach ($dirs as $dir) {
if (!is_dir($dir)) {
mkdir($dir, 0755, true);
}
}
// Initialize metadata file
$metadataFile = 'data/files.json';
if (!file_exists($metadataFile)) {
file_put_contents($metadataFile, json_encode(['files' => []], JSON_PRETTY_PRINT));
}
// Load metadata
function loadMetadata() {
global $metadataFile;
$data = file_get_contents($metadataFile);
return json_decode($data, true);
}
// Save metadata
function saveMetadata($metadata) {
global $metadataFile;
file_put_contents($metadataFile, json_encode($metadata, JSON_PRETTY_PRINT));
}
// Delete directory recursively
function deleteDirectory($dir) {
if (!is_dir($dir)) return;
$files = array_diff(scandir($dir), ['.', '..']);
foreach ($files as $file) {
$path = $dir . '/' . $file;
is_dir($path) ? deleteDirectory($path) : unlink($path);
}
rmdir($dir);
}
// Calculate storage usage
function calculateStorageUsage($directory = 'uploads') {
$totalSize = 0;
if (is_dir($directory)) {
$files = new RecursiveIteratorIterator(
new RecursiveDirectoryIterator($directory, RecursiveDirectoryIterator::SKIP_DOTS),
RecursiveIteratorIterator::CHILD_FIRST
);
foreach ($files as $file) {
if ($file->isFile()) {
$totalSize += $file->getSize();
}
}
}
return $totalSize;
}
// Format bytes to human readable
function formatBytes($bytes, $precision = 2) {
if ($bytes >= 1073741824) {
return number_format($bytes / 1073741824, $precision) . ' GB';
} elseif ($bytes >= 1048576) {
return number_format($bytes / 1048576, $precision) . ' MB';
} elseif ($bytes >= 1024) {
return number_format($bytes / 1024, $precision) . ' KB';
} else {
return $bytes . ' bytes';
}
}
// Storage quota (50 GB in bytes) - FIXED TYPO
$storageQuota = 50 * 1024 * 1024 * 1024;
$storageUsed = calculateStorageUsage();
$storagePercentage = ($storageUsed / $storageQuota) * 100;
// Determine storage color
if ($storagePercentage >= 95) {
$storageColor = '#ea4335';
} elseif ($storagePercentage >= 80) {
$storageColor = '#f9ab00';
} else {
$storageColor = '#1a73e8';
}
// Get current view and folder
$view = isset($_GET['view']) ? $_GET['view'] : 'my-drive';
$currentFolder = isset($_GET['folder']) ? $_GET['folder'] : 'root';
// Handle file upload via AJAX
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_FILES['files'])) {
$uploadedFiles = $_FILES['files'];
$totalFiles = count($uploadedFiles['name']);
$metadata = loadMetadata();
$results = [];
$targetFolder = isset($_POST['targetFolder']) ? $_POST['targetFolder'] : 'root';
// Determine upload path
$uploadPath = 'uploads/';
if ($targetFolder !== 'root') {
foreach ($metadata['files'] as $file) {
if ($file['id'] === $targetFolder && $file['type'] === 'folder') {
$uploadPath = $file['path'] . '/';
break;
}
}
}
for ($i = 0; $i < $totalFiles; $i++) {
if ($uploadedFiles['error'][$i] === UPLOAD_ERR_OK) {
$fileName = basename($uploadedFiles['name'][$i]);
$tempFile = $uploadedFiles['tmp_name'][$i];
$targetFile = $uploadPath . $fileName;
$counter = 1;
$originalName = pathinfo($fileName, PATHINFO_FILENAME);
$extension = pathinfo($fileName, PATHINFO_EXTENSION);
while (file_exists($targetFile)) {
$fileName = $originalName . '_' . $counter . '.' . $extension;
$targetFile = $uploadPath . $fileName;
$counter++;
}
if (move_uploaded_file($tempFile, $targetFile)) {
$fileId = uniqid();
$newFile = [
'id' => $fileId,
'name' => $fileName,
'path' => $targetFile,
'type' => getFileMimeType($targetFile),
'size' => filesize($targetFile),
'created' => time(),
'modified' => time(),
'accessed' => time(),
'starred' => false,
'trashed' => false,
'trashedDate' => null,
'parentFolder' => $targetFolder
];
$metadata['files'][] = $newFile;
$results[] = ['success' => true, 'file' => $newFile];
} else {
$results[] = ['success' => false, 'error' => 'Failed to upload ' . $fileName];
}
}
}
saveMetadata($metadata);
if (isset($_SERVER['HTTP_X_REQUESTED_WITH']) &&
strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) === 'xmlhttprequest') {
header('Content-Type: application/json');
echo json_encode([
'success' => true,
'files' => $results,
'storageUsed' => calculateStorageUsage(),
'storageQuota' => $storageQuota
]);
exit;
}
header('Location: index.php?view=' . $view . '&folder=' . $currentFolder);
exit;
}
// Auto-delete files older than 30 days in trash
$metadata = loadMetadata();
$thirtyDaysAgo = time() - (30 * 24 * 60 * 60);
foreach ($metadata['files'] as $key => $file) {
if (isset($file['trashed']) && $file['trashed'] &&
isset($file['trashedDate']) && $file['trashedDate'] &&
$file['trashedDate'] < $thirtyDaysAgo) {
if ($file['type'] === 'folder') {
if (is_dir($file['path'])) {
deleteDirectory($file['path']);
}
} else {
if (file_exists($file['path'])) {
unlink($file['path']);
}
}
unset($metadata['files'][$key]);
}
}
$metadata['files'] = array_values($metadata['files']);
saveMetadata($metadata);
// Get files based on view
function getFiles($view, $currentFolder) {
$metadata = loadMetadata();
$files = $metadata['files'];
switch ($view) {
case 'my-drive':
return array_filter($files, function($f) use ($currentFolder) {
return !$f['trashed'] && $f['parentFolder'] === $currentFolder;
});
case 'recent':
$recentFiles = array_filter($files, function($f) { return !$f['trashed']; });
usort($recentFiles, function($a, $b) { return $b['accessed'] - $a['accessed']; });
return array_slice($recentFiles, 0, 20);
case 'starred':
return array_filter($files, function($f) { return $f['starred'] && !$f['trashed']; });
case 'trash':
return array_filter($files, function($f) { return $f['trashed']; });
default:
return array_filter($files, function($f) use ($currentFolder) {
return !$f['trashed'] && $f['parentFolder'] === $currentFolder;
});
}
}
$files = getFiles($view, $currentFolder);
// Get folder breadcrumbs
function getBreadcrumbs($folderId) {
if ($folderId === 'root') return [];
$metadata = loadMetadata();
$breadcrumbs = [];
$currentId = $folderId;
while ($currentId !== 'root') {
foreach ($metadata['files'] as $file) {
if ($file['id'] === $currentId) {
array_unshift($breadcrumbs, $file);
$currentId = isset($file['parentFolder']) ? $file['parentFolder'] : 'root';
break;
}
}
if (!isset($file) || $file['id'] !== $currentId) break;
}
return $breadcrumbs;
}
$breadcrumbs = getBreadcrumbs($currentFolder);
function formatFileSize($bytes) {
if ($bytes >= 1073741824) {
return number_format($bytes / 1073741824, 2) . ' GB';
} elseif ($bytes >= 1048576) {
return number_format($bytes / 1048576, 2) . ' MB';
} elseif ($bytes >= 1024) {
return number_format($bytes / 1024, 2) . ' KB';
} else {
return $bytes . ' bytes';
}
}
function getFileMimeType($filePath) {
// Try to get MIME type using multiple methods
$mimeType = false;
// Method 1: Use mime_content_type (most accurate)
if (function_exists('mime_content_type')) {
$mimeType = mime_content_type($filePath);
}
// Method 2: Use finfo (fallback)
if (!$mimeType && function_exists('finfo_open')) {
$finfo = finfo_open(FILEINFO_MIME_TYPE);
$mimeType = finfo_file($finfo, $filePath);
finfo_close($finfo);
}
// Method 3: Detect by extension (for .exe, .bin, etc.)
if ($mimeType === 'application/octet-stream' || !$mimeType) {
$extension = strtolower(pathinfo($filePath, PATHINFO_EXTENSION));
$extensionMap = [
// Executables
'exe' => 'application/x-msdownload',
'bin' => 'application/x-binary',
'dll' => 'application/x-msdownload',
'app' => 'application/x-executable',
'apk' => 'application/vnd.android.package-archive',
'dmg' => 'application/x-apple-diskimage',
'msi' => 'application/x-msdownload',
// Archives
'zip' => 'application/zip',
'rar' => 'application/x-rar-compressed',
'7z' => 'application/x-7z-compressed',
'tar' => 'application/x-tar',
'gz' => 'application/gzip',
'iso' => 'application/x-iso9660-image',
// Documents
'doc' => 'application/msword',
'docx' => 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
'xls' => 'application/vnd.ms-excel',
'xlsx' => 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
'ppt' => 'application/vnd.ms-powerpoint',
'pptx' => 'application/vnd.openxmlformats-officedocument.presentationml.presentation',
// Code files
'js' => 'application/javascript',
'json' => 'application/json',
'py' => 'text/x-python',
'java' => 'text/x-java',
'cpp' => 'text/x-c++',
'c' => 'text/x-c',
'php' => 'text/x-php',
'html' => 'text/html',
'css' => 'text/css',
// Images
'jpg' => 'image/jpeg',
'jpeg' => 'image/jpeg',
'png' => 'image/png',
'gif' => 'image/gif',
'bmp' => 'image/bmp',
'svg' => 'image/svg+xml',
'webp' => 'image/webp',
// Videos
'mp4' => 'video/mp4',
'avi' => 'video/x-msvideo',
'mov' => 'video/quicktime',
'wmv' => 'video/x-ms-wmv',
'mkv' => 'video/x-matroska',
// Audio
'mp3' => 'audio/mpeg',
'wav' => 'audio/wav',
'ogg' => 'audio/ogg',
'flac' => 'audio/flac'
];
if (isset($extensionMap[$extension])) {
$mimeType = $extensionMap[$extension];
}
}
// Default fallback
return $mimeType ?: 'application/octet-stream';
}
function getFileIcon($mimeType) {
// Image files
if (strpos($mimeType, 'image/') === 0) {
return 'https://ssl.gstatic.com/docs/doclist/images/mediatype/icon_1_image_x16.png';
}
// Video files
if (strpos($mimeType, 'video/') === 0) {
return 'https://ssl.gstatic.com/docs/doclist/images/mediatype/icon_1_video_x16.png';
}
// Audio files
if (strpos($mimeType, 'audio/') === 0) {
return 'https://ssl.gstatic.com/docs/doclist/images/mediatype/icon_1_audio_x16.png';
}
// PDF files
if ($mimeType === 'application/pdf') {
return 'https://ssl.gstatic.com/docs/doclist/images/mediatype/icon_1_pdf_x16.png';
}
// Text files
if (strpos($mimeType, 'text/') === 0) {
return 'https://ssl.gstatic.com/docs/doclist/images/mediatype/icon_1_text_x16.png';
}
// Document files (Word, Excel, PowerPoint, etc.)
if (in_array($mimeType, [
'application/msword',
'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
'application/vnd.oasis.opendocument.text'
])) {
return 'https://ssl.gstatic.com/docs/doclist/images/mediatype/icon_1_document_x16.png';
}
// Spreadsheet files
if (in_array($mimeType, [
'application/vnd.ms-excel',
'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
'application/vnd.oasis.opendocument.spreadsheet'
])) {
return 'https://ssl.gstatic.com/docs/doclist/images/mediatype/icon_1_spreadsheet_x16.png';
}
// Presentation files
if (in_array($mimeType, [
'application/vnd.ms-powerpoint',
'application/vnd.openxmlformats-officedocument.presentationml.presentation',
'application/vnd.oasis.opendocument.presentation'
])) {
return 'https://ssl.gstatic.com/docs/doclist/images/mediatype/icon_1_presentation_x16.png';
}
// Archive files (ZIP, RAR, 7Z, TAR, etc.)
if (in_array($mimeType, [
'application/zip',
'application/x-zip-compressed',
'application/x-rar-compressed',
'application/x-7z-compressed',
'application/x-tar',
'application/gzip',
'application/x-compressed'
])) {
return 'https://ssl.gstatic.com/docs/doclist/images/mediatype/icon_1_archive_x16.png';
}
// Code files
if (in_array($mimeType, [
'application/javascript',
'application/json',
'application/xml',
'text/javascript',
'text/x-python',
'text/x-java',
'text/x-c',
'text/x-c++',
'text/x-php',
'text/html',
'text/css'
])) {
return 'https://ssl.gstatic.com/docs/doclist/images/mediatype/icon_1_code_x16.png';
}
// Executable files (.exe, .bin, .app, .dmg, .apk, etc.)
if (in_array($mimeType, [
'application/x-msdownload',
'application/x-executable',
'application/x-binary',
'application/octet-stream',
'application/x-msdos-program',
'application/x-dosexec',
'application/vnd.microsoft.portable-executable'
])) {
return 'https://ssl.gstatic.com/docs/doclist/images/mediatype/icon_1_executable_x16.png';
}
// APK (Android Package)
if ($mimeType === 'application/vnd.android.package-archive') {
return 'https://ssl.gstatic.com/docs/doclist/images/mediatype/icon_1_executable_x16.png';
}
// DMG (Mac Disk Image)
if ($mimeType === 'application/x-apple-diskimage') {
return 'https://ssl.gstatic.com/docs/doclist/images/mediatype/icon_1_executable_x16.png';
}
// ISO (Disk Image)
if ($mimeType === 'application/x-iso9660-image') {
return 'https://ssl.gstatic.com/docs/doclist/images/mediatype/icon_1_archive_x16.png';
}
// Default for unknown types
return 'https://ssl.gstatic.com/docs/doclist/images/mediatype/icon_1_generic_x16.png';
}
function getGoogleDriveIcon($fileName, $mimeType) {
$extension = strtolower(pathinfo($fileName, PATHINFO_EXTENSION));
// FOLDERS
if ($mimeType === 'folder') {
return [
'icon' => 'folder',
'color' => '#5F6368',
'bgColor' => '#ffffff',
'class' => 'folder-item'
];
}
// IMAGES - Show thumbnail
if (strpos($mimeType, 'image/') === 0) {
return [
'icon' => 'image',
'color' => '#EA4335',
'bgColor' => '#ffffff',
'class' => 'image-file',
'showThumbnail' => true
];
}
// VIDEOS
if (strpos($mimeType, 'video/') === 0) {
return [
'icon' => 'play_circle_filled',
'color' => '#EA4335',
'bgColor' => '#ffffff',
'class' => 'video-file',
'showThumbnail' => true
];
}
// AUDIO FILES
if (strpos($mimeType, 'audio/') === 0) {
return [
'icon' => 'audiotrack',
'color' => '#EA4335',
'bgColor' => '#ffffff',
'class' => 'audio-file'
];
}
// PDF FILES
if ($mimeType === 'application/pdf' || $extension === 'pdf') {
return [
'icon' => 'picture_as_pdf',
'color' => '#EA4335',
'bgColor' => '#ffffff',
'class' => 'pdf-file'
];
}
// WORD DOCS
if (in_array($extension, ['doc', 'docx']) || strpos($mimeType, 'word') !== false) {
return [
'icon' => 'description',
'color' => '#4285F4',
'bgColor' => '#ffffff',
'class' => 'word-file'
];
}
// EXCEL/SHEETS
if (in_array($extension, ['xls', 'xlsx']) || strpos($mimeType, 'excel') !== false || strpos($mimeType, 'spreadsheet') !== false) {
return [
'icon' => 'grid_on',
'color' => '#0F9D58',
'bgColor' => '#ffffff',
'class' => 'excel-file'
];
}
// POWERPOINT/SLIDES
if (in_array($extension, ['ppt', 'pptx']) || strpos($mimeType, 'powerpoint') !== false || strpos($mimeType, 'presentation') !== false) {
return [
'icon' => 'slideshow',
'color' => '#FBBC04',
'bgColor' => '#ffffff',
'class' => 'powerpoint-file'
];
}
// ARCHIVES
if (in_array($extension, ['zip', 'rar', '7z', 'tar', 'gz', 'bz2'])) {
return [
'icon' => 'folder_zip',
'color' => '#F4B400',
'bgColor' => '#ffffff',
'class' => 'archive-file'
];
}
// CODE FILES
if (in_array($extension, ['html', 'css', 'js', 'php', 'py', 'java', 'cpp', 'c', 'json', 'xml', 'sql', 'sh', 'bat'])) {
return [
'icon' => 'code',
'color' => '#5F6368',
'bgColor' => '#ffffff',
'class' => 'code-file'
];
}
// TEXT FILES
if (strpos($mimeType, 'text/') === 0 || in_array($extension, ['txt', 'md', 'log'])) {
return [
'icon' => 'description',
'color' => '#5F6368',
'bgColor' => '#ffffff',
'class' => 'text-file'
];
}
// EXECUTABLE FILES (.exe, .msi, .app) ⭐ FIXES YOUR ISSUE
if (in_array($extension, ['exe', 'msi', 'app', 'deb', 'rpm', 'apk'])) {
return [
'icon' => 'insert_drive_file',
'color' => '#80868B',
'bgColor' => '#ffffff',
'class' => 'executable-file'
];
}
// BINARY FILES (.bin, .dll, .dat) ⭐ FIXES YOUR ISSUE
if (in_array($extension, ['bin', 'dat', 'dll', 'sys', 'so', 'o'])) {
return [
'icon' => 'insert_drive_file',
'color' => '#80868B',
'bgColor' => '#ffffff',
'class' => 'binary-file'
];
}
// DISK IMAGES
if (in_array($extension, ['iso', 'img', 'dmg', 'vhd'])) {
return [
'icon' => 'album',
'color' => '#9334E6',
'bgColor' => '#ffffff',
'class' => 'disk-file'
];
}
// DEFAULT
return [
'icon' => 'insert_drive_file',
'color' => '#80868B',
'bgColor' => '#ffffff',
'class' => 'default-file'
];
}
function timeAgo($timestamp) {
$diff = time() - $timestamp;
if ($diff < 60) {
return 'Just now';
} elseif ($diff < 3600) {
$mins = floor($diff / 60);
return $mins . ' minute' . ($mins > 1 ? 's' : '') . ' ago';
} elseif ($diff < 86400) {
$hours = floor($diff / 3600);
return $hours . ' hour' . ($hours > 1 ? 's' : '') . ' ago';
} elseif ($diff < 604800) {
$days = floor($diff / 86400);
return $days . ' day' . ($days > 1 ? 's' : '') . ' ago';
} else {
return date('M j, Y', $timestamp);
}
}
?>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>My Drive - Google Drive</title>
<link href="https://fonts.googleapis.com/css2?family=Roboto:wght@300;400;500;700&display=swap" rel="stylesheet">
<link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">
<link rel="stylesheet" href="style.css">
</head>
<body>
<div class="header">
<div class="header-left">
<!-- MOBILE HAMBURGER MENU (NEW) -->
<div class="hamburger-menu" onclick="toggleMobileSidebar()">
<span class="material-icons">menu</span>
</div>
<div class="header-logo" onclick="window.location.href='index.php'">
<!-- SVG LOGO -->
<svg width="40" height="40" viewBox="0 0 40 40">
<path fill="#4285F4" d="M22.56 12.25c0-.78-.69-1.41-1.54-1.41H12.89c-.85 0-1.54.63-1.54 1.41s.69 1.41 1.54 1.41h8.13c.85 0 1.54-.63 1.54-1.41z"/>
<path fill="#34A853" d="M26.28 16.25c0-.78-.69-1.41-1.54-1.41H12.89c-.85 0-1.54.63-1.54 1.41s.69 1.41 1.54 1.41h11.85c.85 0 1.54-.63 1.54-1.41z"/>
<path fill="#FBBC04" d="M28.6 20.25c0-.78-.69-1.41-1.54-1.41H12.89c-.85 0-1.54.63-1.54 1.41s.69 1.41 1.54 1.41h14.17c.85 0 1.54-.63 1.54-1.41z"/>
<path fill="#EA4335" d="M26.28 24.25c0-.78-.69-1.41-1.54-1.41H12.89c-.85 0-1.54.63-1.54 1.41s.69 1.41 1.54 1.41h11.85c.85 0 1.54-.63 1.54-1.41z"/>
</svg>
</div>
<span class="header-title">Drive</span>
</div>
<div class="header-center">
<div class="search-box">
<span class="material-icons search-icon">search</span>
<input type="text" class="search-input" id="searchInput" placeholder="Search in Drive">
</div>
</div>
<div class="header-right">
<!-- MOBILE SEARCH TOGGLE (NEW) -->
<div class="header-icon search-toggle" onclick="toggleMobileSearch()">
<span class="material-icons">search</span>
</div>
<div class="header-icon"><span class="material-icons">help_outline</span></div>
<div class="header-icon"><span class="material-icons">settings</span></div>
<div class="header-icon"><span class="material-icons">apps</span></div>
<div class="header-icon"><span class="material-icons">account_circle</span></div>
</div>
</div>
<div class="sidebar">
<div class="new-button" id="newButton">
<span class="material-icons">add</span>
<span>New</span>
</div>
<div class="new-dropdown" id="newDropdown">
<div class="dropdown-item" onclick="showFolderDialog()">
<span class="material-icons">create_new_folder</span>
<span>New folder</span>
</div>
<div class="dropdown-item" onclick="triggerFileUpload()">
<span class="material-icons">upload_file</span>
<span>File upload</span>
</div>
<div class="dropdown-item" onclick="triggerFolderUpload()">
<span class="material-icons">drive_folder_upload</span>
<span>Folder upload</span>
</div>
<div class="dropdown-item" onclick="showWebFetchDialog()">
<span class="material-icons">cloud_download</span>
<span>Web Fetch</span>
</div>
<div class="dropdown-divider"></div>
<div class="dropdown-item disabled" title="Feature not available">
<span class="material-icons">description</span>
<span>Google Docs</span>
</div>
<div class="dropdown-item disabled" title="Feature not available">
<span class="material-icons">grid_on</span>
<span>Google Sheets</span>
</div>
<div class="dropdown-item disabled" title="Feature not available">
<span class="material-icons">slideshow</span>
<span>Google Slides</span>
</div>
</div>
<ul class="sidebar-menu">
<li class="sidebar-item <?php echo $view === 'my-drive' ? 'active' : ''; ?>" onclick="window.location.href='index.php?view=my-drive'">
<span class="material-icons">folder</span>
<span>My Drive</span>
</li>
<li class="sidebar-item <?php echo $view === 'shared' ? 'active' : ''; ?>" onclick="window.location.href='shared.php'">
<span class="material-icons">people</span>
<span>Shared with me</span>
</li>
<li class="sidebar-item <?php echo $view === 'recent' ? 'active' : ''; ?>" onclick="window.location.href='index.php?view=recent'">
<span class="material-icons">access_time</span>
<span>Recent</span>
</li>
<li class="sidebar-item <?php echo $view === 'starred' ? 'active' : ''; ?>" onclick="window.location.href='index.php?view=starred'">
<span class="material-icons">star</span>
<span>Starred</span>
</li>
<li class="sidebar-item <?php echo $view === 'trash' ? 'active' : ''; ?>" onclick="window.location.href='index.php?view=trash'">
<span class="material-icons">delete</span>
<span>Trash</span>
</li>
</ul>
<div class="storage-info" title="<?php echo number_format($storagePercentage, 1); ?>% used">
<div class="storage-text">Storage</div>
<div class="storage-bar">
<div class="storage-used" style="width: <?php echo min($storagePercentage, 100); ?>%; background-color: <?php echo $storageColor; ?>;"></div>
</div>
<div class="storage-text"><?php echo formatBytes($storageUsed); ?> of <?php echo formatBytes($storageQuota); ?> used</div>
</div>
</div>
<div class="sidebar-overlay" onclick="closeMobileSidebar()"></div>
<div class="main-content" id="mainContent" data-current-folder="<?php echo htmlspecialchars($currentFolder); ?>">
<?php if (!empty($breadcrumbs) && $view === 'my-drive'): ?>
<div class="breadcrumbs">
<span class="breadcrumb-item" onclick="window.location.href='index.php?view=my-drive&folder=root'">
<span class="material-icons">folder</span> My Drive
</span>
<?php foreach ($breadcrumbs as $crumb): ?>
<span class="material-icons breadcrumb-arrow">chevron_right</span>
<span class="breadcrumb-item" onclick="window.location.href='index.php?view=my-drive&folder=<?php echo htmlspecialchars($crumb['id']); ?>'">
<?php echo htmlspecialchars($crumb['name']); ?>
</span>
<?php endforeach; ?>
</div>
<?php endif; ?>
<?php if ($view === 'shared'): ?>
<div class="empty-state">
<span class="material-icons">people_outline</span>
<h2>Nothing shared yet</h2>
<p>Files and folders others share with you will show up here</p>
</div>
<?php elseif (empty($files)): ?>
<div class="empty-state">
<?php if ($view === 'trash'): ?>
<span class="material-icons">delete_outline</span>
<h2>Trash is empty</h2>
<p>Items you trash are deleted forever after 30 days</p>
<?php elseif ($view === 'starred'): ?>
<span class="material-icons">star_outline</span>
<h2>No starred items</h2>
<p>Add stars to files and folders to find them easily later</p>
<?php elseif ($view === 'recent'): ?>
<span class="material-icons">access_time</span>
<h2>No recent files</h2>
<p>Files you open or edit will show up here</p>
<?php else: ?>
<span class="material-icons">folder_open</span>
<h2>Drop files here or use the "New" button</h2>
<p>Drag files to upload or create a new folder</p>
<?php endif; ?>
</div>
<?php else: ?>
<div class="toolbar">
<div class="toolbar-left">
<span id="selectedCount" style="display: none; margin-right: 12px; color: #5f6368; font-size: 14px;">0 selected</span>
<?php if ($view === 'trash'): ?>
<button class="toolbar-button" onclick="restoreSelected()">
<span class="material-icons">restore_from_trash</span>
Restore
</button>
<button class="toolbar-button" onclick="deleteForeverSelected()">
<span class="material-icons">delete_forever</span>
Delete forever
</button>
<button class="toolbar-button" onclick="emptyTrash()">
<span class="material-icons">delete_sweep</span>
Empty trash
</button>
<?php else: ?>
<button class="toolbar-button" onclick="deleteSelectedFiles()" style="display: none;" id="deleteSelectedBtn">
<span class="material-icons">delete</span>
Move to trash
</button>
<?php endif; ?>
</div>
<div class="toolbar-right">
<button class="toolbar-button" onclick="toggleView('list')" id="listViewBtn">
<span class="material-icons">view_list</span>
</button>
<button class="toolbar-button active" onclick="toggleView('grid')" id="gridViewBtn">
<span class="material-icons">view_module</span>
</button>
</div>
</div>
<div class="file-grid grid-view" id="fileGrid">
<?php foreach ($files as $file): ?>
<?php $iconData = getGoogleDriveIcon($file['name'], $file['type']); ?>
<div class="file-item <?php echo $iconData['class']; ?>"
data-file-id="<?php echo htmlspecialchars($file['id']); ?>"
data-file-name="<?php echo htmlspecialchars($file['name']); ?>"
data-file-path="<?php echo htmlspecialchars($file['path']); ?>"
data-file-type="<?php echo htmlspecialchars($file['type']); ?>"
data-starred="<?php echo $file['starred'] ? 'true' : 'false'; ?>"
onclick="selectFile(event, '<?php echo htmlspecialchars($file['id']); ?>')"
ondblclick="<?php
if ($file['type'] === 'folder') {
echo "window.location.href='index.php?view=my-drive&folder=" . htmlspecialchars($file['id']) . "'";
} else {
echo "openFile('" . htmlspecialchars($file['path']) . "', '" . htmlspecialchars($file['name']) . "', '" . htmlspecialchars($file['type']) . "', '" . htmlspecialchars($file['id']) . "')";
}
?>"
draggable="true">
<div class="file-preview" style="background-color: <?php echo $iconData['bgColor']; ?>;">
<?php if ($file['type'] === 'folder'): ?>
<!-- Folder Icon -->
<span class="material-icons folder-icon" style="color: <?php echo $iconData['color']; ?>;">
<?php echo $iconData['icon']; ?>
</span>
<?php elseif (isset($iconData['showThumbnail']) && $iconData['showThumbnail'] && strpos($file['type'], 'image/') === 0): ?>
<!-- Image Thumbnail -->
<img src="<?php echo htmlspecialchars($file['path']); ?>"
alt="<?php echo htmlspecialchars($file['name']); ?>"
style="width: 100%; height: 100%; object-fit: cover;">
<?php else: ?>
<!-- File Icon (exe, bin, pdf, etc.) -->
<div class="file-icon-preview">
<span class="material-icons" style="color: <?php echo $iconData['color']; ?>; font-size: 64px;">
<?php echo $iconData['icon']; ?>
</span>
</div>
<?php endif; ?>
<!-- Star Badge -->
<?php if ($file['starred']): ?>
<span class="star-badge material-icons">star</span>
<?php endif; ?>
<!-- Shared Indicator -->
<?php if (isset($file['shared']) && $file['shared']['enabled']): ?>
<span class="shared-indicator">SHARED</span>
<?php endif; ?>
<!-- Star Button on Hover -->
<button class="star-button" onclick="toggleStar('<?php echo htmlspecialchars($file['id']); ?>', event)">
<span class="material-icons"><?php echo $file['starred'] ? 'star' : 'star_border'; ?></span>
</button>
</div>
<div class="file-info">
<div class="file-name"><?php echo htmlspecialchars($file['name']); ?></div>
<div class="file-details">
<?php if ($file['type'] !== 'folder'): ?>
<?php echo formatFileSize($file['size']); ?> •
<?php endif; ?>
<?php echo date('M d, Y', $file['modified']); ?>
</div>
</div>
</div>
<?php endforeach; ?>
</div>
<div class="file-info">
<div class="file-name"><?php echo htmlspecialchars($file['name']); ?></div>
<div class="file-details">
<?php if ($file['type'] !== 'folder'): ?>
<?php echo formatFileSize($file['size']); ?> •
<?php endif; ?>
<?php echo date('M d, Y', $file['modified']); ?>
</div>
</div>
</div>
<?php endforeach; ?>
</div>
<?php endif; ?>
</div>
<!-- Context Menu for Files -->
<div class="context-menu" id="fileContextMenu">
<div class="context-menu-item" onclick="contextMenuAction('open')">
<span class="material-icons">open_in_new</span>
<span>Open</span>
</div>
<div class="context-menu-item" onclick="contextMenuAction('preview')">
<span class="material-icons">visibility</span>
<span>Preview</span>
</div>
<div class="context-menu-item" onclick="contextMenuAction('download')">
<span class="material-icons">download</span>
<span>Download</span>
</div>
<div class="context-menu-divider"></div>
<div class="context-menu-item" onclick="contextMenuAction('rename')">
<span class="material-icons">drive_file_rename_outline</span>
<span>Rename</span>
</div>
<div class="context-menu-item" onclick="contextMenuAction('copy')">
<span class="material-icons">content_copy</span>
<span>Make a copy</span>
</div>
<div class="context-menu-item" onclick="contextMenuAction('share')">
<span class="material-icons">person_add</span>
<span>Share</span>
</div>
<div class="context-menu-divider"></div>
<div class="context-menu-item" id="starMenuItem" onclick="contextMenuAction('star')">
<span class="material-icons">star</span>
<span id="starMenuText">Add to starred</span>
</div>
<div class="context-menu-item" onclick="contextMenuAction('trash')">
<span class="material-icons">delete</span>
<span>Move to trash</span>
</div>
</div>
<!-- Context Menu for Empty Space -->
<div class="context-menu" id="emptyContextMenu">
<div class="context-menu-item" onclick="emptyContextAction('upload')">
<span class="material-icons">upload_file</span>
<span>Upload files</span>
</div>
<div class="context-menu-item" onclick="emptyContextAction('folder')">
<span class="material-icons">create_new_folder</span>
<span>New folder</span>
</div>
<div class="context-menu-divider"></div>
<div class="context-menu-item" onclick="emptyContextAction('refresh')">
<span class="material-icons">refresh</span>
<span>Refresh</span>
</div>
</div>
<!-- File Preview Modal -->
<div class="modal" id="fileModal">
<div class="modal-content">
<div class="modal-header">
<div class="modal-title" id="modalTitle">File Preview</div>
<button class="modal-close" onclick="closeModal()">
<span class="material-icons">close</span>
</button>
</div>
<div class="modal-body" id="modalBody"></div>
</div>
</div>
<!-- Share Dialog (Simplified) -->
<div class="modal" id="shareModal">
<div class="modal-content" style="max-width: 500px;">
<div class="modal-header">
<div class="modal-title">
<span class="material-icons" style="vertical-align: middle; margin-right: 8px;">person_add</span>
Share "<span id="shareFileName"></span>"
</div>
<button class="modal-close" onclick="closeShareDialog()">
<span class="material-icons">close</span>
</button>
</div>
<div class="modal-body" style="padding: 24px;">
<!-- Simple share info -->
<div style="margin-bottom: 20px;">
<div style="padding: 16px; background: #e8f4fd; border-radius: 8px; border-left: 4px solid #1a73e8;">
<div style="display: flex; align-items: center; gap: 8px; margin-bottom: 8px;">
<span class="material-icons" style="color: #1a73e8; font-size: 20px;">info</span>
<span style="font-weight: 500; color: #1a73e8; font-size: 14px;">Public File</span>
</div>
<p style="margin: 0; color: #5f6368; font-size: 13px; line-height: 1.5;">
This file is publicly shareable. Anyone with the link can view and download it.
</p>
</div>
</div>
<!-- Link sharing box -->
<div id="linkSharingBox" style="display: none; padding: 16px; background: #f1f3f4; border-radius: 8px;">
<div style="font-size: 13px; color: #5f6368; margin-bottom: 8px;">
<span class="material-icons" style="vertical-align: middle; font-size: 16px; color: #1a73e8;">info</span>
Anyone with this link can view the file
</div>
<div style="display: flex; gap: 8px; align-items: center;">
<input type="text"
id="shareLinkInput"
class="folder-input"
readonly
style="flex: 1; background: #fff; font-size: 13px;">
<button class="button-secondary" onclick="copyShareLink()" style="padding: 8px 16px;">
<span class="material-icons" style="font-size: 18px;">content_copy</span>
Copy
</button>
</div>
</div>
</div>
<div class="modal-footer" style="justify-content: space-between;">
<div style="font-size: 12px; color: #5f6368;">
<span class="material-icons" style="vertical-align: middle; font-size: 16px;">visibility</span>
<span id="shareStatusText">Private</span>
</div>
<button class="button-primary" onclick="closeShareDialog()">Done</button>
</div>
</div>
</div>
<style>
/* Highlight selected option */
input[type="radio"]:checked + div {
color: #1a73e8;
}
label:has(input[type="radio"]:checked) {
border-color: #1a73e8 !important;
background: #e8f0fe;
}
.shared-indicator {
position: absolute;
top: 8px;<div class="context-menu-divider"></div>
right: 32px;
background: #1a73e8;
color: white;
padding: 2px 6px;
border-radius: 4px;
font-size: 10px;
font-weight: 500;
}
</style>
<!-- New Folder Dialog -->
<div class="modal" id="folderModal">
<div class="modal-content folder-dialog">
<div class="modal-header">
<div class="modal-title">New folder</div>
<button class="modal-close" onclick="closeFolderDialog()">
<span class="material-icons">close</span>
</button>
</div>
<div class="modal-body">
<input type="text" id="folderNameInput" class="folder-input" placeholder="Untitled folder" autofocus>
</div>
<div class="modal-footer">
<button class="button-secondary" onclick="closeFolderDialog()">Cancel</button>
<button class="button-primary" id="createFolderBtn" onclick="createFolder()" disabled>Create</button>
</div>
</div>
</div>
<!-- Web Fetch Dialog -->
<div class="modal" id="webFetchModal">
<div class="modal-content folder-dialog">
<div class="modal-header">
<div class="modal-title">
<span class="material-icons" style="vertical-align: middle; margin-right: 8px;">cloud_download</span>
Download from Web
</div>
<button class="modal-close" onclick="closeWebFetchDialog()">
<span class="material-icons">close</span>
</button>
</div>
<div class="modal-body">
<div style="margin-bottom: 20px;">
<label style="display: block; margin-bottom: 8px; font-size: 14px; font-weight: 500; color: #202124;">
File URL <span style="color: #ea4335;">*</span>
</label>
<input type="url"
id="webFetchUrlInput"
class="folder-input"
placeholder="https://example.com/file.pdf"
style="margin-bottom: 4px;">
<span style="font-size: 12px; color: #5f6368;">Enter the direct URL to the file</span>
</div>
<div>
<label style="display: block; margin-bottom: 8px; font-size: 14px; font-weight: 500; color: #202124;">
Custom filename (optional)
</label>
<input type="text"
id="webFetchNameInput"
class="folder-input"
placeholder="my-document.pdf">
<span style="font-size: 12px; color: #5f6368;">Leave empty to use original filename</span>
</div>
<div id="webFetchProgress" style="display: none; margin-top: 16px; padding: 12px; background: #f1f3f4; border-radius: 4px;">
<div style="display: flex; align-items: center; gap: 12px;">
<div class="spinner" style="width: 20px; height: 20px; border: 2px solid #1a73e8; border-top-color: transparent; border-radius: 50%; animation: spin 0.8s linear infinite;"></div>
<span style="font-size: 14px; color: #5f6368;">Downloading file...</span>
</div>
</div>
</div>
<div class="modal-footer">
<button class="button-secondary" onclick="closeWebFetchDialog()">Cancel</button>
<button class="button-primary" id="webFetchDownloadBtn" onclick="downloadFromWeb()">Download</button>
</div>
</div>
</div>
<style>
@keyframes spin {
to { transform: rotate(360deg); }
}
</style>
<!-- Upload Progress Popup -->
<div class="upload-progress" id="uploadProgress">
<div class="upload-header">
<div class="upload-title">
<span id="uploadStatusText">Uploading 0 files</span>
</div>
<div class="upload-actions">
<button class="icon-button" onclick="minimizeUploadProgress()">
<span class="material-icons">minimize</span>
</button>
<button class="icon-button" onclick="closeUploadProgress()">
<span class="material-icons">close</span>
</button>
</div>
</div>
<div class="upload-overall-progress">
<div class="progress-bar">
<div class="progress-fill" id="overallProgress" style="width: 0%"></div>
</div>
<div class="progress-text" id="overallProgressText">0%</div>
</div>
<div class="upload-file-list" id="uploadFileList"></div>
</div>
<!-- Drag & Drop Overlay -->
<div class="drag-overlay" id="dragOverlay">
<div class="drag-content">
<span class="material-icons">cloud_upload</span>
<h2>Drop files to upload</h2>
</div>
</div>
<!-- Toast Notification -->
<div class="toast" id="toast"></div>
<!-- Upload Form (Hidden) -->
<form id="uploadForm" style="display: none;">
<input type="file" id="fileInput" name="files[]" multiple>
<input type="file" id="folderInput" name="files[]" multiple webkitdirectory directory>
</form>
<script>
window.storageQuota = <?php echo $storageQuota; ?>;
window.storageUsed = <?php echo $storageUsed; ?>;
window.currentFolder = '<?php echo htmlspecialchars($currentFolder); ?>';
</script>
<script src="script.js"></script>
</body>
</html>