Files
bsky-social-app/src/view/com/composer/videos/VideoPreview.tsx
T
Eric Bailey 122a46891a [APP-1318] SelectMediaButton (#8828)
* Integrate Sonner for toasts

* Fix animation on iOS

* Refactor API

* Update e2e file

* [APP-1318] Post composer: combine image & video buttons  (#8710)

* add: select media btn

* udpate: compose post with combined image and video support

* add: video combine button with edge cases

* add select media btn

* test: select media btn

* add: media button update

* remove unused files and update toast on android

* update: make strings shorter

* add: ValidatedVideoAsset type

* update link comments and add toast support for native and web

* rebase latest toast and update toast structure

* remove unused prop

* fix types

* undo changes to yarn.lock

* remove: support for mkv files

* update: eslint and prettier

(cherry picked from commit f69779ee130f07e1c49219b53117e3bdd1a9f81b)

* Add missing props to launchImageLibraryAsync

(cherry picked from commit 2e80ae561fd66850f787cac0aae0fa5a6980f8f5)

* Rough out new approach

(cherry picked from commit 9add225160e7e407befc73e9cdd9743a30cdf1cd)

* Comments and cleanup

(cherry picked from commit e69bd186e7335372f440c446ae6643ed0fb15db9)

* Handle native case

(cherry picked from commit 74e38acdfd9181d0557426691fcbcbf0800481ca)

* Refactor

(cherry picked from commit 68aea496db8df54dba5f58da267ad962c28ef995)

* Rename

(cherry picked from commit 8609e59ad14219e7378ee6cb9514d633ce7efc27)

* Cleanup, comments

(cherry picked from commit 6c9c98648e37257285a9c8caeb1eadcc56c81402)

* Rename

(cherry picked from commit 66e3db539d5baa41436c9e49af06e87a78e9e7e1)

* Handle selectionLimit on Android

(cherry picked from commit 251f06dd5e65a7083b810bad3d81114b2fe9ab39)

* create composer images in parallel

(cherry picked from commit 70ea79d9d76d99e9c99a7d2296caed84c718650e)

* Update toast API usage

(cherry picked from commit e370018b8ed8cdfd7675c9634058c72cb59d39de)

* Ensure once one type of media is selected, you can only select more of that type

(cherry picked from commit 1a9e6e0cdb5234667f08e3dd9107ae598941fc23)

* Remove TODO and debug code

* Add more descriptive a11y label to button

Co-authored-by: surfdude29 <149612116+surfdude29@users.noreply.github.com>

* Add back post success toast

* Include mimeType in toast error

* Remove unneeded toast

* Clarify hint

* Typo

Co-authored-by: surfdude29 <149612116+surfdude29@users.noreply.github.com>

* allow gifs on native, just treat as images

* disable haptic toast

* allow gifs on native, treat as videos

* only do keyboard dismiss on native

* tweak pasting logic

* hide web scrubber in certain situations

* Update MaxImages translation

Co-authored-by: surfdude29 <149612116+surfdude29@users.noreply.github.com>

* Add plural formatting to a11y hint translation

Co-authored-by: surfdude29 <149612116+surfdude29@users.noreply.github.com>

* fix suggestion

* Protect against no valid assets selected

* Handle conversion of too-big assets on web

* Reorder

* Bump expo-image-picker to include bug/perf improvements

See https://github.com/expo/expo/blob/main/packages/expo-image-picker/CHANGELOG.md#1700--2025-08-13

* Handle edge case validations

* Ok actually bump expo-image-picker

* Comment

* HEIC support Android

* Fix handling for new picker version, improve size validation

* Remove getVideoMetadata handling, no longer needed

* Handle web video duration

* Update src/view/com/composer/SelectMediaButton.tsx

Co-authored-by: surfdude29 <149612116+surfdude29@users.noreply.github.com>

---------

Co-authored-by: Anastasiya Uraleva <anastasiyauraleva@gmail.com>
Co-authored-by: surfdude29 <149612116+surfdude29@users.noreply.github.com>
Co-authored-by: Samuel Newman <mozzius@protonmail.com>
2025-08-18 18:28:01 -05:00

81 lines
2.2 KiB
TypeScript

import React from 'react'
import {View} from 'react-native'
import {Image} from 'expo-image'
import {type ImagePickerAsset} from 'expo-image-picker'
import {BlueskyVideoView} from '@haileyok/bluesky-video'
import {type CompressedVideo} from '#/lib/media/video/types'
import {clamp} from '#/lib/numbers'
import {useAutoplayDisabled} from '#/state/preferences'
import {ExternalEmbedRemoveBtn} from '#/view/com/composer/ExternalEmbedRemoveBtn'
import {atoms as a, useTheme} from '#/alf'
import {PlayButtonIcon} from '#/components/video/PlayButtonIcon'
import {VideoTranscodeBackdrop} from './VideoTranscodeBackdrop'
export function VideoPreview({
asset,
video,
clear,
isActivePost,
}: {
asset: ImagePickerAsset
video: CompressedVideo
isActivePost: boolean
clear: () => void
}) {
const t = useTheme()
const playerRef = React.useRef<BlueskyVideoView>(null)
const autoplayDisabled = useAutoplayDisabled()
let aspectRatio = asset.width / asset.height
if (isNaN(aspectRatio)) {
aspectRatio = 16 / 9
}
aspectRatio = clamp(aspectRatio, 1 / 1, 3 / 1)
return (
<View
style={[
a.w_full,
a.rounded_sm,
{aspectRatio},
a.overflow_hidden,
a.border,
t.atoms.border_contrast_low,
{backgroundColor: 'black'},
]}>
<View style={[a.absolute, a.inset_0]}>
<VideoTranscodeBackdrop uri={asset.uri} />
</View>
{isActivePost && (
<>
{video.mimeType === 'image/gif' ? (
<Image
style={[a.flex_1]}
autoplay={!autoplayDisabled}
source={{uri: video.uri}}
accessibilityIgnoresInvertColors
cachePolicy="none"
/>
) : (
<BlueskyVideoView
url={video.uri}
autoplay={!autoplayDisabled}
beginMuted={true}
forceTakeover={true}
ref={playerRef}
/>
)}
</>
)}
<ExternalEmbedRemoveBtn onRemove={clear} />
{autoplayDisabled && (
<View style={[a.absolute, a.inset_0, a.justify_center, a.align_center]}>
<PlayButtonIcon />
</View>
)}
</View>
)
}