THEOplayer / react-native-theoplayer

A React Native THEOplayerView component
https://theoplayer.github.io/react-native-theoplayer/
MIT License
64 stars 21 forks source link

Controls not displaying with new @theoplayer/react-native-ui package #160

Closed davidwinograd1 closed 1 year ago

davidwinograd1 commented 1 year ago

Hello! This is my code below. The controls on my player are not displaying. I have been using THEOplayer with the regular UI package for a while now and it has always worked. Now, it has stopped with the new package. Does anyone know why?

"react-native": "0.71.5", "@theoplayer/react-native-ui": "^0.2.0", "react-native-theoplayer": "^2.9.0", "react-native-svg": "^13.10.0", "@react-native-community/slider": "^4.4.2",

import React, {useState, useEffect} from 'react';
import {View, StyleSheet, Dimensions, Platform} from 'react-native';
import {Icon} from 'native-base';
import {
  CONTENT_REACHED_30_SECONDS,
  CONTENT_PLAYBACK_STARTED,
  CONTENT_COMPLETED,
  BUFFERING_STARTED,
  VIDEO_PLAYER_ERROR,
} from '../../../analytics/AnalyticsConstants';
import AsyncStorage from '@react-native-async-storage/async-storage';
import {useNavigation} from '@react-navigation/native';
import Orientation from 'react-native-orientation-locker';
import {useAnalytics} from '@segment/analytics-react-native';
import {
  PlaybackRateSubMenu,
  ChromecastButton,
  LanguageMenuButton,
  QualitySubMenu,
  UiContainer,
  DEFAULT_THEOPLAYER_THEME,
  CenteredDelayedActivityIndicator,
  CenteredControlBar,
  SkipButton,
  PlayButton,
  ControlBar,
  SeekBar,
  MuteButton,
  TimeLabel,
  Spacer,
  SettingsMenuButton,
} from '@theoplayer/react-native-ui';
import {PlayerEventType, THEOplayerView} from 'react-native-theoplayer';

