Phase 1: foundation modules

Central Config with all tunables (retention, GPS timeout, colors,
event type keys, menu item metadata). Event / EventStore handle
persistence via Application.Storage with 7-day pruning. Logger
mirrors the same retention. LayoutMetrics and Haversine provide
resolution-independent geometry helpers. German UI strings and
placeholder menu icons landed alongside so the build stays green.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
EiSiMo 2026-04-11 19:36:15 +02:00
parent 6f56c337f7
commit 43f970d764
19 changed files with 409 additions and 2 deletions

62
source/Config.mc Normal file
View file

@ -0,0 +1,62 @@
import Toybox.Graphics;
import Toybox.Lang;
// Central configuration. All tunable values live here so they can be
// changed without touching feature code.
module Config {
// --- Retention ------------------------------------------------------
const RETENTION_SEC = 7 * 24 * 60 * 60;
// --- GPS ------------------------------------------------------------
const GPS_TIMEOUT_MS = 10000;
const GPS_TARGET_ACCURACY_M = 5;
// --- Animation / UI timings ----------------------------------------
const SUCCESS_DISPLAY_MS = 2500;
const ERROR_DISPLAY_MS = 5000;
const DELETE_HOLD_MS = 2500;
// --- Address resolution --------------------------------------------
const ADDRESS_MAX_DISTANCE_M = 20;
const PHOTON_URL = "https://photon.komoot.io/reverse";
// --- Colors (AMOLED: black background, white fg) -------------------
const COLOR_BG = 0x000000;
const COLOR_FG = 0xFFFFFF;
const COLOR_SUCCESS = 0x00AA00;
const COLOR_ERROR = 0xFF2222;
const COLOR_DELETE = 0xFF2222;
const COLOR_ACCENT = 0xFFFFFF;
// --- Event type keys ------------------------------------------------
const EVENT_GENERAL = "general";
const EVENT_START = "start";
const EVENT_END = "end";
const EVENT_ARRIVAL = "arrival";
const EVENT_ARREST = "arrest";
const EVENT_FORCE = "force";
const EVENT_EVIDENCE = "evidence";
const EVENT_SIGHTING = "sighting";
// --- Special menu actions ------------------------------------------
const ACTION_HISTORY = "history";
const ACTION_DELETE = "delete";
// Menu item metadata. Order matches display order (index 0 is first
// selected). Each entry: key, drawable id, string id, highlight color.
function menuItems() as Array<Dictionary> {
return [
{ :key => ACTION_HISTORY, :icon => Rez.Drawables.IconHistory, :label => Rez.Strings.menu_history, :color => 0xFFFFFF },
{ :key => EVENT_GENERAL, :icon => Rez.Drawables.IconEvent, :label => Rez.Strings.menu_general, :color => 0xFFAA00 },
{ :key => EVENT_START, :icon => Rez.Drawables.IconStart, :label => Rez.Strings.menu_start, :color => 0x00FF00 },
{ :key => EVENT_END, :icon => Rez.Drawables.IconEnd, :label => Rez.Strings.menu_end, :color => 0x00AAFF },
{ :key => EVENT_ARRIVAL, :icon => Rez.Drawables.IconArrival, :label => Rez.Strings.menu_arrival, :color => 0xFFFF00 },
{ :key => EVENT_ARREST, :icon => Rez.Drawables.IconArrest, :label => Rez.Strings.menu_arrest, :color => 0xFF0088 },
{ :key => EVENT_FORCE, :icon => Rez.Drawables.IconForce, :label => Rez.Strings.menu_force, :color => 0xAA00FF },
{ :key => EVENT_EVIDENCE, :icon => Rez.Drawables.IconEvidence, :label => Rez.Strings.menu_evidence, :color => 0x00FFFF },
{ :key => EVENT_SIGHTING, :icon => Rez.Drawables.IconSighting, :label => Rez.Strings.menu_sighting, :color => 0xFF8800 },
{ :key => ACTION_DELETE, :icon => Rez.Drawables.IconDelete, :label => Rez.Strings.menu_delete, :color => 0xFF2222 }
];
}
}