style: apply linter suggestions
This commit is contained in:
@@ -115,7 +115,7 @@ async function checkAuthentication() {
|
||||
window.location.href = '/login?source=session_expired';
|
||||
return;
|
||||
}
|
||||
} catch (err) {
|
||||
} catch (_err) {
|
||||
localStorage.removeItem(USER_DATA_KEY);
|
||||
window.location.href = '/login?source=session_expired';
|
||||
return;
|
||||
@@ -128,9 +128,11 @@ async function checkAuthentication() {
|
||||
console.log('No cached user data, fetching from server');
|
||||
try {
|
||||
const freshData = await refreshUserData();
|
||||
if (freshData && freshData.username) {
|
||||
if (freshData?.username) {
|
||||
const userInitials = freshData.username.substring(0, 2).toUpperCase();
|
||||
document.querySelectorAll('.user-avatar, .user-menu-avatar').forEach((el) => (el.textContent = userInitials));
|
||||
document.querySelectorAll('.user-avatar, .user-menu-avatar').forEach((el) => {
|
||||
el.textContent = userInitials;
|
||||
});
|
||||
window.updateStorageUsageDisplay(freshData);
|
||||
resolveHomeFolder().then(() => window.loadFiles());
|
||||
} else {
|
||||
|
||||
@@ -35,7 +35,7 @@ async function getFolder(id) {
|
||||
cache: 'no-store'
|
||||
};
|
||||
|
||||
let folderInformations = await fetch(`/api/folders/${id}`, requestOptions);
|
||||
const folderInformations = await fetch(`/api/folders/${id}`, requestOptions);
|
||||
if (folderInformations.ok) {
|
||||
return folderInformations.json();
|
||||
} else {
|
||||
@@ -67,7 +67,7 @@ async function rebuildBreadCrumb() {
|
||||
while (id !== null) {
|
||||
console.log(`fetching folder information for folder ${id}`);
|
||||
try {
|
||||
let folderInfo = await getFolder(id);
|
||||
const folderInfo = await getFolder(id);
|
||||
|
||||
// store the Leaf which is the current folder
|
||||
if (currentFolderInfo === null) {
|
||||
@@ -84,7 +84,7 @@ async function rebuildBreadCrumb() {
|
||||
|
||||
// iterate to parent folder
|
||||
id = folderInfo.parent_id;
|
||||
} catch (e) {
|
||||
} catch (_e) {
|
||||
console.log(`Error loading information from folder ${app.currentPath}, falling back to ${app.userHomeFolderId}`);
|
||||
// fallback of root
|
||||
window.uiNotifications.show(
|
||||
@@ -110,7 +110,6 @@ async function rebuildBreadCrumb() {
|
||||
*/
|
||||
async function loadFiles(options = { insertHistory: true }) {
|
||||
const app = window.app;
|
||||
const elements = window.appElements;
|
||||
|
||||
try {
|
||||
console.log('Starting loadFiles() - loading files...', options);
|
||||
@@ -125,7 +124,7 @@ async function loadFiles(options = { insertHistory: true }) {
|
||||
window.isLoadingFiles = true;
|
||||
|
||||
// This to avoid blinking page, a better solution would be to put loading on an overlay and remove timeout
|
||||
let loadingFiles = setTimeout(() => {
|
||||
const loadingFiles = setTimeout(() => {
|
||||
// display loader after few delay (will be canceled if result take less time)
|
||||
window.ui.showError(`
|
||||
<div class="files-loading-spinner">
|
||||
@@ -139,7 +138,7 @@ async function loadFiles(options = { insertHistory: true }) {
|
||||
await window.resolveHomeFolder();
|
||||
}
|
||||
|
||||
const timestamp = new Date().getTime();
|
||||
const timestamp = Math.floor(Date.now() / 1000);
|
||||
|
||||
await rebuildBreadCrumb();
|
||||
|
||||
@@ -181,7 +180,6 @@ async function loadFiles(options = { insertHistory: true }) {
|
||||
|
||||
if (forceRefresh) {
|
||||
url += `&force_refresh=true`;
|
||||
// @ts-ignore
|
||||
requestOptions.headers['X-Force-Refresh'] = 'true';
|
||||
console.log('Forcing complete refresh ignoring cache');
|
||||
}
|
||||
@@ -226,7 +224,7 @@ async function loadFiles(options = { insertHistory: true }) {
|
||||
let fileFound = null;
|
||||
|
||||
// lookup for the given fle
|
||||
for( const file of fileList) {
|
||||
for (const file of fileList) {
|
||||
if (file.id === window.app.viewFile) {
|
||||
fileFound = file;
|
||||
break;
|
||||
@@ -236,14 +234,13 @@ async function loadFiles(options = { insertHistory: true }) {
|
||||
if (fileFound) {
|
||||
console.log(`file ${window.app.viewFile} found, calling viewer`);
|
||||
await window.inlineViewer.openFile(fileFound);
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
// remove file
|
||||
console.log(`file ${window.app.viewFile} not found`);
|
||||
window.app.viewFile = null;
|
||||
|
||||
// correct url/history as file is not found
|
||||
window.updateHistory( false);
|
||||
window.updateHistory(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+24
-20
@@ -126,7 +126,7 @@ function setActionsBarMode(mode, force = false) {
|
||||
elements.gridViewBtn = document.getElementById('grid-view-btn');
|
||||
elements.listViewBtn = document.getElementById('list-view-btn');
|
||||
|
||||
if (window.i18n && window.i18n.translateElement) {
|
||||
if (window.i18n?.translateElement) {
|
||||
window.i18n.translateElement(elements.actionsBar);
|
||||
}
|
||||
|
||||
@@ -231,8 +231,8 @@ function deserializeHash() {
|
||||
|
||||
if (hash_elements[1] === 'files' && hash_elements[2] === 'folder' && hash_elements[3] !== null) {
|
||||
hashContext.path = hash_elements[3];
|
||||
|
||||
if (hash_elements[4] == 'file' && hash_elements[5] !== null) {
|
||||
|
||||
if (hash_elements[4] === 'file' && hash_elements[5] !== null) {
|
||||
hashContext.file = hash_elements[5];
|
||||
}
|
||||
}
|
||||
@@ -248,7 +248,7 @@ function deserializeHash() {
|
||||
function updateHistory(insertHistory) {
|
||||
const app = window.app;
|
||||
|
||||
let historyData = {
|
||||
const historyData = {
|
||||
section: app.currentSection,
|
||||
id: app.currentFolder,
|
||||
file: app.viewFile
|
||||
@@ -261,7 +261,7 @@ function updateHistory(insertHistory) {
|
||||
historyUrl = historyUrl.concat('/folder/', app.currentFolderInfo.id);
|
||||
|
||||
if (window.app.viewFile) {
|
||||
historyUrl = historyUrl.concat('/file/', window.app.viewFile);
|
||||
historyUrl = historyUrl.concat('/file/', window.app.viewFile);
|
||||
}
|
||||
// update title
|
||||
document.title = `OxiCloud: ${app.currentFolderInfo.path}`;
|
||||
@@ -325,7 +325,7 @@ function initApp() {
|
||||
cacheElements();
|
||||
|
||||
// Initialize file sharing module first
|
||||
if (window.fileSharing && window.fileSharing.init) {
|
||||
if (window.fileSharing?.init) {
|
||||
window.fileSharing.init();
|
||||
} else {
|
||||
console.warn('fileSharing module not fully initialized');
|
||||
@@ -349,7 +349,7 @@ function initApp() {
|
||||
}
|
||||
|
||||
// Initialize favorites module if available
|
||||
if (window.favorites && window.favorites.init) {
|
||||
if (window.favorites?.init) {
|
||||
console.log('Initializing favorites module');
|
||||
window.favorites.init();
|
||||
} else {
|
||||
@@ -357,7 +357,7 @@ function initApp() {
|
||||
}
|
||||
|
||||
// Initialize recent files module if available
|
||||
if (window.recent && window.recent.init) {
|
||||
if (window.recent?.init) {
|
||||
console.log('Initializing recent files module');
|
||||
window.recent.init();
|
||||
} else {
|
||||
@@ -365,21 +365,21 @@ function initApp() {
|
||||
}
|
||||
|
||||
// Initialize multi-select / batch actions
|
||||
if (window.multiSelect && window.multiSelect.init) {
|
||||
if (window.multiSelect?.init) {
|
||||
console.log('Initializing multi-select module');
|
||||
window.multiSelect.init();
|
||||
}
|
||||
|
||||
window.addEventListener('authenticationDone', () => {
|
||||
// Check if a context was provided in the URL
|
||||
let hashContext = deserializeHash();
|
||||
const hashContext = deserializeHash();
|
||||
switchSectionTo(hashContext.section);
|
||||
if (hashContext.section === 'files') {
|
||||
if (hashContext.path) {
|
||||
console.log(`init: reusing folder from hash URL: ${hashContext.path}`);
|
||||
window.app.currentPath = hashContext.path;
|
||||
}
|
||||
|
||||
|
||||
if (hashContext.file !== null) {
|
||||
window.app.viewFile = hashContext.file;
|
||||
}
|
||||
@@ -388,7 +388,7 @@ function initApp() {
|
||||
});
|
||||
|
||||
// Wait for translations to load before checking authentication
|
||||
if (window.i18n && window.i18n.isLoaded && window.i18n.isLoaded()) {
|
||||
if (window.i18n?.isLoaded?.()) {
|
||||
// Translations already loaded, proceed with authentication
|
||||
window.checkAuthentication();
|
||||
} else {
|
||||
@@ -401,7 +401,7 @@ function initApp() {
|
||||
|
||||
// Set a timeout as a fallback in case translations take too long
|
||||
setTimeout(() => {
|
||||
if (!window.i18n || !window.i18n.isLoaded || !window.i18n.isLoaded()) {
|
||||
if (!window.i18n?.isLoaded?.()) {
|
||||
console.warn('Translations loading timeout, proceeding with authentication anyway');
|
||||
window.checkAuthentication();
|
||||
}
|
||||
@@ -451,7 +451,9 @@ function setupUploadDropdown() {
|
||||
e.stopPropagation();
|
||||
const isOpen = menu.classList.contains('show');
|
||||
// Close any other open dropdowns
|
||||
document.querySelectorAll('.upload-dropdown-menu.show').forEach((m) => m.classList.remove('show'));
|
||||
document.querySelectorAll('.upload-dropdown-menu.show').forEach((m) => {
|
||||
m.classList.remove('show');
|
||||
});
|
||||
if (!isOpen) {
|
||||
menu.classList.add('show');
|
||||
}
|
||||
@@ -462,14 +464,14 @@ function setupUploadDropdown() {
|
||||
// Close dropdown when clicking outside
|
||||
// remove+add stable handler: guarantees exactly one global listener
|
||||
if (uploadDropdownDocumentClickHandler) {
|
||||
// @ts-ignore
|
||||
document.removeEventListener('click', uploadDropdownDocumentClickHandler);
|
||||
}
|
||||
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.show').forEach((m) => {
|
||||
m.classList.remove('show');
|
||||
});
|
||||
};
|
||||
// @ts-ignore
|
||||
document.addEventListener('click', uploadDropdownDocumentClickHandler);
|
||||
}
|
||||
|
||||
@@ -587,13 +589,15 @@ function setupEventListeners() {
|
||||
elements.navItems.forEach((item) => {
|
||||
item.addEventListener('click', () => {
|
||||
// Remove active class from all nav items
|
||||
elements.navItems.forEach((navItem) => navItem.classList.remove('active'));
|
||||
elements.navItems.forEach((navItem) => {
|
||||
navItem.classList.remove('active');
|
||||
});
|
||||
|
||||
// Add active class to clicked item
|
||||
item.classList.add('active');
|
||||
let _updateHistory = true;
|
||||
|
||||
let itemI18nKey = item.querySelector('span').getAttribute('data-i18n');
|
||||
const itemI18nKey = item.querySelector('span').getAttribute('data-i18n');
|
||||
switch (itemI18nKey) {
|
||||
case 'nav.shared':
|
||||
// Switch to shared view
|
||||
@@ -712,7 +716,7 @@ function updateStorageUsageDisplay(userData) {
|
||||
storageInfo.removeAttribute('data-i18n');
|
||||
|
||||
// Use i18n if available
|
||||
if (window.i18n && window.i18n.t) {
|
||||
if (window.i18n?.t) {
|
||||
storageInfo.textContent = window.i18n.t('storage.used', {
|
||||
percentage: usagePercentage,
|
||||
used: usedFormatted,
|
||||
|
||||
@@ -127,7 +127,7 @@ function getSectionFromNavItem(navItem) {
|
||||
* @returns {boolean} true if the section changed
|
||||
*/
|
||||
function setCurrentSection(section) {
|
||||
if (window.app.currentSection == section) return false;
|
||||
if (window.app.currentSection === section) return false;
|
||||
|
||||
// Set all view flags - true for active section, false for others
|
||||
Object.entries(VIEW_FLAGS).forEach(([key, flag]) => {
|
||||
|
||||
@@ -42,7 +42,7 @@ async function performSearch(query, sortBy) {
|
||||
|
||||
document.addEventListener('search-resort', (e) => {
|
||||
const searchInput = document.querySelector('.search-container input');
|
||||
if (searchInput && searchInput.value.trim()) {
|
||||
if (searchInput?.value.trim()) {
|
||||
performSearch(searchInput.value.trim(), e.detail.sort_by);
|
||||
}
|
||||
});
|
||||
|
||||
@@ -8,7 +8,7 @@ async function loadTrashItems() {
|
||||
try {
|
||||
if (window.multiSelect) window.multiSelect.clear();
|
||||
window.ui.resetFilesList(); // ensure also list visible & error hidden
|
||||
const _tt = window.i18n && window.i18n.t ? window.i18n.t : (k) => k.split('.').pop();
|
||||
const _tt = window.i18n?.t ? window.i18n.t : (k) => k.split('.').pop();
|
||||
elements.filesList.innerHTML = `
|
||||
<div class="list-header trash-header">
|
||||
<div data-i18n="files.name">${_tt('files.name')}</div>
|
||||
@@ -53,8 +53,8 @@ function addTrashItemToView(item) {
|
||||
iconClass = item.icon_class || 'fas fa-folder';
|
||||
typeLabel = window.i18n ? window.i18n.t('files.file_types.folder') : 'Folder';
|
||||
} else {
|
||||
iconClass = item.icon_class || (window.ui && window.ui.getIconClass ? window.ui.getIconClass(item.name) : 'fas fa-file');
|
||||
iconSpecialClass = window.ui && window.ui.getIconSpecialClass ? window.ui.getIconSpecialClass(item.name) : '';
|
||||
iconClass = item.icon_class || (window.ui?.getIconClass ? window.ui.getIconClass(item.name) : 'fas fa-file');
|
||||
iconSpecialClass = window.ui?.getIconSpecialClass ? window.ui.getIconSpecialClass(item.name) : '';
|
||||
const cat = item.category || '';
|
||||
typeLabel = cat
|
||||
? window.i18n
|
||||
|
||||
+54
-56
@@ -359,7 +359,7 @@ const ui = {
|
||||
// First try directory-aware extraction (Finder folder drag & drop)
|
||||
const droppedEntries = await collectDroppedEntries(e.dataTransfer);
|
||||
if (droppedEntries && droppedEntries.length > 0) {
|
||||
const hasFolderStructure = droppedEntries.some((x) => x.relativePath && x.relativePath.includes('/'));
|
||||
const hasFolderStructure = droppedEntries.some((x) => x.relativePath?.includes('/'));
|
||||
if (hasFolderStructure) {
|
||||
fileOps.uploadFolderEntries(droppedEntries);
|
||||
} else {
|
||||
@@ -372,7 +372,7 @@ const ui = {
|
||||
}
|
||||
|
||||
// Detect folder drops: files from folder drops have webkitRelativePath set
|
||||
const hasRelativePaths = Array.from(e.dataTransfer.files).some((f) => f.webkitRelativePath && f.webkitRelativePath.includes('/'));
|
||||
const hasRelativePaths = Array.from(e.dataTransfer.files).some((f) => f.webkitRelativePath?.includes('/'));
|
||||
if (hasRelativePaths) {
|
||||
fileOps.uploadFolderFiles(e.dataTransfer.files);
|
||||
} else {
|
||||
@@ -415,7 +415,7 @@ const ui = {
|
||||
// First try directory-aware extraction (Finder folder drag & drop)
|
||||
const droppedEntries = await collectDroppedEntries(e.dataTransfer);
|
||||
if (droppedEntries && droppedEntries.length > 0) {
|
||||
const hasFolderStructure = droppedEntries.some((x) => x.relativePath && x.relativePath.includes('/'));
|
||||
const hasFolderStructure = droppedEntries.some((x) => x.relativePath?.includes('/'));
|
||||
if (hasFolderStructure) {
|
||||
fileOps.uploadFolderEntries(droppedEntries);
|
||||
} else {
|
||||
@@ -428,7 +428,7 @@ const ui = {
|
||||
}
|
||||
|
||||
// Detect folder drops: files from folder drops have webkitRelativePath set
|
||||
const hasRelativePaths = Array.from(e.dataTransfer.files).some((f) => f.webkitRelativePath && f.webkitRelativePath.includes('/'));
|
||||
const hasRelativePaths = Array.from(e.dataTransfer.files).some((f) => f.webkitRelativePath?.includes('/'));
|
||||
if (hasRelativePaths) {
|
||||
fileOps.uploadFolderFiles(e.dataTransfer.files);
|
||||
} else {
|
||||
@@ -474,13 +474,11 @@ const ui = {
|
||||
updateBreadcrumb() {
|
||||
const breadcrumb = document.querySelector('.breadcrumb');
|
||||
breadcrumb.innerHTML = '';
|
||||
|
||||
const self = this;
|
||||
const path = window.app.breadcrumbPath; // [{id, name}, ...]
|
||||
|
||||
// Helper function to safely get translation text
|
||||
const getTranslatedText = (key, defaultValue) => {
|
||||
if (!window.i18n || !window.i18n.t) return defaultValue;
|
||||
if (!window.i18n?.t) return defaultValue;
|
||||
return window.i18n.t(key);
|
||||
};
|
||||
|
||||
@@ -496,7 +494,7 @@ const ui = {
|
||||
homeIcon.addEventListener('click', () => {
|
||||
window.app.breadcrumbPath = [];
|
||||
window.app.currentPath = window.app.userHomeFolderId;
|
||||
self.updateBreadcrumb();
|
||||
this.updateBreadcrumb();
|
||||
window.loadFiles();
|
||||
});
|
||||
}
|
||||
@@ -535,7 +533,7 @@ const ui = {
|
||||
item.addEventListener('click', () => {
|
||||
window.app.breadcrumbPath = path.slice(0, index + 1);
|
||||
window.app.currentPath = segment.id;
|
||||
self.updateBreadcrumb();
|
||||
this.updateBreadcrumb();
|
||||
window.loadFiles();
|
||||
});
|
||||
|
||||
@@ -543,7 +541,7 @@ const ui = {
|
||||
// dragover – only folders are valid drop targets
|
||||
item.addEventListener('dragover', (e) => {
|
||||
const card = e.target.closest('span');
|
||||
if (!card || !card.dataset.folderId) return;
|
||||
if (!card?.dataset.folderId) return;
|
||||
e.preventDefault();
|
||||
card.classList.add('drop-target');
|
||||
});
|
||||
@@ -552,7 +550,7 @@ const ui = {
|
||||
item.addEventListener('dragleave', (e) => {
|
||||
console.log('dragleave ', e);
|
||||
const card = e.target.closest('span');
|
||||
if (!card || !card.dataset.folderId) return;
|
||||
if (!card?.dataset.folderId) return;
|
||||
card.classList.remove('drop-target');
|
||||
});
|
||||
|
||||
@@ -567,7 +565,7 @@ const ui = {
|
||||
card.classList.remove('drop-target');
|
||||
|
||||
const action = e.dataTransfer?.dropEffect;
|
||||
await self._dropToFolder(action, targetFolderId, e.dataTransfer);
|
||||
await this._dropToFolder(action, targetFolderId, e.dataTransfer);
|
||||
});
|
||||
} else {
|
||||
// Last segment: current location, not clickable
|
||||
@@ -693,7 +691,7 @@ const ui = {
|
||||
},
|
||||
|
||||
_upsertById(arr, item) {
|
||||
if (!Array.isArray(arr) || !item || !item.id) return;
|
||||
if (!Array.isArray(arr) || !item?.id) return;
|
||||
const idx = arr.findIndex((x) => x && x.id === item.id);
|
||||
if (idx >= 0) {
|
||||
arr[idx] = item;
|
||||
@@ -709,11 +707,11 @@ const ui = {
|
||||
* @param {any} dataTransfer fallback if nothing is selected
|
||||
*/
|
||||
async _dropToFolder(action, targetFolderId, dataTransfer) {
|
||||
let selection = window.multiSelect.getSelection(targetFolderId);
|
||||
const selection = window.multiSelect.getSelection(targetFolderId);
|
||||
|
||||
window.multiSelect.clear();
|
||||
|
||||
if (selection.fileIds.length == 0 && selection.folderIds.length == 0) {
|
||||
if (selection.fileIds.length === 0 && selection.folderIds.length === 0) {
|
||||
// try to use dataTransfer (direct move without selection)
|
||||
const id = dataTransfer.getData('text/plain');
|
||||
const isFolder = dataTransfer.getData('application/oxicloud-folder') === 'true';
|
||||
@@ -785,8 +783,6 @@ const ui = {
|
||||
if (!filesList) return;
|
||||
this._delegationReady = true;
|
||||
|
||||
const self = this;
|
||||
|
||||
// ── helpers ────────────────────────────────────────────────
|
||||
const itemInfo = (card) => {
|
||||
if (!card) return null;
|
||||
@@ -796,7 +792,7 @@ const ui = {
|
||||
type: 'file',
|
||||
id: fileId,
|
||||
name: card.dataset.fileName,
|
||||
data: self._items.get(fileId)
|
||||
data: this._items.get(fileId)
|
||||
};
|
||||
const folderId = card.dataset.folderId;
|
||||
if (folderId)
|
||||
@@ -804,7 +800,7 @@ const ui = {
|
||||
type: 'folder',
|
||||
id: folderId,
|
||||
name: card.dataset.folderName,
|
||||
data: self._items.get(folderId)
|
||||
data: this._items.get(folderId)
|
||||
};
|
||||
return null;
|
||||
};
|
||||
@@ -818,25 +814,23 @@ const ui = {
|
||||
// But NOT image files - those should be previewed in the inline viewer
|
||||
const ext = (file.name || '').split('.').pop().toLowerCase();
|
||||
const imageExts = ['jpg', 'jpeg', 'png', 'gif', 'svg', 'webp', 'bmp', 'ico', 'heic', 'heif', 'avif', 'tiff'];
|
||||
const isImage = (file.mime_type && file.mime_type.startsWith('image/')) || imageExts.includes(ext);
|
||||
const isImage = file.mime_type?.startsWith('image/') || imageExts.includes(ext);
|
||||
try {
|
||||
if (!isImage && window.wopiEditor && await window.wopiEditor.canEdit(file.name)) {
|
||||
await window.wopiEditor.openInModal(file.id, file.name, 'edit')
|
||||
if (!isImage && window.wopiEditor && (await window.wopiEditor.canEdit(file.name))) {
|
||||
await window.wopiEditor.openInModal(file.id, file.name, 'edit');
|
||||
return;
|
||||
}
|
||||
}
|
||||
catch (e) {
|
||||
} catch (e) {
|
||||
console.warn(`WOPI Editor failed, falling bck to classic view `, e);
|
||||
}
|
||||
|
||||
if (self.isViewableFile(file) || isImage) {
|
||||
if (this.isViewableFile(file) || isImage) {
|
||||
if (window.inlineViewer) {
|
||||
window.inlineViewer.openFile(file);
|
||||
// update history
|
||||
window.app.viewFile = file.id;
|
||||
window.updateHistory(false);
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
window.fileOps.downloadFile(file.id, file.name);
|
||||
}
|
||||
} else {
|
||||
@@ -849,7 +843,7 @@ const ui = {
|
||||
const folderName = card.dataset.folderName;
|
||||
window.app.breadcrumbPath.push({ id: folderId, name: folderName });
|
||||
window.app.currentPath = folderId;
|
||||
self.updateBreadcrumb();
|
||||
this.updateBreadcrumb();
|
||||
window.loadFiles();
|
||||
};
|
||||
|
||||
@@ -940,7 +934,7 @@ const ui = {
|
||||
window.contextMenus.syncFavoriteOptionLabels();
|
||||
}
|
||||
if (window.contextMenus && typeof window.contextMenus.syncWopiOptionVisibility === 'function') {
|
||||
window.contextMenus.syncWopiOptionVisibility().catch(function () {});
|
||||
window.contextMenus.syncWopiOptionVisibility().catch(() => {});
|
||||
}
|
||||
menu.style.left = `${e.pageX}px`;
|
||||
menu.style.top = `${e.pageY}px`;
|
||||
@@ -949,7 +943,7 @@ const ui = {
|
||||
|
||||
// dragstart
|
||||
filesList.addEventListener('dragstart', (e) => {
|
||||
let card = e.target.closest('.file-item');
|
||||
const card = e.target.closest('.file-item');
|
||||
if (!card) {
|
||||
e.preventDefault();
|
||||
return;
|
||||
@@ -968,11 +962,11 @@ const ui = {
|
||||
// allow copy or move (handled by the browser)
|
||||
e.dataTransfer.effectAllowed = 'copyMove';
|
||||
|
||||
self.draggedItems = document.createElement('div');
|
||||
self.draggedItems.className = 'dragged-items';
|
||||
this.draggedItems = document.createElement('div');
|
||||
this.draggedItems.className = 'dragged-items';
|
||||
|
||||
let selectedCardFromList = filesList.querySelectorAll(`div.selected > div.name-cell`);
|
||||
if (selectedCardFromList.length == 0) {
|
||||
if (selectedCardFromList.length === 0) {
|
||||
// fallback to current element
|
||||
selectedCardFromList = card.querySelectorAll('div.name-cell');
|
||||
}
|
||||
@@ -982,8 +976,8 @@ const ui = {
|
||||
let lastItemDiv = null;
|
||||
|
||||
while (index < selectedCardFromList.length && index < maxElements) {
|
||||
let iconCell = document.createElement('div');
|
||||
let icon = selectedCardFromList[index].getElementsByClassName('file-icon').item(0)?.cloneNode(true);
|
||||
const iconCell = document.createElement('div');
|
||||
const icon = selectedCardFromList[index].getElementsByClassName('file-icon').item(0)?.cloneNode(true);
|
||||
if (icon) {
|
||||
iconCell.appendChild(icon);
|
||||
iconCell.querySelectorAll('img')?.forEach((img) => {
|
||||
@@ -991,28 +985,28 @@ const ui = {
|
||||
});
|
||||
}
|
||||
|
||||
let nameCell = document.createElement('div');
|
||||
let name = selectedCardFromList[index].getElementsByTagName('span').item(0)?.cloneNode(true);
|
||||
const nameCell = document.createElement('div');
|
||||
const name = selectedCardFromList[index].getElementsByTagName('span').item(0)?.cloneNode(true);
|
||||
if (name) {
|
||||
nameCell.appendChild(name);
|
||||
}
|
||||
|
||||
let div = document.createElement('div');
|
||||
const div = document.createElement('div');
|
||||
div.className = 'file-item';
|
||||
div.appendChild(iconCell);
|
||||
div.appendChild(nameCell);
|
||||
|
||||
self.draggedItems.appendChild(div);
|
||||
this.draggedItems.appendChild(div);
|
||||
index += 1;
|
||||
lastItemDiv = div;
|
||||
}
|
||||
|
||||
// if more than 1 item, display the badge
|
||||
if (selectedCardFromList.length > 1) {
|
||||
let badge = document.createElement('span');
|
||||
const badge = document.createElement('span');
|
||||
badge.className = 'dragged-items-badge';
|
||||
badge.innerText = `${selectedCardFromList.length}`;
|
||||
self.draggedItems.appendChild(badge);
|
||||
this.draggedItems.appendChild(badge);
|
||||
}
|
||||
|
||||
// if more than maxElements display the fading
|
||||
@@ -1020,14 +1014,16 @@ const ui = {
|
||||
lastItemDiv.classList.add('fading');
|
||||
}
|
||||
|
||||
self.dragPreview.appendChild(self.draggedItems);
|
||||
e.dataTransfer.setDragImage(self.draggedItems, 0, 0);
|
||||
this.dragPreview.appendChild(this.draggedItems);
|
||||
e.dataTransfer.setDragImage(this.draggedItems, 0, 0);
|
||||
});
|
||||
|
||||
// dragend
|
||||
filesList.addEventListener('dragend', (e) => {
|
||||
self.dragPreview.removeChild(self.draggedItems);
|
||||
document.querySelectorAll('.drop-target').forEach((el) => el.classList.remove('drop-target'));
|
||||
filesList.addEventListener('dragend', (_e) => {
|
||||
this.dragPreview.removeChild(this.draggedItems);
|
||||
document.querySelectorAll('.drop-target').forEach((el) => {
|
||||
el.classList.remove('drop-target');
|
||||
});
|
||||
});
|
||||
|
||||
// dragover – only folders are valid drop targets
|
||||
@@ -1057,7 +1053,7 @@ const ui = {
|
||||
card.classList.remove('drop-target');
|
||||
|
||||
const action = e.dataTransfer.dropEffect;
|
||||
await self._dropToFolder(action, targetFolderId, e.dataTransfer);
|
||||
await this._dropToFolder(action, targetFolderId, e.dataTransfer);
|
||||
});
|
||||
},
|
||||
|
||||
@@ -1111,8 +1107,8 @@ const ui = {
|
||||
|
||||
// SVG icon path (after icons.js replacement)
|
||||
const svg = starBtn.querySelector('svg');
|
||||
const filledPath = window.OxiIcons && window.OxiIcons['star'];
|
||||
const outlinePath = window.OxiIcons && window.OxiIcons['star-outline'];
|
||||
const filledPath = window.OxiIcons?.star;
|
||||
const outlinePath = window.OxiIcons?.['star-outline'];
|
||||
const targetPath = isFavorite ? filledPath : outlinePath;
|
||||
if (svg && targetPath) {
|
||||
const p = svg.querySelector('path');
|
||||
@@ -1159,7 +1155,7 @@ const ui = {
|
||||
el.dataset.folderName = folder.name;
|
||||
el.dataset.parentId = folder.parent_id || '';
|
||||
|
||||
const isFav = window.favorites && window.favorites.isFavorite(folder.id, 'folder');
|
||||
const isFav = window.favorites?.isFavorite(folder.id, 'folder');
|
||||
const formattedDate = window.formatDateTime(folder.modified_at);
|
||||
|
||||
el.innerHTML = `
|
||||
@@ -1203,7 +1199,7 @@ const ui = {
|
||||
: 'Document';
|
||||
const fileSize = file.size_formatted || window.formatFileSize(file.size);
|
||||
const formattedDate = window.formatDateTime(file.modified_at);
|
||||
const isFav = window.favorites && window.favorites.isFavorite(file.id, 'file');
|
||||
const isFav = window.favorites?.isFavorite(file.id, 'file');
|
||||
|
||||
const el = document.createElement('div');
|
||||
el.className = 'file-item';
|
||||
@@ -1213,7 +1209,7 @@ const ui = {
|
||||
el.setAttribute('draggable', 'true');
|
||||
|
||||
el.innerHTML = `
|
||||
|
||||
|
||||
<div class="checkbox-cell"><input type="checkbox" class="item-checkbox"></div>
|
||||
<div class="name-cell">
|
||||
<div class="file-icon ${iconSpecialClass}">
|
||||
@@ -1262,7 +1258,7 @@ const ui = {
|
||||
<div></div><!-- actions -->
|
||||
</div>`;
|
||||
|
||||
if (window.i18n && window.i18n.translateElement) window.i18n.translateElement(filesList);
|
||||
if (window.i18n?.translateElement) window.i18n.translateElement(filesList);
|
||||
|
||||
filesList.classList.remove('hidden');
|
||||
filesContainerError?.classList.add('hidden');
|
||||
@@ -1286,7 +1282,7 @@ const ui = {
|
||||
const filesList = document.getElementById('files-list');
|
||||
if (filesContainerError) filesContainerError.innerHTML = content;
|
||||
|
||||
if (window.i18n && window.i18n.translateElement) window.i18n.translateElement(filesContainerError);
|
||||
if (window.i18n?.translateElement) window.i18n.translateElement(filesContainerError);
|
||||
|
||||
filesContainerError?.classList.remove('hidden');
|
||||
filesList?.classList.add('hidden');
|
||||
@@ -1384,7 +1380,9 @@ function toggleCardSelection(card, event) {
|
||||
*/
|
||||
function showContextMenuAtElement(triggerElement, menuId) {
|
||||
// Hide any open menus first
|
||||
document.querySelectorAll('.context-menu').forEach((m) => (m.style.display = 'none'));
|
||||
document.querySelectorAll('.context-menu').forEach((m) => {
|
||||
m.style.display = 'none';
|
||||
});
|
||||
|
||||
const menu = document.getElementById(menuId);
|
||||
if (!menu) return;
|
||||
@@ -1406,7 +1404,7 @@ function showContextMenuAtElement(triggerElement, menuId) {
|
||||
window.contextMenus.syncFavoriteOptionLabels();
|
||||
}
|
||||
if (window.contextMenus && typeof window.contextMenus.syncWopiOptionVisibility === 'function') {
|
||||
window.contextMenus.syncWopiOptionVisibility().catch(function () {});
|
||||
window.contextMenus.syncWopiOptionVisibility().catch(() => {});
|
||||
}
|
||||
|
||||
menu.style.left = `${left}px`;
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
const uiFileTypes = {
|
||||
// TODO: 'd better to use a canViw() method in inlineViewer
|
||||
isViewableFile(file) {
|
||||
if (!file || !file.mime_type) return false;
|
||||
if (!file?.mime_type) return false;
|
||||
if (file.mime_type.startsWith('image/')) return true;
|
||||
if (file.mime_type === 'application/pdf') return true;
|
||||
if (file.mime_type.startsWith('audio/')) return true;
|
||||
|
||||
@@ -171,7 +171,7 @@ function updateUserMenuData() {
|
||||
const quotaBytes = userData.storage_quota_bytes == null ? 10 * 1024 * 1024 * 1024 : userData.storage_quota_bytes;
|
||||
const percentage = quotaBytes > 0 ? Math.min(Math.round((usedBytes / quotaBytes) * 100), 100) : 0;
|
||||
|
||||
if (storageFill) storageFill.style.width = percentage + '%';
|
||||
if (storageFill) storageFill.style.width = `${percentage}%`;
|
||||
if (storageText) {
|
||||
const used = window.formatFileSize(usedBytes);
|
||||
const total = window.formatQuotaSize(quotaBytes);
|
||||
@@ -206,7 +206,7 @@ function showUserProfileModal() {
|
||||
const percentage = quotaBytes > 0 ? Math.min(Math.round((usedBytes / quotaBytes) * 100), 100) : 0;
|
||||
const barColor = percentage > 90 ? '#ef4444' : percentage > 70 ? '#f59e0b' : '#22c55e';
|
||||
|
||||
const t = (key, fallback) => (window.i18n && window.i18n.t ? window.i18n.t(key) || fallback : fallback);
|
||||
const t = (key, fallback) => (window.i18n?.t ? window.i18n.t(key) || fallback : fallback);
|
||||
|
||||
const existing = document.getElementById('profile-modal-overlay');
|
||||
if (existing) existing.remove();
|
||||
@@ -220,7 +220,7 @@ function showUserProfileModal() {
|
||||
<div class="about-modal-avatar">${initials}</div>
|
||||
<h3 class="about-modal-username">${username}</h3>
|
||||
<p class="about-modal-email">${email}</p>
|
||||
<span class="about-modal-role ${role === 'admin' ? 'about-modal-role-admin' : 'about-modal-role-user'}">${role === 'admin' ? '🛡️ Admin' : '👤 ' + t('user_menu.role_user', 'User')}</span>
|
||||
<span class="about-modal-role ${role === 'admin' ? 'about-modal-role-admin' : 'about-modal-role-user'}">${role === 'admin' ? '🛡️ Admin' : `👤 ${t('user_menu.role_user', 'User')}`}</span>
|
||||
</div>
|
||||
<div class="about-modal-storage">
|
||||
<div class="about-modal-storage-label">
|
||||
@@ -240,7 +240,7 @@ function showUserProfileModal() {
|
||||
// Set dynamic bar width and color via JS property (CSP-safe)
|
||||
const barFill = overlay.querySelector('#about-bar-fill');
|
||||
if (barFill) {
|
||||
barFill.style.width = percentage + '%';
|
||||
barFill.style.width = `${percentage}%`;
|
||||
barFill.style.background = barColor;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user