1 Commits

Author SHA1 Message Date
Chuck
5e6c40ad55 fix(plugins): plugin manager tab doesn't always load on first visit (#319)
* fix(plugins): reset pluginsInitialized on HTMX re-swap; use refreshInstalledPlugins in refreshPlugins

HTMX's `revealed` trigger fires each time the plugins tab becomes
visible (Alpine's x-show toggles display:none which re-triggers the
IntersectionObserver). Each re-reveal fetches a fresh empty HTML
skeleton via hx-swap="innerHTML". The htmx:afterSwap handler reset
window.pluginManager.initialized/initializing but not pluginsInitialized,
so initializePlugins() hit its guard and skipped loadInstalledPlugins()
and searchPluginStore() — leaving the fresh empty DOM unpopulated.

Fix: also reset pluginsInitialized = false in the afterSwap handler.
Existing caches (3s for installed plugins, 5min for store) mean tab
revisits within the TTL render from cache instantly with no extra
API traffic.

Also change refreshPlugins() to call refreshInstalledPlugins() (which
already exists and explicitly invalidates the cache) instead of the
bare loadInstalledPlugins() call that could silently skip the fetch
if the 3-second cache happened to still be valid.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* fix(plugins): use cached store on HTMX re-swap; reserve searchPluginStore(true) for first load

searchPluginStore(true) bypasses the isCacheValid check unconditionally,
so every tab revisit was hitting the GitHub commit-info API even within
the 5-minute cache window.

Set window.pluginManager._reswap = true in the htmx:afterSwap handler
and read it in initializePlugins() to call searchPluginStore(false) on
re-swaps (respects the 5-minute cache) vs searchPluginStore(true) on
first load (always fetches fresh). Explicit user refresh via
refreshPlugins() already calls searchPluginStore(true) directly.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

---------

Co-authored-by: Chuck <chuck@example.com>
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-30 11:57:26 -04:00

View File

@@ -1165,9 +1165,11 @@ function initializePluginPageWhenReady() {
if (target.id === 'plugins-content' ||
target.querySelector('#installed-plugins-grid')) {
console.log('HTMX swap detected for plugins, initializing...');
// Reset initialization flag to allow re-initialization after HTMX swap
// Reset all initialization flags so the fresh empty DOM gets populated
window.pluginManager.initialized = false;
window.pluginManager.initializing = false;
window.pluginManager._reswap = true; // signal: use cached store, don't re-fetch GitHub
pluginsInitialized = false;
initTimer = setTimeout(attemptInit, 100);
}
}, { once: false }); // Allow multiple swaps
@@ -1211,9 +1213,13 @@ function initializePlugins() {
console.warn('[INIT] checkGitHubAuthStatus not available yet');
}
// Load both installed plugins and plugin store
// Load both installed plugins and plugin store.
// On HTMX re-swaps use cached store data (fetchCommitInfo=false) to avoid
// re-hitting GitHub on every tab switch; only fetch fresh on first load.
const isReswap = !!window.pluginManager._reswap;
window.pluginManager._reswap = false;
loadInstalledPlugins();
searchPluginStore(true); // Load plugin store with fresh metadata from GitHub
searchPluginStore(!isReswap);
// Setup search functionality (with guard against duplicate listeners)
const searchInput = document.getElementById('plugin-search');
@@ -5127,7 +5133,7 @@ function refreshPlugins() {
pluginStoreCache = null;
cacheTimestamp = null;
loadInstalledPlugins();
refreshInstalledPlugins(); // invalidates cache before fetching
// Fetch latest metadata from GitHub when refreshing
searchPluginStore(true);
showNotification('Plugins refreshed with latest metadata from GitHub', 'success');