Skip to content

Commit 7b44723

Browse files
Merge pull request #138 from SimformSolutionsPvtLtd/fix/UNT-T30665_android_promise_leak
fix(UNT-T30665): promises leak android
2 parents 9c5415c + 8b19f08 commit 7b44723

File tree

2 files changed

+61
-40
lines changed

2 files changed

+61
-40
lines changed

android/src/main/java/com/audiowaveform/AudioWaveformModule.kt

Lines changed: 28 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -159,13 +159,10 @@ class AudioWaveformModule(context: ReactApplicationContext): ReactContextBaseJav
159159
@ReactMethod
160160
fun startPlayer(obj: ReadableMap, promise: Promise) {
161161
val finishMode = obj.getInt(Constants.finishMode)
162-
val key = obj.getString(Constants.playerKey)
163162
val speed = obj.getDouble(Constants.speed)
164-
if (key != null) {
165-
audioPlayers[key]?.start(finishMode ?: 2, speed.toFloat(),promise)
166-
} else {
167-
promise.reject("startPlayer Error", "Player key can't be null")
168-
}
163+
164+
val player = getPlayerOrReject(obj, promise, "startPlayer Error");
165+
player?.start(finishMode ?: 2, speed.toFloat(),promise)
169166
}
170167

171168
@ReactMethod
@@ -182,25 +179,18 @@ class AudioWaveformModule(context: ReactApplicationContext): ReactContextBaseJav
182179

183180
@ReactMethod
184181
fun pausePlayer(obj: ReadableMap, promise: Promise) {
185-
val key = obj.getString(Constants.playerKey)
186-
if (key != null) {
187-
audioPlayers[key]?.pause(promise)
188-
} else {
189-
promise.reject("pausePlayer Error", "Player key can't be null")
190-
}
182+
val player = getPlayerOrReject(obj, promise, "pausePlayer Error");
183+
player?.pause(promise);
191184
}
192185

