Phase 6: glance widget with cached address

App type changed to widget for glance support. GlanceView shows
event type, date/time, and street+housenumber (or coordinates as
fallback). Addresses are cached in Event storage on first view in
history. Glance-required modules annotated with (:glance). Address
distance threshold raised to 70m.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
EiSiMo 2026-04-13 15:31:46 +02:00
parent eea1a835cd
commit 79cdb9f210
9 changed files with 134 additions and 12 deletions

83
source/GlanceView.mc Normal file
View file

@ -0,0 +1,83 @@
import Toybox.Graphics;
import Toybox.Lang;
import Toybox.Time;
import Toybox.Time.Gregorian;
import Toybox.WatchUi;
// Glance shown in the widget list. Shows the most recent event:
// line 1: event type
// line 2: date + time
// line 3: street + housenumber (if cached)
(:glance)
class GlanceView extends WatchUi.GlanceView {
function initialize() {
GlanceView.initialize();
}
function onUpdate(dc as Dc) as Void {
dc.setColor(Config.COLOR_FG, Config.COLOR_BG);
dc.clear();
var h = dc.getHeight();
var font = Graphics.FONT_GLANCE;
var lineH = dc.getFontHeight(font);
var margin = 4;
var latest = EventStore.latest();
if (latest == null) {
dc.drawText(margin, h / 2, font, "Keine Einträge",
Graphics.TEXT_JUSTIFY_LEFT | Graphics.TEXT_JUSTIFY_VCENTER);
return;
}
var totalH = 3 * lineH;
var startY = (h - totalH) / 2 + lineH / 2;
// Line 1: event type.
dc.drawText(margin, startY, font,
_eventLabel(latest.type),
Graphics.TEXT_JUSTIFY_LEFT | Graphics.TEXT_JUSTIFY_VCENTER);
// Line 2: date + time.
dc.drawText(margin, startY + lineH, font,
_formatTimestamp(latest.timestamp),
Graphics.TEXT_JUSTIFY_LEFT | Graphics.TEXT_JUSTIFY_VCENTER);
// Line 3: address or coordinates.
var line3;
if (latest.address != null) {
line3 = latest.address as String;
} else if (latest.lat != null && latest.lon != null) {
line3 = (latest.lat as Float).format("%.4f") + ", " + (latest.lon as Float).format("%.4f");
} else {
line3 = "Kein Standort";
}
dc.drawText(margin, startY + lineH * 2, font, line3,
Graphics.TEXT_JUSTIFY_LEFT | Graphics.TEXT_JUSTIFY_VCENTER);
}
private function _eventLabel(key as String) as String {
if (key.equals(Config.EVENT_GENERAL)) { return "Ereignis"; }
if (key.equals(Config.EVENT_START)) { return "Einsatzbeginn"; }
if (key.equals(Config.EVENT_END)) { return "Einsatzende"; }
if (key.equals(Config.EVENT_ARRIVAL)) { return "Eintreffen"; }
if (key.equals(Config.EVENT_ARREST)) { return "Festnahme"; }
if (key.equals(Config.EVENT_FORCE)) { return "Zwang"; }
if (key.equals(Config.EVENT_EVIDENCE)) { return "Beweismittel"; }
if (key.equals(Config.EVENT_SIGHTING)) { return "Sichtung"; }
return key;
}
private function _formatTimestamp(ts as Number) as String {
var moment = new Time.Moment(ts);
var info = Gregorian.info(moment, Time.FORMAT_SHORT);
return Lang.format("$1$.$2$.$3$ $4$:$5$", [
info.day.format("%02d"),
info.month.format("%02d"),
info.year,
info.hour.format("%02d"),
info.min.format("%02d")
]);
}
}