diff --git a/src/components/Post/Embed/VideoEmbed/VideoEmbedInner/VideoEmbedInnerWeb.native.tsx b/src/components/Post/Embed/VideoEmbed/VideoEmbedInner/VideoEmbedInnerWeb.native.tsx index 71b3533d03..10e8c73236 100644 --- a/src/components/Post/Embed/VideoEmbed/VideoEmbedInner/VideoEmbedInnerWeb.native.tsx +++ b/src/components/Post/Embed/VideoEmbed/VideoEmbedInner/VideoEmbedInnerWeb.native.tsx @@ -1,23 +1,10 @@ -import {type AppBskyEmbedVideo} from '@atproto/api' +import {type VideoEmbedInnerWebProps} from './VideoEmbedInnerWeb.shared' -export function VideoEmbedInnerWeb(_props: { - embed: AppBskyEmbedVideo.View - active: boolean - setActive: () => void - onScreen: boolean - lastKnownTime: React.RefObject -}): never { +export { + HLSUnsupportedError, + VideoNotFoundError, +} from './VideoEmbedInnerWeb.shared' + +export function VideoEmbedInnerWeb(_props: VideoEmbedInnerWebProps): never { throw new Error('VideoEmbedInnerWeb may not be used on native.') } - -export class HLSUnsupportedError extends Error { - constructor() { - super('HLS is not supported') - } -} - -export class VideoNotFoundError extends Error { - constructor() { - super('Video not found') - } -} diff --git a/src/components/Post/Embed/VideoEmbed/VideoEmbedInner/VideoEmbedInnerWeb.shared.ts b/src/components/Post/Embed/VideoEmbed/VideoEmbedInner/VideoEmbedInnerWeb.shared.ts new file mode 100644 index 0000000000..06abf40408 --- /dev/null +++ b/src/components/Post/Embed/VideoEmbed/VideoEmbedInner/VideoEmbedInnerWeb.shared.ts @@ -0,0 +1,21 @@ +import {type AppBskyEmbedVideo} from '@atproto/api' + +export type VideoEmbedInnerWebProps = { + embed: AppBskyEmbedVideo.View + active: boolean + setActive: () => void + onScreen: boolean + lastKnownTime: React.RefObject +} + +export class HLSUnsupportedError extends Error { + constructor() { + super('HLS is not supported') + } +} + +export class VideoNotFoundError extends Error { + constructor() { + super('Video not found') + } +} diff --git a/src/components/Post/Embed/VideoEmbed/VideoEmbedInner/VideoEmbedInnerWeb.tsx b/src/components/Post/Embed/VideoEmbed/VideoEmbedInner/VideoEmbedInnerWeb.tsx index b97317dfbf..72d9f3a8ba 100644 --- a/src/components/Post/Embed/VideoEmbed/VideoEmbedInner/VideoEmbedInnerWeb.tsx +++ b/src/components/Post/Embed/VideoEmbed/VideoEmbedInner/VideoEmbedInnerWeb.tsx @@ -1,6 +1,5 @@ import {useCallback, useEffect, useId, useRef, useState} from 'react' import {View} from 'react-native' -import {type AppBskyEmbedVideo} from '@atproto/api' import {msg} from '@lingui/core/macro' import {useLingui} from '@lingui/react' import type * as HlsTypes from 'hls.js' @@ -10,21 +9,25 @@ import {atoms as a} from '#/alf' import {AltBadgeWithDialog} from '#/components/AltBadgeWithDialog' import {useFullscreen} from '#/components/hooks/useFullscreen' import * as BandwidthEstimate from './bandwidth-estimate' +import { + HLSUnsupportedError, + type VideoEmbedInnerWebProps, + VideoNotFoundError, +} from './VideoEmbedInnerWeb.shared' import {Controls} from './web-controls/VideoControls' +export { + HLSUnsupportedError, + VideoNotFoundError, +} from './VideoEmbedInnerWeb.shared' + export function VideoEmbedInnerWeb({ embed, active, setActive, onScreen, lastKnownTime, -}: { - embed: AppBskyEmbedVideo.View - active: boolean - setActive: () => void - onScreen: boolean - lastKnownTime: React.RefObject -}) { +}: VideoEmbedInnerWebProps) { const containerRef = useRef(null) const videoRef = useRef(null) const [focused, setFocused] = useState(false) @@ -104,12 +107,6 @@ export function VideoEmbedInnerWeb({ ) } -export class HLSUnsupportedError extends Error { - constructor() { - super('HLS is not supported') - } -} - // Bluesky serves HLS as MPEG-TS with H.264 + AAC. `Hls.isSupported()` is loose // (true if MSE supports *any* of {H.264, AV1, VP9} OR *any* of {AAC, FLAC}), // so on Linux boxes missing H.264 (e.g. no ubuntu-restricted-extras, sandboxed @@ -138,12 +135,6 @@ function canPlayBskyVideoCodecs(): boolean { ) } -export class VideoNotFoundError extends Error { - constructor() { - super('Video not found') - } -} - type CachedPromise = Promise & {value: undefined | T} const promiseForHls = import( // @ts-ignore diff --git a/src/components/Post/Embed/VideoEmbed/VideoEmbedInner/web-controls/VideoControls.native.tsx b/src/components/Post/Embed/VideoEmbed/VideoEmbedInner/web-controls/VideoControls.native.tsx index 0088c186ab..9535d0fc1f 100644 --- a/src/components/Post/Embed/VideoEmbed/VideoEmbedInner/web-controls/VideoControls.native.tsx +++ b/src/components/Post/Embed/VideoEmbed/VideoEmbedInner/web-controls/VideoControls.native.tsx @@ -1,19 +1,5 @@ -import type Hls from 'hls.js' +import {type ControlsProps} from './VideoControls.shared' -export function Controls(_props: { - videoRef: React.RefObject - hlsRef: React.RefObject - active: boolean - setActive: () => void - focused: boolean - setFocused: (focused: boolean) => void - onScreen: boolean - fullscreenRef: React.RefObject - hlsLoading: boolean - hasSubtitleTrack: boolean - isGif: boolean - altText?: string - updateCuePositions: (controlsVisible?: boolean) => void -}): never { +export function Controls(_props: ControlsProps): never { throw new Error('VideoWebControls may not be used on native.') } diff --git a/src/components/Post/Embed/VideoEmbed/VideoEmbedInner/web-controls/VideoControls.shared.ts b/src/components/Post/Embed/VideoEmbed/VideoEmbedInner/web-controls/VideoControls.shared.ts new file mode 100644 index 0000000000..173aa9f1fb --- /dev/null +++ b/src/components/Post/Embed/VideoEmbed/VideoEmbedInner/web-controls/VideoControls.shared.ts @@ -0,0 +1,17 @@ +import type Hls from 'hls.js' + +export type ControlsProps = { + videoRef: React.RefObject + hlsRef: React.RefObject + active: boolean + setActive: () => void + focused: boolean + setFocused: (focused: boolean) => void + onScreen: boolean + fullscreenRef: React.RefObject + hlsLoading: boolean + hasSubtitleTrack: boolean + isGif: boolean + altText?: string + updateCuePositions: (controlsVisible?: boolean) => void +} diff --git a/src/components/Post/Embed/VideoEmbed/VideoEmbedInner/web-controls/VideoControls.tsx b/src/components/Post/Embed/VideoEmbed/VideoEmbedInner/web-controls/VideoControls.tsx index 2e5822589e..57f52e2f22 100644 --- a/src/components/Post/Embed/VideoEmbed/VideoEmbedInner/web-controls/VideoControls.tsx +++ b/src/components/Post/Embed/VideoEmbed/VideoEmbedInner/web-controls/VideoControls.tsx @@ -3,7 +3,6 @@ import {Pressable, View} from 'react-native' import {msg} from '@lingui/core/macro' import {useLingui} from '@lingui/react' import {Trans} from '@lingui/react/macro' -import type Hls from 'hls.js' import {clamp} from '#/lib/numbers' import { @@ -33,6 +32,7 @@ import {TimeIndicator} from '../TimeIndicator' import {ControlButton} from './ControlButton' import {Scrubber} from './Scrubber' import {formatTime, useVideoElement} from './utils' +import {type ControlsProps} from './VideoControls.shared' import {VolumeControl} from './VolumeControl' export function Controls({ @@ -49,21 +49,7 @@ export function Controls({ isGif, altText, updateCuePositions, -}: { - videoRef: React.RefObject - hlsRef: React.RefObject - active: boolean - setActive: () => void - focused: boolean - setFocused: (focused: boolean) => void - onScreen: boolean - fullscreenRef: React.RefObject - hlsLoading: boolean - hasSubtitleTrack: boolean - isGif: boolean - altText?: string - updateCuePositions: (controlsVisible?: boolean) => void -}) { +}: ControlsProps) { const { play, pause, diff --git a/src/components/WelcomeModal.tsx b/src/components/WelcomeModal.tsx index 354aa04906..d2671b1dbb 100644 --- a/src/components/WelcomeModal.tsx +++ b/src/components/WelcomeModal.tsx @@ -10,6 +10,7 @@ import {useLoggedOutViewControls} from '#/state/shell/logged-out' import {Logo} from '#/view/icons/Logo' import {atoms as a, flatten, useBreakpoints, web} from '#/alf' import {Button, ButtonText} from '#/components/Button' +import {type WelcomeModalControl} from '#/components/hooks/useWelcomeModal.shared' import {TimesLarge_Stroke2_Corner0_Rounded as XIcon} from '#/components/icons/Times' import {Text} from '#/components/Typography' import {useAnalytics} from '#/analytics' @@ -17,11 +18,7 @@ import {useAnalytics} from '#/analytics' const welcomeModalBg = require('../../assets/images/welcome-modal-bg.jpg') interface WelcomeModalProps { - control: { - isOpen: boolean - open: () => void - close: () => void - } + control: WelcomeModalControl } export function WelcomeModal({control}: WelcomeModalProps) { diff --git a/src/components/hooks/useWelcomeModal.native.ts b/src/components/hooks/useWelcomeModal.native.ts index ec581d5410..bdd0805d32 100644 --- a/src/components/hooks/useWelcomeModal.native.ts +++ b/src/components/hooks/useWelcomeModal.native.ts @@ -1,7 +1,5 @@ -export function useWelcomeModal(): { - isOpen: boolean - open: () => void - close: () => void -} { +import {type WelcomeModalControl} from './useWelcomeModal.shared' + +export function useWelcomeModal(): WelcomeModalControl { throw new Error('useWelcomeModal is web only') } diff --git a/src/components/hooks/useWelcomeModal.shared.ts b/src/components/hooks/useWelcomeModal.shared.ts new file mode 100644 index 0000000000..1151475e28 --- /dev/null +++ b/src/components/hooks/useWelcomeModal.shared.ts @@ -0,0 +1,5 @@ +export type WelcomeModalControl = { + isOpen: boolean + open: () => void + close: () => void +} diff --git a/src/components/hooks/useWelcomeModal.ts b/src/components/hooks/useWelcomeModal.ts index d0a55a0c18..3e33084b96 100644 --- a/src/components/hooks/useWelcomeModal.ts +++ b/src/components/hooks/useWelcomeModal.ts @@ -2,8 +2,9 @@ import {useEffect, useState} from 'react' import {useSession} from '#/state/session' import {IS_WEB} from '#/env' +import {type WelcomeModalControl} from './useWelcomeModal.shared' -export function useWelcomeModal() { +export function useWelcomeModal(): WelcomeModalControl { const {hasSession} = useSession() const [isOpen, setIsOpen] = useState(false) diff --git a/src/view/com/composer/videos/SubtitleFilePicker.native.tsx b/src/view/com/composer/videos/SubtitleFilePicker.native.tsx index a31e23c22a..b799d2dd84 100644 --- a/src/view/com/composer/videos/SubtitleFilePicker.native.tsx +++ b/src/view/com/composer/videos/SubtitleFilePicker.native.tsx @@ -1,6 +1,5 @@ -export function SubtitleFilePicker(_props: { - onSelectFile: (file: File) => void - disabled?: boolean -}): never { +import {type SubtitleFilePickerProps} from './SubtitleFilePicker.shared' + +export function SubtitleFilePicker(_props: SubtitleFilePickerProps): never { throw new Error('SubtitleFilePicker is a web-only component') } diff --git a/src/view/com/composer/videos/SubtitleFilePicker.shared.ts b/src/view/com/composer/videos/SubtitleFilePicker.shared.ts new file mode 100644 index 0000000000..b4f6f7591c --- /dev/null +++ b/src/view/com/composer/videos/SubtitleFilePicker.shared.ts @@ -0,0 +1,4 @@ +export type SubtitleFilePickerProps = { + onSelectFile: (file: File) => void + disabled?: boolean +} diff --git a/src/view/com/composer/videos/SubtitleFilePicker.tsx b/src/view/com/composer/videos/SubtitleFilePicker.tsx index 44fa582ddf..23277c8681 100644 --- a/src/view/com/composer/videos/SubtitleFilePicker.tsx +++ b/src/view/com/composer/videos/SubtitleFilePicker.tsx @@ -9,14 +9,12 @@ import {atoms as a} from '#/alf' import {Button, ButtonIcon, ButtonText} from '#/components/Button' import {CC_Stroke2_Corner0_Rounded as CCIcon} from '#/components/icons/CC' import * as Toast from '#/components/Toast' +import {type SubtitleFilePickerProps} from './SubtitleFilePicker.shared' export function SubtitleFilePicker({ onSelectFile, disabled, -}: { - onSelectFile: (file: File) => void - disabled?: boolean -}) { +}: SubtitleFilePickerProps) { const {_} = useLingui() const ref = useRef(null)