193186
@ReactMethod
194187
fun seekToPlayer(obj: ReadableMap, promise: Promise) {
195188
try {
196189
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
197190
val progress = obj.getInt(Constants.progress)
198-
val key = obj.getString(Constants.playerKey)
199-
if (key != null) {
200-
audioPlayers[key]?.seekToPosition(progress.toLong(), promise)
201-
} else {
202-
promise.reject("seekTo Error", "Player key can't be null")
203-
}
191+
192+
val player = getPlayerOrReject(obj, promise, "seekTo Error");
193+
player?.seekToPosition(progress.toLong(), promise)
204194
} else {
205195
Log.e(
206196
Constants.LOG_TAG,
@@ -216,24 +206,18 @@ class AudioWaveformModule(context: ReactApplicationContext): ReactContextBaseJav
216206
@ReactMethod
217207
fun setVolume(obj: ReadableMap, promise: Promise) {
218208
val volume = obj.getInt(Constants.volume)
219-
val key = obj.getString(Constants.playerKey)
220-
if (key != null) {
221-
audioPlayers[key]?.setVolume(volume.toFloat(), promise)
222-
} else {
223-
promise.reject("setVolume error", "Player key can't be null")
224-
}
209+
210+
val player = getPlayerOrReject(obj, promise, "setVolume Error");
211+
player?.setVolume(volume.toFloat(), promise)
225212
}
226213

227214
@ReactMethod
228215
fun getDuration(obj: ReadableMap, promise: Promise) {
229-
val key = obj.getString(Constants.playerKey)
230216
val duration = obj.getInt(Constants.durationType)
231217
val type = if (duration == 0) DurationType.Current else DurationType.Max
232-
if (key != null) {
233-
audioPlayers[key]?.getDuration(type, promise)
234-
} else {
235-
promise.reject("getDuration Error", "Player key can't be null")
236-
}
218+
219+
val player = getPlayerOrReject(obj, promise, "getDuration Error");
220+
player?.getDuration(type, promise)
237221
}
238222

239223
@ReactMethod
@@ -429,4 +413,18 @@ class AudioWaveformModule(context: ReactApplicationContext): ReactContextBaseJav
429413
handler.removeCallbacks(emitLiveRecordValue)
430414
}
431415

416+
private fun getPlayerOrReject(arguments: ReadableMap, promise: Promise, errorCode: String): AudioPlayer? {
417+
val key = getPlayerKeyOrReject(arguments, promise, errorCode)
418+
return audioPlayers[key] ?: run {
419+
promise.reject(errorCode, "$errorCode: Player not in the list")
420+
null
421+
}
422+
}
423+
424+
private fun getPlayerKeyOrReject(arguments: ReadableMap, promise: Promise, errorCode: String): String? {
425+
return arguments.getString(Constants.playerKey) ?: run {
426+
promise.reject(errorCode, "$errorCode: Player key can't be null")
427+
null
428+
}
429+
}
432430
}

src/components/Waveform/Waveform.tsx

Lines changed: 33 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -209,14 +209,17 @@ export const Waveform = forwardRef<IWaveformRef, IWaveform>((props, ref) => {
209209
}
210210
};
211211

212-
const stopPlayerAction = async () => {
212+
const stopPlayerAction = async (resetProgress = true) => {
213213
if (mode === 'static') {
214214
try {
215215
const result = await stopPlayer({
216216
playerKey: `PlayerFor${path}`,
217217
});
218218
if (!isNil(result) && result) {
219-
setCurrentProgress(0);
219+
if (resetProgress) {
220+
setCurrentProgress(0);
221+
}
222+
220223
setPlayerState(PlayerState.stopped);
221224
return Promise.resolve(result);
222225
} else {
@@ -258,6 +261,11 @@ export const Waveform = forwardRef<IWaveformRef, IWaveform>((props, ref) => {
258261
);
259262
}
260263
} catch (error) {
264+
if (playerState === PlayerState.paused) {
265+
// If the player is not prepared, triggering the stop will reset the player for next click. Fix blocked paused player after a call to `stopAllPlayers`
266+
await stopPlayerAction();
267+
}
268+
261269
return Promise.reject(error);
262270
}
263271
} else {
@@ -267,14 +275,17 @@ export const Waveform = forwardRef<IWaveformRef, IWaveform>((props, ref) => {
267275
}
268276
};
269277

270-
const pausePlayerAction = async () => {
278+
const pausePlayerAction = async (changePlayerState = true) => {
271279
if (mode === 'static') {
272280
try {
273281
const pause = await pausePlayer({
274282
playerKey: `PlayerFor${path}`,
275283
});
276284
if (pause) {
277-
setPlayerState(PlayerState.paused);
285+
if (changePlayerState) {
286+
setPlayerState(PlayerState.paused);
287+
}
288+
278289
return Promise.resolve(true);
279290
} else {
280291
return Promise.reject(
@@ -423,7 +434,7 @@ export const Waveform = forwardRef<IWaveformRef, IWaveform>((props, ref) => {
423434
// eslint-disable-next-line react-hooks/exhaustive-deps
424435
}, [viewLayout?.width, mode, candleWidth, candleSpace]);
425436

426-
useEffect(() => {
437+
const seekToPlayerAction = async () => {
427438
if (!isNil(seekPosition)) {
428439
if (mode === 'static') {
429440
const seekAmount =
@@ -432,10 +443,18 @@ export const Waveform = forwardRef<IWaveformRef, IWaveform>((props, ref) => {
432443
const clampedSeekAmount = clamp(seekAmount, 0, 1);
433444

434445
if (!panMoving) {
435-
seekToPlayer({
436-
playerKey: `PlayerFor${path}`,
437-
progress: clampedSeekAmount * songDuration,
438-
});
446+
try {
447+
await seekToPlayer({
448+
playerKey: `PlayerFor${path}`,
449+
progress: clampedSeekAmount * songDuration,
450+
});
451+
} catch (e) {
452+
if (playerState === PlayerState.paused) {
453+
// If the player is not prepared, triggering the stop will reset the player for next click. Fix blocked paused player after a call to `stopAllPlayers`
454+
await stopPlayerAction(false);
455+
}
456+
}
457+
439458
if (playerState === PlayerState.playing) {
440459
startPlayerAction();
441460
}
@@ -444,6 +463,10 @@ export const Waveform = forwardRef<IWaveformRef, IWaveform>((props, ref) => {
444463
setCurrentProgress(clampedSeekAmount * songDuration);
445464
}
446465
}
466+
};
467+
468+
useEffect(() => {
469+
seekToPlayerAction();
447470
// eslint-disable-next-line react-hooks/exhaustive-deps
448471
}, [seekPosition, panMoving, mode, songDuration]);
449472

@@ -518,7 +541,7 @@ export const Waveform = forwardRef<IWaveformRef, IWaveform>((props, ref) => {
518541
useEffect(() => {
519542
if (panMoving) {
520543
if (playerState === PlayerState.playing) {
521-
pausePlayerAction();
544+
pausePlayerAction(false);
522545
isAutoPaused.current = true;
523546
}
524547
} else {

0 commit comments

Comments
 (0)