@buoy-gg/time-machine 7.0.36 → 7.0.38
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 +40 -35
- package/lib/commonjs/components/HeaderActions.js +91 -0
- package/lib/commonjs/components/HeaderReloadButton.js +22 -25
- package/lib/commonjs/components/TimeMachineBody.js +68 -13
- package/lib/commonjs/components/floating/NamePromptModal.js +193 -0
- package/lib/commonjs/components/floating/TimeMachineFloatingTool.js +715 -0
- package/lib/commonjs/components/floating/armedPoint.js +92 -0
- package/lib/commonjs/components/floating/barSettings.js +66 -0
- package/lib/commonjs/components/list/CaptureBar.js +2 -0
- package/lib/commonjs/components/list/RestoreOutcomeCard.js +2 -0
- package/lib/commonjs/components/list/SnapshotRow.js +37 -13
- package/lib/commonjs/components/list/SourcesStrip.js +127 -83
- package/lib/commonjs/components/list/UndoDeleteBar.js +3 -1
- package/lib/commonjs/components/preview/RestorePreviewScreen.js +7 -2
- package/lib/commonjs/components/sources.js +19 -8
- package/lib/commonjs/index.js +42 -0
- package/lib/commonjs/preset.js +6 -4
- package/lib/commonjs/store/sourceIds.js +9 -0
- package/lib/commonjs/store/sourceSettings.js +79 -0
- package/lib/commonjs/store/timeMachineStore.js +75 -10
- package/lib/commonjs/sync/timeMachineSyncAdapter.js +5 -1
- package/lib/commonjs/ui/SwipeActionsRow.js +14 -3
- package/lib/commonjs/ui/primitives.js +2 -0
- package/lib/commonjs/ui/tmTheme.js +18 -5
- package/lib/module/components/HeaderActions.js +85 -0
- package/lib/module/components/HeaderReloadButton.js +24 -27
- package/lib/module/components/TimeMachineBody.js +71 -16
- package/lib/module/components/floating/NamePromptModal.js +188 -0
- package/lib/module/components/floating/TimeMachineFloatingTool.js +708 -0
- package/lib/module/components/floating/armedPoint.js +82 -0
- package/lib/module/components/floating/barSettings.js +57 -0
- package/lib/module/components/list/CaptureBar.js +2 -0
- package/lib/module/components/list/RestoreOutcomeCard.js +2 -0
- package/lib/module/components/list/SnapshotRow.js +37 -13
- package/lib/module/components/list/SourcesStrip.js +130 -84
- package/lib/module/components/list/UndoDeleteBar.js +3 -1
- package/lib/module/components/preview/RestorePreviewScreen.js +7 -2
- package/lib/module/components/sources.js +13 -6
- package/lib/module/index.js +7 -1
- package/lib/module/preset.js +6 -4
- package/lib/module/store/sourceIds.js +5 -0
- package/lib/module/store/sourceSettings.js +69 -0
- package/lib/module/store/timeMachineStore.js +74 -9
- package/lib/module/sync/timeMachineSyncAdapter.js +5 -1
- package/lib/module/ui/SwipeActionsRow.js +14 -3
- package/lib/module/ui/primitives.js +2 -0
- package/lib/module/ui/tmTheme.js +18 -5
- package/lib/typescript/components/HeaderActions.d.ts +7 -0
- package/lib/typescript/components/floating/NamePromptModal.d.ts +9 -0
- package/lib/typescript/components/floating/TimeMachineFloatingTool.d.ts +6 -0
- package/lib/typescript/components/floating/armedPoint.d.ts +14 -0
- package/lib/typescript/components/floating/barSettings.d.ts +7 -0
- package/lib/typescript/components/list/SnapshotRow.d.ts +5 -1
- package/lib/typescript/components/list/SourcesStrip.d.ts +3 -1
- package/lib/typescript/components/sources.d.ts +7 -2
- package/lib/typescript/index.d.ts +3 -1
- package/lib/typescript/preset.d.ts +4 -2
- package/lib/typescript/store/snapshotVault.d.ts +6 -0
- package/lib/typescript/store/sourceIds.d.ts +3 -0
- package/lib/typescript/store/sourceSettings.d.ts +9 -0
- package/lib/typescript/store/timeMachineStore.d.ts +16 -1
- package/lib/typescript/sync/timeMachineSyncAdapter.d.ts +4 -0
- package/lib/typescript/ui/tmTheme.d.ts +17 -4
- package/package.json +10 -7
- 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/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/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/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/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/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/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/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/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
|
@@ -0,0 +1,715 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.TIME_MACHINE_FLOATING_TOOL_ID = void 0;
|
|
7
|
+
exports.TimeMachineFloatingTool = TimeMachineFloatingTool;
|
|
8
|
+
exports.openTimeMachineFloatingTool = openTimeMachineFloatingTool;
|
|
9
|
+
var _react = require("react");
|
|
10
|
+
var _reactNative = require("react-native");
|
|
11
|
+
var _sharedUi = require("@buoy-gg/shared-ui");
|
|
12
|
+
var _useTimeMachine = require("../../hooks/useTimeMachine");
|
|
13
|
+
var _timeMachineStore = require("../../store/timeMachineStore");
|
|
14
|
+
var _routeRestore = require("../../store/routeRestore");
|
|
15
|
+
var _sourceSettings = require("../../store/sourceSettings");
|
|
16
|
+
var _RestoreOutcomeCard = require("../list/RestoreOutcomeCard");
|
|
17
|
+
var _format = require("../format");
|
|
18
|
+
var _armedPoint = require("./armedPoint");
|
|
19
|
+
var _NamePromptModal = require("./NamePromptModal");
|
|
20
|
+
var _barSettings = require("./barSettings");
|
|
21
|
+
var _jsxRuntime = require("react/jsx-runtime");
|
|
22
|
+
/**
|
|
23
|
+
* The restore bar: a floating strip that stays over the app with one restore
|
|
24
|
+
* point armed, so "go back to A" is one tap instead of dial → tool → RESTORE.
|
|
25
|
+
*
|
|
26
|
+
* Same shell and shape as Network's throttling strip. Left to right: a
|
|
27
|
+
* "Restore" button, the armed point's name over a status line (the drag
|
|
28
|
+
* surface), a chevron for the picker, a capture button, and ×. Close only
|
|
29
|
+
* dismisses; an armed point is not a running effect, so there is nothing to
|
|
30
|
+
* switch off.
|
|
31
|
+
*
|
|
32
|
+
* Safety: every restore from here first writes the rolling "Before last
|
|
33
|
+
* restore" snapshot, and the status line offers Undo for ten seconds. A
|
|
34
|
+
* control meant to be tapped without looking has to be safe to mis-tap.
|
|
35
|
+
*
|
|
36
|
+
* Feedback follows the list's rule: a clean restore gets no toast, because
|
|
37
|
+
* the restored app is the confirmation. The button flashes a check so a tap
|
|
38
|
+
* on an already-matching screen still visibly did something. Only a partial
|
|
39
|
+
* restore, an error, or the tier cap opens the accessory panel under the
|
|
40
|
+
* strip.
|
|
41
|
+
*/
|
|
42
|
+
|
|
43
|
+
const TIME_MACHINE_FLOATING_TOOL_ID = exports.TIME_MACHINE_FLOATING_TOOL_ID = "time-machine-restore";
|
|
44
|
+
|
|
45
|
+
/** How long "just now" and Undo stay on offer. */
|
|
46
|
+
const RECENT_MS = 10_000;
|
|
47
|
+
const FLASH_MS = 900;
|
|
48
|
+
const PICKER_ROWS = 6;
|
|
49
|
+
const registration = {
|
|
50
|
+
id: TIME_MACHINE_FLOATING_TOOL_ID,
|
|
51
|
+
render: context => /*#__PURE__*/(0, _jsxRuntime.jsx)(TimeMachineFloatingTool, {
|
|
52
|
+
...context
|
|
53
|
+
})
|
|
54
|
+
};
|
|
55
|
+
|
|
56
|
+
// Restore an open bar on the next boot. Dev bundles on a real RN runtime
|
|
57
|
+
// only: a production build must never re-open a devtool at launch, and the
|
|
58
|
+
// desktop dashboard and web mirrors host this module without a device.
|
|
59
|
+
if (typeof __DEV__ !== "undefined" && __DEV__ && typeof navigator !== "undefined" && navigator.product === "ReactNative") {
|
|
60
|
+
(0, _sharedUi.registerPersistentFloatingTool)(registration, _sharedUi.persistentStorage);
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/** Open (or reveal) the restore bar, optionally arming a specific point. */
|
|
64
|
+
function openTimeMachineFloatingTool(armId) {
|
|
65
|
+
if (armId) (0, _armedPoint.setPickedPointId)(armId);
|
|
66
|
+
(0, _sharedUi.openFloatingTool)(registration);
|
|
67
|
+
}
|
|
68
|
+
/** "3 of 5 sources failed", counting the route leg when it was asked for. */
|
|
69
|
+
function failureSummary(outcome) {
|
|
70
|
+
const results = Object.values(outcome.results);
|
|
71
|
+
const failed = results.filter(r => !r.ok || r.skipped.length > 0).length;
|
|
72
|
+
const total = results.length;
|
|
73
|
+
const route = outcome.route;
|
|
74
|
+
const routeFailed = route?.status === "failed" || route?.status === "unavailable";
|
|
75
|
+
if (failed === 0 && routeFailed) return "Route did not restore";
|
|
76
|
+
return `${failed} of ${total} source${total === 1 ? "" : "s"} failed`;
|
|
77
|
+
}
|
|
78
|
+
function failureLines(outcome) {
|
|
79
|
+
const lines = [];
|
|
80
|
+
for (const [id, r] of Object.entries(outcome.results)) {
|
|
81
|
+
if (r.ok && r.skipped.length === 0) continue;
|
|
82
|
+
const reason = r.skipped[0]?.reason ?? r.warnings[0] ?? "did not apply";
|
|
83
|
+
lines.push(`${id}: ${reason}`);
|
|
84
|
+
}
|
|
85
|
+
const route = outcome.route;
|
|
86
|
+
if (route?.status === "failed" || route?.status === "unavailable") lines.push(`route: ${route.status}`);
|
|
87
|
+
return lines;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
/** A short-lived flag: set it, and it clears itself after `ms`. */
|
|
91
|
+
function useFlash(ms) {
|
|
92
|
+
const [token, setToken] = (0, _react.useState)(0);
|
|
93
|
+
(0, _react.useEffect)(() => {
|
|
94
|
+
if (!token) return;
|
|
95
|
+
const timer = setTimeout(() => setToken(0), ms);
|
|
96
|
+
return () => clearTimeout(timer);
|
|
97
|
+
}, [token, ms]);
|
|
98
|
+
return [token > 0, () => setToken(n => n + 1)];
|
|
99
|
+
}
|
|
100
|
+
function TimeMachineFloatingTool({
|
|
101
|
+
id,
|
|
102
|
+
revealToken,
|
|
103
|
+
dismiss
|
|
104
|
+
}) {
|
|
105
|
+
const {
|
|
106
|
+
snapshots,
|
|
107
|
+
hasLoaded,
|
|
108
|
+
busy
|
|
109
|
+
} = (0, _useTimeMachine.useTimeMachineState)();
|
|
110
|
+
const providers = (0, _useTimeMachine.useSnapshotProviders)();
|
|
111
|
+
const pickedId = (0, _react.useSyncExternalStore)(_armedPoint.subscribePickedPoint, _armedPoint.getPickedPointId, _armedPoint.getPickedPointId);
|
|
112
|
+
const snapshotLimit = (0, _sharedUi.useLimit)("timeMachine.snapshots");
|
|
113
|
+
const reloadMode = (0, _react.useSyncExternalStore)(_barSettings.subscribeBarSettings, _barSettings.getBarReloadMode, _barSettings.getBarReloadMode);
|
|
114
|
+
const {
|
|
115
|
+
width
|
|
116
|
+
} = (0, _reactNative.useWindowDimensions)();
|
|
117
|
+
const [panel, setPanel] = (0, _react.useState)(null);
|
|
118
|
+
const [failed, setFailed] = (0, _react.useState)(null);
|
|
119
|
+
const [error, setError] = (0, _react.useState)();
|
|
120
|
+
const [naming, setNaming] = (0, _react.useState)(false);
|
|
121
|
+
const [restoredFlash, flashRestored] = useFlash(FLASH_MS);
|
|
122
|
+
const [capturedFlash, flashCaptured] = useFlash(FLASH_MS);
|
|
123
|
+
// The way back after a bar restore: the safety snapshot's id, for a while.
|
|
124
|
+
const [undo, setUndo] = (0, _react.useState)(null);
|
|
125
|
+
const [undoneAt, setUndoneAt] = (0, _react.useState)(null);
|
|
126
|
+
// Re-render on a slow clock so "just now" and "restored 5s ago" move on.
|
|
127
|
+
const [, setTick] = (0, _react.useState)(0);
|
|
128
|
+
const mounted = (0, _react.useRef)(true);
|
|
129
|
+
(0, _react.useEffect)(() => {
|
|
130
|
+
mounted.current = true;
|
|
131
|
+
void (0, _armedPoint.ensurePickedPointLoaded)();
|
|
132
|
+
void (0, _barSettings.ensureBarSettingsLoaded)();
|
|
133
|
+
void _timeMachineStore.timeMachineStore.ensureLoaded();
|
|
134
|
+
return () => {
|
|
135
|
+
mounted.current = false;
|
|
136
|
+
};
|
|
137
|
+
}, []);
|
|
138
|
+
const armed = (0, _armedPoint.resolveArmedPoint)(snapshots, pickedId);
|
|
139
|
+
const armedId = armed?.id;
|
|
140
|
+
const lastRestoredAt = armed?.lastRestoredAt;
|
|
141
|
+
const createdAt = armed?.createdAt;
|
|
142
|
+
(0, _react.useEffect)(() => {
|
|
143
|
+
if (lastRestoredAt === undefined && createdAt === undefined && !undo && undoneAt === null) return;
|
|
144
|
+
const timer = setInterval(() => setTick(n => n + 1), 2_500);
|
|
145
|
+
return () => clearInterval(timer);
|
|
146
|
+
}, [lastRestoredAt, createdAt, undo, undoneAt]);
|
|
147
|
+
|
|
148
|
+
// A failure belongs to the point it happened on; arming another clears it.
|
|
149
|
+
(0, _react.useEffect)(() => {
|
|
150
|
+
if (failed && failed.snapshotId !== armedId) {
|
|
151
|
+
setFailed(null);
|
|
152
|
+
setPanel(p => p === "outcome" ? null : p);
|
|
153
|
+
}
|
|
154
|
+
}, [armedId, failed]);
|
|
155
|
+
const now = Date.now();
|
|
156
|
+
const undoAvailable = undo !== null && now - undo.at < RECENT_MS && snapshots.some(meta => meta.id === undo.id);
|
|
157
|
+
// The tier cap counts the points you chose to keep, not the safety slot.
|
|
158
|
+
const kept = snapshots.filter(meta => !meta.safety);
|
|
159
|
+
const atCaptureLimit = kept.length >= snapshotLimit;
|
|
160
|
+
const restoreDisabled = !armed || busy !== null;
|
|
161
|
+
const captureDisabled = busy !== null;
|
|
162
|
+
const runRestore = async (targetId, options) => {
|
|
163
|
+
if (busy) return;
|
|
164
|
+
setPanel(null);
|
|
165
|
+
setError(undefined);
|
|
166
|
+
try {
|
|
167
|
+
const outcome = await _timeMachineStore.timeMachineStore.restore(targetId,
|
|
168
|
+
// Reload mode restores storage, parks the route for the next boot
|
|
169
|
+
// and reloads: the only way to reach screens that read storage once.
|
|
170
|
+
reloadMode && options.safetyCapture ? "reload" : "live", undefined, options);
|
|
171
|
+
if (!mounted.current) return;
|
|
172
|
+
if ((0, _RestoreOutcomeCard.restoreNeedsAttention)(outcome)) {
|
|
173
|
+
setFailed(outcome);
|
|
174
|
+
setPanel("outcome");
|
|
175
|
+
} else {
|
|
176
|
+
setFailed(null);
|
|
177
|
+
flashRestored();
|
|
178
|
+
}
|
|
179
|
+
setUndo(outcome.safetySnapshotId ? {
|
|
180
|
+
id: outcome.safetySnapshotId,
|
|
181
|
+
at: Date.now()
|
|
182
|
+
} : null);
|
|
183
|
+
if (outcome.safetySnapshotId) setUndoneAt(null);
|
|
184
|
+
} catch (failure) {
|
|
185
|
+
if (!mounted.current) return;
|
|
186
|
+
setError(failure instanceof Error ? failure.message : String(failure));
|
|
187
|
+
setPanel("error");
|
|
188
|
+
}
|
|
189
|
+
};
|
|
190
|
+
|
|
191
|
+
/** Tap: the point's own route setting applies. Long-press: state only. */
|
|
192
|
+
const restore = (stateOnly = false) => {
|
|
193
|
+
if (!armed) return;
|
|
194
|
+
void runRestore(armed.id, {
|
|
195
|
+
safetyCapture: true,
|
|
196
|
+
...(stateOnly ? {
|
|
197
|
+
restoreRoute: false
|
|
198
|
+
} : {})
|
|
199
|
+
});
|
|
200
|
+
};
|
|
201
|
+
const undoRestore = () => {
|
|
202
|
+
if (!undo) return;
|
|
203
|
+
// Back to where the app was, state only: you have not moved since.
|
|
204
|
+
void runRestore(undo.id, {
|
|
205
|
+
safetyCapture: false,
|
|
206
|
+
restoreRoute: false
|
|
207
|
+
}).then(() => {
|
|
208
|
+
if (mounted.current) setUndoneAt(Date.now());
|
|
209
|
+
});
|
|
210
|
+
};
|
|
211
|
+
|
|
212
|
+
// `+` asks for a name first, in a dialog over the app. An empty name
|
|
213
|
+
// keeps the default (screen and clock).
|
|
214
|
+
const askForName = () => {
|
|
215
|
+
if (busy) return;
|
|
216
|
+
setError(undefined);
|
|
217
|
+
if (atCaptureLimit) {
|
|
218
|
+
setPanel("cap");
|
|
219
|
+
return;
|
|
220
|
+
}
|
|
221
|
+
setPanel(null);
|
|
222
|
+
setNaming(true);
|
|
223
|
+
};
|
|
224
|
+
const capture = async typed => {
|
|
225
|
+
setNaming(false);
|
|
226
|
+
if (busy) return;
|
|
227
|
+
try {
|
|
228
|
+
const meta = await _timeMachineStore.timeMachineStore.capture(typed);
|
|
229
|
+
if (!mounted.current) return;
|
|
230
|
+
// Captured from the bar means "loop back to here": arm it.
|
|
231
|
+
(0, _armedPoint.setPickedPointId)(meta.id);
|
|
232
|
+
setUndo(null);
|
|
233
|
+
flashCaptured();
|
|
234
|
+
} catch (failure) {
|
|
235
|
+
if (!mounted.current) return;
|
|
236
|
+
setError(failure instanceof Error ? failure.message : String(failure));
|
|
237
|
+
setPanel("error");
|
|
238
|
+
}
|
|
239
|
+
};
|
|
240
|
+
const pick = meta => {
|
|
241
|
+
(0, _armedPoint.setPickedPointId)(meta.id);
|
|
242
|
+
setPanel(null);
|
|
243
|
+
};
|
|
244
|
+
const name = armed?.name ?? (hasLoaded ? "No restore points" : "Loading…");
|
|
245
|
+
let status;
|
|
246
|
+
let statusTone = "normal";
|
|
247
|
+
let idle = false;
|
|
248
|
+
if (busy === "restore") status = "Restoring…";else if (busy === "capture") status = "Capturing…";else if (error) {
|
|
249
|
+
status = error;
|
|
250
|
+
statusTone = "danger";
|
|
251
|
+
} else if (failed && armed && failed.snapshotId === armed.id) {
|
|
252
|
+
status = failureSummary(failed);
|
|
253
|
+
statusTone = "danger";
|
|
254
|
+
} else if (!armed) status = hasLoaded ? "Capture one with +" : "";else {
|
|
255
|
+
idle = true;
|
|
256
|
+
const restoredAgo = armed.lastRestoredAt === undefined ? null : now - armed.lastRestoredAt;
|
|
257
|
+
const capturedAgo = now - armed.createdAt;
|
|
258
|
+
if (undoneAt !== null && now - undoneAt < RECENT_MS) status = "undone, state only";else if (restoredAgo !== null && restoredAgo < RECENT_MS) status = "restored just now";else if (capturedAgo < RECENT_MS && restoredAgo === null) status = "captured just now";else if (armed.lastRestoredAt !== undefined) status = `restored ${(0, _format.timeAgo)(armed.lastRestoredAt)}`;else status = `${Object.keys(armed.sources).length} sources`;
|
|
259
|
+
if (reloadMode) status += " · reloads";
|
|
260
|
+
}
|
|
261
|
+
// Say where a restore will take you before it does.
|
|
262
|
+
const destination = idle && !undoAvailable && armed && armed.route && (0, _timeMachineStore.willRestoreRoute)(armed) ? armed.route.pathname : null;
|
|
263
|
+
const pickable = snapshots.filter(meta => !meta.baseline && !meta.safety);
|
|
264
|
+
const captureSummary = (() => {
|
|
265
|
+
const count = providers.filter(p => p.status().canCapture && (0, _sourceSettings.isSourceEnabled)(p.id)).length;
|
|
266
|
+
const route = (0, _routeRestore.captureCurrentRoute)();
|
|
267
|
+
const parts = [`${count} source${count === 1 ? "" : "s"}`];
|
|
268
|
+
if (route) parts.push(route.pathname);
|
|
269
|
+
return parts.join(" · ");
|
|
270
|
+
})();
|
|
271
|
+
let accessory;
|
|
272
|
+
if (panel === "picker") {
|
|
273
|
+
accessory = /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
|
|
274
|
+
style: styles.menu,
|
|
275
|
+
testID: "time-machine-bar-picker",
|
|
276
|
+
children: [/*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.ScrollView, {
|
|
277
|
+
style: styles.pickerList,
|
|
278
|
+
bounces: false,
|
|
279
|
+
children: [pickable.map(meta => {
|
|
280
|
+
const isArmed = meta.id === armed?.id;
|
|
281
|
+
return /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.TouchableOpacity, {
|
|
282
|
+
testID: `time-machine-bar-pick-${meta.id}`,
|
|
283
|
+
accessibilityRole: "button",
|
|
284
|
+
accessibilityState: {
|
|
285
|
+
selected: isArmed
|
|
286
|
+
},
|
|
287
|
+
accessibilityLabel: `Arm ${meta.name}`,
|
|
288
|
+
onPress: () => pick(meta),
|
|
289
|
+
style: styles.pickRow,
|
|
290
|
+
children: [/*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
|
|
291
|
+
style: styles.pickText,
|
|
292
|
+
children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
|
|
293
|
+
numberOfLines: 1,
|
|
294
|
+
style: styles.pickName,
|
|
295
|
+
children: meta.name
|
|
296
|
+
}), /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.Text, {
|
|
297
|
+
numberOfLines: 1,
|
|
298
|
+
style: styles.pickDetail,
|
|
299
|
+
children: [(0, _format.timeAgo)(meta.createdAt), meta.route ? ` · ${meta.route.pathname}` : "", meta.lastRestoredAt !== undefined ? /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
|
|
300
|
+
style: styles.pickRestored,
|
|
301
|
+
children: ` · restored ${(0, _format.timeAgo)(meta.lastRestoredAt)}`
|
|
302
|
+
}) : null]
|
|
303
|
+
})]
|
|
304
|
+
}), isArmed ? /*#__PURE__*/(0, _jsxRuntime.jsx)(_sharedUi.Check, {
|
|
305
|
+
size: 14,
|
|
306
|
+
color: _sharedUi.night.color.accent
|
|
307
|
+
}) : null]
|
|
308
|
+
}, meta.id);
|
|
309
|
+
}), pickable.length === 0 ? /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
|
|
310
|
+
style: styles.menuText,
|
|
311
|
+
children: "No restore points yet."
|
|
312
|
+
}) : null]
|
|
313
|
+
}), pickable.length > PICKER_ROWS ? /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.Text, {
|
|
314
|
+
style: styles.pickerMore,
|
|
315
|
+
children: ["Scroll for ", pickable.length - PICKER_ROWS, " more"]
|
|
316
|
+
}) : null, /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
|
|
317
|
+
style: styles.settingRow,
|
|
318
|
+
testID: "time-machine-bar-reload-mode",
|
|
319
|
+
children: [/*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
|
|
320
|
+
style: styles.settingText,
|
|
321
|
+
children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
|
|
322
|
+
style: styles.settingLabel,
|
|
323
|
+
children: "Reload the app after restoring"
|
|
324
|
+
}), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
|
|
325
|
+
style: styles.settingHint,
|
|
326
|
+
children: "For screens that read their state from storage only when they open, like a cart kept in a React context."
|
|
327
|
+
})]
|
|
328
|
+
}), /*#__PURE__*/(0, _jsxRuntime.jsx)(_sharedUi.NightSwitch, {
|
|
329
|
+
value: reloadMode,
|
|
330
|
+
onValueChange: _barSettings.setBarReloadMode
|
|
331
|
+
})]
|
|
332
|
+
})]
|
|
333
|
+
});
|
|
334
|
+
} else if (panel === "outcome" && failed) {
|
|
335
|
+
accessory = /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
|
|
336
|
+
style: styles.menu,
|
|
337
|
+
testID: "time-machine-bar-outcome",
|
|
338
|
+
children: [failureLines(failed).map(line => /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
|
|
339
|
+
style: styles.menuDanger,
|
|
340
|
+
children: line
|
|
341
|
+
}, line)), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
|
|
342
|
+
style: styles.menuText,
|
|
343
|
+
children: "The full report is on Time Machine's outcome card."
|
|
344
|
+
}), /*#__PURE__*/(0, _jsxRuntime.jsx)(DismissLink, {
|
|
345
|
+
onPress: () => setPanel(null)
|
|
346
|
+
})]
|
|
347
|
+
});
|
|
348
|
+
} else if (panel === "cap") {
|
|
349
|
+
accessory = /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
|
|
350
|
+
style: styles.menu,
|
|
351
|
+
testID: "time-machine-bar-cap",
|
|
352
|
+
children: [/*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.Text, {
|
|
353
|
+
style: styles.menuText,
|
|
354
|
+
children: ["Free plan keeps ", snapshotLimit, " restore point", snapshotLimit === 1 ? "" : "s", ". Delete one in Time Machine, or upgrade to Pro for unlimited snapshots."]
|
|
355
|
+
}), /*#__PURE__*/(0, _jsxRuntime.jsx)(DismissLink, {
|
|
356
|
+
onPress: () => setPanel(null)
|
|
357
|
+
})]
|
|
358
|
+
});
|
|
359
|
+
} else if (panel === "error" && error) {
|
|
360
|
+
accessory = /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
|
|
361
|
+
style: styles.menu,
|
|
362
|
+
testID: "time-machine-bar-error",
|
|
363
|
+
children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
|
|
364
|
+
accessibilityRole: "alert",
|
|
365
|
+
style: styles.menuDanger,
|
|
366
|
+
children: error
|
|
367
|
+
}), /*#__PURE__*/(0, _jsxRuntime.jsx)(DismissLink, {
|
|
368
|
+
onPress: () => {
|
|
369
|
+
setPanel(null);
|
|
370
|
+
setError(undefined);
|
|
371
|
+
}
|
|
372
|
+
})]
|
|
373
|
+
});
|
|
374
|
+
}
|
|
375
|
+
return /*#__PURE__*/(0, _jsxRuntime.jsxs)(_jsxRuntime.Fragment, {
|
|
376
|
+
children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_NamePromptModal.NamePromptModal, {
|
|
377
|
+
visible: naming,
|
|
378
|
+
summary: captureSummary,
|
|
379
|
+
onCapture: typed => void capture(typed),
|
|
380
|
+
onCancel: () => setNaming(false)
|
|
381
|
+
}), /*#__PURE__*/(0, _jsxRuntime.jsx)(_sharedUi.FloatingTool, {
|
|
382
|
+
id: id,
|
|
383
|
+
revealToken: revealToken,
|
|
384
|
+
variant: "strip",
|
|
385
|
+
dragFromSurface: true,
|
|
386
|
+
defaultPlacement: "bottom",
|
|
387
|
+
accessibilityLabel: `Move or hide the action bar. ${armed ? `${armed.name} armed` : "Nothing armed"}`,
|
|
388
|
+
accessory: accessory
|
|
389
|
+
// The hidden tab keeps the tool's icon, so it is not one more
|
|
390
|
+
// anonymous grip on the edge next to the minimized-tools dock.
|
|
391
|
+
,
|
|
392
|
+
handleAdornment: /*#__PURE__*/(0, _jsxRuntime.jsx)(_sharedUi.TimeMachineIcon, {
|
|
393
|
+
size: 12,
|
|
394
|
+
color: _sharedUi.night.color.accent
|
|
395
|
+
}),
|
|
396
|
+
children: /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
|
|
397
|
+
style: [styles.row, {
|
|
398
|
+
width: Math.max(260, Math.min(320, width - 64))
|
|
399
|
+
}],
|
|
400
|
+
children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.TouchableOpacity, {
|
|
401
|
+
testID: "time-machine-bar-restore",
|
|
402
|
+
accessibilityRole: "button",
|
|
403
|
+
accessibilityLabel: armed ? `Restore ${armed.name}` : "Restore, nothing armed",
|
|
404
|
+
accessibilityHint: destination ? `Also returns to ${destination}. Long press to restore state only.` : undefined,
|
|
405
|
+
accessibilityState: {
|
|
406
|
+
disabled: restoreDisabled
|
|
407
|
+
},
|
|
408
|
+
disabled: restoreDisabled,
|
|
409
|
+
onPress: () => restore(false),
|
|
410
|
+
onLongPress: () => restore(true),
|
|
411
|
+
style: [styles.restoreButton, restoreDisabled && styles.disabled],
|
|
412
|
+
children: busy === "restore" ? /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.ActivityIndicator, {
|
|
413
|
+
size: "small",
|
|
414
|
+
color: _sharedUi.night.color.accent
|
|
415
|
+
}) : restoredFlash ? /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
|
|
416
|
+
style: styles.restoreText,
|
|
417
|
+
testID: "time-machine-bar-restored",
|
|
418
|
+
children: "Restored"
|
|
419
|
+
}) : /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
|
|
420
|
+
style: styles.restoreText,
|
|
421
|
+
children: "Restore"
|
|
422
|
+
})
|
|
423
|
+
}), /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
|
|
424
|
+
style: styles.identity,
|
|
425
|
+
children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
|
|
426
|
+
testID: "time-machine-bar-name",
|
|
427
|
+
accessibilityLabel: `Armed restore point: ${name}`,
|
|
428
|
+
numberOfLines: 1
|
|
429
|
+
// Default names are "screen · clock"; the clock is what tells
|
|
430
|
+
// two captures apart, so the end must survive truncation.
|
|
431
|
+
,
|
|
432
|
+
ellipsizeMode: "middle",
|
|
433
|
+
style: styles.name,
|
|
434
|
+
children: name
|
|
435
|
+
}), /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
|
|
436
|
+
style: styles.statusRow,
|
|
437
|
+
children: [/*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.Text, {
|
|
438
|
+
testID: "time-machine-bar-status",
|
|
439
|
+
numberOfLines: 1,
|
|
440
|
+
accessibilityLiveRegion: "polite",
|
|
441
|
+
style: [styles.status, statusTone === "danger" && styles.danger],
|
|
442
|
+
children: [status, destination ? /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
|
|
443
|
+
style: styles.destination,
|
|
444
|
+
children: ` · → ${destination}`
|
|
445
|
+
}) : null]
|
|
446
|
+
}), undoAvailable && !busy ? /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.TouchableOpacity, {
|
|
447
|
+
testID: "time-machine-bar-undo",
|
|
448
|
+
accessibilityRole: "button",
|
|
449
|
+
accessibilityLabel: "Undo the last restore",
|
|
450
|
+
onPress: undoRestore,
|
|
451
|
+
hitSlop: {
|
|
452
|
+
top: 8,
|
|
453
|
+
bottom: 8,
|
|
454
|
+
left: 6,
|
|
455
|
+
right: 6
|
|
456
|
+
},
|
|
457
|
+
children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
|
|
458
|
+
style: styles.undo,
|
|
459
|
+
children: "Undo"
|
|
460
|
+
})
|
|
461
|
+
}) : null]
|
|
462
|
+
})]
|
|
463
|
+
}), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.TouchableOpacity, {
|
|
464
|
+
testID: "time-machine-bar-pick",
|
|
465
|
+
accessibilityRole: "button",
|
|
466
|
+
accessibilityLabel: "Choose another restore point",
|
|
467
|
+
accessibilityState: {
|
|
468
|
+
expanded: panel === "picker"
|
|
469
|
+
},
|
|
470
|
+
onPress: () => setPanel(p => p === "picker" ? null : "picker"),
|
|
471
|
+
style: styles.smallButton,
|
|
472
|
+
children: panel === "picker" ? /*#__PURE__*/(0, _jsxRuntime.jsx)(_sharedUi.ChevronUp, {
|
|
473
|
+
size: 14,
|
|
474
|
+
color: _sharedUi.night.color.textSecondary
|
|
475
|
+
}) : /*#__PURE__*/(0, _jsxRuntime.jsx)(_sharedUi.ChevronDown, {
|
|
476
|
+
size: 14,
|
|
477
|
+
color: _sharedUi.night.color.textSecondary
|
|
478
|
+
})
|
|
479
|
+
}), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.TouchableOpacity, {
|
|
480
|
+
testID: "time-machine-bar-capture",
|
|
481
|
+
accessibilityRole: "button",
|
|
482
|
+
accessibilityLabel: "Capture a new restore point here and arm it",
|
|
483
|
+
accessibilityState: {
|
|
484
|
+
disabled: captureDisabled
|
|
485
|
+
},
|
|
486
|
+
disabled: captureDisabled,
|
|
487
|
+
onPress: askForName,
|
|
488
|
+
style: [styles.smallButton, captureDisabled && styles.disabled],
|
|
489
|
+
children: busy === "capture" ? /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.ActivityIndicator, {
|
|
490
|
+
size: "small",
|
|
491
|
+
color: _sharedUi.night.color.accent
|
|
492
|
+
}) : capturedFlash ? /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
|
|
493
|
+
testID: "time-machine-bar-captured",
|
|
494
|
+
children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_sharedUi.Check, {
|
|
495
|
+
size: 18,
|
|
496
|
+
color: _sharedUi.night.color.accent
|
|
497
|
+
})
|
|
498
|
+
}) : /*#__PURE__*/(0, _jsxRuntime.jsx)(_sharedUi.Plus, {
|
|
499
|
+
size: 18,
|
|
500
|
+
color: atCaptureLimit ? _sharedUi.night.color.textTertiary : _sharedUi.night.color.text
|
|
501
|
+
})
|
|
502
|
+
}), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
|
|
503
|
+
style: styles.separator
|
|
504
|
+
}), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.TouchableOpacity, {
|
|
505
|
+
testID: "time-machine-bar-close",
|
|
506
|
+
accessibilityRole: "button",
|
|
507
|
+
accessibilityLabel: "Close the action bar",
|
|
508
|
+
onPress: dismiss,
|
|
509
|
+
style: styles.closeButton,
|
|
510
|
+
children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_sharedUi.X, {
|
|
511
|
+
size: 16,
|
|
512
|
+
color: _sharedUi.night.color.textSecondary
|
|
513
|
+
})
|
|
514
|
+
})]
|
|
515
|
+
})
|
|
516
|
+
})]
|
|
517
|
+
});
|
|
518
|
+
}
|
|
519
|
+
function DismissLink({
|
|
520
|
+
onPress,
|
|
521
|
+
label = "Dismiss"
|
|
522
|
+
}) {
|
|
523
|
+
return /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.TouchableOpacity, {
|
|
524
|
+
testID: "time-machine-bar-dismiss",
|
|
525
|
+
accessibilityRole: "button",
|
|
526
|
+
onPress: onPress,
|
|
527
|
+
style: styles.dismiss,
|
|
528
|
+
children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
|
|
529
|
+
style: styles.dismissText,
|
|
530
|
+
children: label
|
|
531
|
+
})
|
|
532
|
+
});
|
|
533
|
+
}
|
|
534
|
+
const styles = _reactNative.StyleSheet.create({
|
|
535
|
+
row: {
|
|
536
|
+
flexDirection: "row",
|
|
537
|
+
alignItems: "center",
|
|
538
|
+
gap: 4,
|
|
539
|
+
paddingVertical: 4,
|
|
540
|
+
minHeight: 48
|
|
541
|
+
},
|
|
542
|
+
// The primary action is a word, not a glyph: "Restore" needs no legend.
|
|
543
|
+
// Same pill as Network's strip action: accent ink on a tinted, outlined
|
|
544
|
+
// dark chip, so it belongs to the strip instead of shouting over it.
|
|
545
|
+
restoreButton: {
|
|
546
|
+
height: 32,
|
|
547
|
+
minWidth: 72,
|
|
548
|
+
paddingHorizontal: 12,
|
|
549
|
+
borderRadius: 8,
|
|
550
|
+
borderWidth: 1,
|
|
551
|
+
borderColor: _sharedUi.night.color.accentBorderStrong,
|
|
552
|
+
backgroundColor: _sharedUi.night.color.accentSoft,
|
|
553
|
+
alignItems: "center",
|
|
554
|
+
justifyContent: "center",
|
|
555
|
+
marginLeft: 2
|
|
556
|
+
},
|
|
557
|
+
restoreText: {
|
|
558
|
+
color: _sharedUi.night.color.accent,
|
|
559
|
+
fontSize: 12,
|
|
560
|
+
fontWeight: "700"
|
|
561
|
+
},
|
|
562
|
+
smallButton: {
|
|
563
|
+
width: 32,
|
|
564
|
+
minHeight: 44,
|
|
565
|
+
alignItems: "center",
|
|
566
|
+
justifyContent: "center"
|
|
567
|
+
},
|
|
568
|
+
closeButton: {
|
|
569
|
+
width: 28,
|
|
570
|
+
minHeight: 44,
|
|
571
|
+
alignItems: "center",
|
|
572
|
+
justifyContent: "center"
|
|
573
|
+
},
|
|
574
|
+
identity: {
|
|
575
|
+
flex: 1,
|
|
576
|
+
minHeight: 44,
|
|
577
|
+
justifyContent: "center",
|
|
578
|
+
gap: 1
|
|
579
|
+
},
|
|
580
|
+
name: {
|
|
581
|
+
color: _sharedUi.night.color.text,
|
|
582
|
+
fontSize: 13,
|
|
583
|
+
fontWeight: "500"
|
|
584
|
+
},
|
|
585
|
+
statusRow: {
|
|
586
|
+
flexDirection: "row",
|
|
587
|
+
alignItems: "center",
|
|
588
|
+
gap: 8
|
|
589
|
+
},
|
|
590
|
+
status: {
|
|
591
|
+
color: _sharedUi.night.color.textSecondary,
|
|
592
|
+
fontSize: 10,
|
|
593
|
+
lineHeight: 14,
|
|
594
|
+
flexShrink: 1
|
|
595
|
+
},
|
|
596
|
+
destination: {
|
|
597
|
+
color: _sharedUi.night.color.textTertiary
|
|
598
|
+
},
|
|
599
|
+
danger: {
|
|
600
|
+
color: _sharedUi.night.color.danger
|
|
601
|
+
},
|
|
602
|
+
undo: {
|
|
603
|
+
color: _sharedUi.night.color.accent,
|
|
604
|
+
fontSize: 10,
|
|
605
|
+
lineHeight: 14,
|
|
606
|
+
fontWeight: "700"
|
|
607
|
+
},
|
|
608
|
+
separator: {
|
|
609
|
+
height: 20,
|
|
610
|
+
width: 1,
|
|
611
|
+
backgroundColor: _sharedUi.night.color.separator,
|
|
612
|
+
marginHorizontal: 2
|
|
613
|
+
},
|
|
614
|
+
disabled: {
|
|
615
|
+
opacity: 0.4
|
|
616
|
+
},
|
|
617
|
+
menu: {
|
|
618
|
+
marginVertical: 8,
|
|
619
|
+
padding: 6,
|
|
620
|
+
borderRadius: _sharedUi.night.radius.card,
|
|
621
|
+
borderWidth: 1,
|
|
622
|
+
borderColor: _sharedUi.night.color.separator,
|
|
623
|
+
backgroundColor: _sharedUi.night.color.surface,
|
|
624
|
+
shadowColor: "#000",
|
|
625
|
+
shadowOffset: {
|
|
626
|
+
width: 0,
|
|
627
|
+
height: 6
|
|
628
|
+
},
|
|
629
|
+
shadowOpacity: 0.25,
|
|
630
|
+
shadowRadius: 16,
|
|
631
|
+
elevation: 8
|
|
632
|
+
},
|
|
633
|
+
menuText: {
|
|
634
|
+
color: _sharedUi.night.color.textSecondary,
|
|
635
|
+
fontSize: 12,
|
|
636
|
+
lineHeight: 18,
|
|
637
|
+
padding: 10
|
|
638
|
+
},
|
|
639
|
+
menuDanger: {
|
|
640
|
+
color: _sharedUi.night.color.danger,
|
|
641
|
+
fontSize: 12,
|
|
642
|
+
lineHeight: 18,
|
|
643
|
+
paddingHorizontal: 10,
|
|
644
|
+
paddingTop: 6
|
|
645
|
+
},
|
|
646
|
+
pickerList: {
|
|
647
|
+
maxHeight: PICKER_ROWS * 44
|
|
648
|
+
},
|
|
649
|
+
pickerMore: {
|
|
650
|
+
color: _sharedUi.night.color.textTertiary,
|
|
651
|
+
fontSize: 10,
|
|
652
|
+
lineHeight: 14,
|
|
653
|
+
textAlign: "center",
|
|
654
|
+
paddingVertical: 4
|
|
655
|
+
},
|
|
656
|
+
pickRow: {
|
|
657
|
+
flexDirection: "row",
|
|
658
|
+
alignItems: "center",
|
|
659
|
+
gap: 8,
|
|
660
|
+
minHeight: 44,
|
|
661
|
+
paddingHorizontal: 10,
|
|
662
|
+
borderRadius: _sharedUi.night.radius.row
|
|
663
|
+
},
|
|
664
|
+
pickText: {
|
|
665
|
+
flex: 1
|
|
666
|
+
},
|
|
667
|
+
settingRow: {
|
|
668
|
+
flexDirection: "row",
|
|
669
|
+
alignItems: "center",
|
|
670
|
+
gap: 10,
|
|
671
|
+
paddingHorizontal: 10,
|
|
672
|
+
paddingVertical: 8,
|
|
673
|
+
borderTopWidth: _reactNative.StyleSheet.hairlineWidth,
|
|
674
|
+
borderTopColor: _sharedUi.night.color.separator,
|
|
675
|
+
marginTop: 4
|
|
676
|
+
},
|
|
677
|
+
settingText: {
|
|
678
|
+
flex: 1,
|
|
679
|
+
gap: 2
|
|
680
|
+
},
|
|
681
|
+
settingLabel: {
|
|
682
|
+
color: _sharedUi.night.color.text,
|
|
683
|
+
fontSize: 12,
|
|
684
|
+
fontWeight: "500"
|
|
685
|
+
},
|
|
686
|
+
settingHint: {
|
|
687
|
+
color: _sharedUi.night.color.textTertiary,
|
|
688
|
+
fontSize: 10,
|
|
689
|
+
lineHeight: 13
|
|
690
|
+
},
|
|
691
|
+
pickName: {
|
|
692
|
+
color: _sharedUi.night.color.text,
|
|
693
|
+
fontSize: 13,
|
|
694
|
+
fontWeight: "500"
|
|
695
|
+
},
|
|
696
|
+
pickDetail: {
|
|
697
|
+
color: _sharedUi.night.color.textSecondary,
|
|
698
|
+
fontSize: 10,
|
|
699
|
+
lineHeight: 14
|
|
700
|
+
},
|
|
701
|
+
pickRestored: {
|
|
702
|
+
color: _sharedUi.night.color.accent
|
|
703
|
+
},
|
|
704
|
+
dismiss: {
|
|
705
|
+
alignSelf: "flex-end",
|
|
706
|
+
paddingHorizontal: 10,
|
|
707
|
+
paddingVertical: 8
|
|
708
|
+
},
|
|
709
|
+
dismissText: {
|
|
710
|
+
color: _sharedUi.night.color.accent,
|
|
711
|
+
fontSize: 12,
|
|
712
|
+
fontWeight: "600"
|
|
713
|
+
}
|
|
714
|
+
});
|
|
715
|
+
//# sourceMappingURL=TimeMachineFloatingTool.js.map
|