about summary refs log tree commit diff
diff options
context:
space:
mode:
authorHailey <me@haileyok.com>2024-08-15 16:29:16 -0700
committerGitHub <noreply@github.com>2024-08-15 16:29:16 -0700
commita5af24b53b6085cfb5547592c29155bc10e71f9e (patch)
tree6946c933322c1cdfc455e63c02ca74b18651117b
parentb6e515c664d51ffe357c3562fd514301805ade8c (diff)
downloadvoidsky-a5af24b53b6085cfb5547592c29155bc10e71f9e.tar.zst
Revert "[Video] Download videos" (#4945)
-rw-r--r--bskyweb/cmd/bskyweb/server.go3
-rw-r--r--bskyweb/static/robots.txt1
-rw-r--r--modules/expo-bluesky-swiss-army/android/src/main/java/expo/modules/blueskyswissarmy/hlsdownload/ExpoHLSDownloadModule.kt35
-rw-r--r--modules/expo-bluesky-swiss-army/android/src/main/java/expo/modules/blueskyswissarmy/hlsdownload/HLSDownloadView.kt141
-rw-r--r--modules/expo-bluesky-swiss-army/expo-module.config.json4
-rw-r--r--modules/expo-bluesky-swiss-army/index.ts10
-rw-r--r--modules/expo-bluesky-swiss-army/ios/HLSDownload/ExpoHLSDownloadModule.swift31
-rw-r--r--modules/expo-bluesky-swiss-army/ios/HLSDownload/HLSDownloadView.swift148
-rw-r--r--modules/expo-bluesky-swiss-army/src/HLSDownload/index.native.tsx39
-rw-r--r--modules/expo-bluesky-swiss-army/src/HLSDownload/index.tsx22
-rw-r--r--modules/expo-bluesky-swiss-army/src/HLSDownload/types.ts10
-rw-r--r--package.json4
-rw-r--r--src/Navigation.tsx6
-rw-r--r--src/components/VideoDownloadScreen.native.tsx4
-rw-r--r--src/components/VideoDownloadScreen.tsx215
-rw-r--r--src/lib/routes/types.ts1
-rw-r--r--src/routes.ts1
-rw-r--r--src/view/screens/Storybook/index.tsx46
-rw-r--r--yarn.lock29
19 files changed, 3 insertions, 747 deletions
diff --git a/bskyweb/cmd/bskyweb/server.go b/bskyweb/cmd/bskyweb/server.go
index 01f1a8755..fdef01ce7 100644
--- a/bskyweb/cmd/bskyweb/server.go
+++ b/bskyweb/cmd/bskyweb/server.go
@@ -256,9 +256,6 @@ func serve(cctx *cli.Context) error {
 	e.GET("/profile/:handleOrDID/post/:rkey/liked-by", server.WebGeneric)
 	e.GET("/profile/:handleOrDID/post/:rkey/reposted-by", server.WebGeneric)
 
-	// video download
-	e.GET("/video-download", server.WebGeneric)
-
 	// starter packs
 	e.GET("/starter-pack/:handleOrDID/:rkey", server.WebStarterPack)
 	e.GET("/start/:handleOrDID/:rkey", server.WebStarterPack)
diff --git a/bskyweb/static/robots.txt b/bskyweb/static/robots.txt
index d785755a4..4f8510d18 100644
--- a/bskyweb/static/robots.txt
+++ b/bskyweb/static/robots.txt
@@ -7,4 +7,3 @@
 # be ok.
 User-Agent: *
 Allow: /
-Disallow: /video-download
diff --git a/modules/expo-bluesky-swiss-army/android/src/main/java/expo/modules/blueskyswissarmy/hlsdownload/ExpoHLSDownloadModule.kt b/modules/expo-bluesky-swiss-army/android/src/main/java/expo/modules/blueskyswissarmy/hlsdownload/ExpoHLSDownloadModule.kt
deleted file mode 100644
index 786b84e41..000000000
--- a/modules/expo-bluesky-swiss-army/android/src/main/java/expo/modules/blueskyswissarmy/hlsdownload/ExpoHLSDownloadModule.kt
+++ /dev/null
@@ -1,35 +0,0 @@
-package expo.modules.blueskyswissarmy.hlsdownload
-
-import android.net.Uri
-import expo.modules.kotlin.modules.Module
-import expo.modules.kotlin.modules.ModuleDefinition
-
-class ExpoHLSDownloadModule : Module() {
-  override fun definition() =
-    ModuleDefinition {
-      Name("ExpoHLSDownload")
-
-      Function("isAvailable") {
-        return@Function true
-      }
-
-      View(HLSDownloadView::class) {
-        Events(
-          arrayOf(
-            "onStart",
-            "onError",
-            "onProgress",
-            "onSuccess",
-          ),
-        )
-
-        Prop("downloaderUrl") { view: HLSDownloadView, downloaderUrl: Uri ->
-          view.downloaderUrl = downloaderUrl
-        }
-
-        AsyncFunction("startDownloadAsync") { view: HLSDownloadView, sourceUrl: Uri ->
-          view.startDownload(sourceUrl)
-        }
-      }
-    }
-}
diff --git a/modules/expo-bluesky-swiss-army/android/src/main/java/expo/modules/blueskyswissarmy/hlsdownload/HLSDownloadView.kt b/modules/expo-bluesky-swiss-army/android/src/main/java/expo/modules/blueskyswissarmy/hlsdownload/HLSDownloadView.kt
deleted file mode 100644
index 5f3082a81..000000000
--- a/modules/expo-bluesky-swiss-army/android/src/main/java/expo/modules/blueskyswissarmy/hlsdownload/HLSDownloadView.kt
+++ /dev/null
@@ -1,141 +0,0 @@
-package expo.modules.blueskyswissarmy.hlsdownload
-
-import android.annotation.SuppressLint
-import android.content.Context
-import android.net.Uri
-import android.util.Base64
-import android.util.Log
-import android.webkit.DownloadListener
-import android.webkit.JavascriptInterface
-import android.webkit.WebView
-import expo.modules.kotlin.AppContext
-import expo.modules.kotlin.viewevent.EventDispatcher
-import expo.modules.kotlin.viewevent.ViewEventCallback
-import expo.modules.kotlin.views.ExpoView
-import org.json.JSONObject
-import java.io.File
-import java.io.FileOutputStream
-import java.net.URI
-import java.util.UUID
-
-class HLSDownloadView(
-  context: Context,
-  appContext: AppContext,
-) : ExpoView(context, appContext),
-  DownloadListener {
-  private val webView = WebView(context)
-
-  var downloaderUrl: Uri? = null
-
-  private val onStart by EventDispatcher()
-  private val onError by EventDispatcher()
-  private val onProgress by EventDispatcher()
-  private val onSuccess by EventDispatcher()
-
-  init {
-    this.setupWebView()
-    this.addView(this.webView, LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT))
-  }
-
-  @SuppressLint("SetJavaScriptEnabled")
-  private fun setupWebView() {
-    val webSettings = this.webView.settings
-    webSettings.javaScriptEnabled = true
-    webSettings.domStorageEnabled = true
-
-    webView.setDownloadListener(this)
-    webView.addJavascriptInterface(WebAppInterface(this.onProgress, this.onError), "AndroidInterface")
-  }
-
-  override fun onDetachedFromWindow() {
-    super.onDetachedFromWindow()
-    this.webView.stopLoading()
-    this.webView.clearHistory()
-    this.webView.removeAllViews()
-    this.webView.destroy()
-  }
-
-  fun startDownload(sourceUrl: Uri) {
-    if (this.downloaderUrl == null) {
-      this.onError(mapOf(ERROR_KEY to "Downloader URL is not set."))
-      return
-    }
-
-    val url = URI("${this.downloaderUrl}?videoUrl=$sourceUrl")
-    this.webView.loadUrl(url.toString())
-    this.onStart(mapOf())
-  }
-
-  override fun onDownloadStart(
-    url: String?,
-    userAgent: String?,
-    contentDisposition: String?,
-    mimeType: String?,
-    contentLength: Long,
-  ) {
-    if (url == null) {
-      this.onError(mapOf(ERROR_KEY to "Failed to retrieve download URL from webview."))
-      return
-    }
-
-    val tempDir = context.cacheDir
-    val fileName = "${UUID.randomUUID()}.mp4"
-    val file = File(tempDir, fileName)
-
-    val base64 = url.split(",")[1]
-    val bytes = Base64.decode(base64, Base64.DEFAULT)
-
-    val fos = FileOutputStream(file)
-    try {
-      fos.write(bytes)
-    } catch (e: Exception) {
-      Log.e("FileDownload", "Error downloading file", e)
-      this.onError(mapOf(ERROR_KEY to e.message.toString()))
-      return
-    } finally {
-      fos.close()
-    }
-
-    val uri = Uri.fromFile(file)
-    this.onSuccess(mapOf("uri" to uri.toString()))
-  }
-
-  companion object {
-    const val ERROR_KEY = "message"
-  }
-}
-
-public class WebAppInterface(
-  val onProgress: ViewEventCallback<Map<String, Any>>,
-  val onError: ViewEventCallback<Map<String, Any>>,
-) {
-  @JavascriptInterface
-  public fun onMessage(message: String) {
-    val jsonObject = JSONObject(message)
-    val action = jsonObject.getString("action")
-
-    when (action) {
-      "error" -> {
-        val messageStr = jsonObject.get("messageStr")
-        if (messageStr !is String) {
-          this.onError(mapOf(ERROR_KEY to "Failed to decode JSON post message."))
-          return
-        }
-        this.onError(mapOf(ERROR_KEY to messageStr))
-      }
-      "progress" -> {
-        val messageFloat = jsonObject.get("messageFloat")
-        if (messageFloat !is Number) {
-          this.onError(mapOf(ERROR_KEY to "Failed to decode JSON post message."))
-          return
-        }
-        this.onProgress(mapOf(PROGRESS_KEY to messageFloat))
-      }
-    }
-  }
-
-  companion object {
-    const val PROGRESS_KEY = "progress"
-    const val ERROR_KEY = "message"
-  }
-}
diff --git a/modules/expo-bluesky-swiss-army/expo-module.config.json b/modules/expo-bluesky-swiss-army/expo-module.config.json
index 04411ecf7..4cdc11e99 100644
--- a/modules/expo-bluesky-swiss-army/expo-module.config.json
+++ b/modules/expo-bluesky-swiss-army/expo-module.config.json
@@ -5,7 +5,6 @@
       "ExpoBlueskySharedPrefsModule",
       "ExpoBlueskyReferrerModule",
       "ExpoBlueskyVisibilityViewModule",
-      "ExpoHLSDownloadModule",
       "ExpoPlatformInfoModule"
     ]
   },
