Skip to content

Commit

Permalink
tvOS support - disable controls while hidden for TV, autoFocus playPa…
Browse files Browse the repository at this point in the history
…use button on showControls
  • Loading branch information
LunatiqueCoder committed Sep 10, 2022
1 parent a728dc3 commit 25ae213
Show file tree
Hide file tree
Showing 8 changed files with 53 additions and 14 deletions.
12 changes: 10 additions & 2 deletions src/VideoPlayer.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import React, {useCallback, useState, useEffect, useRef} from 'react';
import {View} from 'react-native';
import React, {useCallback, useState, useEffect, useRef, useMemo} from 'react';
import {View, Platform} from 'react-native';
import Video, {
OnLoadData,
OnProgressData,
Expand Down Expand Up @@ -98,6 +98,11 @@ export const VideoPlayer = (props: VideoPlayerProps) => {

const videoRef = props.videoRef || _videoRef;

const disableControlsWhileHiddenForTV = useMemo(
() => Platform.isTV && !showControls,
[showControls],
);

const toggleFullscreen = () => setIsFullscreen((prevState) => !prevState);
const toggleControls = () => setShowControls((prevState) => !prevState);
const toggleTimer = () => setShowTimeRemaining((prevState) => !prevState);
Expand Down Expand Up @@ -407,6 +412,7 @@ export const VideoPlayer = (props: VideoPlayerProps) => {
volumePosition={volumePosition}
onBack={events.onBack}
resetControlTimeout={resetControlTimeout}
disableControlsWhileHiddenForTV={disableControlsWhileHiddenForTV}
/>
<PlayPause
animations={animations}
Expand All @@ -421,6 +427,7 @@ export const VideoPlayer = (props: VideoPlayerProps) => {
onPressForward={() =>
videoRef?.current?.seek(currentTime + rewindTime)
}
disableControlsWhileHiddenForTV={disableControlsWhileHiddenForTV}
/>
<BottomControls
animations={animations}
Expand All @@ -443,6 +450,7 @@ export const VideoPlayer = (props: VideoPlayerProps) => {
isFullscreen={isFullscreen}
disableFullscreen={disableFullscreen}
toggleFullscreen={toggleFullscreen}
disableControlsWhileHiddenForTV={disableControlsWhileHiddenForTV}
/>
</>
)}
Expand Down
5 changes: 3 additions & 2 deletions src/components/Back/Back.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,12 @@ import {Control} from '../Control';
interface BackProps {
onBack: () => void;
resetControlTimeout?: () => void;
disableControlsWhileHiddenForTV: boolean;
}

export const Back = ({onBack}: BackProps) => {
export const Back = ({onBack, disableControlsWhileHiddenForTV}: BackProps) => {
return (
<Control callback={onBack}>
<Control callback={onBack} disabled={disableControlsWhileHiddenForTV}>
<Image source={require('../../assets/img/back.png')} />
</Control>
);
Expand Down
8 changes: 7 additions & 1 deletion src/components/BottomControls.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import type {VideoAnimations} from '../types';
import {styles} from './styles';

interface BottomControlsProps {
disableControlsWhileHiddenForTV: boolean;
animations: VideoAnimations;
panHandlers: GestureResponderHandlers;
disableTimer: boolean;
Expand All @@ -39,6 +40,7 @@ interface BottomControlsProps {
}

export const BottomControls = ({
disableControlsWhileHiddenForTV,
animations,
panHandlers,
disableSeekbar,
Expand All @@ -62,7 +64,10 @@ export const BottomControls = ({
const timerControl = disableTimer ? (
<NullControl />
) : (
<Timer resetControlTimeout={resetControlTimeout} toggleTimer={toggleTimer}>
<Timer
resetControlTimeout={resetControlTimeout}
toggleTimer={toggleTimer}
disableControlsWhileHiddenForTV={disableControlsWhileHiddenForTV}>
{calculateTime({
showDuration,
showHours,
Expand Down Expand Up @@ -92,6 +97,7 @@ export const BottomControls = ({
isFullscreen={isFullscreen}
toggleFullscreen={toggleFullscreen}
resetControlTimeout={resetControlTimeout}
disableControlsWhileHiddenForTV={disableControlsWhileHiddenForTV}
/>
);

Expand Down
8 changes: 7 additions & 1 deletion src/components/Control.tsx
Original file line number Diff line number Diff line change
@@ -1,22 +1,28 @@
import React, {ReactNode} from 'react';
import React, {ReactNode, RefObject} from 'react';
import {TouchableHighlight, ViewProps} from 'react-native';
import {styles} from './styles';

interface ControlProps extends ViewProps {
children: ReactNode;
callback?: () => void;
controlRef?: RefObject<TouchableHighlight>;
disabled?: boolean;
style?: any;
resetControlTimeout?: () => void;
}

export const Control = ({
children,
callback,
controlRef,
disabled,
style = {},
...props
}: ControlProps) => {
return (
<TouchableHighlight
disabled={disabled}
ref={controlRef}
underlayColor="transparent"
activeOpacity={0.3}
onPress={() => {
Expand Down
5 changes: 4 additions & 1 deletion src/components/Fullscreen.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,14 @@ interface FullscreenProps {
isFullscreen: boolean;
toggleFullscreen: () => void;
resetControlTimeout: () => void;
disableControlsWhileHiddenForTV: boolean;
}

export const Fullscreen = ({
isFullscreen,
toggleFullscreen,
resetControlTimeout,
disableControlsWhileHiddenForTV,
}: FullscreenProps) => {
let source = isFullscreen
? require('../assets/img/shrink.png')
Expand All @@ -20,7 +22,8 @@ export const Fullscreen = ({
<Control
callback={toggleFullscreen}
resetControlTimeout={resetControlTimeout}
style={styles.fullscreen}>
style={styles.fullscreen}
disabled={disableControlsWhileHiddenForTV}>
<Image source={source} />
</Control>
);
Expand Down
16 changes: 11 additions & 5 deletions src/components/PlayPause/PlayPause.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,15 @@
import React from 'react';
import {Animated, Image, Platform} from 'react-native';
import React, {createRef} from 'react';
import {Animated, Image, Platform, TouchableHighlight} from 'react-native';
import {Control} from '../Control';
import {NullControl} from '../NullControl';
import type {VideoAnimations} from '../../types';
import {styles} from './styles';

export const playPauseRef = createRef<TouchableHighlight>();

interface PlayPauseProps {
animations: VideoAnimations;
disableControlsWhileHiddenForTV: boolean;
disablePlayPause: boolean;
paused: boolean;
togglePlayPause: () => void;
Expand All @@ -16,14 +19,13 @@ interface PlayPauseProps {
onPressRewind: () => void;
}

const tvProps = {hasTVPreferredFocus: true};

const play = require('../../assets/img/play.png');
const pause = require('../../assets/img/pause.png');
const rewind = require('../../assets/img/rewind.png');
const forward = require('../../assets/img/forward.png');

export const PlayPause = ({
disableControlsWhileHiddenForTV,
animations,
disablePlayPause,
paused,
Expand All @@ -49,18 +51,22 @@ export const PlayPause = ({
pointerEvents={'box-none'}
style={[styles.container, animatedStyles]}>
<Control
disabled={disableControlsWhileHiddenForTV}
callback={onPressRewind}
resetControlTimeout={resetControlTimeout}>
<Image source={rewind} resizeMode={'contain'} style={styles.rewind} />
</Control>
<Control
disabled={disableControlsWhileHiddenForTV}
callback={togglePlayPause}
resetControlTimeout={resetControlTimeout}
style={styles.playContainer}
{...(Platform.isTV ? tvProps : {})}>
controlRef={playPauseRef}
{...(Platform.isTV ? {hasTVPreferredFocus: showControls} : {})}>
<Image source={source} resizeMode={'contain'} style={styles.play} />
</Control>
<Control
disabled={disableControlsWhileHiddenForTV}
callback={onPressForward}
resetControlTimeout={resetControlTimeout}>
<Image source={forward} resizeMode={'contain'} style={styles.rewind} />
Expand Down
5 changes: 4 additions & 1 deletion src/components/Timer/Timer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,18 +7,21 @@ interface TimerProps {
toggleTimer: () => void;
resetControlTimeout: () => void;
children: ReactNode;
disableControlsWhileHiddenForTV: boolean;
}

export const Timer = ({
children,
toggleTimer,
resetControlTimeout,
disableControlsWhileHiddenForTV,
}: TimerProps) => {
return (
<Control
callback={toggleTimer}
resetControlTimeout={resetControlTimeout}
style={styles.timer}>
style={styles.timer}
disabled={disableControlsWhileHiddenForTV}>
<Text style={styles.timerText}>{children}</Text>
</Control>
);
Expand Down
8 changes: 7 additions & 1 deletion src/components/TopControls.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import {styles} from './styles';
import type {VideoAnimations} from '../types';

interface TopControlProps {
disableControlsWhileHiddenForTV: boolean;
panHandlers: GestureResponderHandlers;
animations: VideoAnimations;
disableBack: boolean;
Expand All @@ -27,6 +28,7 @@ interface TopControlProps {

export const TopControls = memo(
({
disableControlsWhileHiddenForTV,
panHandlers,
animations,
disableBack,
Expand All @@ -40,7 +42,11 @@ export const TopControls = memo(
const backControl = disableBack ? (
<NullControl />
) : (
<Back onBack={onBack} resetControlTimeout={resetControlTimeout} />
<Back
disableControlsWhileHiddenForTV={disableControlsWhileHiddenForTV}
onBack={onBack}
resetControlTimeout={resetControlTimeout}
/>
);

const volumeControl = disableVolume ? (
Expand Down

0 comments on commit 25ae213

Please sign in to comment.