summaryrefslogtreecommitdiff
path: root/source/ui/ListDelegate.mc
diff options
context:
space:
mode:
authorcirakg <cirakg@cirakg.xyz>2026-10-19 22:28:09 +0200
committercirakg <cirakg@cirakg.xyz>2026-10-19 22:28:09 +0200
commit35042ff04ffc50e55ff59a385849442be4429d6b (patch)
tree3c142dd9bfb995b7aacdf39128e591dd3f9370de /source/ui/ListDelegate.mc
parent871aba901501302586895d266fe4569665d9fe70 (diff)
feat(ui): add the list, OTP detail, PIN entry, menu, info screens and glance
List with live codes and countdowns, adaptive rows and lazy headers; OTP detail with ring or bar, next code and HOTP next; PIN keypad or button selector with create, unlock, change, lockout display and pending promotion; native menu; glance with the entry count; self-test after the first frame; option properties with defaults. Codes are computed one per timer event, apart from drawing, for the watchdog. A UI-test build (uitest.jungle) starts with fake entries, PIN 123456 and a frozen clock. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Diffstat (limited to 'source/ui/ListDelegate.mc')
-rw-r--r--source/ui/ListDelegate.mc88
1 files changed, 88 insertions, 0 deletions
diff --git a/source/ui/ListDelegate.mc b/source/ui/ListDelegate.mc
new file mode 100644
index 0000000..a7c8bf0
--- /dev/null
+++ b/source/ui/ListDelegate.mc
@@ -0,0 +1,88 @@
+// Author: cirakg & claude ai
+// Summary: Input on the list (README 13.4): scroll with UP/DOWN or swipes, open with START or a tap, menu (MENU or long press), back exits.
+
+import Toybox.Lang;
+import Toybox.WatchUi;
+
+class ListDelegate extends WatchUi.BehaviorDelegate {
+
+ private var _view as ListView;
+
+ function initialize(view as ListView) {
+ BehaviorDelegate.initialize();
+ _view = view;
+ }
+
+ function onNextPage() as Boolean {
+ AppState.activity();
+ _view.move(1);
+ return true;
+ }
+
+ function onPreviousPage() as Boolean {
+ AppState.activity();
+ _view.move(-1);
+ return true;
+ }
+
+ // On touch screens a tap arrives as the select behaviour first; returning
+ // false passes it on to onTap, which opens the row under the finger. The
+ // START button then comes through onKey.
+ function onSelect() as Boolean {
+ if (Ui.isTouch()) {
+ return false;
+ }
+ openFocused();
+ return true;
+ }
+
+ function onKey(event as WatchUi.KeyEvent) as Boolean {
+ if (Ui.isTouch() && event.getKey() == WatchUi.KEY_ENTER) {
+ openFocused();
+ return true;
+ }
+ return false;
+ }
+
+ private function openFocused() as Void {
+ AppState.activity();
+ var id = _view.focusedId();
+ if (id != null) {
+ Nav.openEntry(id);
+ }
+ }
+
+ // A tap opens the row under the finger.
+ function onTap(event as WatchUi.ClickEvent) as Boolean {
+ AppState.activity();
+ var index = _view.rowAt(event.getCoordinates()[1]);
+ if (index < 0) {
+ return true;
+ }
+ _view.focus = index;
+ var id = _view.focusedId();
+ if (id != null) {
+ Nav.openEntry(id);
+ }
+ return true;
+ }
+
+ // A long press opens the menu too: watches without a MENU button
+ // (Venu X1) have no other way to reach it (README 13.4).
+ function onHold(event as WatchUi.ClickEvent) as Boolean {
+ AppState.activity();
+ Nav.openMenu();
+ return true;
+ }
+
+ function onMenu() as Boolean {
+ AppState.activity();
+ Nav.openMenu();
+ return true;
+ }
+
+ // BACK leaves the app; onStop locks everything.
+ function onBack() as Boolean {
+ return false;
+ }
+}