aboutsummaryrefslogtreecommitdiff
path: root/tools
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 /tools
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 'tools')
-rw-r--r--tools/lint_project.py12
-rw-r--r--tools/ui_flow.py26
2 files changed, 37 insertions, 1 deletions
diff --git a/tools/lint_project.py b/tools/lint_project.py
index 04d525f..c1c225a 100644
--- a/tools/lint_project.py
+++ b/tools/lint_project.py
@@ -42,7 +42,17 @@ AUTHOR = "cirakg & claude ai"
HEADER_LINES = 15
DIAG_FILE = Path("source/util/Diag.mc")
# Folders that hold local tool state or generated output, never project files.
-SKIP_DIRS = {".git", ".cache", ".claude", "build", "node_modules", "__pycache__", ".pytest_cache", ".mypy_cache", ".ruff_cache"}
+SKIP_DIRS = {
+ ".git",
+ ".cache",
+ ".claude",
+ "build",
+ "node_modules",
+ "__pycache__",
+ ".pytest_cache",
+ ".mypy_cache",
+ ".ruff_cache",
+}
# Written by a tool that would drop a hand-added header on the next run.
GENERATED = {Path("docker/docs/package-lock.json")}
diff --git a/tools/ui_flow.py b/tools/ui_flow.py
index 8c08caf..3c7afb2 100644
--- a/tools/ui_flow.py
+++ b/tools/ui_flow.py
@@ -437,8 +437,33 @@ def flow_locked_entry(f: Flow) -> None:
f.expect("list", AUTO_LOCK_TIMEOUT_S)
+def flow_swipes(f: Flow, screen: str) -> None:
+ """On touch screens a vertical swipe scrolls `screen` once, whatever the
+ watch does with page behaviour; checked through the debug logs so no
+ image is involved. A swipe up must report one scroll; on the list the
+ focus must move and a swipe back must return it."""
+ if not f.touch:
+ return
+ pattern = r"DIAG list_move focus=(\d+)" if screen == "list" else r"DIAG info_scroll first=(\d+)"
+ regex = re.compile(pattern)
+ x, top, bottom = f._w() // 2, f._h() // 4, f._h() * 3 // 4
+ seen: list[str] = []
+ for start, end in ((bottom, top), (top, bottom)): # swipe up: next; down: previous
+ f.act()
+ f.sim.swipe(x, start, x, end)
+ f.log.wait_for(pattern, SCREEN_TIMEOUT_S)
+ time.sleep(SETTLE_S)
+ found = [m.group(1) for line in f.log.lines()[f.log.mark :] if (m := regex.search(line))]
+ if len(found) != 1:
+ raise FlowError(f"one swipe on {screen} scrolled {len(found)} times, not once")
+ seen.append(found[0])
+ if screen == "list" and seen[0] == seen[1]:
+ raise FlowError("a swipe on the list didn't move the focus")
+
+
def flow_menu(f: Flow) -> None:
"""The menu, and About on watches whose menu has a focus to move."""
+ flow_swipes(f, "list")
f.menu()
time.sleep(MENU_SETTLE_S)
f.shot("menu")
@@ -454,6 +479,7 @@ def flow_menu(f: Flow) -> None:
f.select()
f.expect("about")
f.shot("about")
+ flow_swipes(f, "about")
f.act()
# Touch-only watches show the menu as a freely scrolling list without
# focus, so there is no reliable "select About"; just close it.