@@ -14,8 +13,7 @@
       "expo.modules.blueskyswissarmy.sharedprefs.ExpoBlueskySharedPrefsModule",
       "expo.modules.blueskyswissarmy.referrer.ExpoBlueskyReferrerModule",
       "expo.modules.blueskyswissarmy.visibilityview.ExpoBlueskyVisibilityViewModule",
-      "expo.modules.blueskyswissarmy.platforminfo.ExpoPlatformInfoModule",
-      "expo.modules.blueskyswissarmy.hlsdownload.ExpoHLSDownloadModule"
+      "expo.modules.blueskyswissarmy.platforminfo.ExpoPlatformInfoModule"
     ]
   }
 }
diff --git a/modules/expo-bluesky-swiss-army/index.ts b/modules/expo-bluesky-swiss-army/index.ts
index 67dc6ee60..2cf4f36c5 100644
--- a/modules/expo-bluesky-swiss-army/index.ts
+++ b/modules/expo-bluesky-swiss-army/index.ts
@@ -1,15 +1,7 @@
-import HLSDownloadView from './src/HLSDownload'
 import * as PlatformInfo from './src/PlatformInfo'
 import {AudioCategory} from './src/PlatformInfo/types'
 import * as Referrer from './src/Referrer'
 import * as SharedPrefs from './src/SharedPrefs'
 import VisibilityView from './src/VisibilityView'
 
