Add header stopwatch and asset cache-busting

- Stopwatch between logo and menu: tap to start, tap to stop, tap to reset
- AppController passes md5-based version hash for app.js and style.css to prevent browser caching issues

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Simon Kühn 2026-04-30 10:35:29 +02:00
parent 80e418f8b7
commit f0cbe5b5d0
4 changed files with 45 additions and 3 deletions

View file

@ -714,3 +714,38 @@ document.addEventListener('visibilitychange',function(){
loadGoals().then(function(g){goals=g;render();}).catch(function(){});
}
});
(function(){
var swEl = document.getElementById('sw');
var state = 0; // 0=stopped, 1=running, 2=paused
var start = 0, elapsed = 0, raf = null;
function fmt(ms){
var s = ms / 1000;
return s.toFixed(2) + 's';
}
function tick(){
swEl.textContent = fmt(Date.now() - start + elapsed);
raf = requestAnimationFrame(tick);
}
swEl.addEventListener('click', function(){
if(state === 0){
start = Date.now(); elapsed = 0;
swEl.classList.add('running');
state = 1; tick();
} else if(state === 1){
cancelAnimationFrame(raf);
elapsed += Date.now() - start;
swEl.textContent = fmt(elapsed);
swEl.classList.remove('running');
state = 2;
} else {
cancelAnimationFrame(raf);
elapsed = 0; swEl.textContent = '0.00s';
swEl.classList.remove('running');
state = 0;
}
});
})();

View file

@ -8,6 +8,8 @@ body{font-family:'DM Sans',sans-serif;background:var(--bg);color:var(--text);min
.hdr-logo{height:100px;width:auto;mix-blend-mode:multiply;display:block}
.hdr-sub{font-size:12px;color:var(--text3);margin-top:1px;font-family:'DM Mono',monospace}
.hdr-btns{display:flex;gap:8px;align-items:center}
.sw{font-family:'DM Mono',monospace;font-size:15px;color:var(--text3);cursor:pointer;user-select:none;letter-spacing:-.5px;min-width:52px;text-align:center}
.sw.running{color:var(--text1)}
.btn-add{width:38px;height:38px;border-radius:50%;background:var(--text);color:var(--bg);border:none;cursor:pointer;font-size:22px;display:flex;align-items:center;justify-content:center;font-weight:300;transition:transform .15s}
.btn-add:active{transform:scale(.92)}
.btn-menu{width:38px;height:38px;border-radius:50%;background:var(--bg3);color:var(--text2);border:1px solid var(--border);cursor:pointer;font-size:20px;display:flex;align-items:center;justify-content:center;transition:transform .15s}

View file

@ -11,6 +11,10 @@ class AppController extends AbstractController
#[Route('/{path}', name: 'app', requirements: ['path' => '.*'], priority: -10)]
public function index(): Response
{
return $this->render('app.html.twig');
$public = $this->getParameter('kernel.project_dir') . '/public/';
return $this->render('app.html.twig', [
'jsv' => substr(md5_file($public . 'app.js'), 0, 8),
'cssv' => substr(md5_file($public . 'style.css'), 0, 8),
]);
}
}

View file

@ -7,7 +7,7 @@
<meta name="mobile-web-app-capable" content="yes"/>
<meta name="apple-mobile-web-app-capable" content="yes"/>
<title>Dudi</title>
<link rel="stylesheet" href="style.css"/>
<link rel="stylesheet" href="style.css?v={{ cssv }}"/>
</head>
<body>
<div class="main-wrap">
@ -16,6 +16,7 @@
<img src="logo.png" alt="Dudi" class="hdr-logo"/>
<div class="hdr-sub" id="tlbl"></div>
</div>
<span id="sw" class="sw">0.00s</span>
<div class="hdr-btns">
<button class="btn-menu" id="btnData">⋯</button>
<button class="btn-add" id="btnNew">+</button>
@ -324,6 +325,6 @@
</div>
</template>
<script src="app.js"></script>
<script src="app.js?v={{ jsv }}"></script>
</body>
</html>