feat(sidebar): add recursive search functionality and toggle button

This commit is contained in:
Will Miao
2025-10-09 17:07:10 +08:00
parent 2b6910bd55
commit d2c2bfbe6a
13 changed files with 124 additions and 26 deletions

View File

@@ -21,6 +21,7 @@ export class SidebarManager {
this.isInitialized = false;
this.displayMode = 'tree'; // 'tree' or 'list'
this.foldersList = [];
this.recursiveSearchEnabled = true;
// Bind methods
this.handleTreeClick = this.handleTreeClick.bind(this);
@@ -36,6 +37,7 @@ export class SidebarManager {
this.updateContainerMargin = this.updateContainerMargin.bind(this);
this.handleDisplayModeToggle = this.handleDisplayModeToggle.bind(this);
this.handleFolderListClick = this.handleFolderListClick.bind(this);
this.handleRecursiveToggle = this.handleRecursiveToggle.bind(this);
}
async initialize(pageControls) {
@@ -89,6 +91,7 @@ export class SidebarManager {
this.isHovering = false;
this.apiClient = null;
this.isInitialized = false;
this.recursiveSearchEnabled = true;
// Reset container margin
const container = document.querySelector('.container');
@@ -111,6 +114,7 @@ export class SidebarManager {
const sidebar = document.getElementById('folderSidebar');
const hoverArea = document.getElementById('sidebarHoverArea');
const displayModeToggleBtn = document.getElementById('sidebarDisplayModeToggle');
const recursiveToggleBtn = document.getElementById('sidebarRecursiveToggle');
if (pinToggleBtn) {
pinToggleBtn.removeEventListener('click', this.handlePinToggle);
@@ -145,6 +149,9 @@ export class SidebarManager {
if (displayModeToggleBtn) {
displayModeToggleBtn.removeEventListener('click', this.handleDisplayModeToggle);
}
if (recursiveToggleBtn) {
recursiveToggleBtn.removeEventListener('click', this.handleRecursiveToggle);
}
}
async init() {
@@ -197,7 +204,7 @@ export class SidebarManager {
updateSidebarTitle() {
const sidebarTitle = document.getElementById('sidebarTitle');
if (sidebarTitle) {
sidebarTitle.textContent = `${this.apiClient.apiConfig.config.displayName} Root`;
sidebarTitle.textContent = translate('sidebar.modelRoot');
}
}
@@ -220,6 +227,12 @@ export class SidebarManager {
collapseAllBtn.addEventListener('click', this.handleCollapseAll);
}
// Recursive toggle button
const recursiveToggleBtn = document.getElementById('sidebarRecursiveToggle');
if (recursiveToggleBtn) {
recursiveToggleBtn.addEventListener('click', this.handleRecursiveToggle);
}
// Tree click handler
const folderTree = document.getElementById('sidebarFolderTree');
if (folderTree) {
@@ -645,11 +658,33 @@ export class SidebarManager {
this.displayMode = this.displayMode === 'tree' ? 'list' : 'tree';
this.updateDisplayModeButton();
this.updateCollapseAllButton();
this.updateRecursiveToggleButton();
this.updateSearchRecursiveOption();
this.saveDisplayMode();
this.loadFolderTree(); // Reload with new display mode
}
async handleRecursiveToggle(event) {
event.stopPropagation();
if (this.displayMode !== 'tree') {
return;
}
this.recursiveSearchEnabled = !this.recursiveSearchEnabled;
setStorageItem(`${this.pageType}_recursiveSearch`, this.recursiveSearchEnabled);
this.updateSearchRecursiveOption();
this.updateRecursiveToggleButton();
if (this.pageControls && typeof this.pageControls.resetAndReload === 'function') {
try {
await this.pageControls.resetAndReload(true);
} catch (error) {
console.error('Failed to reload models after toggling recursive search:', error);
}
}
}
updateDisplayModeButton() {
const displayModeBtn = document.getElementById('sidebarDisplayModeToggle');
if (displayModeBtn) {
@@ -679,8 +714,35 @@ export class SidebarManager {
}
}
updateRecursiveToggleButton() {
const recursiveToggleBtn = document.getElementById('sidebarRecursiveToggle');
if (!recursiveToggleBtn) return;
const icon = recursiveToggleBtn.querySelector('i');
const isTreeMode = this.displayMode === 'tree';
const isActive = isTreeMode && this.recursiveSearchEnabled;
recursiveToggleBtn.classList.toggle('active', isActive);
recursiveToggleBtn.classList.toggle('disabled', !isTreeMode);
recursiveToggleBtn.setAttribute('aria-pressed', isActive ? 'true' : 'false');
recursiveToggleBtn.setAttribute('aria-disabled', isTreeMode ? 'false' : 'true');
if (icon) {
icon.className = 'fas fa-code-branch';
}
if (!isTreeMode) {
recursiveToggleBtn.title = translate('sidebar.recursiveUnavailable');
} else if (this.recursiveSearchEnabled) {
recursiveToggleBtn.title = translate('sidebar.recursiveOn');
} else {
recursiveToggleBtn.title = translate('sidebar.recursiveOff');
}
}
updateSearchRecursiveOption() {
this.pageControls.pageState.searchOptions.recursive = this.displayMode === 'tree';
const isRecursive = this.displayMode === 'tree' && this.recursiveSearchEnabled;
this.pageControls.pageState.searchOptions.recursive = isRecursive;
}
updateTreeSelection() {
@@ -925,15 +987,18 @@ export class SidebarManager {
const isPinned = getStorageItem(`${this.pageType}_sidebarPinned`, true);
const expandedPaths = getStorageItem(`${this.pageType}_expandedNodes`, []);
const displayMode = getStorageItem(`${this.pageType}_displayMode`, 'tree'); // 'tree' or 'list', default to 'tree'
const recursiveSearchEnabled = getStorageItem(`${this.pageType}_recursiveSearch`, true);
this.isPinned = isPinned;
this.expandedNodes = new Set(expandedPaths);
this.displayMode = displayMode;
this.recursiveSearchEnabled = recursiveSearchEnabled;
this.updatePinButton();
this.updateDisplayModeButton();
this.updateCollapseAllButton();
this.updateSearchRecursiveOption();
this.updateRecursiveToggleButton();
}
restoreSelectedFolder() {
@@ -974,4 +1039,4 @@ export class SidebarManager {
}
// Create and export global instance
export const sidebarManager = new SidebarManager();
export const sidebarManager = new SidebarManager();