@buoy-gg/time-machine 7.0.78 → 7.0.80

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.
@@ -1 +1 @@
1
- "use strict";Object.defineProperty(exports,"__esModule",{value:true});exports.HeaderReloadButton=HeaderReloadButton;var _reactNative=require("react-native");var _sharedUi=require("@buoy-gg/shared-ui");var _jsxRuntime=require("react/jsx-runtime");function HeaderReloadButton(){const e=()=>{try{(0,_sharedUi.scheduleReloadApp)({reason:"buoy time-machine reload app"})}catch{}};return(0,_jsxRuntime.jsx)(_reactNative.TouchableOpacity,{style:styles.chip,onPress:e,accessibilityLabel:"Reload app",accessibilityHint:"Reloads the JavaScript bundle without restoring anything",accessibilityRole:"button",testID:"time-machine-reload-app",children:(0,_jsxRuntime.jsx)(_reactNative.Text,{style:styles.label,children:"Reload app"})})}const styles=_reactNative.StyleSheet.create({chip:{height:32,paddingHorizontal:10,borderRadius:8,borderWidth:1,borderColor:_sharedUi.night.color.border,backgroundColor:_sharedUi.night.color.buttonSurface,alignItems:"center",justifyContent:"center"},label:{fontSize:11,fontWeight:"700",color:_sharedUi.night.color.textSecondary}});
1
+ "use strict";Object.defineProperty(exports,"__esModule",{value:true});exports.HeaderReloadButton=HeaderReloadButton;var _reactNative=require("react-native");var _sharedUi=require("@buoy-gg/shared-ui");var _timeMachineStore=require("../store/timeMachineStore");var _jsxRuntime=require("react/jsx-runtime");function HeaderReloadButton(){const e=()=>{_timeMachineStore.timeMachineStore.reloadApp()};return(0,_jsxRuntime.jsx)(_reactNative.TouchableOpacity,{style:styles.chip,onPress:e,accessibilityLabel:"Reload app",accessibilityHint:"Reloads the JavaScript bundle without restoring anything",accessibilityRole:"button",testID:"time-machine-reload-app",children:(0,_jsxRuntime.jsx)(_reactNative.Text,{style:styles.label,children:"Reload app"})})}const styles=_reactNative.StyleSheet.create({chip:{height:32,paddingHorizontal:10,borderRadius:8,borderWidth:1,borderColor:_sharedUi.night.color.border,backgroundColor:_sharedUi.night.color.buttonSurface,alignItems:"center",justifyContent:"center"},label:{fontSize:11,fontWeight:"700",color:_sharedUi.night.color.textSecondary}});
@@ -1 +1 @@
1
- "use strict";Object.defineProperty(exports,"__esModule",{value:true});exports.TimeMachineBody=TimeMachineBody;var _react=require("react");var _reactNative=require("react-native");var _sharedUi=require("@buoy-gg/shared-ui");var _core=require("@buoy-gg/core");var _useTimeMachine=require("../hooks/useTimeMachine");var _timeMachineStore=require("../store/timeMachineStore");var _primitives=require("../ui/primitives");var _tmTheme=require("../ui/tmTheme");var _sources=require("./sources");var _confirm=require("./confirm");var _CaptureBar=require("./list/CaptureBar");var _RestoreOutcomeCard=require("./list/RestoreOutcomeCard");var _SnapshotRow=require("./list/SnapshotRow");var _UndoDeleteBar=require("./list/UndoDeleteBar");var _SourcesStrip=require("./list/SourcesStrip");var _WipeAllRow=require("./list/WipeAllRow");var _PreviewFlow=require("./preview/PreviewFlow");var _TimeMachineFloatingTool=require("./floating/TimeMachineFloatingTool");var _armedPoint=require("./floating/armedPoint");var _sourceSettings=require("../store/sourceSettings");var _jsxRuntime=require("react/jsx-runtime");const isBarOpen=()=>(0,_sharedUi.getFloatingTools)().some(o=>o.id===_TimeMachineFloatingTool.TIME_MACHINE_FLOATING_TOOL_ID);function TimeMachineBody(){const[o,s]=(0,_react.useState)({kind:"list"});const{snapshots:t,busy:l,preview:i}=(0,_useTimeMachine.useTimeMachineState)();const r=(0,_sources.useSourceStatuses)();const n=()=>{_timeMachineStore.timeMachineStore.clearPreview();s({kind:"list"})};if(o.kind==="preview"&&i)return(0,_jsxRuntime.jsx)(_PreviewFlow.PreviewScreen,{preview:i,snapshots:t,busy:l!==null,onClose:n});return(0,_jsxRuntime.jsx)(RestorePointList,{sources:r,onOpenPreview:a=>{void _timeMachineStore.timeMachineStore.buildPreview({snapshotId:a.id});s({kind:"preview"})}})}function RestorePointList({sources:o,onOpenPreview:s}){const{snapshots:t,hasLoaded:l,busy:i,lastOutcome:r,recentlyDeleted:n,remoteProviders:a}=(0,_useTimeMachine.useTimeMachineState)();const c=(0,_sharedUi.useLimit)("timeMachine.snapshots");const u=(0,_core.useToolHost)();const y=(0,_sharedUi.useSafeAreaInsets)({minBottom:16});const d=(0,_react.useSyncExternalStore)(_sharedUi.subscribeFloatingTools,isBarOpen,isBarOpen);const T=(0,_react.useSyncExternalStore)(_armedPoint.subscribePickedPoint,_armedPoint.getPickedPointId,_armedPoint.getPickedPointId);const j=d?(0,_armedPoint.resolveArmedPoint)(t,T)?.id:void 0;const m=(0,_react.useRef)({});const[v,S]=(0,_react.useState)(null);const g=e=>{S(null);(0,_TimeMachineFloatingTool.openTimeMachineFloatingTool)(e);u.minimize()};const f=u.search.trim().toLowerCase();const p=f?t.filter(e=>e.name.toLowerCase().includes(f)):t;const b=t.filter(e=>!e.safety).length>=c;const _=i!==null||b;const M=e=>{if(i)return;if(e.baseline){(0,_confirm.confirmDestructive)("Restore fresh install?","This wipes all app storage and reloads the app.","Wipe & reload",()=>void _timeMachineStore.timeMachineStore.restore(e.id,"reload"));return}const w=(m.current[e.id]??0)+1;m.current[e.id]=w;if(w>=2&&!d)S(e.id);void _timeMachineStore.timeMachineStore.restore(e.id,"live").then(x=>{const P=Object.values(x.results).every(q=>q.ok);if(!P||x.willReload)return;u.minimize()})};const h=v&&!d?t.find(e=>e.id===v)??null:null;return(0,_jsxRuntime.jsxs)(_reactNative.ScrollView,{style:styles.fill,contentContainerStyle:[styles.content,{paddingBottom:y.bottom}],testID:"time-machine-scroll",keyboardShouldPersistTaps:"handled",children:[r&&(0,_RestoreOutcomeCard.restoreNeedsAttention)(r)?(0,_jsxRuntime.jsx)(_RestoreOutcomeCard.RestoreOutcomeCard,{outcome:r}):null,n?(0,_jsxRuntime.jsx)(_UndoDeleteBar.UndoDeleteBar,{name:n.stored.meta.name,at:n.at,onUndo:()=>void _timeMachineStore.timeMachineStore.undoDelete(),onExpire:()=>_timeMachineStore.timeMachineStore.clearRecentlyDeleted()}):null,(0,_jsxRuntime.jsx)(_reactNative.View,{children:(0,_jsxRuntime.jsx)(_CaptureBar.CaptureBar,{disabled:_,busy:i==="capture",onCapture:e=>void _timeMachineStore.timeMachineStore.capture(e)})}),b?(0,_jsxRuntime.jsxs)(_primitives.Footnote,{tone:"warning",testID:"time-machine-limit",children:["Free plan keeps ",c," restore point",c===1?"":"s",". Upgrade to Pro for unlimited snapshots."]}):null,(0,_jsxRuntime.jsx)(_primitives.SectionLabel,{children:"Sources"}),(0,_jsxRuntime.jsx)(_SourcesStrip.SourcesStrip,{sources:o,onToggle:a?void 0:_sourceSettings.setSourceEnabled}),a?null:(0,_jsxRuntime.jsx)(_primitives.Footnote,{testID:"time-machine-sources-hint",children:"Switch a source off to leave it out of every capture and restore."}),(0,_jsxRuntime.jsx)(_primitives.SectionLabel,{children:"Restore Points"}),h?(0,_jsxRuntime.jsxs)(_reactNative.View,{style:styles.barHint,testID:"time-machine-bar-hint",children:[(0,_jsxRuntime.jsxs)(_primitives.Footnote,{children:['Restoring "',h.name,'" a lot? Put it on the floating action bar and restore it with one tap.']}),(0,_jsxRuntime.jsx)(_reactNative.TouchableOpacity,{onPress:()=>g(h.id),accessibilityRole:"button",testID:"time-machine-bar-hint-pin",hitSlop:{top:6,bottom:6,left:6,right:6},children:(0,_jsxRuntime.jsx)(_reactNative.Text,{style:styles.barHintAction,children:"Open the action bar"})})]}):null,(0,_jsxRuntime.jsxs)(_primitives.Group,{children:[p.map(e=>(0,_jsxRuntime.jsx)(_SnapshotRow.SnapshotRow,{meta:e,busy:i!==null,armed:e.id===j,onOpen:()=>s(e),onRestore:()=>M(e),onDelete:()=>void _timeMachineStore.timeMachineStore.delete(e.id),onDuplicate:()=>void _timeMachineStore.timeMachineStore.duplicate(e.id),onArm:()=>g(e.id)},e.id)),p.length===0?(0,_jsxRuntime.jsx)(_sharedUi.ToolEmptyState,{testID:"time-machine-empty",...!l?{otto:"loading",title:"Loading restore points\u2026",message:"Reading the vault off disk."}:t.length>0?{otto:"sad",title:"No restore point matches that name.",message:`Clear the search to see all ${t.length}.`}:{otto:"rewind",title:"No restore points yet",message:"Set up the state you want to come back to, then capture it."}}):null]}),p.length>0?(0,_jsxRuntime.jsx)(_primitives.Footnote,{testID:"time-machine-swipe-hint",children:"Swipe a restore point to copy or delete it."}):null,(0,_jsxRuntime.jsx)(_reactNative.View,{style:styles.spacer}),(0,_jsxRuntime.jsx)(_primitives.Group,{children:(0,_jsxRuntime.jsx)(_WipeAllRow.WipeAllRow,{disabled:i!==null,onWipe:()=>(0,_confirm.confirmDestructive)("Wipe all app state?","This deletes all app storage and reloads the app \u2014 like a fresh install.","Wipe & reload",()=>void _timeMachineStore.timeMachineStore.wipeAll())})}),(0,_jsxRuntime.jsx)(_primitives.Footnote,{centered:true,children:"Deletes all app storage and reloads \u2014 like a fresh install."})]})}const styles=_reactNative.StyleSheet.create({barHint:{marginHorizontal:_tmTheme.tm.gutter,marginBottom:8},barHintAction:{color:_tmTheme.tm.color.accent,fontSize:_tmTheme.tm.font.footnote,fontWeight:"600",paddingHorizontal:_tmTheme.tm.textInset,paddingTop:2},fill:{flex:1,backgroundColor:"transparent"},content:{paddingTop:14},empty:{color:_tmTheme.tm.color.labelSecondary,fontSize:_tmTheme.tm.font.footnote,lineHeight:_tmTheme.tm.font.footnote*1.4,paddingHorizontal:_tmTheme.tm.textInset,paddingVertical:16},spacer:{height:24}});
1
+ "use strict";Object.defineProperty(exports,"__esModule",{value:true});exports.TimeMachineBody=TimeMachineBody;var _react=require("react");var _reactNative=require("react-native");var _sharedUi=require("@buoy-gg/shared-ui");var _core=require("@buoy-gg/core");var _useTimeMachine=require("../hooks/useTimeMachine");var _timeMachineStore=require("../store/timeMachineStore");var _primitives=require("../ui/primitives");var _tmTheme=require("../ui/tmTheme");var _sources=require("./sources");var _confirm=require("./confirm");var _CaptureBar=require("./list/CaptureBar");var _RestoreOutcomeCard=require("./list/RestoreOutcomeCard");var _SnapshotRow=require("./list/SnapshotRow");var _UndoDeleteBar=require("./list/UndoDeleteBar");var _SourcesStrip=require("./list/SourcesStrip");var _WipeAllRow=require("./list/WipeAllRow");var _PreviewFlow=require("./preview/PreviewFlow");var _TimeMachineFloatingTool=require("./floating/TimeMachineFloatingTool");var _armedPoint=require("./floating/armedPoint");var _sourceSettings=require("../store/sourceSettings");var _jsxRuntime=require("react/jsx-runtime");const isBarOpen=()=>(0,_sharedUi.getFloatingTools)().some(o=>o.id===_TimeMachineFloatingTool.TIME_MACHINE_FLOATING_TOOL_ID);function TimeMachineBody(){const[o,s]=(0,_react.useState)({kind:"list"});const{snapshots:t,busy:l,preview:i}=(0,_useTimeMachine.useTimeMachineState)();const r=(0,_sources.useSourceStatuses)();const n=()=>{_timeMachineStore.timeMachineStore.clearPreview();s({kind:"list"})};if(o.kind==="preview"&&i)return(0,_jsxRuntime.jsx)(_PreviewFlow.PreviewScreen,{preview:i,snapshots:t,busy:l!==null,onClose:n});return(0,_jsxRuntime.jsx)(RestorePointList,{sources:r,onOpenPreview:a=>{void _timeMachineStore.timeMachineStore.buildPreview({snapshotId:a.id});s({kind:"preview"})}})}function RestorePointList({sources:o,onOpenPreview:s}){const{snapshots:t,hasLoaded:l,busy:i,lastOutcome:r,recentlyDeleted:n,remoteProviders:a}=(0,_useTimeMachine.useTimeMachineState)();const c=(0,_sharedUi.useLimit)("timeMachine.snapshots");const u=(0,_core.useToolHost)();const w=(0,_sharedUi.useSafeAreaInsets)({minBottom:16});const d=(0,_react.useSyncExternalStore)(_sharedUi.subscribeFloatingTools,isBarOpen,isBarOpen);const y=(0,_react.useSyncExternalStore)(_armedPoint.subscribePickedPoint,_armedPoint.getPickedPointId,_armedPoint.getPickedPointId);const T=d?(0,_armedPoint.resolveArmedPoint)(t,y)?.id:void 0;const m=(0,_react.useRef)({});const[v,S]=(0,_react.useState)(null);const g=e=>{S(null);(0,_TimeMachineFloatingTool.openTimeMachineFloatingTool)(e);u.minimize()};const f=u.search.trim().toLowerCase();const h=f?t.filter(e=>e.name.toLowerCase().includes(f)):t;const b=t.filter(e=>!e.safety).length>=c;const j=i!==null||b;const _=e=>{if(i)return;if(e.baseline){(0,_confirm.confirmDestructive)("Restore fresh install?","This wipes all app storage and reloads the app.","Wipe & reload",()=>void _timeMachineStore.timeMachineStore.restore(e.id,"reload"));return}const x=(m.current[e.id]??0)+1;m.current[e.id]=x;if(x>=2&&!d)S(e.id);void _timeMachineStore.timeMachineStore.restore(e.id,"live").then(M=>{if((0,_timeMachineStore.shouldDockAfterRestore)(M))u.minimize()})};const p=v&&!d?t.find(e=>e.id===v)??null:null;return(0,_jsxRuntime.jsxs)(_reactNative.ScrollView,{style:styles.fill,contentContainerStyle:[styles.content,{paddingBottom:w.bottom}],testID:"time-machine-scroll",keyboardShouldPersistTaps:"handled",children:[r&&(0,_RestoreOutcomeCard.restoreNeedsAttention)(r)?(0,_jsxRuntime.jsx)(_RestoreOutcomeCard.RestoreOutcomeCard,{outcome:r}):null,n?(0,_jsxRuntime.jsx)(_UndoDeleteBar.UndoDeleteBar,{name:n.stored.meta.name,at:n.at,onUndo:()=>void _timeMachineStore.timeMachineStore.undoDelete(),onExpire:()=>_timeMachineStore.timeMachineStore.clearRecentlyDeleted()}):null,(0,_jsxRuntime.jsx)(_reactNative.View,{children:(0,_jsxRuntime.jsx)(_CaptureBar.CaptureBar,{disabled:j,busy:i==="capture",onCapture:e=>void _timeMachineStore.timeMachineStore.capture(e)})}),b?(0,_jsxRuntime.jsxs)(_primitives.Footnote,{tone:"warning",testID:"time-machine-limit",children:["Free plan keeps ",c," restore point",c===1?"":"s",". Upgrade to Pro for unlimited snapshots."]}):null,(0,_jsxRuntime.jsx)(_primitives.SectionLabel,{children:"Sources"}),(0,_jsxRuntime.jsx)(_SourcesStrip.SourcesStrip,{sources:o,onToggle:a?void 0:_sourceSettings.setSourceEnabled}),a?null:(0,_jsxRuntime.jsx)(_primitives.Footnote,{testID:"time-machine-sources-hint",children:"Switch a source off to leave it out of every capture and restore."}),(0,_jsxRuntime.jsx)(_primitives.SectionLabel,{children:"Restore Points"}),p?(0,_jsxRuntime.jsxs)(_reactNative.View,{style:styles.barHint,testID:"time-machine-bar-hint",children:[(0,_jsxRuntime.jsxs)(_primitives.Footnote,{children:['Restoring "',p.name,'" a lot? Put it on the floating action bar and restore it with one tap.']}),(0,_jsxRuntime.jsx)(_reactNative.TouchableOpacity,{onPress:()=>g(p.id),accessibilityRole:"button",testID:"time-machine-bar-hint-pin",hitSlop:{top:6,bottom:6,left:6,right:6},children:(0,_jsxRuntime.jsx)(_reactNative.Text,{style:styles.barHintAction,children:"Open the action bar"})})]}):null,(0,_jsxRuntime.jsxs)(_primitives.Group,{children:[h.map(e=>(0,_jsxRuntime.jsx)(_SnapshotRow.SnapshotRow,{meta:e,busy:i!==null,armed:e.id===T,onOpen:()=>s(e),onRestore:()=>_(e),onDelete:()=>void _timeMachineStore.timeMachineStore.delete(e.id),onDuplicate:()=>void _timeMachineStore.timeMachineStore.duplicate(e.id),onArm:()=>g(e.id)},e.id)),h.length===0?(0,_jsxRuntime.jsx)(_sharedUi.ToolEmptyState,{testID:"time-machine-empty",...!l?{otto:"loading",title:"Loading restore points\u2026",message:"Reading the vault off disk."}:t.length>0?{otto:"sad",title:"No restore point matches that name.",message:`Clear the search to see all ${t.length}.`}:{otto:"rewind",title:"No restore points yet",message:"Set up the state you want to come back to, then capture it."}}):null]}),h.length>0?(0,_jsxRuntime.jsx)(_primitives.Footnote,{testID:"time-machine-swipe-hint",children:"Swipe a restore point to copy or delete it."}):null,(0,_jsxRuntime.jsx)(_reactNative.View,{style:styles.spacer}),(0,_jsxRuntime.jsx)(_primitives.Group,{children:(0,_jsxRuntime.jsx)(_WipeAllRow.WipeAllRow,{disabled:i!==null,onWipe:()=>(0,_confirm.confirmDestructive)("Wipe all app state?","This deletes all app storage and reloads the app \u2014 like a fresh install.","Wipe & reload",()=>void _timeMachineStore.timeMachineStore.wipeAll())})}),(0,_jsxRuntime.jsx)(_primitives.Footnote,{centered:true,children:"Deletes all app storage and reloads \u2014 like a fresh install."})]})}const styles=_reactNative.StyleSheet.create({barHint:{marginHorizontal:_tmTheme.tm.gutter,marginBottom:8},barHintAction:{color:_tmTheme.tm.color.accent,fontSize:_tmTheme.tm.font.footnote,fontWeight:"600",paddingHorizontal:_tmTheme.tm.textInset,paddingTop:2},fill:{flex:1,backgroundColor:"transparent"},content:{paddingTop:14},empty:{color:_tmTheme.tm.color.labelSecondary,fontSize:_tmTheme.tm.font.footnote,lineHeight:_tmTheme.tm.font.footnote*1.4,paddingHorizontal:_tmTheme.tm.textInset,paddingVertical:16},spacer:{height:24}});
@@ -1 +1 @@
1
- "use strict";Object.defineProperty(exports,"__esModule",{value:true});exports.RestoreOutcomeCard=RestoreOutcomeCard;exports.restoreNeedsAttention=restoreNeedsAttention;var _reactNative=require("react-native");var _sharedUi=require("@buoy-gg/shared-ui");var _tmTheme=require("../../ui/tmTheme");var _timeMachineStore=require("../../store/timeMachineStore");var _jsxRuntime=require("react/jsx-runtime");const HIT={top:10,bottom:10,left:10,right:10};function restoreNeedsAttention(e){if(Object.values(e.results).some(o=>!o.ok||o.skipped.length>0))return true;const t=e.route;return t?.status==="failed"||t?.status==="unavailable"}function ResultLine({glyph:e,text:t,ok:o,testID:s}){return(0,_jsxRuntime.jsxs)(_reactNative.Text,{style:[styles.line,{color:o?_tmTheme.tm.color.accent:_tmTheme.tm.color.warning}],numberOfLines:2,testID:s,children:[(0,_jsxRuntime.jsxs)(_reactNative.Text,{style:styles.glyph,children:[e," "]}),t]})}const ROUTE_TEST_ID="time-machine-outcome-route";function RouteResult({route:e}){if(e.status==="navigated")return(0,_jsxRuntime.jsx)(ResultLine,{glyph:"\u2713",ok:true,text:`route \u2014 ${e.href}`,testID:ROUTE_TEST_ID});if(e.status==="deferred")return(0,_jsxRuntime.jsx)(ResultLine,{glyph:"\u21BB",ok:true,text:`route \u2014 ${e.href} after reload`,testID:ROUTE_TEST_ID});return(0,_jsxRuntime.jsx)(ResultLine,{glyph:"\u2715",ok:false,text:`route \u2014 ${e.error??e.status}`,testID:ROUTE_TEST_ID})}function RestoreOutcomeCard({outcome:e}){const t=Object.entries(e.results);const o=e.mode==="reload"||e.willReload;return(0,_jsxRuntime.jsxs)(_reactNative.View,{style:styles.card,testID:"time-machine-outcome",children:[(0,_jsxRuntime.jsxs)(_reactNative.View,{style:styles.headerRow,children:[(0,_jsxRuntime.jsxs)(_reactNative.Text,{style:styles.title,numberOfLines:1,testID:"time-machine-outcome-title",children:["Restored \u201C",e.snapshotName,"\u201D",o?" \xB7 reloading":""]}),(0,_jsxRuntime.jsx)(_reactNative.TouchableOpacity,{onPress:()=>_timeMachineStore.timeMachineStore.clearLastOutcome(),hitSlop:HIT,accessibilityRole:"button",accessibilityLabel:"Dismiss restore result",testID:"time-machine-outcome-dismiss",children:(0,_jsxRuntime.jsx)(_sharedUi.X,{size:13,color:_tmTheme.tm.color.labelSecondary})})]}),t.length===0&&!e.route?(0,_jsxRuntime.jsx)(_reactNative.Text,{style:styles.empty,testID:"time-machine-outcome-empty",children:"No sources restored."}):null,e.route?(0,_jsxRuntime.jsx)(RouteResult,{route:e.route}):null,t.map(([s,r])=>(0,_jsxRuntime.jsxs)(_reactNative.View,{children:[(0,_jsxRuntime.jsx)(ResultLine,{testID:`time-machine-outcome-${s}`,glyph:r.ok?"\u2713":"\u2715",ok:r.ok,text:`${s} \u2014 applied ${r.applied}${r.skipped.length>0?`, skipped ${r.skipped.length}`:""}`}),r.skipped.slice(0,3).map(i=>(0,_jsxRuntime.jsxs)(_reactNative.Text,{style:styles.detail,numberOfLines:2,children:[i.id,": ",i.reason]},i.id)),r.warnings.slice(0,3).map(i=>(0,_jsxRuntime.jsxs)(_reactNative.Text,{style:styles.detail,numberOfLines:2,children:["\u26A0 ",i]},i))]},s))]})}const styles=_reactNative.StyleSheet.create({card:{marginHorizontal:_tmTheme.tm.gutter,marginTop:12,backgroundColor:_tmTheme.tm.color.group,borderRadius:_tmTheme.tm.radius.group,borderWidth:1,borderColor:_tmTheme.tm.color.groupBorder,padding:14,gap:4},headerRow:{flexDirection:"row",alignItems:"center",gap:10,marginBottom:2},title:{flex:1,color:_tmTheme.tm.color.label,fontSize:15,fontWeight:"600",letterSpacing:_tmTheme.tm.tracking.control},line:{fontSize:_tmTheme.tm.font.footnote,lineHeight:_tmTheme.tm.font.footnote*1.4},glyph:{fontWeight:"700"},detail:{color:_tmTheme.tm.color.labelTertiary,fontSize:_tmTheme.tm.font.mono,lineHeight:_tmTheme.tm.font.mono*1.4,paddingLeft:14},empty:{color:_tmTheme.tm.color.labelSecondary,fontSize:_tmTheme.tm.font.footnote}});
1
+ "use strict";Object.defineProperty(exports,"__esModule",{value:true});exports.RestoreOutcomeCard=RestoreOutcomeCard;Object.defineProperty(exports,"restoreNeedsAttention",{enumerable:true,get:function(){return _timeMachineStore.restoreNeedsAttention}});var _reactNative=require("react-native");var _sharedUi=require("@buoy-gg/shared-ui");var _tmTheme=require("../../ui/tmTheme");var _timeMachineStore=require("../../store/timeMachineStore");var _jsxRuntime=require("react/jsx-runtime");const HIT={top:10,bottom:10,left:10,right:10};function ResultLine({glyph:e,text:i,ok:n,testID:o}){return(0,_jsxRuntime.jsxs)(_reactNative.Text,{style:[styles.line,{color:n?_tmTheme.tm.color.accent:_tmTheme.tm.color.warning}],numberOfLines:2,testID:o,children:[(0,_jsxRuntime.jsxs)(_reactNative.Text,{style:styles.glyph,children:[e," "]}),i]})}const ROUTE_TEST_ID="time-machine-outcome-route";function RouteResult({route:e}){if(e.status==="navigated")return(0,_jsxRuntime.jsx)(ResultLine,{glyph:"\u2713",ok:true,text:`route \u2014 ${e.href}`,testID:ROUTE_TEST_ID});if(e.status==="deferred")return(0,_jsxRuntime.jsx)(ResultLine,{glyph:"\u21BB",ok:true,text:`route \u2014 ${e.href} after reload`,testID:ROUTE_TEST_ID});return(0,_jsxRuntime.jsx)(ResultLine,{glyph:"\u2715",ok:false,text:`route \u2014 ${e.error??e.status}`,testID:ROUTE_TEST_ID})}function RestoreOutcomeCard({outcome:e}){const i=Object.entries(e.results);const n=e.mode==="reload"||e.willReload;return(0,_jsxRuntime.jsxs)(_reactNative.View,{style:styles.card,testID:"time-machine-outcome",children:[(0,_jsxRuntime.jsxs)(_reactNative.View,{style:styles.headerRow,children:[(0,_jsxRuntime.jsxs)(_reactNative.Text,{style:styles.title,numberOfLines:1,testID:"time-machine-outcome-title",children:["Restored \u201C",e.snapshotName,"\u201D",n?" \xB7 reloading":""]}),(0,_jsxRuntime.jsx)(_reactNative.TouchableOpacity,{onPress:()=>_timeMachineStore.timeMachineStore.clearLastOutcome(),hitSlop:HIT,accessibilityRole:"button",accessibilityLabel:"Dismiss restore result",testID:"time-machine-outcome-dismiss",children:(0,_jsxRuntime.jsx)(_sharedUi.X,{size:13,color:_tmTheme.tm.color.labelSecondary})})]}),i.length===0&&!e.route?(0,_jsxRuntime.jsx)(_reactNative.Text,{style:styles.empty,testID:"time-machine-outcome-empty",children:"No sources restored."}):null,e.route?(0,_jsxRuntime.jsx)(RouteResult,{route:e.route}):null,i.map(([o,t])=>(0,_jsxRuntime.jsxs)(_reactNative.View,{children:[(0,_jsxRuntime.jsx)(ResultLine,{testID:`time-machine-outcome-${o}`,glyph:t.ok?"\u2713":"\u2715",ok:t.ok,text:`${o} \u2014 applied ${t.applied}${t.skipped.length>0?`, skipped ${t.skipped.length}`:""}`}),t.skipped.slice(0,3).map(r=>(0,_jsxRuntime.jsxs)(_reactNative.Text,{style:styles.detail,numberOfLines:2,children:[r.id,": ",r.reason]},r.id)),t.warnings.slice(0,3).map(r=>(0,_jsxRuntime.jsxs)(_reactNative.Text,{style:styles.detail,numberOfLines:2,children:["\u26A0 ",r]},r))]},o))]})}const styles=_reactNative.StyleSheet.create({card:{marginHorizontal:_tmTheme.tm.gutter,marginTop:12,backgroundColor:_tmTheme.tm.color.group,borderRadius:_tmTheme.tm.radius.group,borderWidth:1,borderColor:_tmTheme.tm.color.groupBorder,padding:14,gap:4},headerRow:{flexDirection:"row",alignItems:"center",gap:10,marginBottom:2},title:{flex:1,color:_tmTheme.tm.color.label,fontSize:15,fontWeight:"600",letterSpacing:_tmTheme.tm.tracking.control},line:{fontSize:_tmTheme.tm.font.footnote,lineHeight:_tmTheme.tm.font.footnote*1.4},glyph:{fontWeight:"700"},detail:{color:_tmTheme.tm.color.labelTertiary,fontSize:_tmTheme.tm.font.mono,lineHeight:_tmTheme.tm.font.mono*1.4,paddingLeft:14},empty:{color:_tmTheme.tm.color.labelSecondary,fontSize:_tmTheme.tm.font.footnote}});
@@ -1 +1 @@
1
- "use strict";Object.defineProperty(exports,"__esModule",{value:true});exports.deleteSnapshot=deleteSnapshot;exports.duplicateSnapshot=duplicateSnapshot;exports.loadIndex=loadIndex;exports.loadSnapshot=loadSnapshot;exports.markSnapshotRestored=markSnapshotRestored;exports.readSnapshot=readSnapshot;exports.renameSnapshot=renameSnapshot;exports.restoreDeletedSnapshot=restoreDeletedSnapshot;exports.saveSnapshot=saveSnapshot;exports.setSnapshotExclusions=setSnapshotExclusions;exports.setSnapshotRestoreRoute=setSnapshotRestoreRoute;exports.setSnapshotScope=setSnapshotScope;var _sharedUi=require("@buoy-gg/shared-ui");const INDEX_KEY="@react_buoy_time_machine:index";const SNAP_PREFIX="@react_buoy_time_machine:snap:";async function loadIndex(){try{const t=await _sharedUi.persistentStorage.getItem(INDEX_KEY);if(!t)return[];const e=JSON.parse(t);return Array.isArray(e)?e:[]}catch{return[]}}async function saveIndex(t){await _sharedUi.persistentStorage.setItem(INDEX_KEY,JSON.stringify(t))}async function saveSnapshot(t,e){const s=JSON.stringify(t);t.meta.sizeBytes=s.length;await _sharedUi.persistentStorage.setItem(SNAP_PREFIX+t.meta.id,JSON.stringify(t));const n=[t.meta,...e.filter(a=>a.id!==t.meta.id)];await saveIndex(n);return n}async function loadSnapshot(t){try{const e=await _sharedUi.persistentStorage.getItem(SNAP_PREFIX+t);return e?JSON.parse(e):null}catch{return null}}async function deleteSnapshot(t,e){await _sharedUi.persistentStorage.removeItem(SNAP_PREFIX+t);const s=e.filter(n=>n.id!==t);await saveIndex(s);return s}async function patchMeta(t,e,s){const n=o=>o.id===t?e(o):o;const a=s.map(n);await _sharedUi.persistentStorage.setItem(INDEX_KEY,JSON.stringify(a));const r=await loadSnapshot(t);if(r){r.meta=n(r.meta);await _sharedUi.persistentStorage.setItem(SNAP_PREFIX+t,JSON.stringify(r))}return a}function setSnapshotScope(t,e,s){return patchMeta(t,n=>{const a={...n};if(e&&e.length>0)a.scope=e;else delete a.scope;return a},s)}function setSnapshotExclusions(t,e,s){return patchMeta(t,n=>{const a={...n};delete a.scope;if(e&&e.length>0)a.excludedKeys=e;else delete a.excludedKeys;return a},s)}function setSnapshotRestoreRoute(t,e,s){return patchMeta(t,n=>({...n,restoreRoute:e}),s)}function markSnapshotRestored(t,e,s){return patchMeta(t,n=>({...n,lastRestoredAt:e}),s)}async function duplicateSnapshot(t,e,s){const n=await loadSnapshot(t);if(!n)return null;const a={meta:{...n.meta,id:`${n.meta.id}_copy_${Date.now().toString(36)}`,name:e,createdAt:Date.now(),lastRestoredAt:void 0},data:n.data};delete a.meta.lastRestoredAt;return{metas:await saveSnapshot(a,s),meta:a.meta}}async function readSnapshot(t){return loadSnapshot(t)}async function restoreDeletedSnapshot(t,e){return saveSnapshot(t,e)}async function renameSnapshot(t,e,s){const n=s.map(r=>r.id===t?{...r,name:e}:r);await saveIndex(n);const a=await loadSnapshot(t);if(a){a.meta.name=e;await _sharedUi.persistentStorage.setItem(SNAP_PREFIX+t,JSON.stringify(a))}return n}
1
+ "use strict";Object.defineProperty(exports,"__esModule",{value:true});exports.deleteSnapshot=deleteSnapshot;exports.duplicateSnapshot=duplicateSnapshot;exports.loadIndex=loadIndex;exports.loadSnapshot=loadSnapshot;exports.markSnapshotRestored=markSnapshotRestored;exports.readSnapshot=readSnapshot;exports.renameSnapshot=renameSnapshot;exports.restoreDeletedSnapshot=restoreDeletedSnapshot;exports.saveSnapshot=saveSnapshot;exports.setSnapshotExclusions=setSnapshotExclusions;exports.setSnapshotRestoreRoute=setSnapshotRestoreRoute;exports.setSnapshotScope=setSnapshotScope;var _sharedUi=require("@buoy-gg/shared-ui");const INDEX_KEY="@react_buoy_time_machine:index";const SNAP_PREFIX="@react_buoy_time_machine:snap:";async function loadIndex(){try{const t=await _sharedUi.persistentStorage.getItem(INDEX_KEY);if(!t)return[];const e=JSON.parse(t);return Array.isArray(e)?e:[]}catch{return[]}}async function saveIndex(t){await _sharedUi.persistentStorage.setItem(INDEX_KEY,JSON.stringify(t))}async function saveSnapshot(t,e){const s=JSON.stringify(t);t.meta.sizeBytes=s.length;await _sharedUi.persistentStorage.setItem(SNAP_PREFIX+t.meta.id,JSON.stringify(t));const n=[t.meta,...e.filter(a=>a.id!==t.meta.id)];await saveIndex(n);return n}async function loadSnapshot(t){try{const e=await _sharedUi.persistentStorage.getItem(SNAP_PREFIX+t);return e?JSON.parse(e):null}catch{return null}}async function deleteSnapshot(t,e){await _sharedUi.persistentStorage.removeItem(SNAP_PREFIX+t);const s=e.filter(n=>n.id!==t);await saveIndex(s);return s}async function patchMeta(t,e,s){const n=o=>o.id===t?e(o):o;const a=s.map(n);await _sharedUi.persistentStorage.setItem(INDEX_KEY,JSON.stringify(a));const r=await loadSnapshot(t);if(r){r.meta=n(r.meta);await _sharedUi.persistentStorage.setItem(SNAP_PREFIX+t,JSON.stringify(r))}return a}function setSnapshotScope(t,e,s){return patchMeta(t,n=>{const a={...n};if(e&&e.length>0)a.scope=e;else delete a.scope;return a},s)}function setSnapshotExclusions(t,e,s){return patchMeta(t,n=>{const a={...n};delete a.scope;if(e&&e.length>0)a.excludedKeys=e;else delete a.excludedKeys;return a},s)}function setSnapshotRestoreRoute(t,e,s){return patchMeta(t,n=>({...n,restoreRoute:e}),s)}function markSnapshotRestored(t,e,s){return patchMeta(t,n=>({...n,lastRestoredAt:e}),s)}async function duplicateSnapshot(t,e,s){const n=await loadSnapshot(t);if(!n)return null;const a={meta:{...n.meta,id:`${n.meta.id}_copy_${Date.now().toString(36)}`,name:e,createdAt:Date.now(),lastRestoredAt:void 0},data:n.data};delete a.meta.lastRestoredAt;delete a.meta.safety;return{metas:await saveSnapshot(a,s),meta:a.meta}}async function readSnapshot(t){return loadSnapshot(t)}async function restoreDeletedSnapshot(t,e){return saveSnapshot(t,e)}async function renameSnapshot(t,e,s){const n=s.map(r=>r.id===t?{...r,name:e}:r);await saveIndex(n);const a=await loadSnapshot(t);if(a){a.meta.name=e;await _sharedUi.persistentStorage.setItem(SNAP_PREFIX+t,JSON.stringify(a))}return n}
@@ -1 +1 @@
1
- "use strict";Object.defineProperty(exports,"__esModule",{value:true});exports.SAFETY_SNAPSHOT_NAME=exports.RESTORE_ORDER=void 0;exports.replaceTimeMachineFromSnapshot=replaceTimeMachineFromSnapshot;exports.setRemoteTimeMachineHandler=setRemoteTimeMachineHandler;exports.timeMachineStore=void 0;exports.willRestoreRoute=willRestoreRoute;var _sharedUi=require("@buoy-gg/shared-ui");var _dataViewer=require("@buoy-gg/shared-ui/dataViewer");var _snapshotVault=require("./snapshotVault");var _routeRestore=require("./routeRestore");var _sourceSettings=require("./sourceSettings");var _sourceIds=require("./sourceIds");const RESTORE_ORDER=exports.RESTORE_ORDER=["storage","redux","zustand","jotai","query"];function defaultSnapshotName(l){const e=new Date;const t=`${String(e.getHours()).padStart(2,"0")}:${String(e.getMinutes()).padStart(2,"0")}`;const s=l?l.pathname==="/"?"Home":l.pathname:null;return s?`${s} \xB7 ${t}`:`Snapshot \xB7 ${t}`}function dedupeName(l,e){const t=new Set(e.map(s=>s.name));if(!t.has(l))return l;for(let s=2;s<1e3;s++){const u=`${l} (${s})`;if(!t.has(u))return u}return l}function willRestoreRoute(l){return!!l.route&&(l.restoreRoute??true)}const SAFETY_SNAPSHOT_NAME=exports.SAFETY_SNAPSHOT_NAME="Before last restore";let remoteHandler=null;function skippedResult(l){return{ok:false,applied:0,skipped:[{id:"*",reason:l}],warnings:[]}}let idCounter=0;function nextId(){idCounter+=1;return`snap_${Date.now().toString(36)}_${idCounter.toString(36)}`}class TimeMachineStore{state={snapshots:[],hasLoaded:false,busy:null,lastOutcome:null,preview:null,remoteProviders:null,remoteRoute:null,recentlyDeleted:null};previewRunId=0;listeners=new Set;loadPromise=null;getState(){return this.state}subscribe=e=>{this.listeners.add(e);void this.ensureLoaded();return()=>{this.listeners.delete(e)}};setState(e){this.state={...this.state,...e};this.listeners.forEach(t=>{try{t()}catch{}})}ensureLoaded(){if(remoteHandler)return Promise.resolve();if(!this.loadPromise){this.loadPromise=(0,_snapshotVault.loadIndex)().then(e=>{if(remoteHandler)return;this.setState({snapshots:e,hasLoaded:true})})}return 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,s){if(remoteHandler){const u=await remoteHandler("capture",{name:e,sourceIds:t});return u.snapshot}await this.ensureLoaded();await(0,_sourceSettings.ensureSourceSettingsLoaded)();this.setState({busy:"capture"});try{const u=(0,_sharedUi.getStateSnapshotProviders)().filter(r=>r.status().canCapture&&(0,_sourceSettings.isSourceEnabled)(r.id)&&(!t||t.includes(r.id)));const i={};const a={};for(const r of u){try{const c=await r.capture();i[r.id]=(0,_sharedUi.superJsonSerialize)(c.data);a[r.id]={warnings:c.warnings}}catch(c){a[r.id]={warnings:[`capture failed: ${String(c)}`]}}}const o=(0,_sourceSettings.isSourceEnabled)(_sourceIds.ROUTE_SOURCE_ID)?(0,_routeRestore.captureCurrentRoute)():null;let h=this.state.snapshots;if(s?.safety){for(const r of h.filter(c=>c.safety)){h=await(0,_snapshotVault.deleteSnapshot)(r.id,h)}}const w={meta:{id:nextId(),name:s?.safety?SAFETY_SNAPSHOT_NAME:dedupeName(e.trim()||defaultSnapshotName(o),h),createdAt:Date.now(),sizeBytes:0,...o?{route:o}:{},...s?.safety?{safety:true}:{},sources:a},data:i};const p=await(0,_snapshotVault.saveSnapshot)(w,h);this.setState({snapshots:p});return w.meta}finally{this.setState({busy:null})}}async captureBaseline(){if(remoteHandler){const s=await remoteHandler("captureBaseline",{});return s.snapshot}await this.ensureLoaded();await(0,_sourceSettings.ensureSourceSettingsLoaded)();const e={meta:{id:nextId(),name:"Fresh install",createdAt:Date.now(),sizeBytes:0,baseline:true,sources:{}},data:{}};const t=await(0,_snapshotVault.saveSnapshot)(e,this.state.snapshots);this.setState({snapshots:t});return e.meta}async restore(e,t,s,u){if(remoteHandler){const a=await remoteHandler("restore",{id:e,mode:t,excludeKeys:s,restoreRoute:u?.restoreRoute});this.setState({lastOutcome:a});return a}await this.ensureLoaded();await(0,_sourceSettings.ensureSourceSettingsLoaded)();let i;if(u?.safetyCapture&&!this.state.snapshots.find(a=>a.id===e)?.safety){i=(await this.capture(SAFETY_SNAPSHOT_NAME,void 0,{safety:true})).id}this.setState({busy:"restore"});try{const a=await(0,_snapshotVault.loadSnapshot)(e);if(!a)throw new Error(`No snapshot with id "${e}"`);const o={snapshotId:e,snapshotName:a.meta.name,mode:t,at:Date.now(),willReload:false,results:{},...i?{safetySnapshotId:i}:{}};if(a.meta.baseline){for(const n of(0,_sharedUi.getStateSnapshotProviders)()){if(n.clear){try{o.results[n.id]=await n.clear()}catch(d){o.results[n.id]=skippedResult(String(d))}}}o.willReload=this.scheduleReload("buoy time-machine baseline");this.setState({lastOutcome:o});return o}const h=[...RESTORE_ORDER.filter(n=>n in a.data),...Object.keys(a.data).filter(n=>!RESTORE_ORDER.includes(n))];const w=n=>{const d=new Map;for(const S of n){const m=S.indexOf("::");if(m<=0)continue;const g=S.slice(0,m);const R=S.slice(m+2);const v=d.get(g)??[];v.push(R);d.set(g,v)}return d};const p=s??a.meta.excludedKeys??[];const r=w(p);const c=!s&&a.meta.scope?.length?w(a.meta.scope):null;const f=(0,_sourceSettings.isSourceEnabled)(_sourceIds.ROUTE_SOURCE_ID)&&(u?.restoreRoute??willRestoreRoute(a.meta));if(t==="reload"){if(a.data.storage&&(0,_sourceSettings.isSourceEnabled)("storage")&&(!c||c.has("storage"))){o.results.storage=await this.restoreSource("storage",a.data.storage,r.get("storage"),c?.get("storage"))}if(f){const n=a.meta.route;try{await(0,_routeRestore.savePendingRoute)(n,a.meta.name);o.route={...n,status:"deferred"}}catch(d){o.route={...n,status:"failed",error:String(d)}}}o.willReload=this.scheduleReload("buoy time-machine restore");this.setState({lastOutcome:o,snapshots:await(0,_snapshotVault.markSnapshotRestored)(e,o.at,this.state.snapshots)});return o}for(const n of h){if(c&&!c.has(n))continue;if(!(0,_sourceSettings.isSourceEnabled)(n)){o.results[n]={ok:true,applied:0,skipped:[],warnings:["Switched off in Sources; left as it is"]};continue}o.results[n]=await this.restoreSource(n,a.data[n],r.get(n),c?.get(n))}if(f){o.route=(0,_routeRestore.navigateToRoute)(a.meta.route)}this.setState({lastOutcome:o,snapshots:await(0,_snapshotVault.markSnapshotRestored)(e,o.at,this.state.snapshots)});return o}finally{this.setState({busy:null})}}async restoreSource(e,t,s,u){const i=(0,_sharedUi.getStateSnapshotProvider)(e);if(!i){return skippedResult("provider not available (package missing or not initialized)")}const a=i.status();if(!a.canRestore){return skippedResult(a.detail??"restore unavailable")}try{const o=s?.length||u?.length?{...s?.length?{excludeKeys:s}:{},...u?.length?{includeKeys:u}:{}}:void 0;return await i.restore((0,_sharedUi.superJsonDeserialize)(t),o)}catch(o){return skippedResult(String(o))}}scheduleReload(e){try{(0,_sharedUi.scheduleReloadApp)({reason:e});return true}catch{return false}}async delete(e){if(remoteHandler){await remoteHandler("delete",{id:e});return}await this.ensureLoaded();await(0,_sourceSettings.ensureSourceSettingsLoaded)();const t=await(0,_snapshotVault.readSnapshot)(e);const s=await(0,_snapshotVault.deleteSnapshot)(e,this.state.snapshots);this.setState({snapshots:s,recentlyDeleted:t?{stored:t,at:Date.now()}:null})}async undoDelete(){const e=this.state.recentlyDeleted;if(!e)return;const t=await(0,_snapshotVault.restoreDeletedSnapshot)(e.stored,this.state.snapshots);this.setState({snapshots:t,recentlyDeleted:null})}clearRecentlyDeleted(){if(this.state.recentlyDeleted)this.setState({recentlyDeleted:null})}async setRestoreRoute(e,t){if(remoteHandler){await remoteHandler("setRestoreRoute",{id:e,restoreRoute:t});return}await this.ensureLoaded();await(0,_sourceSettings.ensureSourceSettingsLoaded)();const s=await(0,_snapshotVault.setSnapshotRestoreRoute)(e,t,this.state.snapshots);this.setState({snapshots:s})}async duplicate(e){if(remoteHandler){const u=await remoteHandler("duplicate",{id:e});return u?.snapshot??null}await this.ensureLoaded();await(0,_sourceSettings.ensureSourceSettingsLoaded)();const t=this.state.snapshots.find(u=>u.id===e);if(!t)return null;const s=await(0,_snapshotVault.duplicateSnapshot)(e,`${t.name} copy`,this.state.snapshots);if(!s)return null;this.setState({snapshots:s.metas});return s.meta}async rename(e,t){if(remoteHandler){await remoteHandler("rename",{id:e,name:t});return}await this.ensureLoaded();await(0,_sourceSettings.ensureSourceSettingsLoaded)();const s=await(0,_snapshotVault.renameSnapshot)(e,t,this.state.snapshots);this.setState({snapshots:s})}async setScope(e,t){if(remoteHandler){await remoteHandler("setScope",{id:e,scope:t});return}await this.ensureLoaded();await(0,_sourceSettings.ensureSourceSettingsLoaded)();const s=await(0,_snapshotVault.setSnapshotScope)(e,t,this.state.snapshots);this.setState({snapshots:s})}async setExclusions(e,t){if(remoteHandler){await remoteHandler("setExclusions",{id:e,excludedKeys:t});return}await this.ensureLoaded();await(0,_sourceSettings.ensureSourceSettingsLoaded)();const s=await(0,_snapshotVault.setSnapshotExclusions)(e,t,this.state.snapshots);this.setState({snapshots:s})}clearLastOutcome(){this.setState({lastOutcome:null})}async wipeAll(){if(remoteHandler){const e=await remoteHandler("wipeAll",{});this.setState({lastOutcome:e});return e}this.setState({busy:"restore"});try{const e={snapshotId:"wipe-all",snapshotName:"Wipe all",mode:"reload",at:Date.now(),willReload:false,results:{}};for(const t of(0,_sharedUi.getStateSnapshotProviders)()){if(t.clear){try{e.results[t.id]=await t.clear()}catch(s){e.results[t.id]=skippedResult(String(s))}}}e.willReload=this.scheduleReload("buoy time-machine wipe all");this.setState({lastOutcome:e});return e}finally{this.setState({busy:null})}}clearPreview(){this.previewRunId+=1;this.setState({preview:null})}async buildPreview(e,t="current"){if(remoteHandler){const i=++this.previewRunId;this.setState({preview:{left:t,right:e,building:true,builtAt:Date.now(),sources:[]}});try{const a=await remoteHandler("preview",{id:e==="current"?void 0:e.snapshotId,compareTo:t==="current"?void 0:t.snapshotId});if(i!==this.previewRunId)return;this.setState({preview:{left:t,right:e,building:false,builtAt:Date.now(),sources:a.sources??[]}})}catch(a){if(i!==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(0,_sourceSettings.ensureSourceSettingsLoaded)();const s=++this.previewRunId;this.setState({preview:{left:t,right:e,building:true,builtAt:Date.now(),sources:[]}});const u=async i=>{if(i==="current")return null;const a=await(0,_snapshotVault.loadSnapshot)(i.snapshotId);if(!a)throw new Error(`No snapshot with id "${i.snapshotId}"`);return a.data};try{if(e==="current")throw new Error("preview target must be a snapshot");const[i,a]=await Promise.all([u(t),(0,_snapshotVault.loadSnapshot)(e.snapshotId)]);if(s!==this.previewRunId)return;if(!a){throw new Error(`No snapshot with id "${e.snapshotId}"`)}const o=a.data;const h=a.meta.baseline===true;const w=h?(0,_sharedUi.getStateSnapshotProviders)().filter(r=>r.clear).map(r=>r.id):[...RESTORE_ORDER.filter(r=>r in o),...Object.keys(o).filter(r=>!RESTORE_ORDER.includes(r))];const p=[];for(const r of w){if(!(0,_sourceSettings.isSourceEnabled)(r))continue;await new Promise(n=>setTimeout(n,0));if(s!==this.previewRunId)return;const c=(0,_sharedUi.getStateSnapshotProvider)(r);const f=c?.label??r;try{const n=h?void 0:(0,_sharedUi.superJsonDeserialize)(o[r]);const d=i===null?void 0:r in i?(0,_sharedUi.superJsonDeserialize)(i[r]):void 0;let S;if(!c){S={items:[{key:r,label:f,verdict:"wont-apply",reason:"tool not installed \u2014 restore skips this source"}],notes:[]}}else if(c.previewItems){S=await c.previewItems(n,d)}else{const m=(0,_dataViewer.objectDiff)(d,n);S={items:[{key:r,label:f,verdict:m.equal?"unchanged":"changed",oldValue:d,newValue:n}],notes:m.truncated?["diff truncated (large value)"]:[]}}if(s!==this.previewRunId)return;p.push({id:r,label:f,...S})}catch(n){p.push({id:r,label:f,items:[],notes:[],error:String(n)})}this.setState({preview:{left:t,right:e,building:true,builtAt:Date.now(),sources:[...p]}})}if(s!==this.previewRunId)return;this.setState({preview:{left:t,right:e,building:false,builtAt:Date.now(),sources:p}})}catch(i){if(s!==this.previewRunId)return;this.setState({preview:{left:t,right:e,building:false,builtAt:Date.now(),sources:[{id:"error",label:"Preview",items:[],notes:[],error:String(i)}]}})}}}const timeMachineStore=exports.timeMachineStore=new TimeMachineStore;function setRemoteTimeMachineHandler(l){remoteHandler=l;if(!l){timeMachineStore.replaceFromSnapshot({})}}function replaceTimeMachineFromSnapshot(l){timeMachineStore.replaceFromSnapshot(l)}
1
+ "use strict";Object.defineProperty(exports,"__esModule",{value:true});exports.SAFETY_SNAPSHOT_NAME=exports.RESTORE_ORDER=void 0;exports.replaceTimeMachineFromSnapshot=replaceTimeMachineFromSnapshot;exports.restoreNeedsAttention=restoreNeedsAttention;exports.setRemoteTimeMachineHandler=setRemoteTimeMachineHandler;exports.shouldDockAfterRestore=shouldDockAfterRestore;exports.timeMachineStore=void 0;exports.willRestoreRoute=willRestoreRoute;var _sharedUi=require("@buoy-gg/shared-ui");var _dataViewer=require("@buoy-gg/shared-ui/dataViewer");var _snapshotVault=require("./snapshotVault");var _routeRestore=require("./routeRestore");var _sourceSettings=require("./sourceSettings");var _sourceIds=require("./sourceIds");const RESTORE_ORDER=exports.RESTORE_ORDER=["storage","redux","zustand","jotai","query"];function defaultSnapshotName(i){const e=new Date;const t=`${String(e.getHours()).padStart(2,"0")}:${String(e.getMinutes()).padStart(2,"0")}`;const s=i?i.pathname==="/"?"Home":i.pathname:null;return s?`${s} \xB7 ${t}`:`Snapshot \xB7 ${t}`}function dedupeName(i,e){const t=new Set(e.map(s=>s.name));if(!t.has(i))return i;for(let s=2;s<1e3;s++){const o=`${i} (${s})`;if(!t.has(o))return o}return i}function willRestoreRoute(i){return!!i.route&&(i.restoreRoute??true)}const SAFETY_SNAPSHOT_NAME=exports.SAFETY_SNAPSHOT_NAME="Before last restore";function restoreNeedsAttention(i){if(Object.values(i.results).some(t=>!t.ok||t.skipped.length>0))return true;const e=i.route;return e?.status==="failed"||e?.status==="unavailable"}function shouldDockAfterRestore(i){return!i.willReload&&!restoreNeedsAttention(i)}function switchedOffResult(){return{ok:true,applied:0,skipped:[],warnings:["Switched off in Sources; left as it is"]}}let remoteHandler=null;function skippedResult(i){return{ok:false,applied:0,skipped:[{id:"*",reason:i}],warnings:[]}}let idCounter=0;function nextId(){idCounter+=1;return`snap_${Date.now().toString(36)}_${idCounter.toString(36)}`}class TimeMachineStore{state={snapshots:[],hasLoaded:false,busy:null,lastOutcome:null,preview:null,remoteProviders:null,remoteRoute:null,recentlyDeleted:null};previewRunId=0;listeners=new Set;loadPromise=null;getState(){return this.state}subscribe=e=>{this.listeners.add(e);void this.ensureLoaded();return()=>{this.listeners.delete(e)}};setState(e){this.state={...this.state,...e};this.listeners.forEach(t=>{try{t()}catch{}})}ensureLoaded(){if(remoteHandler)return Promise.resolve();if(!this.loadPromise){this.loadPromise=(0,_snapshotVault.loadIndex)().then(e=>{if(remoteHandler)return;this.setState({snapshots:e,hasLoaded:true})})}return 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,s){if(remoteHandler){const o=await remoteHandler("capture",{name:e,sourceIds:t});return o.snapshot}await this.ensureLoaded();await(0,_sourceSettings.ensureSourceSettingsLoaded)();this.setState({busy:"capture"});try{const o=(0,_sharedUi.getStateSnapshotProviders)().filter(l=>l.status().canCapture&&(0,_sourceSettings.isSourceEnabled)(l.id)&&(!t||t.includes(l.id)));const c={};const a={};for(const l of o){try{const r=await l.capture();c[l.id]=(0,_sharedUi.superJsonSerialize)(r.data);a[l.id]={warnings:r.warnings}}catch(r){a[l.id]={warnings:[`capture failed: ${String(r)}`]}}}const n=(0,_sourceSettings.isSourceEnabled)(_sourceIds.ROUTE_SOURCE_ID)?(0,_routeRestore.captureCurrentRoute)():null;const p=this.state.snapshots;const h={meta:{id:nextId(),name:s?.safety?SAFETY_SNAPSHOT_NAME:dedupeName(e.trim()||defaultSnapshotName(n),p),createdAt:Date.now(),sizeBytes:0,...n?{route:n}:{},...s?.safety?{safety:true}:{},sources:a},data:c};let S=await(0,_snapshotVault.saveSnapshot)(h,p);if(s?.safety){for(const l of S.filter(r=>r.safety&&r.id!==h.meta.id)){S=await(0,_snapshotVault.deleteSnapshot)(l.id,S)}}this.setState({snapshots:S});return h.meta}finally{this.setState({busy:null})}}async captureBaseline(){if(remoteHandler){const s=await remoteHandler("captureBaseline",{});return s.snapshot}await this.ensureLoaded();await(0,_sourceSettings.ensureSourceSettingsLoaded)();const e={meta:{id:nextId(),name:"Fresh install",createdAt:Date.now(),sizeBytes:0,baseline:true,sources:{}},data:{}};const t=await(0,_snapshotVault.saveSnapshot)(e,this.state.snapshots);this.setState({snapshots:t});return e.meta}async restore(e,t,s,o){if(remoteHandler){const a=await remoteHandler("restore",{id:e,mode:t,excludeKeys:s,restoreRoute:o?.restoreRoute});this.setState({lastOutcome:a});return a}await this.ensureLoaded();await(0,_sourceSettings.ensureSourceSettingsLoaded)();let c;if(o?.safetyCapture&&!this.state.snapshots.find(a=>a.id===e)?.safety){c=(await this.capture(SAFETY_SNAPSHOT_NAME,void 0,{safety:true})).id}this.setState({busy:"restore"});try{const a=await(0,_snapshotVault.loadSnapshot)(e);if(!a)throw new Error(`No snapshot with id "${e}"`);const n={snapshotId:e,snapshotName:a.meta.name,mode:t,at:Date.now(),willReload:false,results:{},...c?{safetySnapshotId:c}:{}};if(a.meta.baseline){await this.clearEnabledSources(n);n.willReload=this.scheduleReload("buoy time-machine baseline");this.setState({lastOutcome:n});return n}const p=[...RESTORE_ORDER.filter(u=>u in a.data),...Object.keys(a.data).filter(u=>!RESTORE_ORDER.includes(u))];const h=u=>{const d=new Map;for(const m of u){const w=m.indexOf("::");if(w<=0)continue;const g=m.slice(0,w);const R=m.slice(w+2);const y=d.get(g)??[];y.push(R);d.set(g,y)}return d};const S=s??a.meta.excludedKeys??[];const l=h(S);const r=!s&&a.meta.scope?.length?h(a.meta.scope):null;const f=(0,_sourceSettings.isSourceEnabled)(_sourceIds.ROUTE_SOURCE_ID)&&(o?.restoreRoute??willRestoreRoute(a.meta));if(t==="reload"){if(a.data.storage&&(0,_sourceSettings.isSourceEnabled)("storage")&&(!r||r.has("storage"))){n.results.storage=await this.restoreSource("storage",a.data.storage,l.get("storage"),r?.get("storage"))}if(f){const u=a.meta.route;try{await(0,_routeRestore.savePendingRoute)(u,a.meta.name);n.route={...u,status:"deferred"}}catch(d){n.route={...u,status:"failed",error:String(d)}}}n.willReload=this.scheduleReload("buoy time-machine restore");this.setState({lastOutcome:n,snapshots:await(0,_snapshotVault.markSnapshotRestored)(e,n.at,this.state.snapshots)});return n}for(const u of p){if(r&&!r.has(u))continue;if(!(0,_sourceSettings.isSourceEnabled)(u)){n.results[u]=switchedOffResult();continue}n.results[u]=await this.restoreSource(u,a.data[u],l.get(u),r?.get(u))}if(f){n.route=(0,_routeRestore.navigateToRoute)(a.meta.route)}this.setState({lastOutcome:n,snapshots:await(0,_snapshotVault.markSnapshotRestored)(e,n.at,this.state.snapshots)});return n}finally{this.setState({busy:null})}}async restoreSource(e,t,s,o){const c=(0,_sharedUi.getStateSnapshotProvider)(e);if(!c){return skippedResult("provider not available (package missing or not initialized)")}const a=c.status();if(!a.canRestore){return skippedResult(a.detail??"restore unavailable")}try{const n=s?.length||o?.length?{...s?.length?{excludeKeys:s}:{},...o?.length?{includeKeys:o}:{}}:void 0;return await c.restore((0,_sharedUi.superJsonDeserialize)(t),n)}catch(n){return skippedResult(String(n))}}async clearEnabledSources(e){for(const t of(0,_sharedUi.getStateSnapshotProviders)()){if(!t.clear)continue;if(!(0,_sourceSettings.isSourceEnabled)(t.id)){e.results[t.id]=switchedOffResult();continue}try{e.results[t.id]=await t.clear()}catch(s){e.results[t.id]=skippedResult(String(s))}}}reloadApp(){if(this.state.busy==="restore")return false;return this.scheduleReload("buoy time-machine reload app")}scheduleReload(e){try{(0,_sharedUi.scheduleReloadApp)({reason:e});return true}catch{return false}}async delete(e){if(remoteHandler){await remoteHandler("delete",{id:e});return}await this.ensureLoaded();await(0,_sourceSettings.ensureSourceSettingsLoaded)();const t=await(0,_snapshotVault.readSnapshot)(e);const s=await(0,_snapshotVault.deleteSnapshot)(e,this.state.snapshots);this.setState({snapshots:s,recentlyDeleted:t?{stored:t,at:Date.now()}:null})}async undoDelete(){const e=this.state.recentlyDeleted;if(!e)return;const t=await(0,_snapshotVault.restoreDeletedSnapshot)(e.stored,this.state.snapshots);this.setState({snapshots:t,recentlyDeleted:null})}clearRecentlyDeleted(){if(this.state.recentlyDeleted)this.setState({recentlyDeleted:null})}async setRestoreRoute(e,t){if(remoteHandler){await remoteHandler("setRestoreRoute",{id:e,restoreRoute:t});return}await this.ensureLoaded();await(0,_sourceSettings.ensureSourceSettingsLoaded)();const s=await(0,_snapshotVault.setSnapshotRestoreRoute)(e,t,this.state.snapshots);this.setState({snapshots:s})}async duplicate(e){if(remoteHandler){const o=await remoteHandler("duplicate",{id:e});return o?.snapshot??null}await this.ensureLoaded();await(0,_sourceSettings.ensureSourceSettingsLoaded)();const t=this.state.snapshots.find(o=>o.id===e);if(!t)return null;const s=await(0,_snapshotVault.duplicateSnapshot)(e,`${t.name} copy`,this.state.snapshots);if(!s)return null;this.setState({snapshots:s.metas});return s.meta}async rename(e,t){if(remoteHandler){await remoteHandler("rename",{id:e,name:t});return}await this.ensureLoaded();await(0,_sourceSettings.ensureSourceSettingsLoaded)();const s=await(0,_snapshotVault.renameSnapshot)(e,t,this.state.snapshots);this.setState({snapshots:s})}async setScope(e,t){if(remoteHandler){await remoteHandler("setScope",{id:e,scope:t});return}await this.ensureLoaded();await(0,_sourceSettings.ensureSourceSettingsLoaded)();const s=await(0,_snapshotVault.setSnapshotScope)(e,t,this.state.snapshots);this.setState({snapshots:s})}async setExclusions(e,t){if(remoteHandler){await remoteHandler("setExclusions",{id:e,excludedKeys:t});return}await this.ensureLoaded();await(0,_sourceSettings.ensureSourceSettingsLoaded)();const s=await(0,_snapshotVault.setSnapshotExclusions)(e,t,this.state.snapshots);this.setState({snapshots:s})}clearLastOutcome(){this.setState({lastOutcome:null})}async wipeAll(){if(remoteHandler){const e=await remoteHandler("wipeAll",{});this.setState({lastOutcome:e});return e}await(0,_sourceSettings.ensureSourceSettingsLoaded)();this.setState({busy:"restore"});try{const e={snapshotId:"wipe-all",snapshotName:"Wipe all",mode:"reload",at:Date.now(),willReload:false,results:{}};await this.clearEnabledSources(e);e.willReload=this.scheduleReload("buoy time-machine wipe all");this.setState({lastOutcome:e});return e}finally{this.setState({busy:null})}}clearPreview(){this.previewRunId+=1;this.setState({preview:null})}async buildPreview(e,t="current"){if(remoteHandler){const o=++this.previewRunId;this.setState({preview:{left:t,right:e,building:true,builtAt:Date.now(),sources:[]}});try{const c=await remoteHandler("preview",{id:e==="current"?void 0:e.snapshotId,compareTo:t==="current"?void 0:t.snapshotId});if(o!==this.previewRunId)return;this.setState({preview:{left:t,right:e,building:false,builtAt:Date.now(),sources:c.sources??[]}})}catch(c){if(o!==this.previewRunId)return;this.setState({preview:{left:t,right:e,building:false,builtAt:Date.now(),sources:[{id:"error",label:"Preview",items:[],notes:[],error:String(c)}]}})}return}await this.ensureLoaded();await(0,_sourceSettings.ensureSourceSettingsLoaded)();const s=++this.previewRunId;await this.runPreview(e,t,o=>this.setState({preview:o}),()=>s===this.previewRunId)}async computePreview(e,t="current"){await this.ensureLoaded();await(0,_sourceSettings.ensureSourceSettingsLoaded)();let s=null;await this.runPreview(e,t,o=>{s=o},()=>true);if(!s)throw new Error("preview build produced no result");return s}async runPreview(e,t,s,o){s({left:t,right:e,building:true,builtAt:Date.now(),sources:[]});const c=async a=>{if(a==="current")return null;const n=await(0,_snapshotVault.loadSnapshot)(a.snapshotId);if(!n)throw new Error(`No snapshot with id "${a.snapshotId}"`);return n.data};try{if(e==="current")throw new Error("preview target must be a snapshot");const[a,n]=await Promise.all([c(t),(0,_snapshotVault.loadSnapshot)(e.snapshotId)]);if(!o())return;if(!n){throw new Error(`No snapshot with id "${e.snapshotId}"`)}const p=n.data;const h=n.meta.baseline===true;const S=h?(0,_sharedUi.getStateSnapshotProviders)().filter(r=>r.clear).map(r=>r.id):[...RESTORE_ORDER.filter(r=>r in p),...Object.keys(p).filter(r=>!RESTORE_ORDER.includes(r))];const l=[];for(const r of S){if(!(0,_sourceSettings.isSourceEnabled)(r))continue;await new Promise(d=>setTimeout(d,0));if(!o())return;const f=(0,_sharedUi.getStateSnapshotProvider)(r);const u=f?.label??r;try{const d=h?void 0:(0,_sharedUi.superJsonDeserialize)(p[r]);const m=a===null?void 0:r in a?(0,_sharedUi.superJsonDeserialize)(a[r]):void 0;let w;if(!f){w={items:[{key:r,label:u,verdict:"wont-apply",reason:"tool not installed \u2014 restore skips this source"}],notes:[]}}else if(f.previewItems){w=await f.previewItems(d,m)}else{const g=(0,_dataViewer.objectDiff)(m,d);w={items:[{key:r,label:u,verdict:g.equal?"unchanged":"changed",oldValue:m,newValue:d}],notes:g.truncated?["diff truncated (large value)"]:[]}}if(!o())return;l.push({id:r,label:u,...w})}catch(d){l.push({id:r,label:u,items:[],notes:[],error:String(d)})}s({left:t,right:e,building:true,builtAt:Date.now(),sources:[...l]})}if(!o())return;s({left:t,right:e,building:false,builtAt:Date.now(),sources:l})}catch(a){if(!o())return;s({left:t,right:e,building:false,builtAt:Date.now(),sources:[{id:"error",label:"Preview",items:[],notes:[],error:String(a)}]})}}}const timeMachineStore=exports.timeMachineStore=new TimeMachineStore;function setRemoteTimeMachineHandler(i){remoteHandler=i;if(!i){timeMachineStore.replaceFromSnapshot({})}}function replaceTimeMachineFromSnapshot(i){timeMachineStore.replaceFromSnapshot(i)}
@@ -1 +1 @@
1
- "use strict";Object.defineProperty(exports,"__esModule",{value:true});exports.timeMachineSyncAdapter=void 0;var _sharedUi=require("@buoy-gg/shared-ui");var _dataViewer=require("@buoy-gg/shared-ui/dataViewer");var _timeMachineStore=require("../store/timeMachineStore");var _snapshotVault=require("../store/snapshotVault");var _routeRestore=require("../store/routeRestore");var _sourceSettings=require("../store/sourceSettings");var _sourceIds=require("../store/sourceIds");function providerStatuses(){return(0,_sharedUi.getStateSnapshotProviders)().map(t=>{const e=t.status();return{id:t.id,label:t.label,canCapture:e.canCapture,canRestore:e.canRestore,detail:e.detail,enabled:(0,_sourceSettings.isSourceEnabled)(t.id)}})}function metadata(){const{snapshots:t,busy:e,lastOutcome:r}=_timeMachineStore.timeMachineStore.getState();const s=(0,_routeRestore.currentRoute)();return{snapshots:t,busy:e,lastOutcome:r,providers:providerStatuses(),route:{available:(0,_routeRestore.canNavigate)(),enabled:(0,_sourceSettings.isSourceEnabled)(_sourceIds.ROUTE_SOURCE_ID),...s?{current:s.href}:{}}}}const timeMachineSyncAdapter=exports.timeMachineSyncAdapter={version:2,getSnapshot:()=>metadata(),subscribe:t=>{const e=_timeMachineStore.timeMachineStore.subscribe(t);const r=(0,_sharedUi.subscribeToStateSnapshotProviders)(t);return()=>{e();r()}},actions:{list:()=>metadata(),capture:async t=>{const{name:e="",sourceIds:r}=t??{};const s=await _timeMachineStore.timeMachineStore.capture(e,r);return{captured:true,snapshot:s}},captureBaseline:async()=>{const t=await _timeMachineStore.timeMachineStore.captureBaseline();return{captured:true,snapshot:t}},wipeAll:async()=>await _timeMachineStore.timeMachineStore.wipeAll(),restore:async t=>{const{id:e,mode:r="live",excludeKeys:s,restoreRoute:a}=t??{};if(!e)throw new Error("restore requires a snapshot `id`");return await _timeMachineStore.timeMachineStore.restore(e,r,s,{restoreRoute:a})},delete:async t=>{const{id:e}=t??{};if(!e)throw new Error("delete requires a snapshot `id`");await _timeMachineStore.timeMachineStore.delete(e);return{deleted:true,id:e}},rename:async t=>{const{id:e,name:r}=t??{};if(!e||!r)throw new Error("rename requires `id` and `name`");await _timeMachineStore.timeMachineStore.rename(e,r);return{renamed:true,id:e,name:r}},setExclusions:async t=>{const{id:e,excludedKeys:r}=t??{};if(!e)throw new Error("setExclusions requires `id`");await _timeMachineStore.timeMachineStore.setExclusions(e,r??null);return{id:e,excluded:r?.length??0}},setRestoreRoute:async t=>{const{id:e,restoreRoute:r}=t??{};if(!e)throw new Error("setRestoreRoute requires `id`");await _timeMachineStore.timeMachineStore.setRestoreRoute(e,r!==false);return{id:e,restoreRoute:r!==false}},duplicate:async t=>{const{id:e}=t??{};if(!e)throw new Error("duplicate requires `id`");const r=await _timeMachineStore.timeMachineStore.duplicate(e);if(!r)throw new Error(`No snapshot with id "${e}"`);return{snapshot:r}},setScope:async t=>{const{id:e,scope:r}=t??{};if(!e)throw new Error("setScope requires a snapshot `id`");await _timeMachineStore.timeMachineStore.setScope(e,r??null);return{scoped:true,id:e,count:r?.length??0}},preview:async t=>{const{id:e,compareTo:r}=t??{};if(!e)throw new Error("preview requires a snapshot `id`");const s={snapshotId:e};const a=r?{snapshotId:r}:"current";await _timeMachineStore.timeMachineStore.buildPreview(s,a);const o=_timeMachineStore.timeMachineStore.getState().preview;if(!o)throw new Error("preview build produced no result");const i=4*1024;return{left:a,right:s,builtAt:o.builtAt,sources:o.sources.map(u=>({...u,items:u.items.map(n=>{const c=n.oldValue!==void 0&&(0,_dataViewer.jsonLikelyLargerThan)(n.oldValue,i);const d=n.newValue!==void 0&&(0,_dataViewer.jsonLikelyLargerThan)(n.newValue,i);return{...n,oldValue:c?void 0:n.oldValue,newValue:d?void 0:n.newValue,...c||d?{valueOmitted:true}:{}}})}))}},inspect:async t=>{const{id:e,sourceId:r}=t??{};if(!e||!r){throw new Error("inspect requires `id` and `sourceId`")}const s=await(0,_snapshotVault.loadSnapshot)(e);if(!s)throw new Error(`No snapshot with id "${e}"`);const a=s.data[r];if(!a){throw new Error(`Snapshot "${e}" has no "${r}" source`)}return{id:e,sourceId:r,warnings:s.meta.sources[r]?.warnings??[],data:(0,_sharedUi.superJsonDeserialize)(a)}}}};
1
+ "use strict";Object.defineProperty(exports,"__esModule",{value:true});exports.timeMachineSyncAdapter=void 0;var _sharedUi=require("@buoy-gg/shared-ui");var _dataViewer=require("@buoy-gg/shared-ui/dataViewer");var _timeMachineStore=require("../store/timeMachineStore");var _snapshotVault=require("../store/snapshotVault");var _routeRestore=require("../store/routeRestore");var _sourceSettings=require("../store/sourceSettings");var _sourceIds=require("../store/sourceIds");function providerStatuses(){return(0,_sharedUi.getStateSnapshotProviders)().map(t=>{const e=t.status();return{id:t.id,label:t.label,canCapture:e.canCapture,canRestore:e.canRestore,detail:e.detail,enabled:(0,_sourceSettings.isSourceEnabled)(t.id)}})}function metadata(){const{snapshots:t,busy:e,lastOutcome:r}=_timeMachineStore.timeMachineStore.getState();const s=(0,_routeRestore.currentRoute)();return{snapshots:t,busy:e,lastOutcome:r,providers:providerStatuses(),route:{available:(0,_routeRestore.canNavigate)(),enabled:(0,_sourceSettings.isSourceEnabled)(_sourceIds.ROUTE_SOURCE_ID),...s?{current:s.href}:{}}}}const timeMachineSyncAdapter=exports.timeMachineSyncAdapter={version:2,getSnapshot:()=>metadata(),subscribe:t=>{const e=_timeMachineStore.timeMachineStore.subscribe(t);const r=(0,_sharedUi.subscribeToStateSnapshotProviders)(t);return()=>{e();r()}},actions:{list:()=>metadata(),capture:async t=>{const{name:e="",sourceIds:r}=t??{};const s=await _timeMachineStore.timeMachineStore.capture(e,r);return{captured:true,snapshot:s}},captureBaseline:async()=>{const t=await _timeMachineStore.timeMachineStore.captureBaseline();return{captured:true,snapshot:t}},wipeAll:async()=>await _timeMachineStore.timeMachineStore.wipeAll(),restore:async t=>{const{id:e,mode:r="live",excludeKeys:s,restoreRoute:o}=t??{};if(!e)throw new Error("restore requires a snapshot `id`");return await _timeMachineStore.timeMachineStore.restore(e,r,s,{restoreRoute:o})},delete:async t=>{const{id:e}=t??{};if(!e)throw new Error("delete requires a snapshot `id`");await _timeMachineStore.timeMachineStore.delete(e);return{deleted:true,id:e}},rename:async t=>{const{id:e,name:r}=t??{};if(!e||!r)throw new Error("rename requires `id` and `name`");await _timeMachineStore.timeMachineStore.rename(e,r);return{renamed:true,id:e,name:r}},setExclusions:async t=>{const{id:e,excludedKeys:r}=t??{};if(!e)throw new Error("setExclusions requires `id`");await _timeMachineStore.timeMachineStore.setExclusions(e,r??null);return{id:e,excluded:r?.length??0}},setRestoreRoute:async t=>{const{id:e,restoreRoute:r}=t??{};if(!e)throw new Error("setRestoreRoute requires `id`");if(typeof r!=="boolean"){throw new Error("setRestoreRoute requires `restoreRoute` (true or false)")}await _timeMachineStore.timeMachineStore.setRestoreRoute(e,r);return{id:e,restoreRoute:r}},duplicate:async t=>{const{id:e}=t??{};if(!e)throw new Error("duplicate requires `id`");const r=await _timeMachineStore.timeMachineStore.duplicate(e);if(!r)throw new Error(`No snapshot with id "${e}"`);return{snapshot:r}},setScope:async t=>{const{id:e,scope:r}=t??{};if(!e)throw new Error("setScope requires a snapshot `id`");await _timeMachineStore.timeMachineStore.setScope(e,r??null);return{scoped:true,id:e,count:r?.length??0}},preview:async t=>{const{id:e,compareTo:r}=t??{};if(!e)throw new Error("preview requires a snapshot `id`");const s={snapshotId:e};const o=r?{snapshotId:r}:"current";const n=await _timeMachineStore.timeMachineStore.computePreview(s,o);const i=4*1024;return{left:o,right:s,builtAt:n.builtAt,sources:n.sources.map(u=>({...u,items:u.items.map(a=>{const c=a.oldValue!==void 0&&(0,_dataViewer.jsonLikelyLargerThan)(a.oldValue,i);const d=a.newValue!==void 0&&(0,_dataViewer.jsonLikelyLargerThan)(a.newValue,i);return{...a,oldValue:c?void 0:a.oldValue,newValue:d?void 0:a.newValue,...c||d?{valueOmitted:true}:{}}})}))}},inspect:async t=>{const{id:e,sourceId:r}=t??{};if(!e||!r){throw new Error("inspect requires `id` and `sourceId`")}const s=await(0,_snapshotVault.loadSnapshot)(e);if(!s)throw new Error(`No snapshot with id "${e}"`);const o=s.data[r];if(!o){throw new Error(`Snapshot "${e}" has no "${r}" source`)}return{id:e,sourceId:r,warnings:s.meta.sources[r]?.warnings??[],data:(0,_sharedUi.superJsonDeserialize)(o)}}}};
@@ -1 +1 @@
1
- "use strict";import{StyleSheet as i,Text as a,TouchableOpacity as l}from"react-native";import{night as e,scheduleReloadApp as c}from"@buoy-gg/shared-ui";import{jsx as t}from"react/jsx-runtime";export function HeaderReloadButton(){const r=()=>{try{c({reason:"buoy time-machine reload app"})}catch{}};return t(l,{style:o.chip,onPress:r,accessibilityLabel:"Reload app",accessibilityHint:"Reloads the JavaScript bundle without restoring anything",accessibilityRole:"button",testID:"time-machine-reload-app",children:t(a,{style:o.label,children:"Reload app"})})}const o=i.create({chip:{height:32,paddingHorizontal:10,borderRadius:8,borderWidth:1,borderColor:e.color.border,backgroundColor:e.color.buttonSurface,alignItems:"center",justifyContent:"center"},label:{fontSize:11,fontWeight:"700",color:e.color.textSecondary}});
1
+ "use strict";import{StyleSheet as i,Text as a,TouchableOpacity as l}from"react-native";import{night as e}from"@buoy-gg/shared-ui";import{timeMachineStore as n}from"../store/timeMachineStore";import{jsx as t}from"react/jsx-runtime";export function HeaderReloadButton(){const r=()=>{n.reloadApp()};return t(l,{style:o.chip,onPress:r,accessibilityLabel:"Reload app",accessibilityHint:"Reloads the JavaScript bundle without restoring anything",accessibilityRole:"button",testID:"time-machine-reload-app",children:t(a,{style:o.label,children:"Reload app"})})}const o=i.create({chip:{height:32,paddingHorizontal:10,borderRadius:8,borderWidth:1,borderColor:e.color.border,backgroundColor:e.color.buttonSurface,alignItems:"center",justifyContent:"center"},label:{fontSize:11,fontWeight:"700",color:e.color.textSecondary}});
@@ -1 +1 @@
1
- "use strict";import{useRef as V,useState as O,useSyncExternalStore as L}from"react";import{ScrollView as G,StyleSheet as q,Text as $,TouchableOpacity as J,View as v}from"react-native";import{useSafeAreaInsets as K,useLimit as Q,ToolEmptyState as X,getFloatingTools as Y,subscribeFloatingTools as Z}from"@buoy-gg/shared-ui";import{useToolHost as ee}from"@buoy-gg/core";import{useTimeMachineState as x}from"../hooks/useTimeMachine";import{timeMachineStore as o}from"../store/timeMachineStore";import{Footnote as c,Group as C,SectionLabel as A}from"../ui/primitives";import{tm as r}from"../ui/tmTheme";import{useSourceStatuses as te}from"./sources";import{confirmDestructive as B}from"./confirm";import{CaptureBar as oe}from"./list/CaptureBar";import{RestoreOutcomeCard as ie,restoreNeedsAttention as ne}from"./list/RestoreOutcomeCard";import{SnapshotRow as re}from"./list/SnapshotRow";import{UndoDeleteBar as se}from"./list/UndoDeleteBar";import{SourcesStrip as le}from"./list/SourcesStrip";import{WipeAllRow as ae}from"./list/WipeAllRow";import{PreviewScreen as ce}from"./preview/PreviewFlow";import{TIME_MACHINE_FLOATING_TOOL_ID as de,openTimeMachineFloatingTool as pe}from"./floating/TimeMachineFloatingTool";import{getPickedPointId as F,resolveArmedPoint as me,subscribePickedPoint as ue}from"./floating/armedPoint";import{setSourceEnabled as he}from"../store/sourceSettings";import{jsx as t,jsxs as d}from"react/jsx-runtime";const z=()=>Y().some(s=>s.id===de);export function TimeMachineBody(){const[s,m]=O({kind:"list"});const{snapshots:i,busy:h,preview:n}=x();const l=te();const a=()=>{o.clearPreview();m({kind:"list"})};if(s.kind==="preview"&&n)return t(ce,{preview:n,snapshots:i,busy:h!==null,onClose:a});return t(fe,{sources:l,onOpenPreview:u=>{void o.buildPreview({snapshotId:u.id});m({kind:"preview"})}})}function fe({sources:s,onOpenPreview:m}){const{snapshots:i,hasLoaded:h,busy:n,lastOutcome:l,recentlyDeleted:a,remoteProviders:u}=x();const f=Q("timeMachine.snapshots");const b=ee();const M=K({minBottom:16});const g=L(Z,z,z);const E=L(ue,F,F);const W=g?me(i,E)?.id:void 0;const w=V({});const[T,I]=O(null);const D=e=>{I(null);pe(e);b.minimize()};const k=b.search.trim().toLowerCase();const y=k?i.filter(e=>e.name.toLowerCase().includes(k)):i;const P=i.filter(e=>!e.safety).length>=f;const _=n!==null||P;const j=e=>{if(n)return;if(e.baseline){B("Restore fresh install?","This wipes all app storage and reloads the app.","Wipe & reload",()=>void o.restore(e.id,"reload"));return}const R=(w.current[e.id]??0)+1;w.current[e.id]=R;if(R>=2&&!g)I(e.id);void o.restore(e.id,"live").then(H=>{const N=Object.values(H.results).every(U=>U.ok);if(!N||H.willReload)return;b.minimize()})};const S=T&&!g?i.find(e=>e.id===T)??null:null;return d(G,{style:p.fill,contentContainerStyle:[p.content,{paddingBottom:M.bottom}],testID:"time-machine-scroll",keyboardShouldPersistTaps:"handled",children:[l&&ne(l)?t(ie,{outcome:l}):null,a?t(se,{name:a.stored.meta.name,at:a.at,onUndo:()=>void o.undoDelete(),onExpire:()=>o.clearRecentlyDeleted()}):null,t(v,{children:t(oe,{disabled:_,busy:n==="capture",onCapture:e=>void o.capture(e)})}),P?d(c,{tone:"warning",testID:"time-machine-limit",children:["Free plan keeps ",f," restore point",f===1?"":"s",". Upgrade to Pro for unlimited snapshots."]}):null,t(A,{children:"Sources"}),t(le,{sources:s,onToggle:u?void 0:he}),u?null:t(c,{testID:"time-machine-sources-hint",children:"Switch a source off to leave it out of every capture and restore."}),t(A,{children:"Restore Points"}),S?d(v,{style:p.barHint,testID:"time-machine-bar-hint",children:[d(c,{children:['Restoring "',S.name,'" a lot? Put it on the floating action bar and restore it with one tap.']}),t(J,{onPress:()=>D(S.id),accessibilityRole:"button",testID:"time-machine-bar-hint-pin",hitSlop:{top:6,bottom:6,left:6,right:6},children:t($,{style:p.barHintAction,children:"Open the action bar"})})]}):null,d(C,{children:[y.map(e=>t(re,{meta:e,busy:n!==null,armed:e.id===W,onOpen:()=>m(e),onRestore:()=>j(e),onDelete:()=>void o.delete(e.id),onDuplicate:()=>void o.duplicate(e.id),onArm:()=>D(e.id)},e.id)),y.length===0?t(X,{testID:"time-machine-empty",...!h?{otto:"loading",title:"Loading restore points\u2026",message:"Reading the vault off disk."}:i.length>0?{otto:"sad",title:"No restore point matches that name.",message:`Clear the search to see all ${i.length}.`}:{otto:"rewind",title:"No restore points yet",message:"Set up the state you want to come back to, then capture it."}}):null]}),y.length>0?t(c,{testID:"time-machine-swipe-hint",children:"Swipe a restore point to copy or delete it."}):null,t(v,{style:p.spacer}),t(C,{children:t(ae,{disabled:n!==null,onWipe:()=>B("Wipe all app state?","This deletes all app storage and reloads the app \u2014 like a fresh install.","Wipe & reload",()=>void o.wipeAll())})}),t(c,{centered:true,children:"Deletes all app storage and reloads \u2014 like a fresh install."})]})}const p=q.create({barHint:{marginHorizontal:r.gutter,marginBottom:8},barHintAction:{color:r.color.accent,fontSize:r.font.footnote,fontWeight:"600",paddingHorizontal:r.textInset,paddingTop:2},fill:{flex:1,backgroundColor:"transparent"},content:{paddingTop:14},empty:{color:r.color.labelSecondary,fontSize:r.font.footnote,lineHeight:r.font.footnote*1.4,paddingHorizontal:r.textInset,paddingVertical:16},spacer:{height:24}});
1
+ "use strict";import{useRef as j,useState as H,useSyncExternalStore as L}from"react";import{ScrollView as U,StyleSheet as V,Text as G,TouchableOpacity as q,View as v}from"react-native";import{useSafeAreaInsets as $,useLimit as J,ToolEmptyState as K,getFloatingTools as Q,subscribeFloatingTools as X}from"@buoy-gg/shared-ui";import{useToolHost as Y}from"@buoy-gg/core";import{useTimeMachineState as O}from"../hooks/useTimeMachine";import{shouldDockAfterRestore as Z,timeMachineStore as o}from"../store/timeMachineStore";import{Footnote as c,Group as x,SectionLabel as A}from"../ui/primitives";import{tm as r}from"../ui/tmTheme";import{useSourceStatuses as ee}from"./sources";import{confirmDestructive as C}from"./confirm";import{CaptureBar as te}from"./list/CaptureBar";import{RestoreOutcomeCard as oe,restoreNeedsAttention as ie}from"./list/RestoreOutcomeCard";import{SnapshotRow as ne}from"./list/SnapshotRow";import{UndoDeleteBar as re}from"./list/UndoDeleteBar";import{SourcesStrip as se}from"./list/SourcesStrip";import{WipeAllRow as le}from"./list/WipeAllRow";import{PreviewScreen as ae}from"./preview/PreviewFlow";import{TIME_MACHINE_FLOATING_TOOL_ID as ce,openTimeMachineFloatingTool as de}from"./floating/TimeMachineFloatingTool";import{getPickedPointId as B,resolveArmedPoint as pe,subscribePickedPoint as me}from"./floating/armedPoint";import{setSourceEnabled as ue}from"../store/sourceSettings";import{jsx as t,jsxs as d}from"react/jsx-runtime";const F=()=>Q().some(s=>s.id===ce);export function TimeMachineBody(){const[s,m]=H({kind:"list"});const{snapshots:i,busy:h,preview:n}=O();const l=ee();const a=()=>{o.clearPreview();m({kind:"list"})};if(s.kind==="preview"&&n)return t(ae,{preview:n,snapshots:i,busy:h!==null,onClose:a});return t(he,{sources:l,onOpenPreview:u=>{void o.buildPreview({snapshotId:u.id});m({kind:"preview"})}})}function he({sources:s,onOpenPreview:m}){const{snapshots:i,hasLoaded:h,busy:n,lastOutcome:l,recentlyDeleted:a,remoteProviders:u}=O();const f=J("timeMachine.snapshots");const g=Y();const z=$({minBottom:16});const b=L(X,F,F);const M=L(me,B,B);const E=b?pe(i,M)?.id:void 0;const w=j({});const[T,D]=H(null);const I=e=>{D(null);de(e);g.minimize()};const k=g.search.trim().toLowerCase();const y=k?i.filter(e=>e.name.toLowerCase().includes(k)):i;const P=i.filter(e=>!e.safety).length>=f;const W=n!==null||P;const _=e=>{if(n)return;if(e.baseline){C("Restore fresh install?","This wipes all app storage and reloads the app.","Wipe & reload",()=>void o.restore(e.id,"reload"));return}const R=(w.current[e.id]??0)+1;w.current[e.id]=R;if(R>=2&&!b)D(e.id);void o.restore(e.id,"live").then(N=>{if(Z(N))g.minimize()})};const S=T&&!b?i.find(e=>e.id===T)??null:null;return d(U,{style:p.fill,contentContainerStyle:[p.content,{paddingBottom:z.bottom}],testID:"time-machine-scroll",keyboardShouldPersistTaps:"handled",children:[l&&ie(l)?t(oe,{outcome:l}):null,a?t(re,{name:a.stored.meta.name,at:a.at,onUndo:()=>void o.undoDelete(),onExpire:()=>o.clearRecentlyDeleted()}):null,t(v,{children:t(te,{disabled:W,busy:n==="capture",onCapture:e=>void o.capture(e)})}),P?d(c,{tone:"warning",testID:"time-machine-limit",children:["Free plan keeps ",f," restore point",f===1?"":"s",". Upgrade to Pro for unlimited snapshots."]}):null,t(A,{children:"Sources"}),t(se,{sources:s,onToggle:u?void 0:ue}),u?null:t(c,{testID:"time-machine-sources-hint",children:"Switch a source off to leave it out of every capture and restore."}),t(A,{children:"Restore Points"}),S?d(v,{style:p.barHint,testID:"time-machine-bar-hint",children:[d(c,{children:['Restoring "',S.name,'" a lot? Put it on the floating action bar and restore it with one tap.']}),t(q,{onPress:()=>I(S.id),accessibilityRole:"button",testID:"time-machine-bar-hint-pin",hitSlop:{top:6,bottom:6,left:6,right:6},children:t(G,{style:p.barHintAction,children:"Open the action bar"})})]}):null,d(x,{children:[y.map(e=>t(ne,{meta:e,busy:n!==null,armed:e.id===E,onOpen:()=>m(e),onRestore:()=>_(e),onDelete:()=>void o.delete(e.id),onDuplicate:()=>void o.duplicate(e.id),onArm:()=>I(e.id)},e.id)),y.length===0?t(K,{testID:"time-machine-empty",...!h?{otto:"loading",title:"Loading restore points\u2026",message:"Reading the vault off disk."}:i.length>0?{otto:"sad",title:"No restore point matches that name.",message:`Clear the search to see all ${i.length}.`}:{otto:"rewind",title:"No restore points yet",message:"Set up the state you want to come back to, then capture it."}}):null]}),y.length>0?t(c,{testID:"time-machine-swipe-hint",children:"Swipe a restore point to copy or delete it."}):null,t(v,{style:p.spacer}),t(x,{children:t(le,{disabled:n!==null,onWipe:()=>C("Wipe all app state?","This deletes all app storage and reloads the app \u2014 like a fresh install.","Wipe & reload",()=>void o.wipeAll())})}),t(c,{centered:true,children:"Deletes all app storage and reloads \u2014 like a fresh install."})]})}const p=V.create({barHint:{marginHorizontal:r.gutter,marginBottom:8},barHintAction:{color:r.color.accent,fontSize:r.font.footnote,fontWeight:"600",paddingHorizontal:r.textInset,paddingTop:2},fill:{flex:1,backgroundColor:"transparent"},content:{paddingTop:14},empty:{color:r.color.labelSecondary,fontSize:r.font.footnote,lineHeight:r.font.footnote*1.4,paddingHorizontal:r.textInset,paddingVertical:16},spacer:{height:24}});
@@ -1 +1 @@
1
- "use strict";import{StyleSheet as h,Text as c,TouchableOpacity as f,View as u}from"react-native";import{X as g}from"@buoy-gg/shared-ui";import{tm as t}from"../../ui/tmTheme";import{timeMachineStore as y}from"../../store/timeMachineStore";import{jsxs as o,jsx as r}from"react/jsx-runtime";const b={top:10,bottom:10,left:10,right:10};export function restoreNeedsAttention(e){if(Object.values(e.results).some(s=>!s.ok||s.skipped.length>0))return true;const n=e.route;return n?.status==="failed"||n?.status==="unavailable"}function m({glyph:e,text:n,ok:s,testID:d}){return o(c,{style:[i.line,{color:s?t.color.accent:t.color.warning}],numberOfLines:2,testID:d,children:[o(c,{style:i.glyph,children:[e," "]}),n]})}const p="time-machine-outcome-route";function x({route:e}){if(e.status==="navigated")return r(m,{glyph:"\u2713",ok:true,text:`route \u2014 ${e.href}`,testID:p});if(e.status==="deferred")return r(m,{glyph:"\u21BB",ok:true,text:`route \u2014 ${e.href} after reload`,testID:p});return r(m,{glyph:"\u2715",ok:false,text:`route \u2014 ${e.error??e.status}`,testID:p})}export function RestoreOutcomeCard({outcome:e}){const n=Object.entries(e.results);const s=e.mode==="reload"||e.willReload;return o(u,{style:i.card,testID:"time-machine-outcome",children:[o(u,{style:i.headerRow,children:[o(c,{style:i.title,numberOfLines:1,testID:"time-machine-outcome-title",children:["Restored \u201C",e.snapshotName,"\u201D",s?" \xB7 reloading":""]}),r(f,{onPress:()=>y.clearLastOutcome(),hitSlop:b,accessibilityRole:"button",accessibilityLabel:"Dismiss restore result",testID:"time-machine-outcome-dismiss",children:r(g,{size:13,color:t.color.labelSecondary})})]}),n.length===0&&!e.route?r(c,{style:i.empty,testID:"time-machine-outcome-empty",children:"No sources restored."}):null,e.route?r(x,{route:e.route}):null,n.map(([d,l])=>o(u,{children:[r(m,{testID:`time-machine-outcome-${d}`,glyph:l.ok?"\u2713":"\u2715",ok:l.ok,text:`${d} \u2014 applied ${l.applied}${l.skipped.length>0?`, skipped ${l.skipped.length}`:""}`}),l.skipped.slice(0,3).map(a=>o(c,{style:i.detail,numberOfLines:2,children:[a.id,": ",a.reason]},a.id)),l.warnings.slice(0,3).map(a=>o(c,{style:i.detail,numberOfLines:2,children:["\u26A0 ",a]},a))]},d))]})}const i=h.create({card:{marginHorizontal:t.gutter,marginTop:12,backgroundColor:t.color.group,borderRadius:t.radius.group,borderWidth:1,borderColor:t.color.groupBorder,padding:14,gap:4},headerRow:{flexDirection:"row",alignItems:"center",gap:10,marginBottom:2},title:{flex:1,color:t.color.label,fontSize:15,fontWeight:"600",letterSpacing:t.tracking.control},line:{fontSize:t.font.footnote,lineHeight:t.font.footnote*1.4},glyph:{fontWeight:"700"},detail:{color:t.color.labelTertiary,fontSize:t.font.mono,lineHeight:t.font.mono*1.4,paddingLeft:14},empty:{color:t.color.labelSecondary,fontSize:t.font.footnote}});
1
+ "use strict";import{StyleSheet as f,Text as s,TouchableOpacity as u,View as p}from"react-native";import{X as g}from"@buoy-gg/shared-ui";import{tm as t}from"../../ui/tmTheme";import{timeMachineStore as y}from"../../store/timeMachineStore";import{restoreNeedsAttention as b}from"../../store/timeMachineStore";import{jsxs as o,jsx as r}from"react/jsx-runtime";const x={top:10,bottom:10,left:10,right:10};export{b as restoreNeedsAttention};function d({glyph:e,text:c,ok:m,testID:a}){return o(s,{style:[i.line,{color:m?t.color.accent:t.color.warning}],numberOfLines:2,testID:a,children:[o(s,{style:i.glyph,children:[e," "]}),c]})}const h="time-machine-outcome-route";function D({route:e}){if(e.status==="navigated")return r(d,{glyph:"\u2713",ok:true,text:`route \u2014 ${e.href}`,testID:h});if(e.status==="deferred")return r(d,{glyph:"\u21BB",ok:true,text:`route \u2014 ${e.href} after reload`,testID:h});return r(d,{glyph:"\u2715",ok:false,text:`route \u2014 ${e.error??e.status}`,testID:h})}export function RestoreOutcomeCard({outcome:e}){const c=Object.entries(e.results);const m=e.mode==="reload"||e.willReload;return o(p,{style:i.card,testID:"time-machine-outcome",children:[o(p,{style:i.headerRow,children:[o(s,{style:i.title,numberOfLines:1,testID:"time-machine-outcome-title",children:["Restored \u201C",e.snapshotName,"\u201D",m?" \xB7 reloading":""]}),r(u,{onPress:()=>y.clearLastOutcome(),hitSlop:x,accessibilityRole:"button",accessibilityLabel:"Dismiss restore result",testID:"time-machine-outcome-dismiss",children:r(g,{size:13,color:t.color.labelSecondary})})]}),c.length===0&&!e.route?r(s,{style:i.empty,testID:"time-machine-outcome-empty",children:"No sources restored."}):null,e.route?r(D,{route:e.route}):null,c.map(([a,n])=>o(p,{children:[r(d,{testID:`time-machine-outcome-${a}`,glyph:n.ok?"\u2713":"\u2715",ok:n.ok,text:`${a} \u2014 applied ${n.applied}${n.skipped.length>0?`, skipped ${n.skipped.length}`:""}`}),n.skipped.slice(0,3).map(l=>o(s,{style:i.detail,numberOfLines:2,children:[l.id,": ",l.reason]},l.id)),n.warnings.slice(0,3).map(l=>o(s,{style:i.detail,numberOfLines:2,children:["\u26A0 ",l]},l))]},a))]})}const i=f.create({card:{marginHorizontal:t.gutter,marginTop:12,backgroundColor:t.color.group,borderRadius:t.radius.group,borderWidth:1,borderColor:t.color.groupBorder,padding:14,gap:4},headerRow:{flexDirection:"row",alignItems:"center",gap:10,marginBottom:2},title:{flex:1,color:t.color.label,fontSize:15,fontWeight:"600",letterSpacing:t.tracking.control},line:{fontSize:t.font.footnote,lineHeight:t.font.footnote*1.4},glyph:{fontWeight:"700"},detail:{color:t.color.labelTertiary,fontSize:t.font.mono,lineHeight:t.font.mono*1.4,paddingLeft:14},empty:{color:t.color.labelSecondary,fontSize:t.font.footnote}});
@@ -1 +1 @@
1
- "use strict";import{persistentStorage as s}from"@buoy-gg/shared-ui";const p="@react_buoy_time_machine:index";const i="@react_buoy_time_machine:snap:";export async function loadIndex(){try{const t=await s.getItem(p);if(!t)return[];const e=JSON.parse(t);return Array.isArray(e)?e:[]}catch{return[]}}async function d(t){await s.setItem(p,JSON.stringify(t))}export async function saveSnapshot(t,e){const r=JSON.stringify(t);t.meta.sizeBytes=r.length;await s.setItem(i+t.meta.id,JSON.stringify(t));const n=[t.meta,...e.filter(a=>a.id!==t.meta.id)];await d(n);return n}export async function loadSnapshot(t){try{const e=await s.getItem(i+t);return e?JSON.parse(e):null}catch{return null}}export async function deleteSnapshot(t,e){await s.removeItem(i+t);const r=e.filter(n=>n.id!==t);await d(r);return r}async function c(t,e,r){const n=u=>u.id===t?e(u):u;const a=r.map(n);await s.setItem(p,JSON.stringify(a));const o=await loadSnapshot(t);if(o){o.meta=n(o.meta);await s.setItem(i+t,JSON.stringify(o))}return a}export function setSnapshotScope(t,e,r){return c(t,n=>{const a={...n};if(e&&e.length>0)a.scope=e;else delete a.scope;return a},r)}export function setSnapshotExclusions(t,e,r){return c(t,n=>{const a={...n};delete a.scope;if(e&&e.length>0)a.excludedKeys=e;else delete a.excludedKeys;return a},r)}export function setSnapshotRestoreRoute(t,e,r){return c(t,n=>({...n,restoreRoute:e}),r)}export function markSnapshotRestored(t,e,r){return c(t,n=>({...n,lastRestoredAt:e}),r)}export async function duplicateSnapshot(t,e,r){const n=await loadSnapshot(t);if(!n)return null;const a={meta:{...n.meta,id:`${n.meta.id}_copy_${Date.now().toString(36)}`,name:e,createdAt:Date.now(),lastRestoredAt:void 0},data:n.data};delete a.meta.lastRestoredAt;return{metas:await saveSnapshot(a,r),meta:a.meta}}export async function readSnapshot(t){return loadSnapshot(t)}export async function restoreDeletedSnapshot(t,e){return saveSnapshot(t,e)}export async function renameSnapshot(t,e,r){const n=r.map(o=>o.id===t?{...o,name:e}:o);await d(n);const a=await loadSnapshot(t);if(a){a.meta.name=e;await s.setItem(i+t,JSON.stringify(a))}return n}
1
+ "use strict";import{persistentStorage as s}from"@buoy-gg/shared-ui";const p="@react_buoy_time_machine:index";const i="@react_buoy_time_machine:snap:";export async function loadIndex(){try{const t=await s.getItem(p);if(!t)return[];const e=JSON.parse(t);return Array.isArray(e)?e:[]}catch{return[]}}async function d(t){await s.setItem(p,JSON.stringify(t))}export async function saveSnapshot(t,e){const r=JSON.stringify(t);t.meta.sizeBytes=r.length;await s.setItem(i+t.meta.id,JSON.stringify(t));const n=[t.meta,...e.filter(a=>a.id!==t.meta.id)];await d(n);return n}export async function loadSnapshot(t){try{const e=await s.getItem(i+t);return e?JSON.parse(e):null}catch{return null}}export async function deleteSnapshot(t,e){await s.removeItem(i+t);const r=e.filter(n=>n.id!==t);await d(r);return r}async function c(t,e,r){const n=u=>u.id===t?e(u):u;const a=r.map(n);await s.setItem(p,JSON.stringify(a));const o=await loadSnapshot(t);if(o){o.meta=n(o.meta);await s.setItem(i+t,JSON.stringify(o))}return a}export function setSnapshotScope(t,e,r){return c(t,n=>{const a={...n};if(e&&e.length>0)a.scope=e;else delete a.scope;return a},r)}export function setSnapshotExclusions(t,e,r){return c(t,n=>{const a={...n};delete a.scope;if(e&&e.length>0)a.excludedKeys=e;else delete a.excludedKeys;return a},r)}export function setSnapshotRestoreRoute(t,e,r){return c(t,n=>({...n,restoreRoute:e}),r)}export function markSnapshotRestored(t,e,r){return c(t,n=>({...n,lastRestoredAt:e}),r)}export async function duplicateSnapshot(t,e,r){const n=await loadSnapshot(t);if(!n)return null;const a={meta:{...n.meta,id:`${n.meta.id}_copy_${Date.now().toString(36)}`,name:e,createdAt:Date.now(),lastRestoredAt:void 0},data:n.data};delete a.meta.lastRestoredAt;delete a.meta.safety;return{metas:await saveSnapshot(a,r),meta:a.meta}}export async function readSnapshot(t){return loadSnapshot(t)}export async function restoreDeletedSnapshot(t,e){return saveSnapshot(t,e)}export async function renameSnapshot(t,e,r){const n=r.map(o=>o.id===t?{...o,name:e}:o);await d(n);const a=await loadSnapshot(t);if(a){a.meta.name=e;await s.setItem(i+t,JSON.stringify(a))}return n}
@@ -1 +1 @@
1
- "use strict";import{getStateSnapshotProvider as L,getStateSnapshotProviders as b,scheduleReloadApp as B,superJsonDeserialize as D,superJsonSerialize as M}from"@buoy-gg/shared-ui";import{objectDiff as _}from"@buoy-gg/shared-ui/dataViewer";import{deleteSnapshot as P,duplicateSnapshot as z,loadIndex as C,loadSnapshot as I,markSnapshotRestored as A,readSnapshot as F,renameSnapshot as H,restoreDeletedSnapshot as j,saveSnapshot as k,setSnapshotRestoreRoute as q,setSnapshotScope as J,setSnapshotExclusions as U}from"./snapshotVault";import{captureCurrentRoute as V,navigateToRoute as W,savePendingRoute as Y}from"./routeRestore";import{ensureSourceSettingsLoaded as w,isSourceEnabled as g}from"./sourceSettings";import{ROUTE_SOURCE_ID as $}from"./sourceIds";export const RESTORE_ORDER=["storage","redux","zustand","jotai","query"];function G(c){const t=new Date;const e=`${String(t.getHours()).padStart(2,"0")}:${String(t.getMinutes()).padStart(2,"0")}`;const s=c?c.pathname==="/"?"Home":c.pathname:null;return s?`${s} \xB7 ${e}`:`Snapshot \xB7 ${e}`}function Q(c,t){const e=new Set(t.map(s=>s.name));if(!e.has(c))return c;for(let s=2;s<1e3;s++){const l=`${c} (${s})`;if(!e.has(l))return l}return c}export function willRestoreRoute(c){return!!c.route&&(c.restoreRoute??true)}export const SAFETY_SNAPSHOT_NAME="Before last restore";let o=null;function R(c){return{ok:false,applied:0,skipped:[{id:"*",reason:c}],warnings:[]}}let x=0;function T(){x+=1;return`snap_${Date.now().toString(36)}_${x.toString(36)}`}class X{state={snapshots:[],hasLoaded:false,busy:null,lastOutcome:null,preview:null,remoteProviders:null,remoteRoute:null,recentlyDeleted:null};previewRunId=0;listeners=new Set;loadPromise=null;getState(){return this.state}subscribe=t=>{this.listeners.add(t);void this.ensureLoaded();return()=>{this.listeners.delete(t)}};setState(t){this.state={...this.state,...t};this.listeners.forEach(e=>{try{e()}catch{}})}ensureLoaded(){if(o)return Promise.resolve();if(!this.loadPromise){this.loadPromise=C().then(t=>{if(o)return;this.setState({snapshots:t,hasLoaded:true})})}return this.loadPromise}replaceFromSnapshot(t){this.setState({snapshots:t.snapshots??[],busy:t.busy??null,lastOutcome:t.lastOutcome??null,remoteProviders:t.providers??[],remoteRoute:t.route??{available:false},hasLoaded:true})}async capture(t,e,s){if(o){const l=await o("capture",{name:t,sourceIds:e});return l.snapshot}await this.ensureLoaded();await w();this.setState({busy:"capture"});try{const l=b().filter(r=>r.status().canCapture&&g(r.id)&&(!e||e.includes(r.id)));const u={};const a={};for(const r of l){try{const d=await r.capture();u[r.id]=M(d.data);a[r.id]={warnings:d.warnings}}catch(d){a[r.id]={warnings:[`capture failed: ${String(d)}`]}}}const i=g($)?V():null;let p=this.state.snapshots;if(s?.safety){for(const r of p.filter(d=>d.safety)){p=await P(r.id,p)}}const S={meta:{id:T(),name:s?.safety?SAFETY_SNAPSHOT_NAME:Q(t.trim()||G(i),p),createdAt:Date.now(),sizeBytes:0,...i?{route:i}:{},...s?.safety?{safety:true}:{},sources:a},data:u};const f=await k(S,p);this.setState({snapshots:f});return S.meta}finally{this.setState({busy:null})}}async captureBaseline(){if(o){const s=await o("captureBaseline",{});return s.snapshot}await this.ensureLoaded();await w();const t={meta:{id:T(),name:"Fresh install",createdAt:Date.now(),sizeBytes:0,baseline:true,sources:{}},data:{}};const e=await k(t,this.state.snapshots);this.setState({snapshots:e});return t.meta}async restore(t,e,s,l){if(o){const a=await o("restore",{id:t,mode:e,excludeKeys:s,restoreRoute:l?.restoreRoute});this.setState({lastOutcome:a});return a}await this.ensureLoaded();await w();let u;if(l?.safetyCapture&&!this.state.snapshots.find(a=>a.id===t)?.safety){u=(await this.capture(SAFETY_SNAPSHOT_NAME,void 0,{safety:true})).id}this.setState({busy:"restore"});try{const a=await I(t);if(!a)throw new Error(`No snapshot with id "${t}"`);const i={snapshotId:t,snapshotName:a.meta.name,mode:e,at:Date.now(),willReload:false,results:{},...u?{safetySnapshotId:u}:{}};if(a.meta.baseline){for(const n of b()){if(n.clear){try{i.results[n.id]=await n.clear()}catch(h){i.results[n.id]=R(String(h))}}}i.willReload=this.scheduleReload("buoy time-machine baseline");this.setState({lastOutcome:i});return i}const p=[...RESTORE_ORDER.filter(n=>n in a.data),...Object.keys(a.data).filter(n=>!RESTORE_ORDER.includes(n))];const S=n=>{const h=new Map;for(const m of n){const v=m.indexOf("::");if(v<=0)continue;const O=m.slice(0,v);const N=m.slice(v+2);const E=h.get(O)??[];E.push(N);h.set(O,E)}return h};const f=s??a.meta.excludedKeys??[];const r=S(f);const d=!s&&a.meta.scope?.length?S(a.meta.scope):null;const y=g($)&&(l?.restoreRoute??willRestoreRoute(a.meta));if(e==="reload"){if(a.data.storage&&g("storage")&&(!d||d.has("storage"))){i.results.storage=await this.restoreSource("storage",a.data.storage,r.get("storage"),d?.get("storage"))}if(y){const n=a.meta.route;try{await Y(n,a.meta.name);i.route={...n,status:"deferred"}}catch(h){i.route={...n,status:"failed",error:String(h)}}}i.willReload=this.scheduleReload("buoy time-machine restore");this.setState({lastOutcome:i,snapshots:await A(t,i.at,this.state.snapshots)});return i}for(const n of p){if(d&&!d.has(n))continue;if(!g(n)){i.results[n]={ok:true,applied:0,skipped:[],warnings:["Switched off in Sources; left as it is"]};continue}i.results[n]=await this.restoreSource(n,a.data[n],r.get(n),d?.get(n))}if(y){i.route=W(a.meta.route)}this.setState({lastOutcome:i,snapshots:await A(t,i.at,this.state.snapshots)});return i}finally{this.setState({busy:null})}}async restoreSource(t,e,s,l){const u=L(t);if(!u){return R("provider not available (package missing or not initialized)")}const a=u.status();if(!a.canRestore){return R(a.detail??"restore unavailable")}try{const i=s?.length||l?.length?{...s?.length?{excludeKeys:s}:{},...l?.length?{includeKeys:l}:{}}:void 0;return await u.restore(D(e),i)}catch(i){return R(String(i))}}scheduleReload(t){try{B({reason:t});return true}catch{return false}}async delete(t){if(o){await o("delete",{id:t});return}await this.ensureLoaded();await w();const e=await F(t);const s=await P(t,this.state.snapshots);this.setState({snapshots:s,recentlyDeleted:e?{stored:e,at:Date.now()}:null})}async undoDelete(){const t=this.state.recentlyDeleted;if(!t)return;const e=await j(t.stored,this.state.snapshots);this.setState({snapshots:e,recentlyDeleted:null})}clearRecentlyDeleted(){if(this.state.recentlyDeleted)this.setState({recentlyDeleted:null})}async setRestoreRoute(t,e){if(o){await o("setRestoreRoute",{id:t,restoreRoute:e});return}await this.ensureLoaded();await w();const s=await q(t,e,this.state.snapshots);this.setState({snapshots:s})}async duplicate(t){if(o){const l=await o("duplicate",{id:t});return l?.snapshot??null}await this.ensureLoaded();await w();const e=this.state.snapshots.find(l=>l.id===t);if(!e)return null;const s=await z(t,`${e.name} copy`,this.state.snapshots);if(!s)return null;this.setState({snapshots:s.metas});return s.meta}async rename(t,e){if(o){await o("rename",{id:t,name:e});return}await this.ensureLoaded();await w();const s=await H(t,e,this.state.snapshots);this.setState({snapshots:s})}async setScope(t,e){if(o){await o("setScope",{id:t,scope:e});return}await this.ensureLoaded();await w();const s=await J(t,e,this.state.snapshots);this.setState({snapshots:s})}async setExclusions(t,e){if(o){await o("setExclusions",{id:t,excludedKeys:e});return}await this.ensureLoaded();await w();const s=await U(t,e,this.state.snapshots);this.setState({snapshots:s})}clearLastOutcome(){this.setState({lastOutcome:null})}async wipeAll(){if(o){const t=await o("wipeAll",{});this.setState({lastOutcome:t});return t}this.setState({busy:"restore"});try{const t={snapshotId:"wipe-all",snapshotName:"Wipe all",mode:"reload",at:Date.now(),willReload:false,results:{}};for(const e of b()){if(e.clear){try{t.results[e.id]=await e.clear()}catch(s){t.results[e.id]=R(String(s))}}}t.willReload=this.scheduleReload("buoy time-machine wipe all");this.setState({lastOutcome:t});return t}finally{this.setState({busy:null})}}clearPreview(){this.previewRunId+=1;this.setState({preview:null})}async buildPreview(t,e="current"){if(o){const u=++this.previewRunId;this.setState({preview:{left:e,right:t,building:true,builtAt:Date.now(),sources:[]}});try{const a=await o("preview",{id:t==="current"?void 0:t.snapshotId,compareTo:e==="current"?void 0:e.snapshotId});if(u!==this.previewRunId)return;this.setState({preview:{left:e,right:t,building:false,builtAt:Date.now(),sources:a.sources??[]}})}catch(a){if(u!==this.previewRunId)return;this.setState({preview:{left:e,right:t,building:false,builtAt:Date.now(),sources:[{id:"error",label:"Preview",items:[],notes:[],error:String(a)}]}})}return}await this.ensureLoaded();await w();const s=++this.previewRunId;this.setState({preview:{left:e,right:t,building:true,builtAt:Date.now(),sources:[]}});const l=async u=>{if(u==="current")return null;const a=await I(u.snapshotId);if(!a)throw new Error(`No snapshot with id "${u.snapshotId}"`);return a.data};try{if(t==="current")throw new Error("preview target must be a snapshot");const[u,a]=await Promise.all([l(e),I(t.snapshotId)]);if(s!==this.previewRunId)return;if(!a){throw new Error(`No snapshot with id "${t.snapshotId}"`)}const i=a.data;const p=a.meta.baseline===true;const S=p?b().filter(r=>r.clear).map(r=>r.id):[...RESTORE_ORDER.filter(r=>r in i),...Object.keys(i).filter(r=>!RESTORE_ORDER.includes(r))];const f=[];for(const r of S){if(!g(r))continue;await new Promise(n=>setTimeout(n,0));if(s!==this.previewRunId)return;const d=L(r);const y=d?.label??r;try{const n=p?void 0:D(i[r]);const h=u===null?void 0:r in u?D(u[r]):void 0;let m;if(!d){m={items:[{key:r,label:y,verdict:"wont-apply",reason:"tool not installed \u2014 restore skips this source"}],notes:[]}}else if(d.previewItems){m=await d.previewItems(n,h)}else{const v=_(h,n);m={items:[{key:r,label:y,verdict:v.equal?"unchanged":"changed",oldValue:h,newValue:n}],notes:v.truncated?["diff truncated (large value)"]:[]}}if(s!==this.previewRunId)return;f.push({id:r,label:y,...m})}catch(n){f.push({id:r,label:y,items:[],notes:[],error:String(n)})}this.setState({preview:{left:e,right:t,building:true,builtAt:Date.now(),sources:[...f]}})}if(s!==this.previewRunId)return;this.setState({preview:{left:e,right:t,building:false,builtAt:Date.now(),sources:f}})}catch(u){if(s!==this.previewRunId)return;this.setState({preview:{left:e,right:t,building:false,builtAt:Date.now(),sources:[{id:"error",label:"Preview",items:[],notes:[],error:String(u)}]}})}}}export const timeMachineStore=new X;export function setRemoteTimeMachineHandler(c){o=c;if(!c){timeMachineStore.replaceFromSnapshot({})}}export function replaceTimeMachineFromSnapshot(c){timeMachineStore.replaceFromSnapshot(c)}
1
+ "use strict";import{getStateSnapshotProvider as P,getStateSnapshotProviders as D,scheduleReloadApp as M,superJsonDeserialize as I,superJsonSerialize as _}from"@buoy-gg/shared-ui";import{objectDiff as z}from"@buoy-gg/shared-ui/dataViewer";import{deleteSnapshot as A,duplicateSnapshot as C,loadIndex as F,loadSnapshot as E,markSnapshotRestored as L,readSnapshot as j,renameSnapshot as H,restoreDeletedSnapshot as q,saveSnapshot as k,setSnapshotRestoreRoute as J,setSnapshotScope as U,setSnapshotExclusions as V}from"./snapshotVault";import{captureCurrentRoute as W,navigateToRoute as Y,savePendingRoute as G}from"./routeRestore";import{ensureSourceSettingsLoaded as p,isSourceEnabled as g}from"./sourceSettings";import{ROUTE_SOURCE_ID as $}from"./sourceIds";export const RESTORE_ORDER=["storage","redux","zustand","jotai","query"];function Q(o){const t=new Date;const e=`${String(t.getHours()).padStart(2,"0")}:${String(t.getMinutes()).padStart(2,"0")}`;const s=o?o.pathname==="/"?"Home":o.pathname:null;return s?`${s} \xB7 ${e}`:`Snapshot \xB7 ${e}`}function X(o,t){const e=new Set(t.map(s=>s.name));if(!e.has(o))return o;for(let s=2;s<1e3;s++){const i=`${o} (${s})`;if(!e.has(i))return i}return o}export function willRestoreRoute(o){return!!o.route&&(o.restoreRoute??true)}export const SAFETY_SNAPSHOT_NAME="Before last restore";export function restoreNeedsAttention(o){if(Object.values(o.results).some(e=>!e.ok||e.skipped.length>0))return true;const t=o.route;return t?.status==="failed"||t?.status==="unavailable"}export function shouldDockAfterRestore(o){return!o.willReload&&!restoreNeedsAttention(o)}function x(){return{ok:true,applied:0,skipped:[],warnings:["Switched off in Sources; left as it is"]}}let u=null;function v(o){return{ok:false,applied:0,skipped:[{id:"*",reason:o}],warnings:[]}}let N=0;function T(){N+=1;return`snap_${Date.now().toString(36)}_${N.toString(36)}`}class Z{state={snapshots:[],hasLoaded:false,busy:null,lastOutcome:null,preview:null,remoteProviders:null,remoteRoute:null,recentlyDeleted:null};previewRunId=0;listeners=new Set;loadPromise=null;getState(){return this.state}subscribe=t=>{this.listeners.add(t);void this.ensureLoaded();return()=>{this.listeners.delete(t)}};setState(t){this.state={...this.state,...t};this.listeners.forEach(e=>{try{e()}catch{}})}ensureLoaded(){if(u)return Promise.resolve();if(!this.loadPromise){this.loadPromise=F().then(t=>{if(u)return;this.setState({snapshots:t,hasLoaded:true})})}return this.loadPromise}replaceFromSnapshot(t){this.setState({snapshots:t.snapshots??[],busy:t.busy??null,lastOutcome:t.lastOutcome??null,remoteProviders:t.providers??[],remoteRoute:t.route??{available:false},hasLoaded:true})}async capture(t,e,s){if(u){const i=await u("capture",{name:t,sourceIds:e});return i.snapshot}await this.ensureLoaded();await p();this.setState({busy:"capture"});try{const i=D().filter(c=>c.status().canCapture&&g(c.id)&&(!e||e.includes(c.id)));const d={};const a={};for(const c of i){try{const r=await c.capture();d[c.id]=_(r.data);a[c.id]={warnings:r.warnings}}catch(r){a[c.id]={warnings:[`capture failed: ${String(r)}`]}}}const n=g($)?W():null;const f=this.state.snapshots;const w={meta:{id:T(),name:s?.safety?SAFETY_SNAPSHOT_NAME:X(t.trim()||Q(n),f),createdAt:Date.now(),sizeBytes:0,...n?{route:n}:{},...s?.safety?{safety:true}:{},sources:a},data:d};let m=await k(w,f);if(s?.safety){for(const c of m.filter(r=>r.safety&&r.id!==w.meta.id)){m=await A(c.id,m)}}this.setState({snapshots:m});return w.meta}finally{this.setState({busy:null})}}async captureBaseline(){if(u){const s=await u("captureBaseline",{});return s.snapshot}await this.ensureLoaded();await p();const t={meta:{id:T(),name:"Fresh install",createdAt:Date.now(),sizeBytes:0,baseline:true,sources:{}},data:{}};const e=await k(t,this.state.snapshots);this.setState({snapshots:e});return t.meta}async restore(t,e,s,i){if(u){const a=await u("restore",{id:t,mode:e,excludeKeys:s,restoreRoute:i?.restoreRoute});this.setState({lastOutcome:a});return a}await this.ensureLoaded();await p();let d;if(i?.safetyCapture&&!this.state.snapshots.find(a=>a.id===t)?.safety){d=(await this.capture(SAFETY_SNAPSHOT_NAME,void 0,{safety:true})).id}this.setState({busy:"restore"});try{const a=await E(t);if(!a)throw new Error(`No snapshot with id "${t}"`);const n={snapshotId:t,snapshotName:a.meta.name,mode:e,at:Date.now(),willReload:false,results:{},...d?{safetySnapshotId:d}:{}};if(a.meta.baseline){await this.clearEnabledSources(n);n.willReload=this.scheduleReload("buoy time-machine baseline");this.setState({lastOutcome:n});return n}const f=[...RESTORE_ORDER.filter(l=>l in a.data),...Object.keys(a.data).filter(l=>!RESTORE_ORDER.includes(l))];const w=l=>{const h=new Map;for(const b of l){const S=b.indexOf("::");if(S<=0)continue;const R=b.slice(0,S);const B=b.slice(S+2);const O=h.get(R)??[];O.push(B);h.set(R,O)}return h};const m=s??a.meta.excludedKeys??[];const c=w(m);const r=!s&&a.meta.scope?.length?w(a.meta.scope):null;const y=g($)&&(i?.restoreRoute??willRestoreRoute(a.meta));if(e==="reload"){if(a.data.storage&&g("storage")&&(!r||r.has("storage"))){n.results.storage=await this.restoreSource("storage",a.data.storage,c.get("storage"),r?.get("storage"))}if(y){const l=a.meta.route;try{await G(l,a.meta.name);n.route={...l,status:"deferred"}}catch(h){n.route={...l,status:"failed",error:String(h)}}}n.willReload=this.scheduleReload("buoy time-machine restore");this.setState({lastOutcome:n,snapshots:await L(t,n.at,this.state.snapshots)});return n}for(const l of f){if(r&&!r.has(l))continue;if(!g(l)){n.results[l]=x();continue}n.results[l]=await this.restoreSource(l,a.data[l],c.get(l),r?.get(l))}if(y){n.route=Y(a.meta.route)}this.setState({lastOutcome:n,snapshots:await L(t,n.at,this.state.snapshots)});return n}finally{this.setState({busy:null})}}async restoreSource(t,e,s,i){const d=P(t);if(!d){return v("provider not available (package missing or not initialized)")}const a=d.status();if(!a.canRestore){return v(a.detail??"restore unavailable")}try{const n=s?.length||i?.length?{...s?.length?{excludeKeys:s}:{},...i?.length?{includeKeys:i}:{}}:void 0;return await d.restore(I(e),n)}catch(n){return v(String(n))}}async clearEnabledSources(t){for(const e of D()){if(!e.clear)continue;if(!g(e.id)){t.results[e.id]=x();continue}try{t.results[e.id]=await e.clear()}catch(s){t.results[e.id]=v(String(s))}}}reloadApp(){if(this.state.busy==="restore")return false;return this.scheduleReload("buoy time-machine reload app")}scheduleReload(t){try{M({reason:t});return true}catch{return false}}async delete(t){if(u){await u("delete",{id:t});return}await this.ensureLoaded();await p();const e=await j(t);const s=await A(t,this.state.snapshots);this.setState({snapshots:s,recentlyDeleted:e?{stored:e,at:Date.now()}:null})}async undoDelete(){const t=this.state.recentlyDeleted;if(!t)return;const e=await q(t.stored,this.state.snapshots);this.setState({snapshots:e,recentlyDeleted:null})}clearRecentlyDeleted(){if(this.state.recentlyDeleted)this.setState({recentlyDeleted:null})}async setRestoreRoute(t,e){if(u){await u("setRestoreRoute",{id:t,restoreRoute:e});return}await this.ensureLoaded();await p();const s=await J(t,e,this.state.snapshots);this.setState({snapshots:s})}async duplicate(t){if(u){const i=await u("duplicate",{id:t});return i?.snapshot??null}await this.ensureLoaded();await p();const e=this.state.snapshots.find(i=>i.id===t);if(!e)return null;const s=await C(t,`${e.name} copy`,this.state.snapshots);if(!s)return null;this.setState({snapshots:s.metas});return s.meta}async rename(t,e){if(u){await u("rename",{id:t,name:e});return}await this.ensureLoaded();await p();const s=await H(t,e,this.state.snapshots);this.setState({snapshots:s})}async setScope(t,e){if(u){await u("setScope",{id:t,scope:e});return}await this.ensureLoaded();await p();const s=await U(t,e,this.state.snapshots);this.setState({snapshots:s})}async setExclusions(t,e){if(u){await u("setExclusions",{id:t,excludedKeys:e});return}await this.ensureLoaded();await p();const s=await V(t,e,this.state.snapshots);this.setState({snapshots:s})}clearLastOutcome(){this.setState({lastOutcome:null})}async wipeAll(){if(u){const t=await u("wipeAll",{});this.setState({lastOutcome:t});return t}await p();this.setState({busy:"restore"});try{const t={snapshotId:"wipe-all",snapshotName:"Wipe all",mode:"reload",at:Date.now(),willReload:false,results:{}};await this.clearEnabledSources(t);t.willReload=this.scheduleReload("buoy time-machine wipe all");this.setState({lastOutcome:t});return t}finally{this.setState({busy:null})}}clearPreview(){this.previewRunId+=1;this.setState({preview:null})}async buildPreview(t,e="current"){if(u){const i=++this.previewRunId;this.setState({preview:{left:e,right:t,building:true,builtAt:Date.now(),sources:[]}});try{const d=await u("preview",{id:t==="current"?void 0:t.snapshotId,compareTo:e==="current"?void 0:e.snapshotId});if(i!==this.previewRunId)return;this.setState({preview:{left:e,right:t,building:false,builtAt:Date.now(),sources:d.sources??[]}})}catch(d){if(i!==this.previewRunId)return;this.setState({preview:{left:e,right:t,building:false,builtAt:Date.now(),sources:[{id:"error",label:"Preview",items:[],notes:[],error:String(d)}]}})}return}await this.ensureLoaded();await p();const s=++this.previewRunId;await this.runPreview(t,e,i=>this.setState({preview:i}),()=>s===this.previewRunId)}async computePreview(t,e="current"){await this.ensureLoaded();await p();let s=null;await this.runPreview(t,e,i=>{s=i},()=>true);if(!s)throw new Error("preview build produced no result");return s}async runPreview(t,e,s,i){s({left:e,right:t,building:true,builtAt:Date.now(),sources:[]});const d=async a=>{if(a==="current")return null;const n=await E(a.snapshotId);if(!n)throw new Error(`No snapshot with id "${a.snapshotId}"`);return n.data};try{if(t==="current")throw new Error("preview target must be a snapshot");const[a,n]=await Promise.all([d(e),E(t.snapshotId)]);if(!i())return;if(!n){throw new Error(`No snapshot with id "${t.snapshotId}"`)}const f=n.data;const w=n.meta.baseline===true;const m=w?D().filter(r=>r.clear).map(r=>r.id):[...RESTORE_ORDER.filter(r=>r in f),...Object.keys(f).filter(r=>!RESTORE_ORDER.includes(r))];const c=[];for(const r of m){if(!g(r))continue;await new Promise(h=>setTimeout(h,0));if(!i())return;const y=P(r);const l=y?.label??r;try{const h=w?void 0:I(f[r]);const b=a===null?void 0:r in a?I(a[r]):void 0;let S;if(!y){S={items:[{key:r,label:l,verdict:"wont-apply",reason:"tool not installed \u2014 restore skips this source"}],notes:[]}}else if(y.previewItems){S=await y.previewItems(h,b)}else{const R=z(b,h);S={items:[{key:r,label:l,verdict:R.equal?"unchanged":"changed",oldValue:b,newValue:h}],notes:R.truncated?["diff truncated (large value)"]:[]}}if(!i())return;c.push({id:r,label:l,...S})}catch(h){c.push({id:r,label:l,items:[],notes:[],error:String(h)})}s({left:e,right:t,building:true,builtAt:Date.now(),sources:[...c]})}if(!i())return;s({left:e,right:t,building:false,builtAt:Date.now(),sources:c})}catch(a){if(!i())return;s({left:e,right:t,building:false,builtAt:Date.now(),sources:[{id:"error",label:"Preview",items:[],notes:[],error:String(a)}]})}}}export const timeMachineStore=new Z;export function setRemoteTimeMachineHandler(o){u=o;if(!o){timeMachineStore.replaceFromSnapshot({})}}export function replaceTimeMachineFromSnapshot(o){timeMachineStore.replaceFromSnapshot(o)}
@@ -1 +1 @@
1
- "use strict";import{getStateSnapshotProviders as f,subscribeToStateSnapshotProviders as m,superJsonDeserialize as E}from"@buoy-gg/shared-ui";import{jsonLikelyLargerThan as p}from"@buoy-gg/shared-ui/dataViewer";import{timeMachineStore as s}from"../store/timeMachineStore";import{loadSnapshot as b}from"../store/snapshotVault";import{canNavigate as y,currentRoute as S}from"../store/routeRestore";import{isSourceEnabled as w}from"../store/sourceSettings";import{ROUTE_SOURCE_ID as v}from"../store/sourceIds";function R(){return f().map(t=>{const e=t.status();return{id:t.id,label:t.label,canCapture:e.canCapture,canRestore:e.canRestore,detail:e.detail,enabled:w(t.id)}})}function h(){const{snapshots:t,busy:e,lastOutcome:r}=s.getState();const o=S();return{snapshots:t,busy:e,lastOutcome:r,providers:R(),route:{available:y(),enabled:w(v),...o?{current:o.href}:{}}}}export const timeMachineSyncAdapter={version:2,getSnapshot:()=>h(),subscribe:t=>{const e=s.subscribe(t);const r=m(t);return()=>{e();r()}},actions:{list:()=>h(),capture:async t=>{const{name:e="",sourceIds:r}=t??{};const o=await s.capture(e,r);return{captured:true,snapshot:o}},captureBaseline:async()=>{const t=await s.captureBaseline();return{captured:true,snapshot:t}},wipeAll:async()=>await s.wipeAll(),restore:async t=>{const{id:e,mode:r="live",excludeKeys:o,restoreRoute:n}=t??{};if(!e)throw new Error("restore requires a snapshot `id`");return await s.restore(e,r,o,{restoreRoute:n})},delete:async t=>{const{id:e}=t??{};if(!e)throw new Error("delete requires a snapshot `id`");await s.delete(e);return{deleted:true,id:e}},rename:async t=>{const{id:e,name:r}=t??{};if(!e||!r)throw new Error("rename requires `id` and `name`");await s.rename(e,r);return{renamed:true,id:e,name:r}},setExclusions:async t=>{const{id:e,excludedKeys:r}=t??{};if(!e)throw new Error("setExclusions requires `id`");await s.setExclusions(e,r??null);return{id:e,excluded:r?.length??0}},setRestoreRoute:async t=>{const{id:e,restoreRoute:r}=t??{};if(!e)throw new Error("setRestoreRoute requires `id`");await s.setRestoreRoute(e,r!==false);return{id:e,restoreRoute:r!==false}},duplicate:async t=>{const{id:e}=t??{};if(!e)throw new Error("duplicate requires `id`");const r=await s.duplicate(e);if(!r)throw new Error(`No snapshot with id "${e}"`);return{snapshot:r}},setScope:async t=>{const{id:e,scope:r}=t??{};if(!e)throw new Error("setScope requires a snapshot `id`");await s.setScope(e,r??null);return{scoped:true,id:e,count:r?.length??0}},preview:async t=>{const{id:e,compareTo:r}=t??{};if(!e)throw new Error("preview requires a snapshot `id`");const o={snapshotId:e};const n=r?{snapshotId:r}:"current";await s.buildPreview(o,n);const i=s.getState().preview;if(!i)throw new Error("preview build produced no result");const u=4*1024;return{left:n,right:o,builtAt:i.builtAt,sources:i.sources.map(c=>({...c,items:c.items.map(a=>{const d=a.oldValue!==void 0&&p(a.oldValue,u);const l=a.newValue!==void 0&&p(a.newValue,u);return{...a,oldValue:d?void 0:a.oldValue,newValue:l?void 0:a.newValue,...d||l?{valueOmitted:true}:{}}})}))}},inspect:async t=>{const{id:e,sourceId:r}=t??{};if(!e||!r){throw new Error("inspect requires `id` and `sourceId`")}const o=await b(e);if(!o)throw new Error(`No snapshot with id "${e}"`);const n=o.data[r];if(!n){throw new Error(`Snapshot "${e}" has no "${r}" source`)}return{id:e,sourceId:r,warnings:o.meta.sources[r]?.warnings??[],data:E(n)}}}};
1
+ "use strict";import{getStateSnapshotProviders as m,subscribeToStateSnapshotProviders as f,superJsonDeserialize as E}from"@buoy-gg/shared-ui";import{jsonLikelyLargerThan as p}from"@buoy-gg/shared-ui/dataViewer";import{timeMachineStore as o}from"../store/timeMachineStore";import{loadSnapshot as y}from"../store/snapshotVault";import{canNavigate as b,currentRoute as S}from"../store/routeRestore";import{isSourceEnabled as w}from"../store/sourceSettings";import{ROUTE_SOURCE_ID as R}from"../store/sourceIds";function v(){return m().map(t=>{const e=t.status();return{id:t.id,label:t.label,canCapture:e.canCapture,canRestore:e.canRestore,detail:e.detail,enabled:w(t.id)}})}function h(){const{snapshots:t,busy:e,lastOutcome:r}=o.getState();const s=S();return{snapshots:t,busy:e,lastOutcome:r,providers:v(),route:{available:b(),enabled:w(R),...s?{current:s.href}:{}}}}export const timeMachineSyncAdapter={version:2,getSnapshot:()=>h(),subscribe:t=>{const e=o.subscribe(t);const r=f(t);return()=>{e();r()}},actions:{list:()=>h(),capture:async t=>{const{name:e="",sourceIds:r}=t??{};const s=await o.capture(e,r);return{captured:true,snapshot:s}},captureBaseline:async()=>{const t=await o.captureBaseline();return{captured:true,snapshot:t}},wipeAll:async()=>await o.wipeAll(),restore:async t=>{const{id:e,mode:r="live",excludeKeys:s,restoreRoute:n}=t??{};if(!e)throw new Error("restore requires a snapshot `id`");return await o.restore(e,r,s,{restoreRoute:n})},delete:async t=>{const{id:e}=t??{};if(!e)throw new Error("delete requires a snapshot `id`");await o.delete(e);return{deleted:true,id:e}},rename:async t=>{const{id:e,name:r}=t??{};if(!e||!r)throw new Error("rename requires `id` and `name`");await o.rename(e,r);return{renamed:true,id:e,name:r}},setExclusions:async t=>{const{id:e,excludedKeys:r}=t??{};if(!e)throw new Error("setExclusions requires `id`");await o.setExclusions(e,r??null);return{id:e,excluded:r?.length??0}},setRestoreRoute:async t=>{const{id:e,restoreRoute:r}=t??{};if(!e)throw new Error("setRestoreRoute requires `id`");if(typeof r!=="boolean"){throw new Error("setRestoreRoute requires `restoreRoute` (true or false)")}await o.setRestoreRoute(e,r);return{id:e,restoreRoute:r}},duplicate:async t=>{const{id:e}=t??{};if(!e)throw new Error("duplicate requires `id`");const r=await o.duplicate(e);if(!r)throw new Error(`No snapshot with id "${e}"`);return{snapshot:r}},setScope:async t=>{const{id:e,scope:r}=t??{};if(!e)throw new Error("setScope requires a snapshot `id`");await o.setScope(e,r??null);return{scoped:true,id:e,count:r?.length??0}},preview:async t=>{const{id:e,compareTo:r}=t??{};if(!e)throw new Error("preview requires a snapshot `id`");const s={snapshotId:e};const n=r?{snapshotId:r}:"current";const i=await o.computePreview(s,n);const u=4*1024;return{left:n,right:s,builtAt:i.builtAt,sources:i.sources.map(c=>({...c,items:c.items.map(a=>{const d=a.oldValue!==void 0&&p(a.oldValue,u);const l=a.newValue!==void 0&&p(a.newValue,u);return{...a,oldValue:d?void 0:a.oldValue,newValue:l?void 0:a.newValue,...d||l?{valueOmitted:true}:{}}})}))}},inspect:async t=>{const{id:e,sourceId:r}=t??{};if(!e||!r){throw new Error("inspect requires `id` and `sourceId`")}const s=await y(e);if(!s)throw new Error(`No snapshot with id "${e}"`);const n=s.data[r];if(!n){throw new Error(`Snapshot "${e}" has no "${r}" source`)}return{id:e,sourceId:r,warnings:s.meta.sources[r]?.warnings??[],data:E(n)}}}};
@@ -1,10 +1,5 @@
1
- import type { RestoreOutcome } from "../../store/timeMachineStore";
2
- /**
3
- * Did this restore do anything the app itself won't show you? Warnings alone
4
- * don't count — "1 derived atom recomputes" is true of every restore and
5
- * would put the card back on screen permanently.
6
- */
7
- export declare function restoreNeedsAttention(outcome: RestoreOutcome): boolean;
1
+ import { restoreNeedsAttention, type RestoreOutcome } from "../../store/timeMachineStore";
2
+ export { restoreNeedsAttention };
8
3
  export declare function RestoreOutcomeCard({ outcome }: {
9
4
  outcome: RestoreOutcome;
10
5
  }): import("react").JSX.Element;
@@ -57,6 +57,18 @@ export interface RestoreOptions {
57
57
  safetyCapture?: boolean;
58
58
  }
59
59
  export declare const SAFETY_SNAPSHOT_NAME = "Before last restore";
60
+ /**
61
+ * Did this restore do anything the app itself won't show you? Warnings alone
62
+ * don't count — "1 derived atom recomputes" is true of every restore and
63
+ * would put the outcome card back on screen permanently.
64
+ */
65
+ export declare function restoreNeedsAttention(outcome: RestoreOutcome): boolean;
66
+ /**
67
+ * May the tool minimize itself after this list restore? Only when nothing
68
+ * needs reading: a skipped item or a failed route is reported on the outcome
69
+ * card, and docking would hide the only place that says so.
70
+ */
71
+ export declare function shouldDockAfterRestore(outcome: RestoreOutcome): boolean;
60
72
  /** Provider capability row as mirrored to a remote dashboard. */
61
73
  export interface RemoteProviderStatus {
62
74
  id: string;
@@ -157,6 +169,14 @@ declare class TimeMachineStore {
157
169
  */
158
170
  restore(id: string, mode: RestoreMode, excludeKeys?: readonly string[], options?: RestoreOptions): Promise<RestoreOutcome>;
159
171
  private restoreSource;
172
+ /** Wipe every clearable source that is still switched on in Sources. */
173
+ private clearEnabledSources;
174
+ /**
175
+ * The header's plain "Reload app". Refused while a restore is still
176
+ * writing: reloading then would kill the realm halfway through and leave
177
+ * the app with part old state, part new. Returns whether it reloaded.
178
+ */
179
+ reloadApp(): boolean;
160
180
  private scheduleReload;
161
181
  /**
162
182
  * Delete, holding the whole record in memory so `undoDelete` can put it
@@ -200,6 +220,18 @@ declare class TimeMachineStore {
200
220
  * never freezes the JS thread in one go.
201
221
  */
202
222
  buildPreview(right: PreviewSideRef, left?: PreviewSideRef): Promise<void>;
223
+ /**
224
+ * Build a preview without showing it: what the MCP and Buoy Desktop
225
+ * `preview` action returns. It never touches `state.preview`, so a remote
226
+ * caller can't replace the preview open on the phone.
227
+ */
228
+ computePreview(right: PreviewSideRef, left?: PreviewSideRef): Promise<PreviewState>;
229
+ /**
230
+ * The preview pipeline. `publish` receives every partial and the final
231
+ * result; `live` says whether this run still counts, checked after every
232
+ * await so a superseded build abandons itself.
233
+ */
234
+ private runPreview;
203
235
  }
204
236
  export declare const timeMachineStore: TimeMachineStore;
205
237
  /**
package/lib/web/index.mjs CHANGED
@@ -1,3 +1,3 @@
1
- "use client";var br=Object.defineProperty;var No=Object.getOwnPropertyDescriptor;var Mo=Object.getOwnPropertyNames;var Vo=Object.prototype.hasOwnProperty;var Fo=(e,t)=>{for(var r in t)br(e,r,{get:t[r],enumerable:true})},wr=(e,t,r,i)=>{if(t&&typeof t=="object"||typeof t=="function")for(let n of Mo(t))!Vo.call(e,n)&&n!==r&&br(e,n,{get:()=>t[n],enumerable:!(i=No(t,n))||i.enumerable});return e},Ko=(e,t,r)=>(wr(e,t,"default"),r&&wr(r,t,"default"));var vr=(()=>{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 _o,getSafeRouter as Sr,persistentStorage as zt}from"@buoy-gg/shared-ui/web";var $t="@react_buoy_time_machine:pending-route",qo=6e4,Jo=8e3,Uo=250;function Go(e){return{pathname:e.pathname,href:e.href}}function at(){let e=_o();return e?Go(e):null}function Yo(){return at()}function Be(){return Sr()!=null}function Lt(e){let t={pathname:e.pathname,href:e.href},r=Sr();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 Qo(e,t){let r={...e,savedAt:Date.now(),...t?{snapshotName:t}:{}};await zt.setItem($t,JSON.stringify(r))}async function Xo(){try{await zt.removeItem($t)}catch{}}async function Zo(){try{let e=await zt.getItem($t);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 xr=false;function Ir(){xr||(xr=true,(async()=>{let e=await Zo();if(!e||(await Xo(),Date.now()-e.savedAt>qo))return;let t=Date.now()+Jo;for(;!Be()&&Date.now()<t;)await new Promise(r=>setTimeout(r,100));Be()&&(await new Promise(r=>setTimeout(r,Uo)),Lt({pathname:e.pathname,href:e.href}))})())}var Rr={};Fo(Rr,{AccessibilityInfo:()=>on,ActivityIndicator:()=>ct,Alert:()=>Hr,Animated:()=>We,AppRegistry:()=>an,AppState:()=>sn,Appearance:()=>nn,BackHandler:()=>ln,Button:()=>Qn,CheckBox:()=>Sn,Clipboard:()=>cn,DeviceEventEmitter:()=>On,Dimensions:()=>dn,Easing:()=>un,FlatList:()=>Tr,I18nManager:()=>hn,Image:()=>xn,ImageBackground:()=>In,InteractionManager:()=>pn,Keyboard:()=>kr,KeyboardAvoidingView:()=>Cr,LayoutAnimation:()=>mn,Linking:()=>fn,LogBox:()=>Pn,Modal:()=>Or,NativeEventEmitter:()=>gn,NativeModules:()=>rn,PanResponder:()=>Dr,Picker:()=>Rn,PixelRatio:()=>yn,Platform:()=>st,Pressable:()=>Pt,ProgressBar:()=>kn,RefreshControl:()=>Dn,SafeAreaView:()=>Tn,ScrollView:()=>Ot,SectionList:()=>Cn,Share:()=>bn,StatusBar:()=>zn,StyleSheet:()=>P,Switch:()=>Yn,Text:()=>d,TextInput:()=>lt,Touchable:()=>$n,TouchableHighlight:()=>Un,TouchableNativeFeedback:()=>Ln,TouchableOpacity:()=>E,TouchableWithoutFeedback:()=>Gn,UIManager:()=>wn,Vibration:()=>vn,View:()=>h,VirtualizedList:()=>En,YellowBox:()=>An,findNodeHandle:()=>Xn,unstable_createElement:()=>tn,useColorScheme:()=>Hn,useLocaleContext:()=>Bn,useWindowDimensions:()=>zr});Ko(Rr,en);import*as en from"react-native-web";import{unstable_createElement as tn,NativeModules as rn,AccessibilityInfo as on,Appearance as nn,AppRegistry as an,AppState as sn,BackHandler as ln,Clipboard as cn,Dimensions as dn,Easing as un,I18nManager as hn,Keyboard as kr,InteractionManager as pn,LayoutAnimation as mn,Linking as fn,NativeEventEmitter as gn,PanResponder as Dr,PixelRatio as yn,Platform as st,Share as bn,UIManager as wn,Vibration as vn,CheckBox as Sn,FlatList as Tr,Image as xn,ImageBackground as In,KeyboardAvoidingView as Cr,Picker as Rn,ProgressBar as kn,RefreshControl as Dn,SafeAreaView as Tn,SectionList as Cn,StatusBar as zn,Touchable as $n,TouchableNativeFeedback as Ln,VirtualizedList as En,YellowBox as An,LogBox as Pn,DeviceEventEmitter as On,useColorScheme as Hn,useLocaleContext as Bn,useWindowDimensions as zr}from"react-native-web";import*as J from"react-native-web";import{createElement as Et,forwardRef as $r,useCallback as jn,useRef as Wn}from"react";import{useEffect as Nn,useState as Mn}from"react";import{createPortal as Vn}from"react-dom";var Fn='-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif';import{jsx as Kn}from"react/jsx-runtime";var je=Symbol.for("@buoy-gg/portal-host"),Lr=e=>{if(!(e instanceof Element))return false;if(e.closest("input, textarea, select"))return true;let t=e.closest("[contenteditable]")?.getAttribute("contenteditable")?.toLowerCase();return t===""||t==="true"||t==="plaintext-only"};function Er(){let e=document;if(e[je])return e[je].host;let t=document.createElement("div");t.dataset.buoyPortalHost="",Object.assign(t.style,{position:"fixed",inset:"0",zIndex:"2147483647",pointerEvents:"none",fontFamily:Fn});let r=()=>{let l=document.fullscreenElement,p=l&&l.tagName!=="CANVAS"?l:document.body;t.parentElement!==p&&p.appendChild(t)},i=new Map,n=l=>{(!t.contains(l.target)||!Lr(l.target))&&i.set(l.code||l.key,{key:l.key,code:l.code,location:l.location,keyCode:l.keyCode,which:l.which,altKey:l.altKey,ctrlKey:l.ctrlKey,metaKey:l.metaKey,shiftKey:l.shiftKey})},a=l=>{i.delete(l.code||l.key)},s=()=>i.clear(),f=()=>{let l=[...i.values()];i.clear();for(let p of l)document.dispatchEvent(new KeyboardEvent("keyup",{...p,bubbles:true}))},u=l=>{Lr(l.target)&&l.stopPropagation()},g=l=>l.stopPropagation();return r(),document.addEventListener("fullscreenchange",r),document.addEventListener("keydown",n,true),document.addEventListener("keyup",a,true),window.addEventListener("blur",s),t.addEventListener("focusin",f),t.addEventListener("keydown",u),t.addEventListener("keyup",u),t.addEventListener("keypress",u),t.addEventListener("wheel",g,{passive:true}),e[je]={host:t,users:0,dispose:()=>{document.removeEventListener("fullscreenchange",r),document.removeEventListener("keydown",n,true),document.removeEventListener("keyup",a,true),window.removeEventListener("blur",s),t.remove(),delete e[je]}},t}function _n({children:e}){let[t,r]=Mn(null);return Nn(()=>{let i=Er(),n=document[je];return n.users++,r(i),()=>{--n.users===0&&n.dispose()}},[]),t?Vn(Kn("div",{"data-buoy-root":"",style:{display:"contents",pointerEvents:"auto"},children:e}),t):null}var $e=J,qn=["shadowColor","shadowOffset","shadowOpacity","shadowRadius","textShadowColor","textShadowOffset","textShadowRadius"],Le=e=>typeof e=="number"?`${e}px`:e;function At(e){if(Array.isArray(e)){let p=e.map(At);return p.some((z,m)=>z!==e[m])?p:e}if(!e||typeof e!="object"||!qn.some(p=>e[p]!=null))return e;let{shadowColor:t,shadowOffset:r,shadowOpacity:i,shadowRadius:n,textShadowColor:a,textShadowOffset:s,textShadowRadius:f,...u}=e;if(t!=null||r!=null||i!=null||n!=null){let p=t??"black",z=i==null?p:`color-mix(in srgb, ${p} ${Math.min(i,1)*100}%, transparent)`,m=`${Le(r?.width??0)} ${Le(r?.height??0)} ${Le(n??0)} ${z}`;u.boxShadow=typeof u.boxShadow=="string"?`${u.boxShadow}, ${m}`:u.boxShadow??m}let{width:g=0,height:l=0}=s??{};if(a&&(g||l||f)){let p=`${Le(g)} ${Le(l)} ${Le(f??0)} ${a}`;u.textShadow=u.textShadow?`${u.textShadow}, ${p}`:p}return u}var Jn=$e.StyleSheet.create({auto:{pointerEvents:"auto"},none:{pointerEvents:"none"},"box-none":{pointerEvents:"box-none"},"box-only":{pointerEvents:"box-only"}});function Ar(e,t){if(typeof e=="function")return i=>Ar(e(i),t);let r=At(e);return t?[r,Jn[t]]:r}var P={...$e.StyleSheet,create:e=>$e.StyleSheet.create(Object.fromEntries(Object.entries(e).map(([t,r])=>[t,At(r)])))};function X(e){let t=$r((i,n)=>{let{accessibilityState:a,accessibilityValue:s,pointerEvents:f,...u}=i;for(let l of["busy","checked","disabled","expanded","selected"])a?.[l]!==void 0&&u[`aria-${l}`]===void 0&&(u[`aria-${l}`]=a[l]);for(let[l,p]of Object.entries({min:"valuemin",max:"valuemax",now:"valuenow",text:"valuetext"}))s?.[l]!==void 0&&u[`aria-${p}`]===void 0&&(u[`aria-${p}`]=s[l]);let g=Ar(u.style,f);return g!==u.style&&(u.style=g),Et(e,{...u,ref:n})}),r=e.State;return r&&Object.assign(t,{State:r}),t.displayName=e.displayName??e.name??"NativeWebView",t}var h=X(J.View),d=X(J.Text),We={...$e.Animated,View:$e.Animated.createAnimatedComponent(h),Text:$e.Animated.createAnimatedComponent(d)},lt=X(J.TextInput),E=X(J.TouchableOpacity),Un=X(J.TouchableHighlight),Gn=X(J.TouchableWithoutFeedback),Pt=X(J.Pressable),Ot=X(J.ScrollView),Pr=$r((e,t)=>{let r=Wn(null),i=jn(n=>{if(n){let a=n;for(;a.parentElement&&a.parentElement!==document.body;)a=a.parentElement;a.parentElement===document.body&&(r.current=a,Object.assign(a.style,{position:"relative",zIndex:"2147483647",pointerEvents:"auto"}),Er().appendChild(a))}else r.current&&(document.body.appendChild(r.current),r.current=null);typeof t=="function"?t(n):t&&(t.current=n)},[t]);return Et(_n,null,Et(J.Modal,{...e,ref:i}))});Pr.displayName="Modal";var Or=X(Pr),Yn=X(J.Switch),ct=X(J.ActivityIndicator),Qn=X(J.Button),Xn=J.findNodeHandle,Hr={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 g=document.createElement("p");g.textContent=t,g.style.cssText="line-height:1.5;white-space:pre-wrap;margin:0 0 20px",n.appendChild(g)}let s=document.createElement("div");s.style.cssText="display:flex;justify-content:flex-end;flex-wrap:wrap;gap:8px";let f=r?.length?r:[{text:"OK"}],u=()=>{n.close?.(),n.remove()};for(let g of f){let l=document.createElement("button");l.type="button",l.textContent=g.text??"OK",l.style.cssText=`padding:9px 14px;border:1px solid #64748b;border-radius:7px;color:white;background:${g.style==="destructive"?"#a52b38":"#283a4d"};cursor:pointer;font:inherit`,l.onclick=()=>{u(),g.onPress?.()},s.appendChild(l)}n.addEventListener("cancel",g=>{g.preventDefault(),i?.cancelable!==false&&(u(),i?.onDismiss?.())}),n.appendChild(s),document.body.appendChild(n),n.showModal?n.showModal():n.setAttribute("open","")}};import{TimeMachineIcon as Zn,TIME_MACHINE_ICON_COLOR as ei}from"@buoy-gg/shared-ui/web";import{useRef as ti,useState as Br,useSyncExternalStore as jr}from"react";import{useSafeAreaInsets as ri,useLimit as oi,ToolEmptyState as ni,getFloatingTools as ii,subscribeFloatingTools as ai}from"@buoy-gg/shared-ui/web";import{useToolHost as si}from"@buoy-gg/core/web";import{useEffect as li,useState as ci,useSyncExternalStore as di}from"react";import{getStateSnapshotProviders as Ht,subscribeToStateSnapshotProviders as ui}from"@buoy-gg/shared-ui/web";import{getStateSnapshotProvider as Wr,getStateSnapshotProviders as dt,scheduleReloadApp as hi,superJsonDeserialize as Bt,superJsonSerialize as pi}from"@buoy-gg/shared-ui/web";import{objectDiff as mi}from"@buoy-gg/shared-ui/web/dataViewer";import{persistentStorage as me}from"@buoy-gg/shared-ui/web";var jt="@react_buoy_time_machine:index",Ne="@react_buoy_time_machine:snap:";async function fi(){try{let e=await me.getItem(jt);if(!e)return[];let t=JSON.parse(e);return Array.isArray(t)?t:[]}catch{return[]}}async function Wt(e){await me.setItem(jt,JSON.stringify(e))}async function ut(e,t){let r=JSON.stringify(e);e.meta.sizeBytes=r.length,await me.setItem(Ne+e.meta.id,JSON.stringify(e));let i=[e.meta,...t.filter(n=>n.id!==e.meta.id)];return await Wt(i),i}async function fe(e){try{let t=await me.getItem(Ne+e);return t?JSON.parse(t):null}catch{return null}}async function Nr(e,t){await me.removeItem(Ne+e);let r=t.filter(i=>i.id!==e);return await Wt(r),r}async function ht(e,t,r){let i=s=>s.id===e?t(s):s,n=r.map(i);await me.setItem(jt,JSON.stringify(n));let a=await fe(e);return a&&(a.meta=i(a.meta),await me.setItem(Ne+e,JSON.stringify(a))),n}function gi(e,t,r){return ht(e,i=>{let n={...i};return t&&t.length>0?n.scope=t:delete n.scope,n},r)}function yi(e,t,r){return ht(e,i=>{let n={...i};return delete n.scope,t&&t.length>0?n.excludedKeys=t:delete n.excludedKeys,n},r)}function bi(e,t,r){return ht(e,i=>({...i,restoreRoute:t}),r)}function Mr(e,t,r){return ht(e,i=>({...i,lastRestoredAt:t}),r)}async function wi(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 ut(n,r),meta:n.meta}}async function vi(e){return fe(e)}async function Si(e,t){return ut(e,t)}async function xi(e,t,r){let i=r.map(a=>a.id===e?{...a,name:t}:a);await Wt(i);let n=await fe(e);return n&&(n.meta.name=t,await me.setItem(Ne+e,JSON.stringify(n))),i}import{definePersistedSetting as Ii,devToolsStorageKeys as Ri}from"@buoy-gg/shared-ui/web";var Vr=Ii(Ri.timeMachine.disabledSources(),[],{sanitize:e=>Array.isArray(e)?e.filter(t=>typeof t=="string"):[]}),xe=new Set,Fr=false,Nt=null,Mt=new Set,Kr=()=>Mt.forEach(e=>e());function ae(){return Fr?Promise.resolve():(Nt||(Nt=Vr.load().then(e=>{xe.size===0&&(xe=new Set(e),Kr())}).finally(()=>{Fr=true})),Nt)}function _r(e){return Mt.add(e),()=>{Mt.delete(e)}}function qr(){return xe}function se(e){return!xe.has(e)}function Jr(e,t){if(t===!xe.has(e))return;let r=new Set(xe);t?r.delete(e):r.add(e),xe=r,Kr(),Vr.save([...r])}var Me="route";var Ve=["storage","redux","zustand","jotai","query"];function ki(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 Di(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 pt(e){return!!e.route&&(e.restoreRoute??true)}var Vt="Before last restore",A=null;function Fe(e){return{ok:false,applied:0,skipped:[{id:"*",reason:e}],warnings:[]}}var Ur=0;function Gr(){return Ur+=1,`snap_${Date.now().toString(36)}_${Ur.toString(36)}`}var Ti=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=fi().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=dt().filter(l=>l.status().canCapture&&se(l.id)&&(!t||t.includes(l.id))),n={},a={};for(let l of i)try{let p=await l.capture();n[l.id]=pi(p.data),a[l.id]={warnings:p.warnings}}catch(p){a[l.id]={warnings:[`capture failed: ${String(p)}`]}}let s=se(Me)?at():null,f=this.state.snapshots;if(r?.safety)for(let l of f.filter(p=>p.safety))f=await Nr(l.id,f);let u={meta:{id:Gr(),name:r?.safety?Vt:Di(e.trim()||ki(s),f),createdAt:Date.now(),sizeBytes:0,...s?{route:s}:{},...r?.safety?{safety:true}:{},sources:a},data:n},g=await ut(u,f);return this.setState({snapshots:g}),u.meta}finally{this.setState({busy:null})}}async captureBaseline(){if(A)return(await A("captureBaseline",{})).snapshot;await this.ensureLoaded(),await ae();let e={meta:{id:Gr(),name:"Fresh install",createdAt:Date.now(),sizeBytes:0,baseline:true,sources:{}},data:{}},t=await ut(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(Vt,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 m of dt())if(m.clear)try{s.results[m.id]=await m.clear()}catch(O){s.results[m.id]=Fe(String(O))}return s.willReload=this.scheduleReload("buoy time-machine baseline"),this.setState({lastOutcome:s}),s}let f=[...Ve.filter(m=>m in a.data),...Object.keys(a.data).filter(m=>!Ve.includes(m))],u=m=>{let O=new Map;for(let j of m){let W=j.indexOf("::");if(W<=0)continue;let v=j.slice(0,W),U=j.slice(W+2),ee=O.get(v)??[];ee.push(U),O.set(v,ee)}return O},g=r??a.meta.excludedKeys??[],l=u(g),p=!r&&a.meta.scope?.length?u(a.meta.scope):null,z=se(Me)&&(i?.restoreRoute??pt(a.meta));if(t==="reload"){if(a.data.storage&&se("storage")&&(!p||p.has("storage"))&&(s.results.storage=await this.restoreSource("storage",a.data.storage,l.get("storage"),p?.get("storage"))),z){let m=a.meta.route;try{await Qo(m,a.meta.name),s.route={...m,status:"deferred"}}catch(O){s.route={...m,status:"failed",error:String(O)}}}return s.willReload=this.scheduleReload("buoy time-machine restore"),this.setState({lastOutcome:s,snapshots:await Mr(e,s.at,this.state.snapshots)}),s}for(let m of f)if(!(p&&!p.has(m))){if(!se(m)){s.results[m]={ok:true,applied:0,skipped:[],warnings:["Switched off in Sources; left as it is"]};continue}s.results[m]=await this.restoreSource(m,a.data[m],l.get(m),p?.get(m))}return z&&(s.route=Lt(a.meta.route)),this.setState({lastOutcome:s,snapshots:await Mr(e,s.at,this.state.snapshots)}),s}finally{this.setState({busy:null})}}async restoreSource(e,t,r,i){let n=Wr(e);if(!n)return Fe("provider not available (package missing or not initialized)");let a=n.status();if(!a.canRestore)return Fe(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(Bt(t),s)}catch(s){return Fe(String(s))}}scheduleReload(e){try{return hi({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 vi(e),r=await Nr(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 Si(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 bi(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 wi(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 xi(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 gi(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 yi(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 dt())if(t.clear)try{e.results[t.id]=await t.clear()}catch(r){e.results[t.id]=Fe(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,f=a.meta.baseline===true,u=f?dt().filter(l=>l.clear).map(l=>l.id):[...Ve.filter(l=>l in s),...Object.keys(s).filter(l=>!Ve.includes(l))],g=[];for(let l of u){if(!se(l))continue;if(await new Promise(m=>setTimeout(m,0)),r!==this.previewRunId)return;let p=Wr(l),z=p?.label??l;try{let m=f?void 0:Bt(s[l]),O=n===null?void 0:l in n?Bt(n[l]):void 0,j;if(!p)j={items:[{key:l,label:z,verdict:"wont-apply",reason:"tool not installed \u2014 restore skips this source"}],notes:[]};else if(p.previewItems)j=await p.previewItems(m,O);else{let W=mi(O,m);j={items:[{key:l,label:z,verdict:W.equal?"unchanged":"changed",oldValue:O,newValue:m}],notes:W.truncated?["diff truncated (large value)"]:[]}}if(r!==this.previewRunId)return;g.push({id:l,label:z,...j})}catch(m){g.push({id:l,label:z,items:[],notes:[],error:String(m)})}this.setState({preview:{left:t,right:e,building:true,builtAt:Date.now(),sources:[...g]}})}if(r!==this.previewRunId)return;this.setState({preview:{left:t,right:e,building:false,builtAt:Date.now(),sources:g}})}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)}]}})}}},x=new Ti;function Ci(e){A=e,e||x.replaceFromSnapshot({})}function zi(e){x.replaceFromSnapshot(e)}function mt(){return di(x.subscribe,()=>x.getState())}function Yr(){let[e,t]=ci(Ht);return li(()=>(t(Ht()),ui(()=>t(Ht()))),[]),e}import{Children as $i}from"react";import{ChevronRight as Li}from"@buoy-gg/shared-ui/web";import{night as N}from"@buoy-gg/shared-ui/web";import{monoFont as Ei}from"@buoy-gg/shared-ui/web";var Ft="2E",Ai="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}${Ft}`,accentSoftStrong:`${N.color.accent}${Ai}`,onAccent:"#0A0A0A",warning:N.color.warning,warningSoft:`${N.color.warning}${Ft}`,danger:N.color.danger,dangerSoft:`${N.color.danger}${Ft}`,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},ft=Ei;import{jsx as Ie,jsxs as Pi}from"react/jsx-runtime";function gt({children:e,testID:t}){return Ie(d,{style:ge.sectionLabel,testID:t,children:e})}function Ke({children:e,centered:t,tone:r="secondary",testID:i}){return Ie(d,{style:[ge.footnote,t?ge.footnoteCentered:null,r==="warning"?ge.footnoteWarning:null],testID:i,children:e})}function yt({children:e,style:t}){let r=$i.toArray(e);return Ie(h,{style:[ge.group,t],children:r.map((i,n)=>Pi(h,{children:[n>0?Ie(h,{style:ge.separator}):null,i]},i.key??n))})}function Qr(){return Ie(Li,{size:16,color:o.color.labelTertiary})}function Oi({label:e,color:t,background:r,testID:i}){return Ie(h,{style:[ge.pill,{backgroundColor:r}],children:Ie(d,{style:[ge.pillText,{color:t}],testID:i,children:e})})}var ge=P.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:P.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 Hi,QueryIcon as Bi,ReduxIcon as ji,RoutesIcon as Wi,StorageIcon as Ni,TimeMachineIcon as Mi,ZustandIcon as Vi}from"@buoy-gg/floating-tools-core/web";import{useSyncExternalStore as Fi}from"react";var Ki={storage:Ni,redux:ji,zustand:Vi,jotai:Hi,query:Bi,route:Wi};function _i(e){return Ki[e]??Mi}function qi(){let{remoteProviders:e,remoteRoute:t}=mt(),r=Yr(),i=Fi(_r,qr,qr),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:Be();return[...n,{id:Me,label:"Route",canCapture:a,canRestore:a,enabled:e?t?.enabled!==false:!i.has(Me),detail:a?"Recorded with every snapshot \u2014 a restore can take you back":"No Expo Router detected \u2014 snapshots record no route"}]}function Ji(e){let t=globalThis.confirm;return t?t(e):true}function Kt(e,t,r,i){if(st.OS==="web"){Ji(`${e}
1
+ "use client";var wr=Object.defineProperty;var Mo=Object.getOwnPropertyDescriptor;var Vo=Object.getOwnPropertyNames;var Fo=Object.prototype.hasOwnProperty;var Ko=(e,t)=>{for(var r in t)wr(e,r,{get:t[r],enumerable:true})},Sr=(e,t,r,n)=>{if(t&&typeof t=="object"||typeof t=="function")for(let i of Vo(t))!Fo.call(e,i)&&i!==r&&wr(e,i,{get:()=>t[i],enumerable:!(n=Mo(t,i))||n.enumerable});return e},_o=(e,t,r)=>(Sr(e,t,"default"),r&&Sr(r,t,"default"));var vr=(()=>{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 qo,getSafeRouter as xr,persistentStorage as Ct}from"@buoy-gg/shared-ui/web";var zt="@react_buoy_time_machine:pending-route",Jo=6e4,Uo=8e3,Go=250;function Xo(e){return{pathname:e.pathname,href:e.href}}function it(){let e=qo();return e?Xo(e):null}function Yo(){return it()}function He(){return xr()!=null}function $t(e){let t={pathname:e.pathname,href:e.href},r=xr();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(n){return{...t,status:"failed",error:String(n)}}}async function Qo(e,t){let r={...e,savedAt:Date.now(),...t?{snapshotName:t}:{}};await Ct.setItem(zt,JSON.stringify(r))}async function Zo(){try{await Ct.removeItem(zt)}catch{}}async function en(){try{let e=await Ct.getItem(zt);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 Ir=false;function Rr(){Ir||(Ir=true,(async()=>{let e=await en();if(!e||(await Zo(),Date.now()-e.savedAt>Jo))return;let t=Date.now()+Uo;for(;!He()&&Date.now()<t;)await new Promise(r=>setTimeout(r,100));He()&&(await new Promise(r=>setTimeout(r,Go)),$t({pathname:e.pathname,href:e.href}))})())}var kr={};Ko(kr,{AccessibilityInfo:()=>nn,ActivityIndicator:()=>lt,Alert:()=>Br,Animated:()=>We,AppRegistry:()=>sn,AppState:()=>ln,Appearance:()=>an,BackHandler:()=>cn,Button:()=>Qn,CheckBox:()=>xn,Clipboard:()=>dn,DeviceEventEmitter:()=>Hn,Dimensions:()=>un,Easing:()=>hn,FlatList:()=>Cr,I18nManager:()=>pn,Image:()=>In,ImageBackground:()=>Rn,InteractionManager:()=>mn,Keyboard:()=>Dr,KeyboardAvoidingView:()=>zr,LayoutAnimation:()=>fn,Linking:()=>gn,LogBox:()=>On,Modal:()=>Hr,NativeEventEmitter:()=>yn,NativeModules:()=>on,PanResponder:()=>Tr,Picker:()=>kn,PixelRatio:()=>bn,Platform:()=>at,Pressable:()=>Pt,ProgressBar:()=>Dn,RefreshControl:()=>Tn,SafeAreaView:()=>Cn,ScrollView:()=>Et,SectionList:()=>zn,Share:()=>wn,StatusBar:()=>$n,StyleSheet:()=>O,Switch:()=>Yn,Text:()=>d,TextInput:()=>st,Touchable:()=>Ln,TouchableHighlight:()=>Gn,TouchableNativeFeedback:()=>An,TouchableOpacity:()=>A,TouchableWithoutFeedback:()=>Xn,UIManager:()=>Sn,Vibration:()=>vn,View:()=>p,VirtualizedList:()=>Pn,YellowBox:()=>En,findNodeHandle:()=>Zn,unstable_createElement:()=>rn,useColorScheme:()=>Bn,useLocaleContext:()=>Wn,useWindowDimensions:()=>$r});_o(kr,tn);import*as tn from"react-native-web";import{unstable_createElement as rn,NativeModules as on,AccessibilityInfo as nn,Appearance as an,AppRegistry as sn,AppState as ln,BackHandler as cn,Clipboard as dn,Dimensions as un,Easing as hn,I18nManager as pn,Keyboard as Dr,InteractionManager as mn,LayoutAnimation as fn,Linking as gn,NativeEventEmitter as yn,PanResponder as Tr,PixelRatio as bn,Platform as at,Share as wn,UIManager as Sn,Vibration as vn,CheckBox as xn,FlatList as Cr,Image as In,ImageBackground as Rn,KeyboardAvoidingView as zr,Picker as kn,ProgressBar as Dn,RefreshControl as Tn,SafeAreaView as Cn,SectionList as zn,StatusBar as $n,Touchable as Ln,TouchableNativeFeedback as An,VirtualizedList as Pn,YellowBox as En,LogBox as On,DeviceEventEmitter as Hn,useColorScheme as Bn,useLocaleContext as Wn,useWindowDimensions as $r}from"react-native-web";import*as J from"react-native-web";import{createElement as Lt,forwardRef as Lr,useCallback as jn,useRef as Nn}from"react";import{useEffect as Mn,useState as Vn}from"react";import{createPortal as Fn}from"react-dom";var Kn='-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif';import{jsx as _n}from"react/jsx-runtime";var Be=Symbol.for("@buoy-gg/portal-host"),Ar=e=>{if(!(e instanceof Element))return false;if(e.closest("input, textarea, select"))return true;let t=e.closest("[contenteditable]")?.getAttribute("contenteditable")?.toLowerCase();return t===""||t==="true"||t==="plaintext-only"};function Pr(){let e=document;if(e[Be])return e[Be].host;let t=document.createElement("div");t.dataset.buoyPortalHost="",Object.assign(t.style,{position:"fixed",inset:"0",zIndex:"2147483647",pointerEvents:"none",fontFamily:Kn});let r=()=>{let c=document.fullscreenElement,u=c&&c.tagName!=="CANVAS"?c:document.body;t.parentElement!==u&&u.appendChild(t)},n=new Map,i=c=>{(!t.contains(c.target)||!Ar(c.target))&&n.set(c.code||c.key,{key:c.key,code:c.code,location:c.location,keyCode:c.keyCode,which:c.which,altKey:c.altKey,ctrlKey:c.ctrlKey,metaKey:c.metaKey,shiftKey:c.shiftKey})},a=c=>{n.delete(c.code||c.key)},s=()=>n.clear(),g=()=>{let c=[...n.values()];n.clear();for(let u of c)document.dispatchEvent(new KeyboardEvent("keyup",{...u,bubbles:true}))},h=c=>{Ar(c.target)&&c.stopPropagation()},m=c=>c.stopPropagation();return r(),document.addEventListener("fullscreenchange",r),document.addEventListener("keydown",i,true),document.addEventListener("keyup",a,true),window.addEventListener("blur",s),t.addEventListener("focusin",g),t.addEventListener("keydown",h),t.addEventListener("keyup",h),t.addEventListener("keypress",h),t.addEventListener("wheel",m,{passive:true}),e[Be]={host:t,users:0,dispose:()=>{document.removeEventListener("fullscreenchange",r),document.removeEventListener("keydown",i,true),document.removeEventListener("keyup",a,true),window.removeEventListener("blur",s),t.remove(),delete e[Be]}},t}function qn({children:e}){let[t,r]=Vn(null);return Mn(()=>{let n=Pr(),i=document[Be];return i.users++,r(n),()=>{--i.users===0&&i.dispose()}},[]),t?Fn(_n("div",{"data-buoy-root":"",style:{display:"contents",pointerEvents:"auto"},children:e}),t):null}var ze=J,Jn=["shadowColor","shadowOffset","shadowOpacity","shadowRadius","textShadowColor","textShadowOffset","textShadowRadius"],$e=e=>typeof e=="number"?`${e}px`:e;function At(e){if(Array.isArray(e)){let u=e.map(At);return u.some((z,w)=>z!==e[w])?u:e}if(!e||typeof e!="object"||!Jn.some(u=>e[u]!=null))return e;let{shadowColor:t,shadowOffset:r,shadowOpacity:n,shadowRadius:i,textShadowColor:a,textShadowOffset:s,textShadowRadius:g,...h}=e;if(t!=null||r!=null||n!=null||i!=null){let u=t??"black",z=n==null?u:`color-mix(in srgb, ${u} ${Math.min(n,1)*100}%, transparent)`,w=`${$e(r?.width??0)} ${$e(r?.height??0)} ${$e(i??0)} ${z}`;h.boxShadow=typeof h.boxShadow=="string"?`${h.boxShadow}, ${w}`:h.boxShadow??w}let{width:m=0,height:c=0}=s??{};if(a&&(m||c||g)){let u=`${$e(m)} ${$e(c)} ${$e(g??0)} ${a}`;h.textShadow=h.textShadow?`${h.textShadow}, ${u}`:u}return h}var Un=ze.StyleSheet.create({auto:{pointerEvents:"auto"},none:{pointerEvents:"none"},"box-none":{pointerEvents:"box-none"},"box-only":{pointerEvents:"box-only"}});function Er(e,t){if(typeof e=="function")return n=>Er(e(n),t);let r=At(e);return t?[r,Un[t]]:r}var O={...ze.StyleSheet,create:e=>ze.StyleSheet.create(Object.fromEntries(Object.entries(e).map(([t,r])=>[t,At(r)])))};function Q(e){let t=Lr((n,i)=>{let{accessibilityState:a,accessibilityValue:s,pointerEvents:g,...h}=n;for(let c of["busy","checked","disabled","expanded","selected"])a?.[c]!==void 0&&h[`aria-${c}`]===void 0&&(h[`aria-${c}`]=a[c]);for(let[c,u]of Object.entries({min:"valuemin",max:"valuemax",now:"valuenow",text:"valuetext"}))s?.[c]!==void 0&&h[`aria-${u}`]===void 0&&(h[`aria-${u}`]=s[c]);let m=Er(h.style,g);return m!==h.style&&(h.style=m),Lt(e,{...h,ref:i})}),r=e.State;return r&&Object.assign(t,{State:r}),t.displayName=e.displayName??e.name??"NativeWebView",t}var p=Q(J.View),d=Q(J.Text),We={...ze.Animated,View:ze.Animated.createAnimatedComponent(p),Text:ze.Animated.createAnimatedComponent(d)},st=Q(J.TextInput),A=Q(J.TouchableOpacity),Gn=Q(J.TouchableHighlight),Xn=Q(J.TouchableWithoutFeedback),Pt=Q(J.Pressable),Et=Q(J.ScrollView),Or=Lr((e,t)=>{let r=Nn(null),n=jn(i=>{if(i){let a=i;for(;a.parentElement&&a.parentElement!==document.body;)a=a.parentElement;a.parentElement===document.body&&(r.current=a,Object.assign(a.style,{position:"relative",zIndex:"2147483647",pointerEvents:"auto"}),Pr().appendChild(a))}else r.current&&(document.body.appendChild(r.current),r.current=null);typeof t=="function"?t(i):t&&(t.current=i)},[t]);return Lt(qn,null,Lt(J.Modal,{...e,ref:n}))});Or.displayName="Modal";var Hr=Q(Or),Yn=Q(J.Switch),lt=Q(J.ActivityIndicator),Qn=Q(J.Button),Zn=J.findNodeHandle,Br={alert(e,t,r,n){if(typeof document>"u")return;let i=document.createElement("dialog");i.dataset.buoyRoot="",i.setAttribute("aria-label",e),i.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",i.appendChild(a),t){let m=document.createElement("p");m.textContent=t,m.style.cssText="line-height:1.5;white-space:pre-wrap;margin:0 0 20px",i.appendChild(m)}let s=document.createElement("div");s.style.cssText="display:flex;justify-content:flex-end;flex-wrap:wrap;gap:8px";let g=r?.length?r:[{text:"OK"}],h=()=>{i.close?.(),i.remove()};for(let m of g){let c=document.createElement("button");c.type="button",c.textContent=m.text??"OK",c.style.cssText=`padding:9px 14px;border:1px solid #64748b;border-radius:7px;color:white;background:${m.style==="destructive"?"#a52b38":"#283a4d"};cursor:pointer;font:inherit`,c.onclick=()=>{h(),m.onPress?.()},s.appendChild(c)}i.addEventListener("cancel",m=>{m.preventDefault(),n?.cancelable!==false&&(h(),n?.onDismiss?.())}),i.appendChild(s),document.body.appendChild(i),i.showModal?i.showModal():i.setAttribute("open","")}};import{TimeMachineIcon as ei,TIME_MACHINE_ICON_COLOR as ti}from"@buoy-gg/shared-ui/web";import{useRef as ri,useState as Wr,useSyncExternalStore as jr}from"react";import{useSafeAreaInsets as oi,useLimit as ni,ToolEmptyState as ii,getFloatingTools as ai,subscribeFloatingTools as si}from"@buoy-gg/shared-ui/web";import{useToolHost as li}from"@buoy-gg/core/web";import{useEffect as ci,useState as di,useSyncExternalStore as ui}from"react";import{getStateSnapshotProviders as Ot,subscribeToStateSnapshotProviders as hi}from"@buoy-gg/shared-ui/web";import{getStateSnapshotProvider as Nr,getStateSnapshotProviders as Ht,scheduleReloadApp as pi,superJsonDeserialize as Bt,superJsonSerialize as mi}from"@buoy-gg/shared-ui/web";import{objectDiff as fi}from"@buoy-gg/shared-ui/web/dataViewer";import{persistentStorage as pe}from"@buoy-gg/shared-ui/web";var Wt="@react_buoy_time_machine:index",je="@react_buoy_time_machine:snap:";async function gi(){try{let e=await pe.getItem(Wt);if(!e)return[];let t=JSON.parse(e);return Array.isArray(t)?t:[]}catch{return[]}}async function jt(e){await pe.setItem(Wt,JSON.stringify(e))}async function ct(e,t){let r=JSON.stringify(e);e.meta.sizeBytes=r.length,await pe.setItem(je+e.meta.id,JSON.stringify(e));let n=[e.meta,...t.filter(i=>i.id!==e.meta.id)];return await jt(n),n}async function me(e){try{let t=await pe.getItem(je+e);return t?JSON.parse(t):null}catch{return null}}async function Mr(e,t){await pe.removeItem(je+e);let r=t.filter(n=>n.id!==e);return await jt(r),r}async function dt(e,t,r){let n=s=>s.id===e?t(s):s,i=r.map(n);await pe.setItem(Wt,JSON.stringify(i));let a=await me(e);return a&&(a.meta=n(a.meta),await pe.setItem(je+e,JSON.stringify(a))),i}function yi(e,t,r){return dt(e,n=>{let i={...n};return t&&t.length>0?i.scope=t:delete i.scope,i},r)}function bi(e,t,r){return dt(e,n=>{let i={...n};return delete i.scope,t&&t.length>0?i.excludedKeys=t:delete i.excludedKeys,i},r)}function wi(e,t,r){return dt(e,n=>({...n,restoreRoute:t}),r)}function Vr(e,t,r){return dt(e,n=>({...n,lastRestoredAt:t}),r)}async function Si(e,t,r){let n=await me(e);if(!n)return null;let i={meta:{...n.meta,id:`${n.meta.id}_copy_${Date.now().toString(36)}`,name:t,createdAt:Date.now(),lastRestoredAt:void 0},data:n.data};return delete i.meta.lastRestoredAt,delete i.meta.safety,{metas:await ct(i,r),meta:i.meta}}async function vi(e){return me(e)}async function xi(e,t){return ct(e,t)}async function Ii(e,t,r){let n=r.map(a=>a.id===e?{...a,name:t}:a);await jt(n);let i=await me(e);return i&&(i.meta.name=t,await pe.setItem(je+e,JSON.stringify(i))),n}import{definePersistedSetting as Ri,devToolsStorageKeys as ki}from"@buoy-gg/shared-ui/web";var Fr=Ri(ki.timeMachine.disabledSources(),[],{sanitize:e=>Array.isArray(e)?e.filter(t=>typeof t=="string"):[]}),xe=new Set,Kr=false,Nt=null,Mt=new Set,_r=()=>Mt.forEach(e=>e());function Z(){return Kr?Promise.resolve():(Nt||(Nt=Fr.load().then(e=>{xe.size===0&&(xe=new Set(e),_r())}).finally(()=>{Kr=true})),Nt)}function qr(e){return Mt.add(e),()=>{Mt.delete(e)}}function Jr(){return xe}function ne(e){return!xe.has(e)}function Ur(e,t){if(t===!xe.has(e))return;let r=new Set(xe);t?r.delete(e):r.add(e),xe=r,_r(),Fr.save([...r])}var Ne="route";var Me=["storage","redux","zustand","jotai","query"];function Di(e){let t=new Date,r=`${String(t.getHours()).padStart(2,"0")}:${String(t.getMinutes()).padStart(2,"0")}`,n=e?e.pathname==="/"?"Home":e.pathname:null;return n?`${n} \xB7 ${r}`:`Snapshot \xB7 ${r}`}function Ti(e,t){let r=new Set(t.map(n=>n.name));if(!r.has(e))return e;for(let n=2;n<1e3;n++){let i=`${e} (${n})`;if(!r.has(i))return i}return e}function ut(e){return!!e.route&&(e.restoreRoute??true)}var Vt="Before last restore";function Ft(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 Ci(e){return!e.willReload&&!Ft(e)}function Gr(){return{ok:true,applied:0,skipped:[],warnings:["Switched off in Sources; left as it is"]}}var P=null;function ht(e){return{ok:false,applied:0,skipped:[{id:"*",reason:e}],warnings:[]}}var Xr=0;function Yr(){return Xr+=1,`snap_${Date.now().toString(36)}_${Xr.toString(36)}`}var zi=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 P?Promise.resolve():(this.loadPromise||(this.loadPromise=gi().then(e=>{P||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(P)return(await P("capture",{name:e,sourceIds:t})).snapshot;await this.ensureLoaded(),await Z(),this.setState({busy:"capture"});try{let n=Ht().filter(c=>c.status().canCapture&&ne(c.id)&&(!t||t.includes(c.id))),i={},a={};for(let c of n)try{let u=await c.capture();i[c.id]=mi(u.data),a[c.id]={warnings:u.warnings}}catch(u){a[c.id]={warnings:[`capture failed: ${String(u)}`]}}let s=ne(Ne)?it():null,g=this.state.snapshots,h={meta:{id:Yr(),name:r?.safety?Vt:Ti(e.trim()||Di(s),g),createdAt:Date.now(),sizeBytes:0,...s?{route:s}:{},...r?.safety?{safety:true}:{},sources:a},data:i},m=await ct(h,g);if(r?.safety)for(let c of m.filter(u=>u.safety&&u.id!==h.meta.id))m=await Mr(c.id,m);return this.setState({snapshots:m}),h.meta}finally{this.setState({busy:null})}}async captureBaseline(){if(P)return(await P("captureBaseline",{})).snapshot;await this.ensureLoaded(),await Z();let e={meta:{id:Yr(),name:"Fresh install",createdAt:Date.now(),sizeBytes:0,baseline:true,sources:{}},data:{}},t=await ct(e,this.state.snapshots);return this.setState({snapshots:t}),e.meta}async restore(e,t,r,n){if(P){let a=await P("restore",{id:e,mode:t,excludeKeys:r,restoreRoute:n?.restoreRoute});return this.setState({lastOutcome:a}),a}await this.ensureLoaded(),await Z();let i;n?.safetyCapture&&!this.state.snapshots.find(a=>a.id===e)?.safety&&(i=(await this.capture(Vt,void 0,{safety:true})).id),this.setState({busy:"restore"});try{let a=await me(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:{},...i?{safetySnapshotId:i}:{}};if(a.meta.baseline)return await this.clearEnabledSources(s),s.willReload=this.scheduleReload("buoy time-machine baseline"),this.setState({lastOutcome:s}),s;let g=[...Me.filter(w=>w in a.data),...Object.keys(a.data).filter(w=>!Me.includes(w))],h=w=>{let E=new Map;for(let M of w){let H=M.indexOf("::");if(H<=0)continue;let S=M.slice(0,H),U=M.slice(H+2),te=E.get(S)??[];te.push(U),E.set(S,te)}return E},m=r??a.meta.excludedKeys??[],c=h(m),u=!r&&a.meta.scope?.length?h(a.meta.scope):null,z=ne(Ne)&&(n?.restoreRoute??ut(a.meta));if(t==="reload"){if(a.data.storage&&ne("storage")&&(!u||u.has("storage"))&&(s.results.storage=await this.restoreSource("storage",a.data.storage,c.get("storage"),u?.get("storage"))),z){let w=a.meta.route;try{await Qo(w,a.meta.name),s.route={...w,status:"deferred"}}catch(E){s.route={...w,status:"failed",error:String(E)}}}return s.willReload=this.scheduleReload("buoy time-machine restore"),this.setState({lastOutcome:s,snapshots:await Vr(e,s.at,this.state.snapshots)}),s}for(let w of g)if(!(u&&!u.has(w))){if(!ne(w)){s.results[w]=Gr();continue}s.results[w]=await this.restoreSource(w,a.data[w],c.get(w),u?.get(w))}return z&&(s.route=$t(a.meta.route)),this.setState({lastOutcome:s,snapshots:await Vr(e,s.at,this.state.snapshots)}),s}finally{this.setState({busy:null})}}async restoreSource(e,t,r,n){let i=Nr(e);if(!i)return ht("provider not available (package missing or not initialized)");let a=i.status();if(!a.canRestore)return ht(a.detail??"restore unavailable");try{let s=r?.length||n?.length?{...r?.length?{excludeKeys:r}:{},...n?.length?{includeKeys:n}:{}}:void 0;return await i.restore(Bt(t),s)}catch(s){return ht(String(s))}}async clearEnabledSources(e){for(let t of Ht())if(t.clear){if(!ne(t.id)){e.results[t.id]=Gr();continue}try{e.results[t.id]=await t.clear()}catch(r){e.results[t.id]=ht(String(r))}}}reloadApp(){return this.state.busy==="restore"?false:this.scheduleReload("buoy time-machine reload app")}scheduleReload(e){try{return pi({reason:e}),true}catch{return false}}async delete(e){if(P){await P("delete",{id:e});return}await this.ensureLoaded(),await Z();let t=await vi(e),r=await Mr(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 xi(e.stored,this.state.snapshots);this.setState({snapshots:t,recentlyDeleted:null})}clearRecentlyDeleted(){this.state.recentlyDeleted&&this.setState({recentlyDeleted:null})}async setRestoreRoute(e,t){if(P){await P("setRestoreRoute",{id:e,restoreRoute:t});return}await this.ensureLoaded(),await Z();let r=await wi(e,t,this.state.snapshots);this.setState({snapshots:r})}async duplicate(e){if(P)return(await P("duplicate",{id:e}))?.snapshot??null;await this.ensureLoaded(),await Z();let t=this.state.snapshots.find(n=>n.id===e);if(!t)return null;let r=await Si(e,`${t.name} copy`,this.state.snapshots);return r?(this.setState({snapshots:r.metas}),r.meta):null}async rename(e,t){if(P){await P("rename",{id:e,name:t});return}await this.ensureLoaded(),await Z();let r=await Ii(e,t,this.state.snapshots);this.setState({snapshots:r})}async setScope(e,t){if(P){await P("setScope",{id:e,scope:t});return}await this.ensureLoaded(),await Z();let r=await yi(e,t,this.state.snapshots);this.setState({snapshots:r})}async setExclusions(e,t){if(P){await P("setExclusions",{id:e,excludedKeys:t});return}await this.ensureLoaded(),await Z();let r=await bi(e,t,this.state.snapshots);this.setState({snapshots:r})}clearLastOutcome(){this.setState({lastOutcome:null})}async wipeAll(){if(P){let e=await P("wipeAll",{});return this.setState({lastOutcome:e}),e}await Z(),this.setState({busy:"restore"});try{let e={snapshotId:"wipe-all",snapshotName:"Wipe all",mode:"reload",at:Date.now(),willReload:false,results:{}};return await this.clearEnabledSources(e),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(P){let n=++this.previewRunId;this.setState({preview:{left:t,right:e,building:true,builtAt:Date.now(),sources:[]}});try{let i=await P("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:i.sources??[]}})}catch(i){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(i)}]}})}return}await this.ensureLoaded(),await Z();let r=++this.previewRunId;await this.runPreview(e,t,n=>this.setState({preview:n}),()=>r===this.previewRunId)}async computePreview(e,t="current"){await this.ensureLoaded(),await Z();let r=null;if(await this.runPreview(e,t,n=>{r=n},()=>true),!r)throw new Error("preview build produced no result");return r}async runPreview(e,t,r,n){r({left:t,right:e,building:true,builtAt:Date.now(),sources:[]});let i=async a=>{if(a==="current")return null;let s=await me(a.snapshotId);if(!s)throw new Error(`No snapshot with id "${a.snapshotId}"`);return s.data};try{if(e==="current")throw new Error("preview target must be a snapshot");let[a,s]=await Promise.all([i(t),me(e.snapshotId)]);if(!n())return;if(!s)throw new Error(`No snapshot with id "${e.snapshotId}"`);let g=s.data,h=s.meta.baseline===true,m=h?Ht().filter(u=>u.clear).map(u=>u.id):[...Me.filter(u=>u in g),...Object.keys(g).filter(u=>!Me.includes(u))],c=[];for(let u of m){if(!ne(u))continue;if(await new Promise(E=>setTimeout(E,0)),!n())return;let z=Nr(u),w=z?.label??u;try{let E=h?void 0:Bt(g[u]),M=a===null?void 0:u in a?Bt(a[u]):void 0,H;if(!z)H={items:[{key:u,label:w,verdict:"wont-apply",reason:"tool not installed \u2014 restore skips this source"}],notes:[]};else if(z.previewItems)H=await z.previewItems(E,M);else{let S=fi(M,E);H={items:[{key:u,label:w,verdict:S.equal?"unchanged":"changed",oldValue:M,newValue:E}],notes:S.truncated?["diff truncated (large value)"]:[]}}if(!n())return;c.push({id:u,label:w,...H})}catch(E){c.push({id:u,label:w,items:[],notes:[],error:String(E)})}r({left:t,right:e,building:true,builtAt:Date.now(),sources:[...c]})}if(!n())return;r({left:t,right:e,building:false,builtAt:Date.now(),sources:c})}catch(a){if(!n())return;r({left:t,right:e,building:false,builtAt:Date.now(),sources:[{id:"error",label:"Preview",items:[],notes:[],error:String(a)}]})}}},x=new zi;function $i(e){P=e,e||x.replaceFromSnapshot({})}function Li(e){x.replaceFromSnapshot(e)}function pt(){return ui(x.subscribe,()=>x.getState())}function Qr(){let[e,t]=di(Ot);return ci(()=>(t(Ot()),hi(()=>t(Ot()))),[]),e}import{Children as Ai}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 Ei}from"@buoy-gg/shared-ui/web";var Kt="2E",Oi="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}${Kt}`,accentSoftStrong:`${j.color.accent}${Oi}`,onAccent:"#0A0A0A",warning:j.color.warning,warningSoft:`${j.color.warning}${Kt}`,danger:j.color.danger,dangerSoft:`${j.color.danger}${Kt}`,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},mt=Ei;import{jsx as Ie,jsxs as Hi}from"react/jsx-runtime";function ft({children:e,testID:t}){return Ie(d,{style:fe.sectionLabel,testID:t,children:e})}function Ve({children:e,centered:t,tone:r="secondary",testID:n}){return Ie(d,{style:[fe.footnote,t?fe.footnoteCentered:null,r==="warning"?fe.footnoteWarning:null],testID:n,children:e})}function gt({children:e,style:t}){let r=Ai.toArray(e);return Ie(p,{style:[fe.group,t],children:r.map((n,i)=>Hi(p,{children:[i>0?Ie(p,{style:fe.separator}):null,n]},n.key??i))})}function Zr(){return Ie(Pi,{size:16,color:o.color.labelTertiary})}function Bi({label:e,color:t,background:r,testID:n}){return Ie(p,{style:[fe.pill,{backgroundColor:r}],children:Ie(d,{style:[fe.pillText,{color:t}],testID:n,children:e})})}var fe=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 Wi,QueryIcon as ji,ReduxIcon as Ni,RoutesIcon as Mi,StorageIcon as Vi,TimeMachineIcon as Fi,ZustandIcon as Ki}from"@buoy-gg/floating-tools-core/web";import{useSyncExternalStore as _i}from"react";var qi={storage:Vi,redux:Ni,zustand:Ki,jotai:Wi,query:ji,route:Mi};function Ji(e){return qi[e]??Fi}function Ui(){let{remoteProviders:e,remoteRoute:t}=pt(),r=Qr(),n=_i(qr,Jr,Jr),i=e?e.map(s=>({...s,enabled:s.enabled!==false})):r.map(s=>({id:s.id,label:s.label,...s.status(),enabled:!n.has(s.id)})),a=e?t?.available===true:He();return[...i,{id:Ne,label:"Route",canCapture:a,canRestore:a,enabled:e?t?.enabled!==false:!n.has(Ne),detail:a?"Recorded with every snapshot \u2014 a restore can take you back":"No Expo Router detected \u2014 snapshots record no route"}]}function Gi(e){let t=globalThis.confirm;return t?t(e):true}function _t(e,t,r,n){if(at.OS==="web"){Gi(`${e}
2
2
 
3
- ${t}`)&&i();return}Hr.alert(e,t,[{text:"Cancel",style:"cancel"},{text:r,style:"destructive",onPress:i}])}import{useState as Ui}from"react";import{jsx as _t,jsxs as Gi}from"react/jsx-runtime";function Yi({disabled:e,busy:t,onCapture:r}){let[i,n]=Ui(""),a=()=>{e||(r(i),n(""),kr.dismiss())};return Gi(h,{style:_e.bar,children:[_t(lt,{style:_e.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"}),_t(E,{style:[_e.button,e?_e.buttonDisabled:null],onPress:a,disabled:e,accessibilityRole:"button",accessibilityLabel:"Capture restore point",testID:"time-machine-capture",children:_t(d,{style:_e.buttonText,children:t?"Capturing\u2026":"Capture"})})]})}var _e=P.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 Qi}from"@buoy-gg/shared-ui/web";import{jsx as ye,jsxs as be}from"react/jsx-runtime";var Xi={top:10,bottom:10,left:10,right:10};function Xr(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 bt({glyph:e,text:t,ok:r,testID:i}){return be(d,{style:[we.line,{color:r?o.color.accent:o.color.warning}],numberOfLines:2,testID:i,children:[be(d,{style:we.glyph,children:[e," "]}),t]})}var qt="time-machine-outcome-route";function Zi({route:e}){return e.status==="navigated"?ye(bt,{glyph:"\u2713",ok:true,text:`route \u2014 ${e.href}`,testID:qt}):e.status==="deferred"?ye(bt,{glyph:"\u21BB",ok:true,text:`route \u2014 ${e.href} after reload`,testID:qt}):ye(bt,{glyph:"\u2715",ok:false,text:`route \u2014 ${e.error??e.status}`,testID:qt})}function ea({outcome:e}){let t=Object.entries(e.results),r=e.mode==="reload"||e.willReload;return be(h,{style:we.card,testID:"time-machine-outcome",children:[be(h,{style:we.headerRow,children:[be(d,{style:we.title,numberOfLines:1,testID:"time-machine-outcome-title",children:["Restored \u201C",e.snapshotName,"\u201D",r?" \xB7 reloading":""]}),ye(E,{onPress:()=>x.clearLastOutcome(),hitSlop:Xi,accessibilityRole:"button",accessibilityLabel:"Dismiss restore result",testID:"time-machine-outcome-dismiss",children:ye(Qi,{size:13,color:o.color.labelSecondary})})]}),t.length===0&&!e.route?ye(d,{style:we.empty,testID:"time-machine-outcome-empty",children:"No sources restored."}):null,e.route?ye(Zi,{route:e.route}):null,t.map(([i,n])=>be(h,{children:[ye(bt,{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=>be(d,{style:we.detail,numberOfLines:2,children:[a.id,": ",a.reason]},a.id)),n.warnings.slice(0,3).map(a=>be(d,{style:we.detail,numberOfLines:2,children:["\u26A0 ",a]},a))]},i))]})}var we=P.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 ta,useRef as Zr}from"react";import{jsx as wt,jsxs as ra}from"react/jsx-runtime";var eo=84,to=8,ve=null;function oa(e,t){let r=false,i=a=>{r=a,a?(ve&&ve!==n&&ve(),ve=n):ve===n&&(ve=null),We.spring(e,{toValue:a?-t:0,useNativeDriver:true,bounciness:0,speed:18}).start()},n=()=>i(false);return{pan:Dr.create({onMoveShouldSetPanResponder:(a,s)=>Math.abs(s.dx)>Math.abs(s.dy)*1.5?s.dx<-to||r&&s.dx>to:false,onPanResponderMove:(a,s)=>{let f=r?-t:0;e.setValue(Math.min(0,Math.max(-t,f+s.dx)))},onPanResponderRelease:(a,s)=>{let f=(r?-t:0)+s.dx;i(s.vx<-.5?true:s.vx>.5?false:f<-t/2)},onPanResponderTerminate:()=>i(r)}),close:n}}function na({children:e,actions:t,testID:r}){let i=eo*t.length,n=Zr(new We.Value(0)).current,a=Zr(null);a.current===null&&(a.current=oa(n,i));let{pan:s,close:f}=a.current;ta(()=>()=>{ve===f&&(ve=null)},[f]);let u=n.interpolate({inputRange:[-24,0],outputRange:[1,0],extrapolate:"clamp"});return ra(h,{style:qe.clip,children:[wt(We.View,{style:[qe.actionLayer,{width:i,opacity:u}],children:t.map(g=>wt(E,{style:[qe.action,g.background?{backgroundColor:g.background}:null],onPress:()=>{f(),g.onPress()},accessibilityLabel:g.label,testID:g.testID??(r?`${r}-${g.label.toLowerCase()}`:void 0),children:wt(d,{style:[qe.actionText,g.color?{color:g.color}:null],numberOfLines:1,children:g.label})},g.label))}),wt(We.View,{style:[qe.content,{transform:[{translateX:n}]}],...s.panHandlers,children:e})]})}var qe=P.create({clip:{overflow:"hidden"},actionLayer:{position:"absolute",top:0,bottom:0,right:0,flexDirection:"row"},action:{width:eo,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 Je(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 ia(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 Jt}from"react/jsx-runtime";function ro(e){if(e.baseline)return"Wipes to fresh install";let t=[Je(e.createdAt),ia(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 aa({meta:e,busy:t,armed:r=false,onOpen:i,onRestore:n,onDelete:a,onDuplicate:s,onArm:f}){let u=`time-machine-snap-${e.id}`;return Re(na,{testID:u,actions:[{label:"Bar",onPress:f},{label:"Dup",onPress:s},{label:"Delete",onPress:a,background:o.color.danger,color:o.color.onDanger}],children:Jt(h,{style:de.row,children:[Jt(E,{style:de.text,onPress:i,activeOpacity:.7,accessibilityRole:"button",accessibilityLabel:`${e.name}. ${ro(e)}. Open restore preview`,testID:u,children:[Re(d,{style:de.name,numberOfLines:1,testID:`${u}-name`,children:e.name}),r?Re(d,{style:de.armed,numberOfLines:1,testID:`${u}-armed`,children:"On the action bar"}):null,Re(d,{style:de.meta,numberOfLines:1,testID:`${u}-meta`,children:ro(e)}),e.lastRestoredAt?Jt(d,{style:de.restored,numberOfLines:1,testID:`${u}-restored`,children:["Restored ",Je(e.lastRestoredAt)]}):null,e.route?Re(d,{style:de.route,numberOfLines:1,testID:`${u}-route`,children:e.route.href}):null]}),Re(E,{onPress:n,disabled:t,style:[de.restore,t?de.actionDisabled:null],accessibilityRole:"button",accessibilityLabel:e.baseline?"Wipe and reload":"Restore",testID:`${u}-restore`,children:Re(Oi,{testID:`${u}-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=P.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:ft,fontSize:o.font.mono,marginTop:4},actionDisabled:{opacity:.4}});import{useEffect as sa}from"react";import{jsx as oo,jsxs as no}from"react/jsx-runtime";var la=8e3;function ca({name:e,at:t,onUndo:r,onExpire:i}){return sa(()=>{let n=setTimeout(i,la);return()=>clearTimeout(n)},[t]),no(h,{style:Ut.bar,testID:"time-machine-undo-bar",children:[no(d,{style:Ut.text,numberOfLines:1,testID:"time-machine-undo-text",children:["Deleted \u201C",e,"\u201D"]}),oo(E,{onPress:r,hitSlop:{top:10,bottom:10,left:10,right:10},accessibilityRole:"button",testID:"time-machine-undo-delete",children:oo(d,{style:Ut.undo,children:"Undo"})})]})}var Ut=P.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 da}from"@buoy-gg/shared-ui/web";import{jsx as le,jsxs as Gt}from"react/jsx-runtime";var ua={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 ha(e){return ua[e.id]??"App data"}function pa(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 ma({source:e,onToggle:t}){let r=_i(e.id),i=ha(e),n=pa(e);return Gt(h,{style:ue.row,testID:`time-machine-source-${e.id}`,accessibilityLabel:`${e.label}: ${i}${n?`. ${n.text}`:""}`,children:[le(h,{style:ue.disc,children:le(r,{size:22,bgColor:o.color.disc})}),Gt(h,{style:ue.text,children:[le(d,{style:ue.label,numberOfLines:1,testID:`time-machine-source-${e.id}-label`,children:e.label}),le(d,{style:ue.description,numberOfLines:2,testID:`time-machine-source-${e.id}-description`,children:i}),n?le(d,{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(h,{testID:`time-machine-source-${e.id}-switch`,children:le(da,{value:e.enabled,disabled:!t,onValueChange:a=>t?.(e.id,a)})})]})}function fa({sources:e,onToggle:t}){let r=e.filter(i=>i.canCapture);return Gt(yt,{children:[r.map(i=>le(ma,{source:i,onToggle:t},i.id)),r.length===0?le(h,{style:ue.row,testID:"time-machine-sources-empty",children:le(d,{style:ue.description,children:"No state tools are set up in this app."})}):null]})}var ue=P.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 io}from"react/jsx-runtime";function ga({disabled:e,onWipe:t}){return io(E,{style:[Yt.row,e?Yt.disabled:null],onPress:t,disabled:e,accessibilityRole:"button",testID:"time-machine-wipe-all",children:io(d,{style:Yt.label,children:"Wipe All App State\u2026"})})}var Yt=P.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 ya,useCallback as ke,useEffect as ao,useMemo as vt,useRef as Qt,useState as Xt}from"react";import{ChevronUp as so,AlertTriangle as ba,RefreshCw as wa,useSafeAreaInsets as va}from"@buoy-gg/shared-ui/web";import{useToolHeader as Sa,useToolHost as xa}from"@buoy-gg/core/web";import{night as St}from"@buoy-gg/shared-ui/web";import{useToolHost as Ia}from"@buoy-gg/core/web";import{night as Zt,scheduleReloadApp as Ra}from"@buoy-gg/shared-ui/web";import{jsx as lo}from"react/jsx-runtime";function ka(){let e=()=>{try{Ra({reason:"buoy time-machine reload app"})}catch{}};return lo(E,{style:co.chip,onPress:e,accessibilityLabel:"Reload app",accessibilityHint:"Reloads the JavaScript bundle without restoring anything",accessibilityRole:"button",testID:"time-machine-reload-app",children:lo(d,{style:co.label,children:"Reload app"})})}var co=P.create({chip:{height:32,paddingHorizontal:10,borderRadius:8,borderWidth:1,borderColor:Zt.color.border,backgroundColor:Zt.color.buttonSurface,alignItems:"center",justifyContent:"center"},label:{fontSize:11,fontWeight:"700",color:Zt.color.textSecondary}});import{useEffect as xt,useRef as Da,useState as Se,useSyncExternalStore as uo}from"react";import{Check as ho,ChevronDown as Ta,ChevronUp as Ca,FloatingTool as za,NightSwitch as $a,Plus as La,TimeMachineIcon as Ea,X as Aa,night as T,openFloatingTool as Pa,persistentStorage as Oa,registerPersistentFloatingTool as Ha,useLimit as Ba}from"@buoy-gg/shared-ui/web";import{devToolsStorageKeys as ja,persistentStorage as er}from"@buoy-gg/shared-ui/web";var tr=ja.timeMachine.armedPoint(),Ue=null,po=false,rr=null,or=new Set,mo=()=>or.forEach(e=>e());function It(){return Ue}function fo(e){return or.add(e),()=>{or.delete(e)}}function Wa(){return po?Promise.resolve():(rr||(rr=er.getItem(tr).then(e=>{Ue===null&&e&&(Ue=e,mo())}).catch(()=>{}).finally(()=>{po=true})),rr)}function nr(e){Ue!==e&&(Ue=e,mo(),(e===null?er.removeItem(tr):er.setItem(tr,e)).catch(()=>{}))}function go(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 Na,useState as Ma}from"react";import{night as H}from"@buoy-gg/shared-ui/web";import{jsx as oe,jsxs as yo}from"react/jsx-runtime";function Va({visible:e,summary:t,onCapture:r,onCancel:i}){let[n,a]=Ma("");Na(()=>{e&&a("")},[e]);let s=()=>r(n.trim());return oe(Or,{visible:e,transparent:true,animationType:"fade",onRequestClose:i,statusBarTranslucent:true,children:oe(Cr,{behavior:st.OS==="ios"?"padding":void 0,style:Z.fill,children:oe(Pt,{style:Z.backdrop,onPress:i,accessibilityLabel:"Cancel",testID:"time-machine-bar-name-backdrop",children:yo(Pt,{style:Z.card,onPress:f=>f.stopPropagation(),testID:"time-machine-bar-name-panel",accessible:false,children:[oe(d,{style:Z.title,children:"Name this restore point"}),t?oe(d,{style:Z.summary,testID:"time-machine-bar-name-summary",children:t}):null,oe(lt,{testID:"time-machine-bar-name-input",accessibilityLabel:"Restore point name",value:n,onChangeText:a,onSubmitEditing:s,placeholder:"Screen and time, if left empty",placeholderTextColor:H.color.placeholder,autoFocus:true,autoCorrect:false,autoCapitalize:"none",returnKeyType:"done",style:Z.input}),oe(d,{style:Z.hint,children:"Captures the state the app is in right now and arms it on the bar."}),yo(h,{style:Z.actions,children:[oe(E,{testID:"time-machine-bar-name-cancel",accessibilityRole:"button",onPress:i,style:Z.secondary,children:oe(d,{style:Z.secondaryText,children:"Cancel"})}),oe(E,{testID:"time-machine-bar-name-capture",accessibilityRole:"button",accessibilityLabel:"Capture and arm this restore point",onPress:s,style:Z.primary,children:oe(d,{style:Z.primaryText,children:"Capture"})})]})]})})})})}var Z=P.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:H.radius.sheet,borderWidth:1,borderColor:H.color.separator,backgroundColor:H.color.surface,padding:18,gap:12,shadowColor:"#000",shadowOffset:{width:0,height:12},shadowOpacity:.4,shadowRadius:24,elevation:12},title:{color:H.color.text,fontSize:H.font.title,fontWeight:"600"},input:{minHeight:44,borderRadius:H.radius.input,borderWidth:1,borderColor:H.color.accentBorder,backgroundColor:H.color.surfaceElevated,color:H.color.text,fontSize:H.font.row,paddingHorizontal:12},summary:{color:H.color.textTertiary,fontSize:H.font.caption,marginTop:-6},hint:{color:H.color.textSecondary,fontSize:H.font.caption,lineHeight:18},actions:{flexDirection:"row",justifyContent:"flex-end",gap:10,marginTop:4},secondary:{minHeight:40,paddingHorizontal:14,borderRadius:H.radius.input,alignItems:"center",justifyContent:"center"},secondaryText:{color:H.color.textSecondary,fontSize:14,fontWeight:"600"},primary:{minHeight:40,paddingHorizontal:18,borderRadius:H.radius.input,backgroundColor:H.color.accent,alignItems:"center",justifyContent:"center"},primaryText:{color:H.color.onAccent,fontSize:14,fontWeight:"700"}});import{devToolsStorageKeys as Fa,persistentStorage as bo}from"@buoy-gg/shared-ui/web";var wo=Fa.timeMachine.barReloadMode(),Ge=false,vo=false,ir=null,ar=new Set,So=()=>ar.forEach(e=>e());function xo(){return Ge}function Ka(e){return ar.add(e),()=>{ar.delete(e)}}function _a(){return vo?Promise.resolve():(ir||(ir=bo.getItem(wo).then(e=>{!Ge&&e==="1"&&(Ge=true,So())}).catch(()=>{}).finally(()=>{vo=true})),ir)}function qa(e){e!==Ge&&(Ge=e,So(),bo.setItem(wo,e?"1":"0").catch(()=>{}))}import{Fragment as Ja,jsx as k,jsxs as F}from"react/jsx-runtime";var sr="time-machine-restore",Rt=1e4,Io=900,lr=6,Ro={id:sr,render:e=>k(Ya,{...e})},ko=false;function Do(){ko||(ko=true,Ha(Ro,Oa))}typeof vr<"u"&&vr&&typeof navigator<"u"&&navigator.product==="ReactNative"&&Do();function cr(e){e&&nr(e),Pa(Ro)}function Ua(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 Ga(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 To(e){let[t,r]=Se(0);return xt(()=>{if(!t)return;let i=setTimeout(()=>r(0),e);return()=>clearTimeout(i)},[t,e]),[t>0,()=>r(i=>i+1)]}function Ya({id:e,revealToken:t,dismiss:r}){let{snapshots:i,hasLoaded:n,busy:a}=mt(),s=Yr(),f=uo(fo,It,It),u=Ba("timeMachine.snapshots"),g=uo(Ka,xo,xo),{width:l}=zr(),[p,z]=Se(null),[m,O]=Se(null),[j,W]=Se(),[v,U]=Se(false),[ee,G]=To(Io),[Ae,te]=To(Io),[K,$]=Se(null),[ne,pe]=Se(null),[,De]=Se(0),ie=Da(true);xt(()=>(ie.current=true,Wa(),_a(),x.ensureLoaded(),()=>{ie.current=false}),[]);let D=go(i,f),et=D?.id,Pe=D?.lastRestoredAt,tt=D?.createdAt;xt(()=>{if(Pe===void 0&&tt===void 0&&!K&&ne===null)return;let b=setInterval(()=>De(V=>V+1),2500);return()=>clearInterval(b)},[Pe,tt,K,ne]),xt(()=>{m&&m.snapshotId!==et&&(O(null),z(b=>b==="outcome"?null:b))},[et,m]);let Te=Date.now(),rt=K!==null&&Te-K.at<Rt&&i.some(b=>b.id===K.id),Oe=i.filter(b=>!b.safety).length>=u,c=!D||a!==null,S=a!==null,C=async(b,V)=>{if(!a){z(null),W(void 0);try{let Q=await x.restore(b,g&&V.safetyCapture?"reload":"live",void 0,V);if(!ie.current)return;Xr(Q)?(O(Q),z("outcome")):(O(null),G()),$(Q.safetySnapshotId?{id:Q.safetySnapshotId,at:Date.now()}:null),Q.safetySnapshotId&&pe(null)}catch(Q){if(!ie.current)return;W(Q instanceof Error?Q.message:String(Q)),z("error")}}},R=(b=false)=>{D&&C(D.id,{safetyCapture:true,...b?{restoreRoute:false}:{}})},_=()=>{K&&C(K.id,{safetyCapture:false,restoreRoute:false}).then(()=>{ie.current&&pe(Date.now())})},re=()=>{if(!a){if(W(void 0),Oe){z("cap");return}z(null),U(true)}},Y=async b=>{if(U(false),!a)try{let V=await x.capture(b);if(!ie.current)return;nr(V.id),$(null),te()}catch(V){if(!ie.current)return;W(V instanceof Error?V.message:String(V)),z("error")}},He=b=>{nr(b.id),z(null)},ot=D?.name??(n?"No restore points":"Loading\u2026"),q,Ce="normal",nt=false;if(a==="restore")q="Restoring\u2026";else if(a==="capture")q="Capturing\u2026";else if(j)q=j,Ce="danger";else if(m&&D&&m.snapshotId===D.id)q=Ua(m),Ce="danger";else if(!D)q=n?"Capture one with +":"";else{nt=true;let b=D.lastRestoredAt===void 0?null:Te-D.lastRestoredAt,V=Te-D.createdAt;ne!==null&&Te-ne<Rt?q="undone, state only":b!==null&&b<Rt?q="restored just now":V<Rt&&b===null?q="captured just now":D.lastRestoredAt!==void 0?q=`restored ${Je(D.lastRestoredAt)}`:q=`${Object.keys(D.sources).length} sources`,g&&(q+=" \xB7 reloads")}let ce=nt&&!rt&&D&&D.route&&pt(D)?D.route.pathname:null,ze=i.filter(b=>!b.baseline&&!b.safety),it=(()=>{let b=s.filter(yr=>yr.status().canCapture&&se(yr.id)).length,V=at(),Q=[`${b} source${b===1?"":"s"}`];return V&&Q.push(V.pathname),Q.join(" \xB7 ")})(),L;return p==="picker"?L=F(h,{style:I.menu,testID:"time-machine-bar-picker",children:[F(Ot,{keyboardShouldPersistTaps:"handled",style:I.pickerList,bounces:false,children:[ze.map(b=>{let V=b.id===D?.id;return F(E,{testID:`time-machine-bar-pick-${b.id}`,accessibilityRole:"button",accessibilityState:{selected:V},accessibilityLabel:`Arm ${b.name}`,onPress:()=>He(b),style:I.pickRow,children:[F(h,{style:I.pickText,children:[k(d,{numberOfLines:1,style:I.pickName,children:b.name}),F(d,{numberOfLines:1,style:I.pickDetail,children:[Je(b.createdAt),b.route?` \xB7 ${b.route.pathname}`:"",b.lastRestoredAt!==void 0?k(d,{style:I.pickRestored,children:` \xB7 restored ${Je(b.lastRestoredAt)}`}):null]})]}),V?k(ho,{size:14,color:T.color.accent}):null]},b.id)}),ze.length===0?k(d,{style:I.menuText,children:"No restore points yet."}):null]}),ze.length>lr?F(d,{style:I.pickerMore,children:["Scroll for ",ze.length-lr," more"]}):null,F(h,{style:I.settingRow,testID:"time-machine-bar-reload-mode",children:[F(h,{style:I.settingText,children:[k(d,{style:I.settingLabel,children:"Reload the app after restoring"}),k(d,{style:I.settingHint,children:"For screens that read their state from storage only when they open, like a cart kept in a React context."})]}),k($a,{value:g,onValueChange:qa,testID:"time-machine-bar-reload-switch",accessibilityLabel:"Reload the app after restoring"})]})]}):p==="outcome"&&m?L=F(h,{style:I.menu,testID:"time-machine-bar-outcome",children:[Ga(m).map(b=>k(d,{style:I.menuDanger,children:b},b)),k(d,{style:I.menuText,children:"The full report is on Time Machine's outcome card."}),k(dr,{onPress:()=>z(null)})]}):p==="cap"?L=F(h,{style:I.menu,testID:"time-machine-bar-cap",children:[F(d,{style:I.menuText,children:["Free plan keeps ",u," restore point",u===1?"":"s",". Delete one in Time Machine, or upgrade to Pro for unlimited snapshots."]}),k(dr,{onPress:()=>z(null)})]}):p==="error"&&j&&(L=F(h,{style:I.menu,testID:"time-machine-bar-error",children:[k(d,{accessibilityRole:"alert",style:I.menuDanger,children:j}),k(dr,{onPress:()=>{z(null),W(void 0)}})]})),F(Ja,{children:[k(Va,{visible:v,summary:it,onCapture:b=>void Y(b),onCancel:()=>U(false)}),k(za,{id:e,revealToken:t,variant:"strip",dragFromSurface:true,defaultPlacement:"bottom",accessibilityLabel:`Move or hide the action bar. ${D?`${D.name} armed`:"Nothing armed"}`,accessory:L,handleAdornment:k(Ea,{size:12,color:T.color.accent}),children:F(h,{style:[I.row,{width:Math.max(260,Math.min(320,l-64))}],children:[k(E,{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:c},disabled:c,onPress:()=>R(false),onLongPress:()=>R(true),style:[I.restoreButton,c&&I.disabled],children:a==="restore"?k(ct,{size:"small",color:T.color.accent}):ee?k(d,{style:I.restoreText,testID:"time-machine-bar-restored",children:"Restored"}):k(d,{style:I.restoreText,children:"Restore"})}),F(h,{style:I.identity,children:[k(d,{testID:"time-machine-bar-name",accessibilityLabel:`Armed restore point: ${ot}`,numberOfLines:1,ellipsizeMode:"middle",style:I.name,children:ot}),F(h,{style:I.statusRow,children:[F(d,{testID:"time-machine-bar-status",numberOfLines:1,accessibilityLiveRegion:"polite",style:[I.status,Ce==="danger"&&I.danger],children:[q,ce?k(d,{style:I.destination,children:` \xB7 \u2192 ${ce}`}):null]}),rt&&!a?k(E,{testID:"time-machine-bar-undo",accessibilityRole:"button",accessibilityLabel:"Undo the last restore",onPress:_,hitSlop:{top:8,bottom:8,left:6,right:6},children:k(d,{style:I.undo,children:"Undo"})}):null]})]}),k(E,{testID:"time-machine-bar-pick",accessibilityRole:"button",accessibilityLabel:"Choose another restore point",accessibilityState:{expanded:p==="picker"},onPress:()=>z(b=>b==="picker"?null:"picker"),style:I.smallButton,children:p==="picker"?k(Ca,{size:14,color:T.color.textSecondary}):k(Ta,{size:14,color:T.color.textSecondary})}),k(E,{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:[I.smallButton,S&&I.disabled],children:a==="capture"?k(ct,{size:"small",color:T.color.accent}):Ae?k(h,{testID:"time-machine-bar-captured",children:k(ho,{size:18,color:T.color.accent})}):k(La,{size:18,color:Oe?T.color.textTertiary:T.color.text})}),k(h,{style:I.separator}),k(E,{testID:"time-machine-bar-close",accessibilityRole:"button",accessibilityLabel:"Close the action bar",onPress:r,style:I.closeButton,children:k(Aa,{size:16,color:T.color.textSecondary})})]})})]})}function dr({onPress:e,label:t="Dismiss"}){return k(E,{testID:"time-machine-bar-dismiss",accessibilityRole:"button",onPress:e,style:I.dismiss,children:k(d,{style:I.dismissText,children:t})})}var I=P.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:lr*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:P.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 kt,jsxs as Co}from"react/jsx-runtime";function Qa({armId:e}){let t=Ia(),r=()=>{cr(e),t.minimize()};return Co(E,{style:Dt.labeledChip,onPress:r,accessibilityLabel:"Open the floating action bar over the app",accessibilityRole:"button",testID:"time-machine-header-bar",children:[kt(h,{style:Dt.glyph}),kt(d,{style:Dt.label,children:"Action bar"})]})}function zo({armId:e}){return Co(h,{style:Dt.row,children:[kt(Qa,{armId:e}),kt(ka,{})]})}var Dt=P.create({row:{flexDirection:"row",alignItems:"center",gap:8},labeledChip:{height:32,flexDirection:"row",alignItems:"center",gap:6,paddingHorizontal:10,borderRadius:8,borderWidth:1,borderColor:St.color.border,backgroundColor:St.color.buttonSurface},glyph:{width:14,height:8,borderRadius:3,borderWidth:1.5,borderColor:St.color.accent},label:{fontSize:11,fontWeight:"700",color:St.color.accent}});import{useMemo as Xa}from"react";import{ABSENT_VALUE as $o,ThemedSplitView as Za,devToolsDefaultTheme as es,toDiffable as Lo}from"@buoy-gg/shared-ui/web/dataViewer";import{jsx as ts,jsxs as Eo}from"react/jsx-runtime";var rs=[];function os({item:e,testID:t}){let{oldValue:r,newValue:i}=Xa(()=>({oldValue:e.verdict==="added"?$o:Lo(e.oldValue),newValue:e.verdict==="removed"?$o:Lo(e.newValue)}),[e]);return Eo(h,{style:Ao.panel,testID:t,children:[e.reason?Eo(d,{style:Ao.reason,children:["\u26A0 ",e.reason]}):null,ts(Za,{oldValue:r,newValue:i,differences:rs,theme:es,scrollEnabled:false})]})}var Ao=P.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 ns,useState as is}from"react";import{jsx as Po,jsxs as as}from"react/jsx-runtime";function ss({name:e,onRename:t}){let[r,i]=is(e);ns(()=>i(e),[e]);let n=()=>{let a=r.trim();if(!a){i(e);return}a!==e&&t(a)};return as(h,{style:ur.row,children:[Po(d,{style:ur.label,children:"Name"}),Po(lt,{style:ur.input,value:r,onChangeText:i,onSubmitEditing:n,onBlur:n,returnKeyType:"done",selectTextOnFocus:true,accessibilityLabel:"Restore point name",testID:"tm-preview-name"})]})}var ur=P.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 Ye={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 ls,jsx as y,jsxs as B}from"react/jsx-runtime";var Oo={storage:"keys",redux:"slices",zustand:"stores",jotai:"atoms",query:"queries"},hr=new Set;function cs(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 Tt(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 Qe({position:e,children:t}){return B(h,{style:[w.cardRow,e.first?w.cardRowFirst:null,e.last?w.cardRowLast:null],children:[e.first?null:y(h,{style:w.cardSeparator}),t]})}function pr({glyph:e,count:t,color:r,testID:i}){return y(h,{style:[w.countPill,{backgroundColor:`${r}26`}],children:B(d,{style:[w.countPillText,{color:r}],testID:i,children:[e,t]})})}function mr({state:e}){return y(h,{style:[w.checkbox,e!=="none"&&w.checkboxChecked],children:e==="none"?null:y(d,{style:w.checkboxGlyph,children:e==="all"?"\u2713":"\u2212"})})}var ds=ya(function({row:e,expanded:t,onOpen:r,onToggle:i}){let n=Ye[e.item.verdict],a=!n.applies||e.excluded,s=e.item.verdict==="changed"||e.item.verdict==="added"||e.item.verdict==="removed",f=`tm-preview-item-${e.sourceId}-${e.item.key}`;return y(Qe,{position:e,children:B(h,{style:[w.itemRow,a&&w.dimmed],children:[y(E,{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:y(mr,{state:!n.applies||e.excluded?"none":"all"})}),B(E,{style:w.itemBodyTouch,onPress:()=>s&&r(),disabled:!s,testID:f,children:[y(d,{style:[w.itemGlyph,{color:n.color}],children:n.glyph}),B(h,{style:w.itemBody,children:[y(d,{style:w.itemLabel,numberOfLines:1,testID:`${f}-label`,children:e.item.label}),e.item.verdict==="changed"&&B(d,{style:w.itemPreview,numberOfLines:1,testID:`${f}-values`,children:[Tt(e.item.oldValue)," \u2192"," ",Tt(e.item.newValue)]}),e.item.verdict==="added"&&y(d,{style:w.itemPreview,numberOfLines:1,testID:`${f}-values`,children:Tt(e.item.newValue)}),e.item.verdict==="removed"&&y(d,{style:[w.itemPreview,w.itemPreviewRemoved],numberOfLines:1,testID:`${f}-values`,children:Tt(e.item.oldValue)}),e.excluded?y(d,{style:w.itemExcluded,testID:`${f}-excluded`,children:"excluded \u2014 restore leaves this untouched"}):e.item.reason&&y(d,{style:w.itemReason,numberOfLines:2,testID:`${f}-reason`,children:e.item.reason})]}),s?t?y(so,{size:16,color:o.color.labelTertiary}):y(Qr,{}):null]})]})})});function us({preview:e,snapshots:t,busy:r,onBack:i,onRestore:n}){let a=xa(),s=a.instanceId!==void 0,f=va({minBottom:16}),[u,g]=Xt({}),[l,p]=Xt(new Set),z=Qt(false),[m,O]=Xt(hr),j=ke(c=>{O(S=>{let C=new Set(S);return C.has(c)?C.delete(c):C.add(c),C})},[]),W=a.search,v=e.right==="current"?void 0:t.find(c=>c.id===e.right.snapshotId),U=Qt(v);U.current=v;let ee=ke(()=>{if(!U.current)return;let c=U.current;x.setRestoreRoute(c.id,!pt(c))},[]),G=v?.baseline===true,Ae=e.left==="current",te=vt(()=>v?v.excludedKeys?.length?new Set(v.excludedKeys):hr:null,[v]),K=!!v?.scope?.length&&!v?.excludedKeys?.length,$=vt(()=>{if(!K||!v?.scope)return hr;let c=new Set(v.scope),S=new Set;for(let C of e.sources)for(let R of C.items){let _=he(C.id,R.key);Ye[R.verdict].applies&&!c.has(_)&&S.add(_)}return S},[K,v,e.sources]),ne=Qt(null);ao(()=>{if(!v||e.building||!te||ne.current===v.id)return;ne.current=v.id,z.current=false;let c=te.size>0?te:$;c.size>0&&p(new Set(c)),K&&c.size>0&&x.setExclusions(v.id,Array.from(c))},[v,e.building,te,$,K]),ao(()=>{if(!v||!te||!z.current||cs(l,te))return;let c=Array.from(l);x.setExclusions(v.id,c.length?c:null)},[l,v,te]);let pe=ke(c=>{z.current=true,p(S=>{let C=new Set(S);return C.has(c)?C.delete(c):C.add(c),C})},[]),De=ke((c,S)=>{z.current=true,p(C=>{let R=new Set(C);for(let _ of c.items){if(!Ye[_.verdict].applies)continue;let re=he(c.id,_.key);S==="all"?R.add(re):R.delete(re)}return R})},[]),ie=ke((c,S)=>{g(C=>({...C,[c]:!S}))},[]),D=vt(()=>{let c=0,S=0,C=0,R=[];for(let _ of e.sources){let re=0;for(let Y of _.items)Ye[Y.verdict].applies?l.has(he(_.id,Y.key))?S+=1:(c+=1,re+=1):Y.verdict==="wont-apply"&&(C+=1);re>0&&R.push(`${re} ${_.label.toLowerCase()}`)}return{applies:c,excludedCount:S,wontApply:C,perSource:R}},[e.sources,l]);Sa(s?{title:"Restore Preview",subtitle:v?.name??"preview",onBack:i,actions:y(zo,{armId:v?.id})}:null,[s,v?.name,v?.id]);let{rows:et,blockedSources:Pe}=vt(()=>{let c=W.trim().toLowerCase(),S=[],C=[];for(let R of e.sources){let _=R.items.some(L=>L.verdict!=="unchanged");if(!_&&!R.error)continue;let re=_||R.notes.length>0||!!R.error,Y=R.items.filter(L=>Ye[L.verdict].applies),He=R.items.filter(L=>L.verdict==="wont-apply").length;He>0&&C.push(R.label);let ot=R.items.length===1?(Oo[R.id]??"items").replace(/ies$/,"y").replace(/s$/,""):Oo[R.id]??"items",q=`${R.items.length} ${ot} \xB7 `+(Y.length>0?`${Y.length} changed`:He>0?`${He} won't apply`:"no changes"),Ce=Y.filter(L=>l.has(he(R.id,L.key))).length,nt=Y.length===0||Ce===0?"all":Ce===Y.length?"none":"some",ce={added:0,removed:0,changed:0};for(let L of R.items)l.has(he(R.id,L.key))||(L.verdict==="added"?ce.added+=1:L.verdict==="removed"?ce.removed+=1:(L.verdict==="changed"||L.verdict==="too-large")&&(ce.changed+=1));let ze=R.items.filter(L=>!(L.verdict==="unchanged"||c&&!L.label.toLowerCase().includes(c))),it=re?u[R.id]??true:true;if(S.push({kind:"source",source:R,collapsed:it,includeState:nt,applicableCount:Y.length,counts:ce,expandable:re,summary:q,first:false,last:false}),!it){for(let L of R.notes)S.push({kind:"note",id:`${R.id}:${L}`,text:L,first:false,last:false});R.error&&S.push({kind:"note",id:`${R.id}:err`,text:`\u26A0 ${R.error}`,first:false,last:false});for(let L of ze){let b=he(R.id,L.key);S.push({kind:"item",sourceId:R.id,item:L,excluded:l.has(b),first:false,last:false}),m.has(b)&&S.push({kind:"diff",sourceId:R.id,item:L,first:false,last:false})}}}return v?.route&&S.push({kind:"route",href:v.route.href,on:pt(v),first:false,last:false}),S.length>0&&(S[0].first=true,S[S.length-1].last=true),{rows:S,blockedSources:C}},[e.sources,W,u,l,m,v]),tt=ke(({item:c})=>{if(c.kind==="source"){let S=c.source,{counts:C}=c;return y(Qe,{position:c,children:B(h,{style:w.sourceCard,children:[y(E,{onPress:()=>De(S,c.includeState),disabled:c.applicableCount===0,hitSlop:{top:10,bottom:10,left:8,right:8},testID:`tm-preview-source-toggle-${S.id}`,children:y(mr,{state:c.applicableCount===0?"none":c.includeState})}),B(E,{style:w.sourceCardTouch,onPress:()=>c.expandable&&ie(S.id,c.collapsed),disabled:!c.expandable,testID:`tm-preview-source-${S.id}`,children:[B(h,{style:w.sourceNameBlock,children:[y(d,{style:w.sourceName,numberOfLines:1,testID:`tm-preview-source-${S.id}-name`,children:S.label}),y(d,{style:w.sourceSummary,numberOfLines:1,testID:`tm-preview-source-${S.id}-summary`,children:c.includeState==="none"&&c.applicableCount>0?`${c.summary} \xB7 excluded`:c.summary})]}),B(h,{style:w.sourceBadges,children:[C.removed>0?y(pr,{glyph:"\u2212",count:C.removed,color:o.color.danger,testID:`tm-preview-source-${S.id}-removed`}):null,C.added>0?y(pr,{glyph:"+",count:C.added,color:o.color.accent,testID:`tm-preview-source-${S.id}-added`}):null,C.changed>0?y(pr,{glyph:"\u2248",count:C.changed,color:o.color.info,testID:`tm-preview-source-${S.id}-changed`}):null]}),c.expandable?c.collapsed?y(Qr,{}):y(so,{size:16,color:o.color.labelTertiary}):null]})]})})}return c.kind==="note"?y(Qe,{position:c,children:y(d,{style:w.noteRow,testID:`tm-preview-note-${c.id}`,children:c.text})}):c.kind==="route"?y(Qe,{position:c,children:B(E,{style:w.routeRow,onPress:ee,accessibilityRole:"switch",accessibilityState:{checked:c.on},accessibilityLabel:`Also return to ${c.href}`,testID:"tm-preview-route",children:[y(mr,{state:c.on?"all":"none"}),B(h,{style:w.routeText,children:[y(d,{style:w.routeTitle,children:"Return to this screen"}),y(d,{style:w.routeHref,numberOfLines:1,testID:"tm-preview-route-href",children:c.href})]})]})}):c.kind==="diff"?y(Qe,{position:c,children:y(os,{item:c.item,testID:`tm-preview-diff-${c.sourceId}-${c.item.key}`})}):y(ds,{row:c,expanded:m.has(he(c.sourceId,c.item.key)),onOpen:()=>j(he(c.sourceId,c.item.key)),onToggle:()=>pe(he(c.sourceId,c.item.key))})},[m,j,ie,pe,De,ee]),Te=ke(c=>c.kind==="source"?`s:${c.source.id}`:c.kind==="note"?`n:${c.id}`:c.kind==="route"?"route":c.kind==="diff"?`d:${c.sourceId}:${c.item.key}`:`i:${c.sourceId}:${c.item.key}`,[]),rt=B(h,{children:[!s&&B(h,{style:w.fallbackHeader,children:[y(E,{onPress:i,hitSlop:hs,testID:"tm-preview-back",children:y(d,{style:w.backText,children:"\u2039 Back"})}),y(d,{style:w.screenTitle,numberOfLines:1,children:"Restore Preview"})]}),v?B(ls,{children:[y(gt,{children:"Restore Point"}),y(yt,{children:y(ss,{name:v.name,onRename:c=>void x.rename(v.id,c)})})]}):null,y(gt,{children:"Changes to Restore"})]}),Oe=r||e.building||D.applies===0;return B(h,{style:w.container,children:[y(Tr,{testID:"tm-preview-list",data:et,renderItem:tt,keyExtractor:Te,ListHeaderComponent:rt,ListEmptyComponent:e.building?y(ct,{style:w.buildingSpinner,size:"small",color:o.color.accent}):y(d,{style:w.emptyText,testID:"tm-preview-empty",children:W?"Nothing matches this filter.":"No changes \u2014 restoring would change nothing."}),ListFooterComponent:y(h,{children:D.wontApply>0?B(h,{style:w.warnNote,children:[y(ba,{size:12,color:o.color.warning}),B(d,{style:w.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:w.listContent}),Ae&&v&&B(h,{style:[w.footer,{paddingBottom:f.bottom}],children:[B(E,{style:[w.cta,G&&w.ctaDanger,Oe&&w.ctaDisabled],onPress:()=>n(G?"reload":"live",Array.from(l)),disabled:G?r||e.building:Oe,testID:"tm-preview-restore",children:[y(wa,{size:16,color:G?o.color.onDanger:o.color.onAccent}),y(d,{style:[w.ctaText,G?w.ctaTextDanger:null],children:G?"Wipe & Reload":"Restore State"})]}),y(d,{style:w.ctaCaption,testID:"tm-preview-cta-caption",children:G?"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 hs={top:10,bottom:10,left:10,right:10},w=P.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:P.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:ft,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:ft,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:ft,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:P.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 ps}from"react/jsx-runtime";function ms(e,t){return e==="current"?void 0:t.find(r=>r.id===e.snapshotId)}function fs({preview:e,snapshots:t,busy:r,onClose:i}){let n=ms(e.right,t);return ps(us,{preview:e,snapshots:t,busy:r,onBack:i,onRestore:(a,s)=>{if(!(!n||r)){if(n.baseline){Kt("Restore fresh install?","This wipes all app storage and reloads the app.","Wipe & reload",()=>void x.restore(n.id,"reload"));return}x.restore(n.id,a,s).then(i)}}})}import{jsx as M,jsxs as Xe}from"react/jsx-runtime";var Ho=()=>ii().some(e=>e.id===sr);function fr(){let[e,t]=Br({kind:"list"}),{snapshots:r,busy:i,preview:n}=mt(),a=qi(),s=()=>{x.clearPreview(),t({kind:"list"})};return e.kind==="preview"&&n?M(fs,{preview:n,snapshots:r,busy:i!==null,onClose:s}):M(gs,{sources:a,onOpenPreview:f=>{x.buildPreview({snapshotId:f.id}),t({kind:"preview"})}})}function gs({sources:e,onOpenPreview:t}){let{snapshots:r,hasLoaded:i,busy:n,lastOutcome:a,recentlyDeleted:s,remoteProviders:f}=mt(),u=oi("timeMachine.snapshots"),g=si(),l=ri({minBottom:16}),p=jr(ai,Ho,Ho),z=jr(fo,It,It),m=p?go(r,z)?.id:void 0,O=ti({}),[j,W]=Br(null),v=$=>{W(null),cr($),g.minimize()},U=g.search.trim().toLowerCase(),ee=U?r.filter($=>$.name.toLowerCase().includes(U)):r,G=r.filter($=>!$.safety).length>=u,Ae=n!==null||G,te=$=>{if(n)return;if($.baseline){Kt("Restore fresh install?","This wipes all app storage and reloads the app.","Wipe & reload",()=>void x.restore($.id,"reload"));return}let ne=(O.current[$.id]??0)+1;O.current[$.id]=ne,ne>=2&&!p&&W($.id),x.restore($.id,"live").then(pe=>{!Object.values(pe.results).every(De=>De.ok)||pe.willReload||g.minimize()})},K=j&&!p?r.find($=>$.id===j)??null:null;return Xe(Ot,{style:Ze.fill,contentContainerStyle:[Ze.content,{paddingBottom:l.bottom}],testID:"time-machine-scroll",keyboardShouldPersistTaps:"handled",children:[a&&Xr(a)?M(ea,{outcome:a}):null,s?M(ca,{name:s.stored.meta.name,at:s.at,onUndo:()=>void x.undoDelete(),onExpire:()=>x.clearRecentlyDeleted()}):null,M(h,{children:M(Yi,{disabled:Ae,busy:n==="capture",onCapture:$=>void x.capture($)})}),G?Xe(Ke,{tone:"warning",testID:"time-machine-limit",children:["Free plan keeps ",u," restore point",u===1?"":"s",". Upgrade to Pro for unlimited snapshots."]}):null,M(gt,{children:"Sources"}),M(fa,{sources:e,onToggle:f?void 0:Jr}),f?null:M(Ke,{testID:"time-machine-sources-hint",children:"Switch a source off to leave it out of every capture and restore."}),M(gt,{children:"Restore Points"}),K?Xe(h,{style:Ze.barHint,testID:"time-machine-bar-hint",children:[Xe(Ke,{children:['Restoring "',K.name,'" a lot? Put it on the floating action bar and restore it with one tap.']}),M(E,{onPress:()=>v(K.id),accessibilityRole:"button",testID:"time-machine-bar-hint-pin",hitSlop:{top:6,bottom:6,left:6,right:6},children:M(d,{style:Ze.barHintAction,children:"Open the action bar"})})]}):null,Xe(yt,{children:[ee.map($=>M(aa,{meta:$,busy:n!==null,armed:$.id===m,onOpen:()=>t($),onRestore:()=>te($),onDelete:()=>void x.delete($.id),onDuplicate:()=>void x.duplicate($.id),onArm:()=>v($.id)},$.id)),ee.length===0?M(ni,{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(Ke,{testID:"time-machine-swipe-hint",children:"Swipe a restore point to copy or delete it."}):null,M(h,{style:Ze.spacer}),M(yt,{children:M(ga,{disabled:n!==null,onWipe:()=>Kt("Wipe all app state?","This deletes all app storage and reloads the app \u2014 like a fresh install.","Wipe & reload",()=>void x.wipeAll())})}),M(Ke,{centered:true,children:"Deletes all app storage and reloads \u2014 like a fresh install."})]})}var Ze=P.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 Bo}from"react/jsx-runtime";var Ct={id:"time-machine",name:"TIME MACHINE",description:"Snapshot & restore app state (storage, stores, query cache)",slot:"both",icon:({size:e,color:t,slot:r})=>Bo(Zn,{size:r==="dial"&&st.OS!=="web"?e*1.5:e,color:t||ei}),component:fr,modal:{subtitle:"snapshot & restore app state",searchable:true,searchPlaceholder:"Filter\u2026",headerActions:Bo(zo,{})}};function ys(e={}){return{...Ct,name:e.name??Ct.name,description:e.description??Ct.description}}import{JsModal as bs}from"@buoy-gg/shared-ui/web";import{jsx as Ee,jsxs as ws}from"react/jsx-runtime";function vs(){return ws(h,{style:gr.header,children:[Ee(d,{style:gr.headerTitle,children:"Time Machine"}),Ee(d,{style:gr.headerSubtitle,children:"Snapshot & restore app state"})]})}function Ss({visible:e,onClose:t,onBack:r,onMinimize:i,persistenceKey:n}){return Ee(bs,{visible:e,onClose:t,onMinimize:i,persistenceKey:n,header:{showToggleButton:true,customContent:Ee(vs,{})},enablePersistence:true,initialMode:"bottomSheet",disableScrollWrapper:true,children:Ee(fr,{})})}function xs(){return Ee(fr,{})}var gr=P.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 Rs,superJsonDeserialize as ks}from"@buoy-gg/shared-ui/web";import{jsonLikelyLargerThan as jo}from"@buoy-gg/shared-ui/web/dataViewer";function Ds(){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 Wo(){let{snapshots:e,busy:t,lastOutcome:r}=x.getState(),i=Yo();return{snapshots:e,busy:t,lastOutcome:r,providers:Ds(),route:{available:Be(),enabled:se(Me),...i?{current:i.href}:{}}}}var Ts={version:2,getSnapshot:()=>Wo(),subscribe:e=>{let t=x.subscribe(e),r=Rs(e);return()=>{t(),r()}},actions:{list:()=>Wo(),capture:async e=>{let{name:t="",sourceIds:r}=e??{};return{captured:true,snapshot:await x.capture(t,r)}},captureBaseline:async()=>({captured:true,snapshot:await x.captureBaseline()}),wipeAll:async()=>await x.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 x.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 x.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 x.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 x.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 x.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 x.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 x.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 x.buildPreview(i,n);let a=x.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(f=>({...f,items:f.items.map(u=>{let g=u.oldValue!==void 0&&jo(u.oldValue,s),l=u.newValue!==void 0&&jo(u.newValue,s);return{...u,oldValue:g?void 0:u.oldValue,newValue:l?void 0:u.newValue,...g||l?{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:ks(n)}}}};Ir();export{Ve as RESTORE_ORDER,Vt as SAFETY_SNAPSHOT_NAME,sr as TIME_MACHINE_FLOATING_TOOL_ID,Ss as TimeMachineModal,xs as TimeMachineToolView,Ir as armPendingRouteRestore,Be as canRestoreRoute,at as captureCurrentRoute,ys as createTimeMachineTool,se as isSourceEnabled,Lt as navigateToRoute,cr as openTimeMachineFloatingTool,zi as replaceTimeMachineFromSnapshot,Ci as setRemoteTimeMachineHandler,Jr as setSourceEnabled,Do as startTimeMachineFloatingToolPersistence,_r as subscribeSourceSettings,x as timeMachineStore,Ts as timeMachineSyncAdapter,Ct as timeMachineToolPreset};
3
+ ${t}`)&&n();return}Br.alert(e,t,[{text:"Cancel",style:"cancel"},{text:r,style:"destructive",onPress:n}])}import{useState as Xi}from"react";import{jsx as qt,jsxs as Yi}from"react/jsx-runtime";function Qi({disabled:e,busy:t,onCapture:r}){let[n,i]=Xi(""),a=()=>{e||(r(n),i(""),Dr.dismiss())};return Yi(p,{style:Fe.bar,children:[qt(st,{style:Fe.input,value:n,onChangeText:i,placeholder:"Name this restore point\u2026",placeholderTextColor:o.color.labelTertiary,editable:!e,onSubmitEditing:a,returnKeyType:"done",testID:"time-machine-name-input"}),qt(A,{style:[Fe.button,e?Fe.buttonDisabled:null],onPress:a,disabled:e,accessibilityRole:"button",accessibilityLabel:"Capture restore point",testID:"time-machine-capture",children:qt(d,{style:Fe.buttonText,children:t?"Capturing\u2026":"Capture"})})]})}var Fe=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 Zi}from"@buoy-gg/shared-ui/web";import{jsx as ge,jsxs as ye}from"react/jsx-runtime";var ea={top:10,bottom:10,left:10,right:10};function yt({glyph:e,text:t,ok:r,testID:n}){return ye(d,{style:[be.line,{color:r?o.color.accent:o.color.warning}],numberOfLines:2,testID:n,children:[ye(d,{style:be.glyph,children:[e," "]}),t]})}var Jt="time-machine-outcome-route";function ta({route:e}){return e.status==="navigated"?ge(yt,{glyph:"\u2713",ok:true,text:`route \u2014 ${e.href}`,testID:Jt}):e.status==="deferred"?ge(yt,{glyph:"\u21BB",ok:true,text:`route \u2014 ${e.href} after reload`,testID:Jt}):ge(yt,{glyph:"\u2715",ok:false,text:`route \u2014 ${e.error??e.status}`,testID:Jt})}function ra({outcome:e}){let t=Object.entries(e.results),r=e.mode==="reload"||e.willReload;return ye(p,{style:be.card,testID:"time-machine-outcome",children:[ye(p,{style:be.headerRow,children:[ye(d,{style:be.title,numberOfLines:1,testID:"time-machine-outcome-title",children:["Restored \u201C",e.snapshotName,"\u201D",r?" \xB7 reloading":""]}),ge(A,{onPress:()=>x.clearLastOutcome(),hitSlop:ea,accessibilityRole:"button",accessibilityLabel:"Dismiss restore result",testID:"time-machine-outcome-dismiss",children:ge(Zi,{size:13,color:o.color.labelSecondary})})]}),t.length===0&&!e.route?ge(d,{style:be.empty,testID:"time-machine-outcome-empty",children:"No sources restored."}):null,e.route?ge(ta,{route:e.route}):null,t.map(([n,i])=>ye(p,{children:[ge(yt,{testID:`time-machine-outcome-${n}`,glyph:i.ok?"\u2713":"\u2715",ok:i.ok,text:`${n} \u2014 applied ${i.applied}${i.skipped.length>0?`, skipped ${i.skipped.length}`:""}`}),i.skipped.slice(0,3).map(a=>ye(d,{style:be.detail,numberOfLines:2,children:[a.id,": ",a.reason]},a.id)),i.warnings.slice(0,3).map(a=>ye(d,{style:be.detail,numberOfLines:2,children:["\u26A0 ",a]},a))]},n))]})}var be=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 oa,useRef as eo}from"react";import{jsx as bt,jsxs as na}from"react/jsx-runtime";var to=84,ro=8,we=null;function ia(e,t){let r=false,n=a=>{r=a,a?(we&&we!==i&&we(),we=i):we===i&&(we=null),We.spring(e,{toValue:a?-t:0,useNativeDriver:true,bounciness:0,speed:18}).start()},i=()=>n(false);return{pan:Tr.create({onMoveShouldSetPanResponder:(a,s)=>Math.abs(s.dx)>Math.abs(s.dy)*1.5?s.dx<-ro||r&&s.dx>ro:false,onPanResponderMove:(a,s)=>{let g=r?-t:0;e.setValue(Math.min(0,Math.max(-t,g+s.dx)))},onPanResponderRelease:(a,s)=>{let g=(r?-t:0)+s.dx;n(s.vx<-.5?true:s.vx>.5?false:g<-t/2)},onPanResponderTerminate:()=>n(r)}),close:i}}function aa({children:e,actions:t,testID:r}){let n=to*t.length,i=eo(new We.Value(0)).current,a=eo(null);a.current===null&&(a.current=ia(i,n));let{pan:s,close:g}=a.current;oa(()=>()=>{we===g&&(we=null)},[g]);let h=i.interpolate({inputRange:[-24,0],outputRange:[1,0],extrapolate:"clamp"});return na(p,{style:Ke.clip,children:[bt(We.View,{style:[Ke.actionLayer,{width:n,opacity:h}],children:t.map(m=>bt(A,{style:[Ke.action,m.background?{backgroundColor:m.background}:null],onPress:()=>{g(),m.onPress()},accessibilityLabel:m.label,testID:m.testID??(r?`${r}-${m.label.toLowerCase()}`:void 0),children:bt(d,{style:[Ke.actionText,m.color?{color:m.color}:null],numberOfLines:1,children:m.label})},m.label))}),bt(We.View,{style:[Ke.content,{transform:[{translateX:i}]}],...s.panHandlers,children:e})]})}var Ke=O.create({clip:{overflow:"hidden"},actionLayer:{position:"absolute",top:0,bottom:0,right:0,flexDirection:"row"},action:{width:to,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 n=Math.round(r/60);return n<24?`${n}h ago`:`${Math.round(n/24)}d ago`}function sa(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 Ut}from"react/jsx-runtime";function oo(e){if(e.baseline)return"Wipes to fresh install";let t=[_e(e.createdAt),sa(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 la({meta:e,busy:t,armed:r=false,onOpen:n,onRestore:i,onDelete:a,onDuplicate:s,onArm:g}){let h=`time-machine-snap-${e.id}`;return Re(aa,{testID:h,actions:[{label:"Bar",onPress:g},{label:"Dup",onPress:s},{label:"Delete",onPress:a,background:o.color.danger,color:o.color.onDanger}],children:Ut(p,{style:de.row,children:[Ut(A,{style:de.text,onPress:n,activeOpacity:.7,accessibilityRole:"button",accessibilityLabel:`${e.name}. ${oo(e)}. Open restore preview`,testID:h,children:[Re(d,{style:de.name,numberOfLines:1,testID:`${h}-name`,children:e.name}),r?Re(d,{style:de.armed,numberOfLines:1,testID:`${h}-armed`,children:"On the action bar"}):null,Re(d,{style:de.meta,numberOfLines:1,testID:`${h}-meta`,children:oo(e)}),e.lastRestoredAt?Ut(d,{style:de.restored,numberOfLines:1,testID:`${h}-restored`,children:["Restored ",_e(e.lastRestoredAt)]}):null,e.route?Re(d,{style:de.route,numberOfLines:1,testID:`${h}-route`,children:e.route.href}):null]}),Re(A,{onPress:i,disabled:t,style:[de.restore,t?de.actionDisabled:null],accessibilityRole:"button",accessibilityLabel:e.baseline?"Wipe and reload":"Restore",testID:`${h}-restore`,children:Re(Bi,{testID:`${h}-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:mt,fontSize:o.font.mono,marginTop:4},actionDisabled:{opacity:.4}});import{useEffect as ca}from"react";import{jsx as no,jsxs as io}from"react/jsx-runtime";var da=8e3;function ua({name:e,at:t,onUndo:r,onExpire:n}){return ca(()=>{let i=setTimeout(n,da);return()=>clearTimeout(i)},[t]),io(p,{style:Gt.bar,testID:"time-machine-undo-bar",children:[io(d,{style:Gt.text,numberOfLines:1,testID:"time-machine-undo-text",children:["Deleted \u201C",e,"\u201D"]}),no(A,{onPress:r,hitSlop:{top:10,bottom:10,left:10,right:10},accessibilityRole:"button",testID:"time-machine-undo-delete",children:no(d,{style:Gt.undo,children:"Undo"})})]})}var Gt=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 ha}from"@buoy-gg/shared-ui/web";import{jsx as le,jsxs as Xt}from"react/jsx-runtime";var pa={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 ma(e){return pa[e.id]??"App data"}function fa(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 ga({source:e,onToggle:t}){let r=Ji(e.id),n=ma(e),i=fa(e);return Xt(p,{style:ue.row,testID:`time-machine-source-${e.id}`,accessibilityLabel:`${e.label}: ${n}${i?`. ${i.text}`:""}`,children:[le(p,{style:ue.disc,children:le(r,{size:22,bgColor:o.color.disc})}),Xt(p,{style:ue.text,children:[le(d,{style:ue.label,numberOfLines:1,testID:`time-machine-source-${e.id}-label`,children:e.label}),le(d,{style:ue.description,numberOfLines:2,testID:`time-machine-source-${e.id}-description`,children:n}),i?le(d,{style:[ue.state,ue[`state_${i.tone}`]],numberOfLines:1,testID:i.tone==="off"?`time-machine-source-${e.id}-off`:`time-machine-source-${e.id}-detail`,children:i.text}):null]}),le(p,{testID:`time-machine-source-${e.id}-switch`,children:le(ha,{value:e.enabled,disabled:!t,onValueChange:a=>t?.(e.id,a)})})]})}function ya({sources:e,onToggle:t}){let r=e.filter(n=>n.canCapture);return Xt(gt,{children:[r.map(n=>le(ga,{source:n,onToggle:t},n.id)),r.length===0?le(p,{style:ue.row,testID:"time-machine-sources-empty",children:le(d,{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 ao}from"react/jsx-runtime";function ba({disabled:e,onWipe:t}){return ao(A,{style:[Yt.row,e?Yt.disabled:null],onPress:t,disabled:e,accessibilityRole:"button",testID:"time-machine-wipe-all",children:ao(d,{style:Yt.label,children:"Wipe All App State\u2026"})})}var Yt=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 wa,useCallback as ke,useEffect as so,useMemo as wt,useRef as Qt,useState as Zt}from"react";import{ChevronUp as lo,AlertTriangle as Sa,RefreshCw as va,useSafeAreaInsets as xa}from"@buoy-gg/shared-ui/web";import{useToolHeader as Ia,useToolHost as Ra}from"@buoy-gg/core/web";import{night as St}from"@buoy-gg/shared-ui/web";import{useToolHost as ka}from"@buoy-gg/core/web";import{night as er}from"@buoy-gg/shared-ui/web";import{jsx as co}from"react/jsx-runtime";function Da(){let e=()=>{x.reloadApp()};return co(A,{style:uo.chip,onPress:e,accessibilityLabel:"Reload app",accessibilityHint:"Reloads the JavaScript bundle without restoring anything",accessibilityRole:"button",testID:"time-machine-reload-app",children:co(d,{style:uo.label,children:"Reload app"})})}var uo=O.create({chip:{height:32,paddingHorizontal:10,borderRadius:8,borderWidth:1,borderColor:er.color.border,backgroundColor:er.color.buttonSurface,alignItems:"center",justifyContent:"center"},label:{fontSize:11,fontWeight:"700",color:er.color.textSecondary}});import{useEffect as vt,useRef as Ta,useState as Se,useSyncExternalStore as ho}from"react";import{Check as po,ChevronDown as Ca,ChevronUp as za,FloatingTool as $a,NightSwitch as La,Plus as Aa,TimeMachineIcon as Pa,X as Ea,night as T,openFloatingTool as Oa,persistentStorage as Ha,registerPersistentFloatingTool as Ba,useLimit as Wa}from"@buoy-gg/shared-ui/web";import{devToolsStorageKeys as ja,persistentStorage as tr}from"@buoy-gg/shared-ui/web";var rr=ja.timeMachine.armedPoint(),qe=null,mo=false,or=null,nr=new Set,fo=()=>nr.forEach(e=>e());function xt(){return qe}function go(e){return nr.add(e),()=>{nr.delete(e)}}function Na(){return mo?Promise.resolve():(or||(or=tr.getItem(rr).then(e=>{qe===null&&e&&(qe=e,fo())}).catch(()=>{}).finally(()=>{mo=true})),or)}function ir(e){qe!==e&&(qe=e,fo(),(e===null?tr.removeItem(rr):tr.setItem(rr,e)).catch(()=>{}))}function yo(e,t){let r=e.filter(i=>!i.baseline&&!i.safety);if(r.length===0)return null;if(t){let i=r.find(a=>a.id===t);if(i)return i}let n=null;for(let i of r)i.lastRestoredAt!==void 0&&(!n||i.lastRestoredAt>(n.lastRestoredAt??0))&&(n=i);return n||r.reduce((i,a)=>a.createdAt>i.createdAt?a:i)}import{useEffect as Ma,useState as Va}from"react";import{night as B}from"@buoy-gg/shared-ui/web";import{jsx as ie,jsxs as bo}from"react/jsx-runtime";function Fa({visible:e,summary:t,onCapture:r,onCancel:n}){let[i,a]=Va("");Ma(()=>{e&&a("")},[e]);let s=()=>r(i.trim());return ie(Hr,{visible:e,transparent:true,animationType:"fade",onRequestClose:n,statusBarTranslucent:true,children:ie(zr,{behavior:at.OS==="ios"?"padding":void 0,style:ee.fill,children:ie(Pt,{style:ee.backdrop,onPress:n,accessibilityLabel:"Cancel",testID:"time-machine-bar-name-backdrop",children:bo(Pt,{style:ee.card,onPress:g=>g.stopPropagation(),testID:"time-machine-bar-name-panel",accessible:false,children:[ie(d,{style:ee.title,children:"Name this restore point"}),t?ie(d,{style:ee.summary,testID:"time-machine-bar-name-summary",children:t}):null,ie(st,{testID:"time-machine-bar-name-input",accessibilityLabel:"Restore point name",value:i,onChangeText:a,onSubmitEditing:s,placeholder:"Screen and time, if left empty",placeholderTextColor:B.color.placeholder,autoFocus:true,autoCorrect:false,autoCapitalize:"none",returnKeyType:"done",style:ee.input}),ie(d,{style:ee.hint,children:"Captures the state the app is in right now and arms it on the bar."}),bo(p,{style:ee.actions,children:[ie(A,{testID:"time-machine-bar-name-cancel",accessibilityRole:"button",onPress:n,style:ee.secondary,children:ie(d,{style:ee.secondaryText,children:"Cancel"})}),ie(A,{testID:"time-machine-bar-name-capture",accessibilityRole:"button",accessibilityLabel:"Capture and arm this restore point",onPress:s,style:ee.primary,children:ie(d,{style:ee.primaryText,children:"Capture"})})]})]})})})})}var ee=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:B.radius.sheet,borderWidth:1,borderColor:B.color.separator,backgroundColor:B.color.surface,padding:18,gap:12,shadowColor:"#000",shadowOffset:{width:0,height:12},shadowOpacity:.4,shadowRadius:24,elevation:12},title:{color:B.color.text,fontSize:B.font.title,fontWeight:"600"},input:{minHeight:44,borderRadius:B.radius.input,borderWidth:1,borderColor:B.color.accentBorder,backgroundColor:B.color.surfaceElevated,color:B.color.text,fontSize:B.font.row,paddingHorizontal:12},summary:{color:B.color.textTertiary,fontSize:B.font.caption,marginTop:-6},hint:{color:B.color.textSecondary,fontSize:B.font.caption,lineHeight:18},actions:{flexDirection:"row",justifyContent:"flex-end",gap:10,marginTop:4},secondary:{minHeight:40,paddingHorizontal:14,borderRadius:B.radius.input,alignItems:"center",justifyContent:"center"},secondaryText:{color:B.color.textSecondary,fontSize:14,fontWeight:"600"},primary:{minHeight:40,paddingHorizontal:18,borderRadius:B.radius.input,backgroundColor:B.color.accent,alignItems:"center",justifyContent:"center"},primaryText:{color:B.color.onAccent,fontSize:14,fontWeight:"700"}});import{devToolsStorageKeys as Ka,persistentStorage as wo}from"@buoy-gg/shared-ui/web";var So=Ka.timeMachine.barReloadMode(),Je=false,vo=false,ar=null,sr=new Set,xo=()=>sr.forEach(e=>e());function Io(){return Je}function _a(e){return sr.add(e),()=>{sr.delete(e)}}function qa(){return vo?Promise.resolve():(ar||(ar=wo.getItem(So).then(e=>{!Je&&e==="1"&&(Je=true,xo())}).catch(()=>{}).finally(()=>{vo=true})),ar)}function Ja(e){e!==Je&&(Je=e,xo(),wo.setItem(So,e?"1":"0").catch(()=>{}))}import{Fragment as Ua,jsx as k,jsxs as F}from"react/jsx-runtime";var lr="time-machine-restore",It=1e4,Ro=900,cr=6,ko={id:lr,render:e=>k(Ya,{...e})},Do=false;function To(){Do||(Do=true,Ba(ko,Ha))}typeof vr<"u"&&vr&&typeof navigator<"u"&&navigator.product==="ReactNative"&&To();function dr(e){e&&ir(e),Oa(ko)}function Ga(e){let t=Object.values(e.results),r=t.filter(s=>!s.ok||s.skipped.length>0).length,n=t.length,i=e.route,a=i?.status==="failed"||i?.status==="unavailable";return r===0&&a?"Route did not restore":`${r} of ${n} source${n===1?"":"s"} failed`}function Xa(e){let t=[];for(let[n,i]of Object.entries(e.results)){if(i.ok&&i.skipped.length===0)continue;let a=i.skipped[0]?.reason??i.warnings[0]??"did not apply";t.push(`${n}: ${a}`)}let r=e.route;return(r?.status==="failed"||r?.status==="unavailable")&&t.push(`route: ${r.status}`),t}function Co(e){let[t,r]=Se(0);return vt(()=>{if(!t)return;let n=setTimeout(()=>r(0),e);return()=>clearTimeout(n)},[t,e]),[t>0,()=>r(n=>n+1)]}function Ya({id:e,revealToken:t,dismiss:r}){let{snapshots:n,hasLoaded:i,busy:a}=pt(),s=Qr(),g=ho(go,xt,xt),h=Wa("timeMachine.snapshots"),m=ho(_a,Io,Io),{width:c}=$r(),[u,z]=Se(null),[w,E]=Se(null),[M,H]=Se(),[S,U]=Se(false),[te,G]=Co(Ro),[Ae,re]=Co(Ro),[K,$]=Se(null),[ae,ve]=Se(null),[,Qe]=Se(0),se=Ta(true);vt(()=>(se.current=true,Na(),qa(),x.ensureLoaded(),()=>{se.current=false}),[]);let D=yo(n,g),Ze=D?.id,Pe=D?.lastRestoredAt,et=D?.createdAt;vt(()=>{if(Pe===void 0&&et===void 0&&!K&&ae===null)return;let y=setInterval(()=>Qe(V=>V+1),2500);return()=>clearInterval(y)},[Pe,et,K,ae]),vt(()=>{w&&w.snapshotId!==Ze&&(E(null),z(y=>y==="outcome"?null:y))},[Ze,w]);let De=Date.now(),tt=K!==null&&De-K.at<It&&n.some(y=>y.id===K.id),Ee=n.filter(y=>!y.safety).length>=h,l=!D||a!==null,v=a!==null,C=async(y,V)=>{if(!a){z(null),H(void 0);try{let Y=await x.restore(y,m&&V.safetyCapture?"reload":"live",void 0,V);if(!se.current)return;Ft(Y)?(E(Y),z("outcome")):(E(null),G()),$(Y.safetySnapshotId?{id:Y.safetySnapshotId,at:Date.now()}:null),Y.safetySnapshotId&&ve(null)}catch(Y){if(!se.current)return;H(Y instanceof Error?Y.message:String(Y)),z("error")}}},R=(y=false)=>{D&&C(D.id,{safetyCapture:true,...y?{restoreRoute:false}:{}})},_=()=>{K&&C(K.id,{safetyCapture:false,restoreRoute:false}).then(()=>{se.current&&ve(Date.now())})},oe=()=>{if(!a){if(H(void 0),Ee){z("cap");return}z(null),U(true)}},X=async y=>{if(U(false),!a)try{let V=await x.capture(y);if(!se.current)return;ir(V.id),$(null),re()}catch(V){if(!se.current)return;H(V instanceof Error?V.message:String(V)),z("error")}},Oe=y=>{ir(y.id),z(null)},rt=D?.name??(i?"No restore points":"Loading\u2026"),q,Te="normal",ot=false;if(a==="restore")q="Restoring\u2026";else if(a==="capture")q="Capturing\u2026";else if(M)q=M,Te="danger";else if(w&&D&&w.snapshotId===D.id)q=Ga(w),Te="danger";else if(!D)q=i?"Capture one with +":"";else{ot=true;let y=D.lastRestoredAt===void 0?null:De-D.lastRestoredAt,V=De-D.createdAt;ae!==null&&De-ae<It?q="undone, state only":y!==null&&y<It?q="restored just now":V<It&&y===null?q="captured just now":D.lastRestoredAt!==void 0?q=`restored ${_e(D.lastRestoredAt)}`:q=`${Object.keys(D.sources).length} sources`,m&&(q+=" \xB7 reloads")}let ce=ot&&!tt&&D&&D.route&&ut(D)?D.route.pathname:null,Ce=n.filter(y=>!y.baseline&&!y.safety),nt=(()=>{let y=s.filter(br=>br.status().canCapture&&ne(br.id)).length,V=it(),Y=[`${y} source${y===1?"":"s"}`];return V&&Y.push(V.pathname),Y.join(" \xB7 ")})(),L;return u==="picker"?L=F(p,{style:I.menu,testID:"time-machine-bar-picker",children:[F(Et,{keyboardShouldPersistTaps:"handled",style:I.pickerList,bounces:false,children:[Ce.map(y=>{let V=y.id===D?.id;return F(A,{testID:`time-machine-bar-pick-${y.id}`,accessibilityRole:"button",accessibilityState:{selected:V},accessibilityLabel:`Arm ${y.name}`,onPress:()=>Oe(y),style:I.pickRow,children:[F(p,{style:I.pickText,children:[k(d,{numberOfLines:1,style:I.pickName,children:y.name}),F(d,{numberOfLines:1,style:I.pickDetail,children:[_e(y.createdAt),y.route?` \xB7 ${y.route.pathname}`:"",y.lastRestoredAt!==void 0?k(d,{style:I.pickRestored,children:` \xB7 restored ${_e(y.lastRestoredAt)}`}):null]})]}),V?k(po,{size:14,color:T.color.accent}):null]},y.id)}),Ce.length===0?k(d,{style:I.menuText,children:"No restore points yet."}):null]}),Ce.length>cr?F(d,{style:I.pickerMore,children:["Scroll for ",Ce.length-cr," more"]}):null,F(p,{style:I.settingRow,testID:"time-machine-bar-reload-mode",children:[F(p,{style:I.settingText,children:[k(d,{style:I.settingLabel,children:"Reload the app after restoring"}),k(d,{style:I.settingHint,children:"For screens that read their state from storage only when they open, like a cart kept in a React context."})]}),k(La,{value:m,onValueChange:Ja,testID:"time-machine-bar-reload-switch",accessibilityLabel:"Reload the app after restoring"})]})]}):u==="outcome"&&w?L=F(p,{style:I.menu,testID:"time-machine-bar-outcome",children:[Xa(w).map(y=>k(d,{style:I.menuDanger,children:y},y)),k(d,{style:I.menuText,children:"The full report is on Time Machine's outcome card."}),k(ur,{onPress:()=>z(null)})]}):u==="cap"?L=F(p,{style:I.menu,testID:"time-machine-bar-cap",children:[F(d,{style:I.menuText,children:["Free plan keeps ",h," restore point",h===1?"":"s",". Delete one in Time Machine, or upgrade to Pro for unlimited snapshots."]}),k(ur,{onPress:()=>z(null)})]}):u==="error"&&M&&(L=F(p,{style:I.menu,testID:"time-machine-bar-error",children:[k(d,{accessibilityRole:"alert",style:I.menuDanger,children:M}),k(ur,{onPress:()=>{z(null),H(void 0)}})]})),F(Ua,{children:[k(Fa,{visible:S,summary:nt,onCapture:y=>void X(y),onCancel:()=>U(false)}),k($a,{id:e,revealToken:t,variant:"strip",dragFromSurface:true,defaultPlacement:"bottom",accessibilityLabel:`Move or hide the action bar. ${D?`${D.name} armed`:"Nothing armed"}`,accessory:L,handleAdornment:k(Pa,{size:12,color:T.color.accent}),children:F(p,{style:[I.row,{width:Math.max(260,Math.min(320,c-64))}],children:[k(A,{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:()=>R(false),onLongPress:()=>R(true),style:[I.restoreButton,l&&I.disabled],children:a==="restore"?k(lt,{size:"small",color:T.color.accent}):te?k(d,{style:I.restoreText,testID:"time-machine-bar-restored",children:"Restored"}):k(d,{style:I.restoreText,children:"Restore"})}),F(p,{style:I.identity,children:[k(d,{testID:"time-machine-bar-name",accessibilityLabel:`Armed restore point: ${rt}`,numberOfLines:1,ellipsizeMode:"middle",style:I.name,children:rt}),F(p,{style:I.statusRow,children:[F(d,{testID:"time-machine-bar-status",numberOfLines:1,accessibilityLiveRegion:"polite",style:[I.status,Te==="danger"&&I.danger],children:[q,ce?k(d,{style:I.destination,children:` \xB7 \u2192 ${ce}`}):null]}),tt&&!a?k(A,{testID:"time-machine-bar-undo",accessibilityRole:"button",accessibilityLabel:"Undo the last restore",onPress:_,hitSlop:{top:8,bottom:8,left:6,right:6},children:k(d,{style:I.undo,children:"Undo"})}):null]})]}),k(A,{testID:"time-machine-bar-pick",accessibilityRole:"button",accessibilityLabel:"Choose another restore point",accessibilityState:{expanded:u==="picker"},onPress:()=>z(y=>y==="picker"?null:"picker"),style:I.smallButton,children:u==="picker"?k(za,{size:14,color:T.color.textSecondary}):k(Ca,{size:14,color:T.color.textSecondary})}),k(A,{testID:"time-machine-bar-capture",accessibilityRole:"button",accessibilityLabel:"Capture a new restore point here and arm it",accessibilityState:{disabled:v},disabled:v,onPress:oe,style:[I.smallButton,v&&I.disabled],children:a==="capture"?k(lt,{size:"small",color:T.color.accent}):Ae?k(p,{testID:"time-machine-bar-captured",children:k(po,{size:18,color:T.color.accent})}):k(Aa,{size:18,color:Ee?T.color.textTertiary:T.color.text})}),k(p,{style:I.separator}),k(A,{testID:"time-machine-bar-close",accessibilityRole:"button",accessibilityLabel:"Close the action bar",onPress:r,style:I.closeButton,children:k(Ea,{size:16,color:T.color.textSecondary})})]})})]})}function ur({onPress:e,label:t="Dismiss"}){return k(A,{testID:"time-machine-bar-dismiss",accessibilityRole:"button",onPress:e,style:I.dismiss,children:k(d,{style:I.dismissText,children:t})})}var I=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:cr*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 Rt,jsxs as zo}from"react/jsx-runtime";function Qa({armId:e}){let t=ka(),r=()=>{dr(e),t.minimize()};return zo(A,{style:kt.labeledChip,onPress:r,accessibilityLabel:"Open the floating action bar over the app",accessibilityRole:"button",testID:"time-machine-header-bar",children:[Rt(p,{style:kt.glyph}),Rt(d,{style:kt.label,children:"Action bar"})]})}function $o({armId:e}){return zo(p,{style:kt.row,children:[Rt(Qa,{armId:e}),Rt(Da,{})]})}var kt=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:St.color.border,backgroundColor:St.color.buttonSurface},glyph:{width:14,height:8,borderRadius:3,borderWidth:1.5,borderColor:St.color.accent},label:{fontSize:11,fontWeight:"700",color:St.color.accent}});import{useMemo as Za}from"react";import{ABSENT_VALUE as Lo,ThemedSplitView as es,devToolsDefaultTheme as ts,toDiffable as Ao}from"@buoy-gg/shared-ui/web/dataViewer";import{jsx as rs,jsxs as Po}from"react/jsx-runtime";var os=[];function ns({item:e,testID:t}){let{oldValue:r,newValue:n}=Za(()=>({oldValue:e.verdict==="added"?Lo:Ao(e.oldValue),newValue:e.verdict==="removed"?Lo:Ao(e.newValue)}),[e]);return Po(p,{style:Eo.panel,testID:t,children:[e.reason?Po(d,{style:Eo.reason,children:["\u26A0 ",e.reason]}):null,rs(es,{oldValue:r,newValue:n,differences:os,theme:ts,scrollEnabled:false})]})}var Eo=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 is,useState as as}from"react";import{jsx as Oo,jsxs as ss}from"react/jsx-runtime";function ls({name:e,onRename:t}){let[r,n]=as(e);is(()=>n(e),[e]);let i=()=>{let a=r.trim();if(!a){n(e);return}a!==e&&t(a)};return ss(p,{style:hr.row,children:[Oo(d,{style:hr.label,children:"Name"}),Oo(st,{style:hr.input,value:r,onChangeText:n,onSubmitEditing:i,onBlur:i,returnKeyType:"done",selectTextOnFocus:true,accessibilityLabel:"Restore point name",testID:"tm-preview-name"})]})}var hr=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 Ue={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 cs,jsx as f,jsxs as W}from"react/jsx-runtime";var Ho={storage:"keys",redux:"slices",zustand:"stores",jotai:"atoms",query:"queries"},pr=new Set;function ds(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 Dt(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 Ge({position:e,children:t}){return W(p,{style:[b.cardRow,e.first?b.cardRowFirst:null,e.last?b.cardRowLast:null],children:[e.first?null:f(p,{style:b.cardSeparator}),t]})}function mr({glyph:e,count:t,color:r,testID:n}){return f(p,{style:[b.countPill,{backgroundColor:`${r}26`}],children:W(d,{style:[b.countPillText,{color:r}],testID:n,children:[e,t]})})}function fr({state:e}){return f(p,{style:[b.checkbox,e!=="none"&&b.checkboxChecked],children:e==="none"?null:f(d,{style:b.checkboxGlyph,children:e==="all"?"\u2713":"\u2212"})})}var us=wa(function({row:e,expanded:t,onOpen:r,onToggle:n}){let i=Ue[e.item.verdict],a=!i.applies||e.excluded,s=e.item.verdict==="changed"||e.item.verdict==="added"||e.item.verdict==="removed",g=`tm-preview-item-${e.sourceId}-${e.item.key}`;return f(Ge,{position:e,children:W(p,{style:[b.itemRow,a&&b.dimmed],children:[f(A,{onPress:n,disabled:!i.applies,hitSlop:{top:10,bottom:10,left:8,right:8},testID:`tm-preview-toggle-${e.sourceId}-${e.item.key}`,accessibilityRole:"checkbox",accessibilityState:{checked:!(!i.applies||e.excluded)},accessibilityLabel:`Include ${e.item.label}`,children:f(fr,{state:!i.applies||e.excluded?"none":"all"})}),W(A,{style:b.itemBodyTouch,onPress:()=>s&&r(),disabled:!s,testID:g,children:[f(d,{style:[b.itemGlyph,{color:i.color}],children:i.glyph}),W(p,{style:b.itemBody,children:[f(d,{style:b.itemLabel,numberOfLines:1,testID:`${g}-label`,children:e.item.label}),e.item.verdict==="changed"&&W(d,{style:b.itemPreview,numberOfLines:1,testID:`${g}-values`,children:[Dt(e.item.oldValue)," \u2192"," ",Dt(e.item.newValue)]}),e.item.verdict==="added"&&f(d,{style:b.itemPreview,numberOfLines:1,testID:`${g}-values`,children:Dt(e.item.newValue)}),e.item.verdict==="removed"&&f(d,{style:[b.itemPreview,b.itemPreviewRemoved],numberOfLines:1,testID:`${g}-values`,children:Dt(e.item.oldValue)}),e.excluded?f(d,{style:b.itemExcluded,testID:`${g}-excluded`,children:"excluded \u2014 restore leaves this untouched"}):e.item.reason&&f(d,{style:b.itemReason,numberOfLines:2,testID:`${g}-reason`,children:e.item.reason})]}),s?t?f(lo,{size:16,color:o.color.labelTertiary}):f(Zr,{}):null]})]})})});function hs({preview:e,snapshots:t,busy:r,onBack:n,onRestore:i}){let a=Ra(),s=a.instanceId!==void 0,g=xa({minBottom:16}),[h,m]=Zt({}),[c,u]=Zt(new Set),z=Qt(false),[w,E]=Zt(pr),M=ke(l=>{E(v=>{let C=new Set(v);return C.has(l)?C.delete(l):C.add(l),C})},[]),H=a.search,S=e.right==="current"?void 0:t.find(l=>l.id===e.right.snapshotId),U=Qt(S);U.current=S;let te=ke(()=>{if(!U.current)return;let l=U.current;x.setRestoreRoute(l.id,!ut(l))},[]),G=S?.baseline===true,Ae=e.left==="current",re=wt(()=>S?S.excludedKeys?.length?new Set(S.excludedKeys):pr:null,[S]),K=!!S?.scope?.length&&!S?.excludedKeys?.length,$=wt(()=>{if(!K||!S?.scope)return pr;let l=new Set(S.scope),v=new Set;for(let C of e.sources)for(let R of C.items){let _=he(C.id,R.key);Ue[R.verdict].applies&&!l.has(_)&&v.add(_)}return v},[K,S,e.sources]),ae=Qt(null);so(()=>{if(!S||e.building||!re||ae.current===S.id)return;ae.current=S.id,z.current=false;let l=re.size>0?re:$;l.size>0&&u(new Set(l)),K&&l.size>0&&x.setExclusions(S.id,Array.from(l))},[S,e.building,re,$,K]),so(()=>{if(!S||!re||!z.current||ds(c,re))return;let l=Array.from(c);x.setExclusions(S.id,l.length?l:null)},[c,S,re]);let ve=ke(l=>{z.current=true,u(v=>{let C=new Set(v);return C.has(l)?C.delete(l):C.add(l),C})},[]),Qe=ke((l,v)=>{z.current=true,u(C=>{let R=new Set(C);for(let _ of l.items){if(!Ue[_.verdict].applies)continue;let oe=he(l.id,_.key);v==="all"?R.add(oe):R.delete(oe)}return R})},[]),se=ke((l,v)=>{m(C=>({...C,[l]:!v}))},[]),D=wt(()=>{let l=0,v=0,C=0,R=[];for(let _ of e.sources){let oe=0;for(let X of _.items)Ue[X.verdict].applies?c.has(he(_.id,X.key))?v+=1:(l+=1,oe+=1):X.verdict==="wont-apply"&&(C+=1);oe>0&&R.push(`${oe} ${_.label.toLowerCase()}`)}return{applies:l,excludedCount:v,wontApply:C,perSource:R}},[e.sources,c]);Ia(s?{title:"Restore Preview",subtitle:S?.name??"preview",onBack:n,actions:f($o,{armId:S?.id})}:null,[s,S?.name,S?.id]);let{rows:Ze,blockedSources:Pe}=wt(()=>{let l=H.trim().toLowerCase(),v=[],C=[];for(let R of e.sources){let _=R.items.some(L=>L.verdict!=="unchanged");if(!_&&!R.error)continue;let oe=_||R.notes.length>0||!!R.error,X=R.items.filter(L=>Ue[L.verdict].applies),Oe=R.items.filter(L=>L.verdict==="wont-apply").length;Oe>0&&C.push(R.label);let rt=R.items.length===1?(Ho[R.id]??"items").replace(/ies$/,"y").replace(/s$/,""):Ho[R.id]??"items",q=`${R.items.length} ${rt} \xB7 `+(X.length>0?`${X.length} changed`:Oe>0?`${Oe} won't apply`:"no changes"),Te=X.filter(L=>c.has(he(R.id,L.key))).length,ot=X.length===0||Te===0?"all":Te===X.length?"none":"some",ce={added:0,removed:0,changed:0};for(let L of R.items)c.has(he(R.id,L.key))||(L.verdict==="added"?ce.added+=1:L.verdict==="removed"?ce.removed+=1:(L.verdict==="changed"||L.verdict==="too-large")&&(ce.changed+=1));let Ce=R.items.filter(L=>!(L.verdict==="unchanged"||l&&!L.label.toLowerCase().includes(l))),nt=oe?h[R.id]??true:true;if(v.push({kind:"source",source:R,collapsed:nt,includeState:ot,applicableCount:X.length,counts:ce,expandable:oe,summary:q,first:false,last:false}),!nt){for(let L of R.notes)v.push({kind:"note",id:`${R.id}:${L}`,text:L,first:false,last:false});R.error&&v.push({kind:"note",id:`${R.id}:err`,text:`\u26A0 ${R.error}`,first:false,last:false});for(let L of Ce){let y=he(R.id,L.key);v.push({kind:"item",sourceId:R.id,item:L,excluded:c.has(y),first:false,last:false}),w.has(y)&&v.push({kind:"diff",sourceId:R.id,item:L,first:false,last:false})}}}return S?.route&&v.push({kind:"route",href:S.route.href,on:ut(S),first:false,last:false}),v.length>0&&(v[0].first=true,v[v.length-1].last=true),{rows:v,blockedSources:C}},[e.sources,H,h,c,w,S]),et=ke(({item:l})=>{if(l.kind==="source"){let v=l.source,{counts:C}=l;return f(Ge,{position:l,children:W(p,{style:b.sourceCard,children:[f(A,{onPress:()=>Qe(v,l.includeState),disabled:l.applicableCount===0,hitSlop:{top:10,bottom:10,left:8,right:8},testID:`tm-preview-source-toggle-${v.id}`,children:f(fr,{state:l.applicableCount===0?"none":l.includeState})}),W(A,{style:b.sourceCardTouch,onPress:()=>l.expandable&&se(v.id,l.collapsed),disabled:!l.expandable,testID:`tm-preview-source-${v.id}`,children:[W(p,{style:b.sourceNameBlock,children:[f(d,{style:b.sourceName,numberOfLines:1,testID:`tm-preview-source-${v.id}-name`,children:v.label}),f(d,{style:b.sourceSummary,numberOfLines:1,testID:`tm-preview-source-${v.id}-summary`,children:l.includeState==="none"&&l.applicableCount>0?`${l.summary} \xB7 excluded`:l.summary})]}),W(p,{style:b.sourceBadges,children:[C.removed>0?f(mr,{glyph:"\u2212",count:C.removed,color:o.color.danger,testID:`tm-preview-source-${v.id}-removed`}):null,C.added>0?f(mr,{glyph:"+",count:C.added,color:o.color.accent,testID:`tm-preview-source-${v.id}-added`}):null,C.changed>0?f(mr,{glyph:"\u2248",count:C.changed,color:o.color.info,testID:`tm-preview-source-${v.id}-changed`}):null]}),l.expandable?l.collapsed?f(Zr,{}):f(lo,{size:16,color:o.color.labelTertiary}):null]})]})})}return l.kind==="note"?f(Ge,{position:l,children:f(d,{style:b.noteRow,testID:`tm-preview-note-${l.id}`,children:l.text})}):l.kind==="route"?f(Ge,{position:l,children:W(A,{style:b.routeRow,onPress:te,accessibilityRole:"switch",accessibilityState:{checked:l.on},accessibilityLabel:`Also return to ${l.href}`,testID:"tm-preview-route",children:[f(fr,{state:l.on?"all":"none"}),W(p,{style:b.routeText,children:[f(d,{style:b.routeTitle,children:"Return to this screen"}),f(d,{style:b.routeHref,numberOfLines:1,testID:"tm-preview-route-href",children:l.href})]})]})}):l.kind==="diff"?f(Ge,{position:l,children:f(ns,{item:l.item,testID:`tm-preview-diff-${l.sourceId}-${l.item.key}`})}):f(us,{row:l,expanded:w.has(he(l.sourceId,l.item.key)),onOpen:()=>M(he(l.sourceId,l.item.key)),onToggle:()=>ve(he(l.sourceId,l.item.key))})},[w,M,se,ve,Qe,te]),De=ke(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}`,[]),tt=W(p,{children:[!s&&W(p,{style:b.fallbackHeader,children:[f(A,{onPress:n,hitSlop:ps,testID:"tm-preview-back",children:f(d,{style:b.backText,children:"\u2039 Back"})}),f(d,{style:b.screenTitle,numberOfLines:1,children:"Restore Preview"})]}),S?W(cs,{children:[f(ft,{children:"Restore Point"}),f(gt,{children:f(ls,{name:S.name,onRename:l=>void x.rename(S.id,l)})})]}):null,f(ft,{children:"Changes to Restore"})]}),Ee=r||e.building||D.applies===0;return W(p,{style:b.container,children:[f(Cr,{testID:"tm-preview-list",data:Ze,renderItem:et,keyExtractor:De,ListHeaderComponent:tt,ListEmptyComponent:e.building?f(lt,{style:b.buildingSpinner,size:"small",color:o.color.accent}):f(d,{style:b.emptyText,testID:"tm-preview-empty",children:H?"Nothing matches this filter.":"No changes \u2014 restoring would change nothing."}),ListFooterComponent:f(p,{children:D.wontApply>0?W(p,{style:b.warnNote,children:[f(Sa,{size:12,color:o.color.warning}),W(d,{style:b.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:b.listContent}),Ae&&S&&W(p,{style:[b.footer,{paddingBottom:g.bottom}],children:[W(A,{style:[b.cta,G&&b.ctaDanger,Ee&&b.ctaDisabled],onPress:()=>i(G?"reload":"live",Array.from(c)),disabled:G?r||e.building:Ee,testID:"tm-preview-restore",children:[f(va,{size:16,color:G?o.color.onDanger:o.color.onAccent}),f(d,{style:[b.ctaText,G?b.ctaTextDanger:null],children:G?"Wipe & Reload":"Restore State"})]}),f(d,{style:b.ctaCaption,testID:"tm-preview-cta-caption",children:G?"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 ps={top:10,bottom:10,left:10,right:10},b=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:mt,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:mt,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:mt,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 ms}from"react/jsx-runtime";function fs(e,t){return e==="current"?void 0:t.find(r=>r.id===e.snapshotId)}function gs({preview:e,snapshots:t,busy:r,onClose:n}){let i=fs(e.right,t);return ms(hs,{preview:e,snapshots:t,busy:r,onBack:n,onRestore:(a,s)=>{if(!(!i||r)){if(i.baseline){_t("Restore fresh install?","This wipes all app storage and reloads the app.","Wipe & reload",()=>void x.restore(i.id,"reload"));return}x.restore(i.id,a,s).then(n)}}})}import{jsx as N,jsxs as Xe}from"react/jsx-runtime";var Bo=()=>ai().some(e=>e.id===lr);function gr(){let[e,t]=Wr({kind:"list"}),{snapshots:r,busy:n,preview:i}=pt(),a=Ui(),s=()=>{x.clearPreview(),t({kind:"list"})};return e.kind==="preview"&&i?N(gs,{preview:i,snapshots:r,busy:n!==null,onClose:s}):N(ys,{sources:a,onOpenPreview:g=>{x.buildPreview({snapshotId:g.id}),t({kind:"preview"})}})}function ys({sources:e,onOpenPreview:t}){let{snapshots:r,hasLoaded:n,busy:i,lastOutcome:a,recentlyDeleted:s,remoteProviders:g}=pt(),h=ni("timeMachine.snapshots"),m=li(),c=oi({minBottom:16}),u=jr(si,Bo,Bo),z=jr(go,xt,xt),w=u?yo(r,z)?.id:void 0,E=ri({}),[M,H]=Wr(null),S=$=>{H(null),dr($),m.minimize()},U=m.search.trim().toLowerCase(),te=U?r.filter($=>$.name.toLowerCase().includes(U)):r,G=r.filter($=>!$.safety).length>=h,Ae=i!==null||G,re=$=>{if(i)return;if($.baseline){_t("Restore fresh install?","This wipes all app storage and reloads the app.","Wipe & reload",()=>void x.restore($.id,"reload"));return}let ae=(E.current[$.id]??0)+1;E.current[$.id]=ae,ae>=2&&!u&&H($.id),x.restore($.id,"live").then(ve=>{Ci(ve)&&m.minimize()})},K=M&&!u?r.find($=>$.id===M)??null:null;return Xe(Et,{style:Ye.fill,contentContainerStyle:[Ye.content,{paddingBottom:c.bottom}],testID:"time-machine-scroll",keyboardShouldPersistTaps:"handled",children:[a&&Ft(a)?N(ra,{outcome:a}):null,s?N(ua,{name:s.stored.meta.name,at:s.at,onUndo:()=>void x.undoDelete(),onExpire:()=>x.clearRecentlyDeleted()}):null,N(p,{children:N(Qi,{disabled:Ae,busy:i==="capture",onCapture:$=>void x.capture($)})}),G?Xe(Ve,{tone:"warning",testID:"time-machine-limit",children:["Free plan keeps ",h," restore point",h===1?"":"s",". Upgrade to Pro for unlimited snapshots."]}):null,N(ft,{children:"Sources"}),N(ya,{sources:e,onToggle:g?void 0:Ur}),g?null:N(Ve,{testID:"time-machine-sources-hint",children:"Switch a source off to leave it out of every capture and restore."}),N(ft,{children:"Restore Points"}),K?Xe(p,{style:Ye.barHint,testID:"time-machine-bar-hint",children:[Xe(Ve,{children:['Restoring "',K.name,'" a lot? Put it on the floating action bar and restore it with one tap.']}),N(A,{onPress:()=>S(K.id),accessibilityRole:"button",testID:"time-machine-bar-hint-pin",hitSlop:{top:6,bottom:6,left:6,right:6},children:N(d,{style:Ye.barHintAction,children:"Open the action bar"})})]}):null,Xe(gt,{children:[te.map($=>N(la,{meta:$,busy:i!==null,armed:$.id===w,onOpen:()=>t($),onRestore:()=>re($),onDelete:()=>void x.delete($.id),onDuplicate:()=>void x.duplicate($.id),onArm:()=>S($.id)},$.id)),te.length===0?N(ii,{testID:"time-machine-empty",...n?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]}),te.length>0?N(Ve,{testID:"time-machine-swipe-hint",children:"Swipe a restore point to copy or delete it."}):null,N(p,{style:Ye.spacer}),N(gt,{children:N(ba,{disabled:i!==null,onWipe:()=>_t("Wipe all app state?","This deletes all app storage and reloads the app \u2014 like a fresh install.","Wipe & reload",()=>void x.wipeAll())})}),N(Ve,{centered:true,children:"Deletes all app storage and reloads \u2014 like a fresh install."})]})}var Ye=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 Wo}from"react/jsx-runtime";var Tt={id:"time-machine",name:"TIME MACHINE",description:"Snapshot & restore app state (storage, stores, query cache)",slot:"both",icon:({size:e,color:t,slot:r})=>Wo(ei,{size:r==="dial"&&at.OS!=="web"?e*1.5:e,color:t||ti}),component:gr,modal:{subtitle:"snapshot & restore app state",searchable:true,searchPlaceholder:"Filter\u2026",headerActions:Wo($o,{})}};function bs(e={}){return{...Tt,name:e.name??Tt.name,description:e.description??Tt.description}}import{JsModal as ws}from"@buoy-gg/shared-ui/web";import{jsx as Le,jsxs as Ss}from"react/jsx-runtime";function vs(){return Ss(p,{style:yr.header,children:[Le(d,{style:yr.headerTitle,children:"Time Machine"}),Le(d,{style:yr.headerSubtitle,children:"Snapshot & restore app state"})]})}function xs({visible:e,onClose:t,onBack:r,onMinimize:n,persistenceKey:i}){return Le(ws,{visible:e,onClose:t,onMinimize:n,persistenceKey:i,header:{showToggleButton:true,customContent:Le(vs,{})},enablePersistence:true,initialMode:"bottomSheet",disableScrollWrapper:true,children:Le(gr,{})})}function Is(){return Le(gr,{})}var yr=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 Rs,subscribeToStateSnapshotProviders as ks,superJsonDeserialize as Ds}from"@buoy-gg/shared-ui/web";import{jsonLikelyLargerThan as jo}from"@buoy-gg/shared-ui/web/dataViewer";function Ts(){return Rs().map(e=>{let t=e.status();return{id:e.id,label:e.label,canCapture:t.canCapture,canRestore:t.canRestore,detail:t.detail,enabled:ne(e.id)}})}function No(){let{snapshots:e,busy:t,lastOutcome:r}=x.getState(),n=Yo();return{snapshots:e,busy:t,lastOutcome:r,providers:Ts(),route:{available:He(),enabled:ne(Ne),...n?{current:n.href}:{}}}}var Cs={version:2,getSnapshot:()=>No(),subscribe:e=>{let t=x.subscribe(e),r=ks(e);return()=>{t(),r()}},actions:{list:()=>No(),capture:async e=>{let{name:t="",sourceIds:r}=e??{};return{captured:true,snapshot:await x.capture(t,r)}},captureBaseline:async()=>({captured:true,snapshot:await x.captureBaseline()}),wipeAll:async()=>await x.wipeAll(),restore:async e=>{let{id:t,mode:r="live",excludeKeys:n,restoreRoute:i}=e??{};if(!t)throw new Error("restore requires a snapshot `id`");return await x.restore(t,r,n,{restoreRoute:i})},delete:async e=>{let{id:t}=e??{};if(!t)throw new Error("delete requires a snapshot `id`");return await x.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 x.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 x.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`");if(typeof r!="boolean")throw new Error("setRestoreRoute requires `restoreRoute` (true or false)");return await x.setRestoreRoute(t,r),{id:t,restoreRoute:r}},duplicate:async e=>{let{id:t}=e??{};if(!t)throw new Error("duplicate requires `id`");let r=await x.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 x.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 n={snapshotId:t},i=r?{snapshotId:r}:"current",a=await x.computePreview(n,i),s=4*1024;return{left:i,right:n,builtAt:a.builtAt,sources:a.sources.map(g=>({...g,items:g.items.map(h=>{let m=h.oldValue!==void 0&&jo(h.oldValue,s),c=h.newValue!==void 0&&jo(h.newValue,s);return{...h,oldValue:m?void 0:h.oldValue,newValue:c?void 0:h.newValue,...m||c?{valueOmitted:true}:{}}})}))}},inspect:async e=>{let{id:t,sourceId:r}=e??{};if(!t||!r)throw new Error("inspect requires `id` and `sourceId`");let n=await me(t);if(!n)throw new Error(`No snapshot with id "${t}"`);let i=n.data[r];if(!i)throw new Error(`Snapshot "${t}" has no "${r}" source`);return{id:t,sourceId:r,warnings:n.meta.sources[r]?.warnings??[],data:Ds(i)}}}};Rr();export{Me as RESTORE_ORDER,Vt as SAFETY_SNAPSHOT_NAME,lr as TIME_MACHINE_FLOATING_TOOL_ID,xs as TimeMachineModal,Is as TimeMachineToolView,Rr as armPendingRouteRestore,He as canRestoreRoute,it as captureCurrentRoute,bs as createTimeMachineTool,ne as isSourceEnabled,$t as navigateToRoute,dr as openTimeMachineFloatingTool,Li as replaceTimeMachineFromSnapshot,$i as setRemoteTimeMachineHandler,Ur as setSourceEnabled,To as startTimeMachineFloatingToolPersistence,qr as subscribeSourceSettings,x as timeMachineStore,Cs as timeMachineSyncAdapter,Tt as timeMachineToolPreset};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@buoy-gg/time-machine",
3
- "version": "7.0.78",
3
+ "version": "7.0.80",
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/floating-tools-core": "^7.0.78",
24
- "@buoy-gg/shared-ui": "^7.0.78"
23
+ "@buoy-gg/floating-tools-core": "^7.0.80",
24
+ "@buoy-gg/shared-ui": "^7.0.80"
25
25
  },
26
26
  "peerDependencies": {
27
- "@buoy-gg/license": "7.0.78",
27
+ "@buoy-gg/license": "7.0.80",
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/core": "^7.0.78",
35
- "@buoy-gg/license": "^7.0.78"
34
+ "@buoy-gg/license": "^7.0.80",
35
+ "@buoy-gg/core": "^7.0.80"
36
36
  },
37
37
  "react-native-builder-bob": {
38
38
  "source": "src",