285 lines
9.1 KiB
JavaScript
285 lines
9.1 KiB
JavaScript
/**
|
|
* OxiCloud - Main Application
|
|
* This file contains the core functionality, initialization and state management
|
|
*/
|
|
|
|
// Global state
|
|
const app = {
|
|
currentView: 'grid', // Current view mode: 'grid' or 'list'
|
|
currentPath: '', // Current folder path
|
|
currentFolder: null, // Current folder object
|
|
contextMenuTargetFolder: null, // Target folder for context menu
|
|
contextMenuTargetFile: null, // Target file for context menu
|
|
selectedTargetFolderId: "", // Selected target folder for move operations
|
|
moveDialogMode: 'file', // Move dialog mode: 'file' or 'folder'
|
|
};
|
|
|
|
// DOM elements
|
|
const elements = {
|
|
// Will be populated on initialization
|
|
};
|
|
|
|
/**
|
|
* Initialize the application
|
|
*/
|
|
function initApp() {
|
|
// Cache DOM elements
|
|
cacheElements();
|
|
|
|
// Create menus and dialogs
|
|
ui.initializeContextMenus();
|
|
|
|
// Setup event listeners
|
|
setupEventListeners();
|
|
|
|
// Load initial view
|
|
app.currentPath = '';
|
|
ui.updateBreadcrumb('');
|
|
loadFiles();
|
|
|
|
// Initialize file renderer if available
|
|
if (window.fileRenderer) {
|
|
console.log('Using optimized file renderer');
|
|
} else {
|
|
console.log('Using standard file rendering');
|
|
}
|
|
|
|
// Check authentication
|
|
checkAuthentication();
|
|
}
|
|
|
|
/**
|
|
* Cache DOM elements for faster access
|
|
*/
|
|
function cacheElements() {
|
|
elements.uploadBtn = document.getElementById('upload-btn');
|
|
elements.dropzone = document.getElementById('dropzone');
|
|
elements.fileInput = document.getElementById('file-input');
|
|
elements.filesGrid = document.getElementById('files-grid');
|
|
elements.filesListView = document.getElementById('files-list-view');
|
|
elements.newFolderBtn = document.getElementById('new-folder-btn');
|
|
elements.gridViewBtn = document.getElementById('grid-view-btn');
|
|
elements.listViewBtn = document.getElementById('list-view-btn');
|
|
elements.breadcrumb = document.querySelector('.breadcrumb');
|
|
elements.logoutBtn = document.getElementById('logout-btn');
|
|
}
|
|
|
|
/**
|
|
* Setup event listeners for main UI elements
|
|
*/
|
|
function setupEventListeners() {
|
|
// Set up drag and drop
|
|
ui.setupDragAndDrop();
|
|
|
|
// Upload button
|
|
elements.uploadBtn.addEventListener('click', () => {
|
|
elements.dropzone.style.display = elements.dropzone.style.display === 'none' ? 'block' : 'none';
|
|
if (elements.dropzone.style.display === 'block') {
|
|
elements.fileInput.click();
|
|
}
|
|
});
|
|
|
|
// File input
|
|
elements.fileInput.addEventListener('change', (e) => {
|
|
if (e.target.files.length > 0) {
|
|
fileOps.uploadFiles(e.target.files);
|
|
}
|
|
});
|
|
|
|
// New folder button
|
|
elements.newFolderBtn.addEventListener('click', () => {
|
|
const folderName = prompt(window.i18n ? window.i18n.t('dialogs.new_name') : 'Nombre de la carpeta:');
|
|
if (folderName) {
|
|
fileOps.createFolder(folderName);
|
|
}
|
|
});
|
|
|
|
// View toggle
|
|
elements.gridViewBtn.addEventListener('click', ui.switchToGridView);
|
|
elements.listViewBtn.addEventListener('click', ui.switchToListView);
|
|
|
|
// Load saved view preference
|
|
const savedView = localStorage.getItem('oxicloud-view');
|
|
if (savedView === 'list') {
|
|
ui.switchToListView();
|
|
}
|
|
|
|
// Logout button
|
|
elements.logoutBtn.addEventListener('click', logout);
|
|
|
|
// Global events to close context menus
|
|
document.addEventListener('click', (e) => {
|
|
const folderMenu = document.getElementById('folder-context-menu');
|
|
const fileMenu = document.getElementById('file-context-menu');
|
|
|
|
if (folderMenu && folderMenu.style.display === 'block' &&
|
|
!folderMenu.contains(e.target)) {
|
|
ui.closeContextMenu();
|
|
}
|
|
|
|
if (fileMenu && fileMenu.style.display === 'block' &&
|
|
!fileMenu.contains(e.target)) {
|
|
ui.closeFileContextMenu();
|
|
}
|
|
});
|
|
}
|
|
|
|
/**
|
|
* Load files and folders for the current path
|
|
*/
|
|
async function loadFiles() {
|
|
try {
|
|
let url = '/api/folders';
|
|
if (app.currentPath) {
|
|
// Use the correct endpoint for folder contents
|
|
url = `/api/folders/${app.currentPath}/contents`;
|
|
}
|
|
|
|
const response = await fetch(url);
|
|
if (!response.ok) {
|
|
throw new Error(`Server responded with status: ${response.status}`);
|
|
}
|
|
const folders = await response.json();
|
|
|
|
// Clear existing files in both views
|
|
elements.filesGrid.innerHTML = '';
|
|
elements.filesListView.innerHTML = `
|
|
<div class="list-header">
|
|
<div data-i18n="files.name">Nombre</div>
|
|
<div data-i18n="files.type">Tipo</div>
|
|
<div data-i18n="files.size">Tamaño</div>
|
|
<div data-i18n="files.modified">Modificado</div>
|
|
</div>
|
|
`;
|
|
|
|
// Translate the header if i18n is available
|
|
if (window.i18n && window.i18n.translatePage) {
|
|
window.i18n.translatePage();
|
|
}
|
|
|
|
// Add folders (check if it's an array)
|
|
const folderList = Array.isArray(folders) ? folders : [];
|
|
folderList.forEach(folder => {
|
|
ui.addFolderToView(folder);
|
|
});
|
|
|
|
// Also load files in this folder
|
|
let filesUrl = '/api/files';
|
|
if (app.currentPath) {
|
|
filesUrl += `?folder_id=${app.currentPath}`;
|
|
}
|
|
|
|
try {
|
|
console.log(`Fetching files from: ${filesUrl}`);
|
|
const filesResponse = await fetch(filesUrl);
|
|
console.log(`Files response status: ${filesResponse.status}`);
|
|
|
|
if (filesResponse.ok) {
|
|
const files = await filesResponse.json();
|
|
console.log(`Files received:`, files);
|
|
|
|
// Add files (check if it's an array)
|
|
const fileList = Array.isArray(files) ? files : [];
|
|
console.log(`Processing ${fileList.length} files`);
|
|
|
|
fileList.forEach(file => {
|
|
console.log(`Adding file to view: ${file.name} (${file.id})`);
|
|
ui.addFileToView(file);
|
|
});
|
|
} else {
|
|
const errorText = await filesResponse.text();
|
|
console.error(`Error loading files: ${filesResponse.status} - ${errorText}`);
|
|
}
|
|
} catch (error) {
|
|
console.error('Error loading files:', error);
|
|
// File API may not be implemented yet, so we silently ignore this error
|
|
}
|
|
|
|
// Update file icons based on file type
|
|
ui.updateFileIcons();
|
|
} catch (error) {
|
|
console.error('Error loading folders:', error);
|
|
ui.showNotification('Error', 'Could not load files and folders');
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Format file size in human-readable format
|
|
* @param {number} bytes - Size in bytes
|
|
* @return {string} Formatted size
|
|
*/
|
|
function formatFileSize(bytes) {
|
|
if (bytes === 0) return '0 Bytes';
|
|
|
|
const k = 1024;
|
|
const sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB'];
|
|
const i = Math.floor(Math.log(bytes) / Math.log(k));
|
|
|
|
return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i];
|
|
}
|
|
|
|
// Expose needed functions to global scope
|
|
window.app = app;
|
|
window.loadFiles = loadFiles;
|
|
window.formatFileSize = formatFileSize;
|
|
|
|
// Set up global selectFolder function for navigation
|
|
window.selectFolder = (id, name) => {
|
|
app.currentPath = id;
|
|
ui.updateBreadcrumb(name);
|
|
loadFiles();
|
|
};
|
|
|
|
/**
|
|
* Check if user is authenticated
|
|
*/
|
|
function checkAuthentication() {
|
|
// Nombres de variables según auth.js
|
|
const TOKEN_KEY = 'oxicloud_token';
|
|
const TOKEN_EXPIRY_KEY = 'oxicloud_token_expiry';
|
|
const USER_DATA_KEY = 'oxicloud_user';
|
|
|
|
const token = localStorage.getItem(TOKEN_KEY);
|
|
const tokenExpiry = localStorage.getItem(TOKEN_EXPIRY_KEY);
|
|
|
|
if (!token || !tokenExpiry || new Date(tokenExpiry) < new Date()) {
|
|
// No token or expired token
|
|
window.location.href = '/login';
|
|
return;
|
|
}
|
|
|
|
// Display user information if available
|
|
const userData = JSON.parse(localStorage.getItem(USER_DATA_KEY) || '{}');
|
|
if (userData.username) {
|
|
// Update user avatar with initials
|
|
const userInitials = userData.username.substring(0, 2).toUpperCase();
|
|
const userAvatar = document.querySelector('.user-avatar');
|
|
if (userAvatar) {
|
|
userAvatar.textContent = userInitials;
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Logout - clear all auth data and redirect to login
|
|
*/
|
|
function logout() {
|
|
// Nombres de variables según auth.js
|
|
const TOKEN_KEY = 'oxicloud_token';
|
|
const REFRESH_TOKEN_KEY = 'oxicloud_refresh_token';
|
|
const TOKEN_EXPIRY_KEY = 'oxicloud_token_expiry';
|
|
const USER_DATA_KEY = 'oxicloud_user';
|
|
|
|
// Clear all authentication data
|
|
localStorage.removeItem(TOKEN_KEY);
|
|
localStorage.removeItem(REFRESH_TOKEN_KEY);
|
|
localStorage.removeItem(TOKEN_EXPIRY_KEY);
|
|
localStorage.removeItem(USER_DATA_KEY);
|
|
|
|
// Redirect to login page
|
|
window.location.href = '/login';
|
|
}
|
|
|
|
// Initialize app when DOM is ready
|
|
document.addEventListener('DOMContentLoaded', initApp);
|