Skip to content

Commit

Permalink
✨Video Embed - Added Vimeo Support (#1075)
Browse files Browse the repository at this point in the history
* Added Vimeo support

* Undid newsletters table modification

* Changed description of video URL

* Fixed broken industry renderer video embed

* Fixed livestream widget references

* Remove comments

* TinaCMS content update by Brady Stroud

* Remove testing change

---------

Co-authored-by: Brady Stroud [SSW] <[email protected]>
Co-authored-by: tina-cloud-app[bot] <58178390+tina-cloud-app[bot]@users.noreply.github.com>
  • Loading branch information
3 people authored Jul 20, 2023
1 parent b0b3200 commit d9886ce
Show file tree
Hide file tree
Showing 9 changed files with 126 additions and 38 deletions.
3 changes: 2 additions & 1 deletion components/blocks/industryRenderer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import Link from "next/link";
import { FaFileDownload } from "react-icons/fa";
import { toast } from "react-toastify";
import { Components } from "tinacms/dist/rich-text";
import { getYouTubeId } from "../../helpers/embeds";
import { BookingForm } from "../bookingForm/bookingForm";
import Button from "../button/button";
import { YouTubeEmbed } from "../embeds/youtubeEmbed";
Expand Down Expand Up @@ -50,7 +51,7 @@ export const Whitepaper = ({
export const VideoEmbed = ({ url }) => (
<div className="relative h-0 overflow-hidden pb-9/16">
<div className="absolute h-full w-full">
<YouTubeEmbed url={url} width="100%" height="100%" />
<YouTubeEmbed id={getYouTubeId(url)} width="100%" height="100%" />
</div>
</div>
);
Expand Down
2 changes: 1 addition & 1 deletion components/blocks/videoEmbed.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ export const videoEmbedBlockSchema: Template = {
label: "Video URL",
name: "url",
description:
"Only YouTube URLs are supported. To embed videos from other sources, please raise an issue",
"Only YouTube and Vimeo URLs are supported. To embed videos from other sources, please raise an issue",
required: true,
},
{
Expand Down
27 changes: 27 additions & 0 deletions components/embeds/vimeoEmbed.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import classNames from "classnames";
import Script from "next/script";

export type VimeoEmbedProps = {
className?: string;
id: string;
autoplay?: boolean;
};

export const VimeoEmbed = ({ className, id, autoplay }: VimeoEmbedProps) => {
return (
<>
<iframe
className={classNames(className, "h-full w-full")}
src={`https://player.vimeo.com/video/${id}?h=62ccd0699b&autoplay=${
autoplay ? 1 : 0
}&title=0&byline=0&portrait=0`}
allow="autoplay; fullscreen; picture-in-picture"
allowFullScreen
/>
<Script
src="https://player.vimeo.com/api/player.js"
strategy="lazyOnload"
/>
</>
);
};
8 changes: 3 additions & 5 deletions components/embeds/youtubeEmbed.tsx
Original file line number Diff line number Diff line change
@@ -1,26 +1,24 @@
import { getYouTubeId } from "../../helpers/embeds";

type YouTubeEmbedProps = {
className?: string;
width: string;
height: string;
url: string;
id: string;
autoplay?: boolean;
};

export const YouTubeEmbed = ({
className,
width,
height,
url,
id,
autoplay,
}: YouTubeEmbedProps) => {
return (
<iframe
className={className}
width={width}
height={height}
src={`https://www.youtube.com/embed/${getYouTubeId(url || "")}?autoplay=${
src={`https://www.youtube.com/embed/${id || ""}?autoplay=${
autoplay ? 1 : 0
}`}
title="YouTube video player"
Expand Down
5 changes: 3 additions & 2 deletions components/liveStream/liveStreamWidget.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { FC, useEffect, useState } from "react";
import { TfiAngleDown, TfiAngleUp } from "react-icons/tfi";
import { Tooltip } from "react-tooltip";
import layoutData from "../../content/global/index.json";
import { getYouTubeId } from "../../helpers/embeds";
import { SpeakerInfo } from "../../services/server/events";
import { YouTubeEmbed } from "../embeds/youtubeEmbed";
import { SubNewsLettersForm } from "../subNewsletter/subNewsletterForm";
Expand Down Expand Up @@ -157,7 +158,7 @@ export const LiveStreamWidget: FC<LiveStreamProps> = ({ isLive, event }) => {
<div className="relative h-0 pt-9/16">
<div className="absolute top-0 h-full w-full">
<YouTubeEmbed
url={youtubeUrls.videoUrl}
id={getYouTubeId(youtubeUrls?.videoUrl)}
width="100%"
height="100%"
/>
Expand All @@ -173,7 +174,7 @@ export const LiveStreamWidget: FC<LiveStreamProps> = ({ isLive, event }) => {
data-aos-anchor-placement="bottom-top"
>
<YouTubeEmbed
url={youtubeUrls.videoUrl}
id={getYouTubeId(youtubeUrls?.videoUrl)}
width="100%"
height="100%"
/>
Expand Down
103 changes: 76 additions & 27 deletions components/videoModal.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,13 @@
import dynamic from "next/dynamic";
import Image from "next/image";
import { useState } from "react";
import { useEffect, useState } from "react";
import { FaPlayCircle } from "react-icons/fa";
import { getYouTubeId } from "../helpers/embeds";
import {
MATCH_URL_VIMEO,
MATCH_URL_YOUTUBE,
getVimeoId,
getYouTubeId,
} from "../helpers/embeds";

const YouTubeEmbed = dynamic(
() => import("./embeds/youtubeEmbed").then((mod) => mod.YouTubeEmbed),
Expand All @@ -11,42 +16,86 @@ const YouTubeEmbed = dynamic(
}
);

export const VideoModal = ({ children = null, url }) => {
const id = url ? getYouTubeId(url) : null;
const VimeoEmbed = dynamic(
() => import("./embeds/vimeoEmbed").then((mod) => mod.VimeoEmbed),
{
ssr: false,
}
);

export const VideoModal = ({ children = null, url }) => {
const [videoId, setVideoId] = useState<string>();
const [clicked, setClicked] = useState<boolean>(false);
const [imageSrc, setImageSrc] = useState<string>(
`https://img.youtube.com/vi/${id}/maxresdefault.jpg`
);
const [imageSrc, setImageSrc] = useState<string>("");

const isYouTube = MATCH_URL_YOUTUBE.test(url);
const isVimeo = MATCH_URL_VIMEO.test(url);

useEffect(() => {
const getVimeoData = async (id: string) => {
const videoData = await fetch(
`https://vimeo.com/api/v2/video/${id}.json`
);
const video = await videoData.json();
return video;
};

if (isYouTube) {
const id = getYouTubeId(url);
setVideoId(id);
setImageSrc(`https://img.youtube.com/vi/${id}/maxresdefault.jpg`);
} else if (isVimeo) {
const id = getVimeoId(url);
setVideoId(id);
getVimeoData(id).then((res) => {
setImageSrc(res[0].thumbnail_large);
});
}
}, []);

return (
<div>
<div className="overflow-hidden rounded">
<div className="relative mx-auto aspect-video h-full w-full">
{!clicked ? (
<div className="h-full w-full " onClick={() => setClicked(true)}>
<Image
src={imageSrc}
fill
alt="YouTube video player"
onError={() => {
if (imageSrc.includes("maxresdefault")) {
setImageSrc(
`https://img.youtube.com/vi/${id}/mqdefault.jpg`
);
}
}}
/>
<PlayArrow />
{imageSrc && (
<>
<Image
src={imageSrc || ""}
fill
alt="Video player"
onError={() => {
if (imageSrc.includes("maxresdefault")) {
setImageSrc(
`https://img.youtube.com/vi/${videoId}/mqdefault.jpg`
);
}
}}
/>
<PlayArrow />{" "}
</>
)}
</div>
) : (
<YouTubeEmbed
className="absolute left-0 top-0"
url={url || ""}
width={"100%"}
height={"100%"}
autoplay={true}
/>
<>
{isYouTube && (
<YouTubeEmbed
className="absolute left-0 top-0"
id={videoId || ""}
width={"100%"}
height={"100%"}
autoplay={true}
/>
)}
{isVimeo && (
<VimeoEmbed
className="absolute left-0 top-0"
id={videoId || ""}
autoplay={true}
/>
)}
</>
)}
</div>
{children}
Expand Down
3 changes: 2 additions & 1 deletion content/pages/home.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,7 @@ SSW Consulting has over 30 years of experience developing awesome Microsoft solu
width={300}
message={<>
### We ❤️ Microsoft

In 1999, we were first recognized as a Microsoft Gold Partner – now renamed Microsoft Cloud Partner. Today [SSW has competencies in a variety of areas](https://www.ssw.com.au/ssw/company/awards/), including Data and AI and Digital & App Innovation.
</>}
/>
Expand All @@ -151,3 +151,4 @@ SSW Consulting has over 30 years of experience developing awesome Microsoft solu
### Bring your apps to China <Flag country="China" />

China is a booming market and now is the time to take advantage of this growing user base. If you have a successful application that you would like to bring to the Chinese market, then working with [SSW can help](/consulting/chinafy-app) streamline your entry into this market.

12 changes: 11 additions & 1 deletion helpers/embeds.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,19 @@
// Taken from https://github.com/cookpete/react-player/blob/master/src/patterns.js#L3
const MATCH_URL_YOUTUBE =
export const MATCH_URL_YOUTUBE =
/(?:youtu\.be\/|youtube(?:-nocookie|education)?\.com\/(?:embed\/|v\/|watch\/|watch\?v=|watch\?.+&v=|shorts\/|live\/))((\w|-){11})|youtube\.com\/playlist\?list=|youtube\.com\/user\//;
// Taken from https://stackoverflow.com/questions/41208456/javascript-regex-vimeo-id
/* eslint-disable no-useless-escape */
export const MATCH_URL_VIMEO =
/(?:www\.|player\.)?vimeo.com\/(?:channels\/(?:\w+\/)?|groups\/(?:[^\/]*)\/videos\/|album\/(?:\d+)\/video\/|video\/|)(\d+)(?:[a-zA-Z0-9_\-]+)?/i;

export const getYouTubeId = (url: string) => {
if (!url) return "";
const match = url.match(MATCH_URL_YOUTUBE);
return match && match[1];
};

export const getVimeoId = (url: string) => {
if (!url) return "";
const match = url.match(MATCH_URL_VIMEO);
return match && match[1];
};
1 change: 1 addition & 0 deletions next.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ const config = {
"img.youtube.com",
"ssw.com.au",
"www.ssw.com.au",
"i.vimeocdn.com",
],
},
output: "standalone", // required for Docker support
Expand Down

0 comments on commit d9886ce

Please sign in to comment.