@bbearai/react-native 0.1.0 → 0.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +4 -4
- package/dist/index.d.mts +9 -1
- package/dist/index.d.ts +9 -1
- package/dist/index.js +53 -37
- package/dist/index.mjs +58 -42
- package/package.json +8 -2
package/README.md
CHANGED
|
@@ -1,19 +1,19 @@
|
|
|
1
|
-
# @
|
|
1
|
+
# @bbearai/react-native
|
|
2
2
|
|
|
3
3
|
BugBear QA widget for React Native mobile apps.
|
|
4
4
|
|
|
5
5
|
## Installation
|
|
6
6
|
|
|
7
7
|
```bash
|
|
8
|
-
npm install @
|
|
8
|
+
npm install @bbearai/react-native @bbearai/core
|
|
9
9
|
# or
|
|
10
|
-
yarn add @
|
|
10
|
+
yarn add @bbearai/react-native @bbearai/core
|
|
11
11
|
```
|
|
12
12
|
|
|
13
13
|
## Quick Start
|
|
14
14
|
|
|
15
15
|
```tsx
|
|
16
|
-
import { BugBearProvider, BugBearWidget } from '@
|
|
16
|
+
import { BugBearProvider, BugBearWidget } from '@bbearai/react-native';
|
|
17
17
|
|
|
18
18
|
function App() {
|
|
19
19
|
return (
|
package/dist/index.d.mts
CHANGED
|
@@ -27,6 +27,8 @@ interface BugBearContextValue {
|
|
|
27
27
|
sendMessage: (threadId: string, content: string) => Promise<boolean>;
|
|
28
28
|
/** Mark a thread as read */
|
|
29
29
|
markAsRead: (threadId: string) => Promise<void>;
|
|
30
|
+
/** Re-check tester status (call after auth state changes) */
|
|
31
|
+
refreshTesterStatus: () => Promise<void>;
|
|
30
32
|
}
|
|
31
33
|
declare function useBugBear(): BugBearContextValue;
|
|
32
34
|
interface BugBearProviderProps {
|
|
@@ -34,8 +36,14 @@ interface BugBearProviderProps {
|
|
|
34
36
|
children: ReactNode;
|
|
35
37
|
/** App version string */
|
|
36
38
|
appVersion?: string;
|
|
39
|
+
/**
|
|
40
|
+
* Set to false to delay initialization until auth is ready.
|
|
41
|
+
* When enabled changes from false to true, BugBear will initialize.
|
|
42
|
+
* @default true
|
|
43
|
+
*/
|
|
44
|
+
enabled?: boolean;
|
|
37
45
|
}
|
|
38
|
-
declare function BugBearProvider({ config, children, appVersion }: BugBearProviderProps): React.JSX.Element;
|
|
46
|
+
declare function BugBearProvider({ config, children, appVersion, enabled }: BugBearProviderProps): React.JSX.Element;
|
|
39
47
|
|
|
40
48
|
interface BugBearButtonProps {
|
|
41
49
|
/** Get current app context */
|
package/dist/index.d.ts
CHANGED
|
@@ -27,6 +27,8 @@ interface BugBearContextValue {
|
|
|
27
27
|
sendMessage: (threadId: string, content: string) => Promise<boolean>;
|
|
28
28
|
/** Mark a thread as read */
|
|
29
29
|
markAsRead: (threadId: string) => Promise<void>;
|
|
30
|
+
/** Re-check tester status (call after auth state changes) */
|
|
31
|
+
refreshTesterStatus: () => Promise<void>;
|
|
30
32
|
}
|
|
31
33
|
declare function useBugBear(): BugBearContextValue;
|
|
32
34
|
interface BugBearProviderProps {
|
|
@@ -34,8 +36,14 @@ interface BugBearProviderProps {
|
|
|
34
36
|
children: ReactNode;
|
|
35
37
|
/** App version string */
|
|
36
38
|
appVersion?: string;
|
|
39
|
+
/**
|
|
40
|
+
* Set to false to delay initialization until auth is ready.
|
|
41
|
+
* When enabled changes from false to true, BugBear will initialize.
|
|
42
|
+
* @default true
|
|
43
|
+
*/
|
|
44
|
+
enabled?: boolean;
|
|
37
45
|
}
|
|
38
|
-
declare function BugBearProvider({ config, children, appVersion }: BugBearProviderProps): React.JSX.Element;
|
|
46
|
+
declare function BugBearProvider({ config, children, appVersion, enabled }: BugBearProviderProps): React.JSX.Element;
|
|
39
47
|
|
|
40
48
|
interface BugBearButtonProps {
|
|
41
49
|
/** Get current app context */
|
package/dist/index.js
CHANGED
|
@@ -60,12 +60,14 @@ var BugBearContext = (0, import_react.createContext)({
|
|
|
60
60
|
getThreadMessages: async () => [],
|
|
61
61
|
sendMessage: async () => false,
|
|
62
62
|
markAsRead: async () => {
|
|
63
|
+
},
|
|
64
|
+
refreshTesterStatus: async () => {
|
|
63
65
|
}
|
|
64
66
|
});
|
|
65
67
|
function useBugBear() {
|
|
66
68
|
return (0, import_react.useContext)(BugBearContext);
|
|
67
69
|
}
|
|
68
|
-
function BugBearProvider({ config, children, appVersion }) {
|
|
70
|
+
function BugBearProvider({ config, children, appVersion, enabled = true }) {
|
|
69
71
|
const [client] = (0, import_react.useState)(() => (0, import_core.createBugBear)(config));
|
|
70
72
|
const [isTester, setIsTester] = (0, import_react.useState)(false);
|
|
71
73
|
const [isQAEnabled, setIsQAEnabled] = (0, import_react.useState)(false);
|
|
@@ -74,7 +76,9 @@ function BugBearProvider({ config, children, appVersion }) {
|
|
|
74
76
|
const [isLoading, setIsLoading] = (0, import_react.useState)(true);
|
|
75
77
|
const [threads, setThreads] = (0, import_react.useState)([]);
|
|
76
78
|
const [unreadCount, setUnreadCount] = (0, import_react.useState)(0);
|
|
77
|
-
const
|
|
79
|
+
const [initCount, setInitCount] = (0, import_react.useState)(0);
|
|
80
|
+
const hasInitialized = (0, import_react.useRef)(false);
|
|
81
|
+
const getDeviceInfo = (0, import_react.useCallback)(() => {
|
|
78
82
|
const { width, height } = import_react_native.Dimensions.get("window");
|
|
79
83
|
return {
|
|
80
84
|
platform: import_react_native.Platform.OS,
|
|
@@ -82,56 +86,67 @@ function BugBearProvider({ config, children, appVersion }) {
|
|
|
82
86
|
appVersion,
|
|
83
87
|
screenSize: { width, height }
|
|
84
88
|
};
|
|
85
|
-
};
|
|
86
|
-
const refreshAssignments = async () => {
|
|
89
|
+
}, [appVersion]);
|
|
90
|
+
const refreshAssignments = (0, import_react.useCallback)(async () => {
|
|
87
91
|
const newAssignments = await client.getAssignedTests();
|
|
88
92
|
setAssignments(newAssignments);
|
|
89
|
-
};
|
|
90
|
-
const refreshThreads = async () => {
|
|
93
|
+
}, [client]);
|
|
94
|
+
const refreshThreads = (0, import_react.useCallback)(async () => {
|
|
91
95
|
const newThreads = await client.getThreadsForTester();
|
|
92
96
|
setThreads(newThreads);
|
|
93
97
|
const totalUnread = newThreads.reduce((sum, t) => sum + t.unreadCount, 0);
|
|
94
98
|
setUnreadCount(totalUnread);
|
|
95
|
-
};
|
|
96
|
-
const getThreadMessages = async (threadId) => {
|
|
99
|
+
}, [client]);
|
|
100
|
+
const getThreadMessages = (0, import_react.useCallback)(async (threadId) => {
|
|
97
101
|
return client.getThreadMessages(threadId);
|
|
98
|
-
};
|
|
99
|
-
const sendMessage = async (threadId, content) => {
|
|
102
|
+
}, [client]);
|
|
103
|
+
const sendMessage = (0, import_react.useCallback)(async (threadId, content) => {
|
|
100
104
|
const success = await client.sendMessage(threadId, content);
|
|
101
105
|
if (success) {
|
|
102
106
|
await refreshThreads();
|
|
103
107
|
}
|
|
104
108
|
return success;
|
|
105
|
-
};
|
|
106
|
-
const markAsRead = async (threadId) => {
|
|
109
|
+
}, [client, refreshThreads]);
|
|
110
|
+
const markAsRead = (0, import_react.useCallback)(async (threadId) => {
|
|
107
111
|
await client.markThreadAsRead(threadId);
|
|
108
112
|
await refreshThreads();
|
|
109
|
-
};
|
|
110
|
-
(0, import_react.
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
113
|
+
}, [client, refreshThreads]);
|
|
114
|
+
const initializeBugBear = (0, import_react.useCallback)(async () => {
|
|
115
|
+
setIsLoading(true);
|
|
116
|
+
try {
|
|
117
|
+
const [qaEnabled, info] = await Promise.all([
|
|
118
|
+
client.isQAEnabled(),
|
|
119
|
+
client.getTesterInfo()
|
|
120
|
+
]);
|
|
121
|
+
setIsQAEnabled(qaEnabled);
|
|
122
|
+
setTesterInfo(info);
|
|
123
|
+
setIsTester(!!info);
|
|
124
|
+
if (info && qaEnabled) {
|
|
125
|
+
await Promise.all([
|
|
126
|
+
refreshAssignments(),
|
|
127
|
+
refreshThreads()
|
|
117
128
|
]);
|
|
118
|
-
setIsQAEnabled(qaEnabled);
|
|
119
|
-
setTesterInfo(info);
|
|
120
|
-
setIsTester(!!info);
|
|
121
|
-
if (info && qaEnabled) {
|
|
122
|
-
await Promise.all([
|
|
123
|
-
refreshAssignments(),
|
|
124
|
-
refreshThreads()
|
|
125
|
-
]);
|
|
126
|
-
}
|
|
127
|
-
} catch (err) {
|
|
128
|
-
console.error("BugBear: Init error", err);
|
|
129
|
-
} finally {
|
|
130
|
-
setIsLoading(false);
|
|
131
129
|
}
|
|
132
|
-
}
|
|
133
|
-
|
|
134
|
-
|
|
130
|
+
} catch (err) {
|
|
131
|
+
console.error("BugBear: Init error", err);
|
|
132
|
+
} finally {
|
|
133
|
+
setIsLoading(false);
|
|
134
|
+
}
|
|
135
|
+
}, [client, refreshAssignments, refreshThreads]);
|
|
136
|
+
const refreshTesterStatus = (0, import_react.useCallback)(async () => {
|
|
137
|
+
await initializeBugBear();
|
|
138
|
+
}, [initializeBugBear]);
|
|
139
|
+
(0, import_react.useEffect)(() => {
|
|
140
|
+
if (enabled && !hasInitialized.current) {
|
|
141
|
+
hasInitialized.current = true;
|
|
142
|
+
initializeBugBear();
|
|
143
|
+
}
|
|
144
|
+
}, [enabled, initializeBugBear]);
|
|
145
|
+
(0, import_react.useEffect)(() => {
|
|
146
|
+
if (initCount > 0) {
|
|
147
|
+
initializeBugBear();
|
|
148
|
+
}
|
|
149
|
+
}, [initCount, initializeBugBear]);
|
|
135
150
|
const currentAssignment = assignments.find(
|
|
136
151
|
(a) => a.status === "in_progress"
|
|
137
152
|
) || assignments[0] || null;
|
|
@@ -156,7 +171,8 @@ function BugBearProvider({ config, children, appVersion }) {
|
|
|
156
171
|
refreshThreads,
|
|
157
172
|
getThreadMessages,
|
|
158
173
|
sendMessage,
|
|
159
|
-
markAsRead
|
|
174
|
+
markAsRead,
|
|
175
|
+
refreshTesterStatus
|
|
160
176
|
}
|
|
161
177
|
},
|
|
162
178
|
children
|
package/dist/index.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// src/BugBearProvider.tsx
|
|
2
|
-
import React, { createContext, useContext, useEffect, useState } from "react";
|
|
2
|
+
import React, { createContext, useContext, useEffect, useState, useCallback, useRef } from "react";
|
|
3
3
|
import {
|
|
4
4
|
createBugBear
|
|
5
5
|
} from "@bbearai/core";
|
|
@@ -24,12 +24,14 @@ var BugBearContext = createContext({
|
|
|
24
24
|
getThreadMessages: async () => [],
|
|
25
25
|
sendMessage: async () => false,
|
|
26
26
|
markAsRead: async () => {
|
|
27
|
+
},
|
|
28
|
+
refreshTesterStatus: async () => {
|
|
27
29
|
}
|
|
28
30
|
});
|
|
29
31
|
function useBugBear() {
|
|
30
32
|
return useContext(BugBearContext);
|
|
31
33
|
}
|
|
32
|
-
function BugBearProvider({ config, children, appVersion }) {
|
|
34
|
+
function BugBearProvider({ config, children, appVersion, enabled = true }) {
|
|
33
35
|
const [client] = useState(() => createBugBear(config));
|
|
34
36
|
const [isTester, setIsTester] = useState(false);
|
|
35
37
|
const [isQAEnabled, setIsQAEnabled] = useState(false);
|
|
@@ -38,7 +40,9 @@ function BugBearProvider({ config, children, appVersion }) {
|
|
|
38
40
|
const [isLoading, setIsLoading] = useState(true);
|
|
39
41
|
const [threads, setThreads] = useState([]);
|
|
40
42
|
const [unreadCount, setUnreadCount] = useState(0);
|
|
41
|
-
const
|
|
43
|
+
const [initCount, setInitCount] = useState(0);
|
|
44
|
+
const hasInitialized = useRef(false);
|
|
45
|
+
const getDeviceInfo = useCallback(() => {
|
|
42
46
|
const { width, height } = Dimensions.get("window");
|
|
43
47
|
return {
|
|
44
48
|
platform: Platform.OS,
|
|
@@ -46,56 +50,67 @@ function BugBearProvider({ config, children, appVersion }) {
|
|
|
46
50
|
appVersion,
|
|
47
51
|
screenSize: { width, height }
|
|
48
52
|
};
|
|
49
|
-
};
|
|
50
|
-
const refreshAssignments = async () => {
|
|
53
|
+
}, [appVersion]);
|
|
54
|
+
const refreshAssignments = useCallback(async () => {
|
|
51
55
|
const newAssignments = await client.getAssignedTests();
|
|
52
56
|
setAssignments(newAssignments);
|
|
53
|
-
};
|
|
54
|
-
const refreshThreads = async () => {
|
|
57
|
+
}, [client]);
|
|
58
|
+
const refreshThreads = useCallback(async () => {
|
|
55
59
|
const newThreads = await client.getThreadsForTester();
|
|
56
60
|
setThreads(newThreads);
|
|
57
61
|
const totalUnread = newThreads.reduce((sum, t) => sum + t.unreadCount, 0);
|
|
58
62
|
setUnreadCount(totalUnread);
|
|
59
|
-
};
|
|
60
|
-
const getThreadMessages = async (threadId) => {
|
|
63
|
+
}, [client]);
|
|
64
|
+
const getThreadMessages = useCallback(async (threadId) => {
|
|
61
65
|
return client.getThreadMessages(threadId);
|
|
62
|
-
};
|
|
63
|
-
const sendMessage = async (threadId, content) => {
|
|
66
|
+
}, [client]);
|
|
67
|
+
const sendMessage = useCallback(async (threadId, content) => {
|
|
64
68
|
const success = await client.sendMessage(threadId, content);
|
|
65
69
|
if (success) {
|
|
66
70
|
await refreshThreads();
|
|
67
71
|
}
|
|
68
72
|
return success;
|
|
69
|
-
};
|
|
70
|
-
const markAsRead = async (threadId) => {
|
|
73
|
+
}, [client, refreshThreads]);
|
|
74
|
+
const markAsRead = useCallback(async (threadId) => {
|
|
71
75
|
await client.markThreadAsRead(threadId);
|
|
72
76
|
await refreshThreads();
|
|
73
|
-
};
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
77
|
+
}, [client, refreshThreads]);
|
|
78
|
+
const initializeBugBear = useCallback(async () => {
|
|
79
|
+
setIsLoading(true);
|
|
80
|
+
try {
|
|
81
|
+
const [qaEnabled, info] = await Promise.all([
|
|
82
|
+
client.isQAEnabled(),
|
|
83
|
+
client.getTesterInfo()
|
|
84
|
+
]);
|
|
85
|
+
setIsQAEnabled(qaEnabled);
|
|
86
|
+
setTesterInfo(info);
|
|
87
|
+
setIsTester(!!info);
|
|
88
|
+
if (info && qaEnabled) {
|
|
89
|
+
await Promise.all([
|
|
90
|
+
refreshAssignments(),
|
|
91
|
+
refreshThreads()
|
|
81
92
|
]);
|
|
82
|
-
setIsQAEnabled(qaEnabled);
|
|
83
|
-
setTesterInfo(info);
|
|
84
|
-
setIsTester(!!info);
|
|
85
|
-
if (info && qaEnabled) {
|
|
86
|
-
await Promise.all([
|
|
87
|
-
refreshAssignments(),
|
|
88
|
-
refreshThreads()
|
|
89
|
-
]);
|
|
90
|
-
}
|
|
91
|
-
} catch (err) {
|
|
92
|
-
console.error("BugBear: Init error", err);
|
|
93
|
-
} finally {
|
|
94
|
-
setIsLoading(false);
|
|
95
93
|
}
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
|
|
94
|
+
} catch (err) {
|
|
95
|
+
console.error("BugBear: Init error", err);
|
|
96
|
+
} finally {
|
|
97
|
+
setIsLoading(false);
|
|
98
|
+
}
|
|
99
|
+
}, [client, refreshAssignments, refreshThreads]);
|
|
100
|
+
const refreshTesterStatus = useCallback(async () => {
|
|
101
|
+
await initializeBugBear();
|
|
102
|
+
}, [initializeBugBear]);
|
|
103
|
+
useEffect(() => {
|
|
104
|
+
if (enabled && !hasInitialized.current) {
|
|
105
|
+
hasInitialized.current = true;
|
|
106
|
+
initializeBugBear();
|
|
107
|
+
}
|
|
108
|
+
}, [enabled, initializeBugBear]);
|
|
109
|
+
useEffect(() => {
|
|
110
|
+
if (initCount > 0) {
|
|
111
|
+
initializeBugBear();
|
|
112
|
+
}
|
|
113
|
+
}, [initCount, initializeBugBear]);
|
|
99
114
|
const currentAssignment = assignments.find(
|
|
100
115
|
(a) => a.status === "in_progress"
|
|
101
116
|
) || assignments[0] || null;
|
|
@@ -120,7 +135,8 @@ function BugBearProvider({ config, children, appVersion }) {
|
|
|
120
135
|
refreshThreads,
|
|
121
136
|
getThreadMessages,
|
|
122
137
|
sendMessage,
|
|
123
|
-
markAsRead
|
|
138
|
+
markAsRead,
|
|
139
|
+
refreshTesterStatus
|
|
124
140
|
}
|
|
125
141
|
},
|
|
126
142
|
children
|
|
@@ -128,7 +144,7 @@ function BugBearProvider({ config, children, appVersion }) {
|
|
|
128
144
|
}
|
|
129
145
|
|
|
130
146
|
// src/BugBearButton.tsx
|
|
131
|
-
import React2, { useState as useState2, useEffect as useEffect2, useRef } from "react";
|
|
147
|
+
import React2, { useState as useState2, useEffect as useEffect2, useRef as useRef2 } from "react";
|
|
132
148
|
import {
|
|
133
149
|
View,
|
|
134
150
|
Text,
|
|
@@ -197,9 +213,9 @@ function BugBearButton({
|
|
|
197
213
|
return { x, y };
|
|
198
214
|
};
|
|
199
215
|
const initialPos = getInitialPosition();
|
|
200
|
-
const pan =
|
|
201
|
-
const isDragging =
|
|
202
|
-
const panResponder =
|
|
216
|
+
const pan = useRef2(new Animated.ValueXY(initialPos)).current;
|
|
217
|
+
const isDragging = useRef2(false);
|
|
218
|
+
const panResponder = useRef2(
|
|
203
219
|
PanResponder.create({
|
|
204
220
|
onStartShouldSetPanResponder: () => draggable,
|
|
205
221
|
onMoveShouldSetPanResponder: (_, gestureState) => {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bbearai/react-native",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.2",
|
|
4
4
|
"description": "BugBear React Native components for mobile apps",
|
|
5
5
|
"main": "./dist/index.js",
|
|
6
6
|
"module": "./dist/index.mjs",
|
|
@@ -25,7 +25,13 @@
|
|
|
25
25
|
"directory": "packages/react-native"
|
|
26
26
|
},
|
|
27
27
|
"license": "MIT",
|
|
28
|
-
"keywords": [
|
|
28
|
+
"keywords": [
|
|
29
|
+
"bugbear",
|
|
30
|
+
"qa",
|
|
31
|
+
"testing",
|
|
32
|
+
"react-native",
|
|
33
|
+
"mobile"
|
|
34
|
+
],
|
|
29
35
|
"scripts": {
|
|
30
36
|
"build": "tsup src/index.tsx --format cjs,esm --dts --external react --external react-native",
|
|
31
37
|
"dev": "tsup src/index.tsx --format cjs,esm --dts --external react --external react-native --watch",
|