[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>
This commit is contained in:
@@ -1,88 +0,0 @@
|
||||
import {useCallback} from 'react'
|
||||
import {type ImagePickerAsset} from 'expo-image-picker'
|
||||
import {msg} from '@lingui/macro'
|
||||
import {useLingui} from '@lingui/react'
|
||||
|
||||
import {
|
||||
SUPPORTED_MIME_TYPES,
|
||||
type SupportedMimeTypes,
|
||||
VIDEO_MAX_DURATION_MS,
|
||||
} from '#/lib/constants'
|
||||
import {useVideoLibraryPermission} from '#/lib/hooks/usePermissions'
|
||||
import {isWeb} from '#/platform/detection'
|
||||
import {isNative} from '#/platform/detection'
|
||||
import {atoms as a, useTheme} from '#/alf'
|
||||
import {Button} from '#/components/Button'
|
||||
import {VideoClip_Stroke2_Corner0_Rounded as VideoClipIcon} from '#/components/icons/VideoClip'
|
||||
import {pickVideo} from './pickVideo'
|
||||
|
||||
type Props = {
|
||||
onSelectVideo: (video: ImagePickerAsset) => void
|
||||
disabled?: boolean
|
||||
setError: (error: string) => void
|
||||
}
|
||||
|
||||
export function SelectVideoBtn({onSelectVideo, disabled, setError}: Props) {
|
||||
const {_} = useLingui()
|
||||
const t = useTheme()
|
||||
const {requestVideoAccessIfNeeded} = useVideoLibraryPermission()
|
||||
|
||||
const onPressSelectVideo = useCallback(async () => {
|
||||
if (isNative && !(await requestVideoAccessIfNeeded())) {
|
||||
return
|
||||
}
|
||||
|
||||
const response = await pickVideo()
|
||||
if (response.assets && response.assets.length > 0) {
|
||||
const asset = response.assets[0]
|
||||
try {
|
||||
if (isWeb) {
|
||||
// asset.duration is null for gifs (see the TODO in pickVideo.web.ts)
|
||||
if (asset.duration && asset.duration > VIDEO_MAX_DURATION_MS) {
|
||||
throw Error(_(msg`Videos must be less than 3 minutes long`))
|
||||
}
|
||||
// compression step on native converts to mp4, so no need to check there
|
||||
if (
|
||||
!SUPPORTED_MIME_TYPES.includes(asset.mimeType as SupportedMimeTypes)
|
||||
) {
|
||||
throw Error(_(msg`Unsupported video type: ${asset.mimeType}`))
|
||||
}
|
||||
} else {
|
||||
if (typeof asset.duration !== 'number') {
|
||||
throw Error('Asset is not a video')
|
||||
}
|
||||
if (asset.duration > VIDEO_MAX_DURATION_MS) {
|
||||
throw Error(_(msg`Videos must be less than 3 minutes long`))
|
||||
}
|
||||
}
|
||||
onSelectVideo(asset)
|
||||
} catch (err) {
|
||||
if (err instanceof Error) {
|
||||
setError(err.message)
|
||||
} else {
|
||||
setError(_(msg`An error occurred while selecting the video`))
|
||||
}
|
||||
}
|
||||
}
|
||||
}, [requestVideoAccessIfNeeded, setError, _, onSelectVideo])
|
||||
|
||||
return (
|
||||
<>
|
||||
<Button
|
||||
testID="openGifBtn"
|
||||
onPress={onPressSelectVideo}
|
||||
label={_(msg`Select video`)}
|
||||
accessibilityHint={_(msg`Opens video picker`)}
|
||||
style={a.p_sm}
|
||||
variant="ghost"
|
||||
shape="round"
|
||||
color="primary"
|
||||
disabled={disabled}>
|
||||
<VideoClipIcon
|
||||
size="lg"
|
||||
style={disabled && t.atoms.text_contrast_low}
|
||||
/>
|
||||
</Button>
|
||||
</>
|
||||
)
|
||||
}
|
||||
@@ -1,9 +1,10 @@
|
||||
import React from 'react'
|
||||
import {View} from 'react-native'
|
||||
import {ImagePickerAsset} from 'expo-image-picker'
|
||||
import {Image} from 'expo-image'
|
||||
import {type ImagePickerAsset} from 'expo-image-picker'
|
||||
import {BlueskyVideoView} from '@haileyok/bluesky-video'
|
||||
|
||||
import {CompressedVideo} from '#/lib/media/video/types'
|
||||
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'
|
||||
@@ -48,13 +49,25 @@ export function VideoPreview({
|
||||
<VideoTranscodeBackdrop uri={asset.uri} />
|
||||
</View>
|
||||
{isActivePost && (
|
||||
<BlueskyVideoView
|
||||
url={video.uri}
|
||||
autoplay={!autoplayDisabled}
|
||||
beginMuted={true}
|
||||
forceTakeover={true}
|
||||
ref={playerRef}
|
||||
/>
|
||||
<>
|
||||
{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 && (
|
||||
|
||||
Reference in New Issue
Block a user