@buoy-gg/clock 7.0.43 → 7.0.45
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -0
- package/lib/commonjs/components/ClockBody.js +1 -1
- package/lib/commonjs/components/ClockChip.js +1 -1
- package/lib/commonjs/components/ClockToolView.js +1 -1
- package/lib/commonjs/components/TokenSection.js +1 -1
- package/lib/commonjs/engine/clockStore.js +1 -1
- package/lib/commonjs/engine/persistence.js +1 -1
- package/lib/commonjs/engine/timers.js +1 -1
- package/lib/commonjs/sync/clockSyncAdapter.js +1 -1
- package/lib/module/components/ClockBody.js +1 -1
- package/lib/module/components/ClockChip.js +1 -1
- package/lib/module/components/ClockToolView.js +1 -1
- package/lib/module/components/TokenSection.js +1 -1
- package/lib/module/engine/clockStore.js +1 -1
- package/lib/module/engine/persistence.js +1 -1
- package/lib/module/engine/timers.js +1 -1
- package/lib/module/sync/clockSyncAdapter.js +1 -1
- package/lib/typescript/components/TokenSection.d.ts +4 -1
- package/lib/typescript/engine/clockStore.d.ts +7 -0
- package/lib/typescript/engine/persistence.d.ts +10 -0
- package/lib/typescript/sync/clockSyncAdapter.d.ts +2 -0
- package/lib/web/index.mjs +1 -1
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -22,6 +22,8 @@ The tool appears in `FloatingDevTools` on its own. If your app reads the clock w
|
|
|
22
22
|
import "@buoy-gg/clock";
|
|
23
23
|
```
|
|
24
24
|
|
|
25
|
+
Jumping ahead, typing a date and the token row are free. Freeze, Speed, keeping the time after a restart and the two token tests need Buoy Pro.
|
|
26
|
+
|
|
25
27
|
The [Clock guide](https://buoy.gg/buoy/latest/docs/tools/clock) lists which time APIs follow the override and which stay on real time. New to Buoy? Start with the [Quick start](https://buoy.gg/buoy/latest/docs/quick-start).
|
|
26
28
|
|
|
27
29
|
---
|
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,"__esModule",{value:true});exports.ClockBody=ClockBody;var _react=require("react");var _sharedUi=require("@buoy-gg/shared-ui");var _clockStore=require("../engine/clockStore");var _clockSyncAdapter=require("../sync/clockSyncAdapter");var _tokenStore=require("../tokens/tokenStore");var _ClockToolView=require("./ClockToolView");var _jsxRuntime=require("react/jsx-runtime");const actions=_clockSyncAdapter.clockSyncAdapter.actions;async function runAction(o,e){const
|
|
1
|
+
"use strict";Object.defineProperty(exports,"__esModule",{value:true});exports.ClockBody=ClockBody;var _react=require("react");var _sharedUi=require("@buoy-gg/shared-ui");var _clockStore=require("../engine/clockStore");var _clockSyncAdapter=require("../sync/clockSyncAdapter");var _tokenStore=require("../tokens/tokenStore");var _ClockToolView=require("./ClockToolView");var _jsxRuntime=require("react/jsx-runtime");const actions=_clockSyncAdapter.clockSyncAdapter.actions;async function runAction(o,e){const t=actions[o];if(!t)throw new Error(`Unknown clock action: ${o}`);return t(e)}function reload(){void(0,_clockStore.holdForNextReload)().then(()=>(0,_sharedUi.reloadApp)("auto","buoy clock")).catch(()=>{})}function ClockBody(){(0,_react.useEffect)(()=>{(0,_clockStore.bootClock)();(0,_tokenStore.startTokenWatch)()},[]);const[o,e]=(0,_react.useState)(_clockStore.getClockSnapshot);(0,_react.useEffect)(()=>(0,_clockStore.subscribeClock)(()=>e((0,_clockStore.getClockSnapshot)())),[]);return(0,_jsxRuntime.jsx)(_ClockToolView.ClockToolView,{snapshot:o,onAction:runAction,onReload:reload})}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,"__esModule",{value:true});exports.CLOCK_CHIP_ID=void 0;exports.ClockChip=ClockChip;exports.openClockChip=openClockChip;exports.watchClockChip=watchClockChip;var _react=require("react");var _reactNative=require("react-native");var _sharedUi=require("@buoy-gg/shared-ui");var _clockStore=require("../engine/clockStore");var _clockMath=require("../engine/clockMath");var _useLiveClock=require("./useLiveClock");var _format=require("./format");var _jsxRuntime=require("react/jsx-runtime");const CLOCK_CHIP_ID=exports.CLOCK_CHIP_ID="clock-chip";const registration={id:CLOCK_CHIP_ID,render:e=>(0,_jsxRuntime.jsx)(ClockChip,{...e})};const isChipOpen=()=>(0,_sharedUi.getFloatingTools)().some(e=>e.id===CLOCK_CHIP_ID);function openClockChip(){(0,_sharedUi.openFloatingTool)(registration)}let watching=false;function watchClockChip(){if(watching)return;watching=true;let e=false;const i=()=>{const t=(0,_clockStore.isClockOverridden)()&&(0,_clockStore.getClockSettings)().showChip;if(t&&!e)(0,_sharedUi.openFloatingTool)(registration);else if(!t&&isChipOpen())(0,_sharedUi.dismissFloatingTool)(CLOCK_CHIP_ID);e=t};(0,_clockStore.subscribeClock)(i);i()}function ClockChip({id:e,revealToken:i}){const t=(0,_react.useSyncExternalStore)(_clockStore.subscribeClock,_clockStore.getStableClockSnapshot,_clockStore.getStableClockSnapshot);const{virtual:r,real:
|
|
1
|
+
"use strict";Object.defineProperty(exports,"__esModule",{value:true});exports.CLOCK_CHIP_ID=void 0;exports.ClockChip=ClockChip;exports.openClockChip=openClockChip;exports.watchClockChip=watchClockChip;var _react=require("react");var _reactNative=require("react-native");var _sharedUi=require("@buoy-gg/shared-ui");var _clockStore=require("../engine/clockStore");var _clockMath=require("../engine/clockMath");var _useLiveClock=require("./useLiveClock");var _format=require("./format");var _jsxRuntime=require("react/jsx-runtime");const CLOCK_CHIP_ID=exports.CLOCK_CHIP_ID="clock-chip";const registration={id:CLOCK_CHIP_ID,render:e=>(0,_jsxRuntime.jsx)(ClockChip,{...e})};const isChipOpen=()=>(0,_sharedUi.getFloatingTools)().some(e=>e.id===CLOCK_CHIP_ID);function openClockChip(){(0,_sharedUi.openFloatingTool)(registration)}let watching=false;function watchClockChip(){if(watching)return;watching=true;let e=false;const i=()=>{const t=(0,_clockStore.isClockOverridden)()&&(0,_clockStore.getClockSettings)().showChip;if(t&&!e)(0,_sharedUi.openFloatingTool)(registration);else if(!t&&isChipOpen())(0,_sharedUi.dismissFloatingTool)(CLOCK_CHIP_ID);e=t};(0,_clockStore.subscribeClock)(i);i()}function ClockChip({id:e,revealToken:i}){const t=(0,_react.useSyncExternalStore)(_clockStore.subscribeClock,_clockStore.getStableClockSnapshot,_clockStore.getStableClockSnapshot);const{virtual:r,real:l}=(0,_useLiveClock.useLiveClock)(t);const o=t.mode==="frozen";const s=o||(0,_sharedUi.getUseIsPro)()();const n=(0,_format.clockStatus)(t);const c=r-l;const a=`${Math.abs(c)<1e3?"0s":(0,_clockMath.formatDuration)(c)} \xB7 ${n.label.toLowerCase()}`;return(0,_jsxRuntime.jsx)(_sharedUi.FloatingTool,{id:e,revealToken:i,variant:"strip",dragFromSurface:true,defaultPlacement:"top",accessibilityLabel:`Move or hide the clock chip. App time ${(0,_format.formatChipTime)(r)}`,handleAdornment:(0,_jsxRuntime.jsx)(_sharedUi.ClockToolIcon,{size:12}),children:(0,_jsxRuntime.jsxs)(_reactNative.View,{style:styles.row,children:[(0,_jsxRuntime.jsx)(_sharedUi.ClockToolIcon,{size:18}),(0,_jsxRuntime.jsxs)(_reactNative.View,{style:styles.text,children:[(0,_jsxRuntime.jsx)(_reactNative.Text,{style:styles.time,numberOfLines:1,testID:"clock-chip-time",children:(0,_format.formatChipTime)(r)}),(0,_jsxRuntime.jsx)(_reactNative.Text,{style:styles.detail,numberOfLines:1,testID:"clock-chip-detail",children:a})]}),s?(0,_jsxRuntime.jsxs)(_reactNative.TouchableOpacity,{testID:o?"clock-chip-resume":"clock-chip-freeze",accessibilityRole:"button",accessibilityLabel:o?"Resume the app clock":"Freeze the app clock",onPress:()=>o?(0,_clockStore.resume)():(0,_clockStore.freeze)(),style:styles.button,hitSlop:{top:8,bottom:8,left:4,right:4},children:[o?(0,_jsxRuntime.jsx)(_sharedUi.Play,{size:16,color:_sharedUi.night.color.accent}):null,o?null:(0,_jsxRuntime.jsx)(_sharedUi.Pause,{size:16,color:_sharedUi.night.color.text})]}):null,s?(0,_jsxRuntime.jsx)(_reactNative.View,{style:styles.separator}):null,(0,_jsxRuntime.jsx)(_reactNative.TouchableOpacity,{testID:"clock-chip-reset",accessibilityRole:"button",accessibilityLabel:"Back to real time",onPress:()=>(0,_clockStore.reset)(),style:styles.button,hitSlop:{top:8,bottom:8,left:4,right:8},children:(0,_jsxRuntime.jsx)(_sharedUi.X,{size:16,color:_sharedUi.night.color.textSecondary})})]})})}const styles=_reactNative.StyleSheet.create({row:{flexDirection:"row",alignItems:"center",gap:10,paddingLeft:10,paddingRight:4,paddingVertical:6,minWidth:220},text:{flexShrink:1,minWidth:120},time:{color:"#F59E0B",fontSize:14,fontWeight:"600",fontVariant:["tabular-nums"]},detail:{color:_sharedUi.night.color.textSecondary,fontSize:11,fontVariant:["tabular-nums"]},button:{width:32,height:32,alignItems:"center",justifyContent:"center",borderRadius:16},separator:{width:_reactNative.StyleSheet.hairlineWidth,height:20,backgroundColor:_sharedUi.night.color.separator}});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,"__esModule",{value:true});exports.ClockToolView=ClockToolView;var _react=require("react");var _reactNative=require("react-native");var _sharedUi=require("@buoy-gg/shared-ui");var _clockMath=require("../engine/clockMath");var _patches=require("../engine/patches");var _useLiveClock=require("./useLiveClock");var _TokenSection=require("./TokenSection");var _format=require("./format");var _jsxRuntime=require("react/jsx-runtime");const AMBER="#F59E0B";function ClockToolView({snapshot:e,onAction:t,onReload:i}){const o=(0,_sharedUi.useSafeAreaInsets)({minBottom:16});const[r,n]=(0,_react.useState)(null);const[s,d]=(0,_react.useState)(null);const l=(a,u)=>{n(null);t(a,u).catch(h=>{n(h instanceof Error?h.message:String(h))})};const c=a=>d(u=>u===a?null:a);if(!e){return(0,_jsxRuntime.jsx)(_reactNative.View,{style:styles.waiting,testID:"clock-waiting",children:(0,_jsxRuntime.jsx)(_sharedUi.NightFootnote,{centered:true,children:"Waiting for the app's clock\u2026"})})}return(0,_jsxRuntime.jsxs)(_reactNative.ScrollView,{style:styles.fill,contentContainerStyle:[styles.content,{paddingBottom:o.bottom}],testID:"clock-scroll",keyboardShouldPersistTaps:"handled",children:[(0,_jsxRuntime.jsx)(Hero,{snapshot:e}),r?(0,_jsxRuntime.jsx)(_sharedUi.NightFootnote,{tone:"danger",centered:true,children:(0,_jsxRuntime.jsx)(_reactNative.Text,{testID:"clock-error",children:r})}):null,(0,_jsxRuntime.jsxs)(_reactNative.View,{children:[(0,_jsxRuntime.jsx)(_sharedUi.NightSectionLabel,{children:"Jump ahead"}),(0,_jsxRuntime.jsx)(JumpBar,{run:l})]}),(0,_jsxRuntime.jsxs)(_reactNative.View,{children:[(0,_jsxRuntime.jsx)(_sharedUi.NightCard,{children:(0,_jsxRuntime.jsxs)(_sharedUi.NightRows,{children:[(0,_jsxRuntime.jsxs)(_reactNative.View,{children:[(0,_jsxRuntime.jsx)(DisclosureRow,{title:"Date & Time",testID:"clock-date-row",open:s==="date",onPress:()=>c("date"),value:(0,_jsxRuntime.jsx)(LiveDateValue,{snapshot:e})}),s==="date"?(0,_jsxRuntime.jsx)(DateEditor,{snapshot:e,run:l,onDone:()=>d(null)}):null]},"date"),(0,_jsxRuntime.jsxs)(_reactNative.View,{style:styles.row,children:[(0,_jsxRuntime.jsx)(_reactNative.Text,{style:styles.rowTitle,children:"Freeze"}),(0,_jsxRuntime.jsx)(_sharedUi.NightSwitch,{value:e.mode==="frozen",testID:"clock-freeze",accessibilityLabel:"Freeze the clock",onValueChange:a=>l(a?"freeze":"resume")})]},"freeze"),(0,_jsxRuntime.jsxs)(_reactNative.View,{children:[(0,_jsxRuntime.jsx)(DisclosureRow,{title:"Speed",testID:"clock-speed-row",open:s==="speed",onPress:()=>c("speed"),value:(0,_jsxRuntime.jsx)(_reactNative.Text,{style:styles.rowValue,children:speedLabel(e)})}),s==="speed"?(0,_jsxRuntime.jsx)(SpeedPicker,{snapshot:e,run:l}):null]},"speed")]})}),(0,_jsxRuntime.jsx)(_sharedUi.NightFootnote,{children:"Only this app's clock changes. Screens pick up the new time when they next render, or all at once when you reload."})]}),e.tokens?(0,_jsxRuntime.jsx)(_TokenSection.TokenSection,{snapshot:e,run:l,openId:s,onToggle:c}):null,(0,_jsxRuntime.jsx)(_sharedUi.NightCard,{children:(0,_jsxRuntime.jsxs)(_sharedUi.NightRows,{children:[i?(0,_jsxRuntime.jsx)(ActionRow,{label:"Reload App",testID:"clock-reload",onPress:i},"reload"):null,(0,_jsxRuntime.jsx)(ActionRow,{label:"Use Real Time",accessibilityLabel:"Reset to real time",testID:"clock-reset",destructive:true,disabled:e.mode==="real",onPress:()=>l("reset")},"reset")]})}),(0,_jsxRuntime.jsxs)(_reactNative.View,{children:[(0,_jsxRuntime.jsx)(_sharedUi.NightSectionLabel,{children:"Options"}),(0,_jsxRuntime.jsx)(OptionsCard,{settings:e.settings,run:l})]})]})}function Hero({snapshot:e}){const{virtual:t,real:i}=(0,_useLiveClock.useLiveClock)(e);const o=(0,_format.clockStatus)(e);const r=e.mode!=="real";const n=(0,_format.formatOffset)(t-i);const s=e.mode==="frozen"?" \xB7 Frozen":r&&e.rate!==1?` \xB7 ${speedLabel(e)}`:"";return(0,_jsxRuntime.jsxs)(_reactNative.View,{style:styles.hero,children:[(0,_jsxRuntime.jsx)(_reactNative.Text,{style:[styles.heroTime,r?styles.heroTimeActive:null],testID:"clock-hero-time",accessibilityLabel:`App clock ${(0,_format.formatClockTime)(t)}`,children:(0,_format.formatClockTime)(t)}),(0,_jsxRuntime.jsx)(_reactNative.Text,{style:styles.heroDate,testID:"clock-hero-date",children:(0,_format.formatClockDate)(t)}),(0,_jsxRuntime.jsx)(_reactNative.View,{testID:"clock-status",accessibilityLabel:`Clock status: ${o.label}${r?`, ${n}`:""}`,children:(0,_jsxRuntime.jsx)(_reactNative.Text,{style:[styles.heroStatus,r?styles.heroStatusActive:null],testID:"clock-offset",children:r?`${n}${s}`:"Real time"})})]})}const HOUR=36e5;const DAY=24*HOUR;const JUMP_BAR=[{ms:HOUR,unit:"hour"},{ms:DAY,unit:"day"},{ms:7*DAY,unit:"week"},{ms:30*DAY,unit:"month"}];function JumpBar({run:e}){return(0,_jsxRuntime.jsx)(_sharedUi.NightCard,{style:styles.jumpBar,children:JUMP_BAR.map((t,i)=>(0,_jsxRuntime.jsxs)(_reactNative.TouchableOpacity,{testID:(0,_format.jumpTestId)(t.ms),accessibilityRole:"button",accessibilityLabel:`Jump ahead one ${t.unit}`,activeOpacity:.6,onPress:()=>e("shift",{by:t.ms}),style:[styles.jump,i>0?styles.jumpDivider:null],children:[(0,_jsxRuntime.jsx)(_reactNative.Text,{style:styles.jumpAmount,children:"+1"}),(0,_jsxRuntime.jsx)(_reactNative.Text,{style:styles.jumpUnit,children:t.unit})]},t.unit))})}function DisclosureRow({title:e,value:t,open:i,onPress:o,testID:r}){return(0,_jsxRuntime.jsxs)(_reactNative.TouchableOpacity,{testID:r,accessibilityRole:"button",accessibilityLabel:e,accessibilityState:{expanded:i},activeOpacity:.6,onPress:o,style:styles.row,children:[(0,_jsxRuntime.jsx)(_reactNative.Text,{style:styles.rowTitle,children:e}),(0,_jsxRuntime.jsxs)(_reactNative.View,{style:styles.rowRight,children:[t,(0,_jsxRuntime.jsx)(_reactNative.View,{style:i?styles.chevronOpen:null,children:(0,_jsxRuntime.jsx)(_sharedUi.ChevronRight,{size:16,color:_sharedUi.night.color.textTertiary})})]})]})}function LiveDateValue({snapshot:e}){const{virtual:t}=(0,_useLiveClock.useLiveClock)(e,1e3);return(0,_jsxRuntime.jsx)(_reactNative.Text,{style:[styles.rowValue,styles.tabular],numberOfLines:1,children:(0,_format.formatChipTime)(t,false)})}function ActionRow({label:e,onPress:t,testID:i,destructive:o,disabled:r,accessibilityLabel:n}){return(0,_jsxRuntime.jsx)(_reactNative.TouchableOpacity,{testID:i,accessibilityRole:"button",accessibilityLabel:n??e,accessibilityState:{disabled:!!r},activeOpacity:.6,disabled:r,onPress:t,style:[styles.row,r?styles.rowDisabled:null],children:(0,_jsxRuntime.jsx)(_reactNative.Text,{style:[styles.actionLabel,o?styles.actionDestructive:null],children:e})})}const PRESETS=_clockMath.TIME_PRESETS.filter(e=>["midnight","month-end","year-end"].includes(e.id));function DateEditor({snapshot:e,run:t,onDone:i}){const[o,r]=(0,_react.useState)("");const{virtual:n}=(0,_useLiveClock.useLiveClock)(e,1e3);const s=()=>o.trim()||(0,_format.formatInputTime)(n);const d=e.mode==="frozen";const l=c=>{t("setTime",{time:c,freeze:d});i()};return(0,_jsxRuntime.jsxs)(_reactNative.View,{style:styles.editor,children:[(0,_jsxRuntime.jsxs)(_reactNative.View,{style:styles.inputRow,children:[(0,_jsxRuntime.jsx)(_reactNative.TextInput,{testID:"clock-time-input",accessibilityLabel:"Date and time",value:o,onChangeText:r,placeholder:(0,_format.formatInputTime)(n),placeholderTextColor:_sharedUi.night.color.placeholder,autoCapitalize:"none",autoCorrect:false,returnKeyType:"done",onSubmitEditing:()=>l(s()),style:styles.input}),(0,_jsxRuntime.jsx)(_sharedUi.NightButton,{label:"Set",testID:"clock-time-apply",accessibilityLabel:"Set this time",size:"md",variant:"primary",fullWidth:false,onPress:()=>l(s())})]}),(0,_jsxRuntime.jsx)(_reactNative.Text,{style:styles.hint,children:"Year-month-day and 24-hour time, or +3d, -2h"}),(0,_jsxRuntime.jsx)(_reactNative.View,{style:styles.presets,children:PRESETS.map(c=>(0,_jsxRuntime.jsx)(_sharedUi.NightChip,{label:c.label,testID:`clock-preset-${c.id}`,onPress:()=>l(c.at(n,_patches.RealDate))},c.id))})]})}const SPEED_TABS=[{key:"1",label:"Normal"},{key:"10",label:"10\xD7"},{key:"60",label:"1 min/s"},{key:"3600",label:"1 hr/s"}];function speedLabel(e){if(e.mode==="real"||e.rate===1)return"Normal";return SPEED_TABS.find(t=>Number(t.key)===e.rate)?.label??(0,_clockMath.formatRate)(e.rate)}function SpeedPicker({snapshot:e,run:t}){const i=e.mode==="real"?"1":String(e.rate);return(0,_jsxRuntime.jsxs)(_reactNative.View,{style:styles.editor,children:[(0,_jsxRuntime.jsx)(_reactNative.View,{style:styles.segmentRow,children:(0,_jsxRuntime.jsx)(_sharedUi.NightSegmented,{tabs:SPEED_TABS,activeKey:i,size:"sm",testIDPrefix:"clock-speed",onChange:o=>t("setRate",{rate:Number(o)})})}),(0,_jsxRuntime.jsx)(_reactNative.Text,{style:styles.hint,children:"Taps, animations and timers keep real speed."})]})}const OPTIONS=[{key:"showChip",title:"Show Floating Clock"},{key:"persist",title:"Keep After Reload"}];function OptionsCard({settings:e,run:t}){return(0,_jsxRuntime.jsx)(_sharedUi.NightCard,{children:(0,_jsxRuntime.jsx)(_sharedUi.NightRows,{children:OPTIONS.map(i=>(0,_jsxRuntime.jsxs)(_reactNative.View,{style:styles.row,children:[(0,_jsxRuntime.jsx)(_reactNative.Text,{style:styles.rowTitle,children:i.title}),(0,_jsxRuntime.jsx)(_sharedUi.NightSwitch,{value:e[i.key],testID:`clock-setting-${i.key}`,accessibilityLabel:i.title,onValueChange:o=>t("updateSettings",{[i.key]:o})})]},i.key))})})}const styles=_reactNative.StyleSheet.create({fill:{flex:1},content:{paddingHorizontal:_sharedUi.night.gutter,paddingTop:8,gap:_sharedUi.night.groupGap},waiting:{flex:1,alignItems:"center",justifyContent:"center",padding:24},hero:{alignItems:"center",paddingTop:12},heroTime:{color:_sharedUi.night.color.text,fontSize:56,fontWeight:"200",fontVariant:["tabular-nums"],letterSpacing:1},heroTimeActive:{color:AMBER},heroDate:{color:_sharedUi.night.color.text,fontSize:17,fontWeight:"500",marginTop:2},heroStatus:{color:_sharedUi.night.color.textTertiary,fontSize:_sharedUi.night.font.caption,fontWeight:"500",marginTop:6},heroStatusActive:{color:_sharedUi.night.color.textSecondary},jumpBar:{flexDirection:"row"},jump:{flex:1,alignItems:"center",paddingVertical:12},jumpDivider:{borderLeftWidth:_reactNative.StyleSheet.hairlineWidth,borderLeftColor:_sharedUi.night.color.separator},jumpAmount:{color:AMBER,fontSize:17,fontWeight:"600",fontVariant:["tabular-nums"]},jumpUnit:{color:_sharedUi.night.color.textSecondary,fontSize:_sharedUi.night.font.caption,marginTop:1},row:{flexDirection:"row",alignItems:"center",justifyContent:"space-between",gap:12,minHeight:50,paddingHorizontal:_sharedUi.night.rowPadH,paddingVertical:10},rowDisabled:{opacity:.4},rowTitle:{color:_sharedUi.night.color.text,fontSize:_sharedUi.night.font.row},rowRight:{flexDirection:"row",alignItems:"center",gap:6,flexShrink:1},rowValue:{color:_sharedUi.night.color.textSecondary,fontSize:_sharedUi.night.font.row},tabular:{fontVariant:["tabular-nums"]},chevronOpen:{transform:[{rotate:"90deg"}]},actionLabel:{color:_sharedUi.night.color.accent,fontSize:_sharedUi.night.font.row},actionDestructive:{color:_sharedUi.night.color.danger},editor:{paddingHorizontal:_sharedUi.night.rowPadH,paddingBottom:14,gap:10},inputRow:{flexDirection:"row",alignItems:"center",gap:8},input:{flex:1,color:_sharedUi.night.color.text,fontFamily:_sharedUi.monoFont,fontSize:15,backgroundColor:_sharedUi.night.color.bg,borderRadius:_sharedUi.night.radius.input,borderWidth:1,borderColor:_sharedUi.night.color.border,paddingHorizontal:12,paddingVertical:8},hint:{color:_sharedUi.night.color.textTertiary,fontSize:_sharedUi.night.font.caption},presets:{flexDirection:"row",flexWrap:"wrap",gap:6},segmentRow:{flexDirection:"row"}});
|
|
1
|
+
"use strict";Object.defineProperty(exports,"__esModule",{value:true});exports.ClockToolView=ClockToolView;var _react=require("react");var _reactNative=require("react-native");var _sharedUi=require("@buoy-gg/shared-ui");var _clockMath=require("../engine/clockMath");var _patches=require("../engine/patches");var _useLiveClock=require("./useLiveClock");var _TokenSection=require("./TokenSection");var _format=require("./format");var _jsxRuntime=require("react/jsx-runtime");const AMBER="#F59E0B";function ClockToolView({snapshot:e,onAction:t,onReload:o}){const n=(0,_sharedUi.useSafeAreaInsets)({minBottom:16});const[i,r]=(0,_react.useState)(null);const[l,u]=(0,_react.useState)(null);const s=(0,_sharedUi.getUseIsPro)()();const[a,p]=(0,_react.useState)(null);const h=c=>p(c);const d=(c,x)=>{r(null);t(c,x).catch(m=>{r(m instanceof Error?m.message:String(m))})};const g=c=>u(x=>x===c?null:c);if(!e){return(0,_jsxRuntime.jsx)(_reactNative.View,{style:styles.waiting,testID:"clock-waiting",children:(0,_jsxRuntime.jsx)(_sharedUi.NightFootnote,{centered:true,children:"Waiting for the app's clock\u2026"})})}return(0,_jsxRuntime.jsxs)(_reactNative.ScrollView,{style:styles.fill,contentContainerStyle:[styles.content,{paddingBottom:n.bottom}],testID:"clock-scroll",keyboardShouldPersistTaps:"handled",children:[(0,_jsxRuntime.jsx)(Hero,{snapshot:e}),i?(0,_jsxRuntime.jsx)(_sharedUi.NightFootnote,{tone:"danger",centered:true,children:(0,_jsxRuntime.jsx)(_reactNative.Text,{testID:"clock-error",children:i})}):null,(0,_jsxRuntime.jsxs)(_reactNative.View,{children:[(0,_jsxRuntime.jsx)(_sharedUi.NightSectionLabel,{children:"Jump ahead"}),(0,_jsxRuntime.jsx)(JumpBar,{run:d})]}),(0,_jsxRuntime.jsxs)(_reactNative.View,{children:[(0,_jsxRuntime.jsx)(_sharedUi.NightCard,{children:(0,_jsxRuntime.jsxs)(_sharedUi.NightRows,{children:[(0,_jsxRuntime.jsxs)(_reactNative.View,{children:[(0,_jsxRuntime.jsx)(DisclosureRow,{title:"Date & Time",testID:"clock-date-row",open:l==="date",onPress:()=>g("date"),value:(0,_jsxRuntime.jsx)(LiveDateValue,{snapshot:e})}),l==="date"?(0,_jsxRuntime.jsx)(DateEditor,{snapshot:e,run:d,onDone:()=>u(null)}):null]},"date"),(0,_jsxRuntime.jsxs)(_reactNative.View,{style:styles.row,children:[(0,_jsxRuntime.jsx)(ProTitle,{title:"Freeze",isPro:s}),(0,_jsxRuntime.jsx)(_sharedUi.NightSwitch,{value:e.mode==="frozen",testID:"clock-freeze",accessibilityLabel:"Freeze the clock",onValueChange:c=>c&&!s?h("Freeze"):d(c?"freeze":"resume")})]},"freeze"),(0,_jsxRuntime.jsxs)(_reactNative.View,{children:[(0,_jsxRuntime.jsx)(DisclosureRow,{title:"Speed",pro:!s,testID:"clock-speed-row",open:l==="speed",onPress:()=>s?g("speed"):h("Speed"),value:(0,_jsxRuntime.jsx)(_reactNative.Text,{style:styles.rowValue,children:speedLabel(e)})}),l==="speed"?(0,_jsxRuntime.jsx)(SpeedPicker,{snapshot:e,run:d}):null]},"speed")]})}),(0,_jsxRuntime.jsx)(_sharedUi.NightFootnote,{children:"Only this app's clock changes. Screens pick up the new time when they next render, or all at once when you reload."})]}),e.tokens?(0,_jsxRuntime.jsx)(_TokenSection.TokenSection,{snapshot:e,run:d,openId:l,onToggle:g,isPro:s,onUpgrade:h}):null,(0,_jsxRuntime.jsx)(_sharedUi.NightCard,{children:(0,_jsxRuntime.jsxs)(_sharedUi.NightRows,{children:[o?(0,_jsxRuntime.jsx)(ActionRow,{label:"Reload App",testID:"clock-reload",onPress:o},"reload"):null,(0,_jsxRuntime.jsx)(ActionRow,{label:"Use Real Time",accessibilityLabel:"Reset to real time",testID:"clock-reset",destructive:true,disabled:e.mode==="real",onPress:()=>d("reset")},"reset")]})}),(0,_jsxRuntime.jsxs)(_reactNative.View,{children:[(0,_jsxRuntime.jsx)(_sharedUi.NightSectionLabel,{children:"Options"}),(0,_jsxRuntime.jsx)(OptionsCard,{settings:e.settings,run:d,isPro:s,onUpgrade:h})]}),(0,_jsxRuntime.jsx)(_sharedUi.ProUpgradeModal,{visible:a!==null&&!s,onClose:()=>p(null),featureName:a??void 0})]})}function ProTitle({title:e,isPro:t}){return(0,_jsxRuntime.jsxs)(_reactNative.View,{style:styles.titleRow,children:[(0,_jsxRuntime.jsx)(_reactNative.Text,{style:styles.rowTitle,children:e}),t?null:(0,_jsxRuntime.jsx)(_sharedUi.ProBadge,{})]})}function Hero({snapshot:e}){const{virtual:t,real:o}=(0,_useLiveClock.useLiveClock)(e);const n=(0,_format.clockStatus)(e);const i=e.mode!=="real";const r=(0,_format.formatOffset)(t-o);const l=e.mode==="frozen"?" \xB7 Frozen":i&&e.rate!==1?` \xB7 ${speedLabel(e)}`:"";return(0,_jsxRuntime.jsxs)(_reactNative.View,{style:styles.hero,children:[(0,_jsxRuntime.jsx)(_reactNative.Text,{style:[styles.heroTime,i?styles.heroTimeActive:null],testID:"clock-hero-time",accessibilityLabel:`App clock ${(0,_format.formatClockTime)(t)}`,children:(0,_format.formatClockTime)(t)}),(0,_jsxRuntime.jsx)(_reactNative.Text,{style:styles.heroDate,testID:"clock-hero-date",children:(0,_format.formatClockDate)(t)}),(0,_jsxRuntime.jsx)(_reactNative.View,{testID:"clock-status",accessibilityLabel:`Clock status: ${n.label}${i?`, ${r}`:""}`,children:(0,_jsxRuntime.jsx)(_reactNative.Text,{style:[styles.heroStatus,i?styles.heroStatusActive:null],testID:"clock-offset",children:i?`${r}${l}`:"Real time"})})]})}const HOUR=36e5;const DAY=24*HOUR;const JUMP_BAR=[{ms:HOUR,unit:"hour"},{ms:DAY,unit:"day"},{ms:7*DAY,unit:"week"},{ms:30*DAY,unit:"month"}];function JumpBar({run:e}){return(0,_jsxRuntime.jsx)(_sharedUi.NightCard,{style:styles.jumpBar,children:JUMP_BAR.map((t,o)=>(0,_jsxRuntime.jsxs)(_reactNative.TouchableOpacity,{testID:(0,_format.jumpTestId)(t.ms),accessibilityRole:"button",accessibilityLabel:`Jump ahead one ${t.unit}`,activeOpacity:.6,onPress:()=>e("shift",{by:t.ms}),style:[styles.jump,o>0?styles.jumpDivider:null],children:[(0,_jsxRuntime.jsx)(_reactNative.Text,{style:styles.jumpAmount,children:"+1"}),(0,_jsxRuntime.jsx)(_reactNative.Text,{style:styles.jumpUnit,children:t.unit})]},t.unit))})}function DisclosureRow({title:e,pro:t,value:o,open:n,onPress:i,testID:r}){return(0,_jsxRuntime.jsxs)(_reactNative.TouchableOpacity,{testID:r,accessibilityRole:"button",accessibilityLabel:e,accessibilityState:{expanded:n},activeOpacity:.6,onPress:i,style:styles.row,children:[(0,_jsxRuntime.jsx)(ProTitle,{title:e,isPro:!t}),(0,_jsxRuntime.jsxs)(_reactNative.View,{style:styles.rowRight,children:[o,(0,_jsxRuntime.jsx)(_reactNative.View,{style:n?styles.chevronOpen:null,children:(0,_jsxRuntime.jsx)(_sharedUi.ChevronRight,{size:16,color:_sharedUi.night.color.textTertiary})})]})]})}function LiveDateValue({snapshot:e}){const{virtual:t}=(0,_useLiveClock.useLiveClock)(e,1e3);return(0,_jsxRuntime.jsx)(_reactNative.Text,{style:[styles.rowValue,styles.tabular],numberOfLines:1,children:(0,_format.formatChipTime)(t,false)})}function ActionRow({label:e,onPress:t,testID:o,destructive:n,disabled:i,accessibilityLabel:r}){return(0,_jsxRuntime.jsx)(_reactNative.TouchableOpacity,{testID:o,accessibilityRole:"button",accessibilityLabel:r??e,accessibilityState:{disabled:!!i},activeOpacity:.6,disabled:i,onPress:t,style:[styles.row,i?styles.rowDisabled:null],children:(0,_jsxRuntime.jsx)(_reactNative.Text,{style:[styles.actionLabel,n?styles.actionDestructive:null],children:e})})}const PRESETS=_clockMath.TIME_PRESETS.filter(e=>["midnight","month-end","year-end"].includes(e.id));function DateEditor({snapshot:e,run:t,onDone:o}){const[n,i]=(0,_react.useState)("");const{virtual:r}=(0,_useLiveClock.useLiveClock)(e,1e3);const l=()=>n.trim()||(0,_format.formatInputTime)(r);const u=e.mode==="frozen";const s=a=>{t("setTime",{time:a,freeze:u});o()};return(0,_jsxRuntime.jsxs)(_reactNative.View,{style:styles.editor,children:[(0,_jsxRuntime.jsxs)(_reactNative.View,{style:styles.inputRow,children:[(0,_jsxRuntime.jsx)(_reactNative.TextInput,{testID:"clock-time-input",accessibilityLabel:"Date and time",value:n,onChangeText:i,placeholder:(0,_format.formatInputTime)(r),placeholderTextColor:_sharedUi.night.color.placeholder,autoCapitalize:"none",autoCorrect:false,returnKeyType:"done",onSubmitEditing:()=>s(l()),style:styles.input}),(0,_jsxRuntime.jsx)(_sharedUi.NightButton,{label:"Set",testID:"clock-time-apply",accessibilityLabel:"Set this time",size:"md",variant:"primary",fullWidth:false,onPress:()=>s(l())})]}),(0,_jsxRuntime.jsx)(_reactNative.Text,{style:styles.hint,children:"Year-month-day and 24-hour time, or +3d, -2h"}),(0,_jsxRuntime.jsx)(_reactNative.View,{style:styles.presets,children:PRESETS.map(a=>(0,_jsxRuntime.jsx)(_sharedUi.NightChip,{label:a.label,testID:`clock-preset-${a.id}`,onPress:()=>s(a.at(r,_patches.RealDate))},a.id))})]})}const SPEED_TABS=[{key:"1",label:"Normal"},{key:"10",label:"10\xD7"},{key:"60",label:"1 min/s"},{key:"3600",label:"1 hr/s"}];function speedLabel(e){if(e.mode==="real"||e.rate===1)return"Normal";return SPEED_TABS.find(t=>Number(t.key)===e.rate)?.label??(0,_clockMath.formatRate)(e.rate)}function SpeedPicker({snapshot:e,run:t}){const o=e.mode==="real"?"1":String(e.rate);return(0,_jsxRuntime.jsxs)(_reactNative.View,{style:styles.editor,children:[(0,_jsxRuntime.jsx)(_reactNative.View,{style:styles.segmentRow,children:(0,_jsxRuntime.jsx)(_sharedUi.NightSegmented,{tabs:SPEED_TABS,activeKey:o,size:"sm",testIDPrefix:"clock-speed",onChange:n=>t("setRate",{rate:Number(n)})})}),(0,_jsxRuntime.jsx)(_reactNative.Text,{style:styles.hint,children:"Taps, animations and timers keep real speed."})]})}const OPTIONS=[{key:"showChip",title:"Show Floating Clock"},{key:"persist",title:"Keep After Reload",pro:true}];function OptionsCard({settings:e,run:t,isPro:o,onUpgrade:n}){return(0,_jsxRuntime.jsx)(_sharedUi.NightCard,{children:(0,_jsxRuntime.jsx)(_sharedUi.NightRows,{children:OPTIONS.map(i=>{const r=!!i.pro&&!o;return(0,_jsxRuntime.jsxs)(_reactNative.View,{style:styles.row,children:[(0,_jsxRuntime.jsx)(ProTitle,{title:i.title,isPro:!r}),(0,_jsxRuntime.jsx)(_sharedUi.NightSwitch,{value:r?false:e[i.key],testID:`clock-setting-${i.key}`,accessibilityLabel:i.title,onValueChange:l=>r?n(i.title):t("updateSettings",{[i.key]:l})})]},i.key)})})})}const styles=_reactNative.StyleSheet.create({fill:{flex:1},content:{paddingHorizontal:_sharedUi.night.gutter,paddingTop:8,gap:_sharedUi.night.groupGap},waiting:{flex:1,alignItems:"center",justifyContent:"center",padding:24},hero:{alignItems:"center",paddingTop:12},heroTime:{color:_sharedUi.night.color.text,fontSize:56,fontWeight:"200",fontVariant:["tabular-nums"],letterSpacing:1},heroTimeActive:{color:AMBER},heroDate:{color:_sharedUi.night.color.text,fontSize:17,fontWeight:"500",marginTop:2},heroStatus:{color:_sharedUi.night.color.textTertiary,fontSize:_sharedUi.night.font.caption,fontWeight:"500",marginTop:6},heroStatusActive:{color:_sharedUi.night.color.textSecondary},jumpBar:{flexDirection:"row"},jump:{flex:1,alignItems:"center",paddingVertical:12},jumpDivider:{borderLeftWidth:_reactNative.StyleSheet.hairlineWidth,borderLeftColor:_sharedUi.night.color.separator},jumpAmount:{color:AMBER,fontSize:17,fontWeight:"600",fontVariant:["tabular-nums"]},jumpUnit:{color:_sharedUi.night.color.textSecondary,fontSize:_sharedUi.night.font.caption,marginTop:1},row:{flexDirection:"row",alignItems:"center",justifyContent:"space-between",gap:12,minHeight:50,paddingHorizontal:_sharedUi.night.rowPadH,paddingVertical:10},rowDisabled:{opacity:.4},rowTitle:{color:_sharedUi.night.color.text,fontSize:_sharedUi.night.font.row},titleRow:{flexDirection:"row",alignItems:"center",gap:8,flexShrink:1},rowRight:{flexDirection:"row",alignItems:"center",gap:6,flexShrink:1},rowValue:{color:_sharedUi.night.color.textSecondary,fontSize:_sharedUi.night.font.row},tabular:{fontVariant:["tabular-nums"]},chevronOpen:{transform:[{rotate:"90deg"}]},actionLabel:{color:_sharedUi.night.color.accent,fontSize:_sharedUi.night.font.row},actionDestructive:{color:_sharedUi.night.color.danger},editor:{paddingHorizontal:_sharedUi.night.rowPadH,paddingBottom:14,gap:10},inputRow:{flexDirection:"row",alignItems:"center",gap:8},input:{flex:1,color:_sharedUi.night.color.text,fontFamily:_sharedUi.monoFont,fontSize:15,backgroundColor:_sharedUi.night.color.bg,borderRadius:_sharedUi.night.radius.input,borderWidth:1,borderColor:_sharedUi.night.color.border,paddingHorizontal:12,paddingVertical:8},hint:{color:_sharedUi.night.color.textTertiary,fontSize:_sharedUi.night.font.caption},presets:{flexDirection:"row",flexWrap:"wrap",gap:6},segmentRow:{flexDirection:"row"}});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,"__esModule",{value:true});exports.TokenSection=TokenSection;var _reactNative=require("react-native");var _sharedUi=require("@buoy-gg/shared-ui");var _clockMath=require("../engine/clockMath");var _useLiveClock=require("./useLiveClock");var _format=require("./format");var _jsxRuntime=require("react/jsx-runtime");const size=e=>(0,_clockMath.formatDuration)(Math.abs(e),{signed:false});function TokenSection({snapshot:e,run:r,openId:o,onToggle:t}){const i=e.tokens;return(0,_jsxRuntime.jsxs)(_reactNative.View,{children:[(0,_jsxRuntime.jsx)(_sharedUi.NightSectionLabel,{children:i.tokens.length>1?"Sign-in tokens":"Sign-in token"}),(0,_jsxRuntime.jsx)(_sharedUi.NightCard,{children:(0,_jsxRuntime.jsxs)(_sharedUi.NightRows,{children:[i.tokens.map((n,s)=>(0,_jsxRuntime.jsxs)(_reactNative.View,{children:[(0,_jsxRuntime.jsx)(TokenRow,{token:n,snapshot:e,index:s,open:o===n.id,onPress:()=>t(n.id)}),o===n.id?(0,_jsxRuntime.jsx)(TokenDetail,{token:n,snapshot:e,run:r}):null]},n.id)),i.tokens.length===0?(0,_jsxRuntime.jsx)(_reactNative.View,{style:styles.row,testID:"clock-token-empty",children:(0,_jsxRuntime.jsx)(_reactNative.Text,{style:styles.emptyText,children:i.available?"No token seen yet":"Needs the Network tool"})},"empty"):null]})}),(0,_jsxRuntime.jsx)(CheckNote,{check:i.check,tokens:i.tokens,snapshot:e,run:r}),i.tokens.length===0?(0,_jsxRuntime.jsx)(_sharedUi.NightFootnote,{children:i.available?"Tokens show up here when the app sends a signed-in request.":"Install @buoy-gg/network so the Clock tool can read the app's tokens."}):null]})}function TokenRow({token:e,snapshot:r,index:o,open:t,onPress:i}){const{virtual:n}=(0,_useLiveClock.useLiveClock)(r,1e3);const s=e.expiresAt!==void 0?e.expiresAt-n:void 0;const l=e.neverExpires?"No expiry":s===void 0?"Unknown":s<=0?"Expired":size(s);const a=s!==void 0&&s<=0?styles.valueDanger:s!==void 0&&s<6e4?styles.valueWarning:null;return(0,_jsxRuntime.jsxs)(_reactNative.TouchableOpacity,{testID:`clock-token-${o}`,accessibilityRole:"button",accessibilityLabel:`${e.label} for ${e.host}: ${s!==void 0&&s>0?`expires in ${l}`:l}`,accessibilityState:{expanded:t},activeOpacity:.6,onPress:i,style:styles.row,children:[(0,_jsxRuntime.jsxs)(_reactNative.View,{style:styles.rowText,children:[(0,_jsxRuntime.jsx)(_reactNative.Text,{style:styles.rowTitle,numberOfLines:1,children:e.label}),(0,_jsxRuntime.jsx)(_reactNative.Text,{style:styles.rowSubtitle,numberOfLines:1,children:`${e.host} \xB7 ${e.hint??e.formatLabel}`})]}),(0,_jsxRuntime.jsxs)(_reactNative.View,{style:styles.rowRight,children:[(0,_jsxRuntime.jsx)(_reactNative.Text,{style:[styles.value,a],testID:`clock-token-${o}-left`,children:l}),(0,_jsxRuntime.jsx)(_reactNative.View,{style:t?styles.chevronOpen:null,children:(0,_jsxRuntime.jsx)(_sharedUi.ChevronRight,{size:16,color:_sharedUi.night.color.textTertiary})})]})]})}function TokenDetail({token:e,snapshot:r,run:o}){const{virtual:t,real:i}=(0,_useLiveClock.useLiveClock)(r,1e3);const n=detailLines(e,t,i);const s=e.expiresAt!==void 0&&e.expiresAt-t>1e4;return(0,_jsxRuntime.jsxs)(_reactNative.View,{style:styles.detail,testID:"clock-token-detail",children:[n.map(l=>(0,_jsxRuntime.jsx)(_reactNative.Text,{style:[styles.detailLine,l.tone==="warn"?styles.warn:null,l.tone==="bad"?styles.bad:null],children:l.text},l.text)),(0,_jsxRuntime.jsxs)(_reactNative.View,{style:styles.buttons,children:[(0,_jsxRuntime.jsx)(_reactNative.View,{style:styles.button,children:(0,_jsxRuntime.jsx)(_sharedUi.NightButton,{label:"Jump to Expiry",testID:"clock-token-jump",accessibilityLabel:"Jump the app's clock to ten seconds before this token expires",size:"md",disabled:!s,onPress:()=>o("jumpToTokenExpiry",{token:e.id})})}),(0,_jsxRuntime.jsx)(_reactNative.View,{style:styles.button,children:(0,_jsxRuntime.jsx)(_sharedUi.NightButton,{label:"Fail Next Request",testID:"clock-token-fail",accessibilityLabel:"Answer the app's next request to this API with 401",size:"md",onPress:()=>o("failNextRequest",{token:e.id})})})]}),(0,_jsxRuntime.jsx)(_reactNative.Text,{style:styles.hint,children:s||e.expiresAt===void 0?"Jump tests an app that refreshes before expiry. Fail tests one that refreshes after a 401.":"This token has already expired on the app's clock. Use Real Time to jump to it again."})]})}function detailLines(e,r,o){const t=[];if(e.expiresAt!==void 0){t.push({text:`Expires ${(0,_format.formatChipTime)(e.expiresAt)}`});if(e.lifetimeMs!==void 0&&e.lifetimeMs>0){t.push({text:`Lasts ${size(e.lifetimeMs)}${e.expirySource?`, from ${e.expirySource}`:""}`})}if(e.serverExpiresAt!==void 0){const i=e.expiresAt-r;const n=e.serverExpiresAt-o;if(Math.abs(i-n)>2e3){t.push({text:n>0?`The server still accepts it for ${size(n)}`:`The server stopped accepting it ${size(n)} ago`})}}}else if(!e.neverExpires){t.push({text:"The token doesn't say when it expires, and no login response did either."})}if(e.hint)t.push({text:e.formatLabel});if(e.issuedBy)t.push({text:`Issued by ${e.issuedBy}`});if(e.refresh?.expiresAt!==void 0){const i=e.refresh.expiresAt-r;t.push({text:i>0?`Refresh token expires in ${size(i)}`:"Refresh token expired"})}if(e.refreshes>0&&e.lastRefreshAt!==void 0){t.push({text:`Refreshed ${e.refreshes===1?"once":`${e.refreshes} times`}, last at ${(0,_format.formatClockTime)(e.lastRefreshAt)}`})}t.push({text:`Sent with ${e.uses} request${e.uses===1?"":"s"}`});if(e.expiredSends>0){t.push({text:`Sent ${e.expiredSends} time${e.expiredSends===1?"":"s"} after it expired on the app's clock`,tone:"warn"})}if(e.rejected>0){t.push({text:`Rejected by the server ${e.rejected} time${e.rejected===1?"":"s"}`,tone:"warn"})}if(e.looping){t.push({text:`Refresh loop: ${e.recentRefreshes} new tokens in 20s`,tone:"bad"})}return t}function CheckNote({check:e,tokens:r,snapshot:o,run:t}){const{virtual:i,real:n}=(0,_useLiveClock.useLiveClock)(o,1e3);if(!e)return null;const s=r.find(d=>d.id===e.tokenId);const{text:l,tone:a}=verdict(e,s,i,n);return(0,_jsxRuntime.jsxs)(_reactNative.View,{style:styles.check,children:[(0,_jsxRuntime.jsx)(_reactNative.Text,{style:[styles.checkText,a==="good"?styles.good:null,a==="bad"?styles.bad:null,a==="warn"?styles.warn:null],testID:"clock-token-check",children:l}),(0,_jsxRuntime.jsx)(_reactNative.TouchableOpacity,{testID:"clock-token-check-done",accessibilityRole:"button",accessibilityLabel:e.status==="waiting"?"Stop the refresh check":"Dismiss",onPress:()=>t("stopTokenCheck"),hitSlop:{top:8,bottom:8,left:8,right:8},children:(0,_jsxRuntime.jsx)(_reactNative.Text,{style:styles.checkDone,children:e.status==="waiting"?"Stop":"Done"})})]})}function verdict(e,r,o,t){if(e.status==="loop"){return{text:`Refresh loop: ${e.newTokens} new tokens since the check started. The new tokens may already look expired to the app's clock.`,tone:"bad"}}if(e.status==="refreshed"){const l=e.newIssuedBy?` by ${e.newIssuedBy}`:"";const a=e.newLifetimeMs&&e.newLifetimeMs>0?`. The new token lasts ${size(e.newLifetimeMs)}`:"";const d=e.kind==="401"&&e.forcedAt!==void 0?"The app got the 401 and refreshed":"Refreshed";const c=e.failedRefreshes>0?` ${e.failedRefreshes===1?"One token request":`${e.failedRefreshes} token requests`} failed first (${e.lastRefreshError}).`:"";return{text:`${d} at ${(0,_format.formatClockTime)(e.refreshedAt??t)}${l}${a}.${c}`,tone:c?"warn":"good"}}const i=t-e.startedAt;const n=(e.staleAfterFailure>0?` It sent the old token again ${e.staleAfterFailure} time${e.staleAfterFailure===1?"":"s"}.`:"")+(e.failedRefreshes>0?` Its token request failed (${e.lastRefreshError}).`:"");if(i>6e4){return{text:`No new token after ${size(i)}. The app may refresh on its next action, or not at all.${n}`,tone:"warn"}}if(e.kind==="401"){return e.forcedAt===void 0?{text:`The next request to ${r?.host??"the API"} will get a 401. Use the app to send one.`}:{text:`The app got the 401. Waiting for a new token\u2026${n}`,tone:n?"warn":void 0}}const s=r?.expiresAt!==void 0?r.expiresAt-o:void 0;return s!==void 0&&s>0?{text:`Expires in ${size(s)} on the app's clock. Waiting for a new token\u2026`}:{text:"Expired on the app's clock. Waiting for the app's next request\u2026"}}const styles=_reactNative.StyleSheet.create({row:{flexDirection:"row",alignItems:"center",justifyContent:"space-between",gap:12,minHeight:56,paddingHorizontal:_sharedUi.night.rowPadH,paddingVertical:10},rowText:{flex:1,minWidth:0},rowTitle:{color:_sharedUi.night.color.text,fontSize:_sharedUi.night.font.row},rowSubtitle:{color:_sharedUi.night.color.textTertiary,fontSize:_sharedUi.night.font.caption,marginTop:2},rowRight:{flexDirection:"row",alignItems:"center",gap:6},value:{color:_sharedUi.night.color.textSecondary,fontSize:_sharedUi.night.font.row,fontVariant:["tabular-nums"]},valueWarning:{color:_sharedUi.night.color.warning},valueDanger:{color:_sharedUi.night.color.danger},chevronOpen:{transform:[{rotate:"90deg"}]},emptyText:{color:_sharedUi.night.color.textSecondary,fontSize:_sharedUi.night.font.row},detail:{paddingHorizontal:_sharedUi.night.rowPadH,paddingBottom:14,gap:4},detailLine:{color:_sharedUi.night.color.textSecondary,fontSize:_sharedUi.night.font.caption},buttons:{flexDirection:"row",gap:8,marginTop:8},button:{flex:1},hint:{color:_sharedUi.night.color.textTertiary,fontSize:_sharedUi.night.font.caption,marginTop:6},check:{flexDirection:"row",alignItems:"flex-start",gap:12,marginTop:8,marginHorizontal:_sharedUi.night.labelInset},checkText:{flex:1,color:_sharedUi.night.color.textSecondary,fontSize:_sharedUi.night.font.caption,lineHeight:18},checkDone:{color:_sharedUi.night.color.accent,fontSize:_sharedUi.night.font.caption,fontWeight:"600"},good:{color:_sharedUi.night.color.accent},warn:{color:_sharedUi.night.color.warning},bad:{color:_sharedUi.night.color.danger}});
|
|
1
|
+
"use strict";Object.defineProperty(exports,"__esModule",{value:true});exports.TokenSection=TokenSection;var _reactNative=require("react-native");var _sharedUi=require("@buoy-gg/shared-ui");var _clockMath=require("../engine/clockMath");var _useLiveClock=require("./useLiveClock");var _format=require("./format");var _jsxRuntime=require("react/jsx-runtime");const size=e=>(0,_clockMath.formatDuration)(Math.abs(e),{signed:false});function TokenSection({snapshot:e,run:o,openId:l,onToggle:i,isPro:n,onUpgrade:r}){const t=e.tokens;return(0,_jsxRuntime.jsxs)(_reactNative.View,{children:[(0,_jsxRuntime.jsx)(_sharedUi.NightSectionLabel,{children:t.tokens.length>1?"Sign-in tokens":"Sign-in token"}),(0,_jsxRuntime.jsx)(_sharedUi.NightCard,{children:(0,_jsxRuntime.jsxs)(_sharedUi.NightRows,{children:[t.tokens.map((s,a)=>(0,_jsxRuntime.jsxs)(_reactNative.View,{children:[(0,_jsxRuntime.jsx)(TokenRow,{token:s,snapshot:e,index:a,open:l===s.id,onPress:()=>i(s.id)}),l===s.id?(0,_jsxRuntime.jsx)(TokenDetail,{token:s,snapshot:e,run:n?o:()=>r("Sign-in token tests"),isPro:n}):null]},s.id)),t.tokens.length===0?(0,_jsxRuntime.jsx)(_reactNative.View,{style:styles.row,testID:"clock-token-empty",children:(0,_jsxRuntime.jsx)(_reactNative.Text,{style:styles.emptyText,children:t.available?"No token seen yet":"Needs the Network tool"})},"empty"):null]})}),(0,_jsxRuntime.jsx)(CheckNote,{check:t.check,tokens:t.tokens,snapshot:e,run:o}),t.tokens.length===0?(0,_jsxRuntime.jsx)(_sharedUi.NightFootnote,{children:t.available?"Tokens show up here when the app sends a signed-in request.":"Install @buoy-gg/network so the Clock tool can read the app's tokens."}):null]})}function TokenRow({token:e,snapshot:o,index:l,open:i,onPress:n}){const{virtual:r}=(0,_useLiveClock.useLiveClock)(o,1e3);const t=e.expiresAt!==void 0?e.expiresAt-r:void 0;const s=e.neverExpires?"No expiry":t===void 0?"Unknown":t<=0?"Expired":size(t);const a=t!==void 0&&t<=0?styles.valueDanger:t!==void 0&&t<6e4?styles.valueWarning:null;return(0,_jsxRuntime.jsxs)(_reactNative.TouchableOpacity,{testID:`clock-token-${l}`,accessibilityRole:"button",accessibilityLabel:`${e.label} for ${e.host}: ${t!==void 0&&t>0?`expires in ${s}`:s}`,accessibilityState:{expanded:i},activeOpacity:.6,onPress:n,style:styles.row,children:[(0,_jsxRuntime.jsxs)(_reactNative.View,{style:styles.rowText,children:[(0,_jsxRuntime.jsx)(_reactNative.Text,{style:styles.rowTitle,numberOfLines:1,children:e.label}),(0,_jsxRuntime.jsx)(_reactNative.Text,{style:styles.rowSubtitle,numberOfLines:1,children:`${e.host} \xB7 ${e.hint??e.formatLabel}`})]}),(0,_jsxRuntime.jsxs)(_reactNative.View,{style:styles.rowRight,children:[(0,_jsxRuntime.jsx)(_reactNative.Text,{style:[styles.value,a],testID:`clock-token-${l}-left`,children:s}),(0,_jsxRuntime.jsx)(_reactNative.View,{style:i?styles.chevronOpen:null,children:(0,_jsxRuntime.jsx)(_sharedUi.ChevronRight,{size:16,color:_sharedUi.night.color.textTertiary})})]})]})}function TokenDetail({token:e,snapshot:o,run:l,isPro:i}){const{virtual:n,real:r}=(0,_useLiveClock.useLiveClock)(o,1e3);const t=detailLines(e,n,r);const s=e.expiresAt!==void 0&&e.expiresAt-n>1e4;return(0,_jsxRuntime.jsxs)(_reactNative.View,{style:styles.detail,testID:"clock-token-detail",children:[t.map(a=>(0,_jsxRuntime.jsx)(_reactNative.Text,{style:[styles.detailLine,a.tone==="warn"?styles.warn:null,a.tone==="bad"?styles.bad:null],children:a.text},a.text)),(0,_jsxRuntime.jsxs)(_reactNative.View,{style:styles.buttons,children:[(0,_jsxRuntime.jsx)(_reactNative.View,{style:styles.button,children:(0,_jsxRuntime.jsx)(_sharedUi.NightButton,{label:"Jump to Expiry",testID:"clock-token-jump",accessibilityLabel:"Jump the app's clock to ten seconds before this token expires",size:"md",disabled:!s,onPress:()=>l("jumpToTokenExpiry",{token:e.id})})}),(0,_jsxRuntime.jsx)(_reactNative.View,{style:styles.button,children:(0,_jsxRuntime.jsx)(_sharedUi.NightButton,{label:"Fail Next Request",testID:"clock-token-fail",accessibilityLabel:"Answer the app's next request to this API with 401",size:"md",onPress:()=>l("failNextRequest",{token:e.id})})})]}),i?null:(0,_jsxRuntime.jsxs)(_reactNative.View,{style:styles.proLine,children:[(0,_jsxRuntime.jsx)(_sharedUi.ProBadge,{}),(0,_jsxRuntime.jsx)(_reactNative.Text,{style:[styles.hint,styles.proHint],children:"Jump to Expiry and Fail Next Request are part of Buoy Pro."})]}),(0,_jsxRuntime.jsx)(_reactNative.Text,{style:styles.hint,children:s||e.expiresAt===void 0?"Jump tests an app that refreshes before expiry. Fail tests one that refreshes after a 401.":"This token has already expired on the app's clock. Use Real Time to jump to it again."})]})}function detailLines(e,o,l){const i=[];if(e.expiresAt!==void 0){i.push({text:`Expires ${(0,_format.formatChipTime)(e.expiresAt)}`});if(e.lifetimeMs!==void 0&&e.lifetimeMs>0){i.push({text:`Lasts ${size(e.lifetimeMs)}${e.expirySource?`, from ${e.expirySource}`:""}`})}if(e.serverExpiresAt!==void 0){const n=e.expiresAt-o;const r=e.serverExpiresAt-l;if(Math.abs(n-r)>2e3){i.push({text:r>0?`The server still accepts it for ${size(r)}`:`The server stopped accepting it ${size(r)} ago`})}}}else if(!e.neverExpires){i.push({text:"The token doesn't say when it expires, and no login response did either."})}if(e.hint)i.push({text:e.formatLabel});if(e.issuedBy)i.push({text:`Issued by ${e.issuedBy}`});if(e.refresh?.expiresAt!==void 0){const n=e.refresh.expiresAt-o;i.push({text:n>0?`Refresh token expires in ${size(n)}`:"Refresh token expired"})}if(e.refreshes>0&&e.lastRefreshAt!==void 0){i.push({text:`Refreshed ${e.refreshes===1?"once":`${e.refreshes} times`}, last at ${(0,_format.formatClockTime)(e.lastRefreshAt)}`})}i.push({text:`Sent with ${e.uses} request${e.uses===1?"":"s"}`});if(e.expiredSends>0){i.push({text:`Sent ${e.expiredSends} time${e.expiredSends===1?"":"s"} after it expired on the app's clock`,tone:"warn"})}if(e.rejected>0){i.push({text:`Rejected by the server ${e.rejected} time${e.rejected===1?"":"s"}`,tone:"warn"})}if(e.looping){i.push({text:`Refresh loop: ${e.recentRefreshes} new tokens in 20s`,tone:"bad"})}return i}function CheckNote({check:e,tokens:o,snapshot:l,run:i}){const{virtual:n,real:r}=(0,_useLiveClock.useLiveClock)(l,1e3);if(!e)return null;const t=o.find(d=>d.id===e.tokenId);const{text:s,tone:a}=verdict(e,t,n,r);return(0,_jsxRuntime.jsxs)(_reactNative.View,{style:styles.check,children:[(0,_jsxRuntime.jsx)(_reactNative.Text,{style:[styles.checkText,a==="good"?styles.good:null,a==="bad"?styles.bad:null,a==="warn"?styles.warn:null],testID:"clock-token-check",children:s}),(0,_jsxRuntime.jsx)(_reactNative.TouchableOpacity,{testID:"clock-token-check-done",accessibilityRole:"button",accessibilityLabel:e.status==="waiting"?"Stop the refresh check":"Dismiss",onPress:()=>i("stopTokenCheck"),hitSlop:{top:8,bottom:8,left:8,right:8},children:(0,_jsxRuntime.jsx)(_reactNative.Text,{style:styles.checkDone,children:e.status==="waiting"?"Stop":"Done"})})]})}function verdict(e,o,l,i){if(e.status==="loop"){return{text:`Refresh loop: ${e.newTokens} new tokens since the check started. The new tokens may already look expired to the app's clock.`,tone:"bad"}}if(e.status==="refreshed"){const s=e.newIssuedBy?` by ${e.newIssuedBy}`:"";const a=e.newLifetimeMs&&e.newLifetimeMs>0?`. The new token lasts ${size(e.newLifetimeMs)}`:"";const d=e.kind==="401"&&e.forcedAt!==void 0?"The app got the 401 and refreshed":"Refreshed";const c=e.failedRefreshes>0?` ${e.failedRefreshes===1?"One token request":`${e.failedRefreshes} token requests`} failed first (${e.lastRefreshError}).`:"";return{text:`${d} at ${(0,_format.formatClockTime)(e.refreshedAt??i)}${s}${a}.${c}`,tone:c?"warn":"good"}}const n=i-e.startedAt;const r=(e.staleAfterFailure>0?` It sent the old token again ${e.staleAfterFailure} time${e.staleAfterFailure===1?"":"s"}.`:"")+(e.failedRefreshes>0?` Its token request failed (${e.lastRefreshError}).`:"");if(n>6e4){return{text:`No new token after ${size(n)}. The app may refresh on its next action, or not at all.${r}`,tone:"warn"}}if(e.kind==="401"){return e.forcedAt===void 0?{text:`The next request to ${o?.host??"the API"} will get a 401. Use the app to send one.`}:{text:`The app got the 401. Waiting for a new token\u2026${r}`,tone:r?"warn":void 0}}const t=o?.expiresAt!==void 0?o.expiresAt-l:void 0;return t!==void 0&&t>0?{text:`Expires in ${size(t)} on the app's clock. Waiting for a new token\u2026`}:{text:"Expired on the app's clock. Waiting for the app's next request\u2026"}}const styles=_reactNative.StyleSheet.create({row:{flexDirection:"row",alignItems:"center",justifyContent:"space-between",gap:12,minHeight:56,paddingHorizontal:_sharedUi.night.rowPadH,paddingVertical:10},rowText:{flex:1,minWidth:0},rowTitle:{color:_sharedUi.night.color.text,fontSize:_sharedUi.night.font.row},rowSubtitle:{color:_sharedUi.night.color.textTertiary,fontSize:_sharedUi.night.font.caption,marginTop:2},rowRight:{flexDirection:"row",alignItems:"center",gap:6},value:{color:_sharedUi.night.color.textSecondary,fontSize:_sharedUi.night.font.row,fontVariant:["tabular-nums"]},valueWarning:{color:_sharedUi.night.color.warning},valueDanger:{color:_sharedUi.night.color.danger},chevronOpen:{transform:[{rotate:"90deg"}]},emptyText:{color:_sharedUi.night.color.textSecondary,fontSize:_sharedUi.night.font.row},detail:{paddingHorizontal:_sharedUi.night.rowPadH,paddingBottom:14,gap:4},detailLine:{color:_sharedUi.night.color.textSecondary,fontSize:_sharedUi.night.font.caption},buttons:{flexDirection:"row",gap:8,marginTop:8},button:{flex:1},hint:{color:_sharedUi.night.color.textTertiary,fontSize:_sharedUi.night.font.caption,marginTop:6},proLine:{flexDirection:"row",alignItems:"center",gap:8,marginTop:6},proHint:{marginTop:0,flexShrink:1},check:{flexDirection:"row",alignItems:"flex-start",gap:12,marginTop:8,marginHorizontal:_sharedUi.night.labelInset},checkText:{flex:1,color:_sharedUi.night.color.textSecondary,fontSize:_sharedUi.night.font.caption,lineHeight:18},checkDone:{color:_sharedUi.night.color.accent,fontSize:_sharedUi.night.font.caption,fontWeight:"600"},good:{color:_sharedUi.night.color.accent},warn:{color:_sharedUi.night.color.warning},bad:{color:_sharedUi.night.color.danger}});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,"__esModule",{value:true});exports.__resetClockStoreForTests=__resetClockStoreForTests;exports.bootClock=bootClock;exports.freeze=freeze;exports.getClockAnchor=getClockAnchor;exports.getClockSettings=getClockSettings;exports.getClockSnapshot=getClockSnapshot;exports.getStableClockSnapshot=getStableClockSnapshot;exports.isClockBooted=isClockBooted;exports.isClockOverridden=isClockOverridden;exports.previewJump=previewJump;exports.reset=reset;exports.resume=resume;exports.setRate=setRate;exports.setTime=setTime;exports.shift=shift;exports.subscribeClock=subscribeClock;exports.updateSettings=updateSettings;exports.virtualNow=virtualNow;var _clockMath=require("./clockMath");var _patches=require("./patches");var _timers=require("./timers");var _persistence=require("./persistence");var _tokenStore=require("../tokens/tokenStore");let state={anchor:_clockMath.REAL_ANCHOR,settings:_persistence.DEFAULT_SETTINGS,lastJump:null,changedAt:null,hydrated:false};const listeners=new Set;let snapshotCache=null;function emit(){snapshotCache=null;listeners.forEach(e=>e())}(0,_tokenStore.subscribeTokens)(emit);function subscribeClock(e){listeners.add(e);return()=>{listeners.delete(e)}}function getClockAnchor(){return state.anchor}function getClockSettings(){return state.settings}function virtualNow(){return(0,_clockMath.virtualAt)(state.anchor,(0,_patches.realNow)())}function isClockOverridden(){return state.anchor.mode!=="real"}function syncPatches(e){if(e.mode==="real"){(0,_patches.setVirtualSource)(null);(0,_patches.uninstallDatePatches)();return}(0,_timers.installTimerTracking)();(0,_patches.setVirtualSource)(t=>(0,_clockMath.virtualAt)(state.anchor,t));(0,_patches.installDatePatches)()}function persist(){const e={v:1,anchor:state.settings.persist?state.anchor:null,settings:state.settings};void(0,_persistence.writeSaved)(e)}function commit(e,{save:t=true}={}){state={...state,...e};if(e.anchor)syncPatches(state.anchor);if(t)persist();emit()}function setAnchor(e,t=state.lastJump){commit({anchor:e,lastJump:t,changedAt:(0,_patches.realNow)(),hydrated:true})}const parseDate=e=>_patches.RealDate.parse(e);function setTime(e,t=false){const r=(0,_patches.realNow)();const n=(0,_clockMath.virtualAt)(state.anchor,r);const o=(0,_clockMath.parseTime)(e,n,parseDate);const s=o-n;setAnchor((0,_clockMath.travelTo)(state.anchor,r,o,t),{byMs:s,firedTimers:0,at:r});return getClockSnapshot()}function shift(e,t){const r=(0,_clockMath.parseDuration)(e);const n=(0,_patches.realNow)();const o=(0,_clockMath.shiftBy)(state.anchor,n,r);const s=(t??state.settings.fireTimersOnJump)&&r>0;setAnchor(o,{byMs:r,firedTimers:0,at:n});if(s){const a=(0,_timers.fireDueWithin)(r);if(a>0){commit({lastJump:{byMs:r,firedTimers:a,at:n}},{save:false})}}return getClockSnapshot()}function freeze(e){const t=(0,_patches.realNow)();const r=(0,_clockMath.virtualAt)(state.anchor,t);const n=e===void 0||e===""?r:(0,_clockMath.parseTime)(e,r,parseDate);setAnchor((0,_clockMath.freezeAt)(state.anchor,t,n));return getClockSnapshot()}function resume(){if(state.anchor.mode==="frozen")setAnchor((0,_clockMath.resume)(state.anchor,(0,_patches.realNow)()));return getClockSnapshot()}function setRate(e){setAnchor((0,_clockMath.withRate)(state.anchor,(0,_patches.realNow)(),Number(e)));return getClockSnapshot()}function reset(){setAnchor(_clockMath.REAL_ANCHOR,null);return getClockSnapshot()}function updateSettings(e){const t={...state.settings};for(const r of Object.keys(_persistence.DEFAULT_SETTINGS)){if(typeof e[r]==="boolean")t[r]=e[r]}commit({settings:t});return getClockSnapshot()}function previewJump(e){return e>0?(0,_timers.countDueWithin)(e):0}let booted=false;function applySaved(e){if(!e){commit({hydrated:true},{save:false});return}
|
|
1
|
+
"use strict";Object.defineProperty(exports,"__esModule",{value:true});exports.__resetClockStoreForTests=__resetClockStoreForTests;exports.bootClock=bootClock;exports.freeze=freeze;exports.getClockAnchor=getClockAnchor;exports.getClockSettings=getClockSettings;exports.getClockSnapshot=getClockSnapshot;exports.getStableClockSnapshot=getStableClockSnapshot;exports.holdForNextReload=holdForNextReload;exports.isClockBooted=isClockBooted;exports.isClockOverridden=isClockOverridden;exports.previewJump=previewJump;exports.reset=reset;exports.resume=resume;exports.setRate=setRate;exports.setTime=setTime;exports.shift=shift;exports.subscribeClock=subscribeClock;exports.updateSettings=updateSettings;exports.virtualNow=virtualNow;var _clockMath=require("./clockMath");var _patches=require("./patches");var _timers=require("./timers");var _persistence=require("./persistence");var _tokenStore=require("../tokens/tokenStore");var _sharedUi=require("@buoy-gg/shared-ui");let state={anchor:_clockMath.REAL_ANCHOR,settings:_persistence.DEFAULT_SETTINGS,lastJump:null,changedAt:null,hydrated:false};const listeners=new Set;let snapshotCache=null;function emit(){snapshotCache=null;listeners.forEach(e=>e())}(0,_tokenStore.subscribeTokens)(emit);function subscribeClock(e){listeners.add(e);return()=>{listeners.delete(e)}}function getClockAnchor(){return state.anchor}function getClockSettings(){return state.settings}function virtualNow(){return(0,_clockMath.virtualAt)(state.anchor,(0,_patches.realNow)())}function isClockOverridden(){return state.anchor.mode!=="real"}function syncPatches(e){if(e.mode==="real"){(0,_patches.setVirtualSource)(null);(0,_patches.uninstallDatePatches)();return}(0,_timers.installTimerTracking)();(0,_patches.setVirtualSource)(t=>(0,_clockMath.virtualAt)(state.anchor,t));(0,_patches.installDatePatches)()}function persist(){const e={v:1,anchor:state.settings.persist&&(0,_sharedUi.isProNow)()?state.anchor:null,settings:state.settings};void(0,_persistence.writeSaved)(e)}function holdForNextReload(){const e=state.settings.persist&&(0,_sharedUi.isProNow)();const t={v:1,anchor:e?state.anchor:null,settings:state.settings};if(state.settings.persist&&state.anchor.mode!=="real"){t.reload={anchor:state.anchor,at:(0,_patches.realNow)()}}return(0,_persistence.writeSaved)(t)}function commit(e,{save:t=true}={}){state={...state,...e};if(e.anchor)syncPatches(state.anchor);if(t)persist();emit()}function setAnchor(e,t=state.lastJump){commit({anchor:e,lastJump:t,changedAt:(0,_patches.realNow)(),hydrated:true})}const parseDate=e=>_patches.RealDate.parse(e);function setTime(e,t=false){const r=(0,_patches.realNow)();const n=(0,_clockMath.virtualAt)(state.anchor,r);const o=(0,_clockMath.parseTime)(e,n,parseDate);const s=o-n;setAnchor((0,_clockMath.travelTo)(state.anchor,r,o,t),{byMs:s,firedTimers:0,at:r});return getClockSnapshot()}function shift(e,t){const r=(0,_clockMath.parseDuration)(e);const n=(0,_patches.realNow)();const o=(0,_clockMath.shiftBy)(state.anchor,n,r);const s=(t??state.settings.fireTimersOnJump)&&r>0;setAnchor(o,{byMs:r,firedTimers:0,at:n});if(s){const a=(0,_timers.fireDueWithin)(r);if(a>0){commit({lastJump:{byMs:r,firedTimers:a,at:n}},{save:false})}}return getClockSnapshot()}function freeze(e){const t=(0,_patches.realNow)();const r=(0,_clockMath.virtualAt)(state.anchor,t);const n=e===void 0||e===""?r:(0,_clockMath.parseTime)(e,r,parseDate);setAnchor((0,_clockMath.freezeAt)(state.anchor,t,n));return getClockSnapshot()}function resume(){if(state.anchor.mode==="frozen")setAnchor((0,_clockMath.resume)(state.anchor,(0,_patches.realNow)()));return getClockSnapshot()}function setRate(e){setAnchor((0,_clockMath.withRate)(state.anchor,(0,_patches.realNow)(),Number(e)));return getClockSnapshot()}function reset(){setAnchor(_clockMath.REAL_ANCHOR,null);return getClockSnapshot()}function updateSettings(e){const t={...state.settings};for(const r of Object.keys(_persistence.DEFAULT_SETTINGS)){if(typeof e[r]==="boolean")t[r]=e[r]}commit({settings:t});return getClockSnapshot()}function previewJump(e){return e>0?(0,_timers.countDueWithin)(e):0}let booted=false;function applySaved(e){if(!e){commit({hydrated:true},{save:false});return}const t=e.reload?(0,_patches.realNow)()-e.reload.at:Infinity;const r=t>=0&&t<_persistence.RELOAD_HOLD_MS?e.reload?.anchor:void 0;if(e.reload)void(0,_persistence.writeSaved)({v:1,anchor:e.anchor,settings:e.settings});const n=e.anchor??r??null;commit({settings:e.settings,anchor:n??_clockMath.REAL_ANCHOR,changedAt:n?(0,_patches.realNow)():null,hydrated:true},{save:false})}function bootClock(){if(booted)return;booted=true;(0,_timers.installTimerTracking)();const e=(0,_persistence.readSavedSync)();if(e!==void 0){applySaved(e);return}void(0,_persistence.readSavedAsync)().then(t=>{if(state.changedAt===null)applySaved(t);else commit({hydrated:true},{save:false})})}function isClockBooted(){return booted}function deviceTimeZone(){try{return Intl.DateTimeFormat().resolvedOptions().timeZone??"unknown"}catch{return"unknown"}}function getClockSnapshot(){const e=(0,_patches.realNow)();const t=(0,_clockMath.virtualAt)(state.anchor,e);return{mode:state.anchor.mode,active:state.anchor.mode!=="real",rate:state.anchor.rate,virtualNow:t,virtualIso:new _patches.RealDate(t).toISOString(),realNow:e,offsetMs:(0,_clockMath.offsetAt)(state.anchor,e),timeZone:deviceTimeZone(),timers:(0,_timers.summarizeTimers)(),lastJump:state.lastJump,changedAt:state.changedAt,settings:state.settings,hydrated:state.hydrated,tokens:(0,_tokenStore.getTokenReport)(),patched:{date:(0,_patches.isDatePatched)(),intl:(0,_patches.isIntlPatched)(),timers:(0,_timers.isTimerTrackingInstalled)(),animatedOnRealClock:(0,_patches.isAnimatedRealClock)()}}}function getStableClockSnapshot(){if(!snapshotCache)snapshotCache=getClockSnapshot();return snapshotCache}function __resetClockStoreForTests(){(0,_patches.setVirtualSource)(null);(0,_patches.uninstallDatePatches)();state={anchor:_clockMath.REAL_ANCHOR,settings:_persistence.DEFAULT_SETTINGS,lastJump:null,changedAt:null,hydrated:false};booted=false;emit()}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,"__esModule",{value:true});exports.DEFAULT_SETTINGS=exports.CLOCK_STORAGE_KEY=void 0;exports.parseSaved=parseSaved;exports.readSavedAsync=readSavedAsync;Object.defineProperty(exports,"readSavedSync",{enumerable:true,get:function(){return _readSavedSync.readSavedSync}});exports.writeSaved=writeSaved;var _sharedUi=require("@buoy-gg/shared-ui");var _clockMath=require("./clockMath");var _readSavedSync=require("./readSavedSync");const DEFAULT_SETTINGS=exports.DEFAULT_SETTINGS={persist:true,showChip:true,fireTimersOnJump:true};const CLOCK_STORAGE_KEY=exports.CLOCK_STORAGE_KEY=_sharedUi.devToolsStorageKeys.clock.state();function parseSaved(t){if(!t)return null;try{const e=JSON.parse(t);if(!e||e.v!==1)return null;const r=e.settings??{};return{v:1,anchor:(0,_clockMath.isAnchor)(e.anchor)?e.anchor:null,settings:{persist:typeof r.persist==="boolean"?r.persist:DEFAULT_SETTINGS.persist,showChip:typeof r.showChip==="boolean"?r.showChip:DEFAULT_SETTINGS.showChip,fireTimersOnJump:typeof r.fireTimersOnJump==="boolean"?r.fireTimersOnJump:DEFAULT_SETTINGS.fireTimersOnJump}}}catch{return null}}async function readSavedAsync(){try{return parseSaved(await _sharedUi.persistentStorage.getItem(CLOCK_STORAGE_KEY))}catch{return null}}let writes=Promise.resolve();function writeSaved(t){const e=JSON.stringify(t);writes=writes.then(()=>_sharedUi.persistentStorage.setItem(CLOCK_STORAGE_KEY,e)).catch(()=>{});return writes.then(()=>{})}
|
|
1
|
+
"use strict";Object.defineProperty(exports,"__esModule",{value:true});exports.RELOAD_HOLD_MS=exports.DEFAULT_SETTINGS=exports.CLOCK_STORAGE_KEY=void 0;exports.parseSaved=parseSaved;exports.readSavedAsync=readSavedAsync;Object.defineProperty(exports,"readSavedSync",{enumerable:true,get:function(){return _readSavedSync.readSavedSync}});exports.writeSaved=writeSaved;var _sharedUi=require("@buoy-gg/shared-ui");var _clockMath=require("./clockMath");var _readSavedSync=require("./readSavedSync");const DEFAULT_SETTINGS=exports.DEFAULT_SETTINGS={persist:true,showChip:true,fireTimersOnJump:true};const RELOAD_HOLD_MS=exports.RELOAD_HOLD_MS=2*6e4;const CLOCK_STORAGE_KEY=exports.CLOCK_STORAGE_KEY=_sharedUi.devToolsStorageKeys.clock.state();function parseSaved(t){if(!t)return null;try{const e=JSON.parse(t);if(!e||e.v!==1)return null;const r=e.settings??{};const s=e.reload&&(0,_clockMath.isAnchor)(e.reload.anchor)&&typeof e.reload.at==="number"?{anchor:e.reload.anchor,at:e.reload.at}:void 0;return{v:1,anchor:(0,_clockMath.isAnchor)(e.anchor)?e.anchor:null,...s?{reload:s}:{},settings:{persist:typeof r.persist==="boolean"?r.persist:DEFAULT_SETTINGS.persist,showChip:typeof r.showChip==="boolean"?r.showChip:DEFAULT_SETTINGS.showChip,fireTimersOnJump:typeof r.fireTimersOnJump==="boolean"?r.fireTimersOnJump:DEFAULT_SETTINGS.fireTimersOnJump}}}catch{return null}}async function readSavedAsync(){try{return parseSaved(await _sharedUi.persistentStorage.getItem(CLOCK_STORAGE_KEY))}catch{return null}}let writes=Promise.resolve();function writeSaved(t){const e=JSON.stringify(t);writes=writes.then(()=>_sharedUi.persistentStorage.setItem(CLOCK_STORAGE_KEY,e)).catch(()=>{});return writes.then(()=>{})}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,"__esModule",{value:true});exports.countDueWithin=countDueWithin;exports.fireDueWithin=fireDueWithin;exports.installTimerTracking=installTimerTracking;exports.isTimerTrackingInstalled=isTimerTrackingInstalled;exports.summarizeTimers=summarizeTimers;exports.uninstallTimerTracking=uninstallTimerTracking;var _patches=require("./patches");const g=globalThis;const TAG="__buoyClockTimer";const pending=new Map;let originals=null;let jumpedMs=0;const timerClock=()=>(0,_patches.realNow)()+jumpedMs;function reportAsync(
|
|
1
|
+
"use strict";Object.defineProperty(exports,"__esModule",{value:true});exports.countDueWithin=countDueWithin;exports.fireDueWithin=fireDueWithin;exports.installTimerTracking=installTimerTracking;exports.isTimerTrackingInstalled=isTimerTrackingInstalled;exports.summarizeTimers=summarizeTimers;exports.uninstallTimerTracking=uninstallTimerTracking;var _patches=require("./patches");const g=globalThis;const TAG="__buoyClockTimer";const pending=new Map;let originals=null;let unpatched={};let jumpedMs=0;const timerClock=()=>(0,_patches.realNow)()+jumpedMs;function reportAsync(n){(originals?.setTimeout??setTimeout)(()=>{throw n},0)}function toDelay(n){const t=Number(n);return Number.isFinite(t)&&t>0?t:0}function isTimerTrackingInstalled(){return originals!==null}function installTimerTracking(){if(originals)return true;const{setTimeout:n,clearTimeout:t,setInterval:i,clearInterval:l}=g;if(typeof n!=="function"||typeof t!=="function")return false;if(n[TAG])return true;unpatched={setTimeout:n,clearTimeout:t,setInterval:i,clearInterval:l};originals={setTimeout:n.bind(globalThis),clearTimeout:t.bind(globalThis),setInterval:(typeof i==="function"?i:n).bind(globalThis),clearInterval:(typeof l==="function"?l:t).bind(globalThis)};const r=originals;const f=function(e,c,...u){if(typeof e!=="function")return r.setTimeout(e,c,...u);const m=toDelay(c);let a;const d=function(){pending.delete(a);return e.apply(this,u)};a=r.setTimeout(d,c);pending.set(a,{kind:"timeout",callback:e,args:u,delay:m,due:timerClock()+m,realHandle:a,run:d});return a};const o=function(e,c,...u){if(typeof e!=="function")return r.setInterval(e,c,...u);const m=toDelay(c);let a;const d=function(){const p=pending.get(a);if(p)p.due=timerClock()+m;return e.apply(this,u)};a=r.setInterval(d,c);pending.set(a,{kind:"interval",callback:e,args:u,delay:m,due:timerClock()+m,realHandle:a,run:d});return a};const s=(e,c)=>{const u=pending.get(e);if(!u)return c(e);pending.delete(e);return u.kind==="interval"?r.clearInterval(u.realHandle):r.clearTimeout(u.realHandle)};const T=function(e){return s(e,r.clearTimeout)};const v=function(e){return s(e,r.clearInterval)};globalThis.__buoyRealTimers={setTimeout:r.setTimeout,clearTimeout:T,setInterval:r.setInterval,clearInterval:v};for(const e of[f,o,T,v]){Object.defineProperty(e,TAG,{value:true})}g.setTimeout=f;g.clearTimeout=T;g.setInterval=o;g.clearInterval=v;return true}function uninstallTimerTracking(){if(!originals)return;g.setTimeout=unpatched.setTimeout;g.clearTimeout=unpatched.clearTimeout;g.setInterval=unpatched.setInterval;g.clearInterval=unpatched.clearInterval;originals=null;pending.clear();jumpedMs=0;delete globalThis.__buoyRealTimers}function summarizeTimers(){const n=timerClock();let t=0;let i=0;let l=null;for(const r of pending.values()){if(r.kind==="interval")i+=1;else{t+=1;const f=Math.max(0,r.due-n);if(l===null||f<l)l=f}}return{total:t+i,timeouts:t,intervals:i,nextTimeoutInMs:l}}function countDueWithin(n){const t=timerClock();let i=0;for(const l of pending.values())if(l.due-t<=n)i+=1;return i}function fireDueWithin(n){if(!originals||!(n>0))return 0;const t=originals;jumpedMs+=n;const i=timerClock();const l=[...pending.entries()].filter(([,o])=>o.due<=i).sort((o,s)=>o[1].due-s[1].due);let r=0;for(const[o,s]of l){if(!pending.has(o))continue;if(s.kind==="timeout"){pending.delete(o);t.clearTimeout(s.realHandle)}else{s.due=i+s.delay}try{s.callback(...s.args)}catch(T){reportAsync(T)}r+=1}const f=timerClock();for(const o of pending.values()){if(o.kind!=="timeout")continue;t.clearTimeout(o.realHandle);o.realHandle=t.setTimeout(o.run,Math.max(0,o.due-f))}return r}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,"__esModule",{value:true});exports.clockSyncAdapter=void 0;var _sharedUi=require("@buoy-gg/shared-ui");var _clockStore=require("../engine/clockStore");var _tokenStore=require("../tokens/tokenStore");var _tokenActions=require("../tokens/tokenActions");function obj(t){return t&&typeof t==="object"?t:{}}function timeParam(t,...e){for(const r of e){const n=t[r];if(typeof n==="string"||typeof n==="number")return n}return void 0}function boolParam(t,e){const r=t[e];if(typeof r==="boolean")return r;if(r==="true")return true;if(r==="false")return false;return void 0}const clockSyncAdapter=exports.clockSyncAdapter=(0,_sharedUi.createSyncAdapter)({version:1,getSnapshot(){return(0,_clockStore.getClockSnapshot)()},subscribe(t){return(0,_clockStore.subscribeClock)(t)},actions:{getState(){(0,_tokenStore.startTokenWatch)();return(0,_clockStore.getClockSnapshot)()},setTime(t){const e=obj(t);const r=timeParam(e,"time","at","date","iso");if(r===void 0){throw new Error('setTime needs `time`: ISO 8601 ("2026-12-31T23:59:50"), epoch ms, or relative ("+1d").')}return(0,_clockStore.setTime)(r,boolParam(e,"freeze")??false)},shift(t){const e=obj(t);const r=timeParam(e,"by","ms","duration","delta");if(r===void 0){throw new Error('shift needs `by`: a duration like "+1d", "-2h30m", "90s", or ms.')}return(0,_clockStore.shift)(r,boolParam(e,"fireTimers"))},freeze(t){return(0,_clockStore.freeze)(timeParam(obj(t),"time","at"))},resume(){return(0,_clockStore.resume)()},setRate(t){const e=obj(t);const r=Number(e.rate??e.speed);if(!Number.isFinite(r))throw new Error("setRate needs a numeric `rate` (1 = normal speed).");return(0,_clockStore.setRate)(r)},reset(){return(0,_clockStore.reset)()},updateSettings(t){const e=obj(t);return(0,_clockStore.updateSettings)({persist:boolParam(e,"persist"),showChip:boolParam(e,"showChip"),fireTimersOnJump:boolParam(e,"fireTimersOnJump")})},jumpToTokenExpiry(t){const e=obj(t);const r=typeof e.token==="string"?e.token:typeof e.id==="string"?e.id:void 0;const n=Number(e.leadMs??e.lead??1e4);return(0,_tokenActions.jumpToTokenExpiry)(r,Number.isFinite(n)?n:1e4)},failNextRequest(t){const e=obj(t);const r=typeof e.token==="string"?e.token:typeof e.id==="string"?e.id:void 0;const n=Number(e.status??401);const o=Number(e.times??1);return(0,_tokenActions.failNextRequest)(r,n,Number.isFinite(o)?o:1)},stopTokenCheck(){return(0,_tokenActions.stopTokenCheck)()}}});
|
|
1
|
+
"use strict";Object.defineProperty(exports,"__esModule",{value:true});exports.clockSyncAdapter=void 0;var _sharedUi=require("@buoy-gg/shared-ui");var _clockStore=require("../engine/clockStore");var _tokenStore=require("../tokens/tokenStore");var _tokenActions=require("../tokens/tokenActions");function obj(t){return t&&typeof t==="object"?t:{}}function timeParam(t,...e){for(const r of e){const n=t[r];if(typeof n==="string"||typeof n==="number")return n}return void 0}function boolParam(t,e){const r=t[e];if(typeof r==="boolean")return r;if(r==="true")return true;if(r==="false")return false;return void 0}const clockSyncAdapter=exports.clockSyncAdapter=(0,_sharedUi.createSyncAdapter)({version:1,getSnapshot(){return(0,_clockStore.getClockSnapshot)()},subscribe(t){return(0,_clockStore.subscribeClock)(t)},actions:{getState(){(0,_tokenStore.startTokenWatch)();return(0,_clockStore.getClockSnapshot)()},setTime(t){const e=obj(t);const r=timeParam(e,"time","at","date","iso");if(r===void 0){throw new Error('setTime needs `time`: ISO 8601 ("2026-12-31T23:59:50"), epoch ms, or relative ("+1d").')}return(0,_clockStore.setTime)(r,boolParam(e,"freeze")??false)},shift(t){const e=obj(t);const r=timeParam(e,"by","ms","duration","delta");if(r===void 0){throw new Error('shift needs `by`: a duration like "+1d", "-2h30m", "90s", or ms.')}return(0,_clockStore.shift)(r,boolParam(e,"fireTimers"))},freeze(t){return(0,_clockStore.freeze)(timeParam(obj(t),"time","at"))},resume(){return(0,_clockStore.resume)()},setRate(t){const e=obj(t);const r=Number(e.rate??e.speed);if(!Number.isFinite(r))throw new Error("setRate needs a numeric `rate` (1 = normal speed).");return(0,_clockStore.setRate)(r)},reset(){return(0,_clockStore.reset)()},updateSettings(t){const e=obj(t);return(0,_clockStore.updateSettings)({persist:boolParam(e,"persist"),showChip:boolParam(e,"showChip"),fireTimersOnJump:boolParam(e,"fireTimersOnJump")})},jumpToTokenExpiry(t){const e=obj(t);const r=typeof e.token==="string"?e.token:typeof e.id==="string"?e.id:void 0;const n=Number(e.leadMs??e.lead??1e4);return(0,_tokenActions.jumpToTokenExpiry)(r,Number.isFinite(n)?n:1e4)},failNextRequest(t){const e=obj(t);const r=typeof e.token==="string"?e.token:typeof e.id==="string"?e.id:void 0;const n=Number(e.status??401);const o=Number(e.times??1);return(0,_tokenActions.failNextRequest)(r,n,Number.isFinite(o)?o:1)},stopTokenCheck(){return(0,_tokenActions.stopTokenCheck)()},async holdForReload(){await(0,_clockStore.holdForNextReload)();return(0,_clockStore.getClockSnapshot)()}}});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";import{useEffect as r,useState as s}from"react";import{reloadApp as
|
|
1
|
+
"use strict";import{useEffect as r,useState as s}from"react";import{reloadApp as e}from"@buoy-gg/shared-ui";import{bootClock as i,getClockSnapshot as c,holdForNextReload as a,subscribeClock as p}from"../engine/clockStore";import{clockSyncAdapter as f}from"../sync/clockSyncAdapter";import{startTokenWatch as l}from"../tokens/tokenStore";import{ClockToolView as m}from"./ClockToolView";import{jsx as u}from"react/jsx-runtime";const k=f.actions;async function h(o,t){const n=k[o];if(!n)throw new Error(`Unknown clock action: ${o}`);return n(t)}function d(){void a().then(()=>e("auto","buoy clock")).catch(()=>{})}export function ClockBody(){r(()=>{i();l()},[]);const[o,t]=s(c);r(()=>p(()=>t(c())),[]);return u(m,{snapshot:o,onAction:h,onReload:d})}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";import{useSyncExternalStore as
|
|
1
|
+
"use strict";import{useSyncExternalStore as I}from"react";import{StyleSheet as m,Text as d,TouchableOpacity as u,View as n}from"react-native";import{ClockToolIcon as f,FloatingTool as L,Pause as T,Play as F,X as D,dismissFloatingTool as P,getFloatingTools as v,getUseIsPro as O,night as l,openFloatingTool as b}from"@buoy-gg/shared-ui";import{freeze as j,getStableClockSnapshot as g,reset as R,resume as W,subscribeClock as k,getClockSettings as V,isClockOverridden as _}from"../engine/clockStore";import{formatDuration as $}from"../engine/clockMath";import{useLiveClock as A}from"./useLiveClock";import{clockStatus as B,formatChipTime as y}from"./format";import{jsx as t,jsxs as a}from"react/jsx-runtime";export const CLOCK_CHIP_ID="clock-chip";const C={id:CLOCK_CHIP_ID,render:e=>t(ClockChip,{...e})};const E=()=>v().some(e=>e.id===CLOCK_CHIP_ID);export function openClockChip(){b(C)}let x=false;export function watchClockChip(){if(x)return;x=true;let e=false;const s=()=>{const o=_()&&V().showChip;if(o&&!e)b(C);else if(!o&&E())P(CLOCK_CHIP_ID);e=o};k(s);s()}export function ClockChip({id:e,revealToken:s}){const o=I(k,g,g);const{virtual:c,real:S}=A(o);const r=o.mode==="frozen";const h=r||O()();const w=B(o);const p=c-S;const z=`${Math.abs(p)<1e3?"0s":$(p)} \xB7 ${w.label.toLowerCase()}`;return t(L,{id:e,revealToken:s,variant:"strip",dragFromSurface:true,defaultPlacement:"top",accessibilityLabel:`Move or hide the clock chip. App time ${y(c)}`,handleAdornment:t(f,{size:12}),children:a(n,{style:i.row,children:[t(f,{size:18}),a(n,{style:i.text,children:[t(d,{style:i.time,numberOfLines:1,testID:"clock-chip-time",children:y(c)}),t(d,{style:i.detail,numberOfLines:1,testID:"clock-chip-detail",children:z})]}),h?a(u,{testID:r?"clock-chip-resume":"clock-chip-freeze",accessibilityRole:"button",accessibilityLabel:r?"Resume the app clock":"Freeze the app clock",onPress:()=>r?W():j(),style:i.button,hitSlop:{top:8,bottom:8,left:4,right:4},children:[r?t(F,{size:16,color:l.color.accent}):null,r?null:t(T,{size:16,color:l.color.text})]}):null,h?t(n,{style:i.separator}):null,t(u,{testID:"clock-chip-reset",accessibilityRole:"button",accessibilityLabel:"Back to real time",onPress:()=>R(),style:i.button,hitSlop:{top:8,bottom:8,left:4,right:8},children:t(D,{size:16,color:l.color.textSecondary})})]})})}const i=m.create({row:{flexDirection:"row",alignItems:"center",gap:10,paddingLeft:10,paddingRight:4,paddingVertical:6,minWidth:220},text:{flexShrink:1,minWidth:120},time:{color:"#F59E0B",fontSize:14,fontWeight:"600",fontVariant:["tabular-nums"]},detail:{color:l.color.textSecondary,fontSize:11,fontVariant:["tabular-nums"]},button:{width:32,height:32,alignItems:"center",justifyContent:"center",borderRadius:16},separator:{width:m.hairlineWidth,height:20,backgroundColor:l.color.separator}});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";import{useState as S}from"react";import{ScrollView as
|
|
1
|
+
"use strict";import{useState as S}from"react";import{ScrollView as $,StyleSheet as L,Text as m,TextInput as H,TouchableOpacity as x,View as n}from"react-native";import{ChevronRight as _,NightButton as J,NightCard as w,NightChip as M,NightFootnote as I,NightRows as v,NightSectionLabel as A,NightSegmented as K,NightSwitch as O,ProBadge as Y,ProUpgradeModal as G,getUseIsPro as q,monoFont as Q,night as i,useSafeAreaInsets as X}from"@buoy-gg/shared-ui";import{TIME_PRESETS as Z,formatRate as ee}from"../engine/clockMath";import{RealDate as te}from"../engine/patches";import{useLiveClock as z}from"./useLiveClock";import{TokenSection as re}from"./TokenSection";import{clockStatus as oe,formatClockDate as ie,formatChipTime as le,formatClockTime as V,formatInputTime as N,formatOffset as ne,jumpTestId as ce}from"./format";import{jsx as e,jsxs as c}from"react/jsx-runtime";const j="#F59E0B";export function ClockToolView({snapshot:t,onAction:o,onReload:s}){const d=X({minBottom:16});const[l,a]=S(null);const[u,y]=S(null);const h=q()();const[p,C]=S(null);const b=f=>C(f);const g=(f,D)=>{a(null);o(f,D).catch(T=>{a(T instanceof Error?T.message:String(T))})};const k=f=>y(D=>D===f?null:f);if(!t){return e(n,{style:r.waiting,testID:"clock-waiting",children:e(I,{centered:true,children:"Waiting for the app's clock\u2026"})})}return c($,{style:r.fill,contentContainerStyle:[r.content,{paddingBottom:d.bottom}],testID:"clock-scroll",keyboardShouldPersistTaps:"handled",children:[e(ae,{snapshot:t}),l?e(I,{tone:"danger",centered:true,children:e(m,{testID:"clock-error",children:l})}):null,c(n,{children:[e(A,{children:"Jump ahead"}),e(de,{run:g})]}),c(n,{children:[e(w,{children:c(v,{children:[c(n,{children:[e(B,{title:"Date & Time",testID:"clock-date-row",open:u==="date",onPress:()=>k("date"),value:e(ue,{snapshot:t})}),u==="date"?e(he,{snapshot:t,run:g,onDone:()=>y(null)}):null]},"date"),c(n,{style:r.row,children:[e(P,{title:"Freeze",isPro:h}),e(O,{value:t.mode==="frozen",testID:"clock-freeze",accessibilityLabel:"Freeze the clock",onValueChange:f=>f&&!h?b("Freeze"):g(f?"freeze":"resume")})]},"freeze"),c(n,{children:[e(B,{title:"Speed",pro:!h,testID:"clock-speed-row",open:u==="speed",onPress:()=>h?k("speed"):b("Speed"),value:e(m,{style:r.rowValue,children:W(t)})}),u==="speed"?e(pe,{snapshot:t,run:g}):null]},"speed")]})}),e(I,{children:"Only this app's clock changes. Screens pick up the new time when they next render, or all at once when you reload."})]}),t.tokens?e(re,{snapshot:t,run:g,openId:u,onToggle:k,isPro:h,onUpgrade:b}):null,e(w,{children:c(v,{children:[s?e(F,{label:"Reload App",testID:"clock-reload",onPress:s},"reload"):null,e(F,{label:"Use Real Time",accessibilityLabel:"Reset to real time",testID:"clock-reset",destructive:true,disabled:t.mode==="real",onPress:()=>g("reset")},"reset")]})}),c(n,{children:[e(A,{children:"Options"}),e(ge,{settings:t.settings,run:g,isPro:h,onUpgrade:b})]}),e(G,{visible:p!==null&&!h,onClose:()=>C(null),featureName:p??void 0})]})}function P({title:t,isPro:o}){return c(n,{style:r.titleRow,children:[e(m,{style:r.rowTitle,children:t}),o?null:e(Y,{})]})}function ae({snapshot:t}){const{virtual:o,real:s}=z(t);const d=oe(t);const l=t.mode!=="real";const a=ne(o-s);const u=t.mode==="frozen"?" \xB7 Frozen":l&&t.rate!==1?` \xB7 ${W(t)}`:"";return c(n,{style:r.hero,children:[e(m,{style:[r.heroTime,l?r.heroTimeActive:null],testID:"clock-hero-time",accessibilityLabel:`App clock ${V(o)}`,children:V(o)}),e(m,{style:r.heroDate,testID:"clock-hero-date",children:ie(o)}),e(n,{testID:"clock-status",accessibilityLabel:`Clock status: ${d.label}${l?`, ${a}`:""}`,children:e(m,{style:[r.heroStatus,l?r.heroStatusActive:null],testID:"clock-offset",children:l?`${a}${u}`:"Real time"})})]})}const E=36e5;const R=24*E;const se=[{ms:E,unit:"hour"},{ms:R,unit:"day"},{ms:7*R,unit:"week"},{ms:30*R,unit:"month"}];function de({run:t}){return e(w,{style:r.jumpBar,children:se.map((o,s)=>c(x,{testID:ce(o.ms),accessibilityRole:"button",accessibilityLabel:`Jump ahead one ${o.unit}`,activeOpacity:.6,onPress:()=>t("shift",{by:o.ms}),style:[r.jump,s>0?r.jumpDivider:null],children:[e(m,{style:r.jumpAmount,children:"+1"}),e(m,{style:r.jumpUnit,children:o.unit})]},o.unit))})}function B({title:t,pro:o,value:s,open:d,onPress:l,testID:a}){return c(x,{testID:a,accessibilityRole:"button",accessibilityLabel:t,accessibilityState:{expanded:d},activeOpacity:.6,onPress:l,style:r.row,children:[e(P,{title:t,isPro:!o}),c(n,{style:r.rowRight,children:[s,e(n,{style:d?r.chevronOpen:null,children:e(_,{size:16,color:i.color.textTertiary})})]})]})}function ue({snapshot:t}){const{virtual:o}=z(t,1e3);return e(m,{style:[r.rowValue,r.tabular],numberOfLines:1,children:le(o,false)})}function F({label:t,onPress:o,testID:s,destructive:d,disabled:l,accessibilityLabel:a}){return e(x,{testID:s,accessibilityRole:"button",accessibilityLabel:a??t,accessibilityState:{disabled:!!l},activeOpacity:.6,disabled:l,onPress:o,style:[r.row,l?r.rowDisabled:null],children:e(m,{style:[r.actionLabel,d?r.actionDestructive:null],children:t})})}const me=Z.filter(t=>["midnight","month-end","year-end"].includes(t.id));function he({snapshot:t,run:o,onDone:s}){const[d,l]=S("");const{virtual:a}=z(t,1e3);const u=()=>d.trim()||N(a);const y=t.mode==="frozen";const h=p=>{o("setTime",{time:p,freeze:y});s()};return c(n,{style:r.editor,children:[c(n,{style:r.inputRow,children:[e(H,{testID:"clock-time-input",accessibilityLabel:"Date and time",value:d,onChangeText:l,placeholder:N(a),placeholderTextColor:i.color.placeholder,autoCapitalize:"none",autoCorrect:false,returnKeyType:"done",onSubmitEditing:()=>h(u()),style:r.input}),e(J,{label:"Set",testID:"clock-time-apply",accessibilityLabel:"Set this time",size:"md",variant:"primary",fullWidth:false,onPress:()=>h(u())})]}),e(m,{style:r.hint,children:"Year-month-day and 24-hour time, or +3d, -2h"}),e(n,{style:r.presets,children:me.map(p=>e(M,{label:p.label,testID:`clock-preset-${p.id}`,onPress:()=>h(p.at(a,te))},p.id))})]})}const U=[{key:"1",label:"Normal"},{key:"10",label:"10\xD7"},{key:"60",label:"1 min/s"},{key:"3600",label:"1 hr/s"}];function W(t){if(t.mode==="real"||t.rate===1)return"Normal";return U.find(o=>Number(o.key)===t.rate)?.label??ee(t.rate)}function pe({snapshot:t,run:o}){const s=t.mode==="real"?"1":String(t.rate);return c(n,{style:r.editor,children:[e(n,{style:r.segmentRow,children:e(K,{tabs:U,activeKey:s,size:"sm",testIDPrefix:"clock-speed",onChange:d=>o("setRate",{rate:Number(d)})})}),e(m,{style:r.hint,children:"Taps, animations and timers keep real speed."})]})}const fe=[{key:"showChip",title:"Show Floating Clock"},{key:"persist",title:"Keep After Reload",pro:true}];function ge({settings:t,run:o,isPro:s,onUpgrade:d}){return e(w,{children:e(v,{children:fe.map(l=>{const a=!!l.pro&&!s;return c(n,{style:r.row,children:[e(P,{title:l.title,isPro:!a}),e(O,{value:a?false:t[l.key],testID:`clock-setting-${l.key}`,accessibilityLabel:l.title,onValueChange:u=>a?d(l.title):o("updateSettings",{[l.key]:u})})]},l.key)})})})}const r=L.create({fill:{flex:1},content:{paddingHorizontal:i.gutter,paddingTop:8,gap:i.groupGap},waiting:{flex:1,alignItems:"center",justifyContent:"center",padding:24},hero:{alignItems:"center",paddingTop:12},heroTime:{color:i.color.text,fontSize:56,fontWeight:"200",fontVariant:["tabular-nums"],letterSpacing:1},heroTimeActive:{color:j},heroDate:{color:i.color.text,fontSize:17,fontWeight:"500",marginTop:2},heroStatus:{color:i.color.textTertiary,fontSize:i.font.caption,fontWeight:"500",marginTop:6},heroStatusActive:{color:i.color.textSecondary},jumpBar:{flexDirection:"row"},jump:{flex:1,alignItems:"center",paddingVertical:12},jumpDivider:{borderLeftWidth:L.hairlineWidth,borderLeftColor:i.color.separator},jumpAmount:{color:j,fontSize:17,fontWeight:"600",fontVariant:["tabular-nums"]},jumpUnit:{color:i.color.textSecondary,fontSize:i.font.caption,marginTop:1},row:{flexDirection:"row",alignItems:"center",justifyContent:"space-between",gap:12,minHeight:50,paddingHorizontal:i.rowPadH,paddingVertical:10},rowDisabled:{opacity:.4},rowTitle:{color:i.color.text,fontSize:i.font.row},titleRow:{flexDirection:"row",alignItems:"center",gap:8,flexShrink:1},rowRight:{flexDirection:"row",alignItems:"center",gap:6,flexShrink:1},rowValue:{color:i.color.textSecondary,fontSize:i.font.row},tabular:{fontVariant:["tabular-nums"]},chevronOpen:{transform:[{rotate:"90deg"}]},actionLabel:{color:i.color.accent,fontSize:i.font.row},actionDestructive:{color:i.color.danger},editor:{paddingHorizontal:i.rowPadH,paddingBottom:14,gap:10},inputRow:{flexDirection:"row",alignItems:"center",gap:8},input:{flex:1,color:i.color.text,fontFamily:Q,fontSize:15,backgroundColor:i.color.bg,borderRadius:i.radius.input,borderWidth:1,borderColor:i.color.border,paddingHorizontal:12,paddingVertical:8},hint:{color:i.color.textTertiary,fontSize:i.font.caption},presets:{flexDirection:"row",flexWrap:"wrap",gap:6},segmentRow:{flexDirection:"row"}});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";import{StyleSheet as T,Text as
|
|
1
|
+
"use strict";import{StyleSheet as T,Text as u,TouchableOpacity as w,View as p}from"react-native";import{ChevronRight as S,NightButton as b,NightCard as R,NightFootnote as A,NightRows as v,NightSectionLabel as D,ProBadge as I,night as r}from"@buoy-gg/shared-ui";import{formatDuration as L}from"../engine/clockMath";import{useLiveClock as m}from"./useLiveClock";import{formatChipTime as z,formatClockTime as $}from"./format";import{jsx as o,jsxs as h}from"react/jsx-runtime";const x=e=>L(Math.abs(e),{signed:false});export function TokenSection({snapshot:e,run:d,openId:c,onToggle:i,isPro:s,onUpgrade:a}){const n=e.tokens;return h(p,{children:[o(D,{children:n.tokens.length>1?"Sign-in tokens":"Sign-in token"}),o(R,{children:h(v,{children:[n.tokens.map((l,f)=>h(p,{children:[o(N,{token:l,snapshot:e,index:f,open:c===l.id,onPress:()=>i(l.id)}),c===l.id?o(E,{token:l,snapshot:e,run:s?d:()=>a("Sign-in token tests"),isPro:s}):null]},l.id)),n.tokens.length===0?o(p,{style:t.row,testID:"clock-token-empty",children:o(u,{style:t.emptyText,children:n.available?"No token seen yet":"Needs the Network tool"})},"empty"):null]})}),o(q,{check:n.check,tokens:n.tokens,snapshot:e,run:d}),n.tokens.length===0?o(A,{children:n.available?"Tokens show up here when the app sends a signed-in request.":"Install @buoy-gg/network so the Clock tool can read the app's tokens."}):null]})}function N({token:e,snapshot:d,index:c,open:i,onPress:s}){const{virtual:a}=m(d,1e3);const n=e.expiresAt!==void 0?e.expiresAt-a:void 0;const l=e.neverExpires?"No expiry":n===void 0?"Unknown":n<=0?"Expired":x(n);const f=n!==void 0&&n<=0?t.valueDanger:n!==void 0&&n<6e4?t.valueWarning:null;return h(w,{testID:`clock-token-${c}`,accessibilityRole:"button",accessibilityLabel:`${e.label} for ${e.host}: ${n!==void 0&&n>0?`expires in ${l}`:l}`,accessibilityState:{expanded:i},activeOpacity:.6,onPress:s,style:t.row,children:[h(p,{style:t.rowText,children:[o(u,{style:t.rowTitle,numberOfLines:1,children:e.label}),o(u,{style:t.rowSubtitle,numberOfLines:1,children:`${e.host} \xB7 ${e.hint??e.formatLabel}`})]}),h(p,{style:t.rowRight,children:[o(u,{style:[t.value,f],testID:`clock-token-${c}-left`,children:l}),o(p,{style:i?t.chevronOpen:null,children:o(S,{size:16,color:r.color.textTertiary})})]})]})}function E({token:e,snapshot:d,run:c,isPro:i}){const{virtual:s,real:a}=m(d,1e3);const n=j(e,s,a);const l=e.expiresAt!==void 0&&e.expiresAt-s>1e4;return h(p,{style:t.detail,testID:"clock-token-detail",children:[n.map(f=>o(u,{style:[t.detailLine,f.tone==="warn"?t.warn:null,f.tone==="bad"?t.bad:null],children:f.text},f.text)),h(p,{style:t.buttons,children:[o(p,{style:t.button,children:o(b,{label:"Jump to Expiry",testID:"clock-token-jump",accessibilityLabel:"Jump the app's clock to ten seconds before this token expires",size:"md",disabled:!l,onPress:()=>c("jumpToTokenExpiry",{token:e.id})})}),o(p,{style:t.button,children:o(b,{label:"Fail Next Request",testID:"clock-token-fail",accessibilityLabel:"Answer the app's next request to this API with 401",size:"md",onPress:()=>c("failNextRequest",{token:e.id})})})]}),i?null:h(p,{style:t.proLine,children:[o(I,{}),o(u,{style:[t.hint,t.proHint],children:"Jump to Expiry and Fail Next Request are part of Buoy Pro."})]}),o(u,{style:t.hint,children:l||e.expiresAt===void 0?"Jump tests an app that refreshes before expiry. Fail tests one that refreshes after a 401.":"This token has already expired on the app's clock. Use Real Time to jump to it again."})]})}function j(e,d,c){const i=[];if(e.expiresAt!==void 0){i.push({text:`Expires ${z(e.expiresAt)}`});if(e.lifetimeMs!==void 0&&e.lifetimeMs>0){i.push({text:`Lasts ${x(e.lifetimeMs)}${e.expirySource?`, from ${e.expirySource}`:""}`})}if(e.serverExpiresAt!==void 0){const s=e.expiresAt-d;const a=e.serverExpiresAt-c;if(Math.abs(s-a)>2e3){i.push({text:a>0?`The server still accepts it for ${x(a)}`:`The server stopped accepting it ${x(a)} ago`})}}}else if(!e.neverExpires){i.push({text:"The token doesn't say when it expires, and no login response did either."})}if(e.hint)i.push({text:e.formatLabel});if(e.issuedBy)i.push({text:`Issued by ${e.issuedBy}`});if(e.refresh?.expiresAt!==void 0){const s=e.refresh.expiresAt-d;i.push({text:s>0?`Refresh token expires in ${x(s)}`:"Refresh token expired"})}if(e.refreshes>0&&e.lastRefreshAt!==void 0){i.push({text:`Refreshed ${e.refreshes===1?"once":`${e.refreshes} times`}, last at ${$(e.lastRefreshAt)}`})}i.push({text:`Sent with ${e.uses} request${e.uses===1?"":"s"}`});if(e.expiredSends>0){i.push({text:`Sent ${e.expiredSends} time${e.expiredSends===1?"":"s"} after it expired on the app's clock`,tone:"warn"})}if(e.rejected>0){i.push({text:`Rejected by the server ${e.rejected} time${e.rejected===1?"":"s"}`,tone:"warn"})}if(e.looping){i.push({text:`Refresh loop: ${e.recentRefreshes} new tokens in 20s`,tone:"bad"})}return i}function q({check:e,tokens:d,snapshot:c,run:i}){const{virtual:s,real:a}=m(c,1e3);if(!e)return null;const n=d.find(g=>g.id===e.tokenId);const{text:l,tone:f}=P(e,n,s,a);return h(p,{style:t.check,children:[o(u,{style:[t.checkText,f==="good"?t.good:null,f==="bad"?t.bad:null,f==="warn"?t.warn:null],testID:"clock-token-check",children:l}),o(w,{testID:"clock-token-check-done",accessibilityRole:"button",accessibilityLabel:e.status==="waiting"?"Stop the refresh check":"Dismiss",onPress:()=>i("stopTokenCheck"),hitSlop:{top:8,bottom:8,left:8,right:8},children:o(u,{style:t.checkDone,children:e.status==="waiting"?"Stop":"Done"})})]})}function P(e,d,c,i){if(e.status==="loop"){return{text:`Refresh loop: ${e.newTokens} new tokens since the check started. The new tokens may already look expired to the app's clock.`,tone:"bad"}}if(e.status==="refreshed"){const l=e.newIssuedBy?` by ${e.newIssuedBy}`:"";const f=e.newLifetimeMs&&e.newLifetimeMs>0?`. The new token lasts ${x(e.newLifetimeMs)}`:"";const g=e.kind==="401"&&e.forcedAt!==void 0?"The app got the 401 and refreshed":"Refreshed";const y=e.failedRefreshes>0?` ${e.failedRefreshes===1?"One token request":`${e.failedRefreshes} token requests`} failed first (${e.lastRefreshError}).`:"";return{text:`${g} at ${$(e.refreshedAt??i)}${l}${f}.${y}`,tone:y?"warn":"good"}}const s=i-e.startedAt;const a=(e.staleAfterFailure>0?` It sent the old token again ${e.staleAfterFailure} time${e.staleAfterFailure===1?"":"s"}.`:"")+(e.failedRefreshes>0?` Its token request failed (${e.lastRefreshError}).`:"");if(s>6e4){return{text:`No new token after ${x(s)}. The app may refresh on its next action, or not at all.${a}`,tone:"warn"}}if(e.kind==="401"){return e.forcedAt===void 0?{text:`The next request to ${d?.host??"the API"} will get a 401. Use the app to send one.`}:{text:`The app got the 401. Waiting for a new token\u2026${a}`,tone:a?"warn":void 0}}const n=d?.expiresAt!==void 0?d.expiresAt-c:void 0;return n!==void 0&&n>0?{text:`Expires in ${x(n)} on the app's clock. Waiting for a new token\u2026`}:{text:"Expired on the app's clock. Waiting for the app's next request\u2026"}}const t=T.create({row:{flexDirection:"row",alignItems:"center",justifyContent:"space-between",gap:12,minHeight:56,paddingHorizontal:r.rowPadH,paddingVertical:10},rowText:{flex:1,minWidth:0},rowTitle:{color:r.color.text,fontSize:r.font.row},rowSubtitle:{color:r.color.textTertiary,fontSize:r.font.caption,marginTop:2},rowRight:{flexDirection:"row",alignItems:"center",gap:6},value:{color:r.color.textSecondary,fontSize:r.font.row,fontVariant:["tabular-nums"]},valueWarning:{color:r.color.warning},valueDanger:{color:r.color.danger},chevronOpen:{transform:[{rotate:"90deg"}]},emptyText:{color:r.color.textSecondary,fontSize:r.font.row},detail:{paddingHorizontal:r.rowPadH,paddingBottom:14,gap:4},detailLine:{color:r.color.textSecondary,fontSize:r.font.caption},buttons:{flexDirection:"row",gap:8,marginTop:8},button:{flex:1},hint:{color:r.color.textTertiary,fontSize:r.font.caption,marginTop:6},proLine:{flexDirection:"row",alignItems:"center",gap:8,marginTop:6},proHint:{marginTop:0,flexShrink:1},check:{flexDirection:"row",alignItems:"flex-start",gap:12,marginTop:8,marginHorizontal:r.labelInset},checkText:{flex:1,color:r.color.textSecondary,fontSize:r.font.caption,lineHeight:18},checkDone:{color:r.color.accent,fontSize:r.font.caption,fontWeight:"600"},good:{color:r.color.accent},warn:{color:r.color.warning},bad:{color:r.color.danger}});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";import{REAL_ANCHOR as l,freezeAt as
|
|
1
|
+
"use strict";import{REAL_ANCHOR as l,freezeAt as b,offsetAt as R,parseDuration as N,parseTime as T,resume as O,shiftBy as J,travelTo as I,virtualAt as c,withRate as P}from"./clockMath";import{RealDate as y,installDatePatches as _,isAnimatedRealClock as E,isDatePatched as F,isIntlPatched as z,realNow as s,setVirtualSource as m,uninstallDatePatches as A}from"./patches";import{countDueWithin as L,fireDueWithin as M,installTimerTracking as S,isTimerTrackingInstalled as Z,summarizeTimers as B}from"./timers";import{DEFAULT_SETTINGS as p,RELOAD_HOLD_MS as H,readSavedAsync as W,readSavedSync as j,writeSaved as g}from"./persistence";import{getTokenReport as G,subscribeTokens as U}from"../tokens/tokenStore";import{isProNow as w}from"@buoy-gg/shared-ui";let e={anchor:l,settings:p,lastJump:null,changedAt:null,hydrated:false};const k=new Set;let f=null;function v(){f=null;k.forEach(t=>t())}U(v);export function subscribeClock(t){k.add(t);return()=>{k.delete(t)}}export function getClockAnchor(){return e.anchor}export function getClockSettings(){return e.settings}export function virtualNow(){return c(e.anchor,s())}export function isClockOverridden(){return e.anchor.mode!=="real"}function V(t){if(t.mode==="real"){m(null);A();return}S();m(n=>c(e.anchor,n));_()}function q(){const t={v:1,anchor:e.settings.persist&&w()?e.anchor:null,settings:e.settings};void g(t)}export function holdForNextReload(){const t=e.settings.persist&&w();const n={v:1,anchor:t?e.anchor:null,settings:e.settings};if(e.settings.persist&&e.anchor.mode!=="real"){n.reload={anchor:e.anchor,at:s()}}return g(n)}function a(t,{save:n=true}={}){e={...e,...t};if(t.anchor)V(e.anchor);if(n)q();v()}function i(t,n=e.lastJump){a({anchor:t,lastJump:n,changedAt:s(),hydrated:true})}const C=t=>y.parse(t);export function setTime(t,n=false){const r=s();const o=c(e.anchor,r);const u=T(t,o,C);const d=u-o;i(I(e.anchor,r,u,n),{byMs:d,firedTimers:0,at:r});return getClockSnapshot()}export function shift(t,n){const r=N(t);const o=s();const u=J(e.anchor,o,r);const d=(n??e.settings.fireTimersOnJump)&&r>0;i(u,{byMs:r,firedTimers:0,at:o});if(d){const x=M(r);if(x>0){a({lastJump:{byMs:r,firedTimers:x,at:o}},{save:false})}}return getClockSnapshot()}export function freeze(t){const n=s();const r=c(e.anchor,n);const o=t===void 0||t===""?r:T(t,r,C);i(b(e.anchor,n,o));return getClockSnapshot()}export function resume(){if(e.anchor.mode==="frozen")i(O(e.anchor,s()));return getClockSnapshot()}export function setRate(t){i(P(e.anchor,s(),Number(t)));return getClockSnapshot()}export function reset(){i(l,null);return getClockSnapshot()}export function updateSettings(t){const n={...e.settings};for(const r of Object.keys(p)){if(typeof t[r]==="boolean")n[r]=t[r]}a({settings:n});return getClockSnapshot()}export function previewJump(t){return t>0?L(t):0}let h=false;function D(t){if(!t){a({hydrated:true},{save:false});return}const n=t.reload?s()-t.reload.at:Infinity;const r=n>=0&&n<H?t.reload?.anchor:void 0;if(t.reload)void g({v:1,anchor:t.anchor,settings:t.settings});const o=t.anchor??r??null;a({settings:t.settings,anchor:o??l,changedAt:o?s():null,hydrated:true},{save:false})}export function bootClock(){if(h)return;h=true;S();const t=j();if(t!==void 0){D(t);return}void W().then(n=>{if(e.changedAt===null)D(n);else a({hydrated:true},{save:false})})}export function isClockBooted(){return h}function K(){try{return Intl.DateTimeFormat().resolvedOptions().timeZone??"unknown"}catch{return"unknown"}}export function getClockSnapshot(){const t=s();const n=c(e.anchor,t);return{mode:e.anchor.mode,active:e.anchor.mode!=="real",rate:e.anchor.rate,virtualNow:n,virtualIso:new y(n).toISOString(),realNow:t,offsetMs:R(e.anchor,t),timeZone:K(),timers:B(),lastJump:e.lastJump,changedAt:e.changedAt,settings:e.settings,hydrated:e.hydrated,tokens:G(),patched:{date:F(),intl:z(),timers:Z(),animatedOnRealClock:E()}}}export function getStableClockSnapshot(){if(!f)f=getClockSnapshot();return f}export function __resetClockStoreForTests(){m(null);A();e={anchor:l,settings:p,lastJump:null,changedAt:null,hydrated:false};h=false;v()}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";import{devToolsStorageKeys as
|
|
1
|
+
"use strict";import{devToolsStorageKeys as a,persistentStorage as s}from"@buoy-gg/shared-ui";import{isAnchor as i}from"./clockMath";export{readSavedSync}from"./readSavedSync";export const DEFAULT_SETTINGS={persist:true,showChip:true,fireTimersOnJump:true};export const RELOAD_HOLD_MS=2*6e4;export const CLOCK_STORAGE_KEY=a.clock.state();export function parseSaved(t){if(!t)return null;try{const e=JSON.parse(t);if(!e||e.v!==1)return null;const r=e.settings??{};const n=e.reload&&i(e.reload.anchor)&&typeof e.reload.at==="number"?{anchor:e.reload.anchor,at:e.reload.at}:void 0;return{v:1,anchor:i(e.anchor)?e.anchor:null,...n?{reload:n}:{},settings:{persist:typeof r.persist==="boolean"?r.persist:DEFAULT_SETTINGS.persist,showChip:typeof r.showChip==="boolean"?r.showChip:DEFAULT_SETTINGS.showChip,fireTimersOnJump:typeof r.fireTimersOnJump==="boolean"?r.fireTimersOnJump:DEFAULT_SETTINGS.fireTimersOnJump}}}catch{return null}}export async function readSavedAsync(){try{return parseSaved(await s.getItem(CLOCK_STORAGE_KEY))}catch{return null}}let o=Promise.resolve();export function writeSaved(t){const e=JSON.stringify(t);o=o.then(()=>s.setItem(CLOCK_STORAGE_KEY,e)).catch(()=>{});return o.then(()=>{})}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";import{realNow as
|
|
1
|
+
"use strict";import{realNow as H}from"./patches";const m=globalThis;const x="__buoyClockTimer";const l=new Map;let T=null;let b={};let g=0;const v=()=>H()+g;function _(n){(T?.setTimeout??setTimeout)(()=>{throw n},0)}function C(n){const t=Number(n);return Number.isFinite(t)&&t>0?t:0}export function isTimerTrackingInstalled(){return T!==null}export function installTimerTracking(){if(T)return true;const{setTimeout:n,clearTimeout:t,setInterval:i,clearInterval:u}=m;if(typeof n!=="function"||typeof t!=="function")return false;if(n[x])return true;b={setTimeout:n,clearTimeout:t,setInterval:i,clearInterval:u};T={setTimeout:n.bind(globalThis),clearTimeout:t.bind(globalThis),setInterval:(typeof i==="function"?i:n).bind(globalThis),clearInterval:(typeof u==="function"?u:t).bind(globalThis)};const r=T;const d=function(e,f,...a){if(typeof e!=="function")return r.setTimeout(e,f,...a);const p=C(f);let c;const y=function(){l.delete(c);return e.apply(this,a)};c=r.setTimeout(y,f);l.set(c,{kind:"timeout",callback:e,args:a,delay:p,due:v()+p,realHandle:c,run:y});return c};const o=function(e,f,...a){if(typeof e!=="function")return r.setInterval(e,f,...a);const p=C(f);let c;const y=function(){const k=l.get(c);if(k)k.due=v()+p;return e.apply(this,a)};c=r.setInterval(y,f);l.set(c,{kind:"interval",callback:e,args:a,delay:p,due:v()+p,realHandle:c,run:y});return c};const s=(e,f)=>{const a=l.get(e);if(!a)return f(e);l.delete(e);return a.kind==="interval"?r.clearInterval(a.realHandle):r.clearTimeout(a.realHandle)};const I=function(e){return s(e,r.clearTimeout)};const h=function(e){return s(e,r.clearInterval)};globalThis.__buoyRealTimers={setTimeout:r.setTimeout,clearTimeout:I,setInterval:r.setInterval,clearInterval:h};for(const e of[d,o,I,h]){Object.defineProperty(e,x,{value:true})}m.setTimeout=d;m.clearTimeout=I;m.setInterval=o;m.clearInterval=h;return true}export function uninstallTimerTracking(){if(!T)return;m.setTimeout=b.setTimeout;m.clearTimeout=b.clearTimeout;m.setInterval=b.setInterval;m.clearInterval=b.clearInterval;T=null;l.clear();g=0;delete globalThis.__buoyRealTimers}export function summarizeTimers(){const n=v();let t=0;let i=0;let u=null;for(const r of l.values()){if(r.kind==="interval")i+=1;else{t+=1;const d=Math.max(0,r.due-n);if(u===null||d<u)u=d}}return{total:t+i,timeouts:t,intervals:i,nextTimeoutInMs:u}}export function countDueWithin(n){const t=v();let i=0;for(const u of l.values())if(u.due-t<=n)i+=1;return i}export function fireDueWithin(n){if(!T||!(n>0))return 0;const t=T;g+=n;const i=v();const u=[...l.entries()].filter(([,o])=>o.due<=i).sort((o,s)=>o[1].due-s[1].due);let r=0;for(const[o,s]of u){if(!l.has(o))continue;if(s.kind==="timeout"){l.delete(o);t.clearTimeout(s.realHandle)}else{s.due=i+s.delay}try{s.callback(...s.args)}catch(I){_(I)}r+=1}const d=v();for(const o of l.values()){if(o.kind!=="timeout")continue;t.clearTimeout(o.realHandle);o.realHandle=t.setTimeout(o.run,Math.max(0,o.due-d))}return r}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";import{createSyncAdapter as
|
|
1
|
+
"use strict";import{createSyncAdapter as f}from"@buoy-gg/shared-ui";import{freeze as m,getClockSnapshot as i,holdForNextReload as c,reset as d,resume as p,setRate as l,setTime as b,shift as h,subscribeClock as k,updateSettings as y}from"../engine/clockStore";import{startTokenWatch as T}from"../tokens/tokenStore";import{failNextRequest as g,jumpToTokenExpiry as N,stopTokenCheck as w}from"../tokens/tokenActions";function o(t){return t&&typeof t==="object"?t:{}}function u(t,...e){for(const r of e){const n=t[r];if(typeof n==="string"||typeof n==="number")return n}return void 0}function s(t,e){const r=t[e];if(typeof r==="boolean")return r;if(r==="true")return true;if(r==="false")return false;return void 0}export const clockSyncAdapter=f({version:1,getSnapshot(){return i()},subscribe(t){return k(t)},actions:{getState(){T();return i()},setTime(t){const e=o(t);const r=u(e,"time","at","date","iso");if(r===void 0){throw new Error('setTime needs `time`: ISO 8601 ("2026-12-31T23:59:50"), epoch ms, or relative ("+1d").')}return b(r,s(e,"freeze")??false)},shift(t){const e=o(t);const r=u(e,"by","ms","duration","delta");if(r===void 0){throw new Error('shift needs `by`: a duration like "+1d", "-2h30m", "90s", or ms.')}return h(r,s(e,"fireTimers"))},freeze(t){return m(u(o(t),"time","at"))},resume(){return p()},setRate(t){const e=o(t);const r=Number(e.rate??e.speed);if(!Number.isFinite(r))throw new Error("setRate needs a numeric `rate` (1 = normal speed).");return l(r)},reset(){return d()},updateSettings(t){const e=o(t);return y({persist:s(e,"persist"),showChip:s(e,"showChip"),fireTimersOnJump:s(e,"fireTimersOnJump")})},jumpToTokenExpiry(t){const e=o(t);const r=typeof e.token==="string"?e.token:typeof e.id==="string"?e.id:void 0;const n=Number(e.leadMs??e.lead??1e4);return N(r,Number.isFinite(n)?n:1e4)},failNextRequest(t){const e=o(t);const r=typeof e.token==="string"?e.token:typeof e.id==="string"?e.id:void 0;const n=Number(e.status??401);const a=Number(e.times??1);return g(r,n,Number.isFinite(a)?a:1)},stopTokenCheck(){return w()},async holdForReload(){await c();return i()}}});
|
|
@@ -1,10 +1,13 @@
|
|
|
1
1
|
import type { ClockSnapshot } from "../engine/clockStore";
|
|
2
2
|
type Run = (action: string, params?: Record<string, unknown>) => void;
|
|
3
|
-
export declare function TokenSection({ snapshot, run, openId, onToggle, }: {
|
|
3
|
+
export declare function TokenSection({ snapshot, run, openId, onToggle, isPro, onUpgrade, }: {
|
|
4
4
|
snapshot: ClockSnapshot;
|
|
5
5
|
run: Run;
|
|
6
6
|
openId: string | null;
|
|
7
7
|
onToggle: (id: string) => void;
|
|
8
|
+
/** Jump to Expiry and Fail Next Request are Pro; the rows stay free. */
|
|
9
|
+
isPro: boolean;
|
|
10
|
+
onUpgrade: (featureName: string) => void;
|
|
8
11
|
}): import("react").JSX.Element;
|
|
9
12
|
export {};
|
|
10
13
|
//# sourceMappingURL=TokenSection.d.ts.map
|
|
@@ -25,6 +25,13 @@ export declare function getClockSettings(): ClockSettings;
|
|
|
25
25
|
/** What the app's clock reads now (real time when no override is on). */
|
|
26
26
|
export declare function virtualNow(): number;
|
|
27
27
|
export declare function isClockOverridden(): boolean;
|
|
28
|
+
/**
|
|
29
|
+
* Keep the changed time through the next reload only. The tool's Reload App
|
|
30
|
+
* button calls this first, so free apps (whose time is not kept after a
|
|
31
|
+
* reload) can still redraw every screen on the new time. A restart without
|
|
32
|
+
* the button goes back to real time. Resolves once the save is written.
|
|
33
|
+
*/
|
|
34
|
+
export declare function holdForNextReload(): Promise<void>;
|
|
28
35
|
export type TimeInput = string | number;
|
|
29
36
|
/** Move the app's clock to a moment. Keeps running unless `freeze`. */
|
|
30
37
|
export declare function setTime(time: TimeInput, freeze?: boolean): ClockSnapshot;
|
|
@@ -23,7 +23,17 @@ export interface SavedClock {
|
|
|
23
23
|
v: 1;
|
|
24
24
|
anchor: ClockAnchor | null;
|
|
25
25
|
settings: ClockSettings;
|
|
26
|
+
/**
|
|
27
|
+
* The time to bring back after one reload from the tool's Reload App
|
|
28
|
+
* button, for apps where `anchor` is not kept (the free plan). Used once.
|
|
29
|
+
*/
|
|
30
|
+
reload?: {
|
|
31
|
+
anchor: ClockAnchor;
|
|
32
|
+
at: number;
|
|
33
|
+
};
|
|
26
34
|
}
|
|
35
|
+
/** A held reload older than this is ignored (the reload never happened). */
|
|
36
|
+
export declare const RELOAD_HOLD_MS: number;
|
|
27
37
|
export declare const CLOCK_STORAGE_KEY: "@react_buoy_clock_state";
|
|
28
38
|
export declare function parseSaved(raw: string | null | undefined): SavedClock | null;
|
|
29
39
|
export declare function readSavedAsync(): Promise<SavedClock | null>;
|
|
@@ -24,6 +24,8 @@ export declare const clockSyncAdapter: import("@buoy-gg/shared-ui").SyncAdapter<
|
|
|
24
24
|
jumpToTokenExpiry(params: Params): ClockSnapshot;
|
|
25
25
|
failNextRequest(params: Params): Promise<ClockSnapshot>;
|
|
26
26
|
stopTokenCheck(): Promise<ClockSnapshot>;
|
|
27
|
+
/** Keep the changed time through the next reload only (Reload App calls it first). */
|
|
28
|
+
holdForReload(): Promise<ClockSnapshot>;
|
|
27
29
|
}>;
|
|
28
30
|
export type ClockAction = keyof NonNullable<typeof clockSyncAdapter.actions>;
|
|
29
31
|
export {};
|
package/lib/web/index.mjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
"use client";var dt=Object.defineProperty;var jr=Object.getOwnPropertyDescriptor;var Lr=Object.getOwnPropertyNames;var Pr=Object.prototype.hasOwnProperty;var Mr=(e,t)=>{for(var r in t)dt(e,r,{get:t[r],enumerable:true})},pt=(e,t,r,n)=>{if(t&&typeof t=="object"||typeof t=="function")for(let o of Lr(t))!Pr.call(e,o)&&o!==r&&dt(e,o,{get:()=>t[o],enumerable:!(n=jr(t,o))||n.enumerable});return e},_r=(e,t,r)=>(pt(e,t,"default"),r&&pt(r,t,"default"));var ht=process.env.NODE_ENV!=="production";typeof window<"u"&&typeof globalThis.global>"u"&&(globalThis.global=globalThis);var mt={};Mr(mt,{AccessibilityInfo:()=>Vr,ActivityIndicator:()=>Pn,Alert:()=>Fn,Animated:()=>yt,AppRegistry:()=>Wr,AppState:()=>Jr,Appearance:()=>Ur,BackHandler:()=>qr,Button:()=>Mn,CheckBox:()=>un,Clipboard:()=>Kr,DeviceEventEmitter:()=>$n,Dimensions:()=>Zr,Easing:()=>Yr,FlatList:()=>fn,I18nManager:()=>Gr,Image:()=>dn,ImageBackground:()=>pn,InteractionManager:()=>Qr,Keyboard:()=>Xr,KeyboardAvoidingView:()=>hn,LayoutAnimation:()=>en,Linking:()=>tn,LogBox:()=>Sn,Modal:()=>jn,NativeEventEmitter:()=>rn,NativeModules:()=>Hr,PanResponder:()=>nn,Picker:()=>mn,PixelRatio:()=>on,Platform:()=>sn,Pressable:()=>Nn,ProgressBar:()=>yn,RefreshControl:()=>gn,SafeAreaView:()=>bn,ScrollView:()=>bt,SectionList:()=>kn,Share:()=>an,StatusBar:()=>xn,StyleSheet:()=>Y,Switch:()=>Ln,Text:()=>g,TextInput:()=>gt,Touchable:()=>vn,TouchableHighlight:()=>En,TouchableNativeFeedback:()=>wn,TouchableOpacity:()=>F,TouchableWithoutFeedback:()=>zn,UIManager:()=>ln,Vibration:()=>cn,View:()=>h,VirtualizedList:()=>An,YellowBox:()=>Tn,findNodeHandle:()=>_n,unstable_createElement:()=>Br,useColorScheme:()=>In,useLocaleContext:()=>Rn,useWindowDimensions:()=>On});_r(mt,Fr);import*as Fr from"react-native-web";import{unstable_createElement as Br,NativeModules as Hr,AccessibilityInfo as Vr,Animated as yt,Appearance as Ur,AppRegistry as Wr,AppState as Jr,BackHandler as qr,Clipboard as Kr,Dimensions as Zr,Easing as Yr,I18nManager as Gr,Keyboard as Xr,InteractionManager as Qr,LayoutAnimation as en,Linking as tn,NativeEventEmitter as rn,PanResponder as nn,PixelRatio as on,Platform as sn,Share as an,StyleSheet as Y,UIManager as ln,Vibration as cn,CheckBox as un,FlatList as fn,Image as dn,ImageBackground as pn,KeyboardAvoidingView as hn,Picker as mn,ProgressBar as yn,RefreshControl as gn,SafeAreaView as bn,SectionList as kn,StatusBar as xn,Touchable as vn,TouchableNativeFeedback as wn,VirtualizedList as An,YellowBox as Tn,LogBox as Sn,DeviceEventEmitter as $n,useColorScheme as In,useLocaleContext as Rn,useWindowDimensions as On}from"react-native-web";import*as O from"react-native-web";import{createElement as Cn,forwardRef as Dn}from"react";function D(e){let t=Dn((n,o)=>{let{accessibilityState:i,accessibilityValue:s,...a}=n;for(let l of["busy","checked","disabled","expanded","selected"])i?.[l]!==void 0&&a[`aria-${l}`]===void 0&&(a[`aria-${l}`]=i[l]);for(let[l,c]of Object.entries({min:"valuemin",max:"valuemax",now:"valuenow",text:"valuetext"}))s?.[l]!==void 0&&a[`aria-${c}`]===void 0&&(a[`aria-${c}`]=s[l]);return Cn(e,{...a,ref:o})}),r=e.State;return r&&Object.assign(t,{State:r}),t.displayName=e.displayName??e.name??"NativeWebView",t}var h=D(O.View),g=D(O.Text),gt=D(O.TextInput),F=D(O.TouchableOpacity),En=D(O.TouchableHighlight),zn=D(O.TouchableWithoutFeedback),Nn=D(O.Pressable),bt=D(O.ScrollView),jn=D(O.Modal),Ln=D(O.Switch),Pn=D(O.ActivityIndicator),Mn=D(O.Button),_n=O.findNodeHandle,Fn={alert(e,t,r,n){if(typeof document>"u")return;let o=document.createElement("dialog");o.dataset.buoyRoot="",o.setAttribute("aria-label",e),o.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 i=document.createElement("h2");if(i.textContent=e,i.style.cssText="font-size:18px;margin:0 0 12px",o.appendChild(i),t){let c=document.createElement("p");c.textContent=t,c.style.cssText="line-height:1.5;white-space:pre-wrap;margin:0 0 20px",o.appendChild(c)}let s=document.createElement("div");s.style.cssText="display:flex;justify-content:flex-end;flex-wrap:wrap;gap:8px";let a=r?.length?r:[{text:"OK"}],l=()=>{o.close?.(),o.remove()};for(let c of a){let u=document.createElement("button");u.type="button",u.textContent=c.text??"OK",u.style.cssText=`padding:9px 14px;border:1px solid #64748b;border-radius:7px;color:white;background:${c.style==="destructive"?"#a52b38":"#283a4d"};cursor:pointer;font:inherit`,u.onclick=()=>{l(),c.onPress?.()},s.appendChild(u)}o.addEventListener("cancel",c=>{c.preventDefault(),n?.cancelable!==false&&(l(),n?.onDismiss?.())}),o.appendChild(s),document.body.appendChild(o),o.showModal?o.showModal():o.setAttribute("open","")}};var Re=Object.freeze({mode:"real",anchorReal:0,anchorVirtual:0,rate:1}),Oe=.1,Ce=86400,Bn=864e13;function L(e,t){return e.mode==="real"?t:e.mode==="frozen"?e.anchorVirtual:e.anchorVirtual+(t-e.anchorReal)*e.rate}function Hn(e,t){return L(e,t)-t}function G(e){if(!Number.isFinite(e)||Math.abs(e)>Bn)throw new RangeError(`Not a valid time: ${e}`);return Math.round(e)}function De(e,t,r,n=false){return{mode:n?"frozen":"running",anchorReal:t,anchorVirtual:G(r),rate:e.mode==="real"?1:e.rate}}function Vn(e,t,r){if(!Number.isFinite(r))throw new RangeError("Jump must be a number of ms");return De(e,t,L(e,t)+r,e.mode==="frozen")}function Un(e,t,r){return De(e,t,r??L(e,t),true)}function Wn(e,t){return e.mode!=="frozen"?e:{...e,mode:"running",anchorReal:t}}function Jn(e,t,r){if(!Number.isFinite(r)||r<Oe||r>Ce)throw new RangeError(`Speed must be between ${Oe}\xD7 and ${Ce}\xD7`);return e.mode==="real"&&r===1?e:{mode:"running",anchorReal:t,anchorVirtual:G(L(e,t)),rate:r}}function qn(e){let t=e;return!!t&&(t.mode==="real"||t.mode==="running"||t.mode==="frozen")&&Number.isFinite(t.anchorReal)&&Number.isFinite(t.anchorVirtual)&&Number.isFinite(t.rate)&&t.rate>=Oe&&t.rate<=Ce}var Kn={ms:1,millisecond:1,milliseconds:1,s:1e3,sec:1e3,secs:1e3,second:1e3,seconds:1e3,m:6e4,min:6e4,mins:6e4,minute:6e4,minutes:6e4,h:36e5,hr:36e5,hrs:36e5,hour:36e5,hours:36e5,d:864e5,day:864e5,days:864e5,w:6048e5,wk:6048e5,week:6048e5,weeks:6048e5,mo:30*864e5,month:30*864e5,months:30*864e5,y:365*864e5,yr:365*864e5,year:365*864e5,years:365*864e5};function Ee(e){if(typeof e=="number"){if(!Number.isFinite(e))throw new RangeError("Duration must be finite");return Math.round(e)}let t=String(e).trim().toLowerCase();if(!t)throw new RangeError("Duration is empty");let r=1;if((t[0]==="+"||t[0]==="-"||t[0]==="\u2212")&&(r=t[0]==="+"?1:-1,t=t.slice(1).trim()),/^\d+(\.\d+)?$/.test(t))return r*Math.round(Number(t));let n=/(\d+(?:\.\d+)?)\s*([a-z]+)/g,o=0,i="",s;for(;s=n.exec(t);){let a=Kn[s[2]];if(a===void 0)throw new RangeError(`Unknown time unit "${s[2]}" in "${e}"`);o+=Number(s[1])*a,i+=s[0]}if(!i||i.replace(/\s/g,"")!==t.replace(/[\s,]/g,""))throw new RangeError(`Could not read "${e}" as a duration. Try "+1d", "-2h30m" or "90s".`);return r*Math.round(o)}function te(e,{signed:t=true}={}){let r=e<0?"\u2212":"+",n=Math.abs(Math.round(e));if(n<1e3)return t&&n>0?`${r}${n}ms`:"0s";let o=[],i=[["y",365*864e5],["d",864e5],["h",36e5],["m",6e4],["s",1e3]];for(let[s,a]of i)if(n>=a&&(o.push(`${Math.floor(n/a)}${s}`),n%=a),o.length===2)break;return`${t?r:""}${o.join(" ")}`}function kt(e,t,r){if(typeof e=="number")return G(e);let n=String(e).trim();if(!n)throw new RangeError("Time is empty");if(/^now$/i.test(n))return t;if(/^[+\-−]/.test(n))return G(t+Ee(n));if(/^\d{11,}$/.test(n))return G(Number(n));let o=n.replace(/^(\d{4}-\d{2}-\d{2})[ ](\d{2}:\d{2})/,"$1T$2"),i=r(o);if(!Number.isFinite(i))throw new RangeError(`Could not read "${e}" as a time. Use ISO 8601 like 2026-12-31T23:59:50, epoch ms, or "+1d".`);return G(i)}var ze=1e4,xt=[{id:"midnight",label:"Before midnight",hint:"23:59:50 tonight",at(e,t){let r=new t(e);return r.setHours(24,0,0,0),r.getTime()-ze}},{id:"month-end",label:"Month end",hint:"last day, 23:59:50",at(e,t){let r=new t(e);return r.setMonth(r.getMonth()+1,1),r.setHours(0,0,0,0),r.getTime()-ze}},{id:"year-end",label:"New Year's Eve",hint:"Dec 31, 23:59:50",at(e,t){let r=new t(e);return r.setFullYear(r.getFullYear()+1,0,1),r.setHours(0,0,0,0),r.getTime()-ze}},{id:"tomorrow-9",label:"Tomorrow 9 AM",hint:"start of a business day",at(e,t){let r=new t(e);return r.setDate(r.getDate()+1),r.setHours(9,0,0,0),r.getTime()}},{id:"leap-day",label:"Leap day",hint:"next Feb 29, 09:00",at(e,t){let r=new t(e).getFullYear();for(;;){let n=r%4===0&&r%100!==0||r%400===0,o=new t(r,1,29,9,0,0,0).getTime();if(n&&o>e)return o;r+=1}}}],ks=[{label:"1m",ms:6e4},{label:"15m",ms:15*6e4},{label:"1h",ms:36e5},{label:"1d",ms:864e5},{label:"7d",ms:7*864e5},{label:"30d",ms:30*864e5},{label:"1y",ms:365*864e5}];function vt(e){return e===3600?"1h/s":e===600?"10m/s":e===60?"1m/s":`${Number.isInteger(e)?e:e.toFixed(1)}\xD7`}var E=globalThis,pe="__buoyClock",A=E.__buoyRealDate??(Date[pe]?Date.__buoyRealDate:Date);E.__buoyRealDate=A;var wt=A.now.bind(A);function T(){return wt()}E.__buoyRealNow=T;var Ne=null,je=0;function he(){let e=wt();return!Ne||je>0?e:Ne(e)}function At(e){Ne=e}function Le(e){je+=1;try{return e()}finally{je-=1}}E.__buoyWithRealClock=Le;function P(...e){let t=new.target;return t?Reflect.construct(A,e.length===0?[he()]:e,t):new A(he()).toString()}P.prototype=A.prototype;Object.defineProperty(P,"name",{value:"Date"});Object.defineProperty(P,"length",{value:7});Object.defineProperty(P,"now",{value:function(){return he()},writable:true,configurable:true});Object.defineProperty(P,"parse",{value:A.parse,writable:true,configurable:true});Object.defineProperty(P,"UTC",{value:A.UTC,writable:true,configurable:true});Object.defineProperty(P,pe,{value:true});Object.defineProperty(P,"__buoyRealDate",{value:A});var re=P,me=false,ye;function Zn(){return me&&E.Date===re}function Yn(){if(E.Date===re){me=true;return}let e=Object.getOwnPropertyDescriptor(E,"Date");Object.defineProperty(E,"Date",{value:re,writable:e?.writable??true,enumerable:e?.enumerable??false,configurable:true}),ye=Object.getOwnPropertyDescriptor(A.prototype,"constructor");try{Object.defineProperty(A.prototype,"constructor",{value:re,writable:true,enumerable:false,configurable:true})}catch{}me=true}function Gn(){if(E.Date===re){let e=Object.getOwnPropertyDescriptor(E,"Date");Object.defineProperty(E,"Date",{value:A,writable:e?.writable??true,enumerable:e?.enumerable??false,configurable:true})}if(ye){try{Object.defineProperty(A.prototype,"constructor",ye)}catch{}ye=void 0}me=false}var ne=[];function Tt(e){return function(t,...r){return e.call(this,t===void 0?he():t,...r)}}function Xn(){if(ne.length)return;let e=E.Intl?.DateTimeFormat?.prototype;if(e)for(let t of["format","formatToParts"]){let r=Object.getOwnPropertyDescriptor(e,t);if(!(!r||!r.configurable))try{if(typeof r.get=="function"){let n=r.get;Object.defineProperty(e,t,{...r,get(){return Tt(n.call(this))}})}else if(typeof r.value=="function")Object.defineProperty(e,t,{...r,value:Tt(r.value)});else continue;ne.push({proto:e,name:t,original:r})}catch{}}}function Qn(){for(let{proto:e,name:t,original:r}of ne)try{Object.defineProperty(e,t,r)}catch{}ne=[]}function eo(){return ne.length>0}function to(){Yn(),Xn()}function ro(){Gn(),Qn()}var Pe=false;function no(e){let t=Object.getPrototypeOf(e);for(;t&&t!==Object.prototype;){if(!Object.prototype.hasOwnProperty.call(t,pe)){for(let r of["start","onUpdate"]){let n=Object.getOwnPropertyDescriptor(t,r);if(n&&typeof n.value=="function"){let o=n.value;t[r]=function(...i){return Le(()=>o.apply(this,i))}}}try{Object.defineProperty(t,pe,{value:true})}catch{return}}t=Object.getPrototypeOf(t)}}function oo(e){if(Pe)return true;try{let t=e;if(typeof t?.Value!="function")return false;let r=Object.getPrototypeOf(new t.Value(0)),n=r?.animate;return typeof n!="function"?false:(r.animate=function(o,...i){return o&&typeof o=="object"&&no(o),n.call(this,o,...i)},Pe=true,true)}catch{return false}}function io(){return Pe}var oe=globalThis,St="__buoyClockTimer",z=new Map,W=null,$t=0,J=()=>T()+$t;function so(e){(W?.setTimeout??setTimeout)(()=>{throw e},0)}function It(e){let t=Number(e);return Number.isFinite(t)&&t>0?t:0}function ao(){return W!==null}function Rt(){if(W)return true;let{setTimeout:e,clearTimeout:t,setInterval:r,clearInterval:n}=oe;if(typeof e!="function"||typeof t!="function")return false;if(e[St])return true;W={setTimeout:e,clearTimeout:t,setInterval:typeof r=="function"?r:e,clearInterval:typeof n=="function"?n:t};let o=W,i=function(u,x,...w){if(typeof u!="function")return o.setTimeout(u,x,...w);let R=It(x),I,j=function(){return z.delete(I),u.apply(this,w)};return I=o.setTimeout(j,x),z.set(I,{kind:"timeout",callback:u,args:w,delay:R,due:J()+R,realHandle:I,run:j}),I},s=function(u,x,...w){if(typeof u!="function")return o.setInterval(u,x,...w);let R=It(x),I,j=function(){let Z=z.get(I);return Z&&(Z.due=J()+R),u.apply(this,w)};return I=o.setInterval(j,x),z.set(I,{kind:"interval",callback:u,args:w,delay:R,due:J()+R,realHandle:I,run:j}),I},a=(u,x)=>{let w=z.get(u);return w?(z.delete(u),w.kind==="interval"?o.clearInterval(w.realHandle):o.clearTimeout(w.realHandle)):x(u)},l=function(u){return a(u,o.clearTimeout)},c=function(u){return a(u,o.clearInterval)};globalThis.__buoyRealTimers={setTimeout:o.setTimeout,clearTimeout:l,setInterval:o.setInterval,clearInterval:c};for(let u of[i,s,l,c])Object.defineProperty(u,St,{value:true});return oe.setTimeout=i,oe.clearTimeout=l,oe.setInterval=s,oe.clearInterval=c,true}function lo(){let e=J(),t=0,r=0,n=null;for(let o of z.values())if(o.kind==="interval")r+=1;else{t+=1;let i=Math.max(0,o.due-e);(n===null||i<n)&&(n=i)}return{total:t+r,timeouts:t,intervals:r,nextTimeoutInMs:n}}function co(e){let t=J(),r=0;for(let n of z.values())n.due-t<=e&&(r+=1);return r}function uo(e){if(!W||!(e>0))return 0;let t=W;$t+=e;let r=J(),n=[...z.entries()].filter(([,s])=>s.due<=r).sort((s,a)=>s[1].due-a[1].due),o=0;for(let[s,a]of n)if(z.has(s)){a.kind==="timeout"?(z.delete(s),t.clearTimeout(a.realHandle)):a.due=r+a.delay;try{a.callback(...a.args)}catch(l){so(l)}o+=1}let i=J();for(let s of z.values())s.kind==="timeout"&&(t.clearTimeout(s.realHandle),s.realHandle=t.setTimeout(s.run,Math.max(0,s.due-i)));return o}import{devToolsStorageKeys as fo,persistentStorage as Ot}from"@buoy-gg/shared-ui/web";var ie={persist:true,showChip:true,fireTimersOnJump:true},Ct=fo.clock.state();function po(e){if(!e)return null;try{let t=JSON.parse(e);if(!t||t.v!==1)return null;let r=t.settings??{};return{v:1,anchor:qn(t.anchor)?t.anchor:null,settings:{persist:typeof r.persist=="boolean"?r.persist:ie.persist,showChip:typeof r.showChip=="boolean"?r.showChip:ie.showChip,fireTimersOnJump:typeof r.fireTimersOnJump=="boolean"?r.fireTimersOnJump:ie.fireTimersOnJump}}}catch{return null}}async function ho(){try{return po(await Ot.getItem(Ct))}catch{return null}}var Me=Promise.resolve();function mo(e){let t=JSON.stringify(e);return Me=Me.then(()=>Ot.setItem(Ct,t)).catch(()=>{}),Me.then(()=>{})}import{dispatchToolAction as yo}from"@buoy-gg/shared-ui/web";import{loadToolModule as go}from"@buoy-gg/shared-ui/web/utils";var Dt="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/",ge={};for(let e=0;e<Dt.length;e++)ge[Dt[e]]=e;ge["-"]=62;ge._=63;function _e(e){let t=e.replace(/=+$/,""),r=[],n=0,o=0;for(let i=0;i<t.length;i++){let s=ge[t[i]];if(s===void 0)return null;n=n<<6|s,o+=6,o>=8&&(o-=8,r.push(n>>o&255))}return r}function bo(e){let t="";for(let r=0;r<e.length;){let n=e[r],o,i;if(n<128)o=n,i=0;else if(n>=192&&n<224)o=n&31,i=1;else if(n>=224&&n<240)o=n&15,i=2;else if(n>=240&&n<248)o=n&7,i=3;else return null;for(let s=1;s<=i;s++){let a=e[r+s];if(a===void 0||(a&192)!==128)return null;o=o<<6|a&63}t+=String.fromCodePoint(o),r+=i+1}return t}function Fe(e){let t=_e(e);return t?Et(t):null}function Et(e){let t=bo(e);if(!t||t[0]!=="{")return null;try{let r=JSON.parse(t);return r&&typeof r=="object"&&!Array.isArray(r)?r:null}catch{return null}}function Be(e){let t=typeof e=="string"&&e.trim()!==""?Number(e):e;return typeof t=="number"&&Number.isFinite(t)&&t>0?t*1e3:void 0}function se(e,t){if(typeof e=="number"&&Number.isFinite(e)&&e>0)return e<1e11?e*1e3:e;if(typeof e=="string"&&e.trim()!==""){let r=e.trim();if(/^\d+(\.\d+)?$/.test(r))return se(Number(r),t);let n=t(r);return Number.isFinite(n)?n:void 0}}function ko(e){let t=typeof e=="string"&&/^\d+(\.\d+)?$/.test(e.trim())?Number(e):e;return typeof t=="number"&&Number.isFinite(t)&&t>0?t:void 0}var xo=/^[A-Za-z0-9_-]{2,}\.[A-Za-z0-9_-]{2,}\.[A-Za-z0-9_-]*$/,vo=/^[A-Za-z0-9_-]{2,}\.[A-Za-z0-9_-]*\.[A-Za-z0-9_-]*\.[A-Za-z0-9_-]{2,}\.[A-Za-z0-9_-]*$/,zt=/^v([1-4])\.(local|public)\.([A-Za-z0-9_-]+)(?:\.([A-Za-z0-9_-]+))?$/,wo={1:256,2:64,3:96,4:64};function B(e){if(typeof e=="string"&&e)return e;if(Array.isArray(e)){let t=e.filter(r=>typeof r=="string");return t.length?t.join(", "):void 0}}function Ao(e,t){let r=e.iss??"",n=e.use;if(r.includes("securetoken.google.com"))return"Firebase ID token";if(r.includes("firebaseappcheck"))return"Firebase App Check token";if(r.includes("cognito-idp"))return n?`Cognito ${n} token`:"Cognito token";if(r.includes("appleid.apple.com"))return"Sign in with Apple token";if(r.includes("accounts.google.com"))return"Google ID token";if(r.includes(".auth0.com")||r.includes("auth0"))return"Auth0 token";if(r.includes("clerk"))return"Clerk session token";if(r.includes("supabase")||r.includes("/auth/v1"))return"Supabase access token";if(r.includes("okta"))return"Okta token";if(r.includes("/realms/"))return"Keycloak token";if(r.includes("login.microsoftonline.com")||r.includes("sts.windows.net"))return"Microsoft Entra token";let o=typeof t?.typ=="string"?t.typ.toLowerCase():"";if(o==="at+jwt"||o==="application/at+jwt")return"OAuth access token"}function To(e,t){let r={iss:B(e.iss),aud:B(e.aud),sub:B(e.sub),scope:B(e.scope??e.scp),use:B(e.token_use)},n=Be(e.exp);return{claims:r,issuedAt:Be(e.iat),notBefore:Be(e.nbf),expiresAt:n,expirySource:n?t:void 0}}function So(e){let[t,r]=e.split("."),n=Fe(t);if(!n||typeof n.alg!="string"&&typeof n.typ!="string")return null;let o=Fe(r);if(!o)return null;let i=typeof n.alg=="string"?n.alg:void 0,s=To(o,"exp claim");return s.claims.alg=i,!s.claims.use&&typeof n.typ=="string"&&n.typ.toUpperCase()!=="JWT"&&(s.claims.use=n.typ),{format:"jwt",formatLabel:i?`JWT \xB7 ${i}`:"JWT",hint:Ao(s.claims,n),...s}}function $o(e){let t=Fe(e.split(".")[0]);return!t||typeof t.enc!="string"?null:{format:"jwe",formatLabel:"Encrypted JWT",claims:{alg:typeof t.alg=="string"?t.alg:void 0}}}function Io(e,t){let r=zt.exec(e);if(!r)return null;let[,n,o,i]=r;if(o==="local")return{format:"paseto-local",formatLabel:`PASETO v${n} (encrypted)`,claims:{}};let s=_e(i),a=wo[n],l=s&&s.length>a?Et(s.slice(0,s.length-a)):null,c={format:"paseto-public",formatLabel:`PASETO v${n}`,claims:{}};return l&&(c.claims={iss:B(l.iss),aud:B(l.aud),sub:B(l.sub)},c.issuedAt=se(l.iat,t),c.notBefore=se(l.nbf,t),c.expiresAt=se(l.exp,t),c.expiresAt&&(c.expirySource="exp claim")),c}function Ro(e){if(!e.startsWith("gAAAAA")||e.length<76)return null;let t=_e(e);if(!t||t[0]!==128||t.length<73||(t.length-57)%16!==0)return null;let r=0;for(let n=1;n<=8;n++)r=r*256+t[n];return r<978307200||r>4102444800?null:{format:"fernet",formatLabel:"Fernet",claims:{},issuedAt:r*1e3}}var Oo=[{test:/^ya29\./,hint:"Google OAuth access token"},{test:/^gh[opsu]_/,hint:"GitHub token"},{test:/^github_pat_/,hint:"GitHub token"},{test:/^xox[abeprs]-/,hint:"Slack token"},{test:/^EAA[A-Za-z0-9]{40,}/,hint:"Facebook access token"},{test:/^shp(at|ca|pa|ss)_/,hint:"Shopify token"},{test:/^(sk|rk|pk)_(live|test)_/,hint:"Stripe API key",neverExpires:true},{test:/^AIza[0-9A-Za-z_-]{35}$/,hint:"Google API key",neverExpires:true}];function be(e,t=Date.parse){let r=e.trim().replace(/^"(.*)"$/,"$1");if(r.length<16||/\s/.test(r))return null;if(xo.test(r)){let i=So(r);if(i)return i}if(vo.test(r)){let i=$o(r);if(i)return i}if(r.startsWith("v")&&zt.test(r)){let i=Io(r,t);if(i)return i}let n=Ro(r);if(n)return n;let o=Oo.find(i=>i.test.test(r));return{format:"opaque",formatLabel:"Opaque",hint:o?.hint,neverExpires:o?.neverExpires,claims:{}}}function Co(e){return!!e&&e.format!=="opaque"}function H(e){let t=2166136261;for(let r=0;r<e.length;r++)t^=e.charCodeAt(r),t=Math.imul(t,16777619)>>>0;return t.toString(16).padStart(8,"0")}function He(e){let t=/^([a-z][a-z0-9+.-]*:\/\/[^/?#]+)/i.exec(e);return t?t[1].toLowerCase():null}function Do(e){let t=He(e);return t?t.replace(/^[a-z][a-z0-9+.-]*:\/\//,""):"unknown"}function Ve(e){return e.replace(/^[a-z][a-z0-9+.-]*:\/\/[^/?#]+/i,"").split(/[?#]/)[0]||"/"}function Eo(e){let t=e.split("#")[0].split("?")[1];if(!t)return[];let r=[];for(let n of t.split("&")){let o=n.indexOf("=");if(!(o<=0))try{r.push([decodeURIComponent(n.slice(0,o)),decodeURIComponent(n.slice(o+1))])}catch{}}return r}var Ue=/(token|jwt|session|auth|appcheck|api[-_]?key|apikey|credential|bearer)/i,zo=new Set(["authorization","cookie","dpop","idempotency-key","x-request-id","x-correlation-id","www-authenticate","proxy-authenticate","x-csrf-token","x-xsrf-token"]),Nt=new Set(["access_token","accesstoken","id_token","token","auth","auth_token","jwt","session","session_token"]),No=new Set(["bearer","token","jwt","dpop","oauth","firebase"]);function jt(e){let t={};if(!e)return t;for(let[r,n]of Object.entries(e))typeof n=="string"?t[r.toLowerCase()]=n:Array.isArray(n)&&(t[r.toLowerCase()]=n.join(", "));return t}function jo(e){let t=[];for(let r of e.split(";")){let n=r.indexOf("=");n<=0||t.push([r.slice(0,n).trim(),r.slice(n+1).trim()])}return t}function ae(e,t,r){let n=be(e,r);return n&&(Co(n)||n.hint||t)?n:null}function Lt(e,t){let r=[],n=jt(e.requestHeaders),o=n.authorization;if(o){let i=/^(\S+)\s+(\S+)$/.exec(o.trim()),s=i?i[1]:void 0,a=i?i[2]:o.trim();if(!s||No.has(s.toLowerCase())){let l=ae(a,true,t);l&&r.push({location:"authorization",name:"Authorization",scheme:s,fp:H(a),info:l})}}for(let[i,s]of Object.entries(n)){if(zo.has(i)||!Ue.test(i))continue;let a=s.replace(/^bearer\s+/i,""),l=ae(a,true,t);l&&r.push({location:"header",name:i,fp:H(a),info:l})}if(n.cookie)for(let[i,s]of jo(n.cookie)){let a=ae(s,Ue.test(i)||/^(sid|sess)/i.test(i),t);a&&r.push({location:"cookie",name:i,fp:H(s),info:a})}for(let[i,s]of Eo(e.url)){let a=ae(s,Nt.has(i.toLowerCase()),t);a&&Nt.has(i.toLowerCase())&&r.push({location:"query",name:i,fp:H(s),info:a})}return r}var Lo=/^(access_?token|accesstoken|token|jwt|auth_?token|session_?token|sessiontoken)$/i,Pt=/^(id_?token|idtoken)$/i,ke=/^(refresh_?token|refreshtoken)$/i,Po=["expires_in","expiresIn","ExpiresIn","expires","ttl"],Mo=["expires_at","expiresAt","ExpiresAt","expiration","Expiration","expiry","expirationTime","expiration_time","access_token_expires_at","accessTokenExpiresAt","accessTokenExpiry"],_o=["refresh_expires_in","refresh_token_expires_in","refreshTokenExpiresIn","refreshExpiresIn"],Fo=["refresh_expires_at","refreshTokenExpiresAt","refresh_token_expires_at"];function Bo(e){if(typeof e!="string")return e;let t=e.trim();if(!(t.startsWith("{")||t.startsWith("[")))return null;try{return JSON.parse(t)}catch{return null}}function We(e,t,r){if(t>4||!e||typeof e!="object")return;if(Array.isArray(e)){for(let o of e.slice(0,5))We(o,t+1,r);return}let n=e;for(let[o,i]of Object.entries(n))typeof i=="string"&&(Lo.test(o)||Pt.test(o)||ke.test(o))?r.push({key:o,value:i,holder:n}):i&&typeof i=="object"&&We(i,t+1,r)}function Ho(e){return ke.test(e)?"refresh":Pt.test(e)?"id":/session/i.test(e)?"session":"access"}function Mt(e,t,r,n,o){for(let i of t){let s=ko(e[i]);if(s!==void 0)return{expiresAt:n+s*1e3,source:i,lifetimeMs:s*1e3}}for(let i of r){let s=se(e[i],o);if(s!==void 0)return{expiresAt:s,source:i}}return{}}function Vo(e){let t=e["set-cookie"];return t?t.split(/,(?=\s*[A-Za-z0-9!#$%&'*+.^_`|~-]+=)/).map(r=>r.trim()):[]}function Uo(e,t){if(e.status===void 0||e.status>=400)return[];let r=`${e.method.toUpperCase()} ${Ve(e.url)}`,n=e.timestamp+(e.duration??0),o=[],i=Bo(e.responseData);if(i){let a=[];We(i,0,a);let l=new Map;for(let c of a.filter(u=>ke.test(u.key))){let u=be(c.value,t);if(!u)continue;let x=Mt(c.holder,_o,Fo,n,t);l.set(c.holder,{fp:H(c.value),expiresAt:u.expiresAt??x.expiresAt,formatLabel:u.formatLabel})}for(let c of a){if(ke.test(c.key))continue;let u=be(c.value,t);if(!u)continue;let x=Mt(c.holder,Po,Mo,n,t);o.push({fp:H(c.value),info:u,role:Ho(c.key),expiresAt:x.expiresAt,expirySource:x.source,lifetimeMs:x.lifetimeMs,issuedBy:r,refresh:l.get(c.holder)})}}let s=jt(e.responseHeaders);for(let a of Vo(s)){let[l,...c]=a.split(";"),u=l.indexOf("=");if(u<=0)continue;let x=l.slice(0,u).trim(),w=l.slice(u+1).trim(),R=ae(w,Ue.test(x)||/^(sid|sess)/i.test(x),t);if(!R||w===""||w.toLowerCase()==="deleted")continue;let I,j,Z;for(let Er of c){let[zr,...Nr]=Er.split("="),ut=zr.trim().toLowerCase(),Ie=Nr.join("=").trim();if(ut==="max-age"&&/^-?\d+$/.test(Ie))Z=Number(Ie)*1e3,I=n+Z,j="Max-Age";else if(ut==="expires"&&j!=="Max-Age"){let ft=t(Ie);Number.isFinite(ft)&&(I=ft,j="Expires")}}o.push({fp:H(w),info:R,role:"cookie",cookie:x,expiresAt:R.expiresAt??I,expirySource:R.expiresAt?R.expirySource:j,lifetimeMs:R.expiresAt?void 0:Z,issuedBy:r})}return o}var Je=e=>A.parse(e),_t=4,Ft=2e4,Wo=8,Jo=8,qo=200,Ko=1e3,C=new Map,X=new Map,Zo=new Set,Yo=new Set,Bt=new Set,Go=/(token|refresh|oauth|session|auth\/)/i,p=null,xe=true,qe=null,Ke=new Set,Ze=false;function le(){Ze||(Ze=true,Promise.resolve().then(()=>{Ze=false,Ke.forEach(e=>e())}))}function Xo(e){return Ke.add(e),()=>{Ke.delete(e)}}function Ht(e,t){if(e.has(t))return false;if(e.size>=Ko){let r=e.values().next().value;r!==void 0&&e.delete(r)}return e.add(t),true}function Ye(e,t){return`${e}|${t.location}:${t.name.toLowerCase()}`}function Vt(e,t){let r=t?.lifetimeMs!==void 0&&t.expiresAt!==void 0,n=r?t.expiresAt:e.expiresAt??t?.expiresAt,o=e.expiresAt??(r?t.observedReal+t.lifetimeMs:t?.expiresAt),i=r?t.expirySource:e.expiresAt?e.expirySource:t?.expirySource,s=r?t.lifetimeMs:e.expiresAt!==void 0&&e.issuedAt!==void 0?e.expiresAt-e.issuedAt:void 0;return{expiresAt:n,serverExpiresAt:o,source:i,lifetimeMs:s}}function Ge(e,t,r,n,o){let i=X.get(t),s=Vt(r,i),a=e.fp!==t;a&&(e.history.unshift({fp:e.fp,firstSeenReal:e.firstSeenReal,expiresAt:e.expiresAt}),e.history.length=Math.min(e.history.length,Jo),e.fp=t,e.firstSeenReal=n,e.firstSeenApp=o,e.uses=0,e.expiredSends=0,e.rejected=0),e.info=r,e.role=i?.role??(a?void 0:e.role),e.issuedBy=i?.issuedBy??(a?void 0:e.issuedBy),e.refresh=i?.refresh??(a?void 0:e.refresh),e.expiresAt=s.expiresAt,e.serverExpiresAt=s.serverExpiresAt,e.expirySource=s.source,e.lifetimeMs=s.lifetimeMs,a&&Qo(e,n)}function Ut(e,t,r,n,o){let i=X.get(r.fp),s=Vt(r.info,i);return{key:e,origin:t,host:Do(t),location:r.location,name:r.name,scheme:r.scheme,fp:r.fp,info:r.info,role:i?.role,issuedBy:i?.issuedBy,refresh:i?.refresh,expiresAt:s.expiresAt,serverExpiresAt:s.serverExpiresAt,expirySource:s.source,lifetimeMs:s.lifetimeMs,firstSeenReal:n,firstSeenApp:o,lastUsedReal:n,lastUsedApp:o,uses:0,expiredSends:0,rejected:0,history:[]}}function Wt(){if(C.size<=Wo)return;let e=null;for(let t of C.values())(!e||t.lastUsedReal<e.lastUsedReal)&&(e=t);e&&e.key!==p?.tokenId&&C.delete(e.key)}function Qo(e,t){!p||p.tokenId!==e.key||(p.newTokens+=1,p.status==="waiting"&&(p.status="refreshed",p.refreshedAt=t,p.ruleId&&p.forcedAt===void 0&&yo("network","deleteOverrideRule",{id:p.ruleId}).catch(()=>{})),p.newTokens>=_t&&t-(p.refreshedAt??t)<=Ft&&(p.status="loop"))}function ei(e){let t=He(e.url);if(!t)return;let r=Lt(e,Je);if(r.length===0)return;let n=T(),o=e.timestamp;for(let i of r){let s=Ye(t,i),a=C.get(s);a?Ge(a,i.fp,i.info,n,o):(a=Ut(s,t,i,n,o),C.set(s,a),Wt()),a.uses+=1,a.lastUsedReal=n,a.lastUsedApp=o,a.expiresAt!==void 0&&o>=a.expiresAt&&(a.expiredSends+=1),p&&p.tokenId===s&&p.forcedAt!==void 0&&i.fp===p.startFp&&(p.staleAfterFailure+=1)}le()}function ti(e){let t=He(e.url);if(!t)return;let r=T(),n=false;if(e.status===401||e.status===403)for(let i of Lt(e,Je)){let s=C.get(Ye(t,i));s&&s.fp===i.fp&&(s.rejected+=1,n=true)}let o=!!p?.ruleId&&e.override?.ruleId===p.ruleId;if(p&&(e.status??0)>=400&&!o){let i=`${e.method.toUpperCase()} ${Ve(e.url)}`;(Bt.has(i)||e.method.toUpperCase()==="POST"&&Go.test(Ve(e.url)))&&(p.failedRefreshes+=1,p.lastRefreshError=`${e.status} ${i}`,n=true)}p?.ruleId&&e.override?.ruleId===p.ruleId&&p.forcedAt===void 0&&(p.forcedAt=r,n=true);for(let i of Uo(e,Je)){if(Bt.add(i.issuedBy),X.set(i.fp,{...i,observedReal:r}),X.size>qo){let s=X.keys().next().value;s!==void 0&&X.delete(s)}if(n=true,i.cookie){let s={location:"cookie",name:i.cookie,fp:i.fp,info:i.info},a=Ye(t,s),l=C.get(a);l?Ge(l,i.fp,i.info,r,e.timestamp):(C.set(a,Ut(a,t,s,r,e.timestamp)),Wt());continue}for(let s of C.values())s.fp===i.fp&&Ge(s,i.fp,s.info,r,s.lastUsedApp)}n&&le()}function ri(e){let t=e;!t||typeof t.id!="string"||typeof t.url!="string"||(Ht(Zo,t.id)&&ei(t),t.status!==void 0&&Ht(Yo,t.id)&&ti(t))}function ve(){if(qe)return true;try{let{networkEventStore:e}=go("@buoy-gg/network");if(!e?.onEvent)throw new Error("no event store");qe=e.onEvent(ri,true),xe=true}catch{xe=false}return le(),xe}function Jt(e,t,r){let n=C.get(t);if(!n)throw new Error(`No token row "${t}".`);return p={kind:e,tokenId:t,startedAt:T(),startFp:n.fp,ruleId:r,status:"waiting",newTokens:0,staleAfterFailure:0,failedRefreshes:0},le(),p}function ni(){p=null,le()}function oi(e){return e.location==="cookie"?`${e.name} cookie`:e.location==="query"?`${e.name} parameter`:e.location==="header"?`${e.name} header`:e.role==="id"||e.info.claims.use==="id"?"ID token":"Access token"}function ii(e,t){let r=[e.firstSeenReal,...e.history.map(o=>o.firstSeenReal)].slice(0,-1).filter(o=>t-o<=Ft).length,n=e.info.issuedAt;return{id:e.key,label:oi(e),host:e.host,location:e.location,name:e.name,scheme:e.scheme,format:e.info.format,formatLabel:e.info.formatLabel,hint:e.info.hint,claims:e.info.claims,fingerprint:e.fp,issuedAt:n,notBefore:e.info.notBefore,expiresAt:e.expiresAt,serverExpiresAt:e.serverExpiresAt,expirySource:e.expirySource,lifetimeMs:e.lifetimeMs,neverExpires:e.info.neverExpires,issuedBy:e.issuedBy,refresh:e.refresh?{expiresAt:e.refresh.expiresAt,formatLabel:e.refresh.formatLabel}:void 0,firstUsed:e.firstSeenApp,lastUsed:e.lastUsedApp,lastUsedReal:e.lastUsedReal,uses:e.uses,refreshes:e.history.length,lastRefreshAt:e.history.length?e.firstSeenReal:void 0,recentRefreshes:r,looping:r>=_t,expiredSends:e.expiredSends,rejected:e.rejected}}function we(){let e=T(),t=[...C.values()].sort((r,n)=>n.lastUsedReal-r.lastUsedReal).map(r=>ii(r,e));if(p?.status==="refreshed"){let r=C.get(p.tokenId);r&&(p.newLifetimeMs=r.lifetimeMs,p.newIssuedBy=r.issuedBy)}return{available:xe,watching:qe!==null,tokens:t,check:p?{...p}:null}}function si(e){let t=we();return e?t.tokens.find(r=>r.id===e)??null:t.tokens.find(r=>r.expiresAt!==void 0)??t.tokens[0]??null}function ai(e){return C.get(e)?.origin??null}var m={anchor:Re,settings:ie,lastJump:null,changedAt:null,hydrated:false},Xe=new Set,Ae=null;function qt(){Ae=null,Xe.forEach(e=>e())}Xo(qt);function ce(e){return Xe.add(e),()=>{Xe.delete(e)}}function li(){return m.settings}function Kt(){return L(m.anchor,T())}function Zt(){return m.anchor.mode!=="real"}function ci(e){if(e.mode==="real"){At(null),ro();return}Rt(),At(t=>L(m.anchor,t)),to()}function ui(){let e={v:1,anchor:m.settings.persist?m.anchor:null,settings:m.settings};mo(e)}function Q(e,{save:t=true}={}){m={...m,...e},e.anchor&&ci(m.anchor),t&&ui(),qt()}function ee(e,t=m.lastJump){Q({anchor:e,lastJump:t,changedAt:T(),hydrated:true})}var Yt=e=>A.parse(e);function Gt(e,t=false){let r=T(),n=L(m.anchor,r),o=kt(e,n,Yt),i=o-n;return ee(De(m.anchor,r,o,t),{byMs:i,firedTimers:0,at:r}),$()}function Qe(e,t){let r=Ee(e),n=T(),o=Vn(m.anchor,n,r),i=(t??m.settings.fireTimersOnJump)&&r>0;if(ee(o,{byMs:r,firedTimers:0,at:n}),i){let s=uo(r);s>0&&Q({lastJump:{byMs:r,firedTimers:s,at:n}},{save:false})}return $()}function et(e){let t=T(),r=L(m.anchor,t),n=e===void 0||e===""?r:kt(e,r,Yt);return ee(Un(m.anchor,t,n)),$()}function tt(){return m.anchor.mode==="frozen"&&ee(Wn(m.anchor,T())),$()}function Xt(e){return ee(Jn(m.anchor,T(),Number(e))),$()}function rt(){return ee(Re,null),$()}function Qt(e){let t={...m.settings};for(let r of Object.keys(ie))typeof e[r]=="boolean"&&(t[r]=e[r]);return Q({settings:t}),$()}function fi(e){return e>0?co(e):0}var er=false;function tr(e){if(!e){Q({hydrated:true},{save:false});return}Q({settings:e.settings,anchor:e.anchor??Re,changedAt:e.anchor?T():null,hydrated:true},{save:false})}function nt(){if(er)return;er=true,Rt();let e=void 0;if(e!==void 0){tr(e);return}ho().then(t=>{m.changedAt===null?tr(t):Q({hydrated:true},{save:false})})}function di(){try{return Intl.DateTimeFormat().resolvedOptions().timeZone??"unknown"}catch{return"unknown"}}function $(){let e=T(),t=L(m.anchor,e);return{mode:m.anchor.mode,active:m.anchor.mode!=="real",rate:m.anchor.rate,virtualNow:t,virtualIso:new A(t).toISOString(),realNow:e,offsetMs:Hn(m.anchor,e),timeZone:di(),timers:lo(),lastJump:m.lastJump,changedAt:m.changedAt,settings:m.settings,hydrated:m.hydrated,tokens:we(),patched:{date:Zn(),intl:eo(),timers:ao(),animatedOnRealClock:io()}}}function rr(){return Ae||(Ae=$()),Ae}import{useSyncExternalStore as pi}from"react";import{ClockToolIcon as nr,FloatingTool as hi,Pause as mi,Play as yi,X as gi,dismissFloatingTool as bi,getFloatingTools as ki,night as ue,openFloatingTool as or}from"@buoy-gg/shared-ui/web";import{useEffect as xi,useState as vi}from"react";function V(e,t=250){let[,r]=vi(0);xi(()=>{let s=setInterval(()=>r(a=>a+1),t);return()=>clearInterval(s)},[t]);let n=T();if(!e)return{virtual:n,real:n};let o=n-e.realNow,i=e.mode==="real"?1:e.rate;return{virtual:e.mode==="frozen"?e.virtualNow:e.virtualNow+o*i,real:n}}var M=e=>String(e).padStart(2,"0");function fe(e){let t=new A(e);return`${M(t.getHours())}:${M(t.getMinutes())}:${M(t.getSeconds())}`}var wi=["Sun","Mon","Tue","Wed","Thu","Fri","Sat"],ir=["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"];function Ai(e){let t=new A(e);return`${wi[t.getDay()]}, ${ir[t.getMonth()]} ${t.getDate()}, ${t.getFullYear()}`}function Te(e,t=true){let r=new A(e),n=t?fe(e):`${M(r.getHours())}:${M(r.getMinutes())}`;return`${ir[r.getMonth()]} ${r.getDate()} \xB7 ${n}`}function sr(e){let t=new A(e);return`${t.getFullYear()}-${M(t.getMonth()+1)}-${M(t.getDate())} ${M(t.getHours())}:${M(t.getMinutes())}`}function Ti(e){if(Math.abs(e)<1e3)return"matches real time";let t=te(Math.abs(e),{signed:false});return e>0?`${t} ahead of real time`:`${t} behind real time`}function ar(e){return e.mode==="real"?{label:"Real time",tone:"neutral"}:e.mode==="frozen"?{label:"Frozen",tone:"info"}:e.rate!==1?{label:`${vt(e.rate)} speed`,tone:"warning"}:{label:"Overridden",tone:"accent"}}function Si(e){return`clock-jump-${e<0?"minus":"plus"}-${te(Math.abs(e),{signed:false}).replace(/\s/g,"")}`}import{jsx as N,jsxs as ot}from"react/jsx-runtime";var Se="clock-chip",lr={id:Se,render:e=>N(ur,{...e})},$i=()=>ki().some(e=>e.id===Se);function Ii(){or(lr)}var cr=false;function Ri(){if(cr)return;cr=true;let e=false,t=()=>{let r=Zt()&&li().showChip;r&&!e?or(lr):!r&&$i()&&bi(Se),e=r};ce(t),t()}function ur({id:e,revealToken:t}){let r=pi(ce,rr,rr),{virtual:n,real:o}=V(r),i=r.mode==="frozen",s=ar(r),a=n-o,l=`${Math.abs(a)<1e3?"0s":te(a)} \xB7 ${s.label.toLowerCase()}`;return N(hi,{id:e,revealToken:t,variant:"strip",dragFromSurface:true,defaultPlacement:"top",accessibilityLabel:`Move or hide the clock chip. App time ${Te(n)}`,handleAdornment:N(nr,{size:12}),children:ot(h,{style:q.row,children:[N(nr,{size:18}),ot(h,{style:q.text,children:[N(g,{style:q.time,numberOfLines:1,testID:"clock-chip-time",children:Te(n)}),N(g,{style:q.detail,numberOfLines:1,testID:"clock-chip-detail",children:l})]}),ot(F,{testID:i?"clock-chip-resume":"clock-chip-freeze",accessibilityRole:"button",accessibilityLabel:i?"Resume the app clock":"Freeze the app clock",onPress:()=>i?tt():et(),style:q.button,hitSlop:{top:8,bottom:8,left:4,right:4},children:[i?N(yi,{size:16,color:ue.color.accent}):null,i?null:N(mi,{size:16,color:ue.color.text})]}),N(h,{style:q.separator}),N(F,{testID:"clock-chip-reset",accessibilityRole:"button",accessibilityLabel:"Back to real time",onPress:()=>rt(),style:q.button,hitSlop:{top:8,bottom:8,left:4,right:8},children:N(gi,{size:16,color:ue.color.textSecondary})})]})})}var q=Y.create({row:{flexDirection:"row",alignItems:"center",gap:10,paddingLeft:10,paddingRight:4,paddingVertical:6,minWidth:220},text:{flexShrink:1,minWidth:120},time:{color:"#F59E0B",fontSize:14,fontWeight:"600",fontVariant:["tabular-nums"]},detail:{color:ue.color.textSecondary,fontSize:11,fontVariant:["tabular-nums"]},button:{width:32,height:32,alignItems:"center",justifyContent:"center",borderRadius:16},separator:{width:Y.hairlineWidth,height:20,backgroundColor:ue.color.separator}});import{ClockToolIcon as Oi,CLOCK_TOOL_ICON_COLOR as Ci,createToolFactory as Di,defineToolPreset as Ei}from"@buoy-gg/shared-ui/web";import{useEffect as fr,useState as zi}from"react";import{reloadApp as Ni}from"@buoy-gg/shared-ui/web";import{createSyncAdapter as ji}from"@buoy-gg/shared-ui/web";import{dispatchToolAction as dr}from"@buoy-gg/shared-ui/web";var pr="No sign-in token seen yet. Use the app so it sends a signed-in request, then try again. Tokens are read from the Network tool's captured requests.";function hr(e){ve();let t=si(e);if(!t)throw new Error(e?`No token "${e}". Read getState for the current ids.`:pr);return t}function mr(e,t=1e4){let r=hr(e);if(r.expiresAt===void 0)throw new Error(r.neverExpires?`${r.label} for ${r.host} is ${r.hint??"a key"} and never expires.`:`${r.label} for ${r.host} (${r.formatLabel}) has no expiry Buoy can read. Use failNextRequest to test the refresh instead.`);let n=r.expiresAt-Math.max(0,t)-Kt();if(n<=0)throw new Error(`${r.label} for ${r.host} has already expired on the app's clock. Go back to real time, or use failNextRequest.`);return Qe(n),Jt("expiry",r.id),$()}async function yr(e,t=401,r=1){let n=hr(e),o=ai(n.id);if(!o)throw new Error(pr);await gr();let i=t===403?403:401,s=n.location==="authorization"||n.location==="header"?{urlPattern:`${o}/*`,requireHeader:n.name.toLowerCase()}:n.location==="query"?{urlPattern:`${o}/*${n.name}=*`}:{urlPattern:`${o}/*`},a=await dr("network","upsertOverrideRule",{name:"Clock: force a token refresh",...s,kind:"respond",status:i,headers:{"content-type":"application/json","www-authenticate":'Bearer error="invalid_token", error_description="The access token expired"'},body:JSON.stringify({error:"invalid_token",error_description:"The access token expired (forced by Buoy Clock to test token refresh)"}),times:Math.max(1,Math.min(10,Math.round(r)))}).catch(l=>{let c=l instanceof Error?l.message:String(l);throw new Error(c.includes("Unknown tool")?"Failing a request needs the Network tool (@buoy-gg/network).":c)});if(!a?.ok||!a.rule)throw new Error(a?.error??"Network did not add the override.");return Jt("401",n.id,a.rule.id),$()}async function gr(){let e=we().check;e?.ruleId&&e.forcedAt===void 0&&await dr("network","deleteOverrideRule",{id:e.ruleId}).catch(()=>{})}async function br(){return await gr(),ni(),$()}function K(e){return e&&typeof e=="object"?e:{}}function it(e,...t){for(let r of t){let n=e[r];if(typeof n=="string"||typeof n=="number")return n}}function de(e,t){let r=e[t];if(typeof r=="boolean")return r;if(r==="true")return true;if(r==="false")return false}var kr=ji({version:1,getSnapshot(){return $()},subscribe(e){return ce(e)},actions:{getState(){return ve(),$()},setTime(e){let t=K(e),r=it(t,"time","at","date","iso");if(r===void 0)throw new Error('setTime needs `time`: ISO 8601 ("2026-12-31T23:59:50"), epoch ms, or relative ("+1d").');return Gt(r,de(t,"freeze")??false)},shift(e){let t=K(e),r=it(t,"by","ms","duration","delta");if(r===void 0)throw new Error('shift needs `by`: a duration like "+1d", "-2h30m", "90s", or ms.');return Qe(r,de(t,"fireTimers"))},freeze(e){return et(it(K(e),"time","at"))},resume(){return tt()},setRate(e){let t=K(e),r=Number(t.rate??t.speed);if(!Number.isFinite(r))throw new Error("setRate needs a numeric `rate` (1 = normal speed).");return Xt(r)},reset(){return rt()},updateSettings(e){let t=K(e);return Qt({persist:de(t,"persist"),showChip:de(t,"showChip"),fireTimersOnJump:de(t,"fireTimersOnJump")})},jumpToTokenExpiry(e){let t=K(e),r=typeof t.token=="string"?t.token:typeof t.id=="string"?t.id:void 0,n=Number(t.leadMs??t.lead??1e4);return mr(r,Number.isFinite(n)?n:1e4)},failNextRequest(e){let t=K(e),r=typeof t.token=="string"?t.token:typeof t.id=="string"?t.id:void 0,n=Number(t.status??401),o=Number(t.times??1);return yr(r,n,Number.isFinite(o)?o:1)},stopTokenCheck(){return br()}}});import{useState as st}from"react";import{ChevronRight as Li,NightButton as Pi,NightCard as $e,NightChip as Mi,NightFootnote as at,NightRows as lt,NightSectionLabel as xr,NightSegmented as _i,NightSwitch as vr,monoFont as Fi,night as y,useSafeAreaInsets as Bi}from"@buoy-gg/shared-ui/web";import{ChevronRight as Hi,NightButton as wr,NightCard as Vi,NightFootnote as Ui,NightRows as Wi,NightSectionLabel as Ji,night as b}from"@buoy-gg/shared-ui/web";import{jsx as v,jsxs as _}from"react/jsx-runtime";var U=e=>te(Math.abs(e),{signed:false});function qi({snapshot:e,run:t,openId:r,onToggle:n}){let o=e.tokens;return _(h,{children:[v(Ji,{children:o.tokens.length>1?"Sign-in tokens":"Sign-in token"}),v(Vi,{children:_(Wi,{children:[o.tokens.map((i,s)=>_(h,{children:[v(Ki,{token:i,snapshot:e,index:s,open:r===i.id,onPress:()=>n(i.id)}),r===i.id?v(Zi,{token:i,snapshot:e,run:t}):null]},i.id)),o.tokens.length===0?v(h,{style:k.row,testID:"clock-token-empty",children:v(g,{style:k.emptyText,children:o.available?"No token seen yet":"Needs the Network tool"})},"empty"):null]})}),v(Gi,{check:o.check,tokens:o.tokens,snapshot:e,run:t}),o.tokens.length===0?v(Ui,{children:o.available?"Tokens show up here when the app sends a signed-in request.":"Install @buoy-gg/network so the Clock tool can read the app's tokens."}):null]})}function Ki({token:e,snapshot:t,index:r,open:n,onPress:o}){let{virtual:i}=V(t,1e3),s=e.expiresAt!==void 0?e.expiresAt-i:void 0,a=e.neverExpires?"No expiry":s===void 0?"Unknown":s<=0?"Expired":U(s),l=s!==void 0&&s<=0?k.valueDanger:s!==void 0&&s<6e4?k.valueWarning:null;return _(F,{testID:`clock-token-${r}`,accessibilityRole:"button",accessibilityLabel:`${e.label} for ${e.host}: ${s!==void 0&&s>0?`expires in ${a}`:a}`,accessibilityState:{expanded:n},activeOpacity:.6,onPress:o,style:k.row,children:[_(h,{style:k.rowText,children:[v(g,{style:k.rowTitle,numberOfLines:1,children:e.label}),v(g,{style:k.rowSubtitle,numberOfLines:1,children:`${e.host} \xB7 ${e.hint??e.formatLabel}`})]}),_(h,{style:k.rowRight,children:[v(g,{style:[k.value,l],testID:`clock-token-${r}-left`,children:a}),v(h,{style:n?k.chevronOpen:null,children:v(Hi,{size:16,color:b.color.textTertiary})})]})]})}function Zi({token:e,snapshot:t,run:r}){let{virtual:n,real:o}=V(t,1e3),i=Yi(e,n,o),s=e.expiresAt!==void 0&&e.expiresAt-n>1e4;return _(h,{style:k.detail,testID:"clock-token-detail",children:[i.map(a=>v(g,{style:[k.detailLine,a.tone==="warn"?k.warn:null,a.tone==="bad"?k.bad:null],children:a.text},a.text)),_(h,{style:k.buttons,children:[v(h,{style:k.button,children:v(wr,{label:"Jump to Expiry",testID:"clock-token-jump",accessibilityLabel:"Jump the app's clock to ten seconds before this token expires",size:"md",disabled:!s,onPress:()=>r("jumpToTokenExpiry",{token:e.id})})}),v(h,{style:k.button,children:v(wr,{label:"Fail Next Request",testID:"clock-token-fail",accessibilityLabel:"Answer the app's next request to this API with 401",size:"md",onPress:()=>r("failNextRequest",{token:e.id})})})]}),v(g,{style:k.hint,children:s||e.expiresAt===void 0?"Jump tests an app that refreshes before expiry. Fail tests one that refreshes after a 401.":"This token has already expired on the app's clock. Use Real Time to jump to it again."})]})}function Yi(e,t,r){let n=[];if(e.expiresAt!==void 0){if(n.push({text:`Expires ${Te(e.expiresAt)}`}),e.lifetimeMs!==void 0&&e.lifetimeMs>0&&n.push({text:`Lasts ${U(e.lifetimeMs)}${e.expirySource?`, from ${e.expirySource}`:""}`}),e.serverExpiresAt!==void 0){let o=e.expiresAt-t,i=e.serverExpiresAt-r;Math.abs(o-i)>2e3&&n.push({text:i>0?`The server still accepts it for ${U(i)}`:`The server stopped accepting it ${U(i)} ago`})}}else e.neverExpires||n.push({text:"The token doesn't say when it expires, and no login response did either."});if(e.hint&&n.push({text:e.formatLabel}),e.issuedBy&&n.push({text:`Issued by ${e.issuedBy}`}),e.refresh?.expiresAt!==void 0){let o=e.refresh.expiresAt-t;n.push({text:o>0?`Refresh token expires in ${U(o)}`:"Refresh token expired"})}return e.refreshes>0&&e.lastRefreshAt!==void 0&&n.push({text:`Refreshed ${e.refreshes===1?"once":`${e.refreshes} times`}, last at ${fe(e.lastRefreshAt)}`}),n.push({text:`Sent with ${e.uses} request${e.uses===1?"":"s"}`}),e.expiredSends>0&&n.push({text:`Sent ${e.expiredSends} time${e.expiredSends===1?"":"s"} after it expired on the app's clock`,tone:"warn"}),e.rejected>0&&n.push({text:`Rejected by the server ${e.rejected} time${e.rejected===1?"":"s"}`,tone:"warn"}),e.looping&&n.push({text:`Refresh loop: ${e.recentRefreshes} new tokens in 20s`,tone:"bad"}),n}function Gi({check:e,tokens:t,snapshot:r,run:n}){let{virtual:o,real:i}=V(r,1e3);if(!e)return null;let s=t.find(c=>c.id===e.tokenId),{text:a,tone:l}=Xi(e,s,o,i);return _(h,{style:k.check,children:[v(g,{style:[k.checkText,l==="good"?k.good:null,l==="bad"?k.bad:null,l==="warn"?k.warn:null],testID:"clock-token-check",children:a}),v(F,{testID:"clock-token-check-done",accessibilityRole:"button",accessibilityLabel:e.status==="waiting"?"Stop the refresh check":"Dismiss",onPress:()=>n("stopTokenCheck"),hitSlop:{top:8,bottom:8,left:8,right:8},children:v(g,{style:k.checkDone,children:e.status==="waiting"?"Stop":"Done"})})]})}function Xi(e,t,r,n){if(e.status==="loop")return{text:`Refresh loop: ${e.newTokens} new tokens since the check started. The new tokens may already look expired to the app's clock.`,tone:"bad"};if(e.status==="refreshed"){let a=e.newIssuedBy?` by ${e.newIssuedBy}`:"",l=e.newLifetimeMs&&e.newLifetimeMs>0?`. The new token lasts ${U(e.newLifetimeMs)}`:"",c=e.kind==="401"&&e.forcedAt!==void 0?"The app got the 401 and refreshed":"Refreshed",u=e.failedRefreshes>0?` ${e.failedRefreshes===1?"One token request":`${e.failedRefreshes} token requests`} failed first (${e.lastRefreshError}).`:"";return{text:`${c} at ${fe(e.refreshedAt??n)}${a}${l}.${u}`,tone:u?"warn":"good"}}let o=n-e.startedAt,i=(e.staleAfterFailure>0?` It sent the old token again ${e.staleAfterFailure} time${e.staleAfterFailure===1?"":"s"}.`:"")+(e.failedRefreshes>0?` Its token request failed (${e.lastRefreshError}).`:"");if(o>6e4)return{text:`No new token after ${U(o)}. The app may refresh on its next action, or not at all.${i}`,tone:"warn"};if(e.kind==="401")return e.forcedAt===void 0?{text:`The next request to ${t?.host??"the API"} will get a 401. Use the app to send one.`}:{text:`The app got the 401. Waiting for a new token\u2026${i}`,tone:i?"warn":void 0};let s=t?.expiresAt!==void 0?t.expiresAt-r:void 0;return s!==void 0&&s>0?{text:`Expires in ${U(s)} on the app's clock. Waiting for a new token\u2026`}:{text:"Expired on the app's clock. Waiting for the app's next request\u2026"}}var k=Y.create({row:{flexDirection:"row",alignItems:"center",justifyContent:"space-between",gap:12,minHeight:56,paddingHorizontal:b.rowPadH,paddingVertical:10},rowText:{flex:1,minWidth:0},rowTitle:{color:b.color.text,fontSize:b.font.row},rowSubtitle:{color:b.color.textTertiary,fontSize:b.font.caption,marginTop:2},rowRight:{flexDirection:"row",alignItems:"center",gap:6},value:{color:b.color.textSecondary,fontSize:b.font.row,fontVariant:["tabular-nums"]},valueWarning:{color:b.color.warning},valueDanger:{color:b.color.danger},chevronOpen:{transform:[{rotate:"90deg"}]},emptyText:{color:b.color.textSecondary,fontSize:b.font.row},detail:{paddingHorizontal:b.rowPadH,paddingBottom:14,gap:4},detailLine:{color:b.color.textSecondary,fontSize:b.font.caption},buttons:{flexDirection:"row",gap:8,marginTop:8},button:{flex:1},hint:{color:b.color.textTertiary,fontSize:b.font.caption,marginTop:6},check:{flexDirection:"row",alignItems:"flex-start",gap:12,marginTop:8,marginHorizontal:b.labelInset},checkText:{flex:1,color:b.color.textSecondary,fontSize:b.font.caption,lineHeight:18},checkDone:{color:b.color.accent,fontSize:b.font.caption,fontWeight:"600"},good:{color:b.color.accent},warn:{color:b.color.warning},bad:{color:b.color.danger}});import{jsx as f,jsxs as S}from"react/jsx-runtime";var Ar="#F59E0B";function Tr({snapshot:e,onAction:t,onReload:r}){let n=Bi({minBottom:16}),[o,i]=st(null),[s,a]=st(null),l=(u,x)=>{i(null),t(u,x).catch(w=>{i(w instanceof Error?w.message:String(w))})},c=u=>a(x=>x===u?null:u);return e?S(bt,{style:d.fill,contentContainerStyle:[d.content,{paddingBottom:n.bottom}],testID:"clock-scroll",keyboardShouldPersistTaps:"handled",children:[f(Qi,{snapshot:e}),o?f(at,{tone:"danger",centered:true,children:f(g,{testID:"clock-error",children:o})}):null,S(h,{children:[f(xr,{children:"Jump ahead"}),f(ts,{run:l})]}),S(h,{children:[f($e,{children:S(lt,{children:[S(h,{children:[f($r,{title:"Date & Time",testID:"clock-date-row",open:s==="date",onPress:()=>c("date"),value:f(rs,{snapshot:e})}),s==="date"?f(os,{snapshot:e,run:l,onDone:()=>a(null)}):null]},"date"),S(h,{style:d.row,children:[f(g,{style:d.rowTitle,children:"Freeze"}),f(vr,{value:e.mode==="frozen",testID:"clock-freeze",accessibilityLabel:"Freeze the clock",onValueChange:u=>l(u?"freeze":"resume")})]},"freeze"),S(h,{children:[f($r,{title:"Speed",testID:"clock-speed-row",open:s==="speed",onPress:()=>c("speed"),value:f(g,{style:d.rowValue,children:Or(e)})}),s==="speed"?f(is,{snapshot:e,run:l}):null]},"speed")]})}),f(at,{children:"Only this app's clock changes. Screens pick up the new time when they next render, or all at once when you reload."})]}),e.tokens?f(qi,{snapshot:e,run:l,openId:s,onToggle:c}):null,f($e,{children:S(lt,{children:[r?f(Ir,{label:"Reload App",testID:"clock-reload",onPress:r},"reload"):null,f(Ir,{label:"Use Real Time",accessibilityLabel:"Reset to real time",testID:"clock-reset",destructive:true,disabled:e.mode==="real",onPress:()=>l("reset")},"reset")]})}),S(h,{children:[f(xr,{children:"Options"}),f(as,{settings:e.settings,run:l})]})]}):f(h,{style:d.waiting,testID:"clock-waiting",children:f(at,{centered:true,children:"Waiting for the app's clock\u2026"})})}function Qi({snapshot:e}){let{virtual:t,real:r}=V(e),n=ar(e),o=e.mode!=="real",i=Ti(t-r),s=e.mode==="frozen"?" \xB7 Frozen":o&&e.rate!==1?` \xB7 ${Or(e)}`:"";return S(h,{style:d.hero,children:[f(g,{style:[d.heroTime,o?d.heroTimeActive:null],testID:"clock-hero-time",accessibilityLabel:`App clock ${fe(t)}`,children:fe(t)}),f(g,{style:d.heroDate,testID:"clock-hero-date",children:Ai(t)}),f(h,{testID:"clock-status",accessibilityLabel:`Clock status: ${n.label}${o?`, ${i}`:""}`,children:f(g,{style:[d.heroStatus,o?d.heroStatusActive:null],testID:"clock-offset",children:o?`${i}${s}`:"Real time"})})]})}var Sr=36e5,ct=24*Sr,es=[{ms:Sr,unit:"hour"},{ms:ct,unit:"day"},{ms:7*ct,unit:"week"},{ms:30*ct,unit:"month"}];function ts({run:e}){return f($e,{style:d.jumpBar,children:es.map((t,r)=>S(F,{testID:Si(t.ms),accessibilityRole:"button",accessibilityLabel:`Jump ahead one ${t.unit}`,activeOpacity:.6,onPress:()=>e("shift",{by:t.ms}),style:[d.jump,r>0?d.jumpDivider:null],children:[f(g,{style:d.jumpAmount,children:"+1"}),f(g,{style:d.jumpUnit,children:t.unit})]},t.unit))})}function $r({title:e,value:t,open:r,onPress:n,testID:o}){return S(F,{testID:o,accessibilityRole:"button",accessibilityLabel:e,accessibilityState:{expanded:r},activeOpacity:.6,onPress:n,style:d.row,children:[f(g,{style:d.rowTitle,children:e}),S(h,{style:d.rowRight,children:[t,f(h,{style:r?d.chevronOpen:null,children:f(Li,{size:16,color:y.color.textTertiary})})]})]})}function rs({snapshot:e}){let{virtual:t}=V(e,1e3);return f(g,{style:[d.rowValue,d.tabular],numberOfLines:1,children:Te(t,false)})}function Ir({label:e,onPress:t,testID:r,destructive:n,disabled:o,accessibilityLabel:i}){return f(F,{testID:r,accessibilityRole:"button",accessibilityLabel:i??e,accessibilityState:{disabled:!!o},activeOpacity:.6,disabled:o,onPress:t,style:[d.row,o?d.rowDisabled:null],children:f(g,{style:[d.actionLabel,n?d.actionDestructive:null],children:e})})}var ns=xt.filter(e=>["midnight","month-end","year-end"].includes(e.id));function os({snapshot:e,run:t,onDone:r}){let[n,o]=st(""),{virtual:i}=V(e,1e3),s=()=>n.trim()||sr(i),a=e.mode==="frozen",l=c=>{t("setTime",{time:c,freeze:a}),r()};return S(h,{style:d.editor,children:[S(h,{style:d.inputRow,children:[f(gt,{testID:"clock-time-input",accessibilityLabel:"Date and time",value:n,onChangeText:o,placeholder:sr(i),placeholderTextColor:y.color.placeholder,autoCapitalize:"none",autoCorrect:false,returnKeyType:"done",onSubmitEditing:()=>l(s()),style:d.input}),f(Pi,{label:"Set",testID:"clock-time-apply",accessibilityLabel:"Set this time",size:"md",variant:"primary",fullWidth:false,onPress:()=>l(s())})]}),f(g,{style:d.hint,children:"Year-month-day and 24-hour time, or +3d, -2h"}),f(h,{style:d.presets,children:ns.map(c=>f(Mi,{label:c.label,testID:`clock-preset-${c.id}`,onPress:()=>l(c.at(i,A))},c.id))})]})}var Rr=[{key:"1",label:"Normal"},{key:"10",label:"10\xD7"},{key:"60",label:"1 min/s"},{key:"3600",label:"1 hr/s"}];function Or(e){return e.mode==="real"||e.rate===1?"Normal":Rr.find(t=>Number(t.key)===e.rate)?.label??vt(e.rate)}function is({snapshot:e,run:t}){let r=e.mode==="real"?"1":String(e.rate);return S(h,{style:d.editor,children:[f(h,{style:d.segmentRow,children:f(_i,{tabs:Rr,activeKey:r,size:"sm",testIDPrefix:"clock-speed",onChange:n=>t("setRate",{rate:Number(n)})})}),f(g,{style:d.hint,children:"Taps, animations and timers keep real speed."})]})}var ss=[{key:"showChip",title:"Show Floating Clock"},{key:"persist",title:"Keep After Reload"}];function as({settings:e,run:t}){return f($e,{children:f(lt,{children:ss.map(r=>S(h,{style:d.row,children:[f(g,{style:d.rowTitle,children:r.title}),f(vr,{value:e[r.key],testID:`clock-setting-${r.key}`,accessibilityLabel:r.title,onValueChange:n=>t("updateSettings",{[r.key]:n})})]},r.key))})})}var d=Y.create({fill:{flex:1},content:{paddingHorizontal:y.gutter,paddingTop:8,gap:y.groupGap},waiting:{flex:1,alignItems:"center",justifyContent:"center",padding:24},hero:{alignItems:"center",paddingTop:12},heroTime:{color:y.color.text,fontSize:56,fontWeight:"200",fontVariant:["tabular-nums"],letterSpacing:1},heroTimeActive:{color:Ar},heroDate:{color:y.color.text,fontSize:17,fontWeight:"500",marginTop:2},heroStatus:{color:y.color.textTertiary,fontSize:y.font.caption,fontWeight:"500",marginTop:6},heroStatusActive:{color:y.color.textSecondary},jumpBar:{flexDirection:"row"},jump:{flex:1,alignItems:"center",paddingVertical:12},jumpDivider:{borderLeftWidth:Y.hairlineWidth,borderLeftColor:y.color.separator},jumpAmount:{color:Ar,fontSize:17,fontWeight:"600",fontVariant:["tabular-nums"]},jumpUnit:{color:y.color.textSecondary,fontSize:y.font.caption,marginTop:1},row:{flexDirection:"row",alignItems:"center",justifyContent:"space-between",gap:12,minHeight:50,paddingHorizontal:y.rowPadH,paddingVertical:10},rowDisabled:{opacity:.4},rowTitle:{color:y.color.text,fontSize:y.font.row},rowRight:{flexDirection:"row",alignItems:"center",gap:6,flexShrink:1},rowValue:{color:y.color.textSecondary,fontSize:y.font.row},tabular:{fontVariant:["tabular-nums"]},chevronOpen:{transform:[{rotate:"90deg"}]},actionLabel:{color:y.color.accent,fontSize:y.font.row},actionDestructive:{color:y.color.danger},editor:{paddingHorizontal:y.rowPadH,paddingBottom:14,gap:10},inputRow:{flexDirection:"row",alignItems:"center",gap:8},input:{flex:1,color:y.color.text,fontFamily:Fi,fontSize:15,backgroundColor:y.color.bg,borderRadius:y.radius.input,borderWidth:1,borderColor:y.color.border,paddingHorizontal:12,paddingVertical:8},hint:{color:y.color.textTertiary,fontSize:y.font.caption},presets:{flexDirection:"row",flexWrap:"wrap",gap:6},segmentRow:{flexDirection:"row"}});import{jsx as ls}from"react/jsx-runtime";var cs=kr.actions;async function us(e,t){let r=cs[e];if(!r)throw new Error(`Unknown clock action: ${e}`);return r(t)}function fs(){Ni("auto","buoy clock").catch(()=>{})}function Cr(){fr(()=>{nt(),ve()},[]);let[e,t]=zi($);return fr(()=>ce(()=>t($())),[]),ls(Tr,{snapshot:e,onAction:us,onReload:fs})}import{jsx as ds}from"react/jsx-runtime";var Dr=Ei({id:"clock",name:"CLOCK",description:"Travel to any date, freeze or speed up the app's clock",slot:"both",color:Ci,icon:({size:e,color:t})=>ds(Oi,{size:e,color:t}),component:Cr,modal:{subtitle:"override the app's date & time"}}),ps=Di(Dr);import{ClockToolIcon as hs,CLOCK_TOOL_ICON_COLOR as ms}from"@buoy-gg/shared-ui/web";var ys=typeof navigator<"u"&&navigator.product==="ReactNative";ys&&(oo(yt),Ri(),typeof ht<"u"&&ht&&nt());export{Se as CLOCK_CHIP_ID,ms as CLOCK_TOOL_ICON_COLOR,Cr as ClockBody,ur as ClockChip,hs as ClockToolIcon,Tr as ClockToolView,xt as TIME_PRESETS,nt as bootClock,kr as clockSyncAdapter,Dr as clockToolPreset,ps as createClockTool,yr as failNextRequest,te as formatDuration,et as freeze,$ as getClockSnapshot,we as getTokenReport,be as inspectToken,Zt as isClockOverridden,mr as jumpToTokenExpiry,Ii as openClockChip,Ee as parseDuration,fi as previewJump,T as realNow,rt as reset,tt as resume,Xt as setRate,Gt as setTime,Qe as shift,ve as startTokenWatch,br as stopTokenCheck,ce as subscribeClock,H as tokenFingerprint,Qt as updateSettings,V as useLiveClock,Kt as virtualNow,Le as withRealClock};
|
|
1
|
+
"use client";var ht=Object.defineProperty;var Fr=Object.getOwnPropertyDescriptor;var Br=Object.getOwnPropertyNames;var Ur=Object.prototype.hasOwnProperty;var Hr=(e,t)=>{for(var r in t)ht(e,r,{get:t[r],enumerable:true})},mt=(e,t,r,n)=>{if(t&&typeof t=="object"||typeof t=="function")for(let o of Br(t))!Ur.call(e,o)&&o!==r&&ht(e,o,{get:()=>t[o],enumerable:!(n=Fr(t,o))||n.enumerable});return e},Vr=(e,t,r)=>(mt(e,t,"default"),r&&mt(r,t,"default"));var gt=process.env.NODE_ENV!=="production";typeof window<"u"&&typeof globalThis.global>"u"&&(globalThis.global=globalThis);var yt={};Hr(yt,{AccessibilityInfo:()=>Kr,ActivityIndicator:()=>Un,Alert:()=>Wn,Animated:()=>bt,AppRegistry:()=>Yr,AppState:()=>Gr,Appearance:()=>Zr,BackHandler:()=>Xr,Button:()=>Hn,CheckBox:()=>mn,Clipboard:()=>Qr,DeviceEventEmitter:()=>Dn,Dimensions:()=>en,Easing:()=>tn,FlatList:()=>gn,I18nManager:()=>rn,Image:()=>yn,ImageBackground:()=>bn,InteractionManager:()=>on,Keyboard:()=>nn,KeyboardAvoidingView:()=>kn,LayoutAnimation:()=>sn,Linking:()=>an,LogBox:()=>On,Modal:()=>Fn,NativeEventEmitter:()=>ln,NativeModules:()=>qr,PanResponder:()=>cn,Picker:()=>xn,PixelRatio:()=>un,Platform:()=>dn,Pressable:()=>_n,ProgressBar:()=>vn,RefreshControl:()=>wn,SafeAreaView:()=>Tn,ScrollView:()=>xt,SectionList:()=>An,Share:()=>fn,StatusBar:()=>Sn,StyleSheet:()=>Y,Switch:()=>Bn,Text:()=>w,TextInput:()=>kt,Touchable:()=>$n,TouchableHighlight:()=>jn,TouchableNativeFeedback:()=>In,TouchableOpacity:()=>B,TouchableWithoutFeedback:()=>Mn,UIManager:()=>pn,Vibration:()=>hn,View:()=>m,VirtualizedList:()=>Rn,YellowBox:()=>Cn,findNodeHandle:()=>Vn,unstable_createElement:()=>Jr,useColorScheme:()=>Pn,useLocaleContext:()=>En,useWindowDimensions:()=>zn});Vr(yt,Wr);import*as Wr from"react-native-web";import{unstable_createElement as Jr,NativeModules as qr,AccessibilityInfo as Kr,Animated as bt,Appearance as Zr,AppRegistry as Yr,AppState as Gr,BackHandler as Xr,Clipboard as Qr,Dimensions as en,Easing as tn,I18nManager as rn,Keyboard as nn,InteractionManager as on,LayoutAnimation as sn,Linking as an,NativeEventEmitter as ln,PanResponder as cn,PixelRatio as un,Platform as dn,Share as fn,StyleSheet as Y,UIManager as pn,Vibration as hn,CheckBox as mn,FlatList as gn,Image as yn,ImageBackground as bn,KeyboardAvoidingView as kn,Picker as xn,ProgressBar as vn,RefreshControl as wn,SafeAreaView as Tn,SectionList as An,StatusBar as Sn,Touchable as $n,TouchableNativeFeedback as In,VirtualizedList as Rn,YellowBox as Cn,LogBox as On,DeviceEventEmitter as Dn,useColorScheme as Pn,useLocaleContext as En,useWindowDimensions as zn}from"react-native-web";import*as O from"react-native-web";import{createElement as Nn,forwardRef as Ln}from"react";function P(e){let t=Ln((n,o)=>{let{accessibilityState:i,accessibilityValue:s,...a}=n;for(let l of["busy","checked","disabled","expanded","selected"])i?.[l]!==void 0&&a[`aria-${l}`]===void 0&&(a[`aria-${l}`]=i[l]);for(let[l,c]of Object.entries({min:"valuemin",max:"valuemax",now:"valuenow",text:"valuetext"}))s?.[l]!==void 0&&a[`aria-${c}`]===void 0&&(a[`aria-${c}`]=s[l]);return Nn(e,{...a,ref:o})}),r=e.State;return r&&Object.assign(t,{State:r}),t.displayName=e.displayName??e.name??"NativeWebView",t}var m=P(O.View),w=P(O.Text),kt=P(O.TextInput),B=P(O.TouchableOpacity),jn=P(O.TouchableHighlight),Mn=P(O.TouchableWithoutFeedback),_n=P(O.Pressable),xt=P(O.ScrollView),Fn=P(O.Modal),Bn=P(O.Switch),Un=P(O.ActivityIndicator),Hn=P(O.Button),Vn=O.findNodeHandle,Wn={alert(e,t,r,n){if(typeof document>"u")return;let o=document.createElement("dialog");o.dataset.buoyRoot="",o.setAttribute("aria-label",e),o.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 i=document.createElement("h2");if(i.textContent=e,i.style.cssText="font-size:18px;margin:0 0 12px",o.appendChild(i),t){let c=document.createElement("p");c.textContent=t,c.style.cssText="line-height:1.5;white-space:pre-wrap;margin:0 0 20px",o.appendChild(c)}let s=document.createElement("div");s.style.cssText="display:flex;justify-content:flex-end;flex-wrap:wrap;gap:8px";let a=r?.length?r:[{text:"OK"}],l=()=>{o.close?.(),o.remove()};for(let c of a){let d=document.createElement("button");d.type="button",d.textContent=c.text??"OK",d.style.cssText=`padding:9px 14px;border:1px solid #64748b;border-radius:7px;color:white;background:${c.style==="destructive"?"#a52b38":"#283a4d"};cursor:pointer;font:inherit`,d.onclick=()=>{l(),c.onPress?.()},s.appendChild(d)}o.addEventListener("cancel",c=>{c.preventDefault(),n?.cancelable!==false&&(l(),n?.onDismiss?.())}),o.appendChild(s),document.body.appendChild(o),o.showModal?o.showModal():o.setAttribute("open","")}};var Ce=Object.freeze({mode:"real",anchorReal:0,anchorVirtual:0,rate:1}),Oe=.1,De=86400,Jn=864e13;function M(e,t){return e.mode==="real"?t:e.mode==="frozen"?e.anchorVirtual:e.anchorVirtual+(t-e.anchorReal)*e.rate}function qn(e,t){return M(e,t)-t}function G(e){if(!Number.isFinite(e)||Math.abs(e)>Jn)throw new RangeError(`Not a valid time: ${e}`);return Math.round(e)}function Pe(e,t,r,n=false){return{mode:n?"frozen":"running",anchorReal:t,anchorVirtual:G(r),rate:e.mode==="real"?1:e.rate}}function Kn(e,t,r){if(!Number.isFinite(r))throw new RangeError("Jump must be a number of ms");return Pe(e,t,M(e,t)+r,e.mode==="frozen")}function Zn(e,t,r){return Pe(e,t,r??M(e,t),true)}function Yn(e,t){return e.mode!=="frozen"?e:{...e,mode:"running",anchorReal:t}}function Gn(e,t,r){if(!Number.isFinite(r)||r<Oe||r>De)throw new RangeError(`Speed must be between ${Oe}\xD7 and ${De}\xD7`);return e.mode==="real"&&r===1?e:{mode:"running",anchorReal:t,anchorVirtual:G(M(e,t)),rate:r}}function vt(e){let t=e;return!!t&&(t.mode==="real"||t.mode==="running"||t.mode==="frozen")&&Number.isFinite(t.anchorReal)&&Number.isFinite(t.anchorVirtual)&&Number.isFinite(t.rate)&&t.rate>=Oe&&t.rate<=De}var Xn={ms:1,millisecond:1,milliseconds:1,s:1e3,sec:1e3,secs:1e3,second:1e3,seconds:1e3,m:6e4,min:6e4,mins:6e4,minute:6e4,minutes:6e4,h:36e5,hr:36e5,hrs:36e5,hour:36e5,hours:36e5,d:864e5,day:864e5,days:864e5,w:6048e5,wk:6048e5,week:6048e5,weeks:6048e5,mo:30*864e5,month:30*864e5,months:30*864e5,y:365*864e5,yr:365*864e5,year:365*864e5,years:365*864e5};function Ee(e){if(typeof e=="number"){if(!Number.isFinite(e))throw new RangeError("Duration must be finite");return Math.round(e)}let t=String(e).trim().toLowerCase();if(!t)throw new RangeError("Duration is empty");let r=1;if((t[0]==="+"||t[0]==="-"||t[0]==="\u2212")&&(r=t[0]==="+"?1:-1,t=t.slice(1).trim()),/^\d+(\.\d+)?$/.test(t))return r*Math.round(Number(t));let n=/(\d+(?:\.\d+)?)\s*([a-z]+)/g,o=0,i="",s;for(;s=n.exec(t);){let a=Xn[s[2]];if(a===void 0)throw new RangeError(`Unknown time unit "${s[2]}" in "${e}"`);o+=Number(s[1])*a,i+=s[0]}if(!i||i.replace(/\s/g,"")!==t.replace(/[\s,]/g,""))throw new RangeError(`Could not read "${e}" as a duration. Try "+1d", "-2h30m" or "90s".`);return r*Math.round(o)}function te(e,{signed:t=true}={}){let r=e<0?"\u2212":"+",n=Math.abs(Math.round(e));if(n<1e3)return t&&n>0?`${r}${n}ms`:"0s";let o=[],i=[["y",365*864e5],["d",864e5],["h",36e5],["m",6e4],["s",1e3]];for(let[s,a]of i)if(n>=a&&(o.push(`${Math.floor(n/a)}${s}`),n%=a),o.length===2)break;return`${t?r:""}${o.join(" ")}`}function wt(e,t,r){if(typeof e=="number")return G(e);let n=String(e).trim();if(!n)throw new RangeError("Time is empty");if(/^now$/i.test(n))return t;if(/^[+\-−]/.test(n))return G(t+Ee(n));if(/^\d{11,}$/.test(n))return G(Number(n));let o=n.replace(/^(\d{4}-\d{2}-\d{2})[ ](\d{2}:\d{2})/,"$1T$2"),i=r(o);if(!Number.isFinite(i))throw new RangeError(`Could not read "${e}" as a time. Use ISO 8601 like 2026-12-31T23:59:50, epoch ms, or "+1d".`);return G(i)}var ze=1e4,Tt=[{id:"midnight",label:"Before midnight",hint:"23:59:50 tonight",at(e,t){let r=new t(e);return r.setHours(24,0,0,0),r.getTime()-ze}},{id:"month-end",label:"Month end",hint:"last day, 23:59:50",at(e,t){let r=new t(e);return r.setMonth(r.getMonth()+1,1),r.setHours(0,0,0,0),r.getTime()-ze}},{id:"year-end",label:"New Year's Eve",hint:"Dec 31, 23:59:50",at(e,t){let r=new t(e);return r.setFullYear(r.getFullYear()+1,0,1),r.setHours(0,0,0,0),r.getTime()-ze}},{id:"tomorrow-9",label:"Tomorrow 9 AM",hint:"start of a business day",at(e,t){let r=new t(e);return r.setDate(r.getDate()+1),r.setHours(9,0,0,0),r.getTime()}},{id:"leap-day",label:"Leap day",hint:"next Feb 29, 09:00",at(e,t){let r=new t(e).getFullYear();for(;;){let n=r%4===0&&r%100!==0||r%400===0,o=new t(r,1,29,9,0,0,0).getTime();if(n&&o>e)return o;r+=1}}}],Cs=[{label:"1m",ms:6e4},{label:"15m",ms:15*6e4},{label:"1h",ms:36e5},{label:"1d",ms:864e5},{label:"7d",ms:7*864e5},{label:"30d",ms:30*864e5},{label:"1y",ms:365*864e5}];function At(e){return e===3600?"1h/s":e===600?"10m/s":e===60?"1m/s":`${Number.isInteger(e)?e:e.toFixed(1)}\xD7`}var E=globalThis,pe="__buoyClock",A=E.__buoyRealDate??(Date[pe]?Date.__buoyRealDate:Date);E.__buoyRealDate=A;var St=A.now.bind(A);function S(){return St()}E.__buoyRealNow=S;var Ne=null,Le=0;function he(){let e=St();return!Ne||Le>0?e:Ne(e)}function $t(e){Ne=e}function je(e){Le+=1;try{return e()}finally{Le-=1}}E.__buoyWithRealClock=je;function _(...e){let t=new.target;return t?Reflect.construct(A,e.length===0?[he()]:e,t):new A(he()).toString()}_.prototype=A.prototype;Object.defineProperty(_,"name",{value:"Date"});Object.defineProperty(_,"length",{value:7});Object.defineProperty(_,"now",{value:function(){return he()},writable:true,configurable:true});Object.defineProperty(_,"parse",{value:A.parse,writable:true,configurable:true});Object.defineProperty(_,"UTC",{value:A.UTC,writable:true,configurable:true});Object.defineProperty(_,pe,{value:true});Object.defineProperty(_,"__buoyRealDate",{value:A});var re=_,me=false,ge;function Qn(){return me&&E.Date===re}function eo(){if(E.Date===re){me=true;return}let e=Object.getOwnPropertyDescriptor(E,"Date");Object.defineProperty(E,"Date",{value:re,writable:e?.writable??true,enumerable:e?.enumerable??false,configurable:true}),ge=Object.getOwnPropertyDescriptor(A.prototype,"constructor");try{Object.defineProperty(A.prototype,"constructor",{value:re,writable:true,enumerable:false,configurable:true})}catch{}me=true}function to(){if(E.Date===re){let e=Object.getOwnPropertyDescriptor(E,"Date");Object.defineProperty(E,"Date",{value:A,writable:e?.writable??true,enumerable:e?.enumerable??false,configurable:true})}if(ge){try{Object.defineProperty(A.prototype,"constructor",ge)}catch{}ge=void 0}me=false}var ne=[];function It(e){return function(t,...r){return e.call(this,t===void 0?he():t,...r)}}function ro(){if(ne.length)return;let e=E.Intl?.DateTimeFormat?.prototype;if(e)for(let t of["format","formatToParts"]){let r=Object.getOwnPropertyDescriptor(e,t);if(!(!r||!r.configurable))try{if(typeof r.get=="function"){let n=r.get;Object.defineProperty(e,t,{...r,get(){return It(n.call(this))}})}else if(typeof r.value=="function")Object.defineProperty(e,t,{...r,value:It(r.value)});else continue;ne.push({proto:e,name:t,original:r})}catch{}}}function no(){for(let{proto:e,name:t,original:r}of ne)try{Object.defineProperty(e,t,r)}catch{}ne=[]}function oo(){return ne.length>0}function io(){eo(),ro()}function so(){to(),no()}var Me=false;function ao(e){let t=Object.getPrototypeOf(e);for(;t&&t!==Object.prototype;){if(!Object.prototype.hasOwnProperty.call(t,pe)){for(let r of["start","onUpdate"]){let n=Object.getOwnPropertyDescriptor(t,r);if(n&&typeof n.value=="function"){let o=n.value;t[r]=function(...i){return je(()=>o.apply(this,i))}}}try{Object.defineProperty(t,pe,{value:true})}catch{return}}t=Object.getPrototypeOf(t)}}function lo(e){if(Me)return true;try{let t=e;if(typeof t?.Value!="function")return false;let r=Object.getPrototypeOf(new t.Value(0)),n=r?.animate;return typeof n!="function"?false:(r.animate=function(o,...i){return o&&typeof o=="object"&&ao(o),n.call(this,o,...i)},Me=true,true)}catch{return false}}function co(){return Me}var oe=globalThis,Rt="__buoyClockTimer",z=new Map,J=null,uo={},Ct=0,q=()=>S()+Ct;function fo(e){(J?.setTimeout??setTimeout)(()=>{throw e},0)}function Ot(e){let t=Number(e);return Number.isFinite(t)&&t>0?t:0}function po(){return J!==null}function Dt(){if(J)return true;let{setTimeout:e,clearTimeout:t,setInterval:r,clearInterval:n}=oe;if(typeof e!="function"||typeof t!="function")return false;if(e[Rt])return true;uo={setTimeout:e,clearTimeout:t,setInterval:r,clearInterval:n},J={setTimeout:e.bind(globalThis),clearTimeout:t.bind(globalThis),setInterval:(typeof r=="function"?r:e).bind(globalThis),clearInterval:(typeof n=="function"?n:t).bind(globalThis)};let o=J,i=function(d,v,...b){if(typeof d!="function")return o.setTimeout(d,v,...b);let I=Ot(v),k,C=function(){return z.delete(k),d.apply(this,b)};return k=o.setTimeout(C,v),z.set(k,{kind:"timeout",callback:d,args:b,delay:I,due:q()+I,realHandle:k,run:C}),k},s=function(d,v,...b){if(typeof d!="function")return o.setInterval(d,v,...b);let I=Ot(v),k,C=function(){let L=z.get(k);return L&&(L.due=q()+I),d.apply(this,b)};return k=o.setInterval(C,v),z.set(k,{kind:"interval",callback:d,args:b,delay:I,due:q()+I,realHandle:k,run:C}),k},a=(d,v)=>{let b=z.get(d);return b?(z.delete(d),b.kind==="interval"?o.clearInterval(b.realHandle):o.clearTimeout(b.realHandle)):v(d)},l=function(d){return a(d,o.clearTimeout)},c=function(d){return a(d,o.clearInterval)};globalThis.__buoyRealTimers={setTimeout:o.setTimeout,clearTimeout:l,setInterval:o.setInterval,clearInterval:c};for(let d of[i,s,l,c])Object.defineProperty(d,Rt,{value:true});return oe.setTimeout=i,oe.clearTimeout=l,oe.setInterval=s,oe.clearInterval=c,true}function ho(){let e=q(),t=0,r=0,n=null;for(let o of z.values())if(o.kind==="interval")r+=1;else{t+=1;let i=Math.max(0,o.due-e);(n===null||i<n)&&(n=i)}return{total:t+r,timeouts:t,intervals:r,nextTimeoutInMs:n}}function mo(e){let t=q(),r=0;for(let n of z.values())n.due-t<=e&&(r+=1);return r}function go(e){if(!J||!(e>0))return 0;let t=J;Ct+=e;let r=q(),n=[...z.entries()].filter(([,s])=>s.due<=r).sort((s,a)=>s[1].due-a[1].due),o=0;for(let[s,a]of n)if(z.has(s)){a.kind==="timeout"?(z.delete(s),t.clearTimeout(a.realHandle)):a.due=r+a.delay;try{a.callback(...a.args)}catch(l){fo(l)}o+=1}let i=q();for(let s of z.values())s.kind==="timeout"&&(t.clearTimeout(s.realHandle),s.realHandle=t.setTimeout(s.run,Math.max(0,s.due-i)));return o}import{devToolsStorageKeys as yo,persistentStorage as Pt}from"@buoy-gg/shared-ui/web";var ie={persist:true,showChip:true,fireTimersOnJump:true},bo=2*6e4,Et=yo.clock.state();function ko(e){if(!e)return null;try{let t=JSON.parse(e);if(!t||t.v!==1)return null;let r=t.settings??{},n=t.reload&&vt(t.reload.anchor)&&typeof t.reload.at=="number"?{anchor:t.reload.anchor,at:t.reload.at}:void 0;return{v:1,anchor:vt(t.anchor)?t.anchor:null,...n?{reload:n}:{},settings:{persist:typeof r.persist=="boolean"?r.persist:ie.persist,showChip:typeof r.showChip=="boolean"?r.showChip:ie.showChip,fireTimersOnJump:typeof r.fireTimersOnJump=="boolean"?r.fireTimersOnJump:ie.fireTimersOnJump}}}catch{return null}}async function xo(){try{return ko(await Pt.getItem(Et))}catch{return null}}var _e=Promise.resolve();function Fe(e){let t=JSON.stringify(e);return _e=_e.then(()=>Pt.setItem(Et,t)).catch(()=>{}),_e.then(()=>{})}import{dispatchToolAction as vo}from"@buoy-gg/shared-ui/web";import{loadToolModule as wo}from"@buoy-gg/shared-ui/web/utils";var zt="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/",ye={};for(let e=0;e<zt.length;e++)ye[zt[e]]=e;ye["-"]=62;ye._=63;function Be(e){let t=e.replace(/=+$/,""),r=[],n=0,o=0;for(let i=0;i<t.length;i++){let s=ye[t[i]];if(s===void 0)return null;n=n<<6|s,o+=6,o>=8&&(o-=8,r.push(n>>o&255))}return r}function To(e){let t="";for(let r=0;r<e.length;){let n=e[r],o,i;if(n<128)o=n,i=0;else if(n>=192&&n<224)o=n&31,i=1;else if(n>=224&&n<240)o=n&15,i=2;else if(n>=240&&n<248)o=n&7,i=3;else return null;for(let s=1;s<=i;s++){let a=e[r+s];if(a===void 0||(a&192)!==128)return null;o=o<<6|a&63}t+=String.fromCodePoint(o),r+=i+1}return t}function Ue(e){let t=Be(e);return t?Nt(t):null}function Nt(e){let t=To(e);if(!t||t[0]!=="{")return null;try{let r=JSON.parse(t);return r&&typeof r=="object"&&!Array.isArray(r)?r:null}catch{return null}}function He(e){let t=typeof e=="string"&&e.trim()!==""?Number(e):e;return typeof t=="number"&&Number.isFinite(t)&&t>0?t*1e3:void 0}function se(e,t){if(typeof e=="number"&&Number.isFinite(e)&&e>0)return e<1e11?e*1e3:e;if(typeof e=="string"&&e.trim()!==""){let r=e.trim();if(/^\d+(\.\d+)?$/.test(r))return se(Number(r),t);let n=t(r);return Number.isFinite(n)?n:void 0}}function Ao(e){let t=typeof e=="string"&&/^\d+(\.\d+)?$/.test(e.trim())?Number(e):e;return typeof t=="number"&&Number.isFinite(t)&&t>0?t:void 0}var So=/^[A-Za-z0-9_-]{2,}\.[A-Za-z0-9_-]{2,}\.[A-Za-z0-9_-]*$/,$o=/^[A-Za-z0-9_-]{2,}\.[A-Za-z0-9_-]*\.[A-Za-z0-9_-]*\.[A-Za-z0-9_-]{2,}\.[A-Za-z0-9_-]*$/,Lt=/^v([1-4])\.(local|public)\.([A-Za-z0-9_-]+)(?:\.([A-Za-z0-9_-]+))?$/,Io={1:256,2:64,3:96,4:64};function U(e){if(typeof e=="string"&&e)return e;if(Array.isArray(e)){let t=e.filter(r=>typeof r=="string");return t.length?t.join(", "):void 0}}function Ro(e,t){let r=e.iss??"",n=e.use;if(r.includes("securetoken.google.com"))return"Firebase ID token";if(r.includes("firebaseappcheck"))return"Firebase App Check token";if(r.includes("cognito-idp"))return n?`Cognito ${n} token`:"Cognito token";if(r.includes("appleid.apple.com"))return"Sign in with Apple token";if(r.includes("accounts.google.com"))return"Google ID token";if(r.includes(".auth0.com")||r.includes("auth0"))return"Auth0 token";if(r.includes("clerk"))return"Clerk session token";if(r.includes("supabase")||r.includes("/auth/v1"))return"Supabase access token";if(r.includes("okta"))return"Okta token";if(r.includes("/realms/"))return"Keycloak token";if(r.includes("login.microsoftonline.com")||r.includes("sts.windows.net"))return"Microsoft Entra token";let o=typeof t?.typ=="string"?t.typ.toLowerCase():"";if(o==="at+jwt"||o==="application/at+jwt")return"OAuth access token"}function Co(e,t){let r={iss:U(e.iss),aud:U(e.aud),sub:U(e.sub),scope:U(e.scope??e.scp),use:U(e.token_use)},n=He(e.exp);return{claims:r,issuedAt:He(e.iat),notBefore:He(e.nbf),expiresAt:n,expirySource:n?t:void 0}}function Oo(e){let[t,r]=e.split("."),n=Ue(t);if(!n||typeof n.alg!="string"&&typeof n.typ!="string")return null;let o=Ue(r);if(!o)return null;let i=typeof n.alg=="string"?n.alg:void 0,s=Co(o,"exp claim");return s.claims.alg=i,!s.claims.use&&typeof n.typ=="string"&&n.typ.toUpperCase()!=="JWT"&&(s.claims.use=n.typ),{format:"jwt",formatLabel:i?`JWT \xB7 ${i}`:"JWT",hint:Ro(s.claims,n),...s}}function Do(e){let t=Ue(e.split(".")[0]);return!t||typeof t.enc!="string"?null:{format:"jwe",formatLabel:"Encrypted JWT",claims:{alg:typeof t.alg=="string"?t.alg:void 0}}}function Po(e,t){let r=Lt.exec(e);if(!r)return null;let[,n,o,i]=r;if(o==="local")return{format:"paseto-local",formatLabel:`PASETO v${n} (encrypted)`,claims:{}};let s=Be(i),a=Io[n],l=s&&s.length>a?Nt(s.slice(0,s.length-a)):null,c={format:"paseto-public",formatLabel:`PASETO v${n}`,claims:{}};return l&&(c.claims={iss:U(l.iss),aud:U(l.aud),sub:U(l.sub)},c.issuedAt=se(l.iat,t),c.notBefore=se(l.nbf,t),c.expiresAt=se(l.exp,t),c.expiresAt&&(c.expirySource="exp claim")),c}function Eo(e){if(!e.startsWith("gAAAAA")||e.length<76)return null;let t=Be(e);if(!t||t[0]!==128||t.length<73||(t.length-57)%16!==0)return null;let r=0;for(let n=1;n<=8;n++)r=r*256+t[n];return r<978307200||r>4102444800?null:{format:"fernet",formatLabel:"Fernet",claims:{},issuedAt:r*1e3}}var zo=[{test:/^ya29\./,hint:"Google OAuth access token"},{test:/^gh[opsu]_/,hint:"GitHub token"},{test:/^github_pat_/,hint:"GitHub token"},{test:/^xox[abeprs]-/,hint:"Slack token"},{test:/^EAA[A-Za-z0-9]{40,}/,hint:"Facebook access token"},{test:/^shp(at|ca|pa|ss)_/,hint:"Shopify token"},{test:/^(sk|rk|pk)_(live|test)_/,hint:"Stripe API key",neverExpires:true},{test:/^AIza[0-9A-Za-z_-]{35}$/,hint:"Google API key",neverExpires:true}];function be(e,t=Date.parse){let r=e.trim().replace(/^"(.*)"$/,"$1");if(r.length<16||/\s/.test(r))return null;if(So.test(r)){let i=Oo(r);if(i)return i}if($o.test(r)){let i=Do(r);if(i)return i}if(r.startsWith("v")&&Lt.test(r)){let i=Po(r,t);if(i)return i}let n=Eo(r);if(n)return n;let o=zo.find(i=>i.test.test(r));return{format:"opaque",formatLabel:"Opaque",hint:o?.hint,neverExpires:o?.neverExpires,claims:{}}}function No(e){return!!e&&e.format!=="opaque"}function H(e){let t=2166136261;for(let r=0;r<e.length;r++)t^=e.charCodeAt(r),t=Math.imul(t,16777619)>>>0;return t.toString(16).padStart(8,"0")}function Ve(e){let t=/^([a-z][a-z0-9+.-]*:\/\/[^/?#]+)/i.exec(e);return t?t[1].toLowerCase():null}function Lo(e){let t=Ve(e);return t?t.replace(/^[a-z][a-z0-9+.-]*:\/\//,""):"unknown"}function We(e){return e.replace(/^[a-z][a-z0-9+.-]*:\/\/[^/?#]+/i,"").split(/[?#]/)[0]||"/"}function jo(e){let t=e.split("#")[0].split("?")[1];if(!t)return[];let r=[];for(let n of t.split("&")){let o=n.indexOf("=");if(!(o<=0))try{r.push([decodeURIComponent(n.slice(0,o)),decodeURIComponent(n.slice(o+1))])}catch{}}return r}var Je=/(token|jwt|session|auth|appcheck|api[-_]?key|apikey|credential|bearer)/i,Mo=new Set(["authorization","cookie","dpop","idempotency-key","x-request-id","x-correlation-id","www-authenticate","proxy-authenticate","x-csrf-token","x-xsrf-token"]),jt=new Set(["access_token","accesstoken","id_token","token","auth","auth_token","jwt","session","session_token"]),_o=new Set(["bearer","token","jwt","dpop","oauth","firebase"]);function Mt(e){let t={};if(!e)return t;for(let[r,n]of Object.entries(e))typeof n=="string"?t[r.toLowerCase()]=n:Array.isArray(n)&&(t[r.toLowerCase()]=n.join(", "));return t}function Fo(e){let t=[];for(let r of e.split(";")){let n=r.indexOf("=");n<=0||t.push([r.slice(0,n).trim(),r.slice(n+1).trim()])}return t}function ae(e,t,r){let n=be(e,r);return n&&(No(n)||n.hint||t)?n:null}function _t(e,t){let r=[],n=Mt(e.requestHeaders),o=n.authorization;if(o){let i=/^(\S+)\s+(\S+)$/.exec(o.trim()),s=i?i[1]:void 0,a=i?i[2]:o.trim();if(!s||_o.has(s.toLowerCase())){let l=ae(a,true,t);l&&r.push({location:"authorization",name:"Authorization",scheme:s,fp:H(a),info:l})}}for(let[i,s]of Object.entries(n)){if(Mo.has(i)||!Je.test(i))continue;let a=s.replace(/^bearer\s+/i,""),l=ae(a,true,t);l&&r.push({location:"header",name:i,fp:H(a),info:l})}if(n.cookie)for(let[i,s]of Fo(n.cookie)){let a=ae(s,Je.test(i)||/^(sid|sess)/i.test(i),t);a&&r.push({location:"cookie",name:i,fp:H(s),info:a})}for(let[i,s]of jo(e.url)){let a=ae(s,jt.has(i.toLowerCase()),t);a&&jt.has(i.toLowerCase())&&r.push({location:"query",name:i,fp:H(s),info:a})}return r}var Bo=/^(access_?token|accesstoken|token|jwt|auth_?token|session_?token|sessiontoken)$/i,Ft=/^(id_?token|idtoken)$/i,ke=/^(refresh_?token|refreshtoken)$/i,Uo=["expires_in","expiresIn","ExpiresIn","expires","ttl"],Ho=["expires_at","expiresAt","ExpiresAt","expiration","Expiration","expiry","expirationTime","expiration_time","access_token_expires_at","accessTokenExpiresAt","accessTokenExpiry"],Vo=["refresh_expires_in","refresh_token_expires_in","refreshTokenExpiresIn","refreshExpiresIn"],Wo=["refresh_expires_at","refreshTokenExpiresAt","refresh_token_expires_at"];function Jo(e){if(typeof e!="string")return e;let t=e.trim();if(!(t.startsWith("{")||t.startsWith("[")))return null;try{return JSON.parse(t)}catch{return null}}function qe(e,t,r){if(t>4||!e||typeof e!="object")return;if(Array.isArray(e)){for(let o of e.slice(0,5))qe(o,t+1,r);return}let n=e;for(let[o,i]of Object.entries(n))typeof i=="string"&&(Bo.test(o)||Ft.test(o)||ke.test(o))?r.push({key:o,value:i,holder:n}):i&&typeof i=="object"&&qe(i,t+1,r)}function qo(e){return ke.test(e)?"refresh":Ft.test(e)?"id":/session/i.test(e)?"session":"access"}function Bt(e,t,r,n,o){for(let i of t){let s=Ao(e[i]);if(s!==void 0)return{expiresAt:n+s*1e3,source:i,lifetimeMs:s*1e3}}for(let i of r){let s=se(e[i],o);if(s!==void 0)return{expiresAt:s,source:i}}return{}}function Ko(e){let t=e["set-cookie"];return t?t.split(/,(?=\s*[A-Za-z0-9!#$%&'*+.^_`|~-]+=)/).map(r=>r.trim()):[]}function Zo(e,t){if(e.status===void 0||e.status>=400)return[];let r=`${e.method.toUpperCase()} ${We(e.url)}`,n=e.timestamp+(e.duration??0),o=[],i=Jo(e.responseData);if(i){let a=[];qe(i,0,a);let l=new Map;for(let c of a.filter(d=>ke.test(d.key))){let d=be(c.value,t);if(!d)continue;let v=Bt(c.holder,Vo,Wo,n,t);l.set(c.holder,{fp:H(c.value),expiresAt:d.expiresAt??v.expiresAt,formatLabel:d.formatLabel})}for(let c of a){if(ke.test(c.key))continue;let d=be(c.value,t);if(!d)continue;let v=Bt(c.holder,Uo,Ho,n,t);o.push({fp:H(c.value),info:d,role:qo(c.key),expiresAt:v.expiresAt,expirySource:v.source,lifetimeMs:v.lifetimeMs,issuedBy:r,refresh:l.get(c.holder)})}}let s=Mt(e.responseHeaders);for(let a of Ko(s)){let[l,...c]=a.split(";"),d=l.indexOf("=");if(d<=0)continue;let v=l.slice(0,d).trim(),b=l.slice(d+1).trim(),I=ae(b,Je.test(v)||/^(sid|sess)/i.test(v),t);if(!I||b===""||b.toLowerCase()==="deleted")continue;let k,C,L;for(let jr of c){let[Mr,..._r]=jr.split("="),ft=Mr.trim().toLowerCase(),Re=_r.join("=").trim();if(ft==="max-age"&&/^-?\d+$/.test(Re))L=Number(Re)*1e3,k=n+L,C="Max-Age";else if(ft==="expires"&&C!=="Max-Age"){let pt=t(Re);Number.isFinite(pt)&&(k=pt,C="Expires")}}o.push({fp:H(b),info:I,role:"cookie",cookie:v,expiresAt:I.expiresAt??k,expirySource:I.expiresAt?I.expirySource:C,lifetimeMs:I.expiresAt?void 0:L,issuedBy:r})}return o}var Ke=e=>A.parse(e),Ut=4,Ht=2e4,Yo=8,Go=8,Xo=200,Qo=1e3,D=new Map,X=new Map,ei=new Set,ti=new Set,Vt=new Set,ri=/(token|refresh|oauth|session|auth\/)/i,p=null,xe=true,Ze=null,Ye=new Set,Ge=false;function le(){Ge||(Ge=true,Promise.resolve().then(()=>{Ge=false,Ye.forEach(e=>e())}))}function ni(e){return Ye.add(e),()=>{Ye.delete(e)}}function Wt(e,t){if(e.has(t))return false;if(e.size>=Qo){let r=e.values().next().value;r!==void 0&&e.delete(r)}return e.add(t),true}function Xe(e,t){return`${e}|${t.location}:${t.name.toLowerCase()}`}function Jt(e,t){let r=t?.lifetimeMs!==void 0&&t.expiresAt!==void 0,n=r?t.expiresAt:e.expiresAt??t?.expiresAt,o=e.expiresAt??(r?t.observedReal+t.lifetimeMs:t?.expiresAt),i=r?t.expirySource:e.expiresAt?e.expirySource:t?.expirySource,s=r?t.lifetimeMs:e.expiresAt!==void 0&&e.issuedAt!==void 0?e.expiresAt-e.issuedAt:void 0;return{expiresAt:n,serverExpiresAt:o,source:i,lifetimeMs:s}}function Qe(e,t,r,n,o){let i=X.get(t),s=Jt(r,i),a=e.fp!==t;a&&(e.history.unshift({fp:e.fp,firstSeenReal:e.firstSeenReal,expiresAt:e.expiresAt}),e.history.length=Math.min(e.history.length,Go),e.fp=t,e.firstSeenReal=n,e.firstSeenApp=o,e.uses=0,e.expiredSends=0,e.rejected=0),e.info=r,e.role=i?.role??(a?void 0:e.role),e.issuedBy=i?.issuedBy??(a?void 0:e.issuedBy),e.refresh=i?.refresh??(a?void 0:e.refresh),e.expiresAt=s.expiresAt,e.serverExpiresAt=s.serverExpiresAt,e.expirySource=s.source,e.lifetimeMs=s.lifetimeMs,a&&oi(e,n)}function qt(e,t,r,n,o){let i=X.get(r.fp),s=Jt(r.info,i);return{key:e,origin:t,host:Lo(t),location:r.location,name:r.name,scheme:r.scheme,fp:r.fp,info:r.info,role:i?.role,issuedBy:i?.issuedBy,refresh:i?.refresh,expiresAt:s.expiresAt,serverExpiresAt:s.serverExpiresAt,expirySource:s.source,lifetimeMs:s.lifetimeMs,firstSeenReal:n,firstSeenApp:o,lastUsedReal:n,lastUsedApp:o,uses:0,expiredSends:0,rejected:0,history:[]}}function Kt(){if(D.size<=Yo)return;let e=null;for(let t of D.values())(!e||t.lastUsedReal<e.lastUsedReal)&&(e=t);e&&e.key!==p?.tokenId&&D.delete(e.key)}function oi(e,t){!p||p.tokenId!==e.key||(p.newTokens+=1,p.status==="waiting"&&(p.status="refreshed",p.refreshedAt=t,p.ruleId&&p.forcedAt===void 0&&vo("network","deleteOverrideRule",{id:p.ruleId}).catch(()=>{})),p.newTokens>=Ut&&t-(p.refreshedAt??t)<=Ht&&(p.status="loop"))}function ii(e){let t=Ve(e.url);if(!t)return;let r=_t(e,Ke);if(r.length===0)return;let n=S(),o=e.timestamp;for(let i of r){let s=Xe(t,i),a=D.get(s);a?Qe(a,i.fp,i.info,n,o):(a=qt(s,t,i,n,o),D.set(s,a),Kt()),a.uses+=1,a.lastUsedReal=n,a.lastUsedApp=o,a.expiresAt!==void 0&&o>=a.expiresAt&&(a.expiredSends+=1),p&&p.tokenId===s&&p.forcedAt!==void 0&&i.fp===p.startFp&&(p.staleAfterFailure+=1)}le()}function si(e){let t=Ve(e.url);if(!t)return;let r=S(),n=false;if(e.status===401||e.status===403)for(let i of _t(e,Ke)){let s=D.get(Xe(t,i));s&&s.fp===i.fp&&(s.rejected+=1,n=true)}let o=!!p?.ruleId&&e.override?.ruleId===p.ruleId;if(p&&(e.status??0)>=400&&!o){let i=`${e.method.toUpperCase()} ${We(e.url)}`;(Vt.has(i)||e.method.toUpperCase()==="POST"&&ri.test(We(e.url)))&&(p.failedRefreshes+=1,p.lastRefreshError=`${e.status} ${i}`,n=true)}p?.ruleId&&e.override?.ruleId===p.ruleId&&p.forcedAt===void 0&&(p.forcedAt=r,n=true);for(let i of Zo(e,Ke)){if(Vt.add(i.issuedBy),X.set(i.fp,{...i,observedReal:r}),X.size>Xo){let s=X.keys().next().value;s!==void 0&&X.delete(s)}if(n=true,i.cookie){let s={location:"cookie",name:i.cookie,fp:i.fp,info:i.info},a=Xe(t,s),l=D.get(a);l?Qe(l,i.fp,i.info,r,e.timestamp):(D.set(a,qt(a,t,s,r,e.timestamp)),Kt());continue}for(let s of D.values())s.fp===i.fp&&Qe(s,i.fp,s.info,r,s.lastUsedApp)}n&&le()}function ai(e){let t=e;!t||typeof t.id!="string"||typeof t.url!="string"||(Wt(ei,t.id)&&ii(t),t.status!==void 0&&Wt(ti,t.id)&&si(t))}function ve(){if(Ze)return true;try{let{networkEventStore:e}=wo("@buoy-gg/network");if(!e?.onEvent)throw new Error("no event store");Ze=e.onEvent(ai,true),xe=true}catch{xe=false}return le(),xe}function Zt(e,t,r){let n=D.get(t);if(!n)throw new Error(`No token row "${t}".`);return p={kind:e,tokenId:t,startedAt:S(),startFp:n.fp,ruleId:r,status:"waiting",newTokens:0,staleAfterFailure:0,failedRefreshes:0},le(),p}function li(){p=null,le()}function ci(e){return e.location==="cookie"?`${e.name} cookie`:e.location==="query"?`${e.name} parameter`:e.location==="header"?`${e.name} header`:e.role==="id"||e.info.claims.use==="id"?"ID token":"Access token"}function ui(e,t){let r=[e.firstSeenReal,...e.history.map(o=>o.firstSeenReal)].slice(0,-1).filter(o=>t-o<=Ht).length,n=e.info.issuedAt;return{id:e.key,label:ci(e),host:e.host,location:e.location,name:e.name,scheme:e.scheme,format:e.info.format,formatLabel:e.info.formatLabel,hint:e.info.hint,claims:e.info.claims,fingerprint:e.fp,issuedAt:n,notBefore:e.info.notBefore,expiresAt:e.expiresAt,serverExpiresAt:e.serverExpiresAt,expirySource:e.expirySource,lifetimeMs:e.lifetimeMs,neverExpires:e.info.neverExpires,issuedBy:e.issuedBy,refresh:e.refresh?{expiresAt:e.refresh.expiresAt,formatLabel:e.refresh.formatLabel}:void 0,firstUsed:e.firstSeenApp,lastUsed:e.lastUsedApp,lastUsedReal:e.lastUsedReal,uses:e.uses,refreshes:e.history.length,lastRefreshAt:e.history.length?e.firstSeenReal:void 0,recentRefreshes:r,looping:r>=Ut,expiredSends:e.expiredSends,rejected:e.rejected}}function we(){let e=S(),t=[...D.values()].sort((r,n)=>n.lastUsedReal-r.lastUsedReal).map(r=>ui(r,e));if(p?.status==="refreshed"){let r=D.get(p.tokenId);r&&(p.newLifetimeMs=r.lifetimeMs,p.newIssuedBy=r.issuedBy)}return{available:xe,watching:Ze!==null,tokens:t,check:p?{...p}:null}}function di(e){let t=we();return e?t.tokens.find(r=>r.id===e)??null:t.tokens.find(r=>r.expiresAt!==void 0)??t.tokens[0]??null}function fi(e){return D.get(e)?.origin??null}import{isProNow as Yt}from"@buoy-gg/shared-ui/web";var f={anchor:Ce,settings:ie,lastJump:null,changedAt:null,hydrated:false},et=new Set,Te=null;function Gt(){Te=null,et.forEach(e=>e())}ni(Gt);function ce(e){return et.add(e),()=>{et.delete(e)}}function pi(){return f.settings}function Xt(){return M(f.anchor,S())}function Qt(){return f.anchor.mode!=="real"}function hi(e){if(e.mode==="real"){$t(null),so();return}Dt(),$t(t=>M(f.anchor,t)),io()}function mi(){let e={v:1,anchor:f.settings.persist&&Yt()?f.anchor:null,settings:f.settings};Fe(e)}function er(){let e={v:1,anchor:f.settings.persist&&Yt()?f.anchor:null,settings:f.settings};return f.settings.persist&&f.anchor.mode!=="real"&&(e.reload={anchor:f.anchor,at:S()}),Fe(e)}function Q(e,{save:t=true}={}){f={...f,...e},e.anchor&&hi(f.anchor),t&&mi(),Gt()}function ee(e,t=f.lastJump){Q({anchor:e,lastJump:t,changedAt:S(),hydrated:true})}var tr=e=>A.parse(e);function rr(e,t=false){let r=S(),n=M(f.anchor,r),o=wt(e,n,tr),i=o-n;return ee(Pe(f.anchor,r,o,t),{byMs:i,firedTimers:0,at:r}),R()}function tt(e,t){let r=Ee(e),n=S(),o=Kn(f.anchor,n,r),i=(t??f.settings.fireTimersOnJump)&&r>0;if(ee(o,{byMs:r,firedTimers:0,at:n}),i){let s=go(r);s>0&&Q({lastJump:{byMs:r,firedTimers:s,at:n}},{save:false})}return R()}function rt(e){let t=S(),r=M(f.anchor,t),n=e===void 0||e===""?r:wt(e,r,tr);return ee(Zn(f.anchor,t,n)),R()}function nt(){return f.anchor.mode==="frozen"&&ee(Yn(f.anchor,S())),R()}function nr(e){return ee(Gn(f.anchor,S(),Number(e))),R()}function ot(){return ee(Ce,null),R()}function or(e){let t={...f.settings};for(let r of Object.keys(ie))typeof e[r]=="boolean"&&(t[r]=e[r]);return Q({settings:t}),R()}function gi(e){return e>0?mo(e):0}var ir=false;function sr(e){if(!e){Q({hydrated:true},{save:false});return}let t=e.reload?S()-e.reload.at:1/0,r=t>=0&&t<bo?e.reload?.anchor:void 0;e.reload&&Fe({v:1,anchor:e.anchor,settings:e.settings});let n=e.anchor??r??null;Q({settings:e.settings,anchor:n??Ce,changedAt:n?S():null,hydrated:true},{save:false})}function it(){if(ir)return;ir=true,Dt();let e=void 0;if(e!==void 0){sr(e);return}xo().then(t=>{f.changedAt===null?sr(t):Q({hydrated:true},{save:false})})}function yi(){try{return Intl.DateTimeFormat().resolvedOptions().timeZone??"unknown"}catch{return"unknown"}}function R(){let e=S(),t=M(f.anchor,e);return{mode:f.anchor.mode,active:f.anchor.mode!=="real",rate:f.anchor.rate,virtualNow:t,virtualIso:new A(t).toISOString(),realNow:e,offsetMs:qn(f.anchor,e),timeZone:yi(),timers:ho(),lastJump:f.lastJump,changedAt:f.changedAt,settings:f.settings,hydrated:f.hydrated,tokens:we(),patched:{date:Qn(),intl:oo(),timers:po(),animatedOnRealClock:co()}}}function ar(){return Te||(Te=R()),Te}import{useSyncExternalStore as bi}from"react";import{ClockToolIcon as lr,FloatingTool as ki,Pause as xi,Play as vi,X as wi,dismissFloatingTool as Ti,getFloatingTools as Ai,getUseIsPro as Si,night as ue,openFloatingTool as cr}from"@buoy-gg/shared-ui/web";import{useEffect as $i,useState as Ii}from"react";function V(e,t=250){let[,r]=Ii(0);$i(()=>{let s=setInterval(()=>r(a=>a+1),t);return()=>clearInterval(s)},[t]);let n=S();if(!e)return{virtual:n,real:n};let o=n-e.realNow,i=e.mode==="real"?1:e.rate;return{virtual:e.mode==="frozen"?e.virtualNow:e.virtualNow+o*i,real:n}}var F=e=>String(e).padStart(2,"0");function de(e){let t=new A(e);return`${F(t.getHours())}:${F(t.getMinutes())}:${F(t.getSeconds())}`}var Ri=["Sun","Mon","Tue","Wed","Thu","Fri","Sat"],ur=["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"];function Ci(e){let t=new A(e);return`${Ri[t.getDay()]}, ${ur[t.getMonth()]} ${t.getDate()}, ${t.getFullYear()}`}function Ae(e,t=true){let r=new A(e),n=t?de(e):`${F(r.getHours())}:${F(r.getMinutes())}`;return`${ur[r.getMonth()]} ${r.getDate()} \xB7 ${n}`}function dr(e){let t=new A(e);return`${t.getFullYear()}-${F(t.getMonth()+1)}-${F(t.getDate())} ${F(t.getHours())}:${F(t.getMinutes())}`}function Oi(e){if(Math.abs(e)<1e3)return"matches real time";let t=te(Math.abs(e),{signed:false});return e>0?`${t} ahead of real time`:`${t} behind real time`}function fr(e){return e.mode==="real"?{label:"Real time",tone:"neutral"}:e.mode==="frozen"?{label:"Frozen",tone:"info"}:e.rate!==1?{label:`${At(e.rate)} speed`,tone:"warning"}:{label:"Overridden",tone:"accent"}}function Di(e){return`clock-jump-${e<0?"minus":"plus"}-${te(Math.abs(e),{signed:false}).replace(/\s/g,"")}`}import{jsx as N,jsxs as st}from"react/jsx-runtime";var Se="clock-chip",pr={id:Se,render:e=>N(mr,{...e})},Pi=()=>Ai().some(e=>e.id===Se);function Ei(){cr(pr)}var hr=false;function zi(){if(hr)return;hr=true;let e=false,t=()=>{let r=Qt()&&pi().showChip;r&&!e?cr(pr):!r&&Pi()&&Ti(Se),e=r};ce(t),t()}function mr({id:e,revealToken:t}){let r=bi(ce,ar,ar),{virtual:n,real:o}=V(r),i=r.mode==="frozen",s=i||Si()(),a=fr(r),l=n-o,c=`${Math.abs(l)<1e3?"0s":te(l)} \xB7 ${a.label.toLowerCase()}`;return N(ki,{id:e,revealToken:t,variant:"strip",dragFromSurface:true,defaultPlacement:"top",accessibilityLabel:`Move or hide the clock chip. App time ${Ae(n)}`,handleAdornment:N(lr,{size:12}),children:st(m,{style:K.row,children:[N(lr,{size:18}),st(m,{style:K.text,children:[N(w,{style:K.time,numberOfLines:1,testID:"clock-chip-time",children:Ae(n)}),N(w,{style:K.detail,numberOfLines:1,testID:"clock-chip-detail",children:c})]}),s?st(B,{testID:i?"clock-chip-resume":"clock-chip-freeze",accessibilityRole:"button",accessibilityLabel:i?"Resume the app clock":"Freeze the app clock",onPress:()=>i?nt():rt(),style:K.button,hitSlop:{top:8,bottom:8,left:4,right:4},children:[i?N(vi,{size:16,color:ue.color.accent}):null,i?null:N(xi,{size:16,color:ue.color.text})]}):null,s?N(m,{style:K.separator}):null,N(B,{testID:"clock-chip-reset",accessibilityRole:"button",accessibilityLabel:"Back to real time",onPress:()=>ot(),style:K.button,hitSlop:{top:8,bottom:8,left:4,right:8},children:N(wi,{size:16,color:ue.color.textSecondary})})]})})}var K=Y.create({row:{flexDirection:"row",alignItems:"center",gap:10,paddingLeft:10,paddingRight:4,paddingVertical:6,minWidth:220},text:{flexShrink:1,minWidth:120},time:{color:"#F59E0B",fontSize:14,fontWeight:"600",fontVariant:["tabular-nums"]},detail:{color:ue.color.textSecondary,fontSize:11,fontVariant:["tabular-nums"]},button:{width:32,height:32,alignItems:"center",justifyContent:"center",borderRadius:16},separator:{width:Y.hairlineWidth,height:20,backgroundColor:ue.color.separator}});import{ClockToolIcon as Ni,CLOCK_TOOL_ICON_COLOR as Li,createToolFactory as ji,defineToolPreset as Mi}from"@buoy-gg/shared-ui/web";import{useEffect as gr,useState as _i}from"react";import{reloadApp as Fi}from"@buoy-gg/shared-ui/web";import{createSyncAdapter as Bi}from"@buoy-gg/shared-ui/web";import{dispatchToolAction as yr}from"@buoy-gg/shared-ui/web";var br="No sign-in token seen yet. Use the app so it sends a signed-in request, then try again. Tokens are read from the Network tool's captured requests.";function kr(e){ve();let t=di(e);if(!t)throw new Error(e?`No token "${e}". Read getState for the current ids.`:br);return t}function xr(e,t=1e4){let r=kr(e);if(r.expiresAt===void 0)throw new Error(r.neverExpires?`${r.label} for ${r.host} is ${r.hint??"a key"} and never expires.`:`${r.label} for ${r.host} (${r.formatLabel}) has no expiry Buoy can read. Use failNextRequest to test the refresh instead.`);let n=r.expiresAt-Math.max(0,t)-Xt();if(n<=0)throw new Error(`${r.label} for ${r.host} has already expired on the app's clock. Go back to real time, or use failNextRequest.`);return tt(n),Zt("expiry",r.id),R()}async function vr(e,t=401,r=1){let n=kr(e),o=fi(n.id);if(!o)throw new Error(br);await wr();let i=t===403?403:401,s=n.location==="authorization"||n.location==="header"?{urlPattern:`${o}/*`,requireHeader:n.name.toLowerCase()}:n.location==="query"?{urlPattern:`${o}/*${n.name}=*`}:{urlPattern:`${o}/*`},a=await yr("network","upsertOverrideRule",{name:"Clock: force a token refresh",...s,kind:"respond",status:i,headers:{"content-type":"application/json","www-authenticate":'Bearer error="invalid_token", error_description="The access token expired"'},body:JSON.stringify({error:"invalid_token",error_description:"The access token expired (forced by Buoy Clock to test token refresh)"}),times:Math.max(1,Math.min(10,Math.round(r)))}).catch(l=>{let c=l instanceof Error?l.message:String(l);throw new Error(c.includes("Unknown tool")?"Failing a request needs the Network tool (@buoy-gg/network).":c)});if(!a?.ok||!a.rule)throw new Error(a?.error??"Network did not add the override.");return Zt("401",n.id,a.rule.id),R()}async function wr(){let e=we().check;e?.ruleId&&e.forcedAt===void 0&&await yr("network","deleteOverrideRule",{id:e.ruleId}).catch(()=>{})}async function Tr(){return await wr(),li(),R()}function Z(e){return e&&typeof e=="object"?e:{}}function at(e,...t){for(let r of t){let n=e[r];if(typeof n=="string"||typeof n=="number")return n}}function fe(e,t){let r=e[t];if(typeof r=="boolean")return r;if(r==="true")return true;if(r==="false")return false}var Ar=Bi({version:1,getSnapshot(){return R()},subscribe(e){return ce(e)},actions:{getState(){return ve(),R()},setTime(e){let t=Z(e),r=at(t,"time","at","date","iso");if(r===void 0)throw new Error('setTime needs `time`: ISO 8601 ("2026-12-31T23:59:50"), epoch ms, or relative ("+1d").');return rr(r,fe(t,"freeze")??false)},shift(e){let t=Z(e),r=at(t,"by","ms","duration","delta");if(r===void 0)throw new Error('shift needs `by`: a duration like "+1d", "-2h30m", "90s", or ms.');return tt(r,fe(t,"fireTimers"))},freeze(e){return rt(at(Z(e),"time","at"))},resume(){return nt()},setRate(e){let t=Z(e),r=Number(t.rate??t.speed);if(!Number.isFinite(r))throw new Error("setRate needs a numeric `rate` (1 = normal speed).");return nr(r)},reset(){return ot()},updateSettings(e){let t=Z(e);return or({persist:fe(t,"persist"),showChip:fe(t,"showChip"),fireTimersOnJump:fe(t,"fireTimersOnJump")})},jumpToTokenExpiry(e){let t=Z(e),r=typeof t.token=="string"?t.token:typeof t.id=="string"?t.id:void 0,n=Number(t.leadMs??t.lead??1e4);return xr(r,Number.isFinite(n)?n:1e4)},failNextRequest(e){let t=Z(e),r=typeof t.token=="string"?t.token:typeof t.id=="string"?t.id:void 0,n=Number(t.status??401),o=Number(t.times??1);return vr(r,n,Number.isFinite(o)?o:1)},stopTokenCheck(){return Tr()},async holdForReload(){return await er(),R()}}});import{useState as $e}from"react";import{ChevronRight as Ui,NightButton as Hi,NightCard as Ie,NightChip as Vi,NightFootnote as lt,NightRows as ct,NightSectionLabel as Sr,NightSegmented as Wi,NightSwitch as $r,ProBadge as Ji,ProUpgradeModal as qi,getUseIsPro as Ki,monoFont as Zi,night as y,useSafeAreaInsets as Yi}from"@buoy-gg/shared-ui/web";import{ChevronRight as Gi,NightButton as Ir,NightCard as Xi,NightFootnote as Qi,NightRows as es,NightSectionLabel as ts,ProBadge as rs,night as x}from"@buoy-gg/shared-ui/web";import{jsx as T,jsxs as j}from"react/jsx-runtime";var W=e=>te(Math.abs(e),{signed:false});function ns({snapshot:e,run:t,openId:r,onToggle:n,isPro:o,onUpgrade:i}){let s=e.tokens;return j(m,{children:[T(ts,{children:s.tokens.length>1?"Sign-in tokens":"Sign-in token"}),T(Xi,{children:j(es,{children:[s.tokens.map((a,l)=>j(m,{children:[T(os,{token:a,snapshot:e,index:l,open:r===a.id,onPress:()=>n(a.id)}),r===a.id?T(is,{token:a,snapshot:e,run:o?t:()=>i("Sign-in token tests"),isPro:o}):null]},a.id)),s.tokens.length===0?T(m,{style:g.row,testID:"clock-token-empty",children:T(w,{style:g.emptyText,children:s.available?"No token seen yet":"Needs the Network tool"})},"empty"):null]})}),T(as,{check:s.check,tokens:s.tokens,snapshot:e,run:t}),s.tokens.length===0?T(Qi,{children:s.available?"Tokens show up here when the app sends a signed-in request.":"Install @buoy-gg/network so the Clock tool can read the app's tokens."}):null]})}function os({token:e,snapshot:t,index:r,open:n,onPress:o}){let{virtual:i}=V(t,1e3),s=e.expiresAt!==void 0?e.expiresAt-i:void 0,a=e.neverExpires?"No expiry":s===void 0?"Unknown":s<=0?"Expired":W(s),l=s!==void 0&&s<=0?g.valueDanger:s!==void 0&&s<6e4?g.valueWarning:null;return j(B,{testID:`clock-token-${r}`,accessibilityRole:"button",accessibilityLabel:`${e.label} for ${e.host}: ${s!==void 0&&s>0?`expires in ${a}`:a}`,accessibilityState:{expanded:n},activeOpacity:.6,onPress:o,style:g.row,children:[j(m,{style:g.rowText,children:[T(w,{style:g.rowTitle,numberOfLines:1,children:e.label}),T(w,{style:g.rowSubtitle,numberOfLines:1,children:`${e.host} \xB7 ${e.hint??e.formatLabel}`})]}),j(m,{style:g.rowRight,children:[T(w,{style:[g.value,l],testID:`clock-token-${r}-left`,children:a}),T(m,{style:n?g.chevronOpen:null,children:T(Gi,{size:16,color:x.color.textTertiary})})]})]})}function is({token:e,snapshot:t,run:r,isPro:n}){let{virtual:o,real:i}=V(t,1e3),s=ss(e,o,i),a=e.expiresAt!==void 0&&e.expiresAt-o>1e4;return j(m,{style:g.detail,testID:"clock-token-detail",children:[s.map(l=>T(w,{style:[g.detailLine,l.tone==="warn"?g.warn:null,l.tone==="bad"?g.bad:null],children:l.text},l.text)),j(m,{style:g.buttons,children:[T(m,{style:g.button,children:T(Ir,{label:"Jump to Expiry",testID:"clock-token-jump",accessibilityLabel:"Jump the app's clock to ten seconds before this token expires",size:"md",disabled:!a,onPress:()=>r("jumpToTokenExpiry",{token:e.id})})}),T(m,{style:g.button,children:T(Ir,{label:"Fail Next Request",testID:"clock-token-fail",accessibilityLabel:"Answer the app's next request to this API with 401",size:"md",onPress:()=>r("failNextRequest",{token:e.id})})})]}),n?null:j(m,{style:g.proLine,children:[T(rs,{}),T(w,{style:[g.hint,g.proHint],children:"Jump to Expiry and Fail Next Request are part of Buoy Pro."})]}),T(w,{style:g.hint,children:a||e.expiresAt===void 0?"Jump tests an app that refreshes before expiry. Fail tests one that refreshes after a 401.":"This token has already expired on the app's clock. Use Real Time to jump to it again."})]})}function ss(e,t,r){let n=[];if(e.expiresAt!==void 0){if(n.push({text:`Expires ${Ae(e.expiresAt)}`}),e.lifetimeMs!==void 0&&e.lifetimeMs>0&&n.push({text:`Lasts ${W(e.lifetimeMs)}${e.expirySource?`, from ${e.expirySource}`:""}`}),e.serverExpiresAt!==void 0){let o=e.expiresAt-t,i=e.serverExpiresAt-r;Math.abs(o-i)>2e3&&n.push({text:i>0?`The server still accepts it for ${W(i)}`:`The server stopped accepting it ${W(i)} ago`})}}else e.neverExpires||n.push({text:"The token doesn't say when it expires, and no login response did either."});if(e.hint&&n.push({text:e.formatLabel}),e.issuedBy&&n.push({text:`Issued by ${e.issuedBy}`}),e.refresh?.expiresAt!==void 0){let o=e.refresh.expiresAt-t;n.push({text:o>0?`Refresh token expires in ${W(o)}`:"Refresh token expired"})}return e.refreshes>0&&e.lastRefreshAt!==void 0&&n.push({text:`Refreshed ${e.refreshes===1?"once":`${e.refreshes} times`}, last at ${de(e.lastRefreshAt)}`}),n.push({text:`Sent with ${e.uses} request${e.uses===1?"":"s"}`}),e.expiredSends>0&&n.push({text:`Sent ${e.expiredSends} time${e.expiredSends===1?"":"s"} after it expired on the app's clock`,tone:"warn"}),e.rejected>0&&n.push({text:`Rejected by the server ${e.rejected} time${e.rejected===1?"":"s"}`,tone:"warn"}),e.looping&&n.push({text:`Refresh loop: ${e.recentRefreshes} new tokens in 20s`,tone:"bad"}),n}function as({check:e,tokens:t,snapshot:r,run:n}){let{virtual:o,real:i}=V(r,1e3);if(!e)return null;let s=t.find(c=>c.id===e.tokenId),{text:a,tone:l}=ls(e,s,o,i);return j(m,{style:g.check,children:[T(w,{style:[g.checkText,l==="good"?g.good:null,l==="bad"?g.bad:null,l==="warn"?g.warn:null],testID:"clock-token-check",children:a}),T(B,{testID:"clock-token-check-done",accessibilityRole:"button",accessibilityLabel:e.status==="waiting"?"Stop the refresh check":"Dismiss",onPress:()=>n("stopTokenCheck"),hitSlop:{top:8,bottom:8,left:8,right:8},children:T(w,{style:g.checkDone,children:e.status==="waiting"?"Stop":"Done"})})]})}function ls(e,t,r,n){if(e.status==="loop")return{text:`Refresh loop: ${e.newTokens} new tokens since the check started. The new tokens may already look expired to the app's clock.`,tone:"bad"};if(e.status==="refreshed"){let a=e.newIssuedBy?` by ${e.newIssuedBy}`:"",l=e.newLifetimeMs&&e.newLifetimeMs>0?`. The new token lasts ${W(e.newLifetimeMs)}`:"",c=e.kind==="401"&&e.forcedAt!==void 0?"The app got the 401 and refreshed":"Refreshed",d=e.failedRefreshes>0?` ${e.failedRefreshes===1?"One token request":`${e.failedRefreshes} token requests`} failed first (${e.lastRefreshError}).`:"";return{text:`${c} at ${de(e.refreshedAt??n)}${a}${l}.${d}`,tone:d?"warn":"good"}}let o=n-e.startedAt,i=(e.staleAfterFailure>0?` It sent the old token again ${e.staleAfterFailure} time${e.staleAfterFailure===1?"":"s"}.`:"")+(e.failedRefreshes>0?` Its token request failed (${e.lastRefreshError}).`:"");if(o>6e4)return{text:`No new token after ${W(o)}. The app may refresh on its next action, or not at all.${i}`,tone:"warn"};if(e.kind==="401")return e.forcedAt===void 0?{text:`The next request to ${t?.host??"the API"} will get a 401. Use the app to send one.`}:{text:`The app got the 401. Waiting for a new token\u2026${i}`,tone:i?"warn":void 0};let s=t?.expiresAt!==void 0?t.expiresAt-r:void 0;return s!==void 0&&s>0?{text:`Expires in ${W(s)} on the app's clock. Waiting for a new token\u2026`}:{text:"Expired on the app's clock. Waiting for the app's next request\u2026"}}var g=Y.create({row:{flexDirection:"row",alignItems:"center",justifyContent:"space-between",gap:12,minHeight:56,paddingHorizontal:x.rowPadH,paddingVertical:10},rowText:{flex:1,minWidth:0},rowTitle:{color:x.color.text,fontSize:x.font.row},rowSubtitle:{color:x.color.textTertiary,fontSize:x.font.caption,marginTop:2},rowRight:{flexDirection:"row",alignItems:"center",gap:6},value:{color:x.color.textSecondary,fontSize:x.font.row,fontVariant:["tabular-nums"]},valueWarning:{color:x.color.warning},valueDanger:{color:x.color.danger},chevronOpen:{transform:[{rotate:"90deg"}]},emptyText:{color:x.color.textSecondary,fontSize:x.font.row},detail:{paddingHorizontal:x.rowPadH,paddingBottom:14,gap:4},detailLine:{color:x.color.textSecondary,fontSize:x.font.caption},buttons:{flexDirection:"row",gap:8,marginTop:8},button:{flex:1},hint:{color:x.color.textTertiary,fontSize:x.font.caption,marginTop:6},proLine:{flexDirection:"row",alignItems:"center",gap:8,marginTop:6},proHint:{marginTop:0,flexShrink:1},check:{flexDirection:"row",alignItems:"flex-start",gap:12,marginTop:8,marginHorizontal:x.labelInset},checkText:{flex:1,color:x.color.textSecondary,fontSize:x.font.caption,lineHeight:18},checkDone:{color:x.color.accent,fontSize:x.font.caption,fontWeight:"600"},good:{color:x.color.accent},warn:{color:x.color.warning},bad:{color:x.color.danger}});import{jsx as u,jsxs as $}from"react/jsx-runtime";var Rr="#F59E0B";function Cr({snapshot:e,onAction:t,onReload:r}){let n=Yi({minBottom:16}),[o,i]=$e(null),[s,a]=$e(null),l=Ki()(),[c,d]=$e(null),v=k=>d(k),b=(k,C)=>{i(null),t(k,C).catch(L=>{i(L instanceof Error?L.message:String(L))})},I=k=>a(C=>C===k?null:k);return e?$(xt,{style:h.fill,contentContainerStyle:[h.content,{paddingBottom:n.bottom}],testID:"clock-scroll",keyboardShouldPersistTaps:"handled",children:[u(cs,{snapshot:e}),o?u(lt,{tone:"danger",centered:true,children:u(w,{testID:"clock-error",children:o})}):null,$(m,{children:[u(Sr,{children:"Jump ahead"}),u(ds,{run:b})]}),$(m,{children:[u(Ie,{children:$(ct,{children:[$(m,{children:[u(Dr,{title:"Date & Time",testID:"clock-date-row",open:s==="date",onPress:()=>I("date"),value:u(fs,{snapshot:e})}),s==="date"?u(hs,{snapshot:e,run:b,onDone:()=>a(null)}):null]},"date"),$(m,{style:h.row,children:[u(ut,{title:"Freeze",isPro:l}),u($r,{value:e.mode==="frozen",testID:"clock-freeze",accessibilityLabel:"Freeze the clock",onValueChange:k=>k&&!l?v("Freeze"):b(k?"freeze":"resume")})]},"freeze"),$(m,{children:[u(Dr,{title:"Speed",pro:!l,testID:"clock-speed-row",open:s==="speed",onPress:()=>l?I("speed"):v("Speed"),value:u(w,{style:h.rowValue,children:zr(e)})}),s==="speed"?u(ms,{snapshot:e,run:b}):null]},"speed")]})}),u(lt,{children:"Only this app's clock changes. Screens pick up the new time when they next render, or all at once when you reload."})]}),e.tokens?u(ns,{snapshot:e,run:b,openId:s,onToggle:I,isPro:l,onUpgrade:v}):null,u(Ie,{children:$(ct,{children:[r?u(Pr,{label:"Reload App",testID:"clock-reload",onPress:r},"reload"):null,u(Pr,{label:"Use Real Time",accessibilityLabel:"Reset to real time",testID:"clock-reset",destructive:true,disabled:e.mode==="real",onPress:()=>b("reset")},"reset")]})}),$(m,{children:[u(Sr,{children:"Options"}),u(ys,{settings:e.settings,run:b,isPro:l,onUpgrade:v})]}),u(qi,{visible:c!==null&&!l,onClose:()=>d(null),featureName:c??void 0})]}):u(m,{style:h.waiting,testID:"clock-waiting",children:u(lt,{centered:true,children:"Waiting for the app's clock\u2026"})})}function ut({title:e,isPro:t}){return $(m,{style:h.titleRow,children:[u(w,{style:h.rowTitle,children:e}),t?null:u(Ji,{})]})}function cs({snapshot:e}){let{virtual:t,real:r}=V(e),n=fr(e),o=e.mode!=="real",i=Oi(t-r),s=e.mode==="frozen"?" \xB7 Frozen":o&&e.rate!==1?` \xB7 ${zr(e)}`:"";return $(m,{style:h.hero,children:[u(w,{style:[h.heroTime,o?h.heroTimeActive:null],testID:"clock-hero-time",accessibilityLabel:`App clock ${de(t)}`,children:de(t)}),u(w,{style:h.heroDate,testID:"clock-hero-date",children:Ci(t)}),u(m,{testID:"clock-status",accessibilityLabel:`Clock status: ${n.label}${o?`, ${i}`:""}`,children:u(w,{style:[h.heroStatus,o?h.heroStatusActive:null],testID:"clock-offset",children:o?`${i}${s}`:"Real time"})})]})}var Or=36e5,dt=24*Or,us=[{ms:Or,unit:"hour"},{ms:dt,unit:"day"},{ms:7*dt,unit:"week"},{ms:30*dt,unit:"month"}];function ds({run:e}){return u(Ie,{style:h.jumpBar,children:us.map((t,r)=>$(B,{testID:Di(t.ms),accessibilityRole:"button",accessibilityLabel:`Jump ahead one ${t.unit}`,activeOpacity:.6,onPress:()=>e("shift",{by:t.ms}),style:[h.jump,r>0?h.jumpDivider:null],children:[u(w,{style:h.jumpAmount,children:"+1"}),u(w,{style:h.jumpUnit,children:t.unit})]},t.unit))})}function Dr({title:e,pro:t,value:r,open:n,onPress:o,testID:i}){return $(B,{testID:i,accessibilityRole:"button",accessibilityLabel:e,accessibilityState:{expanded:n},activeOpacity:.6,onPress:o,style:h.row,children:[u(ut,{title:e,isPro:!t}),$(m,{style:h.rowRight,children:[r,u(m,{style:n?h.chevronOpen:null,children:u(Ui,{size:16,color:y.color.textTertiary})})]})]})}function fs({snapshot:e}){let{virtual:t}=V(e,1e3);return u(w,{style:[h.rowValue,h.tabular],numberOfLines:1,children:Ae(t,false)})}function Pr({label:e,onPress:t,testID:r,destructive:n,disabled:o,accessibilityLabel:i}){return u(B,{testID:r,accessibilityRole:"button",accessibilityLabel:i??e,accessibilityState:{disabled:!!o},activeOpacity:.6,disabled:o,onPress:t,style:[h.row,o?h.rowDisabled:null],children:u(w,{style:[h.actionLabel,n?h.actionDestructive:null],children:e})})}var ps=Tt.filter(e=>["midnight","month-end","year-end"].includes(e.id));function hs({snapshot:e,run:t,onDone:r}){let[n,o]=$e(""),{virtual:i}=V(e,1e3),s=()=>n.trim()||dr(i),a=e.mode==="frozen",l=c=>{t("setTime",{time:c,freeze:a}),r()};return $(m,{style:h.editor,children:[$(m,{style:h.inputRow,children:[u(kt,{testID:"clock-time-input",accessibilityLabel:"Date and time",value:n,onChangeText:o,placeholder:dr(i),placeholderTextColor:y.color.placeholder,autoCapitalize:"none",autoCorrect:false,returnKeyType:"done",onSubmitEditing:()=>l(s()),style:h.input}),u(Hi,{label:"Set",testID:"clock-time-apply",accessibilityLabel:"Set this time",size:"md",variant:"primary",fullWidth:false,onPress:()=>l(s())})]}),u(w,{style:h.hint,children:"Year-month-day and 24-hour time, or +3d, -2h"}),u(m,{style:h.presets,children:ps.map(c=>u(Vi,{label:c.label,testID:`clock-preset-${c.id}`,onPress:()=>l(c.at(i,A))},c.id))})]})}var Er=[{key:"1",label:"Normal"},{key:"10",label:"10\xD7"},{key:"60",label:"1 min/s"},{key:"3600",label:"1 hr/s"}];function zr(e){return e.mode==="real"||e.rate===1?"Normal":Er.find(t=>Number(t.key)===e.rate)?.label??At(e.rate)}function ms({snapshot:e,run:t}){let r=e.mode==="real"?"1":String(e.rate);return $(m,{style:h.editor,children:[u(m,{style:h.segmentRow,children:u(Wi,{tabs:Er,activeKey:r,size:"sm",testIDPrefix:"clock-speed",onChange:n=>t("setRate",{rate:Number(n)})})}),u(w,{style:h.hint,children:"Taps, animations and timers keep real speed."})]})}var gs=[{key:"showChip",title:"Show Floating Clock"},{key:"persist",title:"Keep After Reload",pro:true}];function ys({settings:e,run:t,isPro:r,onUpgrade:n}){return u(Ie,{children:u(ct,{children:gs.map(o=>{let i=!!o.pro&&!r;return $(m,{style:h.row,children:[u(ut,{title:o.title,isPro:!i}),u($r,{value:i?false:e[o.key],testID:`clock-setting-${o.key}`,accessibilityLabel:o.title,onValueChange:s=>i?n(o.title):t("updateSettings",{[o.key]:s})})]},o.key)})})})}var h=Y.create({fill:{flex:1},content:{paddingHorizontal:y.gutter,paddingTop:8,gap:y.groupGap},waiting:{flex:1,alignItems:"center",justifyContent:"center",padding:24},hero:{alignItems:"center",paddingTop:12},heroTime:{color:y.color.text,fontSize:56,fontWeight:"200",fontVariant:["tabular-nums"],letterSpacing:1},heroTimeActive:{color:Rr},heroDate:{color:y.color.text,fontSize:17,fontWeight:"500",marginTop:2},heroStatus:{color:y.color.textTertiary,fontSize:y.font.caption,fontWeight:"500",marginTop:6},heroStatusActive:{color:y.color.textSecondary},jumpBar:{flexDirection:"row"},jump:{flex:1,alignItems:"center",paddingVertical:12},jumpDivider:{borderLeftWidth:Y.hairlineWidth,borderLeftColor:y.color.separator},jumpAmount:{color:Rr,fontSize:17,fontWeight:"600",fontVariant:["tabular-nums"]},jumpUnit:{color:y.color.textSecondary,fontSize:y.font.caption,marginTop:1},row:{flexDirection:"row",alignItems:"center",justifyContent:"space-between",gap:12,minHeight:50,paddingHorizontal:y.rowPadH,paddingVertical:10},rowDisabled:{opacity:.4},rowTitle:{color:y.color.text,fontSize:y.font.row},titleRow:{flexDirection:"row",alignItems:"center",gap:8,flexShrink:1},rowRight:{flexDirection:"row",alignItems:"center",gap:6,flexShrink:1},rowValue:{color:y.color.textSecondary,fontSize:y.font.row},tabular:{fontVariant:["tabular-nums"]},chevronOpen:{transform:[{rotate:"90deg"}]},actionLabel:{color:y.color.accent,fontSize:y.font.row},actionDestructive:{color:y.color.danger},editor:{paddingHorizontal:y.rowPadH,paddingBottom:14,gap:10},inputRow:{flexDirection:"row",alignItems:"center",gap:8},input:{flex:1,color:y.color.text,fontFamily:Zi,fontSize:15,backgroundColor:y.color.bg,borderRadius:y.radius.input,borderWidth:1,borderColor:y.color.border,paddingHorizontal:12,paddingVertical:8},hint:{color:y.color.textTertiary,fontSize:y.font.caption},presets:{flexDirection:"row",flexWrap:"wrap",gap:6},segmentRow:{flexDirection:"row"}});import{jsx as bs}from"react/jsx-runtime";var ks=Ar.actions;async function xs(e,t){let r=ks[e];if(!r)throw new Error(`Unknown clock action: ${e}`);return r(t)}function vs(){er().then(()=>Fi("auto","buoy clock")).catch(()=>{})}function Nr(){gr(()=>{it(),ve()},[]);let[e,t]=_i(R);return gr(()=>ce(()=>t(R())),[]),bs(Cr,{snapshot:e,onAction:xs,onReload:vs})}import{jsx as ws}from"react/jsx-runtime";var Lr=Mi({id:"clock",name:"CLOCK",description:"Travel to any date, freeze or speed up the app's clock",slot:"both",color:Li,icon:({size:e,color:t})=>ws(Ni,{size:e,color:t}),component:Nr,modal:{subtitle:"override the app's date & time"}}),Ts=ji(Lr);import{ClockToolIcon as As,CLOCK_TOOL_ICON_COLOR as Ss}from"@buoy-gg/shared-ui/web";var $s=typeof navigator<"u"&&navigator.product==="ReactNative";$s&&(lo(bt),zi(),typeof gt<"u"&>&&it());export{Se as CLOCK_CHIP_ID,Ss as CLOCK_TOOL_ICON_COLOR,Nr as ClockBody,mr as ClockChip,As as ClockToolIcon,Cr as ClockToolView,Tt as TIME_PRESETS,it as bootClock,Ar as clockSyncAdapter,Lr as clockToolPreset,Ts as createClockTool,vr as failNextRequest,te as formatDuration,rt as freeze,R as getClockSnapshot,we as getTokenReport,be as inspectToken,Qt as isClockOverridden,xr as jumpToTokenExpiry,Ei as openClockChip,Ee as parseDuration,gi as previewJump,S as realNow,ot as reset,nt as resume,nr as setRate,rr as setTime,tt as shift,ve as startTokenWatch,Tr as stopTokenCheck,ce as subscribeClock,H as tokenFingerprint,or as updateSettings,V as useLiveClock,Xt as virtualNow,je as withRealClock};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@buoy-gg/clock",
|
|
3
|
-
"version": "7.0.
|
|
3
|
+
"version": "7.0.45",
|
|
4
4
|
"description": "Clock override for React Native: travel to any date, freeze or speed up time, and jump ahead while firing due timers. Test expirations, countdowns and renewals without touching the device clock.",
|
|
5
5
|
"main": "lib/commonjs/index.js",
|
|
6
6
|
"module": "lib/module/index.js",
|
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
"./lib/web/**/*.mjs"
|
|
18
18
|
],
|
|
19
19
|
"dependencies": {
|
|
20
|
-
"@buoy-gg/shared-ui": "^7.0.
|
|
20
|
+
"@buoy-gg/shared-ui": "^7.0.45"
|
|
21
21
|
},
|
|
22
22
|
"peerDependencies": {
|
|
23
23
|
"react": "*"
|