@buoy-gg/time-machine 7.0.40 → 7.0.42
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 -0
- package/lib/commonjs/components/HeaderActions.js +1 -91
- package/lib/commonjs/components/HeaderReloadButton.js +1 -58
- package/lib/commonjs/components/TimeMachineBody.js +1 -282
- package/lib/commonjs/components/TimeMachineModal.js +1 -74
- package/lib/commonjs/components/confirm.js +2 -38
- package/lib/commonjs/components/floating/NamePromptModal.js +1 -193
- package/lib/commonjs/components/floating/TimeMachineFloatingTool.js +1 -715
- package/lib/commonjs/components/floating/armedPoint.js +1 -92
- package/lib/commonjs/components/floating/barSettings.js +1 -66
- package/lib/commonjs/components/format.js +1 -24
- package/lib/commonjs/components/list/CaptureBar.js +1 -97
- package/lib/commonjs/components/list/RestoreOutcomeCard.js +1 -175
- package/lib/commonjs/components/list/SnapshotRow.js +1 -170
- package/lib/commonjs/components/list/SourcesStrip.js +1 -172
- package/lib/commonjs/components/list/UndoDeleteBar.js +1 -85
- package/lib/commonjs/components/list/WipeAllRow.js +1 -46
- package/lib/commonjs/components/preview/ItemDiffPanel.js +1 -79
- package/lib/commonjs/components/preview/PreviewFlow.js +1 -51
- package/lib/commonjs/components/preview/RestorePointNameRow.js +1 -83
- package/lib/commonjs/components/preview/RestorePreviewScreen.js +1 -1010
- package/lib/commonjs/components/preview/verdictMeta.js +1 -58
- package/lib/commonjs/components/sources.js +1 -83
- package/lib/commonjs/hooks/useTimeMachine.js +1 -24
- package/lib/commonjs/index.js +1 -161
- package/lib/commonjs/preset.js +1 -56
- package/lib/commonjs/store/routeRestore.js +1 -188
- package/lib/commonjs/store/snapshotVault.js +1 -186
- package/lib/commonjs/store/sourceIds.js +1 -9
- package/lib/commonjs/store/sourceSettings.js +1 -79
- package/lib/commonjs/store/timeMachineStore.js +1 -848
- package/lib/commonjs/sync/timeMachineSyncAdapter.js +1 -258
- package/lib/commonjs/ui/SwipeActionsRow.js +1 -178
- package/lib/commonjs/ui/primitives.js +1 -172
- package/lib/commonjs/ui/tmTheme.js +1 -118
- package/lib/module/components/HeaderActions.js +1 -85
- package/lib/module/components/HeaderReloadButton.js +1 -53
- package/lib/module/components/TimeMachineBody.js +1 -277
- package/lib/module/components/TimeMachineModal.js +1 -68
- package/lib/module/components/confirm.js +2 -33
- package/lib/module/components/floating/NamePromptModal.js +1 -188
- package/lib/module/components/floating/TimeMachineFloatingTool.js +1 -708
- package/lib/module/components/floating/armedPoint.js +1 -82
- package/lib/module/components/floating/barSettings.js +1 -57
- package/lib/module/components/format.js +1 -19
- package/lib/module/components/list/CaptureBar.js +1 -92
- package/lib/module/components/list/RestoreOutcomeCard.js +1 -169
- package/lib/module/components/list/SnapshotRow.js +1 -167
- package/lib/module/components/list/SourcesStrip.js +1 -169
- package/lib/module/components/list/UndoDeleteBar.js +1 -82
- package/lib/module/components/list/WipeAllRow.js +1 -41
- package/lib/module/components/preview/ItemDiffPanel.js +1 -74
- package/lib/module/components/preview/PreviewFlow.js +1 -46
- package/lib/module/components/preview/RestorePointNameRow.js +1 -78
- package/lib/module/components/preview/RestorePreviewScreen.js +1 -1005
- package/lib/module/components/preview/verdictMeta.js +1 -54
- package/lib/module/components/sources.js +1 -73
- package/lib/module/hooks/useTimeMachine.js +1 -19
- package/lib/module/index.js +1 -46
- package/lib/module/preset.js +1 -51
- package/lib/module/store/routeRestore.js +1 -176
- package/lib/module/store/snapshotVault.js +1 -170
- package/lib/module/store/sourceIds.js +1 -5
- package/lib/module/store/sourceSettings.js +1 -69
- package/lib/module/store/timeMachineStore.js +1 -839
- package/lib/module/sync/timeMachineSyncAdapter.js +1 -253
- package/lib/module/ui/SwipeActionsRow.js +1 -173
- package/lib/module/ui/primitives.js +1 -164
- package/lib/module/ui/tmTheme.js +1 -114
- package/lib/web/index.mjs +3 -0
- package/package.json +43 -10
- package/lib/commonjs/components/HeaderActions.js.map +0 -1
- package/lib/commonjs/components/HeaderReloadButton.js.map +0 -1
- package/lib/commonjs/components/TimeMachineBody.js.map +0 -1
- package/lib/commonjs/components/TimeMachineModal.js.map +0 -1
- package/lib/commonjs/components/confirm.js.map +0 -1
- package/lib/commonjs/components/floating/NamePromptModal.js.map +0 -1
- package/lib/commonjs/components/floating/TimeMachineFloatingTool.js.map +0 -1
- package/lib/commonjs/components/floating/armedPoint.js.map +0 -1
- package/lib/commonjs/components/floating/barSettings.js.map +0 -1
- package/lib/commonjs/components/format.js.map +0 -1
- package/lib/commonjs/components/list/CaptureBar.js.map +0 -1
- package/lib/commonjs/components/list/RestoreOutcomeCard.js.map +0 -1
- package/lib/commonjs/components/list/SnapshotRow.js.map +0 -1
- package/lib/commonjs/components/list/SourcesStrip.js.map +0 -1
- package/lib/commonjs/components/list/UndoDeleteBar.js.map +0 -1
- package/lib/commonjs/components/list/WipeAllRow.js.map +0 -1
- package/lib/commonjs/components/preview/ItemDiffPanel.js.map +0 -1
- package/lib/commonjs/components/preview/PreviewFlow.js.map +0 -1
- package/lib/commonjs/components/preview/RestorePointNameRow.js.map +0 -1
- package/lib/commonjs/components/preview/RestorePreviewScreen.js.map +0 -1
- package/lib/commonjs/components/preview/verdictMeta.js.map +0 -1
- package/lib/commonjs/components/sources.js.map +0 -1
- package/lib/commonjs/hooks/useTimeMachine.js.map +0 -1
- package/lib/commonjs/index.js.map +0 -1
- package/lib/commonjs/preset.js.map +0 -1
- package/lib/commonjs/store/routeRestore.js.map +0 -1
- package/lib/commonjs/store/snapshotVault.js.map +0 -1
- package/lib/commonjs/store/sourceIds.js.map +0 -1
- package/lib/commonjs/store/sourceSettings.js.map +0 -1
- package/lib/commonjs/store/timeMachineStore.js.map +0 -1
- package/lib/commonjs/sync/timeMachineSyncAdapter.js.map +0 -1
- package/lib/commonjs/ui/SwipeActionsRow.js.map +0 -1
- package/lib/commonjs/ui/primitives.js.map +0 -1
- package/lib/commonjs/ui/tmTheme.js.map +0 -1
- package/lib/module/components/HeaderActions.js.map +0 -1
- package/lib/module/components/HeaderReloadButton.js.map +0 -1
- package/lib/module/components/TimeMachineBody.js.map +0 -1
- package/lib/module/components/TimeMachineModal.js.map +0 -1
- package/lib/module/components/confirm.js.map +0 -1
- package/lib/module/components/floating/NamePromptModal.js.map +0 -1
- package/lib/module/components/floating/TimeMachineFloatingTool.js.map +0 -1
- package/lib/module/components/floating/armedPoint.js.map +0 -1
- package/lib/module/components/floating/barSettings.js.map +0 -1
- package/lib/module/components/format.js.map +0 -1
- package/lib/module/components/list/CaptureBar.js.map +0 -1
- package/lib/module/components/list/RestoreOutcomeCard.js.map +0 -1
- package/lib/module/components/list/SnapshotRow.js.map +0 -1
- package/lib/module/components/list/SourcesStrip.js.map +0 -1
- package/lib/module/components/list/UndoDeleteBar.js.map +0 -1
- package/lib/module/components/list/WipeAllRow.js.map +0 -1
- package/lib/module/components/preview/ItemDiffPanel.js.map +0 -1
- package/lib/module/components/preview/PreviewFlow.js.map +0 -1
- package/lib/module/components/preview/RestorePointNameRow.js.map +0 -1
- package/lib/module/components/preview/RestorePreviewScreen.js.map +0 -1
- package/lib/module/components/preview/verdictMeta.js.map +0 -1
- package/lib/module/components/sources.js.map +0 -1
- package/lib/module/hooks/useTimeMachine.js.map +0 -1
- package/lib/module/index.js.map +0 -1
- package/lib/module/preset.js.map +0 -1
- package/lib/module/store/routeRestore.js.map +0 -1
- package/lib/module/store/snapshotVault.js.map +0 -1
- package/lib/module/store/sourceIds.js.map +0 -1
- package/lib/module/store/sourceSettings.js.map +0 -1
- package/lib/module/store/timeMachineStore.js.map +0 -1
- package/lib/module/sync/timeMachineSyncAdapter.js.map +0 -1
- package/lib/module/ui/SwipeActionsRow.js.map +0 -1
- package/lib/module/ui/primitives.js.map +0 -1
- package/lib/module/ui/tmTheme.js.map +0 -1
- package/lib/typescript/components/HeaderActions.d.ts.map +0 -1
- package/lib/typescript/components/HeaderReloadButton.d.ts.map +0 -1
- package/lib/typescript/components/TimeMachineBody.d.ts.map +0 -1
- package/lib/typescript/components/TimeMachineModal.d.ts.map +0 -1
- package/lib/typescript/components/confirm.d.ts.map +0 -1
- package/lib/typescript/components/floating/NamePromptModal.d.ts.map +0 -1
- package/lib/typescript/components/floating/TimeMachineFloatingTool.d.ts.map +0 -1
- package/lib/typescript/components/floating/armedPoint.d.ts.map +0 -1
- package/lib/typescript/components/floating/barSettings.d.ts.map +0 -1
- package/lib/typescript/components/format.d.ts.map +0 -1
- package/lib/typescript/components/list/CaptureBar.d.ts.map +0 -1
- package/lib/typescript/components/list/RestoreOutcomeCard.d.ts.map +0 -1
- package/lib/typescript/components/list/SnapshotRow.d.ts.map +0 -1
- package/lib/typescript/components/list/SourcesStrip.d.ts.map +0 -1
- package/lib/typescript/components/list/UndoDeleteBar.d.ts.map +0 -1
- package/lib/typescript/components/list/WipeAllRow.d.ts.map +0 -1
- package/lib/typescript/components/preview/ItemDiffPanel.d.ts.map +0 -1
- package/lib/typescript/components/preview/PreviewFlow.d.ts.map +0 -1
- package/lib/typescript/components/preview/RestorePointNameRow.d.ts.map +0 -1
- package/lib/typescript/components/preview/RestorePreviewScreen.d.ts.map +0 -1
- package/lib/typescript/components/preview/verdictMeta.d.ts.map +0 -1
- package/lib/typescript/components/sources.d.ts.map +0 -1
- package/lib/typescript/hooks/useTimeMachine.d.ts.map +0 -1
- package/lib/typescript/index.d.ts.map +0 -1
- package/lib/typescript/preset.d.ts.map +0 -1
- package/lib/typescript/store/routeRestore.d.ts.map +0 -1
- package/lib/typescript/store/snapshotVault.d.ts.map +0 -1
- package/lib/typescript/store/sourceIds.d.ts.map +0 -1
- package/lib/typescript/store/sourceSettings.d.ts.map +0 -1
- package/lib/typescript/store/timeMachineStore.d.ts.map +0 -1
- package/lib/typescript/sync/timeMachineSyncAdapter.d.ts.map +0 -1
- package/lib/typescript/ui/SwipeActionsRow.d.ts.map +0 -1
- package/lib/typescript/ui/primitives.d.ts.map +0 -1
- package/lib/typescript/ui/tmTheme.d.ts.map +0 -1
|
@@ -1,92 +1 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
|
|
3
|
-
Object.defineProperty(exports, "__esModule", {
|
|
4
|
-
value: true
|
|
5
|
-
});
|
|
6
|
-
exports.ensurePickedPointLoaded = ensurePickedPointLoaded;
|
|
7
|
-
exports.getPickedPointId = getPickedPointId;
|
|
8
|
-
exports.resetPickedPointForTests = resetPickedPointForTests;
|
|
9
|
-
exports.resolveArmedPoint = resolveArmedPoint;
|
|
10
|
-
exports.setPickedPointId = setPickedPointId;
|
|
11
|
-
exports.subscribePickedPoint = subscribePickedPoint;
|
|
12
|
-
var _sharedUi = require("@buoy-gg/shared-ui");
|
|
13
|
-
/**
|
|
14
|
-
* Which restore point the floating restore bar restores on tap.
|
|
15
|
-
*
|
|
16
|
-
* The bar needs an answer before the user picks anything, or its first tap is
|
|
17
|
-
* a picker instead of a restore. So the armed point is resolved, not just
|
|
18
|
-
* stored: an explicit pick wins, then the point restored most recently, then
|
|
19
|
-
* the newest capture. Baselines never resolve; restoring one wipes storage
|
|
20
|
-
* and reloads behind a confirm dialog, which is not a one-tap action. The
|
|
21
|
-
* safety slot never resolves either: Undo is its way in.
|
|
22
|
-
*
|
|
23
|
-
* The explicit pick is persisted so it survives the reloads the loop itself
|
|
24
|
-
* causes (RELOAD APP, reload-mode restores).
|
|
25
|
-
*/
|
|
26
|
-
|
|
27
|
-
const KEY = _sharedUi.devToolsStorageKeys.timeMachine.armedPoint();
|
|
28
|
-
let pickedId = null;
|
|
29
|
-
let loaded = false;
|
|
30
|
-
let loadPromise = null;
|
|
31
|
-
const listeners = new Set();
|
|
32
|
-
const notify = () => listeners.forEach(listener => listener());
|
|
33
|
-
function getPickedPointId() {
|
|
34
|
-
return pickedId;
|
|
35
|
-
}
|
|
36
|
-
function subscribePickedPoint(listener) {
|
|
37
|
-
listeners.add(listener);
|
|
38
|
-
return () => {
|
|
39
|
-
listeners.delete(listener);
|
|
40
|
-
};
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
/** Read the saved pick once. Later calls return the same promise. */
|
|
44
|
-
function ensurePickedPointLoaded() {
|
|
45
|
-
if (loaded) return Promise.resolve();
|
|
46
|
-
if (!loadPromise) {
|
|
47
|
-
loadPromise = _sharedUi.persistentStorage.getItem(KEY).then(saved => {
|
|
48
|
-
// A pick made while the read was in flight wins over the disk copy.
|
|
49
|
-
if (pickedId === null && saved) {
|
|
50
|
-
pickedId = saved;
|
|
51
|
-
notify();
|
|
52
|
-
}
|
|
53
|
-
}).catch(() => {}).finally(() => {
|
|
54
|
-
loaded = true;
|
|
55
|
-
});
|
|
56
|
-
}
|
|
57
|
-
return loadPromise;
|
|
58
|
-
}
|
|
59
|
-
function setPickedPointId(id) {
|
|
60
|
-
if (pickedId === id) return;
|
|
61
|
-
pickedId = id;
|
|
62
|
-
notify();
|
|
63
|
-
void (id === null ? _sharedUi.persistentStorage.removeItem(KEY) : _sharedUi.persistentStorage.setItem(KEY, id)).catch(() => {});
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
/** Test seam: forget the pick and the load, without touching storage. */
|
|
67
|
-
function resetPickedPointForTests() {
|
|
68
|
-
pickedId = null;
|
|
69
|
-
loaded = false;
|
|
70
|
-
loadPromise = null;
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
/**
|
|
74
|
-
* The point the bar restores: the saved pick if it still exists, else the
|
|
75
|
-
* most recently restored point, else the newest capture. Never a baseline.
|
|
76
|
-
*/
|
|
77
|
-
function resolveArmedPoint(snapshots, pickedId) {
|
|
78
|
-
const candidates = snapshots.filter(meta => !meta.baseline && !meta.safety);
|
|
79
|
-
if (candidates.length === 0) return null;
|
|
80
|
-
if (pickedId) {
|
|
81
|
-
const picked = candidates.find(meta => meta.id === pickedId);
|
|
82
|
-
if (picked) return picked;
|
|
83
|
-
}
|
|
84
|
-
let best = null;
|
|
85
|
-
for (const meta of candidates) {
|
|
86
|
-
if (meta.lastRestoredAt === undefined) continue;
|
|
87
|
-
if (!best || meta.lastRestoredAt > (best.lastRestoredAt ?? 0)) best = meta;
|
|
88
|
-
}
|
|
89
|
-
if (best) return best;
|
|
90
|
-
return candidates.reduce((newest, meta) => meta.createdAt > newest.createdAt ? meta : newest);
|
|
91
|
-
}
|
|
92
|
-
//# sourceMappingURL=armedPoint.js.map
|
|
1
|
+
"use strict";Object.defineProperty(exports,"__esModule",{value:true});exports.ensurePickedPointLoaded=ensurePickedPointLoaded;exports.getPickedPointId=getPickedPointId;exports.resetPickedPointForTests=resetPickedPointForTests;exports.resolveArmedPoint=resolveArmedPoint;exports.setPickedPointId=setPickedPointId;exports.subscribePickedPoint=subscribePickedPoint;var _sharedUi=require("@buoy-gg/shared-ui");const KEY=_sharedUi.devToolsStorageKeys.timeMachine.armedPoint();let pickedId=null;let loaded=false;let loadPromise=null;const listeners=new Set;const notify=()=>listeners.forEach(e=>e());function getPickedPointId(){return pickedId}function subscribePickedPoint(e){listeners.add(e);return()=>{listeners.delete(e)}}function ensurePickedPointLoaded(){if(loaded)return Promise.resolve();if(!loadPromise){loadPromise=_sharedUi.persistentStorage.getItem(KEY).then(e=>{if(pickedId===null&&e){pickedId=e;notify()}}).catch(()=>{}).finally(()=>{loaded=true})}return loadPromise}function setPickedPointId(e){if(pickedId===e)return;pickedId=e;notify();void(e===null?_sharedUi.persistentStorage.removeItem(KEY):_sharedUi.persistentStorage.setItem(KEY,e)).catch(()=>{})}function resetPickedPointForTests(){pickedId=null;loaded=false;loadPromise=null}function resolveArmedPoint(e,i){const n=e.filter(t=>!t.baseline&&!t.safety);if(n.length===0)return null;if(i){const t=n.find(o=>o.id===i);if(t)return t}let r=null;for(const t of n){if(t.lastRestoredAt===void 0)continue;if(!r||t.lastRestoredAt>(r.lastRestoredAt??0))r=t}if(r)return r;return n.reduce((t,o)=>o.createdAt>t.createdAt?o:t)}
|
|
@@ -1,66 +1 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
|
|
3
|
-
Object.defineProperty(exports, "__esModule", {
|
|
4
|
-
value: true
|
|
5
|
-
});
|
|
6
|
-
exports.ensureBarSettingsLoaded = ensureBarSettingsLoaded;
|
|
7
|
-
exports.getBarReloadMode = getBarReloadMode;
|
|
8
|
-
exports.resetBarSettingsForTests = resetBarSettingsForTests;
|
|
9
|
-
exports.setBarReloadMode = setBarReloadMode;
|
|
10
|
-
exports.subscribeBarSettings = subscribeBarSettings;
|
|
11
|
-
var _sharedUi = require("@buoy-gg/shared-ui");
|
|
12
|
-
/**
|
|
13
|
-
* The action bar's one setting: restore live, or restore and reload.
|
|
14
|
-
*
|
|
15
|
-
* Live restore replaces stores in place and is right for state that lives in
|
|
16
|
-
* Redux, Zustand, Jotai or the query cache. It cannot reach a React context
|
|
17
|
-
* or `useState` that hydrates itself from storage once at mount: the
|
|
18
|
-
* storage key comes back, the screen keeps showing what it already had, and
|
|
19
|
-
* "restore did nothing" is the report. A restore that reloads the app makes
|
|
20
|
-
* those screens rebuild from the restored storage. Persisted, because the
|
|
21
|
-
* reload itself is what brings the bar back.
|
|
22
|
-
*/
|
|
23
|
-
|
|
24
|
-
const KEY = _sharedUi.devToolsStorageKeys.timeMachine.barReloadMode();
|
|
25
|
-
let reloadMode = false;
|
|
26
|
-
let loaded = false;
|
|
27
|
-
let loadPromise = null;
|
|
28
|
-
const listeners = new Set();
|
|
29
|
-
const notify = () => listeners.forEach(listener => listener());
|
|
30
|
-
function getBarReloadMode() {
|
|
31
|
-
return reloadMode;
|
|
32
|
-
}
|
|
33
|
-
function subscribeBarSettings(listener) {
|
|
34
|
-
listeners.add(listener);
|
|
35
|
-
return () => {
|
|
36
|
-
listeners.delete(listener);
|
|
37
|
-
};
|
|
38
|
-
}
|
|
39
|
-
function ensureBarSettingsLoaded() {
|
|
40
|
-
if (loaded) return Promise.resolve();
|
|
41
|
-
if (!loadPromise) {
|
|
42
|
-
loadPromise = _sharedUi.persistentStorage.getItem(KEY).then(saved => {
|
|
43
|
-
if (!reloadMode && saved === "1") {
|
|
44
|
-
reloadMode = true;
|
|
45
|
-
notify();
|
|
46
|
-
}
|
|
47
|
-
}).catch(() => {}).finally(() => {
|
|
48
|
-
loaded = true;
|
|
49
|
-
});
|
|
50
|
-
}
|
|
51
|
-
return loadPromise;
|
|
52
|
-
}
|
|
53
|
-
function setBarReloadMode(on) {
|
|
54
|
-
if (on === reloadMode) return;
|
|
55
|
-
reloadMode = on;
|
|
56
|
-
notify();
|
|
57
|
-
void _sharedUi.persistentStorage.setItem(KEY, on ? "1" : "0").catch(() => {});
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
/** Test seam. */
|
|
61
|
-
function resetBarSettingsForTests() {
|
|
62
|
-
reloadMode = false;
|
|
63
|
-
loaded = false;
|
|
64
|
-
loadPromise = null;
|
|
65
|
-
}
|
|
66
|
-
//# sourceMappingURL=barSettings.js.map
|
|
1
|
+
"use strict";Object.defineProperty(exports,"__esModule",{value:true});exports.ensureBarSettingsLoaded=ensureBarSettingsLoaded;exports.getBarReloadMode=getBarReloadMode;exports.resetBarSettingsForTests=resetBarSettingsForTests;exports.setBarReloadMode=setBarReloadMode;exports.subscribeBarSettings=subscribeBarSettings;var _sharedUi=require("@buoy-gg/shared-ui");const KEY=_sharedUi.devToolsStorageKeys.timeMachine.barReloadMode();let reloadMode=false;let loaded=false;let loadPromise=null;const listeners=new Set;const notify=()=>listeners.forEach(e=>e());function getBarReloadMode(){return reloadMode}function subscribeBarSettings(e){listeners.add(e);return()=>{listeners.delete(e)}}function ensureBarSettingsLoaded(){if(loaded)return Promise.resolve();if(!loadPromise){loadPromise=_sharedUi.persistentStorage.getItem(KEY).then(e=>{if(!reloadMode&&e==="1"){reloadMode=true;notify()}}).catch(()=>{}).finally(()=>{loaded=true})}return loadPromise}function setBarReloadMode(e){if(e===reloadMode)return;reloadMode=e;notify();void _sharedUi.persistentStorage.setItem(KEY,e?"1":"0").catch(()=>{})}function resetBarSettingsForTests(){reloadMode=false;loaded=false;loadPromise=null}
|
|
@@ -1,24 +1 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
|
|
3
|
-
Object.defineProperty(exports, "__esModule", {
|
|
4
|
-
value: true
|
|
5
|
-
});
|
|
6
|
-
exports.formatBytes = formatBytes;
|
|
7
|
-
exports.timeAgo = timeAgo;
|
|
8
|
-
/** Display formatting shared by the Time Machine screens. */
|
|
9
|
-
|
|
10
|
-
function timeAgo(ts) {
|
|
11
|
-
const s = Math.max(0, Math.round((Date.now() - ts) / 1000));
|
|
12
|
-
if (s < 60) return `${s}s ago`;
|
|
13
|
-
const m = Math.round(s / 60);
|
|
14
|
-
if (m < 60) return `${m}m ago`;
|
|
15
|
-
const h = Math.round(m / 60);
|
|
16
|
-
if (h < 24) return `${h}h ago`;
|
|
17
|
-
return `${Math.round(h / 24)}d ago`;
|
|
18
|
-
}
|
|
19
|
-
function formatBytes(bytes) {
|
|
20
|
-
if (bytes < 1024) return `${bytes} B`;
|
|
21
|
-
if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)} KB`;
|
|
22
|
-
return `${(bytes / (1024 * 1024)).toFixed(1)} MB`;
|
|
23
|
-
}
|
|
24
|
-
//# sourceMappingURL=format.js.map
|
|
1
|
+
"use strict";Object.defineProperty(exports,"__esModule",{value:true});exports.formatBytes=formatBytes;exports.timeAgo=timeAgo;function timeAgo(t){const r=Math.max(0,Math.round((Date.now()-t)/1e3));if(r<60)return`${r}s ago`;const o=Math.round(r/60);if(o<60)return`${o}m ago`;const e=Math.round(o/60);if(e<24)return`${e}h ago`;return`${Math.round(e/24)}d ago`}function formatBytes(t){if(t<1024)return`${t} B`;if(t<1024*1024)return`${(t/1024).toFixed(1)} KB`;return`${(t/(1024*1024)).toFixed(1)} MB`}
|
|
@@ -1,97 +1 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
|
|
3
|
-
Object.defineProperty(exports, "__esModule", {
|
|
4
|
-
value: true
|
|
5
|
-
});
|
|
6
|
-
exports.CaptureBar = CaptureBar;
|
|
7
|
-
var _react = require("react");
|
|
8
|
-
var _reactNative = require("react-native");
|
|
9
|
-
var _tmTheme = require("../../ui/tmTheme");
|
|
10
|
-
var _jsxRuntime = require("react/jsx-runtime");
|
|
11
|
-
/**
|
|
12
|
-
* Capture bar — the single field-plus-pill control at the top of the list.
|
|
13
|
-
*
|
|
14
|
-
* Owns the draft name itself so keystrokes re-render this component and not
|
|
15
|
-
* the snapshot list underneath it. The parent only hears about a finished
|
|
16
|
-
* capture.
|
|
17
|
-
*/
|
|
18
|
-
|
|
19
|
-
function CaptureBar({
|
|
20
|
-
disabled,
|
|
21
|
-
busy,
|
|
22
|
-
onCapture
|
|
23
|
-
}) {
|
|
24
|
-
const [name, setName] = (0, _react.useState)("");
|
|
25
|
-
const capture = () => {
|
|
26
|
-
if (disabled) return;
|
|
27
|
-
onCapture(name);
|
|
28
|
-
setName("");
|
|
29
|
-
};
|
|
30
|
-
return /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
|
|
31
|
-
style: styles.bar,
|
|
32
|
-
children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.TextInput, {
|
|
33
|
-
style: styles.input,
|
|
34
|
-
value: name,
|
|
35
|
-
onChangeText: setName,
|
|
36
|
-
placeholder: "Name this restore point\u2026",
|
|
37
|
-
placeholderTextColor: _tmTheme.tm.color.labelTertiary,
|
|
38
|
-
editable: !disabled,
|
|
39
|
-
onSubmitEditing: capture,
|
|
40
|
-
returnKeyType: "done",
|
|
41
|
-
testID: "time-machine-name-input"
|
|
42
|
-
}), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.TouchableOpacity, {
|
|
43
|
-
style: [styles.button, disabled ? styles.buttonDisabled : null],
|
|
44
|
-
onPress: capture,
|
|
45
|
-
disabled: disabled,
|
|
46
|
-
accessibilityRole: "button",
|
|
47
|
-
accessibilityLabel: "Capture restore point",
|
|
48
|
-
testID: "time-machine-capture",
|
|
49
|
-
children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
|
|
50
|
-
style: styles.buttonText,
|
|
51
|
-
children: busy ? "Capturing…" : "Capture"
|
|
52
|
-
})
|
|
53
|
-
})]
|
|
54
|
-
});
|
|
55
|
-
}
|
|
56
|
-
const styles = _reactNative.StyleSheet.create({
|
|
57
|
-
bar: {
|
|
58
|
-
flexDirection: "row",
|
|
59
|
-
alignItems: "center",
|
|
60
|
-
gap: 8,
|
|
61
|
-
marginHorizontal: _tmTheme.tm.gutter,
|
|
62
|
-
backgroundColor: _tmTheme.tm.color.group,
|
|
63
|
-
borderRadius: _tmTheme.tm.radius.group,
|
|
64
|
-
borderWidth: 1,
|
|
65
|
-
borderColor: _tmTheme.tm.color.groupBorder,
|
|
66
|
-
paddingLeft: _tmTheme.tm.textInset,
|
|
67
|
-
padding: 6
|
|
68
|
-
},
|
|
69
|
-
input: {
|
|
70
|
-
flex: 1,
|
|
71
|
-
minWidth: 0,
|
|
72
|
-
color: _tmTheme.tm.color.label,
|
|
73
|
-
fontSize: _tmTheme.tm.font.row,
|
|
74
|
-
letterSpacing: _tmTheme.tm.tracking.row,
|
|
75
|
-
// Zero out the platform chrome so the field reads as part of the card.
|
|
76
|
-
padding: 0,
|
|
77
|
-
backgroundColor: "transparent"
|
|
78
|
-
},
|
|
79
|
-
button: {
|
|
80
|
-
height: 34,
|
|
81
|
-
paddingHorizontal: 16,
|
|
82
|
-
borderRadius: _tmTheme.tm.radius.pill,
|
|
83
|
-
backgroundColor: _tmTheme.tm.color.accent,
|
|
84
|
-
alignItems: "center",
|
|
85
|
-
justifyContent: "center"
|
|
86
|
-
},
|
|
87
|
-
buttonDisabled: {
|
|
88
|
-
opacity: 0.4
|
|
89
|
-
},
|
|
90
|
-
buttonText: {
|
|
91
|
-
color: _tmTheme.tm.color.onAccent,
|
|
92
|
-
fontSize: _tmTheme.tm.font.control,
|
|
93
|
-
fontWeight: "600",
|
|
94
|
-
letterSpacing: _tmTheme.tm.tracking.control
|
|
95
|
-
}
|
|
96
|
-
});
|
|
97
|
-
//# sourceMappingURL=CaptureBar.js.map
|
|
1
|
+
"use strict";Object.defineProperty(exports,"__esModule",{value:true});exports.CaptureBar=CaptureBar;var _react=require("react");var _reactNative=require("react-native");var _tmTheme=require("../../ui/tmTheme");var _jsxRuntime=require("react/jsx-runtime");function CaptureBar({disabled:t,busy:n,onCapture:a}){const[e,r]=(0,_react.useState)("");const o=()=>{if(t)return;a(e);r("")};return(0,_jsxRuntime.jsxs)(_reactNative.View,{style:styles.bar,children:[(0,_jsxRuntime.jsx)(_reactNative.TextInput,{style:styles.input,value:e,onChangeText:r,placeholder:"Name this restore point\u2026",placeholderTextColor:_tmTheme.tm.color.labelTertiary,editable:!t,onSubmitEditing:o,returnKeyType:"done",testID:"time-machine-name-input"}),(0,_jsxRuntime.jsx)(_reactNative.TouchableOpacity,{style:[styles.button,t?styles.buttonDisabled:null],onPress:o,disabled:t,accessibilityRole:"button",accessibilityLabel:"Capture restore point",testID:"time-machine-capture",children:(0,_jsxRuntime.jsx)(_reactNative.Text,{style:styles.buttonText,children:n?"Capturing\u2026":"Capture"})})]})}const styles=_reactNative.StyleSheet.create({bar:{flexDirection:"row",alignItems:"center",gap:8,marginHorizontal:_tmTheme.tm.gutter,backgroundColor:_tmTheme.tm.color.group,borderRadius:_tmTheme.tm.radius.group,borderWidth:1,borderColor:_tmTheme.tm.color.groupBorder,paddingLeft:_tmTheme.tm.textInset,padding:6},input:{flex:1,minWidth:0,color:_tmTheme.tm.color.label,fontSize:_tmTheme.tm.font.row,letterSpacing:_tmTheme.tm.tracking.row,padding:0,backgroundColor:"transparent"},button:{height:34,paddingHorizontal:16,borderRadius:_tmTheme.tm.radius.pill,backgroundColor:_tmTheme.tm.color.accent,alignItems:"center",justifyContent:"center"},buttonDisabled:{opacity:.4},buttonText:{color:_tmTheme.tm.color.onAccent,fontSize:_tmTheme.tm.font.control,fontWeight:"600",letterSpacing:_tmTheme.tm.tracking.control}});
|
|
@@ -1,175 +1 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
|
|
3
|
-
Object.defineProperty(exports, "__esModule", {
|
|
4
|
-
value: true
|
|
5
|
-
});
|
|
6
|
-
exports.RestoreOutcomeCard = RestoreOutcomeCard;
|
|
7
|
-
exports.restoreNeedsAttention = restoreNeedsAttention;
|
|
8
|
-
var _reactNative = require("react-native");
|
|
9
|
-
var _sharedUi = require("@buoy-gg/shared-ui");
|
|
10
|
-
var _tmTheme = require("../../ui/tmTheme");
|
|
11
|
-
var _timeMachineStore = require("../../store/timeMachineStore");
|
|
12
|
-
var _jsxRuntime = require("react/jsx-runtime");
|
|
13
|
-
/**
|
|
14
|
-
* What the last restore did, shown ONLY when something went wrong.
|
|
15
|
-
*
|
|
16
|
-
* A clean restore says so with a toast and then gets out of the way — the
|
|
17
|
-
* restored app is the proof, and a wall of green ticks on top of the list
|
|
18
|
-
* every single time was noise. A restore that skipped or failed a source is
|
|
19
|
-
* the opposite: nothing else on screen would ever tell you, so it stays until
|
|
20
|
-
* dismissed.
|
|
21
|
-
*/
|
|
22
|
-
|
|
23
|
-
const HIT = {
|
|
24
|
-
top: 10,
|
|
25
|
-
bottom: 10,
|
|
26
|
-
left: 10,
|
|
27
|
-
right: 10
|
|
28
|
-
};
|
|
29
|
-
|
|
30
|
-
/**
|
|
31
|
-
* Did this restore do anything the app itself won't show you? Warnings alone
|
|
32
|
-
* don't count — "1 derived atom recomputes" is true of every restore and
|
|
33
|
-
* would put the card back on screen permanently.
|
|
34
|
-
*/
|
|
35
|
-
function restoreNeedsAttention(outcome) {
|
|
36
|
-
if (Object.values(outcome.results).some(r => !r.ok || r.skipped.length > 0)) return true;
|
|
37
|
-
const route = outcome.route;
|
|
38
|
-
return route?.status === "failed" || route?.status === "unavailable";
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
/** ✓ / ✕ / ↻ line — the glyph carries the meaning, the color reinforces it. */
|
|
42
|
-
function ResultLine({
|
|
43
|
-
glyph,
|
|
44
|
-
text,
|
|
45
|
-
ok,
|
|
46
|
-
testID
|
|
47
|
-
}) {
|
|
48
|
-
return /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.Text, {
|
|
49
|
-
style: [styles.line, {
|
|
50
|
-
color: ok ? _tmTheme.tm.color.accent : _tmTheme.tm.color.warning
|
|
51
|
-
}],
|
|
52
|
-
numberOfLines: 2,
|
|
53
|
-
testID: testID,
|
|
54
|
-
children: [/*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.Text, {
|
|
55
|
-
style: styles.glyph,
|
|
56
|
-
children: [glyph, " "]
|
|
57
|
-
}), text]
|
|
58
|
-
});
|
|
59
|
-
}
|
|
60
|
-
const ROUTE_TEST_ID = "time-machine-outcome-route";
|
|
61
|
-
function RouteResult({
|
|
62
|
-
route
|
|
63
|
-
}) {
|
|
64
|
-
if (route.status === "navigated") return /*#__PURE__*/(0, _jsxRuntime.jsx)(ResultLine, {
|
|
65
|
-
glyph: "\u2713",
|
|
66
|
-
ok: true,
|
|
67
|
-
text: `route — ${route.href}`,
|
|
68
|
-
testID: ROUTE_TEST_ID
|
|
69
|
-
});
|
|
70
|
-
if (route.status === "deferred") return /*#__PURE__*/(0, _jsxRuntime.jsx)(ResultLine, {
|
|
71
|
-
glyph: "\u21BB",
|
|
72
|
-
ok: true,
|
|
73
|
-
text: `route — ${route.href} after reload`,
|
|
74
|
-
testID: ROUTE_TEST_ID
|
|
75
|
-
});
|
|
76
|
-
return /*#__PURE__*/(0, _jsxRuntime.jsx)(ResultLine, {
|
|
77
|
-
glyph: "\u2715",
|
|
78
|
-
ok: false,
|
|
79
|
-
text: `route — ${route.error ?? route.status}`,
|
|
80
|
-
testID: ROUTE_TEST_ID
|
|
81
|
-
});
|
|
82
|
-
}
|
|
83
|
-
function RestoreOutcomeCard({
|
|
84
|
-
outcome
|
|
85
|
-
}) {
|
|
86
|
-
const entries = Object.entries(outcome.results);
|
|
87
|
-
const reloading = outcome.mode === "reload" || outcome.willReload;
|
|
88
|
-
return /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
|
|
89
|
-
style: styles.card,
|
|
90
|
-
testID: "time-machine-outcome",
|
|
91
|
-
children: [/*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
|
|
92
|
-
style: styles.headerRow,
|
|
93
|
-
children: [/*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.Text, {
|
|
94
|
-
style: styles.title,
|
|
95
|
-
numberOfLines: 1,
|
|
96
|
-
testID: "time-machine-outcome-title",
|
|
97
|
-
children: ["Restored \u201C", outcome.snapshotName, "\u201D", reloading ? " · reloading" : ""]
|
|
98
|
-
}), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.TouchableOpacity, {
|
|
99
|
-
onPress: () => _timeMachineStore.timeMachineStore.clearLastOutcome(),
|
|
100
|
-
hitSlop: HIT,
|
|
101
|
-
accessibilityRole: "button",
|
|
102
|
-
accessibilityLabel: "Dismiss restore result",
|
|
103
|
-
testID: "time-machine-outcome-dismiss",
|
|
104
|
-
children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_sharedUi.X, {
|
|
105
|
-
size: 13,
|
|
106
|
-
color: _tmTheme.tm.color.labelSecondary
|
|
107
|
-
})
|
|
108
|
-
})]
|
|
109
|
-
}), entries.length === 0 && !outcome.route ? /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
|
|
110
|
-
style: styles.empty,
|
|
111
|
-
testID: "time-machine-outcome-empty",
|
|
112
|
-
children: "No sources restored."
|
|
113
|
-
}) : null, outcome.route ? /*#__PURE__*/(0, _jsxRuntime.jsx)(RouteResult, {
|
|
114
|
-
route: outcome.route
|
|
115
|
-
}) : null, entries.map(([sourceId, result]) => /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
|
|
116
|
-
children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(ResultLine, {
|
|
117
|
-
testID: `time-machine-outcome-${sourceId}`,
|
|
118
|
-
glyph: result.ok ? "✓" : "✕",
|
|
119
|
-
ok: result.ok,
|
|
120
|
-
text: `${sourceId} — applied ${result.applied}${result.skipped.length > 0 ? `, skipped ${result.skipped.length}` : ""}`
|
|
121
|
-
}), result.skipped.slice(0, 3).map(skip => /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.Text, {
|
|
122
|
-
style: styles.detail,
|
|
123
|
-
numberOfLines: 2,
|
|
124
|
-
children: [skip.id, ": ", skip.reason]
|
|
125
|
-
}, skip.id)), result.warnings.slice(0, 3).map(warning => /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.Text, {
|
|
126
|
-
style: styles.detail,
|
|
127
|
-
numberOfLines: 2,
|
|
128
|
-
children: ["\u26A0 ", warning]
|
|
129
|
-
}, warning))]
|
|
130
|
-
}, sourceId))]
|
|
131
|
-
});
|
|
132
|
-
}
|
|
133
|
-
const styles = _reactNative.StyleSheet.create({
|
|
134
|
-
card: {
|
|
135
|
-
marginHorizontal: _tmTheme.tm.gutter,
|
|
136
|
-
marginTop: 12,
|
|
137
|
-
backgroundColor: _tmTheme.tm.color.group,
|
|
138
|
-
borderRadius: _tmTheme.tm.radius.group,
|
|
139
|
-
borderWidth: 1,
|
|
140
|
-
borderColor: _tmTheme.tm.color.groupBorder,
|
|
141
|
-
padding: 14,
|
|
142
|
-
gap: 4
|
|
143
|
-
},
|
|
144
|
-
headerRow: {
|
|
145
|
-
flexDirection: "row",
|
|
146
|
-
alignItems: "center",
|
|
147
|
-
gap: 10,
|
|
148
|
-
marginBottom: 2
|
|
149
|
-
},
|
|
150
|
-
title: {
|
|
151
|
-
flex: 1,
|
|
152
|
-
color: _tmTheme.tm.color.label,
|
|
153
|
-
fontSize: 15,
|
|
154
|
-
fontWeight: "600",
|
|
155
|
-
letterSpacing: _tmTheme.tm.tracking.control
|
|
156
|
-
},
|
|
157
|
-
line: {
|
|
158
|
-
fontSize: _tmTheme.tm.font.footnote,
|
|
159
|
-
lineHeight: _tmTheme.tm.font.footnote * 1.4
|
|
160
|
-
},
|
|
161
|
-
glyph: {
|
|
162
|
-
fontWeight: "700"
|
|
163
|
-
},
|
|
164
|
-
detail: {
|
|
165
|
-
color: _tmTheme.tm.color.labelTertiary,
|
|
166
|
-
fontSize: _tmTheme.tm.font.mono,
|
|
167
|
-
lineHeight: _tmTheme.tm.font.mono * 1.4,
|
|
168
|
-
paddingLeft: 14
|
|
169
|
-
},
|
|
170
|
-
empty: {
|
|
171
|
-
color: _tmTheme.tm.color.labelSecondary,
|
|
172
|
-
fontSize: _tmTheme.tm.font.footnote
|
|
173
|
-
}
|
|
174
|
-
});
|
|
175
|
-
//# sourceMappingURL=RestoreOutcomeCard.js.map
|
|
1
|
+
"use strict";Object.defineProperty(exports,"__esModule",{value:true});exports.RestoreOutcomeCard=RestoreOutcomeCard;exports.restoreNeedsAttention=restoreNeedsAttention;var _reactNative=require("react-native");var _sharedUi=require("@buoy-gg/shared-ui");var _tmTheme=require("../../ui/tmTheme");var _timeMachineStore=require("../../store/timeMachineStore");var _jsxRuntime=require("react/jsx-runtime");const HIT={top:10,bottom:10,left:10,right:10};function restoreNeedsAttention(e){if(Object.values(e.results).some(o=>!o.ok||o.skipped.length>0))return true;const t=e.route;return t?.status==="failed"||t?.status==="unavailable"}function ResultLine({glyph:e,text:t,ok:o,testID:s}){return(0,_jsxRuntime.jsxs)(_reactNative.Text,{style:[styles.line,{color:o?_tmTheme.tm.color.accent:_tmTheme.tm.color.warning}],numberOfLines:2,testID:s,children:[(0,_jsxRuntime.jsxs)(_reactNative.Text,{style:styles.glyph,children:[e," "]}),t]})}const ROUTE_TEST_ID="time-machine-outcome-route";function RouteResult({route:e}){if(e.status==="navigated")return(0,_jsxRuntime.jsx)(ResultLine,{glyph:"\u2713",ok:true,text:`route \u2014 ${e.href}`,testID:ROUTE_TEST_ID});if(e.status==="deferred")return(0,_jsxRuntime.jsx)(ResultLine,{glyph:"\u21BB",ok:true,text:`route \u2014 ${e.href} after reload`,testID:ROUTE_TEST_ID});return(0,_jsxRuntime.jsx)(ResultLine,{glyph:"\u2715",ok:false,text:`route \u2014 ${e.error??e.status}`,testID:ROUTE_TEST_ID})}function RestoreOutcomeCard({outcome:e}){const t=Object.entries(e.results);const o=e.mode==="reload"||e.willReload;return(0,_jsxRuntime.jsxs)(_reactNative.View,{style:styles.card,testID:"time-machine-outcome",children:[(0,_jsxRuntime.jsxs)(_reactNative.View,{style:styles.headerRow,children:[(0,_jsxRuntime.jsxs)(_reactNative.Text,{style:styles.title,numberOfLines:1,testID:"time-machine-outcome-title",children:["Restored \u201C",e.snapshotName,"\u201D",o?" \xB7 reloading":""]}),(0,_jsxRuntime.jsx)(_reactNative.TouchableOpacity,{onPress:()=>_timeMachineStore.timeMachineStore.clearLastOutcome(),hitSlop:HIT,accessibilityRole:"button",accessibilityLabel:"Dismiss restore result",testID:"time-machine-outcome-dismiss",children:(0,_jsxRuntime.jsx)(_sharedUi.X,{size:13,color:_tmTheme.tm.color.labelSecondary})})]}),t.length===0&&!e.route?(0,_jsxRuntime.jsx)(_reactNative.Text,{style:styles.empty,testID:"time-machine-outcome-empty",children:"No sources restored."}):null,e.route?(0,_jsxRuntime.jsx)(RouteResult,{route:e.route}):null,t.map(([s,r])=>(0,_jsxRuntime.jsxs)(_reactNative.View,{children:[(0,_jsxRuntime.jsx)(ResultLine,{testID:`time-machine-outcome-${s}`,glyph:r.ok?"\u2713":"\u2715",ok:r.ok,text:`${s} \u2014 applied ${r.applied}${r.skipped.length>0?`, skipped ${r.skipped.length}`:""}`}),r.skipped.slice(0,3).map(i=>(0,_jsxRuntime.jsxs)(_reactNative.Text,{style:styles.detail,numberOfLines:2,children:[i.id,": ",i.reason]},i.id)),r.warnings.slice(0,3).map(i=>(0,_jsxRuntime.jsxs)(_reactNative.Text,{style:styles.detail,numberOfLines:2,children:["\u26A0 ",i]},i))]},s))]})}const styles=_reactNative.StyleSheet.create({card:{marginHorizontal:_tmTheme.tm.gutter,marginTop:12,backgroundColor:_tmTheme.tm.color.group,borderRadius:_tmTheme.tm.radius.group,borderWidth:1,borderColor:_tmTheme.tm.color.groupBorder,padding:14,gap:4},headerRow:{flexDirection:"row",alignItems:"center",gap:10,marginBottom:2},title:{flex:1,color:_tmTheme.tm.color.label,fontSize:15,fontWeight:"600",letterSpacing:_tmTheme.tm.tracking.control},line:{fontSize:_tmTheme.tm.font.footnote,lineHeight:_tmTheme.tm.font.footnote*1.4},glyph:{fontWeight:"700"},detail:{color:_tmTheme.tm.color.labelTertiary,fontSize:_tmTheme.tm.font.mono,lineHeight:_tmTheme.tm.font.mono*1.4,paddingLeft:14},empty:{color:_tmTheme.tm.color.labelSecondary,fontSize:_tmTheme.tm.font.footnote}});
|
|
@@ -1,170 +1 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
|
|
3
|
-
Object.defineProperty(exports, "__esModule", {
|
|
4
|
-
value: true
|
|
5
|
-
});
|
|
6
|
-
exports.SnapshotRow = SnapshotRow;
|
|
7
|
-
var _reactNative = require("react-native");
|
|
8
|
-
var _primitives = require("../../ui/primitives");
|
|
9
|
-
var _SwipeActionsRow = require("../../ui/SwipeActionsRow");
|
|
10
|
-
var _tmTheme = require("../../ui/tmTheme");
|
|
11
|
-
var _format = require("../format");
|
|
12
|
-
var _jsxRuntime = require("react/jsx-runtime");
|
|
13
|
-
/**
|
|
14
|
-
* One restore point in the list: what it is, when it was taken, how big it
|
|
15
|
-
* is, where it was captured — and the single action worth having at arm's
|
|
16
|
-
* reach. Tapping the row opens the restore preview; the pill restores now.
|
|
17
|
-
*
|
|
18
|
-
* The route is shown as context — where this state was true. Whether a
|
|
19
|
-
* restore also navigates there is decided in the restore preview, beside the
|
|
20
|
-
* other changes it is about to make.
|
|
21
|
-
*
|
|
22
|
-
* Duplicate and delete live behind a swipe. A destructive target beside
|
|
23
|
-
* "Restore" is a mis-tap that costs a snapshot, and the two-step gesture is
|
|
24
|
-
* deliberate enough — recovery is the undo the list offers after, not a
|
|
25
|
-
* dialog before. Renaming is NOT here: it belongs with the restore point's
|
|
26
|
-
* other settings, on the preview screen.
|
|
27
|
-
*/
|
|
28
|
-
|
|
29
|
-
/** "15h ago · 9.5 KB · 5 sources · skips 2" */function describe(meta) {
|
|
30
|
-
if (meta.baseline) return "Wipes to fresh install";
|
|
31
|
-
const parts = [(0, _format.timeAgo)(meta.createdAt), (0, _format.formatBytes)(meta.sizeBytes), `${Object.keys(meta.sources).length} sources`];
|
|
32
|
-
// A saved selection is worth stating on the row — this restore point no
|
|
33
|
-
// longer does the obvious thing, and one tap on RESTORE honors it.
|
|
34
|
-
if (meta.excludedKeys?.length) parts.push(`skips ${meta.excludedKeys.length}`);else if (meta.scope?.length) parts.push(`scoped (${meta.scope.length})`);
|
|
35
|
-
// The bar's own undo slot: kept for one restore, not a point you chose.
|
|
36
|
-
if (meta.safety) parts.unshift("safety copy");
|
|
37
|
-
return parts.join(" · ");
|
|
38
|
-
}
|
|
39
|
-
function SnapshotRow({
|
|
40
|
-
meta,
|
|
41
|
-
busy,
|
|
42
|
-
armed = false,
|
|
43
|
-
onOpen,
|
|
44
|
-
onRestore,
|
|
45
|
-
onDelete,
|
|
46
|
-
onDuplicate,
|
|
47
|
-
onArm
|
|
48
|
-
}) {
|
|
49
|
-
const testID = `time-machine-snap-${meta.id}`;
|
|
50
|
-
return /*#__PURE__*/(0, _jsxRuntime.jsx)(_SwipeActionsRow.SwipeActionsRow, {
|
|
51
|
-
testID: testID,
|
|
52
|
-
actions: [
|
|
53
|
-
// "Bar": put this point on the floating action bar.
|
|
54
|
-
{
|
|
55
|
-
label: "Bar",
|
|
56
|
-
onPress: onArm
|
|
57
|
-
},
|
|
58
|
-
// "Dup" over "Copy": on a row full of text, "Copy" reads as
|
|
59
|
-
// copy-to-clipboard.
|
|
60
|
-
{
|
|
61
|
-
label: "Dup",
|
|
62
|
-
onPress: onDuplicate
|
|
63
|
-
}, {
|
|
64
|
-
label: "Delete",
|
|
65
|
-
onPress: onDelete,
|
|
66
|
-
background: _tmTheme.tm.color.danger,
|
|
67
|
-
color: _tmTheme.tm.color.onDanger
|
|
68
|
-
}],
|
|
69
|
-
children: /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
|
|
70
|
-
style: styles.row,
|
|
71
|
-
children: [/*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.TouchableOpacity, {
|
|
72
|
-
style: styles.text,
|
|
73
|
-
onPress: onOpen,
|
|
74
|
-
activeOpacity: 0.7,
|
|
75
|
-
accessibilityRole: "button",
|
|
76
|
-
accessibilityLabel: `${meta.name}. ${describe(meta)}. Open restore preview`,
|
|
77
|
-
testID: testID,
|
|
78
|
-
children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
|
|
79
|
-
style: styles.name,
|
|
80
|
-
numberOfLines: 1,
|
|
81
|
-
testID: `${testID}-name`,
|
|
82
|
-
children: meta.name
|
|
83
|
-
}), armed ? /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
|
|
84
|
-
style: styles.armed,
|
|
85
|
-
numberOfLines: 1,
|
|
86
|
-
testID: `${testID}-armed`,
|
|
87
|
-
children: "On the action bar"
|
|
88
|
-
}) : null, /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
|
|
89
|
-
style: styles.meta,
|
|
90
|
-
numberOfLines: 1,
|
|
91
|
-
testID: `${testID}-meta`,
|
|
92
|
-
children: describe(meta)
|
|
93
|
-
}), meta.lastRestoredAt ? /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.Text, {
|
|
94
|
-
style: styles.restored,
|
|
95
|
-
numberOfLines: 1,
|
|
96
|
-
testID: `${testID}-restored`,
|
|
97
|
-
children: ["Restored ", (0, _format.timeAgo)(meta.lastRestoredAt)]
|
|
98
|
-
}) : null, meta.route ? /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
|
|
99
|
-
style: styles.route,
|
|
100
|
-
numberOfLines: 1,
|
|
101
|
-
testID: `${testID}-route`,
|
|
102
|
-
children: meta.route.href
|
|
103
|
-
}) : null]
|
|
104
|
-
}), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.TouchableOpacity, {
|
|
105
|
-
onPress: onRestore,
|
|
106
|
-
disabled: busy,
|
|
107
|
-
style: [styles.restore, busy ? styles.actionDisabled : null],
|
|
108
|
-
accessibilityRole: "button",
|
|
109
|
-
accessibilityLabel: meta.baseline ? "Wipe and reload" : "Restore",
|
|
110
|
-
testID: `${testID}-restore`,
|
|
111
|
-
children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_primitives.PillLabel, {
|
|
112
|
-
testID: `${testID}-restore-label`,
|
|
113
|
-
label: meta.baseline ? "Wipe" : "Restore",
|
|
114
|
-
color: meta.baseline ? _tmTheme.tm.color.danger : _tmTheme.tm.color.accent,
|
|
115
|
-
background: meta.baseline ? _tmTheme.tm.color.dangerSoft : _tmTheme.tm.color.accentSoft
|
|
116
|
-
})
|
|
117
|
-
})]
|
|
118
|
-
})
|
|
119
|
-
});
|
|
120
|
-
}
|
|
121
|
-
const styles = _reactNative.StyleSheet.create({
|
|
122
|
-
row: {
|
|
123
|
-
flexDirection: "row",
|
|
124
|
-
alignItems: "center",
|
|
125
|
-
gap: 10,
|
|
126
|
-
paddingHorizontal: _tmTheme.tm.textInset
|
|
127
|
-
},
|
|
128
|
-
// The text block is the tallest child, so its padding sets the row height
|
|
129
|
-
// and the open target spans the full row.
|
|
130
|
-
text: {
|
|
131
|
-
flex: 1,
|
|
132
|
-
minWidth: 0,
|
|
133
|
-
paddingVertical: 11
|
|
134
|
-
},
|
|
135
|
-
restore: {
|
|
136
|
-
justifyContent: "center"
|
|
137
|
-
},
|
|
138
|
-
name: {
|
|
139
|
-
color: _tmTheme.tm.color.label,
|
|
140
|
-
fontSize: _tmTheme.tm.font.row,
|
|
141
|
-
fontWeight: "600",
|
|
142
|
-
letterSpacing: _tmTheme.tm.tracking.row
|
|
143
|
-
},
|
|
144
|
-
meta: {
|
|
145
|
-
color: _tmTheme.tm.color.labelSecondary,
|
|
146
|
-
fontSize: _tmTheme.tm.font.footnote,
|
|
147
|
-
marginTop: 2,
|
|
148
|
-
fontVariant: ["tabular-nums"]
|
|
149
|
-
},
|
|
150
|
-
restored: {
|
|
151
|
-
color: _tmTheme.tm.color.accent,
|
|
152
|
-
fontSize: _tmTheme.tm.font.footnote,
|
|
153
|
-
marginTop: 2
|
|
154
|
-
},
|
|
155
|
-
armed: {
|
|
156
|
-
color: _tmTheme.tm.color.accent,
|
|
157
|
-
fontSize: _tmTheme.tm.font.footnote,
|
|
158
|
-
marginTop: 2
|
|
159
|
-
},
|
|
160
|
-
route: {
|
|
161
|
-
color: _tmTheme.tm.color.labelTertiary,
|
|
162
|
-
fontFamily: _tmTheme.TM_MONO,
|
|
163
|
-
fontSize: _tmTheme.tm.font.mono,
|
|
164
|
-
marginTop: 4
|
|
165
|
-
},
|
|
166
|
-
actionDisabled: {
|
|
167
|
-
opacity: 0.4
|
|
168
|
-
}
|
|
169
|
-
});
|
|
170
|
-
//# sourceMappingURL=SnapshotRow.js.map
|
|
1
|
+
"use strict";Object.defineProperty(exports,"__esModule",{value:true});exports.SnapshotRow=SnapshotRow;var _reactNative=require("react-native");var _primitives=require("../../ui/primitives");var _SwipeActionsRow=require("../../ui/SwipeActionsRow");var _tmTheme=require("../../ui/tmTheme");var _format=require("../format");var _jsxRuntime=require("react/jsx-runtime");function describe(e){if(e.baseline)return"Wipes to fresh install";const o=[(0,_format.timeAgo)(e.createdAt),(0,_format.formatBytes)(e.sizeBytes),`${Object.keys(e.sources).length} sources`];if(e.excludedKeys?.length)o.push(`skips ${e.excludedKeys.length}`);else if(e.scope?.length)o.push(`scoped (${e.scope.length})`);if(e.safety)o.unshift("safety copy");return o.join(" \xB7 ")}function SnapshotRow({meta:e,busy:o,armed:r=false,onOpen:s,onRestore:n,onDelete:i,onDuplicate:l,onArm:c}){const t=`time-machine-snap-${e.id}`;return(0,_jsxRuntime.jsx)(_SwipeActionsRow.SwipeActionsRow,{testID:t,actions:[{label:"Bar",onPress:c},{label:"Dup",onPress:l},{label:"Delete",onPress:i,background:_tmTheme.tm.color.danger,color:_tmTheme.tm.color.onDanger}],children:(0,_jsxRuntime.jsxs)(_reactNative.View,{style:styles.row,children:[(0,_jsxRuntime.jsxs)(_reactNative.TouchableOpacity,{style:styles.text,onPress:s,activeOpacity:.7,accessibilityRole:"button",accessibilityLabel:`${e.name}. ${describe(e)}. Open restore preview`,testID:t,children:[(0,_jsxRuntime.jsx)(_reactNative.Text,{style:styles.name,numberOfLines:1,testID:`${t}-name`,children:e.name}),r?(0,_jsxRuntime.jsx)(_reactNative.Text,{style:styles.armed,numberOfLines:1,testID:`${t}-armed`,children:"On the action bar"}):null,(0,_jsxRuntime.jsx)(_reactNative.Text,{style:styles.meta,numberOfLines:1,testID:`${t}-meta`,children:describe(e)}),e.lastRestoredAt?(0,_jsxRuntime.jsxs)(_reactNative.Text,{style:styles.restored,numberOfLines:1,testID:`${t}-restored`,children:["Restored ",(0,_format.timeAgo)(e.lastRestoredAt)]}):null,e.route?(0,_jsxRuntime.jsx)(_reactNative.Text,{style:styles.route,numberOfLines:1,testID:`${t}-route`,children:e.route.href}):null]}),(0,_jsxRuntime.jsx)(_reactNative.TouchableOpacity,{onPress:n,disabled:o,style:[styles.restore,o?styles.actionDisabled:null],accessibilityRole:"button",accessibilityLabel:e.baseline?"Wipe and reload":"Restore",testID:`${t}-restore`,children:(0,_jsxRuntime.jsx)(_primitives.PillLabel,{testID:`${t}-restore-label`,label:e.baseline?"Wipe":"Restore",color:e.baseline?_tmTheme.tm.color.danger:_tmTheme.tm.color.accent,background:e.baseline?_tmTheme.tm.color.dangerSoft:_tmTheme.tm.color.accentSoft})})]})})}const styles=_reactNative.StyleSheet.create({row:{flexDirection:"row",alignItems:"center",gap:10,paddingHorizontal:_tmTheme.tm.textInset},text:{flex:1,minWidth:0,paddingVertical:11},restore:{justifyContent:"center"},name:{color:_tmTheme.tm.color.label,fontSize:_tmTheme.tm.font.row,fontWeight:"600",letterSpacing:_tmTheme.tm.tracking.row},meta:{color:_tmTheme.tm.color.labelSecondary,fontSize:_tmTheme.tm.font.footnote,marginTop:2,fontVariant:["tabular-nums"]},restored:{color:_tmTheme.tm.color.accent,fontSize:_tmTheme.tm.font.footnote,marginTop:2},armed:{color:_tmTheme.tm.color.accent,fontSize:_tmTheme.tm.font.footnote,marginTop:2},route:{color:_tmTheme.tm.color.labelTertiary,fontFamily:_tmTheme.TM_MONO,fontSize:_tmTheme.tm.font.mono,marginTop:4},actionDisabled:{opacity:.4}});
|