nosnia-audio-recorder 0.1.1 → 0.3.0

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,263 @@
1
+ #import "NosniaAudioPlayer.h"
2
+ #import <AVFoundation/AVFoundation.h>
3
+ #import <React/RCTBridgeModule.h>
4
+ #import <React/RCTEventEmitter.h>
5
+
6
+ @interface NosniaAudioPlayer () <AVAudioPlayerDelegate>
7
+ @property (nonatomic, strong) AVAudioPlayer *audioPlayer;
8
+ @property (nonatomic, assign) BOOL isPlaying;
9
+ @property (nonatomic, strong) NSTimer *progressTimer;
10
+ @property (nonatomic, strong) NSString *currentFilePath;
11
+ @end
12
+
13
+ @implementation NosniaAudioPlayer {
14
+ AVAudioPlayer *_audioPlayer;
15
+ BOOL _isPlaying;
16
+ NSTimer *_progressTimer;
17
+ NSString *_currentFilePath;
18
+ BOOL _hasListeners;
19
+ }
20
+
21
+ RCT_EXPORT_MODULE(NosniaAudioPlayer)
22
+
23
+ - (instancetype)init {
24
+ self = [super init];
25
+ if (self) {
26
+ _isPlaying = NO;
27
+ _hasListeners = NO;
28
+ }
29
+ return self;
30
+ }
31
+
32
+ - (NSArray<NSString *> *)supportedEvents {
33
+ return @[@"onPlaybackProgress", @"onPlaybackComplete"];
34
+ }
35
+
36
+ - (void)startObserving {
37
+ _hasListeners = YES;
38
+ }
39
+
40
+ - (void)stopObserving {
41
+ _hasListeners = NO;
42
+ }
43
+
44
+ - (void)startProgressTimer {
45
+ if (_progressTimer) {
46
+ [_progressTimer invalidate];
47
+ }
48
+
49
+ _progressTimer = [NSTimer scheduledTimerWithTimeInterval:0.1
50
+ repeats:YES
51
+ block:^(NSTimer * _Nonnull timer) {
52
+ if (self->_hasListeners && self->_audioPlayer && self->_isPlaying) {
53
+ NSTimeInterval currentTime = self->_audioPlayer.currentTime;
54
+ NSTimeInterval duration = self->_audioPlayer.duration;
55
+ [self sendEventWithName:@"onPlaybackProgress"
56
+ body:@{
57
+ @"currentTime": @(currentTime * 1000),
58
+ @"duration": @(duration * 1000),
59
+ @"isPlaying": @(self->_audioPlayer.isPlaying)
60
+ }];
61
+ }
62
+ }];
63
+ }
64
+
65
+ - (void)stopProgressTimer {
66
+ if (_progressTimer) {
67
+ [_progressTimer invalidate];
68
+ _progressTimer = nil;
69
+ }
70
+ }
71
+
72
+ - (void)startPlaying:(NSDictionary *)options
73
+ resolve:(RCTPromiseResolveBlock)resolve
74
+ reject:(RCTPromiseRejectBlock)reject {
75
+ @try {
76
+ NSString *filePath = options[@"filePath"];
77
+ if (!filePath) {
78
+ reject(@"INVALID_PATH", @"File path is required", nil);
79
+ return;
80
+ }
81
+
82
+ NSNumber *volume = options[@"volume"] ?: @(1.0);
83
+ NSNumber *loop = options[@"loop"] ?: @(NO);
84
+
85
+ NSURL *fileURL = [NSURL fileURLWithPath:filePath];
86
+ NSError *error = nil;
87
+
88
+ // Setup audio session for playback
89
+ AVAudioSession *audioSession = [AVAudioSession sharedInstance];
90
+ [audioSession setCategory:AVAudioSessionCategoryPlayback error:&error];
91
+ if (error) {
92
+ reject(@"AUDIO_SESSION_ERROR", error.description, error);
93
+ return;
94
+ }
95
+ [audioSession setActive:YES error:&error];
96
+ if (error) {
97
+ reject(@"AUDIO_SESSION_ERROR", error.description, error);
98
+ return;
99
+ }
100
+
101
+ _audioPlayer = [[AVAudioPlayer alloc] initWithContentsOfURL:fileURL error:&error];
102
+ if (error) {
103
+ reject(@"INIT_PLAYER_ERROR", error.description, error);
104
+ return;
105
+ }
106
+
107
+ _audioPlayer.delegate = self;
108
+ _audioPlayer.volume = [volume floatValue];
109
+ _audioPlayer.numberOfLoops = [loop boolValue] ? -1 : 0;
110
+
111
+ if (![_audioPlayer prepareToPlay]) {
112
+ reject(@"PREPARE_ERROR", @"Failed to prepare audio player", nil);
113
+ return;
114
+ }
115
+
116
+ if (![_audioPlayer play]) {
117
+ reject(@"START_PLAYING_ERROR", @"Failed to start playing", nil);
118
+ return;
119
+ }
120
+
121
+ _isPlaying = YES;
122
+ _currentFilePath = filePath;
123
+ [self startProgressTimer];
124
+ resolve(nil);
125
+ } @catch (NSException *exception) {
126
+ reject(@"START_PLAYING_ERROR", exception.reason, nil);
127
+ }
128
+ }
129
+
130
+ - (void)stopPlaying:(RCTPromiseResolveBlock)resolve
131
+ reject:(RCTPromiseRejectBlock)reject {
132
+ @try {
133
+ [self stopProgressTimer];
134
+
135
+ if (_audioPlayer) {
136
+ [_audioPlayer stop];
137
+ _audioPlayer = nil;
138
+ }
139
+
140
+ _isPlaying = NO;
141
+ _currentFilePath = nil;
142
+ resolve(nil);
143
+ } @catch (NSException *exception) {
144
+ reject(@"STOP_PLAYING_ERROR", exception.reason, nil);
145
+ }
146
+ }
147
+
148
+ - (void)pausePlaying:(RCTPromiseResolveBlock)resolve
149
+ reject:(RCTPromiseRejectBlock)reject {
150
+ @try {
151
+ if (!_isPlaying || !_audioPlayer) {
152
+ reject(@"NOT_PLAYING", @"No playback in progress", nil);
153
+ return;
154
+ }
155
+
156
+ [_audioPlayer pause];
157
+ _isPlaying = NO;
158
+ resolve(nil);
159
+ } @catch (NSException *exception) {
160
+ reject(@"PAUSE_ERROR", exception.reason, nil);
161
+ }
162
+ }
163
+
164
+ - (void)resumePlaying:(RCTPromiseResolveBlock)resolve
165
+ reject:(RCTPromiseRejectBlock)reject {
166
+ @try {
167
+ if (!_audioPlayer || _isPlaying) {
168
+ reject(@"NOT_PAUSED", @"Playback is not paused", nil);
169
+ return;
170
+ }
171
+
172
+ [_audioPlayer play];
173
+ _isPlaying = YES;
174
+ resolve(nil);
175
+ } @catch (NSException *exception) {
176
+ reject(@"RESUME_ERROR", exception.reason, nil);
177
+ }
178
+ }
179
+
180
+ - (void)seekToTime:(double)time
181
+ resolve:(RCTPromiseResolveBlock)resolve
182
+ reject:(RCTPromiseRejectBlock)reject {
183
+ @try {
184
+ if (!_audioPlayer) {
185
+ reject(@"NO_PLAYER", @"No audio player initialized", nil);
186
+ return;
187
+ }
188
+
189
+ _audioPlayer.currentTime = time;
190
+ resolve(nil);
191
+ } @catch (NSException *exception) {
192
+ reject(@"SEEK_ERROR", exception.reason, nil);
193
+ }
194
+ }
195
+
196
+ - (void)setVolume:(double)volume
197
+ resolve:(RCTPromiseResolveBlock)resolve
198
+ reject:(RCTPromiseRejectBlock)reject {
199
+ @try {
200
+ if (!_audioPlayer) {
201
+ reject(@"NO_PLAYER", @"No audio player initialized", nil);
202
+ return;
203
+ }
204
+
205
+ _audioPlayer.volume = volume;
206
+ resolve(nil);
207
+ } @catch (NSException *exception) {
208
+ reject(@"SET_VOLUME_ERROR", exception.reason, nil);
209
+ }
210
+ }
211
+
212
+ - (void)getPlayerStatus:(RCTPromiseResolveBlock)resolve
213
+ reject:(RCTPromiseRejectBlock)reject {
214
+ @try {
215
+ NSMutableDictionary *status = [NSMutableDictionary dictionary];
216
+ status[@"isPlaying"] = @(_isPlaying);
217
+
218
+ if (_audioPlayer) {
219
+ status[@"duration"] = @(_audioPlayer.duration * 1000);
220
+ status[@"currentTime"] = @(_audioPlayer.currentTime * 1000);
221
+ } else {
222
+ status[@"duration"] = @(0);
223
+ status[@"currentTime"] = @(0);
224
+ }
225
+
226
+ if (_currentFilePath) {
227
+ status[@"currentFilePath"] = _currentFilePath;
228
+ }
229
+
230
+ resolve(status);
231
+ } @catch (NSException *exception) {
232
+ reject(@"STATUS_ERROR", exception.reason, nil);
233
+ }
234
+ }
235
+
236
+ #pragma mark - AVAudioPlayerDelegate
237
+
238
+ - (void)audioPlayerDidFinishPlaying:(AVAudioPlayer *)player
239
+ successfully:(BOOL)flag {
240
+ _isPlaying = NO;
241
+ [self stopProgressTimer];
242
+
243
+ if (_hasListeners) {
244
+ [self sendEventWithName:@"onPlaybackComplete" body:@{}];
245
+ }
246
+ }
247
+
248
+ - (void)audioPlayerDecodeErrorDidOccur:(AVAudioPlayer *)player
249
+ error:(NSError *)error {
250
+ _isPlaying = NO;
251
+ [self stopProgressTimer];
252
+ }
253
+
254
+ - (std::shared_ptr<facebook::react::TurboModule>)getTurboModule:
255
+ (const facebook::react::ObjCTurboModule::InitParams &)params {
256
+ return std::make_shared<facebook::react::NativeNosniaAudioPlayerSpecJSI>(params);
257
+ }
258
+
259
+ + (NSString *)moduleName {
260
+ return @"NosniaAudioPlayer";
261
+ }
262
+
263
+ @end
@@ -1,6 +1,7 @@
1
1
  #import <NosniaAudioRecorderSpec/NosniaAudioRecorderSpec.h>