-export {
-  AudioCategory,
-  HLSDownloadView,
-  PlatformInfo,
-  Referrer,
-  SharedPrefs,
-  VisibilityView,
-}
+export {AudioCategory, PlatformInfo, Referrer, SharedPrefs, VisibilityView}
diff --git a/modules/expo-bluesky-swiss-army/ios/HLSDownload/ExpoHLSDownloadModule.swift b/modules/expo-bluesky-swiss-army/ios/HLSDownload/ExpoHLSDownloadModule.swift
deleted file mode 100644
index a9b445e48..000000000
--- a/modules/expo-bluesky-swiss-army/ios/HLSDownload/ExpoHLSDownloadModule.swift
+++ /dev/null
@@ -1,31 +0,0 @@
-import ExpoModulesCore
-
-public class ExpoHLSDownloadModule: Module {
-  public func definition() -> ModuleDefinition {
-    Name("ExpoHLSDownload")
-
-    Function("isAvailable") {
-      if #available(iOS 14.5, *) {
-        return true
-      }
-      return false
-    }
-
-    View(HLSDownloadView.self) {
-      Events([
-        "onStart",
-        "onError",
-        "onProgress",
-        "onSuccess"
-      ])
-
-      Prop("downloaderUrl") { (view: HLSDownloadView, downloaderUrl: URL) in
-        view.downloaderUrl = downloaderUrl
-      }
-
-      AsyncFunction("startDownloadAsync") { (view: HLSDownloadView, sourceUrl: URL) in
-        view.startDownload(sourceUrl: sourceUrl)
-      }
-    }
-  }
-}
diff --git a/modules/expo-bluesky-swiss-army/ios/HLSDownload/HLSDownloadView.swift b/modules/expo-bluesky-swiss-army/ios/HLSDownload/HLSDownloadView.swift
deleted file mode 100644
index 591c09335..000000000
--- a/modules/expo-bluesky-swiss-army/ios/HLSDownload/HLSDownloadView.swift
+++ /dev/null
@@ -1,148 +0,0 @@
-import ExpoModulesCore
-import WebKit
-
-class HLSDownloadView: ExpoView, WKScriptMessageHandler, WKNavigationDelegate, WKDownloadDelegate {
-  var webView: WKWebView!
-  var downloaderUrl: URL?
-
-  private var onStart = EventDispatcher()
-  private var onError = EventDispatcher()
-  private var onProgress = EventDispatcher()
-  private var onSuccess = EventDispatcher()
-
-  private var outputUrl: URL?
-
-  public required init(appContext: AppContext? = nil) {
-    super.init(appContext: appContext)
-
-    // controller for post message api
-    let contentController = WKUserContentController()
-    contentController.add(self, name: "onMessage")
-    let configuration = WKWebViewConfiguration()
-    configuration.userContentController = contentController
-
-    // create webview
-    let webView = WKWebView(frame: .zero, configuration: configuration)
-
-    // Use these for debugging, to see the webview itself
-    webView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
-    webView.layer.masksToBounds = false
-    webView.backgroundColor = .clear
-    webView.contentMode = .scaleToFill
-
-    webView.navigationDelegate = self
-
-    self.addSubview(webView)
-    self.webView = webView
-  }
-
-  required init?(coder: NSCoder) {
-    fatalError("init(coder:) has not been implemented")
-  }
-
-  // MARK: - view functions
-
-  func startDownload(sourceUrl: URL) {
-    guard let downloaderUrl = self.downloaderUrl,
-          let url = URL(string: "\(downloaderUrl.absoluteString)?videoUrl=\(sourceUrl.absoluteString)") else {
-      self.onError([
-        "message": "Downloader URL is not set."
-      ])
-      return
-    }
-
-    self.onStart()
-    self.webView.load(URLRequest(url: url))
-  }
-
-  // webview message handling
-
-  func userContentController(_ userContentController: WKUserContentController, didReceive message: WKScriptMessage) {
-    guard let response = message.body as? String,
-          let data = response.data(using: .utf8),
-          let payload = try? JSONDecoder().decode(WebViewActionPayload.self, from: data) else {
-      self.onError([
-        "message": "Failed to decode JSON post message."
-      ])
-      return
-    }
-
-    switch payload.action {
-    case .progress:
-      guard let progress = payload.messageFloat else {
-        self.onError([
-          "message": "Failed to decode JSON post message."
-        ])
-        return
-      }
-      self.onProgress([
-        "progress": progress
-      ])
-      case .error:
-      guard let messageStr = payload.messageStr else {
-        self.onError([
-          "message": "Failed to decode JSON post message."
-        ])
-        return
-      }
-      self.onError([
-        "message": messageStr
-      ])
-    }
-  }
-
-  func webView(_ webView: WKWebView, decidePolicyFor navigationAction: WKNavigationAction) async -> WKNavigationActionPolicy {
-    guard #available(iOS 14.5, *) else {
-      return .cancel
-    }
-
-    if navigationAction.shouldPerformDownload {
-      return .download
-    } else {
-      return .allow
-    }
-  }
-
-  // MARK: - wkdownloaddelegate
-
-  @available(iOS 14.5, *)
-  func webView(_ webView: WKWebView, navigationAction: WKNavigationAction, didBecome download: WKDownload) {
-    download.delegate = self
-  }
-
-  @available(iOS 14.5, *)
-  func webView(_ webView: WKWebView, navigationResponse: WKNavigationResponse, didBecome download: WKDownload) {
-    download.delegate = self
-  }
-
-  @available(iOS 14.5, *)
-  func download(_ download: WKDownload, decideDestinationUsing response: URLResponse, suggestedFilename: String, completionHandler: @escaping (URL?) -> Void) {
-    let directory = NSTemporaryDirectory()
-    let fileName = "\(NSUUID().uuidString).mp4"
-    let url = NSURL.fileURL(withPathComponents: [directory, fileName])
-
-    self.outputUrl = url
-    completionHandler(url)
-  }
-
-  @available(iOS 14.5, *)
-  func downloadDidFinish(_ download: WKDownload) {
-    guard let url = self.outputUrl else {
-      return
-    }
-    self.onSuccess([
-      "uri": url.absoluteString
-    ])
-    self.outputUrl = nil
-  }
-}
-
-struct WebViewActionPayload: Decodable {
-  enum Action: String, Decodable {
-    case progress, error
-  }
-
-  let action: Action
-  let messageStr: String?
-  let messageFloat: Float?
-}
diff --git a/modules/expo-bluesky-swiss-army/src/HLSDownload/index.native.tsx b/modules/expo-bluesky-swiss-army/src/HLSDownload/index.native.tsx
deleted file mode 100644
index 92f26192e..000000000
--- a/modules/expo-bluesky-swiss-army/src/HLSDownload/index.native.tsx
+++ /dev/null
@@ -1,39 +0,0 @@
-import React from 'react'
-import {StyleProp, ViewStyle} from 'react-native'
-import {requireNativeModule, requireNativeViewManager} from 'expo-modules-core'
-
-import {HLSDownloadViewProps} from './types'
-
-const NativeModule = requireNativeModule('ExpoHLSDownload')
-const NativeView: React.ComponentType<
-  HLSDownloadViewProps & {
-    ref: React.RefObject<any>
-    style: StyleProp<ViewStyle>
-  }
-> = requireNativeViewManager('ExpoHLSDownload')
-
-export default class HLSDownloadView extends React.PureComponent<HLSDownloadViewProps> {
-  private nativeRef: React.RefObject<any> = React.createRef()
-
-  constructor(props: HLSDownloadViewProps) {
-    super(props)
-  }
-
-  static isAvailable(): boolean {
-    return NativeModule.isAvailable()
-  }
-
-  async startDownloadAsync(sourceUrl: string): Promise<void> {
-    return await this.nativeRef.current.startDownloadAsync(sourceUrl)
-  }
-
-  render() {
-    return (
-      <NativeView
-        ref={this.nativeRef}
-        style={{height: 0, width: 0}}
-        {...this.props}
-      />
-    )
-  }
-}
diff --git a/modules/expo-bluesky-swiss-army/src/HLSDownload/index.tsx b/modules/expo-bluesky-swiss-army/src/HLSDownload/index.tsx
deleted file mode 100644
index 93c50497f..000000000
--- a/modules/expo-bluesky-swiss-army/src/HLSDownload/index.tsx
+++ /dev/null
@@ -1,22 +0,0 @@
-import React from 'react'
-
-import {NotImplementedError} from '../NotImplemented'
-import {HLSDownloadViewProps} from './types'
-
-export default class HLSDownloadView extends React.PureComponent<HLSDownloadViewProps> {
-  constructor(props: HLSDownloadViewProps) {
-    super(props)
-  }
-
-  static isAvailable(): boolean {
-    return false
-  }
-
-  async startDownloadAsync(sourceUrl: string): Promise<void> {
-    throw new NotImplementedError({sourceUrl})
-  }
-
-  render() {
-    return null
-  }
-}
diff --git a/modules/expo-bluesky-swiss-army/src/HLSDownload/types.ts b/modules/expo-bluesky-swiss-army/src/HLSDownload/types.ts
deleted file mode 100644
index 6a474d282..000000000
--- a/modules/expo-bluesky-swiss-army/src/HLSDownload/types.ts
+++ /dev/null
@@ -1,10 +0,0 @@
-import {NativeSyntheticEvent} from 'react-native'
-
-export interface HLSDownloadViewProps {
-  downloaderUrl: string
-  onSuccess: (e: NativeSyntheticEvent<{uri: string}>) => void
-
-  onStart?: () => void
-  onError?: (e: NativeSyntheticEvent<{message: string}>) => void
-  onProgress?: (e: NativeSyntheticEvent<{progress: number}>) => void
-}
diff --git a/package.json b/package.json
index 088f2faf7..a4523d988 100644
--- a/package.json
+++ b/package.json
@@ -59,8 +59,6 @@
     "@emoji-mart/react": "^1.1.1",
     "@expo/html-elements": "^0.4.2",
     "@expo/webpack-config": "^19.0.0",
