@narumitw/pi-sync 0.50.3 → 0.51.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +4 -1
- package/dist/chunks/{chunk-6LP3MCR2.ts → chunk-2JZFHNLM.ts} +3 -5
- package/dist/chunks/chunk-2JZFHNLM.ts.map +7 -0
- package/dist/chunks/{chunk-LCRI3ABW.ts → chunk-2RZSQWBH.ts} +8 -19
- package/dist/chunks/chunk-2RZSQWBH.ts.map +7 -0
- package/dist/chunks/{chunk-IJ6FJFA5.ts → chunk-4AIHXRKE.ts} +11 -17
- package/dist/chunks/chunk-4AIHXRKE.ts.map +7 -0
- package/dist/chunks/{chunk-C7XY5NF5.ts → chunk-4MPIH46N.ts} +29 -51
- package/dist/chunks/chunk-4MPIH46N.ts.map +7 -0
- package/dist/chunks/{chunk-5B3FXBLE.ts → chunk-6546TS54.ts} +16 -20
- package/dist/chunks/chunk-6546TS54.ts.map +7 -0
- package/dist/chunks/{chunk-Q2TUM5X6.ts → chunk-6NT3YFGY.ts} +2 -2
- package/dist/chunks/chunk-6NT3YFGY.ts.map +7 -0
- package/dist/chunks/{chunk-2B2ELUF5.ts → chunk-7D5SF7P3.ts} +1 -1
- package/dist/chunks/chunk-7D5SF7P3.ts.map +7 -0
- package/dist/chunks/{chunk-YDWUZVPN.ts → chunk-7KHKWL3Q.ts} +28 -47
- package/dist/chunks/chunk-7KHKWL3Q.ts.map +7 -0
- package/dist/chunks/{chunk-ZI5MXMEX.ts → chunk-BVVP33U5.ts} +2 -4
- package/dist/chunks/chunk-BVVP33U5.ts.map +7 -0
- package/dist/chunks/{chunk-SZWBGPID.ts → chunk-DM4X4FIA.ts} +8 -13
- package/dist/chunks/chunk-DM4X4FIA.ts.map +7 -0
- package/dist/chunks/{chunk-SL64RLXR.ts → chunk-DZUSTGQV.ts} +8 -16
- package/dist/chunks/chunk-DZUSTGQV.ts.map +7 -0
- package/dist/chunks/{chunk-YHEMENKV.ts → chunk-E42GXD6D.ts} +13 -19
- package/dist/chunks/chunk-E42GXD6D.ts.map +7 -0
- package/dist/chunks/{chunk-Z4DQF6L3.ts → chunk-ECYCNZOE.ts} +1 -1
- package/dist/chunks/chunk-ECYCNZOE.ts.map +7 -0
- package/dist/chunks/{chunk-OEX4ABY6.ts → chunk-EEJPYTWE.ts} +11 -21
- package/dist/chunks/chunk-EEJPYTWE.ts.map +7 -0
- package/dist/chunks/{chunk-CPEHGXJV.ts → chunk-G4RUXRWZ.ts} +3 -5
- package/dist/chunks/chunk-G4RUXRWZ.ts.map +7 -0
- package/dist/chunks/{chunk-T2B5IU74.ts → chunk-HGJH56KR.ts} +4 -4
- package/dist/chunks/chunk-HGJH56KR.ts.map +7 -0
- package/dist/chunks/{chunk-JAAKLL6M.ts → chunk-IVXEDPAD.ts} +10 -34
- package/dist/chunks/chunk-IVXEDPAD.ts.map +7 -0
- package/dist/chunks/chunk-K3RIEL6J.ts +20 -0
- package/dist/chunks/chunk-K3RIEL6J.ts.map +7 -0
- package/dist/chunks/{chunk-LTBWGSBV.ts → chunk-MSSW6F3R.ts} +1 -1
- package/dist/chunks/chunk-MSSW6F3R.ts.map +7 -0
- package/dist/chunks/{chunk-T3HH3UEJ.ts → chunk-OVDTF5CH.ts} +4 -10
- package/dist/chunks/chunk-OVDTF5CH.ts.map +7 -0
- package/dist/chunks/{chunk-NJFUIVYL.ts → chunk-PWMWOJP4.ts} +1 -1
- package/dist/chunks/chunk-PWMWOJP4.ts.map +7 -0
- package/dist/chunks/{chunk-HUDQATCL.ts → chunk-Q32CQWPM.ts} +6 -8
- package/dist/chunks/chunk-Q32CQWPM.ts.map +7 -0
- package/dist/chunks/{chunk-ETTRJDNP.ts → chunk-QLSN7AGX.ts} +6 -13
- package/dist/chunks/chunk-QLSN7AGX.ts.map +7 -0
- package/dist/chunks/{chunk-THMF4BVL.ts → chunk-SWUXA3MH.ts} +1 -1
- package/dist/chunks/chunk-SWUXA3MH.ts.map +7 -0
- package/dist/chunks/{chunk-TEN2ZBJV.ts → chunk-T2SJD3N7.ts} +2 -4
- package/dist/chunks/chunk-T2SJD3N7.ts.map +7 -0
- package/dist/chunks/{chunk-AUSDLD6F.ts → chunk-T56RNRZJ.ts} +10 -26
- package/dist/chunks/chunk-T56RNRZJ.ts.map +7 -0
- package/dist/chunks/{chunk-DHVFS4QK.ts → chunk-UA7RXOIT.ts} +37 -90
- package/dist/chunks/chunk-UA7RXOIT.ts.map +7 -0
- package/dist/chunks/{chunk-D5X27LCA.ts → chunk-UETBKTDI.ts} +1 -1
- package/dist/chunks/chunk-UETBKTDI.ts.map +7 -0
- package/dist/chunks/{chunk-CHH26D4F.ts → chunk-YFADF5ZQ.ts} +7 -6
- package/dist/chunks/chunk-YFADF5ZQ.ts.map +7 -0
- package/dist/chunks/{chunk-CCSN3F47.ts → chunk-YPXGU5OR.ts} +4 -4
- package/dist/chunks/chunk-YPXGU5OR.ts.map +7 -0
- package/dist/chunks/{file-selection-FTTKAOYX.ts → file-selection-RAVHRYFG.ts} +14 -26
- package/dist/chunks/file-selection-RAVHRYFG.ts.map +7 -0
- package/dist/chunks/{git-backend-GMVS4PD4.ts → git-backend-IAANDL3K.ts} +41 -104
- package/dist/chunks/git-backend-IAANDL3K.ts.map +7 -0
- package/dist/chunks/manager-result-dispatcher-OTUMQM26.ts +23 -0
- package/dist/chunks/{manager-ui-IPAOAWZA.ts → manager-ui-763NEKJY.ts} +124 -251
- package/dist/chunks/manager-ui-763NEKJY.ts.map +7 -0
- package/dist/chunks/remote-selection-ui-TZTJF32Y.ts +22 -0
- package/dist/chunks/{s3-backend-66O4FGBH.ts → s3-backend-XGXUOPUN.ts} +23 -54
- package/dist/chunks/s3-backend-XGXUOPUN.ts.map +7 -0
- package/dist/chunks/{setup-switch-IS2PEZ3J.ts → setup-switch-5G2VNJHL.ts} +9 -9
- package/dist/chunks/{setup-wizard-JUJZYNNM.ts → setup-wizard-YIEWGX32.ts} +12 -12
- package/dist/chunks/setup-wizard-YIEWGX32.ts.map +7 -0
- package/dist/chunks/{snapshot-HKEWCVK6.ts → snapshot-JL5DFSXI.ts} +5 -5
- package/dist/chunks/sync-inspection-P3ENJLNF.ts +20 -0
- package/dist/chunks/{sync-operations-LBX3GKCM.ts → sync-operations-AR76EB6C.ts} +85 -201
- package/dist/chunks/sync-operations-AR76EB6C.ts.map +7 -0
- package/dist/chunks/{sync-state-Q2FTXTW6.ts → sync-state-VHJUZ4YG.ts} +6 -6
- package/dist/chunks/{webdav-backend-ECIKD7SO.ts → webdav-backend-3EGUONAT.ts} +20 -51
- package/dist/chunks/webdav-backend-3EGUONAT.ts.map +7 -0
- package/dist/index.ts +49 -74
- package/dist/index.ts.map +3 -3
- package/docs/settings.md +9 -0
- package/package.json +61 -62
- package/src/backends/backend-factory.ts +15 -15
- package/src/backends/backend-identity.ts +31 -31
- package/src/backends/backend-types.ts +42 -42
- package/src/backends/git/git-backend.ts +714 -788
- package/src/backends/git/git-config.ts +104 -111
- package/src/backends/git/git-runner.ts +230 -247
- package/src/backends/git/git-storage.ts +228 -245
- package/src/backends/s3/s3-backend.ts +408 -441
- package/src/backends/s3/s3-client.ts +288 -333
- package/src/backends/sync-backend.ts +65 -65
- package/src/backends/webdav/webdav-backend.ts +542 -589
- package/src/backends/webdav/webdav-client.ts +292 -316
- package/src/backends/webdav/webdav-config.ts +57 -68
- package/src/commands/command-execution.ts +270 -289
- package/src/commands/command-handler.ts +160 -163
- package/src/commands/command-types.ts +13 -13
- package/src/commands/command.ts +190 -196
- package/src/commands/setup-completions.ts +1 -1
- package/src/paths.ts +47 -47
- package/src/settings/config-errors.ts +4 -5
- package/src/settings/config-file.ts +473 -506
- package/src/settings/config.ts +171 -174
- package/src/settings/settings-management.ts +191 -216
- package/src/settings/settings-store.ts +63 -77
- package/src/settings/settings-types.ts +78 -75
- package/src/settings/settings-validation.ts +328 -364
- package/src/snapshot/session-paths.ts +41 -55
- package/src/snapshot/snapshot-apply.ts +197 -229
- package/src/snapshot/snapshot-codec.ts +29 -31
- package/src/snapshot/snapshot-paths.ts +4 -6
- package/src/snapshot/snapshot-transaction.ts +161 -170
- package/src/snapshot/snapshot-types.ts +24 -24
- package/src/snapshot/snapshot.ts +310 -343
- package/src/state/json-file.ts +11 -11
- package/src/state/lock.ts +226 -242
- package/src/state/lockfile-fs.ts +20 -20
- package/src/state/operation-availability.ts +36 -41
- package/src/state/state-directory.ts +171 -173
- package/src/state/state-types.ts +15 -15
- package/src/state/sync-state-store.ts +23 -23
- package/src/sync/automatic-sync.ts +75 -80
- package/src/sync/remote-snapshot.ts +52 -60
- package/src/sync/setup-switch.ts +99 -114
- package/src/sync/signals.ts +3 -5
- package/src/sync/startup-check.ts +97 -111
- package/src/sync/sync-decision.ts +76 -80
- package/src/sync/sync-error-guidance.ts +41 -48
- package/src/sync/sync-errors.ts +10 -10
- package/src/sync/sync-inspection.ts +29 -33
- package/src/sync/sync-loaders.ts +28 -36
- package/src/sync/sync-mutations.ts +510 -622
- package/src/sync/sync-operations.ts +7 -7
- package/src/sync/sync-policy.ts +296 -326
- package/src/sync/sync-queries.ts +175 -194
- package/src/sync/sync-state.ts +74 -100
- package/src/sync-extension.ts +89 -101
- package/src/sync.ts +26 -26
- package/src/types.ts +37 -37
- package/src/ui/automatic-sync-summary.ts +1 -3
- package/src/ui/cancellable-operation.ts +89 -101
- package/src/ui/file-selection.ts +250 -274
- package/src/ui/manager-attention.ts +51 -63
- package/src/ui/manager-recovery.ts +48 -57
- package/src/ui/manager-result-dispatcher.ts +62 -76
- package/src/ui/manager-state.ts +200 -232
- package/src/ui/manager-ui.ts +264 -362
- package/src/ui/remote-selection-ui.ts +547 -588
- package/src/ui/secret-input.ts +197 -205
- package/src/ui/settings-ui.ts +175 -172
- package/src/ui/setup/git-ui.ts +232 -261
- package/src/ui/setup/s3-credentials-ui.ts +58 -65
- package/src/ui/setup/s3-ui.ts +171 -195
- package/src/ui/setup/setup-actions.ts +91 -101
- package/src/ui/setup/setup-location-ui.ts +121 -137
- package/src/ui/setup/setup-name-ui.ts +27 -27
- package/src/ui/setup/setup-prompts.ts +65 -65
- package/src/ui/setup/setup-review.ts +58 -59
- package/src/ui/setup/setup-switcher.ts +156 -160
- package/src/ui/setup/setup-wizard.ts +28 -28
- package/src/ui/setup/text-input.ts +54 -58
- package/src/ui/setup/webdav-ui.ts +246 -293
- package/src/ui/storage-connections-ui.ts +317 -369
- package/src/ui/sync-attention.ts +148 -164
- package/src/ui/sync-format.ts +110 -121
- package/src/ui/sync-resolution-ui.ts +147 -153
- package/src/ui/sync-setups-ui.ts +218 -238
- package/src/ui/sync-status.ts +17 -0
- package/src/ui/terminal-text.ts +2 -2
- package/dist/chunks/chunk-2B2ELUF5.ts.map +0 -7
- package/dist/chunks/chunk-5B3FXBLE.ts.map +0 -7
- package/dist/chunks/chunk-6LP3MCR2.ts.map +0 -7
- package/dist/chunks/chunk-AUSDLD6F.ts.map +0 -7
- package/dist/chunks/chunk-C7XY5NF5.ts.map +0 -7
- package/dist/chunks/chunk-CCSN3F47.ts.map +0 -7
- package/dist/chunks/chunk-CHH26D4F.ts.map +0 -7
- package/dist/chunks/chunk-CPEHGXJV.ts.map +0 -7
- package/dist/chunks/chunk-D5X27LCA.ts.map +0 -7
- package/dist/chunks/chunk-DHVFS4QK.ts.map +0 -7
- package/dist/chunks/chunk-ETTRJDNP.ts.map +0 -7
- package/dist/chunks/chunk-HUDQATCL.ts.map +0 -7
- package/dist/chunks/chunk-IJ6FJFA5.ts.map +0 -7
- package/dist/chunks/chunk-JAAKLL6M.ts.map +0 -7
- package/dist/chunks/chunk-LCRI3ABW.ts.map +0 -7
- package/dist/chunks/chunk-LTBWGSBV.ts.map +0 -7
- package/dist/chunks/chunk-NJFUIVYL.ts.map +0 -7
- package/dist/chunks/chunk-OEX4ABY6.ts.map +0 -7
- package/dist/chunks/chunk-Q2TUM5X6.ts.map +0 -7
- package/dist/chunks/chunk-SL64RLXR.ts.map +0 -7
- package/dist/chunks/chunk-SZWBGPID.ts.map +0 -7
- package/dist/chunks/chunk-T2B5IU74.ts.map +0 -7
- package/dist/chunks/chunk-T3HH3UEJ.ts.map +0 -7
- package/dist/chunks/chunk-TEN2ZBJV.ts.map +0 -7
- package/dist/chunks/chunk-THMF4BVL.ts.map +0 -7
- package/dist/chunks/chunk-YDWUZVPN.ts.map +0 -7
- package/dist/chunks/chunk-YHEMENKV.ts.map +0 -7
- package/dist/chunks/chunk-Z4DQF6L3.ts.map +0 -7
- package/dist/chunks/chunk-ZI5MXMEX.ts.map +0 -7
- package/dist/chunks/file-selection-FTTKAOYX.ts.map +0 -7
- package/dist/chunks/git-backend-GMVS4PD4.ts.map +0 -7
- package/dist/chunks/manager-result-dispatcher-ASKGOSW5.ts +0 -22
- package/dist/chunks/manager-ui-IPAOAWZA.ts.map +0 -7
- package/dist/chunks/remote-selection-ui-QDNR7WEI.ts +0 -21
- package/dist/chunks/s3-backend-66O4FGBH.ts.map +0 -7
- package/dist/chunks/setup-wizard-JUJZYNNM.ts.map +0 -7
- package/dist/chunks/sync-inspection-CST2KL65.ts +0 -20
- package/dist/chunks/sync-operations-LBX3GKCM.ts.map +0 -7
- package/dist/chunks/webdav-backend-ECIKD7SO.ts.map +0 -7
- /package/dist/chunks/{manager-result-dispatcher-ASKGOSW5.ts.map → manager-result-dispatcher-OTUMQM26.ts.map} +0 -0
- /package/dist/chunks/{remote-selection-ui-QDNR7WEI.ts.map → remote-selection-ui-TZTJF32Y.ts.map} +0 -0
- /package/dist/chunks/{setup-switch-IS2PEZ3J.ts.map → setup-switch-5G2VNJHL.ts.map} +0 -0
- /package/dist/chunks/{snapshot-HKEWCVK6.ts.map → snapshot-JL5DFSXI.ts.map} +0 -0
- /package/dist/chunks/{sync-inspection-CST2KL65.ts.map → sync-inspection-P3ENJLNF.ts.map} +0 -0
- /package/dist/chunks/{sync-state-Q2FTXTW6.ts.map → sync-state-VHJUZ4YG.ts.map} +0 -0
package/src/ui/manager-ui.ts
CHANGED
|
@@ -4,10 +4,10 @@ import { loadConfig } from "../settings/config.js";
|
|
|
4
4
|
import { operationBlocksChanges, operationCanRecover } from "../state/operation-availability.js";
|
|
5
5
|
import { type RunRoute, runCancellableOperation } from "./cancellable-operation.js";
|
|
6
6
|
import {
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
7
|
+
attentionMainMenuItems,
|
|
8
|
+
blockedSyncMenuItem,
|
|
9
|
+
type SyncManagerAttentionOptions,
|
|
10
|
+
showManagerAttention,
|
|
11
11
|
} from "./manager-attention.js";
|
|
12
12
|
import { recoverSyncAccess } from "./manager-recovery.js";
|
|
13
13
|
import { dispatchManagerResult } from "./manager-result-dispatcher.js";
|
|
@@ -19,368 +19,270 @@ import { showStorageConnections } from "./storage-connections-ui.js";
|
|
|
19
19
|
import { observationMatchesConfig } from "./sync-attention.js";
|
|
20
20
|
|
|
21
21
|
export async function showSyncManager(
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
22
|
+
ctx: ExtensionCommandContext,
|
|
23
|
+
runRoute: RunRoute,
|
|
24
|
+
sessionSignal?: AbortSignal,
|
|
25
|
+
options: SyncManagerAttentionOptions = {},
|
|
26
26
|
): Promise<void> {
|
|
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
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
},
|
|
262
|
-
connections: async () => {
|
|
263
|
-
await showStorageConnections(ctx, sessionSignal);
|
|
264
|
-
return { kind: "stay" };
|
|
265
|
-
},
|
|
266
|
-
history: async () => {
|
|
267
|
-
await runRoute("history");
|
|
268
|
-
return { kind: "stay" };
|
|
269
|
-
},
|
|
270
|
-
doctor: async () => {
|
|
271
|
-
const result = await runCancellableOperation(
|
|
272
|
-
ctx,
|
|
273
|
-
"Checking setup access…",
|
|
274
|
-
"doctor",
|
|
275
|
-
runRoute,
|
|
276
|
-
{ signal: sessionSignal },
|
|
277
|
-
);
|
|
278
|
-
return { kind: result.kind === "closed" ? "close" : "stay" };
|
|
279
|
-
},
|
|
280
|
-
unlock: async ({ state, signal: actionSignal }) => {
|
|
281
|
-
const result = await recoverSyncAccess(
|
|
282
|
-
ctx,
|
|
283
|
-
state.manager,
|
|
284
|
-
runRoute,
|
|
285
|
-
sessionSignal,
|
|
286
|
-
actionSignal,
|
|
287
|
-
);
|
|
288
|
-
if (result === "close") return { kind: "close" };
|
|
289
|
-
return result === "restored" ? { kind: "to", screen: "main" } : { kind: "stay" };
|
|
290
|
-
},
|
|
291
|
-
recover: async ({ state, signal: actionSignal }) => {
|
|
292
|
-
const result = await recoverSyncAccess(
|
|
293
|
-
ctx,
|
|
294
|
-
state.manager,
|
|
295
|
-
runRoute,
|
|
296
|
-
sessionSignal,
|
|
297
|
-
actionSignal,
|
|
298
|
-
);
|
|
299
|
-
return { kind: result === "close" ? "close" : "stay" };
|
|
300
|
-
},
|
|
301
|
-
refresh: async () => ({ kind: "stay" }),
|
|
302
|
-
help: async () => {
|
|
303
|
-
await runRoute("help");
|
|
304
|
-
return { kind: "close" };
|
|
305
|
-
},
|
|
306
|
-
init: async () => {
|
|
307
|
-
await runRoute("init");
|
|
308
|
-
return { kind: "stay" };
|
|
309
|
-
},
|
|
310
|
-
back: async () => ({ kind: "back" }),
|
|
311
|
-
},
|
|
312
|
-
});
|
|
313
|
-
await runMenu(ctx, menu, {
|
|
314
|
-
getState: async () => {
|
|
315
|
-
const pendingAttention = options.getAttention?.();
|
|
316
|
-
const observation = options.getObservation?.();
|
|
317
|
-
const manager = await describeManagerState(
|
|
318
|
-
sessionSignal,
|
|
319
|
-
pendingAttention,
|
|
320
|
-
undefined,
|
|
321
|
-
observation,
|
|
322
|
-
);
|
|
323
|
-
if (sessionSignal?.aborted) return { manager };
|
|
324
|
-
// A busy operation suppresses baseline reads, not the stored check-time hint.
|
|
325
|
-
if (
|
|
326
|
-
observation &&
|
|
327
|
-
options.getObservation?.() === observation &&
|
|
328
|
-
!manager.observation &&
|
|
329
|
-
!(manager.operation && operationBlocksChanges(manager.operation))
|
|
330
|
-
) {
|
|
331
|
-
options.onObservationInvalidated?.();
|
|
332
|
-
}
|
|
333
|
-
if (pendingAttention && options.getAttention?.() === pendingAttention && !manager.attention) {
|
|
334
|
-
options.onSelectionResolved?.(pendingAttention);
|
|
335
|
-
}
|
|
336
|
-
return { manager };
|
|
337
|
-
},
|
|
338
|
-
signal: sessionSignal,
|
|
339
|
-
isCurrent: () => !sessionSignal?.aborted,
|
|
340
|
-
});
|
|
27
|
+
if (!ctx.hasUI) {
|
|
28
|
+
await runRoute("help");
|
|
29
|
+
return;
|
|
30
|
+
}
|
|
31
|
+
type Screen = "main" | "more" | "recovery";
|
|
32
|
+
type Action =
|
|
33
|
+
| "review-attention"
|
|
34
|
+
| "sync"
|
|
35
|
+
| "switch"
|
|
36
|
+
| "diff"
|
|
37
|
+
| "settings"
|
|
38
|
+
| "pull"
|
|
39
|
+
| "push"
|
|
40
|
+
| "setups"
|
|
41
|
+
| "connections"
|
|
42
|
+
| "history"
|
|
43
|
+
| "doctor"
|
|
44
|
+
| "unlock"
|
|
45
|
+
| "recover"
|
|
46
|
+
| "refresh"
|
|
47
|
+
| "help"
|
|
48
|
+
| "init"
|
|
49
|
+
| "back";
|
|
50
|
+
interface State {
|
|
51
|
+
manager: Awaited<ReturnType<typeof describeManagerState>>;
|
|
52
|
+
}
|
|
53
|
+
const menu = defineMenu<State, Screen, Action, ExtensionCommandContext>({
|
|
54
|
+
start: "main",
|
|
55
|
+
screens: {
|
|
56
|
+
main: ({ state }) => {
|
|
57
|
+
const attentionItems = attentionMainMenuItems(state.manager);
|
|
58
|
+
const managerItems = state.manager.actions.map(
|
|
59
|
+
(label) => blockedSyncMenuItem(label, state.manager) ?? syncMainMenuItem(label),
|
|
60
|
+
);
|
|
61
|
+
const operationFirst = state.manager.operation !== undefined && state.manager.operation.kind !== "free";
|
|
62
|
+
return {
|
|
63
|
+
kind: "actions",
|
|
64
|
+
title: "Manage sync",
|
|
65
|
+
lines: state.manager.title.split("\n").slice(1),
|
|
66
|
+
items: operationFirst ? [...managerItems, ...attentionItems] : [...attentionItems, ...managerItems],
|
|
67
|
+
hint: "close",
|
|
68
|
+
};
|
|
69
|
+
},
|
|
70
|
+
more: () => ({
|
|
71
|
+
kind: "actions",
|
|
72
|
+
title: "More options",
|
|
73
|
+
items: [
|
|
74
|
+
{ id: "pull", label: "Pull from remote…", action: "pull" },
|
|
75
|
+
{ id: "push", label: "Push to remote…", action: "push" },
|
|
76
|
+
{ id: "setups", label: "Sync setups…", action: "setups" },
|
|
77
|
+
{
|
|
78
|
+
id: "connections",
|
|
79
|
+
label: "Storage connections…",
|
|
80
|
+
action: "connections",
|
|
81
|
+
},
|
|
82
|
+
{
|
|
83
|
+
id: "doctor",
|
|
84
|
+
label: "Check setup",
|
|
85
|
+
description: "Check current setup access. WebDAV also probes writes and repairs history.",
|
|
86
|
+
action: "doctor",
|
|
87
|
+
},
|
|
88
|
+
{ id: "recovery", label: "History & recovery…", to: "recovery" },
|
|
89
|
+
{ id: "help", label: "Help", action: "help" },
|
|
90
|
+
{ id: "back", label: "Back", action: "back" },
|
|
91
|
+
],
|
|
92
|
+
hint: "back",
|
|
93
|
+
}),
|
|
94
|
+
recovery: ({ state }) => ({
|
|
95
|
+
kind: "actions",
|
|
96
|
+
title: "History & recovery",
|
|
97
|
+
items: [
|
|
98
|
+
{ id: "history", label: "Browse history", action: "history" },
|
|
99
|
+
{
|
|
100
|
+
id: "doctor",
|
|
101
|
+
label: "Check setup",
|
|
102
|
+
description: "WebDAV also probes writes and repairs history.",
|
|
103
|
+
action: "doctor",
|
|
104
|
+
},
|
|
105
|
+
...(state.manager.operation && operationCanRecover(state.manager.operation)
|
|
106
|
+
? [{ id: "unlock", label: "Recover stale operation", action: "unlock" as const }]
|
|
107
|
+
: []),
|
|
108
|
+
{ id: "back", label: "Back", action: "back" },
|
|
109
|
+
],
|
|
110
|
+
hint: "back",
|
|
111
|
+
}),
|
|
112
|
+
},
|
|
113
|
+
actions: {
|
|
114
|
+
"review-attention": async () => {
|
|
115
|
+
const attention = options.getAttention?.();
|
|
116
|
+
if (!attention) {
|
|
117
|
+
const observation = options.getObservation?.();
|
|
118
|
+
if (!observation) return { kind: "stay" };
|
|
119
|
+
// A head-only observation is not an authoritative decision. Load a fresh
|
|
120
|
+
// snapshot only after the user activates the existing review flow.
|
|
121
|
+
const { showRemoteSelectionReview } = await import("./remote-selection-ui.js");
|
|
122
|
+
if (sessionSignal?.aborted) return { kind: "close" };
|
|
123
|
+
const config = await loadConfig();
|
|
124
|
+
if (sessionSignal?.aborted) return { kind: "close" };
|
|
125
|
+
if (options.getObservation?.() !== observation || !observationMatchesConfig(observation, config)) {
|
|
126
|
+
options.onObservationInvalidated?.();
|
|
127
|
+
return { kind: "stay" };
|
|
128
|
+
}
|
|
129
|
+
// Keep the check-time hint on cancellation or failure. Route commits and
|
|
130
|
+
// the manager's config/baseline reconciliation own invalidation.
|
|
131
|
+
const result = await showRemoteSelectionReview(ctx, observation.setupName, sessionSignal, undefined, {
|
|
132
|
+
origin: "sync",
|
|
133
|
+
runRoute,
|
|
134
|
+
onSelectionResolved: () => {
|
|
135
|
+
if (!sessionSignal?.aborted && options.getObservation?.() === observation)
|
|
136
|
+
options.onObservationInvalidated?.();
|
|
137
|
+
},
|
|
138
|
+
});
|
|
139
|
+
if (sessionSignal?.aborted) return { kind: "close" };
|
|
140
|
+
if (result.kind === "route-result") {
|
|
141
|
+
return dispatchManagerResult(ctx, result.result, result.route, runRoute, sessionSignal);
|
|
142
|
+
}
|
|
143
|
+
return { kind: result.kind === "closed" || result.kind === "stale" ? "close" : "stay" };
|
|
144
|
+
}
|
|
145
|
+
const disposition = await showManagerAttention(ctx, attention, runRoute, sessionSignal, () =>
|
|
146
|
+
options.onSelectionResolved?.(attention),
|
|
147
|
+
);
|
|
148
|
+
return { kind: disposition };
|
|
149
|
+
},
|
|
150
|
+
sync: async () => {
|
|
151
|
+
const pendingAttention = options.getAttention?.();
|
|
152
|
+
if (pendingAttention) {
|
|
153
|
+
const activeConfig = await loadConfig();
|
|
154
|
+
if (sessionSignal?.aborted) return { kind: "close" };
|
|
155
|
+
if (pendingAttention.decision.setupName === activeConfig.setupName) {
|
|
156
|
+
ctx.ui.notify("Review synced content before starting Sync now.", "warning");
|
|
157
|
+
return { kind: "stay" };
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
const result = await runCancellableOperation(ctx, "Checking current sync setup…", "sync", runRoute, {
|
|
161
|
+
commitAware: true,
|
|
162
|
+
signal: sessionSignal,
|
|
163
|
+
});
|
|
164
|
+
const disposition = await dispatchManagerResult(ctx, result, "sync", runRoute, sessionSignal);
|
|
165
|
+
return disposition.kind === "close" ? { kind: "close" } : { kind: "stay" };
|
|
166
|
+
},
|
|
167
|
+
switch: async () => {
|
|
168
|
+
const result = await showSetupSwitcher(ctx, runRoute, undefined, sessionSignal);
|
|
169
|
+
return result === "pull-attempted" || result === "closed" ? { kind: "close" } : { kind: "stay" };
|
|
170
|
+
},
|
|
171
|
+
diff: async () => {
|
|
172
|
+
const result = await runCancellableOperation(ctx, "Checking current sync setup…", "diff", runRoute, {
|
|
173
|
+
signal: sessionSignal,
|
|
174
|
+
});
|
|
175
|
+
return result.kind === "closed" ? { kind: "close" } : { kind: "stay" };
|
|
176
|
+
},
|
|
177
|
+
settings: async () => {
|
|
178
|
+
await showSyncSettings(ctx, runRoute, sessionSignal);
|
|
179
|
+
return { kind: "stay" };
|
|
180
|
+
},
|
|
181
|
+
pull: async () => {
|
|
182
|
+
const result = await runCancellableOperation(ctx, "Checking remote changes…", "pull", runRoute, {
|
|
183
|
+
commitAware: true,
|
|
184
|
+
cancelledMessage: "Pull check cancelled; no local files were changed.",
|
|
185
|
+
signal: sessionSignal,
|
|
186
|
+
});
|
|
187
|
+
const disposition = await dispatchManagerResult(ctx, result, "pull", runRoute, sessionSignal);
|
|
188
|
+
return disposition.kind === "close" ? { kind: "close" } : { kind: "stay" };
|
|
189
|
+
},
|
|
190
|
+
push: async () => {
|
|
191
|
+
const result = await runCancellableOperation(ctx, "Preparing push preview…", "push", runRoute, {
|
|
192
|
+
commitAware: true,
|
|
193
|
+
cancelledMessage: "Push preparation cancelled; no remote files were changed.",
|
|
194
|
+
signal: sessionSignal,
|
|
195
|
+
});
|
|
196
|
+
const disposition = await dispatchManagerResult(ctx, result, "push", runRoute, sessionSignal);
|
|
197
|
+
return disposition.kind === "close" ? { kind: "close" } : { kind: "stay" };
|
|
198
|
+
},
|
|
199
|
+
setups: async () => {
|
|
200
|
+
const result = await showSyncSetupManager(ctx, runRoute, sessionSignal);
|
|
201
|
+
return result === "exit" ? { kind: "close" } : { kind: "stay" };
|
|
202
|
+
},
|
|
203
|
+
connections: async () => {
|
|
204
|
+
await showStorageConnections(ctx, sessionSignal);
|
|
205
|
+
return { kind: "stay" };
|
|
206
|
+
},
|
|
207
|
+
history: async () => {
|
|
208
|
+
await runRoute("history");
|
|
209
|
+
return { kind: "stay" };
|
|
210
|
+
},
|
|
211
|
+
doctor: async () => {
|
|
212
|
+
const result = await runCancellableOperation(ctx, "Checking setup access…", "doctor", runRoute, {
|
|
213
|
+
signal: sessionSignal,
|
|
214
|
+
});
|
|
215
|
+
return { kind: result.kind === "closed" ? "close" : "stay" };
|
|
216
|
+
},
|
|
217
|
+
unlock: async ({ state, signal: actionSignal }) => {
|
|
218
|
+
const result = await recoverSyncAccess(ctx, state.manager, runRoute, sessionSignal, actionSignal);
|
|
219
|
+
if (result === "close") return { kind: "close" };
|
|
220
|
+
return result === "restored" ? { kind: "to", screen: "main" } : { kind: "stay" };
|
|
221
|
+
},
|
|
222
|
+
recover: async ({ state, signal: actionSignal }) => {
|
|
223
|
+
const result = await recoverSyncAccess(ctx, state.manager, runRoute, sessionSignal, actionSignal);
|
|
224
|
+
return { kind: result === "close" ? "close" : "stay" };
|
|
225
|
+
},
|
|
226
|
+
refresh: async () => ({ kind: "stay" }),
|
|
227
|
+
help: async () => {
|
|
228
|
+
await runRoute("help");
|
|
229
|
+
return { kind: "close" };
|
|
230
|
+
},
|
|
231
|
+
init: async () => {
|
|
232
|
+
await runRoute("init");
|
|
233
|
+
return { kind: "stay" };
|
|
234
|
+
},
|
|
235
|
+
back: async () => ({ kind: "back" }),
|
|
236
|
+
},
|
|
237
|
+
});
|
|
238
|
+
await runMenu(ctx, menu, {
|
|
239
|
+
getState: async () => {
|
|
240
|
+
const pendingAttention = options.getAttention?.();
|
|
241
|
+
const observation = options.getObservation?.();
|
|
242
|
+
const manager = await describeManagerState(sessionSignal, pendingAttention, undefined, observation);
|
|
243
|
+
if (sessionSignal?.aborted) return { manager };
|
|
244
|
+
// A busy operation suppresses baseline reads, not the stored check-time hint.
|
|
245
|
+
if (
|
|
246
|
+
observation &&
|
|
247
|
+
options.getObservation?.() === observation &&
|
|
248
|
+
!manager.observation &&
|
|
249
|
+
!(manager.operation && operationBlocksChanges(manager.operation))
|
|
250
|
+
) {
|
|
251
|
+
options.onObservationInvalidated?.();
|
|
252
|
+
}
|
|
253
|
+
if (pendingAttention && options.getAttention?.() === pendingAttention && !manager.attention) {
|
|
254
|
+
options.onSelectionResolved?.(pendingAttention);
|
|
255
|
+
}
|
|
256
|
+
return { manager };
|
|
257
|
+
},
|
|
258
|
+
signal: sessionSignal,
|
|
259
|
+
isCurrent: () => !sessionSignal?.aborted,
|
|
260
|
+
});
|
|
341
261
|
}
|
|
342
262
|
|
|
343
263
|
function syncMainMenuItem(
|
|
344
|
-
|
|
264
|
+
label: string,
|
|
345
265
|
): ActionMenuItem<
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
| "switch"
|
|
349
|
-
| "diff"
|
|
350
|
-
| "settings"
|
|
351
|
-
| "setups"
|
|
352
|
-
| "connections"
|
|
353
|
-
| "recover"
|
|
354
|
-
| "refresh"
|
|
355
|
-
| "help"
|
|
356
|
-
| "init"
|
|
266
|
+
"main" | "more" | "recovery",
|
|
267
|
+
"sync" | "switch" | "diff" | "settings" | "setups" | "connections" | "recover" | "refresh" | "help" | "init"
|
|
357
268
|
> {
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
["Restore sync access… (recommended)", "recover"],
|
|
378
|
-
["Refresh operation status", "refresh"],
|
|
379
|
-
["Sync setups…", "setups"],
|
|
380
|
-
["Storage connections…", "connections"],
|
|
381
|
-
["Help", "help"],
|
|
382
|
-
["Set up sync", "init"],
|
|
383
|
-
["Use existing settings", "init"],
|
|
384
|
-
]);
|
|
385
|
-
return { id: actions.get(label) ?? "help", label, action: actions.get(label) ?? "help" };
|
|
269
|
+
if (label === "More…") return { id: "more", label, to: "more" };
|
|
270
|
+
if (label === "History & recovery…") return { id: "recovery", label, to: "recovery" };
|
|
271
|
+
const actions = new Map<
|
|
272
|
+
string,
|
|
273
|
+
"sync" | "switch" | "diff" | "settings" | "setups" | "connections" | "recover" | "refresh" | "help" | "init"
|
|
274
|
+
>([
|
|
275
|
+
["Sync now (recommended)", "sync"],
|
|
276
|
+
["Switch sync setup", "switch"],
|
|
277
|
+
["Status & changes", "diff"],
|
|
278
|
+
["Settings", "settings"],
|
|
279
|
+
["Restore sync access… (recommended)", "recover"],
|
|
280
|
+
["Refresh operation status", "refresh"],
|
|
281
|
+
["Sync setups…", "setups"],
|
|
282
|
+
["Storage connections…", "connections"],
|
|
283
|
+
["Help", "help"],
|
|
284
|
+
["Set up sync", "init"],
|
|
285
|
+
["Use existing settings", "init"],
|
|
286
|
+
]);
|
|
287
|
+
return { id: actions.get(label) ?? "help", label, action: actions.get(label) ?? "help" };
|
|
386
288
|
}
|