@buoy-gg/notifications 7.0.82 → 7.0.83

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1 +1 @@
1
- "use strict";Object.defineProperty(exports,"__esModule",{value:true});exports.NotificationToolView=NotificationToolView;var _react=_interopRequireWildcard(require("react"));var _reactNative=require("react-native");var _sharedUi=require("@buoy-gg/shared-ui");var _dataViewer=require("@buoy-gg/shared-ui/dataViewer");var _LocalNotificationTest=require("./LocalNotificationTest");var _notificationStyles=require("./notificationStyles");var _jsxRuntime=require("react/jsx-runtime");function _interopRequireWildcard(e,a){if("function"==typeof WeakMap)var o=new WeakMap,r=new WeakMap;return(_interopRequireWildcard=function(s,y){if(!y&&s&&s.__esModule)return s;var u,x,i={__proto__:null,default:s};if(null===s||"object"!=typeof s&&"function"!=typeof s)return i;if(u=y?r:o){if(u.has(s))return u.get(s);u.set(s,i)}for(const n in s)"default"!==n&&{}.hasOwnProperty.call(s,n)&&((x=(u=Object.defineProperty)&&Object.getOwnPropertyDescriptor(s,n))&&(x.get||x.set)?u(i,n,x):i[n]=s[n]);return i})(e,a)}const labels={received:"App received",response:"Notification response","startup-response":"Response recovered at startup","presentation-decision":"Presentation decision","presentation-error":"Presentation error","background-started":"Background task started","background-completed":"Background task completed","background-error":"Background task failed","app-outcome":"App outcome","local-scheduled":"Local notification scheduled"};function eventTone(e){return e.includes("error")?"danger":e==="startup-response"?"warning":e==="received"||e==="app-outcome"?"accent":"neutral"}function Action({label:e,onPress:a,disabled:o,primary:r,icon:s}){return(0,_jsxRuntime.jsxs)(_reactNative.Pressable,{accessibilityRole:"button",accessibilityLabel:e,accessibilityState:{disabled:!!o},disabled:o,onPress:a,style:({pressed:y})=>[_notificationStyles.styles.button,r&&_notificationStyles.styles.primaryButton,y&&_notificationStyles.styles.pressed,o&&_notificationStyles.styles.disabled],children:[s,(0,_jsxRuntime.jsx)(_reactNative.Text,{style:[_notificationStyles.styles.buttonText,r&&_notificationStyles.styles.primaryButtonText],children:e})]})}function Field({label:e,value:a}){return(0,_jsxRuntime.jsxs)(_reactNative.View,{style:_notificationStyles.styles.field,children:[(0,_jsxRuntime.jsx)(_reactNative.Text,{style:[_notificationStyles.styles.caption,_notificationStyles.styles.fieldLabel],children:e}),(0,_jsxRuntime.jsx)(_reactNative.Text,{selectable:true,style:_notificationStyles.styles.value,children:a})]})}function JsonCard({title:e,value:a,initiallyOpen:o=true}){const[r,s]=(0,_react.useState)(o);const y=JSON.stringify(a??null);const u=(0,_react.useMemo)(()=>JSON.parse(y),[y]);return(0,_jsxRuntime.jsxs)(_sharedUi.NightCard,{glass:true,children:[(0,_jsxRuntime.jsxs)(_reactNative.Pressable,{accessibilityRole:"button",accessibilityLabel:e,accessibilityState:{expanded:r},onPress:()=>s(x=>!x),style:_notificationStyles.styles.disclosure,children:[(0,_jsxRuntime.jsx)(_reactNative.Text,{style:_notificationStyles.styles.disclosureTitle,children:e}),r?(0,_jsxRuntime.jsx)(_sharedUi.ChevronDown,{size:14,color:_sharedUi.night.color.textSecondary}):(0,_jsxRuntime.jsx)(_sharedUi.ChevronRight,{size:14,color:_sharedUi.night.color.textSecondary})]}),r&&(0,_jsxRuntime.jsx)(_reactNative.View,{style:_notificationStyles.styles.jsonBody,children:(0,_jsxRuntime.jsx)(_dataViewer.DataViewer,{title:"",data:u,rawMode:true,initialExpanded:true,showTypeFilter:false})})]})}function NotificationToolView({snapshot:e,onAction:a,sender:o,activeTab:r,onTabChange:s,renderShell:y}){const[u,x]=(0,_react.useState)("send");const i=r??u;const[n,C]=(0,_react.useState)("");const[B,f]=(0,_react.useState)(null);const[d,N]=(0,_react.useState)(false);const[v,w]=(0,_react.useState)(null);const[,A]=(0,_react.useState)(0);const m=(0,_sharedUi.useSafeAreaInsets)({minBottom:16});const h=e?.session?.expiresAt;(0,_react.useEffect)(()=>{if(!h||h<=Date.now())return;const t=setTimeout(()=>A(p=>p+1),h-Date.now()+1);return()=>clearTimeout(t)},[h]);const c=!!h&&h>Date.now();const k=(0,_react.useMemo)(()=>(e?.events??[]).filter(t=>JSON.stringify(t).toLowerCase().includes(n.trim().toLowerCase())).slice().reverse(),[e?.events,n]);const l=e?.events.find(t=>t.id===B);const b=e?.events.length??0;const T=!!e?.provider;function g(t){x(t);s?.(t);w(null)}async function j(t,p){if(d)return false;N(true);w(null);try{await a(t,p);return true}catch(S){w({text:S instanceof Error?S.message:String(S),error:true});return false}finally{N(false)}}const P=()=>{void j("setCaptureSession",{runId:`capture-${Date.now()}`,durationMs:18e5})};const V=()=>{void j("setCaptureSession",{runId:null})};async function L(t){const p=await(0,_sharedUi.copyToClipboard)(t);w({text:p?"Copied to clipboard.":"Clipboard is unavailable. Select the text to copy it.",error:!p})}const D=[{key:"send",label:"Test"},{key:"events",label:`Activity (${b})`}];const R=(0,_jsxRuntime.jsxs)(_sharedUi.ModalHeader,{children:[(0,_jsxRuntime.jsx)(_sharedUi.ModalHeader.Content,{title:"",noMargin:true,children:(0,_jsxRuntime.jsx)(_sharedUi.NightSegmented,{tabs:D,activeKey:i,onChange:g,size:"sm",glass:true})}),(0,_jsxRuntime.jsxs)(_sharedUi.ModalHeader.Actions,{children:[(0,_jsxRuntime.jsx)(_reactNative.Pressable,{accessibilityRole:"button",accessibilityLabel:"Notification settings",onPress:()=>g(i==="setup"||i==="tokens"?"send":"setup"),style:_notificationStyles.styles.iconButton,children:(0,_jsxRuntime.jsx)(_sharedUi.Settings,{size:16,color:i==="setup"||i==="tokens"?_sharedUi.night.color.accent:_sharedUi.night.color.textSecondary})}),i!=="send"&&(0,_jsxRuntime.jsx)(_sharedUi.PowerToggleButton,{isEnabled:c,onToggle:c?V:P,disabled:!T||d,accessibilityLabel:c?"Stop notification capture":"Start notification capture",testID:"notifications-capture"})]})]});const I=(0,_jsxRuntime.jsxs)(_reactNative.View,{style:_notificationStyles.styles.root,children:[T&&i!=="send"&&(0,_jsxRuntime.jsxs)(_reactNative.View,{style:_notificationStyles.styles.status,children:[(0,_jsxRuntime.jsxs)(_reactNative.View,{style:_notificationStyles.styles.statusLabel,children:[(0,_jsxRuntime.jsx)(_reactNative.View,{style:[_notificationStyles.styles.dot,c&&_notificationStyles.styles.liveDot]}),(0,_jsxRuntime.jsx)(_reactNative.Text,{style:_notificationStyles.styles.caption,children:c?"Recording":"Capture stopped"})]}),i!=="events"&&(0,_jsxRuntime.jsx)(_reactNative.Text,{style:_notificationStyles.styles.caption,children:e.durable?"Persistent history":"Memory only"}),i!=="events"&&(0,_jsxRuntime.jsxs)(_reactNative.Text,{style:_notificationStyles.styles.provider,children:[e.provider," \xB7 ",e.platform]})]}),e?.storageError&&(0,_jsxRuntime.jsxs)(_reactNative.Text,{accessibilityRole:"alert",style:_notificationStyles.styles.errorNotice,children:["Storage: ",e.storageError]}),v&&(0,_jsxRuntime.jsx)(_reactNative.Text,{accessibilityRole:v.error?"alert":"text",style:[_notificationStyles.styles.notice,v.error&&_notificationStyles.styles.errorText],children:v.text}),!o&&(0,_jsxRuntime.jsx)(_reactNative.View,{style:i==="send"?_notificationStyles.styles.fill:{display:"none"},children:(0,_jsxRuntime.jsx)(_LocalNotificationTest.LocalNotificationTest,{snapshot:e,onAction:a,onViewActivity:()=>g("events")})}),i==="send"?o??null:!T?(0,_jsxRuntime.jsxs)(_reactNative.ScrollView,{children:[(0,_jsxRuntime.jsx)(_sharedUi.ToolEmptyState,{otto:"paused",title:"Connect notification capture",message:"Install @buoy-gg/notifications and call installExpoNotificationCapture in the app entry point. Use an app-specific development build for remote notifications."}),(0,_jsxRuntime.jsx)(_reactNative.Text,{style:_notificationStyles.styles.emptyFootnote,children:"The desktop sender works with any installed app. Inspection needs the capture integration."})]}):(0,_jsxRuntime.jsxs)(_jsxRuntime.Fragment,{children:[i==="events"&&(0,_jsxRuntime.jsxs)(_jsxRuntime.Fragment,{children:[(0,_jsxRuntime.jsxs)(_reactNative.View,{style:_notificationStyles.styles.searchRow,children:[(0,_jsxRuntime.jsxs)(_reactNative.View,{style:_notificationStyles.styles.searchField,children:[(0,_jsxRuntime.jsx)(_sharedUi.Search,{size:14,color:_sharedUi.night.color.textSecondary}),(0,_jsxRuntime.jsx)(_reactNative.TextInput,{accessibilityLabel:"Filter notification events",placeholder:"Search notifications\u2026",placeholderTextColor:_sharedUi.night.color.placeholder,value:n,onChangeText:t=>{C(t);f(null)},autoCapitalize:"none",autoCorrect:false,style:_notificationStyles.styles.searchInput}),!!n&&(0,_jsxRuntime.jsx)(_reactNative.Pressable,{accessibilityRole:"button",accessibilityLabel:"Clear notification search",onPress:()=>C(""),style:_notificationStyles.styles.clearSearch,children:(0,_jsxRuntime.jsx)(_sharedUi.X,{size:12,color:_sharedUi.night.color.textSecondary})})]}),(0,_jsxRuntime.jsx)(_reactNative.Pressable,{accessibilityRole:"button",accessibilityLabel:"Clear captured events",disabled:d||!b,accessibilityState:{disabled:d||!b},style:[_notificationStyles.styles.iconButton,(d||!b)&&_notificationStyles.styles.disabled],onPress:()=>{void j("clearCapturedEvents").then(t=>{if(t)f(null)})},children:(0,_jsxRuntime.jsx)(_sharedUi.Trash2,{size:14,color:_sharedUi.night.color.textSecondary})})]}),l?(0,_jsxRuntime.jsxs)(_reactNative.ScrollView,{style:_notificationStyles.styles.fill,contentContainerStyle:[_notificationStyles.styles.content,{paddingBottom:m.bottom}],keyboardShouldPersistTaps:"handled",children:[(0,_jsxRuntime.jsxs)(_reactNative.View,{style:_notificationStyles.styles.actionRow,children:[(0,_jsxRuntime.jsx)(Action,{label:"Back to events",onPress:()=>f(null),icon:(0,_jsxRuntime.jsx)(_sharedUi.ChevronLeft,{size:14,color:_sharedUi.night.color.accent})}),(0,_jsxRuntime.jsx)(Action,{label:"Copy event JSON",onPress:()=>{void L(l)},icon:(0,_jsxRuntime.jsx)(_sharedUi.Copy,{size:14,color:_sharedUi.night.color.accent})})]}),(0,_jsxRuntime.jsxs)(_sharedUi.NightCard,{glass:true,padded:true,children:[(0,_jsxRuntime.jsx)(_sharedUi.NightBadge,{label:labels[l.kind]??l.kind,tone:eventTone(l.kind)}),(0,_jsxRuntime.jsx)(_reactNative.Text,{style:_notificationStyles.styles.detailTitle,children:l.title??"Notification event"}),(0,_jsxRuntime.jsx)(_reactNative.Text,{style:_notificationStyles.styles.caption,children:new Date(l.capturedAt).toLocaleString()})]}),(0,_jsxRuntime.jsxs)(_reactNative.View,{children:[(0,_jsxRuntime.jsx)(_sharedUi.NightSectionLabel,{children:"Observation"}),(0,_jsxRuntime.jsx)(_sharedUi.NightCard,{glass:true,children:(0,_jsxRuntime.jsxs)(_sharedUi.NightRows,{children:[(0,_jsxRuntime.jsx)(Field,{label:"App state at callback",value:l.observedAppState}),l.testId&&(0,_jsxRuntime.jsx)(Field,{label:"Test ID",value:l.testId}),l.notificationId&&(0,_jsxRuntime.jsx)(Field,{label:"Notification ID",value:l.notificationId}),l.actionIdentifier&&(0,_jsxRuntime.jsx)(Field,{label:"Action",value:l.actionIdentifier})]})})]}),l.kind==="startup-response"&&(0,_jsxRuntime.jsx)(_reactNative.Text,{style:_notificationStyles.styles.footnote,children:"Recovered from the SDK cache. This alone does not establish why the app launched."}),l.truncated&&(0,_jsxRuntime.jsx)(_reactNative.Text,{style:_notificationStyles.styles.warning,children:"This payload was truncated when captured."}),(0,_jsxRuntime.jsx)(JsonCard,{title:"Payload",value:l.raw}),(0,_jsxRuntime.jsx)(JsonCard,{title:"Full event",value:l,initiallyOpen:false})]}):(0,_jsxRuntime.jsx)(_reactNative.FlatList,{data:k,keyExtractor:t=>t.id,style:_notificationStyles.styles.fill,contentContainerStyle:[_notificationStyles.styles.eventList,{paddingBottom:m.bottom}],keyboardShouldPersistTaps:"handled",initialNumToRender:15,ListHeaderComponent:n?(0,_jsxRuntime.jsxs)(_reactNative.Text,{style:_notificationStyles.styles.resultCount,children:[k.length," of ",b," events"]}):null,ListFooterComponent:e.evicted>0?(0,_jsxRuntime.jsxs)(_reactNative.Text,{style:_notificationStyles.styles.footnote,children:[e.evicted," older records removed by the history limit."]}):null,ListEmptyComponent:(0,_jsxRuntime.jsx)(_sharedUi.ToolEmptyState,{otto:n?"sad":c?"listening":"paused",title:n?"No matching events":c?"Waiting for notifications":"Capture is stopped",message:n?"Try another title, test ID, or payload value.":c?"Send a notification from Buoy Desktop or your app. Background alerts can reach the system tray before an app callback runs.":"Start capture with the power button, then send a notification."}),renderItem:({item:t})=>(0,_jsxRuntime.jsx)(EventRow,{event:t,onPress:()=>f(t.id)})})]}),i==="tokens"&&(0,_jsxRuntime.jsxs)(_reactNative.ScrollView,{style:_notificationStyles.styles.fill,contentContainerStyle:[_notificationStyles.styles.content,{paddingBottom:m.bottom}],keyboardShouldPersistTaps:"handled",children:[(0,_jsxRuntime.jsxs)(_reactNative.View,{children:[(0,_jsxRuntime.jsx)(Action,{label:"Back to settings",onPress:()=>g("setup")}),(0,_jsxRuntime.jsx)(_sharedUi.NightSectionLabel,{children:"Registration"}),(0,_jsxRuntime.jsxs)(_sharedUi.NightCard,{glass:true,padded:true,children:[(0,_jsxRuntime.jsx)(_reactNative.Text,{style:_notificationStyles.styles.bodyText,children:"Register a token to test delivery through your push provider."}),(0,_jsxRuntime.jsxs)(_reactNative.View,{style:_notificationStyles.styles.actionRow,children:[(0,_jsxRuntime.jsx)(Action,{label:"Register device token",onPress:()=>{void j("refreshToken",{type:"device"})},disabled:d,primary:true}),(0,_jsxRuntime.jsx)(Action,{label:"Register Expo token",onPress:()=>{void j("refreshToken",{type:"expo"})},disabled:d||!e.capabilities.includes("expo-token")})]})]}),(0,_jsxRuntime.jsx)(_reactNative.Text,{style:_notificationStyles.styles.footnote,children:"Registration runs only when you or your app request it. Simulator sends work without a token."})]}),e.tokens.length===0?(0,_jsxRuntime.jsx)(_sharedUi.ToolEmptyState,{otto:"listening",title:"No tokens observed",message:"Register a device token above, or let your app register one."}):e.tokens.map((t,p)=>(0,_jsxRuntime.jsxs)(_reactNative.View,{children:[(0,_jsxRuntime.jsx)(_sharedUi.NightSectionLabel,{children:t.type.toUpperCase()+" token"}),(0,_jsxRuntime.jsxs)(_sharedUi.NightCard,{glass:true,padded:true,children:[(0,_jsxRuntime.jsxs)(_reactNative.View,{style:_notificationStyles.styles.actionRow,children:[(0,_jsxRuntime.jsx)(_sharedUi.NightBadge,{label:t.type,tone:"accent"}),t.environment&&(0,_jsxRuntime.jsx)(_reactNative.Text,{style:_notificationStyles.styles.caption,children:t.environment})]}),(0,_jsxRuntime.jsx)(_reactNative.Text,{selectable:true,style:_notificationStyles.styles.token,children:t.value}),t.projectId&&(0,_jsxRuntime.jsxs)(_reactNative.Text,{selectable:true,style:_notificationStyles.styles.caption,children:["Project: ",t.projectId]}),(0,_jsxRuntime.jsxs)(_reactNative.Text,{style:_notificationStyles.styles.caption,children:["Observed ",new Date(t.observedAt).toLocaleString()]}),(0,_jsxRuntime.jsx)(_reactNative.View,{style:_notificationStyles.styles.actionRow,children:(0,_jsxRuntime.jsx)(Action,{label:"Copy "+t.type.toUpperCase()+" token",onPress:()=>{void L(t.value)},icon:(0,_jsxRuntime.jsx)(_sharedUi.Copy,{size:14,color:_sharedUi.night.color.accent})})})]})]},t.type+"-"+p))]}),i==="setup"&&(0,_jsxRuntime.jsxs)(_reactNative.ScrollView,{style:_notificationStyles.styles.fill,contentContainerStyle:[_notificationStyles.styles.content,{paddingBottom:m.bottom}],keyboardShouldPersistTaps:"handled",children:[(0,_jsxRuntime.jsxs)(_reactNative.View,{children:[(0,_jsxRuntime.jsx)(Action,{label:"Device tokens",onPress:()=>g("tokens")}),(0,_jsxRuntime.jsx)(_sharedUi.NightSectionLabel,{children:"Capture session"}),(0,_jsxRuntime.jsxs)(_sharedUi.NightCard,{glass:true,padded:true,children:[(0,_jsxRuntime.jsxs)(_reactNative.View,{style:_notificationStyles.styles.actionRow,children:[(0,_jsxRuntime.jsx)(_sharedUi.NightBadge,{label:c?"Recording":"Stopped",tone:c?"accent":"neutral"}),(0,_jsxRuntime.jsx)(_reactNative.Text,{style:_notificationStyles.styles.caption,children:c?"Until "+new Date(h).toLocaleTimeString():"Ready when you are"})]}),(0,_jsxRuntime.jsxs)(_reactNative.View,{style:_notificationStyles.styles.actionRow,children:[(0,_jsxRuntime.jsx)(Action,{label:"Arm capture for 30 minutes",onPress:P,disabled:d,primary:true}),(0,_jsxRuntime.jsx)(Action,{label:"Stop capture",onPress:V,disabled:d||!c})]})]}),(0,_jsxRuntime.jsx)(_reactNative.Text,{style:_notificationStyles.styles.footnote,children:e.durable?"History is saved on the app and survives app and desktop restarts.":"History is held in memory. Keep the app running to retain it."})]}),(0,_jsxRuntime.jsxs)(_reactNative.View,{children:[(0,_jsxRuntime.jsx)(_sharedUi.NightSectionLabel,{children:"Connected app"}),(0,_jsxRuntime.jsx)(_sharedUi.NightCard,{glass:true,children:(0,_jsxRuntime.jsxs)(_sharedUi.NightRows,{children:[(0,_jsxRuntime.jsx)(Field,{label:"App",value:e.appId??"Not supplied"}),(0,_jsxRuntime.jsx)(Field,{label:"Provider",value:[e.provider,e.providerVersion].filter(Boolean).join(" ")}),(0,_jsxRuntime.jsx)(Field,{label:"Platform",value:e.platform})]})})]}),(0,_jsxRuntime.jsxs)(_reactNative.View,{children:[(0,_jsxRuntime.jsx)(_sharedUi.NightSectionLabel,{children:"Permissions"}),(0,_jsxRuntime.jsx)(_reactNative.View,{style:_notificationStyles.styles.sectionActions,children:(0,_jsxRuntime.jsx)(Action,{label:"Refresh permissions",disabled:d,onPress:()=>{void j("getPermissions")}})}),(0,_jsxRuntime.jsx)(JsonCard,{title:"Permission settings",value:e.permissions})]}),(0,_jsxRuntime.jsxs)(_reactNative.View,{children:[(0,_jsxRuntime.jsx)(_sharedUi.NightSectionLabel,{children:"System tray"}),(0,_jsxRuntime.jsx)(_reactNative.View,{style:_notificationStyles.styles.sectionActions,children:(0,_jsxRuntime.jsx)(Action,{label:"Inspect system tray",disabled:d||!e.capabilities.includes("presented"),onPress:()=>{void j("listPresented")}})}),(0,_jsxRuntime.jsx)(JsonCard,{title:"Currently presented",value:e.presented}),(0,_jsxRuntime.jsx)(_reactNative.Text,{style:_notificationStyles.styles.footnote,children:"Notifications currently in the system tray. Captured history is in Activity."})]}),(0,_jsxRuntime.jsxs)(_reactNative.View,{children:[(0,_jsxRuntime.jsx)(_sharedUi.NightSectionLabel,{children:"Capabilities"}),(0,_jsxRuntime.jsx)(_sharedUi.NightCard,{glass:true,padded:true,children:(0,_jsxRuntime.jsx)(_reactNative.View,{style:_notificationStyles.styles.actionRow,children:e.capabilities.map(t=>(0,_jsxRuntime.jsx)(_sharedUi.NightBadge,{label:t},t))})})]})]})]})]});return(0,_jsxRuntime.jsx)(_jsxRuntime.Fragment,{children:y?y({header:R,body:I}):(0,_jsxRuntime.jsxs)(_reactNative.View,{style:_notificationStyles.styles.root,children:[(0,_jsxRuntime.jsx)(_reactNative.View,{style:_notificationStyles.styles.inlineHeader,children:R}),I]})})}function EventRow({event:e,onPress:a}){const o=eventTone(e.kind);const r=o==="danger"?_sharedUi.night.color.danger:o==="warning"?_sharedUi.night.color.warning:o==="accent"?_sharedUi.night.color.accent:_sharedUi.night.color.textSecondary;return(0,_jsxRuntime.jsxs)(_reactNative.Pressable,{accessibilityRole:"button",accessibilityLabel:(labels[e.kind]??e.kind)+": "+(e.title??e.testId??e.notificationId??"notification"),onPress:a,style:({pressed:s})=>[_notificationStyles.styles.event,s&&_notificationStyles.styles.pressed],children:[(0,_jsxRuntime.jsxs)(_reactNative.View,{style:_notificationStyles.styles.eventTop,children:[(0,_jsxRuntime.jsxs)(_reactNative.View,{style:_notificationStyles.styles.eventKind,children:[(0,_jsxRuntime.jsx)(_sharedUi.NotificationsIcon,{size:13,color:r}),(0,_jsxRuntime.jsx)(_reactNative.Text,{numberOfLines:1,style:[_notificationStyles.styles.eventLabel,{color:r}],children:labels[e.kind]??e.kind})]}),(0,_jsxRuntime.jsx)(_reactNative.Text,{style:_notificationStyles.styles.timestamp,children:new Date(e.capturedAt).toLocaleTimeString()})]}),(0,_jsxRuntime.jsxs)(_reactNative.View,{style:_notificationStyles.styles.eventSubject,children:[(0,_jsxRuntime.jsx)(_reactNative.Text,{numberOfLines:1,style:_notificationStyles.styles.eventTitle,children:e.title??e.testId??e.notificationId??"Notification event"}),(0,_jsxRuntime.jsx)(_sharedUi.ChevronRight,{size:14,color:_sharedUi.night.color.textTertiary})]}),(0,_jsxRuntime.jsxs)(_reactNative.Text,{numberOfLines:1,style:_notificationStyles.styles.eventMeta,children:[e.observedAppState,e.truncated?" \xB7 Truncated":""]})]})}
1
+ "use strict";Object.defineProperty(exports,"__esModule",{value:true});exports.NotificationToolView=NotificationToolView;var _react=_interopRequireWildcard(require("react"));var _reactNative=require("react-native");var _sharedUi=require("@buoy-gg/shared-ui");var _dataViewer=require("@buoy-gg/shared-ui/dataViewer");var _LocalNotificationTest=require("./LocalNotificationTest");var _notificationStyles=require("./notificationStyles");var _jsxRuntime=require("react/jsx-runtime");function _interopRequireWildcard(e,a){if("function"==typeof WeakMap)var o=new WeakMap,r=new WeakMap;return(_interopRequireWildcard=function(s,d){if(!d&&s&&s.__esModule)return s;var u,x,i={__proto__:null,default:s};if(null===s||"object"!=typeof s&&"function"!=typeof s)return i;if(u=d?r:o){if(u.has(s))return u.get(s);u.set(s,i)}for(const l in s)"default"!==l&&{}.hasOwnProperty.call(s,l)&&((x=(u=Object.defineProperty)&&Object.getOwnPropertyDescriptor(s,l))&&(x.get||x.set)?u(i,l,x):i[l]=s[l]);return i})(e,a)}const labels={received:"App received",response:"Notification response","startup-response":"Response recovered at startup","presentation-decision":"Presentation decision","presentation-error":"Presentation error","background-started":"Background task started","background-completed":"Background task completed","background-error":"Background task failed","app-outcome":"App outcome","local-scheduled":"Local notification scheduled"};function eventTone(e){return e.includes("error")?"danger":e==="startup-response"?"warning":e==="received"||e==="app-outcome"?"accent":"neutral"}function Action({label:e,onPress:a,disabled:o,primary:r,icon:s}){return(0,_jsxRuntime.jsxs)(_reactNative.Pressable,{accessibilityRole:"button",accessibilityLabel:e,accessibilityState:{disabled:!!o},disabled:o,onPress:a,style:({pressed:d})=>[_notificationStyles.styles.button,r&&_notificationStyles.styles.primaryButton,d&&_notificationStyles.styles.pressed,o&&_notificationStyles.styles.disabled],children:[s,(0,_jsxRuntime.jsx)(_reactNative.Text,{style:[_notificationStyles.styles.buttonText,r&&_notificationStyles.styles.primaryButtonText],children:e})]})}function Field({label:e,value:a}){return(0,_jsxRuntime.jsxs)(_reactNative.View,{style:_notificationStyles.styles.field,children:[(0,_jsxRuntime.jsx)(_reactNative.Text,{style:[_notificationStyles.styles.caption,_notificationStyles.styles.fieldLabel],children:e}),(0,_jsxRuntime.jsx)(_reactNative.Text,{selectable:true,style:_notificationStyles.styles.value,children:a})]})}function JsonCard({title:e,value:a,initiallyOpen:o=true}){const[r,s]=(0,_react.useState)(o);const d=JSON.stringify(a??null);const u=(0,_react.useMemo)(()=>JSON.parse(d),[d]);return(0,_jsxRuntime.jsxs)(_sharedUi.NightCard,{glass:true,children:[(0,_jsxRuntime.jsxs)(_reactNative.Pressable,{accessibilityRole:"button",accessibilityLabel:e,accessibilityState:{expanded:r},onPress:()=>s(x=>!x),style:_notificationStyles.styles.disclosure,children:[(0,_jsxRuntime.jsx)(_reactNative.Text,{style:_notificationStyles.styles.disclosureTitle,children:e}),r?(0,_jsxRuntime.jsx)(_sharedUi.ChevronDown,{size:14,color:_sharedUi.night.color.textSecondary}):(0,_jsxRuntime.jsx)(_sharedUi.ChevronRight,{size:14,color:_sharedUi.night.color.textSecondary})]}),r&&(0,_jsxRuntime.jsx)(_reactNative.View,{style:_notificationStyles.styles.jsonBody,children:(0,_jsxRuntime.jsx)(_dataViewer.DataViewer,{title:"",data:u,rawMode:true,initialExpanded:true,showTypeFilter:false})})]})}function NotificationToolView({snapshot:e,onAction:a,sender:o,activeTab:r,onTabChange:s,renderShell:d}){const[u,x]=(0,_react.useState)("send");const i=r??u;const[l,C]=(0,_react.useState)("");const[A,f]=(0,_react.useState)(null);const[y,N]=(0,_react.useState)(false);const[v,w]=(0,_react.useState)(null);const[,D]=(0,_react.useState)(0);const m=(0,_sharedUi.useSafeAreaInsets)({minBottom:16});const h=e?.session?.expiresAt;(0,_react.useEffect)(()=>{if(!h||h<=Date.now())return;const t=setTimeout(()=>D(p=>p+1),h-Date.now()+1);return()=>clearTimeout(t)},[h]);const c=!!h&&h>Date.now();const k=(0,_react.useMemo)(()=>(e?.events??[]).filter(t=>JSON.stringify(t).toLowerCase().includes(l.trim().toLowerCase())).slice().reverse(),[e?.events,l]);const n=e?.events.find(t=>t.id===A);const b=e?.events.length??0;const T=!!e?.provider;function g(t){x(t);s?.(t);w(null)}async function j(t,p){if(y)return false;N(true);w(null);try{await a(t,p);return true}catch(S){w({text:S instanceof Error?S.message:String(S),error:true});return false}finally{N(false)}}const P=()=>{void j("setCaptureSession",{runId:`capture-${Date.now()}`,durationMs:18e5})};const V=()=>{void j("setCaptureSession",{runId:null})};async function L(t){const p=await(0,_sharedUi.copyToClipboard)(t);w({text:p?"Copied to clipboard.":"Clipboard is unavailable. Select the text to copy it.",error:!p})}const M=[{key:"send",label:"Test"},{key:"events",label:`Activity (${b})`}];const R=(0,_jsxRuntime.jsx)(_sharedUi.NightSegmented,{tabs:M,activeKey:i,onChange:g,size:"sm",glass:true});const I=(0,_jsxRuntime.jsxs)(_sharedUi.ModalHeader,{children:[(0,_jsxRuntime.jsx)(_sharedUi.ModalHeader.Content,{title:"",noMargin:true,children:d?R:(0,_jsxRuntime.jsx)(_reactNative.View,{style:_notificationStyles.styles.tabsCap,children:R})}),(0,_jsxRuntime.jsxs)(_sharedUi.ModalHeader.Actions,{children:[(0,_jsxRuntime.jsx)(_reactNative.Pressable,{accessibilityRole:"button",accessibilityLabel:"Notification settings",onPress:()=>g(i==="setup"||i==="tokens"?"send":"setup"),style:_notificationStyles.styles.iconButton,children:(0,_jsxRuntime.jsx)(_sharedUi.Settings,{size:16,color:i==="setup"||i==="tokens"?_sharedUi.night.color.accent:_sharedUi.night.color.textSecondary})}),i!=="send"&&(0,_jsxRuntime.jsx)(_sharedUi.PowerToggleButton,{isEnabled:c,onToggle:c?V:P,disabled:!T||y,accessibilityLabel:c?"Stop notification capture":"Start notification capture",testID:"notifications-capture"})]})]});const B=(0,_jsxRuntime.jsxs)(_reactNative.View,{style:_notificationStyles.styles.root,children:[T&&i!=="send"&&(0,_jsxRuntime.jsxs)(_reactNative.View,{style:_notificationStyles.styles.status,children:[(0,_jsxRuntime.jsxs)(_reactNative.View,{style:_notificationStyles.styles.statusLabel,children:[(0,_jsxRuntime.jsx)(_reactNative.View,{style:[_notificationStyles.styles.dot,c&&_notificationStyles.styles.liveDot]}),(0,_jsxRuntime.jsx)(_reactNative.Text,{style:_notificationStyles.styles.caption,children:c?"Recording":"Capture stopped"})]}),i!=="events"&&(0,_jsxRuntime.jsx)(_reactNative.Text,{style:_notificationStyles.styles.caption,children:e.durable?"Persistent history":"Memory only"}),i!=="events"&&(0,_jsxRuntime.jsxs)(_reactNative.Text,{style:_notificationStyles.styles.provider,children:[e.provider," \xB7 ",e.platform]})]}),e?.storageError&&(0,_jsxRuntime.jsxs)(_reactNative.Text,{accessibilityRole:"alert",style:_notificationStyles.styles.errorNotice,children:["Storage: ",e.storageError]}),v&&(0,_jsxRuntime.jsx)(_reactNative.Text,{accessibilityRole:v.error?"alert":"text",style:[_notificationStyles.styles.notice,v.error&&_notificationStyles.styles.errorText],children:v.text}),!o&&(0,_jsxRuntime.jsx)(_reactNative.View,{style:i==="send"?_notificationStyles.styles.fill:{display:"none"},children:(0,_jsxRuntime.jsx)(_LocalNotificationTest.LocalNotificationTest,{snapshot:e,onAction:a,onViewActivity:()=>g("events")})}),i==="send"?o??null:!T?(0,_jsxRuntime.jsxs)(_reactNative.ScrollView,{children:[(0,_jsxRuntime.jsx)(_sharedUi.ToolEmptyState,{otto:"paused",title:"Connect notification capture",message:"Install @buoy-gg/notifications and call installExpoNotificationCapture in the app entry point. Use an app-specific development build for remote notifications."}),(0,_jsxRuntime.jsx)(_reactNative.Text,{style:_notificationStyles.styles.emptyFootnote,children:"The desktop sender works with any installed app. Inspection needs the capture integration."})]}):(0,_jsxRuntime.jsxs)(_jsxRuntime.Fragment,{children:[i==="events"&&(0,_jsxRuntime.jsxs)(_jsxRuntime.Fragment,{children:[(0,_jsxRuntime.jsxs)(_reactNative.View,{style:_notificationStyles.styles.searchRow,children:[(0,_jsxRuntime.jsxs)(_reactNative.View,{style:_notificationStyles.styles.searchField,children:[(0,_jsxRuntime.jsx)(_sharedUi.Search,{size:14,color:_sharedUi.night.color.textSecondary}),(0,_jsxRuntime.jsx)(_reactNative.TextInput,{accessibilityLabel:"Filter notification events",placeholder:"Search notifications\u2026",placeholderTextColor:_sharedUi.night.color.placeholder,value:l,onChangeText:t=>{C(t);f(null)},autoCapitalize:"none",autoCorrect:false,style:_notificationStyles.styles.searchInput}),!!l&&(0,_jsxRuntime.jsx)(_reactNative.Pressable,{accessibilityRole:"button",accessibilityLabel:"Clear notification search",onPress:()=>C(""),style:_notificationStyles.styles.clearSearch,children:(0,_jsxRuntime.jsx)(_sharedUi.X,{size:12,color:_sharedUi.night.color.textSecondary})})]}),(0,_jsxRuntime.jsx)(_reactNative.Pressable,{accessibilityRole:"button",accessibilityLabel:"Clear captured events",disabled:y||!b,accessibilityState:{disabled:y||!b},style:[_notificationStyles.styles.iconButton,(y||!b)&&_notificationStyles.styles.disabled],onPress:()=>{void j("clearCapturedEvents").then(t=>{if(t)f(null)})},children:(0,_jsxRuntime.jsx)(_sharedUi.Trash2,{size:14,color:_sharedUi.night.color.textSecondary})})]}),n?(0,_jsxRuntime.jsxs)(_reactNative.ScrollView,{style:_notificationStyles.styles.fill,contentContainerStyle:[_notificationStyles.styles.content,{paddingBottom:m.bottom}],keyboardShouldPersistTaps:"handled",children:[(0,_jsxRuntime.jsxs)(_reactNative.View,{style:_notificationStyles.styles.actionRow,children:[(0,_jsxRuntime.jsx)(Action,{label:"Back to events",onPress:()=>f(null),icon:(0,_jsxRuntime.jsx)(_sharedUi.ChevronLeft,{size:14,color:_sharedUi.night.color.accent})}),(0,_jsxRuntime.jsx)(Action,{label:"Copy event JSON",onPress:()=>{void L(n)},icon:(0,_jsxRuntime.jsx)(_sharedUi.Copy,{size:14,color:_sharedUi.night.color.accent})})]}),(0,_jsxRuntime.jsxs)(_sharedUi.NightCard,{glass:true,padded:true,children:[(0,_jsxRuntime.jsx)(_sharedUi.NightBadge,{label:labels[n.kind]??n.kind,tone:eventTone(n.kind)}),(0,_jsxRuntime.jsx)(_reactNative.Text,{style:_notificationStyles.styles.detailTitle,children:n.title??"Notification event"}),(0,_jsxRuntime.jsx)(_reactNative.Text,{style:_notificationStyles.styles.caption,children:new Date(n.capturedAt).toLocaleString()})]}),(0,_jsxRuntime.jsxs)(_reactNative.View,{children:[(0,_jsxRuntime.jsx)(_sharedUi.NightSectionLabel,{children:"Observation"}),(0,_jsxRuntime.jsx)(_sharedUi.NightCard,{glass:true,children:(0,_jsxRuntime.jsxs)(_sharedUi.NightRows,{children:[(0,_jsxRuntime.jsx)(Field,{label:"App state at callback",value:n.observedAppState}),n.testId&&(0,_jsxRuntime.jsx)(Field,{label:"Test ID",value:n.testId}),n.notificationId&&(0,_jsxRuntime.jsx)(Field,{label:"Notification ID",value:n.notificationId}),n.actionIdentifier&&(0,_jsxRuntime.jsx)(Field,{label:"Action",value:n.actionIdentifier})]})})]}),n.kind==="startup-response"&&(0,_jsxRuntime.jsx)(_reactNative.Text,{style:_notificationStyles.styles.footnote,children:"Recovered from the SDK cache. This alone does not establish why the app launched."}),n.truncated&&(0,_jsxRuntime.jsx)(_reactNative.Text,{style:_notificationStyles.styles.warning,children:"This payload was truncated when captured."}),(0,_jsxRuntime.jsx)(JsonCard,{title:"Payload",value:n.raw}),(0,_jsxRuntime.jsx)(JsonCard,{title:"Full event",value:n,initiallyOpen:false})]}):(0,_jsxRuntime.jsx)(_reactNative.FlatList,{data:k,keyExtractor:t=>t.id,style:_notificationStyles.styles.fill,contentContainerStyle:[_notificationStyles.styles.eventList,{paddingBottom:m.bottom}],keyboardShouldPersistTaps:"handled",initialNumToRender:15,ListHeaderComponent:l?(0,_jsxRuntime.jsxs)(_reactNative.Text,{style:_notificationStyles.styles.resultCount,children:[k.length," of ",b," events"]}):null,ListFooterComponent:e.evicted>0?(0,_jsxRuntime.jsxs)(_reactNative.Text,{style:_notificationStyles.styles.footnote,children:[e.evicted," older records removed by the history limit."]}):null,ListEmptyComponent:(0,_jsxRuntime.jsx)(_sharedUi.ToolEmptyState,{otto:l?"sad":c?"listening":"paused",title:l?"No matching events":c?"Waiting for notifications":"Capture is stopped",message:l?"Try another title, test ID, or payload value.":c?"Send a notification from Buoy Desktop or your app. Background alerts can reach the system tray before an app callback runs.":"Start capture with the power button, then send a notification."}),renderItem:({item:t})=>(0,_jsxRuntime.jsx)(EventRow,{event:t,onPress:()=>f(t.id)})})]}),i==="tokens"&&(0,_jsxRuntime.jsxs)(_reactNative.ScrollView,{style:_notificationStyles.styles.fill,contentContainerStyle:[_notificationStyles.styles.content,{paddingBottom:m.bottom}],keyboardShouldPersistTaps:"handled",children:[(0,_jsxRuntime.jsxs)(_reactNative.View,{children:[(0,_jsxRuntime.jsx)(Action,{label:"Back to settings",onPress:()=>g("setup")}),(0,_jsxRuntime.jsx)(_sharedUi.NightSectionLabel,{children:"Registration"}),(0,_jsxRuntime.jsxs)(_sharedUi.NightCard,{glass:true,padded:true,children:[(0,_jsxRuntime.jsx)(_reactNative.Text,{style:_notificationStyles.styles.bodyText,children:"Register a token to test delivery through your push provider."}),(0,_jsxRuntime.jsxs)(_reactNative.View,{style:_notificationStyles.styles.actionRow,children:[(0,_jsxRuntime.jsx)(Action,{label:"Register device token",onPress:()=>{void j("refreshToken",{type:"device"})},disabled:y,primary:true}),(0,_jsxRuntime.jsx)(Action,{label:"Register Expo token",onPress:()=>{void j("refreshToken",{type:"expo"})},disabled:y||!e.capabilities.includes("expo-token")})]})]}),(0,_jsxRuntime.jsx)(_reactNative.Text,{style:_notificationStyles.styles.footnote,children:"Registration runs only when you or your app request it. Simulator sends work without a token."})]}),e.tokens.length===0?(0,_jsxRuntime.jsx)(_sharedUi.ToolEmptyState,{otto:"listening",title:"No tokens observed",message:"Register a device token above, or let your app register one."}):e.tokens.map((t,p)=>(0,_jsxRuntime.jsxs)(_reactNative.View,{children:[(0,_jsxRuntime.jsx)(_sharedUi.NightSectionLabel,{children:t.type.toUpperCase()+" token"}),(0,_jsxRuntime.jsxs)(_sharedUi.NightCard,{glass:true,padded:true,children:[(0,_jsxRuntime.jsxs)(_reactNative.View,{style:_notificationStyles.styles.actionRow,children:[(0,_jsxRuntime.jsx)(_sharedUi.NightBadge,{label:t.type,tone:"accent"}),t.environment&&(0,_jsxRuntime.jsx)(_reactNative.Text,{style:_notificationStyles.styles.caption,children:t.environment})]}),(0,_jsxRuntime.jsx)(_reactNative.Text,{selectable:true,style:_notificationStyles.styles.token,children:t.value}),t.projectId&&(0,_jsxRuntime.jsxs)(_reactNative.Text,{selectable:true,style:_notificationStyles.styles.caption,children:["Project: ",t.projectId]}),(0,_jsxRuntime.jsxs)(_reactNative.Text,{style:_notificationStyles.styles.caption,children:["Observed ",new Date(t.observedAt).toLocaleString()]}),(0,_jsxRuntime.jsx)(_reactNative.View,{style:_notificationStyles.styles.actionRow,children:(0,_jsxRuntime.jsx)(Action,{label:"Copy "+t.type.toUpperCase()+" token",onPress:()=>{void L(t.value)},icon:(0,_jsxRuntime.jsx)(_sharedUi.Copy,{size:14,color:_sharedUi.night.color.accent})})})]})]},t.type+"-"+p))]}),i==="setup"&&(0,_jsxRuntime.jsxs)(_reactNative.ScrollView,{style:_notificationStyles.styles.fill,contentContainerStyle:[_notificationStyles.styles.content,{paddingBottom:m.bottom}],keyboardShouldPersistTaps:"handled",children:[(0,_jsxRuntime.jsxs)(_reactNative.View,{children:[(0,_jsxRuntime.jsx)(Action,{label:"Device tokens",onPress:()=>g("tokens")}),(0,_jsxRuntime.jsx)(_sharedUi.NightSectionLabel,{children:"Capture session"}),(0,_jsxRuntime.jsxs)(_sharedUi.NightCard,{glass:true,padded:true,children:[(0,_jsxRuntime.jsxs)(_reactNative.View,{style:_notificationStyles.styles.actionRow,children:[(0,_jsxRuntime.jsx)(_sharedUi.NightBadge,{label:c?"Recording":"Stopped",tone:c?"accent":"neutral"}),(0,_jsxRuntime.jsx)(_reactNative.Text,{style:_notificationStyles.styles.caption,children:c?"Until "+new Date(h).toLocaleTimeString():"Ready when you are"})]}),(0,_jsxRuntime.jsxs)(_reactNative.View,{style:_notificationStyles.styles.actionRow,children:[(0,_jsxRuntime.jsx)(Action,{label:"Arm capture for 30 minutes",onPress:P,disabled:y,primary:true}),(0,_jsxRuntime.jsx)(Action,{label:"Stop capture",onPress:V,disabled:y||!c})]})]}),(0,_jsxRuntime.jsx)(_reactNative.Text,{style:_notificationStyles.styles.footnote,children:e.durable?"History is saved on the app and survives app and desktop restarts.":"History is held in memory. Keep the app running to retain it."})]}),(0,_jsxRuntime.jsxs)(_reactNative.View,{children:[(0,_jsxRuntime.jsx)(_sharedUi.NightSectionLabel,{children:"Connected app"}),(0,_jsxRuntime.jsx)(_sharedUi.NightCard,{glass:true,children:(0,_jsxRuntime.jsxs)(_sharedUi.NightRows,{children:[(0,_jsxRuntime.jsx)(Field,{label:"App",value:e.appId??"Not supplied"}),(0,_jsxRuntime.jsx)(Field,{label:"Provider",value:[e.provider,e.providerVersion].filter(Boolean).join(" ")}),(0,_jsxRuntime.jsx)(Field,{label:"Platform",value:e.platform})]})})]}),(0,_jsxRuntime.jsxs)(_reactNative.View,{children:[(0,_jsxRuntime.jsx)(_sharedUi.NightSectionLabel,{children:"Permissions"}),(0,_jsxRuntime.jsx)(_reactNative.View,{style:_notificationStyles.styles.sectionActions,children:(0,_jsxRuntime.jsx)(Action,{label:"Refresh permissions",disabled:y,onPress:()=>{void j("getPermissions")}})}),(0,_jsxRuntime.jsx)(JsonCard,{title:"Permission settings",value:e.permissions})]}),(0,_jsxRuntime.jsxs)(_reactNative.View,{children:[(0,_jsxRuntime.jsx)(_sharedUi.NightSectionLabel,{children:"System tray"}),(0,_jsxRuntime.jsx)(_reactNative.View,{style:_notificationStyles.styles.sectionActions,children:(0,_jsxRuntime.jsx)(Action,{label:"Inspect system tray",disabled:y||!e.capabilities.includes("presented"),onPress:()=>{void j("listPresented")}})}),(0,_jsxRuntime.jsx)(JsonCard,{title:"Currently presented",value:e.presented}),(0,_jsxRuntime.jsx)(_reactNative.Text,{style:_notificationStyles.styles.footnote,children:"Notifications currently in the system tray. Captured history is in Activity."})]}),(0,_jsxRuntime.jsxs)(_reactNative.View,{children:[(0,_jsxRuntime.jsx)(_sharedUi.NightSectionLabel,{children:"Capabilities"}),(0,_jsxRuntime.jsx)(_sharedUi.NightCard,{glass:true,padded:true,children:(0,_jsxRuntime.jsx)(_reactNative.View,{style:_notificationStyles.styles.actionRow,children:e.capabilities.map(t=>(0,_jsxRuntime.jsx)(_sharedUi.NightBadge,{label:t},t))})})]})]})]})]});return(0,_jsxRuntime.jsx)(_jsxRuntime.Fragment,{children:d?d({header:I,body:B}):(0,_jsxRuntime.jsxs)(_reactNative.View,{style:_notificationStyles.styles.root,children:[(0,_jsxRuntime.jsx)(_reactNative.View,{style:_notificationStyles.styles.inlineHeader,..._sharedUi.windowDragProps,children:I}),B]})})}function EventRow({event:e,onPress:a}){const o=eventTone(e.kind);const r=o==="danger"?_sharedUi.night.color.danger:o==="warning"?_sharedUi.night.color.warning:o==="accent"?_sharedUi.night.color.accent:_sharedUi.night.color.textSecondary;return(0,_jsxRuntime.jsxs)(_reactNative.Pressable,{accessibilityRole:"button",accessibilityLabel:(labels[e.kind]??e.kind)+": "+(e.title??e.testId??e.notificationId??"notification"),onPress:a,style:({pressed:s})=>[_notificationStyles.styles.event,s&&_notificationStyles.styles.pressed],children:[(0,_jsxRuntime.jsxs)(_reactNative.View,{style:_notificationStyles.styles.eventTop,children:[(0,_jsxRuntime.jsxs)(_reactNative.View,{style:_notificationStyles.styles.eventKind,children:[(0,_jsxRuntime.jsx)(_sharedUi.NotificationsIcon,{size:13,color:r}),(0,_jsxRuntime.jsx)(_reactNative.Text,{numberOfLines:1,style:[_notificationStyles.styles.eventLabel,{color:r}],children:labels[e.kind]??e.kind})]}),(0,_jsxRuntime.jsx)(_reactNative.Text,{style:_notificationStyles.styles.timestamp,children:new Date(e.capturedAt).toLocaleTimeString()})]}),(0,_jsxRuntime.jsxs)(_reactNative.View,{style:_notificationStyles.styles.eventSubject,children:[(0,_jsxRuntime.jsx)(_reactNative.Text,{numberOfLines:1,style:_notificationStyles.styles.eventTitle,children:e.title??e.testId??e.notificationId??"Notification event"}),(0,_jsxRuntime.jsx)(_sharedUi.ChevronRight,{size:14,color:_sharedUi.night.color.textTertiary})]}),(0,_jsxRuntime.jsxs)(_reactNative.Text,{numberOfLines:1,style:_notificationStyles.styles.eventMeta,children:[e.observedAppState,e.truncated?" \xB7 Truncated":""]})]})}
@@ -1 +1 @@
1
- "use strict";Object.defineProperty(exports,"__esModule",{value:true});exports.styles=void 0;var _reactNative=require("react-native");var _sharedUi=require("@buoy-gg/shared-ui");const styles=exports.styles=_reactNative.StyleSheet.create({root:{flex:1,minHeight:0,backgroundColor:"transparent"},fill:{flex:1,minHeight:0},inlineHeader:{paddingHorizontal:12,paddingVertical:8,borderBottomWidth:1,borderBottomColor:_sharedUi.night.color.separator},status:{flexDirection:"row",alignItems:"center",flexWrap:"wrap",gap:12,paddingHorizontal:16,paddingVertical:9},statusLabel:{flexDirection:"row",alignItems:"center",gap:6},dot:{width:5,height:5,borderRadius:3,backgroundColor:_sharedUi.night.color.textTertiary},liveDot:{backgroundColor:_sharedUi.night.color.accent},caption:{color:_sharedUi.night.color.textSecondary,fontSize:12,lineHeight:17},provider:{color:_sharedUi.night.color.textSecondary,fontSize:11,marginLeft:"auto",fontFamily:_sharedUi.monoFont},content:{padding:14,gap:20},eventList:{paddingHorizontal:12,paddingTop:2},searchRow:{flexDirection:"row",gap:8,paddingHorizontal:12,paddingBottom:10,alignItems:"center"},searchField:{flex:1,minWidth:0,height:36,flexDirection:"row",alignItems:"center",gap:8,paddingHorizontal:10,backgroundColor:_sharedUi.night.color.glass,borderWidth:1,borderColor:_sharedUi.night.color.glassBorder,borderRadius:_sharedUi.night.radius.row},searchInput:{flex:1,minWidth:0,height:"100%",color:_sharedUi.night.color.text,fontSize:13,padding:0},clearSearch:{padding:6},iconButton:{width:34,height:34,alignItems:"center",justifyContent:"center",backgroundColor:_sharedUi.night.color.buttonSurface,borderRadius:8,borderWidth:1,borderColor:_sharedUi.night.color.border},event:{backgroundColor:_sharedUi.night.color.glass,borderRadius:_sharedUi.night.radius.input,borderWidth:1,borderColor:_sharedUi.night.color.glassBorder,paddingHorizontal:12,paddingVertical:10,marginBottom:6,gap:6},eventTop:{flexDirection:"row",alignItems:"center",gap:10,justifyContent:"space-between"},eventKind:{flexDirection:"row",alignItems:"center",gap:6,flex:1,minWidth:0},eventLabel:{flexShrink:1,fontSize:11,fontWeight:"600"},timestamp:{color:_sharedUi.night.color.textSecondary,fontFamily:_sharedUi.monoFont,fontSize:10},eventSubject:{flexDirection:"row",alignItems:"center",gap:8},eventTitle:{flex:1,color:_sharedUi.night.color.text,fontSize:15,fontWeight:"500"},eventMeta:{color:_sharedUi.night.color.textSecondary,fontFamily:_sharedUi.monoFont,fontSize:10,lineHeight:15},resultCount:{color:_sharedUi.night.color.textSecondary,fontSize:12,marginBottom:10,marginLeft:4},actionRow:{flexDirection:"row",alignItems:"center",flexWrap:"wrap",gap:8},button:{flexDirection:"row",alignItems:"center",justifyContent:"center",gap:6,minHeight:34,paddingVertical:8,paddingHorizontal:14,borderRadius:_sharedUi.night.radius.pill,backgroundColor:_sharedUi.night.color.fillSecondary,alignSelf:"flex-start"},buttonText:{color:_sharedUi.night.color.accent,fontSize:13,fontWeight:"600"},primaryButton:{backgroundColor:_sharedUi.night.color.accent},primaryButtonText:{color:_sharedUi.night.color.onAccent},pressed:{opacity:.7},disabled:{opacity:.4},detailTitle:{color:_sharedUi.night.color.text,fontSize:20,fontWeight:"600"},field:{flexDirection:"row",paddingHorizontal:16,paddingVertical:12,gap:14},fieldLabel:{width:110,flexShrink:0},value:{flex:1,minWidth:0,color:_sharedUi.night.color.text,fontFamily:_sharedUi.monoFont,fontSize:12,lineHeight:18},disclosure:{flexDirection:"row",alignItems:"center",justifyContent:"space-between",paddingHorizontal:16,paddingVertical:14},disclosureTitle:{color:_sharedUi.night.color.text,fontSize:13,fontWeight:"500"},jsonBody:{padding:10,borderTopWidth:1,borderTopColor:_sharedUi.night.color.separator},token:{color:_sharedUi.night.color.text,fontFamily:_sharedUi.monoFont,fontSize:12,lineHeight:20},bodyText:{color:_sharedUi.night.color.text,fontSize:14,lineHeight:21},footnote:{color:_sharedUi.night.color.textSecondary,fontSize:12,lineHeight:18,marginTop:8,marginHorizontal:4},emptyFootnote:{color:_sharedUi.night.color.textSecondary,fontSize:12,lineHeight:18,textAlign:"center",marginHorizontal:28},sectionActions:{flexDirection:"row",marginBottom:10},warning:{color:_sharedUi.night.color.warning,fontSize:12,lineHeight:18},notice:{color:_sharedUi.night.color.accent,backgroundColor:_sharedUi.night.color.glass,paddingHorizontal:16,paddingVertical:10,fontSize:12,lineHeight:18},errorNotice:{color:_sharedUi.night.color.danger,backgroundColor:_sharedUi.night.color.glass,paddingHorizontal:16,paddingVertical:10,fontSize:12,lineHeight:18},errorText:{color:_sharedUi.night.color.danger}});
1
+ "use strict";Object.defineProperty(exports,"__esModule",{value:true});exports.styles=void 0;var _reactNative=require("react-native");var _sharedUi=require("@buoy-gg/shared-ui");const styles=exports.styles=_reactNative.StyleSheet.create({root:{flex:1,minHeight:0,backgroundColor:"transparent"},fill:{flex:1,minHeight:0},inlineHeader:{paddingHorizontal:12,paddingVertical:8,borderBottomWidth:1,borderBottomColor:_sharedUi.night.color.separator},status:{flexDirection:"row",alignItems:"center",flexWrap:"wrap",gap:12,paddingHorizontal:16,paddingVertical:9},statusLabel:{flexDirection:"row",alignItems:"center",gap:6},dot:{width:5,height:5,borderRadius:3,backgroundColor:_sharedUi.night.color.textTertiary},liveDot:{backgroundColor:_sharedUi.night.color.accent},caption:{color:_sharedUi.night.color.textSecondary,fontSize:12,lineHeight:17},provider:{color:_sharedUi.night.color.textSecondary,fontSize:11,marginLeft:"auto",fontFamily:_sharedUi.monoFont},content:{padding:14,gap:20},eventList:{paddingHorizontal:12,paddingTop:2},searchRow:{flexDirection:"row",gap:8,paddingHorizontal:12,paddingBottom:10,alignItems:"center"},searchField:{flex:1,minWidth:0,height:36,flexDirection:"row",alignItems:"center",gap:8,paddingHorizontal:10,backgroundColor:_sharedUi.night.color.glass,borderWidth:1,borderColor:_sharedUi.night.color.glassBorder,borderRadius:_sharedUi.night.radius.row},searchInput:{flex:1,minWidth:0,height:"100%",color:_sharedUi.night.color.text,fontSize:13,padding:0},clearSearch:{padding:6},tabsCap:{width:"100%",maxWidth:360},iconButton:{width:34,height:34,alignItems:"center",justifyContent:"center",backgroundColor:_sharedUi.night.color.buttonSurface,borderRadius:8,borderWidth:1,borderColor:_sharedUi.night.color.border},event:{backgroundColor:_sharedUi.night.color.glass,borderRadius:_sharedUi.night.radius.input,borderWidth:1,borderColor:_sharedUi.night.color.glassBorder,paddingHorizontal:12,paddingVertical:10,marginBottom:6,gap:6},eventTop:{flexDirection:"row",alignItems:"center",gap:10,justifyContent:"space-between"},eventKind:{flexDirection:"row",alignItems:"center",gap:6,flex:1,minWidth:0},eventLabel:{flexShrink:1,fontSize:11,fontWeight:"600"},timestamp:{color:_sharedUi.night.color.textSecondary,fontFamily:_sharedUi.monoFont,fontSize:10},eventSubject:{flexDirection:"row",alignItems:"center",gap:8},eventTitle:{flex:1,color:_sharedUi.night.color.text,fontSize:15,fontWeight:"500"},eventMeta:{color:_sharedUi.night.color.textSecondary,fontFamily:_sharedUi.monoFont,fontSize:10,lineHeight:15},resultCount:{color:_sharedUi.night.color.textSecondary,fontSize:12,marginBottom:10,marginLeft:4},actionRow:{flexDirection:"row",alignItems:"center",flexWrap:"wrap",gap:8},button:{flexDirection:"row",alignItems:"center",justifyContent:"center",gap:6,minHeight:34,paddingVertical:8,paddingHorizontal:14,borderRadius:_sharedUi.night.radius.pill,backgroundColor:_sharedUi.night.color.fillSecondary,alignSelf:"flex-start"},buttonText:{color:_sharedUi.night.color.accent,fontSize:13,fontWeight:"600"},primaryButton:{backgroundColor:_sharedUi.night.color.accent},primaryButtonText:{color:_sharedUi.night.color.onAccent},pressed:{opacity:.7},disabled:{opacity:.4},detailTitle:{color:_sharedUi.night.color.text,fontSize:20,fontWeight:"600"},field:{flexDirection:"row",paddingHorizontal:16,paddingVertical:12,gap:14},fieldLabel:{width:110,flexShrink:0},value:{flex:1,minWidth:0,color:_sharedUi.night.color.text,fontFamily:_sharedUi.monoFont,fontSize:12,lineHeight:18},disclosure:{flexDirection:"row",alignItems:"center",justifyContent:"space-between",paddingHorizontal:16,paddingVertical:14},disclosureTitle:{color:_sharedUi.night.color.text,fontSize:13,fontWeight:"500"},jsonBody:{padding:10,borderTopWidth:1,borderTopColor:_sharedUi.night.color.separator},token:{color:_sharedUi.night.color.text,fontFamily:_sharedUi.monoFont,fontSize:12,lineHeight:20},bodyText:{color:_sharedUi.night.color.text,fontSize:14,lineHeight:21},footnote:{color:_sharedUi.night.color.textSecondary,fontSize:12,lineHeight:18,marginTop:8,marginHorizontal:4},emptyFootnote:{color:_sharedUi.night.color.textSecondary,fontSize:12,lineHeight:18,textAlign:"center",marginHorizontal:28},sectionActions:{flexDirection:"row",marginBottom:10},warning:{color:_sharedUi.night.color.warning,fontSize:12,lineHeight:18},notice:{color:_sharedUi.night.color.accent,backgroundColor:_sharedUi.night.color.glass,paddingHorizontal:16,paddingVertical:10,fontSize:12,lineHeight:18},errorNotice:{color:_sharedUi.night.color.danger,backgroundColor:_sharedUi.night.color.glass,paddingHorizontal:16,paddingVertical:10,fontSize:12,lineHeight:18},errorText:{color:_sharedUi.night.color.danger}});
@@ -1 +1 @@
1
- "use strict";import ke,{useEffect as le,useMemo as Y,useState as k}from"react";import{FlatList as se,Pressable as P,ScrollView as D,Text as l,TextInput as ae,View as r}from"react-native";import{ChevronDown as ce,ChevronLeft as de,ChevronRight as Z,Copy as ee,ModalHeader as V,NightBadge as z,NightCard as g,NightRows as te,NightSectionLabel as v,NightSegmented as ue,NotificationsIcon as pe,PowerToggleButton as ye,Search as he,Settings as be,ToolEmptyState as H,Trash2 as fe,X as me,copyToClipboard as ge,night as a,useSafeAreaInsets as ve}from"@buoy-gg/shared-ui";import{DataViewer as Se}from"@buoy-gg/shared-ui/dataViewer";import{LocalNotificationTest as we}from"./LocalNotificationTest";import{styles as t}from"./notificationStyles";import{jsx as e,jsxs as o,Fragment as J}from"react/jsx-runtime";const K={received:"App received",response:"Notification response","startup-response":"Response recovered at startup","presentation-decision":"Presentation decision","presentation-error":"Presentation error","background-started":"Background task started","background-completed":"Background task completed","background-error":"Background task failed","app-outcome":"App outcome","local-scheduled":"Local notification scheduled"};function ie(i){return i.includes("error")?"danger":i==="startup-response"?"warning":i==="received"||i==="app-outcome"?"accent":"neutral"}function h({label:i,onPress:b,disabled:d,primary:p,icon:S}){return o(P,{accessibilityRole:"button",accessibilityLabel:i,accessibilityState:{disabled:!!d},disabled:d,onPress:b,style:({pressed:w})=>[t.button,p&&t.primaryButton,w&&t.pressed,d&&t.disabled],children:[S,e(l,{style:[t.buttonText,p&&t.primaryButtonText],children:i})]})}function x({label:i,value:b}){return o(r,{style:t.field,children:[e(l,{style:[t.caption,t.fieldLabel],children:i}),e(l,{selectable:true,style:t.value,children:b})]})}function E({title:i,value:b,initiallyOpen:d=true}){const[p,S]=k(d);const w=JSON.stringify(b??null);const F=Y(()=>JSON.parse(w),[w]);return o(g,{glass:true,children:[o(P,{accessibilityRole:"button",accessibilityLabel:i,accessibilityState:{expanded:p},onPress:()=>S(O=>!O),style:t.disclosure,children:[e(l,{style:t.disclosureTitle,children:i}),p?e(ce,{size:14,color:a.color.textSecondary}):e(Z,{size:14,color:a.color.textSecondary})]}),p&&e(r,{style:t.jsonBody,children:e(Se,{title:"",data:F,rawMode:true,initialExpanded:true,showTypeFilter:false})})]})}export function NotificationToolView({snapshot:i,onAction:b,sender:d,activeTab:p,onTabChange:S,renderShell:w}){const[F,O]=k("send");const c=p??F;const[f,U]=k("");const[oe,I]=k(null);const[y,_]=k(false);const[N,B]=k(null);const[,ne]=k(0);const A=ve({minBottom:16});const C=i?.session?.expiresAt;le(()=>{if(!C||C<=Date.now())return;const n=setTimeout(()=>ne(m=>m+1),C-Date.now()+1);return()=>clearTimeout(n)},[C]);const u=!!C&&C>Date.now();const $=Y(()=>(i?.events??[]).filter(n=>JSON.stringify(n).toLowerCase().includes(f.trim().toLowerCase())).slice().reverse(),[i?.events,f]);const s=i?.events.find(n=>n.id===oe);const R=i?.events.length??0;const j=!!i?.provider;function L(n){O(n);S?.(n);B(null)}async function T(n,m){if(y)return false;_(true);B(null);try{await b(n,m);return true}catch(M){B({text:M instanceof Error?M.message:String(M),error:true});return false}finally{_(false)}}const q=()=>{void T("setCaptureSession",{runId:`capture-${Date.now()}`,durationMs:18e5})};const W=()=>{void T("setCaptureSession",{runId:null})};async function X(n){const m=await ge(n);B({text:m?"Copied to clipboard.":"Clipboard is unavailable. Select the text to copy it.",error:!m})}const re=[{key:"send",label:"Test"},{key:"events",label:`Activity (${R})`}];const G=o(V,{children:[e(V.Content,{title:"",noMargin:true,children:e(ue,{tabs:re,activeKey:c,onChange:L,size:"sm",glass:true})}),o(V.Actions,{children:[e(P,{accessibilityRole:"button",accessibilityLabel:"Notification settings",onPress:()=>L(c==="setup"||c==="tokens"?"send":"setup"),style:t.iconButton,children:e(be,{size:16,color:c==="setup"||c==="tokens"?a.color.accent:a.color.textSecondary})}),c!=="send"&&e(ye,{isEnabled:u,onToggle:u?W:q,disabled:!j||y,accessibilityLabel:u?"Stop notification capture":"Start notification capture",testID:"notifications-capture"})]})]});const Q=o(r,{style:t.root,children:[j&&c!=="send"&&o(r,{style:t.status,children:[o(r,{style:t.statusLabel,children:[e(r,{style:[t.dot,u&&t.liveDot]}),e(l,{style:t.caption,children:u?"Recording":"Capture stopped"})]}),c!=="events"&&e(l,{style:t.caption,children:i.durable?"Persistent history":"Memory only"}),c!=="events"&&o(l,{style:t.provider,children:[i.provider," \xB7 ",i.platform]})]}),i?.storageError&&o(l,{accessibilityRole:"alert",style:t.errorNotice,children:["Storage: ",i.storageError]}),N&&e(l,{accessibilityRole:N.error?"alert":"text",style:[t.notice,N.error&&t.errorText],children:N.text}),!d&&e(r,{style:c==="send"?t.fill:{display:"none"},children:e(we,{snapshot:i,onAction:b,onViewActivity:()=>L("events")})}),c==="send"?d??null:!j?o(D,{children:[e(H,{otto:"paused",title:"Connect notification capture",message:"Install @buoy-gg/notifications and call installExpoNotificationCapture in the app entry point. Use an app-specific development build for remote notifications."}),e(l,{style:t.emptyFootnote,children:"The desktop sender works with any installed app. Inspection needs the capture integration."})]}):o(J,{children:[c==="events"&&o(J,{children:[o(r,{style:t.searchRow,children:[o(r,{style:t.searchField,children:[e(he,{size:14,color:a.color.textSecondary}),e(ae,{accessibilityLabel:"Filter notification events",placeholder:"Search notifications\u2026",placeholderTextColor:a.color.placeholder,value:f,onChangeText:n=>{U(n);I(null)},autoCapitalize:"none",autoCorrect:false,style:t.searchInput}),!!f&&e(P,{accessibilityRole:"button",accessibilityLabel:"Clear notification search",onPress:()=>U(""),style:t.clearSearch,children:e(me,{size:12,color:a.color.textSecondary})})]}),e(P,{accessibilityRole:"button",accessibilityLabel:"Clear captured events",disabled:y||!R,accessibilityState:{disabled:y||!R},style:[t.iconButton,(y||!R)&&t.disabled],onPress:()=>{void T("clearCapturedEvents").then(n=>{if(n)I(null)})},children:e(fe,{size:14,color:a.color.textSecondary})})]}),s?o(D,{style:t.fill,contentContainerStyle:[t.content,{paddingBottom:A.bottom}],keyboardShouldPersistTaps:"handled",children:[o(r,{style:t.actionRow,children:[e(h,{label:"Back to events",onPress:()=>I(null),icon:e(de,{size:14,color:a.color.accent})}),e(h,{label:"Copy event JSON",onPress:()=>{void X(s)},icon:e(ee,{size:14,color:a.color.accent})})]}),o(g,{glass:true,padded:true,children:[e(z,{label:K[s.kind]??s.kind,tone:ie(s.kind)}),e(l,{style:t.detailTitle,children:s.title??"Notification event"}),e(l,{style:t.caption,children:new Date(s.capturedAt).toLocaleString()})]}),o(r,{children:[e(v,{children:"Observation"}),e(g,{glass:true,children:o(te,{children:[e(x,{label:"App state at callback",value:s.observedAppState}),s.testId&&e(x,{label:"Test ID",value:s.testId}),s.notificationId&&e(x,{label:"Notification ID",value:s.notificationId}),s.actionIdentifier&&e(x,{label:"Action",value:s.actionIdentifier})]})})]}),s.kind==="startup-response"&&e(l,{style:t.footnote,children:"Recovered from the SDK cache. This alone does not establish why the app launched."}),s.truncated&&e(l,{style:t.warning,children:"This payload was truncated when captured."}),e(E,{title:"Payload",value:s.raw}),e(E,{title:"Full event",value:s,initiallyOpen:false})]}):e(se,{data:$,keyExtractor:n=>n.id,style:t.fill,contentContainerStyle:[t.eventList,{paddingBottom:A.bottom}],keyboardShouldPersistTaps:"handled",initialNumToRender:15,ListHeaderComponent:f?o(l,{style:t.resultCount,children:[$.length," of ",R," events"]}):null,ListFooterComponent:i.evicted>0?o(l,{style:t.footnote,children:[i.evicted," older records removed by the history limit."]}):null,ListEmptyComponent:e(H,{otto:f?"sad":u?"listening":"paused",title:f?"No matching events":u?"Waiting for notifications":"Capture is stopped",message:f?"Try another title, test ID, or payload value.":u?"Send a notification from Buoy Desktop or your app. Background alerts can reach the system tray before an app callback runs.":"Start capture with the power button, then send a notification."}),renderItem:({item:n})=>e(Ce,{event:n,onPress:()=>I(n.id)})})]}),c==="tokens"&&o(D,{style:t.fill,contentContainerStyle:[t.content,{paddingBottom:A.bottom}],keyboardShouldPersistTaps:"handled",children:[o(r,{children:[e(h,{label:"Back to settings",onPress:()=>L("setup")}),e(v,{children:"Registration"}),o(g,{glass:true,padded:true,children:[e(l,{style:t.bodyText,children:"Register a token to test delivery through your push provider."}),o(r,{style:t.actionRow,children:[e(h,{label:"Register device token",onPress:()=>{void T("refreshToken",{type:"device"})},disabled:y,primary:true}),e(h,{label:"Register Expo token",onPress:()=>{void T("refreshToken",{type:"expo"})},disabled:y||!i.capabilities.includes("expo-token")})]})]}),e(l,{style:t.footnote,children:"Registration runs only when you or your app request it. Simulator sends work without a token."})]}),i.tokens.length===0?e(H,{otto:"listening",title:"No tokens observed",message:"Register a device token above, or let your app register one."}):i.tokens.map((n,m)=>o(r,{children:[e(v,{children:n.type.toUpperCase()+" token"}),o(g,{glass:true,padded:true,children:[o(r,{style:t.actionRow,children:[e(z,{label:n.type,tone:"accent"}),n.environment&&e(l,{style:t.caption,children:n.environment})]}),e(l,{selectable:true,style:t.token,children:n.value}),n.projectId&&o(l,{selectable:true,style:t.caption,children:["Project: ",n.projectId]}),o(l,{style:t.caption,children:["Observed ",new Date(n.observedAt).toLocaleString()]}),e(r,{style:t.actionRow,children:e(h,{label:"Copy "+n.type.toUpperCase()+" token",onPress:()=>{void X(n.value)},icon:e(ee,{size:14,color:a.color.accent})})})]})]},n.type+"-"+m))]}),c==="setup"&&o(D,{style:t.fill,contentContainerStyle:[t.content,{paddingBottom:A.bottom}],keyboardShouldPersistTaps:"handled",children:[o(r,{children:[e(h,{label:"Device tokens",onPress:()=>L("tokens")}),e(v,{children:"Capture session"}),o(g,{glass:true,padded:true,children:[o(r,{style:t.actionRow,children:[e(z,{label:u?"Recording":"Stopped",tone:u?"accent":"neutral"}),e(l,{style:t.caption,children:u?"Until "+new Date(C).toLocaleTimeString():"Ready when you are"})]}),o(r,{style:t.actionRow,children:[e(h,{label:"Arm capture for 30 minutes",onPress:q,disabled:y,primary:true}),e(h,{label:"Stop capture",onPress:W,disabled:y||!u})]})]}),e(l,{style:t.footnote,children:i.durable?"History is saved on the app and survives app and desktop restarts.":"History is held in memory. Keep the app running to retain it."})]}),o(r,{children:[e(v,{children:"Connected app"}),e(g,{glass:true,children:o(te,{children:[e(x,{label:"App",value:i.appId??"Not supplied"}),e(x,{label:"Provider",value:[i.provider,i.providerVersion].filter(Boolean).join(" ")}),e(x,{label:"Platform",value:i.platform})]})})]}),o(r,{children:[e(v,{children:"Permissions"}),e(r,{style:t.sectionActions,children:e(h,{label:"Refresh permissions",disabled:y,onPress:()=>{void T("getPermissions")}})}),e(E,{title:"Permission settings",value:i.permissions})]}),o(r,{children:[e(v,{children:"System tray"}),e(r,{style:t.sectionActions,children:e(h,{label:"Inspect system tray",disabled:y||!i.capabilities.includes("presented"),onPress:()=>{void T("listPresented")}})}),e(E,{title:"Currently presented",value:i.presented}),e(l,{style:t.footnote,children:"Notifications currently in the system tray. Captured history is in Activity."})]}),o(r,{children:[e(v,{children:"Capabilities"}),e(g,{glass:true,padded:true,children:e(r,{style:t.actionRow,children:i.capabilities.map(n=>e(z,{label:n},n))})})]})]})]})]});return e(J,{children:w?w({header:G,body:Q}):o(r,{style:t.root,children:[e(r,{style:t.inlineHeader,children:G}),Q]})})}function Ce({event:i,onPress:b}){const d=ie(i.kind);const p=d==="danger"?a.color.danger:d==="warning"?a.color.warning:d==="accent"?a.color.accent:a.color.textSecondary;return o(P,{accessibilityRole:"button",accessibilityLabel:(K[i.kind]??i.kind)+": "+(i.title??i.testId??i.notificationId??"notification"),onPress:b,style:({pressed:S})=>[t.event,S&&t.pressed],children:[o(r,{style:t.eventTop,children:[o(r,{style:t.eventKind,children:[e(pe,{size:13,color:p}),e(l,{numberOfLines:1,style:[t.eventLabel,{color:p}],children:K[i.kind]??i.kind})]}),e(l,{style:t.timestamp,children:new Date(i.capturedAt).toLocaleTimeString()})]}),o(r,{style:t.eventSubject,children:[e(l,{numberOfLines:1,style:t.eventTitle,children:i.title??i.testId??i.notificationId??"Notification event"}),e(Z,{size:14,color:a.color.textTertiary})]}),o(l,{numberOfLines:1,style:t.eventMeta,children:[i.observedAppState,i.truncated?" \xB7 Truncated":""]})]})}
1
+ "use strict";import xe,{useEffect as se,useMemo as Z,useState as k}from"react";import{FlatList as ae,Pressable as x,ScrollView as D,Text as l,TextInput as ce,View as r}from"react-native";import{ChevronDown as de,ChevronLeft as ue,ChevronRight as ee,Copy as te,ModalHeader as V,windowDragProps as pe,NightBadge as z,NightCard as v,NightRows as ie,NightSectionLabel as S,NightSegmented as ye,NotificationsIcon as he,PowerToggleButton as be,Search as fe,Settings as me,ToolEmptyState as H,Trash2 as ge,X as ve,copyToClipboard as Se,night as a,useSafeAreaInsets as we}from"@buoy-gg/shared-ui";import{DataViewer as Ce}from"@buoy-gg/shared-ui/dataViewer";import{LocalNotificationTest as Te}from"./LocalNotificationTest";import{styles as t}from"./notificationStyles";import{jsx as e,jsxs as o,Fragment as J}from"react/jsx-runtime";const K={received:"App received",response:"Notification response","startup-response":"Response recovered at startup","presentation-decision":"Presentation decision","presentation-error":"Presentation error","background-started":"Background task started","background-completed":"Background task completed","background-error":"Background task failed","app-outcome":"App outcome","local-scheduled":"Local notification scheduled"};function oe(i){return i.includes("error")?"danger":i==="startup-response"?"warning":i==="received"||i==="app-outcome"?"accent":"neutral"}function h({label:i,onPress:b,disabled:d,primary:p,icon:w}){return o(x,{accessibilityRole:"button",accessibilityLabel:i,accessibilityState:{disabled:!!d},disabled:d,onPress:b,style:({pressed:f})=>[t.button,p&&t.primaryButton,f&&t.pressed,d&&t.disabled],children:[w,e(l,{style:[t.buttonText,p&&t.primaryButtonText],children:i})]})}function P({label:i,value:b}){return o(r,{style:t.field,children:[e(l,{style:[t.caption,t.fieldLabel],children:i}),e(l,{selectable:true,style:t.value,children:b})]})}function E({title:i,value:b,initiallyOpen:d=true}){const[p,w]=k(d);const f=JSON.stringify(b??null);const F=Z(()=>JSON.parse(f),[f]);return o(v,{glass:true,children:[o(x,{accessibilityRole:"button",accessibilityLabel:i,accessibilityState:{expanded:p},onPress:()=>w(O=>!O),style:t.disclosure,children:[e(l,{style:t.disclosureTitle,children:i}),p?e(de,{size:14,color:a.color.textSecondary}):e(ee,{size:14,color:a.color.textSecondary})]}),p&&e(r,{style:t.jsonBody,children:e(Ce,{title:"",data:F,rawMode:true,initialExpanded:true,showTypeFilter:false})})]})}export function NotificationToolView({snapshot:i,onAction:b,sender:d,activeTab:p,onTabChange:w,renderShell:f}){const[F,O]=k("send");const c=p??F;const[m,U]=k("");const[ne,I]=k(null);const[y,_]=k(false);const[N,B]=k(null);const[,re]=k(0);const A=we({minBottom:16});const C=i?.session?.expiresAt;se(()=>{if(!C||C<=Date.now())return;const n=setTimeout(()=>re(g=>g+1),C-Date.now()+1);return()=>clearTimeout(n)},[C]);const u=!!C&&C>Date.now();const $=Z(()=>(i?.events??[]).filter(n=>JSON.stringify(n).toLowerCase().includes(m.trim().toLowerCase())).slice().reverse(),[i?.events,m]);const s=i?.events.find(n=>n.id===ne);const R=i?.events.length??0;const j=!!i?.provider;function L(n){O(n);w?.(n);B(null)}async function T(n,g){if(y)return false;_(true);B(null);try{await b(n,g);return true}catch(M){B({text:M instanceof Error?M.message:String(M),error:true});return false}finally{_(false)}}const q=()=>{void T("setCaptureSession",{runId:`capture-${Date.now()}`,durationMs:18e5})};const W=()=>{void T("setCaptureSession",{runId:null})};async function X(n){const g=await Se(n);B({text:g?"Copied to clipboard.":"Clipboard is unavailable. Select the text to copy it.",error:!g})}const le=[{key:"send",label:"Test"},{key:"events",label:`Activity (${R})`}];const G=e(ye,{tabs:le,activeKey:c,onChange:L,size:"sm",glass:true});const Q=o(V,{children:[e(V.Content,{title:"",noMargin:true,children:f?G:e(r,{style:t.tabsCap,children:G})}),o(V.Actions,{children:[e(x,{accessibilityRole:"button",accessibilityLabel:"Notification settings",onPress:()=>L(c==="setup"||c==="tokens"?"send":"setup"),style:t.iconButton,children:e(me,{size:16,color:c==="setup"||c==="tokens"?a.color.accent:a.color.textSecondary})}),c!=="send"&&e(be,{isEnabled:u,onToggle:u?W:q,disabled:!j||y,accessibilityLabel:u?"Stop notification capture":"Start notification capture",testID:"notifications-capture"})]})]});const Y=o(r,{style:t.root,children:[j&&c!=="send"&&o(r,{style:t.status,children:[o(r,{style:t.statusLabel,children:[e(r,{style:[t.dot,u&&t.liveDot]}),e(l,{style:t.caption,children:u?"Recording":"Capture stopped"})]}),c!=="events"&&e(l,{style:t.caption,children:i.durable?"Persistent history":"Memory only"}),c!=="events"&&o(l,{style:t.provider,children:[i.provider," \xB7 ",i.platform]})]}),i?.storageError&&o(l,{accessibilityRole:"alert",style:t.errorNotice,children:["Storage: ",i.storageError]}),N&&e(l,{accessibilityRole:N.error?"alert":"text",style:[t.notice,N.error&&t.errorText],children:N.text}),!d&&e(r,{style:c==="send"?t.fill:{display:"none"},children:e(Te,{snapshot:i,onAction:b,onViewActivity:()=>L("events")})}),c==="send"?d??null:!j?o(D,{children:[e(H,{otto:"paused",title:"Connect notification capture",message:"Install @buoy-gg/notifications and call installExpoNotificationCapture in the app entry point. Use an app-specific development build for remote notifications."}),e(l,{style:t.emptyFootnote,children:"The desktop sender works with any installed app. Inspection needs the capture integration."})]}):o(J,{children:[c==="events"&&o(J,{children:[o(r,{style:t.searchRow,children:[o(r,{style:t.searchField,children:[e(fe,{size:14,color:a.color.textSecondary}),e(ce,{accessibilityLabel:"Filter notification events",placeholder:"Search notifications\u2026",placeholderTextColor:a.color.placeholder,value:m,onChangeText:n=>{U(n);I(null)},autoCapitalize:"none",autoCorrect:false,style:t.searchInput}),!!m&&e(x,{accessibilityRole:"button",accessibilityLabel:"Clear notification search",onPress:()=>U(""),style:t.clearSearch,children:e(ve,{size:12,color:a.color.textSecondary})})]}),e(x,{accessibilityRole:"button",accessibilityLabel:"Clear captured events",disabled:y||!R,accessibilityState:{disabled:y||!R},style:[t.iconButton,(y||!R)&&t.disabled],onPress:()=>{void T("clearCapturedEvents").then(n=>{if(n)I(null)})},children:e(ge,{size:14,color:a.color.textSecondary})})]}),s?o(D,{style:t.fill,contentContainerStyle:[t.content,{paddingBottom:A.bottom}],keyboardShouldPersistTaps:"handled",children:[o(r,{style:t.actionRow,children:[e(h,{label:"Back to events",onPress:()=>I(null),icon:e(ue,{size:14,color:a.color.accent})}),e(h,{label:"Copy event JSON",onPress:()=>{void X(s)},icon:e(te,{size:14,color:a.color.accent})})]}),o(v,{glass:true,padded:true,children:[e(z,{label:K[s.kind]??s.kind,tone:oe(s.kind)}),e(l,{style:t.detailTitle,children:s.title??"Notification event"}),e(l,{style:t.caption,children:new Date(s.capturedAt).toLocaleString()})]}),o(r,{children:[e(S,{children:"Observation"}),e(v,{glass:true,children:o(ie,{children:[e(P,{label:"App state at callback",value:s.observedAppState}),s.testId&&e(P,{label:"Test ID",value:s.testId}),s.notificationId&&e(P,{label:"Notification ID",value:s.notificationId}),s.actionIdentifier&&e(P,{label:"Action",value:s.actionIdentifier})]})})]}),s.kind==="startup-response"&&e(l,{style:t.footnote,children:"Recovered from the SDK cache. This alone does not establish why the app launched."}),s.truncated&&e(l,{style:t.warning,children:"This payload was truncated when captured."}),e(E,{title:"Payload",value:s.raw}),e(E,{title:"Full event",value:s,initiallyOpen:false})]}):e(ae,{data:$,keyExtractor:n=>n.id,style:t.fill,contentContainerStyle:[t.eventList,{paddingBottom:A.bottom}],keyboardShouldPersistTaps:"handled",initialNumToRender:15,ListHeaderComponent:m?o(l,{style:t.resultCount,children:[$.length," of ",R," events"]}):null,ListFooterComponent:i.evicted>0?o(l,{style:t.footnote,children:[i.evicted," older records removed by the history limit."]}):null,ListEmptyComponent:e(H,{otto:m?"sad":u?"listening":"paused",title:m?"No matching events":u?"Waiting for notifications":"Capture is stopped",message:m?"Try another title, test ID, or payload value.":u?"Send a notification from Buoy Desktop or your app. Background alerts can reach the system tray before an app callback runs.":"Start capture with the power button, then send a notification."}),renderItem:({item:n})=>e(ke,{event:n,onPress:()=>I(n.id)})})]}),c==="tokens"&&o(D,{style:t.fill,contentContainerStyle:[t.content,{paddingBottom:A.bottom}],keyboardShouldPersistTaps:"handled",children:[o(r,{children:[e(h,{label:"Back to settings",onPress:()=>L("setup")}),e(S,{children:"Registration"}),o(v,{glass:true,padded:true,children:[e(l,{style:t.bodyText,children:"Register a token to test delivery through your push provider."}),o(r,{style:t.actionRow,children:[e(h,{label:"Register device token",onPress:()=>{void T("refreshToken",{type:"device"})},disabled:y,primary:true}),e(h,{label:"Register Expo token",onPress:()=>{void T("refreshToken",{type:"expo"})},disabled:y||!i.capabilities.includes("expo-token")})]})]}),e(l,{style:t.footnote,children:"Registration runs only when you or your app request it. Simulator sends work without a token."})]}),i.tokens.length===0?e(H,{otto:"listening",title:"No tokens observed",message:"Register a device token above, or let your app register one."}):i.tokens.map((n,g)=>o(r,{children:[e(S,{children:n.type.toUpperCase()+" token"}),o(v,{glass:true,padded:true,children:[o(r,{style:t.actionRow,children:[e(z,{label:n.type,tone:"accent"}),n.environment&&e(l,{style:t.caption,children:n.environment})]}),e(l,{selectable:true,style:t.token,children:n.value}),n.projectId&&o(l,{selectable:true,style:t.caption,children:["Project: ",n.projectId]}),o(l,{style:t.caption,children:["Observed ",new Date(n.observedAt).toLocaleString()]}),e(r,{style:t.actionRow,children:e(h,{label:"Copy "+n.type.toUpperCase()+" token",onPress:()=>{void X(n.value)},icon:e(te,{size:14,color:a.color.accent})})})]})]},n.type+"-"+g))]}),c==="setup"&&o(D,{style:t.fill,contentContainerStyle:[t.content,{paddingBottom:A.bottom}],keyboardShouldPersistTaps:"handled",children:[o(r,{children:[e(h,{label:"Device tokens",onPress:()=>L("tokens")}),e(S,{children:"Capture session"}),o(v,{glass:true,padded:true,children:[o(r,{style:t.actionRow,children:[e(z,{label:u?"Recording":"Stopped",tone:u?"accent":"neutral"}),e(l,{style:t.caption,children:u?"Until "+new Date(C).toLocaleTimeString():"Ready when you are"})]}),o(r,{style:t.actionRow,children:[e(h,{label:"Arm capture for 30 minutes",onPress:q,disabled:y,primary:true}),e(h,{label:"Stop capture",onPress:W,disabled:y||!u})]})]}),e(l,{style:t.footnote,children:i.durable?"History is saved on the app and survives app and desktop restarts.":"History is held in memory. Keep the app running to retain it."})]}),o(r,{children:[e(S,{children:"Connected app"}),e(v,{glass:true,children:o(ie,{children:[e(P,{label:"App",value:i.appId??"Not supplied"}),e(P,{label:"Provider",value:[i.provider,i.providerVersion].filter(Boolean).join(" ")}),e(P,{label:"Platform",value:i.platform})]})})]}),o(r,{children:[e(S,{children:"Permissions"}),e(r,{style:t.sectionActions,children:e(h,{label:"Refresh permissions",disabled:y,onPress:()=>{void T("getPermissions")}})}),e(E,{title:"Permission settings",value:i.permissions})]}),o(r,{children:[e(S,{children:"System tray"}),e(r,{style:t.sectionActions,children:e(h,{label:"Inspect system tray",disabled:y||!i.capabilities.includes("presented"),onPress:()=>{void T("listPresented")}})}),e(E,{title:"Currently presented",value:i.presented}),e(l,{style:t.footnote,children:"Notifications currently in the system tray. Captured history is in Activity."})]}),o(r,{children:[e(S,{children:"Capabilities"}),e(v,{glass:true,padded:true,children:e(r,{style:t.actionRow,children:i.capabilities.map(n=>e(z,{label:n},n))})})]})]})]})]});return e(J,{children:f?f({header:Q,body:Y}):o(r,{style:t.root,children:[e(r,{style:t.inlineHeader,...pe,children:Q}),Y]})})}function ke({event:i,onPress:b}){const d=oe(i.kind);const p=d==="danger"?a.color.danger:d==="warning"?a.color.warning:d==="accent"?a.color.accent:a.color.textSecondary;return o(x,{accessibilityRole:"button",accessibilityLabel:(K[i.kind]??i.kind)+": "+(i.title??i.testId??i.notificationId??"notification"),onPress:b,style:({pressed:w})=>[t.event,w&&t.pressed],children:[o(r,{style:t.eventTop,children:[o(r,{style:t.eventKind,children:[e(he,{size:13,color:p}),e(l,{numberOfLines:1,style:[t.eventLabel,{color:p}],children:K[i.kind]??i.kind})]}),e(l,{style:t.timestamp,children:new Date(i.capturedAt).toLocaleTimeString()})]}),o(r,{style:t.eventSubject,children:[e(l,{numberOfLines:1,style:t.eventTitle,children:i.title??i.testId??i.notificationId??"Notification event"}),e(ee,{size:14,color:a.color.textTertiary})]}),o(l,{numberOfLines:1,style:t.eventMeta,children:[i.observedAppState,i.truncated?" \xB7 Truncated":""]})]})}
@@ -1 +1 @@
1
- "use strict";import{StyleSheet as t}from"react-native";import{monoFont as e,night as o}from"@buoy-gg/shared-ui";export const styles=t.create({root:{flex:1,minHeight:0,backgroundColor:"transparent"},fill:{flex:1,minHeight:0},inlineHeader:{paddingHorizontal:12,paddingVertical:8,borderBottomWidth:1,borderBottomColor:o.color.separator},status:{flexDirection:"row",alignItems:"center",flexWrap:"wrap",gap:12,paddingHorizontal:16,paddingVertical:9},statusLabel:{flexDirection:"row",alignItems:"center",gap:6},dot:{width:5,height:5,borderRadius:3,backgroundColor:o.color.textTertiary},liveDot:{backgroundColor:o.color.accent},caption:{color:o.color.textSecondary,fontSize:12,lineHeight:17},provider:{color:o.color.textSecondary,fontSize:11,marginLeft:"auto",fontFamily:e},content:{padding:14,gap:20},eventList:{paddingHorizontal:12,paddingTop:2},searchRow:{flexDirection:"row",gap:8,paddingHorizontal:12,paddingBottom:10,alignItems:"center"},searchField:{flex:1,minWidth:0,height:36,flexDirection:"row",alignItems:"center",gap:8,paddingHorizontal:10,backgroundColor:o.color.glass,borderWidth:1,borderColor:o.color.glassBorder,borderRadius:o.radius.row},searchInput:{flex:1,minWidth:0,height:"100%",color:o.color.text,fontSize:13,padding:0},clearSearch:{padding:6},iconButton:{width:34,height:34,alignItems:"center",justifyContent:"center",backgroundColor:o.color.buttonSurface,borderRadius:8,borderWidth:1,borderColor:o.color.border},event:{backgroundColor:o.color.glass,borderRadius:o.radius.input,borderWidth:1,borderColor:o.color.glassBorder,paddingHorizontal:12,paddingVertical:10,marginBottom:6,gap:6},eventTop:{flexDirection:"row",alignItems:"center",gap:10,justifyContent:"space-between"},eventKind:{flexDirection:"row",alignItems:"center",gap:6,flex:1,minWidth:0},eventLabel:{flexShrink:1,fontSize:11,fontWeight:"600"},timestamp:{color:o.color.textSecondary,fontFamily:e,fontSize:10},eventSubject:{flexDirection:"row",alignItems:"center",gap:8},eventTitle:{flex:1,color:o.color.text,fontSize:15,fontWeight:"500"},eventMeta:{color:o.color.textSecondary,fontFamily:e,fontSize:10,lineHeight:15},resultCount:{color:o.color.textSecondary,fontSize:12,marginBottom:10,marginLeft:4},actionRow:{flexDirection:"row",alignItems:"center",flexWrap:"wrap",gap:8},button:{flexDirection:"row",alignItems:"center",justifyContent:"center",gap:6,minHeight:34,paddingVertical:8,paddingHorizontal:14,borderRadius:o.radius.pill,backgroundColor:o.color.fillSecondary,alignSelf:"flex-start"},buttonText:{color:o.color.accent,fontSize:13,fontWeight:"600"},primaryButton:{backgroundColor:o.color.accent},primaryButtonText:{color:o.color.onAccent},pressed:{opacity:.7},disabled:{opacity:.4},detailTitle:{color:o.color.text,fontSize:20,fontWeight:"600"},field:{flexDirection:"row",paddingHorizontal:16,paddingVertical:12,gap:14},fieldLabel:{width:110,flexShrink:0},value:{flex:1,minWidth:0,color:o.color.text,fontFamily:e,fontSize:12,lineHeight:18},disclosure:{flexDirection:"row",alignItems:"center",justifyContent:"space-between",paddingHorizontal:16,paddingVertical:14},disclosureTitle:{color:o.color.text,fontSize:13,fontWeight:"500"},jsonBody:{padding:10,borderTopWidth:1,borderTopColor:o.color.separator},token:{color:o.color.text,fontFamily:e,fontSize:12,lineHeight:20},bodyText:{color:o.color.text,fontSize:14,lineHeight:21},footnote:{color:o.color.textSecondary,fontSize:12,lineHeight:18,marginTop:8,marginHorizontal:4},emptyFootnote:{color:o.color.textSecondary,fontSize:12,lineHeight:18,textAlign:"center",marginHorizontal:28},sectionActions:{flexDirection:"row",marginBottom:10},warning:{color:o.color.warning,fontSize:12,lineHeight:18},notice:{color:o.color.accent,backgroundColor:o.color.glass,paddingHorizontal:16,paddingVertical:10,fontSize:12,lineHeight:18},errorNotice:{color:o.color.danger,backgroundColor:o.color.glass,paddingHorizontal:16,paddingVertical:10,fontSize:12,lineHeight:18},errorText:{color:o.color.danger}});
1
+ "use strict";import{StyleSheet as t}from"react-native";import{monoFont as e,night as o}from"@buoy-gg/shared-ui";export const styles=t.create({root:{flex:1,minHeight:0,backgroundColor:"transparent"},fill:{flex:1,minHeight:0},inlineHeader:{paddingHorizontal:12,paddingVertical:8,borderBottomWidth:1,borderBottomColor:o.color.separator},status:{flexDirection:"row",alignItems:"center",flexWrap:"wrap",gap:12,paddingHorizontal:16,paddingVertical:9},statusLabel:{flexDirection:"row",alignItems:"center",gap:6},dot:{width:5,height:5,borderRadius:3,backgroundColor:o.color.textTertiary},liveDot:{backgroundColor:o.color.accent},caption:{color:o.color.textSecondary,fontSize:12,lineHeight:17},provider:{color:o.color.textSecondary,fontSize:11,marginLeft:"auto",fontFamily:e},content:{padding:14,gap:20},eventList:{paddingHorizontal:12,paddingTop:2},searchRow:{flexDirection:"row",gap:8,paddingHorizontal:12,paddingBottom:10,alignItems:"center"},searchField:{flex:1,minWidth:0,height:36,flexDirection:"row",alignItems:"center",gap:8,paddingHorizontal:10,backgroundColor:o.color.glass,borderWidth:1,borderColor:o.color.glassBorder,borderRadius:o.radius.row},searchInput:{flex:1,minWidth:0,height:"100%",color:o.color.text,fontSize:13,padding:0},clearSearch:{padding:6},tabsCap:{width:"100%",maxWidth:360},iconButton:{width:34,height:34,alignItems:"center",justifyContent:"center",backgroundColor:o.color.buttonSurface,borderRadius:8,borderWidth:1,borderColor:o.color.border},event:{backgroundColor:o.color.glass,borderRadius:o.radius.input,borderWidth:1,borderColor:o.color.glassBorder,paddingHorizontal:12,paddingVertical:10,marginBottom:6,gap:6},eventTop:{flexDirection:"row",alignItems:"center",gap:10,justifyContent:"space-between"},eventKind:{flexDirection:"row",alignItems:"center",gap:6,flex:1,minWidth:0},eventLabel:{flexShrink:1,fontSize:11,fontWeight:"600"},timestamp:{color:o.color.textSecondary,fontFamily:e,fontSize:10},eventSubject:{flexDirection:"row",alignItems:"center",gap:8},eventTitle:{flex:1,color:o.color.text,fontSize:15,fontWeight:"500"},eventMeta:{color:o.color.textSecondary,fontFamily:e,fontSize:10,lineHeight:15},resultCount:{color:o.color.textSecondary,fontSize:12,marginBottom:10,marginLeft:4},actionRow:{flexDirection:"row",alignItems:"center",flexWrap:"wrap",gap:8},button:{flexDirection:"row",alignItems:"center",justifyContent:"center",gap:6,minHeight:34,paddingVertical:8,paddingHorizontal:14,borderRadius:o.radius.pill,backgroundColor:o.color.fillSecondary,alignSelf:"flex-start"},buttonText:{color:o.color.accent,fontSize:13,fontWeight:"600"},primaryButton:{backgroundColor:o.color.accent},primaryButtonText:{color:o.color.onAccent},pressed:{opacity:.7},disabled:{opacity:.4},detailTitle:{color:o.color.text,fontSize:20,fontWeight:"600"},field:{flexDirection:"row",paddingHorizontal:16,paddingVertical:12,gap:14},fieldLabel:{width:110,flexShrink:0},value:{flex:1,minWidth:0,color:o.color.text,fontFamily:e,fontSize:12,lineHeight:18},disclosure:{flexDirection:"row",alignItems:"center",justifyContent:"space-between",paddingHorizontal:16,paddingVertical:14},disclosureTitle:{color:o.color.text,fontSize:13,fontWeight:"500"},jsonBody:{padding:10,borderTopWidth:1,borderTopColor:o.color.separator},token:{color:o.color.text,fontFamily:e,fontSize:12,lineHeight:20},bodyText:{color:o.color.text,fontSize:14,lineHeight:21},footnote:{color:o.color.textSecondary,fontSize:12,lineHeight:18,marginTop:8,marginHorizontal:4},emptyFootnote:{color:o.color.textSecondary,fontSize:12,lineHeight:18,textAlign:"center",marginHorizontal:28},sectionActions:{flexDirection:"row",marginBottom:10},warning:{color:o.color.warning,fontSize:12,lineHeight:18},notice:{color:o.color.accent,backgroundColor:o.color.glass,paddingHorizontal:16,paddingVertical:10,fontSize:12,lineHeight:18},errorNotice:{color:o.color.danger,backgroundColor:o.color.glass,paddingHorizontal:16,paddingVertical:10,fontSize:12,lineHeight:18},errorText:{color:o.color.danger}});
@@ -86,6 +86,10 @@ export declare const styles: {
86
86
  clearSearch: {
87
87
  padding: number;
88
88
  };
89
+ tabsCap: {
90
+ width: "100%";
91
+ maxWidth: number;
92
+ };
89
93
  iconButton: {
90
94
  width: number;
91
95
  height: number;
package/lib/web/index.mjs CHANGED
@@ -1 +1 @@
1
- "use client";var $e=Object.defineProperty;var St=Object.getOwnPropertyDescriptor;var xt=Object.getOwnPropertyNames;var It=Object.prototype.hasOwnProperty;var kt=(e,t)=>{for(var o in t)$e(e,o,{get:t[o],enumerable:true})},_e=(e,t,o,i)=>{if(t&&typeof t=="object"||typeof t=="function")for(let n of xt(t))!It.call(e,n)&&n!==o&&$e(e,n,{get:()=>t[n],enumerable:!(i=St(t,n))||i.enumerable});return e},Ct=(e,t,o)=>(_e(e,t,"default"),o&&_e(o,t,"default"));var ye=(()=>{try{let e=globalThis.Capacitor;if(e&&typeof e.isNativePlatform=="function"&&e.isNativePlatform())return e.DEBUG===true}catch{}return process.env.NODE_ENV!=="production"})();typeof window<"u"&&typeof globalThis.global>"u"&&(globalThis.global=globalThis);var Je={};kt(Je,{AccessibilityInfo:()=>Pt,ActivityIndicator:()=>No,Alert:()=>Ro,Animated:()=>xo,AppRegistry:()=>Rt,AppState:()=>Ue,Appearance:()=>Et,BackHandler:()=>Lt,Button:()=>Po,CheckBox:()=>Ut,Clipboard:()=>zt,DeviceEventEmitter:()=>so,Dimensions:()=>Ot,Easing:()=>jt,FlatList:()=>qe,I18nManager:()=>Dt,Image:()=>Ge,ImageBackground:()=>qt,InteractionManager:()=>Vt,Keyboard:()=>Bt,KeyboardAvoidingView:()=>Gt,LayoutAnimation:()=>Ht,Linking:()=>Ft,LogBox:()=>ao,Modal:()=>To,NativeEventEmitter:()=>Mt,NativeModules:()=>Nt,PanResponder:()=>Kt,Picker:()=>Xt,PixelRatio:()=>Wt,Platform:()=>ke,Pressable:()=>W,ProgressBar:()=>Yt,RefreshControl:()=>Zt,SafeAreaView:()=>Qt,ScrollView:()=>ne,SectionList:()=>eo,Share:()=>$t,StatusBar:()=>to,StyleSheet:()=>ge,Switch:()=>Ao,Text:()=>u,TextInput:()=>de,Touchable:()=>oo,TouchableHighlight:()=>ko,TouchableNativeFeedback:()=>io,TouchableOpacity:()=>Io,TouchableWithoutFeedback:()=>Co,UIManager:()=>_t,Vibration:()=>Jt,View:()=>f,VirtualizedList:()=>no,YellowBox:()=>ro,findNodeHandle:()=>Eo,unstable_createElement:()=>At,useColorScheme:()=>lo,useLocaleContext:()=>co,useWindowDimensions:()=>po});Ct(Je,Tt);import*as Tt from"react-native-web";import{unstable_createElement as At,NativeModules as Nt,AccessibilityInfo as Pt,Appearance as Et,AppRegistry as Rt,AppState as Ue,BackHandler as Lt,Clipboard as zt,Dimensions as Ot,Easing as jt,I18nManager as Dt,Keyboard as Bt,InteractionManager as Vt,LayoutAnimation as Ht,Linking as Ft,NativeEventEmitter as Mt,PanResponder as Kt,PixelRatio as Wt,Platform as ke,Share as $t,UIManager as _t,Vibration as Jt,CheckBox as Ut,FlatList as qe,Image as Ge,ImageBackground as qt,KeyboardAvoidingView as Gt,Picker as Xt,ProgressBar as Yt,RefreshControl as Zt,SafeAreaView as Qt,SectionList as eo,StatusBar as to,Touchable as oo,TouchableNativeFeedback as io,VirtualizedList as no,YellowBox as ro,LogBox as ao,DeviceEventEmitter as so,useColorScheme as lo,useLocaleContext as co,useWindowDimensions as po}from"react-native-web";import*as j from"react-native-web";import{createElement as Ce,forwardRef as Xe,useCallback as uo,useRef as ho}from"react";import{useEffect as fo,useState as yo}from"react";import{createPortal as go}from"react-dom";var bo='-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif';import{jsx as mo}from"react/jsx-runtime";var ce=Symbol.for("@buoy-gg/portal-host"),Ye=e=>{if(!(e instanceof Element))return false;if(e.closest("input, textarea, select"))return true;let t=e.closest("[contenteditable]")?.getAttribute("contenteditable")?.toLowerCase();return t===""||t==="true"||t==="plaintext-only"};function Ze(){let e=document;if(e[ce])return e[ce].host;let t=document.createElement("div");t.dataset.buoyPortalHost="",Object.assign(t.style,{position:"fixed",inset:"0",zIndex:"2147483647",pointerEvents:"none",fontFamily:bo});let o=()=>{let l=document.fullscreenElement,m=l&&l.tagName!=="CANVAS"?l:document.body;t.parentElement!==m&&m.appendChild(t)},i=new Map,n=l=>{(!t.contains(l.target)||!Ye(l.target))&&i.set(l.code||l.key,{key:l.key,code:l.code,location:l.location,keyCode:l.keyCode,which:l.which,altKey:l.altKey,ctrlKey:l.ctrlKey,metaKey:l.metaKey,shiftKey:l.shiftKey})},r=l=>{i.delete(l.code||l.key)},s=()=>i.clear(),h=()=>{let l=[...i.values()];i.clear();for(let m of l)document.dispatchEvent(new KeyboardEvent("keyup",{...m,bubbles:true}))},p=l=>{Ye(l.target)&&l.stopPropagation()},d=l=>l.stopPropagation();return o(),document.addEventListener("fullscreenchange",o),document.addEventListener("keydown",n,true),document.addEventListener("keyup",r,true),window.addEventListener("blur",s),t.addEventListener("focusin",h),t.addEventListener("keydown",p),t.addEventListener("keyup",p),t.addEventListener("keypress",p),t.addEventListener("wheel",d,{passive:true}),e[ce]={host:t,users:0,dispose:()=>{document.removeEventListener("fullscreenchange",o),document.removeEventListener("keydown",n,true),document.removeEventListener("keyup",r,true),window.removeEventListener("blur",s),t.remove(),delete e[ce]}},t}function vo({children:e}){let[t,o]=yo(null);return fo(()=>{let i=Ze(),n=document[ce];return n.users++,o(i),()=>{--n.users===0&&n.dispose()}},[]),t?go(mo("div",{"data-buoy-root":"",style:{display:"contents",pointerEvents:"auto"},children:e}),t):null}var oe=j,wo=["shadowColor","shadowOffset","shadowOpacity","shadowRadius","textShadowColor","textShadowOffset","textShadowRadius"],ie=e=>typeof e=="number"?`${e}px`:e;function Te(e){if(Array.isArray(e)){let m=e.map(Te);return m.some((N,k)=>N!==e[k])?m:e}if(!e||typeof e!="object"||!wo.some(m=>e[m]!=null))return e;let{shadowColor:t,shadowOffset:o,shadowOpacity:i,shadowRadius:n,textShadowColor:r,textShadowOffset:s,textShadowRadius:h,...p}=e;if(t!=null||o!=null||i!=null||n!=null){let m=t??"black",N=i==null?m:`color-mix(in srgb, ${m} ${Math.min(i,1)*100}%, transparent)`,k=`${ie(o?.width??0)} ${ie(o?.height??0)} ${ie(n??0)} ${N}`;p.boxShadow=typeof p.boxShadow=="string"?`${p.boxShadow}, ${k}`:p.boxShadow??k}let{width:d=0,height:l=0}=s??{};if(r&&(d||l||h)){let m=`${ie(d)} ${ie(l)} ${ie(h??0)} ${r}`;p.textShadow=p.textShadow?`${p.textShadow}, ${m}`:m}return p}var So=oe.StyleSheet.create({auto:{pointerEvents:"auto"},none:{pointerEvents:"none"},"box-none":{pointerEvents:"box-none"},"box-only":{pointerEvents:"box-only"}});function Qe(e,t){if(typeof e=="function")return i=>Qe(e(i),t);let o=Te(e);return t?[o,So[t]]:o}var ge={...oe.StyleSheet,create:e=>oe.StyleSheet.create(Object.fromEntries(Object.entries(e).map(([t,o])=>[t,Te(o)])))};function B(e){let t=Xe((i,n)=>{let{accessibilityState:r,accessibilityValue:s,pointerEvents:h,...p}=i;for(let l of["busy","checked","disabled","expanded","selected"])r?.[l]!==void 0&&p[`aria-${l}`]===void 0&&(p[`aria-${l}`]=r[l]);for(let[l,m]of Object.entries({min:"valuemin",max:"valuemax",now:"valuenow",text:"valuetext"}))s?.[l]!==void 0&&p[`aria-${m}`]===void 0&&(p[`aria-${m}`]=s[l]);let d=Qe(p.style,h);return d!==p.style&&(p.style=d),Ce(e,{...p,ref:n})}),o=e.State;return o&&Object.assign(t,{State:o}),t.displayName=e.displayName??e.name??"NativeWebView",t}var f=B(j.View),u=B(j.Text),xo={...oe.Animated,View:oe.Animated.createAnimatedComponent(f),Text:oe.Animated.createAnimatedComponent(u)},de=B(j.TextInput),Io=B(j.TouchableOpacity),ko=B(j.TouchableHighlight),Co=B(j.TouchableWithoutFeedback),W=B(j.Pressable),ne=B(j.ScrollView),et=Xe((e,t)=>{let o=ho(null),i=uo(n=>{if(n){let r=n;for(;r.parentElement&&r.parentElement!==document.body;)r=r.parentElement;r.parentElement===document.body&&(o.current=r,Object.assign(r.style,{position:"relative",zIndex:"2147483647",pointerEvents:"auto"}),Ze().appendChild(r))}else o.current&&(document.body.appendChild(o.current),o.current=null);typeof t=="function"?t(n):t&&(t.current=n)},[t]);return Ce(vo,null,Ce(j.Modal,{...e,ref:i}))});et.displayName="Modal";var To=B(et),Ao=B(j.Switch),No=B(j.ActivityIndicator),Po=B(j.Button),Eo=j.findNodeHandle,Ro={alert(e,t,o,i){if(typeof document>"u")return;let n=document.createElement("dialog");n.dataset.buoyRoot="",n.setAttribute("aria-label",e),n.style.cssText="position:fixed;inset:0;margin:auto;width:min(440px,90vw);padding:24px;border:1px solid #475569;border-radius:14px;background:#17212e;color:#f1f5f9;font:14px system-ui;box-shadow:0 20px 80px #0008;z-index:2147483647";let r=document.createElement("h2");if(r.textContent=e,r.style.cssText="font-size:18px;margin:0 0 12px",n.appendChild(r),t){let d=document.createElement("p");d.textContent=t,d.style.cssText="line-height:1.5;white-space:pre-wrap;margin:0 0 20px",n.appendChild(d)}let s=document.createElement("div");s.style.cssText="display:flex;justify-content:flex-end;flex-wrap:wrap;gap:8px";let h=o?.length?o:[{text:"OK"}],p=()=>{n.close?.(),n.remove()};for(let d of h){let l=document.createElement("button");l.type="button",l.textContent=d.text??"OK",l.style.cssText=`padding:9px 14px;border:1px solid #64748b;border-radius:7px;color:white;background:${d.style==="destructive"?"#a52b38":"#283a4d"};cursor:pointer;font:inherit`,l.onclick=()=>{p(),d.onPress?.()},s.appendChild(l)}n.addEventListener("cancel",d=>{d.preventDefault(),i?.cancelable!==false&&(p(),i?.onDismiss?.())}),n.appendChild(s),document.body.appendChild(n),n.showModal?n.showModal():n.setAttribute("open","")}};function Lo(e){if(!e.documentDirectory)throw new Error("Expo FileSystem has no persistent document directory.");let t=e.documentDirectory+"buoy-notifications/",o=i=>t+encodeURIComponent(i)+".json";return{async getItem(i){let n=o(i);return(await e.getInfoAsync(n)).exists?e.readAsStringAsync(n):null},async setItem(i,n){(await e.getInfoAsync(t)).exists||await e.makeDirectoryAsync(t,{intermediates:true}),await e.writeAsStringAsync(o(i),n)},async removeItem(i){await e.deleteAsync(o(i),{idempotent:true})},async getAllKeys(){return(await e.getInfoAsync(t)).exists?(await e.readDirectoryAsync(t)).filter(i=>i.endsWith(".json")).flatMap(i=>{try{return[decodeURIComponent(i.slice(0,-5))]}catch{return[]}}):[]}}}function zo(){try{return globalThis.localStorage??null}catch{return null}}function Oo(){let e=zo();return e?{storage:{async getItem(t){return e.getItem(t)},async setItem(t,o){e.setItem(t,o)},async removeItem(t){e.removeItem(t)},async getAllKeys(){let t=[];for(let o=0;o<e.length;o++){let i=e.key(o);i?.startsWith("buoy.notifications.")&&t.push(i)}return t}},durable:true}:{durable:false}}function g(e){return e!==null&&typeof e=="object"&&!Array.isArray(e)?e:{}}function z(e){return typeof e=="string"?e:null}function Ae(e){let t=new WeakSet;function o(i,n){if(i==null)return null;if(typeof i=="string")return i.length>12e3?i.slice(0,12e3)+" [truncated]":i;if(typeof i=="boolean")return i;if(typeof i=="number")return Number.isFinite(i)?i:String(i);if(typeof i!="object")return String(i);if(t.has(i))return"[Circular]";if(n>12)return"[Depth limit]";if(t.add(i),i instanceof Error)return{name:i.name,message:i.message};if(i instanceof Date)return Number.isNaN(i.getTime())?"[Invalid date]":i.toISOString();if(Array.isArray(i))return i.slice(0,200).map(s=>o(s,n+1));let r={};for(let s of Object.keys(i).slice(0,200))try{Object.defineProperty(r,s,{value:o(i[s],n+1),enumerable:true})}catch{r[s]="[Unreadable]"}return r}return o(e,0)}function re(e){let t=0;for(let o of e){let i=o.codePointAt(0);t+=i<=127?1:i<=2047?2:i<=65535?3:4}return t}var Ne="buoy.notifications.v1.",Pe=Ne+"session",tt=Ne+"tokens",be=Ne+"event.",Ee=16*1024,jo=512*1024,Do=200,Re=class{constructor(e={}){this.options=e;this.state={version:1,ready:false,provider:null,providerVersion:null,platform:"unknown",appId:null,capabilities:[],durable:false,storageError:null,evicted:0,session:null,events:[],tokens:[],permissions:null,presented:null};this.listeners=new Set;this.sequence=0;this.queue=Promise.resolve();this.getSnapshot=()=>this.state;this.subscribe=t=>(this.listeners.add(t),()=>{this.listeners.delete(t)});this.now=e.now??Date.now,this.processId=e.processId??`${this.now().toString(36)}-${Math.random().toString(36).slice(2)}`,this.state.durable=!!e.storage&&e.durable===true,this.ready=this.hydrate(),this.queue=this.ready}update(e){this.state={...this.state,...e};for(let t of this.listeners)try{t()}catch{}}configure(e){this.update(e)}allowed(){return this.options.enabled?.()??true}storageFailure(e){this.update({storageError:e instanceof Error?e.message:String(e),durable:false})}serial(e){let t=this.queue.then(e);return this.queue=t.catch(()=>{}),t}async hydrate(){if(!this.allowed()){this.update({ready:true});return}if(this.options.durability)try{this.update({durable:await this.options.durability})}catch(o){this.storageFailure(o)}let e=this.options.storage,t=false;if(e)try{let o=await e.getItem(Pe);if(t=o==="null",o){let s=JSON.parse(o);s&&typeof s.runId=="string"&&Number.isFinite(s.expiresAt)&&s.expiresAt>this.now()&&this.update({session:s})}let i=await e.getItem(tt);if(i){let s=JSON.parse(i);Array.isArray(s)&&this.update({tokens:s.filter(h=>h&&["apns","fcm","expo"].includes(h.type)&&typeof h.value=="string").slice(-10)})}let n=(await e.getAllKeys()).filter(s=>s.startsWith(be)).sort(),r=[];for(let s of n)try{let h=await e.getItem(s);if(!h||re(h)>Ee){await e.removeItem(s);continue}let p=JSON.parse(h);typeof p.id=="string"&&typeof p.kind=="string"&&Number.isFinite(p.capturedAt)?r.push(p):await e.removeItem(s)}catch{await e.removeItem(s)}r.sort((s,h)=>s.capturedAt-h.capturedAt||s.sequence-h.sequence||s.id.localeCompare(h.id)),this.update({events:r}),await this.prune()}catch(o){this.storageFailure(o)}if(this.options.autoStart&&!this.state.session&&!t){let o=this.now(),i={runId:this.processId,startedAt:o,expiresAt:o+1800*1e3};try{await e?.setItem(Pe,JSON.stringify(i))}catch(n){this.storageFailure(n)}this.update({session:i})}this.update({ready:true})}async setCaptureSession(e,t=1800*1e3){if(!this.allowed())throw new Error("Notification capture is disabled in this build.");if(e!==null&&(typeof e!="string"||!e.trim()||e.length>128))throw new Error("runId must contain 1 to 128 characters, or be null to stop capture.");if(!Number.isFinite(t)||t<1e3||t>3600*1e3)throw new Error("Capture duration must be between 1 second and 1 hour.");return this.serial(async()=>{let o=this.now(),i=e===null?null:{runId:e,startedAt:o,expiresAt:o+t};try{this.options.storage&&await this.options.storage.setItem(Pe,JSON.stringify(i))}catch(n){throw this.storageFailure(n),new Error("Could not persist the capture session. Keep the app open and check storage.")}return this.update({session:i}),{session:i,durable:this.state.durable}})}record(e,t,o={}){let i=this.now(),n=this.options.appState?.()??"unknown",r=Ae(t);return this.serial(async()=>{if(!this.allowed())return null;let s=this.state.session;if(!s||s.expiresAt<=i)return s&&this.update({session:null}),null;let h=(l,m=512)=>typeof l=="string"?l.slice(0,m):null,p=h(o.dedupeKey,2048);if(p&&this.state.events.some(l=>l.dedupeKey===p))return null;let d={id:`${this.processId}-${++this.sequence}`,processId:this.processId,sequence:this.sequence,capturedAt:i,runId:s.runId,kind:e,provider:h(o.provider,64)??this.state.provider??"app",observedAppState:n,notificationId:h(o.notificationId),testId:h(o.testId),title:h(o.title,1024),actionIdentifier:h(o.actionIdentifier),...p?{dedupeKey:p}:{},raw:r};re(JSON.stringify(d))>Ee&&(d.raw={note:"Payload exceeded the 16 KiB capture limit."},d.truncated=true),this.update({events:[...this.state.events,d]});try{await this.options.storage?.setItem(be+d.id,JSON.stringify(d))}catch(l){this.storageFailure(l)}try{await this.prune()}catch(l){this.storageFailure(l)}return d})}async prune(){let e=[...this.state.events],t=e.map(n=>re(JSON.stringify(n))),o=t.reduce((n,r)=>n+r,0),i=[];for(;e.length>Do||o>jo;)i.push(e.shift()),o-=t.shift();i.length&&this.update({events:e,evicted:this.state.evicted+i.length});for(let n of i)await this.options.storage?.removeItem(be+n.id)}async clearCapturedEvents(){return this.serial(async()=>{let e=this.state.events;for(let t of e)await this.options.storage?.removeItem(be+t.id);return this.update({events:[],evicted:0}),{cleared:true}})}async observeToken(e,t,o={}){if(this.allowed()){if(!t||t.length>8192)throw new Error("The notification token is empty or too long.");return this.serial(async()=>{let i={type:e,value:t,observedAt:this.now(),...typeof o.projectId=="string"?{projectId:o.projectId.slice(0,256)}:{},...typeof o.environment=="string"?{environment:o.environment.slice(0,256)}:{}},n=[...this.state.tokens.filter(r=>!(r.type===e&&r.projectId===o.projectId&&r.environment===o.environment)),i].slice(-10);this.update({tokens:n});try{await this.options.storage?.setItem(tt,JSON.stringify(n))}catch(r){this.storageFailure(r)}})}}setPermissions(e){let t=Ae(e);this.update({permissions:re(JSON.stringify(t))<=Ee?t:{note:"Permission result exceeded the capture limit."}})}setPresented(e){let t=Ae(e);re(JSON.stringify(t))<=128*1024?this.update({presented:t}):this.update({presented:{note:"System tray result exceeded 128 KiB. Inspect fewer presented notifications in the app.",count:Array.isArray(e)?e.length:null}})}async flush(){await this.queue}};function X(e){let t=g(e),o=g(t.notification??e),i=g(o.request),n=g(i.content),r=g(g(i.trigger).payload),s=g(n.data??r.body);return{notificationId:z(i.identifier),testId:z(s.__buoyTestId),title:z(n.title),actionIdentifier:z(t.actionIdentifier)}}function Bo(e){let t=g(e),o=g(t.notification);return JSON.stringify([g(o.request).identifier,o.date,t.actionIdentifier,t.userText])}function ot(e){if(!e||typeof e!="object")return;let t={};typeof e.appName=="string"&&(t.appName=e.appName.trim().slice(0,80)),typeof e.iconUri=="string"&&e.iconUri.length<=32768&&/^data:image\/(png|jpeg|webp);base64,[A-Za-z0-9+/]+={0,2}$/.test(e.iconUri)&&(t.iconUri=e.iconUri);for(let o of["backgroundColor","textColor"])typeof e[o]=="string"&&/^#[0-9a-f]{6}$/i.test(e[o])&&(t[o]=e[o]);return Object.keys(t).length?t:void 0}function pe(e,t=15e3){return new Promise((o,i)=>{let n=setTimeout(()=>i(new Error("Notification SDK timed out. Check permission and network settings, then retry.")),t);e.then(r=>{clearTimeout(n),o(r)},r=>{clearTimeout(n),i(r)})})}function it(e,t,o){let i=["received","responses","permissions","device-token"];(t.getLastNotificationResponse||t.getLastNotificationResponseAsync)&&i.push("startup-response"),t.getPresentedNotificationsAsync&&i.push("presented"),t.scheduleNotificationAsync&&i.push("local-scheduling"),o.projectId&&t.getExpoPushTokenAsync&&i.push("expo-token"),e.configure({preview:ot(o.preview),provider:"expo",platform:o.platform,appId:o.appId??null,providerVersion:o.providerVersion??null,capabilities:i});let n=false,r=[],s=(d,l=false)=>{n||!d||e.record(l?"startup-response":"response",d,{...X(d),dedupeKey:Bo(d)})};try{r.push(t.addNotificationReceivedListener(d=>{n||e.record("received",d,X(d))})),r.push(t.addNotificationResponseReceivedListener(d=>s(d))),r.push(t.addPushTokenListener(d=>{!n&&(d.type==="ios"||d.type==="android")&&e.observeToken(d.type==="ios"?"apns":"fcm",d.data).catch(()=>{})}))}catch(d){for(let l of r)l.remove();throw d}let h=Promise.resolve().then(()=>t.getLastNotificationResponse?.()??t.getLastNotificationResponseAsync?.()).then(d=>s(d,true));h.catch(()=>{});let p={async getPermissions(){let d=await pe(t.getPermissionsAsync());return e.setPermissions(d),e.getSnapshot().permissions},async listPresented(){if(!t.getPresentedNotificationsAsync)throw new Error("This notification SDK cannot list presented notifications.");let d=await pe(t.getPresentedNotificationsAsync());return e.setPresented(d),e.getSnapshot().presented},async refreshToken(d){let{type:l}=g(d);if(l==="expo"){if(!t.getExpoPushTokenAsync||!o.projectId)throw new Error("Set projectId in installExpoNotificationCapture before requesting an Expo token.");let N=await pe(t.getExpoPushTokenAsync({projectId:o.projectId}));return await e.observeToken("expo",N.data,{projectId:o.projectId}),{type:"expo",value:N.data}}if(l!=="device")throw new Error('Token type must be "device" or "expo".');if(!t.getDevicePushTokenAsync)throw new Error("This notification SDK cannot register a device token.");let m=await pe(t.getDevicePushTokenAsync());if(m.type!=="ios"&&m.type!=="android")throw new Error("This platform does not provide an APNs or FCM token.");return await e.observeToken(m.type==="ios"?"apns":"fcm",m.data),{type:m.type==="ios"?"apns":"fcm",value:m.data}},async scheduleLocal(d){if(!t.scheduleNotificationAsync)throw new Error("This notification SDK cannot schedule local notifications.");let{title:l,body:m,data:N,seconds:k}=g(d);if(typeof l!="string"||typeof m!="string"||typeof k!="number"||!Number.isFinite(k)||k<1||k>3600)throw new Error("Provide title, body and a delay from 1 to 3600 seconds.");if(N!==void 0&&(N===null||typeof N!="object"||Array.isArray(N)))throw new Error("Local notification data must be an object.");let _=await pe(t.scheduleNotificationAsync({content:{title:l,body:m,data:N??{}},trigger:{type:"timeInterval",seconds:k,repeats:false}}));return await e.record("local-scheduled",{title:l,body:m,data:N,seconds:k},{notificationId:_,title:l,testId:typeof g(N).__buoyTestId=="string"?g(N).__buoyTestId:null}),{notificationId:_,transport:"local"}}};return p.getPermissions().catch(()=>{}),{actions:p,ready:h,dispose(){n=true;for(let d of r)d.remove()}}}function Vo(e,t){let o=new Map;return{...t,handleNotification:async function(...i){let n=X(i[0]);n.notificationId&&o.set(n.notificationId,n),o.size>50&&o.delete(o.keys().next().value);try{let r=await t.handleNotification.apply(this,i);return e.record("presentation-decision",{notification:i[0],behavior:r},X(i[0])),r}catch(r){throw e.record("presentation-error",{notification:i[0],error:r},X(i[0])),r}},handleError:function(...i){let n=z(i[0]),r=n?o.get(n):void 0;return n&&o.delete(n),e.record("presentation-error",{source:"sdk",identifier:n,error:i[1]},r??{notificationId:n}),t.handleError?.apply(this,i)}}}function Ho(e){let t=X(e),o=g(e),i=g(o.data),n=g(i.UIApplicationLaunchOptionsRemoteNotificationKey),r={};if(typeof i.dataString=="string")try{r=g(JSON.parse(i.dataString))}catch{}let s=g(i.body??o.body??n.body);return{...t,testId:t.testId??z(r.__buoyTestId)??z(s.__buoyTestId),title:t.title??z(g(o.notification).title)??z(g(g(o.aps??n.aps).alert).title)}}async function Le(e){let t;await Promise.race([e.catch(()=>{}),new Promise(o=>{t=setTimeout(o,250)})]),t&&clearTimeout(t)}function Fo(e,t){return e.configure({capabilities:[...new Set([...e.getSnapshot().capabilities,"background-task"])]}),(async function(...o){let i=g(o[0]).data??o[0],n=Ho(i);await Le(e.record("background-started",o[0],n));try{let r=await t.apply(this,o);return await Le(e.record("background-completed",{input:o[0],result:r},n)),r}catch(r){throw await Le(e.record("background-error",{input:o[0],error:r},n)),r}})}var ae="PushNotifications",ue="LocalNotifications";function me(e){let t=g(e),o=g(t.notification??e),i=g(o.data??o.extra),n=g(i.body),r=o.id;return{notificationId:typeof r=="number"?String(r):z(r),testId:z(i.__buoyTestId)??z(n.__buoyTestId),title:z(o.title)??z(g(g(i.aps).alert).title),actionIdentifier:z(t.actionId)}}function he(e,t=15e3){return new Promise((o,i)=>{let n=setTimeout(()=>i(new Error("The notification plugin timed out. Check permission and network settings, then retry.")),t);e.then(r=>{clearTimeout(n),o(r)},r=>{clearTimeout(n),i(r)})})}function nt(e,t,o){let i=t.hasCapacitorPlugin(ae),n=t.hasCapacitorPlugin(ue),r=["received","responses","permissions"];i&&r.push("device-token","presented"),n&&r.push("local-scheduling"),n&&!i&&r.push("presented"),e.configure({preview:ot(o.preview),provider:"capacitor",platform:o.platform,appId:o.appId??null,providerVersion:o.providerVersion??null,capabilities:r}),t.installCapacitorBridge(),o.appId||t.loadCapacitorAppHost?.().then(b=>{b?.bundleId&&e.configure({appId:b.bundleId})}).catch(()=>{});let s=o.platform==="ios"?"apns":"fcm",h=0,p=new Set,d=250,l=new Map,m=(b,S)=>{let v=l.get(b);if(v!==void 0&&S-v<d)return null;if(l.set(b,S),l.size>100)for(let[C,A]of l)S-A>=d&&l.delete(C);return S},N=b=>{if(b.plugin!==ae&&b.plugin!==ue)return;let S=b.result,v=`${b.plugin}:${b.method}:${JSON.stringify(S??null).slice(0,1500)}`;if(b.kind==="event"&&m(v,b.start)===null)return;let C=`${v}:${b.start}`;if(b.kind==="event")switch(b.method){case"registration":{let A=z(g(S).value);A&&e.observeToken(s,A).catch(()=>{});return}case"pushNotificationReceived":case"localNotificationReceived":e.record("received",S,{...me(S),provider:"capacitor",dedupeKey:C});return;case"pushNotificationActionPerformed":case"localNotificationActionPerformed":e.record("response",S,{...me(S),provider:"capacitor",dedupeKey:C});return;default:return}if(!(b.kind!=="promise"||b.ok!==true))if(b.method==="checkPermissions"||b.method==="requestPermissions")e.setPermissions({plugin:b.plugin,...g(S)});else if(b.plugin===ue&&b.method==="schedule")for(let A of Array.isArray(b.options.notifications)?b.options.notifications:[]){let T=me(A);e.record("local-scheduled",A,{...T,provider:"capacitor"})}else b.method==="getDeliveredNotifications"&&e.setPresented(g(S).notifications??S)},k=()=>{let b=t.getCapacitorCalls();for(let v of b)v.seq<=h||p.has(v.seq)||v.kind==="promise"&&v.end===void 0||(p.add(v.seq),N(v));let S=b[0]?.seq??0;if(S>h+1){h=S-1;for(let v of Array.from(p))v<=h&&p.delete(v)}},_=t.subscribeCapacitorCalls(k);k();let F=i?ae:ue,D={async getPermissions(){if(!i&&!n)throw new Error("Install @capacitor/push-notifications or @capacitor/local-notifications in the app.");let b=await he(t.callCapacitorAsApp(F,"checkPermissions"));return e.setPermissions({plugin:F,...g(b)}),e.getSnapshot().permissions},async listPresented(){if(!i&&!n)throw new Error("This app has no notification plugin that can list presented notifications.");let b=await he(t.callCapacitorNative(F,"getDeliveredNotifications"));return e.setPresented(g(b).notifications??b),e.getSnapshot().presented},async refreshToken(b){let{type:S}=g(b);if(S==="expo")throw new Error("Expo push tokens need expo-notifications; this app uses Capacitor.");if(S!=="device")throw new Error('Token type must be "device".');if(!i)throw new Error("Install @capacitor/push-notifications to register a device token.");let v=null,C=new Promise((A,T)=>{t.listenCapacitorNative(ae,"registration",L=>{let K=z(g(L).value);K&&A(K)}).then(L=>{v=L.remove}),t.listenCapacitorNative(ae,"registrationError",L=>{T(new Error(z(g(L).error)??"Push registration failed."))}).then(L=>{let K=v;v=async()=>{await K?.(),await L.remove()}})});try{await he(t.callCapacitorNative(ae,"register"));let A=await he(C);return await e.observeToken(s,A),{type:s,value:A}}finally{v?.()}},async scheduleLocal(b){if(!n)throw new Error("Install @capacitor/local-notifications to schedule local notifications.");let{title:S,body:v,data:C,seconds:A}=g(b);if(typeof S!="string"||typeof v!="string"||typeof A!="number"||!Number.isFinite(A)||A<1||A>3600)throw new Error("Provide title, body and a delay from 1 to 3600 seconds.");if(C!==void 0&&(C===null||typeof C!="object"||Array.isArray(C)))throw new Error("Local notification data must be an object.");let T=Math.floor(Math.random()*2e9)+1,L={id:T,title:S,body:v,extra:C??{},schedule:{at:new Date(Date.now()+A*1e3).toISOString()}};return await he(t.callCapacitorNative(ue,"schedule",{notifications:[L]})),await e.record("local-scheduled",{title:S,body:v,data:C,seconds:A},{notificationId:String(T),title:S,testId:typeof g(C).__buoyTestId=="string"?g(C).__buoyTestId:null,provider:"capacitor"}),{notificationId:String(T),transport:"local"}}};return D.getPermissions().catch(()=>{}),{actions:D,ready:e.ready,dispose(){_()}}}import*as rt from"@buoy-gg/license/web";var ve=globalThis;function ze(e=false){return typeof ye<"u"&&ye||e===true}function Oe(){return ve.__buoyNotificationsV1?.recorder??null}function at(e){let t=ve.__buoyNotificationsV1;if(!t){let o=e.storage?{storage:e.storage,durable:e.durable===true}:Oo();t={recorder:new Re({...o,enabled:()=>ze(e.enableInRelease),appState:()=>Ue.currentState??"unknown",autoStart:true})},ve.__buoyNotificationsV1=t}return t}function Mo(e,t={}){if(!ze(t.enableInRelease))return null;let o=JSON.stringify([t.platform??ke.OS,t.appId,t.providerVersion,t.projectId,t.enableInRelease,t.preview]),i=at(t);return(i.sdk!==e||i.key!==o)&&(i.attachment?.dispose(),i.attachment=it(i.recorder,e,{...t,platform:t.platform??ke.OS}),i.sdk=e,i.key=o),i.recorder}function st(e={}){let t=rt.capacitorPlatform();if(!t||!ze(e.enableInRelease))return null;let o=JSON.stringify(["capacitor",e.appId,e.providerVersion,e.enableInRelease,e.preview]),i=at(e);return(i.sdk!=="capacitor"||i.key!==o)&&(i.attachment?.dispose(),i.attachment=nt(i.recorder,rt,{...e,platform:t}),i.sdk="capacitor",i.key=o),i.recorder}var lt=new Re;function Y(){let e=ve.__buoyNotificationsV1;if(!e)throw new Error("Install notification capture in the app entry point (installExpoNotificationCapture), before rendering the root component. Capacitor apps capture by themselves in debug builds.");return e}var se={version:1,getSnapshot:()=>(Oe()??lt).getSnapshot(),subscribe:e=>(Oe()??lt).subscribe(e),actions:{getSnapshot:()=>se.getSnapshot(),getCapabilities:()=>{let{ready:e,provider:t,providerVersion:o,platform:i,appId:n,capabilities:r,durable:s,storageError:h}=se.getSnapshot();return{ready:e,provider:t,providerVersion:o,platform:i,appId:n,capabilities:r,durable:s,storageError:h}},getEvent(e){let{id:t}=g(e);if(typeof t!="string")throw new Error("Provide the captured event id.");return Y().recorder.getSnapshot().events.find(o=>o.id===t)??null},async setCaptureSession(e){let{runId:t,durationMs:o}=g(e);if(typeof t!="string"&&t!==null)throw new Error("Provide runId, or null to stop capture.");if(o!==void 0&&typeof o!="number")throw new Error("durationMs must be a number.");return Y().recorder.setCaptureSession(t,o)},clearCapturedEvents:()=>Y().recorder.clearCapturedEvents(),getPermissions:()=>Y().attachment.actions.getPermissions(),listPresented:()=>Y().attachment.actions.listPresented(),refreshToken:e=>Y().attachment.actions.refreshToken(e),scheduleLocal:e=>Y().attachment.actions.scheduleLocal(e)}};import{useEffect as Ko,useMemo as ct,useState as Z}from"react";import{ChevronDown as Wo,ChevronLeft as $o,ChevronRight as dt,Copy as pt,ModalHeader as je,NightBadge as we,NightCard as q,NightRows as ut,NightSectionLabel as G,NightSegmented as _o,NotificationsIcon as Jo,PowerToggleButton as Uo,Search as qo,Settings as Go,ToolEmptyState as De,Trash2 as Xo,X as Yo,copyToClipboard as Zo,night as O,useSafeAreaInsets as Qo}from"@buoy-gg/shared-ui/web";import{DataViewer as ei}from"@buoy-gg/shared-ui/web/dataViewer";import{useRef as ti,useState as Q}from"react";import{NightSegmented as oi,night as le}from"@buoy-gg/shared-ui/web";import{useEffect as ii,useState as ht}from"react";import{CheckCircle as ni,ChevronDown as ri,ChevronRight as ai,NotificationsIcon as ft,XCircle as si,night as E,useSafeAreaInsets as li}from"@buoy-gg/shared-ui/web";import{jsx as P,jsxs as V}from"react/jsx-runtime";function yt(e){let[t,o]=ht(false);ii(()=>o(false),[e.appearance?.iconUri]);let i=e.appearance?.textColor?{color:e.appearance.textColor}:void 0,[n,r]=ht(false),s=li({minBottom:12});return V(f,{style:I.root,children:[P(ne,{testID:"notification-test-scroll",style:I.root,contentContainerStyle:I.scroll,keyboardShouldPersistTaps:"handled",children:V(f,{style:I.content,children:[V(f,{style:I.intro,children:[P(u,{accessibilityRole:"header",style:I.heading,children:"Test a notification"}),P(u,{style:I.caption,children:"Send a test notification to your app."})]}),e.destination,e.previewNote?P(u,{style:I.caption,children:e.previewNote}):V(f,{style:[I.preview,e.appearance?.backgroundColor?{backgroundColor:e.appearance.backgroundColor,borderColor:e.appearance.backgroundColor}:void 0],accessibilityLabel:"Notification preview",children:[V(f,{style:I.row,children:[e.appearance?.iconUri&&!t?P(Ge,{testID:"buoy-internal-notification-preview",source:{uri:e.appearance.iconUri},accessibilityLabel:`${e.appearance.appName??e.appName} icon`,style:I.appIcon,onError:()=>o(true)}):P(f,{style:I.iconFallback,children:P(ft,{size:22,color:E.color.accent})}),P(u,{numberOfLines:1,style:[I.caption,I.appName,i],children:e.appearance?.appName??e.appName}),P(u,{style:[I.caption,i],children:"now"})]}),P(de,{accessibilityLabel:"Notification title",placeholder:"Title",placeholderTextColor:E.color.placeholder,value:e.title,onChangeText:e.onTitleChange,style:[I.input,I.title,i],editable:!e.busy}),P(de,{accessibilityLabel:"Notification message",placeholder:"Message",placeholderTextColor:E.color.placeholder,value:e.message,onChangeText:e.onMessageChange,style:[I.input,i],editable:!e.busy})]}),e.result&&V(f,{accessibilityRole:"summary",accessibilityLiveRegion:"polite",testID:"notification-test-result",style:I.result,children:[V(f,{style:I.row,children:[e.result.failed?P(si,{size:16,color:E.color.danger}):P(ni,{size:16,color:E.color.accent}),P(u,{style:I.resultTitle,children:e.result.title})]}),P(u,{style:I.caption,children:e.result.message}),P(W,{accessibilityRole:"button",accessibilityLabel:"View activity",onPress:e.onViewActivity,style:I.secondary,children:P(u,{style:I.secondaryText,children:"View activity"})})]}),V(f,{children:[V(W,{accessibilityRole:"button",accessibilityLabel:"Notification options",accessibilityState:{expanded:n},onPress:()=>r(!n),style:I.options,children:[n?P(ri,{size:12,color:E.color.textSecondary}):P(ai,{size:12,color:E.color.textSecondary}),P(u,{style:I.caption,children:"Options"})]}),n&&e.options]})]})}),V(f,{style:[I.footer,{paddingBottom:s.bottom}],children:[!!e.error&&P(u,{accessibilityRole:"alert",style:I.error,children:e.error}),!!e.notice&&P(u,{accessibilityLiveRegion:"polite",style:I.caption,children:e.notice}),V(f,{style:I.footerRow,children:[P(u,{style:[I.caption,I.hint],children:e.hint}),V(W,{accessibilityRole:"button",accessibilityLabel:e.busy?"Sending\u2026":"Send notification",accessibilityState:{disabled:e.disabled||e.busy},disabled:e.disabled||e.busy,onPress:e.onSend,style:({pressed:h})=>[I.send,(e.disabled||e.busy)&&I.disabled,h&&I.pressed],children:[P(ft,{size:15,color:E.color.onAccent}),P(u,{style:I.sendText,children:e.busy?"Sending\u2026":"Send notification"})]})]})]})]})}var I=ge.create({root:{flex:1,minHeight:0,minWidth:0},scroll:{padding:16,flexGrow:1},content:{width:"100%",maxWidth:620,alignSelf:"center",gap:20},intro:{gap:8,paddingTop:8},heading:{color:E.color.text,fontSize:22,fontWeight:"600",letterSpacing:-.5},caption:{color:E.color.textSecondary,fontSize:12,lineHeight:18},row:{flexDirection:"row",alignItems:"center",gap:8},appName:{flex:1,fontWeight:"600"},appIcon:{width:36,height:36,borderRadius:8},iconFallback:{width:36,height:36,alignItems:"center",justifyContent:"center",borderRadius:8,backgroundColor:E.color.fillSecondary},preview:{padding:16,gap:8,borderWidth:1,borderColor:E.color.glassBorder,borderRadius:20,backgroundColor:E.color.glass},input:{color:E.color.text,fontSize:14,padding:6,minHeight:36},title:{fontSize:16,fontWeight:"600"},result:{gap:10,padding:16,borderWidth:1,borderColor:E.color.glassBorder,borderRadius:14},resultTitle:{color:E.color.text,fontWeight:"500",fontSize:13,flexShrink:1},secondary:{alignSelf:"flex-start",paddingHorizontal:14,paddingVertical:8,borderRadius:24,backgroundColor:E.color.fillSecondary},secondaryText:{color:E.color.accent,fontSize:13},options:{flexDirection:"row",alignItems:"center",gap:6,paddingVertical:12},footer:{padding:14,gap:8,borderTopWidth:1,borderTopColor:E.color.separator},footerRow:{flexDirection:"row",flexWrap:"wrap",alignItems:"center",justifyContent:"space-between",gap:12},hint:{flexGrow:1,flexShrink:1,flexBasis:200},send:{flexDirection:"row",alignItems:"center",justifyContent:"center",gap:8,borderRadius:24,paddingHorizontal:18,paddingVertical:12,backgroundColor:E.color.accent},sendText:{color:E.color.onAccent,fontSize:13,fontWeight:"600"},disabled:{opacity:.4},pressed:{opacity:.8},error:{color:E.color.danger,fontSize:12,lineHeight:18}});import{jsx as $,jsxs as Se}from"react/jsx-runtime";function ci({snapshot:e,onAction:t,onViewActivity:o}){let[i,n]=Q("Test notification"),[r,s]=Q("Tap to open the app."),[h,p]=Q("{}"),[d,l]=Q("1"),[m,N]=Q(false),k=ti(false),[_,F]=Q(null),[D,b]=Q(null),S={},v=null;try{if(S=JSON.parse(h),!S||typeof S!="object"||Array.isArray(S))throw new Error}catch{v="Custom data must be a JSON object. Open Options to edit it."}async function C(){if(k.current||v)return;k.current=true,N(true),b(null),F(null);let R={testId:`buoy-local-${Date.now()}-${Math.random().toString(36).slice(2)}`,startedAt:Date.now(),appId:e?.appId??null};try{await t("setCaptureSession",{runId:R.testId,durationMs:18e5}),await t("scheduleLocal",{title:i,body:r,data:{...S,__buoyTestId:R.testId},seconds:Number(d)}),b(R)}catch(te){F(te instanceof Error?te.message:String(te))}finally{k.current=false,N(false)}}let A=D&&D.appId===e?.appId?e.events.filter(R=>R.testId===D.testId&&R.capturedAt>=D.startedAt):[],T=A.some(R=>R.kind==="received"),L=A.some(R=>R.kind==="response"||R.kind==="startup-response"),K=A.some(R=>R.kind==="app-outcome"),J=!!e?.capabilities.includes("local-scheduling");return $(yt,{title:i,message:r,onTitleChange:n,onMessageChange:s,appName:"This app",appearance:e?.preview,destination:Se(f,{style:H.destination,children:[Se(f,{style:H.field,children:[$(u,{style:H.label,children:"Device"}),$(u,{style:H.value,children:"This device"})]}),Se(f,{style:H.field,children:[$(u,{style:H.label,children:"Delivery"}),$(u,{style:H.value,children:"Local notification"})]})]}),options:Se(f,{style:H.options,children:[$(u,{style:H.label,children:"Send after"}),$(oi,{tabs:[{key:"1",label:"1 second"},{key:"10",label:"10 seconds"}],activeKey:d,onChange:l,size:"sm",glass:true}),$(u,{style:H.label,children:"Custom data"}),$(de,{accessibilityLabel:"Notification custom data",value:h,onChangeText:p,multiline:true,autoCapitalize:"none",autoCorrect:false,style:H.json}),$(u,{style:H.label,children:"Use the delay to leave the app before delivery. Simulator push and raw APNs payloads are available on desktop."})]}),result:D?{title:K?"App reported an outcome":L?"Notification tapped":T?"Received by app":"Notification scheduled",message:L?"Open Activity to inspect the app\u2019s response.":"Tap the notification to test what opens."}:null,onViewActivity:o,onSend:()=>{C()},busy:m,disabled:!J||!!v,error:_??v,hint:J?d==="10"?"You have 10 seconds to leave the app.":"Sends locally on this device after one second.":"Connect Expo notification capture to send a local test."})}var H=ge.create({destination:{flexDirection:"row",gap:12},field:{flex:1,gap:7},label:{color:le.color.textSecondary,fontSize:12,lineHeight:18},value:{color:le.color.text,fontSize:13,borderWidth:1,borderColor:le.color.glassBorder,backgroundColor:le.color.glass,borderRadius:10,padding:11},options:{gap:12},json:{color:le.color.text,fontSize:12,minHeight:100,textAlignVertical:"top",padding:12,borderWidth:1,borderColor:le.color.glassBorder,borderRadius:10}});import{monoFont as fe,night as w}from"@buoy-gg/shared-ui/web";var c=ge.create({root:{flex:1,minHeight:0,backgroundColor:"transparent"},fill:{flex:1,minHeight:0},inlineHeader:{paddingHorizontal:12,paddingVertical:8,borderBottomWidth:1,borderBottomColor:w.color.separator},status:{flexDirection:"row",alignItems:"center",flexWrap:"wrap",gap:12,paddingHorizontal:16,paddingVertical:9},statusLabel:{flexDirection:"row",alignItems:"center",gap:6},dot:{width:5,height:5,borderRadius:3,backgroundColor:w.color.textTertiary},liveDot:{backgroundColor:w.color.accent},caption:{color:w.color.textSecondary,fontSize:12,lineHeight:17},provider:{color:w.color.textSecondary,fontSize:11,marginLeft:"auto",fontFamily:fe},content:{padding:14,gap:20},eventList:{paddingHorizontal:12,paddingTop:2},searchRow:{flexDirection:"row",gap:8,paddingHorizontal:12,paddingBottom:10,alignItems:"center"},searchField:{flex:1,minWidth:0,height:36,flexDirection:"row",alignItems:"center",gap:8,paddingHorizontal:10,backgroundColor:w.color.glass,borderWidth:1,borderColor:w.color.glassBorder,borderRadius:w.radius.row},searchInput:{flex:1,minWidth:0,height:"100%",color:w.color.text,fontSize:13,padding:0},clearSearch:{padding:6},iconButton:{width:34,height:34,alignItems:"center",justifyContent:"center",backgroundColor:w.color.buttonSurface,borderRadius:8,borderWidth:1,borderColor:w.color.border},event:{backgroundColor:w.color.glass,borderRadius:w.radius.input,borderWidth:1,borderColor:w.color.glassBorder,paddingHorizontal:12,paddingVertical:10,marginBottom:6,gap:6},eventTop:{flexDirection:"row",alignItems:"center",gap:10,justifyContent:"space-between"},eventKind:{flexDirection:"row",alignItems:"center",gap:6,flex:1,minWidth:0},eventLabel:{flexShrink:1,fontSize:11,fontWeight:"600"},timestamp:{color:w.color.textSecondary,fontFamily:fe,fontSize:10},eventSubject:{flexDirection:"row",alignItems:"center",gap:8},eventTitle:{flex:1,color:w.color.text,fontSize:15,fontWeight:"500"},eventMeta:{color:w.color.textSecondary,fontFamily:fe,fontSize:10,lineHeight:15},resultCount:{color:w.color.textSecondary,fontSize:12,marginBottom:10,marginLeft:4},actionRow:{flexDirection:"row",alignItems:"center",flexWrap:"wrap",gap:8},button:{flexDirection:"row",alignItems:"center",justifyContent:"center",gap:6,minHeight:34,paddingVertical:8,paddingHorizontal:14,borderRadius:w.radius.pill,backgroundColor:w.color.fillSecondary,alignSelf:"flex-start"},buttonText:{color:w.color.accent,fontSize:13,fontWeight:"600"},primaryButton:{backgroundColor:w.color.accent},primaryButtonText:{color:w.color.onAccent},pressed:{opacity:.7},disabled:{opacity:.4},detailTitle:{color:w.color.text,fontSize:20,fontWeight:"600"},field:{flexDirection:"row",paddingHorizontal:16,paddingVertical:12,gap:14},fieldLabel:{width:110,flexShrink:0},value:{flex:1,minWidth:0,color:w.color.text,fontFamily:fe,fontSize:12,lineHeight:18},disclosure:{flexDirection:"row",alignItems:"center",justifyContent:"space-between",paddingHorizontal:16,paddingVertical:14},disclosureTitle:{color:w.color.text,fontSize:13,fontWeight:"500"},jsonBody:{padding:10,borderTopWidth:1,borderTopColor:w.color.separator},token:{color:w.color.text,fontFamily:fe,fontSize:12,lineHeight:20},bodyText:{color:w.color.text,fontSize:14,lineHeight:21},footnote:{color:w.color.textSecondary,fontSize:12,lineHeight:18,marginTop:8,marginHorizontal:4},emptyFootnote:{color:w.color.textSecondary,fontSize:12,lineHeight:18,textAlign:"center",marginHorizontal:28},sectionActions:{flexDirection:"row",marginBottom:10},warning:{color:w.color.warning,fontSize:12,lineHeight:18},notice:{color:w.color.accent,backgroundColor:w.color.glass,paddingHorizontal:16,paddingVertical:10,fontSize:12,lineHeight:18},errorNotice:{color:w.color.danger,backgroundColor:w.color.glass,paddingHorizontal:16,paddingVertical:10,fontSize:12,lineHeight:18},errorText:{color:w.color.danger}});import{Fragment as Be,jsx as a,jsxs as y}from"react/jsx-runtime";var Ve={received:"App received",response:"Notification response","startup-response":"Response recovered at startup","presentation-decision":"Presentation decision","presentation-error":"Presentation error","background-started":"Background task started","background-completed":"Background task completed","background-error":"Background task failed","app-outcome":"App outcome","local-scheduled":"Local notification scheduled"};function gt(e){return e.includes("error")?"danger":e==="startup-response"?"warning":e==="received"||e==="app-outcome"?"accent":"neutral"}function M({label:e,onPress:t,disabled:o,primary:i,icon:n}){return y(W,{accessibilityRole:"button",accessibilityLabel:e,accessibilityState:{disabled:!!o},disabled:o,onPress:t,style:({pressed:r})=>[c.button,i&&c.primaryButton,r&&c.pressed,o&&c.disabled],children:[n,a(u,{style:[c.buttonText,i&&c.primaryButtonText],children:e})]})}function ee({label:e,value:t}){return y(f,{style:c.field,children:[a(u,{style:[c.caption,c.fieldLabel],children:e}),a(u,{selectable:true,style:c.value,children:t})]})}function xe({title:e,value:t,initiallyOpen:o=true}){let[i,n]=Z(o),r=JSON.stringify(t??null),s=ct(()=>JSON.parse(r),[r]);return y(q,{glass:true,children:[y(W,{accessibilityRole:"button",accessibilityLabel:e,accessibilityState:{expanded:i},onPress:()=>n(h=>!h),style:c.disclosure,children:[a(u,{style:c.disclosureTitle,children:e}),i?a(Wo,{size:14,color:O.color.textSecondary}):a(dt,{size:14,color:O.color.textSecondary})]}),i&&a(f,{style:c.jsonBody,children:a(ei,{title:"",data:s,rawMode:true,initialExpanded:true,showTypeFilter:false})})]})}function bt({snapshot:e,onAction:t,sender:o,activeTab:i,onTabChange:n,renderShell:r}){let[s,h]=Z("send"),p=i??s,[d,l]=Z(""),[m,N]=Z(null),[k,_]=Z(false),[F,D]=Z(null),[,b]=Z(0),S=Qo({minBottom:16}),v=e?.session?.expiresAt;Ko(()=>{if(!v||v<=Date.now())return;let x=setTimeout(()=>b(U=>U+1),v-Date.now()+1);return()=>clearTimeout(x)},[v]);let C=!!v&&v>Date.now(),A=ct(()=>(e?.events??[]).filter(x=>JSON.stringify(x).toLowerCase().includes(d.trim().toLowerCase())).slice().reverse(),[e?.events,d]),T=e?.events.find(x=>x.id===m),L=e?.events.length??0,K=!!e?.provider;function J(x){h(x),n?.(x),D(null)}async function R(x,U){if(k)return false;_(true),D(null);try{return await t(x,U),true}catch(Ie){return D({text:Ie instanceof Error?Ie.message:String(Ie),error:true}),false}finally{_(false)}}let te=()=>{R("setCaptureSession",{runId:`capture-${Date.now()}`,durationMs:18e5})},Fe=()=>{R("setCaptureSession",{runId:null})};async function Me(x){let U=await Zo(x);D({text:U?"Copied to clipboard.":"Clipboard is unavailable. Select the text to copy it.",error:!U})}let wt=[{key:"send",label:"Test"},{key:"events",label:`Activity (${L})`}],Ke=y(je,{children:[a(je.Content,{title:"",noMargin:true,children:a(_o,{tabs:wt,activeKey:p,onChange:J,size:"sm",glass:true})}),y(je.Actions,{children:[a(W,{accessibilityRole:"button",accessibilityLabel:"Notification settings",onPress:()=>J(p==="setup"||p==="tokens"?"send":"setup"),style:c.iconButton,children:a(Go,{size:16,color:p==="setup"||p==="tokens"?O.color.accent:O.color.textSecondary})}),p!=="send"&&a(Uo,{isEnabled:C,onToggle:C?Fe:te,disabled:!K||k,accessibilityLabel:C?"Stop notification capture":"Start notification capture",testID:"notifications-capture"})]})]}),We=y(f,{style:c.root,children:[K&&p!=="send"&&y(f,{style:c.status,children:[y(f,{style:c.statusLabel,children:[a(f,{style:[c.dot,C&&c.liveDot]}),a(u,{style:c.caption,children:C?"Recording":"Capture stopped"})]}),p!=="events"&&a(u,{style:c.caption,children:e.durable?"Persistent history":"Memory only"}),p!=="events"&&y(u,{style:c.provider,children:[e.provider," \xB7 ",e.platform]})]}),e?.storageError&&y(u,{accessibilityRole:"alert",style:c.errorNotice,children:["Storage: ",e.storageError]}),F&&a(u,{accessibilityRole:F.error?"alert":"text",style:[c.notice,F.error&&c.errorText],children:F.text}),!o&&a(f,{style:p==="send"?c.fill:{display:"none"},children:a(ci,{snapshot:e,onAction:t,onViewActivity:()=>J("events")})}),p==="send"?o??null:K?y(Be,{children:[p==="events"&&y(Be,{children:[y(f,{style:c.searchRow,children:[y(f,{style:c.searchField,children:[a(qo,{size:14,color:O.color.textSecondary}),a(de,{accessibilityLabel:"Filter notification events",placeholder:"Search notifications\u2026",placeholderTextColor:O.color.placeholder,value:d,onChangeText:x=>{l(x),N(null)},autoCapitalize:"none",autoCorrect:false,style:c.searchInput}),!!d&&a(W,{accessibilityRole:"button",accessibilityLabel:"Clear notification search",onPress:()=>l(""),style:c.clearSearch,children:a(Yo,{size:12,color:O.color.textSecondary})})]}),a(W,{accessibilityRole:"button",accessibilityLabel:"Clear captured events",disabled:k||!L,accessibilityState:{disabled:k||!L},style:[c.iconButton,(k||!L)&&c.disabled],onPress:()=>{R("clearCapturedEvents").then(x=>{x&&N(null)})},children:a(Xo,{size:14,color:O.color.textSecondary})})]}),T?y(ne,{style:c.fill,contentContainerStyle:[c.content,{paddingBottom:S.bottom}],keyboardShouldPersistTaps:"handled",children:[y(f,{style:c.actionRow,children:[a(M,{label:"Back to events",onPress:()=>N(null),icon:a($o,{size:14,color:O.color.accent})}),a(M,{label:"Copy event JSON",onPress:()=>{Me(T)},icon:a(pt,{size:14,color:O.color.accent})})]}),y(q,{glass:true,padded:true,children:[a(we,{label:Ve[T.kind]??T.kind,tone:gt(T.kind)}),a(u,{style:c.detailTitle,children:T.title??"Notification event"}),a(u,{style:c.caption,children:new Date(T.capturedAt).toLocaleString()})]}),y(f,{children:[a(G,{children:"Observation"}),a(q,{glass:true,children:y(ut,{children:[a(ee,{label:"App state at callback",value:T.observedAppState}),T.testId&&a(ee,{label:"Test ID",value:T.testId}),T.notificationId&&a(ee,{label:"Notification ID",value:T.notificationId}),T.actionIdentifier&&a(ee,{label:"Action",value:T.actionIdentifier})]})})]}),T.kind==="startup-response"&&a(u,{style:c.footnote,children:"Recovered from the SDK cache. This alone does not establish why the app launched."}),T.truncated&&a(u,{style:c.warning,children:"This payload was truncated when captured."}),a(xe,{title:"Payload",value:T.raw}),a(xe,{title:"Full event",value:T,initiallyOpen:false})]}):a(qe,{data:A,keyExtractor:x=>x.id,style:c.fill,contentContainerStyle:[c.eventList,{paddingBottom:S.bottom}],keyboardShouldPersistTaps:"handled",initialNumToRender:15,ListHeaderComponent:d?y(u,{style:c.resultCount,children:[A.length," of ",L," events"]}):null,ListFooterComponent:e.evicted>0?y(u,{style:c.footnote,children:[e.evicted," older records removed by the history limit."]}):null,ListEmptyComponent:a(De,{otto:d?"sad":C?"listening":"paused",title:d?"No matching events":C?"Waiting for notifications":"Capture is stopped",message:d?"Try another title, test ID, or payload value.":C?"Send a notification from Buoy Desktop or your app. Background alerts can reach the system tray before an app callback runs.":"Start capture with the power button, then send a notification."}),renderItem:({item:x})=>a(di,{event:x,onPress:()=>N(x.id)})})]}),p==="tokens"&&y(ne,{style:c.fill,contentContainerStyle:[c.content,{paddingBottom:S.bottom}],keyboardShouldPersistTaps:"handled",children:[y(f,{children:[a(M,{label:"Back to settings",onPress:()=>J("setup")}),a(G,{children:"Registration"}),y(q,{glass:true,padded:true,children:[a(u,{style:c.bodyText,children:"Register a token to test delivery through your push provider."}),y(f,{style:c.actionRow,children:[a(M,{label:"Register device token",onPress:()=>{R("refreshToken",{type:"device"})},disabled:k,primary:true}),a(M,{label:"Register Expo token",onPress:()=>{R("refreshToken",{type:"expo"})},disabled:k||!e.capabilities.includes("expo-token")})]})]}),a(u,{style:c.footnote,children:"Registration runs only when you or your app request it. Simulator sends work without a token."})]}),e.tokens.length===0?a(De,{otto:"listening",title:"No tokens observed",message:"Register a device token above, or let your app register one."}):e.tokens.map((x,U)=>y(f,{children:[a(G,{children:x.type.toUpperCase()+" token"}),y(q,{glass:true,padded:true,children:[y(f,{style:c.actionRow,children:[a(we,{label:x.type,tone:"accent"}),x.environment&&a(u,{style:c.caption,children:x.environment})]}),a(u,{selectable:true,style:c.token,children:x.value}),x.projectId&&y(u,{selectable:true,style:c.caption,children:["Project: ",x.projectId]}),y(u,{style:c.caption,children:["Observed ",new Date(x.observedAt).toLocaleString()]}),a(f,{style:c.actionRow,children:a(M,{label:"Copy "+x.type.toUpperCase()+" token",onPress:()=>{Me(x.value)},icon:a(pt,{size:14,color:O.color.accent})})})]})]},x.type+"-"+U))]}),p==="setup"&&y(ne,{style:c.fill,contentContainerStyle:[c.content,{paddingBottom:S.bottom}],keyboardShouldPersistTaps:"handled",children:[y(f,{children:[a(M,{label:"Device tokens",onPress:()=>J("tokens")}),a(G,{children:"Capture session"}),y(q,{glass:true,padded:true,children:[y(f,{style:c.actionRow,children:[a(we,{label:C?"Recording":"Stopped",tone:C?"accent":"neutral"}),a(u,{style:c.caption,children:C?"Until "+new Date(v).toLocaleTimeString():"Ready when you are"})]}),y(f,{style:c.actionRow,children:[a(M,{label:"Arm capture for 30 minutes",onPress:te,disabled:k,primary:true}),a(M,{label:"Stop capture",onPress:Fe,disabled:k||!C})]})]}),a(u,{style:c.footnote,children:e.durable?"History is saved on the app and survives app and desktop restarts.":"History is held in memory. Keep the app running to retain it."})]}),y(f,{children:[a(G,{children:"Connected app"}),a(q,{glass:true,children:y(ut,{children:[a(ee,{label:"App",value:e.appId??"Not supplied"}),a(ee,{label:"Provider",value:[e.provider,e.providerVersion].filter(Boolean).join(" ")}),a(ee,{label:"Platform",value:e.platform})]})})]}),y(f,{children:[a(G,{children:"Permissions"}),a(f,{style:c.sectionActions,children:a(M,{label:"Refresh permissions",disabled:k,onPress:()=>{R("getPermissions")}})}),a(xe,{title:"Permission settings",value:e.permissions})]}),y(f,{children:[a(G,{children:"System tray"}),a(f,{style:c.sectionActions,children:a(M,{label:"Inspect system tray",disabled:k||!e.capabilities.includes("presented"),onPress:()=>{R("listPresented")}})}),a(xe,{title:"Currently presented",value:e.presented}),a(u,{style:c.footnote,children:"Notifications currently in the system tray. Captured history is in Activity."})]}),y(f,{children:[a(G,{children:"Capabilities"}),a(q,{glass:true,padded:true,children:a(f,{style:c.actionRow,children:e.capabilities.map(x=>a(we,{label:x},x))})})]})]})]}):y(ne,{children:[a(De,{otto:"paused",title:"Connect notification capture",message:"Install @buoy-gg/notifications and call installExpoNotificationCapture in the app entry point. Use an app-specific development build for remote notifications."}),a(u,{style:c.emptyFootnote,children:"The desktop sender works with any installed app. Inspection needs the capture integration."})]})]});return a(Be,{children:r?r({header:Ke,body:We}):y(f,{style:c.root,children:[a(f,{style:c.inlineHeader,children:Ke}),We]})})}function di({event:e,onPress:t}){let o=gt(e.kind),i=o==="danger"?O.color.danger:o==="warning"?O.color.warning:o==="accent"?O.color.accent:O.color.textSecondary;return y(W,{accessibilityRole:"button",accessibilityLabel:(Ve[e.kind]??e.kind)+": "+(e.title??e.testId??e.notificationId??"notification"),onPress:t,style:({pressed:n})=>[c.event,n&&c.pressed],children:[y(f,{style:c.eventTop,children:[y(f,{style:c.eventKind,children:[a(Jo,{size:13,color:i}),a(u,{numberOfLines:1,style:[c.eventLabel,{color:i}],children:Ve[e.kind]??e.kind})]}),a(u,{style:c.timestamp,children:new Date(e.capturedAt).toLocaleTimeString()})]}),y(f,{style:c.eventSubject,children:[a(u,{numberOfLines:1,style:c.eventTitle,children:e.title??e.testId??e.notificationId??"Notification event"}),a(dt,{size:14,color:O.color.textTertiary})]}),y(u,{numberOfLines:1,style:c.eventMeta,children:[e.observedAppState,e.truncated?" \xB7 Truncated":""]})]})}import{useSyncExternalStore as pi}from"react";import{createToolFactory as ui,defineToolPreset as hi,JsModal as fi,NotificationsIcon as yi}from"@buoy-gg/shared-ui/web";import{jsx as He}from"react/jsx-runtime";function mt(e){let t=pi(se.subscribe,se.getSnapshot);return He(bt,{snapshot:t,renderShell:({header:o,body:i})=>He(fi,{...e,persistenceKey:e.persistenceKey??"buoy-notifications",variant:"night",header:{showToggleButton:true,customContent:o},enablePersistence:true,initialMode:"bottomSheet",disableScrollWrapper:true,children:i}),onAction:async(o,i)=>{let n=se.actions[o];if(!n)throw new Error("This notification action is unavailable.");return n(i)}})}var vt=hi({id:"push-notifications",name:"NOTIFICATIONS",description:"Send a test notification and inspect how the app responds",slot:"both",icon:({size:e,color:t})=>He(yi,{size:e,color:t}),component:mt}),gi=ui(vt);import{NotificationsIcon as bi}from"@buoy-gg/shared-ui/web";function mi(e){let t={...e.data,__buoyTestId:e.testId},o=e.silent?{"content-available":1}:{alert:{title:e.title,body:e.body},sound:"default"};return JSON.stringify(e.adapter==="expo"?{aps:o,body:t}:{...t,aps:o},null,2)}function vi(e){let t=[],o=[];if(typeof e!="string")return{valid:false,bytes:0,errors:["Provide the APNs payload as JSON text."],warnings:o,testId:null};let i=re(e);i>4096&&t.push(`Payload is ${i} bytes. APNs payloads must fit in 4096 UTF-8 bytes.`);let n;try{n=JSON.parse(e)}catch{t.push("Payload is not valid JSON.")}let r=g(n);(!n||typeof n!="object"||Array.isArray(n))&&t.push("The payload must be a JSON object."),(!r.aps||typeof r.aps!="object"||Array.isArray(r.aps))&&t.push('The payload needs an "aps" object.');let s=g(r.aps);s.alert!==void 0&&typeof s.alert!="string"&&(s.alert===null||typeof s.alert!="object"||Array.isArray(s.alert))&&t.push("aps.alert must be text or an object."),s.badge!==void 0&&(!Number.isInteger(s.badge)||Number(s.badge)<0)&&t.push("aps.badge must be a non-negative integer.");for(let p of["content-available","mutable-content"])s[p]!==void 0&&s[p]!==1&&t.push(`aps.${p} must be 1 when present.`);s["content-available"]===1&&o.push("Background execution depends on app configuration and OS scheduling. A successful send does not prove the task ran."),s["mutable-content"]===1&&o.push("Use real APNs delivery to verify notification service extensions."),r.data!==void 0&&r.body===void 0&&o.push("Expo on iOS reads custom data from a top-level body object. This raw payload will be sent unchanged.");let h=g(r.body).__buoyTestId??r.__buoyTestId;return{valid:t.length===0,bytes:i,errors:t,warnings:o,testId:typeof h=="string"?h:null}}var wi=(()=>{try{return globalThis.Capacitor?.isNativePlatform?.()===true}catch{return false}})();wi&&typeof ye<"u"&&ye&&st();export{Re as NotificationRecorder,yt as NotificationTestView,bt as NotificationToolView,bi as NotificationsIcon,mt as NotificationsModal,nt as attachCapacitorNotifications,it as attachExpoNotifications,me as capacitorMetadata,mi as composeSimulatorPayload,Lo as createExpoNotificationStorage,gi as createNotificationTool,X as expoMetadata,Oe as getNotificationRecorder,st as installCapacitorNotificationCapture,Mo as installExpoNotificationCapture,Vo as instrumentExpoNotificationHandler,Fo as instrumentNotificationBackgroundTask,se as notificationSyncAdapter,vt as notificationToolPreset,vi as validateSimulatorPayload};
1
+ "use client";var _e=Object.defineProperty;var xt=Object.getOwnPropertyDescriptor;var It=Object.getOwnPropertyNames;var kt=Object.prototype.hasOwnProperty;var Ct=(e,t)=>{for(var o in t)_e(e,o,{get:t[o],enumerable:true})},Je=(e,t,o,i)=>{if(t&&typeof t=="object"||typeof t=="function")for(let n of It(t))!kt.call(e,n)&&n!==o&&_e(e,n,{get:()=>t[n],enumerable:!(i=xt(t,n))||i.enumerable});return e},Tt=(e,t,o)=>(Je(e,t,"default"),o&&Je(o,t,"default"));var ye=(()=>{try{let e=globalThis.Capacitor;if(e&&typeof e.isNativePlatform=="function"&&e.isNativePlatform())return e.DEBUG===true}catch{}return process.env.NODE_ENV!=="production"})();typeof window<"u"&&typeof globalThis.global>"u"&&(globalThis.global=globalThis);var Ue={};Ct(Ue,{AccessibilityInfo:()=>Et,ActivityIndicator:()=>Po,Alert:()=>Lo,Animated:()=>Io,AppRegistry:()=>Lt,AppState:()=>qe,Appearance:()=>Rt,BackHandler:()=>zt,Button:()=>Eo,CheckBox:()=>qt,Clipboard:()=>Ot,DeviceEventEmitter:()=>lo,Dimensions:()=>jt,Easing:()=>Dt,FlatList:()=>Ge,I18nManager:()=>Bt,Image:()=>Xe,ImageBackground:()=>Gt,InteractionManager:()=>Ht,Keyboard:()=>Vt,KeyboardAvoidingView:()=>Xt,LayoutAnimation:()=>Ft,Linking:()=>Mt,LogBox:()=>so,Modal:()=>Ao,NativeEventEmitter:()=>Wt,NativeModules:()=>Pt,PanResponder:()=>Kt,Picker:()=>Yt,PixelRatio:()=>$t,Platform:()=>ke,Pressable:()=>K,ProgressBar:()=>Zt,RefreshControl:()=>Qt,SafeAreaView:()=>eo,ScrollView:()=>ne,SectionList:()=>to,Share:()=>_t,StatusBar:()=>oo,StyleSheet:()=>ge,Switch:()=>No,Text:()=>u,TextInput:()=>de,Touchable:()=>io,TouchableHighlight:()=>Co,TouchableNativeFeedback:()=>no,TouchableOpacity:()=>ko,TouchableWithoutFeedback:()=>To,UIManager:()=>Jt,Vibration:()=>Ut,View:()=>f,VirtualizedList:()=>ro,YellowBox:()=>ao,findNodeHandle:()=>Ro,unstable_createElement:()=>Nt,useColorScheme:()=>co,useLocaleContext:()=>po,useWindowDimensions:()=>uo});Tt(Ue,At);import*as At from"react-native-web";import{unstable_createElement as Nt,NativeModules as Pt,AccessibilityInfo as Et,Appearance as Rt,AppRegistry as Lt,AppState as qe,BackHandler as zt,Clipboard as Ot,Dimensions as jt,Easing as Dt,I18nManager as Bt,Keyboard as Vt,InteractionManager as Ht,LayoutAnimation as Ft,Linking as Mt,NativeEventEmitter as Wt,PanResponder as Kt,PixelRatio as $t,Platform as ke,Share as _t,UIManager as Jt,Vibration as Ut,CheckBox as qt,FlatList as Ge,Image as Xe,ImageBackground as Gt,KeyboardAvoidingView as Xt,Picker as Yt,ProgressBar as Zt,RefreshControl as Qt,SafeAreaView as eo,SectionList as to,StatusBar as oo,Touchable as io,TouchableNativeFeedback as no,VirtualizedList as ro,YellowBox as ao,LogBox as so,DeviceEventEmitter as lo,useColorScheme as co,useLocaleContext as po,useWindowDimensions as uo}from"react-native-web";import*as j from"react-native-web";import{createElement as Ce,forwardRef as Ye,useCallback as ho,useRef as fo}from"react";import{useEffect as yo,useState as go}from"react";import{createPortal as bo}from"react-dom";var mo='-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif';import{jsx as vo}from"react/jsx-runtime";var ce=Symbol.for("@buoy-gg/portal-host"),Ze=e=>{if(!(e instanceof Element))return false;if(e.closest("input, textarea, select"))return true;let t=e.closest("[contenteditable]")?.getAttribute("contenteditable")?.toLowerCase();return t===""||t==="true"||t==="plaintext-only"};function Qe(){let e=document;if(e[ce])return e[ce].host;let t=document.createElement("div");t.dataset.buoyPortalHost="",Object.assign(t.style,{position:"fixed",inset:"0",zIndex:"2147483647",pointerEvents:"none",fontFamily:mo});let o=()=>{let c=document.fullscreenElement,m=c&&c.tagName!=="CANVAS"?c:document.body;t.parentElement!==m&&m.appendChild(t)},i=new Map,n=c=>{(!t.contains(c.target)||!Ze(c.target))&&i.set(c.code||c.key,{key:c.key,code:c.code,location:c.location,keyCode:c.keyCode,which:c.which,altKey:c.altKey,ctrlKey:c.ctrlKey,metaKey:c.metaKey,shiftKey:c.shiftKey})},r=c=>{i.delete(c.code||c.key)},l=()=>i.clear(),h=()=>{let c=[...i.values()];i.clear();for(let m of c)document.dispatchEvent(new KeyboardEvent("keyup",{...m,bubbles:true}))},p=c=>{Ze(c.target)&&c.stopPropagation()},d=c=>c.stopPropagation();return o(),document.addEventListener("fullscreenchange",o),document.addEventListener("keydown",n,true),document.addEventListener("keyup",r,true),window.addEventListener("blur",l),t.addEventListener("focusin",h),t.addEventListener("keydown",p),t.addEventListener("keyup",p),t.addEventListener("keypress",p),t.addEventListener("wheel",d,{passive:true}),e[ce]={host:t,users:0,dispose:()=>{document.removeEventListener("fullscreenchange",o),document.removeEventListener("keydown",n,true),document.removeEventListener("keyup",r,true),window.removeEventListener("blur",l),t.remove(),delete e[ce]}},t}function wo({children:e}){let[t,o]=go(null);return yo(()=>{let i=Qe(),n=document[ce];return n.users++,o(i),()=>{--n.users===0&&n.dispose()}},[]),t?bo(vo("div",{"data-buoy-root":"",style:{display:"contents",pointerEvents:"auto"},children:e}),t):null}var oe=j,So=["shadowColor","shadowOffset","shadowOpacity","shadowRadius","textShadowColor","textShadowOffset","textShadowRadius"],ie=e=>typeof e=="number"?`${e}px`:e;function Te(e){if(Array.isArray(e)){let m=e.map(Te);return m.some((N,k)=>N!==e[k])?m:e}if(!e||typeof e!="object"||!So.some(m=>e[m]!=null))return e;let{shadowColor:t,shadowOffset:o,shadowOpacity:i,shadowRadius:n,textShadowColor:r,textShadowOffset:l,textShadowRadius:h,...p}=e;if(t!=null||o!=null||i!=null||n!=null){let m=t??"black",N=i==null?m:`color-mix(in srgb, ${m} ${Math.min(i,1)*100}%, transparent)`,k=`${ie(o?.width??0)} ${ie(o?.height??0)} ${ie(n??0)} ${N}`;p.boxShadow=typeof p.boxShadow=="string"?`${p.boxShadow}, ${k}`:p.boxShadow??k}let{width:d=0,height:c=0}=l??{};if(r&&(d||c||h)){let m=`${ie(d)} ${ie(c)} ${ie(h??0)} ${r}`;p.textShadow=p.textShadow?`${p.textShadow}, ${m}`:m}return p}var xo=oe.StyleSheet.create({auto:{pointerEvents:"auto"},none:{pointerEvents:"none"},"box-none":{pointerEvents:"box-none"},"box-only":{pointerEvents:"box-only"}});function et(e,t){if(typeof e=="function")return i=>et(e(i),t);let o=Te(e);return t?[o,xo[t]]:o}var ge={...oe.StyleSheet,create:e=>oe.StyleSheet.create(Object.fromEntries(Object.entries(e).map(([t,o])=>[t,Te(o)])))};function B(e){let t=Ye((i,n)=>{let{accessibilityState:r,accessibilityValue:l,pointerEvents:h,...p}=i;for(let c of["busy","checked","disabled","expanded","selected"])r?.[c]!==void 0&&p[`aria-${c}`]===void 0&&(p[`aria-${c}`]=r[c]);for(let[c,m]of Object.entries({min:"valuemin",max:"valuemax",now:"valuenow",text:"valuetext"}))l?.[c]!==void 0&&p[`aria-${m}`]===void 0&&(p[`aria-${m}`]=l[c]);let d=et(p.style,h);return d!==p.style&&(p.style=d),Ce(e,{...p,ref:n})}),o=e.State;return o&&Object.assign(t,{State:o}),t.displayName=e.displayName??e.name??"NativeWebView",t}var f=B(j.View),u=B(j.Text),Io={...oe.Animated,View:oe.Animated.createAnimatedComponent(f),Text:oe.Animated.createAnimatedComponent(u)},de=B(j.TextInput),ko=B(j.TouchableOpacity),Co=B(j.TouchableHighlight),To=B(j.TouchableWithoutFeedback),K=B(j.Pressable),ne=B(j.ScrollView),tt=Ye((e,t)=>{let o=fo(null),i=ho(n=>{if(n){let r=n;for(;r.parentElement&&r.parentElement!==document.body;)r=r.parentElement;r.parentElement===document.body&&(o.current=r,Object.assign(r.style,{position:"relative",zIndex:"2147483647",pointerEvents:"auto"}),Qe().appendChild(r))}else o.current&&(document.body.appendChild(o.current),o.current=null);typeof t=="function"?t(n):t&&(t.current=n)},[t]);return Ce(wo,null,Ce(j.Modal,{...e,ref:i}))});tt.displayName="Modal";var Ao=B(tt),No=B(j.Switch),Po=B(j.ActivityIndicator),Eo=B(j.Button),Ro=j.findNodeHandle,Lo={alert(e,t,o,i){if(typeof document>"u")return;let n=document.createElement("dialog");n.dataset.buoyRoot="",n.setAttribute("aria-label",e),n.style.cssText="position:fixed;inset:0;margin:auto;width:min(440px,90vw);padding:24px;border:1px solid #475569;border-radius:14px;background:#17212e;color:#f1f5f9;font:14px system-ui;box-shadow:0 20px 80px #0008;z-index:2147483647";let r=document.createElement("h2");if(r.textContent=e,r.style.cssText="font-size:18px;margin:0 0 12px",n.appendChild(r),t){let d=document.createElement("p");d.textContent=t,d.style.cssText="line-height:1.5;white-space:pre-wrap;margin:0 0 20px",n.appendChild(d)}let l=document.createElement("div");l.style.cssText="display:flex;justify-content:flex-end;flex-wrap:wrap;gap:8px";let h=o?.length?o:[{text:"OK"}],p=()=>{n.close?.(),n.remove()};for(let d of h){let c=document.createElement("button");c.type="button",c.textContent=d.text??"OK",c.style.cssText=`padding:9px 14px;border:1px solid #64748b;border-radius:7px;color:white;background:${d.style==="destructive"?"#a52b38":"#283a4d"};cursor:pointer;font:inherit`,c.onclick=()=>{p(),d.onPress?.()},l.appendChild(c)}n.addEventListener("cancel",d=>{d.preventDefault(),i?.cancelable!==false&&(p(),i?.onDismiss?.())}),n.appendChild(l),document.body.appendChild(n),n.showModal?n.showModal():n.setAttribute("open","")}};function zo(e){if(!e.documentDirectory)throw new Error("Expo FileSystem has no persistent document directory.");let t=e.documentDirectory+"buoy-notifications/",o=i=>t+encodeURIComponent(i)+".json";return{async getItem(i){let n=o(i);return(await e.getInfoAsync(n)).exists?e.readAsStringAsync(n):null},async setItem(i,n){(await e.getInfoAsync(t)).exists||await e.makeDirectoryAsync(t,{intermediates:true}),await e.writeAsStringAsync(o(i),n)},async removeItem(i){await e.deleteAsync(o(i),{idempotent:true})},async getAllKeys(){return(await e.getInfoAsync(t)).exists?(await e.readDirectoryAsync(t)).filter(i=>i.endsWith(".json")).flatMap(i=>{try{return[decodeURIComponent(i.slice(0,-5))]}catch{return[]}}):[]}}}function Oo(){try{return globalThis.localStorage??null}catch{return null}}function jo(){let e=Oo();return e?{storage:{async getItem(t){return e.getItem(t)},async setItem(t,o){e.setItem(t,o)},async removeItem(t){e.removeItem(t)},async getAllKeys(){let t=[];for(let o=0;o<e.length;o++){let i=e.key(o);i?.startsWith("buoy.notifications.")&&t.push(i)}return t}},durable:true}:{durable:false}}function g(e){return e!==null&&typeof e=="object"&&!Array.isArray(e)?e:{}}function z(e){return typeof e=="string"?e:null}function Ae(e){let t=new WeakSet;function o(i,n){if(i==null)return null;if(typeof i=="string")return i.length>12e3?i.slice(0,12e3)+" [truncated]":i;if(typeof i=="boolean")return i;if(typeof i=="number")return Number.isFinite(i)?i:String(i);if(typeof i!="object")return String(i);if(t.has(i))return"[Circular]";if(n>12)return"[Depth limit]";if(t.add(i),i instanceof Error)return{name:i.name,message:i.message};if(i instanceof Date)return Number.isNaN(i.getTime())?"[Invalid date]":i.toISOString();if(Array.isArray(i))return i.slice(0,200).map(l=>o(l,n+1));let r={};for(let l of Object.keys(i).slice(0,200))try{Object.defineProperty(r,l,{value:o(i[l],n+1),enumerable:true})}catch{r[l]="[Unreadable]"}return r}return o(e,0)}function re(e){let t=0;for(let o of e){let i=o.codePointAt(0);t+=i<=127?1:i<=2047?2:i<=65535?3:4}return t}var Ne="buoy.notifications.v1.",Pe=Ne+"session",ot=Ne+"tokens",be=Ne+"event.",Ee=16*1024,Do=512*1024,Bo=200,Re=class{constructor(e={}){this.options=e;this.state={version:1,ready:false,provider:null,providerVersion:null,platform:"unknown",appId:null,capabilities:[],durable:false,storageError:null,evicted:0,session:null,events:[],tokens:[],permissions:null,presented:null};this.listeners=new Set;this.sequence=0;this.queue=Promise.resolve();this.getSnapshot=()=>this.state;this.subscribe=t=>(this.listeners.add(t),()=>{this.listeners.delete(t)});this.now=e.now??Date.now,this.processId=e.processId??`${this.now().toString(36)}-${Math.random().toString(36).slice(2)}`,this.state.durable=!!e.storage&&e.durable===true,this.ready=this.hydrate(),this.queue=this.ready}update(e){this.state={...this.state,...e};for(let t of this.listeners)try{t()}catch{}}configure(e){this.update(e)}allowed(){return this.options.enabled?.()??true}storageFailure(e){this.update({storageError:e instanceof Error?e.message:String(e),durable:false})}serial(e){let t=this.queue.then(e);return this.queue=t.catch(()=>{}),t}async hydrate(){if(!this.allowed()){this.update({ready:true});return}if(this.options.durability)try{this.update({durable:await this.options.durability})}catch(o){this.storageFailure(o)}let e=this.options.storage,t=false;if(e)try{let o=await e.getItem(Pe);if(t=o==="null",o){let l=JSON.parse(o);l&&typeof l.runId=="string"&&Number.isFinite(l.expiresAt)&&l.expiresAt>this.now()&&this.update({session:l})}let i=await e.getItem(ot);if(i){let l=JSON.parse(i);Array.isArray(l)&&this.update({tokens:l.filter(h=>h&&["apns","fcm","expo"].includes(h.type)&&typeof h.value=="string").slice(-10)})}let n=(await e.getAllKeys()).filter(l=>l.startsWith(be)).sort(),r=[];for(let l of n)try{let h=await e.getItem(l);if(!h||re(h)>Ee){await e.removeItem(l);continue}let p=JSON.parse(h);typeof p.id=="string"&&typeof p.kind=="string"&&Number.isFinite(p.capturedAt)?r.push(p):await e.removeItem(l)}catch{await e.removeItem(l)}r.sort((l,h)=>l.capturedAt-h.capturedAt||l.sequence-h.sequence||l.id.localeCompare(h.id)),this.update({events:r}),await this.prune()}catch(o){this.storageFailure(o)}if(this.options.autoStart&&!this.state.session&&!t){let o=this.now(),i={runId:this.processId,startedAt:o,expiresAt:o+1800*1e3};try{await e?.setItem(Pe,JSON.stringify(i))}catch(n){this.storageFailure(n)}this.update({session:i})}this.update({ready:true})}async setCaptureSession(e,t=1800*1e3){if(!this.allowed())throw new Error("Notification capture is disabled in this build.");if(e!==null&&(typeof e!="string"||!e.trim()||e.length>128))throw new Error("runId must contain 1 to 128 characters, or be null to stop capture.");if(!Number.isFinite(t)||t<1e3||t>3600*1e3)throw new Error("Capture duration must be between 1 second and 1 hour.");return this.serial(async()=>{let o=this.now(),i=e===null?null:{runId:e,startedAt:o,expiresAt:o+t};try{this.options.storage&&await this.options.storage.setItem(Pe,JSON.stringify(i))}catch(n){throw this.storageFailure(n),new Error("Could not persist the capture session. Keep the app open and check storage.")}return this.update({session:i}),{session:i,durable:this.state.durable}})}record(e,t,o={}){let i=this.now(),n=this.options.appState?.()??"unknown",r=Ae(t);return this.serial(async()=>{if(!this.allowed())return null;let l=this.state.session;if(!l||l.expiresAt<=i)return l&&this.update({session:null}),null;let h=(c,m=512)=>typeof c=="string"?c.slice(0,m):null,p=h(o.dedupeKey,2048);if(p&&this.state.events.some(c=>c.dedupeKey===p))return null;let d={id:`${this.processId}-${++this.sequence}`,processId:this.processId,sequence:this.sequence,capturedAt:i,runId:l.runId,kind:e,provider:h(o.provider,64)??this.state.provider??"app",observedAppState:n,notificationId:h(o.notificationId),testId:h(o.testId),title:h(o.title,1024),actionIdentifier:h(o.actionIdentifier),...p?{dedupeKey:p}:{},raw:r};re(JSON.stringify(d))>Ee&&(d.raw={note:"Payload exceeded the 16 KiB capture limit."},d.truncated=true),this.update({events:[...this.state.events,d]});try{await this.options.storage?.setItem(be+d.id,JSON.stringify(d))}catch(c){this.storageFailure(c)}try{await this.prune()}catch(c){this.storageFailure(c)}return d})}async prune(){let e=[...this.state.events],t=e.map(n=>re(JSON.stringify(n))),o=t.reduce((n,r)=>n+r,0),i=[];for(;e.length>Bo||o>Do;)i.push(e.shift()),o-=t.shift();i.length&&this.update({events:e,evicted:this.state.evicted+i.length});for(let n of i)await this.options.storage?.removeItem(be+n.id)}async clearCapturedEvents(){return this.serial(async()=>{let e=this.state.events;for(let t of e)await this.options.storage?.removeItem(be+t.id);return this.update({events:[],evicted:0}),{cleared:true}})}async observeToken(e,t,o={}){if(this.allowed()){if(!t||t.length>8192)throw new Error("The notification token is empty or too long.");return this.serial(async()=>{let i={type:e,value:t,observedAt:this.now(),...typeof o.projectId=="string"?{projectId:o.projectId.slice(0,256)}:{},...typeof o.environment=="string"?{environment:o.environment.slice(0,256)}:{}},n=[...this.state.tokens.filter(r=>!(r.type===e&&r.projectId===o.projectId&&r.environment===o.environment)),i].slice(-10);this.update({tokens:n});try{await this.options.storage?.setItem(ot,JSON.stringify(n))}catch(r){this.storageFailure(r)}})}}setPermissions(e){let t=Ae(e);this.update({permissions:re(JSON.stringify(t))<=Ee?t:{note:"Permission result exceeded the capture limit."}})}setPresented(e){let t=Ae(e);re(JSON.stringify(t))<=128*1024?this.update({presented:t}):this.update({presented:{note:"System tray result exceeded 128 KiB. Inspect fewer presented notifications in the app.",count:Array.isArray(e)?e.length:null}})}async flush(){await this.queue}};function X(e){let t=g(e),o=g(t.notification??e),i=g(o.request),n=g(i.content),r=g(g(i.trigger).payload),l=g(n.data??r.body);return{notificationId:z(i.identifier),testId:z(l.__buoyTestId),title:z(n.title),actionIdentifier:z(t.actionIdentifier)}}function Vo(e){let t=g(e),o=g(t.notification);return JSON.stringify([g(o.request).identifier,o.date,t.actionIdentifier,t.userText])}function it(e){if(!e||typeof e!="object")return;let t={};typeof e.appName=="string"&&(t.appName=e.appName.trim().slice(0,80)),typeof e.iconUri=="string"&&e.iconUri.length<=32768&&/^data:image\/(png|jpeg|webp);base64,[A-Za-z0-9+/]+={0,2}$/.test(e.iconUri)&&(t.iconUri=e.iconUri);for(let o of["backgroundColor","textColor"])typeof e[o]=="string"&&/^#[0-9a-f]{6}$/i.test(e[o])&&(t[o]=e[o]);return Object.keys(t).length?t:void 0}function pe(e,t=15e3){return new Promise((o,i)=>{let n=setTimeout(()=>i(new Error("Notification SDK timed out. Check permission and network settings, then retry.")),t);e.then(r=>{clearTimeout(n),o(r)},r=>{clearTimeout(n),i(r)})})}function nt(e,t,o){let i=["received","responses","permissions","device-token"];(t.getLastNotificationResponse||t.getLastNotificationResponseAsync)&&i.push("startup-response"),t.getPresentedNotificationsAsync&&i.push("presented"),t.scheduleNotificationAsync&&i.push("local-scheduling"),o.projectId&&t.getExpoPushTokenAsync&&i.push("expo-token"),e.configure({preview:it(o.preview),provider:"expo",platform:o.platform,appId:o.appId??null,providerVersion:o.providerVersion??null,capabilities:i});let n=false,r=[],l=(d,c=false)=>{n||!d||e.record(c?"startup-response":"response",d,{...X(d),dedupeKey:Vo(d)})};try{r.push(t.addNotificationReceivedListener(d=>{n||e.record("received",d,X(d))})),r.push(t.addNotificationResponseReceivedListener(d=>l(d))),r.push(t.addPushTokenListener(d=>{!n&&(d.type==="ios"||d.type==="android")&&e.observeToken(d.type==="ios"?"apns":"fcm",d.data).catch(()=>{})}))}catch(d){for(let c of r)c.remove();throw d}let h=Promise.resolve().then(()=>t.getLastNotificationResponse?.()??t.getLastNotificationResponseAsync?.()).then(d=>l(d,true));h.catch(()=>{});let p={async getPermissions(){let d=await pe(t.getPermissionsAsync());return e.setPermissions(d),e.getSnapshot().permissions},async listPresented(){if(!t.getPresentedNotificationsAsync)throw new Error("This notification SDK cannot list presented notifications.");let d=await pe(t.getPresentedNotificationsAsync());return e.setPresented(d),e.getSnapshot().presented},async refreshToken(d){let{type:c}=g(d);if(c==="expo"){if(!t.getExpoPushTokenAsync||!o.projectId)throw new Error("Set projectId in installExpoNotificationCapture before requesting an Expo token.");let N=await pe(t.getExpoPushTokenAsync({projectId:o.projectId}));return await e.observeToken("expo",N.data,{projectId:o.projectId}),{type:"expo",value:N.data}}if(c!=="device")throw new Error('Token type must be "device" or "expo".');if(!t.getDevicePushTokenAsync)throw new Error("This notification SDK cannot register a device token.");let m=await pe(t.getDevicePushTokenAsync());if(m.type!=="ios"&&m.type!=="android")throw new Error("This platform does not provide an APNs or FCM token.");return await e.observeToken(m.type==="ios"?"apns":"fcm",m.data),{type:m.type==="ios"?"apns":"fcm",value:m.data}},async scheduleLocal(d){if(!t.scheduleNotificationAsync)throw new Error("This notification SDK cannot schedule local notifications.");let{title:c,body:m,data:N,seconds:k}=g(d);if(typeof c!="string"||typeof m!="string"||typeof k!="number"||!Number.isFinite(k)||k<1||k>3600)throw new Error("Provide title, body and a delay from 1 to 3600 seconds.");if(N!==void 0&&(N===null||typeof N!="object"||Array.isArray(N)))throw new Error("Local notification data must be an object.");let _=await pe(t.scheduleNotificationAsync({content:{title:c,body:m,data:N??{}},trigger:{type:"timeInterval",seconds:k,repeats:false}}));return await e.record("local-scheduled",{title:c,body:m,data:N,seconds:k},{notificationId:_,title:c,testId:typeof g(N).__buoyTestId=="string"?g(N).__buoyTestId:null}),{notificationId:_,transport:"local"}}};return p.getPermissions().catch(()=>{}),{actions:p,ready:h,dispose(){n=true;for(let d of r)d.remove()}}}function Ho(e,t){let o=new Map;return{...t,handleNotification:async function(...i){let n=X(i[0]);n.notificationId&&o.set(n.notificationId,n),o.size>50&&o.delete(o.keys().next().value);try{let r=await t.handleNotification.apply(this,i);return e.record("presentation-decision",{notification:i[0],behavior:r},X(i[0])),r}catch(r){throw e.record("presentation-error",{notification:i[0],error:r},X(i[0])),r}},handleError:function(...i){let n=z(i[0]),r=n?o.get(n):void 0;return n&&o.delete(n),e.record("presentation-error",{source:"sdk",identifier:n,error:i[1]},r??{notificationId:n}),t.handleError?.apply(this,i)}}}function Fo(e){let t=X(e),o=g(e),i=g(o.data),n=g(i.UIApplicationLaunchOptionsRemoteNotificationKey),r={};if(typeof i.dataString=="string")try{r=g(JSON.parse(i.dataString))}catch{}let l=g(i.body??o.body??n.body);return{...t,testId:t.testId??z(r.__buoyTestId)??z(l.__buoyTestId),title:t.title??z(g(o.notification).title)??z(g(g(o.aps??n.aps).alert).title)}}async function Le(e){let t;await Promise.race([e.catch(()=>{}),new Promise(o=>{t=setTimeout(o,250)})]),t&&clearTimeout(t)}function Mo(e,t){return e.configure({capabilities:[...new Set([...e.getSnapshot().capabilities,"background-task"])]}),(async function(...o){let i=g(o[0]).data??o[0],n=Fo(i);await Le(e.record("background-started",o[0],n));try{let r=await t.apply(this,o);return await Le(e.record("background-completed",{input:o[0],result:r},n)),r}catch(r){throw await Le(e.record("background-error",{input:o[0],error:r},n)),r}})}var ae="PushNotifications",ue="LocalNotifications";function me(e){let t=g(e),o=g(t.notification??e),i=g(o.data??o.extra),n=g(i.body),r=o.id;return{notificationId:typeof r=="number"?String(r):z(r),testId:z(i.__buoyTestId)??z(n.__buoyTestId),title:z(o.title)??z(g(g(i.aps).alert).title),actionIdentifier:z(t.actionId)}}function he(e,t=15e3){return new Promise((o,i)=>{let n=setTimeout(()=>i(new Error("The notification plugin timed out. Check permission and network settings, then retry.")),t);e.then(r=>{clearTimeout(n),o(r)},r=>{clearTimeout(n),i(r)})})}function rt(e,t,o){let i=t.hasCapacitorPlugin(ae),n=t.hasCapacitorPlugin(ue),r=["received","responses","permissions"];i&&r.push("device-token","presented"),n&&r.push("local-scheduling"),n&&!i&&r.push("presented"),e.configure({preview:it(o.preview),provider:"capacitor",platform:o.platform,appId:o.appId??null,providerVersion:o.providerVersion??null,capabilities:r}),t.installCapacitorBridge(),o.appId||t.loadCapacitorAppHost?.().then(b=>{b?.bundleId&&e.configure({appId:b.bundleId})}).catch(()=>{});let l=o.platform==="ios"?"apns":"fcm",h=0,p=new Set,d=250,c=new Map,m=(b,S)=>{let v=c.get(b);if(v!==void 0&&S-v<d)return null;if(c.set(b,S),c.size>100)for(let[C,A]of c)S-A>=d&&c.delete(C);return S},N=b=>{if(b.plugin!==ae&&b.plugin!==ue)return;let S=b.result,v=`${b.plugin}:${b.method}:${JSON.stringify(S??null).slice(0,1500)}`;if(b.kind==="event"&&m(v,b.start)===null)return;let C=`${v}:${b.start}`;if(b.kind==="event")switch(b.method){case"registration":{let A=z(g(S).value);A&&e.observeToken(l,A).catch(()=>{});return}case"pushNotificationReceived":case"localNotificationReceived":e.record("received",S,{...me(S),provider:"capacitor",dedupeKey:C});return;case"pushNotificationActionPerformed":case"localNotificationActionPerformed":e.record("response",S,{...me(S),provider:"capacitor",dedupeKey:C});return;default:return}if(!(b.kind!=="promise"||b.ok!==true))if(b.method==="checkPermissions"||b.method==="requestPermissions")e.setPermissions({plugin:b.plugin,...g(S)});else if(b.plugin===ue&&b.method==="schedule")for(let A of Array.isArray(b.options.notifications)?b.options.notifications:[]){let T=me(A);e.record("local-scheduled",A,{...T,provider:"capacitor"})}else b.method==="getDeliveredNotifications"&&e.setPresented(g(S).notifications??S)},k=()=>{let b=t.getCapacitorCalls();for(let v of b)v.seq<=h||p.has(v.seq)||v.kind==="promise"&&v.end===void 0||(p.add(v.seq),N(v));let S=b[0]?.seq??0;if(S>h+1){h=S-1;for(let v of Array.from(p))v<=h&&p.delete(v)}},_=t.subscribeCapacitorCalls(k);k();let F=i?ae:ue,D={async getPermissions(){if(!i&&!n)throw new Error("Install @capacitor/push-notifications or @capacitor/local-notifications in the app.");let b=await he(t.callCapacitorAsApp(F,"checkPermissions"));return e.setPermissions({plugin:F,...g(b)}),e.getSnapshot().permissions},async listPresented(){if(!i&&!n)throw new Error("This app has no notification plugin that can list presented notifications.");let b=await he(t.callCapacitorNative(F,"getDeliveredNotifications"));return e.setPresented(g(b).notifications??b),e.getSnapshot().presented},async refreshToken(b){let{type:S}=g(b);if(S==="expo")throw new Error("Expo push tokens need expo-notifications; this app uses Capacitor.");if(S!=="device")throw new Error('Token type must be "device".');if(!i)throw new Error("Install @capacitor/push-notifications to register a device token.");let v=null,C=new Promise((A,T)=>{t.listenCapacitorNative(ae,"registration",L=>{let W=z(g(L).value);W&&A(W)}).then(L=>{v=L.remove}),t.listenCapacitorNative(ae,"registrationError",L=>{T(new Error(z(g(L).error)??"Push registration failed."))}).then(L=>{let W=v;v=async()=>{await W?.(),await L.remove()}})});try{await he(t.callCapacitorNative(ae,"register"));let A=await he(C);return await e.observeToken(l,A),{type:l,value:A}}finally{v?.()}},async scheduleLocal(b){if(!n)throw new Error("Install @capacitor/local-notifications to schedule local notifications.");let{title:S,body:v,data:C,seconds:A}=g(b);if(typeof S!="string"||typeof v!="string"||typeof A!="number"||!Number.isFinite(A)||A<1||A>3600)throw new Error("Provide title, body and a delay from 1 to 3600 seconds.");if(C!==void 0&&(C===null||typeof C!="object"||Array.isArray(C)))throw new Error("Local notification data must be an object.");let T=Math.floor(Math.random()*2e9)+1,L={id:T,title:S,body:v,extra:C??{},schedule:{at:new Date(Date.now()+A*1e3).toISOString()}};return await he(t.callCapacitorNative(ue,"schedule",{notifications:[L]})),await e.record("local-scheduled",{title:S,body:v,data:C,seconds:A},{notificationId:String(T),title:S,testId:typeof g(C).__buoyTestId=="string"?g(C).__buoyTestId:null,provider:"capacitor"}),{notificationId:String(T),transport:"local"}}};return D.getPermissions().catch(()=>{}),{actions:D,ready:e.ready,dispose(){_()}}}import*as at from"@buoy-gg/license/web";var ve=globalThis;function ze(e=false){return typeof ye<"u"&&ye||e===true}function Oe(){return ve.__buoyNotificationsV1?.recorder??null}function st(e){let t=ve.__buoyNotificationsV1;if(!t){let o=e.storage?{storage:e.storage,durable:e.durable===true}:jo();t={recorder:new Re({...o,enabled:()=>ze(e.enableInRelease),appState:()=>qe.currentState??"unknown",autoStart:true})},ve.__buoyNotificationsV1=t}return t}function Wo(e,t={}){if(!ze(t.enableInRelease))return null;let o=JSON.stringify([t.platform??ke.OS,t.appId,t.providerVersion,t.projectId,t.enableInRelease,t.preview]),i=st(t);return(i.sdk!==e||i.key!==o)&&(i.attachment?.dispose(),i.attachment=nt(i.recorder,e,{...t,platform:t.platform??ke.OS}),i.sdk=e,i.key=o),i.recorder}function lt(e={}){let t=at.capacitorPlatform();if(!t||!ze(e.enableInRelease))return null;let o=JSON.stringify(["capacitor",e.appId,e.providerVersion,e.enableInRelease,e.preview]),i=st(e);return(i.sdk!=="capacitor"||i.key!==o)&&(i.attachment?.dispose(),i.attachment=rt(i.recorder,at,{...e,platform:t}),i.sdk="capacitor",i.key=o),i.recorder}var ct=new Re;function Y(){let e=ve.__buoyNotificationsV1;if(!e)throw new Error("Install notification capture in the app entry point (installExpoNotificationCapture), before rendering the root component. Capacitor apps capture by themselves in debug builds.");return e}var se={version:1,getSnapshot:()=>(Oe()??ct).getSnapshot(),subscribe:e=>(Oe()??ct).subscribe(e),actions:{getSnapshot:()=>se.getSnapshot(),getCapabilities:()=>{let{ready:e,provider:t,providerVersion:o,platform:i,appId:n,capabilities:r,durable:l,storageError:h}=se.getSnapshot();return{ready:e,provider:t,providerVersion:o,platform:i,appId:n,capabilities:r,durable:l,storageError:h}},getEvent(e){let{id:t}=g(e);if(typeof t!="string")throw new Error("Provide the captured event id.");return Y().recorder.getSnapshot().events.find(o=>o.id===t)??null},async setCaptureSession(e){let{runId:t,durationMs:o}=g(e);if(typeof t!="string"&&t!==null)throw new Error("Provide runId, or null to stop capture.");if(o!==void 0&&typeof o!="number")throw new Error("durationMs must be a number.");return Y().recorder.setCaptureSession(t,o)},clearCapturedEvents:()=>Y().recorder.clearCapturedEvents(),getPermissions:()=>Y().attachment.actions.getPermissions(),listPresented:()=>Y().attachment.actions.listPresented(),refreshToken:e=>Y().attachment.actions.refreshToken(e),scheduleLocal:e=>Y().attachment.actions.scheduleLocal(e)}};import{useEffect as Ko,useMemo as dt,useState as Z}from"react";import{ChevronDown as $o,ChevronLeft as _o,ChevronRight as pt,Copy as ut,ModalHeader as je,windowDragProps as Jo,NightBadge as we,NightCard as q,NightRows as ht,NightSectionLabel as G,NightSegmented as Uo,NotificationsIcon as qo,PowerToggleButton as Go,Search as Xo,Settings as Yo,ToolEmptyState as De,Trash2 as Zo,X as Qo,copyToClipboard as ei,night as O,useSafeAreaInsets as ti}from"@buoy-gg/shared-ui/web";import{DataViewer as oi}from"@buoy-gg/shared-ui/web/dataViewer";import{useRef as ii,useState as Q}from"react";import{NightSegmented as ni,night as le}from"@buoy-gg/shared-ui/web";import{useEffect as ri,useState as ft}from"react";import{CheckCircle as ai,ChevronDown as si,ChevronRight as li,NotificationsIcon as yt,XCircle as ci,night as E,useSafeAreaInsets as di}from"@buoy-gg/shared-ui/web";import{jsx as P,jsxs as V}from"react/jsx-runtime";function gt(e){let[t,o]=ft(false);ri(()=>o(false),[e.appearance?.iconUri]);let i=e.appearance?.textColor?{color:e.appearance.textColor}:void 0,[n,r]=ft(false),l=di({minBottom:12});return V(f,{style:I.root,children:[P(ne,{testID:"notification-test-scroll",style:I.root,contentContainerStyle:I.scroll,keyboardShouldPersistTaps:"handled",children:V(f,{style:I.content,children:[V(f,{style:I.intro,children:[P(u,{accessibilityRole:"header",style:I.heading,children:"Test a notification"}),P(u,{style:I.caption,children:"Send a test notification to your app."})]}),e.destination,e.previewNote?P(u,{style:I.caption,children:e.previewNote}):V(f,{style:[I.preview,e.appearance?.backgroundColor?{backgroundColor:e.appearance.backgroundColor,borderColor:e.appearance.backgroundColor}:void 0],accessibilityLabel:"Notification preview",children:[V(f,{style:I.row,children:[e.appearance?.iconUri&&!t?P(Xe,{testID:"buoy-internal-notification-preview",source:{uri:e.appearance.iconUri},accessibilityLabel:`${e.appearance.appName??e.appName} icon`,style:I.appIcon,onError:()=>o(true)}):P(f,{style:I.iconFallback,children:P(yt,{size:22,color:E.color.accent})}),P(u,{numberOfLines:1,style:[I.caption,I.appName,i],children:e.appearance?.appName??e.appName}),P(u,{style:[I.caption,i],children:"now"})]}),P(de,{accessibilityLabel:"Notification title",placeholder:"Title",placeholderTextColor:E.color.placeholder,value:e.title,onChangeText:e.onTitleChange,style:[I.input,I.title,i],editable:!e.busy}),P(de,{accessibilityLabel:"Notification message",placeholder:"Message",placeholderTextColor:E.color.placeholder,value:e.message,onChangeText:e.onMessageChange,style:[I.input,i],editable:!e.busy})]}),e.result&&V(f,{accessibilityRole:"summary",accessibilityLiveRegion:"polite",testID:"notification-test-result",style:I.result,children:[V(f,{style:I.row,children:[e.result.failed?P(ci,{size:16,color:E.color.danger}):P(ai,{size:16,color:E.color.accent}),P(u,{style:I.resultTitle,children:e.result.title})]}),P(u,{style:I.caption,children:e.result.message}),P(K,{accessibilityRole:"button",accessibilityLabel:"View activity",onPress:e.onViewActivity,style:I.secondary,children:P(u,{style:I.secondaryText,children:"View activity"})})]}),V(f,{children:[V(K,{accessibilityRole:"button",accessibilityLabel:"Notification options",accessibilityState:{expanded:n},onPress:()=>r(!n),style:I.options,children:[n?P(si,{size:12,color:E.color.textSecondary}):P(li,{size:12,color:E.color.textSecondary}),P(u,{style:I.caption,children:"Options"})]}),n&&e.options]})]})}),V(f,{style:[I.footer,{paddingBottom:l.bottom}],children:[!!e.error&&P(u,{accessibilityRole:"alert",style:I.error,children:e.error}),!!e.notice&&P(u,{accessibilityLiveRegion:"polite",style:I.caption,children:e.notice}),V(f,{style:I.footerRow,children:[P(u,{style:[I.caption,I.hint],children:e.hint}),V(K,{accessibilityRole:"button",accessibilityLabel:e.busy?"Sending\u2026":"Send notification",accessibilityState:{disabled:e.disabled||e.busy},disabled:e.disabled||e.busy,onPress:e.onSend,style:({pressed:h})=>[I.send,(e.disabled||e.busy)&&I.disabled,h&&I.pressed],children:[P(yt,{size:15,color:E.color.onAccent}),P(u,{style:I.sendText,children:e.busy?"Sending\u2026":"Send notification"})]})]})]})]})}var I=ge.create({root:{flex:1,minHeight:0,minWidth:0},scroll:{padding:16,flexGrow:1},content:{width:"100%",maxWidth:620,alignSelf:"center",gap:20},intro:{gap:8,paddingTop:8},heading:{color:E.color.text,fontSize:22,fontWeight:"600",letterSpacing:-.5},caption:{color:E.color.textSecondary,fontSize:12,lineHeight:18},row:{flexDirection:"row",alignItems:"center",gap:8},appName:{flex:1,fontWeight:"600"},appIcon:{width:36,height:36,borderRadius:8},iconFallback:{width:36,height:36,alignItems:"center",justifyContent:"center",borderRadius:8,backgroundColor:E.color.fillSecondary},preview:{padding:16,gap:8,borderWidth:1,borderColor:E.color.glassBorder,borderRadius:20,backgroundColor:E.color.glass},input:{color:E.color.text,fontSize:14,padding:6,minHeight:36},title:{fontSize:16,fontWeight:"600"},result:{gap:10,padding:16,borderWidth:1,borderColor:E.color.glassBorder,borderRadius:14},resultTitle:{color:E.color.text,fontWeight:"500",fontSize:13,flexShrink:1},secondary:{alignSelf:"flex-start",paddingHorizontal:14,paddingVertical:8,borderRadius:24,backgroundColor:E.color.fillSecondary},secondaryText:{color:E.color.accent,fontSize:13},options:{flexDirection:"row",alignItems:"center",gap:6,paddingVertical:12},footer:{padding:14,gap:8,borderTopWidth:1,borderTopColor:E.color.separator},footerRow:{flexDirection:"row",flexWrap:"wrap",alignItems:"center",justifyContent:"space-between",gap:12},hint:{flexGrow:1,flexShrink:1,flexBasis:200},send:{flexDirection:"row",alignItems:"center",justifyContent:"center",gap:8,borderRadius:24,paddingHorizontal:18,paddingVertical:12,backgroundColor:E.color.accent},sendText:{color:E.color.onAccent,fontSize:13,fontWeight:"600"},disabled:{opacity:.4},pressed:{opacity:.8},error:{color:E.color.danger,fontSize:12,lineHeight:18}});import{jsx as $,jsxs as Se}from"react/jsx-runtime";function pi({snapshot:e,onAction:t,onViewActivity:o}){let[i,n]=Q("Test notification"),[r,l]=Q("Tap to open the app."),[h,p]=Q("{}"),[d,c]=Q("1"),[m,N]=Q(false),k=ii(false),[_,F]=Q(null),[D,b]=Q(null),S={},v=null;try{if(S=JSON.parse(h),!S||typeof S!="object"||Array.isArray(S))throw new Error}catch{v="Custom data must be a JSON object. Open Options to edit it."}async function C(){if(k.current||v)return;k.current=true,N(true),b(null),F(null);let R={testId:`buoy-local-${Date.now()}-${Math.random().toString(36).slice(2)}`,startedAt:Date.now(),appId:e?.appId??null};try{await t("setCaptureSession",{runId:R.testId,durationMs:18e5}),await t("scheduleLocal",{title:i,body:r,data:{...S,__buoyTestId:R.testId},seconds:Number(d)}),b(R)}catch(te){F(te instanceof Error?te.message:String(te))}finally{k.current=false,N(false)}}let A=D&&D.appId===e?.appId?e.events.filter(R=>R.testId===D.testId&&R.capturedAt>=D.startedAt):[],T=A.some(R=>R.kind==="received"),L=A.some(R=>R.kind==="response"||R.kind==="startup-response"),W=A.some(R=>R.kind==="app-outcome"),J=!!e?.capabilities.includes("local-scheduling");return $(gt,{title:i,message:r,onTitleChange:n,onMessageChange:l,appName:"This app",appearance:e?.preview,destination:Se(f,{style:H.destination,children:[Se(f,{style:H.field,children:[$(u,{style:H.label,children:"Device"}),$(u,{style:H.value,children:"This device"})]}),Se(f,{style:H.field,children:[$(u,{style:H.label,children:"Delivery"}),$(u,{style:H.value,children:"Local notification"})]})]}),options:Se(f,{style:H.options,children:[$(u,{style:H.label,children:"Send after"}),$(ni,{tabs:[{key:"1",label:"1 second"},{key:"10",label:"10 seconds"}],activeKey:d,onChange:c,size:"sm",glass:true}),$(u,{style:H.label,children:"Custom data"}),$(de,{accessibilityLabel:"Notification custom data",value:h,onChangeText:p,multiline:true,autoCapitalize:"none",autoCorrect:false,style:H.json}),$(u,{style:H.label,children:"Use the delay to leave the app before delivery. Simulator push and raw APNs payloads are available on desktop."})]}),result:D?{title:W?"App reported an outcome":L?"Notification tapped":T?"Received by app":"Notification scheduled",message:L?"Open Activity to inspect the app\u2019s response.":"Tap the notification to test what opens."}:null,onViewActivity:o,onSend:()=>{C()},busy:m,disabled:!J||!!v,error:_??v,hint:J?d==="10"?"You have 10 seconds to leave the app.":"Sends locally on this device after one second.":"Connect Expo notification capture to send a local test."})}var H=ge.create({destination:{flexDirection:"row",gap:12},field:{flex:1,gap:7},label:{color:le.color.textSecondary,fontSize:12,lineHeight:18},value:{color:le.color.text,fontSize:13,borderWidth:1,borderColor:le.color.glassBorder,backgroundColor:le.color.glass,borderRadius:10,padding:11},options:{gap:12},json:{color:le.color.text,fontSize:12,minHeight:100,textAlignVertical:"top",padding:12,borderWidth:1,borderColor:le.color.glassBorder,borderRadius:10}});import{monoFont as fe,night as w}from"@buoy-gg/shared-ui/web";var s=ge.create({root:{flex:1,minHeight:0,backgroundColor:"transparent"},fill:{flex:1,minHeight:0},inlineHeader:{paddingHorizontal:12,paddingVertical:8,borderBottomWidth:1,borderBottomColor:w.color.separator},status:{flexDirection:"row",alignItems:"center",flexWrap:"wrap",gap:12,paddingHorizontal:16,paddingVertical:9},statusLabel:{flexDirection:"row",alignItems:"center",gap:6},dot:{width:5,height:5,borderRadius:3,backgroundColor:w.color.textTertiary},liveDot:{backgroundColor:w.color.accent},caption:{color:w.color.textSecondary,fontSize:12,lineHeight:17},provider:{color:w.color.textSecondary,fontSize:11,marginLeft:"auto",fontFamily:fe},content:{padding:14,gap:20},eventList:{paddingHorizontal:12,paddingTop:2},searchRow:{flexDirection:"row",gap:8,paddingHorizontal:12,paddingBottom:10,alignItems:"center"},searchField:{flex:1,minWidth:0,height:36,flexDirection:"row",alignItems:"center",gap:8,paddingHorizontal:10,backgroundColor:w.color.glass,borderWidth:1,borderColor:w.color.glassBorder,borderRadius:w.radius.row},searchInput:{flex:1,minWidth:0,height:"100%",color:w.color.text,fontSize:13,padding:0},clearSearch:{padding:6},tabsCap:{width:"100%",maxWidth:360},iconButton:{width:34,height:34,alignItems:"center",justifyContent:"center",backgroundColor:w.color.buttonSurface,borderRadius:8,borderWidth:1,borderColor:w.color.border},event:{backgroundColor:w.color.glass,borderRadius:w.radius.input,borderWidth:1,borderColor:w.color.glassBorder,paddingHorizontal:12,paddingVertical:10,marginBottom:6,gap:6},eventTop:{flexDirection:"row",alignItems:"center",gap:10,justifyContent:"space-between"},eventKind:{flexDirection:"row",alignItems:"center",gap:6,flex:1,minWidth:0},eventLabel:{flexShrink:1,fontSize:11,fontWeight:"600"},timestamp:{color:w.color.textSecondary,fontFamily:fe,fontSize:10},eventSubject:{flexDirection:"row",alignItems:"center",gap:8},eventTitle:{flex:1,color:w.color.text,fontSize:15,fontWeight:"500"},eventMeta:{color:w.color.textSecondary,fontFamily:fe,fontSize:10,lineHeight:15},resultCount:{color:w.color.textSecondary,fontSize:12,marginBottom:10,marginLeft:4},actionRow:{flexDirection:"row",alignItems:"center",flexWrap:"wrap",gap:8},button:{flexDirection:"row",alignItems:"center",justifyContent:"center",gap:6,minHeight:34,paddingVertical:8,paddingHorizontal:14,borderRadius:w.radius.pill,backgroundColor:w.color.fillSecondary,alignSelf:"flex-start"},buttonText:{color:w.color.accent,fontSize:13,fontWeight:"600"},primaryButton:{backgroundColor:w.color.accent},primaryButtonText:{color:w.color.onAccent},pressed:{opacity:.7},disabled:{opacity:.4},detailTitle:{color:w.color.text,fontSize:20,fontWeight:"600"},field:{flexDirection:"row",paddingHorizontal:16,paddingVertical:12,gap:14},fieldLabel:{width:110,flexShrink:0},value:{flex:1,minWidth:0,color:w.color.text,fontFamily:fe,fontSize:12,lineHeight:18},disclosure:{flexDirection:"row",alignItems:"center",justifyContent:"space-between",paddingHorizontal:16,paddingVertical:14},disclosureTitle:{color:w.color.text,fontSize:13,fontWeight:"500"},jsonBody:{padding:10,borderTopWidth:1,borderTopColor:w.color.separator},token:{color:w.color.text,fontFamily:fe,fontSize:12,lineHeight:20},bodyText:{color:w.color.text,fontSize:14,lineHeight:21},footnote:{color:w.color.textSecondary,fontSize:12,lineHeight:18,marginTop:8,marginHorizontal:4},emptyFootnote:{color:w.color.textSecondary,fontSize:12,lineHeight:18,textAlign:"center",marginHorizontal:28},sectionActions:{flexDirection:"row",marginBottom:10},warning:{color:w.color.warning,fontSize:12,lineHeight:18},notice:{color:w.color.accent,backgroundColor:w.color.glass,paddingHorizontal:16,paddingVertical:10,fontSize:12,lineHeight:18},errorNotice:{color:w.color.danger,backgroundColor:w.color.glass,paddingHorizontal:16,paddingVertical:10,fontSize:12,lineHeight:18},errorText:{color:w.color.danger}});import{Fragment as Be,jsx as a,jsxs as y}from"react/jsx-runtime";var Ve={received:"App received",response:"Notification response","startup-response":"Response recovered at startup","presentation-decision":"Presentation decision","presentation-error":"Presentation error","background-started":"Background task started","background-completed":"Background task completed","background-error":"Background task failed","app-outcome":"App outcome","local-scheduled":"Local notification scheduled"};function bt(e){return e.includes("error")?"danger":e==="startup-response"?"warning":e==="received"||e==="app-outcome"?"accent":"neutral"}function M({label:e,onPress:t,disabled:o,primary:i,icon:n}){return y(K,{accessibilityRole:"button",accessibilityLabel:e,accessibilityState:{disabled:!!o},disabled:o,onPress:t,style:({pressed:r})=>[s.button,i&&s.primaryButton,r&&s.pressed,o&&s.disabled],children:[n,a(u,{style:[s.buttonText,i&&s.primaryButtonText],children:e})]})}function ee({label:e,value:t}){return y(f,{style:s.field,children:[a(u,{style:[s.caption,s.fieldLabel],children:e}),a(u,{selectable:true,style:s.value,children:t})]})}function xe({title:e,value:t,initiallyOpen:o=true}){let[i,n]=Z(o),r=JSON.stringify(t??null),l=dt(()=>JSON.parse(r),[r]);return y(q,{glass:true,children:[y(K,{accessibilityRole:"button",accessibilityLabel:e,accessibilityState:{expanded:i},onPress:()=>n(h=>!h),style:s.disclosure,children:[a(u,{style:s.disclosureTitle,children:e}),i?a($o,{size:14,color:O.color.textSecondary}):a(pt,{size:14,color:O.color.textSecondary})]}),i&&a(f,{style:s.jsonBody,children:a(oi,{title:"",data:l,rawMode:true,initialExpanded:true,showTypeFilter:false})})]})}function mt({snapshot:e,onAction:t,sender:o,activeTab:i,onTabChange:n,renderShell:r}){let[l,h]=Z("send"),p=i??l,[d,c]=Z(""),[m,N]=Z(null),[k,_]=Z(false),[F,D]=Z(null),[,b]=Z(0),S=ti({minBottom:16}),v=e?.session?.expiresAt;Ko(()=>{if(!v||v<=Date.now())return;let x=setTimeout(()=>b(U=>U+1),v-Date.now()+1);return()=>clearTimeout(x)},[v]);let C=!!v&&v>Date.now(),A=dt(()=>(e?.events??[]).filter(x=>JSON.stringify(x).toLowerCase().includes(d.trim().toLowerCase())).slice().reverse(),[e?.events,d]),T=e?.events.find(x=>x.id===m),L=e?.events.length??0,W=!!e?.provider;function J(x){h(x),n?.(x),D(null)}async function R(x,U){if(k)return false;_(true),D(null);try{return await t(x,U),true}catch(Ie){return D({text:Ie instanceof Error?Ie.message:String(Ie),error:true}),false}finally{_(false)}}let te=()=>{R("setCaptureSession",{runId:`capture-${Date.now()}`,durationMs:18e5})},Fe=()=>{R("setCaptureSession",{runId:null})};async function Me(x){let U=await ei(x);D({text:U?"Copied to clipboard.":"Clipboard is unavailable. Select the text to copy it.",error:!U})}let St=[{key:"send",label:"Test"},{key:"events",label:`Activity (${L})`}],We=a(Uo,{tabs:St,activeKey:p,onChange:J,size:"sm",glass:true}),Ke=y(je,{children:[a(je.Content,{title:"",noMargin:true,children:r?We:a(f,{style:s.tabsCap,children:We})}),y(je.Actions,{children:[a(K,{accessibilityRole:"button",accessibilityLabel:"Notification settings",onPress:()=>J(p==="setup"||p==="tokens"?"send":"setup"),style:s.iconButton,children:a(Yo,{size:16,color:p==="setup"||p==="tokens"?O.color.accent:O.color.textSecondary})}),p!=="send"&&a(Go,{isEnabled:C,onToggle:C?Fe:te,disabled:!W||k,accessibilityLabel:C?"Stop notification capture":"Start notification capture",testID:"notifications-capture"})]})]}),$e=y(f,{style:s.root,children:[W&&p!=="send"&&y(f,{style:s.status,children:[y(f,{style:s.statusLabel,children:[a(f,{style:[s.dot,C&&s.liveDot]}),a(u,{style:s.caption,children:C?"Recording":"Capture stopped"})]}),p!=="events"&&a(u,{style:s.caption,children:e.durable?"Persistent history":"Memory only"}),p!=="events"&&y(u,{style:s.provider,children:[e.provider," \xB7 ",e.platform]})]}),e?.storageError&&y(u,{accessibilityRole:"alert",style:s.errorNotice,children:["Storage: ",e.storageError]}),F&&a(u,{accessibilityRole:F.error?"alert":"text",style:[s.notice,F.error&&s.errorText],children:F.text}),!o&&a(f,{style:p==="send"?s.fill:{display:"none"},children:a(pi,{snapshot:e,onAction:t,onViewActivity:()=>J("events")})}),p==="send"?o??null:W?y(Be,{children:[p==="events"&&y(Be,{children:[y(f,{style:s.searchRow,children:[y(f,{style:s.searchField,children:[a(Xo,{size:14,color:O.color.textSecondary}),a(de,{accessibilityLabel:"Filter notification events",placeholder:"Search notifications\u2026",placeholderTextColor:O.color.placeholder,value:d,onChangeText:x=>{c(x),N(null)},autoCapitalize:"none",autoCorrect:false,style:s.searchInput}),!!d&&a(K,{accessibilityRole:"button",accessibilityLabel:"Clear notification search",onPress:()=>c(""),style:s.clearSearch,children:a(Qo,{size:12,color:O.color.textSecondary})})]}),a(K,{accessibilityRole:"button",accessibilityLabel:"Clear captured events",disabled:k||!L,accessibilityState:{disabled:k||!L},style:[s.iconButton,(k||!L)&&s.disabled],onPress:()=>{R("clearCapturedEvents").then(x=>{x&&N(null)})},children:a(Zo,{size:14,color:O.color.textSecondary})})]}),T?y(ne,{style:s.fill,contentContainerStyle:[s.content,{paddingBottom:S.bottom}],keyboardShouldPersistTaps:"handled",children:[y(f,{style:s.actionRow,children:[a(M,{label:"Back to events",onPress:()=>N(null),icon:a(_o,{size:14,color:O.color.accent})}),a(M,{label:"Copy event JSON",onPress:()=>{Me(T)},icon:a(ut,{size:14,color:O.color.accent})})]}),y(q,{glass:true,padded:true,children:[a(we,{label:Ve[T.kind]??T.kind,tone:bt(T.kind)}),a(u,{style:s.detailTitle,children:T.title??"Notification event"}),a(u,{style:s.caption,children:new Date(T.capturedAt).toLocaleString()})]}),y(f,{children:[a(G,{children:"Observation"}),a(q,{glass:true,children:y(ht,{children:[a(ee,{label:"App state at callback",value:T.observedAppState}),T.testId&&a(ee,{label:"Test ID",value:T.testId}),T.notificationId&&a(ee,{label:"Notification ID",value:T.notificationId}),T.actionIdentifier&&a(ee,{label:"Action",value:T.actionIdentifier})]})})]}),T.kind==="startup-response"&&a(u,{style:s.footnote,children:"Recovered from the SDK cache. This alone does not establish why the app launched."}),T.truncated&&a(u,{style:s.warning,children:"This payload was truncated when captured."}),a(xe,{title:"Payload",value:T.raw}),a(xe,{title:"Full event",value:T,initiallyOpen:false})]}):a(Ge,{data:A,keyExtractor:x=>x.id,style:s.fill,contentContainerStyle:[s.eventList,{paddingBottom:S.bottom}],keyboardShouldPersistTaps:"handled",initialNumToRender:15,ListHeaderComponent:d?y(u,{style:s.resultCount,children:[A.length," of ",L," events"]}):null,ListFooterComponent:e.evicted>0?y(u,{style:s.footnote,children:[e.evicted," older records removed by the history limit."]}):null,ListEmptyComponent:a(De,{otto:d?"sad":C?"listening":"paused",title:d?"No matching events":C?"Waiting for notifications":"Capture is stopped",message:d?"Try another title, test ID, or payload value.":C?"Send a notification from Buoy Desktop or your app. Background alerts can reach the system tray before an app callback runs.":"Start capture with the power button, then send a notification."}),renderItem:({item:x})=>a(ui,{event:x,onPress:()=>N(x.id)})})]}),p==="tokens"&&y(ne,{style:s.fill,contentContainerStyle:[s.content,{paddingBottom:S.bottom}],keyboardShouldPersistTaps:"handled",children:[y(f,{children:[a(M,{label:"Back to settings",onPress:()=>J("setup")}),a(G,{children:"Registration"}),y(q,{glass:true,padded:true,children:[a(u,{style:s.bodyText,children:"Register a token to test delivery through your push provider."}),y(f,{style:s.actionRow,children:[a(M,{label:"Register device token",onPress:()=>{R("refreshToken",{type:"device"})},disabled:k,primary:true}),a(M,{label:"Register Expo token",onPress:()=>{R("refreshToken",{type:"expo"})},disabled:k||!e.capabilities.includes("expo-token")})]})]}),a(u,{style:s.footnote,children:"Registration runs only when you or your app request it. Simulator sends work without a token."})]}),e.tokens.length===0?a(De,{otto:"listening",title:"No tokens observed",message:"Register a device token above, or let your app register one."}):e.tokens.map((x,U)=>y(f,{children:[a(G,{children:x.type.toUpperCase()+" token"}),y(q,{glass:true,padded:true,children:[y(f,{style:s.actionRow,children:[a(we,{label:x.type,tone:"accent"}),x.environment&&a(u,{style:s.caption,children:x.environment})]}),a(u,{selectable:true,style:s.token,children:x.value}),x.projectId&&y(u,{selectable:true,style:s.caption,children:["Project: ",x.projectId]}),y(u,{style:s.caption,children:["Observed ",new Date(x.observedAt).toLocaleString()]}),a(f,{style:s.actionRow,children:a(M,{label:"Copy "+x.type.toUpperCase()+" token",onPress:()=>{Me(x.value)},icon:a(ut,{size:14,color:O.color.accent})})})]})]},x.type+"-"+U))]}),p==="setup"&&y(ne,{style:s.fill,contentContainerStyle:[s.content,{paddingBottom:S.bottom}],keyboardShouldPersistTaps:"handled",children:[y(f,{children:[a(M,{label:"Device tokens",onPress:()=>J("tokens")}),a(G,{children:"Capture session"}),y(q,{glass:true,padded:true,children:[y(f,{style:s.actionRow,children:[a(we,{label:C?"Recording":"Stopped",tone:C?"accent":"neutral"}),a(u,{style:s.caption,children:C?"Until "+new Date(v).toLocaleTimeString():"Ready when you are"})]}),y(f,{style:s.actionRow,children:[a(M,{label:"Arm capture for 30 minutes",onPress:te,disabled:k,primary:true}),a(M,{label:"Stop capture",onPress:Fe,disabled:k||!C})]})]}),a(u,{style:s.footnote,children:e.durable?"History is saved on the app and survives app and desktop restarts.":"History is held in memory. Keep the app running to retain it."})]}),y(f,{children:[a(G,{children:"Connected app"}),a(q,{glass:true,children:y(ht,{children:[a(ee,{label:"App",value:e.appId??"Not supplied"}),a(ee,{label:"Provider",value:[e.provider,e.providerVersion].filter(Boolean).join(" ")}),a(ee,{label:"Platform",value:e.platform})]})})]}),y(f,{children:[a(G,{children:"Permissions"}),a(f,{style:s.sectionActions,children:a(M,{label:"Refresh permissions",disabled:k,onPress:()=>{R("getPermissions")}})}),a(xe,{title:"Permission settings",value:e.permissions})]}),y(f,{children:[a(G,{children:"System tray"}),a(f,{style:s.sectionActions,children:a(M,{label:"Inspect system tray",disabled:k||!e.capabilities.includes("presented"),onPress:()=>{R("listPresented")}})}),a(xe,{title:"Currently presented",value:e.presented}),a(u,{style:s.footnote,children:"Notifications currently in the system tray. Captured history is in Activity."})]}),y(f,{children:[a(G,{children:"Capabilities"}),a(q,{glass:true,padded:true,children:a(f,{style:s.actionRow,children:e.capabilities.map(x=>a(we,{label:x},x))})})]})]})]}):y(ne,{children:[a(De,{otto:"paused",title:"Connect notification capture",message:"Install @buoy-gg/notifications and call installExpoNotificationCapture in the app entry point. Use an app-specific development build for remote notifications."}),a(u,{style:s.emptyFootnote,children:"The desktop sender works with any installed app. Inspection needs the capture integration."})]})]});return a(Be,{children:r?r({header:Ke,body:$e}):y(f,{style:s.root,children:[a(f,{style:s.inlineHeader,...Jo,children:Ke}),$e]})})}function ui({event:e,onPress:t}){let o=bt(e.kind),i=o==="danger"?O.color.danger:o==="warning"?O.color.warning:o==="accent"?O.color.accent:O.color.textSecondary;return y(K,{accessibilityRole:"button",accessibilityLabel:(Ve[e.kind]??e.kind)+": "+(e.title??e.testId??e.notificationId??"notification"),onPress:t,style:({pressed:n})=>[s.event,n&&s.pressed],children:[y(f,{style:s.eventTop,children:[y(f,{style:s.eventKind,children:[a(qo,{size:13,color:i}),a(u,{numberOfLines:1,style:[s.eventLabel,{color:i}],children:Ve[e.kind]??e.kind})]}),a(u,{style:s.timestamp,children:new Date(e.capturedAt).toLocaleTimeString()})]}),y(f,{style:s.eventSubject,children:[a(u,{numberOfLines:1,style:s.eventTitle,children:e.title??e.testId??e.notificationId??"Notification event"}),a(pt,{size:14,color:O.color.textTertiary})]}),y(u,{numberOfLines:1,style:s.eventMeta,children:[e.observedAppState,e.truncated?" \xB7 Truncated":""]})]})}import{useSyncExternalStore as hi}from"react";import{createToolFactory as fi,defineToolPreset as yi,JsModal as gi,NotificationsIcon as bi}from"@buoy-gg/shared-ui/web";import{jsx as He}from"react/jsx-runtime";function vt(e){let t=hi(se.subscribe,se.getSnapshot);return He(mt,{snapshot:t,renderShell:({header:o,body:i})=>He(gi,{...e,persistenceKey:e.persistenceKey??"buoy-notifications",variant:"night",header:{showToggleButton:true,customContent:o},enablePersistence:true,initialMode:"bottomSheet",disableScrollWrapper:true,children:i}),onAction:async(o,i)=>{let n=se.actions[o];if(!n)throw new Error("This notification action is unavailable.");return n(i)}})}var wt=yi({id:"push-notifications",name:"NOTIFICATIONS",description:"Send a test notification and inspect how the app responds",slot:"both",icon:({size:e,color:t})=>He(bi,{size:e,color:t}),component:vt}),mi=fi(wt);import{NotificationsIcon as vi}from"@buoy-gg/shared-ui/web";function wi(e){let t={...e.data,__buoyTestId:e.testId},o=e.silent?{"content-available":1}:{alert:{title:e.title,body:e.body},sound:"default"};return JSON.stringify(e.adapter==="expo"?{aps:o,body:t}:{...t,aps:o},null,2)}function Si(e){let t=[],o=[];if(typeof e!="string")return{valid:false,bytes:0,errors:["Provide the APNs payload as JSON text."],warnings:o,testId:null};let i=re(e);i>4096&&t.push(`Payload is ${i} bytes. APNs payloads must fit in 4096 UTF-8 bytes.`);let n;try{n=JSON.parse(e)}catch{t.push("Payload is not valid JSON.")}let r=g(n);(!n||typeof n!="object"||Array.isArray(n))&&t.push("The payload must be a JSON object."),(!r.aps||typeof r.aps!="object"||Array.isArray(r.aps))&&t.push('The payload needs an "aps" object.');let l=g(r.aps);l.alert!==void 0&&typeof l.alert!="string"&&(l.alert===null||typeof l.alert!="object"||Array.isArray(l.alert))&&t.push("aps.alert must be text or an object."),l.badge!==void 0&&(!Number.isInteger(l.badge)||Number(l.badge)<0)&&t.push("aps.badge must be a non-negative integer.");for(let p of["content-available","mutable-content"])l[p]!==void 0&&l[p]!==1&&t.push(`aps.${p} must be 1 when present.`);l["content-available"]===1&&o.push("Background execution depends on app configuration and OS scheduling. A successful send does not prove the task ran."),l["mutable-content"]===1&&o.push("Use real APNs delivery to verify notification service extensions."),r.data!==void 0&&r.body===void 0&&o.push("Expo on iOS reads custom data from a top-level body object. This raw payload will be sent unchanged.");let h=g(r.body).__buoyTestId??r.__buoyTestId;return{valid:t.length===0,bytes:i,errors:t,warnings:o,testId:typeof h=="string"?h:null}}var xi=(()=>{try{return globalThis.Capacitor?.isNativePlatform?.()===true}catch{return false}})();xi&&typeof ye<"u"&&ye&&lt();export{Re as NotificationRecorder,gt as NotificationTestView,mt as NotificationToolView,vi as NotificationsIcon,vt as NotificationsModal,rt as attachCapacitorNotifications,nt as attachExpoNotifications,me as capacitorMetadata,wi as composeSimulatorPayload,zo as createExpoNotificationStorage,mi as createNotificationTool,X as expoMetadata,Oe as getNotificationRecorder,lt as installCapacitorNotificationCapture,Wo as installExpoNotificationCapture,Ho as instrumentExpoNotificationHandler,Mo as instrumentNotificationBackgroundTask,se as notificationSyncAdapter,wt as notificationToolPreset,Si as validateSimulatorPayload};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@buoy-gg/notifications",
3
- "version": "7.0.82",
3
+ "version": "7.0.83",
4
4
  "description": "Send simulator notifications and inspect app receipt, interactions and device tokens.",
5
5
  "main": "lib/commonjs/index.js",
6
6
  "module": "lib/module/index.js",
@@ -17,10 +17,10 @@
17
17
  "./lib/web/**/*.mjs"
18
18
  ],
19
19
  "dependencies": {
20
- "@buoy-gg/shared-ui": "^7.0.82"
20
+ "@buoy-gg/shared-ui": "^7.0.83"
21
21
  },
22
22
  "peerDependencies": {
23
- "@buoy-gg/license": "7.0.82",
23
+ "@buoy-gg/license": "7.0.83",
24
24
  "react": "*",
25
25
  "react-native": "*"
26
26
  },
@@ -28,7 +28,7 @@
28
28
  "@types/react": "^19.1.0",
29
29
  "@types/react-native": "^0.73.0",
30
30
  "typescript": "~5.8.3",
31
- "@buoy-gg/license": "^7.0.82"
31
+ "@buoy-gg/license": "^7.0.83"
32
32
  },
33
33
  "react-native-builder-bob": {
34
34
  "source": "src",