react-native-iinstall 0.2.14 → 0.2.16

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.
@@ -46,16 +46,20 @@ npm install react-native-iinstall
46
46
  yarn add react-native-iinstall
47
47
  ```
48
48
 
49
- **Note**: The SDK automatically includes necessary dependencies like `react-native-sensors` and `react-native-view-shot`.
49
+ Install required native peer dependencies at app root:
50
50
 
51
- ### Updating to Latest Version (v0.2.13)
51
+ ```bash
52
+ npm install react-native-sensors react-native-view-shot react-native-device-info react-native-audio-recorder-player react-native-record-screen
53
+ ```
54
+
55
+ ### Updating to Latest Version (v0.2.14)
52
56
 
53
57
  If you're using an older version, update to get the latest audio/video improvements:
54
58
 
55
59
  ```bash
56
- npm install react-native-iinstall@0.2.13
60
+ npm install react-native-iinstall@0.2.14
57
61
  # OR
58
- yarn add react-native-iinstall@0.2.13
62
+ yarn add react-native-iinstall@0.2.14
59
63
  ```
60
64
 
61
65
  **Key improvements in v0.2.7:**
@@ -136,7 +140,7 @@ import { registerPushToken, unregisterPushToken } from 'react-native-iinstall';
136
140
 
137
141
  ---
138
142
 
139
- ## 6. Audio & Video Feedback (v0.2.7+)
143
+ ## 6. Audio & Video Feedback (v0.2.14+)
140
144
 
141
145
  The SDK now supports **Audio Feedback** (Voice Notes) and **Screen Recording** with enhanced compatibility and reliability.
142
146
 
@@ -151,6 +155,7 @@ The SDK now supports **Audio Feedback** (Voice Notes) and **Screen Recording** w
151
155
  These features require native modules. If you haven't already, run:
152
156
 
153
157
  ```bash
158
+ npm install react-native-sensors react-native-view-shot react-native-device-info react-native-audio-recorder-player react-native-record-screen
154
159
  cd ios && pod install
