@buoy-gg/notifications 7.0.41 → 7.0.42
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/commonjs/components/LocalNotificationTest.js +1 -185
- package/lib/commonjs/components/NotificationTestView.js +1 -329
- package/lib/commonjs/components/NotificationToolView.js +1 -673
- package/lib/commonjs/components/notificationStyles.js +1 -292
- package/lib/commonjs/expo.js +1 -247
- package/lib/commonjs/index.js +1 -148
- package/lib/commonjs/json.js +1 -58
- package/lib/commonjs/payload.js +1 -68
- package/lib/commonjs/preset.js +1 -56
- package/lib/commonjs/preview.js +1 -18
- package/lib/commonjs/recorder.js +1 -339
- package/lib/commonjs/runtime.js +1 -110
- package/lib/commonjs/storage.js +1 -61
- package/lib/commonjs/types.js +0 -1
- package/lib/module/components/LocalNotificationTest.js +1 -180
- package/lib/module/components/NotificationTestView.js +1 -324
- package/lib/module/components/NotificationToolView.js +1 -668
- package/lib/module/components/notificationStyles.js +1 -288
- package/lib/module/expo.js +1 -241
- package/lib/module/index.js +1 -13
- package/lib/module/json.js +1 -51
- package/lib/module/payload.js +1 -63
- package/lib/module/preset.js +1 -50
- package/lib/module/preview.js +1 -14
- package/lib/module/recorder.js +1 -332
- package/lib/module/runtime.js +1 -103
- package/lib/module/storage.js +1 -56
- package/lib/module/types.js +0 -1
- package/package.json +2 -2
- package/lib/commonjs/components/LocalNotificationTest.js.map +0 -1
- package/lib/commonjs/components/NotificationTestView.js.map +0 -1
- package/lib/commonjs/components/NotificationToolView.js.map +0 -1
- package/lib/commonjs/components/notificationStyles.js.map +0 -1
- package/lib/commonjs/expo.js.map +0 -1
- package/lib/commonjs/index.js.map +0 -1
- package/lib/commonjs/json.js.map +0 -1
- package/lib/commonjs/payload.js.map +0 -1
- package/lib/commonjs/preset.js.map +0 -1
- package/lib/commonjs/preview.js.map +0 -1
- package/lib/commonjs/recorder.js.map +0 -1
- package/lib/commonjs/runtime.js.map +0 -1
- package/lib/commonjs/storage.js.map +0 -1
- package/lib/commonjs/types.js.map +0 -1
- package/lib/module/components/LocalNotificationTest.js.map +0 -1
- package/lib/module/components/NotificationTestView.js.map +0 -1
- package/lib/module/components/NotificationToolView.js.map +0 -1
- package/lib/module/components/notificationStyles.js.map +0 -1
- package/lib/module/expo.js.map +0 -1
- package/lib/module/index.js.map +0 -1
- package/lib/module/json.js.map +0 -1
- package/lib/module/payload.js.map +0 -1
- package/lib/module/preset.js.map +0 -1
- package/lib/module/preview.js.map +0 -1
- package/lib/module/recorder.js.map +0 -1
- package/lib/module/runtime.js.map +0 -1
- package/lib/module/storage.js.map +0 -1
- package/lib/module/types.js.map +0 -1
- package/lib/typescript/components/LocalNotificationTest.d.ts.map +0 -1
- package/lib/typescript/components/NotificationTestView.d.ts.map +0 -1
- package/lib/typescript/components/NotificationToolView.d.ts.map +0 -1
- package/lib/typescript/components/notificationStyles.d.ts.map +0 -1
- package/lib/typescript/expo.d.ts.map +0 -1
- package/lib/typescript/index.d.ts.map +0 -1
- package/lib/typescript/json.d.ts.map +0 -1
- package/lib/typescript/payload.d.ts.map +0 -1
- package/lib/typescript/preset.d.ts.map +0 -1
- package/lib/typescript/preview.d.ts.map +0 -1
- package/lib/typescript/recorder.d.ts.map +0 -1
- package/lib/typescript/runtime.d.ts.map +0 -1
- package/lib/typescript/storage.d.ts.map +0 -1
- package/lib/typescript/types.d.ts.map +0 -1
|
@@ -1,668 +1 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
|
|
3
|
-
import React, { useEffect, useMemo, useState } from "react";
|
|
4
|
-
import { FlatList, Pressable, ScrollView, Text, TextInput, View } from "react-native";
|
|
5
|
-
import { ChevronDown, ChevronLeft, ChevronRight, Copy, ModalHeader, NightBadge, NightCard, NightRows, NightSectionLabel, NightSegmented, NotificationsIcon, PowerToggleButton, Search, Settings, ToolEmptyState, Trash2, X, copyToClipboard, night, useSafeAreaInsets } from "@buoy-gg/shared-ui";
|
|
6
|
-
import { DataViewer } from "@buoy-gg/shared-ui/dataViewer";
|
|
7
|
-
import { LocalNotificationTest } from "./LocalNotificationTest";
|
|
8
|
-
import { styles } from "./notificationStyles";
|
|
9
|
-
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
10
|
-
const labels = {
|
|
11
|
-
received: "App received",
|
|
12
|
-
response: "Notification response",
|
|
13
|
-
"startup-response": "Response recovered at startup",
|
|
14
|
-
"presentation-decision": "Presentation decision",
|
|
15
|
-
"presentation-error": "Presentation error",
|
|
16
|
-
"background-started": "Background task started",
|
|
17
|
-
"background-completed": "Background task completed",
|
|
18
|
-
"background-error": "Background task failed",
|
|
19
|
-
"app-outcome": "App outcome",
|
|
20
|
-
"local-scheduled": "Local notification scheduled"
|
|
21
|
-
};
|
|
22
|
-
function eventTone(kind) {
|
|
23
|
-
return kind.includes("error") ? "danger" : kind === "startup-response" ? "warning" : kind === "received" || kind === "app-outcome" ? "accent" : "neutral";
|
|
24
|
-
}
|
|
25
|
-
function Action({
|
|
26
|
-
label,
|
|
27
|
-
onPress,
|
|
28
|
-
disabled,
|
|
29
|
-
primary,
|
|
30
|
-
icon
|
|
31
|
-
}) {
|
|
32
|
-
return /*#__PURE__*/_jsxs(Pressable, {
|
|
33
|
-
accessibilityRole: "button",
|
|
34
|
-
accessibilityLabel: label,
|
|
35
|
-
accessibilityState: {
|
|
36
|
-
disabled: !!disabled
|
|
37
|
-
},
|
|
38
|
-
disabled: disabled,
|
|
39
|
-
onPress: onPress,
|
|
40
|
-
style: ({
|
|
41
|
-
pressed
|
|
42
|
-
}) => [styles.button, primary && styles.primaryButton, pressed && styles.pressed, disabled && styles.disabled],
|
|
43
|
-
children: [icon, /*#__PURE__*/_jsx(Text, {
|
|
44
|
-
style: [styles.buttonText, primary && styles.primaryButtonText],
|
|
45
|
-
children: label
|
|
46
|
-
})]
|
|
47
|
-
});
|
|
48
|
-
}
|
|
49
|
-
function Field({
|
|
50
|
-
label,
|
|
51
|
-
value
|
|
52
|
-
}) {
|
|
53
|
-
return /*#__PURE__*/_jsxs(View, {
|
|
54
|
-
style: styles.field,
|
|
55
|
-
children: [/*#__PURE__*/_jsx(Text, {
|
|
56
|
-
style: [styles.caption, styles.fieldLabel],
|
|
57
|
-
children: label
|
|
58
|
-
}), /*#__PURE__*/_jsx(Text, {
|
|
59
|
-
selectable: true,
|
|
60
|
-
style: styles.value,
|
|
61
|
-
children: value
|
|
62
|
-
})]
|
|
63
|
-
});
|
|
64
|
-
}
|
|
65
|
-
function JsonCard({
|
|
66
|
-
title,
|
|
67
|
-
value,
|
|
68
|
-
initiallyOpen = true
|
|
69
|
-
}) {
|
|
70
|
-
const [open, setOpen] = useState(initiallyOpen);
|
|
71
|
-
const serialized = JSON.stringify(value ?? null);
|
|
72
|
-
// Device snapshots can recreate unchanged objects. Keep the data tree stable.
|
|
73
|
-
const data = useMemo(() => JSON.parse(serialized), [serialized]);
|
|
74
|
-
return /*#__PURE__*/_jsxs(NightCard, {
|
|
75
|
-
glass: true,
|
|
76
|
-
children: [/*#__PURE__*/_jsxs(Pressable, {
|
|
77
|
-
accessibilityRole: "button",
|
|
78
|
-
accessibilityLabel: title,
|
|
79
|
-
accessibilityState: {
|
|
80
|
-
expanded: open
|
|
81
|
-
},
|
|
82
|
-
onPress: () => setOpen(value => !value),
|
|
83
|
-
style: styles.disclosure,
|
|
84
|
-
children: [/*#__PURE__*/_jsx(Text, {
|
|
85
|
-
style: styles.disclosureTitle,
|
|
86
|
-
children: title
|
|
87
|
-
}), open ? /*#__PURE__*/_jsx(ChevronDown, {
|
|
88
|
-
size: 14,
|
|
89
|
-
color: night.color.textSecondary
|
|
90
|
-
}) : /*#__PURE__*/_jsx(ChevronRight, {
|
|
91
|
-
size: 14,
|
|
92
|
-
color: night.color.textSecondary
|
|
93
|
-
})]
|
|
94
|
-
}), open && /*#__PURE__*/_jsx(View, {
|
|
95
|
-
style: styles.jsonBody,
|
|
96
|
-
children: /*#__PURE__*/_jsx(DataViewer, {
|
|
97
|
-
title: "",
|
|
98
|
-
data: data,
|
|
99
|
-
rawMode: true,
|
|
100
|
-
initialExpanded: true,
|
|
101
|
-
showTypeFilter: false
|
|
102
|
-
})
|
|
103
|
-
})]
|
|
104
|
-
});
|
|
105
|
-
}
|
|
106
|
-
export function NotificationToolView({
|
|
107
|
-
snapshot,
|
|
108
|
-
onAction,
|
|
109
|
-
sender,
|
|
110
|
-
activeTab,
|
|
111
|
-
onTabChange,
|
|
112
|
-
renderShell
|
|
113
|
-
}) {
|
|
114
|
-
const [localTab, setLocalTab] = useState("send");
|
|
115
|
-
const tab = activeTab ?? localTab;
|
|
116
|
-
const [filter, setFilter] = useState("");
|
|
117
|
-
const [selectedId, setSelectedId] = useState(null);
|
|
118
|
-
const [busy, setBusy] = useState(false);
|
|
119
|
-
const [message, setMessage] = useState(null);
|
|
120
|
-
const [, setClock] = useState(0);
|
|
121
|
-
const insets = useSafeAreaInsets({
|
|
122
|
-
minBottom: 16
|
|
123
|
-
});
|
|
124
|
-
const expiresAt = snapshot?.session?.expiresAt;
|
|
125
|
-
useEffect(() => {
|
|
126
|
-
if (!expiresAt || expiresAt <= Date.now()) return;
|
|
127
|
-
const timeout = setTimeout(() => setClock(value => value + 1), expiresAt - Date.now() + 1);
|
|
128
|
-
return () => clearTimeout(timeout);
|
|
129
|
-
}, [expiresAt]);
|
|
130
|
-
const recording = !!expiresAt && expiresAt > Date.now();
|
|
131
|
-
const events = useMemo(() => (snapshot?.events ?? []).filter(event => JSON.stringify(event).toLowerCase().includes(filter.trim().toLowerCase())).slice().reverse(), [snapshot?.events, filter]);
|
|
132
|
-
const selected = snapshot?.events.find(event => event.id === selectedId);
|
|
133
|
-
const count = snapshot?.events.length ?? 0;
|
|
134
|
-
const connected = !!snapshot?.provider;
|
|
135
|
-
function changeTab(next) {
|
|
136
|
-
setLocalTab(next);
|
|
137
|
-
onTabChange?.(next);
|
|
138
|
-
setMessage(null);
|
|
139
|
-
}
|
|
140
|
-
async function act(action, params) {
|
|
141
|
-
if (busy) return false;
|
|
142
|
-
setBusy(true);
|
|
143
|
-
setMessage(null);
|
|
144
|
-
try {
|
|
145
|
-
await onAction(action, params);
|
|
146
|
-
return true;
|
|
147
|
-
} catch (error) {
|
|
148
|
-
setMessage({
|
|
149
|
-
text: error instanceof Error ? error.message : String(error),
|
|
150
|
-
error: true
|
|
151
|
-
});
|
|
152
|
-
return false;
|
|
153
|
-
} finally {
|
|
154
|
-
setBusy(false);
|
|
155
|
-
}
|
|
156
|
-
}
|
|
157
|
-
const arm = () => {
|
|
158
|
-
void act("setCaptureSession", {
|
|
159
|
-
runId: `capture-${Date.now()}`,
|
|
160
|
-
durationMs: 1800000
|
|
161
|
-
});
|
|
162
|
-
};
|
|
163
|
-
const stop = () => {
|
|
164
|
-
void act("setCaptureSession", {
|
|
165
|
-
runId: null
|
|
166
|
-
});
|
|
167
|
-
};
|
|
168
|
-
async function copy(value) {
|
|
169
|
-
const copied = await copyToClipboard(value);
|
|
170
|
-
setMessage({
|
|
171
|
-
text: copied ? "Copied to clipboard." : "Clipboard is unavailable. Select the text to copy it.",
|
|
172
|
-
error: !copied
|
|
173
|
-
});
|
|
174
|
-
}
|
|
175
|
-
const tabs = [{
|
|
176
|
-
key: "send",
|
|
177
|
-
label: "Test"
|
|
178
|
-
}, {
|
|
179
|
-
key: "events",
|
|
180
|
-
label: `Activity (${count})`
|
|
181
|
-
}];
|
|
182
|
-
const header = /*#__PURE__*/_jsxs(ModalHeader, {
|
|
183
|
-
children: [/*#__PURE__*/_jsx(ModalHeader.Content, {
|
|
184
|
-
title: "",
|
|
185
|
-
noMargin: true,
|
|
186
|
-
children: /*#__PURE__*/_jsx(NightSegmented, {
|
|
187
|
-
tabs: tabs,
|
|
188
|
-
activeKey: tab,
|
|
189
|
-
onChange: changeTab,
|
|
190
|
-
size: "sm",
|
|
191
|
-
glass: true
|
|
192
|
-
})
|
|
193
|
-
}), /*#__PURE__*/_jsxs(ModalHeader.Actions, {
|
|
194
|
-
children: [/*#__PURE__*/_jsx(Pressable, {
|
|
195
|
-
accessibilityRole: "button",
|
|
196
|
-
accessibilityLabel: "Notification settings",
|
|
197
|
-
onPress: () => changeTab(tab === "setup" || tab === "tokens" ? "send" : "setup"),
|
|
198
|
-
style: styles.iconButton,
|
|
199
|
-
children: /*#__PURE__*/_jsx(Settings, {
|
|
200
|
-
size: 16,
|
|
201
|
-
color: tab === "setup" || tab === "tokens" ? night.color.accent : night.color.textSecondary
|
|
202
|
-
})
|
|
203
|
-
}), tab !== "send" && /*#__PURE__*/_jsx(PowerToggleButton, {
|
|
204
|
-
isEnabled: recording,
|
|
205
|
-
onToggle: recording ? stop : arm,
|
|
206
|
-
disabled: !connected || busy,
|
|
207
|
-
accessibilityLabel: recording ? "Stop notification capture" : "Start notification capture",
|
|
208
|
-
testID: "notifications-capture"
|
|
209
|
-
})]
|
|
210
|
-
})]
|
|
211
|
-
});
|
|
212
|
-
const body = /*#__PURE__*/_jsxs(View, {
|
|
213
|
-
style: styles.root,
|
|
214
|
-
children: [connected && tab !== "send" && /*#__PURE__*/_jsxs(View, {
|
|
215
|
-
style: styles.status,
|
|
216
|
-
children: [/*#__PURE__*/_jsxs(View, {
|
|
217
|
-
style: styles.statusLabel,
|
|
218
|
-
children: [/*#__PURE__*/_jsx(View, {
|
|
219
|
-
style: [styles.dot, recording && styles.liveDot]
|
|
220
|
-
}), /*#__PURE__*/_jsx(Text, {
|
|
221
|
-
style: styles.caption,
|
|
222
|
-
children: recording ? "Recording" : "Capture stopped"
|
|
223
|
-
})]
|
|
224
|
-
}), tab !== "events" && /*#__PURE__*/_jsx(Text, {
|
|
225
|
-
style: styles.caption,
|
|
226
|
-
children: snapshot.durable ? "Persistent history" : "Memory only"
|
|
227
|
-
}), tab !== "events" && /*#__PURE__*/_jsxs(Text, {
|
|
228
|
-
style: styles.provider,
|
|
229
|
-
children: [snapshot.provider, " \xB7 ", snapshot.platform]
|
|
230
|
-
})]
|
|
231
|
-
}), snapshot?.storageError && /*#__PURE__*/_jsxs(Text, {
|
|
232
|
-
accessibilityRole: "alert",
|
|
233
|
-
style: styles.errorNotice,
|
|
234
|
-
children: ["Storage: ", snapshot.storageError]
|
|
235
|
-
}), message && /*#__PURE__*/_jsx(Text, {
|
|
236
|
-
accessibilityRole: message.error ? "alert" : "text",
|
|
237
|
-
style: [styles.notice, message.error && styles.errorText],
|
|
238
|
-
children: message.text
|
|
239
|
-
}), !sender && /*#__PURE__*/_jsx(View, {
|
|
240
|
-
style: tab === "send" ? styles.fill : {
|
|
241
|
-
display: "none"
|
|
242
|
-
},
|
|
243
|
-
children: /*#__PURE__*/_jsx(LocalNotificationTest, {
|
|
244
|
-
snapshot: snapshot,
|
|
245
|
-
onAction: onAction,
|
|
246
|
-
onViewActivity: () => changeTab("events")
|
|
247
|
-
})
|
|
248
|
-
}), tab === "send" ? sender ?? null : !connected ? /*#__PURE__*/_jsxs(ScrollView, {
|
|
249
|
-
children: [/*#__PURE__*/_jsx(ToolEmptyState, {
|
|
250
|
-
otto: "paused",
|
|
251
|
-
title: "Connect notification capture",
|
|
252
|
-
message: "Install @buoy-gg/notifications and call installExpoNotificationCapture in the app entry point. Use an app-specific development build for remote notifications."
|
|
253
|
-
}), /*#__PURE__*/_jsx(Text, {
|
|
254
|
-
style: styles.emptyFootnote,
|
|
255
|
-
children: "The desktop sender works with any installed app. Inspection needs the capture integration."
|
|
256
|
-
})]
|
|
257
|
-
}) : /*#__PURE__*/_jsxs(_Fragment, {
|
|
258
|
-
children: [tab === "events" && /*#__PURE__*/_jsxs(_Fragment, {
|
|
259
|
-
children: [/*#__PURE__*/_jsxs(View, {
|
|
260
|
-
style: styles.searchRow,
|
|
261
|
-
children: [/*#__PURE__*/_jsxs(View, {
|
|
262
|
-
style: styles.searchField,
|
|
263
|
-
children: [/*#__PURE__*/_jsx(Search, {
|
|
264
|
-
size: 14,
|
|
265
|
-
color: night.color.textSecondary
|
|
266
|
-
}), /*#__PURE__*/_jsx(TextInput, {
|
|
267
|
-
accessibilityLabel: "Filter notification events",
|
|
268
|
-
placeholder: "Search notifications\u2026",
|
|
269
|
-
placeholderTextColor: night.color.placeholder,
|
|
270
|
-
value: filter,
|
|
271
|
-
onChangeText: value => {
|
|
272
|
-
setFilter(value);
|
|
273
|
-
setSelectedId(null);
|
|
274
|
-
},
|
|
275
|
-
autoCapitalize: "none",
|
|
276
|
-
autoCorrect: false,
|
|
277
|
-
style: styles.searchInput
|
|
278
|
-
}), !!filter && /*#__PURE__*/_jsx(Pressable, {
|
|
279
|
-
accessibilityRole: "button",
|
|
280
|
-
accessibilityLabel: "Clear notification search",
|
|
281
|
-
onPress: () => setFilter(""),
|
|
282
|
-
style: styles.clearSearch,
|
|
283
|
-
children: /*#__PURE__*/_jsx(X, {
|
|
284
|
-
size: 12,
|
|
285
|
-
color: night.color.textSecondary
|
|
286
|
-
})
|
|
287
|
-
})]
|
|
288
|
-
}), /*#__PURE__*/_jsx(Pressable, {
|
|
289
|
-
accessibilityRole: "button",
|
|
290
|
-
accessibilityLabel: "Clear captured events",
|
|
291
|
-
disabled: busy || !count,
|
|
292
|
-
accessibilityState: {
|
|
293
|
-
disabled: busy || !count
|
|
294
|
-
},
|
|
295
|
-
style: [styles.iconButton, (busy || !count) && styles.disabled],
|
|
296
|
-
onPress: () => {
|
|
297
|
-
void act("clearCapturedEvents").then(cleared => {
|
|
298
|
-
if (cleared) setSelectedId(null);
|
|
299
|
-
});
|
|
300
|
-
},
|
|
301
|
-
children: /*#__PURE__*/_jsx(Trash2, {
|
|
302
|
-
size: 14,
|
|
303
|
-
color: night.color.textSecondary
|
|
304
|
-
})
|
|
305
|
-
})]
|
|
306
|
-
}), selected ? /*#__PURE__*/_jsxs(ScrollView, {
|
|
307
|
-
style: styles.fill,
|
|
308
|
-
contentContainerStyle: [styles.content, {
|
|
309
|
-
paddingBottom: insets.bottom
|
|
310
|
-
}],
|
|
311
|
-
keyboardShouldPersistTaps: "handled",
|
|
312
|
-
children: [/*#__PURE__*/_jsxs(View, {
|
|
313
|
-
style: styles.actionRow,
|
|
314
|
-
children: [/*#__PURE__*/_jsx(Action, {
|
|
315
|
-
label: "Back to events",
|
|
316
|
-
onPress: () => setSelectedId(null),
|
|
317
|
-
icon: /*#__PURE__*/_jsx(ChevronLeft, {
|
|
318
|
-
size: 14,
|
|
319
|
-
color: night.color.accent
|
|
320
|
-
})
|
|
321
|
-
}), /*#__PURE__*/_jsx(Action, {
|
|
322
|
-
label: "Copy event JSON",
|
|
323
|
-
onPress: () => {
|
|
324
|
-
void copy(selected);
|
|
325
|
-
},
|
|
326
|
-
icon: /*#__PURE__*/_jsx(Copy, {
|
|
327
|
-
size: 14,
|
|
328
|
-
color: night.color.accent
|
|
329
|
-
})
|
|
330
|
-
})]
|
|
331
|
-
}), /*#__PURE__*/_jsxs(NightCard, {
|
|
332
|
-
glass: true,
|
|
333
|
-
padded: true,
|
|
334
|
-
children: [/*#__PURE__*/_jsx(NightBadge, {
|
|
335
|
-
label: labels[selected.kind] ?? selected.kind,
|
|
336
|
-
tone: eventTone(selected.kind)
|
|
337
|
-
}), /*#__PURE__*/_jsx(Text, {
|
|
338
|
-
style: styles.detailTitle,
|
|
339
|
-
children: selected.title ?? "Notification event"
|
|
340
|
-
}), /*#__PURE__*/_jsx(Text, {
|
|
341
|
-
style: styles.caption,
|
|
342
|
-
children: new Date(selected.capturedAt).toLocaleString()
|
|
343
|
-
})]
|
|
344
|
-
}), /*#__PURE__*/_jsxs(View, {
|
|
345
|
-
children: [/*#__PURE__*/_jsx(NightSectionLabel, {
|
|
346
|
-
children: "Observation"
|
|
347
|
-
}), /*#__PURE__*/_jsx(NightCard, {
|
|
348
|
-
glass: true,
|
|
349
|
-
children: /*#__PURE__*/_jsxs(NightRows, {
|
|
350
|
-
children: [/*#__PURE__*/_jsx(Field, {
|
|
351
|
-
label: "App state at callback",
|
|
352
|
-
value: selected.observedAppState
|
|
353
|
-
}), selected.testId && /*#__PURE__*/_jsx(Field, {
|
|
354
|
-
label: "Test ID",
|
|
355
|
-
value: selected.testId
|
|
356
|
-
}), selected.notificationId && /*#__PURE__*/_jsx(Field, {
|
|
357
|
-
label: "Notification ID",
|
|
358
|
-
value: selected.notificationId
|
|
359
|
-
}), selected.actionIdentifier && /*#__PURE__*/_jsx(Field, {
|
|
360
|
-
label: "Action",
|
|
361
|
-
value: selected.actionIdentifier
|
|
362
|
-
})]
|
|
363
|
-
})
|
|
364
|
-
})]
|
|
365
|
-
}), selected.kind === "startup-response" && /*#__PURE__*/_jsx(Text, {
|
|
366
|
-
style: styles.footnote,
|
|
367
|
-
children: "Recovered from the SDK cache. This alone does not establish why the app launched."
|
|
368
|
-
}), selected.truncated && /*#__PURE__*/_jsx(Text, {
|
|
369
|
-
style: styles.warning,
|
|
370
|
-
children: "This payload was truncated when captured."
|
|
371
|
-
}), /*#__PURE__*/_jsx(JsonCard, {
|
|
372
|
-
title: "Payload",
|
|
373
|
-
value: selected.raw
|
|
374
|
-
}), /*#__PURE__*/_jsx(JsonCard, {
|
|
375
|
-
title: "Full event",
|
|
376
|
-
value: selected,
|
|
377
|
-
initiallyOpen: false
|
|
378
|
-
})]
|
|
379
|
-
}) : /*#__PURE__*/_jsx(FlatList, {
|
|
380
|
-
data: events,
|
|
381
|
-
keyExtractor: event => event.id,
|
|
382
|
-
style: styles.fill,
|
|
383
|
-
contentContainerStyle: [styles.eventList, {
|
|
384
|
-
paddingBottom: insets.bottom
|
|
385
|
-
}],
|
|
386
|
-
keyboardShouldPersistTaps: "handled",
|
|
387
|
-
initialNumToRender: 15,
|
|
388
|
-
ListHeaderComponent: filter ? /*#__PURE__*/_jsxs(Text, {
|
|
389
|
-
style: styles.resultCount,
|
|
390
|
-
children: [events.length, " of ", count, " events"]
|
|
391
|
-
}) : null,
|
|
392
|
-
ListFooterComponent: snapshot.evicted > 0 ? /*#__PURE__*/_jsxs(Text, {
|
|
393
|
-
style: styles.footnote,
|
|
394
|
-
children: [snapshot.evicted, " older records removed by the history limit."]
|
|
395
|
-
}) : null,
|
|
396
|
-
ListEmptyComponent: /*#__PURE__*/_jsx(ToolEmptyState, {
|
|
397
|
-
otto: filter ? "sad" : recording ? "listening" : "paused",
|
|
398
|
-
title: filter ? "No matching events" : recording ? "Waiting for notifications" : "Capture is stopped",
|
|
399
|
-
message: filter ? "Try another title, test ID, or payload value." : recording ? "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."
|
|
400
|
-
}),
|
|
401
|
-
renderItem: ({
|
|
402
|
-
item: event
|
|
403
|
-
}) => /*#__PURE__*/_jsx(EventRow, {
|
|
404
|
-
event: event,
|
|
405
|
-
onPress: () => setSelectedId(event.id)
|
|
406
|
-
})
|
|
407
|
-
})]
|
|
408
|
-
}), tab === "tokens" && /*#__PURE__*/_jsxs(ScrollView, {
|
|
409
|
-
style: styles.fill,
|
|
410
|
-
contentContainerStyle: [styles.content, {
|
|
411
|
-
paddingBottom: insets.bottom
|
|
412
|
-
}],
|
|
413
|
-
keyboardShouldPersistTaps: "handled",
|
|
414
|
-
children: [/*#__PURE__*/_jsxs(View, {
|
|
415
|
-
children: [/*#__PURE__*/_jsx(Action, {
|
|
416
|
-
label: "Back to settings",
|
|
417
|
-
onPress: () => changeTab("setup")
|
|
418
|
-
}), /*#__PURE__*/_jsx(NightSectionLabel, {
|
|
419
|
-
children: "Registration"
|
|
420
|
-
}), /*#__PURE__*/_jsxs(NightCard, {
|
|
421
|
-
glass: true,
|
|
422
|
-
padded: true,
|
|
423
|
-
children: [/*#__PURE__*/_jsx(Text, {
|
|
424
|
-
style: styles.bodyText,
|
|
425
|
-
children: "Register a token to test delivery through your push provider."
|
|
426
|
-
}), /*#__PURE__*/_jsxs(View, {
|
|
427
|
-
style: styles.actionRow,
|
|
428
|
-
children: [/*#__PURE__*/_jsx(Action, {
|
|
429
|
-
label: "Register device token",
|
|
430
|
-
onPress: () => {
|
|
431
|
-
void act("refreshToken", {
|
|
432
|
-
type: "device"
|
|
433
|
-
});
|
|
434
|
-
},
|
|
435
|
-
disabled: busy,
|
|
436
|
-
primary: true
|
|
437
|
-
}), /*#__PURE__*/_jsx(Action, {
|
|
438
|
-
label: "Register Expo token",
|
|
439
|
-
onPress: () => {
|
|
440
|
-
void act("refreshToken", {
|
|
441
|
-
type: "expo"
|
|
442
|
-
});
|
|
443
|
-
},
|
|
444
|
-
disabled: busy || !snapshot.capabilities.includes("expo-token")
|
|
445
|
-
})]
|
|
446
|
-
})]
|
|
447
|
-
}), /*#__PURE__*/_jsx(Text, {
|
|
448
|
-
style: styles.footnote,
|
|
449
|
-
children: "Registration runs only when you or your app request it. Simulator sends work without a token."
|
|
450
|
-
})]
|
|
451
|
-
}), snapshot.tokens.length === 0 ? /*#__PURE__*/_jsx(ToolEmptyState, {
|
|
452
|
-
otto: "listening",
|
|
453
|
-
title: "No tokens observed",
|
|
454
|
-
message: "Register a device token above, or let your app register one."
|
|
455
|
-
}) : snapshot.tokens.map((token, i) => /*#__PURE__*/_jsxs(View, {
|
|
456
|
-
children: [/*#__PURE__*/_jsx(NightSectionLabel, {
|
|
457
|
-
children: token.type.toUpperCase() + " token"
|
|
458
|
-
}), /*#__PURE__*/_jsxs(NightCard, {
|
|
459
|
-
glass: true,
|
|
460
|
-
padded: true,
|
|
461
|
-
children: [/*#__PURE__*/_jsxs(View, {
|
|
462
|
-
style: styles.actionRow,
|
|
463
|
-
children: [/*#__PURE__*/_jsx(NightBadge, {
|
|
464
|
-
label: token.type,
|
|
465
|
-
tone: "accent"
|
|
466
|
-
}), token.environment && /*#__PURE__*/_jsx(Text, {
|
|
467
|
-
style: styles.caption,
|
|
468
|
-
children: token.environment
|
|
469
|
-
})]
|
|
470
|
-
}), /*#__PURE__*/_jsx(Text, {
|
|
471
|
-
selectable: true,
|
|
472
|
-
style: styles.token,
|
|
473
|
-
children: token.value
|
|
474
|
-
}), token.projectId && /*#__PURE__*/_jsxs(Text, {
|
|
475
|
-
selectable: true,
|
|
476
|
-
style: styles.caption,
|
|
477
|
-
children: ["Project: ", token.projectId]
|
|
478
|
-
}), /*#__PURE__*/_jsxs(Text, {
|
|
479
|
-
style: styles.caption,
|
|
480
|
-
children: ["Observed ", new Date(token.observedAt).toLocaleString()]
|
|
481
|
-
}), /*#__PURE__*/_jsx(View, {
|
|
482
|
-
style: styles.actionRow,
|
|
483
|
-
children: /*#__PURE__*/_jsx(Action, {
|
|
484
|
-
label: "Copy " + token.type.toUpperCase() + " token",
|
|
485
|
-
onPress: () => {
|
|
486
|
-
void copy(token.value);
|
|
487
|
-
},
|
|
488
|
-
icon: /*#__PURE__*/_jsx(Copy, {
|
|
489
|
-
size: 14,
|
|
490
|
-
color: night.color.accent
|
|
491
|
-
})
|
|
492
|
-
})
|
|
493
|
-
})]
|
|
494
|
-
})]
|
|
495
|
-
}, token.type + "-" + i))]
|
|
496
|
-
}), tab === "setup" && /*#__PURE__*/_jsxs(ScrollView, {
|
|
497
|
-
style: styles.fill,
|
|
498
|
-
contentContainerStyle: [styles.content, {
|
|
499
|
-
paddingBottom: insets.bottom
|
|
500
|
-
}],
|
|
501
|
-
keyboardShouldPersistTaps: "handled",
|
|
502
|
-
children: [/*#__PURE__*/_jsxs(View, {
|
|
503
|
-
children: [/*#__PURE__*/_jsx(Action, {
|
|
504
|
-
label: "Device tokens",
|
|
505
|
-
onPress: () => changeTab("tokens")
|
|
506
|
-
}), /*#__PURE__*/_jsx(NightSectionLabel, {
|
|
507
|
-
children: "Capture session"
|
|
508
|
-
}), /*#__PURE__*/_jsxs(NightCard, {
|
|
509
|
-
glass: true,
|
|
510
|
-
padded: true,
|
|
511
|
-
children: [/*#__PURE__*/_jsxs(View, {
|
|
512
|
-
style: styles.actionRow,
|
|
513
|
-
children: [/*#__PURE__*/_jsx(NightBadge, {
|
|
514
|
-
label: recording ? "Recording" : "Stopped",
|
|
515
|
-
tone: recording ? "accent" : "neutral"
|
|
516
|
-
}), /*#__PURE__*/_jsx(Text, {
|
|
517
|
-
style: styles.caption,
|
|
518
|
-
children: recording ? "Until " + new Date(expiresAt).toLocaleTimeString() : "Ready when you are"
|
|
519
|
-
})]
|
|
520
|
-
}), /*#__PURE__*/_jsxs(View, {
|
|
521
|
-
style: styles.actionRow,
|
|
522
|
-
children: [/*#__PURE__*/_jsx(Action, {
|
|
523
|
-
label: "Arm capture for 30 minutes",
|
|
524
|
-
onPress: arm,
|
|
525
|
-
disabled: busy,
|
|
526
|
-
primary: true
|
|
527
|
-
}), /*#__PURE__*/_jsx(Action, {
|
|
528
|
-
label: "Stop capture",
|
|
529
|
-
onPress: stop,
|
|
530
|
-
disabled: busy || !recording
|
|
531
|
-
})]
|
|
532
|
-
})]
|
|
533
|
-
}), /*#__PURE__*/_jsx(Text, {
|
|
534
|
-
style: styles.footnote,
|
|
535
|
-
children: snapshot.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."
|
|
536
|
-
})]
|
|
537
|
-
}), /*#__PURE__*/_jsxs(View, {
|
|
538
|
-
children: [/*#__PURE__*/_jsx(NightSectionLabel, {
|
|
539
|
-
children: "Connected app"
|
|
540
|
-
}), /*#__PURE__*/_jsx(NightCard, {
|
|
541
|
-
glass: true,
|
|
542
|
-
children: /*#__PURE__*/_jsxs(NightRows, {
|
|
543
|
-
children: [/*#__PURE__*/_jsx(Field, {
|
|
544
|
-
label: "App",
|
|
545
|
-
value: snapshot.appId ?? "Not supplied"
|
|
546
|
-
}), /*#__PURE__*/_jsx(Field, {
|
|
547
|
-
label: "Provider",
|
|
548
|
-
value: [snapshot.provider, snapshot.providerVersion].filter(Boolean).join(" ")
|
|
549
|
-
}), /*#__PURE__*/_jsx(Field, {
|
|
550
|
-
label: "Platform",
|
|
551
|
-
value: snapshot.platform
|
|
552
|
-
})]
|
|
553
|
-
})
|
|
554
|
-
})]
|
|
555
|
-
}), /*#__PURE__*/_jsxs(View, {
|
|
556
|
-
children: [/*#__PURE__*/_jsx(NightSectionLabel, {
|
|
557
|
-
children: "Permissions"
|
|
558
|
-
}), /*#__PURE__*/_jsx(View, {
|
|
559
|
-
style: styles.sectionActions,
|
|
560
|
-
children: /*#__PURE__*/_jsx(Action, {
|
|
561
|
-
label: "Refresh permissions",
|
|
562
|
-
disabled: busy,
|
|
563
|
-
onPress: () => {
|
|
564
|
-
void act("getPermissions");
|
|
565
|
-
}
|
|
566
|
-
})
|
|
567
|
-
}), /*#__PURE__*/_jsx(JsonCard, {
|
|
568
|
-
title: "Permission settings",
|
|
569
|
-
value: snapshot.permissions
|
|
570
|
-
})]
|
|
571
|
-
}), /*#__PURE__*/_jsxs(View, {
|
|
572
|
-
children: [/*#__PURE__*/_jsx(NightSectionLabel, {
|
|
573
|
-
children: "System tray"
|
|
574
|
-
}), /*#__PURE__*/_jsx(View, {
|
|
575
|
-
style: styles.sectionActions,
|
|
576
|
-
children: /*#__PURE__*/_jsx(Action, {
|
|
577
|
-
label: "Inspect system tray",
|
|
578
|
-
disabled: busy || !snapshot.capabilities.includes("presented"),
|
|
579
|
-
onPress: () => {
|
|
580
|
-
void act("listPresented");
|
|
581
|
-
}
|
|
582
|
-
})
|
|
583
|
-
}), /*#__PURE__*/_jsx(JsonCard, {
|
|
584
|
-
title: "Currently presented",
|
|
585
|
-
value: snapshot.presented
|
|
586
|
-
}), /*#__PURE__*/_jsx(Text, {
|
|
587
|
-
style: styles.footnote,
|
|
588
|
-
children: "Notifications currently in the system tray. Captured history is in Activity."
|
|
589
|
-
})]
|
|
590
|
-
}), /*#__PURE__*/_jsxs(View, {
|
|
591
|
-
children: [/*#__PURE__*/_jsx(NightSectionLabel, {
|
|
592
|
-
children: "Capabilities"
|
|
593
|
-
}), /*#__PURE__*/_jsx(NightCard, {
|
|
594
|
-
glass: true,
|
|
595
|
-
padded: true,
|
|
596
|
-
children: /*#__PURE__*/_jsx(View, {
|
|
597
|
-
style: styles.actionRow,
|
|
598
|
-
children: snapshot.capabilities.map(capability => /*#__PURE__*/_jsx(NightBadge, {
|
|
599
|
-
label: capability
|
|
600
|
-
}, capability))
|
|
601
|
-
})
|
|
602
|
-
})]
|
|
603
|
-
})]
|
|
604
|
-
})]
|
|
605
|
-
})]
|
|
606
|
-
});
|
|
607
|
-
return /*#__PURE__*/_jsx(_Fragment, {
|
|
608
|
-
children: renderShell ? renderShell({
|
|
609
|
-
header,
|
|
610
|
-
body
|
|
611
|
-
}) : /*#__PURE__*/_jsxs(View, {
|
|
612
|
-
style: styles.root,
|
|
613
|
-
children: [/*#__PURE__*/_jsx(View, {
|
|
614
|
-
style: styles.inlineHeader,
|
|
615
|
-
children: header
|
|
616
|
-
}), body]
|
|
617
|
-
})
|
|
618
|
-
});
|
|
619
|
-
}
|
|
620
|
-
function EventRow({
|
|
621
|
-
event,
|
|
622
|
-
onPress
|
|
623
|
-
}) {
|
|
624
|
-
const tone = eventTone(event.kind);
|
|
625
|
-
const color = tone === "danger" ? night.color.danger : tone === "warning" ? night.color.warning : tone === "accent" ? night.color.accent : night.color.textSecondary;
|
|
626
|
-
return /*#__PURE__*/_jsxs(Pressable, {
|
|
627
|
-
accessibilityRole: "button",
|
|
628
|
-
accessibilityLabel: (labels[event.kind] ?? event.kind) + ": " + (event.title ?? event.testId ?? event.notificationId ?? "notification"),
|
|
629
|
-
onPress: onPress,
|
|
630
|
-
style: ({
|
|
631
|
-
pressed
|
|
632
|
-
}) => [styles.event, pressed && styles.pressed],
|
|
633
|
-
children: [/*#__PURE__*/_jsxs(View, {
|
|
634
|
-
style: styles.eventTop,
|
|
635
|
-
children: [/*#__PURE__*/_jsxs(View, {
|
|
636
|
-
style: styles.eventKind,
|
|
637
|
-
children: [/*#__PURE__*/_jsx(NotificationsIcon, {
|
|
638
|
-
size: 13,
|
|
639
|
-
color: color
|
|
640
|
-
}), /*#__PURE__*/_jsx(Text, {
|
|
641
|
-
numberOfLines: 1,
|
|
642
|
-
style: [styles.eventLabel, {
|
|
643
|
-
color
|
|
644
|
-
}],
|
|
645
|
-
children: labels[event.kind] ?? event.kind
|
|
646
|
-
})]
|
|
647
|
-
}), /*#__PURE__*/_jsx(Text, {
|
|
648
|
-
style: styles.timestamp,
|
|
649
|
-
children: new Date(event.capturedAt).toLocaleTimeString()
|
|
650
|
-
})]
|
|
651
|
-
}), /*#__PURE__*/_jsxs(View, {
|
|
652
|
-
style: styles.eventSubject,
|
|
653
|
-
children: [/*#__PURE__*/_jsx(Text, {
|
|
654
|
-
numberOfLines: 1,
|
|
655
|
-
style: styles.eventTitle,
|
|
656
|
-
children: event.title ?? event.testId ?? event.notificationId ?? "Notification event"
|
|
657
|
-
}), /*#__PURE__*/_jsx(ChevronRight, {
|
|
658
|
-
size: 14,
|
|
659
|
-
color: night.color.textTertiary
|
|
660
|
-
})]
|
|
661
|
-
}), /*#__PURE__*/_jsxs(Text, {
|
|
662
|
-
numberOfLines: 1,
|
|
663
|
-
style: styles.eventMeta,
|
|
664
|
-
children: [event.observedAppState, event.truncated ? " · Truncated" : ""]
|
|
665
|
-
})]
|
|
666
|
-
});
|
|
667
|
-
}
|
|
668
|
-
//# sourceMappingURL=NotificationToolView.js.map
|
|
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":""]})]})}
|