3rd party embed player (#2217)
* Implement embed player for YT, spotify, and twitch * fix: handle blur event * fix: use video dimensions for twitch * fix: remove hack (?) * fix: remove origin whitelist (?) * fix: prevent ads from opening in browser * fix: handle embeds that don't have a thumb * feat: handle dark/light mode * fix: ts warning * fix: adjust height of no-thumb label * fix: adjust height of no-thumb label * fix: remove debug log, set collapsable to false for player view * fix: fix dimensions "flash" * chore: remove old youtube link test * tests: add tests * fix: thumbless embed position when loading * fix: remove background from webview * cleanup embeds (almost) * more refactoring - Use separate layers for player and overlay to prevent weird sizing issues - Be sure the image is not visible under the player - Clean up some * cleanup styles * parse youtube shorts urls * remove debug * add soundcloud tracks and sets (playlists) * move logic into `ExternalLinkEmbed` * border radius for yt player on native * fix styling on web * allow scrolling in webview on android * remove unnecessary check * autoplay yt on web * fix tests after adding autoplay * move `useNavigation` to top of component --------- Co-authored-by: Paul Frazee <pfrazee@gmail.com>
This commit is contained in:
parent
7ab188dc1f
commit
fedb94dd70
12 changed files with 597 additions and 135 deletions
|
@ -1,6 +1,5 @@
|
|||
import {RichText} from '@atproto/api'
|
||||
import {
|
||||
getYoutubeVideoId,
|
||||
makeRecordUri,
|
||||
toNiceDomain,
|
||||
toShortUrl,
|
||||
|
@ -12,6 +11,7 @@ import {detectLinkables} from '../../src/lib/strings/rich-text-detection'
|
|||
import {shortenLinks} from '../../src/lib/strings/rich-text-manip'
|
||||
import {makeValidHandle, createFullHandle} from '../../src/lib/strings/handles'
|
||||
import {cleanError} from '../../src/lib/strings/errors'
|
||||
import {parseEmbedPlayerFromUrl} from 'lib/strings/embed-player'
|
||||
|
||||
describe('detectLinkables', () => {
|
||||
const inputs = [
|
||||
|
@ -335,32 +335,6 @@ describe('toShareUrl', () => {
|
|||
})
|
||||
})
|
||||
|
||||
describe('getYoutubeVideoId', () => {
|
||||
it(' should return undefined for invalid youtube links', () => {
|
||||
expect(getYoutubeVideoId('')).toBeUndefined()
|
||||
expect(getYoutubeVideoId('https://www.google.com')).toBeUndefined()
|
||||
expect(getYoutubeVideoId('https://www.youtube.com')).toBeUndefined()
|
||||
expect(
|
||||
getYoutubeVideoId('https://www.youtube.com/channelName'),
|
||||
).toBeUndefined()
|
||||
expect(
|
||||
getYoutubeVideoId('https://www.youtube.com/channel/channelName'),
|
||||
).toBeUndefined()
|
||||
})
|
||||
|
||||
it('getYoutubeVideoId should return video id for valid youtube links', () => {
|
||||
expect(getYoutubeVideoId('https://www.youtube.com/watch?v=videoId')).toBe(
|
||||
'videoId',
|
||||
)
|
||||
expect(
|
||||
getYoutubeVideoId(
|
||||
'https://www.youtube.com/watch?v=videoId&feature=share',
|
||||
),
|
||||
).toBe('videoId')
|
||||
expect(getYoutubeVideoId('https://youtu.be/videoId')).toBe('videoId')
|
||||
})
|
||||
})
|
||||
|
||||
describe('shortenLinks', () => {
|
||||
const inputs = [
|
||||
'start https://middle.com/foo/bar?baz=bux#hash end',
|
||||
|
@ -396,6 +370,7 @@ describe('shortenLinks', () => {
|
|||
],
|
||||
],
|
||||
]
|
||||
|
||||
it('correctly shortens rich text while preserving facet URIs', () => {
|
||||
for (let i = 0; i < inputs.length; i++) {
|
||||
const input = inputs[i]
|
||||
|
@ -410,3 +385,141 @@ describe('shortenLinks', () => {
|
|||
}
|
||||
})
|
||||
})
|
||||
|
||||
describe('parseEmbedPlayerFromUrl', () => {
|
||||
const inputs = [
|
||||
'https://youtu.be/videoId',
|
||||
'https://www.youtube.com/watch?v=videoId',
|
||||
'https://www.youtube.com/watch?v=videoId&feature=share',
|
||||
'https://youtube.com/watch?v=videoId',
|
||||
'https://youtube.com/watch?v=videoId&feature=share',
|
||||
'https://youtube.com/shorts/videoId',
|
||||
|
||||
'https://youtube.com/shorts/',
|
||||
'https://youtube.com/',
|
||||
'https://youtube.com/random',
|
||||
|
||||
'https://twitch.tv/channelName',
|
||||
'https://www.twitch.tv/channelName',
|
||||
|
||||
'https://open.spotify.com/playlist/playlistId',
|
||||
'https://open.spotify.com/playlist/playlistId?param=value',
|
||||
|
||||
'https://open.spotify.com/track/songId',
|
||||
'https://open.spotify.com/track/songId?param=value',
|
||||
|
||||
'https://open.spotify.com/album/albumId',
|
||||
'https://open.spotify.com/album/albumId?param=value',
|
||||
|
||||
'https://soundcloud.com/user/track',
|
||||
'https://soundcloud.com/user/sets/set',
|
||||
'https://soundcloud.com/user/',
|
||||
]
|
||||
|
||||
const outputs = [
|
||||
{
|
||||
type: 'youtube_video',
|
||||
videoId: 'videoId',
|
||||
playerUri: 'https://www.youtube.com/embed/videoId?autoplay=1',
|
||||
},
|
||||
{
|
||||
type: 'youtube_video',
|
||||
videoId: 'videoId',
|
||||
playerUri: 'https://www.youtube.com/embed/videoId?autoplay=1',
|
||||
},
|
||||
{
|
||||
type: 'youtube_video',
|
||||
videoId: 'videoId',
|
||||
playerUri: 'https://www.youtube.com/embed/videoId?autoplay=1',
|
||||
},
|
||||
{
|
||||
type: 'youtube_video',
|
||||
videoId: 'videoId',
|
||||
playerUri: 'https://www.youtube.com/embed/videoId?autoplay=1',
|
||||
},
|
||||
{
|
||||
type: 'youtube_video',
|
||||
videoId: 'videoId',
|
||||
playerUri: 'https://www.youtube.com/embed/videoId?autoplay=1',
|
||||
},
|
||||
{
|
||||
type: 'youtube_video',
|
||||
videoId: 'videoId',
|
||||
playerUri: 'https://www.youtube.com/embed/videoId?autoplay=1',
|
||||
},
|
||||
undefined,
|
||||
undefined,
|
||||
undefined,
|
||||
|
||||
{
|
||||
type: 'twitch_live',
|
||||
channelId: 'channelName',
|
||||
playerUri: `https://player.twitch.tv/?volume=0.5&!muted&autoplay&channel=channelName&parent=localhost`,
|
||||
},
|
||||
{
|
||||
type: 'twitch_live',
|
||||
channelId: 'channelName',
|
||||
playerUri: `https://player.twitch.tv/?volume=0.5&!muted&autoplay&channel=channelName&parent=localhost`,
|
||||
},
|
||||
|
||||
{
|
||||
type: 'spotify_playlist',
|
||||
playlistId: 'playlistId',
|
||||
playerUri: `https://open.spotify.com/embed/playlist/playlistId`,
|
||||
},
|
||||
{
|
||||
type: 'spotify_playlist',
|
||||
playlistId: 'playlistId',
|
||||
playerUri: `https://open.spotify.com/embed/playlist/playlistId`,
|
||||
},
|
||||
|
||||
{
|
||||
type: 'spotify_song',
|
||||
songId: 'songId',
|
||||
playerUri: `https://open.spotify.com/embed/track/songId`,
|
||||
},
|
||||
{
|
||||
type: 'spotify_song',
|
||||
songId: 'songId',
|
||||
playerUri: `https://open.spotify.com/embed/track/songId`,
|
||||
},
|
||||
|
||||
{
|
||||
type: 'spotify_album',
|
||||
albumId: 'albumId',
|
||||
playerUri: `https://open.spotify.com/embed/album/albumId`,
|
||||
},
|
||||
{
|
||||
type: 'spotify_album',
|
||||
albumId: 'albumId',
|
||||
playerUri: `https://open.spotify.com/embed/album/albumId`,
|
||||
},
|
||||
|
||||
{
|
||||
type: 'soundcloud_track',
|
||||
user: 'user',
|
||||
track: 'track',
|
||||
playerUri: `https://w.soundcloud.com/player/?url=https://soundcloud.com/user/track&auto_play=true&visual=false&hide_related=true`,
|
||||
},
|
||||
{
|
||||
type: 'soundcloud_set',
|
||||
user: 'user',
|
||||
set: 'set',
|
||||
playerUri: `https://w.soundcloud.com/player/?url=https://soundcloud.com/user/sets/set&auto_play=true&visual=false&hide_related=true`,
|
||||
},
|
||||
undefined,
|
||||
]
|
||||
|
||||
it('correctly grabs the correct id from uri', () => {
|
||||
for (let i = 0; i < inputs.length; i++) {
|
||||
const input = inputs[i]
|
||||
const output = outputs[i]
|
||||
|
||||
const res = parseEmbedPlayerFromUrl(input)
|
||||
|
||||
console.log(input)
|
||||
|
||||
expect(res).toEqual(output)
|
||||
}
|
||||
})
|
||||
})
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue