Video player

Play a video from URL

video
import React, { useEffect, useState } from 'react';
import Video from 'react-native-video';
import { View, Actionable } from '@evlop/native-components';
import { AppState, StyleSheet } from 'react-native';

type Props = {
  data: {
    videoUrl?: string;
    videoAspectRatio?: string | number;
    videoResizeMode?: 'cover' | 'contain' | 'stretch' | 'repeat' | 'none';
    action?: any;
  };
};

function parseAspectRatio(aspect?: string | number) {
  if (!aspect) return undefined;
  if (typeof aspect === 'number') return aspect;

  const value = aspect.trim();

  if (value.includes('/') || value.includes(':')) {
    const separator = value.includes('/') ? '/' : ':';
    const [width, height] = value.split(separator).map(Number);

    if (
      Number.isFinite(width) &&
      Number.isFinite(height) &&
      height !== 0
    ) {
      return width / height;
    }
  }

  const numericValue = Number(value);

  return Number.isFinite(numericValue) && numericValue > 0
    ? numericValue
    : undefined;
}

export default function App({ data = {} } = {} as Props) {
  const {
    videoUrl,
    action,
    videoAspectRatio,
    videoResizeMode = 'cover',
  } = data;

  const [isAppActive, setIsAppActive] = useState(
    AppState.currentState === 'active',
  );

  const aspectRatio = parseAspectRatio(videoAspectRatio);

  useEffect(() => {
    const subscription = AppState.addEventListener('change', state => {
      setIsAppActive(state === 'active');
    });

    return () => subscription.remove();
  }, []);

  return (
    <Actionable action={action}>
      <View
        style={[
          styles.container,
          aspectRatio ? { aspectRatio } : undefined,
        ]}
      >
        {videoUrl ? (
          <Video
            source={{ uri: videoUrl }}
            style={styles.video}
            resizeMode={videoResizeMode as any}
            paused={!isAppActive}
            repeat
            muted
            playInBackground={false}
            playWhenInactive={false}
          />
        ) : null}
      </View>
    </Actionable>
  );
}

const styles = StyleSheet.create({
  container: {
    width: '100%',
    backgroundColor: 'black',
  },
  video: {
    width: '100%',
    height: '100%',
  },
});