react-native-iinstall 0.2.12 → 0.2.14

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.
@@ -0,0 +1,349 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.unregisterPushToken = exports.registerPushToken = exports.IInstallWrapper = exports.IInstall = void 0;
37
+ const react_1 = __importStar(require("react"));
38
+ const react_native_1 = require("react-native");
39
+ const ShakeDetector_1 = require("./ShakeDetector");
40
+ const FeedbackModal_1 = require("./FeedbackModal");
41
+ const pushRegistration_1 = require("./pushRegistration");
42
+ const nativeModules_1 = require("./nativeModules");
43
+ const IInstall = ({ apiKey, apiEndpoint = 'https://iinstall.app', children, enabled = true, showFloatingButtonOnEmulator = true, floatingButtonLabel = 'Report Issue', pushToken, autoRegisterPushToken = true, projectId, onPushTokenRegisterError, }) => {
44
+ const [modalVisible, setModalVisible] = (0, react_1.useState)(false);
45
+ const [screenshotUri, setScreenshotUri] = (0, react_1.useState)(null);
46
+ const [videoUri, setVideoUri] = (0, react_1.useState)(null);
47
+ const [isRecording, setIsRecording] = (0, react_1.useState)(false);
48
+ const [isEmulator, setIsEmulator] = (0, react_1.useState)(false);
49
+ const shakeDetectorRef = (0, react_1.useRef)(null);
50
+ const lastRegisteredPushTokenRef = (0, react_1.useRef)(null);
51
+ // Refs for stable access in shake callback
52
+ const isRecordingRef = (0, react_1.useRef)(isRecording);
53
+ const modalVisibleRef = (0, react_1.useRef)(modalVisible);
54
+ (0, react_1.useEffect)(() => {
55
+ isRecordingRef.current = isRecording;
56
+ modalVisibleRef.current = modalVisible;
57
+ }, [isRecording, modalVisible]);
58
+ (0, react_1.useEffect)(() => {
59
+ let mounted = true;
60
+ (0, nativeModules_1.isEmulatorDevice)()
61
+ .then((value) => {
62
+ if (mounted) {
63
+ setIsEmulator(value);
64
+ }
65
+ })
66
+ .catch(() => {
67
+ if (mounted) {
68
+ setIsEmulator(false);
69
+ }
70
+ });
71
+ return () => {
72
+ mounted = false;
73
+ };
74
+ }, []);
75
+ const handleShake = async () => {
76
+ if (modalVisibleRef.current || isRecordingRef.current)
77
+ return;
78
+ try {
79
+ // Capture screenshot
80
+ const uri = await (0, nativeModules_1.captureScreenImage)({
81
+ format: 'png',
82
+ quality: 0.8,
83
+ });
84
+ setScreenshotUri(uri);
85
+ setModalVisible(true);
86
+ }
87
+ catch (error) {
88
+ console.error('IInstall: Failed to capture screenshot', error);
89
+ setScreenshotUri(null);
90
+ setModalVisible(true);
91
+ }
92
+ };
93
+ // Keep handleShake stable for the detector
94
+ const handleShakeCallback = (0, react_1.useRef)(handleShake);
95
+ (0, react_1.useEffect)(() => {
96
+ handleShakeCallback.current = handleShake;
97
+ });
98
+ (0, react_1.useEffect)(() => {
99
+ if (!enabled || isEmulator)
100
+ return;
101
+ // Use a wrapper to call the current handleShake
102
+ shakeDetectorRef.current = new ShakeDetector_1.ShakeDetector(() => handleShakeCallback.current());
103
+ shakeDetectorRef.current.start();
104
+ return () => {
105
+ shakeDetectorRef.current?.stop();
106
+ };
107
+ }, [enabled, isEmulator]);
108
+ (0, react_1.useEffect)(() => {
109
+ if (!enabled || !autoRegisterPushToken || !pushToken)
110
+ return;
111
+ if (lastRegisteredPushTokenRef.current === pushToken)
112
+ return;
113
+ let cancelled = false;
114
+ const syncPushToken = async () => {
115
+ const deviceUdid = await (0, nativeModules_1.getDeviceUniqueId)();
116
+ const result = await (0, pushRegistration_1.registerPushToken)({
117
+ token: pushToken,
118
+ apiKey,
119
+ apiEndpoint,
120
+ deviceUdid,
121
+ projectId,
122
+ });
123
+ if (cancelled)
124
+ return;
125
+ if (result.success) {
126
+ lastRegisteredPushTokenRef.current = pushToken;
127
+ }
128
+ else {
129
+ const message = result.error || 'Failed to register push token';
130
+ console.warn('IInstall: push token registration failed', message);
131
+ if (onPushTokenRegisterError) {
132
+ onPushTokenRegisterError(message);
133
+ }
134
+ }
135
+ };
136
+ syncPushToken().catch((error) => {
137
+ if (cancelled)
138
+ return;
139
+ const message = error instanceof Error ? error.message : 'Failed to register push token';
140
+ console.warn('IInstall: push token registration failed', message);
141
+ if (onPushTokenRegisterError) {
142
+ onPushTokenRegisterError(message);
143
+ }
144
+ });
145
+ return () => {
146
+ cancelled = true;
147
+ };
148
+ }, [
149
+ enabled,
150
+ autoRegisterPushToken,
151
+ pushToken,
152
+ apiKey,
153
+ apiEndpoint,
154
+ projectId,
155
+ onPushTokenRegisterError,
156
+ ]);
157
+ const handleFloatingButtonPress = async () => {
158
+ await handleShakeCallback.current();
159
+ };
160
+ const shouldShowFloatingButton = enabled &&
161
+ isEmulator &&
162
+ showFloatingButtonOnEmulator &&
163
+ !modalVisible &&
164
+ !isRecording;
165
+ const screenRecordingAvailable = (0, nativeModules_1.hasScreenRecordingSupport)();
166
+ const normalizeVideoUri = (value) => {
167
+ if (react_native_1.Platform.OS === 'ios' && value.startsWith('/')) {
168
+ return `file://${value}`;
169
+ }
170
+ return value;
171
+ };
172
+ const resolveRecordedVideoUri = (recordResult) => {
173
+ if (!recordResult || typeof recordResult !== 'object') {
174
+ return null;
175
+ }
176
+ const candidate = recordResult;
177
+ const values = [
178
+ candidate?.result?.outputURL,
179
+ candidate?.result?.outputUrl,
180
+ candidate?.result?.outputUri,
181
+ candidate?.result?.outputFileURL,
182
+ candidate?.result?.outputFileUri,
183
+ candidate?.result?.uri,
184
+ candidate?.result?.path,
185
+ candidate?.result?.filePath,
186
+ candidate?.result?.fileURL,
187
+ candidate?.outputURL,
188
+ candidate?.outputUrl,
189
+ candidate?.outputUri,
190
+ candidate?.outputFileURL,
191
+ candidate?.outputFileUri,
192
+ candidate?.uri,
193
+ candidate?.path,
194
+ candidate?.filePath,
195
+ candidate?.fileURL,
196
+ ];
197
+ for (const value of values) {
198
+ if (typeof value === 'string' && value.trim().length > 0) {
199
+ return normalizeVideoUri(value);
200
+ }
201
+ }
202
+ for (const value of Object.values(candidate)) {
203
+ if (typeof value === 'string' && value.trim().length > 0) {
204
+ return normalizeVideoUri(value);
205
+ }
206
+ }
207
+ return null;
208
+ };
209
+ const handleStartRecording = async () => {
210
+ if (!screenRecordingAvailable) {
211
+ console.warn('IInstall: Screen recording unavailable. Install react-native-record-screen in your app and rebuild.');
212
+ setModalVisible(true);
213
+ return;
214
+ }
215
+ setModalVisible(false);
216
+ setIsRecording(true);
217
+ try {
218
+ await (0, nativeModules_1.startScreenRecording)({ mic: true });
219
+ }
220
+ catch (e) {
221
+ console.error('Failed to start recording', e);
222
+ setIsRecording(false);
223
+ setModalVisible(true); // Re-open if failed
224
+ }
225
+ };
226
+ const handleStopRecording = async () => {
227
+ try {
228
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
229
+ const res = await (0, nativeModules_1.stopScreenRecording)();
230
+ if (res) {
231
+ const nextVideoUri = resolveRecordedVideoUri(res);
232
+ if (nextVideoUri) {
233
+ setVideoUri(nextVideoUri);
234
+ }
235
+ else {
236
+ console.warn('IInstall: Screen recording finished, but no video URI was returned.', res);
237
+ }
238
+ }
239
+ else {
240
+ console.warn('IInstall: stopRecording returned empty result');
241
+ }
242
+ }
243
+ catch (e) {
244
+ console.error('Failed to stop recording', e);
245
+ }
246
+ finally {
247
+ setIsRecording(false);
248
+ setModalVisible(true);
249
+ }
250
+ };
251
+ return (<react_native_1.View style={react_native_1.StyleSheet.absoluteFill} pointerEvents="box-none">
252
+ <react_native_1.View style={react_native_1.StyleSheet.absoluteFill}>
253
+ {children}
254
+ </react_native_1.View>
255
+
256
+ {shouldShowFloatingButton && (<react_native_1.View style={styles.floatingButtonContainer} pointerEvents="box-none">
257
+ <react_native_1.TouchableOpacity accessibilityRole="button" accessibilityLabel="Open feedback menu" onPress={handleFloatingButtonPress} style={styles.floatingButton}>
258
+ <react_native_1.Text style={styles.floatingButtonText}>{floatingButtonLabel}</react_native_1.Text>
259
+ </react_native_1.TouchableOpacity>
260
+ </react_native_1.View>)}
261
+
262
+ {isRecording && (<react_native_1.SafeAreaView style={styles.recordingOverlay} pointerEvents="box-none">
263
+ <react_native_1.View style={styles.recordingContainer}>
264
+ <react_native_1.View style={styles.recordingDot}/>
265
+ <react_native_1.Text style={styles.recordingText}>Recording Screen...</react_native_1.Text>
266
+ <react_native_1.TouchableOpacity onPress={handleStopRecording} style={styles.stopButton}>
267
+ <react_native_1.Text style={styles.stopButtonText}>Stop</react_native_1.Text>
268
+ </react_native_1.TouchableOpacity>
269
+ </react_native_1.View>
270
+ </react_native_1.SafeAreaView>)}
271
+
272
+ <FeedbackModal_1.FeedbackModal visible={modalVisible} onClose={() => {
273
+ setModalVisible(false);
274
+ setVideoUri(null); // Clear video on close
275
+ setScreenshotUri(null);
276
+ }} screenshotUri={screenshotUri} videoUri={videoUri} onStartRecording={screenRecordingAvailable ? handleStartRecording : undefined} apiKey={apiKey} apiEndpoint={apiEndpoint}/>
277
+ </react_native_1.View>);
278
+ };
279
+ exports.IInstall = IInstall;
280
+ const styles = react_native_1.StyleSheet.create({
281
+ floatingButtonContainer: {
282
+ position: 'absolute',
283
+ right: 16,
284
+ bottom: 28,
285
+ zIndex: 9998,
286
+ elevation: 20,
287
+ },
288
+ floatingButton: {
289
+ backgroundColor: '#0f172a',
290
+ borderColor: '#2563eb',
291
+ borderWidth: 1,
292
+ borderRadius: 24,
293
+ paddingHorizontal: 14,
294
+ paddingVertical: 10,
295
+ shadowColor: '#000',
296
+ shadowOffset: { width: 0, height: 2 },
297
+ shadowOpacity: 0.35,
298
+ shadowRadius: 4,
299
+ },
300
+ floatingButtonText: {
301
+ color: '#FFF',
302
+ fontWeight: '700',
303
+ fontSize: 13,
304
+ },
305
+ recordingOverlay: {
306
+ position: 'absolute',
307
+ top: 50,
308
+ alignSelf: 'center',
309
+ zIndex: 9999,
310
+ },
311
+ recordingContainer: {
312
+ flexDirection: 'row',
313
+ alignItems: 'center',
314
+ backgroundColor: 'rgba(0,0,0,0.8)',
315
+ padding: 10,
316
+ borderRadius: 30,
317
+ paddingHorizontal: 20,
318
+ },
319
+ recordingDot: {
320
+ width: 10,
321
+ height: 10,
322
+ borderRadius: 5,
323
+ backgroundColor: '#ff4444',
324
+ marginRight: 10,
325
+ },
326
+ recordingText: {
327
+ color: '#FFF',
328
+ fontWeight: '600',
329
+ marginRight: 15,
330
+ },
331
+ stopButton: {
332
+ backgroundColor: '#FFF',
333
+ paddingVertical: 5,
334
+ paddingHorizontal: 15,
335
+ borderRadius: 15,
336
+ },
337
+ stopButtonText: {
338
+ color: '#000',
339
+ fontWeight: 'bold',
340
+ fontSize: 12,
341
+ }
342
+ });
343
+ exports.default = exports.IInstall;
344
+ // Export the wrapper component for simulator/emulator support
345
+ var IInstallWrapper_1 = require("./IInstallWrapper");
346
+ Object.defineProperty(exports, "IInstallWrapper", { enumerable: true, get: function () { return IInstallWrapper_1.IInstallWrapper; } });
347
+ var pushRegistration_2 = require("./pushRegistration");
348
+ Object.defineProperty(exports, "registerPushToken", { enumerable: true, get: function () { return pushRegistration_2.registerPushToken; } });
349
+ Object.defineProperty(exports, "unregisterPushToken", { enumerable: true, get: function () { return pushRegistration_2.unregisterPushToken; } });
@@ -0,0 +1,37 @@
1
+ type CaptureScreenOptions = {
2
+ format?: 'png' | 'jpg' | 'webm' | 'raw';
3
+ quality?: number;
4
+ result?: 'tmpfile' | 'base64' | 'data-uri' | 'zip-base64';
5
+ };
6
+ type RecordBackEvent = {
7
+ currentPosition: number;
8
+ };
9
+ export type AudioRecorderPlayerLike = {
10
+ startRecorder: (uri?: string, audioSets?: Record<string, unknown>) => Promise<string>;
11
+ stopRecorder: () => Promise<string>;
12
+ addRecordBackListener: (callback: (recordingMeta: RecordBackEvent) => void) => void;
13
+ removeRecordBackListener: () => void;
14
+ mmssss: (milisecs: number) => string;
15
+ };
16
+ export type DeviceMetadata = {
17
+ device: string;
18
+ systemName: string;
19
+ systemVersion: string;
20
+ appVersion: string;
21
+ buildNumber: string;
22
+ brand: string;
23
+ isEmulator: boolean;
24
+ };
25
+ export declare function isEmulatorDevice(): Promise<boolean>;
26
+ export declare function getDeviceUniqueId(): Promise<string | undefined>;
27
+ export declare function getDeviceMetadata(): Promise<DeviceMetadata>;
28
+ export declare function hasScreenRecordingSupport(): boolean;
29
+ export declare function startScreenRecording(config?: {
30
+ mic?: boolean;
31
+ }): Promise<void>;
32
+ export declare function stopScreenRecording(): Promise<unknown>;
33
+ export declare function captureScreenImage(options?: CaptureScreenOptions): Promise<string>;
34
+ export declare function hasAudioRecordingSupport(): boolean;
35
+ export declare function createAudioRecorderPlayer(): AudioRecorderPlayerLike | null;
36
+ export declare function getAudioRecordingPreset(): Record<string, string | number>;
37
+ export {};
@@ -0,0 +1,231 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.isEmulatorDevice = isEmulatorDevice;
4
+ exports.getDeviceUniqueId = getDeviceUniqueId;
5
+ exports.getDeviceMetadata = getDeviceMetadata;
6
+ exports.hasScreenRecordingSupport = hasScreenRecordingSupport;
7
+ exports.startScreenRecording = startScreenRecording;
8
+ exports.stopScreenRecording = stopScreenRecording;
9
+ exports.captureScreenImage = captureScreenImage;
10
+ exports.hasAudioRecordingSupport = hasAudioRecordingSupport;
11
+ exports.createAudioRecorderPlayer = createAudioRecorderPlayer;
12
+ exports.getAudioRecordingPreset = getAudioRecordingPreset;
13
+ const react_native_1 = require("react-native");
14
+ const warnedKeys = new Set();
15
+ function warnOnce(key, message) {
16
+ if (warnedKeys.has(key)) {
17
+ return;
18
+ }
19
+ warnedKeys.add(key);
20
+ console.warn(message);
21
+ }
22
+ function getDefaultExport(moduleValue) {
23
+ if (!moduleValue) {
24
+ return null;
25
+ }
26
+ if (typeof moduleValue === 'object' && moduleValue !== null && 'default' in moduleValue) {
27
+ return moduleValue.default;
28
+ }
29
+ return moduleValue;
30
+ }
31
+ function loadRawModule(moduleName) {
32
+ try {
33
+ return require(moduleName);
34
+ }
35
+ catch (error) {
36
+ const reason = error instanceof Error ? error.message : String(error);
37
+ warnOnce(`missing:${moduleName}`, `[iInstall SDK] Missing native dependency "${moduleName}". Install it in your app root and rebuild. (${reason})`);
38
+ return null;
39
+ }
40
+ }
41
+ let cachedDeviceInfoModule;
42
+ let cachedCaptureScreen;
43
+ let cachedRecordScreenModule;
44
+ let cachedAudioModule;
45
+ function getDeviceInfoModule() {
46
+ if (cachedDeviceInfoModule !== undefined) {
47
+ return cachedDeviceInfoModule;
48
+ }
49
+ const required = loadRawModule('react-native-device-info');
50
+ cachedDeviceInfoModule = required ? getDefaultExport(required) : null;
51
+ return cachedDeviceInfoModule;
52
+ }
53
+ function getCaptureScreenFn() {
54
+ if (cachedCaptureScreen !== undefined) {
55
+ return cachedCaptureScreen;
56
+ }
57
+ const required = loadRawModule('react-native-view-shot');
58
+ cachedCaptureScreen = required?.captureScreen ?? null;
59
+ if (!cachedCaptureScreen) {
60
+ warnOnce('missing:react-native-view-shot:captureScreen', '[iInstall SDK] Screenshot capture unavailable: react-native-view-shot is not linked correctly.');
61
+ }
62
+ return cachedCaptureScreen;
63
+ }
64
+ function getRecordScreenModule() {
65
+ if (cachedRecordScreenModule !== undefined) {
66
+ return cachedRecordScreenModule;
67
+ }
68
+ const required = loadRawModule('react-native-record-screen');
69
+ cachedRecordScreenModule = required ? getDefaultExport(required) : null;
70
+ return cachedRecordScreenModule;
71
+ }
72
+ function getAudioRecorderModule() {
73
+ if (cachedAudioModule !== undefined) {
74
+ return cachedAudioModule;
75
+ }
76
+ cachedAudioModule = loadRawModule('react-native-audio-recorder-player');
77
+ return cachedAudioModule;
78
+ }
79
+ function fallbackString(value, defaultValue) {
80
+ if (!value || value.trim().length === 0) {
81
+ return defaultValue;
82
+ }
83
+ return value;
84
+ }
85
+ async function isEmulatorDevice() {
86
+ const moduleRef = getDeviceInfoModule();
87
+ if (!moduleRef?.isEmulator) {
88
+ return false;
89
+ }
90
+ try {
91
+ return await moduleRef.isEmulator();
92
+ }
93
+ catch {
94
+ return false;
95
+ }
96
+ }
97
+ async function getDeviceUniqueId() {
98
+ const moduleRef = getDeviceInfoModule();
99
+ if (!moduleRef?.getUniqueId) {
100
+ return undefined;
101
+ }
102
+ try {
103
+ const value = await moduleRef.getUniqueId();
104
+ return fallbackString(value, 'unknown');
105
+ }
106
+ catch {
107
+ return undefined;
108
+ }
109
+ }
110
+ async function getDeviceMetadata() {
111
+ const moduleRef = getDeviceInfoModule();
112
+ const systemName = react_native_1.Platform.OS === 'ios' ? 'iOS' : react_native_1.Platform.OS;
113
+ const systemVersion = String(react_native_1.Platform.Version ?? 'unknown');
114
+ const metadata = {
115
+ device: 'Unknown Device',
116
+ systemName,
117
+ systemVersion,
118
+ appVersion: 'unknown',
119
+ buildNumber: 'unknown',
120
+ brand: react_native_1.Platform.OS === 'ios' ? 'Apple' : 'Unknown',
121
+ isEmulator: false,
122
+ };
123
+ if (!moduleRef) {
124
+ return metadata;
125
+ }
126
+ try {
127
+ metadata.device = fallbackString(moduleRef.getModel?.(), metadata.device);
128
+ }
129
+ catch {
130
+ // noop
131
+ }
132
+ try {
133
+ metadata.systemName = fallbackString(moduleRef.getSystemName?.(), metadata.systemName);
134
+ }
135
+ catch {
136
+ // noop
137
+ }
138
+ try {
139
+ metadata.systemVersion = fallbackString(moduleRef.getSystemVersion?.(), metadata.systemVersion);
140
+ }
141
+ catch {
142
+ // noop
143
+ }
144
+ try {
145
+ metadata.appVersion = fallbackString(moduleRef.getVersion?.(), metadata.appVersion);
146
+ }
147
+ catch {
148
+ // noop
149
+ }
150
+ try {
151
+ metadata.buildNumber = fallbackString(moduleRef.getBuildNumber?.(), metadata.buildNumber);
152
+ }
153
+ catch {
154
+ // noop
155
+ }
156
+ try {
157
+ metadata.brand = fallbackString(moduleRef.getBrand?.(), metadata.brand);
158
+ }
159
+ catch {
160
+ // noop
161
+ }
162
+ try {
163
+ metadata.isEmulator = moduleRef.isEmulator ? await moduleRef.isEmulator() : false;
164
+ }
165
+ catch {
166
+ metadata.isEmulator = false;
167
+ }
168
+ return metadata;
169
+ }
170
+ function hasScreenRecordingSupport() {
171
+ const moduleRef = getRecordScreenModule();
172
+ return Boolean(moduleRef?.startRecording && moduleRef?.stopRecording);
173
+ }
174
+ async function startScreenRecording(config = { mic: true }) {
175
+ const moduleRef = getRecordScreenModule();
176
+ if (!moduleRef?.startRecording) {
177
+ throw new Error('Screen recording dependency missing. Install react-native-record-screen and rebuild the app.');
178
+ }
179
+ await moduleRef.startRecording(config);
180
+ }
181
+ async function stopScreenRecording() {
182
+ const moduleRef = getRecordScreenModule();
183
+ if (!moduleRef?.stopRecording) {
184
+ throw new Error('Screen recording dependency missing. Install react-native-record-screen and rebuild the app.');
185
+ }
186
+ return moduleRef.stopRecording();
187
+ }
188
+ async function captureScreenImage(options) {
189
+ const captureScreen = getCaptureScreenFn();
190
+ if (!captureScreen) {
191
+ throw new Error('Screenshot dependency missing. Install react-native-view-shot and rebuild the app.');
192
+ }
193
+ return captureScreen(options);
194
+ }
195
+ function hasAudioRecordingSupport() {
196
+ const moduleRef = getAudioRecorderModule();
197
+ const recorderCtor = moduleRef?.default;
198
+ return typeof recorderCtor === 'function';
199
+ }
200
+ function createAudioRecorderPlayer() {
201
+ const moduleRef = getAudioRecorderModule();
202
+ const recorderCtor = moduleRef?.default;
203
+ if (typeof recorderCtor !== 'function') {
204
+ warnOnce('missing:react-native-audio-recorder-player:ctor', '[iInstall SDK] Audio recording unavailable: react-native-audio-recorder-player is not linked correctly.');
205
+ return null;
206
+ }
207
+ try {
208
+ return new recorderCtor();
209
+ }
210
+ catch (error) {
211
+ const reason = error instanceof Error ? error.message : String(error);
212
+ warnOnce('missing:react-native-audio-recorder-player:new', `[iInstall SDK] Failed to initialize audio recorder. (${reason})`);
213
+ return null;
214
+ }
215
+ }
216
+ function getAudioRecordingPreset() {
217
+ const moduleRef = getAudioRecorderModule();
218
+ return {
219
+ AVFormatIDKeyIOS: moduleRef?.AVEncodingOption?.aac ?? 'aac',
220
+ AVEncoderAudioQualityKeyIOS: moduleRef?.AVEncoderAudioQualityIOSType?.high ?? 96,
221
+ AVSampleRateKeyIOS: 44100,
222
+ AVNumberOfChannelsKeyIOS: 1,
223
+ AVEncoderBitRateKeyIOS: 128000,
224
+ AudioEncoderAndroid: moduleRef?.AudioEncoderAndroidType?.AAC ?? 3,
225
+ AudioSourceAndroid: moduleRef?.AudioSourceAndroidType?.MIC ?? 1,
226
+ OutputFormatAndroid: moduleRef?.OutputFormatAndroidType?.MPEG_4 ?? 2,
227
+ AudioEncodingBitRateAndroid: 128000,
228
+ AudioSamplingRateAndroid: 44100,
229
+ AudioChannelsAndroid: 1,
230
+ };
231
+ }
@@ -0,0 +1,22 @@
1
+ export type PushPlatform = 'IOS' | 'ANDROID';
2
+ export interface RegisterPushTokenParams {
3
+ token: string;
4
+ apiKey: string;
5
+ apiEndpoint?: string;
6
+ deviceUdid?: string;
7
+ projectId?: string;
8
+ platform?: PushPlatform;
9
+ }
10
+ export interface UnregisterPushTokenParams {
11
+ token: string;
12
+ apiKey: string;
13
+ apiEndpoint?: string;
14
+ }
15
+ export interface PushRegistrationResult {
16
+ success: boolean;
17
+ data?: any;
18
+ error?: string;
19
+ status: number;
20
+ }
21
+ export declare function registerPushToken({ token, apiKey, apiEndpoint, deviceUdid, projectId, platform, }: RegisterPushTokenParams): Promise<PushRegistrationResult>;
22
+ export declare function unregisterPushToken({ token, apiKey, apiEndpoint, }: UnregisterPushTokenParams): Promise<PushRegistrationResult>;