aboutsummaryrefslogtreecommitdiff
path: root/source/app/OtpWalletApp.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/app/OtpWalletApp.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/app/OtpWalletApp.mc')
-rw-r--r--source/app/OtpWalletApp.mc47
1 files changed, 34 insertions, 13 deletions
diff --git a/source/app/OtpWalletApp.mc b/source/app/OtpWalletApp.mc
index 8858878..7419433 100644
--- a/source/app/OtpWalletApp.mc
+++ b/source/app/OtpWalletApp.mc
@@ -1,17 +1,19 @@
// Author: cirakg & claude ai
-// Summary: Application entry point (Connect IQ AppBase): lifecycle and first view.
+// Summary: Application entry point (Connect IQ AppBase): lifecycle, first view, glance, locking on exit.
//
-// OtpWalletApp: the application entry point (Connect IQ AppBase).
+// Connect IQ lifecycle: initialize -> onStart -> getInitialView (or
+// getGlanceView in glance mode) -> views run -> onStop.
//
-// M0 skeleton: the app shows a home screen with its name and version. Later
-// milestones add the vault, settings processing, locking and the glance.
+// The vault is opened in getInitialView, not onStart: onStart also runs in
+// glance mode, which has too little memory for it.
//
-// Connect IQ lifecycle: initialize -> onStart -> getInitialView -> (views run)
-// -> onStop.
+// Security: onStop locks the vault (keys and decrypted codes are wiped). It
+// runs when the user leaves the app, and also when Garmin's system passcode
+// shuts running apps down.
//
-// Security note for later milestones: onStop is where every key and decrypted
-// secret gets wiped. It runs when the user leaves the app, and also when
-// Garmin's system passcode shuts running apps down.
+// getGlanceView is (:glance), so the compiler checks this class against the
+// glance scope too. The other methods never run in glance mode and use
+// non-glance code, so they opt out with (:typecheck(disableGlanceCheck)).
import Toybox.Application;
import Toybox.Lang;
@@ -19,22 +21,41 @@ import Toybox.WatchUi;
class OtpWalletApp extends Application.AppBase {
+ // True once the full app (not the glance) has started.
+ private var _started as Boolean = false;
+
function initialize() {
AppBase.initialize();
// Start of the start-up timer reported by `make perf` (debug builds only).
Diag.markStart();
}
- // Called after the app is loaded, before the first view is shown.
function onStart(state as Dictionary?) as Void {
}
- // Called when the app exits, for any reason.
+ (:typecheck(disableGlanceCheck))
+ // onStop also runs after the glance, where AppState was never loaded.
function onStop(state as Dictionary?) as Void {
+ if (_started) {
+ AppState.lock();
+ }
}
- // The first screen and its input handler.
+ // The list, or a full-screen message when the data can't be used.
+ (:typecheck(disableGlanceCheck))
function getInitialView() as [Views] or [Views, InputDelegates] {
- return [new HomeView(), new HomeDelegate()];
+ _started = true;
+ AppState.start();
+ var error = AppState.startError;
+ if (error != null) {
+ return [new InfoView("OTP Wallet", [error], "error"), new InfoDelegate()];
+ }
+ var list = new ListView();
+ return [list, new ListDelegate(list)];
+ }
+
+ (:glance)
+ function getGlanceView() as [WatchUi.GlanceView] or [WatchUi.GlanceView, WatchUi.GlanceViewDelegate] or Null {
+ return [new OtpGlanceView()];
}
}