aboutsummaryrefslogtreecommitdiff
path: root/source/app/Options.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/Options.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/Options.mc')
-rw-r--r--source/app/Options.mc78
1 files changed, 78 insertions, 0 deletions
diff --git a/source/app/Options.mc b/source/app/Options.mc
new file mode 100644
index 0000000..0b4715c
--- /dev/null
+++ b/source/app/Options.mc
@@ -0,0 +1,78 @@
+// Author: cirakg & claude ai
+// Summary: The user's options (README 10.2, Options group), read from app properties with safe defaults.
+//
+// The properties are defined in resources/settings/properties.xml (reading
+// an undefined one stops the app with an uncatchable system error); M7 adds
+// the phone form. A value of the wrong type or out of range falls back to
+// the default below.
+
+import Toybox.Application;
+import Toybox.Lang;
+
+class Options {
+
+ static const CODE_NORMAL = 0;
+ static const CODE_LARGE = 1;
+ static const CODE_HUGE = 2;
+
+ static const THEME_DARK = 0;
+ static const THEME_LIGHT = 1;
+
+ // optAutoLock list values, in ms: Immediately, 15 s, 30 s, 1 min, 2 min, 5 min.
+ static const AUTO_LOCK_CHOICES = [0, 15000, 30000, 60000, 120000, 300000];
+ static const AUTO_LOCK_DEFAULT = 3;
+ static const MAX_TIME_OFFSET_S = 120;
+
+ var autoLockMs as Number = 60000;
+ var eraseAfterFailures as Boolean = false;
+ var timeOffset as Number = 0;
+ var codeSize as Number = CODE_LARGE;
+ var theme as Number = THEME_DARK;
+ var showGroups as Boolean = true;
+ var encryptNames as Boolean = false;
+ var glanceCode as Boolean = false;
+ var fullBrightness as Boolean = true;
+
+ function initialize() {
+ }
+
+ // Read every option; anything missing or invalid keeps its default.
+ function load() as Void {
+ var autoLock = choice("optAutoLock", AUTO_LOCK_DEFAULT, AUTO_LOCK_CHOICES.size() - 1);
+ autoLockMs = AUTO_LOCK_CHOICES[autoLock] as Number;
+ eraseAfterFailures = flag("optWipe", false);
+ var offset = number("optTimeOffset");
+ timeOffset = (offset != null && offset >= -MAX_TIME_OFFSET_S && offset <= MAX_TIME_OFFSET_S) ? offset : 0;
+ codeSize = choice("optCodeSize", CODE_LARGE, CODE_HUGE);
+ theme = choice("optTheme", THEME_DARK, THEME_LIGHT);
+ showGroups = flag("optGroups", true);
+ encryptNames = flag("optEncryptNames", false);
+ glanceCode = flag("optGlanceCode", false);
+ fullBrightness = flag("optBrightness", true);
+ }
+
+ // A property, or null when it doesn't exist (before M7) or can't be read.
+ private function raw(key as String) as Application.Properties.ValueType or Null {
+ try {
+ return Application.Properties.getValue(key);
+ } catch (e instanceof Lang.Exception) {
+ return null;
+ }
+ }
+
+ private function number(key as String) as Number? {
+ var v = raw(key);
+ return v instanceof Number ? v : null;
+ }
+
+ // A list index in 0..max, or the default.
+ private function choice(key as String, defaultValue as Number, max as Number) as Number {
+ var v = number(key);
+ return (v != null && v >= 0 && v <= max) ? v : defaultValue;
+ }
+
+ private function flag(key as String, defaultValue as Boolean) as Boolean {
+ var v = raw(key);
+ return v instanceof Boolean ? v : defaultValue;
+ }
+}