LonelyCpp / react-native-youtube-iframe

A wrapper of the Youtube-iframe API built for react native.
https://lonelycpp.github.io/react-native-youtube-iframe/
MIT License
614 stars 155 forks source link

Inner player crashes if selected in iOS Voiceover while showing thumbnail #119

Open AlanSl opened 3 years ago

AlanSl commented 3 years ago

Describe the bug On iOS with VoiceOver active, if an unplayed YouTube WebView is selected, it fails:

It looks like YouTube's accessibility text generator expects video metadata to have been loaded before the item is selected, which won't happen unless the the video is set to autoplay. Strangely, after this happens there is a working play button a couple of swipes down but the default play button doesn't work so the user might just go back thinking the video failed and not discover this.

Android TalkBack works as expected.

To Reproduce

<View>
  <YoutubePlayer
    height={height}
    videoId={videoId}
  />
</View>

Compare the behaviour with an autoplaying video, which does not have the problem (because the metadata is loaded before you can select the element). For example:

<View>
  <YoutubePlayer
    play={true}
    height={height}
    videoId={videoId}
  />
</View>

Expected behavior

Same behaviour as if the video is allowed to start buffering and download metadata before selecting it: no crash on select, just reads the description.

Smartphone (please complete the following information):

Additional context

As a workaround you can make sure that the video auto-buffers if VoiceOver is on, for example:

export const Video = ({
  height,
  videoId,
  autoPlay = false,
  autoBuffer = false,
  screenReaderEnabled = false
}) => {
  // Workaround https://github.com/LonelyCpp/react-native-youtube-iframe/issues/119
  const voiceoverOn = Platform.OS === 'ios' && screenReaderEnabled;

  const [playing, setPlaying] = useState(voiceoverOn || autoPlay || autoBuffer);
  const [buffering, setBuffering] = useState(false);

  const handleChangeState = (event) => {
    if (event === 'buffering') {
      setBuffering(true);
    }
    if (event === 'playing') {
      setPlaying(buffering ? autoPlay : true);
      setBuffering(false);
    }
    if (event === 'paused') {
      setPlaying(false);
    }
  };

  return (
    <View>
      <YoutubePlayer
        play={playing}
        onChangeState={handleChangeState}
        height={height}
        videoId={videoId}
      />
    </View>
  );
};
LonelyCpp commented 3 years ago

Hello, thanks for the very detailed report!!

I'm not quite sure how I can test Voiceover from my simulator, I'll try the accessibility inspector if I can see what the issue is.

Can you check how voiceover works on a webpage with an youtube iframe? I would expect it to behave in a similarly. For example you can try - https://codepen.io/SurajMDurgad/pen/KKVZBoQ