about summary refs log tree commit diff
diff options
context:
space:
mode:
authorHailey <me@haileyok.com>2024-02-06 11:05:17 -0800
committerGitHub <noreply@github.com>2024-02-06 11:05:17 -0800
commit856f80fc6df731b1dbe9efa289ad6a4f728d4e0d (patch)
tree815d7ed5b083fe36cca321efa60042d14b22c16e
parenta9ab13e5a936c4d917b878bd53f4e536fa8c95f8 (diff)
downloadvoidsky-856f80fc6df731b1dbe9efa289ad6a4f728d4e0d.tar.zst
fix some youtube videos not properly loading (#2726)
* add player iframe to bskyweb

* iframe for youtube content

* update tests

* ts error
-rw-r--r--__tests__/lib/string.test.ts23
-rw-r--r--bskyweb/cmd/bskyweb/server.go1
-rw-r--r--bskyweb/static/iframe/youtube.html49
-rw-r--r--src/lib/strings/embed-player.ts13
-rw-r--r--src/view/com/util/post-embeds/ExternalPlayerEmbed.tsx8
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