@buoy-gg/time-machine 7.0.41 → 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/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 +2 -3
- package/package.json +7 -7
- 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,169 +1 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Sources — one settings row per source, each with a switch.
|
|
5
|
-
*
|
|
6
|
-
* The iOS Settings shape the rest of the tool uses, because that is what a
|
|
7
|
-
* list of things you can turn on and off looks like: icon, name, a line of
|
|
8
|
-
* status, and a switch at the trailing edge. Off means every capture and
|
|
9
|
-
* restore leaves that source alone, for the store whose full replace the
|
|
10
|
-
* app cannot survive.
|
|
11
|
-
*
|
|
12
|
-
* Only sources the app has wired are listed; a library the app does not use
|
|
13
|
-
* is not a choice to make. Icons keep full brightness in every state. Under
|
|
14
|
-
* each name is what the source holds, in plain words; a short state line
|
|
15
|
-
* appears only when something is off or capture-only.
|
|
16
|
-
*/
|
|
17
|
-
import { StyleSheet, Text, View } from "react-native";
|
|
18
|
-
import { NightSwitch } from "@buoy-gg/shared-ui";
|
|
19
|
-
import { Group } from "../../ui/primitives";
|
|
20
|
-
import { tm } from "../../ui/tmTheme";
|
|
21
|
-
import { sourceIcon } from "../sources";
|
|
22
|
-
|
|
23
|
-
/**
|
|
24
|
-
* What each source holds, in words for someone who has never heard of the
|
|
25
|
-
* library. The library name is the row title; this line is the meaning.
|
|
26
|
-
*/
|
|
27
|
-
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
28
|
-
const DESCRIPTIONS = {
|
|
29
|
-
storage: "Settings, sign-in and other things saved on the device",
|
|
30
|
-
redux: "Data the whole app shares between screens",
|
|
31
|
-
zustand: "Data the whole app shares between screens",
|
|
32
|
-
jotai: "Small pieces of data screens share",
|
|
33
|
-
query: "Data the app loaded from the server",
|
|
34
|
-
route: "Which screen you were on"
|
|
35
|
-
};
|
|
36
|
-
function describe(source) {
|
|
37
|
-
return DESCRIPTIONS[source.id] ?? "App data";
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
/**
|
|
41
|
-
* The short state under the description, when there is one worth saying.
|
|
42
|
-
* "Working" is the default and needs no line.
|
|
43
|
-
*/
|
|
44
|
-
function stateLine(source) {
|
|
45
|
-
if (!source.enabled) return {
|
|
46
|
-
text: "Off · left as it is",
|
|
47
|
-
tone: "off"
|
|
48
|
-
};
|
|
49
|
-
if (!source.canRestore) return {
|
|
50
|
-
text: "Can be saved but not put back",
|
|
51
|
-
tone: "warn"
|
|
52
|
-
};
|
|
53
|
-
return null;
|
|
54
|
-
}
|
|
55
|
-
function SourceRow({
|
|
56
|
-
source,
|
|
57
|
-
onToggle
|
|
58
|
-
}) {
|
|
59
|
-
const Icon = sourceIcon(source.id);
|
|
60
|
-
const description = describe(source);
|
|
61
|
-
const state = stateLine(source);
|
|
62
|
-
return /*#__PURE__*/_jsxs(View, {
|
|
63
|
-
style: styles.row,
|
|
64
|
-
testID: `time-machine-source-${source.id}`,
|
|
65
|
-
accessibilityLabel: `${source.label}: ${description}${state ? `. ${state.text}` : ""}`,
|
|
66
|
-
children: [/*#__PURE__*/_jsx(View, {
|
|
67
|
-
style: styles.disc,
|
|
68
|
-
children: /*#__PURE__*/_jsx(Icon, {
|
|
69
|
-
size: 22,
|
|
70
|
-
bgColor: tm.color.disc
|
|
71
|
-
})
|
|
72
|
-
}), /*#__PURE__*/_jsxs(View, {
|
|
73
|
-
style: styles.text,
|
|
74
|
-
children: [/*#__PURE__*/_jsx(Text, {
|
|
75
|
-
style: styles.label,
|
|
76
|
-
numberOfLines: 1,
|
|
77
|
-
testID: `time-machine-source-${source.id}-label`,
|
|
78
|
-
children: source.label
|
|
79
|
-
}), /*#__PURE__*/_jsx(Text, {
|
|
80
|
-
style: styles.description,
|
|
81
|
-
numberOfLines: 2,
|
|
82
|
-
testID: `time-machine-source-${source.id}-description`,
|
|
83
|
-
children: description
|
|
84
|
-
}), state ? /*#__PURE__*/_jsx(Text, {
|
|
85
|
-
style: [styles.state, styles[`state_${state.tone}`]],
|
|
86
|
-
numberOfLines: 1,
|
|
87
|
-
testID: state.tone === "off" ? `time-machine-source-${source.id}-off` : `time-machine-source-${source.id}-detail`,
|
|
88
|
-
children: state.text
|
|
89
|
-
}) : null]
|
|
90
|
-
}), /*#__PURE__*/_jsx(View, {
|
|
91
|
-
testID: `time-machine-source-${source.id}-switch`,
|
|
92
|
-
children: /*#__PURE__*/_jsx(NightSwitch, {
|
|
93
|
-
value: source.enabled
|
|
94
|
-
// The desktop mirror shows the device's setting and cannot flip it.
|
|
95
|
-
,
|
|
96
|
-
disabled: !onToggle,
|
|
97
|
-
onValueChange: next => onToggle?.(source.id, next)
|
|
98
|
-
})
|
|
99
|
-
})]
|
|
100
|
-
});
|
|
101
|
-
}
|
|
102
|
-
export function SourcesStrip({
|
|
103
|
-
sources,
|
|
104
|
-
onToggle
|
|
105
|
-
}) {
|
|
106
|
-
// A source the app has not wired (no Redux Provider, no Zustand stores)
|
|
107
|
-
// is not listed: there is nothing to capture and nothing to switch off.
|
|
108
|
-
const wired = sources.filter(source => source.canCapture);
|
|
109
|
-
return /*#__PURE__*/_jsxs(Group, {
|
|
110
|
-
children: [wired.map(source => /*#__PURE__*/_jsx(SourceRow, {
|
|
111
|
-
source: source,
|
|
112
|
-
onToggle: onToggle
|
|
113
|
-
}, source.id)), wired.length === 0 ? /*#__PURE__*/_jsx(View, {
|
|
114
|
-
style: styles.row,
|
|
115
|
-
testID: "time-machine-sources-empty",
|
|
116
|
-
children: /*#__PURE__*/_jsx(Text, {
|
|
117
|
-
style: styles.description,
|
|
118
|
-
children: "No state tools are set up in this app."
|
|
119
|
-
})
|
|
120
|
-
}) : null]
|
|
121
|
-
});
|
|
122
|
-
}
|
|
123
|
-
const styles = StyleSheet.create({
|
|
124
|
-
row: {
|
|
125
|
-
flexDirection: "row",
|
|
126
|
-
alignItems: "center",
|
|
127
|
-
gap: 12,
|
|
128
|
-
minHeight: tm.rowMinHeight,
|
|
129
|
-
paddingHorizontal: tm.textInset,
|
|
130
|
-
paddingVertical: 10
|
|
131
|
-
},
|
|
132
|
-
disc: {
|
|
133
|
-
width: 36,
|
|
134
|
-
height: 36,
|
|
135
|
-
borderRadius: tm.radius.pill,
|
|
136
|
-
backgroundColor: tm.color.disc,
|
|
137
|
-
alignItems: "center",
|
|
138
|
-
justifyContent: "center"
|
|
139
|
-
},
|
|
140
|
-
text: {
|
|
141
|
-
flex: 1,
|
|
142
|
-
minWidth: 0,
|
|
143
|
-
gap: 2
|
|
144
|
-
},
|
|
145
|
-
label: {
|
|
146
|
-
color: tm.color.label,
|
|
147
|
-
fontSize: tm.font.row,
|
|
148
|
-
fontWeight: "500",
|
|
149
|
-
letterSpacing: tm.tracking.row
|
|
150
|
-
},
|
|
151
|
-
description: {
|
|
152
|
-
fontSize: tm.font.footnote,
|
|
153
|
-
lineHeight: tm.font.footnote * 1.3,
|
|
154
|
-
color: tm.color.labelSecondary
|
|
155
|
-
},
|
|
156
|
-
state: {
|
|
157
|
-
fontSize: tm.font.mono,
|
|
158
|
-
lineHeight: tm.font.mono * 1.3,
|
|
159
|
-
fontWeight: "600",
|
|
160
|
-
marginTop: 1
|
|
161
|
-
},
|
|
162
|
-
state_off: {
|
|
163
|
-
color: tm.color.labelTertiary
|
|
164
|
-
},
|
|
165
|
-
state_warn: {
|
|
166
|
-
color: tm.color.warning
|
|
167
|
-
}
|
|
168
|
-
});
|
|
169
|
-
//# sourceMappingURL=SourcesStrip.js.map
|
|
1
|
+
"use strict";import{StyleSheet as f,Text as c,View as s}from"react-native";import{NightSwitch as m}from"@buoy-gg/shared-ui";import{Group as p}from"../../ui/primitives";import{tm as t}from"../../ui/tmTheme";import{sourceIcon as u}from"../sources";import{jsx as i,jsxs as d}from"react/jsx-runtime";const g={storage:"Settings, sign-in and other things saved on the device",redux:"Data the whole app shares between screens",zustand:"Data the whole app shares between screens",jotai:"Small pieces of data screens share",query:"Data the app loaded from the server",route:"Which screen you were on"};function b(e){return g[e.id]??"App data"}function w(e){if(!e.enabled)return{text:"Off \xB7 left as it is",tone:"off"};if(!e.canRestore)return{text:"Can be saved but not put back",tone:"warn"};return null}function y({source:e,onToggle:a}){const l=u(e.id);const o=b(e);const r=w(e);return d(s,{style:n.row,testID:`time-machine-source-${e.id}`,accessibilityLabel:`${e.label}: ${o}${r?`. ${r.text}`:""}`,children:[i(s,{style:n.disc,children:i(l,{size:22,bgColor:t.color.disc})}),d(s,{style:n.text,children:[i(c,{style:n.label,numberOfLines:1,testID:`time-machine-source-${e.id}-label`,children:e.label}),i(c,{style:n.description,numberOfLines:2,testID:`time-machine-source-${e.id}-description`,children:o}),r?i(c,{style:[n.state,n[`state_${r.tone}`]],numberOfLines:1,testID:r.tone==="off"?`time-machine-source-${e.id}-off`:`time-machine-source-${e.id}-detail`,children:r.text}):null]}),i(s,{testID:`time-machine-source-${e.id}-switch`,children:i(m,{value:e.enabled,disabled:!a,onValueChange:h=>a?.(e.id,h)})})]})}export function SourcesStrip({sources:e,onToggle:a}){const l=e.filter(o=>o.canCapture);return d(p,{children:[l.map(o=>i(y,{source:o,onToggle:a},o.id)),l.length===0?i(s,{style:n.row,testID:"time-machine-sources-empty",children:i(c,{style:n.description,children:"No state tools are set up in this app."})}):null]})}const n=f.create({row:{flexDirection:"row",alignItems:"center",gap:12,minHeight:t.rowMinHeight,paddingHorizontal:t.textInset,paddingVertical:10},disc:{width:36,height:36,borderRadius:t.radius.pill,backgroundColor:t.color.disc,alignItems:"center",justifyContent:"center"},text:{flex:1,minWidth:0,gap:2},label:{color:t.color.label,fontSize:t.font.row,fontWeight:"500",letterSpacing:t.tracking.row},description:{fontSize:t.font.footnote,lineHeight:t.font.footnote*1.3,color:t.color.labelSecondary},state:{fontSize:t.font.mono,lineHeight:t.font.mono*1.3,fontWeight:"600",marginTop:1},state_off:{color:t.color.labelTertiary},state_warn:{color:t.color.warning}});
|
|
@@ -1,82 +1 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* The way back from a swipe-delete.
|
|
5
|
-
*
|
|
6
|
-
* Swipe-then-tap is deliberate, which is why there's no confirmation dialog —
|
|
7
|
-
* but deliberate and recoverable are different properties, and a restore
|
|
8
|
-
* point can stand for state that took ten minutes and a cooperative backend
|
|
9
|
-
* to build. The record is held in memory until this bar expires.
|
|
10
|
-
*/
|
|
11
|
-
import { useEffect } from "react";
|
|
12
|
-
import { StyleSheet, Text, TouchableOpacity, View } from "react-native";
|
|
13
|
-
import { tm } from "../../ui/tmTheme";
|
|
14
|
-
|
|
15
|
-
/** Long enough to notice and react, short enough not to linger. */
|
|
16
|
-
import { jsxs as _jsxs, jsx as _jsx } from "react/jsx-runtime";
|
|
17
|
-
const WINDOW_MS = 8000;
|
|
18
|
-
export function UndoDeleteBar({
|
|
19
|
-
name,
|
|
20
|
-
at,
|
|
21
|
-
onUndo,
|
|
22
|
-
onExpire
|
|
23
|
-
}) {
|
|
24
|
-
useEffect(() => {
|
|
25
|
-
const timer = setTimeout(onExpire, WINDOW_MS);
|
|
26
|
-
return () => clearTimeout(timer);
|
|
27
|
-
// `at` keyed rather than `onExpire`: a new delete must restart the clock.
|
|
28
|
-
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
29
|
-
}, [at]);
|
|
30
|
-
return /*#__PURE__*/_jsxs(View, {
|
|
31
|
-
style: styles.bar,
|
|
32
|
-
testID: "time-machine-undo-bar",
|
|
33
|
-
children: [/*#__PURE__*/_jsxs(Text, {
|
|
34
|
-
style: styles.text,
|
|
35
|
-
numberOfLines: 1,
|
|
36
|
-
testID: "time-machine-undo-text",
|
|
37
|
-
children: ["Deleted \u201C", name, "\u201D"]
|
|
38
|
-
}), /*#__PURE__*/_jsx(TouchableOpacity, {
|
|
39
|
-
onPress: onUndo,
|
|
40
|
-
hitSlop: {
|
|
41
|
-
top: 10,
|
|
42
|
-
bottom: 10,
|
|
43
|
-
left: 10,
|
|
44
|
-
right: 10
|
|
45
|
-
},
|
|
46
|
-
accessibilityRole: "button",
|
|
47
|
-
testID: "time-machine-undo-delete",
|
|
48
|
-
children: /*#__PURE__*/_jsx(Text, {
|
|
49
|
-
style: styles.undo,
|
|
50
|
-
children: "Undo"
|
|
51
|
-
})
|
|
52
|
-
})]
|
|
53
|
-
});
|
|
54
|
-
}
|
|
55
|
-
const styles = StyleSheet.create({
|
|
56
|
-
bar: {
|
|
57
|
-
flexDirection: "row",
|
|
58
|
-
alignItems: "center",
|
|
59
|
-
gap: 12,
|
|
60
|
-
marginHorizontal: tm.gutter,
|
|
61
|
-
marginTop: 12,
|
|
62
|
-
minHeight: 46,
|
|
63
|
-
paddingHorizontal: tm.textInset,
|
|
64
|
-
backgroundColor: tm.color.group,
|
|
65
|
-
borderRadius: tm.radius.group,
|
|
66
|
-
borderWidth: 1,
|
|
67
|
-
borderColor: tm.color.groupBorder
|
|
68
|
-
},
|
|
69
|
-
text: {
|
|
70
|
-
flex: 1,
|
|
71
|
-
color: tm.color.labelSecondary,
|
|
72
|
-
fontSize: tm.font.control,
|
|
73
|
-
letterSpacing: tm.tracking.control
|
|
74
|
-
},
|
|
75
|
-
undo: {
|
|
76
|
-
color: tm.color.accent,
|
|
77
|
-
fontSize: tm.font.control,
|
|
78
|
-
fontWeight: "600",
|
|
79
|
-
letterSpacing: tm.tracking.control
|
|
80
|
-
}
|
|
81
|
-
});
|
|
82
|
-
//# sourceMappingURL=UndoDeleteBar.js.map
|
|
1
|
+
"use strict";import{useEffect as d}from"react";import{StyleSheet as m,Text as o,TouchableOpacity as u,View as g}from"react-native";import{tm as t}from"../../ui/tmTheme";import{jsxs as r,jsx as n}from"react/jsx-runtime";const f=8e3;export function UndoDeleteBar({name:i,at:c,onUndo:l,onExpire:s}){d(()=>{const a=setTimeout(s,f);return()=>clearTimeout(a)},[c]);return r(g,{style:e.bar,testID:"time-machine-undo-bar",children:[r(o,{style:e.text,numberOfLines:1,testID:"time-machine-undo-text",children:["Deleted \u201C",i,"\u201D"]}),n(u,{onPress:l,hitSlop:{top:10,bottom:10,left:10,right:10},accessibilityRole:"button",testID:"time-machine-undo-delete",children:n(o,{style:e.undo,children:"Undo"})})]})}const e=m.create({bar:{flexDirection:"row",alignItems:"center",gap:12,marginHorizontal:t.gutter,marginTop:12,minHeight:46,paddingHorizontal:t.textInset,backgroundColor:t.color.group,borderRadius:t.radius.group,borderWidth:1,borderColor:t.color.groupBorder},text:{flex:1,color:t.color.labelSecondary,fontSize:t.font.control,letterSpacing:t.tracking.control},undo:{color:t.color.accent,fontSize:t.font.control,fontWeight:"600",letterSpacing:t.tracking.control}});
|
|
@@ -1,41 +1 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* "Wipe All App State…" — the destructive utility, deliberately last, alone
|
|
5
|
-
* in its own card and with no icon competing for attention.
|
|
6
|
-
*/
|
|
7
|
-
import { StyleSheet, Text, TouchableOpacity } from "react-native";
|
|
8
|
-
import { tm } from "../../ui/tmTheme";
|
|
9
|
-
import { jsx as _jsx } from "react/jsx-runtime";
|
|
10
|
-
export function WipeAllRow({
|
|
11
|
-
disabled,
|
|
12
|
-
onWipe
|
|
13
|
-
}) {
|
|
14
|
-
return /*#__PURE__*/_jsx(TouchableOpacity, {
|
|
15
|
-
style: [styles.row, disabled ? styles.disabled : null],
|
|
16
|
-
onPress: onWipe,
|
|
17
|
-
disabled: disabled,
|
|
18
|
-
accessibilityRole: "button",
|
|
19
|
-
testID: "time-machine-wipe-all",
|
|
20
|
-
children: /*#__PURE__*/_jsx(Text, {
|
|
21
|
-
style: styles.label,
|
|
22
|
-
children: "Wipe All App State\u2026"
|
|
23
|
-
})
|
|
24
|
-
});
|
|
25
|
-
}
|
|
26
|
-
const styles = StyleSheet.create({
|
|
27
|
-
row: {
|
|
28
|
-
minHeight: tm.rowMinHeight,
|
|
29
|
-
alignItems: "center",
|
|
30
|
-
justifyContent: "center"
|
|
31
|
-
},
|
|
32
|
-
disabled: {
|
|
33
|
-
opacity: 0.4
|
|
34
|
-
},
|
|
35
|
-
label: {
|
|
36
|
-
color: tm.color.danger,
|
|
37
|
-
fontSize: tm.font.row,
|
|
38
|
-
letterSpacing: tm.tracking.row
|
|
39
|
-
}
|
|
40
|
-
});
|
|
41
|
-
//# sourceMappingURL=WipeAllRow.js.map
|
|
1
|
+
"use strict";import{StyleSheet as r,Text as n,TouchableOpacity as s}from"react-native";import{tm as e}from"../../ui/tmTheme";import{jsx as l}from"react/jsx-runtime";export function WipeAllRow({disabled:i,onWipe:o}){return l(s,{style:[t.row,i?t.disabled:null],onPress:o,disabled:i,accessibilityRole:"button",testID:"time-machine-wipe-all",children:l(n,{style:t.label,children:"Wipe All App State\u2026"})})}const t=r.create({row:{minHeight:e.rowMinHeight,alignItems:"center",justifyContent:"center"},disabled:{opacity:.4},label:{color:e.color.danger,fontSize:e.font.row,letterSpacing:e.tracking.row}});
|
|
@@ -1,74 +1 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* One preview item's before/after, rendered INLINE under its row rather than
|
|
5
|
-
* on a screen of its own — "what changed in this key" is a glance question,
|
|
6
|
-
* and losing the list to answer it costs you the place you were reading.
|
|
7
|
-
*
|
|
8
|
-
* Split view only, with no view switcher. Side-by-side is the shape that
|
|
9
|
-
* answers the question here ("what is it now, what will it become"), and
|
|
10
|
-
* inside a list row the segmented control cost more vertical space than the
|
|
11
|
-
* diff it was switching.
|
|
12
|
-
*
|
|
13
|
-
* The render-layer viewer only handles plain JSON faithfully, so both sides
|
|
14
|
-
* pass through toDiffable (Dates→ISO, Maps→objects, BigInt→"1n", cycles→
|
|
15
|
-
* "[Circular]") and the pair is memoized ONCE per item — the storage tool's
|
|
16
|
-
* fix for the fresh-identity-every-render trap that redux/zustand still have.
|
|
17
|
-
*
|
|
18
|
-
* No scroller of its own: this sits inside the preview's FlatList, so the
|
|
19
|
-
* viewer renders at natural height with `scrollEnabled={false}` (the storage
|
|
20
|
-
* matched-pair contract).
|
|
21
|
-
*/
|
|
22
|
-
import { useMemo } from "react";
|
|
23
|
-
import { StyleSheet, Text, View } from "react-native";
|
|
24
|
-
import { ABSENT_VALUE, ThemedSplitView, devToolsDefaultTheme, toDiffable } from "@buoy-gg/shared-ui/dataViewer";
|
|
25
|
-
import { tm } from "../../ui/tmTheme";
|
|
26
|
-
import { jsxs as _jsxs, jsx as _jsx } from "react/jsx-runtime";
|
|
27
|
-
const EMPTY = [];
|
|
28
|
-
export function ItemDiffPanel({
|
|
29
|
-
item,
|
|
30
|
-
testID
|
|
31
|
-
}) {
|
|
32
|
-
// ABSENT_VALUE keeps added/removed reading as pure additions/removals
|
|
33
|
-
// instead of diffs against the literal "null".
|
|
34
|
-
const {
|
|
35
|
-
oldValue,
|
|
36
|
-
newValue
|
|
37
|
-
} = useMemo(() => ({
|
|
38
|
-
oldValue: item.verdict === "added" ? ABSENT_VALUE : toDiffable(item.oldValue),
|
|
39
|
-
newValue: item.verdict === "removed" ? ABSENT_VALUE : toDiffable(item.newValue)
|
|
40
|
-
}), [item]);
|
|
41
|
-
return /*#__PURE__*/_jsxs(View, {
|
|
42
|
-
style: styles.panel,
|
|
43
|
-
testID: testID,
|
|
44
|
-
children: [item.reason ? /*#__PURE__*/_jsxs(Text, {
|
|
45
|
-
style: styles.reason,
|
|
46
|
-
children: ["\u26A0 ", item.reason]
|
|
47
|
-
}) : null, /*#__PURE__*/_jsx(ThemedSplitView, {
|
|
48
|
-
oldValue: oldValue,
|
|
49
|
-
newValue: newValue,
|
|
50
|
-
differences: EMPTY,
|
|
51
|
-
theme: devToolsDefaultTheme,
|
|
52
|
-
scrollEnabled: false
|
|
53
|
-
})]
|
|
54
|
-
});
|
|
55
|
-
}
|
|
56
|
-
const styles = StyleSheet.create({
|
|
57
|
-
// Same fill as the rows above it: this is part of the card, not a thing
|
|
58
|
-
// floating under it.
|
|
59
|
-
panel: {
|
|
60
|
-
// Only a token indent: the viewer lays values out at their natural width
|
|
61
|
-
// and a 51pt inset (matching the checkbox column) clipped long numbers.
|
|
62
|
-
paddingLeft: 16,
|
|
63
|
-
paddingRight: 12,
|
|
64
|
-
paddingTop: 10,
|
|
65
|
-
paddingBottom: 14,
|
|
66
|
-
gap: 10,
|
|
67
|
-
backgroundColor: tm.color.group
|
|
68
|
-
},
|
|
69
|
-
reason: {
|
|
70
|
-
color: tm.color.warning,
|
|
71
|
-
fontSize: tm.font.footnote
|
|
72
|
-
}
|
|
73
|
-
});
|
|
74
|
-
//# sourceMappingURL=ItemDiffPanel.js.map
|
|
1
|
+
"use strict";import{useMemo as f}from"react";import{StyleSheet as i,Text as u,View as c}from"react-native";import{ABSENT_VALUE as l,ThemedSplitView as p,devToolsDefaultTheme as m,toDiffable as r}from"@buoy-gg/shared-ui/dataViewer";import{tm as o}from"../../ui/tmTheme";import{jsxs as n,jsx as V}from"react/jsx-runtime";const g=[];export function ItemDiffPanel({item:e,testID:a}){const{oldValue:s,newValue:d}=f(()=>({oldValue:e.verdict==="added"?l:r(e.oldValue),newValue:e.verdict==="removed"?l:r(e.newValue)}),[e]);return n(c,{style:t.panel,testID:a,children:[e.reason?n(u,{style:t.reason,children:["\u26A0 ",e.reason]}):null,V(p,{oldValue:s,newValue:d,differences:g,theme:m,scrollEnabled:false})]})}const t=i.create({panel:{paddingLeft:16,paddingRight:12,paddingTop:10,paddingBottom:14,gap:10,backgroundColor:o.color.group},reason:{color:o.color.warning,fontSize:o.font.footnote}});
|
|
@@ -1,46 +1 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* The preview screen, wired to the store — the restore leg (baseline
|
|
5
|
-
* confirmation, the route prompt, landing back on the list) lives here so
|
|
6
|
-
* RestorePreviewScreen stays presentation.
|
|
7
|
-
*
|
|
8
|
-
* Kept apart from the restore-point list so each screen mounts and unmounts
|
|
9
|
-
* as a whole tree — the router in ../TimeMachineBody picks one, never swaps
|
|
10
|
-
* branches inside a live tree. (Item diffs are NOT a screen: they expand
|
|
11
|
-
* inline inside the preview's list.)
|
|
12
|
-
*/
|
|
13
|
-
import { timeMachineStore } from "../../store/timeMachineStore";
|
|
14
|
-
import { confirmDestructive } from "../confirm";
|
|
15
|
-
import { RestorePreviewScreen } from "./RestorePreviewScreen";
|
|
16
|
-
import { jsx as _jsx } from "react/jsx-runtime";
|
|
17
|
-
function snapshotFor(ref, snapshots) {
|
|
18
|
-
return ref === "current" ? undefined : snapshots.find(s => s.id === ref.snapshotId);
|
|
19
|
-
}
|
|
20
|
-
export function PreviewScreen({
|
|
21
|
-
preview,
|
|
22
|
-
snapshots,
|
|
23
|
-
busy,
|
|
24
|
-
onClose
|
|
25
|
-
}) {
|
|
26
|
-
const rightMeta = snapshotFor(preview.right, snapshots);
|
|
27
|
-
const restore = (mode, excludeKeys) => {
|
|
28
|
-
if (!rightMeta || busy) return;
|
|
29
|
-
if (rightMeta.baseline) {
|
|
30
|
-
confirmDestructive("Restore fresh install?", "This wipes all app storage and reloads the app.", "Wipe & reload", () => void timeMachineStore.restore(rightMeta.id, "reload"));
|
|
31
|
-
return;
|
|
32
|
-
}
|
|
33
|
-
// Land back on the list, where the outcome card reports the results —
|
|
34
|
-
// the preview's diff is stale the moment restore runs. Whether the route
|
|
35
|
-
// comes back is the restore point's own setting, toggled on its row.
|
|
36
|
-
void timeMachineStore.restore(rightMeta.id, mode, excludeKeys).then(onClose);
|
|
37
|
-
};
|
|
38
|
-
return /*#__PURE__*/_jsx(RestorePreviewScreen, {
|
|
39
|
-
preview: preview,
|
|
40
|
-
snapshots: snapshots,
|
|
41
|
-
busy: busy,
|
|
42
|
-
onBack: onClose,
|
|
43
|
-
onRestore: restore
|
|
44
|
-
});
|
|
45
|
-
}
|
|
46
|
-
//# sourceMappingURL=PreviewFlow.js.map
|
|
1
|
+
"use strict";import{timeMachineStore as n}from"../../store/timeMachineStore";import{confirmDestructive as p}from"../confirm";import{RestorePreviewScreen as c}from"./RestorePreviewScreen";import{jsx as f}from"react/jsx-runtime";function m(e,r){return e==="current"?void 0:r.find(t=>t.id===e.snapshotId)}export function PreviewScreen({preview:e,snapshots:r,busy:t,onClose:i}){const o=m(e.right,r);const s=(a,d)=>{if(!o||t)return;if(o.baseline){p("Restore fresh install?","This wipes all app storage and reloads the app.","Wipe & reload",()=>void n.restore(o.id,"reload"));return}void n.restore(o.id,a,d).then(i)};return f(c,{preview:e,snapshots:r,busy:t,onBack:i,onRestore:s})}
|
|
@@ -1,78 +1 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* The restore point's name, editable in place.
|
|
5
|
-
*
|
|
6
|
-
* Renaming lives on the preview rather than behind a swipe on the list: the
|
|
7
|
-
* list is for picking one, and you rarely know a name is wrong until you're
|
|
8
|
-
* looking at what the point actually contains.
|
|
9
|
-
*
|
|
10
|
-
* Commits on blur as well as on return — tapping away from a field you have
|
|
11
|
-
* just typed into should keep the typing. Finder and iOS both treat leaving
|
|
12
|
-
* as accepting, and silently discarding an edit is the one outcome nobody
|
|
13
|
-
* wants.
|
|
14
|
-
*/
|
|
15
|
-
import { useEffect, useState } from "react";
|
|
16
|
-
import { StyleSheet, Text, TextInput, View } from "react-native";
|
|
17
|
-
import { tm } from "../../ui/tmTheme";
|
|
18
|
-
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
19
|
-
export function RestorePointNameRow({
|
|
20
|
-
name,
|
|
21
|
-
onRename
|
|
22
|
-
}) {
|
|
23
|
-
const [draft, setDraft] = useState(name);
|
|
24
|
-
|
|
25
|
-
// A rename from anywhere else (MCP, the desktop) should show up here.
|
|
26
|
-
useEffect(() => setDraft(name), [name]);
|
|
27
|
-
const commit = () => {
|
|
28
|
-
const trimmed = draft.trim();
|
|
29
|
-
if (!trimmed) {
|
|
30
|
-
setDraft(name); // an empty name would make the row unidentifiable
|
|
31
|
-
return;
|
|
32
|
-
}
|
|
33
|
-
if (trimmed !== name) onRename(trimmed);
|
|
34
|
-
};
|
|
35
|
-
return /*#__PURE__*/_jsxs(View, {
|
|
36
|
-
style: styles.row,
|
|
37
|
-
children: [/*#__PURE__*/_jsx(Text, {
|
|
38
|
-
style: styles.label,
|
|
39
|
-
children: "Name"
|
|
40
|
-
}), /*#__PURE__*/_jsx(TextInput, {
|
|
41
|
-
style: styles.input,
|
|
42
|
-
value: draft,
|
|
43
|
-
onChangeText: setDraft,
|
|
44
|
-
onSubmitEditing: commit,
|
|
45
|
-
onBlur: commit,
|
|
46
|
-
returnKeyType: "done",
|
|
47
|
-
selectTextOnFocus: true,
|
|
48
|
-
accessibilityLabel: "Restore point name",
|
|
49
|
-
testID: "tm-preview-name"
|
|
50
|
-
})]
|
|
51
|
-
});
|
|
52
|
-
}
|
|
53
|
-
const styles = StyleSheet.create({
|
|
54
|
-
row: {
|
|
55
|
-
flexDirection: "row",
|
|
56
|
-
alignItems: "center",
|
|
57
|
-
gap: 14,
|
|
58
|
-
minHeight: tm.rowMinHeight,
|
|
59
|
-
paddingHorizontal: tm.textInset
|
|
60
|
-
},
|
|
61
|
-
label: {
|
|
62
|
-
color: tm.color.labelSecondary,
|
|
63
|
-
fontSize: tm.font.row,
|
|
64
|
-
letterSpacing: tm.tracking.row
|
|
65
|
-
},
|
|
66
|
-
input: {
|
|
67
|
-
flex: 1,
|
|
68
|
-
minWidth: 0,
|
|
69
|
-
color: tm.color.label,
|
|
70
|
-
fontSize: tm.font.row,
|
|
71
|
-
fontWeight: "600",
|
|
72
|
-
letterSpacing: tm.tracking.row,
|
|
73
|
-
textAlign: "right",
|
|
74
|
-
padding: 0,
|
|
75
|
-
backgroundColor: "transparent"
|
|
76
|
-
}
|
|
77
|
-
});
|
|
78
|
-
//# sourceMappingURL=RestorePointNameRow.js.map
|
|
1
|
+
"use strict";import{useEffect as c,useState as m}from"react";import{StyleSheet as f,Text as p,TextInput as g,View as u}from"react-native";import{tm as t}from"../../ui/tmTheme";import{jsx as s,jsxs as d}from"react/jsx-runtime";export function RestorePointNameRow({name:e,onRename:a}){const[n,o]=m(e);c(()=>o(e),[e]);const l=()=>{const r=n.trim();if(!r){o(e);return}if(r!==e)a(r)};return d(u,{style:i.row,children:[s(p,{style:i.label,children:"Name"}),s(g,{style:i.input,value:n,onChangeText:o,onSubmitEditing:l,onBlur:l,returnKeyType:"done",selectTextOnFocus:true,accessibilityLabel:"Restore point name",testID:"tm-preview-name"})]})}const i=f.create({row:{flexDirection:"row",alignItems:"center",gap:14,minHeight:t.rowMinHeight,paddingHorizontal:t.textInset},label:{color:t.color.labelSecondary,fontSize:t.font.row,letterSpacing:t.tracking.row},input:{flex:1,minWidth:0,color:t.color.label,fontSize:t.font.row,fontWeight:"600",letterSpacing:t.tracking.row,textAlign:"right",padding:0,backgroundColor:"transparent"}});
|