summaryrefslogtreecommitdiff
path: root/source/ui/Gesture.mc
diff options
context:
space:
mode:
authorcirakg <cirakg@cirakg.xyz>2026-10-25 13:13:39 +0100
committercirakg <cirakg@cirakg.xyz>2026-10-25 13:13:39 +0100
commit404b505a41362f340e79374ee3ad4dbd468da3e4 (patch)
tree883d4f1ecda6c30ce890b1aa4026c8ba1726804e /source/ui/Gesture.mc
parent096b5a4d17c85fa5f87db3e72364e9c3506d1e64 (diff)
fix(ui): vertical swipes and drags scroll the list and text screens
The Forerunner 70 sends no page behaviour for a swipe on a custom view, so the list and info screens only scrolled with the buttons. Swipes and drags now scroll them directly; one gesture scrolls once even when the device also sends the page behaviour, and a drag's release opens no row. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Diffstat (limited to 'source/ui/Gesture.mc')
-rw-r--r--source/ui/Gesture.mc88
1 files changed, 88 insertions, 0 deletions
diff --git a/source/ui/Gesture.mc b/source/ui/Gesture.mc
new file mode 100644
index 0000000..0824eb1
--- /dev/null
+++ b/source/ui/Gesture.mc
@@ -0,0 +1,88 @@
+// Author: cirakg & claude ai
+// Summary: Vertical swipes and drags that scroll a custom view (the Forerunner 70 sends no next/previous-page behaviour for them), scrolling once per gesture.
+
+import Toybox.Lang;
+import Toybox.System;
+import Toybox.WatchUi;
+
+// A touch gesture can reach a delegate several ways at once: as drag events,
+// as a swipe, and as the next/previous-page behaviour. Some watches send only
+// the drag. The first one to scroll marks the time; the others arriving within
+// DEDUPE_MS are ignored, so one gesture scrolls once. The UP/DOWN buttons
+// never mark, so they are only held back right after a touch gesture.
+module Gesture {
+
+ const DEDUPE_MS = 300;
+ // A drag shorter than this part of the screen height does not scroll.
+ const MIN_DRAG_DIVISOR = 8;
+ // A drag longer than this part still counts as a drag, not a tap.
+ const SLOP_DIVISOR = 32;
+
+ var _scrolledMs as Number? = null;
+ var _draggedMs as Number? = null;
+ var _startY as Number? = null;
+
+ function _within(since as Number?) as Boolean {
+ if (since == null) {
+ return false;
+ }
+ var elapsed = System.getTimer() - since;
+ return elapsed >= 0 && elapsed < DEDUPE_MS;
+ }
+
+ // True right after a touch gesture scrolled: next/previous-page and
+ // swipe events in this window belong to that gesture.
+ function recent() as Boolean {
+ return _within(_scrolledMs);
+ }
+
+ // True right after a drag: a tap arriving now is its end, not a tap.
+ function tapIgnored() as Boolean {
+ return _within(_draggedMs);
+ }
+
+ function isVertical(event as WatchUi.SwipeEvent) as Boolean {
+ var direction = event.getDirection();
+ return direction == WatchUi.SWIPE_UP || direction == WatchUi.SWIPE_DOWN;
+ }
+
+ // The step for a vertical swipe: 1 (next, swipe up), -1 (previous), or 0
+ // when this gesture already scrolled.
+ function swipeStep(event as WatchUi.SwipeEvent) as Number {
+ if (recent()) {
+ return 0;
+ }
+ _scrolledMs = System.getTimer();
+ return event.getDirection() == WatchUi.SWIPE_UP ? 1 : -1;
+ }
+
+ // Feed a drag event. At the end of a long enough vertical drag returns
+ // the signed number of units to scroll (positive = next, finger moved
+ // up), at least 1 and distance / unit otherwise; 0 for anything else.
+ function dragStep(event as WatchUi.DragEvent, unit as Number) as Number {
+ var y = event.getCoordinates()[1];
+ var type = event.getType();
+ if (type == WatchUi.DRAG_TYPE_START) {
+ _startY = y;
+ return 0;
+ }
+ var start = _startY;
+ if (type != WatchUi.DRAG_TYPE_STOP || start == null) {
+ return 0;
+ }
+ _startY = null;
+ var height = System.getDeviceSettings().screenHeight;
+ var distance = start - y;
+ var length = distance < 0 ? -distance : distance;
+ if (length > height / SLOP_DIVISOR) {
+ _draggedMs = System.getTimer();
+ }
+ if (length < height / MIN_DRAG_DIVISOR || recent()) {
+ return 0;
+ }
+ _scrolledMs = System.getTimer();
+ var units = unit > 0 ? length / unit : 1;
+ units = units < 1 ? 1 : units;
+ return distance < 0 ? -units : units;
+ }
+}