├── .nvmrc ├── .watchmanconfig ├── docs ├── static │ ├── .nojekyll │ └── img │ │ ├── favicon.png │ │ ├── og-image.png │ │ ├── banners │ │ ├── twg-dark.png │ │ └── twg-light.png │ │ ├── logo.svg │ │ ├── customization.svg │ │ └── rely-on-rnv.svg ├── src │ ├── pages │ │ ├── markdown-page.md │ │ ├── index.module.css │ │ └── index.tsx │ ├── components │ │ └── HomepageFeatures │ │ │ ├── styles.module.css │ │ │ └── index.tsx │ ├── theme │ │ ├── TOC │ │ │ ├── styles.module.css │ │ │ └── index.tsx │ │ └── components │ │ │ └── PremiumSupport │ │ │ ├── PremiumSupport.tsx │ │ │ └── PremiumSupport.style.css │ └── css │ │ └── custom.css ├── tsconfig.json ├── .gitignore ├── sidebars.ts ├── README.md ├── package.json ├── docs │ ├── installation.md │ ├── api │ │ ├── events.md │ │ ├── methods.md │ │ ├── styles.md │ │ └── properties.md │ └── intro.md └── docusaurus.config.ts ├── example ├── App.js ├── android │ ├── app │ │ ├── src │ │ │ ├── main │ │ │ │ ├── res │ │ │ │ │ ├── values-night │ │ │ │ │ │ └── colors.xml │ │ │ │ │ ├── mipmap-hdpi │ │ │ │ │ │ ├── ic_launcher.png │ │ │ │ │ │ ├── ic_launcher_round.png │ │ │ │ │ │ └── ic_launcher_foreground.png │ │ │ │ │ ├── mipmap-mdpi │ │ │ │ │ │ ├── ic_launcher.png │ │ │ │ │ │ ├── ic_launcher_round.png │ │ │ │ │ │ └── ic_launcher_foreground.png │ │ │ │ │ ├── mipmap-xhdpi │ │ │ │ │ │ ├── ic_launcher.png │ │ │ │ │ │ ├── ic_launcher_round.png │ │ │ │ │ │ └── ic_launcher_foreground.png │ │ │ │ │ ├── mipmap-xxhdpi │ │ │ │ │ │ ├── ic_launcher.png │ │ │ │ │ │ ├── ic_launcher_round.png │ │ │ │ │ │ └── ic_launcher_foreground.png │ │ │ │ │ ├── mipmap-xxxhdpi │ │ │ │ │ │ ├── ic_launcher.png │ │ │ │ │ │ ├── ic_launcher_round.png │ │ │ │ │ │ └── ic_launcher_foreground.png │ │ │ │ │ ├── drawable │ │ │ │ │ │ ├── splashscreen.xml │ │ │ │ │ │ └── rn_edit_text_material.xml │ │ │ │ │ ├── drawable-hdpi │ │ │ │ │ │ └── splashscreen_image.png │ │ │ │ │ ├── drawable-mdpi │ │ │ │ │ │ └── splashscreen_image.png │ │ │ │ │ ├── drawable-xhdpi │ │ │ │ │ │ └── splashscreen_image.png │ │ │ │ │ ├── drawable-xxhdpi │ │ │ │ │ │ └── splashscreen_image.png │ │ │ │ │ ├── drawable-xxxhdpi │ │ │ │ │ │ └── splashscreen_image.png │ │ │ │ │ ├── values │ │ │ │ │ │ ├── colors.xml │ │ │ │ │ │ ├── strings.xml │ │ │ │ │ │ └── styles.xml │ │ │ │ │ └── mipmap-anydpi-v26 │ │ │ │ │ │ ├── ic_launcher.xml │ │ │ │ │ │ └── ic_launcher_round.xml │ │ │ │ ├── AndroidManifest.xml │ │ │ │ └── java │ │ │ │ │ └── videoplayer │ │ │ │ │ └── example │ │ │ │ │ ├── MainApplication.kt │ │ │ │ │ └── MainActivity.kt │ │ │ └── debug │ │ │ │ └── AndroidManifest.xml │ │ ├── debug.keystore │ │ ├── proguard-rules.pro │ │ └── build.gradle │ ├── gradle │ │ └── wrapper │ │ │ ├── gradle-wrapper.jar │ │ │ └── gradle-wrapper.properties │ ├── .gitignore │ ├── react-settings-plugin │ │ ├── src │ │ │ └── main │ │ │ │ └── kotlin │ │ │ │ └── expo │ │ │ │ └── plugins │ │ │ │ └── ReactSettingsPlugin.kt │ │ └── build.gradle.kts │ ├── build.gradle │ ├── gradle.properties │ ├── settings.gradle │ ├── gradlew.bat │ └── gradlew ├── assets │ ├── icon.png │ ├── splash.png │ ├── favicon.png │ └── adaptive-icon.png ├── ios │ ├── Podfile.properties.json │ ├── example │ │ ├── Images.xcassets │ │ │ ├── Contents.json │ │ │ ├── SplashScreen.imageset │ │ │ │ ├── image.png │ │ │ │ └── Contents.json │ │ │ ├── SplashScreenBackground.imageset │ │ │ │ ├── image.png │ │ │ │ └── Contents.json │ │ │ └── AppIcon.appiconset │ │ │ │ ├── App-Icon-1024x1024@1x.png │ │ │ │ └── Contents.json │ │ ├── example-Bridging-Header.h │ │ ├── noop-file.swift │ │ ├── AppDelegate.h │ │ ├── example.entitlements │ │ ├── main.m │ │ ├── Supporting │ │ │ └── Expo.plist │ │ ├── PrivacyInfo.xcprivacy │ │ ├── Info.plist │ │ ├── AppDelegate.mm │ │ └── SplashScreen.storyboard │ ├── example.xcworkspace │ │ └── contents.xcworkspacedata │ ├── .gitignore │ ├── .xcode.env │ ├── Podfile │ └── example.xcodeproj │ │ └── xcshareddata │ │ └── xcschemes │ │ └── example.xcscheme ├── tsconfig.json ├── babel.config.js ├── metro.config.js ├── app.json ├── package.json └── src │ └── App.tsx ├── src ├── __tests__ │ └── index.test.tsx ├── img │ ├── pause.png │ ├── play.png │ ├── pause@2x.png │ ├── pause@3x.png │ ├── play@2x.png │ ├── play@3x.png │ ├── fullscreen.png │ ├── volume_off.png │ ├── volume_on.png │ ├── fullscreen@2x.png │ ├── fullscreen@3x.png │ ├── volume_off@2x.png │ ├── volume_off@3x.png │ ├── volume_on@2x.png │ └── volume_on@3x.png ├── controls │ ├── Fullscreen.tsx │ ├── Mute.tsx │ ├── PlayButton.tsx │ ├── ControlsAnimatedWrapper.tsx │ ├── Duration.tsx │ ├── Controls.tsx │ └── Seekbar.tsx ├── Thumbnail.tsx ├── index.tsx └── Video.tsx ├── .gitattributes ├── .github ├── FUNDING.yml ├── ISSUE_TEMPLATE │ ├── config.yml │ ├── feature-request.yml │ └── bug-report.yml ├── workflows │ ├── validate-issue.yml │ ├── check-docs-build.yml │ ├── stale.yml │ ├── deploy-docs.yml │ └── ci.yml ├── actions │ └── setup │ │ └── action.yml └── PULL_REQUEST_TEMPLATE.md ├── tsconfig.build.json ├── babel.config.js ├── lefthook.yml ├── .editorconfig ├── .yarnrc.yml ├── tsconfig.json ├── LICENSE ├── .gitignore ├── README.md ├── package.json ├── CONTRIBUTING.md └── CODE_OF_CONDUCT.md /.nvmrc: -------------------------------------------------------------------------------- 1 | v18 2 | -------------------------------------------------------------------------------- /.watchmanconfig: -------------------------------------------------------------------------------- 1 | {} -------------------------------------------------------------------------------- /docs/static/.nojekyll: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /example/App.js: -------------------------------------------------------------------------------- 1 | export { default } from './src/App'; 2 | -------------------------------------------------------------------------------- /src/__tests__/index.test.tsx: -------------------------------------------------------------------------------- 1 | it.todo('write a test'); 2 | -------------------------------------------------------------------------------- /example/android/app/src/main/res/values-night/colors.xml: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | *.pbxproj -text 2 | # specific for windows script files 3 | *.bat text eol=crlf -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | # These are supported funding model platforms 2 | 3 | github: TheWidlarzGroup 4 | -------------------------------------------------------------------------------- /tsconfig.build.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig", 3 | "exclude": ["example", "docs", "lib"] 4 | } 5 | -------------------------------------------------------------------------------- /src/img/pause.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheWidlarzGroup/react-native-video-player/HEAD/src/img/pause.png -------------------------------------------------------------------------------- /src/img/play.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheWidlarzGroup/react-native-video-player/HEAD/src/img/play.png -------------------------------------------------------------------------------- /src/img/pause@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheWidlarzGroup/react-native-video-player/HEAD/src/img/pause@2x.png -------------------------------------------------------------------------------- /src/img/pause@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheWidlarzGroup/react-native-video-player/HEAD/src/img/pause@3x.png -------------------------------------------------------------------------------- /src/img/play@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheWidlarzGroup/react-native-video-player/HEAD/src/img/play@2x.png -------------------------------------------------------------------------------- /src/img/play@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheWidlarzGroup/react-native-video-player/HEAD/src/img/play@3x.png -------------------------------------------------------------------------------- /example/assets/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheWidlarzGroup/react-native-video-player/HEAD/example/assets/icon.png -------------------------------------------------------------------------------- /src/img/fullscreen.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheWidlarzGroup/react-native-video-player/HEAD/src/img/fullscreen.png -------------------------------------------------------------------------------- /src/img/volume_off.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheWidlarzGroup/react-native-video-player/HEAD/src/img/volume_off.png -------------------------------------------------------------------------------- /src/img/volume_on.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheWidlarzGroup/react-native-video-player/HEAD/src/img/volume_on.png -------------------------------------------------------------------------------- /example/assets/splash.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheWidlarzGroup/react-native-video-player/HEAD/example/assets/splash.png -------------------------------------------------------------------------------- /example/ios/Podfile.properties.json: -------------------------------------------------------------------------------- 1 | { 2 | "expo.jsEngine": "hermes", 3 | "EX_DEV_CLIENT_NETWORK_INSPECTOR": "true" 4 | } 5 | -------------------------------------------------------------------------------- /src/img/fullscreen@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheWidlarzGroup/react-native-video-player/HEAD/src/img/fullscreen@2x.png -------------------------------------------------------------------------------- /src/img/fullscreen@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheWidlarzGroup/react-native-video-player/HEAD/src/img/fullscreen@3x.png -------------------------------------------------------------------------------- /src/img/volume_off@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheWidlarzGroup/react-native-video-player/HEAD/src/img/volume_off@2x.png -------------------------------------------------------------------------------- /src/img/volume_off@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheWidlarzGroup/react-native-video-player/HEAD/src/img/volume_off@3x.png -------------------------------------------------------------------------------- /src/img/volume_on@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheWidlarzGroup/react-native-video-player/HEAD/src/img/volume_on@2x.png -------------------------------------------------------------------------------- /src/img/volume_on@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheWidlarzGroup/react-native-video-player/HEAD/src/img/volume_on@3x.png -------------------------------------------------------------------------------- /docs/static/img/favicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheWidlarzGroup/react-native-video-player/HEAD/docs/static/img/favicon.png -------------------------------------------------------------------------------- /docs/static/img/og-image.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheWidlarzGroup/react-native-video-player/HEAD/docs/static/img/og-image.png -------------------------------------------------------------------------------- /example/assets/favicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheWidlarzGroup/react-native-video-player/HEAD/example/assets/favicon.png -------------------------------------------------------------------------------- /example/ios/example/Images.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "version" : 1, 4 | "author" : "expo" 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /example/assets/adaptive-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheWidlarzGroup/react-native-video-player/HEAD/example/assets/adaptive-icon.png -------------------------------------------------------------------------------- /example/android/app/debug.keystore: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheWidlarzGroup/react-native-video-player/HEAD/example/android/app/debug.keystore -------------------------------------------------------------------------------- /docs/static/img/banners/twg-dark.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheWidlarzGroup/react-native-video-player/HEAD/docs/static/img/banners/twg-dark.png -------------------------------------------------------------------------------- /docs/static/img/banners/twg-light.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheWidlarzGroup/react-native-video-player/HEAD/docs/static/img/banners/twg-light.png -------------------------------------------------------------------------------- /example/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../tsconfig", 3 | "compilerOptions": { 4 | // Avoid expo-cli auto-generating a tsconfig 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /babel.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | presets: [ 3 | ['module:react-native-builder-bob/babel-preset', { modules: 'commonjs' }], 4 | ], 5 | }; 6 | -------------------------------------------------------------------------------- /example/ios/example/example-Bridging-Header.h: -------------------------------------------------------------------------------- 1 | // 2 | // Use this file to import your target's public headers that you would like to expose to Swift. 3 | // 4 | -------------------------------------------------------------------------------- /example/ios/example/noop-file.swift: -------------------------------------------------------------------------------- 1 | // 2 | // @generated 3 | // A blank Swift file must be created for native modules with Swift files to work correctly. 4 | // 5 | -------------------------------------------------------------------------------- /docs/src/pages/markdown-page.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Markdown page example 3 | --- 4 | 5 | # Markdown page example 6 | 7 | You don't need React to write simple standalone pages. 8 | -------------------------------------------------------------------------------- /example/android/gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheWidlarzGroup/react-native-video-player/HEAD/example/android/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /example/ios/example/AppDelegate.h: -------------------------------------------------------------------------------- 1 | #import 2 | #import 3 | #import 4 | 5 | @interface AppDelegate : EXAppDelegateWrapper 6 | 7 | @end 8 | -------------------------------------------------------------------------------- /example/android/app/src/main/res/mipmap-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheWidlarzGroup/react-native-video-player/HEAD/example/android/app/src/main/res/mipmap-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /example/android/app/src/main/res/mipmap-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheWidlarzGroup/react-native-video-player/HEAD/example/android/app/src/main/res/mipmap-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /example/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheWidlarzGroup/react-native-video-player/HEAD/example/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheWidlarzGroup/react-native-video-player/HEAD/example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheWidlarzGroup/react-native-video-player/HEAD/example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /example/android/app/src/main/res/drawable/splashscreen.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /example/android/app/src/main/res/mipmap-hdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheWidlarzGroup/react-native-video-player/HEAD/example/android/app/src/main/res/mipmap-hdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /example/android/app/src/main/res/mipmap-mdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheWidlarzGroup/react-native-video-player/HEAD/example/android/app/src/main/res/mipmap-mdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /example/android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheWidlarzGroup/react-native-video-player/HEAD/example/android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheWidlarzGroup/react-native-video-player/HEAD/example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /example/ios/example/Images.xcassets/SplashScreen.imageset/image.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheWidlarzGroup/react-native-video-player/HEAD/example/ios/example/Images.xcassets/SplashScreen.imageset/image.png -------------------------------------------------------------------------------- /example/android/app/src/main/res/drawable-hdpi/splashscreen_image.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheWidlarzGroup/react-native-video-player/HEAD/example/android/app/src/main/res/drawable-hdpi/splashscreen_image.png -------------------------------------------------------------------------------- /example/android/app/src/main/res/drawable-mdpi/splashscreen_image.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheWidlarzGroup/react-native-video-player/HEAD/example/android/app/src/main/res/drawable-mdpi/splashscreen_image.png -------------------------------------------------------------------------------- /example/android/app/src/main/res/drawable-xhdpi/splashscreen_image.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheWidlarzGroup/react-native-video-player/HEAD/example/android/app/src/main/res/drawable-xhdpi/splashscreen_image.png -------------------------------------------------------------------------------- /example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheWidlarzGroup/react-native-video-player/HEAD/example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /example/android/app/src/main/res/drawable-xxhdpi/splashscreen_image.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheWidlarzGroup/react-native-video-player/HEAD/example/android/app/src/main/res/drawable-xxhdpi/splashscreen_image.png -------------------------------------------------------------------------------- /example/android/app/src/main/res/drawable-xxxhdpi/splashscreen_image.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheWidlarzGroup/react-native-video-player/HEAD/example/android/app/src/main/res/drawable-xxxhdpi/splashscreen_image.png -------------------------------------------------------------------------------- /example/android/app/src/main/res/mipmap-hdpi/ic_launcher_foreground.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheWidlarzGroup/react-native-video-player/HEAD/example/android/app/src/main/res/mipmap-hdpi/ic_launcher_foreground.png -------------------------------------------------------------------------------- /example/android/app/src/main/res/mipmap-mdpi/ic_launcher_foreground.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheWidlarzGroup/react-native-video-player/HEAD/example/android/app/src/main/res/mipmap-mdpi/ic_launcher_foreground.png -------------------------------------------------------------------------------- /example/android/app/src/main/res/mipmap-xhdpi/ic_launcher_foreground.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheWidlarzGroup/react-native-video-player/HEAD/example/android/app/src/main/res/mipmap-xhdpi/ic_launcher_foreground.png -------------------------------------------------------------------------------- /example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheWidlarzGroup/react-native-video-player/HEAD/example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.png -------------------------------------------------------------------------------- /example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheWidlarzGroup/react-native-video-player/HEAD/example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.png -------------------------------------------------------------------------------- /example/ios/example/Images.xcassets/SplashScreenBackground.imageset/image.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheWidlarzGroup/react-native-video-player/HEAD/example/ios/example/Images.xcassets/SplashScreenBackground.imageset/image.png -------------------------------------------------------------------------------- /example/android/.gitignore: -------------------------------------------------------------------------------- 1 | # OSX 2 | # 3 | .DS_Store 4 | 5 | # Android/IntelliJ 6 | # 7 | build/ 8 | .idea 9 | .gradle 10 | local.properties 11 | *.iml 12 | *.hprof 13 | .cxx/ 14 | 15 | # Bundle artifacts 16 | *.jsbundle 17 | -------------------------------------------------------------------------------- /example/ios/example/Images.xcassets/AppIcon.appiconset/App-Icon-1024x1024@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheWidlarzGroup/react-native-video-player/HEAD/example/ios/example/Images.xcassets/AppIcon.appiconset/App-Icon-1024x1024@1x.png -------------------------------------------------------------------------------- /example/ios/example/example.entitlements: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /docs/src/components/HomepageFeatures/styles.module.css: -------------------------------------------------------------------------------- 1 | .features { 2 | display: flex; 3 | align-items: center; 4 | padding: 2rem 0; 5 | width: 100%; 6 | } 7 | 8 | .featureSvg { 9 | height: 200px; 10 | width: 200px; 11 | } 12 | -------------------------------------------------------------------------------- /example/ios/example/main.m: -------------------------------------------------------------------------------- 1 | #import 2 | 3 | #import "AppDelegate.h" 4 | 5 | int main(int argc, char * argv[]) { 6 | @autoreleasepool { 7 | return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); 8 | } 9 | } 10 | 11 | -------------------------------------------------------------------------------- /example/android/app/src/main/res/values/colors.xml: -------------------------------------------------------------------------------- 1 | 2 | #ffffff 3 | #ffffff 4 | #023c69 5 | #ffffff 6 | -------------------------------------------------------------------------------- /example/android/app/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | example 3 | contain 4 | false 5 | -------------------------------------------------------------------------------- /example/ios/example.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /docs/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | // This file is not used in compilation. It is here just for a nice editor experience. 3 | "extends": "@docusaurus/tsconfig", 4 | "compilerOptions": { 5 | "baseUrl": ".", 6 | "paths": { 7 | "@site/*": ["./*"] 8 | } 9 | }, 10 | "exclude": [".docusaurus", "build"] 11 | } 12 | -------------------------------------------------------------------------------- /example/android/gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionBase=GRADLE_USER_HOME 2 | distributionPath=wrapper/dists 3 | distributionUrl=https\://services.gradle.org/distributions/gradle-8.8-all.zip 4 | networkTimeout=10000 5 | validateDistributionUrl=true 6 | zipStoreBase=GRADLE_USER_HOME 7 | zipStorePath=wrapper/dists 8 | -------------------------------------------------------------------------------- /example/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /example/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /docs/.gitignore: -------------------------------------------------------------------------------- 1 | # Dependencies 2 | /node_modules 3 | 4 | # Production 5 | /build 6 | 7 | # Generated files 8 | .docusaurus 9 | .cache-loader 10 | 11 | # Misc 12 | .DS_Store 13 | .env.local 14 | .env.development.local 15 | .env.test.local 16 | .env.production.local 17 | 18 | npm-debug.log* 19 | yarn-debug.log* 20 | yarn-error.log* 21 | -------------------------------------------------------------------------------- /example/ios/example/Images.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images": [ 3 | { 4 | "filename": "App-Icon-1024x1024@1x.png", 5 | "idiom": "universal", 6 | "platform": "ios", 7 | "size": "1024x1024" 8 | } 9 | ], 10 | "info": { 11 | "version": 1, 12 | "author": "expo" 13 | } 14 | } -------------------------------------------------------------------------------- /lefthook.yml: -------------------------------------------------------------------------------- 1 | pre-commit: 2 | parallel: true 3 | commands: 4 | lint: 5 | glob: "*.{js,ts,jsx,tsx}" 6 | run: npx eslint {staged_files} 7 | types: 8 | glob: "*.{js,ts, jsx, tsx}" 9 | run: npx tsc 10 | commit-msg: 11 | parallel: true 12 | commands: 13 | commitlint: 14 | run: npx commitlint --edit 15 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | # EditorConfig helps developers define and maintain consistent 2 | # coding styles between different editors and IDEs 3 | # editorconfig.org 4 | 5 | root = true 6 | 7 | [*] 8 | 9 | indent_style = space 10 | indent_size = 2 11 | 12 | end_of_line = lf 13 | charset = utf-8 14 | trim_trailing_whitespace = true 15 | insert_final_newline = true 16 | -------------------------------------------------------------------------------- /.yarnrc.yml: -------------------------------------------------------------------------------- 1 | nodeLinker: node-modules 2 | nmHoistingLimits: workspaces 3 | 4 | plugins: 5 | - path: .yarn/plugins/@yarnpkg/plugin-interactive-tools.cjs 6 | spec: "@yarnpkg/plugin-interactive-tools" 7 | - path: .yarn/plugins/@yarnpkg/plugin-workspace-tools.cjs 8 | spec: "@yarnpkg/plugin-workspace-tools" 9 | 10 | yarnPath: .yarn/releases/yarn-3.6.1.cjs 11 | -------------------------------------------------------------------------------- /example/android/react-settings-plugin/src/main/kotlin/expo/plugins/ReactSettingsPlugin.kt: -------------------------------------------------------------------------------- 1 | package expo.plugins 2 | 3 | import org.gradle.api.Plugin 4 | import org.gradle.api.initialization.Settings 5 | 6 | class ReactSettingsPlugin : Plugin { 7 | override fun apply(settings: Settings) { 8 | // Do nothing, just register the plugin. 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /docs/src/theme/TOC/styles.module.css: -------------------------------------------------------------------------------- 1 | .tableOfContents { 2 | max-height: calc(100vh - (var(--ifm-navbar-height) + 2rem)); 3 | overflow-y: auto; 4 | position: sticky; 5 | top: calc(var(--ifm-navbar-height) + 1rem); 6 | } 7 | 8 | @media (max-width: 996px) { 9 | .tableOfContents { 10 | display: none; 11 | } 12 | 13 | .docItemContainer { 14 | padding: 0 0.3rem; 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/config.yml: -------------------------------------------------------------------------------- 1 | blank_issues_enabled: false 2 | contact_links: 3 | - name: GitHub Discussions 4 | url: https://github.com/TheWidlarzGroup/react-native-video-player/discussions 5 | about: Please ask and answer questions here. 6 | - name: TheWidlarzGroup Discord 7 | url: https://discord.gg/7Y6eE62hXM 8 | about: Feel free to join our Discord server and ask questions there. 9 | -------------------------------------------------------------------------------- /example/babel.config.js: -------------------------------------------------------------------------------- 1 | const path = require('path'); 2 | const { getConfig } = require('react-native-builder-bob/babel-config'); 3 | const pkg = require('../package.json'); 4 | 5 | const root = path.resolve(__dirname, '..'); 6 | 7 | module.exports = function (api) { 8 | api.cache(true); 9 | 10 | return getConfig( 11 | { 12 | presets: ['babel-preset-expo'], 13 | }, 14 | { root, pkg } 15 | ); 16 | }; 17 | -------------------------------------------------------------------------------- /example/android/app/src/debug/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /example/ios/example/Images.xcassets/SplashScreen.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images": [ 3 | { 4 | "idiom": "universal", 5 | "filename": "image.png", 6 | "scale": "1x" 7 | }, 8 | { 9 | "idiom": "universal", 10 | "scale": "2x" 11 | }, 12 | { 13 | "idiom": "universal", 14 | "scale": "3x" 15 | } 16 | ], 17 | "info": { 18 | "version": 1, 19 | "author": "expo" 20 | } 21 | } -------------------------------------------------------------------------------- /example/ios/example/Supporting/Expo.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | EXUpdatesCheckOnLaunch 6 | ALWAYS 7 | EXUpdatesEnabled 8 | 9 | EXUpdatesLaunchWaitMs 10 | 0 11 | 12 | -------------------------------------------------------------------------------- /example/ios/example/Images.xcassets/SplashScreenBackground.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images": [ 3 | { 4 | "idiom": "universal", 5 | "filename": "image.png", 6 | "scale": "1x" 7 | }, 8 | { 9 | "idiom": "universal", 10 | "scale": "2x" 11 | }, 12 | { 13 | "idiom": "universal", 14 | "scale": "3x" 15 | } 16 | ], 17 | "info": { 18 | "version": 1, 19 | "author": "expo" 20 | } 21 | } -------------------------------------------------------------------------------- /example/ios/.gitignore: -------------------------------------------------------------------------------- 1 | # OSX 2 | # 3 | .DS_Store 4 | 5 | # Xcode 6 | # 7 | build/ 8 | *.pbxuser 9 | !default.pbxuser 10 | *.mode1v3 11 | !default.mode1v3 12 | *.mode2v3 13 | !default.mode2v3 14 | *.perspectivev3 15 | !default.perspectivev3 16 | xcuserdata 17 | *.xccheckout 18 | *.moved-aside 19 | DerivedData 20 | *.hmap 21 | *.ipa 22 | *.xcuserstate 23 | project.xcworkspace 24 | .xcode.env.local 25 | 26 | # Bundle artifacts 27 | *.jsbundle 28 | 29 | # CocoaPods 30 | /Pods/ 31 | -------------------------------------------------------------------------------- /example/android/react-settings-plugin/build.gradle.kts: -------------------------------------------------------------------------------- 1 | import org.jetbrains.kotlin.gradle.tasks.KotlinCompile 2 | 3 | plugins { 4 | kotlin("jvm") version "1.9.24" 5 | id("java-gradle-plugin") 6 | } 7 | 8 | repositories { 9 | mavenCentral() 10 | } 11 | 12 | gradlePlugin { 13 | plugins { 14 | create("reactSettingsPlugin") { 15 | id = "com.facebook.react.settings" 16 | implementationClass = "expo.plugins.ReactSettingsPlugin" 17 | } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /example/ios/.xcode.env: -------------------------------------------------------------------------------- 1 | # This `.xcode.env` file is versioned and is used to source the environment 2 | # used when running script phases inside Xcode. 3 | # To customize your local environment, you can create an `.xcode.env.local` 4 | # file that is not versioned. 5 | 6 | # NODE_BINARY variable contains the PATH to the node executable. 7 | # 8 | # Customize the NODE_BINARY variable here. 9 | # For example, to use nvm with brew, add the following line 10 | # . "$(brew --prefix nvm)/nvm.sh" --no-use 11 | export NODE_BINARY=$(command -v node) 12 | -------------------------------------------------------------------------------- /example/metro.config.js: -------------------------------------------------------------------------------- 1 | const path = require('path'); 2 | const { getDefaultConfig } = require('@expo/metro-config'); 3 | const { getConfig } = require('react-native-builder-bob/metro-config'); 4 | const pkg = require('../package.json'); 5 | 6 | const root = path.resolve(__dirname, '..'); 7 | 8 | /** 9 | * Metro configuration 10 | * https://facebook.github.io/metro/docs/configuration 11 | * 12 | * @type {import('metro-config').MetroConfig} 13 | */ 14 | module.exports = getConfig(getDefaultConfig(__dirname), { 15 | root, 16 | pkg, 17 | project: __dirname, 18 | }); 19 | -------------------------------------------------------------------------------- /.github/workflows/validate-issue.yml: -------------------------------------------------------------------------------- 1 | name: Issue Validator and Labeler 2 | 3 | on: 4 | issues: 5 | types: [opened, edited] 6 | 7 | jobs: 8 | validate-and-label: 9 | runs-on: ubuntu-latest 10 | steps: 11 | - uses: actions/checkout@v4 12 | 13 | - name: Validate Issue Template and Add Labels 14 | uses: actions/github-script@v7 15 | with: 16 | github-token: ${{secrets.GITHUB_TOKEN}} 17 | script: | 18 | const script = require('./.github/scripts/validate.js') 19 | await script({github, context}) -------------------------------------------------------------------------------- /docs/src/theme/components/PremiumSupport/PremiumSupport.tsx: -------------------------------------------------------------------------------- 1 | import Link from '@docusaurus/Link'; 2 | import './PremiumSupport.style.css'; 3 | 4 | export const PremiumSupport = () => { 5 | return ( 6 |
7 | We are TheWidlarzGroup 8 | 14 | Premium support → 15 | 16 |
17 | ); 18 | }; 19 | -------------------------------------------------------------------------------- /example/android/app/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # By default, the flags in this file are appended to flags specified 3 | # in /usr/local/Cellar/android-sdk/24.3.3/tools/proguard/proguard-android.txt 4 | # You can edit the include path and order by changing the proguardFiles 5 | # directive in build.gradle. 6 | # 7 | # For more details, see 8 | # http://developer.android.com/guide/developing/tools/proguard.html 9 | 10 | # react-native-reanimated 11 | -keep class com.swmansion.reanimated.** { *; } 12 | -keep class com.facebook.react.turbomodule.** { *; } 13 | 14 | # Add any project specific keep options here: 15 | -------------------------------------------------------------------------------- /.github/workflows/check-docs-build.yml: -------------------------------------------------------------------------------- 1 | name: Check Documentation Build 2 | 3 | on: 4 | workflow_dispatch: 5 | pull_request: 6 | paths: 7 | - '.github/workflows/check-docs-build.yml' 8 | - 'docs/**' 9 | jobs: 10 | build_docs: 11 | runs-on: ubuntu-latest 12 | steps: 13 | - name: Checkout repository 14 | uses: actions/checkout@v3 15 | with: 16 | submodules: recursive 17 | 18 | - name: Setup 19 | uses: ./.github/actions/setup 20 | with: 21 | github_token: ${{ secrets.GITHUB_TOKEN }} 22 | 23 | - name: Build Documentation 24 | run: | 25 | cd docs 26 | yarn install 27 | yarn build 28 | -------------------------------------------------------------------------------- /docs/src/pages/index.module.css: -------------------------------------------------------------------------------- 1 | /** 2 | * CSS files with the .module.css suffix will be treated as CSS modules 3 | * and scoped locally. 4 | */ 5 | 6 | .heroBanner { 7 | padding: 5rem 0; 8 | text-align: center; 9 | position: relative; 10 | overflow: hidden; 11 | background-color: #87ccef; 12 | color: black; 13 | } 14 | 15 | .hero__icon{ 16 | font-size: 100px; 17 | } 18 | 19 | .hero__subtitle { 20 | max-width: 40rem; 21 | margin-inline: auto; 22 | } 23 | 24 | @media screen and (max-width: 996px) { 25 | .heroBanner { 26 | padding: 2rem; 27 | } 28 | } 29 | 30 | .buttons { 31 | display: flex; 32 | align-items: center; 33 | justify-content: center; 34 | margin-top: 4rem; 35 | } 36 | -------------------------------------------------------------------------------- /example/app.json: -------------------------------------------------------------------------------- 1 | { 2 | "expo": { 3 | "name": "example", 4 | "slug": "example", 5 | "version": "1.0.0", 6 | "orientation": "portrait", 7 | "icon": "./assets/icon.png", 8 | "userInterfaceStyle": "light", 9 | "splash": { 10 | "image": "./assets/splash.png", 11 | "resizeMode": "contain", 12 | "backgroundColor": "#ffffff" 13 | }, 14 | "ios": { 15 | "supportsTablet": true, 16 | "bundleIdentifier": "videoplayer.example" 17 | }, 18 | "android": { 19 | "adaptiveIcon": { 20 | "foregroundImage": "./assets/adaptive-icon.png", 21 | "backgroundColor": "#ffffff" 22 | }, 23 | "package": "videoplayer.example" 24 | }, 25 | "web": { 26 | "favicon": "./assets/favicon.png" 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /example/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "react-native-video-player-example", 3 | "version": "1.0.0", 4 | "main": "expo/AppEntry.js", 5 | "scripts": { 6 | "start": "expo start", 7 | "android": "expo run:android", 8 | "ios": "expo run:ios", 9 | "web": "expo start --web" 10 | }, 11 | "dependencies": { 12 | "@expo/metro-runtime": "~3.2.3", 13 | "@shopify/react-native-skia": "^1.5.10", 14 | "expo": "~51.0.28", 15 | "expo-status-bar": "~1.12.1", 16 | "react": "18.2.0", 17 | "react-dom": "18.2.0", 18 | "react-native": "0.74.5", 19 | "react-native-reanimated": "^3.16.6", 20 | "react-native-video": "6.8.0", 21 | "react-native-web": "~0.19.10", 22 | "react-scan": "native" 23 | }, 24 | "devDependencies": { 25 | "@babel/core": "^7.20.0", 26 | "react-native-builder-bob": "^0.31.0" 27 | }, 28 | "private": true 29 | } 30 | -------------------------------------------------------------------------------- /.github/actions/setup/action.yml: -------------------------------------------------------------------------------- 1 | name: Setup 2 | description: Setup Node.js and install dependencies 3 | 4 | runs: 5 | using: composite 6 | steps: 7 | - name: Setup Node.js 8 | uses: actions/setup-node@v3 9 | with: 10 | node-version-file: .nvmrc 11 | 12 | - name: Cache dependencies 13 | id: yarn-cache 14 | uses: actions/cache@v3 15 | with: 16 | path: | 17 | **/node_modules 18 | .yarn/install-state.gz 19 | key: ${{ runner.os }}-yarn-${{ hashFiles('yarn.lock') }}-${{ hashFiles('**/package.json', '!node_modules/**') }} 20 | restore-keys: | 21 | ${{ runner.os }}-yarn-${{ hashFiles('yarn.lock') }} 22 | ${{ runner.os }}-yarn- 23 | 24 | - name: Install dependencies 25 | if: steps.yarn-cache.outputs.cache-hit != 'true' 26 | run: yarn install --immutable 27 | shell: bash 28 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "rootDir": ".", 4 | "paths": { 5 | "react-native-video-player": ["./src/index"] 6 | }, 7 | "allowUnreachableCode": false, 8 | "allowUnusedLabels": false, 9 | "esModuleInterop": true, 10 | "forceConsistentCasingInFileNames": true, 11 | "jsx": "react-jsx", 12 | "lib": ["ESNext"], 13 | "module": "ESNext", 14 | "moduleResolution": "Bundler", 15 | "noEmit": true, 16 | "noFallthroughCasesInSwitch": true, 17 | "noImplicitReturns": true, 18 | "noImplicitUseStrict": false, 19 | "noStrictGenericChecks": false, 20 | "noUncheckedIndexedAccess": true, 21 | "noUnusedLocals": true, 22 | "noUnusedParameters": true, 23 | "resolveJsonModule": true, 24 | "skipLibCheck": true, 25 | "strict": true, 26 | "target": "ESNext", 27 | "verbatimModuleSyntax": true 28 | }, 29 | "exclude": ["docs", "lib"] 30 | } 31 | -------------------------------------------------------------------------------- /docs/src/theme/TOC/index.tsx: -------------------------------------------------------------------------------- 1 | import clsx from 'clsx'; 2 | import TOCItems from '@theme/TOCItems'; 3 | import type { Props } from '@theme/TOC'; 4 | import { PremiumSupport } from '@site/src/theme/components/PremiumSupport/PremiumSupport'; 5 | 6 | import styles from './styles.module.css'; 7 | 8 | // Using a custom className 9 | // This prevents TOCInline/TOCCollapsible getting highlighted by mistake 10 | const LINK_CLASS_NAME = 'table-of-contents__link toc-highlight'; 11 | const LINK_ACTIVE_CLASS_NAME = 'table-of-contents__link--active'; 12 | 13 | export default function TOC({ className, ...props }: Props): JSX.Element { 14 | return ( 15 |
16 | 21 | 22 |
23 | ); 24 | } 25 | -------------------------------------------------------------------------------- /docs/sidebars.ts: -------------------------------------------------------------------------------- 1 | import type { SidebarsConfig } from '@docusaurus/plugin-content-docs'; 2 | 3 | const sidebars: SidebarsConfig = { 4 | docsSidebar: [ 5 | 'intro', 6 | 'installation', 7 | { 8 | type: 'category', 9 | label: 'API', 10 | collapsed: false, 11 | link: { 12 | type: 'generated-index', 13 | }, 14 | items: [ 15 | { 16 | type: 'doc', 17 | id: 'api/properties', 18 | label: 'Properties', 19 | }, 20 | { 21 | type: 'doc', 22 | id: 'api/events', 23 | label: 'Events', 24 | }, 25 | { 26 | type: 'doc', 27 | id: 'api/methods', 28 | label: 'Methods', 29 | }, 30 | { 31 | type: 'doc', 32 | id: 'api/styles', 33 | label: 'Styles', 34 | }, 35 | ], 36 | }, 37 | ], 38 | }; 39 | 40 | export default sidebars; 41 | -------------------------------------------------------------------------------- /docs/README.md: -------------------------------------------------------------------------------- 1 | # Website 2 | 3 | This website is built using [Docusaurus](https://docusaurus.io/), a modern static website generator. 4 | 5 | ### Installation 6 | 7 | ``` 8 | $ yarn 9 | ``` 10 | 11 | ### Local Development 12 | 13 | ``` 14 | $ yarn start 15 | ``` 16 | 17 | This command starts a local development server and opens up a browser window. Most changes are reflected live without having to restart the server. 18 | 19 | ### Build 20 | 21 | ``` 22 | $ yarn build 23 | ``` 24 | 25 | This command generates static content into the `build` directory and can be served using any static contents hosting service. 26 | 27 | ### Deployment 28 | 29 | Using SSH: 30 | 31 | ``` 32 | $ USE_SSH=true yarn deploy 33 | ``` 34 | 35 | Not using SSH: 36 | 37 | ``` 38 | $ GIT_USER= yarn deploy 39 | ``` 40 | 41 | If you are using GitHub pages for hosting, this command is a convenient way to build the website and push to the `gh-pages` branch. 42 | -------------------------------------------------------------------------------- /example/android/app/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 9 | 14 | 17 | -------------------------------------------------------------------------------- /.github/workflows/stale.yml: -------------------------------------------------------------------------------- 1 | name: Close inactive issues 2 | on: 3 | schedule: 4 | - cron: "30 1 * * *" 5 | workflow_dispatch: 6 | 7 | jobs: 8 | close-issues: 9 | runs-on: ubuntu-latest 10 | permissions: 11 | issues: write 12 | pull-requests: write 13 | steps: 14 | - uses: actions/stale@v5 15 | with: 16 | days-before-issue-stale: 30 17 | days-before-issue-close: 14 18 | stale-issue-label: "stale" 19 | stale-issue-message: "This issue is stale because it has been open for 30 days with no activity. If there won't be any activity in the next 14 days, this issue will be closed automatically." 20 | close-issue-message: "This issue was closed because it has been inactive for 14 days since being marked as stale." 21 | days-before-pr-stale: -1 22 | days-before-pr-close: -1 23 | exempt-issue-labels: "feature,Accepted,good first issue" 24 | repo-token: ${{ secrets.GITHUB_TOKEN }} 25 | -------------------------------------------------------------------------------- /src/controls/Fullscreen.tsx: -------------------------------------------------------------------------------- 1 | import type { CustomStyles } from 'react-native-video-player'; 2 | import { memo } from 'react'; 3 | import { Image, StyleSheet, TouchableOpacity } from 'react-native'; 4 | 5 | interface FullscreenProps { 6 | controlButtonCustomStyles: CustomStyles['controlButton']; 7 | controlIconCustomStyles: CustomStyles['controlIcon']; 8 | onToggleFullScreen: () => void; 9 | } 10 | 11 | export const Fullscreen = memo( 12 | ({ 13 | onToggleFullScreen, 14 | controlIconCustomStyles, 15 | controlButtonCustomStyles, 16 | }: FullscreenProps) => { 17 | return ( 18 | 22 | 26 | 27 | ); 28 | } 29 | ); 30 | 31 | const styles = StyleSheet.create({ 32 | extraControl: { 33 | color: 'white', 34 | padding: 8, 35 | }, 36 | }); 37 | -------------------------------------------------------------------------------- /.github/PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | 19 | ## Summary 20 | 21 | ### Motivation 22 | 23 | ### Changes 24 | 25 | ## Test plan 26 | -------------------------------------------------------------------------------- /.github/workflows/deploy-docs.yml: -------------------------------------------------------------------------------- 1 | name: Deploy Documentation 2 | 3 | on: 4 | workflow_dispatch: 5 | push: 6 | branches: 7 | - master 8 | paths: 9 | - '.github/workflows/deploy-docs.yml' 10 | - 'docs/**' 11 | jobs: 12 | build_and_deploy_docs: 13 | runs-on: ubuntu-latest 14 | permissions: 15 | contents: write 16 | steps: 17 | - name: Checkout repository 18 | uses: actions/checkout@v3 19 | with: 20 | submodules: recursive 21 | 22 | - name: Setup 23 | uses: ./.github/actions/setup 24 | with: 25 | github_token: ${{ secrets.GITHUB_TOKEN }} 26 | 27 | - name: Build Documentation 28 | run: | 29 | cd docs 30 | yarn install 31 | yarn build 32 | 33 | - name: Deploy to GitHub Pages 34 | uses: peaceiris/actions-gh-pages@v3 35 | with: 36 | github_token: ${{ secrets.GITHUB_TOKEN }} 37 | publish_dir: ./docs/build 38 | user_name: github-actions[bot] 39 | user_email: 41898282+github-actions[bot]@users.noreply.github.com 40 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2024 Kamil 4 | Permission is hereby granted, free of charge, to any person obtaining a copy 5 | of this software and associated documentation files (the "Software"), to deal 6 | in the Software without restriction, including without limitation the rights 7 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | copies of the Software, and to permit persons to whom the Software is 9 | furnished to do so, subject to the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be included in all 12 | copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 20 | SOFTWARE. 21 | -------------------------------------------------------------------------------- /src/controls/Mute.tsx: -------------------------------------------------------------------------------- 1 | import { memo } from 'react'; 2 | import type { CustomStyles } from 'react-native-video-player'; 3 | import { Image, StyleSheet, TouchableOpacity } from 'react-native'; 4 | 5 | interface MuteProps { 6 | controlButtonCustomStyles: CustomStyles['controlButton']; 7 | controlIconCustomStyles: CustomStyles['controlIcon']; 8 | isMuted: boolean; 9 | onMutePress: () => void; 10 | } 11 | 12 | export const Mute = memo( 13 | ({ 14 | isMuted, 15 | onMutePress, 16 | controlButtonCustomStyles, 17 | controlIconCustomStyles, 18 | }: MuteProps) => { 19 | return ( 20 | 24 | 32 | 33 | ); 34 | } 35 | ); 36 | 37 | const styles = StyleSheet.create({ 38 | extraControl: { 39 | color: 'white', 40 | padding: 8, 41 | }, 42 | }); 43 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # OSX 2 | # 3 | .DS_Store 4 | 5 | # XDE 6 | .expo/ 7 | 8 | # VSCode 9 | .vscode/ 10 | jsconfig.json 11 | 12 | # Xcode 13 | # 14 | build/ 15 | *.pbxuser 16 | !default.pbxuser 17 | *.mode1v3 18 | !default.mode1v3 19 | *.mode2v3 20 | !default.mode2v3 21 | *.perspectivev3 22 | !default.perspectivev3 23 | xcuserdata 24 | *.xccheckout 25 | *.moved-aside 26 | DerivedData 27 | *.hmap 28 | *.ipa 29 | *.xcuserstate 30 | project.xcworkspace 31 | 32 | # Android/IJ 33 | # 34 | .classpath 35 | .cxx 36 | .gradle 37 | .idea 38 | .project 39 | .settings 40 | local.properties 41 | android.iml 42 | 43 | # Cocoapods 44 | # 45 | example/ios/Pods 46 | 47 | # Ruby 48 | example/vendor/ 49 | 50 | # node.js 51 | # 52 | node_modules/ 53 | npm-debug.log 54 | yarn-debug.log 55 | yarn-error.log 56 | 57 | # BUCK 58 | buck-out/ 59 | \.buckd/ 60 | android/app/libs 61 | android/keystores/debug.keystore 62 | 63 | # Yarn 64 | .yarn/* 65 | !.yarn/patches 66 | !.yarn/plugins 67 | !.yarn/releases 68 | !.yarn/sdks 69 | !.yarn/versions 70 | 71 | # Expo 72 | .expo/ 73 | 74 | # Turborepo 75 | .turbo/ 76 | 77 | # generated by bob 78 | lib/ 79 | 80 | # React Native Codegen 81 | ios/generated 82 | android/generated 83 | -------------------------------------------------------------------------------- /src/controls/PlayButton.tsx: -------------------------------------------------------------------------------- 1 | import { Image, StyleSheet, TouchableOpacity } from 'react-native'; 2 | import type { CustomStyles } from 'react-native-video-player'; 3 | import { memo } from 'react'; 4 | 5 | interface PlayButtonProps { 6 | controlButtonCustomStyles?: CustomStyles['controlButton']; 7 | playControlCustomStyles?: CustomStyles['playControl']; 8 | isPlaying: boolean; 9 | onPlayPress: () => void; 10 | } 11 | 12 | export const PlayButton = memo( 13 | ({ 14 | isPlaying, 15 | onPlayPress, 16 | playControlCustomStyles, 17 | controlButtonCustomStyles, 18 | }: PlayButtonProps) => { 19 | return ( 20 | 28 | 33 | 34 | ); 35 | } 36 | ); 37 | 38 | const styles = StyleSheet.create({ 39 | playControl: { 40 | color: 'white', 41 | padding: 8, 42 | }, 43 | }); 44 | -------------------------------------------------------------------------------- /docs/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "docs", 3 | "version": "0.0.0", 4 | "private": true, 5 | "scripts": { 6 | "docusaurus": "docusaurus", 7 | "start": "docusaurus start", 8 | "build": "docusaurus build", 9 | "swizzle": "docusaurus swizzle", 10 | "deploy": "docusaurus deploy", 11 | "clear": "docusaurus clear", 12 | "serve": "docusaurus serve", 13 | "write-translations": "docusaurus write-translations", 14 | "write-heading-ids": "docusaurus write-heading-ids", 15 | "typecheck": "tsc" 16 | }, 17 | "dependencies": { 18 | "@docusaurus/core": "3.6.3", 19 | "@docusaurus/preset-classic": "3.6.3", 20 | "@mdx-js/react": "^3.0.0", 21 | "clsx": "^2.0.0", 22 | "prism-react-renderer": "^2.3.0", 23 | "react": "^18.0.0", 24 | "react-dom": "^18.0.0" 25 | }, 26 | "devDependencies": { 27 | "@docusaurus/module-type-aliases": "3.6.3", 28 | "@docusaurus/tsconfig": "3.6.3", 29 | "@docusaurus/types": "3.6.3", 30 | "typescript": "~5.6.2" 31 | }, 32 | "browserslist": { 33 | "production": [ 34 | ">0.5%", 35 | "not dead", 36 | "not op_mini all" 37 | ], 38 | "development": [ 39 | "last 3 chrome version", 40 | "last 3 firefox version", 41 | "last 5 safari version" 42 | ] 43 | }, 44 | "engines": { 45 | "node": ">=18.0" 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /docs/src/theme/components/PremiumSupport/PremiumSupport.style.css: -------------------------------------------------------------------------------- 1 | .premium-support__container { 2 | display: none; 3 | flex-direction: column; 4 | text-align: center; 5 | background-color: #171717; 6 | padding: 1rem; 7 | margin: 1rem; 8 | gap: 1rem; 9 | border-radius: 0.5rem; 10 | } 11 | 12 | .premium-support__text { 13 | padding-left: 0.5rem; 14 | padding-right: 0.5rem; 15 | font-weight: bold; 16 | color: #fff; 17 | } 18 | 19 | .premium-support__link { 20 | width: 90%; 21 | border-radius: .25rem; 22 | margin: 0 auto; 23 | border: none; 24 | padding: 0.5rem 1rem; 25 | font-weight: 500; 26 | background-color: #f9d85b; 27 | color: #171717; 28 | transition: transform 0.3s ease, background-color 0.3s ease; 29 | text-align: center; 30 | display: inline-block; 31 | } 32 | 33 | .premium-support__link:hover { 34 | transform: scale(1.05); 35 | background-color: #fff; 36 | color: #171717; 37 | text-decoration: none; 38 | } 39 | 40 | html[data-theme="dark"] .premium-support__container { 41 | background-color: #87ccef; 42 | } 43 | 44 | html[data-theme="dark"] .premium-support__text { 45 | color: #171717; 46 | } 47 | 48 | html[data-theme="dark"] .premium-support__link { 49 | background-color: #171717; 50 | color: #fff; 51 | } 52 | 53 | @media (min-width: 1516px) { 54 | .premium-support__container { 55 | display: flex; 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /.github/workflows/ci.yml: -------------------------------------------------------------------------------- 1 | name: CI 2 | on: 3 | push: 4 | branches: 5 | - master 6 | pull_request: 7 | branches: 8 | - master 9 | merge_group: 10 | types: 11 | - checks_requested 12 | 13 | jobs: 14 | lint: 15 | runs-on: ubuntu-latest 16 | steps: 17 | - name: Checkout 18 | uses: actions/checkout@v3 19 | 20 | - name: Setup 21 | uses: ./.github/actions/setup 22 | 23 | - name: Lint files 24 | run: yarn lint 25 | 26 | - name: Typecheck files 27 | run: yarn typecheck 28 | 29 | test: 30 | runs-on: ubuntu-latest 31 | steps: 32 | - name: Checkout 33 | uses: actions/checkout@v3 34 | 35 | - name: Setup 36 | uses: ./.github/actions/setup 37 | 38 | - name: Run unit tests 39 | run: yarn test --maxWorkers=2 --coverage 40 | 41 | build-library: 42 | runs-on: ubuntu-latest 43 | steps: 44 | - name: Checkout 45 | uses: actions/checkout@v3 46 | 47 | - name: Setup 48 | uses: ./.github/actions/setup 49 | 50 | - name: Build package 51 | run: yarn prepare 52 | 53 | build-web: 54 | runs-on: ubuntu-latest 55 | steps: 56 | - name: Checkout 57 | uses: actions/checkout@v3 58 | 59 | - name: Setup 60 | uses: ./.github/actions/setup 61 | 62 | - name: Build example for Web 63 | run: | 64 | yarn example expo export --platform web 65 | -------------------------------------------------------------------------------- /example/ios/example/PrivacyInfo.xcprivacy: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | NSPrivacyAccessedAPITypes 6 | 7 | 8 | NSPrivacyAccessedAPIType 9 | NSPrivacyAccessedAPICategoryUserDefaults 10 | NSPrivacyAccessedAPITypeReasons 11 | 12 | CA92.1 13 | 14 | 15 | 16 | NSPrivacyAccessedAPIType 17 | NSPrivacyAccessedAPICategoryFileTimestamp 18 | NSPrivacyAccessedAPITypeReasons 19 | 20 | 0A2A.1 21 | 3B52.1 22 | C617.1 23 | 24 | 25 | 26 | NSPrivacyAccessedAPIType 27 | NSPrivacyAccessedAPICategoryDiskSpace 28 | NSPrivacyAccessedAPITypeReasons 29 | 30 | E174.1 31 | 85F4.1 32 | 33 | 34 | 35 | NSPrivacyAccessedAPIType 36 | NSPrivacyAccessedAPICategorySystemBootTime 37 | NSPrivacyAccessedAPITypeReasons 38 | 39 | 35F9.1 40 | 41 | 42 | 43 | NSPrivacyCollectedDataTypes 44 | 45 | NSPrivacyTracking 46 | 47 | 48 | 49 | -------------------------------------------------------------------------------- /docs/docs/installation.md: -------------------------------------------------------------------------------- 1 | import Tabs from '@theme/Tabs'; 2 | import TabItem from '@theme/TabItem'; 3 | 4 | # Installation 5 | 6 | Getting started with `react-native-video-player` is quick and easy. Follow these steps to integrate the library into your React Native project. 7 | 8 | --- 9 | 10 | ## Step 1: Install the Library 11 | 12 | Select your package manager below to see the appropriate installation command: 13 | 14 | 15 | 16 | ```bash 17 | npm install react-native-video-player react-native-video 18 | ``` 19 | 20 | 21 | ```bash 22 | yarn add react-native-video-player react-native-video 23 | ``` 24 | 25 | 26 | 27 | --- 28 | 29 | ## Step 2: Install iOS Dependencies 30 | 31 | If you're targeting iOS, navigate to the `ios` directory and run `pod install` to install the necessary CocoaPods: 32 | 33 | ``` 34 | cd ios 35 | pod install 36 | ``` 37 | 38 | --- 39 | 40 | ## Example Usage 41 | 42 | Here’s a simple example of how to use `react-native-video-player` in your app: 43 | 44 | ```tsx 45 | import React from 'react'; 46 | import {View} from 'react-native'; 47 | import VideoPlayer from 'react-native-video-player'; 48 | 49 | const App = () => ( 50 | 51 | 56 | 57 | ); 58 | 59 | export default App; 60 | ``` 61 | 62 | --- 63 | 64 | You're now ready to use `react-native-video-player` in your project. Happy coding! 🚀 65 | -------------------------------------------------------------------------------- /docs/src/pages/index.tsx: -------------------------------------------------------------------------------- 1 | import clsx from 'clsx'; 2 | import Link from '@docusaurus/Link'; 3 | import useDocusaurusContext from '@docusaurus/useDocusaurusContext'; 4 | import Layout from '@theme/Layout'; 5 | import HomepageFeatures from '@site/src/components/HomepageFeatures'; 6 | import Heading from '@theme/Heading'; 7 | 8 | import styles from './index.module.css'; 9 | 10 | function HomepageHeader() { 11 | const { siteConfig } = useDocusaurusContext(); 12 | return ( 13 |
14 |
15 | 🎥 16 | 17 | {siteConfig.title} 18 | 19 |

