Skip to content

Commit 8589558

Browse files
committed
feat: multiple thumbnail resolution support 🚀
1 parent ffce59b commit 8589558

File tree

3 files changed

+42
-22
lines changed

3 files changed

+42
-22
lines changed

README.md

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
# React Lite Youtube Embed
2-
React component version of [lite-youtube-embed]([https://](https://github.com/paulirish/lite-youtube-embed)) power by tsdx, which focus on visual performance, rendering just like the real thing but much faster.
2+
React component version of [lite-youtube-embed](https://github.com/paulirish/lite-youtube-embed) build with tsdx, which focus on visual performance, rendering just like the real thing but much faster.
33

44
[![FOSSA Status](https://app.fossa.com/api/projects/git%2Bgithub.com%2Fkylemocode%2Freact-lite-yt-embed.svg?type=shield)](https://app.fossa.com/projects/git%2Bgithub.com%2Fkylemocode%2Freact-lite-yt-embed?ref=badge_shield)
55
[![Weekly Downloads](https://img.shields.io/npm/dw/react-lite-yt-embed)](https://img.shields.io/npm/dw/react-lite-yt-embed)
@@ -24,7 +24,7 @@ $ npm install react-lite-yt-embed
2424

2525
## Overview
2626
### Introduction
27-
'react-lite-yt-embed' is a react component version of popular package [lite-youtube-embed]([https://](https://github.com/paulirish/lite-youtube-embed)), which can use in React project including server-side-rendering project. It renders just like the real iframe but way much faster.
27+
'react-lite-yt-embed' is a react component version of popular package [lite-youtube-embed](https://github.com/paulirish/lite-youtube-embed), which can use in React project including SSR and CSR project. It renders just like the real iframe but way much faster.
2828

2929
## Basic Usage
3030

@@ -41,21 +41,21 @@ import { LiteYoutubeEmbed } from 'react-lite-yt-embed';
4141

4242
## Component Props
4343

44-
| props | required | default value | Type | Description |
45-
|-------------|----------|---------------|--------------------------|-----------------------------------------------------------------------------------------------|
46-
| id | true | none | `string` | The unique id of the youtube video |
47-
| defaultPlay | false | false | `boolean` | Set defaultPlay as `true` will directly show youtube iframe |
48-
| isPlaylist | false | false | `boolean` | If you want to play playlist, set this as `true` and pass the playlist id |
49-
| noCookie | false | true | `boolean` | Use "https://www.youtube-nocookie.com" as path or "https://www.youtube.com" |
50-
| mute | false | true | `boolean` | Set the video is mute or not. |
51-
| Params | false | {} | `Object<string, string>` | Query string params (autoplay and mute are default query string, you do not have to set them) |
52-
53-
54-
## Roadmap
44+
| props | required | default value | Type | Description |
45+
|-------------------|----------|-----------------|-----------------------------------------------|------------------------------------------------------------------------------------------------------------------------------------|
46+
| id | true | none | `string` | The unique id of the youtube video |
47+
| defaultPlay | false | false | `boolean` | Set defaultPlay as `true` will directly show youtube iframe |
48+
| isPlaylist | false | false | `boolean` | If you want to play playlist, set this as `true` and pass the playlist id |
49+
| noCookie | false | true | `boolean` | Use "https://www.youtube-nocookie.com" as path or "https://www.youtube.com" |
50+
| mute | false | true | `boolean` | Set the video is mute or not. |
51+
| params | false | {} | `Object<string, string>` | Query string params (autoplay and mute are default query string, you do not have to set them), the value have to be a string type. |
52+
| isMobile | false | false | `boolean` | Use in mobile device or not. |
53+
| mobileResolution | false | 'hqdefault' | 'hqdefault' \| 'sddefault' \| 'maxresdefault' | You can specify the resolution of the thumbnail image on the phone (default is hqdefault, which is a lower resolution). |
54+
| desktopResolution | false | 'maxresdefault' | 'hqdefault' \| 'sddefault' \| 'maxresdefault' | You can specify the resolution of the thumbnail image on the desktop (default is maxresdefault, which is the highest resolution). |
55+
56+
## Roadmap (Welcome contribution)
5557
- [ ] Use react-testing-library to test whether component render correctly.
5658
- [ ] More features
57-
- [x] Setup lint-stage
58-
- [x] Add Prettier
5959
- [ ] CI/CD pipeline
6060

6161
## License

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
{
2-
"version": "1.1.3",
2+
"version": "1.1.5",
33
"license": "MIT",
44
"main": "dist/index.js",
55
"typings": "dist/index.d.ts",

src/LiteYoutubeEmbed.tsx

Lines changed: 26 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import React, { useState } from 'react';
1+
import React, { useState, useEffect } from 'react';
22

33
import styles from './styles.module.css';
44

@@ -8,6 +8,9 @@ const qs = (params: Record<string, string>) => {
88
.join('&');
99
}
1010

11+
// https://stackoverflow.com/questions/2068344/how-do-i-get-a-youtube-video-thumbnail-from-the-youtube-api
12+
type ResolutionType = 'maxresdefault' | 'sddefault' | 'hqdefault';
13+
1114
interface ILiteYouTubeEmbedProps {
1215
id: string;
1316
adLinksPreconnect?: boolean;
@@ -16,6 +19,9 @@ interface ILiteYouTubeEmbedProps {
1619
noCookie?: boolean;
1720
mute?: boolean;
1821
params?: Record<string, string>;
22+
isMobile?: boolean;
23+
mobileResolution?: ResolutionType;
24+
desktopResolution?: ResolutionType;
1925
}
2026

2127
const LiteYoutubeEmbed = ({
@@ -26,15 +32,19 @@ const LiteYoutubeEmbed = ({
2632
isPlaylist = false,
2733
noCookie = true,
2834
mute = true,
35+
isMobile = false,
36+
mobileResolution = 'hqdefault',
37+
desktopResolution = 'maxresdefault',
2938
}: ILiteYouTubeEmbedProps): React.ReactElement => {
30-
const [isPreconnected, setIsPreconnected] = useState(false);
31-
const [iframeLoaded, setIframeLoaded] = useState(defaultPlay);
32-
3339
const muteParam = mute || defaultPlay ? '1' : '0'; // Default play must be mute
3440
const queryString = qs({ autoplay: '1', mute: muteParam, ...params });
35-
const posterUrl = `https://i.ytimg.com/vi/${id}/hqdefault.jpg`; // * Lo, the youtube placeholder image! (aka the thumbnail, poster image, etc)
41+
const defaultPosterUrl = isMobile ? `https://i.ytimg.com/vi/${id}/${mobileResolution}.jpg` : `https://i.ytimg.com/vi/${id}/${desktopResolution}.jpg`;
3642
const ytUrl = noCookie ? 'https://www.youtube-nocookie.com' : 'https://www.youtube.com';
37-
const iframeSrc = isPlaylist ? `${ytUrl}/embed/videoseries?list=${id}` : `${ytUrl}/embed/${id}?${queryString}`;
43+
const iframeSrc = isPlaylist ? `${ytUrl}/embed/videoseries?list=${id}` : `${ytUrl}/embed/${id}?${queryString}`; // * Lo, the youtube placeholder image! (aka the thumbnail, poster image, etc)
44+
45+
const [isPreconnected, setIsPreconnected] = useState(false);
46+
const [iframeLoaded, setIframeLoaded] = useState(defaultPlay);
47+
const [posterUrl, setPosterUrl] = useState(defaultPosterUrl);
3848

3949
const warmConnections = () => {
4050
if (isPreconnected) return;
@@ -46,6 +56,16 @@ const LiteYoutubeEmbed = ({
4656
setIframeLoaded(true);
4757
};
4858

59+
// fallback to hqdefault resolution if maxresdefault is not supported.
60+
useEffect(() => {
61+
if ((isMobile && mobileResolution === 'hqdefault') || (!isMobile && desktopResolution === 'hqdefault')) return;
62+
const img = new Image();
63+
img.onload = function() {
64+
if (img.width === 120 || img.width === 0) setPosterUrl(`https://i.ytimg.com/vi/${id}/hqdefault.jpg`);
65+
};
66+
img.src = posterUrl;
67+
}, [id, posterUrl]);
68+
4969
return (
5070
<>
5171
{/* Link is "body-ok" element. Reference: https://html.spec.whatwg.org/multipage/links.html#body-ok */}

0 commit comments

Comments
 (0)