UNPKG

react-native-vimeo-bridge

Version:

🎥 Easy-to-use Vimeo player for React Native with cross-platform support

251 lines (244 loc) • 9.72 kB
"use strict"; import { useCallback, useEffect, useMemo, useRef, useState } from 'react'; import { Dimensions, StyleSheet } from 'react-native'; import WebView from 'react-native-webview'; import WebviewVimeoPlayerController from "./module/WebviewVimeoPlayerController.js"; import { INTERNAL_SET_CONTROLLER_INSTANCE } from "./symbol.js"; import { webviewScripts } from "./utils/webviewScripts.js"; import VimeoViewWrapper from "./VimeoViewWrapper.js"; import { jsx as _jsx } from "react/jsx-runtime"; const { width: screenWidth } = Dimensions.get('window'); function VimeoView({ player, height = 200, width = screenWidth, style, webViewProps, webViewStyle }) { const webViewRef = useRef(null); const playerRef = useRef(null); const [isReady, setIsReady] = useState(false); const dataDetectorTypes = useMemo(() => ['none'], []); const handleMessage = useCallback(event => { const response = JSON.parse(event.nativeEvent.data); if (!response) { return; } if (response.type === 'onReady') { setIsReady(true); return; } if (response.type === 'commandResult') { if (!playerRef.current) { console.warn('Player controller not available for command result'); return; } const pendingCommands = playerRef.current?.getPendingCommands(); const resolver = pendingCommands?.get(response.id); if (resolver) { resolver(response.data); pendingCommands?.delete(response.id); } return; } if (player.hasListeners(response.type)) { player.emit(response.type, response.data); } }, [player]); const createPlayerHTML = useCallback(() => { const sourceUri = player.getSource(); if (sourceUri === null) { return '<html><body><div style="width: 100%; height: 100%; display: flex; justify-content: center; align-items: center; color: #fff;">Invalid Vimeo URL</div></body></html>'; } const embedOptions = player.getOptions(); const options = { url: sourceUri, ...embedOptions }; return /* html */` <!DOCTYPE html> <html> <head> <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no"> <style> * { margin: 0; padding: 0; box-sizing: border-box; } body { background-color: #000; overflow: hidden; } #vimeo-player { width: 100%; height: 100vh; } iframe { width: 100%; height: 100%; } </style> <script src="https://player.vimeo.com/api/player.js"></script> </head> <body> <div id="vimeo-player"></div> <script> (function() { 'use strict'; const player = new Vimeo.Player('vimeo-player', ${JSON.stringify(options)}); const sendMessage = (type) => (data) => { if (window.ReactNativeWebView) { window.ReactNativeWebView.postMessage(JSON.stringify({ type, data, })); } }; if (player) { sendMessage('onReady')(null); player.on('play', sendMessage('play')); player.on('playing', sendMessage('playing')); player.on('pause', sendMessage('pause')); player.on('ended', sendMessage('ended')); player.on('timeupdate', sendMessage('timeupdate')); player.on('progress', sendMessage('progress')); player.on('seeking', sendMessage('seeking')); player.on('seeked', sendMessage('seeked')); player.on('texttrackchange', sendMessage('texttrackchange')); player.on('chapterchange', sendMessage('chapterchange')); player.on('cuechange', sendMessage('cuechange')); player.on('cuepoint', sendMessage('cuepoint')); player.on('volumechange', sendMessage('volumechange')); player.on('playbackratechange', sendMessage('playbackratechange')); player.on('bufferstart', sendMessage('bufferstart')); player.on('bufferend', sendMessage('bufferend')); player.on('error', sendMessage('error')); player.on('loaded', (data) => { sendMessage('loaded')(data); const iframe = document.querySelector('iframe'); if (iframe) { iframe.style.width = '100%'; iframe.style.height = '100%'; } }); player.on('durationchange', sendMessage('durationchange')); player.on('fullscreenchange', sendMessage('fullscreenchange')); player.on('qualitychange', sendMessage('qualitychange')); player.on('camerachange', sendMessage('camerachange')); player.on('resize', sendMessage('resize')); player.on('enterpictureinpicture', sendMessage('enterpictureinpicture')); player.on('leavepictureinpicture', sendMessage('leavepictureinpicture')); ${webviewScripts.receiveMessage} window.playerCommands = { play: () => player.play(), pause: () => player.pause(), unload: () => player.unload(), setCurrentTime: (seconds) => player.setCurrentTime(seconds), setVolume: (volume) => player.setVolume(volume), setMuted: (muted) => player.setMuted(muted), getCurrentTime: () => player.getCurrentTime(), getDuration: () => player.getDuration(), setPlaybackRate: (rate) => player.setPlaybackRate(rate), getPlaybackRate: () => player.getPlaybackRate(), getVideoId: () => player.getVideoId(), getVideoTitle: () => player.getVideoTitle(), getVideoWidth: () => player.getVideoWidth(), getVideoHeight: () => player.getVideoHeight(), getVideoUrl: () => player.getVideoUrl(), requestFullscreen: () => player.requestFullscreen(), exitFullscreen: () => player.exitFullscreen(), getFullscreen: () => player.getFullscreen(), 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), } } })(); </script> </body> </html> `; }, [player]); useEffect(() => { if (isReady && webViewRef.current) { const controller = WebviewVimeoPlayerController.createInstance(webViewRef); playerRef.current = controller; player[INTERNAL_SET_CONTROLLER_INSTANCE](controller); } }, [isReady, player]); useEffect(() => { return () => { if (playerRef.current) { playerRef.current = null; } }; }, []); return /*#__PURE__*/_jsx(VimeoViewWrapper, { width: width, height: height, style: style, children: /*#__PURE__*/_jsx(WebView, { domStorageEnabled: true, allowsFullscreenVideo: true, allowsInlineMediaPlayback: true, bounces: false, scrollEnabled: false, mediaPlaybackRequiresUserAction: false, originWhitelist: ['*'], style: [styles.webView, webViewStyle] // iOS specific props , allowsLinkPreview: false, dataDetectorTypes: dataDetectorTypes // Android specific props , mixedContentMode: "compatibility", thirdPartyCookiesEnabled: false, webviewDebuggingEnabled: __DEV__, ...webViewProps, ref: webViewRef, javaScriptEnabled: true, source: { html: createPlayerHTML() }, onMessage: handleMessage }) }); } const styles = StyleSheet.create({ webView: { backgroundColor: 'transparent' } }); export default VimeoView; //# sourceMappingURL=VimeoView.js.map