@buoy-gg/time-machine 7.0.22 → 7.0.24
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/lib/commonjs/components/TimeMachineBody.js +147 -677
- package/lib/commonjs/components/TimeMachineBody.js.map +1 -1
- package/lib/commonjs/components/TimeMachineModal.js +10 -11
- package/lib/commonjs/components/TimeMachineModal.js.map +1 -1
- package/lib/commonjs/components/confirm.js +39 -0
- package/lib/commonjs/components/confirm.js.map +1 -0
- package/lib/commonjs/components/format.js +24 -0
- package/lib/commonjs/components/format.js.map +1 -0
- package/lib/commonjs/components/list/CaptureBar.js +95 -0
- package/lib/commonjs/components/list/CaptureBar.js.map +1 -0
- package/lib/commonjs/components/list/RestoreOutcomeCard.js +162 -0
- package/lib/commonjs/components/list/RestoreOutcomeCard.js.map +1 -0
- package/lib/commonjs/components/list/SnapshotRow.js +141 -0
- package/lib/commonjs/components/list/SnapshotRow.js.map +1 -0
- package/lib/commonjs/components/list/SourcesStrip.js +126 -0
- package/lib/commonjs/components/list/SourcesStrip.js.map +1 -0
- package/lib/commonjs/components/list/UndoDeleteBar.js +81 -0
- package/lib/commonjs/components/list/UndoDeleteBar.js.map +1 -0
- package/lib/commonjs/components/list/WipeAllRow.js +46 -0
- package/lib/commonjs/components/list/WipeAllRow.js.map +1 -0
- package/lib/commonjs/components/preview/ItemDiffPanel.js +77 -0
- package/lib/commonjs/components/preview/ItemDiffPanel.js.map +1 -0
- package/lib/commonjs/components/preview/PreviewFlow.js +51 -0
- package/lib/commonjs/components/preview/PreviewFlow.js.map +1 -0
- package/lib/commonjs/components/preview/RestorePointNameRow.js +83 -0
- package/lib/commonjs/components/preview/RestorePointNameRow.js.map +1 -0
- package/lib/commonjs/components/preview/RestorePreviewScreen.js +549 -635
- package/lib/commonjs/components/preview/RestorePreviewScreen.js.map +1 -1
- package/lib/commonjs/components/preview/verdictMeta.js +8 -8
- package/lib/commonjs/components/preview/verdictMeta.js.map +1 -1
- package/lib/commonjs/components/sources.js +72 -0
- package/lib/commonjs/components/sources.js.map +1 -0
- package/lib/commonjs/store/snapshotVault.js +93 -9
- package/lib/commonjs/store/snapshotVault.js.map +1 -1
- package/lib/commonjs/store/timeMachineStore.js +125 -6
- package/lib/commonjs/store/timeMachineStore.js.map +1 -1
- package/lib/commonjs/sync/timeMachineSyncAdapter.js +41 -0
- package/lib/commonjs/sync/timeMachineSyncAdapter.js.map +1 -1
- package/lib/commonjs/ui/SwipeActionsRow.js +167 -0
- package/lib/commonjs/ui/SwipeActionsRow.js.map +1 -0
- package/lib/commonjs/ui/primitives.js +164 -0
- package/lib/commonjs/ui/primitives.js.map +1 -0
- package/lib/commonjs/ui/tmTheme.js +103 -0
- package/lib/commonjs/ui/tmTheme.js.map +1 -0
- package/lib/module/components/TimeMachineBody.js +150 -680
- package/lib/module/components/TimeMachineBody.js.map +1 -1
- package/lib/module/components/TimeMachineModal.js +11 -12
- package/lib/module/components/TimeMachineModal.js.map +1 -1
- package/lib/module/components/confirm.js +34 -0
- package/lib/module/components/confirm.js.map +1 -0
- package/lib/module/components/format.js +19 -0
- package/lib/module/components/format.js.map +1 -0
- package/lib/module/components/list/CaptureBar.js +90 -0
- package/lib/module/components/list/CaptureBar.js.map +1 -0
- package/lib/module/components/list/RestoreOutcomeCard.js +156 -0
- package/lib/module/components/list/RestoreOutcomeCard.js.map +1 -0
- package/lib/module/components/list/SnapshotRow.js +138 -0
- package/lib/module/components/list/SnapshotRow.js.map +1 -0
- package/lib/module/components/list/SourcesStrip.js +121 -0
- package/lib/module/components/list/SourcesStrip.js.map +1 -0
- package/lib/module/components/list/UndoDeleteBar.js +78 -0
- package/lib/module/components/list/UndoDeleteBar.js.map +1 -0
- package/lib/module/components/list/WipeAllRow.js +41 -0
- package/lib/module/components/list/WipeAllRow.js.map +1 -0
- package/lib/module/components/preview/ItemDiffPanel.js +72 -0
- package/lib/module/components/preview/ItemDiffPanel.js.map +1 -0
- package/lib/module/components/preview/PreviewFlow.js +46 -0
- package/lib/module/components/preview/PreviewFlow.js.map +1 -0
- package/lib/module/components/preview/RestorePointNameRow.js +78 -0
- package/lib/module/components/preview/RestorePointNameRow.js.map +1 -0
- package/lib/module/components/preview/RestorePreviewScreen.js +552 -638
- package/lib/module/components/preview/RestorePreviewScreen.js.map +1 -1
- package/lib/module/components/preview/verdictMeta.js +9 -8
- package/lib/module/components/preview/verdictMeta.js.map +1 -1
- package/lib/module/components/sources.js +66 -0
- package/lib/module/components/sources.js.map +1 -0
- package/lib/module/store/snapshotVault.js +87 -9
- package/lib/module/store/snapshotVault.js.map +1 -1
- package/lib/module/store/timeMachineStore.js +125 -7
- package/lib/module/store/timeMachineStore.js.map +1 -1
- package/lib/module/sync/timeMachineSyncAdapter.js +41 -0
- package/lib/module/sync/timeMachineSyncAdapter.js.map +1 -1
- package/lib/module/ui/SwipeActionsRow.js +162 -0
- package/lib/module/ui/SwipeActionsRow.js.map +1 -0
- package/lib/module/ui/primitives.js +156 -0
- package/lib/module/ui/primitives.js.map +1 -0
- package/lib/module/ui/tmTheme.js +99 -0
- package/lib/module/ui/tmTheme.js.map +1 -0
- package/lib/typescript/components/TimeMachineBody.d.ts.map +1 -1
- package/lib/typescript/components/TimeMachineModal.d.ts.map +1 -1
- package/lib/typescript/components/confirm.d.ts +2 -0
- package/lib/typescript/components/confirm.d.ts.map +1 -0
- package/lib/typescript/components/format.d.ts +4 -0
- package/lib/typescript/components/format.d.ts.map +1 -0
- package/lib/typescript/components/list/CaptureBar.d.ts +6 -0
- package/lib/typescript/components/list/CaptureBar.d.ts.map +1 -0
- package/lib/typescript/components/list/RestoreOutcomeCard.d.ts +11 -0
- package/lib/typescript/components/list/RestoreOutcomeCard.d.ts.map +1 -0
- package/lib/typescript/components/list/SnapshotRow.d.ts +12 -0
- package/lib/typescript/components/list/SnapshotRow.d.ts.map +1 -0
- package/lib/typescript/components/list/SourcesStrip.d.ts +5 -0
- package/lib/typescript/components/list/SourcesStrip.d.ts.map +1 -0
- package/lib/typescript/components/list/UndoDeleteBar.d.ts +8 -0
- package/lib/typescript/components/list/UndoDeleteBar.d.ts.map +1 -0
- package/lib/typescript/components/list/WipeAllRow.d.ts +5 -0
- package/lib/typescript/components/list/WipeAllRow.d.ts.map +1 -0
- package/lib/typescript/components/preview/ItemDiffPanel.d.ts +5 -0
- package/lib/typescript/components/preview/ItemDiffPanel.d.ts.map +1 -0
- package/lib/typescript/components/preview/PreviewFlow.d.ts +9 -0
- package/lib/typescript/components/preview/PreviewFlow.d.ts.map +1 -0
- package/lib/typescript/components/preview/RestorePointNameRow.d.ts +5 -0
- package/lib/typescript/components/preview/RestorePointNameRow.d.ts.map +1 -0
- package/lib/typescript/components/preview/RestorePreviewScreen.d.ts +1 -5
- package/lib/typescript/components/preview/RestorePreviewScreen.d.ts.map +1 -1
- package/lib/typescript/components/preview/verdictMeta.d.ts +5 -0
- package/lib/typescript/components/preview/verdictMeta.d.ts.map +1 -1
- package/lib/typescript/components/sources.d.ts +36 -0
- package/lib/typescript/components/sources.d.ts.map +1 -0
- package/lib/typescript/store/snapshotVault.d.ts +48 -0
- package/lib/typescript/store/snapshotVault.d.ts.map +1 -1
- package/lib/typescript/store/timeMachineStore.d.ts +35 -1
- package/lib/typescript/store/timeMachineStore.d.ts.map +1 -1
- package/lib/typescript/sync/timeMachineSyncAdapter.d.ts +17 -0
- package/lib/typescript/sync/timeMachineSyncAdapter.d.ts.map +1 -1
- package/lib/typescript/ui/SwipeActionsRow.d.ts +32 -0
- package/lib/typescript/ui/SwipeActionsRow.d.ts.map +1 -0
- package/lib/typescript/ui/primitives.d.ts +57 -0
- package/lib/typescript/ui/primitives.d.ts.map +1 -0
- package/lib/typescript/ui/tmTheme.d.ts +67 -0
- package/lib/typescript/ui/tmTheme.d.ts.map +1 -0
- package/package.json +7 -7
- package/src/components/TimeMachineBody.tsx +183 -817
- package/src/components/TimeMachineModal.tsx +10 -11
- package/src/components/confirm.ts +35 -0
- package/src/components/format.ts +17 -0
- package/src/components/list/CaptureBar.tsx +100 -0
- package/src/components/list/RestoreOutcomeCard.tsx +159 -0
- package/src/components/list/SnapshotRow.tsx +155 -0
- package/src/components/list/SourcesStrip.tsx +124 -0
- package/src/components/list/UndoDeleteBar.tsx +76 -0
- package/src/components/list/WipeAllRow.tsx +42 -0
- package/src/components/preview/ItemDiffPanel.tsx +77 -0
- package/src/components/preview/PreviewFlow.tsx +70 -0
- package/src/components/preview/RestorePointNameRow.tsx +80 -0
- package/src/components/preview/RestorePreviewScreen.tsx +535 -535
- package/src/components/preview/verdictMeta.ts +8 -8
- package/src/components/sources.ts +92 -0
- package/src/store/snapshotVault.ts +131 -9
- package/src/store/timeMachineStore.ts +136 -5
- package/src/sync/timeMachineSyncAdapter.ts +30 -0
- package/src/ui/SwipeActionsRow.tsx +199 -0
- package/src/ui/primitives.tsx +157 -0
- package/src/ui/tmTheme.ts +107 -0
- package/lib/commonjs/components/preview/ItemDetailScreen.js +0 -189
- package/lib/commonjs/components/preview/ItemDetailScreen.js.map +0 -1
- package/lib/module/components/preview/ItemDetailScreen.js +0 -184
- package/lib/module/components/preview/ItemDetailScreen.js.map +0 -1
- package/lib/typescript/components/preview/ItemDetailScreen.d.ts +0 -11
- package/lib/typescript/components/preview/ItemDetailScreen.d.ts.map +0 -1
- package/src/components/preview/ItemDetailScreen.tsx +0 -172
|
@@ -1,726 +1,196 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
|
-
* Time Machine body —
|
|
5
|
-
* the Restore Preview flow (tap a snapshot row → item-level diff of what a
|
|
6
|
-
* restore would change; tap an item → tree/split detail).
|
|
4
|
+
* Time Machine body — the screen router plus the restore-point list.
|
|
7
5
|
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
6
|
+
* Screens: list → preview. Each is its own component that mounts and
|
|
7
|
+
* unmounts whole (no branching inside a single tree), and each owns its own
|
|
8
|
+
* scrolling — the host must NOT wrap this in a scroll view, or the preview's
|
|
9
|
+
* virtualized FlatList is defeated. Item diffs expand inline in that list
|
|
10
|
+
* rather than being a third screen.
|
|
11
|
+
*
|
|
12
|
+
* The list follows the grouped-inset surface in ../ui: capture bar, the
|
|
13
|
+
* Sources strip, one card of restore points with swipe-to-delete, and the
|
|
14
|
+
* app-wide wipe kept last and understated.
|
|
11
15
|
*/
|
|
12
16
|
import { useState } from "react";
|
|
13
|
-
import {
|
|
14
|
-
import {
|
|
15
|
-
import { JotaiIcon, QueryIcon, ReduxIcon, RoutesIcon, StorageIcon, TimeMachineIcon, ZustandIcon } from "@buoy-gg/floating-tools-core";
|
|
17
|
+
import { ScrollView, StyleSheet, Text, View } from "react-native";
|
|
18
|
+
import { useSafeAreaInsets, useLimit } from "@buoy-gg/shared-ui";
|
|
16
19
|
import { useToolHost } from "@buoy-gg/core";
|
|
17
20
|
import { useIsPro } from "@buoy-gg/license";
|
|
18
|
-
import {
|
|
21
|
+
import { useTimeMachineState } from "../hooks/useTimeMachine";
|
|
19
22
|
import { timeMachineStore } from "../store/timeMachineStore";
|
|
20
|
-
import {
|
|
21
|
-
import {
|
|
22
|
-
import {
|
|
23
|
-
import {
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
const
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
return `${(bytes / (1024 * 1024)).toFixed(1)} MB`;
|
|
49
|
-
}
|
|
50
|
-
function warningCount(meta) {
|
|
51
|
-
return Object.values(meta.sources).reduce((sum, s) => sum + s.warnings.length, 0);
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
/** RN-web's Alert renders no buttons — fall back to the browser dialog there. */
|
|
55
|
-
function confirmDestructive(title, message, confirmLabel, onConfirm) {
|
|
56
|
-
if (Platform.OS === "web") {
|
|
57
|
-
const confirmFn = globalThis.confirm;
|
|
58
|
-
if (!confirmFn || confirmFn(`${title}\n\n${message}`)) onConfirm();
|
|
59
|
-
return;
|
|
60
|
-
}
|
|
61
|
-
Alert.alert(title, message, [{
|
|
62
|
-
text: "Cancel",
|
|
63
|
-
style: "cancel"
|
|
64
|
-
}, {
|
|
65
|
-
text: confirmLabel,
|
|
66
|
-
style: "destructive",
|
|
67
|
-
onPress: onConfirm
|
|
68
|
-
}]);
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
/**
|
|
72
|
-
* "Also go back to the screen this was captured on?"
|
|
73
|
-
*
|
|
74
|
-
* Asked BEFORE the restore runs, because a reload-mode restore has to park the
|
|
75
|
-
* route in storage before the JS realm dies — there is no "after" to ask in.
|
|
76
|
-
* `onChoose(withRoute)` runs the restore; dismissing cancels it entirely.
|
|
77
|
-
*
|
|
78
|
-
* RN-web's Alert renders no buttons, so the web (Buoy Desktop) path uses the
|
|
79
|
-
* browser dialog: OK = state + route, Cancel = state only.
|
|
80
|
-
*/
|
|
81
|
-
function confirmRestoreRoute(snapshotName, href, onChoose) {
|
|
82
|
-
const message = `“${snapshotName}” was captured on ${href}. Go back to that screen too, or restore state only?`;
|
|
83
|
-
if (Platform.OS === "web") {
|
|
84
|
-
const confirmFn = globalThis.confirm;
|
|
85
|
-
onChoose(confirmFn ? confirmFn(`Also return to ${href}?\n\n${message}`) : false);
|
|
86
|
-
return;
|
|
87
|
-
}
|
|
88
|
-
Alert.alert("Restore route too?", message, [{
|
|
89
|
-
text: "Cancel",
|
|
90
|
-
style: "cancel"
|
|
91
|
-
}, {
|
|
92
|
-
text: "State only",
|
|
93
|
-
onPress: () => onChoose(false)
|
|
94
|
-
}, {
|
|
95
|
-
text: `Go to ${href}`,
|
|
96
|
-
onPress: () => onChoose(true)
|
|
97
|
-
}]);
|
|
98
|
-
}
|
|
23
|
+
import { Footnote, Group, SectionLabel } from "../ui/primitives";
|
|
24
|
+
import { tm } from "../ui/tmTheme";
|
|
25
|
+
import { useSourceStatuses } from "./sources";
|
|
26
|
+
import { confirmDestructive } from "./confirm";
|
|
27
|
+
import { CaptureBar } from "./list/CaptureBar";
|
|
28
|
+
import { RestoreOutcomeCard, restoreNeedsAttention } from "./list/RestoreOutcomeCard";
|
|
29
|
+
import { SnapshotRow } from "./list/SnapshotRow";
|
|
30
|
+
import { UndoDeleteBar } from "./list/UndoDeleteBar";
|
|
31
|
+
import { SourcesStrip } from "./list/SourcesStrip";
|
|
32
|
+
import { WipeAllRow } from "./list/WipeAllRow";
|
|
33
|
+
import { PreviewScreen } from "./preview/PreviewFlow";
|
|
34
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
35
|
+
export function TimeMachineBody() {
|
|
36
|
+
const [screen, setScreen] = useState({
|
|
37
|
+
kind: "list"
|
|
38
|
+
});
|
|
39
|
+
const {
|
|
40
|
+
snapshots,
|
|
41
|
+
busy,
|
|
42
|
+
preview
|
|
43
|
+
} = useTimeMachineState();
|
|
44
|
+
const sources = useSourceStatuses();
|
|
45
|
+
const backToList = () => {
|
|
46
|
+
timeMachineStore.clearPreview();
|
|
47
|
+
setScreen({
|
|
48
|
+
kind: "list"
|
|
49
|
+
});
|
|
50
|
+
};
|
|
99
51
|
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
outcome
|
|
119
|
-
}) {
|
|
120
|
-
const entries = Object.entries(outcome.results);
|
|
121
|
-
return /*#__PURE__*/_jsxs(View, {
|
|
122
|
-
style: styles.outcomePanel,
|
|
123
|
-
children: [/*#__PURE__*/_jsxs(View, {
|
|
124
|
-
style: styles.outcomeHeaderRow,
|
|
125
|
-
children: [/*#__PURE__*/_jsxs(Text, {
|
|
126
|
-
style: styles.outcomeTitle,
|
|
127
|
-
children: ["Restored \u201C", outcome.snapshotName, "\u201D", outcome.mode === "reload" || outcome.willReload ? " · reloading" : ""]
|
|
128
|
-
}), /*#__PURE__*/_jsx(TouchableOpacity, {
|
|
129
|
-
onPress: () => timeMachineStore.clearLastOutcome(),
|
|
130
|
-
hitSlop: {
|
|
131
|
-
top: 8,
|
|
132
|
-
bottom: 8,
|
|
133
|
-
left: 8,
|
|
134
|
-
right: 8
|
|
135
|
-
},
|
|
136
|
-
children: /*#__PURE__*/_jsx(Text, {
|
|
137
|
-
style: styles.outcomeDismiss,
|
|
138
|
-
children: "\u2715"
|
|
139
|
-
})
|
|
140
|
-
})]
|
|
141
|
-
}), entries.length === 0 && /*#__PURE__*/_jsx(Text, {
|
|
142
|
-
style: styles.outcomeLine,
|
|
143
|
-
children: "no sources restored"
|
|
144
|
-
}), outcome.route && /*#__PURE__*/_jsx(Text, {
|
|
145
|
-
style: [styles.outcomeLine, (outcome.route.status === "failed" || outcome.route.status === "unavailable") && styles.outcomeLineBad],
|
|
146
|
-
children: outcome.route.status === "navigated" ? `✓ route — ${outcome.route.href}` : outcome.route.status === "deferred" ? `↻ route — ${outcome.route.href} after reload` : `✕ route — ${outcome.route.error ?? outcome.route.status}`
|
|
147
|
-
}), entries.map(([sourceId, r]) => /*#__PURE__*/_jsxs(View, {
|
|
148
|
-
style: styles.outcomeSource,
|
|
149
|
-
children: [/*#__PURE__*/_jsxs(Text, {
|
|
150
|
-
style: [styles.outcomeLine, !r.ok && styles.outcomeLineBad],
|
|
151
|
-
children: [r.ok ? "✓" : "✕", " ", sourceId, " \u2014 applied ", r.applied, r.skipped.length > 0 ? `, skipped ${r.skipped.length}` : ""]
|
|
152
|
-
}), r.skipped.slice(0, 3).map(skip => /*#__PURE__*/_jsxs(Text, {
|
|
153
|
-
style: styles.outcomeDetail,
|
|
154
|
-
children: ["\xB7 ", skip.id, ": ", skip.reason]
|
|
155
|
-
}, skip.id)), r.warnings.slice(0, 3).map(warning => /*#__PURE__*/_jsxs(Text, {
|
|
156
|
-
style: styles.outcomeDetail,
|
|
157
|
-
children: ["\u26A0 ", warning]
|
|
158
|
-
}, warning))]
|
|
159
|
-
}, sourceId))]
|
|
52
|
+
// The preview can't render without a built diff (clearPreview races a
|
|
53
|
+
// back-navigation) — fall through to the list rather than an empty shell.
|
|
54
|
+
if (screen.kind === "preview" && preview) return /*#__PURE__*/_jsx(PreviewScreen, {
|
|
55
|
+
preview: preview,
|
|
56
|
+
snapshots: snapshots,
|
|
57
|
+
busy: busy !== null,
|
|
58
|
+
onClose: backToList
|
|
59
|
+
});
|
|
60
|
+
return /*#__PURE__*/_jsx(RestorePointList, {
|
|
61
|
+
sources: sources,
|
|
62
|
+
onOpenPreview: meta => {
|
|
63
|
+
void timeMachineStore.buildPreview({
|
|
64
|
+
snapshotId: meta.id
|
|
65
|
+
});
|
|
66
|
+
setScreen({
|
|
67
|
+
kind: "preview"
|
|
68
|
+
});
|
|
69
|
+
}
|
|
160
70
|
});
|
|
161
71
|
}
|
|
162
|
-
|
|
72
|
+
function RestorePointList({
|
|
73
|
+
sources,
|
|
74
|
+
onOpenPreview
|
|
75
|
+
}) {
|
|
163
76
|
const {
|
|
164
77
|
snapshots,
|
|
165
78
|
hasLoaded,
|
|
166
79
|
busy,
|
|
167
80
|
lastOutcome,
|
|
168
|
-
|
|
169
|
-
remoteProviders,
|
|
170
|
-
remoteRoute
|
|
81
|
+
recentlyDeleted
|
|
171
82
|
} = useTimeMachineState();
|
|
172
|
-
const localProviders = useSnapshotProviders();
|
|
173
83
|
const isPro = useIsPro();
|
|
84
|
+
const snapshotLimit = useLimit("timeMachine.snapshots");
|
|
174
85
|
const host = useToolHost();
|
|
175
|
-
const
|
|
176
|
-
|
|
177
|
-
kind: "list"
|
|
86
|
+
const insets = useSafeAreaInsets({
|
|
87
|
+
minBottom: 16
|
|
178
88
|
});
|
|
179
|
-
const [picker, setPicker] = useState(null);
|
|
180
89
|
|
|
181
|
-
// Header search (when hosted by the core shell) filters the
|
|
182
|
-
const
|
|
183
|
-
const
|
|
90
|
+
// Header search (when hosted by the core shell) filters the list.
|
|
91
|
+
const query = host.search.trim().toLowerCase();
|
|
92
|
+
const visible = query ? snapshots.filter(s => s.name.toLowerCase().includes(query)) : snapshots;
|
|
184
93
|
|
|
185
|
-
//
|
|
186
|
-
|
|
187
|
-
const
|
|
188
|
-
id: p.id,
|
|
189
|
-
label: p.label,
|
|
190
|
-
...p.status()
|
|
191
|
-
}));
|
|
94
|
+
// Infinity for Pro, so this is simply false for them.
|
|
95
|
+
const atCaptureLimit = snapshots.length >= snapshotLimit;
|
|
96
|
+
const captureDisabled = busy !== null || atCaptureLimit;
|
|
192
97
|
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
// with the tool still open. Each restore point shows the route it holds.
|
|
206
|
-
detail: routeAvailable ? "recorded with every snapshot — restore can take you back" : "no Expo Router detected — snapshots record no route"
|
|
207
|
-
};
|
|
208
|
-
const sourceTiles = [...providers, routeSource];
|
|
209
|
-
const atFreeLimit = !isPro && snapshots.length >= FREE_SNAPSHOT_LIMIT;
|
|
210
|
-
const captureDisabled = busy !== null || atFreeLimit;
|
|
211
|
-
const capture = () => {
|
|
212
|
-
if (captureDisabled) return;
|
|
213
|
-
void timeMachineStore.capture(name);
|
|
214
|
-
setName("");
|
|
215
|
-
};
|
|
216
|
-
const restore = (meta, mode, excludeKeys) => {
|
|
98
|
+
/**
|
|
99
|
+
* Restoring is the last thing anyone wants from this screen, so the tool
|
|
100
|
+
* gets out of the way the moment it worked — with no toast and no banner.
|
|
101
|
+
* The restored app IS the confirmation, and anything announcing it is one
|
|
102
|
+
* more thing to dismiss on a flow people run dozens of times an hour.
|
|
103
|
+
*
|
|
104
|
+
* It MINIMIZES rather than closes: the list, the search and the screen you
|
|
105
|
+
* were on all survive, and coming back is one tap on the dock. A partial
|
|
106
|
+
* restore stays open instead, because the outcome card is the only place
|
|
107
|
+
* the per-source failures are reported.
|
|
108
|
+
*/
|
|
109
|
+
const restore = meta => {
|
|
217
110
|
if (busy) return;
|
|
218
111
|
if (meta.baseline) {
|
|
219
112
|
confirmDestructive("Restore fresh install?", "This wipes all app storage and reloads the app.", "Wipe & reload", () => void timeMachineStore.restore(meta.id, "reload"));
|
|
220
113
|
return;
|
|
221
114
|
}
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
115
|
+
void timeMachineStore.restore(meta.id, "live").then(outcome => {
|
|
116
|
+
const clean = Object.values(outcome.results).every(r => r.ok);
|
|
117
|
+
if (!clean || outcome.willReload) return;
|
|
118
|
+
host.minimize();
|
|
226
119
|
});
|
|
227
120
|
};
|
|
228
|
-
const remove = meta => {
|
|
229
|
-
confirmDestructive("Delete snapshot?", `“${meta.name}” cannot be recovered.`, "Delete", () => void timeMachineStore.delete(meta.id));
|
|
230
|
-
};
|
|
231
|
-
const wipeAll = () => {
|
|
232
|
-
if (busy) return;
|
|
233
|
-
confirmDestructive("Wipe all app state?", "This deletes all app storage and reloads the app — like a fresh install.", "Wipe & reload", () => void timeMachineStore.wipeAll());
|
|
234
|
-
};
|
|
235
|
-
const openPreview = meta => {
|
|
236
|
-
void timeMachineStore.buildPreview({
|
|
237
|
-
snapshotId: meta.id
|
|
238
|
-
});
|
|
239
|
-
setScreen({
|
|
240
|
-
kind: "preview"
|
|
241
|
-
});
|
|
242
|
-
};
|
|
243
|
-
const closePreview = () => {
|
|
244
|
-
timeMachineStore.clearPreview();
|
|
245
|
-
setScreen({
|
|
246
|
-
kind: "list"
|
|
247
|
-
});
|
|
248
|
-
};
|
|
249
|
-
|
|
250
|
-
// ── Preview / item screens ──
|
|
251
|
-
if (screen.kind === "item" && preview) {
|
|
252
|
-
return /*#__PURE__*/_jsx(ItemDetailScreen, {
|
|
253
|
-
sourceLabel: screen.sourceLabel,
|
|
254
|
-
item: screen.item,
|
|
255
|
-
leftLabel: preview.left === "current" ? "CURRENT" : snapshots.find(s => s.id === preview.left.snapshotId)?.name ?? "snapshot",
|
|
256
|
-
rightLabel: preview.right === "current" ? "CURRENT" : snapshots.find(s => s.id === preview.right.snapshotId)?.name ?? "snapshot",
|
|
257
|
-
onBack: () => setScreen({
|
|
258
|
-
kind: "preview"
|
|
259
|
-
})
|
|
260
|
-
});
|
|
261
|
-
}
|
|
262
|
-
if (screen.kind === "preview" && preview) {
|
|
263
|
-
const rightMeta = preview.right === "current" ? undefined : snapshots.find(s => s.id === preview.right.snapshotId);
|
|
264
|
-
const pickerItems = [];
|
|
265
|
-
if (picker) {
|
|
266
|
-
const otherRef = picker === "left" ? preview.right : preview.left;
|
|
267
|
-
const otherId = otherRef === "current" ? null : otherRef.snapshotId;
|
|
268
|
-
if (picker === "left") {
|
|
269
|
-
pickerItems.push({
|
|
270
|
-
index: 0,
|
|
271
|
-
label: "Current state",
|
|
272
|
-
timestamp: "live",
|
|
273
|
-
relativeTime: "now",
|
|
274
|
-
selected: preview.left === "current"
|
|
275
|
-
});
|
|
276
|
-
}
|
|
277
|
-
snapshots.forEach((s, i) => {
|
|
278
|
-
const ref = {
|
|
279
|
-
snapshotId: s.id
|
|
280
|
-
};
|
|
281
|
-
const current = picker === "left" ? preview.left : preview.right;
|
|
282
|
-
pickerItems.push({
|
|
283
|
-
index: picker === "left" ? i + 1 : i,
|
|
284
|
-
label: s.baseline ? `⌂ ${s.name}` : s.name,
|
|
285
|
-
timestamp: new Date(s.createdAt).toLocaleTimeString(),
|
|
286
|
-
relativeTime: timeAgo(s.createdAt),
|
|
287
|
-
disabled: s.id === otherId || picker === "right" && s.baseline,
|
|
288
|
-
selected: current !== "current" && current.snapshotId === s.id
|
|
289
|
-
});
|
|
290
|
-
});
|
|
291
|
-
}
|
|
292
|
-
const onPickerSelect = index => {
|
|
293
|
-
const side = picker;
|
|
294
|
-
setPicker(null);
|
|
295
|
-
if (!side) return;
|
|
296
|
-
let ref;
|
|
297
|
-
if (side === "left") {
|
|
298
|
-
ref = index === 0 ? "current" : {
|
|
299
|
-
snapshotId: snapshots[index - 1].id
|
|
300
|
-
};
|
|
301
|
-
void timeMachineStore.buildPreview(preview.right, ref);
|
|
302
|
-
} else {
|
|
303
|
-
ref = {
|
|
304
|
-
snapshotId: snapshots[index].id
|
|
305
|
-
};
|
|
306
|
-
void timeMachineStore.buildPreview(ref, preview.left);
|
|
307
|
-
}
|
|
308
|
-
};
|
|
309
|
-
return /*#__PURE__*/_jsxs(View, {
|
|
310
|
-
style: styles.screenFill,
|
|
311
|
-
children: [/*#__PURE__*/_jsx(RestorePreviewScreen, {
|
|
312
|
-
preview: preview,
|
|
313
|
-
snapshots: snapshots,
|
|
314
|
-
busy: busy !== null,
|
|
315
|
-
onBack: closePreview,
|
|
316
|
-
onOpenItem: (sourceId, item) => {
|
|
317
|
-
const source = preview.sources.find(s => s.id === sourceId);
|
|
318
|
-
setScreen({
|
|
319
|
-
kind: "item",
|
|
320
|
-
sourceId,
|
|
321
|
-
sourceLabel: source?.label ?? sourceId,
|
|
322
|
-
item
|
|
323
|
-
});
|
|
324
|
-
},
|
|
325
|
-
onRestore: (mode, excludeKeys) => {
|
|
326
|
-
if (!rightMeta || busy) return;
|
|
327
|
-
if (rightMeta.baseline) {
|
|
328
|
-
confirmDestructive("Restore fresh install?", "This wipes all app storage and reloads the app.", "Wipe & reload", () => void timeMachineStore.restore(rightMeta.id, "reload"));
|
|
329
|
-
return;
|
|
330
|
-
}
|
|
331
|
-
// Land back on the list, where the outcome panel reports the
|
|
332
|
-
// results — the preview's diff is stale the moment restore runs.
|
|
333
|
-
restoreWithRoutePrompt(rightMeta, restoreRoute => {
|
|
334
|
-
void timeMachineStore.restore(rightMeta.id, mode, excludeKeys, {
|
|
335
|
-
restoreRoute
|
|
336
|
-
}).then(() => closePreview());
|
|
337
|
-
});
|
|
338
|
-
},
|
|
339
|
-
onPickSide: setPicker,
|
|
340
|
-
onRefresh: () => void timeMachineStore.buildPreview(preview.right, preview.left)
|
|
341
|
-
}), picker && /*#__PURE__*/_jsx(EventPickerModal, {
|
|
342
|
-
isOpen: true,
|
|
343
|
-
onClose: () => setPicker(null),
|
|
344
|
-
title: picker === "left" ? "Compare from" : "Compare to",
|
|
345
|
-
position: picker,
|
|
346
|
-
items: pickerItems,
|
|
347
|
-
onSelect: onPickerSelect
|
|
348
|
-
})]
|
|
349
|
-
});
|
|
350
|
-
}
|
|
351
|
-
|
|
352
|
-
// ── List screen ──
|
|
353
|
-
const unavailable = sourceTiles.filter(p => p.detail && (!p.canCapture || !p.canRestore));
|
|
354
121
|
return /*#__PURE__*/_jsxs(ScrollView, {
|
|
355
|
-
style: styles.
|
|
356
|
-
contentContainerStyle: styles.
|
|
357
|
-
|
|
122
|
+
style: styles.fill,
|
|
123
|
+
contentContainerStyle: [styles.content, {
|
|
124
|
+
paddingBottom: insets.bottom
|
|
125
|
+
}],
|
|
126
|
+
children: [lastOutcome && restoreNeedsAttention(lastOutcome) ? /*#__PURE__*/_jsx(RestoreOutcomeCard, {
|
|
358
127
|
outcome: lastOutcome
|
|
359
|
-
}), /*#__PURE__*/
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
}), /*#__PURE__*/_jsx(TextInput, {
|
|
367
|
-
style: styles.captureInput,
|
|
368
|
-
value: name,
|
|
369
|
-
onChangeText: setName,
|
|
370
|
-
placeholder: "Name this restore point\u2026",
|
|
371
|
-
placeholderTextColor: buoyColors.textMuted,
|
|
372
|
-
editable: !captureDisabled,
|
|
373
|
-
onSubmitEditing: capture,
|
|
374
|
-
returnKeyType: "done",
|
|
375
|
-
testID: "time-machine-name-input"
|
|
376
|
-
})]
|
|
377
|
-
}), /*#__PURE__*/_jsx(TouchableOpacity, {
|
|
378
|
-
style: [styles.captureButton, captureDisabled && styles.buttonDisabled],
|
|
379
|
-
onPress: capture,
|
|
128
|
+
}) : null, recentlyDeleted ? /*#__PURE__*/_jsx(UndoDeleteBar, {
|
|
129
|
+
name: recentlyDeleted.stored.meta.name,
|
|
130
|
+
at: recentlyDeleted.at,
|
|
131
|
+
onUndo: () => void timeMachineStore.undoDelete(),
|
|
132
|
+
onExpire: () => timeMachineStore.clearRecentlyDeleted()
|
|
133
|
+
}) : null, /*#__PURE__*/_jsx(View, {
|
|
134
|
+
children: /*#__PURE__*/_jsx(CaptureBar, {
|
|
380
135
|
disabled: captureDisabled,
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
})
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
children: [
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
style: styles.providerDetail,
|
|
419
|
-
children: [p.label, ": ", p.detail]
|
|
420
|
-
}, p.id)), routeAvailable && /*#__PURE__*/_jsxs(Text, {
|
|
421
|
-
style: styles.providerDetail,
|
|
422
|
-
numberOfLines: 1,
|
|
423
|
-
children: [routeSource.label, ": ", routeSource.detail]
|
|
424
|
-
}), /*#__PURE__*/_jsx(Text, {
|
|
425
|
-
style: [styles.sectionTitle, styles.sectionSpacing],
|
|
426
|
-
children: "Restore points"
|
|
427
|
-
}), hasLoaded && snapshots.length === 0 && /*#__PURE__*/_jsx(Text, {
|
|
428
|
-
style: styles.emptyText,
|
|
429
|
-
children: "No restore points yet. Set up the state you want to return to, then capture it."
|
|
430
|
-
}), visibleSnapshots.map(meta => {
|
|
431
|
-
const warnings = warningCount(meta);
|
|
432
|
-
return /*#__PURE__*/_jsxs(TouchableOpacity, {
|
|
433
|
-
style: styles.snapshotCard,
|
|
434
|
-
onPress: () => openPreview(meta),
|
|
435
|
-
testID: `time-machine-snap-${meta.id}`,
|
|
436
|
-
children: [/*#__PURE__*/_jsx(View, {
|
|
437
|
-
style: styles.snapshotIconTile,
|
|
438
|
-
children: meta.baseline ? /*#__PURE__*/_jsx(Home, {
|
|
439
|
-
size: 17,
|
|
440
|
-
color: buoyColors.textSecondary
|
|
441
|
-
}) : /*#__PURE__*/_jsx(TimeMachineIcon, {
|
|
442
|
-
size: 18
|
|
443
|
-
})
|
|
444
|
-
}), /*#__PURE__*/_jsxs(View, {
|
|
445
|
-
style: styles.snapshotInfo,
|
|
446
|
-
children: [/*#__PURE__*/_jsx(Text, {
|
|
447
|
-
style: styles.snapshotName,
|
|
448
|
-
numberOfLines: 1,
|
|
449
|
-
children: meta.name
|
|
450
|
-
}), /*#__PURE__*/_jsxs(Text, {
|
|
451
|
-
style: styles.snapshotMeta,
|
|
452
|
-
numberOfLines: 1,
|
|
453
|
-
children: [meta.baseline ? "wipes to fresh install" : `${timeAgo(meta.createdAt)} · ${formatBytes(meta.sizeBytes)} · ${Object.keys(meta.sources).length} sources`, meta.scope?.length ? ` · scoped (${meta.scope.length})` : "", warnings > 0 ? ` · ⚠ ${warnings}` : ""]
|
|
454
|
-
}), !meta.baseline && meta.route && /*#__PURE__*/_jsxs(Text, {
|
|
455
|
-
style: styles.snapshotRoute,
|
|
456
|
-
numberOfLines: 1,
|
|
457
|
-
children: ["\u2316 ", meta.route.href]
|
|
458
|
-
})]
|
|
459
|
-
}), !meta.baseline ? /*#__PURE__*/_jsx(TouchableOpacity, {
|
|
460
|
-
style: [styles.rowAction, busy && styles.buttonDisabled],
|
|
461
|
-
onPress: () => restore(meta, "live"),
|
|
462
|
-
disabled: busy !== null,
|
|
463
|
-
accessibilityLabel: "Restore",
|
|
464
|
-
children: /*#__PURE__*/_jsx(Text, {
|
|
465
|
-
style: styles.rowActionLabel,
|
|
466
|
-
children: "RESTORE"
|
|
467
|
-
})
|
|
468
|
-
}) : /*#__PURE__*/_jsx(TouchableOpacity, {
|
|
469
|
-
style: [styles.rowAction, busy && styles.buttonDisabled],
|
|
470
|
-
onPress: () => restore(meta, "reload"),
|
|
471
|
-
disabled: busy !== null,
|
|
472
|
-
accessibilityLabel: "Wipe and reload",
|
|
473
|
-
children: /*#__PURE__*/_jsx(Text, {
|
|
474
|
-
style: styles.rowActionLabelDanger,
|
|
475
|
-
children: "WIPE"
|
|
476
|
-
})
|
|
477
|
-
}), /*#__PURE__*/_jsx(TouchableOpacity, {
|
|
478
|
-
style: styles.rowAction,
|
|
479
|
-
onPress: () => remove(meta),
|
|
480
|
-
hitSlop: {
|
|
481
|
-
top: 8,
|
|
482
|
-
bottom: 8,
|
|
483
|
-
left: 4,
|
|
484
|
-
right: 8
|
|
485
|
-
},
|
|
486
|
-
accessibilityLabel: "Delete",
|
|
487
|
-
children: /*#__PURE__*/_jsx(Trash2, {
|
|
488
|
-
size: 14,
|
|
489
|
-
color: buoyColors.error
|
|
490
|
-
})
|
|
491
|
-
})]
|
|
492
|
-
}, meta.id);
|
|
493
|
-
}), /*#__PURE__*/_jsxs(TouchableOpacity, {
|
|
494
|
-
style: [styles.wipeAllButton, busy && styles.buttonDisabled],
|
|
495
|
-
onPress: wipeAll,
|
|
496
|
-
disabled: busy !== null,
|
|
497
|
-
testID: "time-machine-wipe-all",
|
|
498
|
-
children: [/*#__PURE__*/_jsx(Trash2, {
|
|
499
|
-
size: 13,
|
|
500
|
-
color: buoyColors.error
|
|
501
|
-
}), /*#__PURE__*/_jsx(Text, {
|
|
502
|
-
style: styles.wipeAllText,
|
|
503
|
-
children: "Wipe all app state\u2026"
|
|
504
|
-
})]
|
|
505
|
-
}), /*#__PURE__*/_jsx(Text, {
|
|
506
|
-
style: styles.wipeAllCaption,
|
|
136
|
+
busy: busy === "capture",
|
|
137
|
+
onCapture: name => void timeMachineStore.capture(name)
|
|
138
|
+
})
|
|
139
|
+
}), atCaptureLimit ? /*#__PURE__*/_jsxs(Footnote, {
|
|
140
|
+
tone: "warning",
|
|
141
|
+
children: ["Free plan keeps ", snapshotLimit, " restore points. Upgrade to Pro for unlimited snapshots."]
|
|
142
|
+
}) : null, /*#__PURE__*/_jsx(SectionLabel, {
|
|
143
|
+
children: "Sources"
|
|
144
|
+
}), /*#__PURE__*/_jsx(SourcesStrip, {
|
|
145
|
+
sources: sources
|
|
146
|
+
}), sources.filter(s => s.detail && !(s.canCapture && s.canRestore)).map(s => /*#__PURE__*/_jsxs(Footnote, {
|
|
147
|
+
children: [s.label, ": ", s.detail]
|
|
148
|
+
}, s.id)), /*#__PURE__*/_jsx(SectionLabel, {
|
|
149
|
+
children: "Restore Points"
|
|
150
|
+
}), /*#__PURE__*/_jsxs(Group, {
|
|
151
|
+
children: [visible.map(meta => /*#__PURE__*/_jsx(SnapshotRow, {
|
|
152
|
+
meta: meta,
|
|
153
|
+
busy: busy !== null,
|
|
154
|
+
onOpen: () => onOpenPreview(meta),
|
|
155
|
+
onRestore: () => restore(meta),
|
|
156
|
+
onDelete: () => void timeMachineStore.delete(meta.id),
|
|
157
|
+
onDuplicate: () => void timeMachineStore.duplicate(meta.id)
|
|
158
|
+
}, meta.id)), visible.length === 0 ? /*#__PURE__*/_jsx(Text, {
|
|
159
|
+
style: styles.empty,
|
|
160
|
+
children: !hasLoaded ? "Loading restore points…" : snapshots.length > 0 ? "No restore point matches that name." : "Set up the state you want to come back to, then capture it."
|
|
161
|
+
}) : null]
|
|
162
|
+
}), visible.length > 0 ? /*#__PURE__*/_jsx(Footnote, {
|
|
163
|
+
children: "Swipe a restore point to rename, copy or delete it."
|
|
164
|
+
}) : null, /*#__PURE__*/_jsx(View, {
|
|
165
|
+
style: styles.spacer
|
|
166
|
+
}), /*#__PURE__*/_jsx(Group, {
|
|
167
|
+
children: /*#__PURE__*/_jsx(WipeAllRow, {
|
|
168
|
+
disabled: busy !== null,
|
|
169
|
+
onWipe: () => confirmDestructive("Wipe all app state?", "This deletes all app storage and reloads the app — like a fresh install.", "Wipe & reload", () => void timeMachineStore.wipeAll())
|
|
170
|
+
})
|
|
171
|
+
}), /*#__PURE__*/_jsx(Footnote, {
|
|
172
|
+
centered: true,
|
|
507
173
|
children: "Deletes all app storage and reloads \u2014 like a fresh install."
|
|
508
174
|
})]
|
|
509
175
|
});
|
|
510
176
|
}
|
|
511
177
|
const styles = StyleSheet.create({
|
|
512
|
-
|
|
513
|
-
flex: 1
|
|
514
|
-
},
|
|
515
|
-
container: {
|
|
516
|
-
padding: 12,
|
|
517
|
-
gap: 8
|
|
518
|
-
},
|
|
519
|
-
captureCard: {
|
|
520
|
-
flexDirection: "row",
|
|
521
|
-
alignItems: "center",
|
|
522
|
-
gap: 8
|
|
523
|
-
},
|
|
524
|
-
captureField: {
|
|
178
|
+
fill: {
|
|
525
179
|
flex: 1,
|
|
526
|
-
|
|
527
|
-
alignItems: "center",
|
|
528
|
-
gap: 8,
|
|
529
|
-
backgroundColor: buoyColors.card,
|
|
530
|
-
borderColor: buoyColors.border,
|
|
531
|
-
borderWidth: 1,
|
|
532
|
-
borderRadius: 10,
|
|
533
|
-
paddingHorizontal: 10
|
|
534
|
-
},
|
|
535
|
-
captureInput: {
|
|
536
|
-
flex: 1,
|
|
537
|
-
color: buoyColors.text,
|
|
538
|
-
fontSize: 13,
|
|
539
|
-
paddingVertical: 9
|
|
540
|
-
},
|
|
541
|
-
captureButton: {
|
|
542
|
-
backgroundColor: buoyColors.primary,
|
|
543
|
-
borderRadius: 10,
|
|
544
|
-
paddingHorizontal: 16,
|
|
545
|
-
paddingVertical: 10,
|
|
546
|
-
justifyContent: "center"
|
|
547
|
-
},
|
|
548
|
-
captureButtonText: {
|
|
549
|
-
color: "#0A0A0A",
|
|
550
|
-
fontSize: 12,
|
|
551
|
-
fontWeight: "700",
|
|
552
|
-
letterSpacing: 0.5
|
|
553
|
-
},
|
|
554
|
-
buttonDisabled: {
|
|
555
|
-
opacity: 0.4
|
|
556
|
-
},
|
|
557
|
-
freeLimitNote: {
|
|
558
|
-
color: buoyColors.warning,
|
|
559
|
-
fontSize: 11
|
|
560
|
-
},
|
|
561
|
-
sectionRow: {
|
|
562
|
-
flexDirection: "row",
|
|
563
|
-
alignItems: "center",
|
|
564
|
-
justifyContent: "space-between",
|
|
565
|
-
marginTop: 12,
|
|
566
|
-
gap: 10
|
|
567
|
-
},
|
|
568
|
-
sectionTitle: {
|
|
569
|
-
color: buoyColors.text,
|
|
570
|
-
fontSize: 14,
|
|
571
|
-
fontWeight: "700"
|
|
572
|
-
},
|
|
573
|
-
sectionSpacing: {
|
|
574
|
-
marginTop: 14
|
|
575
|
-
},
|
|
576
|
-
sourceTiles: {
|
|
577
|
-
flexDirection: "row",
|
|
578
|
-
gap: 6,
|
|
579
|
-
flexWrap: "wrap",
|
|
580
|
-
justifyContent: "flex-end",
|
|
581
|
-
flex: 1
|
|
582
|
-
},
|
|
583
|
-
sourceTile: {
|
|
584
|
-
width: 32,
|
|
585
|
-
height: 32,
|
|
586
|
-
borderRadius: 9,
|
|
587
|
-
backgroundColor: buoyColors.card,
|
|
588
|
-
borderColor: buoyColors.border,
|
|
589
|
-
borderWidth: 1,
|
|
590
|
-
alignItems: "center",
|
|
591
|
-
justifyContent: "center"
|
|
592
|
-
},
|
|
593
|
-
sourceTileDot: {
|
|
594
|
-
position: "absolute",
|
|
595
|
-
top: 3,
|
|
596
|
-
right: 3,
|
|
597
|
-
width: 6,
|
|
598
|
-
height: 6,
|
|
599
|
-
borderRadius: 3
|
|
600
|
-
},
|
|
601
|
-
providerDetail: {
|
|
602
|
-
color: buoyColors.textMuted,
|
|
603
|
-
fontSize: 10,
|
|
604
|
-
marginTop: 4
|
|
605
|
-
},
|
|
606
|
-
emptyText: {
|
|
607
|
-
color: buoyColors.textMuted,
|
|
608
|
-
fontSize: 12,
|
|
609
|
-
marginTop: 8
|
|
610
|
-
},
|
|
611
|
-
snapshotCard: {
|
|
612
|
-
flexDirection: "row",
|
|
613
|
-
alignItems: "center",
|
|
614
|
-
backgroundColor: buoyColors.card,
|
|
615
|
-
borderColor: buoyColors.border,
|
|
616
|
-
borderWidth: 1,
|
|
617
|
-
borderRadius: 12,
|
|
618
|
-
paddingHorizontal: 12,
|
|
619
|
-
paddingVertical: 10,
|
|
620
|
-
marginTop: 8,
|
|
621
|
-
gap: 10
|
|
622
|
-
},
|
|
623
|
-
snapshotIconTile: {
|
|
624
|
-
width: 36,
|
|
625
|
-
height: 36,
|
|
626
|
-
borderRadius: 10,
|
|
627
|
-
backgroundColor: buoyColors.hover,
|
|
628
|
-
alignItems: "center",
|
|
629
|
-
justifyContent: "center"
|
|
630
|
-
},
|
|
631
|
-
snapshotInfo: {
|
|
632
|
-
flex: 1,
|
|
633
|
-
minWidth: 0,
|
|
634
|
-
gap: 2
|
|
635
|
-
},
|
|
636
|
-
snapshotName: {
|
|
637
|
-
color: buoyColors.text,
|
|
638
|
-
fontSize: 14,
|
|
639
|
-
fontWeight: "700"
|
|
640
|
-
},
|
|
641
|
-
snapshotMeta: {
|
|
642
|
-
color: buoyColors.textMuted,
|
|
643
|
-
fontSize: 10,
|
|
644
|
-
fontVariant: ["tabular-nums"]
|
|
645
|
-
},
|
|
646
|
-
snapshotRoute: {
|
|
647
|
-
color: buoyColors.textSecondary,
|
|
648
|
-
fontSize: 10
|
|
649
|
-
},
|
|
650
|
-
rowAction: {
|
|
651
|
-
padding: 4,
|
|
652
|
-
justifyContent: "center",
|
|
653
|
-
alignItems: "center"
|
|
654
|
-
},
|
|
655
|
-
rowActionLabel: {
|
|
656
|
-
color: buoyColors.primary,
|
|
657
|
-
fontSize: 12,
|
|
658
|
-
fontWeight: "600"
|
|
659
|
-
},
|
|
660
|
-
rowActionLabelDanger: {
|
|
661
|
-
color: buoyColors.error,
|
|
662
|
-
fontSize: 12,
|
|
663
|
-
fontWeight: "600"
|
|
664
|
-
},
|
|
665
|
-
wipeAllButton: {
|
|
666
|
-
flexDirection: "row",
|
|
667
|
-
alignItems: "center",
|
|
668
|
-
justifyContent: "center",
|
|
669
|
-
gap: 7,
|
|
670
|
-
borderColor: `${buoyColors.error}55`,
|
|
671
|
-
borderWidth: 1,
|
|
672
|
-
borderRadius: 10,
|
|
673
|
-
paddingVertical: 10,
|
|
674
|
-
marginTop: 18
|
|
675
|
-
},
|
|
676
|
-
wipeAllText: {
|
|
677
|
-
color: buoyColors.error,
|
|
678
|
-
fontSize: 12.5,
|
|
679
|
-
fontWeight: "600"
|
|
680
|
-
},
|
|
681
|
-
wipeAllCaption: {
|
|
682
|
-
color: buoyColors.textMuted,
|
|
683
|
-
fontSize: 10,
|
|
684
|
-
textAlign: "center",
|
|
685
|
-
marginTop: 6
|
|
686
|
-
},
|
|
687
|
-
outcomePanel: {
|
|
688
|
-
backgroundColor: buoyColors.card,
|
|
689
|
-
borderColor: buoyColors.borderStrong,
|
|
690
|
-
borderWidth: 1,
|
|
691
|
-
borderRadius: 8,
|
|
692
|
-
padding: 10,
|
|
693
|
-
gap: 4
|
|
694
|
-
},
|
|
695
|
-
outcomeHeaderRow: {
|
|
696
|
-
flexDirection: "row",
|
|
697
|
-
justifyContent: "space-between",
|
|
698
|
-
alignItems: "center"
|
|
699
|
-
},
|
|
700
|
-
outcomeTitle: {
|
|
701
|
-
color: buoyColors.text,
|
|
702
|
-
fontSize: 12,
|
|
703
|
-
fontWeight: "700",
|
|
704
|
-
flex: 1
|
|
705
|
-
},
|
|
706
|
-
outcomeDismiss: {
|
|
707
|
-
color: buoyColors.textMuted,
|
|
708
|
-
fontSize: 13
|
|
709
|
-
},
|
|
710
|
-
outcomeSource: {
|
|
711
|
-
gap: 2
|
|
180
|
+
backgroundColor: tm.color.sheet
|
|
712
181
|
},
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
fontSize: 11
|
|
182
|
+
content: {
|
|
183
|
+
paddingTop: 14
|
|
716
184
|
},
|
|
717
|
-
|
|
718
|
-
color:
|
|
185
|
+
empty: {
|
|
186
|
+
color: tm.color.labelSecondary,
|
|
187
|
+
fontSize: tm.font.footnote,
|
|
188
|
+
lineHeight: tm.font.footnote * 1.4,
|
|
189
|
+
paddingHorizontal: tm.textInset,
|
|
190
|
+
paddingVertical: 16
|
|
719
191
|
},
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
fontSize: 10,
|
|
723
|
-
paddingLeft: 12
|
|
192
|
+
spacer: {
|
|
193
|
+
height: 24
|
|
724
194
|
}
|
|
725
195
|
});
|
|
726
196
|
//# sourceMappingURL=TimeMachineBody.js.map
|