export function Player({
  player,
  setPlayer,
  contentType,
  id,
  title,
  mediaId,
  premium,
  creatorId,
  creatorName,
  thumbnail,
  content,
}) {
  const [reached30seconds, setReached30Seconds] = useState(false);
  const [playbackStarted, setPlaybackStarted] = useState(false);
  const [playbackCompleted, setPlaybackCompleted] = useState(false);
  const {screen, track, identify, group, alias, reset, flush} = useAnalytics();
  const navigation = useNavigation();
  const [isFullScreen, setFullScreen] = useState(false);
  const chromeless = playerConfig?.chromeless ?? false;

  useEffect(() => {
    if (reached30seconds) {
      track(CONTENT_REACHED_30_SECONDS, {
        content_type: contentType,
        post_id: id,
        post_title: title,
        media_id: mediaId,
        premium_plan: premium,
        creator_id: creatorId,
        creator_name: creatorName,
      });
    }
  }, [reached30seconds]);

  async function onLoad(player) {
    if (!playbackStarted) {
      setPlaybackStarted(true);

      track(CONTENT_PLAYBACK_STARTED, {
        content_type: contentType,

        post_id: id,
        post_title: title,
        media_id: mediaId,
        premium_plan: premium,

        creator_id: creatorId,
        creator_name: creatorName,
      });
    }

    try {
      const value = await AsyncStorage.getItem(`POST_${id}`);

      if (value !== null) {
        setTimeout(() => {
          player.currentTime = parseInt(value);
        }, 1000);
      }
    } catch (e) {}
  }

  async function onProgress(player) {
    if (player.currentTime > 30000 && !reached30seconds) {
      await setReached30Seconds(true);
    }

    if (player.currentTime === player.duration - 1000 && !playbackCompleted) {
      setPlaybackCompleted(true);

      track(CONTENT_COMPLETED, {
        content_type: contentType,

        post_id: id,
        post_title: title,
        media_id: mediaId,
        premium_plan: premium,

        creator_id: creatorId,
        creator_name: creatorName,
      });
    }

    if (player.currentTime > 0 && player.currentTime % 1000 === 0) {
      try {
        await AsyncStorage.setItem(`POST_${id}`, player.currentTime.toString());
      } catch (e) {}
    }
  }

  useEffect(() => {
    const orientationListener = (orientation) => {
      const parent = navigation.dangerouslyGetParent();

      if (
        orientation === 'LANDSCAPE-LEFT' ||
        orientation === 'LANDSCAPE-RIGHT'
      ) {
        parent.setOptions({tabBarVisible: false});
        navigation.setOptions({headerShown: false});
        setFullScreen(true);
      }

      if (orientation === 'PORTRAIT') {
        parent.setOptions({tabBarVisible: true});
        navigation.setOptions({headerShown: true});
        setFullScreen(false);
      }
    };

    Orientation.addOrientationListener(orientationListener);

    return () => {
      Orientation.removeOrientationListener(orientationListener);
    };
  }, [isFullScreen]);

  const playerConfig = {
    mediaControl: {
      mediaSessionEnabled: true,
    },
    chromeless: true,
    cast: {
      chromecast: {
        appID: ...
      },
      strategy: 'auto',
    },
    libraryLocation: 'theoplayer',
    license: ...
  };

  const source = {
    sources: [
      {
        src: content,
        type: 'application/x-mpegurl',
      },
    ],
    poster: thumbnail,
    metadata: {
      title: title,
      subtitle: creatorName,
    },
  };

  const onReady = (player) => {
    player.autoplay = true;
    player.source = source;

    setPlayer(player);

    player.addEventListener('waiting', () => {
      console.log('Video is buffering');
      track(BUFFERING_STARTED, {
        content_type: contentType,

        post_id: id,
        post_title: title,
        media_id: mediaId,
        premium_plan: premium,

        creator_id: creatorId,
        creator_name: creatorName,
      });
    });

    player.addEventListener(PlayerEventType.ERROR, () => {
      track(VIDEO_PLAYER_ERROR, {
        content_type: contentType,

        post_id: id,
        post_title: title,
        media_id: mediaId,
        premium_plan: premium,

        creator_id: creatorId,
        creator_name: creatorName,
      });
    });

    onLoad(player);

    player.addEventListener(PlayerEventType.TIME_UPDATE, () => {
      onProgress(player);
    });

    player.backgroundAudioConfiguration = {enabled: true};
    player.pipConfiguration = {startsAutomatically: true};
  };

  function CustomFullscreenButton() {
    const toggleFullScreen = () => {
      setFullScreen(!isFullScreen);

      if (!isFullScreen) {
        Orientation.lockToLandscapeLeft();
      } else {
        Orientation.unlockAllOrientations();
      }
    };

    return (
      <TouchableOpacity onPress={toggleFullScreen}>
        <Icon
          name="arrows-alt"
          type="FontAwesome"
          style={{fontSize: 20, color: '#FFF', marginTop: 5}}
        />
      </TouchableOpacity>
    );
  }

  return (
    <View
      style={{
        borderBottomColor: '#202020',
      }}>
      <View style={isFullScreen ? styles.fullscreenPlayer : styles.player}>
        <THEOplayerView config={playerConfig} onPlayerReady={onReady}>
          {player !== undefined && chromeless && (
            <UiContainer
              theme={{
                ...DEFAULT_THEOPLAYER_THEME,
                dimensions: {
                  controlBarHeight: 32,
                  centerControlBarHeight: 42,
                },
                text: {
                  textAlignVertical: 'center',
                  textAlign: 'center',
                  alignSelf: 'center',
                  fontSize: 14,
                },
                fadeAnimationTimoutMs: 1000,
              }}
              player={player}
              top={
                <ControlBar>
                  {Platform.OS === 'android' && !Platform.isTV && (
                    <ChromecastButton />
                  )}
                  <LanguageMenuButton />
                  <SettingsMenuButton>
                    <QualitySubMenu />
                    <PlaybackRateSubMenu />
                  </SettingsMenuButton>
                </ControlBar>
              }
              behind={<CenteredDelayedActivityIndicator size={50} />}
              center={
                <CenteredControlBar
                  left={
                    <SkipButton skip={-30} style={{width: 45, height: 45}} />
                  }
                  middle={<PlayButton />}
                  right={
                    <SkipButton skip={30} style={{width: 45, height: 45}} />
                  }
                />
              }
              bottom={
                <>
                  <ControlBar>
                    <SeekBar
                      style={{marginTop: Platform.OS === 'android' ? 7 : 0}}
                    />
                  </ControlBar>
                  <ControlBar>
                    <MuteButton />
                    <TimeLabel showDuration={true} />
                    <Spacer />
                    <CustomFullscreenButton />
                  </ControlBar>
                </>
              }
            />
          )}
        </THEOplayerView>
      </View>
    </View>
  );
}

export default Player;

const styles = StyleSheet.create({
  player: {
    width: '100%',
    height: undefined,
    aspectRatio: 16 / 9,
    backgroundColor: 'black',
  },
  fullscreenPlayer: {
    marginLeft: 25,
    width: Dimensions.get('window').height - 20,
    height: Dimensions.get('window').width - 20,
    minWidth: Dimensions.get('window').height - 20,
    minHeight: Dimensions.get('window').width - 20,
  },
});
wvanhaevre commented 1 year ago

Hi, can you verify the value of 'chromeless'? It depends on the playerconfig const chromeless = playerConfig?.chromeless ?? false; which is defined later.

wvanhaevre commented 1 year ago

Suggested fix was confirmed.