20 | {''} component for React Native with 21 | controls that uses react-native-video under the hood 22 |

23 |
24 | 28 | Get Started 29 | 30 |
31 |
32 |
33 | ); 34 | } 35 | 36 | export default function Home(): JSX.Element { 37 | const { siteConfig } = useDocusaurusContext(); 38 | return ( 39 | 43 | 44 |
45 | 46 |
47 |
48 | ); 49 | } 50 | -------------------------------------------------------------------------------- /example/android/build.gradle: -------------------------------------------------------------------------------- 1 | // Top-level build file where you can add configuration options common to all sub-projects/modules. 2 | 3 | buildscript { 4 | ext { 5 | buildToolsVersion = findProperty('android.buildToolsVersion') ?: '34.0.0' 6 | minSdkVersion = Integer.parseInt(findProperty('android.minSdkVersion') ?: '23') 7 | compileSdkVersion = Integer.parseInt(findProperty('android.compileSdkVersion') ?: '34') 8 | targetSdkVersion = Integer.parseInt(findProperty('android.targetSdkVersion') ?: '34') 9 | kotlinVersion = findProperty('android.kotlinVersion') ?: '1.9.23' 10 | 11 | ndkVersion = "26.1.10909125" 12 | } 13 | repositories { 14 | google() 15 | mavenCentral() 16 | } 17 | dependencies { 18 | classpath('com.android.tools.build:gradle') 19 | classpath('com.facebook.react:react-native-gradle-plugin') 20 | classpath('org.jetbrains.kotlin:kotlin-gradle-plugin') 21 | } 22 | } 23 | 24 | apply plugin: "com.facebook.react.rootproject" 25 | 26 | allprojects { 27 | repositories { 28 | maven { 29 | // All of React Native (JS, Obj-C sources, Android binaries) is installed from npm 30 | url(new File(['node', '--print', "require.resolve('react-native/package.json')"].execute(null, rootDir).text.trim(), '../android')) 31 | } 32 | maven { 33 | // Android JSC is installed from npm 34 | url(new File(['node', '--print', "require.resolve('jsc-android/package.json', { paths: [require.resolve('react-native/package.json')] })"].execute(null, rootDir).text.trim(), '../dist')) 35 | } 36 | 37 | google() 38 | mavenCentral() 39 | maven { url 'https://www.jitpack.io' } 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /docs/docs/api/events.md: -------------------------------------------------------------------------------- 1 | # API - Events 2 | 3 | The `react-native-video-player` component exposes a set of events that allow you to interact with and control the video playback. Below, you’ll find a detailed list of these events, their descriptions, and how to use them. These events give you full flexibility to customize the behavior of the video player. 4 | 5 | --- 6 | 7 | ## Component Events 8 | 9 | ### `onStart` 10 | - **Type**: `function` 11 | - **Description**: Callback function triggered when the start button is pressed. 12 | - **Example**: 13 | ``` 14 | onStart={() => { 15 | console.log('Video started!'); 16 | }} 17 | ``` 18 | 19 | --- 20 | 21 | ### `onPlayPress` 22 | - **Type**: `function` 23 | - **Description**: Callback function triggered when the play button is pressed. 24 | - **Example**: 25 | ``` 26 | onPlayPress={() => { 27 | console.log('Play button pressed!'); 28 | }} 29 | ``` 30 | 31 | --- 32 | 33 | ### `onHideControls` 34 | - **Type**: `function` 35 | - **Description**: Callback function triggered when the video controls are hidden. 36 | - **Example**: 37 | ``` 38 | onHideControls={() => { 39 | console.log('Controls are hidden.'); 40 | }} 41 | ``` 42 | 43 | --- 44 | 45 | ### `onShowControls` 46 | - **Type**: `function` 47 | - **Description**: Callback function triggered when the video controls are shown. 48 | - **Example**: 49 | ``` 50 | onShowControls={() => { 51 | console.log('Controls are shown.'); 52 | }} 53 | ``` 54 | 55 | --- 56 | 57 | ## Additional Events from `react-native-video` 58 | 59 | The `react-native-video-player` component also supports all events from the underlying [react-native-video](https://github.com/TheWidlarzGroup.com/react-native-video) library. These include events like `onLoad`, `onError`, `onEnd`, and more. 60 | 61 | For a full list of events and how to use them, refer to the [react-native-video events documentation](https://docs.thewidlarzgroup.com/react-native-video/component/events). 62 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature-request.yml: -------------------------------------------------------------------------------- 1 | name: Feature request 2 | description: Suggest an idea for this project 3 | title: "[Feature]: " 4 | labels: ["feature"] 5 | assignees: [] 6 | body: 7 | - type: markdown 8 | attributes: 9 | value: Thanks for taking the time to fill out this feature request! 10 | 11 | - type: textarea 12 | id: description 13 | attributes: 14 | label: Description 15 | description: Tell us your idea and why will concern if we implement it. You can also create a PR 😄 16 | placeholder: Tell us your idea! 17 | value: "Idea" 18 | validations: 19 | required: true 20 | 21 | - type: textarea 22 | id: why-it-is-needed 23 | attributes: 24 | label: Why it is needed ? 25 | description: Tell us your why it is needed! 26 | placeholder: Why it is needed ? 27 | value: "Because ..." 28 | validations: 29 | required: true 30 | 31 | - type: textarea 32 | id: possible-implementation 33 | attributes: 34 | label: Possible implementation 35 | description: | 36 | Tell us your possible implementation! It really helps if you could describe from a technical POV how this new feature would work, which code it rely on, etc 37 | placeholder: How to implement ? 38 | value: "Technical POV how to do it" 39 | validations: 40 | required: false 41 | 42 | - type: textarea 43 | id: code-sample 44 | attributes: 45 | label: Code sample 46 | description: Please show how the new code could work, if doable 47 | placeholder: Code sample 48 | value: "Code sample" 49 | validations: 50 | required: false 51 | 52 | - type: markdown 53 | attributes: 54 | value: | 55 | # Support 56 | 57 | **If this functionality is important to you and you need it, contact [TheWidlarzGroup](https://www.thewidlarzgroup.com/?utm_source=rnv&utm_medium=feature-request#Contact) - [`hi@thewidlarzgroup.com`](mailto:hi@thewidlarzgroup.com)** 58 | 59 | 60 | -------------------------------------------------------------------------------- /src/controls/ControlsAnimatedWrapper.tsx: -------------------------------------------------------------------------------- 1 | import type { CustomStyles } from 'react-native-video-player'; 2 | import { 3 | forwardRef, 4 | memo, 5 | useCallback, 6 | useImperativeHandle, 7 | useRef, 8 | } from 'react'; 9 | import { Animated, StyleSheet } from 'react-native'; 10 | 11 | export interface AnimationRef { 12 | runControlsAnimation: (toValue: number, callback?: () => void) => void; 13 | } 14 | 15 | interface AnimatedWrapperProps { 16 | animationDuration: number; 17 | children: React.ReactNode; 18 | customStylesControls: CustomStyles['controls']; 19 | } 20 | 21 | export const AnimatedWrapper = memo( 22 | forwardRef( 23 | ({ animationDuration, children, customStylesControls }, ref) => { 24 | const animationValue = useRef(new Animated.Value(0)).current; 25 | 26 | const runControlsAnimation = useCallback( 27 | (toValue: number, callback?: () => void) => { 28 | Animated.timing(animationValue, { 29 | toValue, 30 | duration: animationDuration, 31 | useNativeDriver: true, 32 | }).start(callback); 33 | }, 34 | [animationDuration, animationValue] 35 | ); 36 | 37 | useImperativeHandle(ref, () => ({ 38 | runControlsAnimation, 39 | })); 40 | 41 | const controlsTranslateY = animationValue.interpolate({ 42 | inputRange: [0, 1], 43 | outputRange: [48, 0], 44 | }); 45 | 46 | return ( 47 | 54 | {children} 55 | 56 | ); 57 | } 58 | ) 59 | ); 60 | 61 | const styles = StyleSheet.create({ 62 | controls: { 63 | backgroundColor: 'rgba(0, 0, 0, 0.6)', 64 | height: 48, 65 | marginTop: -48, 66 | flexDirection: 'row', 67 | alignItems: 'center', 68 | }, 69 | }); 70 | -------------------------------------------------------------------------------- /example/android/app/src/main/res/drawable/rn_edit_text_material.xml: -------------------------------------------------------------------------------- 1 | 2 | 16 | 22 | 23 | 24 | 33 | 34 | 35 | 36 | 37 | 38 | -------------------------------------------------------------------------------- /src/controls/Duration.tsx: -------------------------------------------------------------------------------- 1 | import { forwardRef, memo, useImperativeHandle, useState } from 'react'; 2 | import type { CustomStyles } from 'react-native-video-player'; 3 | import { StyleSheet, Text } from 'react-native'; 4 | import type { ProgressRef } from './Controls'; 5 | 6 | const getDurationTime = (duration: number): string => { 7 | const padTimeValueString = (value: number): string => 8 | value.toString().padStart(2, '0'); 9 | 10 | if (!Number.isFinite(duration)) return ''; 11 | 12 | const seconds = Math.floor(duration % 60); 13 | const minutes = Math.floor((duration / 60) % 60); 14 | const hours = Math.floor((duration / 3600) % 24); 15 | 16 | return hours 17 | ? `${padTimeValueString(hours)}:${padTimeValueString(minutes)}:${padTimeValueString(seconds)}` 18 | : `${padTimeValueString(minutes)}:${padTimeValueString(seconds)}`; 19 | }; 20 | 21 | const ProgressingDuration = forwardRef< 22 | ProgressRef, 23 | { 24 | duration: number; 25 | durationTextCustomStyles: CustomStyles['durationText']; 26 | } 27 | >(({ duration, durationTextCustomStyles }, ref) => { 28 | const [progress, setProgress] = useState(0); 29 | 30 | useImperativeHandle(ref, () => ({ 31 | onProgress: setProgress, 32 | })); 33 | return ( 34 | 35 | {getDurationTime(progress * duration)} 36 | 37 | ); 38 | }); 39 | 40 | export const DurationText = memo( 41 | forwardRef< 42 | ProgressRef, 43 | { 44 | duration: number; 45 | durationTextCustomStyles: CustomStyles['durationText']; 46 | } 47 | >(({ duration, durationTextCustomStyles }, ref) => { 48 | return ( 49 | <> 50 | 55 | 56 | {` / ${getDurationTime(duration)}`} 57 | 58 | 59 | ); 60 | }) 61 | ); 62 | 63 | const styles = StyleSheet.create({ 64 | durationText: { 65 | color: 'white', 66 | }, 67 | }); 68 | -------------------------------------------------------------------------------- /example/android/app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | -------------------------------------------------------------------------------- /docs/docs/api/methods.md: -------------------------------------------------------------------------------- 1 | # API - Methods 2 | 3 | The `react-native-video-player` component exposes some methods through a ref. These methods provide direct control over video playback, allowing you to customize and manage the player programmatically. 4 | 5 | --- 6 | 7 | ## Using Ref Methods 8 | 9 | To access the methods, you need to create a ref for the `VideoPlayer` component. Here's an example of how to set up a ref and use the available methods: 10 | 11 | ```tsx 12 | import React, {useRef} from 'react'; 13 | import VideoPlayer, {type VideoPlayerRef} from 'react-native-video-player'; 14 | 15 | const App = () => { 16 | const playerRef = useRef(null); 17 | 18 | const handlePause = () => { 19 | playerRef.current?.pause(); 20 | }; 21 | 22 | return ( 23 | 27 | ); 28 | }; 29 | ``` 30 | 31 | --- 32 | 33 | ## Available Methods 34 | 35 | ### `seek(time)` 36 | - **Description**: Moves the video playback to the specified `time` (in seconds). 37 | - **Parameters**: 38 | - `time` (number): The time in seconds to which the player should seek. 39 | - **Example**: 40 | ```ts 41 | playerRef.current?.seek(30); // Seeks to the 30th second 42 | ``` 43 | 44 | --- 45 | 46 | ### `pause()` 47 | - **Description**: Pauses the video playback. 48 | - **Example**: 49 | ```ts 50 | playerRef.current?.pause(); 51 | ``` 52 | 53 | --- 54 | 55 | ### `resume()` 56 | - **Description**: Resumes video playback from the current position. 57 | - **Example**: 58 | ```ts 59 | playerRef.current?.resume(); 60 | ``` 61 | 62 | --- 63 | 64 | ### `stop()` 65 | - **Description**: Stops the video playback and resets it to the beginning. 66 | - **Example**: 67 | ```ts 68 | playerRef.current?.stop(); 69 | ``` 70 | 71 | --- 72 | 73 | The `react-native-video-player` component also supports all methods from the underlying [react-native-video](https://github.com/TheWidlarzGroup.com/react-native-video) library. These include methods like `save`, `setFullScreen`, and more. 74 | 75 | For a full list of methods and how to use them, refer to the [react-native-video methods documentation](https://docs.thewidlarzgroup.com/react-native-video/component/methods). 76 | -------------------------------------------------------------------------------- /example/android/app/src/main/java/videoplayer/example/MainApplication.kt: -------------------------------------------------------------------------------- 1 | package videoplayer.example 2 | 3 | import android.app.Application 4 | import android.content.res.Configuration 5 | 6 | import com.facebook.react.PackageList 7 | import com.facebook.react.ReactApplication 8 | import com.facebook.react.ReactNativeHost 9 | import com.facebook.react.ReactPackage 10 | import com.facebook.react.ReactHost 11 | import com.facebook.react.defaults.DefaultNewArchitectureEntryPoint.load 12 | import com.facebook.react.defaults.DefaultReactNativeHost 13 | import com.facebook.soloader.SoLoader 14 | 15 | import expo.modules.ApplicationLifecycleDispatcher 16 | import expo.modules.ReactNativeHostWrapper 17 | 18 | class MainApplication : Application(), ReactApplication { 19 | 20 | override val reactNativeHost: ReactNativeHost = ReactNativeHostWrapper( 21 | this, 22 | object : DefaultReactNativeHost(this) { 23 | override fun getPackages(): List { 24 | // Packages that cannot be autolinked yet can be added manually here, for example: 25 | // packages.add(new MyReactNativePackage()); 26 | return PackageList(this).packages 27 | } 28 | 29 | override fun getJSMainModuleName(): String = ".expo/.virtual-metro-entry" 30 | 31 | override fun getUseDeveloperSupport(): Boolean = BuildConfig.DEBUG 32 | 33 | override val isNewArchEnabled: Boolean = BuildConfig.IS_NEW_ARCHITECTURE_ENABLED 34 | override val isHermesEnabled: Boolean = BuildConfig.IS_HERMES_ENABLED 35 | } 36 | ) 37 | 38 | override val reactHost: ReactHost 39 | get() = ReactNativeHostWrapper.createReactHost(applicationContext, reactNativeHost) 40 | 41 | override fun onCreate() { 42 | super.onCreate() 43 | SoLoader.init(this, false) 44 | if (BuildConfig.IS_NEW_ARCHITECTURE_ENABLED) { 45 | // If you opted-in for the New Architecture, we load the native entry point for this app. 46 | load() 47 | } 48 | ApplicationLifecycleDispatcher.onApplicationCreate(this) 49 | } 50 | 51 | override fun onConfigurationChanged(newConfig: Configuration) { 52 | super.onConfigurationChanged(newConfig) 53 | ApplicationLifecycleDispatcher.onConfigurationChanged(this, newConfig) 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /docs/docusaurus.config.ts: -------------------------------------------------------------------------------- 1 | import { themes as prismThemes } from 'prism-react-renderer'; 2 | import type { Config, ThemeConfig } from '@docusaurus/types'; 3 | import type * as Preset from '@docusaurus/preset-classic'; 4 | 5 | // This runs in Node.js - Don't use client-side code here (browser APIs, JSX...) 6 | 7 | const config: Config = { 8 | title: 'React Native Video Player', 9 | favicon: 'img/favicon.png', 10 | // Set the production url of your site here 11 | url: 'https://docs.thewidlarzgroup.com', 12 | baseUrl: '/react-native-video-player/', 13 | 14 | organizationName: 'TheWidlarzGroup', // Usually your GitHub org/user name. 15 | projectName: 'react-native-video-player', // Usually your repo name. 16 | 17 | onBrokenLinks: 'throw', 18 | onBrokenMarkdownLinks: 'warn', 19 | 20 | // Even if you don't use internationalization, you can use this field to set 21 | // useful metadata like html lang. For example, if your site is Chinese, you 22 | // may want to replace "en" with "zh-Hans". 23 | i18n: { 24 | defaultLocale: 'en', 25 | locales: ['en'], 26 | }, 27 | 28 | presets: [ 29 | [ 30 | 'classic', 31 | { 32 | docs: { 33 | sidebarPath: './sidebars.ts', 34 | editUrl: 35 | 'https://github.com/TheWidlarzGroup/react-native-video-player/tree/master/docs/', 36 | }, 37 | theme: { 38 | customCss: './src/css/custom.css', 39 | }, 40 | } satisfies Preset.Options, 41 | ], 42 | ], 43 | 44 | themeConfig: { 45 | image: 'img/og-image.png', 46 | navbar: { 47 | title: '🎥 React Native Video Player', 48 | hideOnScroll: true, 49 | items: [ 50 | { 51 | type: 'docSidebar', 52 | sidebarId: 'docsSidebar', 53 | position: 'left', 54 | label: 'Documentation', 55 | }, 56 | { 57 | 'href': 58 | 'https://github.com/TheWidlarzGroup/react-native-video-player', 59 | // label: 'GitHub', 60 | 'position': 'right', 61 | 'className': 'header-github-link', 62 | 'aria-label': 'GitHub repository', 63 | }, 64 | ], 65 | }, 66 | prism: { 67 | theme: prismThemes.github, 68 | darkTheme: prismThemes.oceanicNext, 69 | }, 70 | } satisfies ThemeConfig, 71 | }; 72 | 73 | export default config; 74 | -------------------------------------------------------------------------------- /docs/src/components/HomepageFeatures/index.tsx: -------------------------------------------------------------------------------- 1 | import clsx from 'clsx'; 2 | import Heading from '@theme/Heading'; 3 | import styles from './styles.module.css'; 4 | 5 | type FeatureItem = { 6 | title: string; 7 | Svg: React.ComponentType>; 8 | description: JSX.Element; 9 | }; 10 | 11 | const FeatureList: FeatureItem[] = [ 12 | { 13 | title: 'Focus on Customization', 14 | Svg: require('@site/static/img/customization.svg').default, 15 | description: ( 16 | <> 17 | With built-in, customizable UI components, you can quickly tailor the 18 | video player to match your app's design and style, allowing you to focus 19 | more on your app's core features and user experience. 20 | 21 | ), 22 | }, 23 | { 24 | title: 'Powered by react-native-video', 25 | Svg: require('@site/static/img/rely-on-rnv.svg').default, 26 | description: ( 27 | <> 28 | Built on the reliable react-native-video foundation, this 29 | library enhances functionality and reliability, while also giving you 30 | the flexibility to extend it further as needed. 31 | 32 | ), 33 | }, 34 | { 35 | title: 'Easy to Use', 36 | Svg: require('@site/static/img/easy-to-use.svg').default, 37 | description: ( 38 | <> 39 | react-native-video-player makes video integration simple with custom 40 | controls and support for all react-native-video props, 41 | letting you easily switch your existing Video components. 42 | 43 | ), 44 | }, 45 | ]; 46 | 47 | function Feature({ title, Svg, description }: FeatureItem) { 48 | return ( 49 |
50 |
51 | 52 |
53 |
54 | {title} 55 |

