adding recent feature + bug fixed
This commit is contained in:
@@ -0,0 +1,78 @@
|
||||
/* Estilos para la funcionalidad de archivos recientes */
|
||||
|
||||
/* Indicador de reciente */
|
||||
.recent-indicator {
|
||||
position: absolute;
|
||||
top: 10px;
|
||||
right: 10px;
|
||||
width: 25px;
|
||||
height: 25px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
border-radius: 50%;
|
||||
color: #6c757d;
|
||||
z-index: 5;
|
||||
}
|
||||
|
||||
/* Estilos para los elementos de la vista de recientes */
|
||||
.recent-item {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
/* Ajustes para la vista de cuadrícula */
|
||||
.file-card.recent-item {
|
||||
border-left: 3px solid #6c757d;
|
||||
}
|
||||
|
||||
/* Ajustes para la vista de lista */
|
||||
.file-item.recent-item {
|
||||
position: relative;
|
||||
grid-template-columns: 30px minmax(200px, 2fr) 1fr 1fr 120px;
|
||||
}
|
||||
|
||||
.file-item.recent-item .recent-indicator {
|
||||
position: relative;
|
||||
top: 0;
|
||||
right: 0;
|
||||
width: 30px;
|
||||
height: 30px;
|
||||
}
|
||||
|
||||
/* Estilos para el estado vacío específico de recientes */
|
||||
.recents-empty-state {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding: 50px 20px;
|
||||
text-align: center;
|
||||
color: #6c757d;
|
||||
}
|
||||
|
||||
.recents-empty-state i {
|
||||
font-size: 48px;
|
||||
color: #6c757d;
|
||||
margin-bottom: 20px;
|
||||
opacity: 0.6;
|
||||
}
|
||||
|
||||
.recents-empty-state p {
|
||||
margin-bottom: 10px;
|
||||
max-width: 400px;
|
||||
}
|
||||
|
||||
/* Tooltip para tiempo de acceso */
|
||||
.recent-item .file-info {
|
||||
cursor: help;
|
||||
}
|
||||
|
||||
/* Animación para archivos recientes */
|
||||
.recent-item {
|
||||
animation: recent-fade-in 0.3s ease;
|
||||
}
|
||||
|
||||
@keyframes recent-fade-in {
|
||||
from { opacity: 0; transform: translateY(10px); }
|
||||
to { opacity: 1; transform: translateY(0); }
|
||||
}
|
||||
@@ -8,7 +8,9 @@
|
||||
<!-- Styles -->
|
||||
<link rel="stylesheet" href="/css/style.css">
|
||||
<link rel="stylesheet" href="/css/inlineViewer.css">
|
||||
<link rel="stylesheet" href="/css/fileViewer.css">
|
||||
<link rel="stylesheet" href="/css/favorites.css">
|
||||
<link rel="stylesheet" href="/css/recent.css">
|
||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0-beta3/css/all.min.css">
|
||||
<link rel="preconnect" href="https://cdnjs.cloudflare.com" crossorigin>
|
||||
|
||||
@@ -16,12 +18,14 @@
|
||||
<script src="/js/i18n.js"></script>
|
||||
<script src="/js/languageSelector.js"></script>
|
||||
<script src="/js/inlineViewer.js"></script>
|
||||
<script src="/js/fileViewer.js"></script>
|
||||
<script src="/js/fileRenderer.js"></script>
|
||||
<script src="/js/fileSharing.js"></script>
|
||||
<script src="/js/contextMenus.js"></script>
|
||||
<script src="/js/fileOperations.js"></script>
|
||||
<script src="/js/search.js"></script>
|
||||
<script src="/js/favorites.js"></script>
|
||||
<script src="/js/recent.js"></script>
|
||||
<script src="/js/ui.js"></script>
|
||||
<script src="/js/components/sharedView.js"></script>
|
||||
<script src="/js/app.js"></script>
|
||||
|
||||
+119
-1
@@ -15,7 +15,8 @@ const app = {
|
||||
isTrashView: false, // Whether we're in trash view
|
||||
isSharedView: false, // Whether we're in shared view
|
||||
isFavoritesView: false, // Whether we're in favorites view
|
||||
currentSection: 'files', // Current section: 'files', 'trash', 'shared' or 'favorites'
|
||||
isRecentView: false, // Whether we're in recent files view
|
||||
currentSection: 'files', // Current section: 'files', 'trash', 'shared', 'favorites' or 'recent'
|
||||
isSearchMode: false, // Whether we're in search mode
|
||||
// File sharing related properties
|
||||
shareDialogItem: null, // Item being shared in share dialog
|
||||
@@ -82,6 +83,14 @@ function initApp() {
|
||||
console.warn('Favorites module not available or not initializable');
|
||||
}
|
||||
|
||||
// Initialize recent files module if available
|
||||
if (window.recent && window.recent.init) {
|
||||
console.log('Initializing recent files module');
|
||||
window.recent.init();
|
||||
} else {
|
||||
console.warn('Recent files module not available or not initializable');
|
||||
}
|
||||
|
||||
// Wait for translations to load before checking authentication
|
||||
if (window.i18n && window.i18n.isLoaded && window.i18n.isLoaded()) {
|
||||
// Translations already loaded, proceed with authentication
|
||||
@@ -206,6 +215,13 @@ function setupEventListeners() {
|
||||
return;
|
||||
}
|
||||
|
||||
// Check if this is the recent files item
|
||||
if (item.querySelector('span').getAttribute('data-i18n') === 'nav.recent') {
|
||||
// Switch to recent files view
|
||||
switchToRecentFilesView();
|
||||
return;
|
||||
}
|
||||
|
||||
// Check if this is the trash item
|
||||
if (item === elements.trashBtn) {
|
||||
// Hide shared view if active
|
||||
@@ -760,6 +776,7 @@ function switchToFilesView() {
|
||||
app.isTrashView = false;
|
||||
app.isSharedView = false;
|
||||
app.isFavoritesView = false;
|
||||
app.isRecentView = false;
|
||||
app.currentSection = 'files';
|
||||
|
||||
// Update UI
|
||||
@@ -929,10 +946,111 @@ function switchToFavoritesView() {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Switch to the recent files view
|
||||
*/
|
||||
function switchToRecentFilesView() {
|
||||
// Hide other views
|
||||
app.isTrashView = false;
|
||||
app.isSharedView = false;
|
||||
app.isFavoritesView = false;
|
||||
|
||||
// Set recent view as active
|
||||
app.isRecentView = true;
|
||||
app.currentSection = 'recent';
|
||||
|
||||
// Remove active class from all nav items
|
||||
elements.navItems.forEach(navItem => navItem.classList.remove('active'));
|
||||
|
||||
// Find recent nav item and make it active
|
||||
const recentNavItem = document.querySelector('.nav-item:nth-child(3)');
|
||||
if (recentNavItem) {
|
||||
recentNavItem.classList.add('active');
|
||||
}
|
||||
|
||||
// Update UI
|
||||
elements.pageTitle.textContent = window.i18n ? window.i18n.t('nav.recent') : 'Recientes';
|
||||
|
||||
// Clear breadcrumb and show root
|
||||
ui.updateBreadcrumb(window.i18n ? window.i18n.t('nav.recent') : 'Recientes');
|
||||
|
||||
// Hide shared view if it exists
|
||||
if (window.sharedView) {
|
||||
window.sharedView.hide();
|
||||
}
|
||||
|
||||
// Configure actions bar for recent view
|
||||
elements.actionsBar.innerHTML = `
|
||||
<div class="action-buttons">
|
||||
<button class="btn btn-secondary" id="clear-recent-btn">
|
||||
<i class="fas fa-broom" style="margin-right: 5px;"></i> <span data-i18n="actions.clear_recent">Limpiar recientes</span>
|
||||
</button>
|
||||
</div>
|
||||
<div class="view-toggle">
|
||||
<button class="toggle-btn active" id="grid-view-btn" title="Vista de cuadrícula">
|
||||
<i class="fas fa-th"></i>
|
||||
</button>
|
||||
<button class="toggle-btn" id="list-view-btn" title="Vista de lista">
|
||||
<i class="fas fa-list"></i>
|
||||
</button>
|
||||
</div>
|
||||
`;
|
||||
elements.actionsBar.style.display = 'flex';
|
||||
|
||||
// Add event listener for clear button
|
||||
document.getElementById('clear-recent-btn').addEventListener('click', () => {
|
||||
if (window.recent) {
|
||||
window.recent.clearRecentFiles();
|
||||
window.recent.displayRecentFiles();
|
||||
window.ui.showNotification('Limpieza completada', 'Se ha limpiado el historial de archivos recientes');
|
||||
}
|
||||
});
|
||||
|
||||
// Restore view toggle event listeners
|
||||
document.getElementById('grid-view-btn').addEventListener('click', ui.switchToGridView);
|
||||
document.getElementById('list-view-btn').addEventListener('click', ui.switchToListView);
|
||||
|
||||
// Update cached elements
|
||||
elements.gridViewBtn = document.getElementById('grid-view-btn');
|
||||
elements.listViewBtn = document.getElementById('list-view-btn');
|
||||
|
||||
// Show standard files containers
|
||||
const filesGrid = document.getElementById('files-grid');
|
||||
const filesListView = document.getElementById('files-list-view');
|
||||
|
||||
if (filesGrid) {
|
||||
filesGrid.style.display = app.currentView === 'grid' ? 'grid' : 'none';
|
||||
}
|
||||
|
||||
if (filesListView) {
|
||||
filesListView.style.display = app.currentView === 'list' ? 'block' : 'none';
|
||||
}
|
||||
|
||||
// Check if recent files module is initialized
|
||||
if (window.recent) {
|
||||
// Display recent files
|
||||
window.recent.displayRecentFiles();
|
||||
} else {
|
||||
console.error('Recent files module not loaded or initialized');
|
||||
|
||||
// Show error in UI
|
||||
const filesGrid = document.getElementById('files-grid');
|
||||
if (filesGrid) {
|
||||
filesGrid.innerHTML = `
|
||||
<div class="empty-state">
|
||||
<i class="fas fa-exclamation-circle" style="font-size: 48px; color: #f44336; margin-bottom: 16px;"></i>
|
||||
<p>Error al cargar el módulo de archivos recientes</p>
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Expose view switching functions globally
|
||||
window.switchToFilesView = switchToFilesView;
|
||||
window.switchToSharedView = switchToSharedView;
|
||||
window.switchToFavoritesView = switchToFavoritesView;
|
||||
window.switchToRecentFilesView = switchToRecentFilesView;
|
||||
|
||||
/**
|
||||
* Check if user is authenticated and load user's home folder
|
||||
|
||||
@@ -79,6 +79,47 @@ const contextMenus = {
|
||||
});
|
||||
|
||||
// File context menu options
|
||||
document.getElementById('view-file-option').addEventListener('click', () => {
|
||||
if (window.app.contextMenuTargetFile) {
|
||||
// Fetch file details to get the mime type
|
||||
fetch(`/api/files/${window.app.contextMenuTargetFile.id}?metadata=true`)
|
||||
.then(response => response.json())
|
||||
.then(fileDetails => {
|
||||
// Check if viewable file type
|
||||
if ((fileDetails.mime_type && fileDetails.mime_type.startsWith('image/')) ||
|
||||
(fileDetails.mime_type && fileDetails.mime_type === 'application/pdf')) {
|
||||
// Open with inline viewer
|
||||
if (window.inlineViewer) {
|
||||
window.inlineViewer.openFile(fileDetails);
|
||||
} else if (window.fileViewer) {
|
||||
window.fileViewer.open(fileDetails);
|
||||
} else {
|
||||
// If no viewer is available, download directly
|
||||
window.fileOps.downloadFile(
|
||||
window.app.contextMenuTargetFile.id,
|
||||
window.app.contextMenuTargetFile.name
|
||||
);
|
||||
}
|
||||
} else {
|
||||
// For non-viewable files, download
|
||||
window.fileOps.downloadFile(
|
||||
window.app.contextMenuTargetFile.id,
|
||||
window.app.contextMenuTargetFile.name
|
||||
);
|
||||
}
|
||||
})
|
||||
.catch(error => {
|
||||
console.error('Error fetching file details:', error);
|
||||
// On error, fallback to download
|
||||
window.fileOps.downloadFile(
|
||||
window.app.contextMenuTargetFile.id,
|
||||
window.app.contextMenuTargetFile.name
|
||||
);
|
||||
});
|
||||
}
|
||||
window.ui.closeFileContextMenu();
|
||||
});
|
||||
|
||||
document.getElementById('download-file-option').addEventListener('click', () => {
|
||||
if (window.app.contextMenuTargetFile) {
|
||||
window.fileOps.downloadFile(
|
||||
|
||||
@@ -246,7 +246,7 @@ class InlineViewer {
|
||||
|
||||
this.showErrorMessage(container);
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
// Helper to show error message
|
||||
showErrorMessage(container) {
|
||||
@@ -256,7 +256,7 @@ class InlineViewer {
|
||||
message.innerHTML = `
|
||||
<div class="inline-viewer-icon"><i class="fas fa-exclamation-triangle"></i></div>
|
||||
<div class="inline-viewer-text">
|
||||
<p>Error al cargar el archivo.</p>`
|
||||
<p>Error al cargar el archivo.</p>
|
||||
<p>Intenta descargarlo directamente.</p>
|
||||
</div>
|
||||
`;
|
||||
|
||||
@@ -0,0 +1,291 @@
|
||||
/**
|
||||
* OxiCloud - Recent Files Module
|
||||
* This file handles tracking and displaying recently accessed files
|
||||
*/
|
||||
|
||||
// Recent Files Module
|
||||
const recent = {
|
||||
// Key for storing recent files in localStorage
|
||||
STORAGE_KEY: 'oxicloud_recent_files',
|
||||
|
||||
// Maximum number of recent files to store
|
||||
MAX_RECENT_FILES: 20,
|
||||
|
||||
/**
|
||||
* Initialize recent files module
|
||||
*/
|
||||
init() {
|
||||
console.log('Initializing recent files module');
|
||||
this.ensureRecentFilesStorage();
|
||||
this.setupEventListeners();
|
||||
},
|
||||
|
||||
/**
|
||||
* Make sure the recent files storage is initialized
|
||||
*/
|
||||
ensureRecentFilesStorage() {
|
||||
if (!localStorage.getItem(this.STORAGE_KEY)) {
|
||||
localStorage.setItem(this.STORAGE_KEY, JSON.stringify([]));
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Set up event listeners to track file access
|
||||
*/
|
||||
setupEventListeners() {
|
||||
// Listen for custom event when a file is accessed
|
||||
document.addEventListener('file-accessed', (event) => {
|
||||
if (event.detail && event.detail.file) {
|
||||
this.addRecentFile(event.detail.file);
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* Add a file to recent files
|
||||
* @param {Object} file - File object containing id, name, folder_id, etc.
|
||||
*/
|
||||
addRecentFile(file) {
|
||||
// Don't add if no file or no ID
|
||||
if (!file || !file.id) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Get current recent files
|
||||
const recentFiles = this.getRecentFiles();
|
||||
|
||||
// Remove if file already exists in recent files
|
||||
const existingIndex = recentFiles.findIndex(item => item.id === file.id);
|
||||
if (existingIndex !== -1) {
|
||||
recentFiles.splice(existingIndex, 1);
|
||||
}
|
||||
|
||||
// Add file with timestamp to the beginning of the array
|
||||
const fileWithTimestamp = {
|
||||
...file,
|
||||
accessedAt: Date.now()
|
||||
};
|
||||
|
||||
recentFiles.unshift(fileWithTimestamp);
|
||||
|
||||
// Keep only the most recent files (limit to MAX_RECENT_FILES)
|
||||
const trimmedFiles = recentFiles.slice(0, this.MAX_RECENT_FILES);
|
||||
|
||||
// Save back to localStorage
|
||||
localStorage.setItem(this.STORAGE_KEY, JSON.stringify(trimmedFiles));
|
||||
},
|
||||
|
||||
/**
|
||||
* Get recent files from localStorage
|
||||
* @returns {Array} Array of recent file objects with timestamps
|
||||
*/
|
||||
getRecentFiles() {
|
||||
try {
|
||||
const recentFilesJson = localStorage.getItem(this.STORAGE_KEY);
|
||||
return recentFilesJson ? JSON.parse(recentFilesJson) : [];
|
||||
} catch (error) {
|
||||
console.error('Error loading recent files:', error);
|
||||
return [];
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Clear all recent files
|
||||
*/
|
||||
clearRecentFiles() {
|
||||
localStorage.setItem(this.STORAGE_KEY, JSON.stringify([]));
|
||||
},
|
||||
|
||||
/**
|
||||
* Display recent files in the UI
|
||||
*/
|
||||
async displayRecentFiles() {
|
||||
try {
|
||||
const recentFiles = this.getRecentFiles();
|
||||
|
||||
// Clear existing content
|
||||
const filesGrid = document.getElementById('files-grid');
|
||||
const filesListView = document.getElementById('files-list-view');
|
||||
|
||||
filesGrid.innerHTML = '';
|
||||
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.last_accessed">Último acceso</div>
|
||||
</div>
|
||||
`;
|
||||
|
||||
// Update breadcrumb for recents
|
||||
window.ui.updateBreadcrumb(window.i18n ? window.i18n.t('nav.recent') : 'Recientes');
|
||||
|
||||
// Show empty state if no recent files
|
||||
if (recentFiles.length === 0) {
|
||||
const emptyState = document.createElement('div');
|
||||
emptyState.className = 'empty-state';
|
||||
emptyState.innerHTML = `
|
||||
<i class="fas fa-clock" style="font-size: 48px; color: #ddd; margin-bottom: 16px;"></i>
|
||||
<p>${window.i18n ? window.i18n.t('recent.empty_state') : 'No hay archivos recientes'}</p>
|
||||
<p>${window.i18n ? window.i18n.t('recent.empty_hint') : 'Los archivos que abras aparecerán aquí'}</p>
|
||||
`;
|
||||
filesGrid.appendChild(emptyState);
|
||||
return;
|
||||
}
|
||||
|
||||
// Process each recent file
|
||||
for (const recentFile of recentFiles) {
|
||||
this.createRecentFileElement(recentFile, filesGrid, filesListView);
|
||||
}
|
||||
|
||||
// Update file icons
|
||||
window.ui.updateFileIcons();
|
||||
|
||||
} catch (error) {
|
||||
console.error('Error displaying recent files:', error);
|
||||
window.ui.showNotification('Error', 'Error al cargar archivos recientes');
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Create a file element for a recent file
|
||||
* @param {Object} file - Recent file object
|
||||
* @param {HTMLElement} filesGrid - Grid view container
|
||||
* @param {HTMLElement} filesListView - List view container
|
||||
*/
|
||||
createRecentFileElement(file, filesGrid, filesListView) {
|
||||
// Determine icon and type
|
||||
let iconClass = 'fas fa-file';
|
||||
let iconSpecialClass = '';
|
||||
let typeLabel = 'Documento';
|
||||
|
||||
if (file.mime_type) {
|
||||
if (file.mime_type.startsWith('image/')) {
|
||||
iconClass = 'fas fa-file-image';
|
||||
iconSpecialClass = 'image-icon';
|
||||
typeLabel = window.i18n ? window.i18n.t('files.file_types.image') : 'Imagen';
|
||||
} else if (file.mime_type.startsWith('text/')) {
|
||||
iconClass = 'fas fa-file-alt';
|
||||
iconSpecialClass = 'text-icon';
|
||||
typeLabel = window.i18n ? window.i18n.t('files.file_types.text') : 'Texto';
|
||||
} else if (file.mime_type.startsWith('video/')) {
|
||||
iconClass = 'fas fa-file-video';
|
||||
iconSpecialClass = 'video-icon';
|
||||
typeLabel = window.i18n ? window.i18n.t('files.file_types.video') : 'Video';
|
||||
} else if (file.mime_type.startsWith('audio/')) {
|
||||
iconClass = 'fas fa-file-audio';
|
||||
iconSpecialClass = 'audio-icon';
|
||||
typeLabel = window.i18n ? window.i18n.t('files.file_types.audio') : 'Audio';
|
||||
} else if (file.mime_type === 'application/pdf') {
|
||||
iconClass = 'fas fa-file-pdf';
|
||||
iconSpecialClass = 'pdf-icon';
|
||||
typeLabel = window.i18n ? window.i18n.t('files.file_types.pdf') : 'PDF';
|
||||
}
|
||||
}
|
||||
|
||||
// Format size and date
|
||||
const fileSize = window.formatFileSize ? window.formatFileSize(file.size || 0) : '0 B';
|
||||
const accessedDate = new Date(file.accessedAt);
|
||||
const formattedDate = accessedDate.toLocaleDateString() + ' ' +
|
||||
accessedDate.toLocaleTimeString([], {hour: '2-digit', minute:'2-digit'});
|
||||
|
||||
// Grid view element
|
||||
const fileGridElement = document.createElement('div');
|
||||
fileGridElement.className = 'file-card recent-item';
|
||||
fileGridElement.dataset.fileId = file.id;
|
||||
fileGridElement.dataset.fileName = file.name;
|
||||
fileGridElement.dataset.folderId = file.folder_id || "";
|
||||
|
||||
fileGridElement.innerHTML = `
|
||||
<div class="recent-indicator">
|
||||
<i class="fas fa-clock"></i>
|
||||
</div>
|
||||
<div class="file-icon ${iconSpecialClass}">
|
||||
<i class="${iconClass}"></i>
|
||||
</div>
|
||||
<div class="file-name">${file.name}</div>
|
||||
<div class="file-info">Accedido ${formattedDate.split(' ')[0]}</div>
|
||||
`;
|
||||
|
||||
// Download on click
|
||||
fileGridElement.addEventListener('click', () => {
|
||||
window.location.href = `/api/files/${file.id}`;
|
||||
|
||||
// Dispatch custom event to update recent files
|
||||
document.dispatchEvent(new CustomEvent('file-accessed', {
|
||||
detail: { file }
|
||||
}));
|
||||
});
|
||||
|
||||
// Context menu
|
||||
fileGridElement.addEventListener('contextmenu', (e) => {
|
||||
e.preventDefault();
|
||||
|
||||
window.app.contextMenuTargetFile = {
|
||||
id: file.id,
|
||||
name: file.name,
|
||||
folder_id: file.folder_id || ""
|
||||
};
|
||||
|
||||
let fileContextMenu = document.getElementById('file-context-menu');
|
||||
fileContextMenu.style.left = `${e.pageX}px`;
|
||||
fileContextMenu.style.top = `${e.pageY}px`;
|
||||
fileContextMenu.style.display = 'block';
|
||||
});
|
||||
|
||||
filesGrid.appendChild(fileGridElement);
|
||||
|
||||
// List view element
|
||||
const fileListElement = document.createElement('div');
|
||||
fileListElement.className = 'file-item recent-item';
|
||||
fileListElement.dataset.fileId = file.id;
|
||||
fileListElement.dataset.fileName = file.name;
|
||||
fileListElement.dataset.folderId = file.folder_id || "";
|
||||
|
||||
fileListElement.innerHTML = `
|
||||
<div class="recent-indicator">
|
||||
<i class="fas fa-clock"></i>
|
||||
</div>
|
||||
<div class="name-cell">
|
||||
<div class="file-icon ${iconSpecialClass}">
|
||||
<i class="${iconClass}"></i>
|
||||
</div>
|
||||
<span>${file.name}</span>
|
||||
</div>
|
||||
<div class="type-cell">${typeLabel}</div>
|
||||
<div class="size-cell">${fileSize}</div>
|
||||
<div class="date-cell">${formattedDate}</div>
|
||||
`;
|
||||
|
||||
// Download on click
|
||||
fileListElement.addEventListener('click', () => {
|
||||
window.location.href = `/api/files/${file.id}`;
|
||||
|
||||
// Dispatch custom event to update recent files
|
||||
document.dispatchEvent(new CustomEvent('file-accessed', {
|
||||
detail: { file }
|
||||
}));
|
||||
});
|
||||
|
||||
// Context menu
|
||||
fileListElement.addEventListener('contextmenu', (e) => {
|
||||
e.preventDefault();
|
||||
|
||||
window.app.contextMenuTargetFile = {
|
||||
id: file.id,
|
||||
name: file.name,
|
||||
folder_id: file.folder_id || ""
|
||||
};
|
||||
|
||||
let fileContextMenu = document.getElementById('file-context-menu');
|
||||
fileContextMenu.style.left = `${e.pageX}px`;
|
||||
fileContextMenu.style.top = `${e.pageY}px`;
|
||||
fileContextMenu.style.display = 'block';
|
||||
});
|
||||
|
||||
filesListView.appendChild(fileListElement);
|
||||
}
|
||||
};
|
||||
|
||||
// Expose recent module globally
|
||||
window.recent = recent;
|
||||
+53
-4
@@ -43,6 +43,9 @@ const ui = {
|
||||
fileMenu.className = 'context-menu';
|
||||
fileMenu.id = 'file-context-menu';
|
||||
fileMenu.innerHTML = `
|
||||
<div class="context-menu-item" id="view-file-option">
|
||||
<i class="fas fa-eye"></i> <span data-i18n="actions.view">Ver</span>
|
||||
</div>
|
||||
<div class="context-menu-item" id="download-file-option">
|
||||
<i class="fas fa-download"></i> <span data-i18n="actions.download">Descargar</span>
|
||||
</div>
|
||||
@@ -766,9 +769,32 @@ const ui = {
|
||||
});
|
||||
});
|
||||
|
||||
// Download on click
|
||||
// View or download on click
|
||||
fileGridElement.addEventListener('click', () => {
|
||||
window.location.href = `/api/files/${file.id}`;
|
||||
// Track this file access for recent files
|
||||
if (window.recent) {
|
||||
document.dispatchEvent(new CustomEvent('file-accessed', {
|
||||
detail: { file }
|
||||
}));
|
||||
}
|
||||
|
||||
// Check if it's a viewable file type
|
||||
if ((file.mime_type && file.mime_type.startsWith('image/')) ||
|
||||
(file.mime_type && file.mime_type === 'application/pdf')) {
|
||||
// Open in the inline viewer
|
||||
if (window.inlineViewer) {
|
||||
window.inlineViewer.openFile(file);
|
||||
} else if (window.fileViewer) {
|
||||
// Fallback to standard file viewer
|
||||
window.fileViewer.open(file);
|
||||
} else {
|
||||
// No viewer available, download directly
|
||||
window.location.href = `/api/files/${file.id}`;
|
||||
}
|
||||
} else {
|
||||
// For other file types, download directly
|
||||
window.location.href = `/api/files/${file.id}`;
|
||||
}
|
||||
});
|
||||
|
||||
// Context menu
|
||||
@@ -823,9 +849,32 @@ const ui = {
|
||||
});
|
||||
});
|
||||
|
||||
// Download on click
|
||||
// View or download on click
|
||||
fileListElement.addEventListener('click', () => {
|
||||
window.location.href = `/api/files/${file.id}`;
|
||||
// Track this file access for recent files
|
||||
if (window.recent) {
|
||||
document.dispatchEvent(new CustomEvent('file-accessed', {
|
||||
detail: { file }
|
||||
}));
|
||||
}
|
||||
|
||||
// Check if it's a viewable file type
|
||||
if ((file.mime_type && file.mime_type.startsWith('image/')) ||
|
||||
(file.mime_type && file.mime_type === 'application/pdf')) {
|
||||
// Open in the inline viewer
|
||||
if (window.inlineViewer) {
|
||||
window.inlineViewer.openFile(file);
|
||||
} else if (window.fileViewer) {
|
||||
// Fallback to standard file viewer
|
||||
window.fileViewer.open(file);
|
||||
} else {
|
||||
// No viewer available, download directly
|
||||
window.location.href = `/api/files/${file.id}`;
|
||||
}
|
||||
} else {
|
||||
// For other file types, download directly
|
||||
window.location.href = `/api/files/${file.id}`;
|
||||
}
|
||||
});
|
||||
|
||||
// Context menu (list view)
|
||||
|
||||
@@ -19,12 +19,14 @@
|
||||
"move_to": "Move to",
|
||||
"delete": "Delete",
|
||||
"download": "Download",
|
||||
"view": "View",
|
||||
"cancel": "Cancel",
|
||||
"confirm": "Confirm",
|
||||
"share": "Share",
|
||||
"copy": "Copy",
|
||||
"notify": "Notify",
|
||||
"send": "Send"
|
||||
"send": "Send",
|
||||
"clear_recent": "Clear recent"
|
||||
},
|
||||
"share": {
|
||||
"dialogTitle": "Share Link",
|
||||
|
||||
@@ -138,12 +138,14 @@
|
||||
"move_to": "Mover a",
|
||||
"delete": "Eliminar",
|
||||
"download": "Descargar",
|
||||
"view": "Ver",
|
||||
"cancel": "Cancelar",
|
||||
"confirm": "Confirmar",
|
||||
"share": "Compartir",
|
||||
"copy": "Copiar",
|
||||
"notify": "Notificar",
|
||||
"send": "Enviar"
|
||||
"send": "Enviar",
|
||||
"clear_recent": "Limpiar recientes"
|
||||
},
|
||||
"files": {
|
||||
"name": "Nombre",
|
||||
|
||||
Reference in New Issue
Block a user