diff --git a/assets/css/style.css b/assets/css/style.css
index 7d13e65..13f427f 100644
--- a/assets/css/style.css
+++ b/assets/css/style.css
@@ -108,10 +108,8 @@ body {
position: relative;
display: flex;
align-items: center;
- justify-content: center;
+ justify-content: flex-end;
width: 100%;
- max-width: none;
- margin: 0;
}
.header-title {
@@ -128,8 +126,6 @@ body {
pointer-events: auto;
/* prevent title overlapping action buttons on small screens */
max-width: calc(100% - 200px);
- overflow: hidden;
- text-overflow: ellipsis;
}
.header-version {
diff --git a/assets/js/app.js b/assets/js/app.js
index 3c55628..5aa6077 100644
--- a/assets/js/app.js
+++ b/assets/js/app.js
@@ -76,12 +76,14 @@ function reportError(payload) {
}
// ── Webapp update notification ───────────────────────────────────────────────
-// Checks the latest GitHub release once per session and shows a text banner
-// if the running webapp version is outdated.
+// Checks both the deployed webapp version and the latest GitHub release.
+// Fires on tab focus and every 5 minutes.
+const _loadedVersion = (document.querySelector('.header-version')?.textContent?.trim() || '').replace(/^v/, '');
+
function _checkWebappUpdate() {
const STORAGE_KEY = '_evershelf_update_checked_at'; // last-checked timestamp
const SEEN_KEY = '_evershelf_update_seen_ts'; // published_at of last-dismissed release
- const TTL_MS = 6 * 60 * 60 * 1000; // re-check every 6 h (localStorage)
+ const TTL_MS = 5 * 60 * 1000; // re-check every 5 min
const now = Date.now();
const lastCheck = parseInt(localStorage.getItem(STORAGE_KEY) || '0', 10);
if (now - lastCheck < TTL_MS) return;
@@ -91,19 +93,22 @@ function _checkWebappUpdate() {
.then(r => r.ok ? r.json() : null)
.then(data => {
if (!data) return;
- // Release date-based comparison: show banner only if the release is
- // newer than the last one the user acknowledged.
- const publishedAt = data.published_at || '';
- const seenTs = localStorage.getItem(SEEN_KEY) || '';
- if (!publishedAt || publishedAt === seenTs) return;
-
- const latestTag = (data.latest_tag || '').replace(/^v/, '');
- const current = (document.querySelector('.header-version')?.textContent?.trim() || '').replace(/^v/, '');
- // If tag looks like a proper semver and they match → no update needed
- if (/^\d+\.\d+/.test(latestTag) && current && current === latestTag) return;
-
- // Show a dismissible banner at the top of the page
if (document.getElementById('_evershelf_update_banner')) return;
+
+ // ── Check 1: server has a different version deployed since this page loaded ──
+ const serverVer = (data.webapp_version || '').replace(/^v/, '');
+ const deployChanged = serverVer && _loadedVersion && serverVer !== _loadedVersion;
+
+ // ── Check 2: a newer GitHub release not yet acknowledged ──
+ const publishedAt = data.published_at || '';
+ const seenTs = localStorage.getItem(SEEN_KEY) || '';
+ const latestTag = (data.latest_tag || '').replace(/^v/, '');
+ const releaseNewer = publishedAt && publishedAt !== seenTs &&
+ /^\d+\.\d+/.test(latestTag) &&
+ _loadedVersion && latestTag !== _loadedVersion;
+
+ if (!deployChanged && !releaseNewer) return;
+
const banner = document.createElement('div');
banner.id = '_evershelf_update_banner';
banner.style.cssText = [
@@ -114,22 +119,30 @@ function _checkWebappUpdate() {
'border-bottom:2px solid #fbbf24',
'box-shadow:0 2px 8px rgba(0,0,0,.4)',
].join(';');
- const releaseUrl = data.html_url || 'https://github.com/dadaloop82/EverShelf/releases/latest';
- const versionText = /^\d+\.\d+/.test(latestTag) ? ` ${latestTag}` : '';
- banner.innerHTML =
- `⬆️ EverShelf${versionText} disponibile. ` +
- `novità` +
- `` +
+
+ let msgHtml, dismissAction;
+ if (deployChanged) {
+ // Server files updated — simple reload prompt
+ msgHtml = `🔄 Nuova versione dell'app disponibile sul server.`;
+ dismissAction = () => banner.remove(); // just hide, will reappear next check
+ } else {
+ const releaseUrl = data.html_url || 'https://github.com/dadaloop82/EverShelf/releases/latest';
+ const versionText = /^\d+\.\d+/.test(latestTag) ? ` v${latestTag}` : '';
+ msgHtml = `⬆️ EverShelf${versionText} disponibile. ` +
+ `novità`;
+ dismissAction = () => { localStorage.setItem(SEEN_KEY, publishedAt); banner.remove(); };
+ }
+
+ banner.innerHTML = msgHtml +
+ `` +
``;
document.body.prepend(banner);
- document.getElementById('_evershelf_banner_close').onclick = () => {
- localStorage.setItem(SEEN_KEY, publishedAt); // mark as seen
- banner.remove();
- };
- // Auto-dismiss after 30 s (without marking as seen, so it reappears next visit)
- setTimeout(() => banner.remove(), 30000);
+ document.getElementById('_evershelf_banner_close').onclick = dismissAction;
+ // Auto-dismiss after 30 s without marking as seen
+ setTimeout(() => { if (banner.isConnected) banner.remove(); }, 30000);
})
.catch(() => {});
}
@@ -11763,7 +11776,10 @@ async function _initApp() {
// 3) Aggiorna immediatamente quando la tab torna visibile (es. torni da Bring! app)
document.addEventListener('visibilitychange', () => {
- if (!document.hidden) refreshCurrentPage();
+ if (!document.hidden) {
+ refreshCurrentPage();
+ _checkWebappUpdate(); // also check for app updates when user returns to tab
+ }
});
// 4) Background Bring sync ogni 5 min — completamente autonomo, non dipende