mirror of
https://github.com/willmiao/ComfyUI-Lora-Manager.git
synced 2026-03-21 21:22:11 -03:00
Fix layout
This commit is contained in:
@@ -1,16 +1,19 @@
|
||||
import { state } from '../state/index.js';
|
||||
import { loadMoreLoras } from '../api/loraApi.js';
|
||||
import { debounce } from './debounce.js';
|
||||
|
||||
export function initializeInfiniteScroll() {
|
||||
if (state.observer) {
|
||||
state.observer.disconnect();
|
||||
}
|
||||
|
||||
const debouncedLoadMore = debounce(loadMoreLoras, 200);
|
||||
|
||||
state.observer = new IntersectionObserver(
|
||||
(entries) => {
|
||||
const target = entries[0];
|
||||
if (target.isIntersecting && !state.isLoading && state.hasMore) {
|
||||
loadMoreLoras();
|
||||
debouncedLoadMore();
|
||||
}
|
||||
},
|
||||
{ threshold: 0.1 }
|
||||
|
||||
@@ -30,6 +30,34 @@ export class SearchManager {
|
||||
|
||||
// Initialize search options
|
||||
this.initSearchOptions();
|
||||
|
||||
// Add global click handler to close panels when clicking outside
|
||||
document.addEventListener('click', (e) => {
|
||||
// Close search options panel when clicking outside
|
||||
if (this.searchOptionsPanel &&
|
||||
!this.searchOptionsPanel.contains(e.target) &&
|
||||
e.target !== this.searchOptionsToggle &&
|
||||
!this.searchOptionsToggle.contains(e.target)) {
|
||||
this.closeSearchOptionsPanel();
|
||||
}
|
||||
|
||||
// Close filter panel when clicking outside (if filterManager exists)
|
||||
const filterPanel = document.getElementById('filterPanel');
|
||||
const filterButton = document.getElementById('filterButton');
|
||||
if (filterPanel &&
|
||||
!filterPanel.contains(e.target) &&
|
||||
e.target !== filterButton &&
|
||||
!filterButton.contains(e.target) &&
|
||||
window.filterManager) {
|
||||
window.filterManager.closeFilterPanel();
|
||||
}
|
||||
});
|
||||
|
||||
// Initialize panel positions
|
||||
this.updatePanelPositions();
|
||||
|
||||
// Add resize listener
|
||||
window.addEventListener('resize', this.updatePanelPositions.bind(this));
|
||||
}
|
||||
|
||||
initSearchOptions() {
|
||||
@@ -103,16 +131,6 @@ export class SearchManager {
|
||||
|
||||
// Ensure at least one search option is selected
|
||||
this.validateSearchOptions();
|
||||
|
||||
// Close panel when clicking outside
|
||||
document.addEventListener('click', (e) => {
|
||||
if (this.searchOptionsPanel &&
|
||||
!this.searchOptionsPanel.contains(e.target) &&
|
||||
e.target !== this.searchOptionsToggle &&
|
||||
!this.searchOptionsToggle.contains(e.target)) {
|
||||
this.closeSearchOptionsPanel();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Add method to validate search options
|
||||
@@ -137,6 +155,8 @@ export class SearchManager {
|
||||
if (this.searchOptionsPanel) {
|
||||
const isHidden = this.searchOptionsPanel.classList.contains('hidden');
|
||||
if (isHidden) {
|
||||
// Update position before showing
|
||||
this.updatePanelPositions();
|
||||
this.searchOptionsPanel.classList.remove('hidden');
|
||||
this.searchOptionsToggle.classList.add('active');
|
||||
} else {
|
||||
@@ -209,6 +229,9 @@ export class SearchManager {
|
||||
this.isSearching = true;
|
||||
state.loadingManager.showSimpleLoading('Searching...');
|
||||
|
||||
// Store current scroll position
|
||||
const scrollPosition = window.pageYOffset || document.documentElement.scrollTop;
|
||||
|
||||
state.currentPage = 1;
|
||||
state.hasMore = true;
|
||||
|
||||
@@ -250,6 +273,14 @@ export class SearchManager {
|
||||
state.hasMore = state.currentPage < data.total_pages;
|
||||
state.currentPage++;
|
||||
}
|
||||
|
||||
// Restore scroll position after content is loaded
|
||||
setTimeout(() => {
|
||||
window.scrollTo({
|
||||
top: scrollPosition,
|
||||
behavior: 'instant' // Use 'instant' to prevent animation
|
||||
});
|
||||
}, 10);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Search error:', error);
|
||||
@@ -259,4 +290,23 @@ export class SearchManager {
|
||||
state.loadingManager.hide();
|
||||
}
|
||||
}
|
||||
|
||||
updatePanelPositions() {
|
||||
const searchOptionsPanel = document.getElementById('searchOptionsPanel');
|
||||
const filterPanel = document.getElementById('filterPanel');
|
||||
|
||||
if (!searchOptionsPanel || !filterPanel) return;
|
||||
|
||||
// Get the controls container
|
||||
const controls = document.querySelector('.controls');
|
||||
if (!controls) return;
|
||||
|
||||
// Calculate the position based on the bottom of the controls container
|
||||
const controlsRect = controls.getBoundingClientRect();
|
||||
const topPosition = controlsRect.bottom + 10; // Add 10px padding
|
||||
|
||||
// Set the positions
|
||||
searchOptionsPanel.style.top = `${topPosition}px`;
|
||||
filterPanel.style.top = `${topPosition}px`;
|
||||
}
|
||||
}
|
||||
@@ -98,16 +98,57 @@ export function openCivitai(modelName) {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Dynamically positions the search options panel and filter panel
|
||||
* based on the current layout and folder tags container height
|
||||
*/
|
||||
export function updatePanelPositions() {
|
||||
const searchOptionsPanel = document.getElementById('searchOptionsPanel');
|
||||
const filterPanel = document.getElementById('filterPanel');
|
||||
|
||||
if (!searchOptionsPanel || !filterPanel) return;
|
||||
|
||||
// Get the controls container
|
||||
const controls = document.querySelector('.controls');
|
||||
if (!controls) return;
|
||||
|
||||
// Calculate the position based on the bottom of the controls container
|
||||
const controlsRect = controls.getBoundingClientRect();
|
||||
const topPosition = controlsRect.bottom + 10; // Add 10px padding
|
||||
|
||||
// Set the positions
|
||||
searchOptionsPanel.style.top = `${topPosition}px`;
|
||||
filterPanel.style.top = `${topPosition}px`;
|
||||
}
|
||||
|
||||
// Update the toggleFolderTags function
|
||||
export function toggleFolderTags() {
|
||||
const folderTags = document.querySelector('.folder-tags');
|
||||
const btn = document.querySelector('.toggle-folders-btn');
|
||||
const isCollapsed = folderTags.classList.toggle('collapsed');
|
||||
const toggleBtn = document.querySelector('.toggle-folders-btn i');
|
||||
|
||||
// 更新按钮提示文本
|
||||
btn.title = isCollapsed ? 'Expand folder tags' : 'Collapse folder tags';
|
||||
|
||||
// 保存状态到 localStorage
|
||||
localStorage.setItem('folderTagsCollapsed', isCollapsed);
|
||||
if (folderTags) {
|
||||
folderTags.classList.toggle('collapsed');
|
||||
|
||||
if (folderTags.classList.contains('collapsed')) {
|
||||
toggleBtn.className = 'fas fa-chevron-down';
|
||||
toggleBtn.parentElement.title = 'Expand folder tags';
|
||||
localStorage.setItem('folderTagsCollapsed', 'true');
|
||||
} else {
|
||||
toggleBtn.className = 'fas fa-chevron-up';
|
||||
toggleBtn.parentElement.title = 'Collapse folder tags';
|
||||
localStorage.setItem('folderTagsCollapsed', 'false');
|
||||
}
|
||||
|
||||
// Update panel positions after toggling
|
||||
// Use a small delay to ensure the DOM has updated
|
||||
setTimeout(() => {
|
||||
if (window.searchManager && typeof window.searchManager.updatePanelPositions === 'function') {
|
||||
window.searchManager.updatePanelPositions();
|
||||
} else if (typeof updatePanelPositions === 'function') {
|
||||
updatePanelPositions();
|
||||
}
|
||||
}, 50);
|
||||
}
|
||||
}
|
||||
|
||||
// Add this to your existing initialization code
|
||||
@@ -128,10 +169,13 @@ export function initBackToTop() {
|
||||
button.title = 'Back to top';
|
||||
document.body.appendChild(button);
|
||||
|
||||
// Get the scrollable container
|
||||
const scrollContainer = document.querySelector('.page-content');
|
||||
|
||||
// Show/hide button based on scroll position
|
||||
const toggleBackToTop = () => {
|
||||
const scrollThreshold = window.innerHeight * 0.75;
|
||||
if (window.scrollY > scrollThreshold) {
|
||||
const scrollThreshold = window.innerHeight * 0.3;
|
||||
if (scrollContainer.scrollTop > scrollThreshold) {
|
||||
button.classList.add('visible');
|
||||
} else {
|
||||
button.classList.remove('visible');
|
||||
@@ -140,14 +184,14 @@ export function initBackToTop() {
|
||||
|
||||
// Smooth scroll to top
|
||||
button.addEventListener('click', () => {
|
||||
window.scrollTo({
|
||||
scrollContainer.scrollTo({
|
||||
top: 0,
|
||||
behavior: 'smooth'
|
||||
});
|
||||
});
|
||||
|
||||
// Listen for scroll events
|
||||
window.addEventListener('scroll', toggleBackToTop);
|
||||
// Listen for scroll events on the scrollable container
|
||||
scrollContainer.addEventListener('scroll', toggleBackToTop);
|
||||
|
||||
// Initial check
|
||||
toggleBackToTop();
|
||||
|
||||
Reference in New Issue
Block a user