feat(settings): allow hiding folder sidebar

This commit is contained in:
pixelpaws
2025-11-03 06:39:13 +08:00
parent 1f9f821576
commit 94e0308a12
19 changed files with 163 additions and 11 deletions

View File

@@ -31,6 +31,9 @@ export class SidebarManager {
this.dragHandlersInitialized = false;
this.folderTreeElement = null;
this.currentDropTarget = null;
this.lastPageControls = null;
this.isDisabledBySetting = false;
this.initializationPromise = null;
// Bind methods
this.handleTreeClick = this.handleTreeClick.bind(this);
@@ -55,7 +58,15 @@ export class SidebarManager {
this.handleFolderDrop = this.handleFolderDrop.bind(this);
}
setHostPageControls(pageControls) {
this.lastPageControls = pageControls;
}
async initialize(pageControls) {
if (this.isDisabledBySetting) {
return;
}
// Clean up previous initialization if exists
if (this.isInitialized) {
this.cleanup();
@@ -63,6 +74,7 @@ export class SidebarManager {
this.pageControls = pageControls;
this.pageType = pageControls.pageType;
this.lastPageControls = pageControls;
this.apiClient = getModelApiClient();
// Set initial sidebar state immediately (hidden by default)
@@ -73,6 +85,10 @@ export class SidebarManager {
this.updateSidebarTitle();
this.restoreSidebarState();
await this.loadFolderTree();
if (this.isDisabledBySetting) {
this.cleanup();
return;
}
this.restoreSelectedFolder();
// Apply final state with animation after everything is loaded
@@ -132,8 +148,9 @@ export class SidebarManager {
// Remove resize event listener
window.removeEventListener('resize', this.updateContainerMargin);
console.log('SidebarManager cleaned up');
this.initializationPromise = null;
}
removeEventHandlers() {
@@ -471,9 +488,11 @@ export class SidebarManager {
}
setInitialSidebarState() {
if (this.isDisabledBySetting) return;
const sidebar = document.getElementById('folderSidebar');
const hoverArea = document.getElementById('sidebarHoverArea');
if (!sidebar || !hoverArea) return;
// Get stored pin state
@@ -492,6 +511,8 @@ export class SidebarManager {
}
applyFinalSidebarState() {
if (this.isDisabledBySetting) return;
// Use requestAnimationFrame to ensure DOM is ready
requestAnimationFrame(() => {
this.updateAutoHideState();
@@ -668,6 +689,8 @@ export class SidebarManager {
}
updateAutoHideState() {
if (this.isDisabledBySetting) return;
const sidebar = document.getElementById('folderSidebar');
const hoverArea = document.getElementById('sidebarHoverArea');
@@ -708,8 +731,8 @@ export class SidebarManager {
updateContainerMargin() {
const container = document.querySelector('.container');
const sidebar = document.getElementById('folderSidebar');
if (!container || !sidebar) return;
if (!container || !sidebar || this.isDisabledBySetting) return;
// Reset margin to default
container.style.marginLeft = '';
@@ -729,6 +752,65 @@ export class SidebarManager {
}
}
updateDomVisibility(enabled) {
const sidebar = document.getElementById('folderSidebar');
const hoverArea = document.getElementById('sidebarHoverArea');
if (sidebar) {
sidebar.classList.toggle('hidden-by-setting', !enabled);
sidebar.setAttribute('aria-hidden', (!enabled).toString());
}
if (hoverArea) {
hoverArea.classList.toggle('hidden-by-setting', !enabled);
if (!enabled) {
hoverArea.classList.add('disabled');
}
}
}
async setSidebarEnabled(enabled) {
this.isDisabledBySetting = !enabled;
this.updateDomVisibility(enabled);
if (!enabled) {
this.isHovering = false;
this.isVisible = false;
if (this.isInitialized) {
this.cleanup();
} else {
const container = document.querySelector('.container');
if (container) {
container.style.marginLeft = '';
}
}
return;
}
if (this.isInitialized) {
this.updateAutoHideState();
return;
}
if (!this.lastPageControls) {
return;
}
if (!this.initializationPromise) {
this.initializationPromise = this.initialize(this.lastPageControls)
.catch((error) => {
console.error('Sidebar initialization failed:', error);
})
.finally(() => {
this.initializationPromise = null;
});
}
await this.initializationPromise;
}
updatePinButton() {
const pinBtn = document.getElementById('sidebarPinToggle');
if (pinBtn) {
@@ -1327,6 +1409,10 @@ export class SidebarManager {
}
async refresh() {
if (this.isDisabledBySetting || !this.isInitialized) {
return;
}
await this.loadFolderTree();
this.restoreSelectedFolder();
}

View File

@@ -1,5 +1,5 @@
// PageControls.js - Manages controls for both LoRAs and Checkpoints pages
import { getCurrentPageState, setCurrentPageType } from '../../state/index.js';
import { state, getCurrentPageState, setCurrentPageType } from '../../state/index.js';
import { getStorageItem, setStorageItem, getSessionItem, setSessionItem } from '../../utils/storageHelpers.js';
import { showToast } from '../../utils/uiHelpers.js';
import { performModelUpdateCheck } from '../../utils/updateCheckHelpers.js';
@@ -75,7 +75,9 @@ export class PageControls {
*/
async initSidebarManager() {
try {
await this.sidebarManager.initialize(this);
this.sidebarManager.setHostPageControls(this);
const shouldShowSidebar = state?.global?.settings?.show_folder_sidebar !== false;
await this.sidebarManager.setSidebarEnabled(shouldShowSidebar);
} catch (error) {
console.error('Failed to initialize SidebarManager:', error);
}

View File

@@ -8,6 +8,7 @@ import { i18n } from '../i18n/index.js';
import { configureModelCardVideo } from '../components/shared/ModelCard.js';
import { validatePriorityTagString, getPriorityTagSuggestionsMap, invalidatePriorityTagSuggestionsCache } from '../utils/priorityTagHelpers.js';
import { bannerService } from './BannerService.js';
import { sidebarManager } from '../components/SidebarManager.js';
export class SettingsManager {
constructor() {
@@ -388,6 +389,12 @@ export class SettingsManager {
cardInfoDisplaySelect.value = state.global.settings.card_info_display || 'always';
}
const showFolderSidebarCheckbox = document.getElementById('showFolderSidebar');
if (showFolderSidebarCheckbox) {
const showSidebarSetting = state.global.settings.show_folder_sidebar;
showFolderSidebarCheckbox.checked = showSidebarSetting !== false;
}
// Set model card footer action
const modelCardFooterActionSelect = document.getElementById('modelCardFooterAction');
if (modelCardFooterActionSelect) {
@@ -1699,6 +1706,13 @@ export class SettingsManager {
// Apply card info display setting
const cardInfoDisplay = state.global.settings.card_info_display || 'always';
document.body.classList.toggle('hover-reveal', cardInfoDisplay === 'hover');
const shouldShowSidebar = state.global.settings.show_folder_sidebar !== false;
if (sidebarManager && typeof sidebarManager.setSidebarEnabled === 'function') {
sidebarManager.setSidebarEnabled(shouldShowSidebar).catch((error) => {
console.error('Failed to apply sidebar visibility setting:', error);
});
}
}
}

View File

@@ -26,6 +26,7 @@ const DEFAULT_SETTINGS_BASE = Object.freeze({
autoplay_on_hover: false,
display_density: 'default',
card_info_display: 'always',
show_folder_sidebar: true,
model_name_display: 'model_name',
model_card_footer_action: 'example_images',
include_trigger_words: false,