Youttube video embed

Embed a youtube video

import React, {useMemo} from 'react';
import {View} from '@evlop/native-components';
import {WebView} from 'react-native-webview';

type Props = {
  data: {
    url?: string;
    aspectRatio?: string;
    autoplay?: boolean;
    controls?: boolean;
  };
};

function getId(input?: string) {
  if (!input) return '';
  const embed = input.match(/embed\/([A-Za-z0-9_-]{11})/);
  if (embed) return embed[1];

  const short = input.match(/youtu\.be\/([A-Za-z0-9_-]{11})/);
  if (short) return short[1];

  const watch = input.match(/[?&]v=([A-Za-z0-9_-]{11})/);
  if (watch) return watch[1];

  return input.trim();
}

export default function AppBlock({data}: Props) {
  const {embedUrl, containerStyle, aspectRatioProp} = useMemo(() => {
    const id = getId(data?.url || '');

    let url = `https://www.youtube.com/embed/${id}?rel=0&playsinline=1`;
    url += '&autoplay=' + (data?.autoplay ? '1' : '0');
    url += '&controls=' + (data?.controls ? '1' : '0');

    // parse aspect ratio like "16/9" -> number
    let ratio = 16 / 9;
    try {
      if (data?.aspectRatio) {
        const parts = String(data.aspectRatio).split('/').map(p => Number(p));
        if (parts.length === 2 && !isNaN(parts[0]) && !isNaN(parts[1]) && parts[1] !== 0) {
          ratio = parts[0] / parts[1];
        }
      }
    } catch (e) {
      // fallback to default
    }

    const style = {width: '100%', aspectRatio: ratio as number};

    return {embedUrl: url, containerStyle: style, aspectRatioProp: ratio};
  }, [data?.url, data?.aspectRatio, data?.autoplay, data?.controls]);

  if (!data?.url) {
    return <View width="100%" height={0} />;
  }

  return (
    <View width="100%" bg="black">
      <WebView
        source={{uri: embedUrl}}
        style={containerStyle}
        allowsInlineMediaPlayback
        javaScriptEnabled
        domStorageEnabled
        mediaPlaybackRequiresUserAction={false}
      />
    </View>
  );
}
Loading...