- Tap on non-selected icon rotates instead of opening, flag prevents onSelect from double-firing - GpsService.stop() for clean cancellation - LoadingView stops GPS on hide (BACK button) - LoadingDelegate allows BACK to cancel GPS acquisition Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
95 lines
3.1 KiB
MonkeyC
95 lines
3.1 KiB
MonkeyC
import Toybox.Graphics;
|
|
import Toybox.Lang;
|
|
import Toybox.Math;
|
|
import Toybox.Time;
|
|
import Toybox.Timer;
|
|
import Toybox.WatchUi;
|
|
|
|
// Full-screen loading state shown while GpsService is acquiring a
|
|
// fix. Draws a circular progress bar along the display edge plus
|
|
// the German prompt "Standort wird bestimmt" in the center.
|
|
class LoadingView extends WatchUi.View {
|
|
|
|
private var _eventType as String;
|
|
private var _gps as GpsService or Null;
|
|
private var _animTimer as Timer.Timer;
|
|
private var _startMs as Number = 0;
|
|
|
|
function initialize(eventType as String) {
|
|
View.initialize();
|
|
_eventType = eventType;
|
|
_animTimer = new Timer.Timer();
|
|
}
|
|
|
|
function onShow() as Void {
|
|
_startMs = _nowMs();
|
|
_animTimer.start(method(:_tick), 50, true);
|
|
_gps = new GpsService(method(:_onGpsResult));
|
|
_gps.start();
|
|
}
|
|
|
|
function onHide() as Void {
|
|
_animTimer.stop();
|
|
if (_gps != null) {
|
|
_gps.stop();
|
|
_gps = null;
|
|
}
|
|
}
|
|
|
|
function _tick() as Void {
|
|
WatchUi.requestUpdate();
|
|
}
|
|
|
|
function _onGpsResult(result as Dictionary or Null) as Void {
|
|
_animTimer.stop();
|
|
var now = Time.now().value();
|
|
if (result != null) {
|
|
var event = new Event(
|
|
_eventType,
|
|
now,
|
|
result["lat"] as Float or Null,
|
|
result["lon"] as Float or Null,
|
|
result["acc"] as Float or Null
|
|
);
|
|
EventStore.add(event);
|
|
WatchUi.switchToView(new SuccessView(), null, WatchUi.SLIDE_IMMEDIATE);
|
|
} else {
|
|
// No usable fix at all → save event with null coords (per
|
|
// spec), but still surface an error screen so the user
|
|
// knows GPS did not lock.
|
|
var event = new Event(_eventType, now, null, null, null);
|
|
EventStore.add(event);
|
|
WatchUi.switchToView(new ErrorView(), null, WatchUi.SLIDE_IMMEDIATE);
|
|
}
|
|
}
|
|
|
|
function onUpdate(dc as Dc) as Void {
|
|
dc.setColor(Config.COLOR_FG, Config.COLOR_BG);
|
|
dc.clear();
|
|
|
|
var cx = LayoutMetrics.centerX(dc);
|
|
var cy = LayoutMetrics.centerY(dc);
|
|
var radius = LayoutMetrics.edgeArcRadius(dc);
|
|
|
|
// Circular progress — white arc that grows with elapsed time.
|
|
var elapsed = _nowMs() - _startMs;
|
|
var progress = elapsed.toFloat() / Config.GPS_TIMEOUT_MS.toFloat();
|
|
if (progress > 1.0) { progress = 1.0; }
|
|
|
|
dc.setPenWidth(LayoutMetrics.edgeArcPenWidth(dc));
|
|
dc.setColor(Config.COLOR_ACCENT, Config.COLOR_BG);
|
|
var sweep = progress * 360.0;
|
|
// drawArc uses degrees with 0° = 3 o'clock and counter-clockwise.
|
|
// Start at 12 o'clock and sweep clockwise.
|
|
var startDeg = 90;
|
|
var endDeg = 90 - sweep;
|
|
dc.drawArc(cx, cy, radius, Graphics.ARC_CLOCKWISE, startDeg, endDeg);
|
|
|
|
dc.setColor(Config.COLOR_FG, Config.COLOR_BG);
|
|
TextUtils.drawResourceCentered(dc, Rez.Strings.loading_gps, cx, cy, Graphics.FONT_TINY);
|
|
}
|
|
|
|
private function _nowMs() as Number {
|
|
return System.getTimer();
|
|
}
|
|
}
|