Bluesky app fork with some witchin' additions 💫

Fix video thumbnails on native (#8774)

authored by samuel.fm and committed by

GitHub 7b5d11eb b3256826

+93 -99
+1 -1
package.json
··· 142 142 "expo-file-system": "~18.1.10", 143 143 "expo-font": "~13.3.1", 144 144 "expo-haptics": "~14.1.4", 145 - "expo-image": "~2.2.1", 145 + "expo-image": "^2.4.0", 146 146 "expo-image-crop-tool": "^0.1.8", 147 147 "expo-image-manipulator": "~13.1.7", 148 148 "expo-image-picker": "~16.1.4",
+79 -82
src/components/Post/Embed/VideoEmbed/VideoEmbedInner/VideoEmbedInnerNative.tsx
··· 1 - import React, {useRef} from 'react' 1 + import {useImperativeHandle, useRef, useState} from 'react' 2 2 import {Pressable, type StyleProp, View, type ViewStyle} from 'react-native' 3 3 import {type AppBskyEmbedVideo} from '@atproto/api' 4 4 import {BlueskyVideoView} from '@haileyok/bluesky-video' ··· 17 17 import {useVideoMuteState} from '#/components/Post/Embed/VideoEmbed/VideoVolumeContext' 18 18 import {TimeIndicator} from './TimeIndicator' 19 19 20 - export const VideoEmbedInnerNative = React.forwardRef( 21 - function VideoEmbedInnerNative( 22 - { 23 - embed, 24 - setStatus, 25 - setIsLoading, 26 - setIsActive, 27 - }: { 28 - embed: AppBskyEmbedVideo.View 29 - setStatus: (status: 'playing' | 'paused') => void 30 - setIsLoading: (isLoading: boolean) => void 31 - setIsActive: (isActive: boolean) => void 32 - }, 33 - ref: React.Ref<{togglePlayback: () => void}>, 34 - ) { 35 - const {_} = useLingui() 36 - const videoRef = useRef<BlueskyVideoView>(null) 37 - const autoplayDisabled = useAutoplayDisabled() 38 - const isWithinMessage = useIsWithinMessage() 39 - const [muted, setMuted] = useVideoMuteState() 20 + export function VideoEmbedInnerNative({ 21 + ref, 22 + embed, 23 + setStatus, 24 + setIsLoading, 25 + setIsActive, 26 + }: { 27 + ref: React.Ref<{togglePlayback: () => void}> 28 + embed: AppBskyEmbedVideo.View 29 + setStatus: (status: 'playing' | 'paused') => void 30 + setIsLoading: (isLoading: boolean) => void 31 + setIsActive: (isActive: boolean) => void 32 + }) { 33 + const {_} = useLingui() 34 + const videoRef = useRef<BlueskyVideoView>(null) 35 + const autoplayDisabled = useAutoplayDisabled() 36 + const isWithinMessage = useIsWithinMessage() 37 + const [muted, setMuted] = useVideoMuteState() 40 38 41 - const [isPlaying, setIsPlaying] = React.useState(false) 42 - const [timeRemaining, setTimeRemaining] = React.useState(0) 43 - const [error, setError] = React.useState<string>() 39 + const [isPlaying, setIsPlaying] = useState(false) 40 + const [timeRemaining, setTimeRemaining] = useState(0) 41 + const [error, setError] = useState<string>() 44 42 45 - React.useImperativeHandle(ref, () => ({ 46 - togglePlayback: () => { 47 - videoRef.current?.togglePlayback() 48 - }, 49 - })) 43 + useImperativeHandle(ref, () => ({ 44 + togglePlayback: () => { 45 + videoRef.current?.togglePlayback() 46 + }, 47 + })) 50 48 51 - if (error) { 52 - throw new Error(error) 53 - } 49 + if (error) { 50 + throw new Error(error) 51 + } 54 52 55 - return ( 56 - <View style={[a.flex_1, a.relative]}> 57 - <BlueskyVideoView 58 - url={embed.playlist} 59 - autoplay={!autoplayDisabled && !isWithinMessage} 60 - beginMuted={autoplayDisabled ? false : muted} 61 - style={[a.rounded_sm]} 62 - onActiveChange={e => { 63 - setIsActive(e.nativeEvent.isActive) 64 - }} 65 - onLoadingChange={e => { 66 - setIsLoading(e.nativeEvent.isLoading) 67 - }} 68 - onMutedChange={e => { 69 - setMuted(e.nativeEvent.isMuted) 70 - }} 71 - onStatusChange={e => { 72 - setStatus(e.nativeEvent.status) 73 - setIsPlaying(e.nativeEvent.status === 'playing') 74 - }} 75 - onTimeRemainingChange={e => { 76 - setTimeRemaining(e.nativeEvent.timeRemaining) 77 - }} 78 - onError={e => { 79 - setError(e.nativeEvent.error) 80 - }} 81 - ref={videoRef} 82 - accessibilityLabel={ 83 - embed.alt ? _(msg`Video: ${embed.alt}`) : _(msg`Video`) 84 - } 85 - accessibilityHint="" 86 - /> 87 - <VideoControls 88 - enterFullscreen={() => { 89 - videoRef.current?.enterFullscreen(true) 90 - }} 91 - toggleMuted={() => { 92 - videoRef.current?.toggleMuted() 93 - }} 94 - togglePlayback={() => { 95 - videoRef.current?.togglePlayback() 96 - }} 97 - isPlaying={isPlaying} 98 - timeRemaining={timeRemaining} 99 - /> 100 - <MediaInsetBorder /> 101 - </View> 102 - ) 103 - }, 104 - ) 53 + return ( 54 + <View style={[a.flex_1, a.relative]}> 55 + <BlueskyVideoView 56 + url={embed.playlist} 57 + autoplay={!autoplayDisabled && !isWithinMessage} 58 + beginMuted={autoplayDisabled ? false : muted} 59 + style={[a.rounded_sm]} 60 + onActiveChange={e => { 61 + setIsActive(e.nativeEvent.isActive) 62 + }} 63 + onLoadingChange={e => { 64 + setIsLoading(e.nativeEvent.isLoading) 65 + }} 66 + onMutedChange={e => { 67 + setMuted(e.nativeEvent.isMuted) 68 + }} 69 + onStatusChange={e => { 70 + setStatus(e.nativeEvent.status) 71 + setIsPlaying(e.nativeEvent.status === 'playing') 72 + }} 73 + onTimeRemainingChange={e => { 74 + setTimeRemaining(e.nativeEvent.timeRemaining) 75 + }} 76 + onError={e => { 77 + setError(e.nativeEvent.error) 78 + }} 79 + ref={videoRef} 80 + accessibilityLabel={ 81 + embed.alt ? _(msg`Video: ${embed.alt}`) : _(msg`Video`) 82 + } 83 + accessibilityHint="" 84 + /> 85 + <VideoControls 86 + enterFullscreen={() => { 87 + videoRef.current?.enterFullscreen(true) 88 + }} 89 + toggleMuted={() => { 90 + videoRef.current?.toggleMuted() 91 + }} 92 + togglePlayback={() => { 93 + videoRef.current?.togglePlayback() 94 + }} 95 + isPlaying={isPlaying} 96 + timeRemaining={timeRemaining} 97 + /> 98 + <MediaInsetBorder /> 99 + </View> 100 + ) 101 + } 105 102 106 103 function VideoControls({ 107 104 enterFullscreen,
+9 -12
src/components/Post/Embed/VideoEmbed/index.tsx
··· 1 - import React, {useCallback, useState} from 'react' 1 + import {useCallback, useRef, useState} from 'react' 2 2 import {ActivityIndicator, View} from 'react-native' 3 3 import {ImageBackground} from 'expo-image' 4 4 import {type AppBskyEmbedVideo} from '@atproto/api' ··· 81 81 82 82 function InnerWrapper({embed}: Props) { 83 83 const {_} = useLingui() 84 - const ref = React.useRef<{togglePlayback: () => void}>(null) 84 + const ref = useRef<{togglePlayback: () => void}>(null) 85 85 86 - const [status, setStatus] = React.useState<'playing' | 'paused' | 'pending'>( 86 + const [status, setStatus] = useState<'playing' | 'paused' | 'pending'>( 87 87 'pending', 88 88 ) 89 - const [isLoading, setIsLoading] = React.useState(false) 90 - const [isActive, setIsActive] = React.useState(false) 89 + const [isLoading, setIsLoading] = useState(false) 90 + const [isActive, setIsActive] = useState(false) 91 91 const showSpinner = useThrottledValue(isActive && isLoading, 100) 92 92 93 93 const showOverlay = ··· 96 96 (status === 'paused' && !isActive) || 97 97 status === 'pending' 98 98 99 - React.useEffect(() => { 100 - if (!isActive && status !== 'pending') { 101 - setStatus('pending') 102 - } 103 - }, [isActive, status]) 99 + if (!isActive && status !== 'pending') { 100 + setStatus('pending') 101 + } 104 102 105 103 return ( 106 104 <> ··· 131 129 onPress={() => { 132 130 ref.current?.togglePlayback() 133 131 }} 134 - label={_(msg`Play video`)} 135 - color="secondary"> 132 + label={_(msg`Play video`)}> 136 133 {showSpinner ? ( 137 134 <View 138 135 style={[
+4 -4
yarn.lock
··· 11301 11301 dependencies: 11302 11302 expo-image-loader "~5.1.0" 11303 11303 11304 - expo-image@~2.2.1: 11305 - version "2.2.1" 11306 - resolved "https://registry.yarnpkg.com/expo-image/-/expo-image-2.2.1.tgz#b4aa706a25f7e8902ac854a8da249caf4a90cd67" 11307 - integrity sha512-5ZSggMi0X2G9AN0aM+sdkCyyZ6YcWvGs9KYLYrRBVUN3ph6RBiu6mKGpaNN1TAscySRnH1eHbUE1H+Qeq7qm1g== 11304 + expo-image@^2.4.0: 11305 + version "2.4.0" 11306 + resolved "https://registry.yarnpkg.com/expo-image/-/expo-image-2.4.0.tgz#02f7fd743387206914cd431a6367f5be53509e3e" 11307 + integrity sha512-TQ/LvrtJ9JBr+Tf198CAqflxcvdhuj7P24n0LQ1jHaWIVA7Z+zYKbYHnSMPSDMul/y0U46Z5bFLbiZiSidgcNw== 11308 11308 11309 11309 expo-json-utils@~0.15.0: 11310 11310 version "0.15.0"