{description}

56 |
57 |
58 | ); 59 | } 60 | 61 | export default function HomepageFeatures(): JSX.Element { 62 | return ( 63 |
64 |
65 |
66 | {FeatureList.map((props, idx) => ( 67 | 68 | ))} 69 |
70 |
71 |
72 | ); 73 | } 74 | -------------------------------------------------------------------------------- /example/android/app/src/main/java/videoplayer/example/MainActivity.kt: -------------------------------------------------------------------------------- 1 | package videoplayer.example 2 | 3 | import android.os.Build 4 | import android.os.Bundle 5 | 6 | import com.facebook.react.ReactActivity 7 | import com.facebook.react.ReactActivityDelegate 8 | import com.facebook.react.defaults.DefaultNewArchitectureEntryPoint.fabricEnabled 9 | import com.facebook.react.defaults.DefaultReactActivityDelegate 10 | 11 | import expo.modules.ReactActivityDelegateWrapper 12 | 13 | class MainActivity : ReactActivity() { 14 | override fun onCreate(savedInstanceState: Bundle?) { 15 | // Set the theme to AppTheme BEFORE onCreate to support 16 | // coloring the background, status bar, and navigation bar. 17 | // This is required for expo-splash-screen. 18 | setTheme(R.style.AppTheme); 19 | super.onCreate(null) 20 | } 21 | 22 | /** 23 | * Returns the name of the main component registered from JavaScript. This is used to schedule 24 | * rendering of the component. 25 | */ 26 | override fun getMainComponentName(): String = "main" 27 | 28 | /** 29 | * Returns the instance of the [ReactActivityDelegate]. We use [DefaultReactActivityDelegate] 30 | * which allows you to enable New Architecture with a single boolean flags [fabricEnabled] 31 | */ 32 | override fun createReactActivityDelegate(): ReactActivityDelegate { 33 | return ReactActivityDelegateWrapper( 34 | this, 35 | BuildConfig.IS_NEW_ARCHITECTURE_ENABLED, 36 | object : DefaultReactActivityDelegate( 37 | this, 38 | mainComponentName, 39 | fabricEnabled 40 | ){}) 41 | } 42 | 43 | /** 44 | * Align the back button behavior with Android S 45 | * where moving root activities to background instead of finishing activities. 46 | * @see onBackPressed 47 | */ 48 | override fun invokeDefaultOnBackPressed() { 49 | if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.R) { 50 | if (!moveTaskToBack(false)) { 51 | // For non-root activities, use the default implementation to finish them. 52 | super.invokeDefaultOnBackPressed() 53 | } 54 | return 55 | } 56 | 57 | // Use the default back button implementation on Android S 58 | // because it's doing more than [Activity.moveTaskToBack] in fact. 59 | super.invokeDefaultOnBackPressed() 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /example/ios/example/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CADisableMinimumFrameDurationOnPhone 6 | 7 | CFBundleDevelopmentRegion 8 | $(DEVELOPMENT_LANGUAGE) 9 | CFBundleDisplayName 10 | example 11 | CFBundleExecutable 12 | $(EXECUTABLE_NAME) 13 | CFBundleIdentifier 14 | $(PRODUCT_BUNDLE_IDENTIFIER) 15 | CFBundleInfoDictionaryVersion 16 | 6.0 17 | CFBundleName 18 | $(PRODUCT_NAME) 19 | CFBundlePackageType 20 | $(PRODUCT_BUNDLE_PACKAGE_TYPE) 21 | CFBundleShortVersionString 22 | 1.0.0 23 | CFBundleSignature 24 | ???? 25 | CFBundleURLTypes 26 | 27 | 28 | CFBundleURLSchemes 29 | 30 | videoplayer.example 31 | 32 | 33 | 34 | CFBundleVersion 35 | 1 36 | LSRequiresIPhoneOS 37 | 38 | NSAppTransportSecurity 39 | 40 | NSAllowsArbitraryLoads 41 | 42 | NSAllowsLocalNetworking 43 | 44 | 45 | UILaunchStoryboardName 46 | SplashScreen 47 | UIRequiredDeviceCapabilities 48 | 49 | arm64 50 | 51 | UIRequiresFullScreen 52 | 53 | UIStatusBarStyle 54 | UIStatusBarStyleDefault 55 | UISupportedInterfaceOrientations 56 | 57 | UIInterfaceOrientationPortrait 58 | UIInterfaceOrientationPortraitUpsideDown 59 | 60 | UISupportedInterfaceOrientations~ipad 61 | 62 | UIInterfaceOrientationPortrait 63 | UIInterfaceOrientationPortraitUpsideDown 64 | UIInterfaceOrientationLandscapeLeft 65 | UIInterfaceOrientationLandscapeRight 66 | 67 | UIUserInterfaceStyle 68 | Light 69 | UIViewControllerBasedStatusBarAppearance 70 | 71 | 72 | -------------------------------------------------------------------------------- /example/android/gradle.properties: -------------------------------------------------------------------------------- 1 | # Project-wide Gradle settings. 2 | 3 | # IDE (e.g. Android Studio) users: 4 | # Gradle settings configured through the IDE *will override* 5 | # any settings specified in this file. 6 | 7 | # For more details on how to configure your build environment visit 8 | # http://www.gradle.org/docs/current/userguide/build_environment.html 9 | 10 | # Specifies the JVM arguments used for the daemon process. 11 | # The setting is particularly useful for tweaking memory settings. 12 | # Default value: -Xmx512m -XX:MaxMetaspaceSize=256m 13 | org.gradle.jvmargs=-Xmx2048m -XX:MaxMetaspaceSize=512m 14 | 15 | # When configured, Gradle will run in incubating parallel mode. 16 | # This option should only be used with decoupled projects. More details, visit 17 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects 18 | # org.gradle.parallel=true 19 | 20 | # AndroidX package structure to make it clearer which packages are bundled with the 21 | # Android operating system, and which are packaged with your app's APK 22 | # https://developer.android.com/topic/libraries/support-library/androidx-rn 23 | android.useAndroidX=true 24 | 25 | # Automatically convert third-party libraries to use AndroidX 26 | android.enableJetifier=true 27 | 28 | # Enable AAPT2 PNG crunching 29 | android.enablePngCrunchInReleaseBuilds=true 30 | 31 | # Use this property to specify which architecture you want to build. 32 | # You can also override it from the CLI using 33 | # ./gradlew -PreactNativeArchitectures=x86_64 34 | reactNativeArchitectures=armeabi-v7a,arm64-v8a,x86,x86_64 35 | 36 | # Use this property to enable support to the new architecture. 37 | # This will allow you to use TurboModules and the Fabric render in 38 | # your application. You should enable this flag either if you want 39 | # to write custom TurboModules/Fabric components OR use libraries that 40 | # are providing them. 41 | newArchEnabled=false 42 | 43 | # Use this property to enable or disable the Hermes JS engine. 44 | # If set to false, you will be using JSC instead. 45 | hermesEnabled=true 46 | 47 | # Enable GIF support in React Native images (~200 B increase) 48 | expo.gif.enabled=true 49 | # Enable webp support in React Native images (~85 KB increase) 50 | expo.webp.enabled=true 51 | # Enable animated webp support (~3.4 MB increase) 52 | # Disabled by default because iOS doesn't support animated webp 53 | expo.webp.animated=false 54 | 55 | # Enable network inspector 56 | EX_DEV_CLIENT_NETWORK_INSPECTOR=true 57 | 58 | # Use legacy packaging to compress native libraries in the resulting APK. 59 | expo.useLegacyPackaging=false 60 | -------------------------------------------------------------------------------- /src/Thumbnail.tsx: -------------------------------------------------------------------------------- 1 | import { 2 | Image, 3 | ImageBackground, 4 | type ImageSourcePropType, 5 | StyleSheet, 6 | TouchableOpacity, 7 | } from 'react-native'; 8 | import type { CustomStyles, VideoPlayerProps } from './index'; 9 | import { memo } from 'react'; 10 | 11 | interface StartButtonProps { 12 | onStart: () => void; 13 | customStylesPlayButton: CustomStyles['playButton']; 14 | customStylesPlayArrow: CustomStyles['playArrow']; 15 | } 16 | 17 | interface ThumbnailProps extends StartButtonProps { 18 | thumbnailSource: ImageSourcePropType; 19 | style: VideoPlayerProps['style']; 20 | sizeStyles: { height: number; width: number }; 21 | onStart: () => void; 22 | customStylesThumbnail: CustomStyles['thumbnail']; 23 | customStylesThumbnailImage: CustomStyles['thumbnailImage']; 24 | customStylesPlayButton: CustomStyles['playButton']; 25 | customStylesPlayArrow: CustomStyles['playArrow']; 26 | } 27 | 28 | export const StartButton = ({ 29 | onStart, 30 | customStylesPlayButton, 31 | customStylesPlayArrow, 32 | }: StartButtonProps) => { 33 | return ( 34 | 38 | 42 | 43 | ); 44 | }; 45 | 46 | export const Thumbnail = memo( 47 | ({ 48 | thumbnailSource, 49 | style, 50 | sizeStyles, 51 | onStart, 52 | customStylesThumbnail, 53 | customStylesThumbnailImage, 54 | customStylesPlayButton, 55 | customStylesPlayArrow, 56 | }: ThumbnailProps) => { 57 | return ( 58 | 63 | 68 | 69 | ); 70 | } 71 | ); 72 | 73 | const styles = StyleSheet.create({ 74 | thumbnail: { 75 | backgroundColor: 'black', 76 | justifyContent: 'center', 77 | alignItems: 'center', 78 | }, 79 | playButton: { 80 | backgroundColor: 'rgba(0, 0, 0, 0.6)', 81 | borderRadius: 32, 82 | width: 64, 83 | height: 64, 84 | justifyContent: 'center', 85 | alignItems: 'center', 86 | }, 87 | playArrow: { 88 | width: 28, 89 | height: 28, 90 | marginLeft: 2, 91 | }, 92 | }); 93 | -------------------------------------------------------------------------------- /docs/src/css/custom.css: -------------------------------------------------------------------------------- 1 | /** 2 | * Any CSS included here will be global. The classic template 3 | * bundles Infima by default. Infima is a CSS framework designed to 4 | * work well for content-centric websites. 5 | */ 6 | 7 | /* You can override the default Infima variables here. */ 8 | :root { 9 | --ifm-color-primary: #4542dc; 10 | --ifm-color-primary-dark: #29784c; 11 | --ifm-color-primary-darker: #277148; 12 | --ifm-color-primary-darkest: #205d3b; 13 | --ifm-color-primary-light: #33925d; 14 | --ifm-color-primary-lighter: #359962; 15 | --ifm-color-primary-lightest: #3cad6e; 16 | --ifm-color-primary-warning: #e63946; 17 | --ifm-color-primary-black: #171717; 18 | --ifm-color-primary-white: #ffffff; 19 | 20 | --ifm-code-font-size: 95%; 21 | --docusaurus-highlighted-code-line-bg: rgba(0, 0, 0, 0.1); 22 | } 23 | 24 | /* For readability concerns, you should choose a lighter palette in dark mode. */ 25 | [data-theme='dark'] { 26 | --ifm-color-primary: #87ccef; 27 | --ifm-color-primary-dark: #70add2; 28 | --ifm-color-primary-darker: #5a8eb4; 29 | --ifm-color-primary-darkest: #3f6585; 30 | --ifm-color-primary-light: #a3dbf2; 31 | --ifm-color-primary-lighter: #b9e4f6; 32 | --ifm-color-primary-lightest: #cfeaeb; 33 | --ifm-color-primary-warning: #e63946; 34 | --ifm-color-primary-black: #171717; 35 | --ifm-color-primary-white: #ffffff; 36 | --docusaurus-highlighted-code-line-bg: rgba(0, 0, 0, 0.3); 37 | } 38 | 39 | .header-github-link::before { 40 | content: ''; 41 | width: 24px; 42 | height: 24px; 43 | display: flex; 44 | background-color: var(--ifm-navbar-link-color); 45 | mask-image: url("data:image/svg+xml,%3Csvg viewBox='0 0 24 24' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1.523.105-3.176 0 0 1.005-.322 3.3 1.23.96-.267 1.98-.399 3-.405 1.02.006 2.04.138 3 .405 2.28-1.552 3.285-1.23 3.285-1.23.645 1.653.24 2.873.12 3.176.765.84 1.23 1.91 1.23 3.22 0 4.61-2.805 5.625-5.475 5.92.42.36.81 1.096.81 2.22 0 1.606-.015 2.896-.015 3.286 0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12'/%3E%3C/svg%3E"); 46 | transition: background-color var(--ifm-transition-fast) 47 | var(--ifm-transition-timing-default); 48 | } 49 | 50 | .header-github-link:hover::before { 51 | background-color: var(--ifm-navbar-link-hover-color); 52 | } 53 | 54 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # react-native-video-player 2 | 3 | 🎥 `` component for React Native with a few controls. This player uses [react-native-video](https://github.com/TheWidlarzGroup/react-native-video) under the hood 4 | 5 |
6 | 9 |
10 | 11 | ## Documentation 12 | documentation is available at [docs.thewidlarzgroup.com/react-native-video-player/](https://docs.thewidlarzgroup.com/react-native-video-player/) 13 | 14 | ## Installation 15 | 16 | ``` 17 | yarn add react-native-video-player react-native-video 18 | ``` 19 | 20 | or 21 | ``` 22 | npm install --save react-native-video-player react-native-video 23 | ``` 24 | 25 | Then, install pods 26 | ``` 27 | cd ios 28 | pod install 29 | ``` 30 | 31 | ## Example 32 | 33 | ```tsx 34 | import VideoPlayer, { type VideoPlayerRef } from 'react-native-video-player'; 35 | 36 | const playerRef = useRef(null); 37 | 38 | console.log(e)} 48 | showDuration={true} 49 | /> 50 | ``` 51 | 52 | ## Future features 53 | 54 | Check out our [Roadmap](https://github.com/TheWidlarzGroup/react-native-video-player/discussions/186) for what's coming up next! We're always working on new features and improvements, so stay tuned! 55 | 56 | ## Community support 57 | We have a discord server where you can ask questions and get help. [Join the discord server](https://discord.gg/WXuM4Tgb9X) 58 | 59 | ## Enterprise Support 60 |

61 | 📱 react-native-video-player is provided as it is. For enterprise support or other business inquiries, please contact us 🤝. We can help you with the integration, customization and maintenance. We are providing both free and commercial support for this project. let's build something awesome together! 🚀 62 |

63 | 64 | 65 | 66 | 67 | TheWidlarzGroup 68 | 69 | 70 | -------------------------------------------------------------------------------- /docs/docs/intro.md: -------------------------------------------------------------------------------- 1 | import useBaseUrl from '@docusaurus/useBaseUrl'; 2 | import ThemedImage from '@theme/ThemedImage'; 3 | 4 | # Introduction 5 | 6 | Welcome to **react-native-video-player**, a lightweight and user-friendly video player for React Native. Built on the reliable [react-native-video](https://github.com/TheWidlarzGroup/react-native-video), this library simplifies the integration of video playback with custom controls and enhanced functionality. Whether you're a seasoned developer or just starting with React Native, `react-native-video-player` offers a straightforward way to add rich video experiences to your app. 7 | 8 | ## Why Use react-native-video-player? 9 | 10 | When it comes to video playback, you need a solution that's powerful, flexible, and easy to use. Here’s what makes this library stand out: 11 | 12 | - **Custom Controls**: Ready-to-use, intuitive controls for seamless video playback. 13 | - **Compatibility**: Full support for all props from `react-native-video`, so you can easily adapt your existing components. 14 | - **Extensibility**: Customize the player to match your app’s unique design and user experience. 15 | - **Ease of Integration**: With minimal setup required, you can focus on what matters—your app’s features and functionality. 16 | 17 | ## Features at a Glance 18 | 19 | - Plug-and-play setup 20 | - Customizable controls for play, pause, seek, fullscreen, and more. 21 | - Thumbnail support for video previews and end screens. 22 | - Ref methods to control playback programmatically. 23 | - Built-in support for styling 24 | 25 | Whether you're creating a social media app, an e-learning platform, or a media player, `react-native-video-player` gives you the tools to deliver a high-quality video experience effortlessly. 26 | 27 | ## What’s Next? 28 | 29 | - [Installation](/docs/installation): Get started with just a few commands. 30 | - [Api](/docs/category/api): Explore all available props, styles, and customization options. 31 | - **Community**: Join our [Discord server](https://discord.gg/7Y6eE62hXM) to connect with other developers, ask questions, and share your feedback. 32 | - [Roadmap](https://github.com/TheWidlarzGroup/react-native-video-player/discussions/186): See what’s coming next for this library. 33 | - [Enterprise Support](https://www.thewidlarzgroup.com/?utm_source=rnvp&utm_medium=docs#Contact): Need professional help such as custom video solutions? Contact us for integration, customization, or maintenance support. 34 | 35 | We’re excited to have you onboard. Let’s build something awesome together! 🚀 36 | 37 | 44 | -------------------------------------------------------------------------------- /example/src/App.tsx: -------------------------------------------------------------------------------- 1 | import { useRef } from 'react'; 2 | import { 3 | View, 4 | Text, 5 | Button, 6 | SafeAreaView, 7 | ActivityIndicator, 8 | StyleSheet, 9 | } from 'react-native'; 10 | import VideoPlayer, { type VideoPlayerRef } from 'react-native-video-player'; 11 | import { ReactScan } from 'react-scan/native'; 12 | 13 | const App = () => { 14 | const playerRef = useRef(null); 15 | const progress = useRef(0); 16 | 17 | return ( 18 | 19 | 24 | 25 | React Native Video Player 26 | 27 | ( 44 | 51 | 52 | 53 | )} 54 | controlsTimeout={2000} 55 | onProgress={({ currentTime }) => { 56 | progress.current = currentTime; 57 | }} 58 | onError={(e) => console.log(e)} 59 | showDuration={true} 60 | ref={playerRef} 61 | /> 62 | 63 |