Files
Oxicloud/static/index.html
T
Dionisio 1ceae0ce94 Frontend optimizations: SVG icons, remove updateFileIcons, unify rendering, scope translatePage
- Replace Font Awesome CDN with inline SVG system (icons.js + MutationObserver)
- Remove updateFileIcons() (~140 lines) - redundant with backend icon_class + MutationObserver
- Migrate favorites.js and recent.js to use shared ui.renderFolders/renderFiles (eliminate ~260 lines of duplicate rendering + per-item event listeners)
- Add view-mode aware click delegation for favorites/recent views
- Fix _createFileCard to apply icon_special_class
- Add translateElement(root) for scoped i18n translation
- Replace full-page translatePage() calls with scoped translateElement() or inline t()
- Remove redundant translatePage() calls in shared.js and auth.js
- Remove Alpine.js from Service Worker cache
2026-02-16 21:51:53 +01:00

315 lines
15 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title data-i18n="app.title">OxiCloud</title>
<!-- Apply saved theme immediately to prevent flash of light mode -->
<script>if(localStorage.getItem('oxicloud_theme')==='dark')document.documentElement.setAttribute('data-theme','dark');</script>
<!-- Styles -->
<link rel="stylesheet" href="/css/style.css">
<link rel="stylesheet" href="/css/inlineViewer.css">
<link rel="stylesheet" href="/css/favorites.css">
<link rel="stylesheet" href="/css/recent.css">
<!-- Scripts (defer: download in parallel, execute in order, after HTML parsed) -->
<script defer src="/js/i18n.js"></script>
<script defer src="/js/languageSelector.js"></script>
<script defer src="/js/notifications.js"></script>
<script defer src="/js/modal.js"></script>
<script defer src="/js/ui.js"></script>
<script defer src="/js/contextMenus.js"></script>
<script defer src="/js/fileOperations.js"></script>
<script defer src="/js/multiSelect.js"></script>
<script defer src="/js/search.js"></script>
<script defer src="/js/favorites.js"></script>
<script defer src="/js/recent.js"></script>
<script defer src="/js/fileSharing.js"></script>
<script defer src="/js/components/sharedView.js"></script>
<script defer src="/js/inlineViewer.js"></script>
<script defer src="/js/icons.js"></script>
<script defer src="/js/app.js"></script>
<!-- Service Worker Registration -->
<script>
if ('serviceWorker' in navigator) {
window.addEventListener('load', () => {
navigator.serviceWorker.register('/sw.js')
.then(reg => console.log('Service Worker registered successfully'))
.catch(err => console.log('Service Worker registration failed:', err));
});
}
</script>
</head>
<body>
<!-- Sidebar -->
<div class="sidebar">
<a href="/" class="logo-container" style="text-decoration:none;color:inherit;">
<div class="logo">
<svg viewBox="0 0 500 500">
<path d="M345 310c32 0 58-26 58-58s-26-58-58-58c-6.2 0-12 0.9-17.5 2.7C318 166 289 143 255 143c-34.3 0-63.1 22.6-73 53.7C176.9 195.7 171 195 165 195c-32 0-58 26-58 58s26 58 58 58h180z" fill="#fff"/>
</svg>
</div>
<div class="app-name">OxiCloud</div>
</a>
<div class="nav-menu">
<div class="nav-item active">
<i class="fas fa-folder"></i>
<span data-i18n="nav.files">Files</span>
</div>
<div class="nav-item" id="nav-shared">
<i class="fas fa-share-alt"></i>
<span data-i18n="nav.shared">Shared</span>
</div>
<div class="nav-item">
<i class="fas fa-clock"></i>
<span data-i18n="nav.recent">Recent</span>
</div>
<div class="nav-item">
<i class="fas fa-star"></i>
<span data-i18n="nav.favorites">Favorites</span>
</div>
<div class="nav-item">
<i class="fas fa-trash"></i>
<span data-i18n="nav.trash">Trash</span>
</div>
</div>
<div class="storage-container">
<div class="storage-title"><i class="fas fa-database"></i> <span data-i18n="storage.title">Storage</span></div>
<div class="storage-bar">
<div class="storage-fill"></div>
</div>
<div class="storage-info" data-i18n="storage.calculating">Calculating...</div>
</div>
</div>
<!-- Main Content -->
<div class="main-content">
<!-- Top Bar -->
<div class="top-bar">
<div class="search-container">
<i class="fas fa-search search-icon"></i>
<input type="text" id="search-input" data-i18n-placeholder="actions.search" placeholder="Search files, folders...">
<button id="search-button" class="search-button" data-i18n-title="actions.search_btn" title="Search">
<i class="fas fa-search"></i>
</button>
</div>
<div class="user-controls">
<div id="language-selector"></div>
<!-- Notification Bell -->
<div class="notif-wrapper" id="notif-wrapper">
<button class="notif-bell-btn" id="notif-bell-btn" title="Notifications">
<i class="fas fa-bell"></i>
<span class="notif-badge" id="notif-badge" style="display:none">0</span>
</button>
<div class="notif-panel" id="notif-panel">
<div class="notif-panel-header">
<span class="notif-panel-title" data-i18n="notifications.title">Notifications</span>
<button class="notif-clear-btn" id="notif-clear-btn" title="Clear all">
<i class="fas fa-check-double"></i>
</button>
</div>
<div class="notif-panel-body" id="notif-panel-body">
<div class="notif-empty" id="notif-empty">
<i class="fas fa-bell-slash"></i>
<span data-i18n="notifications.empty">No notifications</span>
</div>
</div>
</div>
</div>
<div class="user-menu-wrapper" id="user-menu-wrapper">
<button class="user-avatar-btn" id="user-avatar-btn">
<div class="user-avatar" id="user-avatar">AD</div>
</button>
<div class="user-menu" id="user-menu">
<div class="user-menu-header">
<div class="user-menu-avatar" id="user-menu-avatar">AD</div>
<div class="user-menu-info">
<div class="user-menu-name" id="user-menu-name">User</div>
<div class="user-menu-email" id="user-menu-email">user@oxicloud.app</div>
</div>
</div>
<div class="user-menu-role-badge" id="user-menu-role-badge" style="display:none">
<span class="role-badge role-badge-admin"><i class="fas fa-shield-alt"></i> Admin</span>
</div>
<div class="user-menu-storage">
<div class="user-menu-storage-label">
<i class="fas fa-database"></i>
<span data-i18n="storage.title">Storage</span>
</div>
<div class="user-menu-storage-bar">
<div class="user-menu-storage-fill" id="user-menu-storage-fill"></div>
</div>
<div class="user-menu-storage-text" id="user-menu-storage-text">0% used</div>
</div>
<div class="user-menu-divider"></div>
<button class="user-menu-item user-menu-admin" id="user-menu-admin" style="display:none">
<i class="fas fa-cogs"></i>
<span data-i18n="user_menu.admin_panel">Admin panel</span>
</button>
<button class="user-menu-item" id="user-menu-profile">
<i class="fas fa-user-circle"></i>
<span data-i18n="user_menu.profile">My profile</span>
</button>
<div class="user-menu-divider" id="user-menu-admin-divider" style="display:none"></div>
<button class="user-menu-item" id="user-menu-theme">
<i class="fas fa-moon"></i>
<span data-i18n="user_menu.appearance">Appearance</span>
<div class="theme-toggle-pill" id="theme-toggle-pill">
<div class="theme-toggle-knob"></div>
</div>
</button>
<button class="user-menu-item" id="user-menu-about">
<i class="fas fa-info-circle"></i>
<span data-i18n="user_menu.about">About OxiCloud</span>
</button>
<div class="user-menu-divider"></div>
<button class="user-menu-item user-menu-logout" id="user-menu-logout">
<i class="fas fa-sign-out-alt"></i>
<span data-i18n="actions.logout">Log out</span>
</button>
</div>
</div>
</div>
</div>
<div class="content-area">
<h1 class="page-title" data-i18n="nav.files">Files</h1>
<div class="actions-bar">
<div class="action-buttons">
<div class="upload-dropdown" id="upload-dropdown">
<button class="btn btn-primary" id="upload-btn">
<i class="fas fa-cloud-upload-alt"></i>
<span data-i18n="actions.upload">Upload</span>
<i class="fas fa-caret-down" style="margin-left: 4px; font-size: 12px;"></i>
</button>
<div class="upload-dropdown-menu" id="upload-dropdown-menu">
<button class="upload-dropdown-item" id="upload-files-btn">
<i class="fas fa-file"></i>
<span data-i18n="actions.upload_files">Upload files</span>
</button>
<button class="upload-dropdown-item" id="upload-folder-btn">
<i class="fas fa-folder-open"></i>
<span data-i18n="actions.upload_folder">Upload folder</span>
</button>
</div>
</div>
<button class="btn btn-secondary" id="new-folder-btn">
<i class="fas fa-folder-plus"></i>
<span data-i18n="actions.new_folder">New folder</span>
</button>
</div>
<div class="view-toggle">
<button class="toggle-btn active" id="grid-view-btn" title="Grid view">
<i class="fas fa-th"></i>
</button>
<button class="toggle-btn" id="list-view-btn" title="List view">
<i class="fas fa-list"></i>
</button>
</div>
</div>
<div class="dropzone" id="dropzone">
<i class="fas fa-cloud-upload-alt" style="font-size: 32px; margin-bottom: 10px;"></i>
<p data-i18n="dropzone.drag_files">Drag files here or click to select</p>
<input type="file" id="file-input" style="display: none;" multiple>
<input type="file" id="folder-input" style="display: none;" webkitdirectory directory multiple>
<div class="upload-progress">
<div class="progress-bar">
<div class="progress-fill"></div>
</div>
</div>
</div>
<div class="breadcrumb">
<span class="breadcrumb-item" data-i18n="breadcrumb.home">Home</span>
</div>
<!-- Files Container -->
<div class="files-container">
<!-- Grid View -->
<div class="files-grid" id="files-grid">
<!-- Files will be populated here -->
</div>
<!-- List View (hidden by default) -->
<div class="files-list-view" id="files-list-view" style="display: none;">
<div class="list-header">
<div class="list-header-checkbox"><input type="checkbox" id="select-all-checkbox" title="Select all"></div>
<div data-i18n="files.name">Name</div>
<div data-i18n="files.type">Type</div>
<div data-i18n="files.size">Size</div>
<div data-i18n="files.modified">Modified</div>
</div>
<!-- Files will be populated here in list view -->
</div>
</div>
</div>
</div>
<!-- Input Modal (for New Folder, Rename, etc.) -->
<div id="input-modal" class="modal-overlay">
<div class="modal-container">
<div class="modal-header">
<div class="modal-icon">
<i id="modal-icon" class="fas fa-folder-plus"></i>
</div>
<h3 id="modal-title" data-i18n="dialogs.new_folder_title">New folder</h3>
<button class="modal-close-btn" id="modal-close-btn">
<i class="fas fa-times"></i>
</button>
</div>
<div class="modal-body">
<label id="modal-label" for="modal-input" data-i18n="dialogs.folder_name">Folder name</label>
<input type="text" id="modal-input" class="modal-input" placeholder="" autocomplete="off">
</div>
<div class="modal-footer">
<button class="btn btn-secondary" id="modal-cancel-btn" data-i18n="actions.cancel">Cancel</button>
<button class="btn btn-primary" id="modal-confirm-btn" data-i18n="actions.confirm">Create</button>
</div>
</div>
</div>
<!-- About Modal -->
<div class="about-modal-overlay" id="about-modal-overlay">
<div class="about-modal">
<div class="about-modal-logo">
<i class="fas fa-cloud"></i>
</div>
<h2>OxiCloud</h2>
<div class="about-version" id="about-version">v...</div>
<div class="about-description" data-i18n="user_menu.about_description">
Cloud storage platform built with Rust &amp; Clean Architecture. Fast, secure, and private.
</div>
<div class="about-tech">
<span class="about-tech-badge">Rust</span>
<span class="about-tech-badge">Axum</span>
<span class="about-tech-badge">PostgreSQL</span>
<span class="about-tech-badge">Clean Architecture</span>
</div>
<div class="about-links">
<a href="https://github.com" class="about-link" target="_blank" rel="noopener">
<i class="fab fa-github"></i> GitHub
</a>
<a href="#" class="about-link" id="about-license-link">
<i class="fas fa-file-alt"></i> MIT License
</a>
</div>
<button class="about-close-btn" id="about-close-btn" data-i18n="actions.close">Close</button>
</div>
</div>
<!-- Upload Progress Toast (hidden – driven by notification bell) -->
<div class="upload-toast" id="upload-toast" style="display:none"></div>
</body>
</html>