-    "@ffmpeg/ffmpeg": "^0.12.10",
-    "@ffmpeg/util": "^0.12.1",
     "@floating-ui/dom": "^1.6.3",
     "@floating-ui/react-dom": "^2.0.8",
     "@formatjs/intl-locale": "^4.0.0",
@@ -145,7 +143,6 @@
     "expo-web-browser": "~13.0.3",
     "fast-text-encoding": "^1.0.6",
     "history": "^5.3.0",
-    "hls-parser": "^0.13.3",
     "hls.js": "^1.5.11",
     "js-sha256": "^0.9.0",
     "jwt-decode": "^4.0.0",
@@ -227,7 +224,6 @@
     "@testing-library/react-native": "^11.5.2",
     "@tsconfig/react-native": "^2.0.3",
     "@types/he": "^1.1.2",
-    "@types/hls-parser": "^0.8.7",
     "@types/jest": "^29.4.0",
     "@types/lodash.chunk": "^4.2.7",
     "@types/lodash.debounce": "^4.0.7",
diff --git a/src/Navigation.tsx b/src/Navigation.tsx
index 0d151427f..79856879c 100644
--- a/src/Navigation.tsx
+++ b/src/Navigation.tsx
@@ -50,7 +50,6 @@ import {
   StarterPackScreenShort,
 } from '#/screens/StarterPack/StarterPackScreen'
 import {Wizard} from '#/screens/StarterPack/Wizard'
