From 21a62d79c364e5cac811257b2fd39889212b8ad3 Mon Sep 17 00:00:00 2001 From: EiSiMo Date: Mon, 13 Apr 2026 19:41:57 +0200 Subject: [PATCH] Fix tap-to-rotate and GPS cancel crash - 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) --- source/GpsService.mc | 8 ++++++++ source/LoadingDelegate.mc | 15 +++++++++++++++ source/LoadingView.mc | 4 ++++ source/MenuDelegate.mc | 23 +++++++++++++++-------- 4 files changed, 42 insertions(+), 8 deletions(-) create mode 100644 source/LoadingDelegate.mc diff --git a/source/GpsService.mc b/source/GpsService.mc index 7101556..59805f5 100644 --- a/source/GpsService.mc +++ b/source/GpsService.mc @@ -60,6 +60,14 @@ class GpsService { } } + function stop() as Void { + if (_finished) { return; } + _finished = true; + _timer.stop(); + _pollTimer.stop(); + Position.enableLocationEvents(Position.LOCATION_DISABLE, method(:_onPosition)); + } + function _onTimeout() as Void { _finish(_bestFix); } diff --git a/source/LoadingDelegate.mc b/source/LoadingDelegate.mc new file mode 100644 index 0000000..9cbbd94 --- /dev/null +++ b/source/LoadingDelegate.mc @@ -0,0 +1,15 @@ +import Toybox.Lang; +import Toybox.WatchUi; + +// Allows the user to cancel GPS acquisition by pressing BACK. +class LoadingDelegate extends WatchUi.BehaviorDelegate { + + function initialize() { + BehaviorDelegate.initialize(); + } + + function onBack() as Boolean { + WatchUi.popView(WatchUi.SLIDE_RIGHT); + return true; + } +} diff --git a/source/LoadingView.mc b/source/LoadingView.mc index edcf697..8cc7eb6 100644 --- a/source/LoadingView.mc +++ b/source/LoadingView.mc @@ -30,6 +30,10 @@ class LoadingView extends WatchUi.View { function onHide() as Void { _animTimer.stop(); + if (_gps != null) { + _gps.stop(); + _gps = null; + } } function _tick() as Void { diff --git a/source/MenuDelegate.mc b/source/MenuDelegate.mc index a13a4df..0169b64 100644 --- a/source/MenuDelegate.mc +++ b/source/MenuDelegate.mc @@ -7,6 +7,7 @@ import Toybox.WatchUi; class MenuDelegate extends WatchUi.BehaviorDelegate { private var _view as MenuView; + private var _tapHandled as Boolean = false; function initialize(view as MenuView) { BehaviorDelegate.initialize(); @@ -28,18 +29,24 @@ class MenuDelegate extends WatchUi.BehaviorDelegate { var tapX = coords[0] as Number; var tapY = coords[1] as Number; var idx = _view.itemIndexAt(tapX, tapY); - if (idx < 0) { return false; } - if (idx == _view.selectedIndex()) { - // Tap on already-selected item → open it. - return _openSelected(); + if (idx >= 0 && idx != _view.selectedIndex()) { + // Tap on non-selected icon → rotate to it, block onSelect. + _view.rotateTo(idx); + _tapHandled = true; + return true; } - // Tap on another item → rotate to it. - _view.rotateTo(idx); - return true; + + // Tap on selected icon or empty area → let onSelect handle it. + return false; } function onSelect() as Boolean { + // If a tap already handled this event, skip. + if (_tapHandled) { + _tapHandled = false; + return true; + } return _openSelected(); } @@ -58,7 +65,7 @@ class MenuDelegate extends WatchUi.BehaviorDelegate { return true; } - WatchUi.pushView(new LoadingView(key), null, WatchUi.SLIDE_IMMEDIATE); + WatchUi.pushView(new LoadingView(key), new LoadingDelegate(), WatchUi.SLIDE_IMMEDIATE); return true; } }