155
160
  ```
156
161
 
@@ -219,7 +224,7 @@ A: The app will work fine, but features like "Shake to Report" and automatic ses
219
224
  A: Ensure your project icon URL is valid. If the image fails to load, the dashboard now automatically falls back to showing the project's initial letter on a styled background.
220
225
 
221
226
  **Q: Audio feedback shows 0:00 duration in dashboard?**
222
- A: Update to SDK v0.2.7+ which fixes audio codec compatibility. Audio files are now encoded as AAC instead of ALAC for better browser compatibility.
227
+ A: Update to SDK v0.2.14+ which includes the audio codec compatibility fixes. Audio files are encoded as AAC for browser playback.
223
228
 
224
229
  **Q: Screen recording sometimes doesn't capture?**
225
- A: Update to SDK v0.2.7+ which includes enhanced URI extraction and better error handling for screen recordings across different devices.
230
+ A: Update to SDK v0.2.14+ which includes enhanced URI extraction and better error handling for screen recordings across different devices.
package/README.md CHANGED
@@ -176,7 +176,7 @@ await unregisterPushToken({
176
176
  - **Shake not working?** Test on real device or enable "Shake" in simulator
177
177
  - **Network errors?** Verify `apiEndpoint` is base URL only (not `/api/sdk/issue`)
178
178
  - **Permissions denied?** Check platform-specific setup in integration guide
179
- - **Audio issues?** Ensure SDK v0.2.7+ for AAC codec support
179
+ - **Audio issues?** Ensure SDK v0.2.14+ and rebuild after native peer install
180
180
  - **Native module is null/undefined?** Reinstall peer deps in app root, run `cd ios && pod install`, then rebuild the app
181
181
 
182
182
  ### Getting Help
@@ -1,8 +1,8 @@
1
1
  {
2
- "version": "0.2.14",
2
+ "version": "0.2.16",
3
3
  "highlights": [
4
- "Auto push token registration support via IInstall pushToken prop",
5
- "Manual helpers: registerPushToken and unregisterPushToken",
6
- "Maintains audio/video feedback workflow and emulator floating button"
4
+ "Native modules now declared as peer dependencies for reliable app-root autolinking",
5
+ "SDK now lazy-loads native modules and degrades gracefully instead of hard crashing",
6
+ "Updated integration docs with explicit peer dependency install commands"
7
7
  ]
8
8
  }
@@ -32,15 +32,11 @@ var __importStar = (this && this.__importStar) || (function () {
32
32
  return result;
33
33
  };
34
34
  })();
35
- var __importDefault = (this && this.__importDefault) || function (mod) {
36
- return (mod && mod.__esModule) ? mod : { "default": mod };
37
- };
38
35
  Object.defineProperty(exports, "__esModule", { value: true });
39
36
  exports.FeedbackModal = void 0;
40
37
  const react_1 = __importStar(require("react"));
41
38
  const react_native_1 = require("react-native");
42
- const react_native_device_info_1 = __importDefault(require("react-native-device-info"));
43
- const react_native_audio_recorder_player_1 = __importStar(require("react-native-audio-recorder-player"));
39
+ const nativeModules_1 = require("./nativeModules");
44
40
  const FeedbackModal = ({ visible, onClose, screenshotUri, videoUri, onStartRecording, apiKey, apiEndpoint }) => {
45
41
  const [description, setDescription] = (0, react_1.useState)('');
46
42
  const [isSending, setIsSending] = (0, react_1.useState)(false);
@@ -48,16 +44,21 @@ const FeedbackModal = ({ visible, onClose, screenshotUri, videoUri, onStartRecor
48
44
  const [isRecordingAudio, setIsRecordingAudio] = (0, react_1.useState)(false);
49
45
  const [audioUri, setAudioUri] = (0, react_1.useState)(null);
50
46
  const [audioDuration, setAudioDuration] = (0, react_1.useState)('00:00');
51
- const audioRecorderPlayer = (0, react_1.useRef)(new react_native_audio_recorder_player_1.default()).current;
47
+ const audioRecordingAvailable = (0, nativeModules_1.hasAudioRecordingSupport)();
48
+ const audioRecorderPlayer = (0, react_1.useRef)((0, nativeModules_1.createAudioRecorderPlayer)()).current;
52
49
  (0, react_1.useEffect)(() => {
53
50
  return () => {
54
51
  // Cleanup
55
- if (isRecordingAudio) {
56
- audioRecorderPlayer.stopRecorder();
52
+ if (isRecordingAudio && audioRecorderPlayer) {
53
+ audioRecorderPlayer.stopRecorder().catch(() => undefined);
57
54
  }
58
55
  };
59
- }, [isRecordingAudio]);
56
+ }, [audioRecorderPlayer, isRecordingAudio]);
60
57
  const onStartAudioRecord = async () => {
58
+ if (!audioRecorderPlayer || !audioRecordingAvailable) {
59
+ react_native_1.Alert.alert('Audio unavailable', 'Install react-native-audio-recorder-player in your app root, then rebuild the app.');
60
+ return;
61
+ }
61
62
  if (react_native_1.Platform.OS === 'android') {
62
63
  try {
63
64
  const grants = await react_native_1.PermissionsAndroid.requestMultiple([
@@ -77,20 +78,7 @@ const FeedbackModal = ({ visible, onClose, screenshotUri, videoUri, onStartRecor
77
78
  }
78
79
  }
79
80
  try {
80
- const audioSet = {
81
- AVFormatIDKeyIOS: react_native_audio_recorder_player_1.AVEncodingOption.aac,
82
- AVEncoderAudioQualityKeyIOS: react_native_audio_recorder_player_1.AVEncoderAudioQualityIOSType.high,
83
- AVSampleRateKeyIOS: 44100,
84
- AVNumberOfChannelsKeyIOS: 1,
85
- AVEncoderBitRateKeyIOS: 128000,
86
- AudioEncoderAndroid: react_native_audio_recorder_player_1.AudioEncoderAndroidType.AAC,
87
- AudioSourceAndroid: react_native_audio_recorder_player_1.AudioSourceAndroidType.MIC,
88
- OutputFormatAndroid: react_native_audio_recorder_player_1.OutputFormatAndroidType.MPEG_4,
89
- AudioEncodingBitRateAndroid: 128000,
90
- AudioSamplingRateAndroid: 44100,
91
- AudioChannelsAndroid: 1,
92
- };
93
- const result = await audioRecorderPlayer.startRecorder(undefined, audioSet);
81
+ const result = await audioRecorderPlayer.startRecorder(undefined, (0, nativeModules_1.getAudioRecordingPreset)());
94
82
  audioRecorderPlayer.addRecordBackListener((e) => {
95
83
  setAudioDuration(audioRecorderPlayer.mmssss(Math.floor(e.currentPosition)));
96
84
  return;
@@ -104,6 +92,9 @@ const FeedbackModal = ({ visible, onClose, screenshotUri, videoUri, onStartRecor
104
92
  }
105
93
  };
106
94
  const onStopAudioRecord = async () => {
95
+ if (!audioRecorderPlayer) {
96
+ return;
97
+ }
107
98
  try {
108
99
  const result = await audioRecorderPlayer.stopRecorder();
109
100
  audioRecorderPlayer.removeRecordBackListener();
@@ -120,7 +111,7 @@ const FeedbackModal = ({ visible, onClose, screenshotUri, videoUri, onStartRecor
120
111
  setAudioDuration('00:00');
121
112
  };
122
113
  const handleClose = async () => {
123
- if (isRecordingAudio) {
114
+ if (isRecordingAudio && audioRecorderPlayer) {
124
115
  try {
125
116
  await audioRecorderPlayer.stopRecorder();
126
117
  }
@@ -181,20 +172,13 @@ const FeedbackModal = ({ visible, onClose, screenshotUri, videoUri, onStartRecor
181
172
  });
182
173
  }
183
174
  // 4. Metadata
184
- const metadata = {
185
- device: react_native_device_info_1.default.getModel(),
186
- systemName: react_native_device_info_1.default.getSystemName(),
187
- systemVersion: react_native_device_info_1.default.getSystemVersion(),
188
- appVersion: react_native_device_info_1.default.getVersion(),
189
- buildNumber: react_native_device_info_1.default.getBuildNumber(),
190
- brand: react_native_device_info_1.default.getBrand(),
191
- isEmulator: await react_native_device_info_1.default.isEmulator(),
192
- };
175
+ const metadata = await (0, nativeModules_1.getDeviceMetadata)();
193
176
  formData.append('metadata', JSON.stringify(metadata));
194
177
  // 5. Other fields
195
178
  formData.append('description', description);
196
179
  formData.append('apiKey', apiKey);
197
- formData.append('udid', await react_native_device_info_1.default.getUniqueId());
180
+ const deviceUdid = await (0, nativeModules_1.getDeviceUniqueId)();
181
+ formData.append('udid', deviceUdid || 'unknown');
198
182
  // 6. Send
199
183
  const response = await fetch(`${apiEndpoint}/api/feedback`, {
200
184
  method: 'POST',
@@ -257,9 +241,20 @@ const FeedbackModal = ({ visible, onClose, screenshotUri, videoUri, onStartRecor
257
241
  {/* Media Actions Row */}
258
242
  <react_native_1.View style={styles.actionsRow}>
259
243
  {/* Audio Recorder */}
260
- <react_native_1.TouchableOpacity style={[styles.actionBtn, isRecordingAudio ? styles.recordingBtn : undefined, audioUri ? styles.hasAudioBtn : undefined]} onPress={isRecordingAudio ? onStopAudioRecord : onStartAudioRecord}>
244
+ <react_native_1.TouchableOpacity style={[
245
+ styles.actionBtn,
246
+ isRecordingAudio ? styles.recordingBtn : undefined,
247
+ audioUri ? styles.hasAudioBtn : undefined,
248
+ !audioRecordingAvailable ? styles.disabledActionBtn : undefined,
249
+ ]} onPress={isRecordingAudio ? onStopAudioRecord : onStartAudioRecord} disabled={!audioRecordingAvailable}>
261
250
  <react_native_1.Text style={[styles.actionBtnText, (isRecordingAudio || audioUri) ? { color: '#FFF' } : undefined]}>
262
- {isRecordingAudio ? `Stop (${audioDuration})` : audioUri ? 'Re-record Audio' : '🎙 Record Audio'}
251
+ {!audioRecordingAvailable
252
+ ? '🎙 Audio Unavailable'
253
+ : isRecordingAudio
254
+ ? `Stop (${audioDuration})`
255
+ : audioUri
256
+ ? 'Re-record Audio'
257
+ : '🎙 Record Audio'}
263
258
  </react_native_1.Text>
264
259
  </react_native_1.TouchableOpacity>
265
260
 
@@ -372,6 +367,9 @@ const styles = react_native_1.StyleSheet.create({
372
367
  hasAudioBtn: {
373
368
  backgroundColor: '#4CAF50',
374
369
  },
370
+ disabledActionBtn: {
371
+ opacity: 0.45,
372
+ },
375
373
  actionBtnText: {
376
374
  fontSize: 14,
377
375
  fontWeight: '600',
package/lib/index.js CHANGED
@@ -32,19 +32,14 @@ var __importStar = (this && this.__importStar) || (function () {
32
32
  return result;
33
33
  };
34
34
  })();
35
- var __importDefault = (this && this.__importDefault) || function (mod) {
36
- return (mod && mod.__esModule) ? mod : { "default": mod };
37
- };
38
35
  Object.defineProperty(exports, "__esModule", { value: true });
39
36
  exports.unregisterPushToken = exports.registerPushToken = exports.IInstallWrapper = exports.IInstall = void 0;
40
37
  const react_1 = __importStar(require("react"));
41
38
  const react_native_1 = require("react-native");
42
- const react_native_view_shot_1 = require("react-native-view-shot");
43
39
  const ShakeDetector_1 = require("./ShakeDetector");
44
40
  const FeedbackModal_1 = require("./FeedbackModal");
45
- const react_native_record_screen_1 = __importDefault(require("react-native-record-screen"));
46
- const react_native_device_info_1 = __importDefault(require("react-native-device-info"));
47
41
  const pushRegistration_1 = require("./pushRegistration");
42
+ const nativeModules_1 = require("./nativeModules");
48
43
  const IInstall = ({ apiKey, apiEndpoint = 'https://iinstall.app', children, enabled = true, showFloatingButtonOnEmulator = true, floatingButtonLabel = 'Report Issue', pushToken, autoRegisterPushToken = true, projectId, onPushTokenRegisterError, }) => {
49
44
  const [modalVisible, setModalVisible] = (0, react_1.useState)(false);
50
45
  const [screenshotUri, setScreenshotUri] = (0, react_1.useState)(null);
@@ -62,7 +57,7 @@ const IInstall = ({ apiKey, apiEndpoint = 'https://iinstall.app', children, enab
62
57
  }, [isRecording, modalVisible]);
63
58
  (0, react_1.useEffect)(() => {
64
59
  let mounted = true;
65
- react_native_device_info_1.default.isEmulator()
60
+ (0, nativeModules_1.isEmulatorDevice)()
66
61
  .then((value) => {
67
62
  if (mounted) {
68
63
  setIsEmulator(value);
@@ -82,7 +77,7 @@ const IInstall = ({ apiKey, apiEndpoint = 'https://iinstall.app', children, enab
82
77
  return;
83
78
  try {
84
79
  // Capture screenshot
85
- const uri = await (0, react_native_view_shot_1.captureScreen)({
80
+ const uri = await (0, nativeModules_1.captureScreenImage)({
86
81
  format: 'png',
87
82
  quality: 0.8,
88
83
  });
@@ -117,7 +112,7 @@ const IInstall = ({ apiKey, apiEndpoint = 'https://iinstall.app', children, enab
117
112
  return;
118
113
  let cancelled = false;
119
114
  const syncPushToken = async () => {
120
- const deviceUdid = await react_native_device_info_1.default.getUniqueId().catch(() => undefined);
115
+ const deviceUdid = await (0, nativeModules_1.getDeviceUniqueId)();
121
116
  const result = await (0, pushRegistration_1.registerPushToken)({
122
117
  token: pushToken,
123
118
  apiKey,
@@ -167,6 +162,7 @@ const IInstall = ({ apiKey, apiEndpoint = 'https://iinstall.app', children, enab
167
162
  showFloatingButtonOnEmulator &&
168
163
  !modalVisible &&
169
164
  !isRecording;
165
+ const screenRecordingAvailable = (0, nativeModules_1.hasScreenRecordingSupport)();
170
166
  const normalizeVideoUri = (value) => {
171
167
  if (react_native_1.Platform.OS === 'ios' && value.startsWith('/')) {
172
168
  return `file://${value}`;
