Feature: FAB → 'Alle Funktionen' — kompaktes Chip-Grid aller verfügbaren Seiten (SW by-v751)
This commit is contained in:
parent
fdbd5448bc
commit
bd7b694874
5 changed files with 74 additions and 6 deletions
|
|
@ -327,7 +327,7 @@ MEDIA_DIR = os.getenv("MEDIA_DIR", "/data/media")
|
||||||
os.makedirs(MEDIA_DIR, exist_ok=True)
|
os.makedirs(MEDIA_DIR, exist_ok=True)
|
||||||
app.mount("/media", StaticFiles(directory=MEDIA_DIR), name="media")
|
app.mount("/media", StaticFiles(directory=MEDIA_DIR), name="media")
|
||||||
|
|
||||||
APP_VER = "750" # muss mit APP_VER in app.js übereinstimmen
|
APP_VER = "751" # muss mit APP_VER in app.js übereinstimmen
|
||||||
|
|
||||||
@app.get("/api/version")
|
@app.get("/api/version")
|
||||||
async def app_version():
|
async def app_version():
|
||||||
|
|
|
||||||
|
|
@ -578,7 +578,7 @@
|
||||||
<script src="/js/api.js?v=94"></script>
|
<script src="/js/api.js?v=94"></script>
|
||||||
<script src="/js/ui.js?v=94"></script>
|
<script src="/js/ui.js?v=94"></script>
|
||||||
<script src="/js/app.js?v=94"></script>
|
<script src="/js/app.js?v=94"></script>
|
||||||
<script src="/js/worlds.js?v=750"></script>
|
<script src="/js/worlds.js?v=751"></script>
|
||||||
|
|
||||||
<!-- Feature-Seiten werden lazy geladen -->
|
<!-- Feature-Seiten werden lazy geladen -->
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@
|
||||||
Router, State-Management, Navigation, Initialisierung.
|
Router, State-Management, Navigation, Initialisierung.
|
||||||
============================================================ */
|
============================================================ */
|
||||||
|
|
||||||
const APP_VER = '750'; // ← bei jedem Deploy mit Frontend-Änderungen erhöhen
|
const APP_VER = '751'; // ← bei jedem Deploy mit Frontend-Änderungen erhöhen
|
||||||
const APP_VERSION = '1.5.0'; // ← semantische Version, wird bei make release gesetzt
|
const APP_VERSION = '1.5.0'; // ← semantische Version, wird bei make release gesetzt
|
||||||
const IS_STAGING = location.hostname === 'staging.banyaro.app';
|
const IS_STAGING = location.hostname === 'staging.banyaro.app';
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -267,7 +267,6 @@ window.Worlds = (() => {
|
||||||
|
|
||||||
function _openFab() {
|
function _openFab() {
|
||||||
const options = _fabOptions();
|
const options = _fabOptions();
|
||||||
if (!options.length) return;
|
|
||||||
|
|
||||||
const meldenPages = new Set(['poison','lost','recalls','map']);
|
const meldenPages = new Set(['poison','lost','recalls','map']);
|
||||||
const meldenCount = options.filter(o => meldenPages.has(o.page)).length;
|
const meldenCount = options.filter(o => meldenPages.has(o.page)).length;
|
||||||
|
|
@ -282,7 +281,7 @@ window.Worlds = (() => {
|
||||||
padding:20px 16px calc(env(safe-area-inset-bottom,16px) + 16px);
|
padding:20px 16px calc(env(safe-area-inset-bottom,16px) + 16px);
|
||||||
box-shadow:0 -8px 32px rgba(0,0,0,0.2)">
|
box-shadow:0 -8px 32px rgba(0,0,0,0.2)">
|
||||||
<div style="display:flex;align-items:center;justify-content:space-between;margin-bottom:16px">
|
<div style="display:flex;align-items:center;justify-content:space-between;margin-bottom:16px">
|
||||||
<div style="font-size:var(--text-base);font-weight:700">${title}</div>
|
<div style="font-size:var(--text-base);font-weight:700">${options.length ? title : 'Schnellzugriff'}</div>
|
||||||
<button id="fab-close" style="background:var(--c-border);border:none;border-radius:50%;
|
<button id="fab-close" style="background:var(--c-border);border:none;border-radius:50%;
|
||||||
width:28px;height:28px;cursor:pointer;display:flex;align-items:center;justify-content:center">
|
width:28px;height:28px;cursor:pointer;display:flex;align-items:center;justify-content:center">
|
||||||
<svg class="ph-icon" style="width:14px;height:14px"><use href="/icons/phosphor.svg#x"></use></svg>
|
<svg class="ph-icon" style="width:14px;height:14px"><use href="/icons/phosphor.svg#x"></use></svg>
|
||||||
|
|
@ -308,6 +307,12 @@ window.Worlds = (() => {
|
||||||
</button>
|
</button>
|
||||||
`).join('')}
|
`).join('')}
|
||||||
</div>
|
</div>
|
||||||
|
<button id="fab-all-btn" style="display:flex;align-items:center;justify-content:center;gap:8px;
|
||||||
|
width:100%;margin-top:${options.length ? '14px' : '0'};padding:12px;border:none;
|
||||||
|
background:none;cursor:pointer;color:var(--c-primary);font-size:var(--text-sm);font-weight:600">
|
||||||
|
<svg class="ph-icon" style="width:16px;height:16px"><use href="/icons/phosphor.svg#squares-four"></use></svg>
|
||||||
|
Alle Funktionen
|
||||||
|
</button>
|
||||||
</div>
|
</div>
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
|
@ -316,6 +321,7 @@ window.Worlds = (() => {
|
||||||
const _close = () => ov.remove();
|
const _close = () => ov.remove();
|
||||||
ov.querySelector('#fab-backdrop').addEventListener('click', _close);
|
ov.querySelector('#fab-backdrop').addEventListener('click', _close);
|
||||||
ov.querySelector('#fab-close').addEventListener('click', _close);
|
ov.querySelector('#fab-close').addEventListener('click', _close);
|
||||||
|
ov.querySelector('#fab-all-btn').addEventListener('click', () => { _close(); _openAllChips(); });
|
||||||
ov.querySelectorAll('.fab-option').forEach(btn => {
|
ov.querySelectorAll('.fab-option').forEach(btn => {
|
||||||
btn.addEventListener('click', () => {
|
btn.addEventListener('click', () => {
|
||||||
_close();
|
_close();
|
||||||
|
|
@ -333,6 +339,68 @@ window.Worlds = (() => {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function _openAllChips() {
|
||||||
|
const worldNames = ['jetzt', 'hund', 'welt'];
|
||||||
|
const worldLabels = { jetzt: 'JETZT', hund: 'HUND', welt: 'WELT' };
|
||||||
|
|
||||||
|
const sections = worldNames.map(w => {
|
||||||
|
const chips = (_DEFAULT_CONFIG[w] || []).map(_chipMeta).filter(c => c && _chipAllowed(c));
|
||||||
|
if (!chips.length) return '';
|
||||||
|
return `
|
||||||
|
<div style="margin-bottom:20px">
|
||||||
|
<div style="font-size:var(--text-xs);font-weight:700;color:var(--c-text-secondary);
|
||||||
|
letter-spacing:0.08em;margin-bottom:10px">${worldLabels[w]}</div>
|
||||||
|
<div style="display:grid;grid-template-columns:repeat(4,1fr);gap:8px">
|
||||||
|
${chips.map(c => `
|
||||||
|
<button class="all-chip-btn" data-page="${c.page}"
|
||||||
|
style="display:flex;flex-direction:column;align-items:center;gap:6px;
|
||||||
|
background:var(--c-bg-card);border:1px solid var(--c-border);
|
||||||
|
border-radius:14px;padding:12px 6px;cursor:pointer;
|
||||||
|
transition:background .12s">
|
||||||
|
<svg class="ph-icon" style="width:1.4rem;height:1.4rem;color:var(--c-primary)">
|
||||||
|
<use href="/icons/phosphor.svg#${c.icon}"></use>
|
||||||
|
</svg>
|
||||||
|
<span style="font-size:10px;font-weight:600;color:var(--c-text);text-align:center;
|
||||||
|
line-height:1.2;word-break:break-word">${c.label}</span>
|
||||||
|
</button>
|
||||||
|
`).join('')}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
`;
|
||||||
|
}).join('');
|
||||||
|
|
||||||
|
const ov = document.createElement('div');
|
||||||
|
ov.id = 'fab-overlay';
|
||||||
|
ov.style.cssText = 'position:fixed;inset:0;z-index:460;display:flex;flex-direction:column;justify-content:flex-end';
|
||||||
|
ov.innerHTML = `
|
||||||
|
<div id="fab-backdrop" style="position:absolute;inset:0;background:rgba(0,0,0,0.55);backdrop-filter:blur(2px)"></div>
|
||||||
|
<div style="position:relative;z-index:1;background:var(--c-bg);border-radius:24px 24px 0 0;
|
||||||
|
padding:20px 16px calc(env(safe-area-inset-bottom,16px) + 16px);
|
||||||
|
box-shadow:0 -8px 32px rgba(0,0,0,0.2);max-height:82vh;overflow-y:auto">
|
||||||
|
<div style="display:flex;align-items:center;justify-content:space-between;margin-bottom:20px">
|
||||||
|
<div style="font-size:var(--text-base);font-weight:700">Alle Funktionen</div>
|
||||||
|
<button id="fab-close" style="background:var(--c-border);border:none;border-radius:50%;
|
||||||
|
width:28px;height:28px;cursor:pointer;display:flex;align-items:center;justify-content:center">
|
||||||
|
<svg class="ph-icon" style="width:14px;height:14px"><use href="/icons/phosphor.svg#x"></use></svg>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
${sections}
|
||||||
|
</div>
|
||||||
|
`;
|
||||||
|
|
||||||
|
document.body.appendChild(ov);
|
||||||
|
|
||||||
|
const _close = () => ov.remove();
|
||||||
|
ov.querySelector('#fab-backdrop').addEventListener('click', _close);
|
||||||
|
ov.querySelector('#fab-close').addEventListener('click', _close);
|
||||||
|
ov.querySelectorAll('.all-chip-btn').forEach(btn => {
|
||||||
|
btn.addEventListener('click', () => {
|
||||||
|
_close();
|
||||||
|
navigateTo(btn.dataset.page);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
// ── SCHNELL-GASSI ─────────────────────────────────────────────
|
// ── SCHNELL-GASSI ─────────────────────────────────────────────
|
||||||
|
|
||||||
async function _openQuickGassi() {
|
async function _openQuickGassi() {
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@
|
||||||
Offline-Cache + Push Notifications + Tile-Cache
|
Offline-Cache + Push Notifications + Tile-Cache
|
||||||
============================================================ */
|
============================================================ */
|
||||||
|
|
||||||
const CACHE_VERSION = 'by-v750';
|
const CACHE_VERSION = 'by-v751';
|
||||||
const CACHE_STATIC = `${CACHE_VERSION}-static`;
|
const CACHE_STATIC = `${CACHE_VERSION}-static`;
|
||||||
const CACHE_TILES = 'ban-yaro-tiles-v1'; // bleibt über SW-Updates erhalten
|
const CACHE_TILES = 'ban-yaro-tiles-v1'; // bleibt über SW-Updates erhalten
|
||||||
const CACHE_API = 'ban-yaro-api-v1'; // API-Response-Cache
|
const CACHE_API = 'ban-yaro-api-v1'; // API-Response-Cache
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue