Feature: Phone-Frame mit 9 App-Screenshots im Hero — SW by-v449, APP_VER 428
- 9 Screenshots synchron mit Hero-Text (Fade gemeinsam) - CSS-Phone-Frame, Statusleiste per margin-top abgeschnitten - /img Static-Mount in main.py - Screenshots als JPEG optimiert (8MB → 2.5MB gesamt) - Vorladen aller Folgebilder beim Start
|
|
@ -220,6 +220,7 @@ STATIC_DIR = os.path.join(os.path.dirname(__file__), "static")
|
|||
app.mount("/css", StaticFiles(directory=f"{STATIC_DIR}/css"), name="css")
|
||||
app.mount("/js", StaticFiles(directory=f"{STATIC_DIR}/js"), name="js")
|
||||
app.mount("/icons", StaticFiles(directory=f"{STATIC_DIR}/icons"), name="icons")
|
||||
app.mount("/img", StaticFiles(directory=f"{STATIC_DIR}/img"), name="img")
|
||||
|
||||
# User-generierte Medien (Fotos aus Tagebuch, Giftköder-Alarm, etc.)
|
||||
MEDIA_DIR = os.getenv("MEDIA_DIR", "/data/media")
|
||||
|
|
|
|||
BIN
backend/static/img/screenshots/screen-1.jpg
Normal file
|
After Width: | Height: | Size: 250 KiB |
BIN
backend/static/img/screenshots/screen-2.jpg
Normal file
|
After Width: | Height: | Size: 438 KiB |
BIN
backend/static/img/screenshots/screen-3.jpg
Normal file
|
After Width: | Height: | Size: 171 KiB |
BIN
backend/static/img/screenshots/screen-4.jpg
Normal file
|
After Width: | Height: | Size: 187 KiB |
BIN
backend/static/img/screenshots/screen-5.jpg
Normal file
|
After Width: | Height: | Size: 535 KiB |
BIN
backend/static/img/screenshots/screen-6.jpg
Normal file
|
After Width: | Height: | Size: 288 KiB |
BIN
backend/static/img/screenshots/screen-7.jpg
Normal file
|
After Width: | Height: | Size: 173 KiB |
BIN
backend/static/img/screenshots/screen-8.jpg
Normal file
|
After Width: | Height: | Size: 226 KiB |
BIN
backend/static/img/screenshots/screen-9.jpg
Normal file
|
After Width: | Height: | Size: 226 KiB |
|
|
@ -3,7 +3,7 @@
|
|||
Router, State-Management, Navigation, Initialisierung.
|
||||
============================================================ */
|
||||
|
||||
const APP_VER = '427'; // ← bei jedem Deploy mit Frontend-Änderungen erhöhen
|
||||
const APP_VER = '428'; // ← bei jedem Deploy mit Frontend-Änderungen erhöhen
|
||||
|
||||
const App = (() => {
|
||||
|
||||
|
|
|
|||
|
|
@ -13,15 +13,15 @@ window.Page_welcome = (() => {
|
|||
// HERO-SLIDES — rotieren alle 4 Sekunden
|
||||
// ----------------------------------------------------------
|
||||
const HERO_SLIDES = [
|
||||
{ headline: 'Jeder Moment zählt.', sub: 'Fotos, Notizen, Stimmungen — das Tagebuch deines Hundes.' },
|
||||
{ headline: 'Deine Gegend. Sein Revier.', sub: 'Hundeparks, Gassi-Spots und mehr — alles auf der Karte.' },
|
||||
{ headline: 'Kein Termin verpasst.', sub: 'Impfungen, Gewicht, Tierarzt — mit KI, individuell auf deinen Hund angepasst.' },
|
||||
{ headline: 'Wir achten auf deinen Hund.', sub: 'Gefahren in deiner Nähe — damit ihr gezielt aus dem Weg gehen könnt.' },
|
||||
{ headline: 'Wie eine App. Nur ohne App Store.', sub: 'Einmal auf „Zum Homescreen" — fertig. Kein Store, keine Updates, kein Stress.' },
|
||||
{ headline: 'Lieblingsrouten für immer.', sub: 'Speichere eure besten Strecken — und entdecke neue in der Nähe.' },
|
||||
{ headline: 'Gassi ist kein Solosport.', sub: 'Triff andere Hundebesitzer — spontan, in deiner Umgebung.' },
|
||||
{ headline: 'Dein virtueller Trainer.', sub: '100+ Übungen, Schritt für Schritt — individuell auf deinen Hund abgestimmt.' },
|
||||
{ headline: 'Frag nach. Du bist nicht allein.', sub: 'Erfahrungen, Tipps, Hilfe — von Hundebesitzern für Hundebesitzer.' },
|
||||
{ headline: 'Jeder Moment zählt.', sub: 'Fotos, Notizen, Stimmungen — das Tagebuch deines Hundes.', screen: '/img/screenshots/screen-1.jpg' },
|
||||
{ headline: 'Deine Gegend. Sein Revier.', sub: 'Hundeparks, Gassi-Spots und mehr — alles auf der Karte.', screen: '/img/screenshots/screen-2.jpg' },
|
||||
{ headline: 'Kein Termin verpasst.', sub: 'Impfungen, Gewicht, Tierarzt — mit KI, individuell auf deinen Hund angepasst.', screen: '/img/screenshots/screen-3.jpg' },
|
||||
{ headline: 'Wir achten auf deinen Hund.', sub: 'Gefahren in deiner Nähe — damit ihr gezielt aus dem Weg gehen könnt.', screen: '/img/screenshots/screen-4.jpg' },
|
||||
{ headline: 'Wie eine App. Nur ohne App Store.', sub: 'Einmal auf „Zum Homescreen" — fertig. Kein Store, keine Updates.', screen: '/img/screenshots/screen-5.jpg' },
|
||||
{ headline: 'Lieblingsrouten für immer.', sub: 'Speichere eure besten Strecken — und entdecke neue in der Nähe.', screen: '/img/screenshots/screen-6.jpg' },
|
||||
{ headline: 'Gassi ist kein Solosport.', sub: 'Triff andere Hundebesitzer — spontan, in deiner Umgebung.', screen: '/img/screenshots/screen-7.jpg' },
|
||||
{ headline: 'Dein virtueller Trainer.', sub: '100+ Übungen, Schritt für Schritt — individuell auf deinen Hund abgestimmt.', screen: '/img/screenshots/screen-8.jpg' },
|
||||
{ headline: 'Frag nach. Du bist nicht allein.', sub: 'Erfahrungen, Tipps, Hilfe — von Hundebesitzern für Hundebesitzer.', screen: '/img/screenshots/screen-9.jpg' },
|
||||
];
|
||||
|
||||
async function init(container, appState, params = {}) {
|
||||
|
|
@ -99,6 +99,11 @@ window.Page_welcome = (() => {
|
|||
<p class="wc-lhero-sub" id="wc-hero-sub">${HERO_SLIDES[0].sub}</p>
|
||||
<span class="wc-hero-counter" id="wc-hero-counter">1 / ${HERO_SLIDES.length}</span>
|
||||
|
||||
<div class="wc-phone-frame">
|
||||
<img class="wc-phone-screen" id="wc-phone-screen"
|
||||
src="${HERO_SLIDES[0].screen}" alt="" loading="eager">
|
||||
</div>
|
||||
|
||||
<div class="wc-lhero-cta">
|
||||
${hasPrompt ? `
|
||||
<button class="btn wc-btn-hero" id="welcome-install-hero-btn">
|
||||
|
|
@ -346,6 +351,23 @@ window.Page_welcome = (() => {
|
|||
font-weight: var(--weight-semibold); letter-spacing: 0.08em;
|
||||
margin-bottom: var(--space-5); position: relative;
|
||||
}
|
||||
.wc-phone-frame {
|
||||
width: 188px;
|
||||
border-radius: 30px;
|
||||
border: 3px solid rgba(255,255,255,0.28);
|
||||
box-shadow: 0 24px 64px rgba(0,0,0,0.45), 0 0 0 1px rgba(0,0,0,0.12);
|
||||
overflow: hidden;
|
||||
margin: 0 auto var(--space-5);
|
||||
position: relative;
|
||||
background: #111;
|
||||
}
|
||||
.wc-phone-screen {
|
||||
width: 100%;
|
||||
display: block;
|
||||
margin-top: -24px; /* iOS-Statusleiste abschneiden */
|
||||
transition: opacity 0.4s ease;
|
||||
}
|
||||
|
||||
.wc-lhero-cta {
|
||||
display: flex; flex-direction: column;
|
||||
align-items: center; gap: var(--space-3);
|
||||
|
|
@ -546,6 +568,7 @@ window.Page_welcome = (() => {
|
|||
.wc-lhero-cta { flex-direction: row; justify-content: center; }
|
||||
.wc-btn-hero { width: auto; }
|
||||
.wc-grid { grid-template-columns: repeat(4, 1fr); }
|
||||
.wc-phone-frame { width: 220px; }
|
||||
}
|
||||
@media (min-width: 1024px) {
|
||||
.wc-lhero { padding: var(--space-8) var(--space-4) var(--space-10); }
|
||||
|
|
@ -570,18 +593,26 @@ window.Page_welcome = (() => {
|
|||
const headline = _container.querySelector('#wc-hero-headline');
|
||||
const sub = _container.querySelector('#wc-hero-sub');
|
||||
const counter = _container.querySelector('#wc-hero-counter');
|
||||
const screen = _container.querySelector('#wc-phone-screen');
|
||||
if (!headline || !sub) return;
|
||||
|
||||
// nächste Screenshots vorladen
|
||||
HERO_SLIDES.forEach(s => { const i = new Image(); i.src = s.screen; });
|
||||
|
||||
_heroInterval = setInterval(() => {
|
||||
headline.style.opacity = '0';
|
||||
sub.style.opacity = '0';
|
||||
if (screen) screen.style.opacity = '0';
|
||||
|
||||
setTimeout(() => {
|
||||
idx = (idx + 1) % HERO_SLIDES.length;
|
||||
headline.textContent = HERO_SLIDES[idx].headline;
|
||||
sub.textContent = HERO_SLIDES[idx].sub;
|
||||
const slide = HERO_SLIDES[idx];
|
||||
headline.textContent = slide.headline;
|
||||
sub.textContent = slide.sub;
|
||||
if (screen) screen.src = slide.screen;
|
||||
headline.style.opacity = '1';
|
||||
sub.style.opacity = '1';
|
||||
if (screen) screen.style.opacity = '1';
|
||||
if (counter) counter.textContent = `${idx + 1} / ${HERO_SLIDES.length}`;
|
||||
}, 400);
|
||||
}, 6000);
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
Offline-Cache + Push Notifications + Tile-Cache
|
||||
============================================================ */
|
||||
|
||||
const CACHE_VERSION = 'by-v448';
|
||||
const CACHE_VERSION = 'by-v449';
|
||||
const CACHE_STATIC = `${CACHE_VERSION}-static`;
|
||||
const CACHE_TILES = 'ban-yaro-tiles-v1'; // bleibt über SW-Updates erhalten
|
||||
|
||||
|
|
|
|||