2
2
  #import <React/RCTBridgeModule.h>
3
+ #import <React/RCTEventEmitter.h>
3
4
 
4
- @interface NosniaAudioRecorder : NSObject <NativeNosniaAudioRecorderSpec>
5
+ @interface NosniaAudioRecorder : RCTEventEmitter <NativeNosniaAudioRecorderSpec>
5
6
 
6
7
  @end
@@ -1,27 +1,72 @@
1
1
  #import "NosniaAudioRecorder.h"
2
2
  #import <AVFoundation/AVFoundation.h>
3
3
  #import <React/RCTBridgeModule.h>
4
+ #import <React/RCTEventEmitter.h>
4
5
 
5
6
  @interface NosniaAudioRecorder () <AVAudioRecorderDelegate>
6
7
  @property (nonatomic, strong) AVAudioRecorder *audioRecorder;
7
8
  @property (nonatomic, strong) NSURL *recordingURL;
8
9
  @property (nonatomic, assign) BOOL isRecording;
10
+ @property (nonatomic, strong) NSTimer *progressTimer;
9
11
  @end
10
12
 
11
13
  @implementation NosniaAudioRecorder {
12
14
  AVAudioRecorder *_audioRecorder;
13
15
  NSURL *_recordingURL;
14
16
  BOOL _isRecording;
17
+ NSTimer *_progressTimer;
18
+ BOOL _hasListeners;
15
19
  }
