summaryrefslogtreecommitdiff
path: root/source/ui/QueueMenu.mc
blob: 3f9161df6d38cd3216e280ea536b3fb16098291f (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
// Author:  cirakg & claude ai
// Summary: "Phone changes": lists the changes to locked entries waiting for the PIN, and confirms or rejects them (README 7.9).
//
// Confirming always asks for the PIN, even while the watch is unlocked:
// the point is that a person at the watch agrees, not that a key is
// available. (Before any PIN exists only "Require PIN" can wait here, and
// confirming creates the PIN. "Require PIN" items are applied by the PIN
// screen itself, ChangeQueue.applyLocks, and listed in the results.) The changes are then applied by a
// ChangeQueueJob on a timer and the results screen shows what happened.

import Toybox.Lang;
import Toybox.WatchUi;

module QueueMenu {

    function build() as WatchUi.Menu2 {
        var vault = AppState.theVault();
        var menu = new WatchUi.Menu2({:title => "Phone changes"});
        menu.addItem(new WatchUi.MenuItem("Confirm all", vault.hasPin() ? "Asks for your PIN" : "Sets a PIN first", :confirm, null));
        menu.addItem(new WatchUi.MenuItem("Reject all", null, :reject, null));
        var items = ChangeQueue.descriptions(vault);
        for (var i = 0; i < items.size(); i++) {
            menu.addItem(new WatchUi.MenuItem(items[i], null, i, null));
        }
        return menu;
    }
}

class QueueMenuDelegate extends WatchUi.Menu2InputDelegate {

    function initialize() {
        Menu2InputDelegate.initialize();
    }

    function onSelect(item as WatchUi.MenuItem) as Void {
        AppState.activity();
        var id = item.getId();
        var vault = AppState.theVault();
        if (id == :confirm) {
            var then = new ApplyQueueAfterPin();
            var mode = vault.hasPin() ? PinView.MODE_UNLOCK : PinView.MODE_CREATE;
            WatchUi.switchToView(new PinView(mode, then.method(:run)), new PinDelegate(), WatchUi.SLIDE_LEFT);
        } else if (id == :reject) {
            var lines = ["Rejected these changes from the phone:"] as Array<String>;
            lines.addAll(ChangeQueue.descriptions(vault));
            ChangeQueue.clear(vault);
            Results.save(lines);
            WatchUi.switchToView(new InfoView("Results", lines, "results"), new InfoDelegate(), WatchUi.SLIDE_LEFT);
            Results.markSeen();
            AppState.processSettings(); // the About fields mention waiting changes
        } else if (id instanceof Number) {
            // The full text of one change (menu labels are cut short).
            var items = ChangeQueue.descriptions(vault);
            if (id < items.size()) {
                WatchUi.pushView(new InfoView("Change", [items[id]] as Array<String>, "change"), new InfoDelegate(),
                    WatchUi.SLIDE_LEFT);
            }
        }
    }
}

// After the PIN: apply the waiting changes, then show what happened.
class ApplyQueueAfterPin {

    // The job's timer driver (kept so it isn't collected while it runs).
    var runner as Jobs.JobRunner? = null;
    private var _job as ChangeQueueJob? = null;

    function initialize() {
    }

    function run() as Void {
        var job = new ChangeQueueJob(AppState.theVault());
        _job = job;
        WatchUi.switchToView(new InfoView("Results", ["Applying the changes…"] as Array<String>, "applying"), new InfoDelegate(),
            WatchUi.SLIDE_LEFT);
        var r = new Jobs.JobRunner(job, 1, method(:onDone));
        runner = r;
        r.start();
    }

    function onDone() as Void {
        var job = _job as ChangeQueueJob;
        _job = null;
        runner = null;
        AppState.theCodes().clear();
        Results.save(job.lines);
        WatchUi.switchToView(new InfoView("Results", job.lines, "results"), new InfoDelegate(), WatchUi.SLIDE_IMMEDIATE);
        Results.markSeen();
        AppState.processSettings(); // refresh the catalog on the phone
    }
}