Repository: ihmpavel/expo-video-player
Branch: master
Commit: d9a71db1e9c7
Files: 34
Total size: 73.8 KB
Directory structure:
gitextract_337zigfa/
├── .eslintrc.js
├── .github/
│ ├── FUNDING.yml
│ ├── ISSUE_TEMPLATE/
│ │ ├── bug_report.md
│ │ └── feature_request.md
│ └── dependabot.yml
├── .gitignore
├── .npmignore
├── .prettierrc.js
├── .vscode/
│ └── settings.json
├── CHANGELOG.md
├── LICENSE
├── README.md
├── dist/
│ ├── constants.d.ts
│ ├── constants.js
│ ├── index.d.ts
│ ├── index.js
│ ├── props.d.ts
│ ├── props.js
│ ├── utils.d.ts
│ └── utils.js
├── example-app/
│ ├── .expo-shared/
│ │ └── assets.json
│ ├── .gitignore
│ ├── App.tsx
│ ├── app.json
│ ├── babel.config.js
│ ├── package.json
│ └── tsconfig.json
├── lib/
│ ├── constants.tsx
│ ├── index.tsx
│ ├── props.tsx
│ └── utils.tsx
├── migration-1x-to-2x.md
├── package.json
└── tsconfig.json
================================================
FILE CONTENTS
================================================
================================================
FILE: .eslintrc.js
================================================
// https://robertcooper.me/post/using-eslint-and-prettier-in-a-typescript-project
module.exports = {
parser: '@typescript-eslint/parser',
extends: [
'plugin:react/recommended',
'plugin:@typescript-eslint/recommended',
'plugin:@typescript-eslint/eslint-recommended',
'plugin:prettier/recommended',
],
parserOptions: {
ecmaVersion: 2020,
sourceType: 'module',
ecmaFeatures: {
jsx: true,
},
},
rules: {
'@typescript-eslint/semi': ['error', 'never'],
'@typescript-eslint/no-use-before-define': [
'error',
{ functions: false, classes: false, variables: false, typedefs: true },
],
'@typescript-eslint/explicit-function-return-type': 0,
'@typescript-eslint/prefer-interface': 0,
'@typescript-eslint/interface-name-prefix': 0,
'@typescript-eslint/no-non-null-assertion': 0,
'@typescript-eslint/explicit-module-boundary-types': 0,
'@typescript-eslint/camelcase': 0,
'@typescript-eslint/ban-ts-ignore': 0,
'@typescript-eslint/explicit-member-accessibility': 0,
semi: 'off',
eqeqeq: 'error',
'arrow-parens': ['error', 'as-needed'],
'no-use-before-define': ['error', { functions: false, classes: false, variables: false }],
'prefer-arrow-callback': 1,
'no-use-before-define': 0,
'max-len': ['warn', { code: 100, ignoreComments: true, ignorePattern: '^import .*' }],
'new-parens': 'error',
'no-bitwise': 'error',
'no-console': ['warn', { allow: ['warn', 'info', 'error'] }],
'no-caller': 'error',
'no-multiple-empty-lines': ['error', { max: 2, maxEOF: 1, maxBOF: 0 }],
'quote-props': ['error', 'as-needed'],
'sort-imports-es6-autofix/sort-imports-es6': [
2,
{
ignoreCase: false,
ignoreMemberSort: false,
memberSyntaxSortOrder: ['none', 'all', 'multiple', 'single'],
},
],
'no-irregular-whitespace': 'warn',
'react/jsx-uses-react': 'off',
'react/react-in-jsx-scope': 'off',
'react/prop-types': 'off',
},
plugins: ['sort-imports-es6-autofix', 'react-hooks'],
settings: {
react: {
version: 'detect',
},
},
}
================================================
FILE: .github/FUNDING.yml
================================================
github: ihmpavel
================================================
FILE: .github/ISSUE_TEMPLATE/bug_report.md
================================================
---
name: Bug report
about: Create a report to help us improve
title: ''
labels: bug
assignees: ''
---
**Describe the bug**
A clear and concise description of what the bug is.
**To Reproduce**
Steps to reproduce the behavior:
1. Go to '...'
2. Click on '....'
3. Scroll down to '....'
4. See error
Link to reproduction on (Snack)[https://snack.expo.io/]
**Expected behavior**
A clear and concise description of what you expected to happen.
**Additional information:**
- Type: [e.g. Simulator/Expo/Snack/Real device]
- Device: [e.g. iPhone X]
- OS: [e.g. iOS8.1]
- Package version [e.g. 1.0.0]
- Expo version (in `app.json`)
- Expo CLI version
**Additional context**
Add any other context about the problem here.
**Screenshots** (if applicable)
================================================
FILE: .github/ISSUE_TEMPLATE/feature_request.md
================================================
---
name: Feature request
about: Suggest an idea for this project
title: ''
labels: ''
assignees: ''
---
**Is your feature request related to a problem? Please describe.**
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
**Describe the solution you'd like**
A clear and concise description of what you want to happen.
**Describe alternatives you've considered**
A clear and concise description of any alternative solutions or features you've considered.
**Additional context**
Add any other context or screenshots about the feature request here.
================================================
FILE: .github/dependabot.yml
================================================
version: 2
updates:
- package-ecosystem: npm
directory: "/"
schedule:
interval: weekly
time: "04:00"
open-pull-requests-limit: 10
================================================
FILE: .gitignore
================================================
node_modules/**/*
================================================
FILE: .npmignore
================================================
lib/
example-app/
.vscode/
.github/
.eslintrc.js
.prettierrc.js
tsconfig.json
jest.config.js
================================================
FILE: .prettierrc.js
================================================
module.exports = {
semi: false,
useTabs: false,
trailingComma: "es5",
singleQuote: true,
printWidth: 100,
tabWidth: 2,
arrowParens: "avoid",
jsxSingleQuote: true
};
================================================
FILE: .vscode/settings.json
================================================
{
"typescript.tsdk": "node_modules\\typescript\\lib",
"eslint.autoFixOnSave": true,
"eslint.validate": [
"javascript",
"javascriptreact",
{
"language": "typescript",
"autoFix": true
},
{
"language": "typescriptreact",
"autoFix": true
}
],
"editor.formatOnSave": true,
"[javascript]": {
"editor.formatOnSave": false,
},
"[javascriptreact]": {
"editor.formatOnSave": false,
},
"[typescript]": {
"editor.formatOnSave": false,
},
"[typescriptreact]": {
"editor.formatOnSave": false,
},
"editor.codeActionsOnSave": {
"source.fixAll.eslint": true
},
}
================================================
FILE: CHANGELOG.md
================================================
# ChangeLog
## 2.2.0 (September 29, 2022)
- Fix: Prevent accidental pressing of buttons in overlay header when the overlay is not visible by [@lpezzolla](https://github.com/lpezzolla) [#724](https://github.com/ihmpavel/expo-video-player/pull/724)
- Fix: Use fullscreen icons passed in props as an alternative to package-defined icons by [@lpezzolla](https://github.com/lpezzolla) [#727](https://github.com/ihmpavel/expo-video-player/pull/727)
## 2.1.0 (June 24, 2022)
- Enhancements: Updated packages and bumped Expo SDK version
- Enhancements: Added `mute` functionality
## 2.0.4 (January 24, 2021)
- Fix: Replay icon on iOS [#469](https://github.com/ihmpavel/expo-video-player/issues/469)
## 2.0.3 (December 8, 2021)
- Fix: Rebuild app to include `header` on top of the component instead of bottom
## 2.0.2 (December 4, 2021)
- Enhancements: Updated packages and bumped Expo SDK version
- Enhancements: Added `autoHidePlayer` by [@hungvu193](https://github.com/hungvu193) [#506](https://github.com/ihmpavel/expo-video-player/pull/506)
- Enhancements: Added `header` by [@Qeepsake](https://github.com/Qeepsake) [#516](https://github.com/ihmpavel/expo-video-player/pull/516)
## 2.0.1 (June 27, 2021)
- Fix: Expo Web [#433](https://github.com/ihmpavel/expo-video-player/issues/433)
## 2.0.0 (June 20, 2021)
- Rewritten, simplified
- If you are upgrading from version `1.x`, please check [Migration guide to version 2](https://github.com/ihmpavel/expo-video-player/blob/master/migration-1x-to-2x.md)
## 1.6.1 (October 10, 2020)
- Enhancements: Updated packages and bumped Expo SDK version
## 1.6.0 (August 19, 2020)
- Fix: Renamed iosThumbImage to thumbImage
- Enhancements: Remove deprecated Slider in favor of [community version](https://github.com/react-native-community/react-native-slider)
- Enhancements: Added videoRef prop
## 1.5.8 (May 6, 2020)
- Enhancements: Allow disabling Slider
## 1.5.7 (January 31, 2020)
- Fix: Revert removing depracated Slider from RN Core
## 1.5.6 (January 29, 2020)
- Fix: Switch inFullscreen logic
- Enhancements: Remove deprecated Slider
## 1.5.5 (January 1, 2020)
- Happy new Year 🎉
- Fix: Simplify logic
## 1.5.4 (December 29, 2019)
- Fix: Building
## 1.5.3 (December 29, 2019)
- Fix: TypeScript types
- Enhancements: Updated README
## 1.5.2 (December 20, 2019)
- Enhancements: Expo SDK 36
- Enhancements: Updated README
## 1.5.1 (September 30, 2019)
- Fix: Play/Pause icon clicking
## 1.5.0 (August 27, 2019)
- Enhancements: Human readable debug
- Enhancements: Renamed `isPortrait` to `inFullscreen`
- Fix: Removed buggy internet status debug
## 1.4.0 (August 27, 2019)
- Enhancement: Added width/height props to `` [#7](https://github.com/ihmpavel/expo-video-player/issues/7)
- Enhancement: Added `videoBackground` prop
- Enhancement: Added more video examples
- Enhancement: Checking internet status with hooks
## 1.3.1 (August 25, 2019)
- Fix: Do not add to npm registry Lint source files
## 1.3.0 (August 25, 2019)
- Enhancement: Added changelog
- Enhancement: Fully rewritten, code cleanup
- Enhancement: Rewritten `example app`, now in TS
- Fix: Add setAudioModeAsync key [#2](https://github.com/ihmpavel/expo-video-player/issues/2)
- Fix: Updated Expo [#3](https://github.com/ihmpavel/expo-video-player/issues/3)
## 1.2.0 (April 12, 2019)
- Enhancement: Refactored code
## 1.1.1 (April 12, 2019)
- Enhancement: Updated dependencies
## 1.1.0 (April 12, 2019)
- Fix: Crashing app
## 1.0.0 (December 22, 2018)
- Initial release 🙌🤗
================================================
FILE: LICENSE
================================================
MIT License
Copyright (c) 2021 @ihmpavel/expo-video-player
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
================================================
FILE: README.md
================================================
# Basic info
Video wrappper component for Expo ecosystem built on top of the Expo's [Video component](https://docs.expo.io/versions/latest/sdk/video/). This library basically adds UI controls like in the YouTube app, which gives you the opportunity to play, pause, replay, change video position and a lot of styling options.
The package has a lot of configuration options to fit all your needs. Only `source` in `videoProps: { source: {} }` is required. Check the Props table below.
For compatibility information, scroll down to Compatibility. The FAQ is here
## ⚠️ Updating from version 1.x to 2.x
If you are updating from version 1.x to 2.x, there are some breaking changes in the API. Please visit [Migration guide to version 2](https://github.com/ihmpavel/expo-video-player/blob/master/migration-1x-to-2x.md) to make your transition as easy as possible. In version 2.x [@react-native-community/netinfo](https://github.com/react-native-netinfo/react-native-netinfo) has been removed.
## Installation
- Install Video Player component typing into terminal `yarn add expo-video-player` _or_ `npm install expo-video-player`
- You also need `expo-av` and `@react-native-community/slider`. Install them with `expo-cli` (`expo install expo-av @react-native-community/slider`)
## Usage
The showcase of some of the possibilities you can create is in the folder [example-app](https://github.com/ihmpavel/expo-video-player/blob/master/example-app). There is Fullscreen, ref, local file, custom icons, styling...
Minimal code to make `VideoPlayer` working
```
import { ResizeMode } from 'expo-av'
import VideoPlayer from 'expo-video-player'
```
## Props
For default prop values, please visit [/lib/props.tsx](https://github.com/ihmpavel/expo-video-player/blob/master/lib/props.tsx#L11)
| Property | Type | Description |
| ---- | :-------: | ----------- |
| **videoProps** | [`VideoProps`](https://docs.expo.io/versions/latest/sdk/video/#props) | At least `source` is required |
| **errorCallback** | (error: ErrorType) => void | Function which is fired when an error occurs |
| **playbackCallback** | (status: AVPlaybackStatus) => void | Function which is fired every time `onPlaybackStatusUpdate` occurs |
| **defaultControlsVisible** | `boolean` | Show controls on darker overlay when video starts playing. Default is `false` |
| **timeVisible** | `boolean` | Show current time and final length in the bottom. Default is `true` |
| **textStyle** | `TextStyle` | Object containing `` styling |
| **slider** | `{ visible?: boolean } & SliderProps` | Object containing any of [@react-native-community/slider](https://github.com/callstack/react-native-slider) props. Your styling may break default layout. Also hide slider by providing `visible: false` prop. You are unable to overwrite `ref`, `value`, `onSlidingStart` and `onSlidingComplete` |
| **activityIndicator** | `ActivityIndicatorProps` | Any values from [ActivityIndicator](https://reactnative.dev/docs/activityindicator) |
| **animation** | `{ fadeInDuration?: number, fadeOutDuration?: number }` | Duration of animations in milliseconds |
| **style** | `{ width?: number, height?: number, videoBackgroundColor?: ColorValue, controlsBackgroundColor?: ColorValue }` | Basic styling of `` |
| **icon** | `{ size?: number, color?: ColorValue, style?: TextStyle, pause?: JSX.Element, play?: JSX.Element, replay?: JSX.Element, fullscreen?: JSX.Element, exitFullscreen?: JSX.Element, mute?: JSX.Element, exitMute?: JSX.Element }` | Icon styling. Check more in the [example-app](https://github.com/ihmpavel/expo-video-player/blob/master/example-app/App.tsx) |
| **fullscreen** | `{ enterFullscreen?: () => void, exitFullscreen?: () => void, inFullscreen?: boolean, visible?: boolean }` | Usage of `Fullscreen` mode is in the [example-app](https://github.com/ihmpavel/expo-video-player/blob/master/example-app/App.tsx#L182) |
| **autoHidePlayer** | `boolean` | Prevent player from hiding after certain time, by setting it to `false` you need to tap the screen again to hide the player. Default is `true` |
| **header** | `ReactNode` | Render header component same as in YouTube app. Default `undefined` |
| **mute** | `{ enterMute?: () => void, exitMute?: () => void, isMute?: boolean, visible?: boolean }` | Usage of `mute` mode is in the [example-app](example-app/App.tsx) |
## Compatibility
Library version | Expo SDK version
---- | -------
2.1.x | >= SDK 45
2.x.x | >= SDK 38
1.6.x | >= SDK 38
1.5.x | >= SDK 34
1.4.x | >= SDK 34
1.3.x | >= SDK 34
1.2.x | >= SDK 33
1.1.x | >= SDK 32
1.x.x | >= SDK 32
### CHANGELOG
Changelog added in version 1.3.0
Read [CHANGELOG.md](https://github.com/ihmpavel/expo-video-player/blob/master/CHANGELOG.md)
### FAQ
- **How to make fullscreen working?** Please visit [example-app](https://github.com/ihmpavel/expo-video-player/blob/master/example-app/App.tsx#L182)
- **How to use ref?** Please visit [example-app](https://github.com/ihmpavel/expo-video-player/blob/master/example-app/App.tsx)
- **What to do if I disconnect from the internet while playing video from remote source?** You need to stop/pause playback yourself. I highly recommend using [@react-native-community/netinfo](https://github.com/react-native-netinfo/react-native-netinfo) for this kind of stuff
- **Do you support subtitles?** Have a look at [#1](https://github.com/ihmpavel/expo-video-player/issues/1)
- **Can I support you?** Yes, please [Become a sponsor](https://github.com/sponsors/ihmpavel)
### TODO
- [ ] make tests
#### Some articles
- Inspired by [expo/videoplayer](https://github.com/expo/videoplayer) _(already deprecated)_
- [Typescript default props](https://github.com/typescript-cheatsheets/react/issues/415)
- [Creating a typescript module](https://codeburst.io/https-chidume-nnamdi-com-npm-module-in-typescript-12b3b22f0724)
- [Creating a component for React](https://medium.com/@BrodaNoel/how-to-create-a-react-component-and-publish-it-in-npm-668ad7d363ce)
## More packages from me
- [all-iso-language-codes](https://github.com/ihmpavel/all-iso-language-codes) - List of ISO 639-1, 639-2T, 639-2B and 639-3 codes with translations in all available languages
- [expo-video-player](https://github.com/ihmpavel/expo-video-player) - Customizable Video Player controls for Expo
- [free-email-domains-list](https://github.com/ihmpavel/free-email-domains-list) - Fresh list of all free email domain providers. Can be used to check if an email address belongs to a company. Updated weekly
================================================
FILE: dist/constants.d.ts
================================================
export declare enum ControlStates {
Visible = "Visible",
Hidden = "Hidden"
}
export declare enum PlaybackStates {
Loading = "Loading",
Playing = "Playing",
Paused = "Paused",
Buffering = "Buffering",
Error = "Error",
Ended = "Ended"
}
export declare enum ErrorSeverity {
Fatal = "Fatal",
NonFatal = "NonFatal"
}
export declare type ErrorType = {
type: ErrorSeverity;
message: string;
obj: Record;
};
================================================
FILE: dist/constants.js
================================================
export var ControlStates;
(function (ControlStates) {
ControlStates["Visible"] = "Visible";
ControlStates["Hidden"] = "Hidden";
})(ControlStates || (ControlStates = {}));
export var PlaybackStates;
(function (PlaybackStates) {
PlaybackStates["Loading"] = "Loading";
PlaybackStates["Playing"] = "Playing";
PlaybackStates["Paused"] = "Paused";
PlaybackStates["Buffering"] = "Buffering";
PlaybackStates["Error"] = "Error";
PlaybackStates["Ended"] = "Ended";
})(PlaybackStates || (PlaybackStates = {}));
export var ErrorSeverity;
(function (ErrorSeverity) {
ErrorSeverity["Fatal"] = "Fatal";
ErrorSeverity["NonFatal"] = "NonFatal";
})(ErrorSeverity || (ErrorSeverity = {}));
================================================
FILE: dist/index.d.ts
================================================
import { AVPlaybackStatus } from 'expo-av';
import { Props } from './props';
import React from 'react';
declare const VideoPlayer: {
(tempProps: Props): JSX.Element;
defaultProps: {
errorCallback: (error: import("./constants").ErrorType) => void;
playbackCallback: (status: AVPlaybackStatus) => void;
defaultControlsVisible: boolean;
timeVisible: boolean;
textStyle: import("react-native").TextStyle;
slider: {
visible?: boolean | undefined;
} & import("@react-native-community/slider").SliderProps;
activityIndicator: import("react-native").ActivityIndicatorProps;
animation: {
fadeInDuration?: number | undefined;
fadeOutDuration?: number | undefined;
};
header: React.ReactNode;
style: {
width?: number | undefined;
height?: number | undefined;
videoBackgroundColor?: import("react-native").ColorValue | undefined;
controlsBackgroundColor?: import("react-native").ColorValue | undefined;
};
icon: {
size?: number | undefined;
color?: import("react-native").ColorValue | undefined;
style?: import("react-native").TextStyle | undefined;
pause?: JSX.Element | undefined;
play?: JSX.Element | undefined;
replay?: JSX.Element | undefined;
loading?: JSX.Element | undefined;
fullscreen?: JSX.Element | undefined;
exitFullscreen?: JSX.Element | undefined;
mute?: JSX.Element | undefined;
exitMute?: JSX.Element | undefined;
};
fullscreen: {
enterFullscreen?: (() => void) | undefined;
exitFullscreen?: (() => void) | undefined;
inFullscreen?: boolean | undefined;
visible?: boolean | undefined;
};
autoHidePlayer: boolean;
mute: {
enterMute?: (() => void) | undefined;
exitMute?: (() => void) | undefined;
isMute?: boolean | undefined;
visible?: boolean | undefined;
};
};
};
export default VideoPlayer;
================================================
FILE: dist/index.js
================================================
import { __awaiter, __rest } from "tslib";
import { Audio, Video } from 'expo-av';
import { ActivityIndicator, Animated, StyleSheet, Text, TouchableWithoutFeedback, View, } from 'react-native';
import { ControlStates, ErrorSeverity, PlaybackStates } from './constants';
import { ErrorMessage, TouchableButton, deepMerge, getMinutesSecondsFromMilliseconds, styles, } from './utils';
import { MaterialIcons } from '@expo/vector-icons';
import { defaultProps } from './props';
import { useEffect, useRef, useState } from 'react';
import React from 'react';
import Slider from '@react-native-community/slider';
const VideoPlayer = (tempProps) => {
const props = deepMerge(defaultProps, tempProps);
let playbackInstance = null;
let controlsTimer = null;
let initialShow = props.defaultControlsVisible;
const header = props.header;
const [errorMessage, setErrorMessage] = useState('');
const controlsOpacity = useRef(new Animated.Value(props.defaultControlsVisible ? 1 : 0)).current;
const [controlsState, setControlsState] = useState(props.defaultControlsVisible ? ControlStates.Visible : ControlStates.Hidden);
const [playbackInstanceInfo, setPlaybackInstanceInfo] = useState({
position: 0,
duration: 0,
state: props.videoProps.source ? PlaybackStates.Loading : PlaybackStates.Error,
});
// We need to extract ref, because of misstypes in
// eslint-disable-next-line @typescript-eslint/no-unused-vars
const _a = props.slider, { ref: sliderRef } = _a, sliderProps = __rest(_a, ["ref"]);
const screenRatio = props.style.width / props.style.height;
let videoHeight = props.style.height;
let videoWidth = videoHeight * screenRatio;
if (videoWidth > props.style.width) {
videoWidth = props.style.width;
videoHeight = videoWidth / screenRatio;
}
useEffect(() => {
setAudio();
return () => {
if (playbackInstance) {
playbackInstance.setStatusAsync({
shouldPlay: false,
});
}
};
}, []);
useEffect(() => {
if (!props.videoProps.source) {
console.error('[VideoPlayer] `Source` is a required in `videoProps`. ' +
'Check https://docs.expo.io/versions/latest/sdk/video/#usage');
setErrorMessage('`Source` is a required in `videoProps`');
setPlaybackInstanceInfo(Object.assign(Object.assign({}, playbackInstanceInfo), { state: PlaybackStates.Error }));
}
else {
setPlaybackInstanceInfo(Object.assign(Object.assign({}, playbackInstanceInfo), { state: PlaybackStates.Playing }));
}
}, [props.videoProps.source]);
const hideAnimation = () => {
Animated.timing(controlsOpacity, {
toValue: 0,
duration: props.animation.fadeOutDuration,
useNativeDriver: true,
}).start(({ finished }) => {
if (finished) {
setControlsState(ControlStates.Hidden);
}
});
};
const animationToggle = () => {
if (controlsState === ControlStates.Hidden) {
Animated.timing(controlsOpacity, {
toValue: 1,
duration: props.animation.fadeInDuration,
useNativeDriver: true,
}).start(({ finished }) => {
if (finished) {
setControlsState(ControlStates.Visible);
}
});
}
else if (controlsState === ControlStates.Visible) {
hideAnimation();
}
if (controlsTimer === null && props.autoHidePlayer) {
controlsTimer = setTimeout(() => {
if (playbackInstanceInfo.state === PlaybackStates.Playing &&
controlsState === ControlStates.Hidden) {
hideAnimation();
}
if (controlsTimer) {
clearTimeout(controlsTimer);
}
controlsTimer = null;
}, 2000);
}
};
// Set audio mode to play even in silent mode (like the YouTube app)
const setAudio = () => __awaiter(void 0, void 0, void 0, function* () {
try {
yield Audio.setAudioModeAsync({
playsInSilentModeIOS: true,
});
}
catch (e) {
props.errorCallback({
type: ErrorSeverity.NonFatal,
message: 'Audio.setAudioModeAsync',
obj: e,
});
}
});
const updatePlaybackCallback = (status) => {
props.playbackCallback(status);
if (status.isLoaded) {
setPlaybackInstanceInfo(Object.assign(Object.assign({}, playbackInstanceInfo), { position: status.positionMillis, duration: status.durationMillis || 0, state: status.positionMillis === status.durationMillis
? PlaybackStates.Ended
: status.isBuffering
? PlaybackStates.Buffering
: status.shouldPlay
? PlaybackStates.Playing
: PlaybackStates.Paused }));
if ((status.didJustFinish && controlsState === ControlStates.Hidden) ||
(status.isBuffering && controlsState === ControlStates.Hidden && initialShow)) {
animationToggle();
initialShow = false;
}
}
else {
if (status.isLoaded === false && status.error) {
const errorMsg = `Encountered a fatal error during playback: ${status.error}`;
setErrorMessage(errorMsg);
props.errorCallback({ type: ErrorSeverity.Fatal, message: errorMsg, obj: {} });
}
}
};
const togglePlay = () => __awaiter(void 0, void 0, void 0, function* () {
if (controlsState === ControlStates.Hidden) {
return;
}
const shouldPlay = playbackInstanceInfo.state !== PlaybackStates.Playing;
if (playbackInstance !== null) {
yield playbackInstance.setStatusAsync(Object.assign({ shouldPlay }, (playbackInstanceInfo.state === PlaybackStates.Ended && { positionMillis: 0 })));
setPlaybackInstanceInfo(Object.assign(Object.assign({}, playbackInstanceInfo), { state: playbackInstanceInfo.state === PlaybackStates.Playing
? PlaybackStates.Paused
: PlaybackStates.Playing }));
if (shouldPlay) {
animationToggle();
}
}
});
if (playbackInstanceInfo.state === PlaybackStates.Error) {
return (
);
}
if (playbackInstanceInfo.state === PlaybackStates.Loading) {
return (
{props.icon.loading || }
);
}
return (
);
};
VideoPlayer.defaultProps = defaultProps;
export default VideoPlayer;
================================================
FILE: dist/props.d.ts
================================================
import { AVPlaybackStatus, Video, VideoProps } from 'expo-av';
import { ActivityIndicatorProps, TextStyle } from 'react-native';
import { ColorValue } from 'react-native';
import { ErrorType } from './constants';
import { MutableRefObject, ReactNode } from 'react';
import { SliderProps } from '@react-native-community/slider';
export declare type Props = RequiredProps & DefaultProps;
export declare const defaultProps: DefaultProps;
declare type RequiredProps = {
videoProps: VideoProps & {
ref?: MutableRefObject