16
20
 
21
+ RCT_EXPORT_MODULE(NosniaAudioRecorder)
22
+
17
23
  - (instancetype)init {
18
24
  self = [super init];
19
25
  if (self) {
20
26
  _isRecording = NO;
27
+ _hasListeners = NO;
21
28
  }
22
29
  return self;
23
30
  }
24
31
 
32
+ - (NSArray<NSString *> *)supportedEvents {
33
+ return @[@"onRecordingProgress"];
34
+ }
35
+
36
+ - (void)startObserving {
37
+ _hasListeners = YES;
38
+ }
39
+
40
+ - (void)stopObserving {
41
+ _hasListeners = NO;
42
+ }
43
+
44
+ - (void)startProgressTimer {
45
+ if (_progressTimer) {
46
+ [_progressTimer invalidate];
47
+ }
48
+
49
+ _progressTimer = [NSTimer scheduledTimerWithTimeInterval:0.1
50
+ repeats:YES
51
+ block:^(NSTimer * _Nonnull timer) {
52
+ if (self->_hasListeners && self->_audioRecorder && self->_isRecording) {
53
+ NSTimeInterval currentTime = self->_audioRecorder.currentTime;
54
+ [self sendEventWithName:@"onRecordingProgress"
55
+ body:@{
56
+ @"duration": @(currentTime * 1000),
57
+ @"isRecording": @(self->_audioRecorder.isRecording)
58
+ }];
59
+ }
60
+ }];
61
+ }
62
+
63
+ - (void)stopProgressTimer {
64
+ if (_progressTimer) {
65
+ [_progressTimer invalidate];
66
+ _progressTimer = nil;
67
+ }
68
+ }
69
+
25
70
  - (NSString *)getRecordingDirectory {
26
71
  NSArray *paths = NSSearchPathForDirectoriesInDomains(
27
72
  NSDocumentDirectory,
@@ -104,6 +149,7 @@
104
149
  }
105
150
 
106
151
  _isRecording = YES;
152
+ [self startProgressTimer];
107
153
  resolve(nil);
108
154
  } @catch (NSException *exception) {
109
155
  reject(@"START_RECORDING_ERROR", exception.reason, nil);
@@ -118,6 +164,7 @@
118
164
  return;
119
165
  }
