diff options
-rw-r--r-- | __tests__/lib/string.test.ts | 23 | ||||
-rw-r--r-- | bskyweb/cmd/bskyweb/server.go | 1 | ||||
-rw-r--r-- | bskyweb/static/iframe/youtube.html | 49 | ||||
-rw-r--r-- | src/lib/strings/embed-player.ts | 13 | ||||
-rw-r--r-- | src/view/com/util/post-embeds/ExternalPlayerEmbed.tsx | 8 |
5 files changed, 71 insertions, 23 deletions
diff --git a/__tests__/lib/string.test.ts b/__tests__/lib/string.test.ts index b3aa48f4a..f003e5acc 100644 --- a/__tests__/lib/string.test.ts +++ b/__tests__/lib/string.test.ts @@ -462,45 +462,38 @@ describe('parseEmbedPlayerFromUrl', () => { { type: 'youtube_video', source: 'youtube', - playerUri: - 'https://www.youtube.com/embed/videoId?autoplay=1&playsinline=1&start=0', + playerUri: 'https://bsky.app/iframe/youtube.html?videoId=videoId&start=0', }, { type: 'youtube_video', source: 'youtube', - playerUri: - 'https://www.youtube.com/embed/videoId?autoplay=1&playsinline=1&start=0', + playerUri: 'https://bsky.app/iframe/youtube.html?videoId=videoId&start=0', }, { type: 'youtube_video', source: 'youtube', - playerUri: - 'https://www.youtube.com/embed/videoId?autoplay=1&playsinline=1&start=0', + playerUri: 'https://bsky.app/iframe/youtube.html?videoId=videoId&start=0', }, { type: 'youtube_video', source: 'youtube', - playerUri: - 'https://www.youtube.com/embed/videoId?autoplay=1&playsinline=1&start=0', + playerUri: 'https://bsky.app/iframe/youtube.html?videoId=videoId&start=0', }, { type: 'youtube_video', source: 'youtube', - playerUri: - 'https://www.youtube.com/embed/videoId?autoplay=1&playsinline=1&start=0', + playerUri: 'https://bsky.app/iframe/youtube.html?videoId=videoId&start=0', }, { type: 'youtube_short', source: 'youtubeShorts', hideDetails: true, - playerUri: - 'https://www.youtube.com/embed/videoId?autoplay=1&playsinline=1&start=0', + playerUri: 'https://bsky.app/iframe/youtube.html?videoId=videoId&start=0', }, { type: 'youtube_video', source: 'youtube', - playerUri: - 'https://www.youtube.com/embed/videoId?autoplay=1&playsinline=1&start=0', + playerUri: 'https://bsky.app/iframe/youtube.html?videoId=videoId&start=0', }, undefined, @@ -759,8 +752,6 @@ describe('parseEmbedPlayerFromUrl', () => { const res = parseEmbedPlayerFromUrl(input) - console.log(input) - expect(res).toEqual(output) } }) diff --git a/bskyweb/cmd/bskyweb/server.go b/bskyweb/cmd/bskyweb/server.go index c4a12a2fa..76b7bcc06 100644 --- a/bskyweb/cmd/bskyweb/server.go +++ b/bskyweb/cmd/bskyweb/server.go @@ -159,6 +159,7 @@ func serve(cctx *cli.Context) error { e.GET("/security.txt", func(c echo.Context) error { return c.Redirect(http.StatusMovedPermanently, "/.well-known/security.txt") }) + e.GET("/iframe/youtube.html", echo.WrapHandler(staticHandler)) e.GET("/static/*", echo.WrapHandler(http.StripPrefix("/static/", staticHandler)), func(next echo.HandlerFunc) echo.HandlerFunc { return func(c echo.Context) error { path := c.Request().URL.Path diff --git a/bskyweb/static/iframe/youtube.html b/bskyweb/static/iframe/youtube.html new file mode 100644 index 000000000..f2ada2ec5 --- /dev/null +++ b/bskyweb/static/iframe/youtube.html @@ -0,0 +1,49 @@ +<!DOCTYPE html><meta name="viewport" content="width=device-width, initial-scale=1" /> +<style> + body { + margin: 0; + } + .container { + position: relative; + width: 100%; + height: 0; + padding-bottom: 56.25%; + } + .video { + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 100%; + } +</style> +<div class="container"><div class="video" id="player"></div></div> +<script> + const url = new URL(window.location) + const viewport = document.querySelector("meta[name=viewport]") + + const tag = document.createElement("script") + tag.src = "https://www.youtube.com/iframe_api" + const firstScriptTag = document.getElementsByTagName('script')[0]; + firstScriptTag.parentNode.insertBefore(tag, firstScriptTag); + + let player + function onYouTubeIframeAPIReady() { + player = new YT.Player('player', { + width: "1000", + height: "1000", + videoId: url.searchParams.get('videoId'), + playerVars: { + autoplay: 1, + start: url.searchParams.get('start'), + rel: 0, + loop: 0, + playsinline: 1, + origin: url.origin + }, + }); + } + function onPlayerReady(event) { + event.target.playVideo(); + } +</script> diff --git a/src/lib/strings/embed-player.ts b/src/lib/strings/embed-player.ts index 3270b6f07..21a575b91 100644 --- a/src/lib/strings/embed-player.ts +++ b/src/lib/strings/embed-player.ts @@ -1,4 +1,5 @@ -import {Dimensions, Platform} from 'react-native' +import {Dimensions} from 'react-native' +import {isWeb} from 'platform/detection' const {height: SCREEN_HEIGHT} = Dimensions.get('window') export const embedPlayerSources = [ @@ -73,7 +74,7 @@ export function parseEmbedPlayerFromUrl( return { type: 'youtube_video', source: 'youtube', - playerUri: `https://www.youtube.com/embed/${videoId}?autoplay=1&playsinline=1&start=${seek}`, + playerUri: `https://bsky.app/iframe/youtube.html?videoId=${videoId}&start=${seek}`, } } } @@ -92,7 +93,7 @@ export function parseEmbedPlayerFromUrl( type: page === 'shorts' ? 'youtube_short' : 'youtube_video', source: page === 'shorts' ? 'youtubeShorts' : 'youtube', hideDetails: page === 'shorts' ? true : undefined, - playerUri: `https://www.youtube.com/embed/${videoId}?autoplay=1&playsinline=1&start=${seek}`, + playerUri: `https://bsky.app/iframe/youtube.html?videoId=${videoId}&start=${seek}`, } } } @@ -103,8 +104,10 @@ export function parseEmbedPlayerFromUrl( urlp.hostname === 'www.twitch.tv' || urlp.hostname === 'm.twitch.tv' ) { - const parent = - Platform.OS === 'web' ? window.location.hostname : 'localhost' + const parent = isWeb + ? // @ts-ignore only for web + window.location.hostname + : 'localhost' const [_, channelOrVideo, clipOrId, id] = urlp.pathname.split('/') diff --git a/src/view/com/util/post-embeds/ExternalPlayerEmbed.tsx b/src/view/com/util/post-embeds/ExternalPlayerEmbed.tsx index 8b0858b69..d556e7669 100644 --- a/src/view/com/util/post-embeds/ExternalPlayerEmbed.tsx +++ b/src/view/com/util/post-embeds/ExternalPlayerEmbed.tsx @@ -78,9 +78,13 @@ function Player({ onLoad: () => void }) { // ensures we only load what's requested + // when it's a youtube video, we need to allow both bsky.app and youtube.com const onShouldStartLoadWithRequest = React.useCallback( - (event: ShouldStartLoadRequest) => event.url === params.playerUri, - [params.playerUri], + (event: ShouldStartLoadRequest) => + event.url === params.playerUri || + (params.source.startsWith('youtube') && + event.url.includes('www.youtube.com')), + [params.playerUri, params.source], ) // Don't show the player until it is active |