-import {VideoDownloadScreen} from '#/components/VideoDownloadScreen'
 import {Referrer} from '../modules/expo-bluesky-swiss-army'
 import {init as initAnalytics} from './lib/analytics/analytics'
 import {useWebScrollRestoration} from './lib/hooks/useWebScrollRestoration'
@@ -365,11 +364,6 @@ function commonScreens(Stack: typeof HomeTab, unreadCountLabel?: string) {
         getComponent={() => Wizard}
         options={{title: title(msg`Edit your starter pack`), requireAuth: true}}
       />
-      <Stack.Screen
-        name="VideoDownload"
-        getComponent={() => VideoDownloadScreen}
-        options={{title: title(msg`Download video`)}}
-      />
     </>
   )
 }
diff --git a/src/components/VideoDownloadScreen.native.tsx b/src/components/VideoDownloadScreen.native.tsx
deleted file mode 100644
index a1f6466fd..000000000
--- a/src/components/VideoDownloadScreen.native.tsx
+++ /dev/null
@@ -1,4 +0,0 @@
-export function VideoDownloadScreen() {
-  // @TODO redirect
-  return null
-}
diff --git a/src/components/VideoDownloadScreen.tsx b/src/components/VideoDownloadScreen.tsx
deleted file mode 100644
index 3169d265d..000000000
--- a/src/components/VideoDownloadScreen.tsx
+++ /dev/null
@@ -1,215 +0,0 @@
-import React from 'react'
-import {parse} from 'hls-parser'
-import {MasterPlaylist, MediaPlaylist, Variant} from 'hls-parser/types'
-
-interface PostMessageData {
-  action: 'progress' | 'error'
-  messageStr?: string
-  messageFloat?: number
-}
-
-function postMessage(data: PostMessageData) {
-  // @ts-expect-error safari webview only
-  if (window?.webkit) {
-    // @ts-expect-error safari webview only
-    window.webkit.messageHandlers.onMessage.postMessage(JSON.stringify(data))
-    // @ts-expect-error android webview only
-  } else if (AndroidInterface) {
-    // @ts-expect-error android webview only
-    AndroidInterface.onMessage(JSON.stringify(data))
-  }
-}
-
-function createSegementUrl(originalUrl: string, newFile: string) {
-  const parts = originalUrl.split('/')
-  parts[parts.length - 1] = newFile
-  return parts.join('/')
-}
-
-export function VideoDownloadScreen() {
-  const ffmpegRef = React.useRef<any>(null)
-  const fetchFileRef = React.useRef<any>(null)
-
-  const [dataUrl, setDataUrl] = React.useState<any>(null)
-
-  const load = React.useCallback(async () => {
-    const ffmpegLib = await import('@ffmpeg/ffmpeg')
-    const ffmpeg = new ffmpegLib.FFmpeg()
-    ffmpegRef.current = ffmpeg
-
-    const ffmpegUtilLib = await import('@ffmpeg/util')
-    fetchFileRef.current = ffmpegUtilLib.fetchFile
-
-    const baseURL = 'https://unpkg.com/@ffmpeg/core@0.12.6/dist/esm'
-
-    await ffmpeg.load({
-      coreURL: await ffmpegUtilLib.toBlobURL(
-        `${baseURL}/ffmpeg-core.js`,
-        'text/javascript',
-      ),
-      wasmURL: await ffmpegUtilLib.toBlobURL(
-        `${baseURL}/ffmpeg-core.wasm`,
-        'application/wasm',
-      ),
-    })
-  }, [])
-
-  const createMp4 = React.useCallback(async (videoUrl: string) => {
-    // Get the master playlist and find the best variant
-    const masterPlaylistRes = await fetch(videoUrl)
-    const masterPlaylistText = await masterPlaylistRes.text()
-    const masterPlaylist = parse(masterPlaylistText) as MasterPlaylist
-
-    // If URL given is not a master playlist, we probably cannot handle this.
-    if (!masterPlaylist.isMasterPlaylist) {
-      postMessage({
-        action: 'error',
-        messageStr: 'A master playlist was not found in the provided playlist.',
-      })
-      return
-    }
-
-    // Figure out what the best quality is. These should generally be in order, but we'll check them all just in case
-    let bestVariant: Variant | undefined
-    for (const variant of masterPlaylist.variants) {
-      if (!bestVariant || variant.bandwidth > bestVariant.bandwidth) {
-        bestVariant = variant
-      }
-    }
-
-    // Should only happen if there was no variants at all given to us. Mostly for types.
-    if (!bestVariant) {
-      postMessage({
-        action: 'error',
-        messageStr: 'No variants were found in the provided master playlist.',
-      })
-      return
-    }
-
-    const urlParts = videoUrl.split('/')
-    urlParts[urlParts.length - 1] = bestVariant?.uri
-    const bestVariantUrl = urlParts.join('/')
-
-    // Download and parse m3u8
-    const hlsFileRes = await fetch(bestVariantUrl)
-    const hlsPlainText = await hlsFileRes.text()
-    const playlist = parse(hlsPlainText) as MediaPlaylist
-
-    // This one shouldn't be a master playlist - again just for types really
-    if (playlist.isMasterPlaylist) {
-      postMessage({
-        action: 'error',
-        messageStr: 'An unknown error has occurred.',
-      })
-      return
-    }
-
-    const ffmpeg = ffmpegRef.current
-
-    // Get the correctly ordered file names. We need to remove the tracking info from the end of the file name
-    const segments = playlist.segments.map(segment => {
-      return segment.uri.split('?')[0]
-    })
-
-    // Download each segment
-    let error: string | null = null
-    let completed = 0
-    await Promise.all(
-      playlist.segments.map(async segment => {
-        const uri = createSegementUrl(bestVariantUrl, segment.uri)
-        const filename = segment.uri.split('?')[0]
-
-        const res = await fetch(uri)
-        if (!res.ok) {
-          error = 'Failed to download playlist segment.'
-        }
-
-        const blob = await res.blob()
-        try {
-          await ffmpeg.writeFile(filename, await fetchFileRef.current(blob))
-        } catch (e: unknown) {
-          error = 'Failed to write file.'
-        } finally {
-          completed++
-          const progress = completed / playlist.segments.length
-          postMessage({
-            action: 'progress',
-            messageFloat: progress,
-          })
-        }
-      }),
-    )
-
-    // Do something if there was an error
-    if (error) {
-      postMessage({
-        action: 'error',
-        messageStr: error,
-      })
-      return
-    }
-
-    // Put the segments together
-    await ffmpeg.exec([
-      '-i',
-      `concat:${segments.join('|')}`,
-      '-c:v',
-      'copy',
-      'output.mp4',
-    ])
-
-    const fileData = await ffmpeg.readFile('output.mp4')
-    const blob = new Blob([fileData.buffer], {type: 'video/mp4'})
-    const dataUrl = await new Promise<string | null>(resolve => {
-      const reader = new FileReader()
-      reader.onloadend = () => resolve(reader.result as string)
-      reader.onerror = () => resolve(null)
-      reader.readAsDataURL(blob)
-    })
-    return dataUrl
-  }, [])
-
-  const download = React.useCallback(
-    async (videoUrl: string) => {
-      await load()
-      const mp4Res = await createMp4(videoUrl)
-
-      if (!mp4Res) {
-        postMessage({
-          action: 'error',
-          messageStr: 'An error occurred while creating the MP4.',
-        })
-        return
-      }
-
-      setDataUrl(mp4Res)
-    },
-    [createMp4, load],
-  )
-
-  React.useEffect(() => {
-    const url = new URL(window.location.href)
-    const videoUrl = url.searchParams.get('videoUrl')
-
-    if (!videoUrl) {
-      postMessage({action: 'error', messageStr: 'No video URL provided'})
-    } else {
-      setDataUrl(null)
-      download(videoUrl)
-    }
-  }, [download])
-
-  if (!dataUrl) return null
-
-  return (
-    <div>
-      <a
-        href={dataUrl}
-        ref={el => {
-          el?.click()
-        }}
-        download="video.mp4"
-      />
-    </div>
-  )
-}
diff --git a/src/lib/routes/types.ts b/src/lib/routes/types.ts
index 77e7266a4..0cc83b475 100644
--- a/src/lib/routes/types.ts
+++ b/src/lib/routes/types.ts
@@ -50,7 +50,6 @@ export type CommonNavigatorParams = {
   StarterPackShort: {code: string}
   StarterPackWizard: undefined
   StarterPackEdit: {rkey?: string}
-  VideoDownload: undefined
 }
 
 export type BottomTabNavigatorParams = CommonNavigatorParams & {
diff --git a/src/routes.ts b/src/routes.ts
index bda2d98e4..c9e23e08c 100644
--- a/src/routes.ts
+++ b/src/routes.ts
@@ -48,5 +48,4 @@ export const router = new Router({
   StarterPack: '/starter-pack/:name/:rkey',
   StarterPackShort: '/starter-pack-short/:code',
   StarterPackWizard: '/starter-pack/create',
-  VideoDownload: '/video-download',
 })
diff --git a/src/view/screens/Storybook/index.tsx b/src/view/screens/Storybook/index.tsx
index c6da63314..71dbe8839 100644
--- a/src/view/screens/Storybook/index.tsx
+++ b/src/view/screens/Storybook/index.tsx
@@ -1,17 +1,12 @@
 import React from 'react'
 import {ScrollView, View} from 'react-native'
-import {deleteAsync} from 'expo-file-system'
-import {saveToLibraryAsync} from 'expo-media-library'
 
 import {useSetThemePrefs} from '#/state/shell'
-import {useVideoLibraryPermission} from 'lib/hooks/usePermissions'
-import {isIOS, isWeb} from 'platform/detection'
+import {isWeb} from 'platform/detection'
 import {CenteredView} from '#/view/com/util/Views'
-import * as Toast from 'view/com/util/Toast'
 import {ListContained} from 'view/screens/Storybook/ListContained'
 import {atoms as a, ThemeProvider, useTheme} from '#/alf'
 import {Button, ButtonText} from '#/components/Button'
-import {HLSDownloadView} from '../../../../modules/expo-bluesky-swiss-army'
 import {Breakpoints} from './Breakpoints'
 import {Buttons} from './Buttons'
 import {Dialogs} from './Dialogs'
@@ -38,49 +33,10 @@ function StorybookInner() {
   const t = useTheme()
   const {setColorMode, setDarkTheme} = useSetThemePrefs()
   const [showContainedList, setShowContainedList] = React.useState(false)
-  const hlsDownloadRef = React.useRef<HLSDownloadView>(null)
-
-  const {requestVideoAccessIfNeeded} = useVideoLibraryPermission()
 
   return (
     <CenteredView style={[t.atoms.bg]}>
       <View style={[a.p_xl, a.gap_5xl, {paddingBottom: 100}]}>
-        <HLSDownloadView
-          ref={hlsDownloadRef}
-          downloaderUrl={
-            isIOS
-              ? 'http://localhost:19006/video-download'
-              : 'http://10.0.2.2:19006/video-download'
-          }
-          onSuccess={async e => {
-            const uri = e.nativeEvent.uri
-            const permsRes = await requestVideoAccessIfNeeded()
-            if (!permsRes) return
-
-            await saveToLibraryAsync(uri)
-            try {
-              deleteAsync(uri)
-            } catch (err) {
-              console.error('Failed to delete file', err)
-            }
-            Toast.show('Video saved to library')
-          }}
-          onStart={() => console.log('Download is starting')}
-          onError={e => console.log(e.nativeEvent.message)}
-          onProgress={e => console.log(e.nativeEvent.progress)}
-        />
-        <Button
-          variant="solid"
-          color="primary"
-          size="small"
-          onPress={async () => {
-            hlsDownloadRef.current?.startDownloadAsync(
-              'https://lumi.jazco.dev/watch/did:plc:q6gjnaw2blty4crticxkmujt/Qmc8w93UpTa2adJHg4ZhnDPrBs1EsbzrekzPcqF5SwusuZ/playlist.m3u8?download=true',
-            )
-          }}
-          label="Video download test">
-          <ButtonText>Video download test</ButtonText>
-        </Button>
         {!showContainedList ? (
           <>
             <View style={[a.flex_row, a.align_start, a.gap_md]}>
diff --git a/yarn.lock b/yarn.lock
index 28308d951..cd0508d6a 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -3925,23 +3925,6 @@
   resolved "https://registry.yarnpkg.com/@fastify/deepmerge/-/deepmerge-1.3.0.tgz#8116858108f0c7d9fd460d05a7d637a13fe3239a"
   integrity sha512-J8TOSBq3SoZbDhM9+R/u77hP93gz/rajSA+K2kGyijPpORPWUXHUpTaleoj+92As0S9uPRP7Oi8IqMf0u+ro6A==
 
-"@ffmpeg/ffmpeg@^0.12.10":
-  version "0.12.10"
-  resolved "https://registry.yarnpkg.com/@ffmpeg/ffmpeg/-/ffmpeg-0.12.10.tgz#e3cce21f21f11f33dfc1ec1d5ad5694f4a3073c9"
-  integrity sha512-lVtk8PW8e+NUzGZhPTWj2P1J4/NyuCrbDD3O9IGpSeLYtUZKBqZO8CNj1WYGghep/MXoM8e1qVY1GztTkf8YYQ==
-  dependencies:
-    "@ffmpeg/types" "^0.12.2"
-
-"@ffmpeg/types@^0.12.2":
-  version "0.12.2"
-  resolved "https://registry.yarnpkg.com/@ffmpeg/types/-/types-0.12.2.tgz#bc7eef321ae50225c247091f1f23fd3087c6aa1d"
-  integrity sha512-NJtxwPoLb60/z1Klv0ueshguWQ/7mNm106qdHkB4HL49LXszjhjCCiL+ldHJGQ9ai2Igx0s4F24ghigy//ERdA==
-
-"@ffmpeg/util@^0.12.1":
-  version "0.12.1"
-  resolved "https://registry.yarnpkg.com/@ffmpeg/util/-/util-0.12.1.tgz#98afa20d7b4c0821eebdb205ddcfa5d07b0a4f53"
-  integrity sha512-10jjfAKWaDyb8+nAkijcsi9wgz/y26LOc1NKJradNMyCIl6usQcBbhkjX5qhALrSBcOy6TOeksunTYa+a03qNQ==
-
 "@floating-ui/core@^1.0.0":
   version "1.6.0"
   resolved "https://registry.yarnpkg.com/@floating-ui/core/-/core-1.6.0.tgz#fa41b87812a16bf123122bf945946bae3fdf7fc1"
@@ -8024,13 +8007,6 @@
   resolved "https://registry.yarnpkg.com/@types/he/-/he-1.2.0.tgz#3845193e597d943bab4e61ca5d7f3d8fc3d572a3"
   integrity sha512-uH2smqTN4uGReAiKedIVzoLUAXIYLBTbSofhx3hbNqj74Ua6KqFsLYszduTrLCMEAEAozF73DbGi/SC1bzQq4g==
 
-"@types/hls-parser@^0.8.7":
-  version "0.8.7"
-  resolved "https://registry.yarnpkg.com/@types/hls-parser/-/hls-parser-0.8.7.tgz#26360493231ed8606ebe995976c63c69c3982657"
-  integrity sha512-3ry9V6i/uhSbNdvBUENAqt2p5g+xKIbjkr5Qv4EaXe7eIJnaGQntFZalRLQlKoEop381a0LwUr2qNKKlxQC4TQ==
-  dependencies:
-    "@types/node" "*"
-
 "@types/html-minifier-terser@^6.0.0":
   version "6.1.0"
   resolved "https://registry.yarnpkg.com/@types/html-minifier-terser/-/html-minifier-terser-6.1.0.tgz#4fc33a00c1d0c16987b1a20cf92d20614c55ac35"
@@ -13480,11 +13456,6 @@ history@^5.3.0:
   dependencies:
     "@babel/runtime" "^7.7.6"
 
-hls-parser@^0.13.3:
-  version "0.13.3"
-  resolved "https://registry.yarnpkg.com/hls-parser/-/hls-parser-0.13.3.tgz#5f7a305629cf462bbf16a4d080e03e0be714f1fe"
-  integrity sha512-DXqW7bwx9j2qFcAXS/LBJTDJWitxknb6oUnsnTvECHrecPvPbhRgIu45OgNDUU6gpwKxMJx40SHRRUUhdIM2gA==
-
 hls.js@^1.5.11:
   version "1.5.11"
   resolved "https://registry.yarnpkg.com/hls.js/-/hls.js-1.5.11.tgz#3941347df454983859ae8c75fe19e8818719a826"