120
166
 
167
+ [self stopProgressTimer];
121
168
  [_audioRecorder stop];
122
169
  NSString *filePath = [_recordingURL path];
123
170
  _audioRecorder = nil;
@@ -162,6 +209,8 @@
162
209
  - (void)cancelRecording:(RCTPromiseResolveBlock)resolve
163
210
  reject:(RCTPromiseRejectBlock)reject {
164
211
  @try {
212
+ [self stopProgressTimer];
213
+
165
214
  if (_audioRecorder) {
166
215
  [_audioRecorder stop];
167
216
  _audioRecorder = nil;
@@ -224,11 +273,13 @@
224
273
  - (void)audioRecorderDidFinishRecording:(AVAudioRecorder *)recorder
225
274
  successfully:(BOOL)flag {
226
275
  _isRecording = NO;
276
+ [self stopProgressTimer];
227
277
  }
228
278
 
229
279
  - (void)audioRecorderEncodeErrorDidOccur:(AVAudioRecorder *)recorder
230
280
  error:(NSError *)error {
231
281
  _isRecording = NO;
282
+ [self stopProgressTimer];
232
283
  }
233
284
 
234
285
  - (std::shared_ptr<facebook::react::TurboModule>)getTurboModule:
@@ -0,0 +1,176 @@
1
+ "use strict";
2
+
3
+ import { NativeEventEmitter, NativeModules } from 'react-native';
4
+ import NativeModule from "./NativeNosniaAudioPlayer.js";
5
+ class AudioPlayer {
6
+ static instance = null;
7
+ progressListener = null;
8
+ completeListener = null;
9
+ constructor() {
10
+ this.eventEmitter = new NativeEventEmitter(NativeModules.NosniaAudioPlayer);
11
+ }
12
+ static getInstance() {
13
+ if (!AudioPlayer.instance) {
14
+ AudioPlayer.instance = new AudioPlayer();
15
+ }
16
+ return AudioPlayer.instance;
17
+ }
18
+
19
+ /**
20
+ * Add a listener for playback progress updates
21
+ * @param callback Function called with playback progress (every 100ms during playback)
22
+ * @returns Function to remove the listener
23
+ */
24
+ addPlaybackProgressListener(callback) {
25
+ if (this.progressListener) {
26
+ this.progressListener.remove();
27
+ }
28
+ this.progressListener = this.eventEmitter.addListener('onPlaybackProgress', data => callback(data));
29
+ return () => {
30
+ if (this.progressListener) {
31
+ this.progressListener.remove();
32
+ this.progressListener = null;
33
+ }
34
+ };
35
+ }
36
+
37
+ /**
38
+ * Remove the playback progress listener
39
+ */
40
+ removePlaybackProgressListener() {
41
+ if (this.progressListener) {
42
+ this.progressListener.remove();
43
+ this.progressListener = null;
44
+ }
45
+ }
46
+
47
+ /**
48
+ * Add a listener for playback completion
49
+ * @param callback Function called when playback completes
50
+ * @returns Function to remove the listener
51
+ */
52
+ addPlaybackCompleteListener(callback) {
53
+ if (this.completeListener) {
54
+ this.completeListener.remove();
55
+ }
56
+ this.completeListener = this.eventEmitter.addListener('onPlaybackComplete', callback);
57
+ return () => {
58
+ if (this.completeListener) {
59
+ this.completeListener.remove();
60
+ this.completeListener = null;
61
+ }
62
+ };
63
+ }
64
+
65
+ /**
66
+ * Remove the playback complete listener
67
+ */
68
+ removePlaybackCompleteListener() {
69
+ if (this.completeListener) {
70
+ this.completeListener.remove();
71
+ this.completeListener = null;
72
+ }
73
+ }
74
+
75
+ /**
76
+ * Start playing audio from a file path
77
+ * @param options Configuration options (filePath, volume, loop)
78
+ * @returns Promise that resolves when playback starts
79
+ */
80
+ async startPlaying(options) {
81
+ try {
82
+ const config = {
83
+ volume: 1.0,
84
+ loop: false,
85
+ ...options
86
+ };
87
+ return await NativeModule.startPlaying(config);
88
+ } catch (error) {
89
+ console.error('Error starting playback:', error);
90
+ throw error;
91
+ }
92
+ }
93
+
94
+ /**
95
+ * Stop playing and reset player
96
+ * @returns Promise that resolves when playback stops
97
+ */
98
+ async stopPlaying() {
99
+ try {
100
+ return await NativeModule.stopPlaying();
101
+ } catch (error) {
102
+ console.error('Error stopping playback:', error);
103
+ throw error;
104
+ }
105
+ }
106
+
107
+ /**
108
+ * Pause the current playback
109
+ * @returns Promise that resolves when playback is paused
110
+ */
111
+ async pausePlaying() {
112
+ try {
113
+ return await NativeModule.pausePlaying();
114
+ } catch (error) {
115
+ console.error('Error pausing playback:', error);
116
+ throw error;
117
+ }
118
+ }
119
+
120
+ /**
121
+ * Resume a paused playback
122
+ * @returns Promise that resolves when playback resumes
123
+ */
124
+ async resumePlaying() {
125
+ try {
126
+ return await NativeModule.resumePlaying();
127
+ } catch (error) {
128
+ console.error('Error resuming playback:', error);
129
+ throw error;
130
+ }
131
+ }
132
+
133
+ /**
134
+ * Seek to a specific time in the audio
135
+ * @param time Time in seconds
136
+ * @returns Promise that resolves when seek completes
137
+ */
138
+ async seekToTime(time) {
139
+ try {
140
+ return await NativeModule.seekToTime(time);
141
+ } catch (error) {
142
+ console.error('Error seeking:', error);
143
+ throw error;
144
+ }
145
+ }
146
+
147
+ /**
148
+ * Set the playback volume
149
+ * @param volume Volume level (0.0 to 1.0)
150
+ * @returns Promise that resolves when volume is set
151
+ */
152
+ async setVolume(volume) {
153
+ try {
154
+ const clampedVolume = Math.max(0, Math.min(1, volume));
155
+ return await NativeModule.setVolume(clampedVolume);
156
+ } catch (error) {
157
+ console.error('Error setting volume:', error);
158
+ throw error;
159
+ }
160
+ }
161
+
162
+ /**
163
+ * Get the current status of the player
164
+ * @returns Promise that resolves to the current player status
165
+ */
166
+ async getStatus() {
167
+ try {
168
+ return await NativeModule.getPlayerStatus();
169
+ } catch (error) {
170
+ console.error('Error getting player status:', error);
171
+ throw error;
172
+ }
173
+ }
174
+ }
175
+ export const NosniaAudioPlayer = AudioPlayer.getInstance();
176
+ //# sourceMappingURL=AudioPlayer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["NativeEventEmitter","NativeModules","NativeModule","AudioPlayer","instance","progressListener","completeListener","constructor","eventEmitter","NosniaAudioPlayer","getInstance","addPlaybackProgressListener","callback","remove","addListener","data","removePlaybackProgressListener","addPlaybackCompleteListener","removePlaybackCompleteListener","startPlaying","options","config","volume","loop","error","console","stopPlaying","pausePlaying","resumePlaying","seekToTime","time","setVolume","clampedVolume","Math","max","min","getStatus","getPlayerStatus"],"sourceRoot":"..\\..\\src","sources":["AudioPlayer.tsx"],"mappings":"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","ignoreList":[]}
@@ -0,0 +1,5 @@
1
+ "use strict";
2
+
3
+ import { TurboModuleRegistry } from 'react-native';
4
+ export default TurboModuleRegistry.getEnforcing('NosniaAudioPlayer');
5
+ //# sourceMappingURL=NativeNosniaAudioPlayer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["TurboModuleRegistry","getEnforcing"],"sourceRoot":"..\\..\\src","sources":["NativeNosniaAudioPlayer.ts"],"mappings":";;AAAA,SAASA,mBAAmB,QAA0B,cAAc;AAyBpE,eAAeA,mBAAmB,CAACC,YAAY,CAAO,mBAAmB,CAAC","ignoreList":[]}
@@ -1,9 +1,13 @@
1
1
  "use strict";
2
2
 
3
+ import { NativeEventEmitter, NativeModules } from 'react-native';
3
4
  import NativeModule from "./NativeNosniaAudioRecorder.js";
4
5
  class AudioRecorder {
5
6
  static instance = null;
6
- constructor() {}
7
+ progressListener = null;
8
+ constructor() {
9
+ this.eventEmitter = new NativeEventEmitter(NativeModules.NosniaAudioRecorder);
10
+ }
7
11
  static getInstance() {
8
12
  if (!AudioRecorder.instance) {
9
13
  AudioRecorder.instance = new AudioRecorder();
@@ -11,6 +15,35 @@ class AudioRecorder {
11
15
  return AudioRecorder.instance;
12
16
  }
13
17
 
18
+ /**
19
+ * Add a listener for recording progress updates
20
+ * @param callback Function called with duration updates (every 100ms during recording)
21
+ * @returns Function to remove the listener
22
+ */
23
+ addRecordingProgressListener(callback) {
24
+ // Remove existing listener if any
25
+ if (this.progressListener) {
26
+ this.progressListener.remove();
27
+ }
28
+ this.progressListener = this.eventEmitter.addListener('onRecordingProgress', data => callback(data));
29
+ return () => {
30
+ if (this.progressListener) {
31
+ this.progressListener.remove();
32
+ this.progressListener = null;
33
+ }
34
+ };
35
+ }
36
+
37
+ /**
38
+ * Remove the recording progress listener
39
+ */
40
+ removeRecordingProgressListener() {
41
+ if (this.progressListener) {
42
+ this.progressListener.remove();
43
+ this.progressListener = null;
44
+ }
45
+ }
46
+
14
47
  /**
15
48
  * Request audio recording permission from the user
16
49
  * @returns Promise that resolves to true if permission is granted
@@ -130,4 +163,7 @@ class AudioRecorder {
130
163
  }
131
164
  }
132
165
  export const NosniaAudioRecorder = AudioRecorder.getInstance();
166
+
167
+ // Export AudioPlayer
168
+ export { NosniaAudioPlayer } from "./AudioPlayer.js";
133
169
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"names":["NativeModule","AudioRecorder","instance","constructor","getInstance","requestPermission","requestAudioPermission","error","console","checkPermission","checkAudioPermission","startRecording","options","hasPermission","Error","config","bitrate","channels","sampleRate","stopRecording","pauseRecording","resumeRecording","cancelRecording","getStatus","getRecorderStatus","NosniaAudioRecorder"],"sourceRoot":"..\\..\\src","sources":["index.tsx"],"mappings":"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","ignoreList":[]}
1
+ {"version":3,"names":["NativeEventEmitter","NativeModules","NativeModule","AudioRecorder","instance","progressListener","constructor","eventEmitter","NosniaAudioRecorder","getInstance","addRecordingProgressListener","callback","remove","addListener","data","removeRecordingProgressListener","requestPermission","requestAudioPermission","error","console","checkPermission","checkAudioPermission","startRecording","options","hasPermission","Error","config","bitrate","channels","sampleRate","stopRecording","pauseRecording","resumeRecording","cancelRecording","getStatus","getRecorderStatus","NosniaAudioPlayer"],"sourceRoot":"..\\..\\src","sources":["index.tsx"],"mappings":"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","ignoreList":[]}