@@ -211,10 +207,15 @@ const IInstall = ({ apiKey, apiEndpoint = 'https://iinstall.app', children, enab
211
207
  return null;
212
208
  };
213
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
+ }
214
215
  setModalVisible(false);
215
216
  setIsRecording(true);
216
217
  try {
217
- await react_native_record_screen_1.default.startRecording({ mic: true });
218
+ await (0, nativeModules_1.startScreenRecording)({ mic: true });
218
219
  }
219
220
  catch (e) {
220
221
  console.error('Failed to start recording', e);
@@ -225,7 +226,7 @@ const IInstall = ({ apiKey, apiEndpoint = 'https://iinstall.app', children, enab
225
226
  const handleStopRecording = async () => {
226
227
  try {
227
228
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
228
- const res = await react_native_record_screen_1.default.stopRecording();
229
+ const res = await (0, nativeModules_1.stopScreenRecording)();
229
230
  if (res) {
230
231
  const nextVideoUri = resolveRecordedVideoUri(res);
231
232
  if (nextVideoUri) {
@@ -272,7 +273,7 @@ const IInstall = ({ apiKey, apiEndpoint = 'https://iinstall.app', children, enab
272
273
  setModalVisible(false);
273
274
  setVideoUri(null); // Clear video on close
274
275
  setScreenshotUri(null);
275
- }} screenshotUri={screenshotUri} videoUri={videoUri} onStartRecording={handleStartRecording} apiKey={apiKey} apiEndpoint={apiEndpoint}/>
276
+ }} screenshotUri={screenshotUri} videoUri={videoUri} onStartRecording={screenRecordingAvailable ? handleStartRecording : undefined} apiKey={apiKey} apiEndpoint={apiEndpoint}/>
276
277
  </react_native_1.View>);
277
278
  };
278
279
  exports.IInstall = IInstall;
@@ -194,12 +194,12 @@ async function captureScreenImage(options) {
194
194
  }
195
195
  function hasAudioRecordingSupport() {
196
196
  const moduleRef = getAudioRecorderModule();
197
- const recorderCtor = moduleRef?.default;
197
+ const recorderCtor = typeof moduleRef === 'function' ? moduleRef : moduleRef?.default;
198
198
  return typeof recorderCtor === 'function';
199
199
  }
200
200
  function createAudioRecorderPlayer() {
201
201
  const moduleRef = getAudioRecorderModule();
202
- const recorderCtor = moduleRef?.default;
202
+ const recorderCtor = typeof moduleRef === 'function' ? moduleRef : moduleRef?.default;
203
203
  if (typeof recorderCtor !== 'function') {
204
204
  warnOnce('missing:react-native-audio-recorder-player:ctor', '[iInstall SDK] Audio recording unavailable: react-native-audio-recorder-player is not linked correctly.');
205
205
  return null;
@@ -215,15 +215,16 @@ function createAudioRecorderPlayer() {
215
215
  }
216
216
  function getAudioRecordingPreset() {
217
217
  const moduleRef = getAudioRecorderModule();
218
+ const namedExports = typeof moduleRef === 'object' && moduleRef !== null ? moduleRef : undefined;
218
219
  return {
219
- AVFormatIDKeyIOS: moduleRef?.AVEncodingOption?.aac ?? 'aac',
220
- AVEncoderAudioQualityKeyIOS: moduleRef?.AVEncoderAudioQualityIOSType?.high ?? 96,
220
+ AVFormatIDKeyIOS: namedExports?.AVEncodingOption?.aac ?? 'aac',
221
+ AVEncoderAudioQualityKeyIOS: namedExports?.AVEncoderAudioQualityIOSType?.high ?? 96,
221
222
  AVSampleRateKeyIOS: 44100,
222
223
  AVNumberOfChannelsKeyIOS: 1,
223
224
  AVEncoderBitRateKeyIOS: 128000,
224
- AudioEncoderAndroid: moduleRef?.AudioEncoderAndroidType?.AAC ?? 3,
225
- AudioSourceAndroid: moduleRef?.AudioSourceAndroidType?.MIC ?? 1,
226
- OutputFormatAndroid: moduleRef?.OutputFormatAndroidType?.MPEG_4 ?? 2,
225
+ AudioEncoderAndroid: namedExports?.AudioEncoderAndroidType?.AAC ?? 3,
226
+ AudioSourceAndroid: namedExports?.AudioSourceAndroidType?.MIC ?? 1,
227
+ OutputFormatAndroid: namedExports?.OutputFormatAndroidType?.MPEG_4 ?? 2,
227
228
  AudioEncodingBitRateAndroid: 128000,
228
229
  AudioSamplingRateAndroid: 44100,
229
230
  AudioChannelsAndroid: 1,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "react-native-iinstall",
3
- "version": "0.2.14",
3
+ "version": "0.2.16",
4
4
  "description": "🎯 IInstall React Native SDK - The ultimate beta testing & QA feedback tool. Shake-to-report with voice recordings, screen recordings, and screenshots. Zero-config setup with TypeScript support. Perfect for beta testing, QA teams, and user feedback collection.",
5
5
  "author": "TesterFlow Team",
6
6
  "license": "MIT",
@@ -39,7 +39,8 @@
39
39
  ],
40
40
  "scripts": {
41
41
  "prebuild": "npm run prepare:release",
42
- "build": "tsc",
42
+ "clean:build": "node -e \"require('fs').rmSync('lib',{ recursive: true, force: true })\"",
43
+ "build": "npm run clean:build && tsc",
43
44
  "sync:release-manifest": "node scripts/sync-release-manifest.mjs",
44
45
  "check:release-manifest": "node scripts/check-release-manifest.mjs",
45
46
  "prepare:release": "npm run sync:release-manifest && npm run check:release-manifest",
@@ -35,6 +35,8 @@ type AudioRecorderModule = {
35
35
  OutputFormatAndroidType?: { MPEG_4?: number };
36
36
  };
37
37
 
38
+ type AudioRecorderModuleValue = AudioRecorderModule | (new () => AudioRecorderPlayerLike);
39
+
38
40
  type RecordBackEvent = {
39
41
  currentPosition: number;
40
42
  };
@@ -93,7 +95,7 @@ function loadRawModule<T>(moduleName: string): T | null {
93
95
  let cachedDeviceInfoModule: DeviceInfoModule | null | undefined;
94
96
  let cachedCaptureScreen: ((options?: CaptureScreenOptions) => Promise<string>) | null | undefined;
95
97
  let cachedRecordScreenModule: RecordScreenModule | null | undefined;
96
- let cachedAudioModule: AudioRecorderModule | null | undefined;
98
+ let cachedAudioModule: AudioRecorderModuleValue | null | undefined;
97
99
 
98
100
  function getDeviceInfoModule(): DeviceInfoModule | null {
99
101
  if (cachedDeviceInfoModule !== undefined) {
@@ -128,11 +130,11 @@ function getRecordScreenModule(): RecordScreenModule | null {
128
130
  return cachedRecordScreenModule;
129
131
  }
130
132
 
131
- function getAudioRecorderModule(): AudioRecorderModule | null {
133
+ function getAudioRecorderModule(): AudioRecorderModuleValue | null {
132
134
  if (cachedAudioModule !== undefined) {
133
135
  return cachedAudioModule;
134
136
  }
135
- cachedAudioModule = loadRawModule<AudioRecorderModule>('react-native-audio-recorder-player');
137
+ cachedAudioModule = loadRawModule<AudioRecorderModuleValue>('react-native-audio-recorder-player');
136
138
  return cachedAudioModule;
137
139
  }
138
140
 
@@ -263,13 +265,15 @@ export async function captureScreenImage(options?: CaptureScreenOptions): Promis
263
265
 
264
266
  export function hasAudioRecordingSupport(): boolean {
265
267
  const moduleRef = getAudioRecorderModule();
266
- const recorderCtor = moduleRef?.default;
268
+ const recorderCtor =
269
+ typeof moduleRef === 'function' ? moduleRef : moduleRef?.default;
267
270
  return typeof recorderCtor === 'function';
268
271
  }
269
272
 
270
273
  export function createAudioRecorderPlayer(): AudioRecorderPlayerLike | null {
271
274
  const moduleRef = getAudioRecorderModule();
272
- const recorderCtor = moduleRef?.default;
275
+ const recorderCtor =
276
+ typeof moduleRef === 'function' ? moduleRef : moduleRef?.default;
273
277
  if (typeof recorderCtor !== 'function') {
274
278
  warnOnce(
275
279
  'missing:react-native-audio-recorder-player:ctor',
@@ -292,15 +296,16 @@ export function createAudioRecorderPlayer(): AudioRecorderPlayerLike | null {
292
296
 
293
297
  export function getAudioRecordingPreset(): Record<string, string | number> {
294
298
  const moduleRef = getAudioRecorderModule();
299
+ const namedExports = typeof moduleRef === 'object' && moduleRef !== null ? moduleRef : undefined;
295
300
  return {
296
- AVFormatIDKeyIOS: moduleRef?.AVEncodingOption?.aac ?? 'aac',
297
- AVEncoderAudioQualityKeyIOS: moduleRef?.AVEncoderAudioQualityIOSType?.high ?? 96,
301
+ AVFormatIDKeyIOS: namedExports?.AVEncodingOption?.aac ?? 'aac',
302
+ AVEncoderAudioQualityKeyIOS: namedExports?.AVEncoderAudioQualityIOSType?.high ?? 96,
298
303
  AVSampleRateKeyIOS: 44100,
299
304
  AVNumberOfChannelsKeyIOS: 1,
300
305
  AVEncoderBitRateKeyIOS: 128000,
301
- AudioEncoderAndroid: moduleRef?.AudioEncoderAndroidType?.AAC ?? 3,
302
- AudioSourceAndroid: moduleRef?.AudioSourceAndroidType?.MIC ?? 1,
303
- OutputFormatAndroid: moduleRef?.OutputFormatAndroidType?.MPEG_4 ?? 2,
306
+ AudioEncoderAndroid: namedExports?.AudioEncoderAndroidType?.AAC ?? 3,
307
+ AudioSourceAndroid: namedExports?.AudioSourceAndroidType?.MIC ?? 1,
308
+ OutputFormatAndroid: namedExports?.OutputFormatAndroidType?.MPEG_4 ?? 2,
304
309
  AudioEncodingBitRateAndroid: 128000,
305
310
  AudioSamplingRateAndroid: 44100,
306
311
  AudioChannelsAndroid: 1,
@@ -1,2 +0,0 @@
1
- #!/usr/bin/env node
2
- export {};
@@ -1,38 +0,0 @@
1
- #!/usr/bin/env node
2
- "use strict";
3
- import fs from 'node:fs';
4
- import path from 'node:path';
5
- const cwd = process.cwd();
6
- const packagePath = path.join(cwd, 'package.json');
7
- const manifestPath = path.join(cwd, 'RELEASE_MANIFEST.json');
8
- function readJson(filePath) {
9
- const raw = fs.readFileSync(filePath, 'utf8');
10
- return JSON.parse(raw);
11
- }
12
- try {
13
- if (!fs.existsSync(manifestPath)) {
14
- console.error('RELEASE_MANIFEST.json not found');
15
- process.exit(1);
16
- }
17
- const pkg = readJson(packagePath);
18
- const manifest = readJson(manifestPath);
19
- const packageVersion = String(pkg?.version || '').trim();
20
- const manifestVersion = String(manifest?.version || '').trim();
21
- if (!packageVersion) {
22
- console.error('SDK package version missing in package.json');
23
- process.exit(1);
24
- }
25
- if (!manifestVersion) {
26
- console.error('RELEASE_MANIFEST version missing');
27
- process.exit(1);
28
- }
29
- if (packageVersion !== manifestVersion) {
30
- console.error(`Release mismatch: package.json=${packageVersion}, RELEASE_MANIFEST.json=${manifestVersion}`);
31
- process.exit(1);
32
- }
33
- console.log(`Release manifest check OK: react-native-iinstall@${packageVersion}`);
34
- }
35
- catch (error) {
36
- console.error('Failed to verify RELEASE_MANIFEST:', error);
37
- process.exit(1);
38
- }
@@ -1,2 +0,0 @@
1
- #!/usr/bin/env node
2
- export {};
@@ -1,38 +0,0 @@
1
- #!/usr/bin/env node
2
- "use strict";
3
- import fs from 'node:fs';
4
- import path from 'node:path';
5
- const cwd = process.cwd();
6
- const packagePath = path.join(cwd, 'package.json');
7
- const manifestPath = path.join(cwd, 'RELEASE_MANIFEST.json');
8
- function readJson(filePath) {
9
- const raw = fs.readFileSync(filePath, 'utf8');
10
- return JSON.parse(raw);
11
- }
12
- function writeJson(filePath, value) {
13
- fs.writeFileSync(filePath, `${JSON.stringify(value, null, 2)}\n`, 'utf8');
14
- }
15
- try {
16
- const pkg = readJson(packagePath);
17
- const packageVersion = String(pkg?.version || '').trim();
18
- if (!packageVersion) {
19
- console.error('SDK package version missing in package.json');
20
- process.exit(1);
21
- }
22
- let manifest = {
23
- version: packageVersion,
24
- highlights: [],
25
- };
26
- if (fs.existsSync(manifestPath)) {
27
- manifest = {
28
- ...readJson(manifestPath),
29
- version: packageVersion,
30
- };
31
- }
32
- writeJson(manifestPath, manifest);
33
- console.log(`Synced RELEASE_MANIFEST -> react-native-iinstall@${packageVersion}`);
34
- }
35
- catch (error) {
36
- console.error('Failed to sync RELEASE_MANIFEST:', error);
37
- process.exit(1);
38
- }
@@ -1,12 +0,0 @@
1
- import React from 'react';
2
- interface FeedbackModalProps {
3
- visible: boolean;
4
- onClose: () => void;
5
- screenshotUri: string | null;
6
- videoUri?: string | null;
7
- onStartRecording?: () => void;
8
- apiKey: string;
9
- apiEndpoint: string;
10
- }
11
- export declare const FeedbackModal: React.FC<FeedbackModalProps>;
12
- export {};