summaryrefslogtreecommitdiff
path: root/source
diff options
context:
space:
mode:
Diffstat (limited to 'source')
-rw-r--r--source/app/AppInfo.mc16
-rw-r--r--source/app/OtpWalletApp.mc40
-rw-r--r--source/ui/HomeDelegate.mc16
-rw-r--r--source/ui/HomeView.mc42
-rw-r--r--source/util/Diag.mc50
5 files changed, 164 insertions, 0 deletions
diff --git a/source/app/AppInfo.mc b/source/app/AppInfo.mc
new file mode 100644
index 0000000..5b2a586
--- /dev/null
+++ b/source/app/AppInfo.mc
@@ -0,0 +1,16 @@
+// Author: cirakg & claude ai
+// Summary: Build-time facts about the app, such as its semantic version.
+//
+// AppInfo: build-time facts about the app.
+//
+// VERSION follows semantic versioning (README section 22). It is shown on the
+// home screen now and in the About screen and settings later; keep it equal to
+// the newest version in CHANGELOG.md once releases start.
+
+import Toybox.Lang;
+
+module AppInfo {
+
+ // Semantic version of the app: MAJOR.MINOR.PATCH.
+ const VERSION = "0.1.0";
+}
diff --git a/source/app/OtpWalletApp.mc b/source/app/OtpWalletApp.mc
new file mode 100644
index 0000000..8858878
--- /dev/null
+++ b/source/app/OtpWalletApp.mc
@@ -0,0 +1,40 @@
+// Author: cirakg & claude ai
+// Summary: Application entry point (Connect IQ AppBase): lifecycle and first view.
+//
+// OtpWalletApp: the application entry point (Connect IQ AppBase).
+//
+// M0 skeleton: the app shows a home screen with its name and version. Later
+// milestones add the vault, settings processing, locking and the glance.
+//
+// Connect IQ lifecycle: initialize -> onStart -> getInitialView -> (views run)
+// -> onStop.
+//
+// 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.
+
+import Toybox.Application;
+import Toybox.Lang;
+import Toybox.WatchUi;
+
+class OtpWalletApp extends Application.AppBase {
+
+ 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.
+ function onStop(state as Dictionary?) as Void {
+ }
+
+ // The first screen and its input handler.
+ function getInitialView() as [Views] or [Views, InputDelegates] {
+ return [new HomeView(), new HomeDelegate()];
+ }
+}
diff --git a/source/ui/HomeDelegate.mc b/source/ui/HomeDelegate.mc
new file mode 100644
index 0000000..fe23ae6
--- /dev/null
+++ b/source/ui/HomeDelegate.mc
@@ -0,0 +1,16 @@
+// Author: cirakg & claude ai
+// Summary: Input handling for the home screen.
+//
+// HomeDelegate: input handling for the home screen.
+//
+// M0 has no actions yet. Inheriting BehaviorDelegate keeps the default
+// behaviours, so BACK (button or swipe) leaves the app on every device.
+
+import Toybox.WatchUi;
+
+class HomeDelegate extends WatchUi.BehaviorDelegate {
+
+ function initialize() {
+ BehaviorDelegate.initialize();
+ }
+}
diff --git a/source/ui/HomeView.mc b/source/ui/HomeView.mc
new file mode 100644
index 0000000..f73c783
--- /dev/null
+++ b/source/ui/HomeView.mc
@@ -0,0 +1,42 @@
+// Author: cirakg & claude ai
+// Summary: M0 placeholder home screen showing the app name and version.
+//
+// HomeView: the M0 placeholder home screen. It draws the app name and version
+// in the centre of the screen. Milestone M4 replaces it with the entry list.
+//
+// Performance note: everything that allocates (loading the name string,
+// building the version text) happens once in initialize(), not in onUpdate().
+
+import Toybox.Graphics;
+import Toybox.Lang;
+import Toybox.WatchUi;
+
+class HomeView extends WatchUi.View {
+
+ private var _title as String;
+ private var _version as String;
+ // Set after the first complete draw, so start-up diagnostics run once.
+ private var _firstFrameDone as Boolean = false;
+
+ function initialize() {
+ View.initialize();
+ _title = WatchUi.loadResource(Rez.Strings.AppName) as String;
+ _version = "v" + AppInfo.VERSION;
+ }
+
+ function onUpdate(dc as Graphics.Dc) as Void {
+ var centerX = dc.getWidth() / 2;
+ var centerY = dc.getHeight() / 2;
+ var justify = Graphics.TEXT_JUSTIFY_CENTER | Graphics.TEXT_JUSTIFY_VCENTER;
+
+ dc.setColor(Graphics.COLOR_WHITE, Graphics.COLOR_BLACK);
+ dc.clear();
+ dc.drawText(centerX, centerY, Graphics.FONT_MEDIUM, _title, justify);
+ dc.drawText(centerX, centerY + dc.getFontHeight(Graphics.FONT_MEDIUM), Graphics.FONT_XTINY, _version, justify);
+
+ if (!_firstFrameDone) {
+ _firstFrameDone = true;
+ Diag.firstFrame();
+ }
+ }
+}
diff --git a/source/util/Diag.mc b/source/util/Diag.mc
new file mode 100644
index 0000000..aea2a70
--- /dev/null
+++ b/source/util/Diag.mc
@@ -0,0 +1,50 @@
+// Author: cirakg & claude ai
+// Summary: Debug-only diagnostics (start-up time, memory) for `make perf` and `make memtest`.
+//
+// Debug builds print one machine-readable line per event to the simulator
+// console: "DIAG", the event name, then key=value pairs, for example
+// DIAG first_frame startup_ms=1 mem_used=6984 mem_total=781888
+// tools/check_budgets.py reads these lines and compares them with
+// tools/budgets.json. Plain key=value pairs are used instead of JSON because
+// the simulator console escapes quotes. Release builds compile the empty
+// (:release) versions instead, so a real watch running a release build never
+// logs anything.
+//
+// Security rule: only timings and memory counters ever go through here, never
+// secrets, codes or entry names. This is the only file allowed to call
+// System.println outside tests (enforced by tools/lint_project.py).
+
+import Toybox.Lang;
+import Toybox.System;
+
+module Diag {
+
+ // System.getTimer() value when the app object was created.
+ (:debug)
+ var startMs as Number = 0;
+
+ // Start the start-up timer. Called from OtpWalletApp.initialize().
+ (:debug)
+ function markStart() as Void {
+ startMs = System.getTimer();
+ }
+
+ (:release)
+ function markStart() as Void {
+ }
+
+ // Report start-up time and memory use after the first complete frame.
+ // startup_ms covers app object creation to the end of the first draw. The
+ // time the system needs to load the program before that is invisible to
+ // the app; app-diag.sh measures it from outside (README section 18).
+ (:debug)
+ function firstFrame() as Void {
+ var stats = System.getSystemStats();
+ System.println("DIAG first_frame startup_ms=" + (System.getTimer() - startMs)
+ + " mem_used=" + stats.usedMemory + " mem_total=" + stats.totalMemory);
+ }
+
+ (:release)
+ function firstFrame() as Void {
+ }
+}