Merge pull request #309 from EdouardVanbelle/refactor/keep-badge-order

This commit is contained in:
Dionisio Pozo
2026-04-25 21:20:58 +02:00
committed by GitHub
14 changed files with 198 additions and 178 deletions
+1 -1
View File
@@ -10,7 +10,7 @@
padding: 6px;
min-width: 200px;
z-index: 2000;
display: none;
display: block;
animation: contextMenuIn 0.15s ease-out;
}
+5 -13
View File
@@ -27,7 +27,7 @@
width: 100%;
height: 100%;
background-color: var(--color-overlay-light);
display: none;
display: flex;
align-items: center;
justify-content: center;
z-index: 3000;
@@ -106,7 +106,7 @@
width: 100%;
height: 100%;
background-color: var(--color-overlay-light);
display: none;
display: flex;
justify-content: center;
align-items: center;
z-index: 3000;
@@ -205,7 +205,7 @@
width: 100%;
height: 100%;
background-color: var(--color-overlay-light);
display: none;
display: flex;
justify-content: center;
align-items: center;
z-index: 3000;
@@ -213,10 +213,6 @@
animation: modalFadeIn 0.2s ease;
}
.shared-dialog.active {
display: flex;
}
.shared-dialog-content {
background-color: var(--color-bg-surface);
border-radius: 16px;
@@ -512,7 +508,7 @@
width: 100%;
height: 100%;
background-color: var(--color-overlay-light);
display: none;
display: flex;
align-items: center;
justify-content: center;
z-index: 4000;
@@ -593,16 +589,12 @@
width: 100%;
height: 100%;
background-color: var(--color-overlay);
display: none;
display: flex;
align-items: center;
justify-content: center;
z-index: 1000;
}
.dialog.active {
display: flex;
}
.dialog-content {
background-color: var(--color-bg-surface);
border-radius: 10px;
+2 -6
View File
@@ -1,6 +1,6 @@
/* About Modal */
.about-modal-overlay {
display: none;
display: flex;
position: fixed;
inset: 0;
background: var(--color-overlay);
@@ -10,10 +10,6 @@
align-items: center;
}
.about-modal-overlay.show {
display: flex;
}
.about-modal {
background: var(--color-bg-surface);
border-radius: 20px;
@@ -130,7 +126,7 @@
width: 100%;
height: 100%;
background-color: var(--color-overlay);
display: none;
display: flex;
justify-content: center;
align-items: center;
z-index: 3000;
+2 -2
View File
@@ -37,7 +37,7 @@
text-align: center;
margin: 20px 0;
color: var(--color-text-medium);
display: none;
display: block;
}
.dropzone-icon {
@@ -53,7 +53,7 @@
.upload-progress {
margin-top: 15px;
width: 100%;
display: none;
display: block;
}
.progress-bar {
+1 -5
View File
@@ -11,7 +11,7 @@
}
.upload-dropdown-menu {
display: none;
display: block;
position: absolute;
top: calc(100% + 6px);
left: 0;
@@ -25,10 +25,6 @@
animation: dropdownFadeIn 0.15s ease-out;
}
.upload-dropdown-menu.show {
display: block;
}
@keyframes dropdownFadeIn {
from {
opacity: 0;
+3 -3
View File
@@ -216,12 +216,12 @@
<span class="breadcrumb-item" data-i18n="breadcrumb.home">Home</span>
</div>
<div class="dropzone" id="dropzone">
<div class="dropzone hidden" id="dropzone">
<i class="fas fa-cloud-upload-alt dropzone-icon"></i>
<p data-i18n="dropzone.drag_files">Drag files here or click to select</p>
<input type="file" id="file-input" class="hidden" multiple>
<input type="file" id="folder-input" class="hidden" webkitdirectory directory multiple>
<div class="upload-progress">
<div class="upload-progress hidden">
<div class="progress-bar">
<div class="progress-fill"></div>
</div>
@@ -266,7 +266,7 @@
</div>
<!-- About Modal -->
<div class="about-modal-overlay" id="about-modal-overlay">
<div class="about-modal-overlay hidden" id="about-modal-overlay">
<div class="about-modal">
<div class="about-modal-logo">
<i class="fas fa-cloud"></i>
+12 -13
View File
@@ -89,7 +89,7 @@ const ACTIONS_BAR_TEMPLATES = {
<span data-i18n="actions.upload">Upload</span>
<i class="fas fa-caret-down icon-ml"></i>
</button>
<div class="upload-dropdown-menu" id="upload-dropdown-menu">
<div class="upload-dropdown-menu hidden" 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>
@@ -187,14 +187,14 @@ function setupActionsBarDelegation() {
case 'upload-files-btn': {
e.stopPropagation();
const menu = document.getElementById('upload-dropdown-menu');
if (menu) menu.classList.remove('show');
if (menu) menu.classList.add('hidden');
if (elements.fileInput) elements.fileInput.click();
break;
}
case 'upload-folder-btn': {
e.stopPropagation();
const menu = document.getElementById('upload-dropdown-menu');
if (menu) menu.classList.remove('show');
if (menu) menu.classList.add('hidden');
const folderInput = document.getElementById('folder-input');
if (folderInput) folderInput.click();
break;
@@ -456,13 +456,13 @@ function setupUploadDropdown() {
'click',
(e) => {
e.stopPropagation();
const isOpen = menu.classList.contains('show');
const isOpen = !menu.classList.contains('hidden');
// Close any other open dropdowns
document.querySelectorAll('.upload-dropdown-menu.show').forEach((m) => {
m.classList.remove('show');
document.querySelectorAll('.upload-dropdown-menu').forEach((m) => {
m.classList.add('hidden');
});
if (!isOpen) {
menu.classList.add('show');
menu.classList.remove('hidden');
}
},
{ signal }
@@ -475,8 +475,8 @@ function setupUploadDropdown() {
}
uploadDropdownDocumentClickHandler = (e) => {
if (e.target.closest('#upload-dropdown')) return;
document.querySelectorAll('.upload-dropdown-menu.show').forEach((m) => {
m.classList.remove('show');
document.querySelectorAll('.upload-dropdown-menu').forEach((m) => {
m.classList.add('hidden');
});
};
document.addEventListener('click', uploadDropdownDocumentClickHandler);
@@ -663,13 +663,12 @@ function setupEventListeners() {
// Global events to close context menus and deselect cards
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)) {
if (folderMenu && !folderMenu.classList.contains('hidden') && !folderMenu.contains(e.target)) {
ui.closeContextMenu();
}
if (fileMenu && fileMenu.style.display === 'block' && !fileMenu.contains(e.target)) {
const fileMenu = document.getElementById('file-context-menu');
if (fileMenu && !fileMenu.classList.contains('hidden') && !fileMenu.contains(e.target)) {
ui.closeFileContextMenu();
}
});
+92 -51
View File
@@ -7,7 +7,7 @@
import { escapeHtml, formatDateTime, formatFileSize } from '../core/formatters.js';
import { i18n } from '../core/i18n.js';
import { OxiIcons, replaceIconsInElement } from '../core/icons.js';
import { OxiIcons } from '../core/icons.js';
import { contextMenus } from '../features/files/contextMenus.js';
import { fileOps } from '../features/files/fileOperations.js';
import { inlineViewer } from '../features/files/inlineViewer.js';
@@ -38,7 +38,7 @@ const ui = {
// Folder context menu
if (!document.getElementById('folder-context-menu')) {
const folderMenu = document.createElement('div');
folderMenu.className = 'context-menu';
folderMenu.classList.add('context-menu', 'hidden');
folderMenu.id = 'folder-context-menu';
folderMenu.innerHTML = `
<div class="context-menu-item" id="download-folder-option">
@@ -68,7 +68,7 @@ const ui = {
// File context menu
if (!document.getElementById('file-context-menu')) {
const fileMenu = document.createElement('div');
fileMenu.className = 'context-menu';
fileMenu.classList.add('context-menu', 'hidden');
fileMenu.id = 'file-context-menu';
fileMenu.innerHTML = `
<div class="context-menu-item" id="view-file-option">
@@ -111,7 +111,7 @@ const ui = {
// Rename dialog — modern
if (!document.getElementById('rename-dialog')) {
const renameDialog = document.createElement('div');
renameDialog.className = 'rename-dialog';
renameDialog.classList.add('rename-dialog', 'hidden');
renameDialog.id = 'rename-dialog';
renameDialog.innerHTML = `
<div class="rename-dialog-content">
@@ -134,7 +134,7 @@ const ui = {
// Move dialog — modern with navigation
if (!document.getElementById('move-file-dialog')) {
const moveDialog = document.createElement('div');
moveDialog.className = 'rename-dialog';
moveDialog.classList.add('rename-dialog', 'hidden');
moveDialog.id = 'move-file-dialog';
moveDialog.innerHTML = `
<div class="rename-dialog-content">
@@ -161,7 +161,7 @@ const ui = {
// Share dialog
if (!document.getElementById('share-dialog')) {
const shareDialog = document.createElement('div');
shareDialog.className = 'share-dialog';
shareDialog.classList.add('share-dialog', 'hidden');
shareDialog.id = 'share-dialog';
shareDialog.innerHTML = `
<div class="share-dialog-content">
@@ -208,6 +208,7 @@ const ui = {
</div>
</div>
</div>
<button class="btn btn-primary btn-small" id="share-confirm-btn" data-i18n="actions.share">Share</button>
</div>
<div id="new-share-section" class="share-section hidden">
@@ -226,15 +227,15 @@ const ui = {
</div>
<div class="share-dialog-buttons">
<button class="btn btn-secondary" id="share-cancel-btn" data-i18n="actions.cancel">Cancel</button>
<button class="btn btn-primary" id="share-confirm-btn" data-i18n="actions.share">Share</button>
<button class="btn btn-secondary" id="share-close-btn" data-i18n="actions.close">Close</button>
</div>
</div>
`;
i18n.translateElement(shareDialog);
document.body.appendChild(shareDialog);
// Add event listeners for share dialog
document.getElementById('share-cancel-btn').addEventListener('click', () => {
document.getElementById('share-close-btn').addEventListener('click', () => {
contextMenus.closeShareDialog();
});
@@ -251,12 +252,26 @@ const ui = {
const shareUrl = document.getElementById('generated-share-url').value;
contextMenus.showEmailNotificationDialog(shareUrl);
});
// FIXME make generic function (close all dialog / etc)
document.addEventListener('keydown', (e) => {
const dialog = document.getElementById('share-dialog');
if (e.key === 'Escape' && !dialog?.classList.contains('hidden')) {
contextMenus.closeShareDialog();
}
});
shareDialog.addEventListener('click', (e) => {
if (e.target === shareDialog) {
contextMenus.closeShareDialog();
}
});
}
// Notification dialog
if (!document.getElementById('notification-dialog')) {
const notificationDialog = document.createElement('div');
notificationDialog.className = 'share-dialog';
notificationDialog.classList.add('share-dialog', 'hidden');
notificationDialog.id = 'notification-dialog';
notificationDialog.innerHTML = `
<div class="share-dialog-content">
@@ -298,7 +313,7 @@ const ui = {
// Playlist selection dialog
if (!document.getElementById('playlist-dialog')) {
const playlistDialog = document.createElement('div');
playlistDialog.className = 'share-dialog';
playlistDialog.classList.add('share-dialog', 'hidden');
playlistDialog.id = 'playlist-dialog';
playlistDialog.innerHTML = `
<div class="share-dialog-content">
@@ -417,7 +432,7 @@ const ui = {
fileOps.uploadFiles(droppedEntries.map((x) => x.file));
}
setTimeout(() => {
dropzone.style.display = 'none';
dropzone?.classList.add('hidden');
}, 500);
return;
}
@@ -431,7 +446,7 @@ const ui = {
}
}
setTimeout(() => {
dropzone.style.display = 'none';
dropzone?.classList.add('hidden');
}, 500);
});
@@ -439,8 +454,8 @@ const ui = {
document.addEventListener('dragover', (e) => {
e.preventDefault();
if (e.dataTransfer.types.includes('Files')) {
dropzone.style.display = 'block';
dropzone.classList.add('active');
dropzone?.classList.remove('hidden');
dropzone?.classList.add('active');
}
});
@@ -449,7 +464,7 @@ const ui = {
dropzone.classList.remove('active');
setTimeout(() => {
if (!dropzone.classList.contains('active')) {
dropzone.style.display = 'none';
dropzone?.classList.add('hidden');
}
}, 100);
}
@@ -473,7 +488,7 @@ const ui = {
fileOps.uploadFiles(droppedEntries.map((x) => x.file));
}
setTimeout(() => {
dropzone.style.display = 'none';
dropzone?.classList.add('hidden');
}, 500);
return;
}
@@ -488,7 +503,7 @@ const ui = {
}
setTimeout(() => {
dropzone.style.display = 'none';
dropzone?.classList.add('hidden');
}, 500);
});
},
@@ -667,7 +682,7 @@ const ui = {
closeContextMenu() {
const menu = document.getElementById('folder-context-menu');
if (menu) {
menu.style.display = 'none';
menu.classList.add('hidden');
app.contextMenuTargetFolder = null;
}
},
@@ -678,7 +693,7 @@ const ui = {
closeFileContextMenu() {
const menu = document.getElementById('file-context-menu');
if (menu) {
menu.style.display = 'none';
menu.classList.add('hidden');
app.contextMenuTargetFile = null;
}
},
@@ -994,7 +1009,7 @@ const ui = {
}
menu.style.left = `${e.pageX}px`;
menu.style.top = `${e.pageY}px`;
menu.style.display = 'block';
menu?.classList.remove('hidden');
});
// dragstart
@@ -1119,18 +1134,19 @@ const ui = {
* ================================================================ */
_bindStarClick(el) {
const star = el.querySelector('.favorite-star');
if (!star) return;
star.addEventListener('click', (e) => {
star?.addEventListener('click', (e) => {
e.stopPropagation();
e.stopImmediatePropagation();
e.preventDefault();
if (!favorites) return;
const itemId = star.dataset.itemId;
const itemType = star.dataset.itemType;
const itemName = star.dataset.itemName;
// FIXME: make a function
const itemElement = shared?.closest('.file-item');
const itemId = itemElement.dataset.fileId ? itemElement.dataset.fileId : itemElement.dataset.folderId;
const itemType = itemElement.dataset.fileId ? 'file' : 'folder';
const itemName = itemElement.dataset.fileId ? itemElement.dataset.fileName : itemElement.dataset.folderName;
const isActive = star.classList.contains('active');
@@ -1147,6 +1163,30 @@ const ui = {
contextMenus.syncFavoriteOptionLabels();
}
});
const shared = el.querySelector('.file-badge-shared');
shared?.addEventListener('click', (e) => {
e.stopPropagation();
e.stopImmediatePropagation();
e.preventDefault();
// FIXME: make a function
const itemElement = shared?.closest('.file-item');
const itemId = itemElement.dataset.fileId ? itemElement.dataset.fileId : itemElement.dataset.folderId;
const itemType = itemElement.dataset.fileId ? 'file' : 'folder';
const itemName = itemElement.dataset.fileId ? itemElement.dataset.fileName : itemElement.dataset.folderName;
// TODO corrently dirty
const item = {
id: itemId,
item_id: itemId,
item_type: itemType,
item_name: itemName
};
contextMenus.showShareDialog(item, itemType);
});
},
/**
@@ -1155,9 +1195,10 @@ const ui = {
setFavoriteVisualState(itemId, itemType, isFavorite) {
const selector = itemType === 'folder' ? `#files-list .file-item[data-folder-id="${itemId}"]` : `#files-list .file-item[data-file-id="${itemId}"]`;
const card = document.querySelector(selector);
const starBtn = card ? card.querySelector('.favorite-star') : null;
const item = document.querySelector(selector);
const starBtn = item?.querySelector('.favorite-star');
// chzn
if (starBtn) {
starBtn.classList.toggle('active', !!isFavorite);
@@ -1180,20 +1221,21 @@ const ui = {
}
}
const listItem = document.querySelector(selector);
if (listItem) {
const nameCell = listItem.querySelector('.name-cell');
if (nameCell) {
let inlineStar = nameCell.querySelector('.favorite-star-inline');
if (isFavorite && !inlineStar) {
inlineStar = document.createElement('i');
inlineStar.className = 'fas fa-star favorite-star-inline';
nameCell.appendChild(inlineStar);
replaceIconsInElement(nameCell);
} else if (!isFavorite && inlineStar) {
inlineStar.remove();
}
// toggle favorite's badge
if (item) {
const badgeFavorite = item.querySelector('.file-badge-favorite');
badgeFavorite?.classList.toggle('hidden', !isFavorite);
}
},
setSharedVisualState(itemId, itemType, isShared) {
console.log(`setSharedVisual call for ${itemId} ${itemType} to ${isShared}`);
const selector = itemType === 'folder' ? `#files-list .file-item[data-folder-id="${itemId}"]` : `#files-list .file-item[data-file-id="${itemId}"]`;
// toggle favorite's badge
const item = document.querySelector(selector);
if (item) {
const badgeShared = item.querySelector('.file-badge-shared');
badgeShared?.classList.toggle('hidden', !isShared);
}
},
@@ -1220,14 +1262,14 @@ const ui = {
<i class="fas fa-folder"></i>
</div>
<span>${escapeHtml(folder.name)}</span>
${isFav ? '<i class="fas fa-star favorite-star-inline"></i>' : ''}
${isShared ? '<div class="file-badge-shared"><i class="fas fa-share-alt"></i></div>' : ''}
<div class="file-badge file-badge-favorite ${isFav ? '' : 'hidden'}"><i class="fas fa-star favorite-star-inline"></i></div>
<div class="file-badge file-badge-shared ${isShared ? '' : 'hidden'}"><i class="fas fa-share-alt"></i></div>
</div>
<div class="type-cell">${i18n ? i18n.t('files.file_types.folder') : 'Folder'}</div>
<div class="size-cell">--</div>
<div class="date-cell">${formattedDate}</div>
<div class="action-cell">
<button class="favorite-star${isFav ? ' active' : ''}" data-item-id="${folder.id}" data-item-type="folder" data-item-name="${escapeHtml(folder.name)}">
<button class="favorite-star${isFav ? ' active' : ''}">
<i class="${isFav ? 'fas' : 'far'} fa-star"></i>
</button>
<button class="file-actions"><i class="fas fa-ellipsis-v"></i></button>
@@ -1268,15 +1310,14 @@ const ui = {
<i class="${iconClass}"></i>
</div>
<span>${escapeHtml(file.name)}</span>
${isFav ? '<i class="fas fa-star favorite-star-inline"></i>' : ''}
${isShared ? '<div class="file-badge-shared"><i class="fas fa-share-alt"></i></div>' : ''}
<div class="file-badge file-badge-favorite ${isFav ? '' : 'hidden'}"><i class="fas fa-star favorite-star-inline"></i></div>
<div class="file-badge file-badge-shared ${isShared ? '' : 'hidden'}"><i class="fas fa-share-alt"></i></div>
</div>
<div class="type-cell">${typeLabel}</div>
<div class="size-cell">${fileSize}</div>
<div class="date-cell">${formattedDate}</div>
<div class="action-cell">
<button class="favorite-star${isFav ? ' active' : ''}" data-item-id="${file.id}" data-item-type="file" data-item-name="${escapeHtml(file.name)}">
<button class="favorite-star${isFav ? ' active' : ''}">
<i class="${isFav ? 'fas' : 'far'} fa-star"></i>
</button>
<button class="file-actions"><i class="fas fa-ellipsis-v"></i></button>
@@ -1434,7 +1475,7 @@ function toggleCardSelection(card, event) {
function showContextMenuAtElement(triggerElement, menuId) {
// Hide any open menus first
document.querySelectorAll('.context-menu').forEach((m) => {
m.style.display = 'none';
m.classList.add('hidden');
});
const menu = document.getElementById(menuId);
@@ -1465,7 +1506,7 @@ function showContextMenuAtElement(triggerElement, menuId) {
menu.style.left = `${left}px`;
menu.style.top = `${top}px`;
menu.style.display = 'block';
menu.classList.remove('hidden');
}
/**
-22
View File
@@ -7,7 +7,6 @@ import { notifications } from '../core/notifications.js';
const uiNotifications = {
show(title, message) {
if (notifications && typeof notifications.addNotification === 'function') {
const normalizedTitle = String(title || '').toLowerCase();
let icon = 'fa-info-circle';
let iconClass = 'upload';
@@ -37,27 +36,6 @@ const uiNotifications = {
});
return;
}
let notification = document.querySelector('.notification');
if (!notification) {
notification = document.createElement('div');
notification.className = 'notification';
notification.innerHTML = `
<div class="notification-title">${title}</div>
<div class="notification-message">${message}</div>
`;
document.body.appendChild(notification);
} else {
notification.querySelector('.notification-title').textContent = title;
notification.querySelector('.notification-message').textContent = message;
}
notification.style.display = 'block';
setTimeout(() => {
notification.style.display = 'none';
}, 5000);
}
};
export { uiNotifications };
+6 -6
View File
@@ -129,7 +129,7 @@ function setupUserMenu() {
aboutBtn.addEventListener('click', () => {
wrapper.classList.remove('open');
const overlay = document.getElementById('about-modal-overlay');
if (overlay) overlay.classList.add('show');
if (overlay) overlay.classList.remove('hidden');
});
}
@@ -137,18 +137,18 @@ function setupUserMenu() {
const aboutOverlay = document.getElementById('about-modal-overlay');
if (aboutCloseBtn) {
aboutCloseBtn.addEventListener('click', () => {
aboutOverlay.classList.remove('show');
aboutOverlay.classList.add('hidden');
});
}
if (aboutOverlay) {
aboutOverlay.addEventListener('click', (e) => {
if (e.target === aboutOverlay) {
aboutOverlay.classList.remove('show');
aboutOverlay.classList.add('hidden');
}
});
document.addEventListener('keydown', (e) => {
if (e.key === 'Escape' && aboutOverlay.classList.contains('show')) {
aboutOverlay.classList.remove('show');
if (e.key === 'Escape' && !aboutOverlay.classList.contains('hidden')) {
aboutOverlay.classList.add('hidden');
}
});
}
@@ -218,7 +218,7 @@ function showUserProfileModal() {
const overlay = document.createElement('div');
overlay.id = 'profile-modal-overlay';
overlay.className = 'about-modal-overlay';
overlay.classList.add('about-modal-overlay', 'hidden');
overlay.innerHTML = `
<div class="about-modal about-modal-body">
<div class="about-modal-header">
+11 -2
View File
@@ -8,14 +8,23 @@ import { replaceIconsInElement } from './icons.js';
const Modal = {
// Modal element references
/** @private @type {HTMLElement | null} */
overlay: null,
// FIXME: unused ?
container: null,
/** @private @type {HTMLElement | null} */
icon: null,
/** @private @type {HTMLElement | null} */
title: null,
/** @private @type {HTMLElement | null} */
label: null,
/** @private @type {HTMLElement | null} */
input: null,
/** @private @type {HTMLElement | null} */
cancelBtn: null,
/** @private @type {HTMLElement | null} */
confirmBtn: null,
/** @private @type {HTMLElement | null} */
closeBtn: null,
// Current callback
@@ -169,7 +178,7 @@ const Modal = {
if (!this.overlay) return;
// Show overlay
this.overlay.style.display = 'flex';
this.overlay.classList.remove('hidden');
// Trigger animation
requestAnimationFrame(() => {
@@ -206,7 +215,7 @@ const Modal = {
this.overlay.classList.remove('active');
setTimeout(() => {
this.overlay.style.display = 'none';
this.overlay.classList.add('hidden');
if (!confirmed && this.onCancel) {
this.onCancel();
+17 -13
View File
@@ -294,7 +294,7 @@ const contextMenus = {
// Each handler checks its own state, so multiple dialogs can be closed with multiple Escape presses
if (!_moveDialogEscapeHandler) {
_moveDialogEscapeHandler = (e) => {
if (e.key === 'Escape' && moveFileDialog.style.display === 'flex') {
if (e.key === 'Escape' && !moveFileDialog?.classList.contains('hidden')) {
this.closeMoveDialog();
}
};
@@ -383,7 +383,7 @@ const contextMenus = {
// Update header text
const headerSpan = renameDialog.querySelector('.rename-dialog-header span');
if (headerSpan) headerSpan.textContent = i18n ? i18n.t('dialogs.rename_folder') : 'Rename folder';
renameDialog.style.display = 'flex';
renameDialog?.classList.remove('hidden');
renameInput.focus();
renameInput.select();
},
@@ -403,7 +403,7 @@ const contextMenus = {
// Update header text
const headerSpan = renameDialog.querySelector('.rename-dialog-header span');
if (headerSpan) headerSpan.textContent = i18n ? i18n.t('dialogs.rename_file') : 'Rename file';
renameDialog.style.display = 'flex';
renameDialog?.classList.remove('hidden');
renameInput.focus();
renameInput.select();
},
@@ -412,7 +412,7 @@ const contextMenus = {
* Close rename dialog
*/
closeRenameDialog() {
document.getElementById('rename-dialog').style.display = 'none';
document.getElementById('rename-dialog')?.classList.add('hidden');
app.contextMenuTargetFolder = null;
app.renameTarget = null;
},
@@ -478,14 +478,14 @@ const contextMenus = {
await this.loadMoveDialogFolders(startFolderId);
// Show dialog
document.getElementById('move-file-dialog').style.display = 'flex';
document.getElementById('move-file-dialog')?.classList.remove('hidden');
},
/**
* Close move dialog
*/
closeMoveDialog() {
document.getElementById('move-file-dialog').style.display = 'none';
document.getElementById('move-file-dialog')?.classList.add('hidden');
app.contextMenuTargetFile = null;
app.contextMenuTargetFolder = null;
},
@@ -909,6 +909,7 @@ const contextMenus = {
btn.closest('.existing-share-item').remove();
if (existingSharesContainer.children.length === 0) {
document.getElementById('existing-shares-section').classList.add('hidden');
ui.setSharedVisualState(item.id, item.type, false);
}
}
});
@@ -923,7 +924,7 @@ const contextMenus = {
if (newShareSection) newShareSection.classList.add('hidden');
// Show dialog
shareDialog.style.display = 'flex';
shareDialog.classList.remove('hidden');
console.log('Share dialog opened for', itemType, item.name);
} catch (error) {
console.error('Error opening share dialog:', error);
@@ -992,6 +993,9 @@ const contextMenus = {
shareUrl.select();
}
// Update Item's shared badge
ui.setSharedVisualState(item.id, item.type, true);
// Show success message
ui.showNotification(
i18n ? i18n.t('notifications.link_created') : 'Link created',
@@ -1017,7 +1021,7 @@ const contextMenus = {
app.notificationShareUrl = shareUrl;
// Show dialog
document.getElementById('notification-dialog').style.display = 'flex';
document.getElementById('notification-dialog')?.classList.remove('hidden');
},
/**
@@ -1042,7 +1046,7 @@ const contextMenus = {
try {
fileSharing.sendShareNotification(shareUrl, email, message);
document.getElementById('notification-dialog').style.display = 'none';
document.getElementById('notification-dialog')?.classList.add('hidden');
} catch (error) {
console.error('Error sending notification:', error);
ui.showNotification('Error', 'Could not send notification');
@@ -1054,7 +1058,7 @@ const contextMenus = {
*/
closeShareDialog() {
const dialog = document.getElementById('share-dialog');
if (dialog) dialog.style.display = 'none';
if (dialog) dialog.classList.add('hidden');
app.shareDialogItem = null;
app.shareDialogItemType = null;
},
@@ -1063,7 +1067,7 @@ const contextMenus = {
* Close notification dialog
*/
closeNotificationDialog() {
document.getElementById('notification-dialog').style.display = 'none';
document.getElementById('notification-dialog')?.classList.add('hidden');
app.notificationShareUrl = null;
},
@@ -1096,7 +1100,7 @@ const contextMenus = {
if (addBtn) addBtn.disabled = true;
// Show dialog
dialog.style.display = 'flex';
dialog.classList.remove('hidden');
requestAnimationFrame(() => dialog.classList.add('active'));
// Load playlists
@@ -1195,7 +1199,7 @@ const contextMenus = {
if (dialog) {
dialog.classList.remove('active');
setTimeout(() => {
dialog.style.display = 'none';
dialog.classList.add('hidden');
}, 200);
}
app.playlistDialogFiles = null;
+8 -8
View File
@@ -289,7 +289,7 @@ const fileOps = {
const progressBar = document.querySelector('.progress-fill');
const uploadProgressDiv = document.querySelector('.upload-progress');
if (uploadProgressDiv) {
uploadProgressDiv.style.display = 'block';
uploadProgressDiv.classList.remove('hidden');
}
if (progressBar) {
progressBar.style.width = '0%';
@@ -322,7 +322,7 @@ const fileOps = {
}
if (totalFiles === 0) {
if (uploadProgressDiv) uploadProgressDiv.style.display = 'none';
if (uploadProgressDiv) uploadProgressDiv.classList.add('hidden');
this._isUploading = false;
return;
}
@@ -412,8 +412,8 @@ const fileOps = {
}
const dropzone = document.getElementById('dropzone');
if (dropzone) dropzone.style.display = 'none';
if (uploadProgressDiv) uploadProgressDiv.style.display = 'none';
if (dropzone) dropzone.classList.add('hidden');
if (uploadProgressDiv) uploadProgressDiv.classList.add('hidden');
} finally {
this._isUploading = false;
}
@@ -450,7 +450,7 @@ const fileOps = {
const progressBar = document.querySelector('.progress-fill');
const uploadProgressDiv = document.querySelector('.upload-progress');
if (uploadProgressDiv) {
uploadProgressDiv.style.display = 'block';
uploadProgressDiv.classList.remove('hidden');
}
if (progressBar) {
progressBar.style.width = '0%';
@@ -468,7 +468,7 @@ const fileOps = {
const totalFiles = validEntries.length;
if (totalFiles === 0) {
if (uploadProgressDiv) uploadProgressDiv.style.display = 'none';
if (uploadProgressDiv) uploadProgressDiv.classList.add('hidden');
return;
}
@@ -678,8 +678,8 @@ const fileOps = {
}
const dropzone = document.getElementById('dropzone');
if (dropzone) dropzone.style.display = 'none';
if (uploadProgressDiv) uploadProgressDiv.style.display = 'none';
if (dropzone) dropzone.classList.add('hidden');
if (uploadProgressDiv) uploadProgressDiv.classList.add('hidden');
} finally {
this._isUploading = false;
}
+12 -7
View File
@@ -157,7 +157,7 @@ const sharedView = {
</div>
<!-- Share Edit Dialog (sharedView-specific) -->
<div id="shared-view-edit-dialog" class="shared-dialog">
<div id="shared-view-edit-dialog" class="shared-dialog hidden">
<div class="shared-dialog-content">
<div class="shared-dialog-header">
<span id="sv-dialog-icon">📄</span>
@@ -196,7 +196,7 @@ const sharedView = {
</div>
<!-- Notification Dialog (sharedView-specific) -->
<div id="sv-notification-dialog" class="shared-dialog">
<div id="sv-notification-dialog" class="shared-dialog hidden">
<div class="shared-dialog-content">
<div class="shared-dialog-header">
<span id="sv-notify-dialog-icon">📧</span>
@@ -493,12 +493,12 @@ const sharedView = {
}
}
shareDialog.classList.add('active');
shareDialog.classList.remove('hidden');
},
closeShareDialog() {
const d = document.getElementById('shared-view-edit-dialog');
if (d) d.classList.remove('active');
if (d) d.classList.add('hidden');
this.currentItem = null;
},
@@ -516,12 +516,12 @@ const sharedView = {
if (nameEl) nameEl.textContent = dn;
if (emailEl) emailEl.value = '';
if (msgEl) msgEl.value = '';
d.classList.add('active');
d.classList.remove('hidden');
},
closeNotificationDialog() {
const d = document.getElementById('sv-notification-dialog');
if (d) d.classList.remove('active');
if (d) d.classList.add('hidden');
this.currentItem = null;
},
@@ -575,6 +575,7 @@ const sharedView = {
};
try {
// FIXME: redundance with fileSharing
const res = await fetch(`/api/shares/${this.currentItem.id}`, {
method: 'PUT',
headers: this._headers(true),
@@ -589,7 +590,8 @@ const sharedView = {
console.error('Error updating share:', err);
this.showNotification(err.message || 'Error updating share', 'error');
}
// update UI
ui.setSharedVisualState(this.currentItem.item_id, this.currentItem.item_type, true);
this.closeShareDialog();
await this.loadItems(true);
this.filterAndSortItems();
@@ -600,6 +602,7 @@ const sharedView = {
if (!this.currentItem) return;
try {
// FIXME: redundance with fileSharing
const res = await fetch(`/api/shares/${this.currentItem.id}`, {
method: 'DELETE',
headers: this._headers()
@@ -614,6 +617,8 @@ const sharedView = {
this.closeShareDialog();
await this.loadItems(true);
this.filterAndSortItems();
// update UI
ui.setSharedVisualState(this.currentItem.item_id, this.currentItem.item_type, this.isShared(this.currentItem.item_id, this.currentItem.item_type));
},
// Send notification (stub)