diff options
Diffstat (limited to 'source/ui/DebugMenu.mc')
| -rw-r--r-- | source/ui/DebugMenu.mc | 110 |
1 files changed, 110 insertions, 0 deletions
diff --git a/source/ui/DebugMenu.mc b/source/ui/DebugMenu.mc new file mode 100644 index 0000000..f1ab407 --- /dev/null +++ b/source/ui/DebugMenu.mc @@ -0,0 +1,110 @@ +// Author: cirakg & claude ai +// Summary: Debug-only menu items: load demo entries, the performance overlay and the on-watch benchmark. +// +// Release builds compile the empty (:release) module instead, so none of this +// reaches the Store build. The benchmark is how the watch's real speed gets +// measured (docs/PERFORMANCE.md): sideload a debug build and run it. + +import Toybox.Lang; +import Toybox.System; +import Toybox.Timer; +import Toybox.WatchUi; + +(:debug) +module DebugMenu { + + function addItems(menu as WatchUi.Menu2) as Void { + menu.addItem(new WatchUi.MenuItem("Debug: demo entries", "Adds fake entries", :debugDemo, null)); + menu.addItem(new WatchUi.MenuItem("Debug: overlay", Diag.overlayOn ? "On" : "Off", :debugOverlay, null)); + menu.addItem(new WatchUi.MenuItem("Debug: benchmark", "Takes a few seconds", :debugBench, null)); + } + + function handle(id as Object?) as Void { + if (id == :debugDemo) { + try { + Fixtures.load(AppState.theVault()); + } catch (e instanceof VaultError) { + // Entry cap or full store: load what fits. + } + AppState.theCodes().clear(); + WatchUi.popView(WatchUi.SLIDE_DOWN); + } else if (id == :debugOverlay) { + Diag.overlayOn = !Diag.overlayOn; + WatchUi.popView(WatchUi.SLIDE_DOWN); + } else if (id == :debugBench) { + var runner = new BenchRunner(); + bench = runner; + WatchUi.switchToView(new InfoView("Benchmark", ["Measuring…"], "bench_running"), new InfoDelegate(), + WatchUi.SLIDE_LEFT); + runner.start(); + } + } + + // The running benchmark (kept so its timer isn't collected). + var bench as BenchRunner? = null; + + // Times the operations the budgets depend on, one per timer event, so no + // event comes near the watchdog limit (it is enforced on the watch and in + // normal simulator runs). + class BenchRunner { + + private var _lines as Array<String> = [] as Array<String>; + private var _step as Number = 0; + private var _timer as Timer.Timer? = null; + + function initialize() { + } + + function start() as Void { + var t = new Timer.Timer(); + t.start(method(:tick), 200, true); + _timer = t; + } + + function tick() as Void { + var t = System.getTimer(); + if (_step == 0) { + for (var i = 0; i < 5; i++) { + Otp.totp(Hashes.SHA1, new [20]b, 1800000000l, 30, 6); + } + _lines.add("TOTP SHA-1: " + (System.getTimer() - t) / 5 + " ms"); + } else if (_step == 1) { + Otp.totp(Hashes.SHA512, new [64]b, 1800000000l, 30, 6); + _lines.add("TOTP SHA-512: " + (System.getTimer() - t) + " ms"); + } else if (_step == 2) { + _lines.add("PIN derivation: " + Kdf.calibrate(1000, Kdf.ITERATIONS_PER_STEP) + " iterations per second"); + } else if (_step == 3) { + var vault = AppState.theVault(); + var ids = vault.ids(); + for (var i = 0; i < ids.size(); i++) { + vault.header(ids[i]); + } + _lines.add("Headers: " + ids.size() + " in " + (System.getTimer() - t) + " ms"); + } else if (_step == 4) { + SelfTest.run(); + _lines.add("Self-test: " + (System.getTimer() - t) + " ms"); + } else { + var stats = System.getSystemStats(); + _lines.add("Memory: " + stats.usedMemory / 1024 + " of " + stats.totalMemory / 1024 + " KB"); + var timer = _timer; + if (timer != null) { + timer.stop(); + } + bench = null; + WatchUi.switchToView(new InfoView("Benchmark", _lines, "bench"), new InfoDelegate(), WatchUi.SLIDE_IMMEDIATE); + return; + } + _step++; + } + } +} + +(:release) +module DebugMenu { + + function addItems(menu as WatchUi.Menu2) as Void { + } + + function handle(id as Object?) as Void { + } +} |
