Show Live/Ended status on LiveTrack sessions
CI / check (push) Successful in 57s
CI / deploy (push) Successful in 26s

A session's own end timestamp is absent until the activity is
actually stopped, so its presence/absence is the status signal — no
new data needed, just reading what was already there. Shown as a
badge next to the session in the list and in its map hover popup.
This commit is contained in:
randy committed 2026-09-06 23:32:58 +02:00
1 parent 55607aece9
commit 6b8ea27e22
3 files changed
+47 -5

No files matched your search

+20 -2
View File
@@ -446,8 +446,7 @@ html, body {
.livetrack-panel__row {
display: flex;
align-items: center;
justify-content: space-between;
gap: 8px;
gap: 6px;
width: 100%;
padding: 6px 4px;
border: none;
@@ -472,6 +471,8 @@ html, body {
}
.livetrack-panel__label {
flex: 1;
min-width: 0;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
@@ -481,6 +482,23 @@ html, body {
font-family: monospace;
}
.livetrack-badge {
flex-shrink: 0;
padding: 2px 6px;
border-radius: 3px;
background: #e5e5e5;
color: #666;
font-size: 10px;
font-weight: 600;
text-transform: uppercase;
letter-spacing: 0.02em;
}
.livetrack-badge--live {
background: #d7f3e3;
color: #1b7a43;
}
.livetrack-panel__time {
flex-shrink: 0;
color: #888;
+16 -3
View File
@@ -90,7 +90,11 @@ export class LiveTrackPanelControl {
timeSpan.className = "livetrack-panel__time";
timeSpan.textContent = new Date(received_at).toLocaleString();
button.append(labelSpan, timeSpan);
if (summary) {
button.append(statusBadge(summary.active), labelSpan, timeSpan);
} else {
button.append(labelSpan, timeSpan);
}
button.addEventListener("click", () => this._toggleTrack(id, button));
li.appendChild(button);
this._list.appendChild(li);
@@ -213,8 +217,9 @@ export class LiveTrackPanelControl {
// data — session_name in particular is user-supplied (whatever the LiveTrack
// session was named on the watch/app) — so escape before it lands in HTML,
// same as GpxPanelControl's popups do for GPX file contents.
function popupHtml({ session_name, activity_type, distance_meters, duration_secs, time, speed_meters_per_sec, heart_rate_beats_per_min }) {
const parts = [`<strong>${escapeHtml(session_name || "LiveTrack session")}</strong>`];
function popupHtml({ session_name, activity_type, distance_meters, duration_secs, active, time, speed_meters_per_sec, heart_rate_beats_per_min }) {
const status = active ? `<span class="livetrack-badge livetrack-badge--live">Live</span>` : `<span class="livetrack-badge">Ended</span>`;
const parts = [`<strong>${escapeHtml(session_name || "LiveTrack session")}</strong> ${status}`];
const stats = [];
if (activity_type) stats.push(escapeHtml(titleCase(activity_type)));
@@ -243,6 +248,14 @@ function escapeHtml(text) {
return div.innerHTML;
}
function statusBadge(active) {
const badge = document.createElement("span");
badge.className = "livetrack-badge";
badge.classList.toggle("livetrack-badge--live", !!active);
badge.textContent = active ? "Live" : "Ended";
return badge;
}
function summaryLabel({ session_name, activity_type, distance_meters, duration_secs }) {
const parts = [];
if (activity_type) parts.push(titleCase(activity_type));