mirror of
https://github.com/willmiao/ComfyUI-Lora-Manager.git
synced 2026-03-25 15:15:44 -03:00
Refactor panel position management and enhance recipe card handling
- Removed redundant updatePanelPositions calls from various components and centralized the logic in the uiHelpers.js for better maintainability. - Introduced appendRecipeCards function in RecipeManager to streamline the addition of recipe cards from search results. - Cleaned up unused code related to search input handling and recipe loading, improving overall code clarity and performance. - Updated HeaderManager and SearchManager to utilize the new updatePanelPositions function, ensuring consistent panel positioning across the application.
This commit is contained in:
@@ -101,53 +101,4 @@ export class HeaderManager {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
// Helper method to update panel positions (can be called from window resize handlers)
|
|
||||||
updatePanelPositions() {
|
|
||||||
if (this.searchManager && typeof this.searchManager.updatePanelPositions === 'function') {
|
|
||||||
this.searchManager.updatePanelPositions();
|
|
||||||
} else {
|
|
||||||
const searchOptionsPanel = document.getElementById('searchOptionsPanel');
|
|
||||||
const filterPanel = document.getElementById('filterPanel');
|
|
||||||
|
|
||||||
if (!searchOptionsPanel && !filterPanel) return;
|
|
||||||
|
|
||||||
// Get the header element
|
|
||||||
const header = document.querySelector('.app-header');
|
|
||||||
if (!header) return;
|
|
||||||
|
|
||||||
// Calculate the position based on the bottom of the header
|
|
||||||
const headerRect = header.getBoundingClientRect();
|
|
||||||
const topPosition = headerRect.bottom + 5; // Add 5px padding
|
|
||||||
|
|
||||||
// Set the positions
|
|
||||||
if (searchOptionsPanel) {
|
|
||||||
searchOptionsPanel.style.top = `${topPosition}px`;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (filterPanel) {
|
|
||||||
filterPanel.style.top = `${topPosition}px`;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Adjust panel horizontal position based on the search container
|
|
||||||
const searchContainer = document.querySelector('.header-search');
|
|
||||||
if (searchContainer) {
|
|
||||||
const searchRect = searchContainer.getBoundingClientRect();
|
|
||||||
|
|
||||||
// Position the search options panel aligned with the search container
|
|
||||||
if (searchOptionsPanel) {
|
|
||||||
searchOptionsPanel.style.right = `${window.innerWidth - searchRect.right}px`;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Position the filter panel aligned with the filter button
|
|
||||||
if (filterPanel) {
|
|
||||||
const filterButton = document.getElementById('filterButton');
|
|
||||||
if (filterButton) {
|
|
||||||
const filterRect = filterButton.getBoundingClientRect();
|
|
||||||
filterPanel.style.right = `${window.innerWidth - filterRect.right}px`;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import { modalManager } from './managers/ModalManager.js';
|
|||||||
import { updateService } from './managers/UpdateService.js';
|
import { updateService } from './managers/UpdateService.js';
|
||||||
import { HeaderManager } from './components/Header.js';
|
import { HeaderManager } from './components/Header.js';
|
||||||
import { SettingsManager } from './managers/SettingsManager.js';
|
import { SettingsManager } from './managers/SettingsManager.js';
|
||||||
import { showToast, initTheme, initBackToTop, updatePanelPositions, lazyLoadImages } from './utils/uiHelpers.js';
|
import { showToast, initTheme, initBackToTop, lazyLoadImages } from './utils/uiHelpers.js';
|
||||||
import { initializeInfiniteScroll } from './utils/infiniteScroll.js';
|
import { initializeInfiniteScroll } from './utils/infiniteScroll.js';
|
||||||
|
|
||||||
// Core application class
|
// Core application class
|
||||||
@@ -30,12 +30,6 @@ export class AppCore {
|
|||||||
initTheme();
|
initTheme();
|
||||||
initBackToTop();
|
initBackToTop();
|
||||||
|
|
||||||
// Set up event listeners
|
|
||||||
window.addEventListener('resize', updatePanelPositions);
|
|
||||||
|
|
||||||
// Initial positioning
|
|
||||||
updatePanelPositions();
|
|
||||||
|
|
||||||
// Mark as initialized
|
// Mark as initialized
|
||||||
this.initialized = true;
|
this.initialized = true;
|
||||||
|
|
||||||
@@ -66,9 +60,6 @@ export class AppCore {
|
|||||||
initializeInfiniteScroll(pageType);
|
initializeInfiniteScroll(pageType);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update panel positions
|
|
||||||
updatePanelPositions();
|
|
||||||
|
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import { BASE_MODELS, BASE_MODEL_CLASSES } from '../utils/constants.js';
|
import { BASE_MODELS, BASE_MODEL_CLASSES } from '../utils/constants.js';
|
||||||
import { state, getCurrentPageState } from '../state/index.js';
|
import { state, getCurrentPageState } from '../state/index.js';
|
||||||
import { showToast } from '../utils/uiHelpers.js';
|
import { showToast, updatePanelPositions } from '../utils/uiHelpers.js';
|
||||||
import { resetAndReload } from '../api/loraApi.js';
|
import { resetAndReload } from '../api/loraApi.js';
|
||||||
|
|
||||||
export class FilterManager {
|
export class FilterManager {
|
||||||
@@ -155,11 +155,7 @@ export class FilterManager {
|
|||||||
|
|
||||||
if (isHidden) {
|
if (isHidden) {
|
||||||
// Update panel positions before showing
|
// Update panel positions before showing
|
||||||
if (window.searchManager && typeof window.searchManager.updatePanelPositions === 'function') {
|
|
||||||
window.searchManager.updatePanelPositions();
|
|
||||||
} else if (typeof updatePanelPositions === 'function') {
|
|
||||||
updatePanelPositions();
|
updatePanelPositions();
|
||||||
}
|
|
||||||
|
|
||||||
this.filterPanel.classList.remove('hidden');
|
this.filterPanel.classList.remove('hidden');
|
||||||
this.filterButton.classList.add('active');
|
this.filterButton.classList.add('active');
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { showToast } from '../utils/uiHelpers.js';
|
import { showToast, updatePanelPositions } from '../utils/uiHelpers.js';
|
||||||
|
|
||||||
export class RecipeFilterManager {
|
export class RecipeFilterManager {
|
||||||
constructor() {
|
constructor() {
|
||||||
@@ -165,11 +165,7 @@ export class RecipeFilterManager {
|
|||||||
|
|
||||||
if (isHidden) {
|
if (isHidden) {
|
||||||
// Update panel positions before showing
|
// Update panel positions before showing
|
||||||
if (window.searchManager && typeof window.searchManager.updatePanelPositions === 'function') {
|
|
||||||
window.searchManager.updatePanelPositions();
|
|
||||||
} else if (typeof updatePanelPositions === 'function') {
|
|
||||||
updatePanelPositions();
|
updatePanelPositions();
|
||||||
}
|
|
||||||
|
|
||||||
this.filterPanel.classList.remove('hidden');
|
this.filterPanel.classList.remove('hidden');
|
||||||
this.filterButton.classList.add('active');
|
this.filterButton.classList.add('active');
|
||||||
|
|||||||
@@ -33,10 +33,7 @@ export class RecipeSearchManager extends SearchManager {
|
|||||||
const grid = document.getElementById('recipeGrid');
|
const grid = document.getElementById('recipeGrid');
|
||||||
|
|
||||||
if (!searchTerm) {
|
if (!searchTerm) {
|
||||||
if (state) {
|
window.recipeManager.loadRecipes();
|
||||||
state.pages.recipes.currentPage = 1;
|
|
||||||
}
|
|
||||||
this.resetAndReloadRecipes();
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -112,34 +109,12 @@ export class RecipeSearchManager extends SearchManager {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
resetAndReloadRecipes() {
|
|
||||||
if (window.recipeManager && typeof window.recipeManager.loadRecipes === 'function') {
|
|
||||||
window.recipeManager.loadRecipes();
|
|
||||||
} else {
|
|
||||||
// Fallback to reloading the page
|
|
||||||
window.location.reload();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
appendRecipeCards(recipes) {
|
appendRecipeCards(recipes) {
|
||||||
// This function would be implemented in the recipes page
|
|
||||||
// Similar to appendLoraCards for loras
|
|
||||||
const grid = document.getElementById('recipeGrid');
|
const grid = document.getElementById('recipeGrid');
|
||||||
if (!grid) return;
|
if (!grid) return;
|
||||||
|
|
||||||
if (typeof window.appendRecipeCards === 'function') {
|
// Create data object in the format expected by the RecipeManager
|
||||||
window.appendRecipeCards(recipes);
|
const data = { items: recipes, has_more: false };
|
||||||
} else {
|
window.recipeManager.updateRecipesGrid(data, false);
|
||||||
// Fallback implementation
|
|
||||||
recipes.forEach(recipe => {
|
|
||||||
const card = document.createElement('div');
|
|
||||||
card.className = 'recipe-card';
|
|
||||||
card.innerHTML = `
|
|
||||||
<h3>${recipe.name}</h3>
|
|
||||||
<p>${recipe.description || 'No description'}</p>
|
|
||||||
`;
|
|
||||||
grid.appendChild(card);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,3 +1,4 @@
|
|||||||
|
import { updatePanelPositions } from "../utils/uiHelpers.js";
|
||||||
/**
|
/**
|
||||||
* SearchManager - Handles search functionality across different pages
|
* SearchManager - Handles search functionality across different pages
|
||||||
* Each page can extend or customize this base functionality
|
* Each page can extend or customize this base functionality
|
||||||
@@ -27,11 +28,10 @@ export class SearchManager {
|
|||||||
this.initEventListeners();
|
this.initEventListeners();
|
||||||
this.loadSearchPreferences();
|
this.loadSearchPreferences();
|
||||||
|
|
||||||
// Initialize panel positions
|
updatePanelPositions();
|
||||||
this.updatePanelPositions();
|
|
||||||
|
|
||||||
// Add resize listener
|
// Add resize listener
|
||||||
window.addEventListener('resize', this.updatePanelPositions.bind(this));
|
window.addEventListener('resize', updatePanelPositions);
|
||||||
}
|
}
|
||||||
|
|
||||||
initEventListeners() {
|
initEventListeners() {
|
||||||
@@ -161,7 +161,7 @@ export class SearchManager {
|
|||||||
const isHidden = this.searchOptionsPanel.classList.contains('hidden');
|
const isHidden = this.searchOptionsPanel.classList.contains('hidden');
|
||||||
if (isHidden) {
|
if (isHidden) {
|
||||||
// Update position before showing
|
// Update position before showing
|
||||||
this.updatePanelPositions();
|
updatePanelPositions();
|
||||||
this.searchOptionsPanel.classList.remove('hidden');
|
this.searchOptionsPanel.classList.remove('hidden');
|
||||||
this.searchOptionsToggle.classList.add('active');
|
this.searchOptionsToggle.classList.add('active');
|
||||||
|
|
||||||
@@ -267,56 +267,6 @@ export class SearchManager {
|
|||||||
return options;
|
return options;
|
||||||
}
|
}
|
||||||
|
|
||||||
updatePanelPositions() {
|
|
||||||
const searchOptionsPanel = document.getElementById('searchOptionsPanel');
|
|
||||||
const filterPanel = document.getElementById('filterPanel');
|
|
||||||
|
|
||||||
if (!searchOptionsPanel && !filterPanel) return;
|
|
||||||
|
|
||||||
// Get the header element
|
|
||||||
const header = document.querySelector('.app-header');
|
|
||||||
if (!header) return;
|
|
||||||
|
|
||||||
// Calculate the position based on the bottom of the header
|
|
||||||
const headerRect = header.getBoundingClientRect();
|
|
||||||
const topPosition = headerRect.bottom + 5; // Add 5px padding
|
|
||||||
|
|
||||||
// Set the positions
|
|
||||||
if (searchOptionsPanel) {
|
|
||||||
searchOptionsPanel.style.top = `${topPosition}px`;
|
|
||||||
|
|
||||||
// Make sure the panel is visible when positioned
|
|
||||||
if (!searchOptionsPanel.classList.contains('hidden') &&
|
|
||||||
window.getComputedStyle(searchOptionsPanel).display === 'none') {
|
|
||||||
searchOptionsPanel.style.display = 'block';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (filterPanel) {
|
|
||||||
filterPanel.style.top = `${topPosition}px`;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Adjust panel horizontal position based on the search container
|
|
||||||
const searchContainer = document.querySelector('.header-search');
|
|
||||||
if (searchContainer) {
|
|
||||||
const searchRect = searchContainer.getBoundingClientRect();
|
|
||||||
|
|
||||||
// Position the search options panel aligned with the search container
|
|
||||||
if (searchOptionsPanel) {
|
|
||||||
searchOptionsPanel.style.right = `${window.innerWidth - searchRect.right}px`;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Position the filter panel aligned with the filter button
|
|
||||||
if (filterPanel) {
|
|
||||||
const filterButton = document.getElementById('filterButton');
|
|
||||||
if (filterButton) {
|
|
||||||
const filterRect = filterButton.getBoundingClientRect();
|
|
||||||
filterPanel.style.right = `${window.innerWidth - filterRect.right}px`;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
performSearch() {
|
performSearch() {
|
||||||
const query = this.searchInput.value.trim();
|
const query = this.searchInput.value.trim();
|
||||||
const options = this.getActiveSearchOptions();
|
const options = this.getActiveSearchOptions();
|
||||||
|
|||||||
@@ -59,6 +59,12 @@ class RecipeManager {
|
|||||||
window.importRecipes = () => this.importRecipes();
|
window.importRecipes = () => this.importRecipes();
|
||||||
window.importManager = this.importManager;
|
window.importManager = this.importManager;
|
||||||
window.loadMoreRecipes = () => this.loadMoreRecipes();
|
window.loadMoreRecipes = () => this.loadMoreRecipes();
|
||||||
|
|
||||||
|
// Add appendRecipeCards function for the search manager to use
|
||||||
|
window.appendRecipeCards = (recipes) => {
|
||||||
|
const data = { items: recipes, has_more: false };
|
||||||
|
this.updateRecipesGrid(data, false);
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
initEventListeners() {
|
initEventListeners() {
|
||||||
@@ -70,28 +76,6 @@ class RecipeManager {
|
|||||||
this.loadRecipes();
|
this.loadRecipes();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// Search input
|
|
||||||
const searchInput = document.getElementById('searchInput');
|
|
||||||
if (searchInput) {
|
|
||||||
let debounceTimeout;
|
|
||||||
searchInput.addEventListener('input', () => {
|
|
||||||
clearTimeout(debounceTimeout);
|
|
||||||
debounceTimeout = setTimeout(() => {
|
|
||||||
this.pageState.filters.search = searchInput.value;
|
|
||||||
this.loadRecipes();
|
|
||||||
}, 300);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// Import button
|
|
||||||
const importButton = document.querySelector('button[onclick="importRecipes()"]');
|
|
||||||
if (importButton) {
|
|
||||||
importButton.onclick = (e) => {
|
|
||||||
e.preventDefault();
|
|
||||||
this.importManager.showImportModal();
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async loadRecipes(resetPage = true) {
|
async loadRecipes(resetPage = true) {
|
||||||
|
|||||||
@@ -106,20 +106,45 @@ export function updatePanelPositions() {
|
|||||||
const searchOptionsPanel = document.getElementById('searchOptionsPanel');
|
const searchOptionsPanel = document.getElementById('searchOptionsPanel');
|
||||||
const filterPanel = document.getElementById('filterPanel');
|
const filterPanel = document.getElementById('filterPanel');
|
||||||
|
|
||||||
if (!searchOptionsPanel || !filterPanel) return;
|
if (!searchOptionsPanel && !filterPanel) return;
|
||||||
|
|
||||||
// Get the controls container
|
// Get the header element
|
||||||
const controls = document.querySelector('.controls');
|
const header = document.querySelector('.app-header');
|
||||||
if (!controls) return;
|
if (!header) return;
|
||||||
|
|
||||||
// Calculate the position based on the bottom of the controls container
|
// Calculate the position based on the bottom of the header
|
||||||
const controlsRect = controls.getBoundingClientRect();
|
const headerRect = header.getBoundingClientRect();
|
||||||
const topPosition = controlsRect.bottom + 10; // Add 10px padding
|
const topPosition = headerRect.bottom + 5; // Add 5px padding
|
||||||
|
|
||||||
// Set the positions
|
// Set the positions
|
||||||
|
if (searchOptionsPanel) {
|
||||||
searchOptionsPanel.style.top = `${topPosition}px`;
|
searchOptionsPanel.style.top = `${topPosition}px`;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (filterPanel) {
|
||||||
filterPanel.style.top = `${topPosition}px`;
|
filterPanel.style.top = `${topPosition}px`;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Adjust panel horizontal position based on the search container
|
||||||
|
const searchContainer = document.querySelector('.header-search');
|
||||||
|
if (searchContainer) {
|
||||||
|
const searchRect = searchContainer.getBoundingClientRect();
|
||||||
|
|
||||||
|
// Position the search options panel aligned with the search container
|
||||||
|
if (searchOptionsPanel) {
|
||||||
|
searchOptionsPanel.style.right = `${window.innerWidth - searchRect.right}px`;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Position the filter panel aligned with the filter button
|
||||||
|
if (filterPanel) {
|
||||||
|
const filterButton = document.getElementById('filterButton');
|
||||||
|
if (filterButton) {
|
||||||
|
const filterRect = filterButton.getBoundingClientRect();
|
||||||
|
filterPanel.style.right = `${window.innerWidth - filterRect.right}px`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Update the toggleFolderTags function
|
// Update the toggleFolderTags function
|
||||||
export function toggleFolderTags() {
|
export function toggleFolderTags() {
|
||||||
@@ -144,11 +169,7 @@ export function toggleFolderTags() {
|
|||||||
// Update panel positions after toggling
|
// Update panel positions after toggling
|
||||||
// Use a small delay to ensure the DOM has updated
|
// Use a small delay to ensure the DOM has updated
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
if (window.searchManager && typeof window.searchManager.updatePanelPositions === 'function') {
|
|
||||||
window.searchManager.updatePanelPositions();
|
|
||||||
} else if (typeof updatePanelPositions === 'function') {
|
|
||||||
updatePanelPositions();
|
updatePanelPositions();
|
||||||
}
|
|
||||||
}, 50);
|
}, 50);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -77,13 +77,3 @@
|
|||||||
{% block main_script %}
|
{% block main_script %}
|
||||||
<script type="module" src="/loras_static/js/recipes.js"></script>
|
<script type="module" src="/loras_static/js/recipes.js"></script>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
{% block additional_scripts %}
|
|
||||||
<script>
|
|
||||||
// Refresh recipes
|
|
||||||
function refreshRecipes() {
|
|
||||||
// Will be implemented in recipes.js
|
|
||||||
window.location.reload();
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
{% endblock %}
|
|
||||||
Reference in New Issue
Block a user