summaryrefslogtreecommitdiff
path: root/source/settings
diff options
context:
space:
mode:
Diffstat (limited to 'source/settings')
-rw-r--r--source/settings/AboutScan.mc20
-rw-r--r--source/settings/ManageForm.mc25
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) {