From b5b313090a0c710a44c3067c52fd4ca77ecfdfe7 Mon Sep 17 00:00:00 2001 From: master3395 Date: Thu, 26 Mar 2026 15:22:56 +0100 Subject: [PATCH] pluginHolder: fix plugin store cache timestamp display and stale refresh trigger. Render next cache update in Norwegian format and mark overdue cache clearly while triggering background refresh from Installed view when cache metadata is expired. --- .../templates/pluginHolder/plugins.html | 24 ++++++++++++------- pluginHolder/views.py | 23 +++++++++++++++--- 2 files changed, 35 insertions(+), 12 deletions(-) diff --git a/pluginHolder/templates/pluginHolder/plugins.html b/pluginHolder/templates/pluginHolder/plugins.html index ee7d05484..c82e92e7a 100644 --- a/pluginHolder/templates/pluginHolder/plugins.html +++ b/pluginHolder/templates/pluginHolder/plugins.html @@ -1737,7 +1737,7 @@ {% trans "Cache Information:" %} {% trans "Plugin store data is cached for 1 hour to improve performance and reduce GitHub API rate limits. New plugins may take up to 1 hour to appear after being published." %} {% if cache_expiry_timestamp %} -
{% trans "Next cache update:" %} {% trans "Calculating..." %} +
{% trans "Next cache update:" %} {% trans "Calculating..." %} {% endif %}

@@ -3250,8 +3250,8 @@ function updateCacheExpiryTime() { return; } - // Get user's locale preferences - const locale = navigator.language || navigator.userLanguage || 'en-US'; + // Always use Norwegian format for NO-facing UI: DD.MM.YYYY kl. HH:MM + const locale = 'nb-NO'; const timezone = Intl.DateTimeFormat().resolvedOptions().timeZone; // Format date and time according to user's locale @@ -3264,7 +3264,6 @@ function updateCacheExpiryTime() { const timeOptions = { hour: '2-digit', minute: '2-digit', - second: '2-digit', hour12: false }; @@ -3273,11 +3272,18 @@ function updateCacheExpiryTime() { const timeStr = expiryDate.toLocaleTimeString(locale, timeOptions); // Combine with timezone abbreviation - const formatted = dateStr + ' ' + timeStr; - - // Display with timezone info - expiryElement.textContent = formatted; - expiryElement.title = 'Local time: ' + formatted + ' | Timezone: ' + timezone; + const formatted = dateStr + ' kl. ' + timeStr; + const expired = expiryElement.getAttribute('data-expired') === '1'; + const refreshStarted = expiryElement.getAttribute('data-refresh-started') === '1'; + + if (expired) { + expiryElement.textContent = refreshStarted + ? ('Utlopt (' + formatted + ') - oppdaterer i bakgrunnen') + : ('Utlopt (' + formatted + ')'); + } else { + expiryElement.textContent = formatted; + } + expiryElement.title = 'Lokal tid: ' + formatted + ' | Tidssone: ' + timezone; } catch (e) { console.error('Error formatting cache expiry time:', e); expiryElement.textContent = 'Error calculating time'; diff --git a/pluginHolder/views.py b/pluginHolder/views.py index 07545cc56..8939e430f 100644 --- a/pluginHolder/views.py +++ b/pluginHolder/views.py @@ -650,8 +650,13 @@ def installed(request): for p in pluginList: logging.writeToFile(f" - {p.get('plugin_dir')}: installed={p.get('installed')}, enabled={p.get('enabled')}") - # Get cache expiry timestamp for display (will be converted to local time in browser) + # Get cache expiry timestamp for display (browser formats this as nb-NO) cache_expiry_timestamp, _ = _get_cache_expiry_time() + cache_expired = _is_cache_expired(cache_expiry_timestamp) + refresh_started = False + if cache_expired: + # If cache is stale while on Installed page, trigger best-effort background refresh. + refresh_started = _try_start_plugin_store_refresh_background() # Sort plugins A-Å by name (case-insensitive) for Grid and Table view pluginList.sort(key=lambda p: (p.get('name') or '').lower()) @@ -671,9 +676,11 @@ def installed(request): pass proc = httpProc(request, 'pluginHolder/plugins.html', - {'plugins': pluginList, 'error_plugins': errorPlugins, + {'plugins': pluginList, 'error_plugins': errorPlugins, 'installed_count': installed_count, 'active_count': active_count, - 'cache_expiry_timestamp': cache_expiry_timestamp}, 'managePlugins') + 'cache_expiry_timestamp': cache_expiry_timestamp, + 'cache_expired': cache_expired, + 'cache_refresh_started': refresh_started}, 'managePlugins') return proc.render() @csrf_exempt @@ -946,6 +953,16 @@ def _get_cache_expiry_time(): logging.writeToFile(f"Error getting cache expiry time: {str(e)}") return None, None + +def _is_cache_expired(expiry_timestamp): + """Return True if provided cache expiry timestamp is in the past.""" + try: + if not expiry_timestamp: + return False + return float(expiry_timestamp) <= time.time() + except Exception: + return False + def _get_cached_plugins(allow_expired=False): """Get plugins from cache if available and not expired