@buoy-gg/time-machine 7.0.56 → 7.0.57
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 +2 -0
- package/lib/commonjs/components/floating/TimeMachineFloatingTool.js +1 -1
- package/lib/commonjs/index.js +1 -1
- package/lib/module/components/floating/TimeMachineFloatingTool.js +1 -1
- package/lib/module/index.js +1 -1
- package/lib/typescript/components/floating/TimeMachineFloatingTool.d.ts +2 -0
- package/lib/typescript/index.d.ts +1 -1
- package/lib/web/index.mjs +2 -2
- package/package.json +6 -6
package/README.md
CHANGED
|
@@ -61,4 +61,6 @@ Device data can travel over your LAN to the configured broker. Account validatio
|
|
|
61
61
|
|
|
62
62
|
## Web support (unreleased)
|
|
63
63
|
|
|
64
|
+
In dev builds, a saved bar opens on web boot.
|
|
65
|
+
|
|
64
66
|
Register this package’s /web namespace in FloatingDevTools modules to use its shared panels and actions in a browser app. The browser build is available in this checkout and has not been published yet. See the [web setup guide](https://buoy.gg/buoy/latest/docs/web-preview) for registration, dependencies, and browser boundaries.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,"__esModule",{value:true});exports.TIME_MACHINE_FLOATING_TOOL_ID=void 0;exports.TimeMachineFloatingTool=TimeMachineFloatingTool;exports.openTimeMachineFloatingTool=openTimeMachineFloatingTool;var _react=require("react");var _reactNative=require("react-native");var _sharedUi=require("@buoy-gg/shared-ui");var _useTimeMachine=require("../../hooks/useTimeMachine");var _timeMachineStore=require("../../store/timeMachineStore");var _routeRestore=require("../../store/routeRestore");var _sourceSettings=require("../../store/sourceSettings");var _RestoreOutcomeCard=require("../list/RestoreOutcomeCard");var _format=require("../format");var _armedPoint=require("./armedPoint");var _NamePromptModal=require("./NamePromptModal");var _barSettings=require("./barSettings");var _jsxRuntime=require("react/jsx-runtime");const TIME_MACHINE_FLOATING_TOOL_ID=exports.TIME_MACHINE_FLOATING_TOOL_ID="time-machine-restore";const RECENT_MS=1e4;const FLASH_MS=900;const PICKER_ROWS=6;const registration={id:TIME_MACHINE_FLOATING_TOOL_ID,render:r=>(0,_jsxRuntime.jsx)(TimeMachineFloatingTool,{...r})};if(typeof __DEV__!=="undefined"&&__DEV__&&typeof navigator!=="undefined"&&navigator.product==="ReactNative"){(0,_sharedUi.registerPersistentFloatingTool)(registration,_sharedUi.persistentStorage)}function openTimeMachineFloatingTool(r){if(r)(0,_armedPoint.setPickedPointId)(r);(0,_sharedUi.openFloatingTool)(registration)}function failureSummary(r){const n=Object.values(r.results);const d=n.filter(y=>!y.ok||y.skipped.length>0).length;const s=n.length;const u=r.route;const o=u?.status==="failed"||u?.status==="unavailable";if(d===0&&o)return"Route did not restore";return`${d} of ${s} source${s===1?"":"s"} failed`}function failureLines(r){const n=[];for(const[s,u]of Object.entries(r.results)){if(u.ok&&u.skipped.length===0)continue;const o=u.skipped[0]?.reason??u.warnings[0]??"did not apply";n.push(`${s}: ${o}`)}const d=r.route;if(d?.status==="failed"||d?.status==="unavailable")n.push(`route: ${d.status}`);return n}function useFlash(r){const[n,d]=(0,_react.useState)(0);(0,_react.useEffect)(()=>{if(!n)return;const s=setTimeout(()=>d(0),r);return()=>clearTimeout(s)},[n,r]);return[n>0,()=>d(s=>s+1)]}function TimeMachineFloatingTool({id:r,revealToken:n,dismiss:d}){const{snapshots:s,hasLoaded:u,busy:o}=(0,_useTimeMachine.useTimeMachineState)();const y=(0,_useTimeMachine.useSnapshotProviders)();const q=(0,_react.useSyncExternalStore)(_armedPoint.subscribePickedPoint,_armedPoint.getPickedPointId,_armedPoint.getPickedPointId);const k=(0,_sharedUi.useLimit)("timeMachine.snapshots");const w=(0,_react.useSyncExternalStore)(_barSettings.subscribeBarSettings,_barSettings.getBarReloadMode,_barSettings.getBarReloadMode);const{width:B}=(0,_reactNative.useWindowDimensions)();const[f,a]=(0,_react.useState)(null);const[h,I]=(0,_react.useState)(null);const[b,p]=(0,_react.useState)();const[W,v]=(0,_react.useState)(false);const[U,G]=useFlash(FLASH_MS);const[K,X]=useFlash(FLASH_MS);const[g,M]=(0,_react.useState)(null);const[T,A]=(0,_react.useState)(null);const[,J]=(0,_react.useState)(0);const m=(0,_react.useRef)(true);(0,_react.useEffect)(()=>{m.current=true;void(0,_armedPoint.ensurePickedPointLoaded)();void(0,_barSettings.ensureBarSettingsLoaded)();void _timeMachineStore.timeMachineStore.ensureLoaded();return()=>{m.current=false}},[]);const t=(0,_armedPoint.resolveArmedPoint)(s,q);const C=t?.id;const L=t?.lastRestoredAt;const O=t?.createdAt;(0,_react.useEffect)(()=>{if(L===void 0&&O===void 0&&!g&&T===null)return;const e=setInterval(()=>J(i=>i+1),2500);return()=>clearInterval(e)},[L,O,g,T]);(0,_react.useEffect)(()=>{if(h&&h.snapshotId!==C){I(null);a(e=>e==="outcome"?null:e)}},[C,h]);const S=Date.now();const z=g!==null&&S-g.at<RECENT_MS&&s.some(e=>e.id===g.id);const Q=s.filter(e=>!e.safety);const H=Q.length>=k;const D=!t||o!==null;const _=o!==null;const E=async(e,i)=>{if(o)return;a(null);p(void 0);try{const c=await _timeMachineStore.timeMachineStore.restore(e,w&&i.safetyCapture?"reload":"live",void 0,i);if(!m.current)return;if((0,_RestoreOutcomeCard.restoreNeedsAttention)(c)){I(c);a("outcome")}else{I(null);G()}M(c.safetySnapshotId?{id:c.safetySnapshotId,at:Date.now()}:null);if(c.safetySnapshotId)A(null)}catch(c){if(!m.current)return;p(c instanceof Error?c.message:String(c));a("error")}};const F=(e=false)=>{if(!t)return;void E(t.id,{safetyCapture:true,...e?{restoreRoute:false}:{}})};const Y=()=>{if(!g)return;void E(g.id,{safetyCapture:false,restoreRoute:false}).then(()=>{if(m.current)A(Date.now())})};const Z=()=>{if(o)return;p(void 0);if(H){a("cap");return}a(null);v(true)};const ee=async e=>{v(false);if(o)return;try{const i=await _timeMachineStore.timeMachineStore.capture(e);if(!m.current)return;(0,_armedPoint.setPickedPointId)(i.id);M(null);X()}catch(i){if(!m.current)return;p(i instanceof Error?i.message:String(i));a("error")}};const te=e=>{(0,_armedPoint.setPickedPointId)(e.id);a(null)};const N=t?.name??(u?"No restore points":"Loading\u2026");let l;let P="normal";let V=false;if(o==="restore")l="Restoring\u2026";else if(o==="capture")l="Capturing\u2026";else if(b){l=b;P="danger"}else if(h&&t&&h.snapshotId===t.id){l=failureSummary(h);P="danger"}else if(!t)l=u?"Capture one with +":"";else{V=true;const e=t.lastRestoredAt===void 0?null:S-t.lastRestoredAt;const i=S-t.createdAt;if(T!==null&&S-T<RECENT_MS)l="undone, state only";else if(e!==null&&e<RECENT_MS)l="restored just now";else if(i<RECENT_MS&&e===null)l="captured just now";else if(t.lastRestoredAt!==void 0)l=`restored ${(0,_format.timeAgo)(t.lastRestoredAt)}`;else l=`${Object.keys(t.sources).length} sources`;if(w)l+=" \xB7 reloads"}const j=V&&!z&&t&&t.route&&(0,_timeMachineStore.willRestoreRoute)(t)?t.route.pathname:null;const R=s.filter(e=>!e.baseline&&!e.safety);const ie=(()=>{const e=y.filter($=>$.status().canCapture&&(0,_sourceSettings.isSourceEnabled)($.id)).length;const i=(0,_routeRestore.captureCurrentRoute)();const c=[`${e} source${e===1?"":"s"}`];if(i)c.push(i.pathname);return c.join(" \xB7 ")})();let x;if(f==="picker"){x=(0,_jsxRuntime.jsxs)(_reactNative.View,{style:styles.menu,testID:"time-machine-bar-picker",children:[(0,_jsxRuntime.jsxs)(_reactNative.ScrollView,{style:styles.pickerList,bounces:false,children:[R.map(e=>{const i=e.id===t?.id;return(0,_jsxRuntime.jsxs)(_reactNative.TouchableOpacity,{testID:`time-machine-bar-pick-${e.id}`,accessibilityRole:"button",accessibilityState:{selected:i},accessibilityLabel:`Arm ${e.name}`,onPress:()=>te(e),style:styles.pickRow,children:[(0,_jsxRuntime.jsxs)(_reactNative.View,{style:styles.pickText,children:[(0,_jsxRuntime.jsx)(_reactNative.Text,{numberOfLines:1,style:styles.pickName,children:e.name}),(0,_jsxRuntime.jsxs)(_reactNative.Text,{numberOfLines:1,style:styles.pickDetail,children:[(0,_format.timeAgo)(e.createdAt),e.route?` \xB7 ${e.route.pathname}`:"",e.lastRestoredAt!==void 0?(0,_jsxRuntime.jsx)(_reactNative.Text,{style:styles.pickRestored,children:` \xB7 restored ${(0,_format.timeAgo)(e.lastRestoredAt)}`}):null]})]}),i?(0,_jsxRuntime.jsx)(_sharedUi.Check,{size:14,color:_sharedUi.night.color.accent}):null]},e.id)}),R.length===0?(0,_jsxRuntime.jsx)(_reactNative.Text,{style:styles.menuText,children:"No restore points yet."}):null]}),R.length>PICKER_ROWS?(0,_jsxRuntime.jsxs)(_reactNative.Text,{style:styles.pickerMore,children:["Scroll for ",R.length-PICKER_ROWS," more"]}):null,(0,_jsxRuntime.jsxs)(_reactNative.View,{style:styles.settingRow,testID:"time-machine-bar-reload-mode",children:[(0,_jsxRuntime.jsxs)(_reactNative.View,{style:styles.settingText,children:[(0,_jsxRuntime.jsx)(_reactNative.Text,{style:styles.settingLabel,children:"Reload the app after restoring"}),(0,_jsxRuntime.jsx)(_reactNative.Text,{style:styles.settingHint,children:"For screens that read their state from storage only when they open, like a cart kept in a React context."})]}),(0,_jsxRuntime.jsx)(_sharedUi.NightSwitch,{value:w,onValueChange:_barSettings.setBarReloadMode})]})]})}else if(f==="outcome"&&h){x=(0,_jsxRuntime.jsxs)(_reactNative.View,{style:styles.menu,testID:"time-machine-bar-outcome",children:[failureLines(h).map(e=>(0,_jsxRuntime.jsx)(_reactNative.Text,{style:styles.menuDanger,children:e},e)),(0,_jsxRuntime.jsx)(_reactNative.Text,{style:styles.menuText,children:"The full report is on Time Machine's outcome card."}),(0,_jsxRuntime.jsx)(DismissLink,{onPress:()=>a(null)})]})}else if(f==="cap"){x=(0,_jsxRuntime.jsxs)(_reactNative.View,{style:styles.menu,testID:"time-machine-bar-cap",children:[(0,_jsxRuntime.jsxs)(_reactNative.Text,{style:styles.menuText,children:["Free plan keeps ",k," restore point",k===1?"":"s",". Delete one in Time Machine, or upgrade to Pro for unlimited snapshots."]}),(0,_jsxRuntime.jsx)(DismissLink,{onPress:()=>a(null)})]})}else if(f==="error"&&b){x=(0,_jsxRuntime.jsxs)(_reactNative.View,{style:styles.menu,testID:"time-machine-bar-error",children:[(0,_jsxRuntime.jsx)(_reactNative.Text,{accessibilityRole:"alert",style:styles.menuDanger,children:b}),(0,_jsxRuntime.jsx)(DismissLink,{onPress:()=>{a(null);p(void 0)}})]})}return(0,_jsxRuntime.jsxs)(_jsxRuntime.Fragment,{children:[(0,_jsxRuntime.jsx)(_NamePromptModal.NamePromptModal,{visible:W,summary:ie,onCapture:e=>void ee(e),onCancel:()=>v(false)}),(0,_jsxRuntime.jsx)(_sharedUi.FloatingTool,{id:r,revealToken:n,variant:"strip",dragFromSurface:true,defaultPlacement:"bottom",accessibilityLabel:`Move or hide the action bar. ${t?`${t.name} armed`:"Nothing armed"}`,accessory:x,handleAdornment:(0,_jsxRuntime.jsx)(_sharedUi.TimeMachineIcon,{size:12,color:_sharedUi.night.color.accent}),children:(0,_jsxRuntime.jsxs)(_reactNative.View,{style:[styles.row,{width:Math.max(260,Math.min(320,B-64))}],children:[(0,_jsxRuntime.jsx)(_reactNative.TouchableOpacity,{testID:"time-machine-bar-restore",accessibilityRole:"button",accessibilityLabel:t?`Restore ${t.name}`:"Restore, nothing armed",accessibilityHint:j?`Also returns to ${j}. Long press to restore state only.`:void 0,accessibilityState:{disabled:D},disabled:D,onPress:()=>F(false),onLongPress:()=>F(true),style:[styles.restoreButton,D&&styles.disabled],children:o==="restore"?(0,_jsxRuntime.jsx)(_reactNative.ActivityIndicator,{size:"small",color:_sharedUi.night.color.accent}):U?(0,_jsxRuntime.jsx)(_reactNative.Text,{style:styles.restoreText,testID:"time-machine-bar-restored",children:"Restored"}):(0,_jsxRuntime.jsx)(_reactNative.Text,{style:styles.restoreText,children:"Restore"})}),(0,_jsxRuntime.jsxs)(_reactNative.View,{style:styles.identity,children:[(0,_jsxRuntime.jsx)(_reactNative.Text,{testID:"time-machine-bar-name",accessibilityLabel:`Armed restore point: ${N}`,numberOfLines:1,ellipsizeMode:"middle",style:styles.name,children:N}),(0,_jsxRuntime.jsxs)(_reactNative.View,{style:styles.statusRow,children:[(0,_jsxRuntime.jsxs)(_reactNative.Text,{testID:"time-machine-bar-status",numberOfLines:1,accessibilityLiveRegion:"polite",style:[styles.status,P==="danger"&&styles.danger],children:[l,j?(0,_jsxRuntime.jsx)(_reactNative.Text,{style:styles.destination,children:` \xB7 \u2192 ${j}`}):null]}),z&&!o?(0,_jsxRuntime.jsx)(_reactNative.TouchableOpacity,{testID:"time-machine-bar-undo",accessibilityRole:"button",accessibilityLabel:"Undo the last restore",onPress:Y,hitSlop:{top:8,bottom:8,left:6,right:6},children:(0,_jsxRuntime.jsx)(_reactNative.Text,{style:styles.undo,children:"Undo"})}):null]})]}),(0,_jsxRuntime.jsx)(_reactNative.TouchableOpacity,{testID:"time-machine-bar-pick",accessibilityRole:"button",accessibilityLabel:"Choose another restore point",accessibilityState:{expanded:f==="picker"},onPress:()=>a(e=>e==="picker"?null:"picker"),style:styles.smallButton,children:f==="picker"?(0,_jsxRuntime.jsx)(_sharedUi.ChevronUp,{size:14,color:_sharedUi.night.color.textSecondary}):(0,_jsxRuntime.jsx)(_sharedUi.ChevronDown,{size:14,color:_sharedUi.night.color.textSecondary})}),(0,_jsxRuntime.jsx)(_reactNative.TouchableOpacity,{testID:"time-machine-bar-capture",accessibilityRole:"button",accessibilityLabel:"Capture a new restore point here and arm it",accessibilityState:{disabled:_},disabled:_,onPress:Z,style:[styles.smallButton,_&&styles.disabled],children:o==="capture"?(0,_jsxRuntime.jsx)(_reactNative.ActivityIndicator,{size:"small",color:_sharedUi.night.color.accent}):K?(0,_jsxRuntime.jsx)(_reactNative.View,{testID:"time-machine-bar-captured",children:(0,_jsxRuntime.jsx)(_sharedUi.Check,{size:18,color:_sharedUi.night.color.accent})}):(0,_jsxRuntime.jsx)(_sharedUi.Plus,{size:18,color:H?_sharedUi.night.color.textTertiary:_sharedUi.night.color.text})}),(0,_jsxRuntime.jsx)(_reactNative.View,{style:styles.separator}),(0,_jsxRuntime.jsx)(_reactNative.TouchableOpacity,{testID:"time-machine-bar-close",accessibilityRole:"button",accessibilityLabel:"Close the action bar",onPress:d,style:styles.closeButton,children:(0,_jsxRuntime.jsx)(_sharedUi.X,{size:16,color:_sharedUi.night.color.textSecondary})})]})})]})}function DismissLink({onPress:r,label:n="Dismiss"}){return(0,_jsxRuntime.jsx)(_reactNative.TouchableOpacity,{testID:"time-machine-bar-dismiss",accessibilityRole:"button",onPress:r,style:styles.dismiss,children:(0,_jsxRuntime.jsx)(_reactNative.Text,{style:styles.dismissText,children:n})})}const styles=_reactNative.StyleSheet.create({row:{flexDirection:"row",alignItems:"center",gap:4,paddingVertical:4,minHeight:48},restoreButton:{height:32,minWidth:72,paddingHorizontal:12,borderRadius:8,borderWidth:1,borderColor:_sharedUi.night.color.accentBorderStrong,backgroundColor:_sharedUi.night.color.accentSoft,alignItems:"center",justifyContent:"center",marginLeft:2},restoreText:{color:_sharedUi.night.color.accent,fontSize:12,fontWeight:"700"},smallButton:{width:32,minHeight:44,alignItems:"center",justifyContent:"center"},closeButton:{width:28,minHeight:44,alignItems:"center",justifyContent:"center"},identity:{flex:1,minHeight:44,justifyContent:"center",gap:1},name:{color:_sharedUi.night.color.text,fontSize:13,fontWeight:"500"},statusRow:{flexDirection:"row",alignItems:"center",gap:8},status:{color:_sharedUi.night.color.textSecondary,fontSize:10,lineHeight:14,flexShrink:1},destination:{color:_sharedUi.night.color.textTertiary},danger:{color:_sharedUi.night.color.danger},undo:{color:_sharedUi.night.color.accent,fontSize:10,lineHeight:14,fontWeight:"700"},separator:{height:20,width:1,backgroundColor:_sharedUi.night.color.separator,marginHorizontal:2},disabled:{opacity:.4},menu:{marginVertical:8,padding:6,borderRadius:_sharedUi.night.radius.card,borderWidth:1,borderColor:_sharedUi.night.color.separator,backgroundColor:_sharedUi.night.color.surface,shadowColor:"#000",shadowOffset:{width:0,height:6},shadowOpacity:.25,shadowRadius:16,elevation:8},menuText:{color:_sharedUi.night.color.textSecondary,fontSize:12,lineHeight:18,padding:10},menuDanger:{color:_sharedUi.night.color.danger,fontSize:12,lineHeight:18,paddingHorizontal:10,paddingTop:6},pickerList:{maxHeight:PICKER_ROWS*44},pickerMore:{color:_sharedUi.night.color.textTertiary,fontSize:10,lineHeight:14,textAlign:"center",paddingVertical:4},pickRow:{flexDirection:"row",alignItems:"center",gap:8,minHeight:44,paddingHorizontal:10,borderRadius:_sharedUi.night.radius.row},pickText:{flex:1},settingRow:{flexDirection:"row",alignItems:"center",gap:10,paddingHorizontal:10,paddingVertical:8,borderTopWidth:_reactNative.StyleSheet.hairlineWidth,borderTopColor:_sharedUi.night.color.separator,marginTop:4},settingText:{flex:1,gap:2},settingLabel:{color:_sharedUi.night.color.text,fontSize:12,fontWeight:"500"},settingHint:{color:_sharedUi.night.color.textTertiary,fontSize:10,lineHeight:13},pickName:{color:_sharedUi.night.color.text,fontSize:13,fontWeight:"500"},pickDetail:{color:_sharedUi.night.color.textSecondary,fontSize:10,lineHeight:14},pickRestored:{color:_sharedUi.night.color.accent},dismiss:{alignSelf:"flex-end",paddingHorizontal:10,paddingVertical:8},dismissText:{color:_sharedUi.night.color.accent,fontSize:12,fontWeight:"600"}});
|
|
1
|
+
"use strict";Object.defineProperty(exports,"__esModule",{value:true});exports.TIME_MACHINE_FLOATING_TOOL_ID=void 0;exports.TimeMachineFloatingTool=TimeMachineFloatingTool;exports.openTimeMachineFloatingTool=openTimeMachineFloatingTool;exports.startTimeMachineFloatingToolPersistence=startTimeMachineFloatingToolPersistence;var _react=require("react");var _reactNative=require("react-native");var _sharedUi=require("@buoy-gg/shared-ui");var _useTimeMachine=require("../../hooks/useTimeMachine");var _timeMachineStore=require("../../store/timeMachineStore");var _routeRestore=require("../../store/routeRestore");var _sourceSettings=require("../../store/sourceSettings");var _RestoreOutcomeCard=require("../list/RestoreOutcomeCard");var _format=require("../format");var _armedPoint=require("./armedPoint");var _NamePromptModal=require("./NamePromptModal");var _barSettings=require("./barSettings");var _jsxRuntime=require("react/jsx-runtime");const TIME_MACHINE_FLOATING_TOOL_ID=exports.TIME_MACHINE_FLOATING_TOOL_ID="time-machine-restore";const RECENT_MS=1e4;const FLASH_MS=900;const PICKER_ROWS=6;const registration={id:TIME_MACHINE_FLOATING_TOOL_ID,render:r=>(0,_jsxRuntime.jsx)(TimeMachineFloatingTool,{...r})};let persistenceStarted=false;function startTimeMachineFloatingToolPersistence(){if(persistenceStarted)return;persistenceStarted=true;(0,_sharedUi.registerPersistentFloatingTool)(registration,_sharedUi.persistentStorage)}if(typeof __DEV__!=="undefined"&&__DEV__&&typeof navigator!=="undefined"&&navigator.product==="ReactNative"){startTimeMachineFloatingToolPersistence()}function openTimeMachineFloatingTool(r){if(r)(0,_armedPoint.setPickedPointId)(r);(0,_sharedUi.openFloatingTool)(registration)}function failureSummary(r){const n=Object.values(r.results);const d=n.filter(y=>!y.ok||y.skipped.length>0).length;const o=n.length;const u=r.route;const s=u?.status==="failed"||u?.status==="unavailable";if(d===0&&s)return"Route did not restore";return`${d} of ${o} source${o===1?"":"s"} failed`}function failureLines(r){const n=[];for(const[o,u]of Object.entries(r.results)){if(u.ok&&u.skipped.length===0)continue;const s=u.skipped[0]?.reason??u.warnings[0]??"did not apply";n.push(`${o}: ${s}`)}const d=r.route;if(d?.status==="failed"||d?.status==="unavailable")n.push(`route: ${d.status}`);return n}function useFlash(r){const[n,d]=(0,_react.useState)(0);(0,_react.useEffect)(()=>{if(!n)return;const o=setTimeout(()=>d(0),r);return()=>clearTimeout(o)},[n,r]);return[n>0,()=>d(o=>o+1)]}function TimeMachineFloatingTool({id:r,revealToken:n,dismiss:d}){const{snapshots:o,hasLoaded:u,busy:s}=(0,_useTimeMachine.useTimeMachineState)();const y=(0,_useTimeMachine.useSnapshotProviders)();const q=(0,_react.useSyncExternalStore)(_armedPoint.subscribePickedPoint,_armedPoint.getPickedPointId,_armedPoint.getPickedPointId);const k=(0,_sharedUi.useLimit)("timeMachine.snapshots");const w=(0,_react.useSyncExternalStore)(_barSettings.subscribeBarSettings,_barSettings.getBarReloadMode,_barSettings.getBarReloadMode);const{width:B}=(0,_reactNative.useWindowDimensions)();const[f,a]=(0,_react.useState)(null);const[h,I]=(0,_react.useState)(null);const[b,p]=(0,_react.useState)();const[W,v]=(0,_react.useState)(false);const[U,G]=useFlash(FLASH_MS);const[K,X]=useFlash(FLASH_MS);const[g,_]=(0,_react.useState)(null);const[T,A]=(0,_react.useState)(null);const[,J]=(0,_react.useState)(0);const m=(0,_react.useRef)(true);(0,_react.useEffect)(()=>{m.current=true;void(0,_armedPoint.ensurePickedPointLoaded)();void(0,_barSettings.ensureBarSettingsLoaded)();void _timeMachineStore.timeMachineStore.ensureLoaded();return()=>{m.current=false}},[]);const t=(0,_armedPoint.resolveArmedPoint)(o,q);const C=t?.id;const L=t?.lastRestoredAt;const O=t?.createdAt;(0,_react.useEffect)(()=>{if(L===void 0&&O===void 0&&!g&&T===null)return;const e=setInterval(()=>J(i=>i+1),2500);return()=>clearInterval(e)},[L,O,g,T]);(0,_react.useEffect)(()=>{if(h&&h.snapshotId!==C){I(null);a(e=>e==="outcome"?null:e)}},[C,h]);const S=Date.now();const z=g!==null&&S-g.at<RECENT_MS&&o.some(e=>e.id===g.id);const Q=o.filter(e=>!e.safety);const H=Q.length>=k;const P=!t||s!==null;const D=s!==null;const F=async(e,i)=>{if(s)return;a(null);p(void 0);try{const c=await _timeMachineStore.timeMachineStore.restore(e,w&&i.safetyCapture?"reload":"live",void 0,i);if(!m.current)return;if((0,_RestoreOutcomeCard.restoreNeedsAttention)(c)){I(c);a("outcome")}else{I(null);G()}_(c.safetySnapshotId?{id:c.safetySnapshotId,at:Date.now()}:null);if(c.safetySnapshotId)A(null)}catch(c){if(!m.current)return;p(c instanceof Error?c.message:String(c));a("error")}};const E=(e=false)=>{if(!t)return;void F(t.id,{safetyCapture:true,...e?{restoreRoute:false}:{}})};const Y=()=>{if(!g)return;void F(g.id,{safetyCapture:false,restoreRoute:false}).then(()=>{if(m.current)A(Date.now())})};const Z=()=>{if(s)return;p(void 0);if(H){a("cap");return}a(null);v(true)};const ee=async e=>{v(false);if(s)return;try{const i=await _timeMachineStore.timeMachineStore.capture(e);if(!m.current)return;(0,_armedPoint.setPickedPointId)(i.id);_(null);X()}catch(i){if(!m.current)return;p(i instanceof Error?i.message:String(i));a("error")}};const te=e=>{(0,_armedPoint.setPickedPointId)(e.id);a(null)};const N=t?.name??(u?"No restore points":"Loading\u2026");let l;let M="normal";let V=false;if(s==="restore")l="Restoring\u2026";else if(s==="capture")l="Capturing\u2026";else if(b){l=b;M="danger"}else if(h&&t&&h.snapshotId===t.id){l=failureSummary(h);M="danger"}else if(!t)l=u?"Capture one with +":"";else{V=true;const e=t.lastRestoredAt===void 0?null:S-t.lastRestoredAt;const i=S-t.createdAt;if(T!==null&&S-T<RECENT_MS)l="undone, state only";else if(e!==null&&e<RECENT_MS)l="restored just now";else if(i<RECENT_MS&&e===null)l="captured just now";else if(t.lastRestoredAt!==void 0)l=`restored ${(0,_format.timeAgo)(t.lastRestoredAt)}`;else l=`${Object.keys(t.sources).length} sources`;if(w)l+=" \xB7 reloads"}const j=V&&!z&&t&&t.route&&(0,_timeMachineStore.willRestoreRoute)(t)?t.route.pathname:null;const R=o.filter(e=>!e.baseline&&!e.safety);const ie=(()=>{const e=y.filter($=>$.status().canCapture&&(0,_sourceSettings.isSourceEnabled)($.id)).length;const i=(0,_routeRestore.captureCurrentRoute)();const c=[`${e} source${e===1?"":"s"}`];if(i)c.push(i.pathname);return c.join(" \xB7 ")})();let x;if(f==="picker"){x=(0,_jsxRuntime.jsxs)(_reactNative.View,{style:styles.menu,testID:"time-machine-bar-picker",children:[(0,_jsxRuntime.jsxs)(_reactNative.ScrollView,{style:styles.pickerList,bounces:false,children:[R.map(e=>{const i=e.id===t?.id;return(0,_jsxRuntime.jsxs)(_reactNative.TouchableOpacity,{testID:`time-machine-bar-pick-${e.id}`,accessibilityRole:"button",accessibilityState:{selected:i},accessibilityLabel:`Arm ${e.name}`,onPress:()=>te(e),style:styles.pickRow,children:[(0,_jsxRuntime.jsxs)(_reactNative.View,{style:styles.pickText,children:[(0,_jsxRuntime.jsx)(_reactNative.Text,{numberOfLines:1,style:styles.pickName,children:e.name}),(0,_jsxRuntime.jsxs)(_reactNative.Text,{numberOfLines:1,style:styles.pickDetail,children:[(0,_format.timeAgo)(e.createdAt),e.route?` \xB7 ${e.route.pathname}`:"",e.lastRestoredAt!==void 0?(0,_jsxRuntime.jsx)(_reactNative.Text,{style:styles.pickRestored,children:` \xB7 restored ${(0,_format.timeAgo)(e.lastRestoredAt)}`}):null]})]}),i?(0,_jsxRuntime.jsx)(_sharedUi.Check,{size:14,color:_sharedUi.night.color.accent}):null]},e.id)}),R.length===0?(0,_jsxRuntime.jsx)(_reactNative.Text,{style:styles.menuText,children:"No restore points yet."}):null]}),R.length>PICKER_ROWS?(0,_jsxRuntime.jsxs)(_reactNative.Text,{style:styles.pickerMore,children:["Scroll for ",R.length-PICKER_ROWS," more"]}):null,(0,_jsxRuntime.jsxs)(_reactNative.View,{style:styles.settingRow,testID:"time-machine-bar-reload-mode",children:[(0,_jsxRuntime.jsxs)(_reactNative.View,{style:styles.settingText,children:[(0,_jsxRuntime.jsx)(_reactNative.Text,{style:styles.settingLabel,children:"Reload the app after restoring"}),(0,_jsxRuntime.jsx)(_reactNative.Text,{style:styles.settingHint,children:"For screens that read their state from storage only when they open, like a cart kept in a React context."})]}),(0,_jsxRuntime.jsx)(_sharedUi.NightSwitch,{value:w,onValueChange:_barSettings.setBarReloadMode})]})]})}else if(f==="outcome"&&h){x=(0,_jsxRuntime.jsxs)(_reactNative.View,{style:styles.menu,testID:"time-machine-bar-outcome",children:[failureLines(h).map(e=>(0,_jsxRuntime.jsx)(_reactNative.Text,{style:styles.menuDanger,children:e},e)),(0,_jsxRuntime.jsx)(_reactNative.Text,{style:styles.menuText,children:"The full report is on Time Machine's outcome card."}),(0,_jsxRuntime.jsx)(DismissLink,{onPress:()=>a(null)})]})}else if(f==="cap"){x=(0,_jsxRuntime.jsxs)(_reactNative.View,{style:styles.menu,testID:"time-machine-bar-cap",children:[(0,_jsxRuntime.jsxs)(_reactNative.Text,{style:styles.menuText,children:["Free plan keeps ",k," restore point",k===1?"":"s",". Delete one in Time Machine, or upgrade to Pro for unlimited snapshots."]}),(0,_jsxRuntime.jsx)(DismissLink,{onPress:()=>a(null)})]})}else if(f==="error"&&b){x=(0,_jsxRuntime.jsxs)(_reactNative.View,{style:styles.menu,testID:"time-machine-bar-error",children:[(0,_jsxRuntime.jsx)(_reactNative.Text,{accessibilityRole:"alert",style:styles.menuDanger,children:b}),(0,_jsxRuntime.jsx)(DismissLink,{onPress:()=>{a(null);p(void 0)}})]})}return(0,_jsxRuntime.jsxs)(_jsxRuntime.Fragment,{children:[(0,_jsxRuntime.jsx)(_NamePromptModal.NamePromptModal,{visible:W,summary:ie,onCapture:e=>void ee(e),onCancel:()=>v(false)}),(0,_jsxRuntime.jsx)(_sharedUi.FloatingTool,{id:r,revealToken:n,variant:"strip",dragFromSurface:true,defaultPlacement:"bottom",accessibilityLabel:`Move or hide the action bar. ${t?`${t.name} armed`:"Nothing armed"}`,accessory:x,handleAdornment:(0,_jsxRuntime.jsx)(_sharedUi.TimeMachineIcon,{size:12,color:_sharedUi.night.color.accent}),children:(0,_jsxRuntime.jsxs)(_reactNative.View,{style:[styles.row,{width:Math.max(260,Math.min(320,B-64))}],children:[(0,_jsxRuntime.jsx)(_reactNative.TouchableOpacity,{testID:"time-machine-bar-restore",accessibilityRole:"button",accessibilityLabel:t?`Restore ${t.name}`:"Restore, nothing armed",accessibilityHint:j?`Also returns to ${j}. Long press to restore state only.`:void 0,accessibilityState:{disabled:P},disabled:P,onPress:()=>E(false),onLongPress:()=>E(true),style:[styles.restoreButton,P&&styles.disabled],children:s==="restore"?(0,_jsxRuntime.jsx)(_reactNative.ActivityIndicator,{size:"small",color:_sharedUi.night.color.accent}):U?(0,_jsxRuntime.jsx)(_reactNative.Text,{style:styles.restoreText,testID:"time-machine-bar-restored",children:"Restored"}):(0,_jsxRuntime.jsx)(_reactNative.Text,{style:styles.restoreText,children:"Restore"})}),(0,_jsxRuntime.jsxs)(_reactNative.View,{style:styles.identity,children:[(0,_jsxRuntime.jsx)(_reactNative.Text,{testID:"time-machine-bar-name",accessibilityLabel:`Armed restore point: ${N}`,numberOfLines:1,ellipsizeMode:"middle",style:styles.name,children:N}),(0,_jsxRuntime.jsxs)(_reactNative.View,{style:styles.statusRow,children:[(0,_jsxRuntime.jsxs)(_reactNative.Text,{testID:"time-machine-bar-status",numberOfLines:1,accessibilityLiveRegion:"polite",style:[styles.status,M==="danger"&&styles.danger],children:[l,j?(0,_jsxRuntime.jsx)(_reactNative.Text,{style:styles.destination,children:` \xB7 \u2192 ${j}`}):null]}),z&&!s?(0,_jsxRuntime.jsx)(_reactNative.TouchableOpacity,{testID:"time-machine-bar-undo",accessibilityRole:"button",accessibilityLabel:"Undo the last restore",onPress:Y,hitSlop:{top:8,bottom:8,left:6,right:6},children:(0,_jsxRuntime.jsx)(_reactNative.Text,{style:styles.undo,children:"Undo"})}):null]})]}),(0,_jsxRuntime.jsx)(_reactNative.TouchableOpacity,{testID:"time-machine-bar-pick",accessibilityRole:"button",accessibilityLabel:"Choose another restore point",accessibilityState:{expanded:f==="picker"},onPress:()=>a(e=>e==="picker"?null:"picker"),style:styles.smallButton,children:f==="picker"?(0,_jsxRuntime.jsx)(_sharedUi.ChevronUp,{size:14,color:_sharedUi.night.color.textSecondary}):(0,_jsxRuntime.jsx)(_sharedUi.ChevronDown,{size:14,color:_sharedUi.night.color.textSecondary})}),(0,_jsxRuntime.jsx)(_reactNative.TouchableOpacity,{testID:"time-machine-bar-capture",accessibilityRole:"button",accessibilityLabel:"Capture a new restore point here and arm it",accessibilityState:{disabled:D},disabled:D,onPress:Z,style:[styles.smallButton,D&&styles.disabled],children:s==="capture"?(0,_jsxRuntime.jsx)(_reactNative.ActivityIndicator,{size:"small",color:_sharedUi.night.color.accent}):K?(0,_jsxRuntime.jsx)(_reactNative.View,{testID:"time-machine-bar-captured",children:(0,_jsxRuntime.jsx)(_sharedUi.Check,{size:18,color:_sharedUi.night.color.accent})}):(0,_jsxRuntime.jsx)(_sharedUi.Plus,{size:18,color:H?_sharedUi.night.color.textTertiary:_sharedUi.night.color.text})}),(0,_jsxRuntime.jsx)(_reactNative.View,{style:styles.separator}),(0,_jsxRuntime.jsx)(_reactNative.TouchableOpacity,{testID:"time-machine-bar-close",accessibilityRole:"button",accessibilityLabel:"Close the action bar",onPress:d,style:styles.closeButton,children:(0,_jsxRuntime.jsx)(_sharedUi.X,{size:16,color:_sharedUi.night.color.textSecondary})})]})})]})}function DismissLink({onPress:r,label:n="Dismiss"}){return(0,_jsxRuntime.jsx)(_reactNative.TouchableOpacity,{testID:"time-machine-bar-dismiss",accessibilityRole:"button",onPress:r,style:styles.dismiss,children:(0,_jsxRuntime.jsx)(_reactNative.Text,{style:styles.dismissText,children:n})})}const styles=_reactNative.StyleSheet.create({row:{flexDirection:"row",alignItems:"center",gap:4,paddingVertical:4,minHeight:48},restoreButton:{height:32,minWidth:72,paddingHorizontal:12,borderRadius:8,borderWidth:1,borderColor:_sharedUi.night.color.accentBorderStrong,backgroundColor:_sharedUi.night.color.accentSoft,alignItems:"center",justifyContent:"center",marginLeft:2},restoreText:{color:_sharedUi.night.color.accent,fontSize:12,fontWeight:"700"},smallButton:{width:32,minHeight:44,alignItems:"center",justifyContent:"center"},closeButton:{width:28,minHeight:44,alignItems:"center",justifyContent:"center"},identity:{flex:1,minHeight:44,justifyContent:"center",gap:1},name:{color:_sharedUi.night.color.text,fontSize:13,fontWeight:"500"},statusRow:{flexDirection:"row",alignItems:"center",gap:8},status:{color:_sharedUi.night.color.textSecondary,fontSize:10,lineHeight:14,flexShrink:1},destination:{color:_sharedUi.night.color.textTertiary},danger:{color:_sharedUi.night.color.danger},undo:{color:_sharedUi.night.color.accent,fontSize:10,lineHeight:14,fontWeight:"700"},separator:{height:20,width:1,backgroundColor:_sharedUi.night.color.separator,marginHorizontal:2},disabled:{opacity:.4},menu:{marginVertical:8,padding:6,borderRadius:_sharedUi.night.radius.card,borderWidth:1,borderColor:_sharedUi.night.color.separator,backgroundColor:_sharedUi.night.color.surface,shadowColor:"#000",shadowOffset:{width:0,height:6},shadowOpacity:.25,shadowRadius:16,elevation:8},menuText:{color:_sharedUi.night.color.textSecondary,fontSize:12,lineHeight:18,padding:10},menuDanger:{color:_sharedUi.night.color.danger,fontSize:12,lineHeight:18,paddingHorizontal:10,paddingTop:6},pickerList:{maxHeight:PICKER_ROWS*44},pickerMore:{color:_sharedUi.night.color.textTertiary,fontSize:10,lineHeight:14,textAlign:"center",paddingVertical:4},pickRow:{flexDirection:"row",alignItems:"center",gap:8,minHeight:44,paddingHorizontal:10,borderRadius:_sharedUi.night.radius.row},pickText:{flex:1},settingRow:{flexDirection:"row",alignItems:"center",gap:10,paddingHorizontal:10,paddingVertical:8,borderTopWidth:_reactNative.StyleSheet.hairlineWidth,borderTopColor:_sharedUi.night.color.separator,marginTop:4},settingText:{flex:1,gap:2},settingLabel:{color:_sharedUi.night.color.text,fontSize:12,fontWeight:"500"},settingHint:{color:_sharedUi.night.color.textTertiary,fontSize:10,lineHeight:13},pickName:{color:_sharedUi.night.color.text,fontSize:13,fontWeight:"500"},pickDetail:{color:_sharedUi.night.color.textSecondary,fontSize:10,lineHeight:14},pickRestored:{color:_sharedUi.night.color.accent},dismiss:{alignSelf:"flex-end",paddingHorizontal:10,paddingVertical:8},dismissText:{color:_sharedUi.night.color.accent,fontSize:12,fontWeight:"600"}});
|
package/lib/commonjs/index.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,"__esModule",{value:true});Object.defineProperty(exports,"RESTORE_ORDER",{enumerable:true,get:function(){return _timeMachineStore.RESTORE_ORDER}});Object.defineProperty(exports,"SAFETY_SNAPSHOT_NAME",{enumerable:true,get:function(){return _timeMachineStore.SAFETY_SNAPSHOT_NAME}});Object.defineProperty(exports,"TIME_MACHINE_FLOATING_TOOL_ID",{enumerable:true,get:function(){return _TimeMachineFloatingTool.TIME_MACHINE_FLOATING_TOOL_ID}});Object.defineProperty(exports,"TimeMachineModal",{enumerable:true,get:function(){return _TimeMachineModal.TimeMachineModal}});Object.defineProperty(exports,"TimeMachineToolView",{enumerable:true,get:function(){return _TimeMachineModal.TimeMachineToolView}});Object.defineProperty(exports,"armPendingRouteRestore",{enumerable:true,get:function(){return _routeRestore.armPendingRouteRestore}});Object.defineProperty(exports,"canRestoreRoute",{enumerable:true,get:function(){return _routeRestore.canNavigate}});Object.defineProperty(exports,"captureCurrentRoute",{enumerable:true,get:function(){return _routeRestore.captureCurrentRoute}});Object.defineProperty(exports,"createTimeMachineTool",{enumerable:true,get:function(){return _preset.createTimeMachineTool}});Object.defineProperty(exports,"isSourceEnabled",{enumerable:true,get:function(){return _sourceSettings.isSourceEnabled}});Object.defineProperty(exports,"navigateToRoute",{enumerable:true,get:function(){return _routeRestore.navigateToRoute}});Object.defineProperty(exports,"openTimeMachineFloatingTool",{enumerable:true,get:function(){return _TimeMachineFloatingTool.openTimeMachineFloatingTool}});Object.defineProperty(exports,"replaceTimeMachineFromSnapshot",{enumerable:true,get:function(){return _timeMachineStore.replaceTimeMachineFromSnapshot}});Object.defineProperty(exports,"setRemoteTimeMachineHandler",{enumerable:true,get:function(){return _timeMachineStore.setRemoteTimeMachineHandler}});Object.defineProperty(exports,"setSourceEnabled",{enumerable:true,get:function(){return _sourceSettings.setSourceEnabled}});Object.defineProperty(exports,"subscribeSourceSettings",{enumerable:true,get:function(){return _sourceSettings.subscribeSourceSettings}});Object.defineProperty(exports,"timeMachineStore",{enumerable:true,get:function(){return _timeMachineStore.timeMachineStore}});Object.defineProperty(exports,"timeMachineSyncAdapter",{enumerable:true,get:function(){return _timeMachineSyncAdapter.timeMachineSyncAdapter}});Object.defineProperty(exports,"timeMachineToolPreset",{enumerable:true,get:function(){return _preset.timeMachineToolPreset}});var _routeRestore=require("./store/routeRestore");var _preset=require("./preset");var _TimeMachineModal=require("./components/TimeMachineModal");var _TimeMachineFloatingTool=require("./components/floating/TimeMachineFloatingTool");var _timeMachineSyncAdapter=require("./sync/timeMachineSyncAdapter");var _timeMachineStore=require("./store/timeMachineStore");var _sourceSettings=require("./store/sourceSettings");(0,_routeRestore.armPendingRouteRestore)();
|
|
1
|
+
"use strict";Object.defineProperty(exports,"__esModule",{value:true});Object.defineProperty(exports,"RESTORE_ORDER",{enumerable:true,get:function(){return _timeMachineStore.RESTORE_ORDER}});Object.defineProperty(exports,"SAFETY_SNAPSHOT_NAME",{enumerable:true,get:function(){return _timeMachineStore.SAFETY_SNAPSHOT_NAME}});Object.defineProperty(exports,"TIME_MACHINE_FLOATING_TOOL_ID",{enumerable:true,get:function(){return _TimeMachineFloatingTool.TIME_MACHINE_FLOATING_TOOL_ID}});Object.defineProperty(exports,"TimeMachineModal",{enumerable:true,get:function(){return _TimeMachineModal.TimeMachineModal}});Object.defineProperty(exports,"TimeMachineToolView",{enumerable:true,get:function(){return _TimeMachineModal.TimeMachineToolView}});Object.defineProperty(exports,"armPendingRouteRestore",{enumerable:true,get:function(){return _routeRestore.armPendingRouteRestore}});Object.defineProperty(exports,"canRestoreRoute",{enumerable:true,get:function(){return _routeRestore.canNavigate}});Object.defineProperty(exports,"captureCurrentRoute",{enumerable:true,get:function(){return _routeRestore.captureCurrentRoute}});Object.defineProperty(exports,"createTimeMachineTool",{enumerable:true,get:function(){return _preset.createTimeMachineTool}});Object.defineProperty(exports,"isSourceEnabled",{enumerable:true,get:function(){return _sourceSettings.isSourceEnabled}});Object.defineProperty(exports,"navigateToRoute",{enumerable:true,get:function(){return _routeRestore.navigateToRoute}});Object.defineProperty(exports,"openTimeMachineFloatingTool",{enumerable:true,get:function(){return _TimeMachineFloatingTool.openTimeMachineFloatingTool}});Object.defineProperty(exports,"replaceTimeMachineFromSnapshot",{enumerable:true,get:function(){return _timeMachineStore.replaceTimeMachineFromSnapshot}});Object.defineProperty(exports,"setRemoteTimeMachineHandler",{enumerable:true,get:function(){return _timeMachineStore.setRemoteTimeMachineHandler}});Object.defineProperty(exports,"setSourceEnabled",{enumerable:true,get:function(){return _sourceSettings.setSourceEnabled}});Object.defineProperty(exports,"startTimeMachineFloatingToolPersistence",{enumerable:true,get:function(){return _TimeMachineFloatingTool.startTimeMachineFloatingToolPersistence}});Object.defineProperty(exports,"subscribeSourceSettings",{enumerable:true,get:function(){return _sourceSettings.subscribeSourceSettings}});Object.defineProperty(exports,"timeMachineStore",{enumerable:true,get:function(){return _timeMachineStore.timeMachineStore}});Object.defineProperty(exports,"timeMachineSyncAdapter",{enumerable:true,get:function(){return _timeMachineSyncAdapter.timeMachineSyncAdapter}});Object.defineProperty(exports,"timeMachineToolPreset",{enumerable:true,get:function(){return _preset.timeMachineToolPreset}});var _routeRestore=require("./store/routeRestore");var _preset=require("./preset");var _TimeMachineModal=require("./components/TimeMachineModal");var _TimeMachineFloatingTool=require("./components/floating/TimeMachineFloatingTool");var _timeMachineSyncAdapter=require("./sync/timeMachineSyncAdapter");var _timeMachineStore=require("./store/timeMachineStore");var _sourceSettings=require("./store/sourceSettings");(0,_routeRestore.armPendingRouteRestore)();
|
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";import{useEffect as P,useRef as Le,useState as S,useSyncExternalStore as ne}from"react";import{ActivityIndicator as ie,ScrollView as Ce,StyleSheet as se,Text as s,TouchableOpacity as x,View as p,useWindowDimensions as Ae}from"react-native";import{Check as le,ChevronDown as ve,ChevronUp as ze,FloatingTool as Pe,NightSwitch as He,Plus as Me,TimeMachineIcon as _e,X as $e,night as r,openFloatingTool as Fe,persistentStorage as je,registerPersistentFloatingTool as Ne,useLimit as Oe}from"@buoy-gg/shared-ui";import{useSnapshotProviders as Ee,useTimeMachineState as We}from"../../hooks/useTimeMachine";import{timeMachineStore as E,willRestoreRoute as Be}from"../../store/timeMachineStore";import{captureCurrentRoute as Ve}from"../../store/routeRestore";import{isSourceEnabled as Ue}from"../../store/sourceSettings";import{restoreNeedsAttention as Ge}from"../list/RestoreOutcomeCard";import{timeAgo as W}from"../format";import{ensurePickedPointLoaded as Ke,getPickedPointId as ae,resolveArmedPoint as Xe,setPickedPointId as B,subscribePickedPoint as qe}from"./armedPoint";import{NamePromptModal as Je}from"./NamePromptModal";import{ensureBarSettingsLoaded as Qe,getBarReloadMode as ce,setBarReloadMode as Ye,subscribeBarSettings as Ze}from"./barSettings";import{jsx as o,jsxs as a,Fragment as et}from"react/jsx-runtime";export const TIME_MACHINE_FLOATING_TOOL_ID="time-machine-restore";const H=1e4;const de=900;const V=6;const ue={id:TIME_MACHINE_FLOATING_TOOL_ID,render:l=>o(TimeMachineFloatingTool,{...l})};if(typeof __DEV__!=="undefined"&&__DEV__&&typeof navigator!=="undefined"&&navigator.product==="ReactNative"){Ne(ue,je)}export function openTimeMachineFloatingTool(l){if(l)B(l);Fe(ue)}function tt(l){const c=Object.values(l.results);const g=c.filter(D=>!D.ok||D.skipped.length>0).length;const u=c.length;const y=l.route;const d=y?.status==="failed"||y?.status==="unavailable";if(g===0&&d)return"Route did not restore";return`${g} of ${u} source${u===1?"":"s"} failed`}function ot(l){const c=[];for(const[u,y]of Object.entries(l.results)){if(y.ok&&y.skipped.length===0)continue;const d=y.skipped[0]?.reason??y.warnings[0]??"did not apply";c.push(`${u}: ${d}`)}const g=l.route;if(g?.status==="failed"||g?.status==="unavailable")c.push(`route: ${g.status}`);return c}function he(l){const[c,g]=S(0);P(()=>{if(!c)return;const u=setTimeout(()=>g(0),l);return()=>clearTimeout(u)},[c,l]);return[c>0,()=>g(u=>u+1)]}export function TimeMachineFloatingTool({id:l,revealToken:c,dismiss:g}){const{snapshots:u,hasLoaded:y,busy:d}=We();const D=Ee();const me=ne(qe,ae,ae);const M=Oe("timeMachine.snapshots");const _=ne(Ze,ce,ce);const{width:fe}=Ae();const[T,h]=S(null);const[b,$]=S(null);const[L,w]=S();const[pe,F]=S(false);const[ge,ye]=he(de);const[be,Se]=he(de);const[R,G]=S(null);const[C,K]=S(null);const[,Re]=S(0);const k=Le(true);P(()=>{k.current=true;void Ke();void Qe();void E.ensureLoaded();return()=>{k.current=false}},[]);const n=Xe(u,me);const X=n?.id;const q=n?.lastRestoredAt;const J=n?.createdAt;P(()=>{if(q===void 0&&J===void 0&&!R&&C===null)return;const e=setInterval(()=>Re(i=>i+1),2500);return()=>clearInterval(e)},[q,J,R,C]);P(()=>{if(b&&b.snapshotId!==X){$(null);h(e=>e==="outcome"?null:e)}},[X,b]);const A=Date.now();const Q=R!==null&&A-R.at<H&&u.some(e=>e.id===R.id);const ke=u.filter(e=>!e.safety);const Y=ke.length>=M;const j=!n||d!==null;const N=d!==null;const Z=async(e,i)=>{if(d)return;h(null);w(void 0);try{const f=await E.restore(e,_&&i.safetyCapture?"reload":"live",void 0,i);if(!k.current)return;if(Ge(f)){$(f);h("outcome")}else{$(null);ye()}G(f.safetySnapshotId?{id:f.safetySnapshotId,at:Date.now()}:null);if(f.safetySnapshotId)K(null)}catch(f){if(!k.current)return;w(f instanceof Error?f.message:String(f));h("error")}};const ee=(e=false)=>{if(!n)return;void Z(n.id,{safetyCapture:true,...e?{restoreRoute:false}:{}})};const xe=()=>{if(!R)return;void Z(R.id,{safetyCapture:false,restoreRoute:false}).then(()=>{if(k.current)K(Date.now())})};const Te=()=>{if(d)return;w(void 0);if(Y){h("cap");return}h(null);F(true)};const we=async e=>{F(false);if(d)return;try{const i=await E.capture(e);if(!k.current)return;B(i.id);G(null);Se()}catch(i){if(!k.current)return;w(i instanceof Error?i.message:String(i));h("error")}};const Ie=e=>{B(e.id);h(null)};const te=n?.name??(y?"No restore points":"Loading\u2026");let m;let O="normal";let oe=false;if(d==="restore")m="Restoring\u2026";else if(d==="capture")m="Capturing\u2026";else if(L){m=L;O="danger"}else if(b&&n&&b.snapshotId===n.id){m=tt(b);O="danger"}else if(!n)m=y?"Capture one with +":"";else{oe=true;const e=n.lastRestoredAt===void 0?null:A-n.lastRestoredAt;const i=A-n.createdAt;if(C!==null&&A-C<H)m="undone, state only";else if(e!==null&&e<H)m="restored just now";else if(i<H&&e===null)m="captured just now";else if(n.lastRestoredAt!==void 0)m=`restored ${W(n.lastRestoredAt)}`;else m=`${Object.keys(n.sources).length} sources`;if(_)m+=" \xB7 reloads"}const v=oe&&!Q&&n&&n.route&&Be(n)?n.route.pathname:null;const z=u.filter(e=>!e.baseline&&!e.safety);const De=(()=>{const e=D.filter(re=>re.status().canCapture&&Ue(re.id)).length;const i=Ve();const f=[`${e} source${e===1?"":"s"}`];if(i)f.push(i.pathname);return f.join(" \xB7 ")})();let I;if(T==="picker"){I=a(p,{style:t.menu,testID:"time-machine-bar-picker",children:[a(Ce,{style:t.pickerList,bounces:false,children:[z.map(e=>{const i=e.id===n?.id;return a(x,{testID:`time-machine-bar-pick-${e.id}`,accessibilityRole:"button",accessibilityState:{selected:i},accessibilityLabel:`Arm ${e.name}`,onPress:()=>Ie(e),style:t.pickRow,children:[a(p,{style:t.pickText,children:[o(s,{numberOfLines:1,style:t.pickName,children:e.name}),a(s,{numberOfLines:1,style:t.pickDetail,children:[W(e.createdAt),e.route?` \xB7 ${e.route.pathname}`:"",e.lastRestoredAt!==void 0?o(s,{style:t.pickRestored,children:` \xB7 restored ${W(e.lastRestoredAt)}`}):null]})]}),i?o(le,{size:14,color:r.color.accent}):null]},e.id)}),z.length===0?o(s,{style:t.menuText,children:"No restore points yet."}):null]}),z.length>V?a(s,{style:t.pickerMore,children:["Scroll for ",z.length-V," more"]}):null,a(p,{style:t.settingRow,testID:"time-machine-bar-reload-mode",children:[a(p,{style:t.settingText,children:[o(s,{style:t.settingLabel,children:"Reload the app after restoring"}),o(s,{style:t.settingHint,children:"For screens that read their state from storage only when they open, like a cart kept in a React context."})]}),o(He,{value:_,onValueChange:Ye})]})]})}else if(T==="outcome"&&b){I=a(p,{style:t.menu,testID:"time-machine-bar-outcome",children:[ot(b).map(e=>o(s,{style:t.menuDanger,children:e},e)),o(s,{style:t.menuText,children:"The full report is on Time Machine's outcome card."}),o(U,{onPress:()=>h(null)})]})}else if(T==="cap"){I=a(p,{style:t.menu,testID:"time-machine-bar-cap",children:[a(s,{style:t.menuText,children:["Free plan keeps ",M," restore point",M===1?"":"s",". Delete one in Time Machine, or upgrade to Pro for unlimited snapshots."]}),o(U,{onPress:()=>h(null)})]})}else if(T==="error"&&L){I=a(p,{style:t.menu,testID:"time-machine-bar-error",children:[o(s,{accessibilityRole:"alert",style:t.menuDanger,children:L}),o(U,{onPress:()=>{h(null);w(void 0)}})]})}return a(et,{children:[o(Je,{visible:pe,summary:De,onCapture:e=>void we(e),onCancel:()=>F(false)}),o(Pe,{id:l,revealToken:c,variant:"strip",dragFromSurface:true,defaultPlacement:"bottom",accessibilityLabel:`Move or hide the action bar. ${n?`${n.name} armed`:"Nothing armed"}`,accessory:I,handleAdornment:o(_e,{size:12,color:r.color.accent}),children:a(p,{style:[t.row,{width:Math.max(260,Math.min(320,fe-64))}],children:[o(x,{testID:"time-machine-bar-restore",accessibilityRole:"button",accessibilityLabel:n?`Restore ${n.name}`:"Restore, nothing armed",accessibilityHint:v?`Also returns to ${v}. Long press to restore state only.`:void 0,accessibilityState:{disabled:j},disabled:j,onPress:()=>ee(false),onLongPress:()=>ee(true),style:[t.restoreButton,j&&t.disabled],children:d==="restore"?o(ie,{size:"small",color:r.color.accent}):ge?o(s,{style:t.restoreText,testID:"time-machine-bar-restored",children:"Restored"}):o(s,{style:t.restoreText,children:"Restore"})}),a(p,{style:t.identity,children:[o(s,{testID:"time-machine-bar-name",accessibilityLabel:`Armed restore point: ${te}`,numberOfLines:1,ellipsizeMode:"middle",style:t.name,children:te}),a(p,{style:t.statusRow,children:[a(s,{testID:"time-machine-bar-status",numberOfLines:1,accessibilityLiveRegion:"polite",style:[t.status,O==="danger"&&t.danger],children:[m,v?o(s,{style:t.destination,children:` \xB7 \u2192 ${v}`}):null]}),Q&&!d?o(x,{testID:"time-machine-bar-undo",accessibilityRole:"button",accessibilityLabel:"Undo the last restore",onPress:xe,hitSlop:{top:8,bottom:8,left:6,right:6},children:o(s,{style:t.undo,children:"Undo"})}):null]})]}),o(x,{testID:"time-machine-bar-pick",accessibilityRole:"button",accessibilityLabel:"Choose another restore point",accessibilityState:{expanded:T==="picker"},onPress:()=>h(e=>e==="picker"?null:"picker"),style:t.smallButton,children:T==="picker"?o(ze,{size:14,color:r.color.textSecondary}):o(ve,{size:14,color:r.color.textSecondary})}),o(x,{testID:"time-machine-bar-capture",accessibilityRole:"button",accessibilityLabel:"Capture a new restore point here and arm it",accessibilityState:{disabled:N},disabled:N,onPress:Te,style:[t.smallButton,N&&t.disabled],children:d==="capture"?o(ie,{size:"small",color:r.color.accent}):be?o(p,{testID:"time-machine-bar-captured",children:o(le,{size:18,color:r.color.accent})}):o(Me,{size:18,color:Y?r.color.textTertiary:r.color.text})}),o(p,{style:t.separator}),o(x,{testID:"time-machine-bar-close",accessibilityRole:"button",accessibilityLabel:"Close the action bar",onPress:g,style:t.closeButton,children:o($e,{size:16,color:r.color.textSecondary})})]})})]})}function U({onPress:l,label:c="Dismiss"}){return o(x,{testID:"time-machine-bar-dismiss",accessibilityRole:"button",onPress:l,style:t.dismiss,children:o(s,{style:t.dismissText,children:c})})}const t=se.create({row:{flexDirection:"row",alignItems:"center",gap:4,paddingVertical:4,minHeight:48},restoreButton:{height:32,minWidth:72,paddingHorizontal:12,borderRadius:8,borderWidth:1,borderColor:r.color.accentBorderStrong,backgroundColor:r.color.accentSoft,alignItems:"center",justifyContent:"center",marginLeft:2},restoreText:{color:r.color.accent,fontSize:12,fontWeight:"700"},smallButton:{width:32,minHeight:44,alignItems:"center",justifyContent:"center"},closeButton:{width:28,minHeight:44,alignItems:"center",justifyContent:"center"},identity:{flex:1,minHeight:44,justifyContent:"center",gap:1},name:{color:r.color.text,fontSize:13,fontWeight:"500"},statusRow:{flexDirection:"row",alignItems:"center",gap:8},status:{color:r.color.textSecondary,fontSize:10,lineHeight:14,flexShrink:1},destination:{color:r.color.textTertiary},danger:{color:r.color.danger},undo:{color:r.color.accent,fontSize:10,lineHeight:14,fontWeight:"700"},separator:{height:20,width:1,backgroundColor:r.color.separator,marginHorizontal:2},disabled:{opacity:.4},menu:{marginVertical:8,padding:6,borderRadius:r.radius.card,borderWidth:1,borderColor:r.color.separator,backgroundColor:r.color.surface,shadowColor:"#000",shadowOffset:{width:0,height:6},shadowOpacity:.25,shadowRadius:16,elevation:8},menuText:{color:r.color.textSecondary,fontSize:12,lineHeight:18,padding:10},menuDanger:{color:r.color.danger,fontSize:12,lineHeight:18,paddingHorizontal:10,paddingTop:6},pickerList:{maxHeight:V*44},pickerMore:{color:r.color.textTertiary,fontSize:10,lineHeight:14,textAlign:"center",paddingVertical:4},pickRow:{flexDirection:"row",alignItems:"center",gap:8,minHeight:44,paddingHorizontal:10,borderRadius:r.radius.row},pickText:{flex:1},settingRow:{flexDirection:"row",alignItems:"center",gap:10,paddingHorizontal:10,paddingVertical:8,borderTopWidth:se.hairlineWidth,borderTopColor:r.color.separator,marginTop:4},settingText:{flex:1,gap:2},settingLabel:{color:r.color.text,fontSize:12,fontWeight:"500"},settingHint:{color:r.color.textTertiary,fontSize:10,lineHeight:13},pickName:{color:r.color.text,fontSize:13,fontWeight:"500"},pickDetail:{color:r.color.textSecondary,fontSize:10,lineHeight:14},pickRestored:{color:r.color.accent},dismiss:{alignSelf:"flex-end",paddingHorizontal:10,paddingVertical:8},dismissText:{color:r.color.accent,fontSize:12,fontWeight:"600"}});
|
|
1
|
+
"use strict";import{useEffect as z,useRef as Ce,useState as S,useSyncExternalStore as ne}from"react";import{ActivityIndicator as ie,ScrollView as Ae,StyleSheet as se,Text as s,TouchableOpacity as k,View as p,useWindowDimensions as ve}from"react-native";import{Check as le,ChevronDown as Pe,ChevronUp as ze,FloatingTool as He,NightSwitch as Me,Plus as _e,TimeMachineIcon as $e,X as Fe,night as r,openFloatingTool as je,persistentStorage as Ne,registerPersistentFloatingTool as Oe,useLimit as Ee}from"@buoy-gg/shared-ui";import{useSnapshotProviders as We,useTimeMachineState as Be}from"../../hooks/useTimeMachine";import{timeMachineStore as E,willRestoreRoute as Ve}from"../../store/timeMachineStore";import{captureCurrentRoute as Ue}from"../../store/routeRestore";import{isSourceEnabled as Ge}from"../../store/sourceSettings";import{restoreNeedsAttention as Ke}from"../list/RestoreOutcomeCard";import{timeAgo as W}from"../format";import{ensurePickedPointLoaded as Xe,getPickedPointId as ae,resolveArmedPoint as qe,setPickedPointId as B,subscribePickedPoint as Je}from"./armedPoint";import{NamePromptModal as Qe}from"./NamePromptModal";import{ensureBarSettingsLoaded as Ye,getBarReloadMode as ce,setBarReloadMode as Ze,subscribeBarSettings as et}from"./barSettings";import{jsx as o,jsxs as a,Fragment as tt}from"react/jsx-runtime";export const TIME_MACHINE_FLOATING_TOOL_ID="time-machine-restore";const H=1e4;const de=900;const V=6;const ue={id:TIME_MACHINE_FLOATING_TOOL_ID,render:l=>o(TimeMachineFloatingTool,{...l})};let he=false;export function startTimeMachineFloatingToolPersistence(){if(he)return;he=true;Oe(ue,Ne)}if(typeof __DEV__!=="undefined"&&__DEV__&&typeof navigator!=="undefined"&&navigator.product==="ReactNative"){startTimeMachineFloatingToolPersistence()}export function openTimeMachineFloatingTool(l){if(l)B(l);je(ue)}function ot(l){const c=Object.values(l.results);const g=c.filter(D=>!D.ok||D.skipped.length>0).length;const u=c.length;const y=l.route;const d=y?.status==="failed"||y?.status==="unavailable";if(g===0&&d)return"Route did not restore";return`${g} of ${u} source${u===1?"":"s"} failed`}function rt(l){const c=[];for(const[u,y]of Object.entries(l.results)){if(y.ok&&y.skipped.length===0)continue;const d=y.skipped[0]?.reason??y.warnings[0]??"did not apply";c.push(`${u}: ${d}`)}const g=l.route;if(g?.status==="failed"||g?.status==="unavailable")c.push(`route: ${g.status}`);return c}function me(l){const[c,g]=S(0);z(()=>{if(!c)return;const u=setTimeout(()=>g(0),l);return()=>clearTimeout(u)},[c,l]);return[c>0,()=>g(u=>u+1)]}export function TimeMachineFloatingTool({id:l,revealToken:c,dismiss:g}){const{snapshots:u,hasLoaded:y,busy:d}=Be();const D=We();const fe=ne(Je,ae,ae);const M=Ee("timeMachine.snapshots");const _=ne(et,ce,ce);const{width:pe}=ve();const[T,h]=S(null);const[b,$]=S(null);const[L,w]=S();const[ge,F]=S(false);const[ye,be]=me(de);const[Se,Re]=me(de);const[R,G]=S(null);const[C,K]=S(null);const[,xe]=S(0);const x=Ce(true);z(()=>{x.current=true;void Xe();void Ye();void E.ensureLoaded();return()=>{x.current=false}},[]);const n=qe(u,fe);const X=n?.id;const q=n?.lastRestoredAt;const J=n?.createdAt;z(()=>{if(q===void 0&&J===void 0&&!R&&C===null)return;const e=setInterval(()=>xe(i=>i+1),2500);return()=>clearInterval(e)},[q,J,R,C]);z(()=>{if(b&&b.snapshotId!==X){$(null);h(e=>e==="outcome"?null:e)}},[X,b]);const A=Date.now();const Q=R!==null&&A-R.at<H&&u.some(e=>e.id===R.id);const ke=u.filter(e=>!e.safety);const Y=ke.length>=M;const j=!n||d!==null;const N=d!==null;const Z=async(e,i)=>{if(d)return;h(null);w(void 0);try{const f=await E.restore(e,_&&i.safetyCapture?"reload":"live",void 0,i);if(!x.current)return;if(Ke(f)){$(f);h("outcome")}else{$(null);be()}G(f.safetySnapshotId?{id:f.safetySnapshotId,at:Date.now()}:null);if(f.safetySnapshotId)K(null)}catch(f){if(!x.current)return;w(f instanceof Error?f.message:String(f));h("error")}};const ee=(e=false)=>{if(!n)return;void Z(n.id,{safetyCapture:true,...e?{restoreRoute:false}:{}})};const Te=()=>{if(!R)return;void Z(R.id,{safetyCapture:false,restoreRoute:false}).then(()=>{if(x.current)K(Date.now())})};const we=()=>{if(d)return;w(void 0);if(Y){h("cap");return}h(null);F(true)};const Ie=async e=>{F(false);if(d)return;try{const i=await E.capture(e);if(!x.current)return;B(i.id);G(null);Re()}catch(i){if(!x.current)return;w(i instanceof Error?i.message:String(i));h("error")}};const De=e=>{B(e.id);h(null)};const te=n?.name??(y?"No restore points":"Loading\u2026");let m;let O="normal";let oe=false;if(d==="restore")m="Restoring\u2026";else if(d==="capture")m="Capturing\u2026";else if(L){m=L;O="danger"}else if(b&&n&&b.snapshotId===n.id){m=ot(b);O="danger"}else if(!n)m=y?"Capture one with +":"";else{oe=true;const e=n.lastRestoredAt===void 0?null:A-n.lastRestoredAt;const i=A-n.createdAt;if(C!==null&&A-C<H)m="undone, state only";else if(e!==null&&e<H)m="restored just now";else if(i<H&&e===null)m="captured just now";else if(n.lastRestoredAt!==void 0)m=`restored ${W(n.lastRestoredAt)}`;else m=`${Object.keys(n.sources).length} sources`;if(_)m+=" \xB7 reloads"}const v=oe&&!Q&&n&&n.route&&Ve(n)?n.route.pathname:null;const P=u.filter(e=>!e.baseline&&!e.safety);const Le=(()=>{const e=D.filter(re=>re.status().canCapture&&Ge(re.id)).length;const i=Ue();const f=[`${e} source${e===1?"":"s"}`];if(i)f.push(i.pathname);return f.join(" \xB7 ")})();let I;if(T==="picker"){I=a(p,{style:t.menu,testID:"time-machine-bar-picker",children:[a(Ae,{style:t.pickerList,bounces:false,children:[P.map(e=>{const i=e.id===n?.id;return a(k,{testID:`time-machine-bar-pick-${e.id}`,accessibilityRole:"button",accessibilityState:{selected:i},accessibilityLabel:`Arm ${e.name}`,onPress:()=>De(e),style:t.pickRow,children:[a(p,{style:t.pickText,children:[o(s,{numberOfLines:1,style:t.pickName,children:e.name}),a(s,{numberOfLines:1,style:t.pickDetail,children:[W(e.createdAt),e.route?` \xB7 ${e.route.pathname}`:"",e.lastRestoredAt!==void 0?o(s,{style:t.pickRestored,children:` \xB7 restored ${W(e.lastRestoredAt)}`}):null]})]}),i?o(le,{size:14,color:r.color.accent}):null]},e.id)}),P.length===0?o(s,{style:t.menuText,children:"No restore points yet."}):null]}),P.length>V?a(s,{style:t.pickerMore,children:["Scroll for ",P.length-V," more"]}):null,a(p,{style:t.settingRow,testID:"time-machine-bar-reload-mode",children:[a(p,{style:t.settingText,children:[o(s,{style:t.settingLabel,children:"Reload the app after restoring"}),o(s,{style:t.settingHint,children:"For screens that read their state from storage only when they open, like a cart kept in a React context."})]}),o(Me,{value:_,onValueChange:Ze})]})]})}else if(T==="outcome"&&b){I=a(p,{style:t.menu,testID:"time-machine-bar-outcome",children:[rt(b).map(e=>o(s,{style:t.menuDanger,children:e},e)),o(s,{style:t.menuText,children:"The full report is on Time Machine's outcome card."}),o(U,{onPress:()=>h(null)})]})}else if(T==="cap"){I=a(p,{style:t.menu,testID:"time-machine-bar-cap",children:[a(s,{style:t.menuText,children:["Free plan keeps ",M," restore point",M===1?"":"s",". Delete one in Time Machine, or upgrade to Pro for unlimited snapshots."]}),o(U,{onPress:()=>h(null)})]})}else if(T==="error"&&L){I=a(p,{style:t.menu,testID:"time-machine-bar-error",children:[o(s,{accessibilityRole:"alert",style:t.menuDanger,children:L}),o(U,{onPress:()=>{h(null);w(void 0)}})]})}return a(tt,{children:[o(Qe,{visible:ge,summary:Le,onCapture:e=>void Ie(e),onCancel:()=>F(false)}),o(He,{id:l,revealToken:c,variant:"strip",dragFromSurface:true,defaultPlacement:"bottom",accessibilityLabel:`Move or hide the action bar. ${n?`${n.name} armed`:"Nothing armed"}`,accessory:I,handleAdornment:o($e,{size:12,color:r.color.accent}),children:a(p,{style:[t.row,{width:Math.max(260,Math.min(320,pe-64))}],children:[o(k,{testID:"time-machine-bar-restore",accessibilityRole:"button",accessibilityLabel:n?`Restore ${n.name}`:"Restore, nothing armed",accessibilityHint:v?`Also returns to ${v}. Long press to restore state only.`:void 0,accessibilityState:{disabled:j},disabled:j,onPress:()=>ee(false),onLongPress:()=>ee(true),style:[t.restoreButton,j&&t.disabled],children:d==="restore"?o(ie,{size:"small",color:r.color.accent}):ye?o(s,{style:t.restoreText,testID:"time-machine-bar-restored",children:"Restored"}):o(s,{style:t.restoreText,children:"Restore"})}),a(p,{style:t.identity,children:[o(s,{testID:"time-machine-bar-name",accessibilityLabel:`Armed restore point: ${te}`,numberOfLines:1,ellipsizeMode:"middle",style:t.name,children:te}),a(p,{style:t.statusRow,children:[a(s,{testID:"time-machine-bar-status",numberOfLines:1,accessibilityLiveRegion:"polite",style:[t.status,O==="danger"&&t.danger],children:[m,v?o(s,{style:t.destination,children:` \xB7 \u2192 ${v}`}):null]}),Q&&!d?o(k,{testID:"time-machine-bar-undo",accessibilityRole:"button",accessibilityLabel:"Undo the last restore",onPress:Te,hitSlop:{top:8,bottom:8,left:6,right:6},children:o(s,{style:t.undo,children:"Undo"})}):null]})]}),o(k,{testID:"time-machine-bar-pick",accessibilityRole:"button",accessibilityLabel:"Choose another restore point",accessibilityState:{expanded:T==="picker"},onPress:()=>h(e=>e==="picker"?null:"picker"),style:t.smallButton,children:T==="picker"?o(ze,{size:14,color:r.color.textSecondary}):o(Pe,{size:14,color:r.color.textSecondary})}),o(k,{testID:"time-machine-bar-capture",accessibilityRole:"button",accessibilityLabel:"Capture a new restore point here and arm it",accessibilityState:{disabled:N},disabled:N,onPress:we,style:[t.smallButton,N&&t.disabled],children:d==="capture"?o(ie,{size:"small",color:r.color.accent}):Se?o(p,{testID:"time-machine-bar-captured",children:o(le,{size:18,color:r.color.accent})}):o(_e,{size:18,color:Y?r.color.textTertiary:r.color.text})}),o(p,{style:t.separator}),o(k,{testID:"time-machine-bar-close",accessibilityRole:"button",accessibilityLabel:"Close the action bar",onPress:g,style:t.closeButton,children:o(Fe,{size:16,color:r.color.textSecondary})})]})})]})}function U({onPress:l,label:c="Dismiss"}){return o(k,{testID:"time-machine-bar-dismiss",accessibilityRole:"button",onPress:l,style:t.dismiss,children:o(s,{style:t.dismissText,children:c})})}const t=se.create({row:{flexDirection:"row",alignItems:"center",gap:4,paddingVertical:4,minHeight:48},restoreButton:{height:32,minWidth:72,paddingHorizontal:12,borderRadius:8,borderWidth:1,borderColor:r.color.accentBorderStrong,backgroundColor:r.color.accentSoft,alignItems:"center",justifyContent:"center",marginLeft:2},restoreText:{color:r.color.accent,fontSize:12,fontWeight:"700"},smallButton:{width:32,minHeight:44,alignItems:"center",justifyContent:"center"},closeButton:{width:28,minHeight:44,alignItems:"center",justifyContent:"center"},identity:{flex:1,minHeight:44,justifyContent:"center",gap:1},name:{color:r.color.text,fontSize:13,fontWeight:"500"},statusRow:{flexDirection:"row",alignItems:"center",gap:8},status:{color:r.color.textSecondary,fontSize:10,lineHeight:14,flexShrink:1},destination:{color:r.color.textTertiary},danger:{color:r.color.danger},undo:{color:r.color.accent,fontSize:10,lineHeight:14,fontWeight:"700"},separator:{height:20,width:1,backgroundColor:r.color.separator,marginHorizontal:2},disabled:{opacity:.4},menu:{marginVertical:8,padding:6,borderRadius:r.radius.card,borderWidth:1,borderColor:r.color.separator,backgroundColor:r.color.surface,shadowColor:"#000",shadowOffset:{width:0,height:6},shadowOpacity:.25,shadowRadius:16,elevation:8},menuText:{color:r.color.textSecondary,fontSize:12,lineHeight:18,padding:10},menuDanger:{color:r.color.danger,fontSize:12,lineHeight:18,paddingHorizontal:10,paddingTop:6},pickerList:{maxHeight:V*44},pickerMore:{color:r.color.textTertiary,fontSize:10,lineHeight:14,textAlign:"center",paddingVertical:4},pickRow:{flexDirection:"row",alignItems:"center",gap:8,minHeight:44,paddingHorizontal:10,borderRadius:r.radius.row},pickText:{flex:1},settingRow:{flexDirection:"row",alignItems:"center",gap:10,paddingHorizontal:10,paddingVertical:8,borderTopWidth:se.hairlineWidth,borderTopColor:r.color.separator,marginTop:4},settingText:{flex:1,gap:2},settingLabel:{color:r.color.text,fontSize:12,fontWeight:"500"},settingHint:{color:r.color.textTertiary,fontSize:10,lineHeight:13},pickName:{color:r.color.text,fontSize:13,fontWeight:"500"},pickDetail:{color:r.color.textSecondary,fontSize:10,lineHeight:14},pickRestored:{color:r.color.accent},dismiss:{alignSelf:"flex-end",paddingHorizontal:10,paddingVertical:8},dismissText:{color:r.color.accent,fontSize:12,fontWeight:"600"}});
|
package/lib/module/index.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";import{armPendingRouteRestore as e}from"./store/routeRestore";export{timeMachineToolPreset,createTimeMachineTool}from"./preset";export{TimeMachineModal,TimeMachineToolView}from"./components/TimeMachineModal";export{openTimeMachineFloatingTool,TIME_MACHINE_FLOATING_TOOL_ID}from"./components/floating/TimeMachineFloatingTool";export{timeMachineSyncAdapter}from"./sync/timeMachineSyncAdapter";export{timeMachineStore,RESTORE_ORDER,SAFETY_SNAPSHOT_NAME}from"./store/timeMachineStore";export{armPendingRouteRestore,captureCurrentRoute,navigateToRoute,canNavigate as canRestoreRoute}from"./store/routeRestore";export{isSourceEnabled,setSourceEnabled,subscribeSourceSettings}from"./store/sourceSettings";export{setRemoteTimeMachineHandler,replaceTimeMachineFromSnapshot}from"./store/timeMachineStore";e();
|
|
1
|
+
"use strict";import{armPendingRouteRestore as e}from"./store/routeRestore";export{timeMachineToolPreset,createTimeMachineTool}from"./preset";export{TimeMachineModal,TimeMachineToolView}from"./components/TimeMachineModal";export{openTimeMachineFloatingTool,startTimeMachineFloatingToolPersistence,TIME_MACHINE_FLOATING_TOOL_ID}from"./components/floating/TimeMachineFloatingTool";export{timeMachineSyncAdapter}from"./sync/timeMachineSyncAdapter";export{timeMachineStore,RESTORE_ORDER,SAFETY_SNAPSHOT_NAME}from"./store/timeMachineStore";export{armPendingRouteRestore,captureCurrentRoute,navigateToRoute,canNavigate as canRestoreRoute}from"./store/routeRestore";export{isSourceEnabled,setSourceEnabled,subscribeSourceSettings}from"./store/sourceSettings";export{setRemoteTimeMachineHandler,replaceTimeMachineFromSnapshot}from"./store/timeMachineStore";e();
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import { type FloatingToolRenderContext } from "@buoy-gg/shared-ui";
|
|
2
2
|
export declare const TIME_MACHINE_FLOATING_TOOL_ID = "time-machine-restore";
|
|
3
|
+
/** Restore saved bars when the app host starts. */
|
|
4
|
+
export declare function startTimeMachineFloatingToolPersistence(): void;
|
|
3
5
|
/** Open (or reveal) the restore bar, optionally arming a specific point. */
|
|
4
6
|
export declare function openTimeMachineFloatingTool(armId?: string): void;
|
|
5
7
|
export declare function TimeMachineFloatingTool({ id, revealToken, dismiss, }: FloatingToolRenderContext): import("react").JSX.Element;
|
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
*/
|
|
12
12
|
export { timeMachineToolPreset, createTimeMachineTool } from "./preset";
|
|
13
13
|
export { TimeMachineModal, TimeMachineToolView, type TimeMachineModalProps, } from "./components/TimeMachineModal";
|
|
14
|
-
export { openTimeMachineFloatingTool, TIME_MACHINE_FLOATING_TOOL_ID, } from "./components/floating/TimeMachineFloatingTool";
|
|
14
|
+
export { openTimeMachineFloatingTool, startTimeMachineFloatingToolPersistence, TIME_MACHINE_FLOATING_TOOL_ID, } from "./components/floating/TimeMachineFloatingTool";
|
|
15
15
|
export { timeMachineSyncAdapter } from "./sync/timeMachineSyncAdapter";
|
|
16
16
|
export { timeMachineStore, RESTORE_ORDER, SAFETY_SNAPSHOT_NAME, type RestoreMode, type RestoreOptions, type RestoreOutcome, type TimeMachineState, type RemoteProviderStatus, type PreviewSource, } from "./store/timeMachineStore";
|
|
17
17
|
export { armPendingRouteRestore, captureCurrentRoute, navigateToRoute, canNavigate as canRestoreRoute, type SnapshotRoute, type RouteRestoreResult, type RouteRestoreStatus, } from "./store/routeRestore";
|
package/lib/web/index.mjs
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
"use client";var pr=Object.defineProperty;var To=Object.getOwnPropertyDescriptor;var Co=Object.getOwnPropertyNames;var $o=Object.prototype.hasOwnProperty;var zo=(e,t)=>{for(var r in t)pr(e,r,{get:t[r],enumerable:true})},mr=(e,t,r,i)=>{if(t&&typeof t=="object"||typeof t=="function")for(let n of Co(t))!$o.call(e,n)&&n!==r&&pr(e,n,{get:()=>t[n],enumerable:!(i=To(t,n))||i.enumerable});return e},Lo=(e,t,r)=>(mr(e,t,"default"),r&&mr(r,t,"default"));var fr=process.env.NODE_ENV!=="production";typeof window<"u"&&typeof globalThis.global>"u"&&(globalThis.global=globalThis);import{getSafeCurrentRoute as Po,getSafeRouter as gr,persistentStorage as kt}from"@buoy-gg/shared-ui/web";var Tt="@react_buoy_time_machine:pending-route",Ao=6e4,Oo=8e3,Ho=250;function Eo(e){return{pathname:e.pathname,href:e.href}}function ot(){let e=Po();return e?Eo(e):null}function Bo(){return ot()}function He(){return gr()!=null}function Ct(e){let t={pathname:e.pathname,href:e.href},r=gr();if(!r?.navigate)return{...t,status:"unavailable",error:"expo-router is not available on this device"};try{return r.navigate(e.href),{...t,status:"navigated"}}catch(i){return{...t,status:"failed",error:String(i)}}}async function Wo(e,t){let r={...e,savedAt:Date.now(),...t?{snapshotName:t}:{}};await kt.setItem(Tt,JSON.stringify(r))}async function jo(){try{await kt.removeItem(Tt)}catch{}}async function No(){try{let e=await kt.getItem(Tt);if(!e)return null;let t=JSON.parse(e);return typeof t?.href!="string"||!t.href||typeof t.savedAt!="number"?null:{pathname:typeof t.pathname=="string"?t.pathname:t.href,href:t.href,savedAt:t.savedAt,snapshotName:typeof t.snapshotName=="string"?t.snapshotName:void 0}}catch{return null}}var br=false;function yr(){br||(br=true,(async()=>{let e=await No();if(!e||(await jo(),Date.now()-e.savedAt>Ao))return;let t=Date.now()+Oo;for(;!He()&&Date.now()<t;)await new Promise(r=>setTimeout(r,100));He()&&(await new Promise(r=>setTimeout(r,Ho)),Ct({pathname:e.pathname,href:e.href}))})())}var wr={};zo(wr,{AccessibilityInfo:()=>_o,ActivityIndicator:()=>at,Alert:()=>Dr,Animated:()=>Ee,AppRegistry:()=>qo,AppState:()=>Jo,Appearance:()=>Ko,BackHandler:()=>Uo,Button:()=>Ln,CheckBox:()=>cn,Clipboard:()=>Yo,DeviceEventEmitter:()=>In,Dimensions:()=>Xo,Easing:()=>Go,FlatList:()=>vr,I18nManager:()=>Qo,Image:()=>dn,ImageBackground:()=>un,InteractionManager:()=>en,Keyboard:()=>Zo,KeyboardAvoidingView:()=>xr,LayoutAnimation:()=>tn,Linking:()=>rn,LogBox:()=>xn,Modal:()=>Rr,NativeEventEmitter:()=>on,NativeModules:()=>Fo,PanResponder:()=>Sr,Picker:()=>hn,PixelRatio:()=>nn,Platform:()=>nt,Pressable:()=>$t,ProgressBar:()=>pn,RefreshControl:()=>mn,SafeAreaView:()=>fn,ScrollView:()=>zt,SectionList:()=>gn,Share:()=>an,StatusBar:()=>bn,StyleSheet:()=>O,Switch:()=>zn,Text:()=>c,TextInput:()=>it,Touchable:()=>yn,TouchableHighlight:()=>Cn,TouchableNativeFeedback:()=>wn,TouchableOpacity:()=>P,TouchableWithoutFeedback:()=>$n,UIManager:()=>sn,Vibration:()=>ln,View:()=>u,VirtualizedList:()=>Sn,YellowBox:()=>vn,findNodeHandle:()=>Pn,unstable_createElement:()=>Vo,useColorScheme:()=>Rn,useLocaleContext:()=>Dn,useWindowDimensions:()=>Ir});Lo(wr,Mo);import*as Mo from"react-native-web";import{unstable_createElement as Vo,NativeModules as Fo,AccessibilityInfo as _o,Animated as Ee,Appearance as Ko,AppRegistry as qo,AppState as Jo,BackHandler as Uo,Clipboard as Yo,Dimensions as Xo,Easing as Go,I18nManager as Qo,Keyboard as Zo,InteractionManager as en,LayoutAnimation as tn,Linking as rn,NativeEventEmitter as on,PanResponder as Sr,PixelRatio as nn,Platform as nt,Share as an,StyleSheet as O,UIManager as sn,Vibration as ln,CheckBox as cn,FlatList as vr,Image as dn,ImageBackground as un,KeyboardAvoidingView as xr,Picker as hn,ProgressBar as pn,RefreshControl as mn,SafeAreaView as fn,SectionList as gn,StatusBar as bn,Touchable as yn,TouchableNativeFeedback as wn,VirtualizedList as Sn,YellowBox as vn,LogBox as xn,DeviceEventEmitter as In,useColorScheme as Rn,useLocaleContext as Dn,useWindowDimensions as Ir}from"react-native-web";import*as J from"react-native-web";import{createElement as kn,forwardRef as Tn}from"react";function Q(e){let t=Tn((i,n)=>{let{accessibilityState:a,accessibilityValue:s,...h}=i;for(let m of["busy","checked","disabled","expanded","selected"])a?.[m]!==void 0&&h[`aria-${m}`]===void 0&&(h[`aria-${m}`]=a[m]);for(let[m,y]of Object.entries({min:"valuemin",max:"valuemax",now:"valuenow",text:"valuetext"}))s?.[m]!==void 0&&h[`aria-${y}`]===void 0&&(h[`aria-${y}`]=s[m]);return kn(e,{...h,ref:n})}),r=e.State;return r&&Object.assign(t,{State:r}),t.displayName=e.displayName??e.name??"NativeWebView",t}var u=Q(J.View),c=Q(J.Text),it=Q(J.TextInput),P=Q(J.TouchableOpacity),Cn=Q(J.TouchableHighlight),$n=Q(J.TouchableWithoutFeedback),$t=Q(J.Pressable),zt=Q(J.ScrollView),Rr=Q(J.Modal),zn=Q(J.Switch),at=Q(J.ActivityIndicator),Ln=Q(J.Button),Pn=J.findNodeHandle,Dr={alert(e,t,r,i){if(typeof document>"u")return;let n=document.createElement("dialog");n.dataset.buoyRoot="",n.setAttribute("aria-label",e),n.style.cssText="position:fixed;inset:0;margin:auto;width:min(440px,90vw);padding:24px;border:1px solid #475569;border-radius:14px;background:#17212e;color:#f1f5f9;font:14px system-ui;box-shadow:0 20px 80px #0008;z-index:2147483647";let a=document.createElement("h2");if(a.textContent=e,a.style.cssText="font-size:18px;margin:0 0 12px",n.appendChild(a),t){let y=document.createElement("p");y.textContent=t,y.style.cssText="line-height:1.5;white-space:pre-wrap;margin:0 0 20px",n.appendChild(y)}let s=document.createElement("div");s.style.cssText="display:flex;justify-content:flex-end;flex-wrap:wrap;gap:8px";let h=r?.length?r:[{text:"OK"}],m=()=>{n.close?.(),n.remove()};for(let y of h){let d=document.createElement("button");d.type="button",d.textContent=y.text??"OK",d.style.cssText=`padding:9px 14px;border:1px solid #64748b;border-radius:7px;color:white;background:${y.style==="destructive"?"#a52b38":"#283a4d"};cursor:pointer;font:inherit`,d.onclick=()=>{m(),y.onPress?.()},s.appendChild(d)}n.addEventListener("cancel",y=>{y.preventDefault(),i?.cancelable!==false&&(m(),i?.onDismiss?.())}),n.appendChild(s),document.body.appendChild(n),n.showModal?n.showModal():n.setAttribute("open","")}};import{TimeMachineIcon as An,TIME_MACHINE_ICON_COLOR as On}from"@buoy-gg/shared-ui/web";import{useRef as Hn,useState as kr,useSyncExternalStore as Tr}from"react";import{useSafeAreaInsets as En,useLimit as Bn,ToolEmptyState as Wn,getFloatingTools as jn,subscribeFloatingTools as Nn}from"@buoy-gg/shared-ui/web";import{useToolHost as Mn}from"@buoy-gg/core/web";import{useEffect as Vn,useState as Fn,useSyncExternalStore as _n}from"react";import{getStateSnapshotProviders as Lt,subscribeToStateSnapshotProviders as Kn}from"@buoy-gg/shared-ui/web";import{getStateSnapshotProvider as Cr,getStateSnapshotProviders as st,scheduleReloadApp as qn,superJsonDeserialize as Pt,superJsonSerialize as Jn}from"@buoy-gg/shared-ui/web";import{objectDiff as Un}from"@buoy-gg/shared-ui/web/dataViewer";import{persistentStorage as me}from"@buoy-gg/shared-ui/web";var At="@react_buoy_time_machine:index",Be="@react_buoy_time_machine:snap:";async function Yn(){try{let e=await me.getItem(At);if(!e)return[];let t=JSON.parse(e);return Array.isArray(t)?t:[]}catch{return[]}}async function Ot(e){await me.setItem(At,JSON.stringify(e))}async function lt(e,t){let r=JSON.stringify(e);e.meta.sizeBytes=r.length,await me.setItem(Be+e.meta.id,JSON.stringify(e));let i=[e.meta,...t.filter(n=>n.id!==e.meta.id)];return await Ot(i),i}async function fe(e){try{let t=await me.getItem(Be+e);return t?JSON.parse(t):null}catch{return null}}async function $r(e,t){await me.removeItem(Be+e);let r=t.filter(i=>i.id!==e);return await Ot(r),r}async function ct(e,t,r){let i=s=>s.id===e?t(s):s,n=r.map(i);await me.setItem(At,JSON.stringify(n));let a=await fe(e);return a&&(a.meta=i(a.meta),await me.setItem(Be+e,JSON.stringify(a))),n}function Xn(e,t,r){return ct(e,i=>{let n={...i};return t&&t.length>0?n.scope=t:delete n.scope,n},r)}function Gn(e,t,r){return ct(e,i=>{let n={...i};return delete n.scope,t&&t.length>0?n.excludedKeys=t:delete n.excludedKeys,n},r)}function Qn(e,t,r){return ct(e,i=>({...i,restoreRoute:t}),r)}function zr(e,t,r){return ct(e,i=>({...i,lastRestoredAt:t}),r)}async function Zn(e,t,r){let i=await fe(e);if(!i)return null;let n={meta:{...i.meta,id:`${i.meta.id}_copy_${Date.now().toString(36)}`,name:t,createdAt:Date.now(),lastRestoredAt:void 0},data:i.data};return delete n.meta.lastRestoredAt,{metas:await lt(n,r),meta:n.meta}}async function ei(e){return fe(e)}async function ti(e,t){return lt(e,t)}async function ri(e,t,r){let i=r.map(a=>a.id===e?{...a,name:t}:a);await Ot(i);let n=await fe(e);return n&&(n.meta.name=t,await me.setItem(Be+e,JSON.stringify(n))),i}import{definePersistedSetting as oi,devToolsStorageKeys as ni}from"@buoy-gg/shared-ui/web";var Lr=oi(ni.timeMachine.disabledSources(),[],{sanitize:e=>Array.isArray(e)?e.filter(t=>typeof t=="string"):[]}),xe=new Set,Pr=false,Ht=null,Et=new Set,Ar=()=>Et.forEach(e=>e());function ae(){return Pr?Promise.resolve():(Ht||(Ht=Lr.load().then(e=>{xe.size===0&&(xe=new Set(e),Ar())}).finally(()=>{Pr=true})),Ht)}function Or(e){return Et.add(e),()=>{Et.delete(e)}}function Hr(){return xe}function se(e){return!xe.has(e)}function Er(e,t){if(t===!xe.has(e))return;let r=new Set(xe);t?r.delete(e):r.add(e),xe=r,Ar(),Lr.save([...r])}var We="route";var je=["storage","redux","zustand","jotai","query"];function ii(e){let t=new Date,r=`${String(t.getHours()).padStart(2,"0")}:${String(t.getMinutes()).padStart(2,"0")}`,i=e?e.pathname==="/"?"Home":e.pathname:null;return i?`${i} \xB7 ${r}`:`Snapshot \xB7 ${r}`}function ai(e,t){let r=new Set(t.map(i=>i.name));if(!r.has(e))return e;for(let i=2;i<1e3;i++){let n=`${e} (${i})`;if(!r.has(n))return n}return e}function dt(e){return!!e.route&&(e.restoreRoute??true)}var Bt="Before last restore",A=null;function Ne(e){return{ok:false,applied:0,skipped:[{id:"*",reason:e}],warnings:[]}}var Br=0;function Wr(){return Br+=1,`snap_${Date.now().toString(36)}_${Br.toString(36)}`}var si=class{constructor(){this.state={snapshots:[],hasLoaded:false,busy:null,lastOutcome:null,preview:null,remoteProviders:null,remoteRoute:null,recentlyDeleted:null};this.previewRunId=0;this.listeners=new Set;this.loadPromise=null;this.subscribe=e=>(this.listeners.add(e),this.ensureLoaded(),()=>{this.listeners.delete(e)})}getState(){return this.state}setState(e){this.state={...this.state,...e},this.listeners.forEach(t=>{try{t()}catch{}})}ensureLoaded(){return A?Promise.resolve():(this.loadPromise||(this.loadPromise=Yn().then(e=>{A||this.setState({snapshots:e,hasLoaded:true})})),this.loadPromise)}replaceFromSnapshot(e){this.setState({snapshots:e.snapshots??[],busy:e.busy??null,lastOutcome:e.lastOutcome??null,remoteProviders:e.providers??[],remoteRoute:e.route??{available:false},hasLoaded:true})}async capture(e,t,r){if(A)return(await A("capture",{name:e,sourceIds:t})).snapshot;await this.ensureLoaded(),await ae(),this.setState({busy:"capture"});try{let i=st().filter(d=>d.status().canCapture&&se(d.id)&&(!t||t.includes(d.id))),n={},a={};for(let d of i)try{let k=await d.capture();n[d.id]=Jn(k.data),a[d.id]={warnings:k.warnings}}catch(k){a[d.id]={warnings:[`capture failed: ${String(k)}`]}}let s=se(We)?ot():null,h=this.state.snapshots;if(r?.safety)for(let d of h.filter(k=>k.safety))h=await $r(d.id,h);let m={meta:{id:Wr(),name:r?.safety?Bt:ai(e.trim()||ii(s),h),createdAt:Date.now(),sizeBytes:0,...s?{route:s}:{},...r?.safety?{safety:true}:{},sources:a},data:n},y=await lt(m,h);return this.setState({snapshots:y}),m.meta}finally{this.setState({busy:null})}}async captureBaseline(){if(A)return(await A("captureBaseline",{})).snapshot;await this.ensureLoaded(),await ae();let e={meta:{id:Wr(),name:"Fresh install",createdAt:Date.now(),sizeBytes:0,baseline:true,sources:{}},data:{}},t=await lt(e,this.state.snapshots);return this.setState({snapshots:t}),e.meta}async restore(e,t,r,i){if(A){let a=await A("restore",{id:e,mode:t,excludeKeys:r,restoreRoute:i?.restoreRoute});return this.setState({lastOutcome:a}),a}await this.ensureLoaded(),await ae();let n;i?.safetyCapture&&!this.state.snapshots.find(a=>a.id===e)?.safety&&(n=(await this.capture(Bt,void 0,{safety:true})).id),this.setState({busy:"restore"});try{let a=await fe(e);if(!a)throw new Error(`No snapshot with id "${e}"`);let s={snapshotId:e,snapshotName:a.meta.name,mode:t,at:Date.now(),willReload:false,results:{},...n?{safetySnapshotId:n}:{}};if(a.meta.baseline){for(let b of st())if(b.clear)try{s.results[b.id]=await b.clear()}catch(H){s.results[b.id]=Ne(String(H))}return s.willReload=this.scheduleReload("buoy time-machine baseline"),this.setState({lastOutcome:s}),s}let h=[...je.filter(b=>b in a.data),...Object.keys(a.data).filter(b=>!je.includes(b))],m=b=>{let H=new Map;for(let W of b){let j=W.indexOf("::");if(j<=0)continue;let w=W.slice(0,j),U=W.slice(j+2),ee=H.get(w)??[];ee.push(U),H.set(w,ee)}return H},y=r??a.meta.excludedKeys??[],d=m(y),k=!r&&a.meta.scope?.length?m(a.meta.scope):null,L=se(We)&&(i?.restoreRoute??dt(a.meta));if(t==="reload"){if(a.data.storage&&se("storage")&&(!k||k.has("storage"))&&(s.results.storage=await this.restoreSource("storage",a.data.storage,d.get("storage"),k?.get("storage"))),L){let b=a.meta.route;try{await Wo(b,a.meta.name),s.route={...b,status:"deferred"}}catch(H){s.route={...b,status:"failed",error:String(H)}}}return s.willReload=this.scheduleReload("buoy time-machine restore"),this.setState({lastOutcome:s,snapshots:await zr(e,s.at,this.state.snapshots)}),s}for(let b of h)if(!(k&&!k.has(b))){if(!se(b)){s.results[b]={ok:true,applied:0,skipped:[],warnings:["Switched off in Sources; left as it is"]};continue}s.results[b]=await this.restoreSource(b,a.data[b],d.get(b),k?.get(b))}return L&&(s.route=Ct(a.meta.route)),this.setState({lastOutcome:s,snapshots:await zr(e,s.at,this.state.snapshots)}),s}finally{this.setState({busy:null})}}async restoreSource(e,t,r,i){let n=Cr(e);if(!n)return Ne("provider not available (package missing or not initialized)");let a=n.status();if(!a.canRestore)return Ne(a.detail??"restore unavailable");try{let s=r?.length||i?.length?{...r?.length?{excludeKeys:r}:{},...i?.length?{includeKeys:i}:{}}:void 0;return await n.restore(Pt(t),s)}catch(s){return Ne(String(s))}}scheduleReload(e){try{return qn({reason:e}),true}catch{return false}}async delete(e){if(A){await A("delete",{id:e});return}await this.ensureLoaded(),await ae();let t=await ei(e),r=await $r(e,this.state.snapshots);this.setState({snapshots:r,recentlyDeleted:t?{stored:t,at:Date.now()}:null})}async undoDelete(){let e=this.state.recentlyDeleted;if(!e)return;let t=await ti(e.stored,this.state.snapshots);this.setState({snapshots:t,recentlyDeleted:null})}clearRecentlyDeleted(){this.state.recentlyDeleted&&this.setState({recentlyDeleted:null})}async setRestoreRoute(e,t){if(A){await A("setRestoreRoute",{id:e,restoreRoute:t});return}await this.ensureLoaded(),await ae();let r=await Qn(e,t,this.state.snapshots);this.setState({snapshots:r})}async duplicate(e){if(A)return(await A("duplicate",{id:e}))?.snapshot??null;await this.ensureLoaded(),await ae();let t=this.state.snapshots.find(i=>i.id===e);if(!t)return null;let r=await Zn(e,`${t.name} copy`,this.state.snapshots);return r?(this.setState({snapshots:r.metas}),r.meta):null}async rename(e,t){if(A){await A("rename",{id:e,name:t});return}await this.ensureLoaded(),await ae();let r=await ri(e,t,this.state.snapshots);this.setState({snapshots:r})}async setScope(e,t){if(A){await A("setScope",{id:e,scope:t});return}await this.ensureLoaded(),await ae();let r=await Xn(e,t,this.state.snapshots);this.setState({snapshots:r})}async setExclusions(e,t){if(A){await A("setExclusions",{id:e,excludedKeys:t});return}await this.ensureLoaded(),await ae();let r=await Gn(e,t,this.state.snapshots);this.setState({snapshots:r})}clearLastOutcome(){this.setState({lastOutcome:null})}async wipeAll(){if(A){let e=await A("wipeAll",{});return this.setState({lastOutcome:e}),e}this.setState({busy:"restore"});try{let e={snapshotId:"wipe-all",snapshotName:"Wipe all",mode:"reload",at:Date.now(),willReload:false,results:{}};for(let t of st())if(t.clear)try{e.results[t.id]=await t.clear()}catch(r){e.results[t.id]=Ne(String(r))}return e.willReload=this.scheduleReload("buoy time-machine wipe all"),this.setState({lastOutcome:e}),e}finally{this.setState({busy:null})}}clearPreview(){this.previewRunId+=1,this.setState({preview:null})}async buildPreview(e,t="current"){if(A){let n=++this.previewRunId;this.setState({preview:{left:t,right:e,building:true,builtAt:Date.now(),sources:[]}});try{let a=await A("preview",{id:e==="current"?void 0:e.snapshotId,compareTo:t==="current"?void 0:t.snapshotId});if(n!==this.previewRunId)return;this.setState({preview:{left:t,right:e,building:false,builtAt:Date.now(),sources:a.sources??[]}})}catch(a){if(n!==this.previewRunId)return;this.setState({preview:{left:t,right:e,building:false,builtAt:Date.now(),sources:[{id:"error",label:"Preview",items:[],notes:[],error:String(a)}]}})}return}await this.ensureLoaded(),await ae();let r=++this.previewRunId;this.setState({preview:{left:t,right:e,building:true,builtAt:Date.now(),sources:[]}});let i=async n=>{if(n==="current")return null;let a=await fe(n.snapshotId);if(!a)throw new Error(`No snapshot with id "${n.snapshotId}"`);return a.data};try{if(e==="current")throw new Error("preview target must be a snapshot");let[n,a]=await Promise.all([i(t),fe(e.snapshotId)]);if(r!==this.previewRunId)return;if(!a)throw new Error(`No snapshot with id "${e.snapshotId}"`);let s=a.data,h=a.meta.baseline===true,m=h?st().filter(d=>d.clear).map(d=>d.id):[...je.filter(d=>d in s),...Object.keys(s).filter(d=>!je.includes(d))],y=[];for(let d of m){if(!se(d))continue;if(await new Promise(b=>setTimeout(b,0)),r!==this.previewRunId)return;let k=Cr(d),L=k?.label??d;try{let b=h?void 0:Pt(s[d]),H=n===null?void 0:d in n?Pt(n[d]):void 0,W;if(!k)W={items:[{key:d,label:L,verdict:"wont-apply",reason:"tool not installed \u2014 restore skips this source"}],notes:[]};else if(k.previewItems)W=await k.previewItems(b,H);else{let j=Un(H,b);W={items:[{key:d,label:L,verdict:j.equal?"unchanged":"changed",oldValue:H,newValue:b}],notes:j.truncated?["diff truncated (large value)"]:[]}}if(r!==this.previewRunId)return;y.push({id:d,label:L,...W})}catch(b){y.push({id:d,label:L,items:[],notes:[],error:String(b)})}this.setState({preview:{left:t,right:e,building:true,builtAt:Date.now(),sources:[...y]}})}if(r!==this.previewRunId)return;this.setState({preview:{left:t,right:e,building:false,builtAt:Date.now(),sources:y}})}catch(n){if(r!==this.previewRunId)return;this.setState({preview:{left:t,right:e,building:false,builtAt:Date.now(),sources:[{id:"error",label:"Preview",items:[],notes:[],error:String(n)}]}})}}},v=new si;function li(e){A=e,e||v.replaceFromSnapshot({})}function ci(e){v.replaceFromSnapshot(e)}function ut(){return _n(v.subscribe,()=>v.getState())}function jr(){let[e,t]=Fn(Lt);return Vn(()=>(t(Lt()),Kn(()=>t(Lt()))),[]),e}import{Children as di}from"react";import{ChevronRight as ui}from"@buoy-gg/shared-ui/web";import{night as N}from"@buoy-gg/shared-ui/web";import{monoFont as hi}from"@buoy-gg/shared-ui/web";var Wt="2E",pi="4D",o={color:{sheet:"rgba(5, 5, 5, 0.92)",group:N.color.glass,groupBorder:N.color.glassBorder,rowPressed:N.color.glassElevated,separator:N.color.separator,fill:N.color.glassElevated,fillStrong:N.color.fillTertiary,ring:N.color.bg,disc:N.color.surfaceElevated,label:N.color.text,labelSecondary:N.color.textSecondary,labelTertiary:N.color.textTertiary,accent:N.color.accent,accentSoft:`${N.color.accent}${Wt}`,accentSoftStrong:`${N.color.accent}${pi}`,onAccent:"#0A0A0A",warning:N.color.warning,warningSoft:`${N.color.warning}${Wt}`,danger:N.color.danger,dangerSoft:`${N.color.danger}${Wt}`,onDanger:"#FFFFFF",info:N.color.info},radius:{group:14,pill:99},gutter:14,textInset:16,separatorInset:16,font:{row:17,control:15,footnote:13,mono:12},tracking:{row:-.43,control:-.2},rowMinHeight:52},ht=hi;import{jsx as Ie,jsxs as mi}from"react/jsx-runtime";function pt({children:e,testID:t}){return Ie(c,{style:ge.sectionLabel,testID:t,children:e})}function Me({children:e,centered:t,tone:r="secondary",testID:i}){return Ie(c,{style:[ge.footnote,t?ge.footnoteCentered:null,r==="warning"?ge.footnoteWarning:null],testID:i,children:e})}function mt({children:e,style:t}){let r=di.toArray(e);return Ie(u,{style:[ge.group,t],children:r.map((i,n)=>mi(u,{children:[n>0?Ie(u,{style:ge.separator}):null,i]},i.key??n))})}function Nr(){return Ie(ui,{size:16,color:o.color.labelTertiary})}function fi({label:e,color:t,background:r,testID:i}){return Ie(u,{style:[ge.pill,{backgroundColor:r}],children:Ie(c,{style:[ge.pillText,{color:t}],testID:i,children:e})})}var ge=O.create({sectionLabel:{color:o.color.labelSecondary,fontSize:o.font.footnote,fontWeight:"500",textTransform:"uppercase",letterSpacing:.4,paddingHorizontal:o.gutter+o.textInset,paddingTop:22,paddingBottom:7},footnote:{color:o.color.labelSecondary,fontSize:o.font.footnote,lineHeight:o.font.footnote*1.35,paddingHorizontal:o.gutter+o.textInset,paddingTop:7},footnoteCentered:{textAlign:"center"},footnoteWarning:{color:o.color.warning},group:{marginHorizontal:o.gutter,backgroundColor:o.color.group,borderRadius:o.radius.group,borderWidth:1,borderColor:o.color.groupBorder,overflow:"hidden"},separator:{height:O.hairlineWidth,marginLeft:o.separatorInset,backgroundColor:o.color.separator},pill:{height:32,paddingHorizontal:15,borderRadius:o.radius.pill,alignItems:"center",justifyContent:"center"},pillText:{fontSize:o.font.control,fontWeight:"600",letterSpacing:o.tracking.control}});import{JotaiIcon as gi,QueryIcon as bi,ReduxIcon as yi,RoutesIcon as wi,StorageIcon as Si,TimeMachineIcon as vi,ZustandIcon as xi}from"@buoy-gg/floating-tools-core/web";import{useSyncExternalStore as Ii}from"react";var Ri={storage:Si,redux:yi,zustand:xi,jotai:gi,query:bi,route:wi};function Di(e){return Ri[e]??vi}function ki(){let{remoteProviders:e,remoteRoute:t}=ut(),r=jr(),i=Ii(Or,Hr,Hr),n=e?e.map(s=>({...s,enabled:s.enabled!==false})):r.map(s=>({id:s.id,label:s.label,...s.status(),enabled:!i.has(s.id)})),a=e?t?.available===true:He();return[...n,{id:We,label:"Route",canCapture:a,canRestore:a,enabled:e?t?.enabled!==false:!i.has(We),detail:a?"Recorded with every snapshot \u2014 a restore can take you back":"No Expo Router detected \u2014 snapshots record no route"}]}function Ti(e){let t=globalThis.confirm;return t?t(e):true}function jt(e,t,r,i){if(nt.OS==="web"){Ti(`${e}
|
|
1
|
+
"use client";var pr=Object.defineProperty;var $o=Object.getOwnPropertyDescriptor;var zo=Object.getOwnPropertyNames;var Lo=Object.prototype.hasOwnProperty;var Po=(e,t)=>{for(var r in t)pr(e,r,{get:t[r],enumerable:true})},mr=(e,t,r,i)=>{if(t&&typeof t=="object"||typeof t=="function")for(let n of zo(t))!Lo.call(e,n)&&n!==r&&pr(e,n,{get:()=>t[n],enumerable:!(i=$o(t,n))||i.enumerable});return e},Ao=(e,t,r)=>(mr(e,t,"default"),r&&mr(r,t,"default"));var fr=(()=>{try{let e=globalThis.Capacitor;if(e&&typeof e.isNativePlatform=="function"&&e.isNativePlatform())return e.DEBUG===true}catch{}return process.env.NODE_ENV!=="production"})();typeof window<"u"&&typeof globalThis.global>"u"&&(globalThis.global=globalThis);import{getSafeCurrentRoute as Oo,getSafeRouter as gr,persistentStorage as kt}from"@buoy-gg/shared-ui/web";var Tt="@react_buoy_time_machine:pending-route",Ho=6e4,Eo=8e3,Bo=250;function Wo(e){return{pathname:e.pathname,href:e.href}}function ot(){let e=Oo();return e?Wo(e):null}function No(){return ot()}function He(){return gr()!=null}function Ct(e){let t={pathname:e.pathname,href:e.href},r=gr();if(!r?.navigate)return{...t,status:"unavailable",error:"expo-router is not available on this device"};try{return r.navigate(e.href),{...t,status:"navigated"}}catch(i){return{...t,status:"failed",error:String(i)}}}async function jo(e,t){let r={...e,savedAt:Date.now(),...t?{snapshotName:t}:{}};await kt.setItem(Tt,JSON.stringify(r))}async function Mo(){try{await kt.removeItem(Tt)}catch{}}async function Vo(){try{let e=await kt.getItem(Tt);if(!e)return null;let t=JSON.parse(e);return typeof t?.href!="string"||!t.href||typeof t.savedAt!="number"?null:{pathname:typeof t.pathname=="string"?t.pathname:t.href,href:t.href,savedAt:t.savedAt,snapshotName:typeof t.snapshotName=="string"?t.snapshotName:void 0}}catch{return null}}var br=false;function yr(){br||(br=true,(async()=>{let e=await Vo();if(!e||(await Mo(),Date.now()-e.savedAt>Ho))return;let t=Date.now()+Eo;for(;!He()&&Date.now()<t;)await new Promise(r=>setTimeout(r,100));He()&&(await new Promise(r=>setTimeout(r,Bo)),Ct({pathname:e.pathname,href:e.href}))})())}var wr={};Po(wr,{AccessibilityInfo:()=>qo,ActivityIndicator:()=>at,Alert:()=>Dr,Animated:()=>Ee,AppRegistry:()=>Uo,AppState:()=>Yo,Appearance:()=>Jo,BackHandler:()=>Go,Button:()=>An,CheckBox:()=>un,Clipboard:()=>Xo,DeviceEventEmitter:()=>Dn,Dimensions:()=>Qo,Easing:()=>Zo,FlatList:()=>vr,I18nManager:()=>en,Image:()=>hn,ImageBackground:()=>pn,InteractionManager:()=>rn,Keyboard:()=>tn,KeyboardAvoidingView:()=>xr,LayoutAnimation:()=>on,Linking:()=>nn,LogBox:()=>Rn,Modal:()=>Rr,NativeEventEmitter:()=>an,NativeModules:()=>Ko,PanResponder:()=>Sr,Picker:()=>mn,PixelRatio:()=>sn,Platform:()=>nt,Pressable:()=>$t,ProgressBar:()=>fn,RefreshControl:()=>gn,SafeAreaView:()=>bn,ScrollView:()=>zt,SectionList:()=>yn,Share:()=>ln,StatusBar:()=>wn,StyleSheet:()=>O,Switch:()=>Pn,Text:()=>c,TextInput:()=>it,Touchable:()=>Sn,TouchableHighlight:()=>zn,TouchableNativeFeedback:()=>vn,TouchableOpacity:()=>P,TouchableWithoutFeedback:()=>Ln,UIManager:()=>cn,Vibration:()=>dn,View:()=>u,VirtualizedList:()=>xn,YellowBox:()=>In,findNodeHandle:()=>On,unstable_createElement:()=>_o,useColorScheme:()=>kn,useLocaleContext:()=>Tn,useWindowDimensions:()=>Ir});Ao(wr,Fo);import*as Fo from"react-native-web";import{unstable_createElement as _o,NativeModules as Ko,AccessibilityInfo as qo,Animated as Ee,Appearance as Jo,AppRegistry as Uo,AppState as Yo,BackHandler as Go,Clipboard as Xo,Dimensions as Qo,Easing as Zo,I18nManager as en,Keyboard as tn,InteractionManager as rn,LayoutAnimation as on,Linking as nn,NativeEventEmitter as an,PanResponder as Sr,PixelRatio as sn,Platform as nt,Share as ln,StyleSheet as O,UIManager as cn,Vibration as dn,CheckBox as un,FlatList as vr,Image as hn,ImageBackground as pn,KeyboardAvoidingView as xr,Picker as mn,ProgressBar as fn,RefreshControl as gn,SafeAreaView as bn,SectionList as yn,StatusBar as wn,Touchable as Sn,TouchableNativeFeedback as vn,VirtualizedList as xn,YellowBox as In,LogBox as Rn,DeviceEventEmitter as Dn,useColorScheme as kn,useLocaleContext as Tn,useWindowDimensions as Ir}from"react-native-web";import*as J from"react-native-web";import{createElement as Cn,forwardRef as $n}from"react";function Q(e){let t=$n((i,n)=>{let{accessibilityState:a,accessibilityValue:s,...h}=i;for(let m of["busy","checked","disabled","expanded","selected"])a?.[m]!==void 0&&h[`aria-${m}`]===void 0&&(h[`aria-${m}`]=a[m]);for(let[m,y]of Object.entries({min:"valuemin",max:"valuemax",now:"valuenow",text:"valuetext"}))s?.[m]!==void 0&&h[`aria-${y}`]===void 0&&(h[`aria-${y}`]=s[m]);return Cn(e,{...h,ref:n})}),r=e.State;return r&&Object.assign(t,{State:r}),t.displayName=e.displayName??e.name??"NativeWebView",t}var u=Q(J.View),c=Q(J.Text),it=Q(J.TextInput),P=Q(J.TouchableOpacity),zn=Q(J.TouchableHighlight),Ln=Q(J.TouchableWithoutFeedback),$t=Q(J.Pressable),zt=Q(J.ScrollView),Rr=Q(J.Modal),Pn=Q(J.Switch),at=Q(J.ActivityIndicator),An=Q(J.Button),On=J.findNodeHandle,Dr={alert(e,t,r,i){if(typeof document>"u")return;let n=document.createElement("dialog");n.dataset.buoyRoot="",n.setAttribute("aria-label",e),n.style.cssText="position:fixed;inset:0;margin:auto;width:min(440px,90vw);padding:24px;border:1px solid #475569;border-radius:14px;background:#17212e;color:#f1f5f9;font:14px system-ui;box-shadow:0 20px 80px #0008;z-index:2147483647";let a=document.createElement("h2");if(a.textContent=e,a.style.cssText="font-size:18px;margin:0 0 12px",n.appendChild(a),t){let y=document.createElement("p");y.textContent=t,y.style.cssText="line-height:1.5;white-space:pre-wrap;margin:0 0 20px",n.appendChild(y)}let s=document.createElement("div");s.style.cssText="display:flex;justify-content:flex-end;flex-wrap:wrap;gap:8px";let h=r?.length?r:[{text:"OK"}],m=()=>{n.close?.(),n.remove()};for(let y of h){let d=document.createElement("button");d.type="button",d.textContent=y.text??"OK",d.style.cssText=`padding:9px 14px;border:1px solid #64748b;border-radius:7px;color:white;background:${y.style==="destructive"?"#a52b38":"#283a4d"};cursor:pointer;font:inherit`,d.onclick=()=>{m(),y.onPress?.()},s.appendChild(d)}n.addEventListener("cancel",y=>{y.preventDefault(),i?.cancelable!==false&&(m(),i?.onDismiss?.())}),n.appendChild(s),document.body.appendChild(n),n.showModal?n.showModal():n.setAttribute("open","")}};import{TimeMachineIcon as Hn,TIME_MACHINE_ICON_COLOR as En}from"@buoy-gg/shared-ui/web";import{useRef as Bn,useState as kr,useSyncExternalStore as Tr}from"react";import{useSafeAreaInsets as Wn,useLimit as Nn,ToolEmptyState as jn,getFloatingTools as Mn,subscribeFloatingTools as Vn}from"@buoy-gg/shared-ui/web";import{useToolHost as Fn}from"@buoy-gg/core/web";import{useEffect as _n,useState as Kn,useSyncExternalStore as qn}from"react";import{getStateSnapshotProviders as Lt,subscribeToStateSnapshotProviders as Jn}from"@buoy-gg/shared-ui/web";import{getStateSnapshotProvider as Cr,getStateSnapshotProviders as st,scheduleReloadApp as Un,superJsonDeserialize as Pt,superJsonSerialize as Yn}from"@buoy-gg/shared-ui/web";import{objectDiff as Gn}from"@buoy-gg/shared-ui/web/dataViewer";import{persistentStorage as me}from"@buoy-gg/shared-ui/web";var At="@react_buoy_time_machine:index",Be="@react_buoy_time_machine:snap:";async function Xn(){try{let e=await me.getItem(At);if(!e)return[];let t=JSON.parse(e);return Array.isArray(t)?t:[]}catch{return[]}}async function Ot(e){await me.setItem(At,JSON.stringify(e))}async function lt(e,t){let r=JSON.stringify(e);e.meta.sizeBytes=r.length,await me.setItem(Be+e.meta.id,JSON.stringify(e));let i=[e.meta,...t.filter(n=>n.id!==e.meta.id)];return await Ot(i),i}async function fe(e){try{let t=await me.getItem(Be+e);return t?JSON.parse(t):null}catch{return null}}async function $r(e,t){await me.removeItem(Be+e);let r=t.filter(i=>i.id!==e);return await Ot(r),r}async function ct(e,t,r){let i=s=>s.id===e?t(s):s,n=r.map(i);await me.setItem(At,JSON.stringify(n));let a=await fe(e);return a&&(a.meta=i(a.meta),await me.setItem(Be+e,JSON.stringify(a))),n}function Qn(e,t,r){return ct(e,i=>{let n={...i};return t&&t.length>0?n.scope=t:delete n.scope,n},r)}function Zn(e,t,r){return ct(e,i=>{let n={...i};return delete n.scope,t&&t.length>0?n.excludedKeys=t:delete n.excludedKeys,n},r)}function ei(e,t,r){return ct(e,i=>({...i,restoreRoute:t}),r)}function zr(e,t,r){return ct(e,i=>({...i,lastRestoredAt:t}),r)}async function ti(e,t,r){let i=await fe(e);if(!i)return null;let n={meta:{...i.meta,id:`${i.meta.id}_copy_${Date.now().toString(36)}`,name:t,createdAt:Date.now(),lastRestoredAt:void 0},data:i.data};return delete n.meta.lastRestoredAt,{metas:await lt(n,r),meta:n.meta}}async function ri(e){return fe(e)}async function oi(e,t){return lt(e,t)}async function ni(e,t,r){let i=r.map(a=>a.id===e?{...a,name:t}:a);await Ot(i);let n=await fe(e);return n&&(n.meta.name=t,await me.setItem(Be+e,JSON.stringify(n))),i}import{definePersistedSetting as ii,devToolsStorageKeys as ai}from"@buoy-gg/shared-ui/web";var Lr=ii(ai.timeMachine.disabledSources(),[],{sanitize:e=>Array.isArray(e)?e.filter(t=>typeof t=="string"):[]}),xe=new Set,Pr=false,Ht=null,Et=new Set,Ar=()=>Et.forEach(e=>e());function ae(){return Pr?Promise.resolve():(Ht||(Ht=Lr.load().then(e=>{xe.size===0&&(xe=new Set(e),Ar())}).finally(()=>{Pr=true})),Ht)}function Or(e){return Et.add(e),()=>{Et.delete(e)}}function Hr(){return xe}function se(e){return!xe.has(e)}function Er(e,t){if(t===!xe.has(e))return;let r=new Set(xe);t?r.delete(e):r.add(e),xe=r,Ar(),Lr.save([...r])}var We="route";var Ne=["storage","redux","zustand","jotai","query"];function si(e){let t=new Date,r=`${String(t.getHours()).padStart(2,"0")}:${String(t.getMinutes()).padStart(2,"0")}`,i=e?e.pathname==="/"?"Home":e.pathname:null;return i?`${i} \xB7 ${r}`:`Snapshot \xB7 ${r}`}function li(e,t){let r=new Set(t.map(i=>i.name));if(!r.has(e))return e;for(let i=2;i<1e3;i++){let n=`${e} (${i})`;if(!r.has(n))return n}return e}function dt(e){return!!e.route&&(e.restoreRoute??true)}var Bt="Before last restore",A=null;function je(e){return{ok:false,applied:0,skipped:[{id:"*",reason:e}],warnings:[]}}var Br=0;function Wr(){return Br+=1,`snap_${Date.now().toString(36)}_${Br.toString(36)}`}var ci=class{constructor(){this.state={snapshots:[],hasLoaded:false,busy:null,lastOutcome:null,preview:null,remoteProviders:null,remoteRoute:null,recentlyDeleted:null};this.previewRunId=0;this.listeners=new Set;this.loadPromise=null;this.subscribe=e=>(this.listeners.add(e),this.ensureLoaded(),()=>{this.listeners.delete(e)})}getState(){return this.state}setState(e){this.state={...this.state,...e},this.listeners.forEach(t=>{try{t()}catch{}})}ensureLoaded(){return A?Promise.resolve():(this.loadPromise||(this.loadPromise=Xn().then(e=>{A||this.setState({snapshots:e,hasLoaded:true})})),this.loadPromise)}replaceFromSnapshot(e){this.setState({snapshots:e.snapshots??[],busy:e.busy??null,lastOutcome:e.lastOutcome??null,remoteProviders:e.providers??[],remoteRoute:e.route??{available:false},hasLoaded:true})}async capture(e,t,r){if(A)return(await A("capture",{name:e,sourceIds:t})).snapshot;await this.ensureLoaded(),await ae(),this.setState({busy:"capture"});try{let i=st().filter(d=>d.status().canCapture&&se(d.id)&&(!t||t.includes(d.id))),n={},a={};for(let d of i)try{let k=await d.capture();n[d.id]=Yn(k.data),a[d.id]={warnings:k.warnings}}catch(k){a[d.id]={warnings:[`capture failed: ${String(k)}`]}}let s=se(We)?ot():null,h=this.state.snapshots;if(r?.safety)for(let d of h.filter(k=>k.safety))h=await $r(d.id,h);let m={meta:{id:Wr(),name:r?.safety?Bt:li(e.trim()||si(s),h),createdAt:Date.now(),sizeBytes:0,...s?{route:s}:{},...r?.safety?{safety:true}:{},sources:a},data:n},y=await lt(m,h);return this.setState({snapshots:y}),m.meta}finally{this.setState({busy:null})}}async captureBaseline(){if(A)return(await A("captureBaseline",{})).snapshot;await this.ensureLoaded(),await ae();let e={meta:{id:Wr(),name:"Fresh install",createdAt:Date.now(),sizeBytes:0,baseline:true,sources:{}},data:{}},t=await lt(e,this.state.snapshots);return this.setState({snapshots:t}),e.meta}async restore(e,t,r,i){if(A){let a=await A("restore",{id:e,mode:t,excludeKeys:r,restoreRoute:i?.restoreRoute});return this.setState({lastOutcome:a}),a}await this.ensureLoaded(),await ae();let n;i?.safetyCapture&&!this.state.snapshots.find(a=>a.id===e)?.safety&&(n=(await this.capture(Bt,void 0,{safety:true})).id),this.setState({busy:"restore"});try{let a=await fe(e);if(!a)throw new Error(`No snapshot with id "${e}"`);let s={snapshotId:e,snapshotName:a.meta.name,mode:t,at:Date.now(),willReload:false,results:{},...n?{safetySnapshotId:n}:{}};if(a.meta.baseline){for(let b of st())if(b.clear)try{s.results[b.id]=await b.clear()}catch(H){s.results[b.id]=je(String(H))}return s.willReload=this.scheduleReload("buoy time-machine baseline"),this.setState({lastOutcome:s}),s}let h=[...Ne.filter(b=>b in a.data),...Object.keys(a.data).filter(b=>!Ne.includes(b))],m=b=>{let H=new Map;for(let W of b){let N=W.indexOf("::");if(N<=0)continue;let w=W.slice(0,N),U=W.slice(N+2),ee=H.get(w)??[];ee.push(U),H.set(w,ee)}return H},y=r??a.meta.excludedKeys??[],d=m(y),k=!r&&a.meta.scope?.length?m(a.meta.scope):null,L=se(We)&&(i?.restoreRoute??dt(a.meta));if(t==="reload"){if(a.data.storage&&se("storage")&&(!k||k.has("storage"))&&(s.results.storage=await this.restoreSource("storage",a.data.storage,d.get("storage"),k?.get("storage"))),L){let b=a.meta.route;try{await jo(b,a.meta.name),s.route={...b,status:"deferred"}}catch(H){s.route={...b,status:"failed",error:String(H)}}}return s.willReload=this.scheduleReload("buoy time-machine restore"),this.setState({lastOutcome:s,snapshots:await zr(e,s.at,this.state.snapshots)}),s}for(let b of h)if(!(k&&!k.has(b))){if(!se(b)){s.results[b]={ok:true,applied:0,skipped:[],warnings:["Switched off in Sources; left as it is"]};continue}s.results[b]=await this.restoreSource(b,a.data[b],d.get(b),k?.get(b))}return L&&(s.route=Ct(a.meta.route)),this.setState({lastOutcome:s,snapshots:await zr(e,s.at,this.state.snapshots)}),s}finally{this.setState({busy:null})}}async restoreSource(e,t,r,i){let n=Cr(e);if(!n)return je("provider not available (package missing or not initialized)");let a=n.status();if(!a.canRestore)return je(a.detail??"restore unavailable");try{let s=r?.length||i?.length?{...r?.length?{excludeKeys:r}:{},...i?.length?{includeKeys:i}:{}}:void 0;return await n.restore(Pt(t),s)}catch(s){return je(String(s))}}scheduleReload(e){try{return Un({reason:e}),true}catch{return false}}async delete(e){if(A){await A("delete",{id:e});return}await this.ensureLoaded(),await ae();let t=await ri(e),r=await $r(e,this.state.snapshots);this.setState({snapshots:r,recentlyDeleted:t?{stored:t,at:Date.now()}:null})}async undoDelete(){let e=this.state.recentlyDeleted;if(!e)return;let t=await oi(e.stored,this.state.snapshots);this.setState({snapshots:t,recentlyDeleted:null})}clearRecentlyDeleted(){this.state.recentlyDeleted&&this.setState({recentlyDeleted:null})}async setRestoreRoute(e,t){if(A){await A("setRestoreRoute",{id:e,restoreRoute:t});return}await this.ensureLoaded(),await ae();let r=await ei(e,t,this.state.snapshots);this.setState({snapshots:r})}async duplicate(e){if(A)return(await A("duplicate",{id:e}))?.snapshot??null;await this.ensureLoaded(),await ae();let t=this.state.snapshots.find(i=>i.id===e);if(!t)return null;let r=await ti(e,`${t.name} copy`,this.state.snapshots);return r?(this.setState({snapshots:r.metas}),r.meta):null}async rename(e,t){if(A){await A("rename",{id:e,name:t});return}await this.ensureLoaded(),await ae();let r=await ni(e,t,this.state.snapshots);this.setState({snapshots:r})}async setScope(e,t){if(A){await A("setScope",{id:e,scope:t});return}await this.ensureLoaded(),await ae();let r=await Qn(e,t,this.state.snapshots);this.setState({snapshots:r})}async setExclusions(e,t){if(A){await A("setExclusions",{id:e,excludedKeys:t});return}await this.ensureLoaded(),await ae();let r=await Zn(e,t,this.state.snapshots);this.setState({snapshots:r})}clearLastOutcome(){this.setState({lastOutcome:null})}async wipeAll(){if(A){let e=await A("wipeAll",{});return this.setState({lastOutcome:e}),e}this.setState({busy:"restore"});try{let e={snapshotId:"wipe-all",snapshotName:"Wipe all",mode:"reload",at:Date.now(),willReload:false,results:{}};for(let t of st())if(t.clear)try{e.results[t.id]=await t.clear()}catch(r){e.results[t.id]=je(String(r))}return e.willReload=this.scheduleReload("buoy time-machine wipe all"),this.setState({lastOutcome:e}),e}finally{this.setState({busy:null})}}clearPreview(){this.previewRunId+=1,this.setState({preview:null})}async buildPreview(e,t="current"){if(A){let n=++this.previewRunId;this.setState({preview:{left:t,right:e,building:true,builtAt:Date.now(),sources:[]}});try{let a=await A("preview",{id:e==="current"?void 0:e.snapshotId,compareTo:t==="current"?void 0:t.snapshotId});if(n!==this.previewRunId)return;this.setState({preview:{left:t,right:e,building:false,builtAt:Date.now(),sources:a.sources??[]}})}catch(a){if(n!==this.previewRunId)return;this.setState({preview:{left:t,right:e,building:false,builtAt:Date.now(),sources:[{id:"error",label:"Preview",items:[],notes:[],error:String(a)}]}})}return}await this.ensureLoaded(),await ae();let r=++this.previewRunId;this.setState({preview:{left:t,right:e,building:true,builtAt:Date.now(),sources:[]}});let i=async n=>{if(n==="current")return null;let a=await fe(n.snapshotId);if(!a)throw new Error(`No snapshot with id "${n.snapshotId}"`);return a.data};try{if(e==="current")throw new Error("preview target must be a snapshot");let[n,a]=await Promise.all([i(t),fe(e.snapshotId)]);if(r!==this.previewRunId)return;if(!a)throw new Error(`No snapshot with id "${e.snapshotId}"`);let s=a.data,h=a.meta.baseline===true,m=h?st().filter(d=>d.clear).map(d=>d.id):[...Ne.filter(d=>d in s),...Object.keys(s).filter(d=>!Ne.includes(d))],y=[];for(let d of m){if(!se(d))continue;if(await new Promise(b=>setTimeout(b,0)),r!==this.previewRunId)return;let k=Cr(d),L=k?.label??d;try{let b=h?void 0:Pt(s[d]),H=n===null?void 0:d in n?Pt(n[d]):void 0,W;if(!k)W={items:[{key:d,label:L,verdict:"wont-apply",reason:"tool not installed \u2014 restore skips this source"}],notes:[]};else if(k.previewItems)W=await k.previewItems(b,H);else{let N=Gn(H,b);W={items:[{key:d,label:L,verdict:N.equal?"unchanged":"changed",oldValue:H,newValue:b}],notes:N.truncated?["diff truncated (large value)"]:[]}}if(r!==this.previewRunId)return;y.push({id:d,label:L,...W})}catch(b){y.push({id:d,label:L,items:[],notes:[],error:String(b)})}this.setState({preview:{left:t,right:e,building:true,builtAt:Date.now(),sources:[...y]}})}if(r!==this.previewRunId)return;this.setState({preview:{left:t,right:e,building:false,builtAt:Date.now(),sources:y}})}catch(n){if(r!==this.previewRunId)return;this.setState({preview:{left:t,right:e,building:false,builtAt:Date.now(),sources:[{id:"error",label:"Preview",items:[],notes:[],error:String(n)}]}})}}},v=new ci;function di(e){A=e,e||v.replaceFromSnapshot({})}function ui(e){v.replaceFromSnapshot(e)}function ut(){return qn(v.subscribe,()=>v.getState())}function Nr(){let[e,t]=Kn(Lt);return _n(()=>(t(Lt()),Jn(()=>t(Lt()))),[]),e}import{Children as hi}from"react";import{ChevronRight as pi}from"@buoy-gg/shared-ui/web";import{night as j}from"@buoy-gg/shared-ui/web";import{monoFont as mi}from"@buoy-gg/shared-ui/web";var Wt="2E",fi="4D",o={color:{sheet:"rgba(5, 5, 5, 0.92)",group:j.color.glass,groupBorder:j.color.glassBorder,rowPressed:j.color.glassElevated,separator:j.color.separator,fill:j.color.glassElevated,fillStrong:j.color.fillTertiary,ring:j.color.bg,disc:j.color.surfaceElevated,label:j.color.text,labelSecondary:j.color.textSecondary,labelTertiary:j.color.textTertiary,accent:j.color.accent,accentSoft:`${j.color.accent}${Wt}`,accentSoftStrong:`${j.color.accent}${fi}`,onAccent:"#0A0A0A",warning:j.color.warning,warningSoft:`${j.color.warning}${Wt}`,danger:j.color.danger,dangerSoft:`${j.color.danger}${Wt}`,onDanger:"#FFFFFF",info:j.color.info},radius:{group:14,pill:99},gutter:14,textInset:16,separatorInset:16,font:{row:17,control:15,footnote:13,mono:12},tracking:{row:-.43,control:-.2},rowMinHeight:52},ht=mi;import{jsx as Ie,jsxs as gi}from"react/jsx-runtime";function pt({children:e,testID:t}){return Ie(c,{style:ge.sectionLabel,testID:t,children:e})}function Me({children:e,centered:t,tone:r="secondary",testID:i}){return Ie(c,{style:[ge.footnote,t?ge.footnoteCentered:null,r==="warning"?ge.footnoteWarning:null],testID:i,children:e})}function mt({children:e,style:t}){let r=hi.toArray(e);return Ie(u,{style:[ge.group,t],children:r.map((i,n)=>gi(u,{children:[n>0?Ie(u,{style:ge.separator}):null,i]},i.key??n))})}function jr(){return Ie(pi,{size:16,color:o.color.labelTertiary})}function bi({label:e,color:t,background:r,testID:i}){return Ie(u,{style:[ge.pill,{backgroundColor:r}],children:Ie(c,{style:[ge.pillText,{color:t}],testID:i,children:e})})}var ge=O.create({sectionLabel:{color:o.color.labelSecondary,fontSize:o.font.footnote,fontWeight:"500",textTransform:"uppercase",letterSpacing:.4,paddingHorizontal:o.gutter+o.textInset,paddingTop:22,paddingBottom:7},footnote:{color:o.color.labelSecondary,fontSize:o.font.footnote,lineHeight:o.font.footnote*1.35,paddingHorizontal:o.gutter+o.textInset,paddingTop:7},footnoteCentered:{textAlign:"center"},footnoteWarning:{color:o.color.warning},group:{marginHorizontal:o.gutter,backgroundColor:o.color.group,borderRadius:o.radius.group,borderWidth:1,borderColor:o.color.groupBorder,overflow:"hidden"},separator:{height:O.hairlineWidth,marginLeft:o.separatorInset,backgroundColor:o.color.separator},pill:{height:32,paddingHorizontal:15,borderRadius:o.radius.pill,alignItems:"center",justifyContent:"center"},pillText:{fontSize:o.font.control,fontWeight:"600",letterSpacing:o.tracking.control}});import{JotaiIcon as yi,QueryIcon as wi,ReduxIcon as Si,RoutesIcon as vi,StorageIcon as xi,TimeMachineIcon as Ii,ZustandIcon as Ri}from"@buoy-gg/floating-tools-core/web";import{useSyncExternalStore as Di}from"react";var ki={storage:xi,redux:Si,zustand:Ri,jotai:yi,query:wi,route:vi};function Ti(e){return ki[e]??Ii}function Ci(){let{remoteProviders:e,remoteRoute:t}=ut(),r=Nr(),i=Di(Or,Hr,Hr),n=e?e.map(s=>({...s,enabled:s.enabled!==false})):r.map(s=>({id:s.id,label:s.label,...s.status(),enabled:!i.has(s.id)})),a=e?t?.available===true:He();return[...n,{id:We,label:"Route",canCapture:a,canRestore:a,enabled:e?t?.enabled!==false:!i.has(We),detail:a?"Recorded with every snapshot \u2014 a restore can take you back":"No Expo Router detected \u2014 snapshots record no route"}]}function $i(e){let t=globalThis.confirm;return t?t(e):true}function Nt(e,t,r,i){if(nt.OS==="web"){$i(`${e}
|
|
2
2
|
|
|
3
|
-
${t}`)&&i();return}Dr.alert(e,t,[{text:"Cancel",style:"cancel"},{text:r,style:"destructive",onPress:i}])}import{useState as Ci}from"react";import{jsx as Nt,jsxs as $i}from"react/jsx-runtime";function zi({disabled:e,busy:t,onCapture:r}){let[i,n]=Ci(""),a=()=>{e||(r(i),n(""))};return $i(u,{style:Ve.bar,children:[Nt(it,{style:Ve.input,value:i,onChangeText:n,placeholder:"Name this restore point\u2026",placeholderTextColor:o.color.labelTertiary,editable:!e,onSubmitEditing:a,returnKeyType:"done",testID:"time-machine-name-input"}),Nt(P,{style:[Ve.button,e?Ve.buttonDisabled:null],onPress:a,disabled:e,accessibilityRole:"button",accessibilityLabel:"Capture restore point",testID:"time-machine-capture",children:Nt(c,{style:Ve.buttonText,children:t?"Capturing\u2026":"Capture"})})]})}var Ve=O.create({bar:{flexDirection:"row",alignItems:"center",gap:8,marginHorizontal:o.gutter,backgroundColor:o.color.group,borderRadius:o.radius.group,borderWidth:1,borderColor:o.color.groupBorder,paddingLeft:o.textInset,padding:6},input:{flex:1,minWidth:0,color:o.color.label,fontSize:o.font.row,letterSpacing:o.tracking.row,padding:0,backgroundColor:"transparent"},button:{height:34,paddingHorizontal:16,borderRadius:o.radius.pill,backgroundColor:o.color.accent,alignItems:"center",justifyContent:"center"},buttonDisabled:{opacity:.4},buttonText:{color:o.color.onAccent,fontSize:o.font.control,fontWeight:"600",letterSpacing:o.tracking.control}});import{X as Li}from"@buoy-gg/shared-ui/web";import{jsx as be,jsxs as ye}from"react/jsx-runtime";var Pi={top:10,bottom:10,left:10,right:10};function Mr(e){if(Object.values(e.results).some(r=>!r.ok||r.skipped.length>0))return true;let t=e.route;return t?.status==="failed"||t?.status==="unavailable"}function ft({glyph:e,text:t,ok:r,testID:i}){return ye(c,{style:[we.line,{color:r?o.color.accent:o.color.warning}],numberOfLines:2,testID:i,children:[ye(c,{style:we.glyph,children:[e," "]}),t]})}var Mt="time-machine-outcome-route";function Ai({route:e}){return e.status==="navigated"?be(ft,{glyph:"\u2713",ok:true,text:`route \u2014 ${e.href}`,testID:Mt}):e.status==="deferred"?be(ft,{glyph:"\u21BB",ok:true,text:`route \u2014 ${e.href} after reload`,testID:Mt}):be(ft,{glyph:"\u2715",ok:false,text:`route \u2014 ${e.error??e.status}`,testID:Mt})}function Oi({outcome:e}){let t=Object.entries(e.results),r=e.mode==="reload"||e.willReload;return ye(u,{style:we.card,testID:"time-machine-outcome",children:[ye(u,{style:we.headerRow,children:[ye(c,{style:we.title,numberOfLines:1,testID:"time-machine-outcome-title",children:["Restored \u201C",e.snapshotName,"\u201D",r?" \xB7 reloading":""]}),be(P,{onPress:()=>v.clearLastOutcome(),hitSlop:Pi,accessibilityRole:"button",accessibilityLabel:"Dismiss restore result",testID:"time-machine-outcome-dismiss",children:be(Li,{size:13,color:o.color.labelSecondary})})]}),t.length===0&&!e.route?be(c,{style:we.empty,testID:"time-machine-outcome-empty",children:"No sources restored."}):null,e.route?be(Ai,{route:e.route}):null,t.map(([i,n])=>ye(u,{children:[be(ft,{testID:`time-machine-outcome-${i}`,glyph:n.ok?"\u2713":"\u2715",ok:n.ok,text:`${i} \u2014 applied ${n.applied}${n.skipped.length>0?`, skipped ${n.skipped.length}`:""}`}),n.skipped.slice(0,3).map(a=>ye(c,{style:we.detail,numberOfLines:2,children:[a.id,": ",a.reason]},a.id)),n.warnings.slice(0,3).map(a=>ye(c,{style:we.detail,numberOfLines:2,children:["\u26A0 ",a]},a))]},i))]})}var we=O.create({card:{marginHorizontal:o.gutter,marginTop:12,backgroundColor:o.color.group,borderRadius:o.radius.group,borderWidth:1,borderColor:o.color.groupBorder,padding:14,gap:4},headerRow:{flexDirection:"row",alignItems:"center",gap:10,marginBottom:2},title:{flex:1,color:o.color.label,fontSize:15,fontWeight:"600",letterSpacing:o.tracking.control},line:{fontSize:o.font.footnote,lineHeight:o.font.footnote*1.4},glyph:{fontWeight:"700"},detail:{color:o.color.labelTertiary,fontSize:o.font.mono,lineHeight:o.font.mono*1.4,paddingLeft:14},empty:{color:o.color.labelSecondary,fontSize:o.font.footnote}});import{useEffect as Hi,useRef as Vr}from"react";import{jsx as gt,jsxs as Ei}from"react/jsx-runtime";var Fr=84,_r=8,Se=null;function Bi(e,t){let r=false,i=a=>{r=a,a?(Se&&Se!==n&&Se(),Se=n):Se===n&&(Se=null),Ee.spring(e,{toValue:a?-t:0,useNativeDriver:true,bounciness:0,speed:18}).start()},n=()=>i(false);return{pan:Sr.create({onMoveShouldSetPanResponder:(a,s)=>Math.abs(s.dx)>Math.abs(s.dy)*1.5?s.dx<-_r||r&&s.dx>_r:false,onPanResponderMove:(a,s)=>{let h=r?-t:0;e.setValue(Math.min(0,Math.max(-t,h+s.dx)))},onPanResponderRelease:(a,s)=>{let h=(r?-t:0)+s.dx;i(s.vx<-.5?true:s.vx>.5?false:h<-t/2)},onPanResponderTerminate:()=>i(r)}),close:n}}function Wi({children:e,actions:t,testID:r}){let i=Fr*t.length,n=Vr(new Ee.Value(0)).current,a=Vr(null);a.current===null&&(a.current=Bi(n,i));let{pan:s,close:h}=a.current;Hi(()=>()=>{Se===h&&(Se=null)},[h]);let m=n.interpolate({inputRange:[-24,0],outputRange:[1,0],extrapolate:"clamp"});return Ei(u,{style:Fe.clip,children:[gt(Ee.View,{style:[Fe.actionLayer,{width:i,opacity:m}],children:t.map(y=>gt(P,{style:[Fe.action,y.background?{backgroundColor:y.background}:null],onPress:()=>{h(),y.onPress()},accessibilityLabel:y.label,testID:y.testID??(r?`${r}-${y.label.toLowerCase()}`:void 0),children:gt(c,{style:[Fe.actionText,y.color?{color:y.color}:null],numberOfLines:1,children:y.label})},y.label))}),gt(Ee.View,{style:[Fe.content,{transform:[{translateX:n}]}],...s.panHandlers,children:e})]})}var Fe=O.create({clip:{overflow:"hidden"},actionLayer:{position:"absolute",top:0,bottom:0,right:0,flexDirection:"row"},action:{width:Fr,height:"100%",backgroundColor:o.color.fillStrong,alignItems:"center",justifyContent:"center",paddingHorizontal:6},actionText:{color:o.color.label,fontSize:o.font.footnote,fontWeight:"600",letterSpacing:o.tracking.control},content:{backgroundColor:o.color.group}});function _e(e){let t=Math.max(0,Math.round((Date.now()-e)/1e3));if(t<60)return`${t}s ago`;let r=Math.round(t/60);if(r<60)return`${r}m ago`;let i=Math.round(r/60);return i<24?`${i}h ago`:`${Math.round(i/24)}d ago`}function ji(e){return e<1024?`${e} B`:e<1024*1024?`${(e/1024).toFixed(1)} KB`:`${(e/(1024*1024)).toFixed(1)} MB`}import{jsx as Re,jsxs as Vt}from"react/jsx-runtime";function Kr(e){if(e.baseline)return"Wipes to fresh install";let t=[_e(e.createdAt),ji(e.sizeBytes),`${Object.keys(e.sources).length} sources`];return e.excludedKeys?.length?t.push(`skips ${e.excludedKeys.length}`):e.scope?.length&&t.push(`scoped (${e.scope.length})`),e.safety&&t.unshift("safety copy"),t.join(" \xB7 ")}function Ni({meta:e,busy:t,armed:r=false,onOpen:i,onRestore:n,onDelete:a,onDuplicate:s,onArm:h}){let m=`time-machine-snap-${e.id}`;return Re(Wi,{testID:m,actions:[{label:"Bar",onPress:h},{label:"Dup",onPress:s},{label:"Delete",onPress:a,background:o.color.danger,color:o.color.onDanger}],children:Vt(u,{style:de.row,children:[Vt(P,{style:de.text,onPress:i,activeOpacity:.7,accessibilityRole:"button",accessibilityLabel:`${e.name}. ${Kr(e)}. Open restore preview`,testID:m,children:[Re(c,{style:de.name,numberOfLines:1,testID:`${m}-name`,children:e.name}),r?Re(c,{style:de.armed,numberOfLines:1,testID:`${m}-armed`,children:"On the action bar"}):null,Re(c,{style:de.meta,numberOfLines:1,testID:`${m}-meta`,children:Kr(e)}),e.lastRestoredAt?Vt(c,{style:de.restored,numberOfLines:1,testID:`${m}-restored`,children:["Restored ",_e(e.lastRestoredAt)]}):null,e.route?Re(c,{style:de.route,numberOfLines:1,testID:`${m}-route`,children:e.route.href}):null]}),Re(P,{onPress:n,disabled:t,style:[de.restore,t?de.actionDisabled:null],accessibilityRole:"button",accessibilityLabel:e.baseline?"Wipe and reload":"Restore",testID:`${m}-restore`,children:Re(fi,{testID:`${m}-restore-label`,label:e.baseline?"Wipe":"Restore",color:e.baseline?o.color.danger:o.color.accent,background:e.baseline?o.color.dangerSoft:o.color.accentSoft})})]})})}var de=O.create({row:{flexDirection:"row",alignItems:"center",gap:10,paddingHorizontal:o.textInset},text:{flex:1,minWidth:0,paddingVertical:11},restore:{justifyContent:"center"},name:{color:o.color.label,fontSize:o.font.row,fontWeight:"600",letterSpacing:o.tracking.row},meta:{color:o.color.labelSecondary,fontSize:o.font.footnote,marginTop:2,fontVariant:["tabular-nums"]},restored:{color:o.color.accent,fontSize:o.font.footnote,marginTop:2},armed:{color:o.color.accent,fontSize:o.font.footnote,marginTop:2},route:{color:o.color.labelTertiary,fontFamily:ht,fontSize:o.font.mono,marginTop:4},actionDisabled:{opacity:.4}});import{useEffect as Mi}from"react";import{jsx as qr,jsxs as Jr}from"react/jsx-runtime";var Vi=8e3;function Fi({name:e,at:t,onUndo:r,onExpire:i}){return Mi(()=>{let n=setTimeout(i,Vi);return()=>clearTimeout(n)},[t]),Jr(u,{style:Ft.bar,testID:"time-machine-undo-bar",children:[Jr(c,{style:Ft.text,numberOfLines:1,testID:"time-machine-undo-text",children:["Deleted \u201C",e,"\u201D"]}),qr(P,{onPress:r,hitSlop:{top:10,bottom:10,left:10,right:10},accessibilityRole:"button",testID:"time-machine-undo-delete",children:qr(c,{style:Ft.undo,children:"Undo"})})]})}var Ft=O.create({bar:{flexDirection:"row",alignItems:"center",gap:12,marginHorizontal:o.gutter,marginTop:12,minHeight:46,paddingHorizontal:o.textInset,backgroundColor:o.color.group,borderRadius:o.radius.group,borderWidth:1,borderColor:o.color.groupBorder},text:{flex:1,color:o.color.labelSecondary,fontSize:o.font.control,letterSpacing:o.tracking.control},undo:{color:o.color.accent,fontSize:o.font.control,fontWeight:"600",letterSpacing:o.tracking.control}});import{NightSwitch as _i}from"@buoy-gg/shared-ui/web";import{jsx as le,jsxs as _t}from"react/jsx-runtime";var Ki={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 qi(e){return Ki[e.id]??"App data"}function Ji(e){return e.enabled?e.canRestore?null:{text:"Can be saved but not put back",tone:"warn"}:{text:"Off \xB7 left as it is",tone:"off"}}function Ui({source:e,onToggle:t}){let r=Di(e.id),i=qi(e),n=Ji(e);return _t(u,{style:ue.row,testID:`time-machine-source-${e.id}`,accessibilityLabel:`${e.label}: ${i}${n?`. ${n.text}`:""}`,children:[le(u,{style:ue.disc,children:le(r,{size:22,bgColor:o.color.disc})}),_t(u,{style:ue.text,children:[le(c,{style:ue.label,numberOfLines:1,testID:`time-machine-source-${e.id}-label`,children:e.label}),le(c,{style:ue.description,numberOfLines:2,testID:`time-machine-source-${e.id}-description`,children:i}),n?le(c,{style:[ue.state,ue[`state_${n.tone}`]],numberOfLines:1,testID:n.tone==="off"?`time-machine-source-${e.id}-off`:`time-machine-source-${e.id}-detail`,children:n.text}):null]}),le(u,{testID:`time-machine-source-${e.id}-switch`,children:le(_i,{value:e.enabled,disabled:!t,onValueChange:a=>t?.(e.id,a)})})]})}function Yi({sources:e,onToggle:t}){let r=e.filter(i=>i.canCapture);return _t(mt,{children:[r.map(i=>le(Ui,{source:i,onToggle:t},i.id)),r.length===0?le(u,{style:ue.row,testID:"time-machine-sources-empty",children:le(c,{style:ue.description,children:"No state tools are set up in this app."})}):null]})}var ue=O.create({row:{flexDirection:"row",alignItems:"center",gap:12,minHeight:o.rowMinHeight,paddingHorizontal:o.textInset,paddingVertical:10},disc:{width:36,height:36,borderRadius:o.radius.pill,backgroundColor:o.color.disc,alignItems:"center",justifyContent:"center"},text:{flex:1,minWidth:0,gap:2},label:{color:o.color.label,fontSize:o.font.row,fontWeight:"500",letterSpacing:o.tracking.row},description:{fontSize:o.font.footnote,lineHeight:o.font.footnote*1.3,color:o.color.labelSecondary},state:{fontSize:o.font.mono,lineHeight:o.font.mono*1.3,fontWeight:"600",marginTop:1},state_off:{color:o.color.labelTertiary},state_warn:{color:o.color.warning}});import{jsx as Ur}from"react/jsx-runtime";function Xi({disabled:e,onWipe:t}){return Ur(P,{style:[Kt.row,e?Kt.disabled:null],onPress:t,disabled:e,accessibilityRole:"button",testID:"time-machine-wipe-all",children:Ur(c,{style:Kt.label,children:"Wipe All App State\u2026"})})}var Kt=O.create({row:{minHeight:o.rowMinHeight,alignItems:"center",justifyContent:"center"},disabled:{opacity:.4},label:{color:o.color.danger,fontSize:o.font.row,letterSpacing:o.tracking.row}});import{memo as Gi,useCallback as De,useEffect as Yr,useMemo as bt,useRef as qt,useState as Jt}from"react";import{ChevronUp as Xr,AlertTriangle as Qi,RefreshCw as Zi,useSafeAreaInsets as ea}from"@buoy-gg/shared-ui/web";import{useToolHeader as ta,useToolHost as ra}from"@buoy-gg/core/web";import{night as yt}from"@buoy-gg/shared-ui/web";import{useToolHost as oa}from"@buoy-gg/core/web";import{night as Ut,scheduleReloadApp as na}from"@buoy-gg/shared-ui/web";import{jsx as Gr}from"react/jsx-runtime";function ia(){let e=()=>{try{na({reason:"buoy time-machine reload app"})}catch{}};return Gr(P,{style:Qr.chip,onPress:e,accessibilityLabel:"Reload app",accessibilityHint:"Reloads the JavaScript bundle without restoring anything",accessibilityRole:"button",testID:"time-machine-reload-app",children:Gr(c,{style:Qr.label,children:"Reload app"})})}var Qr=O.create({chip:{height:32,paddingHorizontal:10,borderRadius:8,borderWidth:1,borderColor:Ut.color.border,backgroundColor:Ut.color.buttonSurface,alignItems:"center",justifyContent:"center"},label:{fontSize:11,fontWeight:"700",color:Ut.color.textSecondary}});import{useEffect as wt,useRef as aa,useState as ve,useSyncExternalStore as Zr}from"react";import{Check as eo,ChevronDown as sa,ChevronUp as la,FloatingTool as ca,NightSwitch as da,Plus as ua,TimeMachineIcon as ha,X as pa,night as T,openFloatingTool as ma,persistentStorage as fa,registerPersistentFloatingTool as ga,useLimit as ba}from"@buoy-gg/shared-ui/web";import{devToolsStorageKeys as ya,persistentStorage as Yt}from"@buoy-gg/shared-ui/web";var Xt=ya.timeMachine.armedPoint(),Ke=null,to=false,Gt=null,Qt=new Set,ro=()=>Qt.forEach(e=>e());function St(){return Ke}function oo(e){return Qt.add(e),()=>{Qt.delete(e)}}function wa(){return to?Promise.resolve():(Gt||(Gt=Yt.getItem(Xt).then(e=>{Ke===null&&e&&(Ke=e,ro())}).catch(()=>{}).finally(()=>{to=true})),Gt)}function Zt(e){Ke!==e&&(Ke=e,ro(),(e===null?Yt.removeItem(Xt):Yt.setItem(Xt,e)).catch(()=>{}))}function no(e,t){let r=e.filter(n=>!n.baseline&&!n.safety);if(r.length===0)return null;if(t){let n=r.find(a=>a.id===t);if(n)return n}let i=null;for(let n of r)n.lastRestoredAt!==void 0&&(!i||n.lastRestoredAt>(i.lastRestoredAt??0))&&(i=n);return i||r.reduce((n,a)=>a.createdAt>n.createdAt?a:n)}import{useEffect as Sa,useState as va}from"react";import{night as E}from"@buoy-gg/shared-ui/web";import{jsx as oe,jsxs as io}from"react/jsx-runtime";function xa({visible:e,summary:t,onCapture:r,onCancel:i}){let[n,a]=va("");Sa(()=>{e&&a("")},[e]);let s=()=>r(n.trim());return oe(Rr,{visible:e,transparent:true,animationType:"fade",onRequestClose:i,statusBarTranslucent:true,children:oe(xr,{behavior:nt.OS==="ios"?"padding":void 0,style:Z.fill,children:oe($t,{style:Z.backdrop,onPress:i,accessibilityLabel:"Cancel",testID:"time-machine-bar-name-backdrop",children:io($t,{style:Z.card,onPress:h=>h.stopPropagation(),testID:"time-machine-bar-name-panel",accessible:false,children:[oe(c,{style:Z.title,children:"Name this restore point"}),t?oe(c,{style:Z.summary,testID:"time-machine-bar-name-summary",children:t}):null,oe(it,{testID:"time-machine-bar-name-input",accessibilityLabel:"Restore point name",value:n,onChangeText:a,onSubmitEditing:s,placeholder:"Screen and time, if left empty",placeholderTextColor:E.color.placeholder,autoFocus:true,autoCorrect:false,autoCapitalize:"none",returnKeyType:"done",style:Z.input}),oe(c,{style:Z.hint,children:"Captures the state the app is in right now and arms it on the bar."}),io(u,{style:Z.actions,children:[oe(P,{testID:"time-machine-bar-name-cancel",accessibilityRole:"button",onPress:i,style:Z.secondary,children:oe(c,{style:Z.secondaryText,children:"Cancel"})}),oe(P,{testID:"time-machine-bar-name-capture",accessibilityRole:"button",accessibilityLabel:"Capture and arm this restore point",onPress:s,style:Z.primary,children:oe(c,{style:Z.primaryText,children:"Capture"})})]})]})})})})}var Z=O.create({fill:{flex:1},backdrop:{flex:1,backgroundColor:"rgba(0, 0, 0, 0.55)",alignItems:"center",justifyContent:"center",padding:24},card:{width:"100%",maxWidth:360,borderRadius:E.radius.sheet,borderWidth:1,borderColor:E.color.separator,backgroundColor:E.color.surface,padding:18,gap:12,shadowColor:"#000",shadowOffset:{width:0,height:12},shadowOpacity:.4,shadowRadius:24,elevation:12},title:{color:E.color.text,fontSize:E.font.title,fontWeight:"600"},input:{minHeight:44,borderRadius:E.radius.input,borderWidth:1,borderColor:E.color.accentBorder,backgroundColor:E.color.surfaceElevated,color:E.color.text,fontSize:E.font.row,paddingHorizontal:12},summary:{color:E.color.textTertiary,fontSize:E.font.caption,marginTop:-6},hint:{color:E.color.textSecondary,fontSize:E.font.caption,lineHeight:18},actions:{flexDirection:"row",justifyContent:"flex-end",gap:10,marginTop:4},secondary:{minHeight:40,paddingHorizontal:14,borderRadius:E.radius.input,alignItems:"center",justifyContent:"center"},secondaryText:{color:E.color.textSecondary,fontSize:14,fontWeight:"600"},primary:{minHeight:40,paddingHorizontal:18,borderRadius:E.radius.input,backgroundColor:E.color.accent,alignItems:"center",justifyContent:"center"},primaryText:{color:E.color.onAccent,fontSize:14,fontWeight:"700"}});import{devToolsStorageKeys as Ia,persistentStorage as ao}from"@buoy-gg/shared-ui/web";var so=Ia.timeMachine.barReloadMode(),qe=false,lo=false,er=null,tr=new Set,co=()=>tr.forEach(e=>e());function uo(){return qe}function Ra(e){return tr.add(e),()=>{tr.delete(e)}}function Da(){return lo?Promise.resolve():(er||(er=ao.getItem(so).then(e=>{!qe&&e==="1"&&(qe=true,co())}).catch(()=>{}).finally(()=>{lo=true})),er)}function ka(e){e!==qe&&(qe=e,co(),ao.setItem(so,e?"1":"0").catch(()=>{}))}import{Fragment as Ta,jsx as R,jsxs as F}from"react/jsx-runtime";var rr="time-machine-restore",vt=1e4,ho=900,or=6,po={id:rr,render:e=>R(za,{...e})};typeof fr<"u"&&fr&&typeof navigator<"u"&&navigator.product==="ReactNative"&&ga(po,fa);function nr(e){e&&Zt(e),ma(po)}function Ca(e){let t=Object.values(e.results),r=t.filter(s=>!s.ok||s.skipped.length>0).length,i=t.length,n=e.route,a=n?.status==="failed"||n?.status==="unavailable";return r===0&&a?"Route did not restore":`${r} of ${i} source${i===1?"":"s"} failed`}function $a(e){let t=[];for(let[i,n]of Object.entries(e.results)){if(n.ok&&n.skipped.length===0)continue;let a=n.skipped[0]?.reason??n.warnings[0]??"did not apply";t.push(`${i}: ${a}`)}let r=e.route;return(r?.status==="failed"||r?.status==="unavailable")&&t.push(`route: ${r.status}`),t}function mo(e){let[t,r]=ve(0);return wt(()=>{if(!t)return;let i=setTimeout(()=>r(0),e);return()=>clearTimeout(i)},[t,e]),[t>0,()=>r(i=>i+1)]}function za({id:e,revealToken:t,dismiss:r}){let{snapshots:i,hasLoaded:n,busy:a}=ut(),s=jr(),h=Zr(oo,St,St),m=ba("timeMachine.snapshots"),y=Zr(Ra,uo,uo),{width:d}=Ir(),[k,L]=ve(null),[b,H]=ve(null),[W,j]=ve(),[w,U]=ve(false),[ee,Y]=mo(ho),[Le,te]=mo(ho),[_,$]=ve(null),[ne,pe]=ve(null),[,ke]=ve(0),ie=aa(true);wt(()=>(ie.current=true,wa(),Da(),v.ensureLoaded(),()=>{ie.current=false}),[]);let D=no(i,h),Ge=D?.id,Pe=D?.lastRestoredAt,Qe=D?.createdAt;wt(()=>{if(Pe===void 0&&Qe===void 0&&!_&&ne===null)return;let f=setInterval(()=>ke(V=>V+1),2500);return()=>clearInterval(f)},[Pe,Qe,_,ne]),wt(()=>{b&&b.snapshotId!==Ge&&(H(null),L(f=>f==="outcome"?null:f))},[Ge,b]);let Te=Date.now(),Ze=_!==null&&Te-_.at<vt&&i.some(f=>f.id===_.id),Ae=i.filter(f=>!f.safety).length>=m,l=!D||a!==null,S=a!==null,C=async(f,V)=>{if(!a){L(null),j(void 0);try{let G=await v.restore(f,y&&V.safetyCapture?"reload":"live",void 0,V);if(!ie.current)return;Mr(G)?(H(G),L("outcome")):(H(null),Y()),$(G.safetySnapshotId?{id:G.safetySnapshotId,at:Date.now()}:null),G.safetySnapshotId&&pe(null)}catch(G){if(!ie.current)return;j(G instanceof Error?G.message:String(G)),L("error")}}},I=(f=false)=>{D&&C(D.id,{safetyCapture:true,...f?{restoreRoute:false}:{}})},K=()=>{_&&C(_.id,{safetyCapture:false,restoreRoute:false}).then(()=>{ie.current&&pe(Date.now())})},re=()=>{if(!a){if(j(void 0),Ae){L("cap");return}L(null),U(true)}},X=async f=>{if(U(false),!a)try{let V=await v.capture(f);if(!ie.current)return;Zt(V.id),$(null),te()}catch(V){if(!ie.current)return;j(V instanceof Error?V.message:String(V)),L("error")}},Oe=f=>{Zt(f.id),L(null)},et=D?.name??(n?"No restore points":"Loading\u2026"),q,Ce="normal",tt=false;if(a==="restore")q="Restoring\u2026";else if(a==="capture")q="Capturing\u2026";else if(W)q=W,Ce="danger";else if(b&&D&&b.snapshotId===D.id)q=Ca(b),Ce="danger";else if(!D)q=n?"Capture one with +":"";else{tt=true;let f=D.lastRestoredAt===void 0?null:Te-D.lastRestoredAt,V=Te-D.createdAt;ne!==null&&Te-ne<vt?q="undone, state only":f!==null&&f<vt?q="restored just now":V<vt&&f===null?q="captured just now":D.lastRestoredAt!==void 0?q=`restored ${_e(D.lastRestoredAt)}`:q=`${Object.keys(D.sources).length} sources`,y&&(q+=" \xB7 reloads")}let ce=tt&&!Ze&&D&&D.route&&dt(D)?D.route.pathname:null,$e=i.filter(f=>!f.baseline&&!f.safety),rt=(()=>{let f=s.filter(hr=>hr.status().canCapture&&se(hr.id)).length,V=ot(),G=[`${f} source${f===1?"":"s"}`];return V&&G.push(V.pathname),G.join(" \xB7 ")})(),z;return k==="picker"?z=F(u,{style:x.menu,testID:"time-machine-bar-picker",children:[F(zt,{style:x.pickerList,bounces:false,children:[$e.map(f=>{let V=f.id===D?.id;return F(P,{testID:`time-machine-bar-pick-${f.id}`,accessibilityRole:"button",accessibilityState:{selected:V},accessibilityLabel:`Arm ${f.name}`,onPress:()=>Oe(f),style:x.pickRow,children:[F(u,{style:x.pickText,children:[R(c,{numberOfLines:1,style:x.pickName,children:f.name}),F(c,{numberOfLines:1,style:x.pickDetail,children:[_e(f.createdAt),f.route?` \xB7 ${f.route.pathname}`:"",f.lastRestoredAt!==void 0?R(c,{style:x.pickRestored,children:` \xB7 restored ${_e(f.lastRestoredAt)}`}):null]})]}),V?R(eo,{size:14,color:T.color.accent}):null]},f.id)}),$e.length===0?R(c,{style:x.menuText,children:"No restore points yet."}):null]}),$e.length>or?F(c,{style:x.pickerMore,children:["Scroll for ",$e.length-or," more"]}):null,F(u,{style:x.settingRow,testID:"time-machine-bar-reload-mode",children:[F(u,{style:x.settingText,children:[R(c,{style:x.settingLabel,children:"Reload the app after restoring"}),R(c,{style:x.settingHint,children:"For screens that read their state from storage only when they open, like a cart kept in a React context."})]}),R(da,{value:y,onValueChange:ka})]})]}):k==="outcome"&&b?z=F(u,{style:x.menu,testID:"time-machine-bar-outcome",children:[$a(b).map(f=>R(c,{style:x.menuDanger,children:f},f)),R(c,{style:x.menuText,children:"The full report is on Time Machine's outcome card."}),R(ir,{onPress:()=>L(null)})]}):k==="cap"?z=F(u,{style:x.menu,testID:"time-machine-bar-cap",children:[F(c,{style:x.menuText,children:["Free plan keeps ",m," restore point",m===1?"":"s",". Delete one in Time Machine, or upgrade to Pro for unlimited snapshots."]}),R(ir,{onPress:()=>L(null)})]}):k==="error"&&W&&(z=F(u,{style:x.menu,testID:"time-machine-bar-error",children:[R(c,{accessibilityRole:"alert",style:x.menuDanger,children:W}),R(ir,{onPress:()=>{L(null),j(void 0)}})]})),F(Ta,{children:[R(xa,{visible:w,summary:rt,onCapture:f=>void X(f),onCancel:()=>U(false)}),R(ca,{id:e,revealToken:t,variant:"strip",dragFromSurface:true,defaultPlacement:"bottom",accessibilityLabel:`Move or hide the action bar. ${D?`${D.name} armed`:"Nothing armed"}`,accessory:z,handleAdornment:R(ha,{size:12,color:T.color.accent}),children:F(u,{style:[x.row,{width:Math.max(260,Math.min(320,d-64))}],children:[R(P,{testID:"time-machine-bar-restore",accessibilityRole:"button",accessibilityLabel:D?`Restore ${D.name}`:"Restore, nothing armed",accessibilityHint:ce?`Also returns to ${ce}. Long press to restore state only.`:void 0,accessibilityState:{disabled:l},disabled:l,onPress:()=>I(false),onLongPress:()=>I(true),style:[x.restoreButton,l&&x.disabled],children:a==="restore"?R(at,{size:"small",color:T.color.accent}):ee?R(c,{style:x.restoreText,testID:"time-machine-bar-restored",children:"Restored"}):R(c,{style:x.restoreText,children:"Restore"})}),F(u,{style:x.identity,children:[R(c,{testID:"time-machine-bar-name",accessibilityLabel:`Armed restore point: ${et}`,numberOfLines:1,ellipsizeMode:"middle",style:x.name,children:et}),F(u,{style:x.statusRow,children:[F(c,{testID:"time-machine-bar-status",numberOfLines:1,accessibilityLiveRegion:"polite",style:[x.status,Ce==="danger"&&x.danger],children:[q,ce?R(c,{style:x.destination,children:` \xB7 \u2192 ${ce}`}):null]}),Ze&&!a?R(P,{testID:"time-machine-bar-undo",accessibilityRole:"button",accessibilityLabel:"Undo the last restore",onPress:K,hitSlop:{top:8,bottom:8,left:6,right:6},children:R(c,{style:x.undo,children:"Undo"})}):null]})]}),R(P,{testID:"time-machine-bar-pick",accessibilityRole:"button",accessibilityLabel:"Choose another restore point",accessibilityState:{expanded:k==="picker"},onPress:()=>L(f=>f==="picker"?null:"picker"),style:x.smallButton,children:k==="picker"?R(la,{size:14,color:T.color.textSecondary}):R(sa,{size:14,color:T.color.textSecondary})}),R(P,{testID:"time-machine-bar-capture",accessibilityRole:"button",accessibilityLabel:"Capture a new restore point here and arm it",accessibilityState:{disabled:S},disabled:S,onPress:re,style:[x.smallButton,S&&x.disabled],children:a==="capture"?R(at,{size:"small",color:T.color.accent}):Le?R(u,{testID:"time-machine-bar-captured",children:R(eo,{size:18,color:T.color.accent})}):R(ua,{size:18,color:Ae?T.color.textTertiary:T.color.text})}),R(u,{style:x.separator}),R(P,{testID:"time-machine-bar-close",accessibilityRole:"button",accessibilityLabel:"Close the action bar",onPress:r,style:x.closeButton,children:R(pa,{size:16,color:T.color.textSecondary})})]})})]})}function ir({onPress:e,label:t="Dismiss"}){return R(P,{testID:"time-machine-bar-dismiss",accessibilityRole:"button",onPress:e,style:x.dismiss,children:R(c,{style:x.dismissText,children:t})})}var x=O.create({row:{flexDirection:"row",alignItems:"center",gap:4,paddingVertical:4,minHeight:48},restoreButton:{height:32,minWidth:72,paddingHorizontal:12,borderRadius:8,borderWidth:1,borderColor:T.color.accentBorderStrong,backgroundColor:T.color.accentSoft,alignItems:"center",justifyContent:"center",marginLeft:2},restoreText:{color:T.color.accent,fontSize:12,fontWeight:"700"},smallButton:{width:32,minHeight:44,alignItems:"center",justifyContent:"center"},closeButton:{width:28,minHeight:44,alignItems:"center",justifyContent:"center"},identity:{flex:1,minHeight:44,justifyContent:"center",gap:1},name:{color:T.color.text,fontSize:13,fontWeight:"500"},statusRow:{flexDirection:"row",alignItems:"center",gap:8},status:{color:T.color.textSecondary,fontSize:10,lineHeight:14,flexShrink:1},destination:{color:T.color.textTertiary},danger:{color:T.color.danger},undo:{color:T.color.accent,fontSize:10,lineHeight:14,fontWeight:"700"},separator:{height:20,width:1,backgroundColor:T.color.separator,marginHorizontal:2},disabled:{opacity:.4},menu:{marginVertical:8,padding:6,borderRadius:T.radius.card,borderWidth:1,borderColor:T.color.separator,backgroundColor:T.color.surface,shadowColor:"#000",shadowOffset:{width:0,height:6},shadowOpacity:.25,shadowRadius:16,elevation:8},menuText:{color:T.color.textSecondary,fontSize:12,lineHeight:18,padding:10},menuDanger:{color:T.color.danger,fontSize:12,lineHeight:18,paddingHorizontal:10,paddingTop:6},pickerList:{maxHeight:or*44},pickerMore:{color:T.color.textTertiary,fontSize:10,lineHeight:14,textAlign:"center",paddingVertical:4},pickRow:{flexDirection:"row",alignItems:"center",gap:8,minHeight:44,paddingHorizontal:10,borderRadius:T.radius.row},pickText:{flex:1},settingRow:{flexDirection:"row",alignItems:"center",gap:10,paddingHorizontal:10,paddingVertical:8,borderTopWidth:O.hairlineWidth,borderTopColor:T.color.separator,marginTop:4},settingText:{flex:1,gap:2},settingLabel:{color:T.color.text,fontSize:12,fontWeight:"500"},settingHint:{color:T.color.textTertiary,fontSize:10,lineHeight:13},pickName:{color:T.color.text,fontSize:13,fontWeight:"500"},pickDetail:{color:T.color.textSecondary,fontSize:10,lineHeight:14},pickRestored:{color:T.color.accent},dismiss:{alignSelf:"flex-end",paddingHorizontal:10,paddingVertical:8},dismissText:{color:T.color.accent,fontSize:12,fontWeight:"600"}});import{jsx as xt,jsxs as fo}from"react/jsx-runtime";function La({armId:e}){let t=oa(),r=()=>{nr(e),t.minimize()};return fo(P,{style:It.labeledChip,onPress:r,accessibilityLabel:"Open the floating action bar over the app",accessibilityRole:"button",testID:"time-machine-header-bar",children:[xt(u,{style:It.glyph}),xt(c,{style:It.label,children:"Action bar"})]})}function go({armId:e}){return fo(u,{style:It.row,children:[xt(La,{armId:e}),xt(ia,{})]})}var It=O.create({row:{flexDirection:"row",alignItems:"center",gap:8},labeledChip:{height:32,flexDirection:"row",alignItems:"center",gap:6,paddingHorizontal:10,borderRadius:8,borderWidth:1,borderColor:yt.color.border,backgroundColor:yt.color.buttonSurface},glyph:{width:14,height:8,borderRadius:3,borderWidth:1.5,borderColor:yt.color.accent},label:{fontSize:11,fontWeight:"700",color:yt.color.accent}});import{useMemo as Pa}from"react";import{ABSENT_VALUE as bo,ThemedSplitView as Aa,devToolsDefaultTheme as Oa,toDiffable as yo}from"@buoy-gg/shared-ui/web/dataViewer";import{jsx as Ha,jsxs as wo}from"react/jsx-runtime";var Ea=[];function Ba({item:e,testID:t}){let{oldValue:r,newValue:i}=Pa(()=>({oldValue:e.verdict==="added"?bo:yo(e.oldValue),newValue:e.verdict==="removed"?bo:yo(e.newValue)}),[e]);return wo(u,{style:So.panel,testID:t,children:[e.reason?wo(c,{style:So.reason,children:["\u26A0 ",e.reason]}):null,Ha(Aa,{oldValue:r,newValue:i,differences:Ea,theme:Oa,scrollEnabled:false})]})}var So=O.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}});import{useEffect as Wa,useState as ja}from"react";import{jsx as vo,jsxs as Na}from"react/jsx-runtime";function Ma({name:e,onRename:t}){let[r,i]=ja(e);Wa(()=>i(e),[e]);let n=()=>{let a=r.trim();if(!a){i(e);return}a!==e&&t(a)};return Na(u,{style:ar.row,children:[vo(c,{style:ar.label,children:"Name"}),vo(it,{style:ar.input,value:r,onChangeText:i,onSubmitEditing:n,onBlur:n,returnKeyType:"done",selectTextOnFocus:true,accessibilityLabel:"Restore point name",testID:"tm-preview-name"})]})}var ar=O.create({row:{flexDirection:"row",alignItems:"center",gap:14,minHeight:o.rowMinHeight,paddingHorizontal:o.textInset},label:{color:o.color.labelSecondary,fontSize:o.font.row,letterSpacing:o.tracking.row},input:{flex:1,minWidth:0,color:o.color.label,fontSize:o.font.row,fontWeight:"600",letterSpacing:o.tracking.row,textAlign:"right",padding:0,backgroundColor:"transparent"}});var Je={added:{glyph:"+",color:o.color.accent,label:"added",applies:true},removed:{glyph:"\u2212",color:o.color.danger,label:"removed",applies:true},changed:{glyph:"\u2248",color:o.color.info,label:"changed",applies:true},"too-large":{glyph:"\u2248",color:o.color.warning,label:"changed (large)",applies:true},unchanged:{glyph:"=",color:o.color.labelTertiary,label:"unchanged",applies:false},"wont-apply":{glyph:"\u2298",color:o.color.warning,label:"won't apply",applies:false},recomputes:{glyph:"\u21BB",color:o.color.labelTertiary,label:"recomputes",applies:false}};import{Fragment as Va,jsx as p,jsxs as B}from"react/jsx-runtime";var xo={storage:"keys",redux:"slices",zustand:"stores",jotai:"atoms",query:"queries"},sr=new Set;function Fa(e,t){if(e.size!==t.size)return false;for(let r of e)if(!t.has(r))return false;return true}function he(e,t){return`${e}::${t}`}function Rt(e){if(e===void 0)return"\u2205";try{let t=typeof e=="string"?`"${e}"`:JSON.stringify(e);return t?t.length>46?`${t.slice(0,43)}\u2026`:t:String(e)}catch{return"[complex]"}}function Ue({position:e,children:t}){return B(u,{style:[g.cardRow,e.first?g.cardRowFirst:null,e.last?g.cardRowLast:null],children:[e.first?null:p(u,{style:g.cardSeparator}),t]})}function lr({glyph:e,count:t,color:r,testID:i}){return p(u,{style:[g.countPill,{backgroundColor:`${r}26`}],children:B(c,{style:[g.countPillText,{color:r}],testID:i,children:[e,t]})})}function cr({state:e}){return p(u,{style:[g.checkbox,e!=="none"&&g.checkboxChecked],children:e==="none"?null:p(c,{style:g.checkboxGlyph,children:e==="all"?"\u2713":"\u2212"})})}var _a=Gi(function({row:e,expanded:t,onOpen:r,onToggle:i}){let n=Je[e.item.verdict],a=!n.applies||e.excluded,s=e.item.verdict==="changed"||e.item.verdict==="added"||e.item.verdict==="removed",h=`tm-preview-item-${e.sourceId}-${e.item.key}`;return p(Ue,{position:e,children:B(u,{style:[g.itemRow,a&&g.dimmed],children:[p(P,{onPress:i,disabled:!n.applies,hitSlop:{top:10,bottom:10,left:8,right:8},testID:`tm-preview-toggle-${e.sourceId}-${e.item.key}`,accessibilityRole:"checkbox",accessibilityState:{checked:!(!n.applies||e.excluded)},accessibilityLabel:`Include ${e.item.label}`,children:p(cr,{state:!n.applies||e.excluded?"none":"all"})}),B(P,{style:g.itemBodyTouch,onPress:()=>s&&r(),disabled:!s,testID:h,children:[p(c,{style:[g.itemGlyph,{color:n.color}],children:n.glyph}),B(u,{style:g.itemBody,children:[p(c,{style:g.itemLabel,numberOfLines:1,testID:`${h}-label`,children:e.item.label}),e.item.verdict==="changed"&&B(c,{style:g.itemPreview,numberOfLines:1,testID:`${h}-values`,children:[Rt(e.item.oldValue)," \u2192"," ",Rt(e.item.newValue)]}),e.item.verdict==="added"&&p(c,{style:g.itemPreview,numberOfLines:1,testID:`${h}-values`,children:Rt(e.item.newValue)}),e.item.verdict==="removed"&&p(c,{style:[g.itemPreview,g.itemPreviewRemoved],numberOfLines:1,testID:`${h}-values`,children:Rt(e.item.oldValue)}),e.excluded?p(c,{style:g.itemExcluded,testID:`${h}-excluded`,children:"excluded \u2014 restore leaves this untouched"}):e.item.reason&&p(c,{style:g.itemReason,numberOfLines:2,testID:`${h}-reason`,children:e.item.reason})]}),s?t?p(Xr,{size:16,color:o.color.labelTertiary}):p(Nr,{}):null]})]})})});function Ka({preview:e,snapshots:t,busy:r,onBack:i,onRestore:n}){let a=ra(),s=a.instanceId!==void 0,h=ea({minBottom:16}),[m,y]=Jt({}),[d,k]=Jt(new Set),L=qt(false),[b,H]=Jt(sr),W=De(l=>{H(S=>{let C=new Set(S);return C.has(l)?C.delete(l):C.add(l),C})},[]),j=a.search,w=e.right==="current"?void 0:t.find(l=>l.id===e.right.snapshotId),U=qt(w);U.current=w;let ee=De(()=>{if(!U.current)return;let l=U.current;v.setRestoreRoute(l.id,!dt(l))},[]),Y=w?.baseline===true,Le=e.left==="current",te=bt(()=>w?w.excludedKeys?.length?new Set(w.excludedKeys):sr:null,[w]),_=!!w?.scope?.length&&!w?.excludedKeys?.length,$=bt(()=>{if(!_||!w?.scope)return sr;let l=new Set(w.scope),S=new Set;for(let C of e.sources)for(let I of C.items){let K=he(C.id,I.key);Je[I.verdict].applies&&!l.has(K)&&S.add(K)}return S},[_,w,e.sources]),ne=qt(null);Yr(()=>{if(!w||e.building||!te||ne.current===w.id)return;ne.current=w.id,L.current=false;let l=te.size>0?te:$;l.size>0&&k(new Set(l)),_&&l.size>0&&v.setExclusions(w.id,Array.from(l))},[w,e.building,te,$,_]),Yr(()=>{if(!w||!te||!L.current||Fa(d,te))return;let l=Array.from(d);v.setExclusions(w.id,l.length?l:null)},[d,w,te]);let pe=De(l=>{L.current=true,k(S=>{let C=new Set(S);return C.has(l)?C.delete(l):C.add(l),C})},[]),ke=De((l,S)=>{L.current=true,k(C=>{let I=new Set(C);for(let K of l.items){if(!Je[K.verdict].applies)continue;let re=he(l.id,K.key);S==="all"?I.add(re):I.delete(re)}return I})},[]),ie=De((l,S)=>{y(C=>({...C,[l]:!S}))},[]),D=bt(()=>{let l=0,S=0,C=0,I=[];for(let K of e.sources){let re=0;for(let X of K.items)Je[X.verdict].applies?d.has(he(K.id,X.key))?S+=1:(l+=1,re+=1):X.verdict==="wont-apply"&&(C+=1);re>0&&I.push(`${re} ${K.label.toLowerCase()}`)}return{applies:l,excludedCount:S,wontApply:C,perSource:I}},[e.sources,d]);ta(s?{title:"Restore Preview",subtitle:w?.name??"preview",onBack:i,actions:p(go,{armId:w?.id})}:null,[s,w?.name,w?.id]);let{rows:Ge,blockedSources:Pe}=bt(()=>{let l=j.trim().toLowerCase(),S=[],C=[];for(let I of e.sources){let K=I.items.some(z=>z.verdict!=="unchanged");if(!K&&!I.error)continue;let re=K||I.notes.length>0||!!I.error,X=I.items.filter(z=>Je[z.verdict].applies),Oe=I.items.filter(z=>z.verdict==="wont-apply").length;Oe>0&&C.push(I.label);let et=I.items.length===1?(xo[I.id]??"items").replace(/ies$/,"y").replace(/s$/,""):xo[I.id]??"items",q=`${I.items.length} ${et} \xB7 `+(X.length>0?`${X.length} changed`:Oe>0?`${Oe} won't apply`:"no changes"),Ce=X.filter(z=>d.has(he(I.id,z.key))).length,tt=X.length===0||Ce===0?"all":Ce===X.length?"none":"some",ce={added:0,removed:0,changed:0};for(let z of I.items)d.has(he(I.id,z.key))||(z.verdict==="added"?ce.added+=1:z.verdict==="removed"?ce.removed+=1:(z.verdict==="changed"||z.verdict==="too-large")&&(ce.changed+=1));let $e=I.items.filter(z=>!(z.verdict==="unchanged"||l&&!z.label.toLowerCase().includes(l))),rt=re?m[I.id]??true:true;if(S.push({kind:"source",source:I,collapsed:rt,includeState:tt,applicableCount:X.length,counts:ce,expandable:re,summary:q,first:false,last:false}),!rt){for(let z of I.notes)S.push({kind:"note",id:`${I.id}:${z}`,text:z,first:false,last:false});I.error&&S.push({kind:"note",id:`${I.id}:err`,text:`\u26A0 ${I.error}`,first:false,last:false});for(let z of $e){let f=he(I.id,z.key);S.push({kind:"item",sourceId:I.id,item:z,excluded:d.has(f),first:false,last:false}),b.has(f)&&S.push({kind:"diff",sourceId:I.id,item:z,first:false,last:false})}}}return w?.route&&S.push({kind:"route",href:w.route.href,on:dt(w),first:false,last:false}),S.length>0&&(S[0].first=true,S[S.length-1].last=true),{rows:S,blockedSources:C}},[e.sources,j,m,d,b,w]),Qe=De(({item:l})=>{if(l.kind==="source"){let S=l.source,{counts:C}=l;return p(Ue,{position:l,children:B(u,{style:g.sourceCard,children:[p(P,{onPress:()=>ke(S,l.includeState),disabled:l.applicableCount===0,hitSlop:{top:10,bottom:10,left:8,right:8},testID:`tm-preview-source-toggle-${S.id}`,children:p(cr,{state:l.applicableCount===0?"none":l.includeState})}),B(P,{style:g.sourceCardTouch,onPress:()=>l.expandable&&ie(S.id,l.collapsed),disabled:!l.expandable,testID:`tm-preview-source-${S.id}`,children:[B(u,{style:g.sourceNameBlock,children:[p(c,{style:g.sourceName,numberOfLines:1,testID:`tm-preview-source-${S.id}-name`,children:S.label}),p(c,{style:g.sourceSummary,numberOfLines:1,testID:`tm-preview-source-${S.id}-summary`,children:l.includeState==="none"&&l.applicableCount>0?`${l.summary} \xB7 excluded`:l.summary})]}),B(u,{style:g.sourceBadges,children:[C.removed>0?p(lr,{glyph:"\u2212",count:C.removed,color:o.color.danger,testID:`tm-preview-source-${S.id}-removed`}):null,C.added>0?p(lr,{glyph:"+",count:C.added,color:o.color.accent,testID:`tm-preview-source-${S.id}-added`}):null,C.changed>0?p(lr,{glyph:"\u2248",count:C.changed,color:o.color.info,testID:`tm-preview-source-${S.id}-changed`}):null]}),l.expandable?l.collapsed?p(Nr,{}):p(Xr,{size:16,color:o.color.labelTertiary}):null]})]})})}return l.kind==="note"?p(Ue,{position:l,children:p(c,{style:g.noteRow,testID:`tm-preview-note-${l.id}`,children:l.text})}):l.kind==="route"?p(Ue,{position:l,children:B(P,{style:g.routeRow,onPress:ee,accessibilityRole:"switch",accessibilityState:{checked:l.on},accessibilityLabel:`Also return to ${l.href}`,testID:"tm-preview-route",children:[p(cr,{state:l.on?"all":"none"}),B(u,{style:g.routeText,children:[p(c,{style:g.routeTitle,children:"Return to this screen"}),p(c,{style:g.routeHref,numberOfLines:1,testID:"tm-preview-route-href",children:l.href})]})]})}):l.kind==="diff"?p(Ue,{position:l,children:p(Ba,{item:l.item,testID:`tm-preview-diff-${l.sourceId}-${l.item.key}`})}):p(_a,{row:l,expanded:b.has(he(l.sourceId,l.item.key)),onOpen:()=>W(he(l.sourceId,l.item.key)),onToggle:()=>pe(he(l.sourceId,l.item.key))})},[b,W,ie,pe,ke,ee]),Te=De(l=>l.kind==="source"?`s:${l.source.id}`:l.kind==="note"?`n:${l.id}`:l.kind==="route"?"route":l.kind==="diff"?`d:${l.sourceId}:${l.item.key}`:`i:${l.sourceId}:${l.item.key}`,[]),Ze=B(u,{children:[!s&&B(u,{style:g.fallbackHeader,children:[p(P,{onPress:i,hitSlop:qa,testID:"tm-preview-back",children:p(c,{style:g.backText,children:"\u2039 Back"})}),p(c,{style:g.screenTitle,numberOfLines:1,children:"Restore Preview"})]}),w?B(Va,{children:[p(pt,{children:"Restore Point"}),p(mt,{children:p(Ma,{name:w.name,onRename:l=>void v.rename(w.id,l)})})]}):null,p(pt,{children:"Changes to Restore"})]}),Ae=r||e.building||D.applies===0;return B(u,{style:g.container,children:[p(vr,{testID:"tm-preview-list",data:Ge,renderItem:Qe,keyExtractor:Te,ListHeaderComponent:Ze,ListEmptyComponent:e.building?p(at,{style:g.buildingSpinner,size:"small",color:o.color.accent}):p(c,{style:g.emptyText,testID:"tm-preview-empty",children:j?"Nothing matches this filter.":"No changes \u2014 restoring would change nothing."}),ListFooterComponent:p(u,{children:D.wontApply>0?B(u,{style:g.warnNote,children:[p(Qi,{size:12,color:o.color.warning}),B(c,{style:g.warnNoteText,testID:"tm-preview-wont-apply",children:[D.wontApply," item",D.wontApply===1?"":"s"," ","won't apply \u2014 expand"," ",Pe.length>0?Pe.join(" and "):"the source"," ","to see the reason."]})]}):null}),keyboardShouldPersistTaps:"handled",removeClippedSubviews:true,initialNumToRender:20,windowSize:7,contentContainerStyle:g.listContent}),Le&&w&&B(u,{style:[g.footer,{paddingBottom:h.bottom}],children:[B(P,{style:[g.cta,Y&&g.ctaDanger,Ae&&g.ctaDisabled],onPress:()=>n(Y?"reload":"live",Array.from(d)),disabled:Y?r||e.building:Ae,testID:"tm-preview-restore",children:[p(Zi,{size:16,color:Y?o.color.onDanger:o.color.onAccent}),p(c,{style:[g.ctaText,Y?g.ctaTextDanger:null],children:Y?"Wipe & Reload":"Restore State"})]}),p(c,{style:g.ctaCaption,testID:"tm-preview-cta-caption",children:Y?"This wipes all app storage and reloads the app.":D.excludedCount>0?`Restores ${D.applies} of ${D.applies+D.excludedCount} change${D.applies+D.excludedCount===1?"":"s"} \u2014 everything else stays as it is.`:"This will replace the current state with the snapshot."})]})]})}var qa={top:10,bottom:10,left:10,right:10},g=O.create({container:{flex:1,backgroundColor:"transparent"},fallbackHeader:{flexDirection:"row",alignItems:"center",paddingHorizontal:o.gutter,paddingVertical:10,gap:10},backText:{color:o.color.accent,fontSize:o.font.control},screenTitle:{color:o.color.label,fontSize:20,fontWeight:"700",letterSpacing:o.tracking.row,flex:1},dimmed:{opacity:.5},listContent:{paddingTop:14,paddingBottom:12},cardRow:{marginHorizontal:o.gutter,backgroundColor:o.color.group},cardRowFirst:{borderTopLeftRadius:o.radius.group,borderTopRightRadius:o.radius.group},cardRowLast:{borderBottomLeftRadius:o.radius.group,borderBottomRightRadius:o.radius.group,marginBottom:10},cardSeparator:{height:O.hairlineWidth,marginLeft:51,backgroundColor:o.color.separator},warnNote:{flexDirection:"row",alignItems:"flex-start",gap:6,paddingHorizontal:o.gutter+o.textInset,paddingTop:8},warnNoteText:{flex:1,color:o.color.labelSecondary,fontSize:o.font.footnote,lineHeight:o.font.footnote*1.35},countPill:{borderRadius:o.radius.pill,paddingHorizontal:9,paddingVertical:3},countPillText:{fontFamily:ht,fontSize:o.font.footnote,fontWeight:"600"},checkbox:{width:23,height:23,borderRadius:o.radius.pill,borderWidth:1.7,borderColor:o.color.labelTertiary,alignItems:"center",justifyContent:"center"},checkboxChecked:{borderColor:o.color.accent,backgroundColor:o.color.accent},checkboxGlyph:{color:o.color.onAccent,fontSize:13,fontWeight:"700",lineHeight:15},routeRow:{flexDirection:"row",alignItems:"center",minHeight:58,paddingHorizontal:o.textInset,paddingVertical:9,gap:12},routeText:{flex:1,minWidth:0,gap:2},routeTitle:{color:o.color.label,fontSize:o.font.row,fontWeight:"600",letterSpacing:o.tracking.row},routeHref:{color:o.color.labelSecondary,fontFamily:ht,fontSize:o.font.mono},sourceCard:{flexDirection:"row",alignItems:"center",minHeight:58,paddingHorizontal:o.textInset,paddingVertical:9,gap:12},sourceCardTouch:{flex:1,flexDirection:"row",alignItems:"center",gap:12,minWidth:0},sourceNameBlock:{flex:1,minWidth:0,gap:2},sourceName:{color:o.color.label,fontSize:o.font.row,fontWeight:"600",letterSpacing:o.tracking.row},sourceSummary:{color:o.color.labelSecondary,fontSize:o.font.footnote,fontVariant:["tabular-nums"]},sourceBadges:{flexDirection:"row",gap:6},noteRow:{color:o.color.labelTertiary,fontSize:o.font.footnote,lineHeight:o.font.footnote*1.35,paddingHorizontal:o.textInset,paddingVertical:9},itemRow:{flexDirection:"row",alignItems:"center",paddingLeft:o.textInset,paddingRight:o.textInset,paddingVertical:10,gap:12},itemBodyTouch:{flex:1,flexDirection:"row",alignItems:"center",gap:10,minWidth:0},itemGlyph:{fontSize:14,fontWeight:"700",width:14,textAlign:"center"},itemBody:{flex:1,minWidth:0},itemLabel:{color:o.color.label,fontSize:o.font.control,letterSpacing:o.tracking.control},itemPreview:{color:o.color.labelSecondary,fontFamily:ht,fontSize:o.font.mono,marginTop:3},itemPreviewRemoved:{textDecorationLine:"line-through"},itemReason:{color:o.color.warning,fontSize:o.font.mono,marginTop:3},itemExcluded:{color:o.color.labelTertiary,fontSize:o.font.mono,marginTop:3,fontStyle:"italic"},buildingSpinner:{marginTop:28},emptyText:{color:o.color.labelSecondary,fontSize:o.font.footnote,textAlign:"center",marginTop:28},footer:{paddingHorizontal:o.gutter,paddingTop:10,gap:8,borderTopColor:o.color.separator,borderTopWidth:O.hairlineWidth,backgroundColor:o.color.sheet},cta:{flexDirection:"row",alignItems:"center",justifyContent:"center",gap:8,height:50,backgroundColor:o.color.accent,borderRadius:o.radius.group},ctaDanger:{backgroundColor:o.color.danger},ctaTextDanger:{color:o.color.onDanger},ctaDisabled:{opacity:.4},ctaText:{color:o.color.onAccent,fontSize:o.font.row,fontWeight:"600",letterSpacing:o.tracking.row},ctaCaption:{color:o.color.labelSecondary,fontSize:o.font.footnote,lineHeight:o.font.footnote*1.35,textAlign:"center"}});import{jsx as Ja}from"react/jsx-runtime";function Ua(e,t){return e==="current"?void 0:t.find(r=>r.id===e.snapshotId)}function Ya({preview:e,snapshots:t,busy:r,onClose:i}){let n=Ua(e.right,t);return Ja(Ka,{preview:e,snapshots:t,busy:r,onBack:i,onRestore:(a,s)=>{if(!(!n||r)){if(n.baseline){jt("Restore fresh install?","This wipes all app storage and reloads the app.","Wipe & reload",()=>void v.restore(n.id,"reload"));return}v.restore(n.id,a,s).then(i)}}})}import{jsx as M,jsxs as Ye}from"react/jsx-runtime";var Io=()=>jn().some(e=>e.id===rr);function dr(){let[e,t]=kr({kind:"list"}),{snapshots:r,busy:i,preview:n}=ut(),a=ki(),s=()=>{v.clearPreview(),t({kind:"list"})};return e.kind==="preview"&&n?M(Ya,{preview:n,snapshots:r,busy:i!==null,onClose:s}):M(Xa,{sources:a,onOpenPreview:h=>{v.buildPreview({snapshotId:h.id}),t({kind:"preview"})}})}function Xa({sources:e,onOpenPreview:t}){let{snapshots:r,hasLoaded:i,busy:n,lastOutcome:a,recentlyDeleted:s,remoteProviders:h}=ut(),m=Bn("timeMachine.snapshots"),y=Mn(),d=En({minBottom:16}),k=Tr(Nn,Io,Io),L=Tr(oo,St,St),b=k?no(r,L)?.id:void 0,H=Hn({}),[W,j]=kr(null),w=$=>{j(null),nr($),y.minimize()},U=y.search.trim().toLowerCase(),ee=U?r.filter($=>$.name.toLowerCase().includes(U)):r,Y=r.filter($=>!$.safety).length>=m,Le=n!==null||Y,te=$=>{if(n)return;if($.baseline){jt("Restore fresh install?","This wipes all app storage and reloads the app.","Wipe & reload",()=>void v.restore($.id,"reload"));return}let ne=(H.current[$.id]??0)+1;H.current[$.id]=ne,ne>=2&&!k&&j($.id),v.restore($.id,"live").then(pe=>{!Object.values(pe.results).every(ke=>ke.ok)||pe.willReload||y.minimize()})},_=W&&!k?r.find($=>$.id===W)??null:null;return Ye(zt,{style:Xe.fill,contentContainerStyle:[Xe.content,{paddingBottom:d.bottom}],testID:"time-machine-scroll",keyboardShouldPersistTaps:"handled",children:[a&&Mr(a)?M(Oi,{outcome:a}):null,s?M(Fi,{name:s.stored.meta.name,at:s.at,onUndo:()=>void v.undoDelete(),onExpire:()=>v.clearRecentlyDeleted()}):null,M(u,{children:M(zi,{disabled:Le,busy:n==="capture",onCapture:$=>void v.capture($)})}),Y?Ye(Me,{tone:"warning",testID:"time-machine-limit",children:["Free plan keeps ",m," restore point",m===1?"":"s",". Upgrade to Pro for unlimited snapshots."]}):null,M(pt,{children:"Sources"}),M(Yi,{sources:e,onToggle:h?void 0:Er}),h?null:M(Me,{testID:"time-machine-sources-hint",children:"Switch a source off to leave it out of every capture and restore."}),M(pt,{children:"Restore Points"}),_?Ye(u,{style:Xe.barHint,testID:"time-machine-bar-hint",children:[Ye(Me,{children:['Restoring "',_.name,'" a lot? Put it on the floating action bar and restore it with one tap.']}),M(P,{onPress:()=>w(_.id),accessibilityRole:"button",testID:"time-machine-bar-hint-pin",hitSlop:{top:6,bottom:6,left:6,right:6},children:M(c,{style:Xe.barHintAction,children:"Open the action bar"})})]}):null,Ye(mt,{children:[ee.map($=>M(Ni,{meta:$,busy:n!==null,armed:$.id===b,onOpen:()=>t($),onRestore:()=>te($),onDelete:()=>void v.delete($.id),onDuplicate:()=>void v.duplicate($.id),onArm:()=>w($.id)},$.id)),ee.length===0?M(Wn,{testID:"time-machine-empty",...i?r.length>0?{otto:"sad",title:"No restore point matches that name.",message:`Clear the search to see all ${r.length}.`}:{otto:"rewind",title:"No restore points yet",message:"Set up the state you want to come back to, then capture it."}:{otto:"loading",title:"Loading restore points\u2026",message:"Reading the vault off disk."}}):null]}),ee.length>0?M(Me,{testID:"time-machine-swipe-hint",children:"Swipe a restore point to copy or delete it."}):null,M(u,{style:Xe.spacer}),M(mt,{children:M(Xi,{disabled:n!==null,onWipe:()=>jt("Wipe all app state?","This deletes all app storage and reloads the app \u2014 like a fresh install.","Wipe & reload",()=>void v.wipeAll())})}),M(Me,{centered:true,children:"Deletes all app storage and reloads \u2014 like a fresh install."})]})}var Xe=O.create({barHint:{marginHorizontal:o.gutter,marginBottom:8},barHintAction:{color:o.color.accent,fontSize:o.font.footnote,fontWeight:"600",paddingHorizontal:o.textInset,paddingTop:2},fill:{flex:1,backgroundColor:"transparent"},content:{paddingTop:14},empty:{color:o.color.labelSecondary,fontSize:o.font.footnote,lineHeight:o.font.footnote*1.4,paddingHorizontal:o.textInset,paddingVertical:16},spacer:{height:24}});import{jsx as Ro}from"react/jsx-runtime";var Dt={id:"time-machine",name:"TIME MACHINE",description:"Snapshot & restore app state (storage, stores, query cache)",slot:"both",icon:({size:e,color:t,slot:r})=>Ro(An,{size:r==="dial"&&nt.OS!=="web"?e*1.5:e,color:t||On}),component:dr,modal:{subtitle:"snapshot & restore app state",searchable:true,searchPlaceholder:"Filter\u2026",headerActions:Ro(go,{})}};function Ga(e={}){return{...Dt,name:e.name??Dt.name,description:e.description??Dt.description}}import{JsModal as Qa}from"@buoy-gg/shared-ui/web";import{jsx as ze,jsxs as Za}from"react/jsx-runtime";function es(){return Za(u,{style:ur.header,children:[ze(c,{style:ur.headerTitle,children:"Time Machine"}),ze(c,{style:ur.headerSubtitle,children:"Snapshot & restore app state"})]})}function ts({visible:e,onClose:t,onBack:r,onMinimize:i,persistenceKey:n}){return ze(Qa,{visible:e,onClose:t,onMinimize:i,persistenceKey:n,header:{showToggleButton:true,customContent:ze(es,{})},enablePersistence:true,initialMode:"bottomSheet",disableScrollWrapper:true,children:ze(dr,{})})}function rs(){return ze(dr,{})}var ur=O.create({header:{paddingHorizontal:4,gap:2},headerTitle:{color:o.color.label,fontSize:22,fontWeight:"700",letterSpacing:.3},headerSubtitle:{color:o.color.labelSecondary,fontSize:o.font.footnote}});import{getStateSnapshotProviders as os,subscribeToStateSnapshotProviders as ns,superJsonDeserialize as is}from"@buoy-gg/shared-ui/web";import{jsonLikelyLargerThan as Do}from"@buoy-gg/shared-ui/web/dataViewer";function as(){return os().map(e=>{let t=e.status();return{id:e.id,label:e.label,canCapture:t.canCapture,canRestore:t.canRestore,detail:t.detail,enabled:se(e.id)}})}function ko(){let{snapshots:e,busy:t,lastOutcome:r}=v.getState(),i=Bo();return{snapshots:e,busy:t,lastOutcome:r,providers:as(),route:{available:He(),enabled:se(We),...i?{current:i.href}:{}}}}var ss={version:2,getSnapshot:()=>ko(),subscribe:e=>{let t=v.subscribe(e),r=ns(e);return()=>{t(),r()}},actions:{list:()=>ko(),capture:async e=>{let{name:t="",sourceIds:r}=e??{};return{captured:true,snapshot:await v.capture(t,r)}},captureBaseline:async()=>({captured:true,snapshot:await v.captureBaseline()}),wipeAll:async()=>await v.wipeAll(),restore:async e=>{let{id:t,mode:r="live",excludeKeys:i,restoreRoute:n}=e??{};if(!t)throw new Error("restore requires a snapshot `id`");return await v.restore(t,r,i,{restoreRoute:n})},delete:async e=>{let{id:t}=e??{};if(!t)throw new Error("delete requires a snapshot `id`");return await v.delete(t),{deleted:true,id:t}},rename:async e=>{let{id:t,name:r}=e??{};if(!t||!r)throw new Error("rename requires `id` and `name`");return await v.rename(t,r),{renamed:true,id:t,name:r}},setExclusions:async e=>{let{id:t,excludedKeys:r}=e??{};if(!t)throw new Error("setExclusions requires `id`");return await v.setExclusions(t,r??null),{id:t,excluded:r?.length??0}},setRestoreRoute:async e=>{let{id:t,restoreRoute:r}=e??{};if(!t)throw new Error("setRestoreRoute requires `id`");return await v.setRestoreRoute(t,r!==false),{id:t,restoreRoute:r!==false}},duplicate:async e=>{let{id:t}=e??{};if(!t)throw new Error("duplicate requires `id`");let r=await v.duplicate(t);if(!r)throw new Error(`No snapshot with id "${t}"`);return{snapshot:r}},setScope:async e=>{let{id:t,scope:r}=e??{};if(!t)throw new Error("setScope requires a snapshot `id`");return await v.setScope(t,r??null),{scoped:true,id:t,count:r?.length??0}},preview:async e=>{let{id:t,compareTo:r}=e??{};if(!t)throw new Error("preview requires a snapshot `id`");let i={snapshotId:t},n=r?{snapshotId:r}:"current";await v.buildPreview(i,n);let a=v.getState().preview;if(!a)throw new Error("preview build produced no result");let s=4*1024;return{left:n,right:i,builtAt:a.builtAt,sources:a.sources.map(h=>({...h,items:h.items.map(m=>{let y=m.oldValue!==void 0&&Do(m.oldValue,s),d=m.newValue!==void 0&&Do(m.newValue,s);return{...m,oldValue:y?void 0:m.oldValue,newValue:d?void 0:m.newValue,...y||d?{valueOmitted:true}:{}}})}))}},inspect:async e=>{let{id:t,sourceId:r}=e??{};if(!t||!r)throw new Error("inspect requires `id` and `sourceId`");let i=await fe(t);if(!i)throw new Error(`No snapshot with id "${t}"`);let n=i.data[r];if(!n)throw new Error(`Snapshot "${t}" has no "${r}" source`);return{id:t,sourceId:r,warnings:i.meta.sources[r]?.warnings??[],data:is(n)}}}};yr();export{je as RESTORE_ORDER,Bt as SAFETY_SNAPSHOT_NAME,rr as TIME_MACHINE_FLOATING_TOOL_ID,ts as TimeMachineModal,rs as TimeMachineToolView,yr as armPendingRouteRestore,He as canRestoreRoute,ot as captureCurrentRoute,Ga as createTimeMachineTool,se as isSourceEnabled,Ct as navigateToRoute,nr as openTimeMachineFloatingTool,ci as replaceTimeMachineFromSnapshot,li as setRemoteTimeMachineHandler,Er as setSourceEnabled,Or as subscribeSourceSettings,v as timeMachineStore,ss as timeMachineSyncAdapter,Dt as timeMachineToolPreset};
|
|
3
|
+
${t}`)&&i();return}Dr.alert(e,t,[{text:"Cancel",style:"cancel"},{text:r,style:"destructive",onPress:i}])}import{useState as zi}from"react";import{jsx as jt,jsxs as Li}from"react/jsx-runtime";function Pi({disabled:e,busy:t,onCapture:r}){let[i,n]=zi(""),a=()=>{e||(r(i),n(""))};return Li(u,{style:Ve.bar,children:[jt(it,{style:Ve.input,value:i,onChangeText:n,placeholder:"Name this restore point\u2026",placeholderTextColor:o.color.labelTertiary,editable:!e,onSubmitEditing:a,returnKeyType:"done",testID:"time-machine-name-input"}),jt(P,{style:[Ve.button,e?Ve.buttonDisabled:null],onPress:a,disabled:e,accessibilityRole:"button",accessibilityLabel:"Capture restore point",testID:"time-machine-capture",children:jt(c,{style:Ve.buttonText,children:t?"Capturing\u2026":"Capture"})})]})}var Ve=O.create({bar:{flexDirection:"row",alignItems:"center",gap:8,marginHorizontal:o.gutter,backgroundColor:o.color.group,borderRadius:o.radius.group,borderWidth:1,borderColor:o.color.groupBorder,paddingLeft:o.textInset,padding:6},input:{flex:1,minWidth:0,color:o.color.label,fontSize:o.font.row,letterSpacing:o.tracking.row,padding:0,backgroundColor:"transparent"},button:{height:34,paddingHorizontal:16,borderRadius:o.radius.pill,backgroundColor:o.color.accent,alignItems:"center",justifyContent:"center"},buttonDisabled:{opacity:.4},buttonText:{color:o.color.onAccent,fontSize:o.font.control,fontWeight:"600",letterSpacing:o.tracking.control}});import{X as Ai}from"@buoy-gg/shared-ui/web";import{jsx as be,jsxs as ye}from"react/jsx-runtime";var Oi={top:10,bottom:10,left:10,right:10};function Mr(e){if(Object.values(e.results).some(r=>!r.ok||r.skipped.length>0))return true;let t=e.route;return t?.status==="failed"||t?.status==="unavailable"}function ft({glyph:e,text:t,ok:r,testID:i}){return ye(c,{style:[we.line,{color:r?o.color.accent:o.color.warning}],numberOfLines:2,testID:i,children:[ye(c,{style:we.glyph,children:[e," "]}),t]})}var Mt="time-machine-outcome-route";function Hi({route:e}){return e.status==="navigated"?be(ft,{glyph:"\u2713",ok:true,text:`route \u2014 ${e.href}`,testID:Mt}):e.status==="deferred"?be(ft,{glyph:"\u21BB",ok:true,text:`route \u2014 ${e.href} after reload`,testID:Mt}):be(ft,{glyph:"\u2715",ok:false,text:`route \u2014 ${e.error??e.status}`,testID:Mt})}function Ei({outcome:e}){let t=Object.entries(e.results),r=e.mode==="reload"||e.willReload;return ye(u,{style:we.card,testID:"time-machine-outcome",children:[ye(u,{style:we.headerRow,children:[ye(c,{style:we.title,numberOfLines:1,testID:"time-machine-outcome-title",children:["Restored \u201C",e.snapshotName,"\u201D",r?" \xB7 reloading":""]}),be(P,{onPress:()=>v.clearLastOutcome(),hitSlop:Oi,accessibilityRole:"button",accessibilityLabel:"Dismiss restore result",testID:"time-machine-outcome-dismiss",children:be(Ai,{size:13,color:o.color.labelSecondary})})]}),t.length===0&&!e.route?be(c,{style:we.empty,testID:"time-machine-outcome-empty",children:"No sources restored."}):null,e.route?be(Hi,{route:e.route}):null,t.map(([i,n])=>ye(u,{children:[be(ft,{testID:`time-machine-outcome-${i}`,glyph:n.ok?"\u2713":"\u2715",ok:n.ok,text:`${i} \u2014 applied ${n.applied}${n.skipped.length>0?`, skipped ${n.skipped.length}`:""}`}),n.skipped.slice(0,3).map(a=>ye(c,{style:we.detail,numberOfLines:2,children:[a.id,": ",a.reason]},a.id)),n.warnings.slice(0,3).map(a=>ye(c,{style:we.detail,numberOfLines:2,children:["\u26A0 ",a]},a))]},i))]})}var we=O.create({card:{marginHorizontal:o.gutter,marginTop:12,backgroundColor:o.color.group,borderRadius:o.radius.group,borderWidth:1,borderColor:o.color.groupBorder,padding:14,gap:4},headerRow:{flexDirection:"row",alignItems:"center",gap:10,marginBottom:2},title:{flex:1,color:o.color.label,fontSize:15,fontWeight:"600",letterSpacing:o.tracking.control},line:{fontSize:o.font.footnote,lineHeight:o.font.footnote*1.4},glyph:{fontWeight:"700"},detail:{color:o.color.labelTertiary,fontSize:o.font.mono,lineHeight:o.font.mono*1.4,paddingLeft:14},empty:{color:o.color.labelSecondary,fontSize:o.font.footnote}});import{useEffect as Bi,useRef as Vr}from"react";import{jsx as gt,jsxs as Wi}from"react/jsx-runtime";var Fr=84,_r=8,Se=null;function Ni(e,t){let r=false,i=a=>{r=a,a?(Se&&Se!==n&&Se(),Se=n):Se===n&&(Se=null),Ee.spring(e,{toValue:a?-t:0,useNativeDriver:true,bounciness:0,speed:18}).start()},n=()=>i(false);return{pan:Sr.create({onMoveShouldSetPanResponder:(a,s)=>Math.abs(s.dx)>Math.abs(s.dy)*1.5?s.dx<-_r||r&&s.dx>_r:false,onPanResponderMove:(a,s)=>{let h=r?-t:0;e.setValue(Math.min(0,Math.max(-t,h+s.dx)))},onPanResponderRelease:(a,s)=>{let h=(r?-t:0)+s.dx;i(s.vx<-.5?true:s.vx>.5?false:h<-t/2)},onPanResponderTerminate:()=>i(r)}),close:n}}function ji({children:e,actions:t,testID:r}){let i=Fr*t.length,n=Vr(new Ee.Value(0)).current,a=Vr(null);a.current===null&&(a.current=Ni(n,i));let{pan:s,close:h}=a.current;Bi(()=>()=>{Se===h&&(Se=null)},[h]);let m=n.interpolate({inputRange:[-24,0],outputRange:[1,0],extrapolate:"clamp"});return Wi(u,{style:Fe.clip,children:[gt(Ee.View,{style:[Fe.actionLayer,{width:i,opacity:m}],children:t.map(y=>gt(P,{style:[Fe.action,y.background?{backgroundColor:y.background}:null],onPress:()=>{h(),y.onPress()},accessibilityLabel:y.label,testID:y.testID??(r?`${r}-${y.label.toLowerCase()}`:void 0),children:gt(c,{style:[Fe.actionText,y.color?{color:y.color}:null],numberOfLines:1,children:y.label})},y.label))}),gt(Ee.View,{style:[Fe.content,{transform:[{translateX:n}]}],...s.panHandlers,children:e})]})}var Fe=O.create({clip:{overflow:"hidden"},actionLayer:{position:"absolute",top:0,bottom:0,right:0,flexDirection:"row"},action:{width:Fr,height:"100%",backgroundColor:o.color.fillStrong,alignItems:"center",justifyContent:"center",paddingHorizontal:6},actionText:{color:o.color.label,fontSize:o.font.footnote,fontWeight:"600",letterSpacing:o.tracking.control},content:{backgroundColor:o.color.group}});function _e(e){let t=Math.max(0,Math.round((Date.now()-e)/1e3));if(t<60)return`${t}s ago`;let r=Math.round(t/60);if(r<60)return`${r}m ago`;let i=Math.round(r/60);return i<24?`${i}h ago`:`${Math.round(i/24)}d ago`}function Mi(e){return e<1024?`${e} B`:e<1024*1024?`${(e/1024).toFixed(1)} KB`:`${(e/(1024*1024)).toFixed(1)} MB`}import{jsx as Re,jsxs as Vt}from"react/jsx-runtime";function Kr(e){if(e.baseline)return"Wipes to fresh install";let t=[_e(e.createdAt),Mi(e.sizeBytes),`${Object.keys(e.sources).length} sources`];return e.excludedKeys?.length?t.push(`skips ${e.excludedKeys.length}`):e.scope?.length&&t.push(`scoped (${e.scope.length})`),e.safety&&t.unshift("safety copy"),t.join(" \xB7 ")}function Vi({meta:e,busy:t,armed:r=false,onOpen:i,onRestore:n,onDelete:a,onDuplicate:s,onArm:h}){let m=`time-machine-snap-${e.id}`;return Re(ji,{testID:m,actions:[{label:"Bar",onPress:h},{label:"Dup",onPress:s},{label:"Delete",onPress:a,background:o.color.danger,color:o.color.onDanger}],children:Vt(u,{style:de.row,children:[Vt(P,{style:de.text,onPress:i,activeOpacity:.7,accessibilityRole:"button",accessibilityLabel:`${e.name}. ${Kr(e)}. Open restore preview`,testID:m,children:[Re(c,{style:de.name,numberOfLines:1,testID:`${m}-name`,children:e.name}),r?Re(c,{style:de.armed,numberOfLines:1,testID:`${m}-armed`,children:"On the action bar"}):null,Re(c,{style:de.meta,numberOfLines:1,testID:`${m}-meta`,children:Kr(e)}),e.lastRestoredAt?Vt(c,{style:de.restored,numberOfLines:1,testID:`${m}-restored`,children:["Restored ",_e(e.lastRestoredAt)]}):null,e.route?Re(c,{style:de.route,numberOfLines:1,testID:`${m}-route`,children:e.route.href}):null]}),Re(P,{onPress:n,disabled:t,style:[de.restore,t?de.actionDisabled:null],accessibilityRole:"button",accessibilityLabel:e.baseline?"Wipe and reload":"Restore",testID:`${m}-restore`,children:Re(bi,{testID:`${m}-restore-label`,label:e.baseline?"Wipe":"Restore",color:e.baseline?o.color.danger:o.color.accent,background:e.baseline?o.color.dangerSoft:o.color.accentSoft})})]})})}var de=O.create({row:{flexDirection:"row",alignItems:"center",gap:10,paddingHorizontal:o.textInset},text:{flex:1,minWidth:0,paddingVertical:11},restore:{justifyContent:"center"},name:{color:o.color.label,fontSize:o.font.row,fontWeight:"600",letterSpacing:o.tracking.row},meta:{color:o.color.labelSecondary,fontSize:o.font.footnote,marginTop:2,fontVariant:["tabular-nums"]},restored:{color:o.color.accent,fontSize:o.font.footnote,marginTop:2},armed:{color:o.color.accent,fontSize:o.font.footnote,marginTop:2},route:{color:o.color.labelTertiary,fontFamily:ht,fontSize:o.font.mono,marginTop:4},actionDisabled:{opacity:.4}});import{useEffect as Fi}from"react";import{jsx as qr,jsxs as Jr}from"react/jsx-runtime";var _i=8e3;function Ki({name:e,at:t,onUndo:r,onExpire:i}){return Fi(()=>{let n=setTimeout(i,_i);return()=>clearTimeout(n)},[t]),Jr(u,{style:Ft.bar,testID:"time-machine-undo-bar",children:[Jr(c,{style:Ft.text,numberOfLines:1,testID:"time-machine-undo-text",children:["Deleted \u201C",e,"\u201D"]}),qr(P,{onPress:r,hitSlop:{top:10,bottom:10,left:10,right:10},accessibilityRole:"button",testID:"time-machine-undo-delete",children:qr(c,{style:Ft.undo,children:"Undo"})})]})}var Ft=O.create({bar:{flexDirection:"row",alignItems:"center",gap:12,marginHorizontal:o.gutter,marginTop:12,minHeight:46,paddingHorizontal:o.textInset,backgroundColor:o.color.group,borderRadius:o.radius.group,borderWidth:1,borderColor:o.color.groupBorder},text:{flex:1,color:o.color.labelSecondary,fontSize:o.font.control,letterSpacing:o.tracking.control},undo:{color:o.color.accent,fontSize:o.font.control,fontWeight:"600",letterSpacing:o.tracking.control}});import{NightSwitch as qi}from"@buoy-gg/shared-ui/web";import{jsx as le,jsxs as _t}from"react/jsx-runtime";var Ji={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 Ui(e){return Ji[e.id]??"App data"}function Yi(e){return e.enabled?e.canRestore?null:{text:"Can be saved but not put back",tone:"warn"}:{text:"Off \xB7 left as it is",tone:"off"}}function Gi({source:e,onToggle:t}){let r=Ti(e.id),i=Ui(e),n=Yi(e);return _t(u,{style:ue.row,testID:`time-machine-source-${e.id}`,accessibilityLabel:`${e.label}: ${i}${n?`. ${n.text}`:""}`,children:[le(u,{style:ue.disc,children:le(r,{size:22,bgColor:o.color.disc})}),_t(u,{style:ue.text,children:[le(c,{style:ue.label,numberOfLines:1,testID:`time-machine-source-${e.id}-label`,children:e.label}),le(c,{style:ue.description,numberOfLines:2,testID:`time-machine-source-${e.id}-description`,children:i}),n?le(c,{style:[ue.state,ue[`state_${n.tone}`]],numberOfLines:1,testID:n.tone==="off"?`time-machine-source-${e.id}-off`:`time-machine-source-${e.id}-detail`,children:n.text}):null]}),le(u,{testID:`time-machine-source-${e.id}-switch`,children:le(qi,{value:e.enabled,disabled:!t,onValueChange:a=>t?.(e.id,a)})})]})}function Xi({sources:e,onToggle:t}){let r=e.filter(i=>i.canCapture);return _t(mt,{children:[r.map(i=>le(Gi,{source:i,onToggle:t},i.id)),r.length===0?le(u,{style:ue.row,testID:"time-machine-sources-empty",children:le(c,{style:ue.description,children:"No state tools are set up in this app."})}):null]})}var ue=O.create({row:{flexDirection:"row",alignItems:"center",gap:12,minHeight:o.rowMinHeight,paddingHorizontal:o.textInset,paddingVertical:10},disc:{width:36,height:36,borderRadius:o.radius.pill,backgroundColor:o.color.disc,alignItems:"center",justifyContent:"center"},text:{flex:1,minWidth:0,gap:2},label:{color:o.color.label,fontSize:o.font.row,fontWeight:"500",letterSpacing:o.tracking.row},description:{fontSize:o.font.footnote,lineHeight:o.font.footnote*1.3,color:o.color.labelSecondary},state:{fontSize:o.font.mono,lineHeight:o.font.mono*1.3,fontWeight:"600",marginTop:1},state_off:{color:o.color.labelTertiary},state_warn:{color:o.color.warning}});import{jsx as Ur}from"react/jsx-runtime";function Qi({disabled:e,onWipe:t}){return Ur(P,{style:[Kt.row,e?Kt.disabled:null],onPress:t,disabled:e,accessibilityRole:"button",testID:"time-machine-wipe-all",children:Ur(c,{style:Kt.label,children:"Wipe All App State\u2026"})})}var Kt=O.create({row:{minHeight:o.rowMinHeight,alignItems:"center",justifyContent:"center"},disabled:{opacity:.4},label:{color:o.color.danger,fontSize:o.font.row,letterSpacing:o.tracking.row}});import{memo as Zi,useCallback as De,useEffect as Yr,useMemo as bt,useRef as qt,useState as Jt}from"react";import{ChevronUp as Gr,AlertTriangle as ea,RefreshCw as ta,useSafeAreaInsets as ra}from"@buoy-gg/shared-ui/web";import{useToolHeader as oa,useToolHost as na}from"@buoy-gg/core/web";import{night as yt}from"@buoy-gg/shared-ui/web";import{useToolHost as ia}from"@buoy-gg/core/web";import{night as Ut,scheduleReloadApp as aa}from"@buoy-gg/shared-ui/web";import{jsx as Xr}from"react/jsx-runtime";function sa(){let e=()=>{try{aa({reason:"buoy time-machine reload app"})}catch{}};return Xr(P,{style:Qr.chip,onPress:e,accessibilityLabel:"Reload app",accessibilityHint:"Reloads the JavaScript bundle without restoring anything",accessibilityRole:"button",testID:"time-machine-reload-app",children:Xr(c,{style:Qr.label,children:"Reload app"})})}var Qr=O.create({chip:{height:32,paddingHorizontal:10,borderRadius:8,borderWidth:1,borderColor:Ut.color.border,backgroundColor:Ut.color.buttonSurface,alignItems:"center",justifyContent:"center"},label:{fontSize:11,fontWeight:"700",color:Ut.color.textSecondary}});import{useEffect as wt,useRef as la,useState as ve,useSyncExternalStore as Zr}from"react";import{Check as eo,ChevronDown as ca,ChevronUp as da,FloatingTool as ua,NightSwitch as ha,Plus as pa,TimeMachineIcon as ma,X as fa,night as T,openFloatingTool as ga,persistentStorage as ba,registerPersistentFloatingTool as ya,useLimit as wa}from"@buoy-gg/shared-ui/web";import{devToolsStorageKeys as Sa,persistentStorage as Yt}from"@buoy-gg/shared-ui/web";var Gt=Sa.timeMachine.armedPoint(),Ke=null,to=false,Xt=null,Qt=new Set,ro=()=>Qt.forEach(e=>e());function St(){return Ke}function oo(e){return Qt.add(e),()=>{Qt.delete(e)}}function va(){return to?Promise.resolve():(Xt||(Xt=Yt.getItem(Gt).then(e=>{Ke===null&&e&&(Ke=e,ro())}).catch(()=>{}).finally(()=>{to=true})),Xt)}function Zt(e){Ke!==e&&(Ke=e,ro(),(e===null?Yt.removeItem(Gt):Yt.setItem(Gt,e)).catch(()=>{}))}function no(e,t){let r=e.filter(n=>!n.baseline&&!n.safety);if(r.length===0)return null;if(t){let n=r.find(a=>a.id===t);if(n)return n}let i=null;for(let n of r)n.lastRestoredAt!==void 0&&(!i||n.lastRestoredAt>(i.lastRestoredAt??0))&&(i=n);return i||r.reduce((n,a)=>a.createdAt>n.createdAt?a:n)}import{useEffect as xa,useState as Ia}from"react";import{night as E}from"@buoy-gg/shared-ui/web";import{jsx as oe,jsxs as io}from"react/jsx-runtime";function Ra({visible:e,summary:t,onCapture:r,onCancel:i}){let[n,a]=Ia("");xa(()=>{e&&a("")},[e]);let s=()=>r(n.trim());return oe(Rr,{visible:e,transparent:true,animationType:"fade",onRequestClose:i,statusBarTranslucent:true,children:oe(xr,{behavior:nt.OS==="ios"?"padding":void 0,style:Z.fill,children:oe($t,{style:Z.backdrop,onPress:i,accessibilityLabel:"Cancel",testID:"time-machine-bar-name-backdrop",children:io($t,{style:Z.card,onPress:h=>h.stopPropagation(),testID:"time-machine-bar-name-panel",accessible:false,children:[oe(c,{style:Z.title,children:"Name this restore point"}),t?oe(c,{style:Z.summary,testID:"time-machine-bar-name-summary",children:t}):null,oe(it,{testID:"time-machine-bar-name-input",accessibilityLabel:"Restore point name",value:n,onChangeText:a,onSubmitEditing:s,placeholder:"Screen and time, if left empty",placeholderTextColor:E.color.placeholder,autoFocus:true,autoCorrect:false,autoCapitalize:"none",returnKeyType:"done",style:Z.input}),oe(c,{style:Z.hint,children:"Captures the state the app is in right now and arms it on the bar."}),io(u,{style:Z.actions,children:[oe(P,{testID:"time-machine-bar-name-cancel",accessibilityRole:"button",onPress:i,style:Z.secondary,children:oe(c,{style:Z.secondaryText,children:"Cancel"})}),oe(P,{testID:"time-machine-bar-name-capture",accessibilityRole:"button",accessibilityLabel:"Capture and arm this restore point",onPress:s,style:Z.primary,children:oe(c,{style:Z.primaryText,children:"Capture"})})]})]})})})})}var Z=O.create({fill:{flex:1},backdrop:{flex:1,backgroundColor:"rgba(0, 0, 0, 0.55)",alignItems:"center",justifyContent:"center",padding:24},card:{width:"100%",maxWidth:360,borderRadius:E.radius.sheet,borderWidth:1,borderColor:E.color.separator,backgroundColor:E.color.surface,padding:18,gap:12,shadowColor:"#000",shadowOffset:{width:0,height:12},shadowOpacity:.4,shadowRadius:24,elevation:12},title:{color:E.color.text,fontSize:E.font.title,fontWeight:"600"},input:{minHeight:44,borderRadius:E.radius.input,borderWidth:1,borderColor:E.color.accentBorder,backgroundColor:E.color.surfaceElevated,color:E.color.text,fontSize:E.font.row,paddingHorizontal:12},summary:{color:E.color.textTertiary,fontSize:E.font.caption,marginTop:-6},hint:{color:E.color.textSecondary,fontSize:E.font.caption,lineHeight:18},actions:{flexDirection:"row",justifyContent:"flex-end",gap:10,marginTop:4},secondary:{minHeight:40,paddingHorizontal:14,borderRadius:E.radius.input,alignItems:"center",justifyContent:"center"},secondaryText:{color:E.color.textSecondary,fontSize:14,fontWeight:"600"},primary:{minHeight:40,paddingHorizontal:18,borderRadius:E.radius.input,backgroundColor:E.color.accent,alignItems:"center",justifyContent:"center"},primaryText:{color:E.color.onAccent,fontSize:14,fontWeight:"700"}});import{devToolsStorageKeys as Da,persistentStorage as ao}from"@buoy-gg/shared-ui/web";var so=Da.timeMachine.barReloadMode(),qe=false,lo=false,er=null,tr=new Set,co=()=>tr.forEach(e=>e());function uo(){return qe}function ka(e){return tr.add(e),()=>{tr.delete(e)}}function Ta(){return lo?Promise.resolve():(er||(er=ao.getItem(so).then(e=>{!qe&&e==="1"&&(qe=true,co())}).catch(()=>{}).finally(()=>{lo=true})),er)}function Ca(e){e!==qe&&(qe=e,co(),ao.setItem(so,e?"1":"0").catch(()=>{}))}import{Fragment as $a,jsx as R,jsxs as F}from"react/jsx-runtime";var rr="time-machine-restore",vt=1e4,ho=900,or=6,po={id:rr,render:e=>R(Pa,{...e})},mo=false;function fo(){mo||(mo=true,ya(po,ba))}typeof fr<"u"&&fr&&typeof navigator<"u"&&navigator.product==="ReactNative"&&fo();function nr(e){e&&Zt(e),ga(po)}function za(e){let t=Object.values(e.results),r=t.filter(s=>!s.ok||s.skipped.length>0).length,i=t.length,n=e.route,a=n?.status==="failed"||n?.status==="unavailable";return r===0&&a?"Route did not restore":`${r} of ${i} source${i===1?"":"s"} failed`}function La(e){let t=[];for(let[i,n]of Object.entries(e.results)){if(n.ok&&n.skipped.length===0)continue;let a=n.skipped[0]?.reason??n.warnings[0]??"did not apply";t.push(`${i}: ${a}`)}let r=e.route;return(r?.status==="failed"||r?.status==="unavailable")&&t.push(`route: ${r.status}`),t}function go(e){let[t,r]=ve(0);return wt(()=>{if(!t)return;let i=setTimeout(()=>r(0),e);return()=>clearTimeout(i)},[t,e]),[t>0,()=>r(i=>i+1)]}function Pa({id:e,revealToken:t,dismiss:r}){let{snapshots:i,hasLoaded:n,busy:a}=ut(),s=Nr(),h=Zr(oo,St,St),m=wa("timeMachine.snapshots"),y=Zr(ka,uo,uo),{width:d}=Ir(),[k,L]=ve(null),[b,H]=ve(null),[W,N]=ve(),[w,U]=ve(false),[ee,Y]=go(ho),[Le,te]=go(ho),[_,$]=ve(null),[ne,pe]=ve(null),[,ke]=ve(0),ie=la(true);wt(()=>(ie.current=true,va(),Ta(),v.ensureLoaded(),()=>{ie.current=false}),[]);let D=no(i,h),Xe=D?.id,Pe=D?.lastRestoredAt,Qe=D?.createdAt;wt(()=>{if(Pe===void 0&&Qe===void 0&&!_&&ne===null)return;let f=setInterval(()=>ke(V=>V+1),2500);return()=>clearInterval(f)},[Pe,Qe,_,ne]),wt(()=>{b&&b.snapshotId!==Xe&&(H(null),L(f=>f==="outcome"?null:f))},[Xe,b]);let Te=Date.now(),Ze=_!==null&&Te-_.at<vt&&i.some(f=>f.id===_.id),Ae=i.filter(f=>!f.safety).length>=m,l=!D||a!==null,S=a!==null,C=async(f,V)=>{if(!a){L(null),N(void 0);try{let X=await v.restore(f,y&&V.safetyCapture?"reload":"live",void 0,V);if(!ie.current)return;Mr(X)?(H(X),L("outcome")):(H(null),Y()),$(X.safetySnapshotId?{id:X.safetySnapshotId,at:Date.now()}:null),X.safetySnapshotId&&pe(null)}catch(X){if(!ie.current)return;N(X instanceof Error?X.message:String(X)),L("error")}}},I=(f=false)=>{D&&C(D.id,{safetyCapture:true,...f?{restoreRoute:false}:{}})},K=()=>{_&&C(_.id,{safetyCapture:false,restoreRoute:false}).then(()=>{ie.current&&pe(Date.now())})},re=()=>{if(!a){if(N(void 0),Ae){L("cap");return}L(null),U(true)}},G=async f=>{if(U(false),!a)try{let V=await v.capture(f);if(!ie.current)return;Zt(V.id),$(null),te()}catch(V){if(!ie.current)return;N(V instanceof Error?V.message:String(V)),L("error")}},Oe=f=>{Zt(f.id),L(null)},et=D?.name??(n?"No restore points":"Loading\u2026"),q,Ce="normal",tt=false;if(a==="restore")q="Restoring\u2026";else if(a==="capture")q="Capturing\u2026";else if(W)q=W,Ce="danger";else if(b&&D&&b.snapshotId===D.id)q=za(b),Ce="danger";else if(!D)q=n?"Capture one with +":"";else{tt=true;let f=D.lastRestoredAt===void 0?null:Te-D.lastRestoredAt,V=Te-D.createdAt;ne!==null&&Te-ne<vt?q="undone, state only":f!==null&&f<vt?q="restored just now":V<vt&&f===null?q="captured just now":D.lastRestoredAt!==void 0?q=`restored ${_e(D.lastRestoredAt)}`:q=`${Object.keys(D.sources).length} sources`,y&&(q+=" \xB7 reloads")}let ce=tt&&!Ze&&D&&D.route&&dt(D)?D.route.pathname:null,$e=i.filter(f=>!f.baseline&&!f.safety),rt=(()=>{let f=s.filter(hr=>hr.status().canCapture&&se(hr.id)).length,V=ot(),X=[`${f} source${f===1?"":"s"}`];return V&&X.push(V.pathname),X.join(" \xB7 ")})(),z;return k==="picker"?z=F(u,{style:x.menu,testID:"time-machine-bar-picker",children:[F(zt,{style:x.pickerList,bounces:false,children:[$e.map(f=>{let V=f.id===D?.id;return F(P,{testID:`time-machine-bar-pick-${f.id}`,accessibilityRole:"button",accessibilityState:{selected:V},accessibilityLabel:`Arm ${f.name}`,onPress:()=>Oe(f),style:x.pickRow,children:[F(u,{style:x.pickText,children:[R(c,{numberOfLines:1,style:x.pickName,children:f.name}),F(c,{numberOfLines:1,style:x.pickDetail,children:[_e(f.createdAt),f.route?` \xB7 ${f.route.pathname}`:"",f.lastRestoredAt!==void 0?R(c,{style:x.pickRestored,children:` \xB7 restored ${_e(f.lastRestoredAt)}`}):null]})]}),V?R(eo,{size:14,color:T.color.accent}):null]},f.id)}),$e.length===0?R(c,{style:x.menuText,children:"No restore points yet."}):null]}),$e.length>or?F(c,{style:x.pickerMore,children:["Scroll for ",$e.length-or," more"]}):null,F(u,{style:x.settingRow,testID:"time-machine-bar-reload-mode",children:[F(u,{style:x.settingText,children:[R(c,{style:x.settingLabel,children:"Reload the app after restoring"}),R(c,{style:x.settingHint,children:"For screens that read their state from storage only when they open, like a cart kept in a React context."})]}),R(ha,{value:y,onValueChange:Ca})]})]}):k==="outcome"&&b?z=F(u,{style:x.menu,testID:"time-machine-bar-outcome",children:[La(b).map(f=>R(c,{style:x.menuDanger,children:f},f)),R(c,{style:x.menuText,children:"The full report is on Time Machine's outcome card."}),R(ir,{onPress:()=>L(null)})]}):k==="cap"?z=F(u,{style:x.menu,testID:"time-machine-bar-cap",children:[F(c,{style:x.menuText,children:["Free plan keeps ",m," restore point",m===1?"":"s",". Delete one in Time Machine, or upgrade to Pro for unlimited snapshots."]}),R(ir,{onPress:()=>L(null)})]}):k==="error"&&W&&(z=F(u,{style:x.menu,testID:"time-machine-bar-error",children:[R(c,{accessibilityRole:"alert",style:x.menuDanger,children:W}),R(ir,{onPress:()=>{L(null),N(void 0)}})]})),F($a,{children:[R(Ra,{visible:w,summary:rt,onCapture:f=>void G(f),onCancel:()=>U(false)}),R(ua,{id:e,revealToken:t,variant:"strip",dragFromSurface:true,defaultPlacement:"bottom",accessibilityLabel:`Move or hide the action bar. ${D?`${D.name} armed`:"Nothing armed"}`,accessory:z,handleAdornment:R(ma,{size:12,color:T.color.accent}),children:F(u,{style:[x.row,{width:Math.max(260,Math.min(320,d-64))}],children:[R(P,{testID:"time-machine-bar-restore",accessibilityRole:"button",accessibilityLabel:D?`Restore ${D.name}`:"Restore, nothing armed",accessibilityHint:ce?`Also returns to ${ce}. Long press to restore state only.`:void 0,accessibilityState:{disabled:l},disabled:l,onPress:()=>I(false),onLongPress:()=>I(true),style:[x.restoreButton,l&&x.disabled],children:a==="restore"?R(at,{size:"small",color:T.color.accent}):ee?R(c,{style:x.restoreText,testID:"time-machine-bar-restored",children:"Restored"}):R(c,{style:x.restoreText,children:"Restore"})}),F(u,{style:x.identity,children:[R(c,{testID:"time-machine-bar-name",accessibilityLabel:`Armed restore point: ${et}`,numberOfLines:1,ellipsizeMode:"middle",style:x.name,children:et}),F(u,{style:x.statusRow,children:[F(c,{testID:"time-machine-bar-status",numberOfLines:1,accessibilityLiveRegion:"polite",style:[x.status,Ce==="danger"&&x.danger],children:[q,ce?R(c,{style:x.destination,children:` \xB7 \u2192 ${ce}`}):null]}),Ze&&!a?R(P,{testID:"time-machine-bar-undo",accessibilityRole:"button",accessibilityLabel:"Undo the last restore",onPress:K,hitSlop:{top:8,bottom:8,left:6,right:6},children:R(c,{style:x.undo,children:"Undo"})}):null]})]}),R(P,{testID:"time-machine-bar-pick",accessibilityRole:"button",accessibilityLabel:"Choose another restore point",accessibilityState:{expanded:k==="picker"},onPress:()=>L(f=>f==="picker"?null:"picker"),style:x.smallButton,children:k==="picker"?R(da,{size:14,color:T.color.textSecondary}):R(ca,{size:14,color:T.color.textSecondary})}),R(P,{testID:"time-machine-bar-capture",accessibilityRole:"button",accessibilityLabel:"Capture a new restore point here and arm it",accessibilityState:{disabled:S},disabled:S,onPress:re,style:[x.smallButton,S&&x.disabled],children:a==="capture"?R(at,{size:"small",color:T.color.accent}):Le?R(u,{testID:"time-machine-bar-captured",children:R(eo,{size:18,color:T.color.accent})}):R(pa,{size:18,color:Ae?T.color.textTertiary:T.color.text})}),R(u,{style:x.separator}),R(P,{testID:"time-machine-bar-close",accessibilityRole:"button",accessibilityLabel:"Close the action bar",onPress:r,style:x.closeButton,children:R(fa,{size:16,color:T.color.textSecondary})})]})})]})}function ir({onPress:e,label:t="Dismiss"}){return R(P,{testID:"time-machine-bar-dismiss",accessibilityRole:"button",onPress:e,style:x.dismiss,children:R(c,{style:x.dismissText,children:t})})}var x=O.create({row:{flexDirection:"row",alignItems:"center",gap:4,paddingVertical:4,minHeight:48},restoreButton:{height:32,minWidth:72,paddingHorizontal:12,borderRadius:8,borderWidth:1,borderColor:T.color.accentBorderStrong,backgroundColor:T.color.accentSoft,alignItems:"center",justifyContent:"center",marginLeft:2},restoreText:{color:T.color.accent,fontSize:12,fontWeight:"700"},smallButton:{width:32,minHeight:44,alignItems:"center",justifyContent:"center"},closeButton:{width:28,minHeight:44,alignItems:"center",justifyContent:"center"},identity:{flex:1,minHeight:44,justifyContent:"center",gap:1},name:{color:T.color.text,fontSize:13,fontWeight:"500"},statusRow:{flexDirection:"row",alignItems:"center",gap:8},status:{color:T.color.textSecondary,fontSize:10,lineHeight:14,flexShrink:1},destination:{color:T.color.textTertiary},danger:{color:T.color.danger},undo:{color:T.color.accent,fontSize:10,lineHeight:14,fontWeight:"700"},separator:{height:20,width:1,backgroundColor:T.color.separator,marginHorizontal:2},disabled:{opacity:.4},menu:{marginVertical:8,padding:6,borderRadius:T.radius.card,borderWidth:1,borderColor:T.color.separator,backgroundColor:T.color.surface,shadowColor:"#000",shadowOffset:{width:0,height:6},shadowOpacity:.25,shadowRadius:16,elevation:8},menuText:{color:T.color.textSecondary,fontSize:12,lineHeight:18,padding:10},menuDanger:{color:T.color.danger,fontSize:12,lineHeight:18,paddingHorizontal:10,paddingTop:6},pickerList:{maxHeight:or*44},pickerMore:{color:T.color.textTertiary,fontSize:10,lineHeight:14,textAlign:"center",paddingVertical:4},pickRow:{flexDirection:"row",alignItems:"center",gap:8,minHeight:44,paddingHorizontal:10,borderRadius:T.radius.row},pickText:{flex:1},settingRow:{flexDirection:"row",alignItems:"center",gap:10,paddingHorizontal:10,paddingVertical:8,borderTopWidth:O.hairlineWidth,borderTopColor:T.color.separator,marginTop:4},settingText:{flex:1,gap:2},settingLabel:{color:T.color.text,fontSize:12,fontWeight:"500"},settingHint:{color:T.color.textTertiary,fontSize:10,lineHeight:13},pickName:{color:T.color.text,fontSize:13,fontWeight:"500"},pickDetail:{color:T.color.textSecondary,fontSize:10,lineHeight:14},pickRestored:{color:T.color.accent},dismiss:{alignSelf:"flex-end",paddingHorizontal:10,paddingVertical:8},dismissText:{color:T.color.accent,fontSize:12,fontWeight:"600"}});import{jsx as xt,jsxs as bo}from"react/jsx-runtime";function Aa({armId:e}){let t=ia(),r=()=>{nr(e),t.minimize()};return bo(P,{style:It.labeledChip,onPress:r,accessibilityLabel:"Open the floating action bar over the app",accessibilityRole:"button",testID:"time-machine-header-bar",children:[xt(u,{style:It.glyph}),xt(c,{style:It.label,children:"Action bar"})]})}function yo({armId:e}){return bo(u,{style:It.row,children:[xt(Aa,{armId:e}),xt(sa,{})]})}var It=O.create({row:{flexDirection:"row",alignItems:"center",gap:8},labeledChip:{height:32,flexDirection:"row",alignItems:"center",gap:6,paddingHorizontal:10,borderRadius:8,borderWidth:1,borderColor:yt.color.border,backgroundColor:yt.color.buttonSurface},glyph:{width:14,height:8,borderRadius:3,borderWidth:1.5,borderColor:yt.color.accent},label:{fontSize:11,fontWeight:"700",color:yt.color.accent}});import{useMemo as Oa}from"react";import{ABSENT_VALUE as wo,ThemedSplitView as Ha,devToolsDefaultTheme as Ea,toDiffable as So}from"@buoy-gg/shared-ui/web/dataViewer";import{jsx as Ba,jsxs as vo}from"react/jsx-runtime";var Wa=[];function Na({item:e,testID:t}){let{oldValue:r,newValue:i}=Oa(()=>({oldValue:e.verdict==="added"?wo:So(e.oldValue),newValue:e.verdict==="removed"?wo:So(e.newValue)}),[e]);return vo(u,{style:xo.panel,testID:t,children:[e.reason?vo(c,{style:xo.reason,children:["\u26A0 ",e.reason]}):null,Ba(Ha,{oldValue:r,newValue:i,differences:Wa,theme:Ea,scrollEnabled:false})]})}var xo=O.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}});import{useEffect as ja,useState as Ma}from"react";import{jsx as Io,jsxs as Va}from"react/jsx-runtime";function Fa({name:e,onRename:t}){let[r,i]=Ma(e);ja(()=>i(e),[e]);let n=()=>{let a=r.trim();if(!a){i(e);return}a!==e&&t(a)};return Va(u,{style:ar.row,children:[Io(c,{style:ar.label,children:"Name"}),Io(it,{style:ar.input,value:r,onChangeText:i,onSubmitEditing:n,onBlur:n,returnKeyType:"done",selectTextOnFocus:true,accessibilityLabel:"Restore point name",testID:"tm-preview-name"})]})}var ar=O.create({row:{flexDirection:"row",alignItems:"center",gap:14,minHeight:o.rowMinHeight,paddingHorizontal:o.textInset},label:{color:o.color.labelSecondary,fontSize:o.font.row,letterSpacing:o.tracking.row},input:{flex:1,minWidth:0,color:o.color.label,fontSize:o.font.row,fontWeight:"600",letterSpacing:o.tracking.row,textAlign:"right",padding:0,backgroundColor:"transparent"}});var Je={added:{glyph:"+",color:o.color.accent,label:"added",applies:true},removed:{glyph:"\u2212",color:o.color.danger,label:"removed",applies:true},changed:{glyph:"\u2248",color:o.color.info,label:"changed",applies:true},"too-large":{glyph:"\u2248",color:o.color.warning,label:"changed (large)",applies:true},unchanged:{glyph:"=",color:o.color.labelTertiary,label:"unchanged",applies:false},"wont-apply":{glyph:"\u2298",color:o.color.warning,label:"won't apply",applies:false},recomputes:{glyph:"\u21BB",color:o.color.labelTertiary,label:"recomputes",applies:false}};import{Fragment as _a,jsx as p,jsxs as B}from"react/jsx-runtime";var Ro={storage:"keys",redux:"slices",zustand:"stores",jotai:"atoms",query:"queries"},sr=new Set;function Ka(e,t){if(e.size!==t.size)return false;for(let r of e)if(!t.has(r))return false;return true}function he(e,t){return`${e}::${t}`}function Rt(e){if(e===void 0)return"\u2205";try{let t=typeof e=="string"?`"${e}"`:JSON.stringify(e);return t?t.length>46?`${t.slice(0,43)}\u2026`:t:String(e)}catch{return"[complex]"}}function Ue({position:e,children:t}){return B(u,{style:[g.cardRow,e.first?g.cardRowFirst:null,e.last?g.cardRowLast:null],children:[e.first?null:p(u,{style:g.cardSeparator}),t]})}function lr({glyph:e,count:t,color:r,testID:i}){return p(u,{style:[g.countPill,{backgroundColor:`${r}26`}],children:B(c,{style:[g.countPillText,{color:r}],testID:i,children:[e,t]})})}function cr({state:e}){return p(u,{style:[g.checkbox,e!=="none"&&g.checkboxChecked],children:e==="none"?null:p(c,{style:g.checkboxGlyph,children:e==="all"?"\u2713":"\u2212"})})}var qa=Zi(function({row:e,expanded:t,onOpen:r,onToggle:i}){let n=Je[e.item.verdict],a=!n.applies||e.excluded,s=e.item.verdict==="changed"||e.item.verdict==="added"||e.item.verdict==="removed",h=`tm-preview-item-${e.sourceId}-${e.item.key}`;return p(Ue,{position:e,children:B(u,{style:[g.itemRow,a&&g.dimmed],children:[p(P,{onPress:i,disabled:!n.applies,hitSlop:{top:10,bottom:10,left:8,right:8},testID:`tm-preview-toggle-${e.sourceId}-${e.item.key}`,accessibilityRole:"checkbox",accessibilityState:{checked:!(!n.applies||e.excluded)},accessibilityLabel:`Include ${e.item.label}`,children:p(cr,{state:!n.applies||e.excluded?"none":"all"})}),B(P,{style:g.itemBodyTouch,onPress:()=>s&&r(),disabled:!s,testID:h,children:[p(c,{style:[g.itemGlyph,{color:n.color}],children:n.glyph}),B(u,{style:g.itemBody,children:[p(c,{style:g.itemLabel,numberOfLines:1,testID:`${h}-label`,children:e.item.label}),e.item.verdict==="changed"&&B(c,{style:g.itemPreview,numberOfLines:1,testID:`${h}-values`,children:[Rt(e.item.oldValue)," \u2192"," ",Rt(e.item.newValue)]}),e.item.verdict==="added"&&p(c,{style:g.itemPreview,numberOfLines:1,testID:`${h}-values`,children:Rt(e.item.newValue)}),e.item.verdict==="removed"&&p(c,{style:[g.itemPreview,g.itemPreviewRemoved],numberOfLines:1,testID:`${h}-values`,children:Rt(e.item.oldValue)}),e.excluded?p(c,{style:g.itemExcluded,testID:`${h}-excluded`,children:"excluded \u2014 restore leaves this untouched"}):e.item.reason&&p(c,{style:g.itemReason,numberOfLines:2,testID:`${h}-reason`,children:e.item.reason})]}),s?t?p(Gr,{size:16,color:o.color.labelTertiary}):p(jr,{}):null]})]})})});function Ja({preview:e,snapshots:t,busy:r,onBack:i,onRestore:n}){let a=na(),s=a.instanceId!==void 0,h=ra({minBottom:16}),[m,y]=Jt({}),[d,k]=Jt(new Set),L=qt(false),[b,H]=Jt(sr),W=De(l=>{H(S=>{let C=new Set(S);return C.has(l)?C.delete(l):C.add(l),C})},[]),N=a.search,w=e.right==="current"?void 0:t.find(l=>l.id===e.right.snapshotId),U=qt(w);U.current=w;let ee=De(()=>{if(!U.current)return;let l=U.current;v.setRestoreRoute(l.id,!dt(l))},[]),Y=w?.baseline===true,Le=e.left==="current",te=bt(()=>w?w.excludedKeys?.length?new Set(w.excludedKeys):sr:null,[w]),_=!!w?.scope?.length&&!w?.excludedKeys?.length,$=bt(()=>{if(!_||!w?.scope)return sr;let l=new Set(w.scope),S=new Set;for(let C of e.sources)for(let I of C.items){let K=he(C.id,I.key);Je[I.verdict].applies&&!l.has(K)&&S.add(K)}return S},[_,w,e.sources]),ne=qt(null);Yr(()=>{if(!w||e.building||!te||ne.current===w.id)return;ne.current=w.id,L.current=false;let l=te.size>0?te:$;l.size>0&&k(new Set(l)),_&&l.size>0&&v.setExclusions(w.id,Array.from(l))},[w,e.building,te,$,_]),Yr(()=>{if(!w||!te||!L.current||Ka(d,te))return;let l=Array.from(d);v.setExclusions(w.id,l.length?l:null)},[d,w,te]);let pe=De(l=>{L.current=true,k(S=>{let C=new Set(S);return C.has(l)?C.delete(l):C.add(l),C})},[]),ke=De((l,S)=>{L.current=true,k(C=>{let I=new Set(C);for(let K of l.items){if(!Je[K.verdict].applies)continue;let re=he(l.id,K.key);S==="all"?I.add(re):I.delete(re)}return I})},[]),ie=De((l,S)=>{y(C=>({...C,[l]:!S}))},[]),D=bt(()=>{let l=0,S=0,C=0,I=[];for(let K of e.sources){let re=0;for(let G of K.items)Je[G.verdict].applies?d.has(he(K.id,G.key))?S+=1:(l+=1,re+=1):G.verdict==="wont-apply"&&(C+=1);re>0&&I.push(`${re} ${K.label.toLowerCase()}`)}return{applies:l,excludedCount:S,wontApply:C,perSource:I}},[e.sources,d]);oa(s?{title:"Restore Preview",subtitle:w?.name??"preview",onBack:i,actions:p(yo,{armId:w?.id})}:null,[s,w?.name,w?.id]);let{rows:Xe,blockedSources:Pe}=bt(()=>{let l=N.trim().toLowerCase(),S=[],C=[];for(let I of e.sources){let K=I.items.some(z=>z.verdict!=="unchanged");if(!K&&!I.error)continue;let re=K||I.notes.length>0||!!I.error,G=I.items.filter(z=>Je[z.verdict].applies),Oe=I.items.filter(z=>z.verdict==="wont-apply").length;Oe>0&&C.push(I.label);let et=I.items.length===1?(Ro[I.id]??"items").replace(/ies$/,"y").replace(/s$/,""):Ro[I.id]??"items",q=`${I.items.length} ${et} \xB7 `+(G.length>0?`${G.length} changed`:Oe>0?`${Oe} won't apply`:"no changes"),Ce=G.filter(z=>d.has(he(I.id,z.key))).length,tt=G.length===0||Ce===0?"all":Ce===G.length?"none":"some",ce={added:0,removed:0,changed:0};for(let z of I.items)d.has(he(I.id,z.key))||(z.verdict==="added"?ce.added+=1:z.verdict==="removed"?ce.removed+=1:(z.verdict==="changed"||z.verdict==="too-large")&&(ce.changed+=1));let $e=I.items.filter(z=>!(z.verdict==="unchanged"||l&&!z.label.toLowerCase().includes(l))),rt=re?m[I.id]??true:true;if(S.push({kind:"source",source:I,collapsed:rt,includeState:tt,applicableCount:G.length,counts:ce,expandable:re,summary:q,first:false,last:false}),!rt){for(let z of I.notes)S.push({kind:"note",id:`${I.id}:${z}`,text:z,first:false,last:false});I.error&&S.push({kind:"note",id:`${I.id}:err`,text:`\u26A0 ${I.error}`,first:false,last:false});for(let z of $e){let f=he(I.id,z.key);S.push({kind:"item",sourceId:I.id,item:z,excluded:d.has(f),first:false,last:false}),b.has(f)&&S.push({kind:"diff",sourceId:I.id,item:z,first:false,last:false})}}}return w?.route&&S.push({kind:"route",href:w.route.href,on:dt(w),first:false,last:false}),S.length>0&&(S[0].first=true,S[S.length-1].last=true),{rows:S,blockedSources:C}},[e.sources,N,m,d,b,w]),Qe=De(({item:l})=>{if(l.kind==="source"){let S=l.source,{counts:C}=l;return p(Ue,{position:l,children:B(u,{style:g.sourceCard,children:[p(P,{onPress:()=>ke(S,l.includeState),disabled:l.applicableCount===0,hitSlop:{top:10,bottom:10,left:8,right:8},testID:`tm-preview-source-toggle-${S.id}`,children:p(cr,{state:l.applicableCount===0?"none":l.includeState})}),B(P,{style:g.sourceCardTouch,onPress:()=>l.expandable&&ie(S.id,l.collapsed),disabled:!l.expandable,testID:`tm-preview-source-${S.id}`,children:[B(u,{style:g.sourceNameBlock,children:[p(c,{style:g.sourceName,numberOfLines:1,testID:`tm-preview-source-${S.id}-name`,children:S.label}),p(c,{style:g.sourceSummary,numberOfLines:1,testID:`tm-preview-source-${S.id}-summary`,children:l.includeState==="none"&&l.applicableCount>0?`${l.summary} \xB7 excluded`:l.summary})]}),B(u,{style:g.sourceBadges,children:[C.removed>0?p(lr,{glyph:"\u2212",count:C.removed,color:o.color.danger,testID:`tm-preview-source-${S.id}-removed`}):null,C.added>0?p(lr,{glyph:"+",count:C.added,color:o.color.accent,testID:`tm-preview-source-${S.id}-added`}):null,C.changed>0?p(lr,{glyph:"\u2248",count:C.changed,color:o.color.info,testID:`tm-preview-source-${S.id}-changed`}):null]}),l.expandable?l.collapsed?p(jr,{}):p(Gr,{size:16,color:o.color.labelTertiary}):null]})]})})}return l.kind==="note"?p(Ue,{position:l,children:p(c,{style:g.noteRow,testID:`tm-preview-note-${l.id}`,children:l.text})}):l.kind==="route"?p(Ue,{position:l,children:B(P,{style:g.routeRow,onPress:ee,accessibilityRole:"switch",accessibilityState:{checked:l.on},accessibilityLabel:`Also return to ${l.href}`,testID:"tm-preview-route",children:[p(cr,{state:l.on?"all":"none"}),B(u,{style:g.routeText,children:[p(c,{style:g.routeTitle,children:"Return to this screen"}),p(c,{style:g.routeHref,numberOfLines:1,testID:"tm-preview-route-href",children:l.href})]})]})}):l.kind==="diff"?p(Ue,{position:l,children:p(Na,{item:l.item,testID:`tm-preview-diff-${l.sourceId}-${l.item.key}`})}):p(qa,{row:l,expanded:b.has(he(l.sourceId,l.item.key)),onOpen:()=>W(he(l.sourceId,l.item.key)),onToggle:()=>pe(he(l.sourceId,l.item.key))})},[b,W,ie,pe,ke,ee]),Te=De(l=>l.kind==="source"?`s:${l.source.id}`:l.kind==="note"?`n:${l.id}`:l.kind==="route"?"route":l.kind==="diff"?`d:${l.sourceId}:${l.item.key}`:`i:${l.sourceId}:${l.item.key}`,[]),Ze=B(u,{children:[!s&&B(u,{style:g.fallbackHeader,children:[p(P,{onPress:i,hitSlop:Ua,testID:"tm-preview-back",children:p(c,{style:g.backText,children:"\u2039 Back"})}),p(c,{style:g.screenTitle,numberOfLines:1,children:"Restore Preview"})]}),w?B(_a,{children:[p(pt,{children:"Restore Point"}),p(mt,{children:p(Fa,{name:w.name,onRename:l=>void v.rename(w.id,l)})})]}):null,p(pt,{children:"Changes to Restore"})]}),Ae=r||e.building||D.applies===0;return B(u,{style:g.container,children:[p(vr,{testID:"tm-preview-list",data:Xe,renderItem:Qe,keyExtractor:Te,ListHeaderComponent:Ze,ListEmptyComponent:e.building?p(at,{style:g.buildingSpinner,size:"small",color:o.color.accent}):p(c,{style:g.emptyText,testID:"tm-preview-empty",children:N?"Nothing matches this filter.":"No changes \u2014 restoring would change nothing."}),ListFooterComponent:p(u,{children:D.wontApply>0?B(u,{style:g.warnNote,children:[p(ea,{size:12,color:o.color.warning}),B(c,{style:g.warnNoteText,testID:"tm-preview-wont-apply",children:[D.wontApply," item",D.wontApply===1?"":"s"," ","won't apply \u2014 expand"," ",Pe.length>0?Pe.join(" and "):"the source"," ","to see the reason."]})]}):null}),keyboardShouldPersistTaps:"handled",removeClippedSubviews:true,initialNumToRender:20,windowSize:7,contentContainerStyle:g.listContent}),Le&&w&&B(u,{style:[g.footer,{paddingBottom:h.bottom}],children:[B(P,{style:[g.cta,Y&&g.ctaDanger,Ae&&g.ctaDisabled],onPress:()=>n(Y?"reload":"live",Array.from(d)),disabled:Y?r||e.building:Ae,testID:"tm-preview-restore",children:[p(ta,{size:16,color:Y?o.color.onDanger:o.color.onAccent}),p(c,{style:[g.ctaText,Y?g.ctaTextDanger:null],children:Y?"Wipe & Reload":"Restore State"})]}),p(c,{style:g.ctaCaption,testID:"tm-preview-cta-caption",children:Y?"This wipes all app storage and reloads the app.":D.excludedCount>0?`Restores ${D.applies} of ${D.applies+D.excludedCount} change${D.applies+D.excludedCount===1?"":"s"} \u2014 everything else stays as it is.`:"This will replace the current state with the snapshot."})]})]})}var Ua={top:10,bottom:10,left:10,right:10},g=O.create({container:{flex:1,backgroundColor:"transparent"},fallbackHeader:{flexDirection:"row",alignItems:"center",paddingHorizontal:o.gutter,paddingVertical:10,gap:10},backText:{color:o.color.accent,fontSize:o.font.control},screenTitle:{color:o.color.label,fontSize:20,fontWeight:"700",letterSpacing:o.tracking.row,flex:1},dimmed:{opacity:.5},listContent:{paddingTop:14,paddingBottom:12},cardRow:{marginHorizontal:o.gutter,backgroundColor:o.color.group},cardRowFirst:{borderTopLeftRadius:o.radius.group,borderTopRightRadius:o.radius.group},cardRowLast:{borderBottomLeftRadius:o.radius.group,borderBottomRightRadius:o.radius.group,marginBottom:10},cardSeparator:{height:O.hairlineWidth,marginLeft:51,backgroundColor:o.color.separator},warnNote:{flexDirection:"row",alignItems:"flex-start",gap:6,paddingHorizontal:o.gutter+o.textInset,paddingTop:8},warnNoteText:{flex:1,color:o.color.labelSecondary,fontSize:o.font.footnote,lineHeight:o.font.footnote*1.35},countPill:{borderRadius:o.radius.pill,paddingHorizontal:9,paddingVertical:3},countPillText:{fontFamily:ht,fontSize:o.font.footnote,fontWeight:"600"},checkbox:{width:23,height:23,borderRadius:o.radius.pill,borderWidth:1.7,borderColor:o.color.labelTertiary,alignItems:"center",justifyContent:"center"},checkboxChecked:{borderColor:o.color.accent,backgroundColor:o.color.accent},checkboxGlyph:{color:o.color.onAccent,fontSize:13,fontWeight:"700",lineHeight:15},routeRow:{flexDirection:"row",alignItems:"center",minHeight:58,paddingHorizontal:o.textInset,paddingVertical:9,gap:12},routeText:{flex:1,minWidth:0,gap:2},routeTitle:{color:o.color.label,fontSize:o.font.row,fontWeight:"600",letterSpacing:o.tracking.row},routeHref:{color:o.color.labelSecondary,fontFamily:ht,fontSize:o.font.mono},sourceCard:{flexDirection:"row",alignItems:"center",minHeight:58,paddingHorizontal:o.textInset,paddingVertical:9,gap:12},sourceCardTouch:{flex:1,flexDirection:"row",alignItems:"center",gap:12,minWidth:0},sourceNameBlock:{flex:1,minWidth:0,gap:2},sourceName:{color:o.color.label,fontSize:o.font.row,fontWeight:"600",letterSpacing:o.tracking.row},sourceSummary:{color:o.color.labelSecondary,fontSize:o.font.footnote,fontVariant:["tabular-nums"]},sourceBadges:{flexDirection:"row",gap:6},noteRow:{color:o.color.labelTertiary,fontSize:o.font.footnote,lineHeight:o.font.footnote*1.35,paddingHorizontal:o.textInset,paddingVertical:9},itemRow:{flexDirection:"row",alignItems:"center",paddingLeft:o.textInset,paddingRight:o.textInset,paddingVertical:10,gap:12},itemBodyTouch:{flex:1,flexDirection:"row",alignItems:"center",gap:10,minWidth:0},itemGlyph:{fontSize:14,fontWeight:"700",width:14,textAlign:"center"},itemBody:{flex:1,minWidth:0},itemLabel:{color:o.color.label,fontSize:o.font.control,letterSpacing:o.tracking.control},itemPreview:{color:o.color.labelSecondary,fontFamily:ht,fontSize:o.font.mono,marginTop:3},itemPreviewRemoved:{textDecorationLine:"line-through"},itemReason:{color:o.color.warning,fontSize:o.font.mono,marginTop:3},itemExcluded:{color:o.color.labelTertiary,fontSize:o.font.mono,marginTop:3,fontStyle:"italic"},buildingSpinner:{marginTop:28},emptyText:{color:o.color.labelSecondary,fontSize:o.font.footnote,textAlign:"center",marginTop:28},footer:{paddingHorizontal:o.gutter,paddingTop:10,gap:8,borderTopColor:o.color.separator,borderTopWidth:O.hairlineWidth,backgroundColor:o.color.sheet},cta:{flexDirection:"row",alignItems:"center",justifyContent:"center",gap:8,height:50,backgroundColor:o.color.accent,borderRadius:o.radius.group},ctaDanger:{backgroundColor:o.color.danger},ctaTextDanger:{color:o.color.onDanger},ctaDisabled:{opacity:.4},ctaText:{color:o.color.onAccent,fontSize:o.font.row,fontWeight:"600",letterSpacing:o.tracking.row},ctaCaption:{color:o.color.labelSecondary,fontSize:o.font.footnote,lineHeight:o.font.footnote*1.35,textAlign:"center"}});import{jsx as Ya}from"react/jsx-runtime";function Ga(e,t){return e==="current"?void 0:t.find(r=>r.id===e.snapshotId)}function Xa({preview:e,snapshots:t,busy:r,onClose:i}){let n=Ga(e.right,t);return Ya(Ja,{preview:e,snapshots:t,busy:r,onBack:i,onRestore:(a,s)=>{if(!(!n||r)){if(n.baseline){Nt("Restore fresh install?","This wipes all app storage and reloads the app.","Wipe & reload",()=>void v.restore(n.id,"reload"));return}v.restore(n.id,a,s).then(i)}}})}import{jsx as M,jsxs as Ye}from"react/jsx-runtime";var Do=()=>Mn().some(e=>e.id===rr);function dr(){let[e,t]=kr({kind:"list"}),{snapshots:r,busy:i,preview:n}=ut(),a=Ci(),s=()=>{v.clearPreview(),t({kind:"list"})};return e.kind==="preview"&&n?M(Xa,{preview:n,snapshots:r,busy:i!==null,onClose:s}):M(Qa,{sources:a,onOpenPreview:h=>{v.buildPreview({snapshotId:h.id}),t({kind:"preview"})}})}function Qa({sources:e,onOpenPreview:t}){let{snapshots:r,hasLoaded:i,busy:n,lastOutcome:a,recentlyDeleted:s,remoteProviders:h}=ut(),m=Nn("timeMachine.snapshots"),y=Fn(),d=Wn({minBottom:16}),k=Tr(Vn,Do,Do),L=Tr(oo,St,St),b=k?no(r,L)?.id:void 0,H=Bn({}),[W,N]=kr(null),w=$=>{N(null),nr($),y.minimize()},U=y.search.trim().toLowerCase(),ee=U?r.filter($=>$.name.toLowerCase().includes(U)):r,Y=r.filter($=>!$.safety).length>=m,Le=n!==null||Y,te=$=>{if(n)return;if($.baseline){Nt("Restore fresh install?","This wipes all app storage and reloads the app.","Wipe & reload",()=>void v.restore($.id,"reload"));return}let ne=(H.current[$.id]??0)+1;H.current[$.id]=ne,ne>=2&&!k&&N($.id),v.restore($.id,"live").then(pe=>{!Object.values(pe.results).every(ke=>ke.ok)||pe.willReload||y.minimize()})},_=W&&!k?r.find($=>$.id===W)??null:null;return Ye(zt,{style:Ge.fill,contentContainerStyle:[Ge.content,{paddingBottom:d.bottom}],testID:"time-machine-scroll",keyboardShouldPersistTaps:"handled",children:[a&&Mr(a)?M(Ei,{outcome:a}):null,s?M(Ki,{name:s.stored.meta.name,at:s.at,onUndo:()=>void v.undoDelete(),onExpire:()=>v.clearRecentlyDeleted()}):null,M(u,{children:M(Pi,{disabled:Le,busy:n==="capture",onCapture:$=>void v.capture($)})}),Y?Ye(Me,{tone:"warning",testID:"time-machine-limit",children:["Free plan keeps ",m," restore point",m===1?"":"s",". Upgrade to Pro for unlimited snapshots."]}):null,M(pt,{children:"Sources"}),M(Xi,{sources:e,onToggle:h?void 0:Er}),h?null:M(Me,{testID:"time-machine-sources-hint",children:"Switch a source off to leave it out of every capture and restore."}),M(pt,{children:"Restore Points"}),_?Ye(u,{style:Ge.barHint,testID:"time-machine-bar-hint",children:[Ye(Me,{children:['Restoring "',_.name,'" a lot? Put it on the floating action bar and restore it with one tap.']}),M(P,{onPress:()=>w(_.id),accessibilityRole:"button",testID:"time-machine-bar-hint-pin",hitSlop:{top:6,bottom:6,left:6,right:6},children:M(c,{style:Ge.barHintAction,children:"Open the action bar"})})]}):null,Ye(mt,{children:[ee.map($=>M(Vi,{meta:$,busy:n!==null,armed:$.id===b,onOpen:()=>t($),onRestore:()=>te($),onDelete:()=>void v.delete($.id),onDuplicate:()=>void v.duplicate($.id),onArm:()=>w($.id)},$.id)),ee.length===0?M(jn,{testID:"time-machine-empty",...i?r.length>0?{otto:"sad",title:"No restore point matches that name.",message:`Clear the search to see all ${r.length}.`}:{otto:"rewind",title:"No restore points yet",message:"Set up the state you want to come back to, then capture it."}:{otto:"loading",title:"Loading restore points\u2026",message:"Reading the vault off disk."}}):null]}),ee.length>0?M(Me,{testID:"time-machine-swipe-hint",children:"Swipe a restore point to copy or delete it."}):null,M(u,{style:Ge.spacer}),M(mt,{children:M(Qi,{disabled:n!==null,onWipe:()=>Nt("Wipe all app state?","This deletes all app storage and reloads the app \u2014 like a fresh install.","Wipe & reload",()=>void v.wipeAll())})}),M(Me,{centered:true,children:"Deletes all app storage and reloads \u2014 like a fresh install."})]})}var Ge=O.create({barHint:{marginHorizontal:o.gutter,marginBottom:8},barHintAction:{color:o.color.accent,fontSize:o.font.footnote,fontWeight:"600",paddingHorizontal:o.textInset,paddingTop:2},fill:{flex:1,backgroundColor:"transparent"},content:{paddingTop:14},empty:{color:o.color.labelSecondary,fontSize:o.font.footnote,lineHeight:o.font.footnote*1.4,paddingHorizontal:o.textInset,paddingVertical:16},spacer:{height:24}});import{jsx as ko}from"react/jsx-runtime";var Dt={id:"time-machine",name:"TIME MACHINE",description:"Snapshot & restore app state (storage, stores, query cache)",slot:"both",icon:({size:e,color:t,slot:r})=>ko(Hn,{size:r==="dial"&&nt.OS!=="web"?e*1.5:e,color:t||En}),component:dr,modal:{subtitle:"snapshot & restore app state",searchable:true,searchPlaceholder:"Filter\u2026",headerActions:ko(yo,{})}};function Za(e={}){return{...Dt,name:e.name??Dt.name,description:e.description??Dt.description}}import{JsModal as es}from"@buoy-gg/shared-ui/web";import{jsx as ze,jsxs as ts}from"react/jsx-runtime";function rs(){return ts(u,{style:ur.header,children:[ze(c,{style:ur.headerTitle,children:"Time Machine"}),ze(c,{style:ur.headerSubtitle,children:"Snapshot & restore app state"})]})}function os({visible:e,onClose:t,onBack:r,onMinimize:i,persistenceKey:n}){return ze(es,{visible:e,onClose:t,onMinimize:i,persistenceKey:n,header:{showToggleButton:true,customContent:ze(rs,{})},enablePersistence:true,initialMode:"bottomSheet",disableScrollWrapper:true,children:ze(dr,{})})}function ns(){return ze(dr,{})}var ur=O.create({header:{paddingHorizontal:4,gap:2},headerTitle:{color:o.color.label,fontSize:22,fontWeight:"700",letterSpacing:.3},headerSubtitle:{color:o.color.labelSecondary,fontSize:o.font.footnote}});import{getStateSnapshotProviders as is,subscribeToStateSnapshotProviders as as,superJsonDeserialize as ss}from"@buoy-gg/shared-ui/web";import{jsonLikelyLargerThan as To}from"@buoy-gg/shared-ui/web/dataViewer";function ls(){return is().map(e=>{let t=e.status();return{id:e.id,label:e.label,canCapture:t.canCapture,canRestore:t.canRestore,detail:t.detail,enabled:se(e.id)}})}function Co(){let{snapshots:e,busy:t,lastOutcome:r}=v.getState(),i=No();return{snapshots:e,busy:t,lastOutcome:r,providers:ls(),route:{available:He(),enabled:se(We),...i?{current:i.href}:{}}}}var cs={version:2,getSnapshot:()=>Co(),subscribe:e=>{let t=v.subscribe(e),r=as(e);return()=>{t(),r()}},actions:{list:()=>Co(),capture:async e=>{let{name:t="",sourceIds:r}=e??{};return{captured:true,snapshot:await v.capture(t,r)}},captureBaseline:async()=>({captured:true,snapshot:await v.captureBaseline()}),wipeAll:async()=>await v.wipeAll(),restore:async e=>{let{id:t,mode:r="live",excludeKeys:i,restoreRoute:n}=e??{};if(!t)throw new Error("restore requires a snapshot `id`");return await v.restore(t,r,i,{restoreRoute:n})},delete:async e=>{let{id:t}=e??{};if(!t)throw new Error("delete requires a snapshot `id`");return await v.delete(t),{deleted:true,id:t}},rename:async e=>{let{id:t,name:r}=e??{};if(!t||!r)throw new Error("rename requires `id` and `name`");return await v.rename(t,r),{renamed:true,id:t,name:r}},setExclusions:async e=>{let{id:t,excludedKeys:r}=e??{};if(!t)throw new Error("setExclusions requires `id`");return await v.setExclusions(t,r??null),{id:t,excluded:r?.length??0}},setRestoreRoute:async e=>{let{id:t,restoreRoute:r}=e??{};if(!t)throw new Error("setRestoreRoute requires `id`");return await v.setRestoreRoute(t,r!==false),{id:t,restoreRoute:r!==false}},duplicate:async e=>{let{id:t}=e??{};if(!t)throw new Error("duplicate requires `id`");let r=await v.duplicate(t);if(!r)throw new Error(`No snapshot with id "${t}"`);return{snapshot:r}},setScope:async e=>{let{id:t,scope:r}=e??{};if(!t)throw new Error("setScope requires a snapshot `id`");return await v.setScope(t,r??null),{scoped:true,id:t,count:r?.length??0}},preview:async e=>{let{id:t,compareTo:r}=e??{};if(!t)throw new Error("preview requires a snapshot `id`");let i={snapshotId:t},n=r?{snapshotId:r}:"current";await v.buildPreview(i,n);let a=v.getState().preview;if(!a)throw new Error("preview build produced no result");let s=4*1024;return{left:n,right:i,builtAt:a.builtAt,sources:a.sources.map(h=>({...h,items:h.items.map(m=>{let y=m.oldValue!==void 0&&To(m.oldValue,s),d=m.newValue!==void 0&&To(m.newValue,s);return{...m,oldValue:y?void 0:m.oldValue,newValue:d?void 0:m.newValue,...y||d?{valueOmitted:true}:{}}})}))}},inspect:async e=>{let{id:t,sourceId:r}=e??{};if(!t||!r)throw new Error("inspect requires `id` and `sourceId`");let i=await fe(t);if(!i)throw new Error(`No snapshot with id "${t}"`);let n=i.data[r];if(!n)throw new Error(`Snapshot "${t}" has no "${r}" source`);return{id:t,sourceId:r,warnings:i.meta.sources[r]?.warnings??[],data:ss(n)}}}};yr();export{Ne as RESTORE_ORDER,Bt as SAFETY_SNAPSHOT_NAME,rr as TIME_MACHINE_FLOATING_TOOL_ID,os as TimeMachineModal,ns as TimeMachineToolView,yr as armPendingRouteRestore,He as canRestoreRoute,ot as captureCurrentRoute,Za as createTimeMachineTool,se as isSourceEnabled,Ct as navigateToRoute,nr as openTimeMachineFloatingTool,ui as replaceTimeMachineFromSnapshot,di as setRemoteTimeMachineHandler,Er as setSourceEnabled,fo as startTimeMachineFloatingToolPersistence,Or as subscribeSourceSettings,v as timeMachineStore,cs as timeMachineSyncAdapter,Dt as timeMachineToolPreset};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@buoy-gg/time-machine",
|
|
3
|
-
"version": "7.0.
|
|
3
|
+
"version": "7.0.57",
|
|
4
4
|
"description": "Time Machine - snapshot & restore app state (storage, redux, zustand, jotai, react-query) for React Native DevTools",
|
|
5
5
|
"main": "lib/commonjs/index.js",
|
|
6
6
|
"module": "lib/module/index.js",
|
|
@@ -20,19 +20,19 @@
|
|
|
20
20
|
"./lib/web/**/*.mjs"
|
|
21
21
|
],
|
|
22
22
|
"dependencies": {
|
|
23
|
-
"@buoy-gg/
|
|
24
|
-
"@buoy-gg/
|
|
23
|
+
"@buoy-gg/shared-ui": "^7.0.57",
|
|
24
|
+
"@buoy-gg/floating-tools-core": "^7.0.57"
|
|
25
25
|
},
|
|
26
26
|
"peerDependencies": {
|
|
27
|
-
"@buoy-gg/license": "7.0.
|
|
27
|
+
"@buoy-gg/license": "7.0.57",
|
|
28
28
|
"react": "*"
|
|
29
29
|
},
|
|
30
30
|
"devDependencies": {
|
|
31
31
|
"@types/react": "^19.1.0",
|
|
32
32
|
"@types/react-native": "^0.73.0",
|
|
33
33
|
"typescript": "~5.8.3",
|
|
34
|
-
"@buoy-gg/
|
|
35
|
-
"@buoy-gg/
|
|
34
|
+
"@buoy-gg/core": "^7.0.57",
|
|
35
|
+
"@buoy-gg/license": "^7.0.57"
|
|
36
36
|
},
|
|
37
37
|
"react-native-builder-bob": {
|
|
38
38
|
"source": "src",
|