|
import app from '../app.js';
|
|
import './login-view.js';
|
|
import './file-list.js';
|
|
import './file-upload-view.js';
|
|
import './share-modal.js';
|
|
import './photo-gallery.js';
|
|
import './file-preview.js';
|
|
import './deleted-files.js';
|
|
import './admin-dashboard.js';
|
|
import './toast-notification.js';
|
|
import './starred-items.js';
|
|
import './recent-files.js';
|
|
import './shared-items.js';
|
|
import './billing-dashboard.js';
|
|
import './admin-billing.js';
|
|
import './code-editor-view.js';
|
|
import './cookie-consent.js';
|
|
import './user-settings.js'; // Import the new user settings component
|
|
import { shortcuts } from '../shortcuts.js';
|
|
|
|
const api = app.getAPI();
|
|
const logger = app.getLogger();
|
|
const appState = app.getState();
|
|
|
|
export class RBoxApp extends HTMLElement {
|
|
constructor() {
|
|
super();
|
|
this.currentView = 'files';
|
|
this.user = null;
|
|
this.navigationStack = [];
|
|
this.boundHandlePopState = this.handlePopState.bind(this);
|
|
this.popstateAttached = false;
|
|
this.currentSearchId = 0;
|
|
}
|
|
|
|
async connectedCallback() {
|
|
try {
|
|
await this.init();
|
|
this.addEventListener('show-toast', this.handleShowToast);
|
|
|
|
if (!this.popstateAttached) {
|
|
window.addEventListener('popstate', this.boundHandlePopState);
|
|
this.popstateAttached = true;
|
|
logger.debug('Popstate listener attached');
|
|
}
|
|
} catch (error) {
|
|
logger.error('Failed to initialize RBoxApp', error);
|
|
this.innerHTML = `
|
|
<div style="padding: 2rem; text-align: center; font-family: sans-serif;">
|
|
<h1 style="color: #d32f2f;">Failed to Load Application</h1>
|
|
<p>${error.message}</p>
|
|
<button onclick="location.reload()" style="padding: 0.75rem 1.5rem; background: #2196F3; color: white; border: none; border-radius: 4px; cursor: pointer; font-size: 1rem;">
|
|
Reload Page
|
|
</button>
|
|
</div>
|
|
`;
|
|
}
|
|
}
|
|
|
|
disconnectedCallback() {
|
|
this.removeEventListener('show-toast', this.handleShowToast);
|
|
if (this.popstateAttached) {
|
|
window.removeEventListener('popstate', this.boundHandlePopState);
|
|
this.popstateAttached = false;
|
|
logger.debug('Popstate listener removed');
|
|
}
|
|
}
|
|
|
|
handleShowToast = (event) => {
|
|
const { message, type, duration } = event.detail;
|
|
this.showToast(message, type, duration);
|
|
}
|
|
|
|
showToast(message, type = 'info', duration = 3000) {
|
|
const toast = document.createElement('toast-notification');
|
|
document.body.appendChild(toast);
|
|
toast.show(message, type, duration);
|
|
}
|
|
|
|
async init() {
|
|
try {
|
|
if (!api.getToken()) {
|
|
logger.info('No token found, showing login');
|
|
this.showLogin();
|
|
} else {
|
|
logger.info('Initializing application with stored token');
|
|
this.user = await api.getCurrentUser();
|
|
appState.setState({ user: this.user });
|
|
logger.info('User loaded successfully', { username: this.user.username });
|
|
this.render();
|
|
}
|
|
} catch (error) {
|
|
logger.error('Failed to initialize application', error);
|
|
api.setToken(null);
|
|
this.showLogin();
|
|
}
|
|
}
|
|
|
|
showLogin() {
|
|
this.innerHTML = `
|
|
<div class="login-container">
|
|
<login-view></login-view>
|
|
</div>
|
|
<footer class="app-footer">
|
|
<nav class="footer-nav">
|
|
<ul class="footer-links">
|
|
<li><a href="/static/legal/privacy_policy.md" target="_blank" rel="noopener noreferrer">Privacy Policy</a></li>
|
|
<li><a href="/static/legal/data_processing_agreement.md" target="_blank" rel="noopener noreferrer">Data Processing Agreement</a></li>
|
|
<li><a href="/static/legal/terms_of_service.md" target="_blank" rel="noopener noreferrer">Terms of Service</a></li>
|
|
<li><a href="/static/legal/cookie_policy.md" target="_blank" rel="noopener noreferrer">Cookie Policy</a></li>
|
|
<li><a href="/static/legal/security_policy.md" target="_blank" rel="noopener noreferrer">Security Policy</a></li>
|
|
<li><a href="/static/legal/compliance_statement.md" target="_blank" rel="noopener noreferrer">Compliance Statement</a></li>
|
|
<li><a href="/static/legal/data_portability_deletion_policy.md" target="_blank" rel="noopener noreferrer">Data Portability & Deletion</a></li>
|
|
<li><a href="/static/legal/contact_complaint_mechanism.md" target="_blank" rel="noopener noreferrer">Contact & Complaints</a></li>
|
|
</ul>
|
|
</nav>
|
|
<p class="footer-text">© ${new Date().getFullYear()} RBox Cloud Storage. All rights reserved.</p>
|
|
</footer>
|
|
<cookie-consent></cookie-consent>
|
|
`;
|
|
const loginView = this.querySelector('login-view');
|
|
loginView.addEventListener('auth-success', () => this.init());
|
|
}
|
|
|
|
render() {
|
|
this.innerHTML = `
|
|
<div class="app-container">
|
|
<header class="app-header">
|
|
<div class="header-left">
|
|
<h1 class="app-title">RBox</h1>
|
|
</div>
|
|
<div class="header-center">
|
|
<input type="search" placeholder="Search..." class="search-input" id="search-input">
|
|
</div>
|
|
<div class="header-right">
|
|
<span class="user-info">${this.user.username}</span>
|
|
<button class="button" id="logout-btn">Logout</button>
|
|
</div>
|
|
</header>
|
|
|
|
<div class="app-body">
|
|
<aside class="app-sidebar">
|
|
<nav class="sidebar-nav">
|
|
<h3 class="nav-title">Navigation</h3>
|
|
<ul class="nav-list">
|
|
<li><a href="#" class="nav-link active" data-view="files">My Files</a></li>
|
|
<li><a href="#" class="nav-link" data-view="photos">Photo Gallery</a></li>
|
|
<li><a href="#" class="nav-link" data-view="shared">Shared Items</a></li>
|
|
<li><a href="#" class="nav-link" data-view="deleted">Deleted Files</a></li>
|
|
<li><a href="#" class="nav-link" data-view="billing">Billing</a></li>
|
|
<li><a href="#" class="nav-link" data-view="user-settings">User Settings</a></li>
|
|
${this.user && this.user.is_superuser ? `<li><a href="#" class="nav-link" data-view="admin">Admin Dashboard</a></li>` : ''}
|
|
${this.user && this.user.is_superuser ? `<li><a href="#" class="nav-link" data-view="admin-billing">Admin Billing</a></li>` : ''}
|
|
</ul>
|
|
<h3 class="nav-title">Quick Access</h3>
|
|
<ul class="nav-list">
|
|
<li><a href="#" class="nav-link" data-view="starred">Starred</a></li>
|
|
<li><a href="#" class="nav-link" data-view="recent">Recent</a></li>
|
|
</ul>
|
|
</nav>
|
|
</aside>
|
|
|
|
<main class="app-main">
|
|
<div id="main-content">
|
|
<file-list></file-list>
|
|
</div>
|
|
</main>
|
|
</div>
|
|
|
|
<share-modal></share-modal>
|
|
|
|
<footer class="app-footer">
|
|
<nav class="footer-nav">
|
|
<ul class="footer-links">
|
|
<li><a href="/static/legal/privacy_policy.md" target="_blank" rel="noopener noreferrer">Privacy Policy</a></li>
|
|
<li><a href="/static/legal/data_processing_agreement.md" target="_blank" rel="noopener noreferrer">Data Processing Agreement</a></li>
|
|
<li><a href="/static/legal/terms_of_service.md" target="_blank" rel="noopener noreferrer">Terms of Service</a></li>
|
|
<li><a href="/static/legal/cookie_policy.md" target="_blank" rel="noopener noreferrer">Cookie Policy</a></li>
|
|
<li><a href="/static/legal/security_policy.md" target="_blank" rel="noopener noreferrer">Security Policy</a></li>
|
|
<li><a href="/static/legal/compliance_statement.md" target="_blank" rel="noopener noreferrer">Compliance Statement</a></li>
|
|
<li><a href="/static/legal/data_portability_deletion_policy.md" target="_blank" rel="noopener noreferrer">Data Portability & Deletion</a></li>
|
|
<li><a href="/static/legal/contact_complaint_mechanism.md" target="_blank" rel="noopener noreferrer">Contact & Complaints</a></li>
|
|
</ul>
|
|
</nav>
|
|
<p class="footer-text">© ${new Date().getFullYear()} RBox Cloud Storage. All rights reserved.</p>
|
|
</footer>
|
|
</div>
|
|
<cookie-consent></cookie-consent>
|
|
`;
|
|
|
|
this.initializeNavigation();
|
|
this.attachListeners();
|
|
this.registerShortcuts();
|
|
}
|
|
|
|
initializeNavigation() {
|
|
if (!window.history.state) {
|
|
const hash = window.location.hash.slice(1);
|
|
if (hash && hash !== '') {
|
|
const view = hash.split('/')[0];
|
|
const validViews = ['files', 'photos', 'shared', 'deleted', 'starred', 'recent', 'admin', 'billing', 'admin-billing'];
|
|
if (validViews.includes(view)) {
|
|
window.history.replaceState({ view: view }, '', `#${hash}`);
|
|
this.currentView = view;
|
|
} else {
|
|
window.history.replaceState({ view: 'files' }, '', '#files');
|
|
}
|
|
} else {
|
|
window.history.replaceState({ view: 'files' }, '', '#files');
|
|
}
|
|
}
|
|
}
|
|
|
|
registerShortcuts() {
|
|
shortcuts.register('ctrl+u', () => {
|
|
const fileList = this.querySelector('file-list');
|
|
const folderId = fileList ? fileList.currentFolderId : null;
|
|
this.showUpload(folderId);
|
|
});
|
|
|
|
shortcuts.register('ctrl+f', () => {
|
|
const searchInput = this.querySelector('#search-input');
|
|
if (searchInput) {
|
|
searchInput.focus();
|
|
}
|
|
});
|
|
|
|
shortcuts.register('ctrl+/', () => {
|
|
this.showShortcutsHelp();
|
|
});
|
|
|
|
shortcuts.register('ctrl+shift+n', () => {
|
|
if (this.currentView === 'files') {
|
|
const fileList = this.querySelector('file-list');
|
|
if (fileList) {
|
|
fileList.triggerCreateFolder();
|
|
}
|
|
}
|
|
});
|
|
|
|
shortcuts.register('1', () => {
|
|
this.switchView('files');
|
|
});
|
|
|
|
shortcuts.register('2', () => {
|
|
this.switchView('photos');
|
|
});
|
|
|
|
shortcuts.register('3', () => {
|
|
this.switchView('shared');
|
|
});
|
|
|
|
shortcuts.register('4', () => {
|
|
this.switchView('deleted');
|
|
});
|
|
|
|
shortcuts.register('5', () => {
|
|
if (this.user && this.user.is_superuser) {
|
|
this.switchView('admin');
|
|
}
|
|
});
|
|
|
|
shortcuts.register('f2', () => {
|
|
const fileListComponent = document.querySelector('file-list');
|
|
if (fileListComponent && fileListComponent.selectedFiles && fileListComponent.selectedFiles.size === 1) {
|
|
const fileId = Array.from(fileListComponent.selectedFiles)[0];
|
|
const file = fileListComponent.files.find(f => f.id === fileId);
|
|
if (file) {
|
|
const newName = prompt('Enter new name:', file.name);
|
|
if (newName && newName !== file.name) {
|
|
api.renameFile(fileId, newName).then(() => {
|
|
fileListComponent.loadContents(fileListComponent.currentFolderId);
|
|
document.dispatchEvent(new CustomEvent('show-toast', {
|
|
detail: { message: 'File renamed successfully', type: 'success' }
|
|
}));
|
|
}).catch(error => {
|
|
document.dispatchEvent(new CustomEvent('show-toast', {
|
|
detail: { message: 'Failed to rename file', type: 'error' }
|
|
}));
|
|
});
|
|
}
|
|
}
|
|
} else if (fileListComponent && fileListComponent.selectedFolders && fileListComponent.selectedFolders.size === 1) {
|
|
const folderId = Array.from(fileListComponent.selectedFolders)[0];
|
|
const folder = fileListComponent.folders.find(f => f.id === folderId);
|
|
if (folder) {
|
|
const newName = prompt('Enter new name:', folder.name);
|
|
if (newName && newName !== folder.name) {
|
|
api.updateFolder(folderId, { name: newName }).then(() => {
|
|
fileListComponent.loadContents(fileListComponent.currentFolderId);
|
|
document.dispatchEvent(new CustomEvent('show-toast', {
|
|
detail: { message: 'Folder renamed successfully', type: 'success' }
|
|
}));
|
|
}).catch(error => {
|
|
document.dispatchEvent(new CustomEvent('show-toast', {
|
|
detail: { message: 'Failed to rename folder', type: 'error' }
|
|
}));
|
|
});
|
|
}
|
|
}
|
|
}
|
|
});
|
|
}
|
|
|
|
showShortcutsHelp() {
|
|
const helpContent = `
|
|
<div class="shortcuts-help-modal">
|
|
<div class="shortcuts-help-content">
|
|
<h2>Keyboard Shortcuts</h2>
|
|
<div class="shortcuts-list">
|
|
<h3>File Operations</h3>
|
|
<div class="shortcut-item">
|
|
<kbd>Ctrl + U</kbd>
|
|
<span>Upload files</span>
|
|
</div>
|
|
<div class="shortcut-item">
|
|
<kbd>Ctrl + Shift + N</kbd>
|
|
<span>Create new folder</span>
|
|
</div>
|
|
<div class="shortcut-item">
|
|
<kbd>Ctrl + F</kbd>
|
|
<span>Focus search</span>
|
|
</div>
|
|
|
|
<h3>Navigation</h3>
|
|
<div class="shortcut-item">
|
|
<kbd>1</kbd>
|
|
<span>My Files</span>
|
|
</div>
|
|
<div class="shortcut-item">
|
|
<kbd>2</kbd>
|
|
<span>Photo Gallery</span>
|
|
</div>
|
|
<div class="shortcut-item">
|
|
<kbd>3</kbd>
|
|
<span>Shared Items</span>
|
|
</div>
|
|
<div class="shortcut-item">
|
|
<kbd>4</kbd>
|
|
<span>Deleted Files</span>
|
|
</div>
|
|
${this.user && this.user.is_superuser ? `
|
|
<div class="shortcut-item">
|
|
<kbd>5</kbd>
|
|
<span>Admin Dashboard</span>
|
|
</div>` : ''}
|
|
|
|
<h3>General</h3>
|
|
<div class="shortcut-item">
|
|
<kbd>ESC</kbd>
|
|
<span>Close modals</span>
|
|
</div>
|
|
<div class="shortcut-item">
|
|
<kbd>Ctrl + /</kbd>
|
|
<span>Show this help</span>
|
|
</div>
|
|
</div>
|
|
<button class="button" id="close-shortcuts-help">Close</button>
|
|
</div>
|
|
</div>
|
|
`;
|
|
|
|
const helpDiv = document.createElement('div');
|
|
helpDiv.innerHTML = helpContent;
|
|
helpDiv.querySelector('.shortcuts-help-modal').style.cssText = `
|
|
position: fixed;
|
|
top: 0;
|
|
left: 0;
|
|
right: 0;
|
|
bottom: 0;
|
|
background: rgba(0,0,0,0.5);
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
z-index: 10000;
|
|
`;
|
|
document.body.appendChild(helpDiv);
|
|
|
|
const closeHelp = () => {
|
|
document.body.removeChild(helpDiv);
|
|
document.removeEventListener('keydown', handleEscape);
|
|
};
|
|
|
|
const handleEscape = (e) => {
|
|
if (e.key === 'Escape') {
|
|
closeHelp();
|
|
}
|
|
};
|
|
|
|
const closeBtn = helpDiv.querySelector('#close-shortcuts-help');
|
|
closeBtn.addEventListener('click', closeHelp);
|
|
helpDiv.querySelector('.shortcuts-help-modal').addEventListener('click', (e) => {
|
|
if (e.target.classList.contains('shortcuts-help-modal')) closeHelp();
|
|
});
|
|
|
|
document.addEventListener('keydown', handleEscape);
|
|
}
|
|
|
|
attachListeners() {
|
|
this.querySelector('#logout-btn')?.addEventListener('click', () => {
|
|
logger.info('User logout initiated', { action: 'USER_LOGOUT' });
|
|
api.logout();
|
|
});
|
|
|
|
this.querySelectorAll('.nav-link').forEach(link => {
|
|
link.addEventListener('click', (e) => {
|
|
e.preventDefault();
|
|
const view = link.dataset.view;
|
|
this.switchView(view);
|
|
});
|
|
});
|
|
|
|
const fileList = this.querySelector('file-list');
|
|
if (fileList) {
|
|
fileList.addEventListener('upload-request', (e) => {
|
|
this.showUpload(e.detail.folderId);
|
|
});
|
|
|
|
fileList.addEventListener('folder-open', (e) => {
|
|
fileList.loadContents(e.detail.folderId);
|
|
});
|
|
|
|
fileList.addEventListener('share-request', (e) => {
|
|
const modal = this.querySelector('share-modal');
|
|
modal.show(e.detail.fileId);
|
|
});
|
|
}
|
|
|
|
this.addEventListener('upload-complete', () => {
|
|
const fileList = this.querySelector('file-list');
|
|
if (fileList) {
|
|
fileList.loadContents(fileList.currentFolderId);
|
|
}
|
|
});
|
|
|
|
const searchInput = this.querySelector('#search-input');
|
|
if (searchInput) {
|
|
let searchTimeout;
|
|
searchInput.addEventListener('input', (e) => {
|
|
clearTimeout(searchTimeout);
|
|
const query = e.target.value.trim();
|
|
if (query.length > 0) {
|
|
searchTimeout = setTimeout(() => this.performSearch(query), 300);
|
|
}
|
|
});
|
|
}
|
|
|
|
this.addEventListener('photo-click', (e) => {
|
|
this.showFilePreview(e.detail.photo);
|
|
});
|
|
|
|
this.addEventListener('share-file', (e) => {
|
|
const modal = this.querySelector('share-modal');
|
|
modal.show(e.detail.file.id);
|
|
});
|
|
|
|
this.addEventListener('edit-file', (e) => {
|
|
this.showCodeEditor(e.detail.file);
|
|
});
|
|
}
|
|
|
|
handlePopState(e) {
|
|
logger.debug('Popstate event', { state: e.state, url: window.location.href });
|
|
|
|
this.closeAllOverlays();
|
|
|
|
if (e.state && e.state.view) {
|
|
const view = e.state.view;
|
|
|
|
if (view === 'code-editor' && e.state.file) {
|
|
logger.debug('Restoring code editor view');
|
|
this.showCodeEditor(e.state.file, false);
|
|
} else if (view === 'file-preview' && e.state.file) {
|
|
logger.debug('Restoring file preview view');
|
|
this.showFilePreview(e.state.file, false);
|
|
} else if (view === 'upload') {
|
|
logger.debug('Restoring upload view');
|
|
const folderId = e.state.folderId !== undefined ? e.state.folderId : null;
|
|
this.showUpload(folderId, false);
|
|
} else {
|
|
logger.debug('Switching to view', { view });
|
|
this.switchView(view, false);
|
|
}
|
|
} else {
|
|
logger.debug('No state, defaulting to files view');
|
|
this.switchView('files', false);
|
|
}
|
|
}
|
|
|
|
closeAllOverlays() {
|
|
logger.debug('Closing all overlays');
|
|
|
|
const existingEditor = this.querySelector('code-editor-view');
|
|
if (existingEditor) {
|
|
logger.debug('Hiding code editor');
|
|
existingEditor.hide();
|
|
}
|
|
|
|
const existingPreview = this.querySelector('file-preview');
|
|
if (existingPreview) {
|
|
logger.debug('Hiding file preview');
|
|
existingPreview.hide();
|
|
}
|
|
|
|
const existingUpload = this.querySelector('file-upload-view');
|
|
if (existingUpload) {
|
|
logger.debug('Hiding file upload');
|
|
existingUpload.hide();
|
|
}
|
|
|
|
const shareModal = this.querySelector('share-modal');
|
|
if (shareModal && shareModal.style.display !== 'none') {
|
|
logger.debug('Hiding share modal');
|
|
shareModal.style.display = 'none';
|
|
}
|
|
}
|
|
|
|
showCodeEditor(file, pushState = true) {
|
|
logger.debug('Showing code editor', { file: file.name, pushState });
|
|
this.closeAllOverlays();
|
|
|
|
const mainElement = this.querySelector('.app-main');
|
|
const editorView = document.createElement('code-editor-view');
|
|
mainElement.appendChild(editorView);
|
|
editorView.setFile(file, this.currentView);
|
|
|
|
if (pushState) {
|
|
const currentState = window.history.state || {};
|
|
const currentView = currentState.view || this.currentView;
|
|
|
|
if (currentView !== 'code-editor') {
|
|
window.history.pushState(
|
|
{ view: 'code-editor', file: file, previousView: currentView },
|
|
'',
|
|
`#editor/${file.id}`
|
|
);
|
|
logger.debug('Pushed code editor state', { previousView: currentView });
|
|
} else {
|
|
logger.debug('Already in code editor view, replacing state');
|
|
window.history.replaceState(
|
|
{ view: 'code-editor', file: file, previousView: currentView },
|
|
'',
|
|
`#editor/${file.id}`
|
|
);
|
|
}
|
|
}
|
|
}
|
|
|
|
showFilePreview(file, pushState = true) {
|
|
logger.debug('Showing file preview', { file: file.name, pushState });
|
|
this.closeAllOverlays();
|
|
|
|
const mainElement = this.querySelector('.app-main');
|
|
const preview = document.createElement('file-preview');
|
|
mainElement.appendChild(preview);
|
|
preview.show(file, false);
|
|
|
|
if (pushState) {
|
|
const currentState = window.history.state || {};
|
|
const currentView = currentState.view || this.currentView;
|
|
|
|
if (currentView !== 'file-preview') {
|
|
window.history.pushState(
|
|
{ view: 'file-preview', file: file, previousView: currentView },
|
|
'',
|
|
`#preview/${file.id}`
|
|
);
|
|
logger.debug('Pushed file preview state', { previousView: currentView });
|
|
} else {
|
|
logger.debug('Already in file preview view, replacing state');
|
|
window.history.replaceState(
|
|
{ view: 'file-preview', file: file, previousView: currentView },
|
|
'',
|
|
`#preview/${file.id}`
|
|
);
|
|
}
|
|
}
|
|
}
|
|
|
|
showUpload(folderId = null, pushState = true) {
|
|
logger.debug('Showing upload view', { folderId, pushState });
|
|
this.closeAllOverlays();
|
|
|
|
const mainElement = this.querySelector('.app-main');
|
|
const uploadView = document.createElement('file-upload-view');
|
|
mainElement.appendChild(uploadView);
|
|
uploadView.setFolder(folderId);
|
|
|
|
if (pushState) {
|
|
const currentState = window.history.state || {};
|
|
const currentView = currentState.view || this.currentView;
|
|
|
|
if (currentView !== 'upload') {
|
|
window.history.pushState(
|
|
{ view: 'upload', folderId: folderId, previousView: currentView },
|
|
'',
|
|
'#upload'
|
|
);
|
|
logger.debug('Pushed upload state', { previousView: currentView });
|
|
} else {
|
|
logger.debug('Already in upload view, replacing state');
|
|
window.history.replaceState(
|
|
{ view: 'upload', folderId: folderId, previousView: currentView },
|
|
'',
|
|
'#upload'
|
|
);
|
|
}
|
|
}
|
|
}
|
|
|
|
async performSearch(query) {
|
|
const searchId = ++this.currentSearchId;
|
|
try {
|
|
const files = await api.searchFiles(query);
|
|
if (searchId !== this.currentSearchId) return;
|
|
const mainContent = this.querySelector('#main-content');
|
|
mainContent.innerHTML = `
|
|
<div class="search-results">
|
|
<h2>Search Results for "${query}"</h2>
|
|
<file-list data-search-mode="true"></file-list>
|
|
</div>
|
|
`;
|
|
const fileList = mainContent.querySelector('file-list');
|
|
fileList.setFiles(files);
|
|
this.attachListeners();
|
|
} catch (error) {
|
|
if (searchId === this.currentSearchId) {
|
|
console.error('Search failed:', error);
|
|
}
|
|
}
|
|
}
|
|
|
|
switchView(view, pushState = true) {
|
|
this.closeAllOverlays();
|
|
|
|
if(this.currentView === view) return;
|
|
this.currentView = view;
|
|
|
|
this.querySelectorAll('.nav-link').forEach(link => {
|
|
link.classList.remove('active');
|
|
});
|
|
this.querySelector(`[data-view="${view}"]`)?.classList.add('active');
|
|
|
|
const mainContent = this.querySelector('#main-content');
|
|
|
|
if (pushState) {
|
|
window.history.pushState({ view: view }, '', `#${view}`);
|
|
}
|
|
|
|
switch (view) {
|
|
case 'files':
|
|
mainContent.innerHTML = '<file-list></file-list>';
|
|
this.attachListeners();
|
|
break;
|
|
case 'photos':
|
|
mainContent.innerHTML = '<photo-gallery></photo-gallery>';
|
|
this.attachListeners();
|
|
break;
|
|
case 'shared':
|
|
mainContent.innerHTML = '<shared-items></shared-items>';
|
|
this.attachListeners();
|
|
break;
|
|
case 'deleted':
|
|
mainContent.innerHTML = '<deleted-files></deleted-files>';
|
|
this.attachListeners();
|
|
break;
|
|
case 'starred':
|
|
mainContent.innerHTML = '<starred-items></starred-items>';
|
|
this.attachListeners();
|
|
break;
|
|
case 'recent':
|
|
mainContent.innerHTML = '<recent-files></recent-files>';
|
|
this.attachListeners();
|
|
break;
|
|
case 'admin':
|
|
mainContent.innerHTML = '<admin-dashboard></admin-dashboard>';
|
|
this.attachListeners();
|
|
break;
|
|
case 'billing':
|
|
mainContent.innerHTML = '<billing-dashboard></billing-dashboard>';
|
|
this.attachListeners();
|
|
break;
|
|
case 'user-settings':
|
|
mainContent.innerHTML = '<user-settings></user-settings>';
|
|
this.attachListeners();
|
|
break;
|
|
case 'admin-billing':
|
|
mainContent.innerHTML = '<admin-billing></admin-billing>';
|
|
this.attachListeners();
|
|
break;
|
|
}
|
|
}
|
|
}
|