diff options
Diffstat (limited to 'source/settings')
| -rw-r--r-- | source/settings/AboutScan.mc | 20 | ||||
| -rw-r--r-- | source/settings/ManageForm.mc | 25 |
2 files changed, 37 insertions, 8 deletions
diff --git a/source/settings/AboutScan.mc b/source/settings/AboutScan.mc index 8fc898a..559cce9 100644 --- a/source/settings/AboutScan.mc +++ b/source/settings/AboutScan.mc @@ -1,5 +1,5 @@ // Author: cirakg & claude ai -// Summary: Writes the read-only About fields (catalog, version, storage use) and applies "Encrypt names" to existing entries. +// Summary: Writes the read-only About fields (catalog, version, storage use), applies "Encrypt names" to existing entries and updates the glance code. // // One pass over every entry header, a few per step: // * catalog: "K7F2 GitHub (alice) · 9QXR Gym card · ...", so the Manage @@ -11,8 +11,11 @@ // "Encrypt names" option are re-sealed, one per step. Locked ones need // the session; if one can't be done now, the next scan retries (after // the next PIN entry, which runs the processor again). +// * The glance code (GlanceCode.mc): the first favourite TOTP or Steam +// entry without the PIN is sealed for the glance, or the glance item +// removed when there is none or the option is off. // The scan only runs when something it reports changed: a form was -// applied, or the signature of the entry list (IDs, pending, option, +// applied, or the signature of the entry list (IDs, pending, options, // version) differs from the last complete scan. import Toybox.Lang; @@ -35,6 +38,7 @@ class AboutScan extends Jobs.Job { private var _left as Number = 0; private var _bytes as Number = 0; private var _incomplete as Boolean = false; + private var _glanceId as String? = null; function initialize(vault as Vault, store as Forms.Store) { Job.initialize(); @@ -55,6 +59,7 @@ class AboutScan extends Jobs.Job { content.add(vault.ids().toString()); content.add(vault.pendingIds().toString()); content.add(vault.encryptNames); + content.add(vault.glanceCode); content.add(ChangeQueue.count(vault)); content.add(AppInfo.VERSION); return Forms.hash(vault, content); @@ -102,6 +107,9 @@ class AboutScan extends Jobs.Job { } } addItem(id + " " + describe(header) + (header.locked ? " (PIN)" : "")); + if (_glanceId == null && GlanceStore.qualifies(header)) { + _glanceId = id; + } return converted; } @@ -156,6 +164,14 @@ class AboutScan extends Jobs.Job { setIfChanged("catalog", catalog); setIfChanged("storageUse", use); setIfChanged("version", AppInfo.VERSION); + try { + GlanceStore.update(_vault, _glanceId); + } catch (e instanceof Lang.Exception) { + // Damaged entry or a full store: no glance code, and the scan + // runs again next time. + _vault.storage().deleteValue(GlanceCode.KEY); + _incomplete = true; + } if (!_incomplete) { try { _vault.storage().setValue(SIGNATURE_KEY, signature(_vault)); diff --git a/source/settings/ManageForm.mc b/source/settings/ManageForm.mc index b92c40d..a075880 100644 --- a/source/settings/ManageForm.mc +++ b/source/settings/ManageForm.mc @@ -6,8 +6,8 @@ // * ManageForm.read(): the mg* fields to a ManageAction or a problem. // * ManageRun: a job that checks the action against the entry and then // applies it, or queues it (ChangeQueue) when it touches a locked -// entry: edit, replace, counter, "Don't require PIN" and delete wait -// until the PIN is entered on the watch. "Require PIN" waits too while +// entry: edit, replace, counter, "Don't require PIN", the favourite +// mark and delete wait until the PIN is entered on the watch. "Require PIN" waits too while // the watch is locked (it needs the master key). Moving never waits: // the order isn't protected and a position is absolute, so applying a // move twice can't hit another entry. @@ -28,8 +28,11 @@ class ManageAction { static const REPLACE = 4; static const COUNTER = 5; static const DELETE = 6; + static const FAVORITE = 7; + static const UNFAVORITE = 8; - static const NAMES = ["Edit details", "Move", "Require PIN", "Don't require PIN", "Replace contents", "Set counter", "Delete"]; + static const NAMES = ["Edit details", "Move", "Require PIN", "Don't require PIN", "Replace contents", "Set counter", "Delete", + "Mark as favourite", "Remove favourite"]; // Codec tags of the queued form. static const T_ID = 1; @@ -114,7 +117,7 @@ class ManageAction { if (!(id instanceof String) || !(action instanceof Long) || !(position instanceof Long) || !(counter instanceof Long)) { return null; } - if (action < EDIT || action > DELETE || !Entry.isValidId(id)) { + if (action < EDIT || action > UNFAVORITE || !Entry.isValidId(id)) { return null; } a.id = id; @@ -173,7 +176,7 @@ module ManageForm { return "Entry ID: '" + Text.clip(a.id, 8) + "' is not an ID. IDs have 4 characters, like K7F2"; } var action = Forms.number(store, "mgAction"); - if (action == null || action < ManageAction.EDIT || action > ManageAction.DELETE) { + if (action == null || action < ManageAction.EDIT || action > ManageAction.UNFAVORITE) { return "Action: choose one from the list"; } a.action = action; @@ -334,6 +337,12 @@ class ManageRun extends Jobs.Job { if (a.action == ManageAction.UNLOCK && !header.locked) { return a.id + " doesn't require the PIN"; } + if (a.action == ManageAction.FAVORITE && header.favorite) { + return a.id + " is already a favourite"; + } + if (a.action == ManageAction.UNFAVORITE && !header.favorite) { + return a.id + " is not a favourite"; + } if (a.action == ManageAction.REPLACE && isOtp && !a.decoded) { var raw = a.material as ByteArray; var text = Bytes.toUtf8(raw); @@ -435,7 +444,8 @@ class ManageRun extends Jobs.Job { return true; } - // Edit, lock, unlock or replace: open, change, re-seal. Null or the problem. + // Edit, lock, unlock, (un)favourite or replace: open, change, re-seal. + // Null or the problem. private function changeEntry() as String? { var a = _a; var target = a.id + (a.label.length() > 0 ? " " + a.label : ""); @@ -453,6 +463,9 @@ class ManageRun extends Jobs.Job { } else if (a.action == ManageAction.LOCK || a.action == ManageAction.UNLOCK) { entry.locked = a.action == ManageAction.LOCK; message = target + (entry.locked ? " now requires the PIN" : " no longer requires the PIN"); + } else if (a.action == ManageAction.FAVORITE || a.action == ManageAction.UNFAVORITE) { + entry.favorite = a.action == ManageAction.FAVORITE; + message = target + (entry.favorite ? " is now a favourite" : " is no longer a favourite"); } else { var material = a.material as ByteArray; if (entry.kind == Entry.KIND_OTP) { |
