Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions .changeset/quiet-bees-happen.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
---
"react-native-vimeo-bridge": patch
---

fix: resolve vimeo player memory leak and unnecessary re-subscriptions

- Extract `throttleMs` from `callbackOrThrottle` to optimize `useEffect` dependencies
- Add `controller.off()` cleanup logic when last listener is removed
- Prevent memory leaks on component unmount
30 changes: 29 additions & 1 deletion src/VimeoView.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -173,7 +173,35 @@ function VimeoView({ player, height = 200, width = screenWidth, style, webViewPr
getVideoWidth: () => player.getVideoWidth(),
getVideoHeight: () => player.getVideoHeight(),
getVideoUrl: () => player.getVideoUrl(),
destroy: () => player.destroy(),
destroy: () => {
player.off('play');
player.off('playing');
player.off('pause');
player.off('ended');
player.off('timeupdate');
player.off('progress');
player.off('seeking');
player.off('seeked');
player.off('texttrackchange');
player.off('chapterchange');
player.off('cuechange');
player.off('cuepoint');
player.off('volumechange');
player.off('playbackratechange');
player.off('bufferstart');
player.off('bufferend');
player.off('error');
player.off('loaded');
player.off('durationchange');
player.off('fullscreenchange');
player.off('qualitychange');
player.off('camerachange');
player.off('resize');
player.off('enterpictureinpicture');
player.off('leavepictureinpicture');
player.destroy();
},
off: (event) => player.off(event),
}
}
})();
Expand Down
6 changes: 3 additions & 3 deletions src/hooks/useVimeoEvent.ts
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ function useVimeoEvent<T extends keyof VimeoPlayerEventMap>(
deps?: React.DependencyList,
): VimeoPlayerEventMap[T] | null | undefined {
const isCallback = typeof callbackOrThrottle === 'function';
const throttleMs = typeof callbackOrThrottle === 'number' ? callbackOrThrottle : undefined;

const callbackRef = useRef<EventCallback<VimeoPlayerEventMap[T]> | null>(isCallback ? callbackOrThrottle : null);

Expand All @@ -73,8 +74,7 @@ function useVimeoEvent<T extends keyof VimeoPlayerEventMap>(
}

if (!isCallback) {
if (eventType === 'timeupdate' && typeof callbackOrThrottle === 'number') {
const throttleMs = callbackOrThrottle;
if (eventType === 'timeupdate' && throttleMs) {
const now = Date.now();
if (now - lastUpdateRef.current < throttleMs) {
return;
Expand All @@ -87,7 +87,7 @@ function useVimeoEvent<T extends keyof VimeoPlayerEventMap>(
});

return unsubscribe;
}, [player, eventType, isCallback, callbackOrThrottle]);
}, [player, eventType, isCallback, throttleMs]);

return isCallback ? undefined : data;
}
Expand Down
1 change: 1 addition & 0 deletions src/module/VimeoPlayer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ class VimeoPlayer {
eventSet?.delete(callback);

if (eventSet?.size === 0) {
this.controller?.off(eventType);
this.listeners.delete(eventType);
}
};
Expand Down
6 changes: 5 additions & 1 deletion src/module/WebVimeoPlayerController.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import type { EmbedOptions, VimeoPlayer } from '../types/vimeo';
import type { EmbedOptions, EventCallback, VimeoPlayer } from '../types/vimeo';

class WebVimeoPlayerController {
private player: VimeoPlayer | null = null;
Expand Down Expand Up @@ -152,6 +152,10 @@ class WebVimeoPlayerController {
return this.player?.getVideoUrl() ?? '';
}

off(event: string, callback?: EventCallback): void {
this.player?.off(event, callback);
}

dispose(): void {
if (this.player) {
try {
Expand Down
5 changes: 5 additions & 0 deletions src/module/WebviewVimeoPlayerController.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import type WebView from 'react-native-webview';
import type { EventCallback } from '../types/vimeo';

class WebviewVimeoPlayerController {
private webViewRef: React.RefObject<WebView | null>;
Expand Down Expand Up @@ -96,6 +97,10 @@ class WebviewVimeoPlayerController {
await this.executeCommand('destroy');
}

async off(event: string, _callback?: EventCallback): Promise<void> {
await this.executeCommand('off', [event]);
}

private executeCommand(
command: string,
args: (string | number | boolean | undefined)[] = [],
Expand Down