feat(frontend): i18n expansion, admin/profile i18n, grid/list view fix, empty state

- Add 5 new locales (hi, ar, ru, ja, ko) — now 14 total
- Admin panel: 117 i18n keys, confirm modal, animated tabs, no inline handlers
- Profile page: 58 i18n keys with data-i18n attributes
- Fix i18n safeT() shadowing bug and translationsLoaded timing
- Fix grid/list view: list header no longer shows in grid mode on login
- Fix classList.toggle hidden sync for view switching across all nav functions
- Revert .hidden important that broke login page rendering
- Add files empty state (no_files + empty_hint) with translations
- Fix language selector dropdown scroll and styling
- Fix admin panel scroll with sticky tabs
This commit is contained in:
Diocrafts
2026-03-09 00:08:34 +01:00
parent f409a9edd7
commit df336da679
43 changed files with 6645 additions and 2043 deletions
+13 -2
View File
@@ -110,8 +110,19 @@ async function loadFiles(options = {}) {
const folderList = Array.isArray(listing.folders) ? listing.folders : [];
const fileList = Array.isArray(listing.files) ? listing.files : [];
window.ui.renderFolders(folderList);
window.ui.renderFiles(fileList);
if (folderList.length === 0 && fileList.length === 0) {
const emptyState = document.createElement('div');
emptyState.className = 'empty-state';
emptyState.innerHTML = `
<i class="fas fa-folder-open empty-state-icon"></i>
<p>${_t('files.no_files')}</p>
<p>${_t('files.empty_hint')}</p>
`;
elements.filesGrid.appendChild(emptyState);
} else {
window.ui.renderFolders(folderList);
window.ui.renderFiles(fileList);
}
console.log(`Loaded ${folderList.length} folders and ${fileList.length} files`);
} catch (error) {
+4 -2
View File
@@ -473,8 +473,8 @@ function setupEventListeners() {
// Show files containers (to be filled with trash)
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';
if (filesGrid) { filesGrid.style.display = app.currentView === 'grid' ? 'grid' : 'none'; filesGrid.classList.toggle('hidden', app.currentView !== 'grid'); }
if (filesListView) { filesListView.style.display = app.currentView === 'list' ? 'flex' : 'none'; filesListView.classList.toggle('hidden', app.currentView !== 'list'); }
// Update UI
elements.pageTitle.textContent = window.i18n ? window.i18n.t('nav.trash') : 'Trash';
@@ -494,6 +494,8 @@ function setupEventListeners() {
const savedView = localStorage.getItem('oxicloud-view');
if (savedView === 'list') {
ui.switchToListView();
} else {
ui.switchToGridView();
}
// User menu
+41 -5
View File
@@ -3,6 +3,34 @@
* Extracted from main.js to keep navigation concerns isolated.
*/
/**
* Sync the hidden class and inline display for the grid/list containers
* based on the current view preference.
*/
function syncViewContainers() {
const filesGrid = document.getElementById('files-grid');
const filesListView = document.getElementById('files-list-view');
const isGrid = window.app.currentView === 'grid';
if (filesGrid) {
filesGrid.style.display = isGrid ? 'grid' : 'none';
filesGrid.classList.toggle('hidden', !isGrid);
}
if (filesListView) {
filesListView.style.display = isGrid ? 'none' : 'flex';
filesListView.classList.toggle('hidden', isGrid);
}
}
/**
* Hide both grid and list containers (used when switching to non-file views).
*/
function hideFileContainers() {
const filesGrid = document.getElementById('files-grid');
const filesListView = document.getElementById('files-list-view');
if (filesGrid) { filesGrid.style.display = 'none'; filesGrid.classList.add('hidden'); }
if (filesListView) { filesListView.style.display = 'none'; filesListView.classList.add('hidden'); }
}
/**
* Mobile sidebar toggle functionality
*/
@@ -136,6 +164,8 @@ function switchToSharedView() {
const filesListView = document.getElementById('files-list-view');
if (filesGrid) filesGrid.style.display = 'none';
if (filesListView) filesListView.style.display = 'none';
if (filesGrid) filesGrid.classList.add('hidden');
if (filesListView) filesListView.classList.add('hidden');
// Show shared view
if (window.sharedView) {
@@ -157,7 +187,9 @@ function switchToFilesView() {
const filesGrid = document.getElementById('files-grid');
const filesListView = document.getElementById('files-list-view');
if (filesGrid) filesGrid.style.display = window.app.currentView === 'grid' ? 'grid' : 'none';
if (filesListView) filesListView.style.display = window.app.currentView === 'list' ? 'block' : 'none';
if (filesGrid) filesGrid.classList.toggle('hidden', window.app.currentView !== 'grid');
if (filesListView) filesListView.style.display = window.app.currentView === 'list' ? 'flex' : 'none';
if (filesListView) filesListView.classList.toggle('hidden', window.app.currentView !== 'list');
// Reset to home folder and update breadcrumb
window.app.currentPath = window.app.userHomeFolderId || '';
@@ -180,7 +212,9 @@ function switchToFavoritesView() {
const filesGrid = document.getElementById('files-grid');
const filesListView = document.getElementById('files-list-view');
if (filesGrid) filesGrid.style.display = window.app.currentView === 'grid' ? 'grid' : 'none';
if (filesListView) filesListView.style.display = window.app.currentView === 'list' ? 'block' : 'none';
if (filesGrid) filesGrid.classList.toggle('hidden', window.app.currentView !== 'grid');
if (filesListView) filesListView.style.display = window.app.currentView === 'list' ? 'flex' : 'none';
if (filesListView) filesListView.classList.toggle('hidden', window.app.currentView !== 'list');
if (window.favorites) {
window.favorites.displayFavorites();
@@ -211,7 +245,9 @@ function switchToRecentFilesView() {
const filesGrid = document.getElementById('files-grid');
const filesListView = document.getElementById('files-list-view');
if (filesGrid) filesGrid.style.display = window.app.currentView === 'grid' ? 'grid' : 'none';
if (filesListView) filesListView.style.display = window.app.currentView === 'list' ? 'block' : 'none';
if (filesGrid) filesGrid.classList.toggle('hidden', window.app.currentView !== 'grid');
if (filesListView) filesListView.style.display = window.app.currentView === 'list' ? 'flex' : 'none';
if (filesListView) filesListView.classList.toggle('hidden', window.app.currentView !== 'list');
if (window.recent) {
window.recent.displayRecentFiles();
@@ -242,8 +278,8 @@ function switchToPhotosView() {
// Hide file containers
const filesGrid = document.getElementById('files-grid');
const filesListView = document.getElementById('files-list-view');
if (filesGrid) filesGrid.style.display = 'none';
if (filesListView) filesListView.style.display = 'none';
if (filesGrid) { filesGrid.style.display = 'none'; filesGrid.classList.add('hidden'); }
if (filesListView) { filesListView.style.display = 'none'; filesListView.classList.add('hidden'); }
// Show photos view
if (window.photosView) {
+4
View File
@@ -450,7 +450,9 @@ const ui = {
this._hydrateViewIfNeeded('grid');
filesGrid.style.display = 'grid';
filesGrid.classList.remove('hidden');
filesListView.style.display = 'none';
filesListView.classList.add('hidden');
gridViewBtn.classList.add('active');
listViewBtn.classList.remove('active');
window.app.currentView = 'grid';
@@ -469,7 +471,9 @@ const ui = {
this._hydrateViewIfNeeded('list');
filesGrid.style.display = 'none';
filesGrid.classList.add('hidden');
filesListView.style.display = 'flex';
filesListView.classList.remove('hidden');
gridViewBtn.classList.remove('active');
listViewBtn.classList.add('active');
window.app.currentView = 'list';