Add toggle for grid, list and compact list views

This commit is contained in:
Kylian Schmidt
2025-07-22 13:19:53 +02:00
parent dced82a56f
commit 3e2aaa4be8
8 changed files with 648 additions and 13 deletions
+3 -3
View File
@@ -9,7 +9,7 @@ import { RecentPlotsManager } from './recent-plots-manager.js';
import { ComparisonManager } from './comparison-manager.js';
import { StatsManager } from './stats-manager.js';
import { KeyboardManager } from './keyboard-manager.js';
import { ExportManager } from './export-manager.js';
import { ViewManager } from './view-manager.js';
import { Utils } from './utils.js';
/**
@@ -29,7 +29,7 @@ export class GalleryApp {
this.recentPlotsManager = new RecentPlotsManager(this.MAX_RECENT_PLOTS);
this.comparisonManager = new ComparisonManager();
this.statsManager = new StatsManager();
this.exportManager = new ExportManager();
this.viewManager = new ViewManager();
this.keyboardManager = new KeyboardManager(this);
this.utils = Utils;
@@ -38,7 +38,7 @@ export class GalleryApp {
window.searchManager = this.searchManager;
window.recentPlotsManager = this.recentPlotsManager;
window.comparisonManager = this.comparisonManager;
window.exportManager = this.exportManager;
window.viewManager = this.viewManager;
window.utils = this.utils;
this.init();
+7
View File
@@ -39,6 +39,13 @@ export class KeyboardManager {
}
}
if (e.ctrlKey && e.key === 'v') {
e.preventDefault();
if (this.app.viewManager) {
this.app.viewManager.cycleView();
}
}
if (e.key === 'F5') {
e.preventDefault();
if (this.app.utils && this.app.utils.refreshGallery) {
+203
View File
@@ -0,0 +1,203 @@
/**
* View Controls Manager - handles switching between grid, list-large, and list-compact views
*/
export class ViewManager {
constructor() {
this.currentView = 'grid';
this.init();
}
/**
* Initialize view controls
*/
init() {
this.setupViewButtons();
this.loadSavedView();
this.updateControlsVisibility();
}
/**
* Update visibility of view controls based on plot content
*/
updateControlsVisibility() {
const plotContainer = document.getElementById('plotContainer');
const viewControls = document.querySelector('.view-controls');
if (!plotContainer || !viewControls) return;
const hasPlots = plotContainer.children.length > 0;
viewControls.style.display = hasPlots ? 'flex' : 'none';
}
/**
* Setup view toggle buttons
*/
setupViewButtons() {
const viewButtons = document.querySelectorAll('.view-btn');
console.log('ViewManager: Found', viewButtons.length, 'view buttons');
viewButtons.forEach(button => {
button.addEventListener('click', (e) => {
const newView = button.getAttribute('data-view');
console.log('ViewManager: Switching to view:', newView);
this.switchView(newView);
});
});
}
/**
* Switch to a different view mode
*/
switchView(viewMode) {
console.log('ViewManager: switchView called with:', viewMode, 'current:', this.currentView);
if (viewMode === this.currentView) return;
const plotContainer = document.getElementById('plotContainer');
const viewButtons = document.querySelectorAll('.view-btn');
if (!plotContainer) {
console.error('ViewManager: plotContainer not found');
return;
}
console.log('ViewManager: Plot container found, classes before:', plotContainer.className);
// Remove current view class
plotContainer.classList.remove(
'grid-view',
'list-large-view',
'list-compact-view'
);
// Add new view class
switch (viewMode) {
case 'grid':
plotContainer.classList.add('grid-view');
break;
case 'list-large':
plotContainer.classList.add('list-large-view');
break;
case 'list-compact':
plotContainer.classList.add('list-compact-view');
break;
default:
plotContainer.classList.add('grid-view');
viewMode = 'grid';
}
console.log('ViewManager: Plot container classes after:', plotContainer.className);
// Update button states
viewButtons.forEach(btn => {
if (btn.getAttribute('data-view') === viewMode) {
btn.classList.add('active');
} else {
btn.classList.remove('active');
}
});
// Save the preference
this.currentView = viewMode;
this.saveViewPreference(viewMode);
// Trigger any necessary layout updates
this.onViewChanged(viewMode);
}
/**
* Save view preference to localStorage
*/
saveViewPreference(viewMode) {
try {
localStorage.setItem('gallery-view-mode', viewMode);
} catch (e) {
// Ignore localStorage errors
}
}
/**
* Load saved view preference
*/
loadSavedView() {
try {
const savedView = localStorage.getItem('gallery-view-mode');
if (savedView && ['grid', 'list-large', 'list-compact'].includes(savedView)) {
this.switchView(savedView);
}
} catch (e) {
// Ignore localStorage errors, use default
}
}
/**
* Handle view change events - can be extended for additional functionality
*/
onViewChanged(viewMode) {
// Dispatch custom event for other components that might need to know
const event = new CustomEvent('viewChanged', {
detail: { viewMode }
});
document.dispatchEvent(event);
// Update any other UI elements that depend on view mode
this.updateUIForView(viewMode);
}
/**
* Update UI elements based on current view
*/
updateUIForView(viewMode) {
// You can add view-specific UI updates here
// For example, adjusting search result highlighting, etc.
// Update any tooltips or help text
const viewButtons = document.querySelectorAll('.view-btn');
viewButtons.forEach(btn => {
const btnView = btn.getAttribute('data-view');
if (btnView === viewMode) {
btn.style.transform = 'scale(1.05)';
} else {
btn.style.transform = 'scale(1)';
}
});
}
/**
* Get current view mode
*/
getCurrentView() {
return this.currentView;
}
/**
* Refresh controls visibility (call this when gallery content changes)
*/
refresh() {
this.updateControlsVisibility();
}
/**
* Check if current view is grid mode
*/
isGridView() {
return this.currentView === 'grid';
}
/**
* Check if current view is list mode (either variant)
*/
isListView() {
return this.currentView === 'list-large' || this.currentView === 'list-compact';
}
/**
* Cycle through view modes (useful for keyboard shortcuts)
*/
cycleView() {
const views = ['grid', 'list-large', 'list-compact'];
const currentIndex = views.indexOf(this.currentView);
const nextIndex = (currentIndex + 1) % views.length;
this.switchView(views[nextIndex]);
}
}