refactor(mobile): replace react-native-video with expo-video, hide control in list, close #3417

This commit is contained in:
Stephen Zhou 2025-04-23 13:21:48 +08:00
parent eb3cb7db28
commit 1f5dd2a165
No known key found for this signature in database
5 changed files with 43 additions and 72 deletions

View File

@ -158,7 +158,6 @@ export default ({ config }: ConfigContext): ExpoConfig => ({
photosPermission: "Allow $(PRODUCT_NAME) to access your photos.",
},
],
"react-native-video",
[
"expo-notifications",
{

View File

@ -118,7 +118,6 @@
"react-native-svg": "15.11.2",
"react-native-track-player": "4.1.1",
"react-native-uikit-colors": "0.5.1",
"react-native-video": "6.13.0",
"react-native-volume-manager": "2.0.8",
"react-native-web": "0.20.0",
"react-native-webview": "13.13.5",

View File

@ -7,7 +7,6 @@ import Animated, {
useSharedValue,
withSpring,
} from "react-native-reanimated"
import Video from "react-native-video"
import { Galeria } from "@/src/components/ui/image/galeria"
import type { MediaModel } from "@/src/database/schemas/types"
@ -15,6 +14,7 @@ import { EntryGridFooter } from "@/src/modules/entry-content/EntryGridFooter"
import { Image } from "../image/Image"
import { ImageContextMenu } from "../image/ImageContextMenu"
import { VideoPlayer } from "../video/VideoPlayer"
export const MediaCarousel = ({
entryId,
@ -36,8 +36,6 @@ export const MediaCarousel = ({
// const activeIndex = useSharedValue(0)
const [activeIndex, setActiveIndex] = useState(0)
const [isVideoInFullscreen, setIsVideoInFullscreen] = useState(false)
return (
<View
onLayout={(e) => {
@ -45,7 +43,17 @@ export const MediaCarousel = ({
}}
>
<View className="relative overflow-hidden rounded-md">
<Galeria urls={useMemo(() => media.map((m) => m.url), [media])}>
<Galeria
urls={useMemo(
() =>
media
.map((m) =>
m.type === "video" ? m.preview_image_url : m.type === "photo" ? m.url : undefined,
)
.filter(Boolean) as string[],
[media],
)}
>
<ScrollView
onScroll={(e) => {
setActiveIndex(Math.round(e.nativeEvent.contentOffset.x / containerWidth))
@ -61,6 +69,25 @@ export const MediaCarousel = ({
style={{ height: containerHeight }}
>
{media.map((m, index) => {
const imageUrl = m.type === "video" ? m.preview_image_url : m.url
if (!imageUrl) {
return null
}
const ImageItem = (
<Galeria.Image onPreview={onPreview} index={index}>
<Image
proxy={{
height: 400,
}}
source={{ uri: imageUrl }}
blurhash={m.blurhash}
className="w-full"
aspectRatio={aspectRatio}
placeholderContentFit="cover"
/>
</Galeria.Image>
)
if (m.type === "photo") {
return (
<View
@ -68,42 +95,19 @@ export const MediaCarousel = ({
className="relative"
style={{ width: containerWidth, height: containerHeight }}
>
<ImageContextMenu entryId={entryId} imageUrl={m.url} view={view}>
<Galeria.Image onPreview={onPreview} index={index}>
<Image
proxy={{
height: 400,
}}
source={{ uri: m.url }}
blurhash={m.blurhash}
className="w-full"
aspectRatio={aspectRatio}
placeholderContentFit="cover"
/>
</Galeria.Image>
<ImageContextMenu entryId={entryId} imageUrl={imageUrl} view={view}>
{ImageItem}
</ImageContextMenu>
</View>
)
} else if (m.type === "video") {
return (
<ImageContextMenu
key={index}
entryId={entryId}
imageUrl={m.preview_image_url}
view={view}
>
<Video
source={{ uri: m.url }}
style={{ width: containerWidth, height: containerHeight }}
muted={!isVideoInFullscreen}
repeat
poster={{
source: { uri: m.preview_image_url },
resizeMode: "cover",
}}
controls
onFullscreenPlayerWillPresent={() => setIsVideoInFullscreen(true)}
onFullscreenPlayerWillDismiss={() => setIsVideoInFullscreen(false)}
<ImageContextMenu key={index} entryId={entryId} imageUrl={imageUrl} view={view}>
<VideoPlayer
source={m.url}
height={containerHeight}
width={containerWidth}
placeholder={ImageItem}
/>
</ImageContextMenu>
)

View File

@ -35,7 +35,8 @@ export function VideoPlayer({
<VideoView
ref={viewViewRef}
style={{
width: "100%",
width: width ?? "100%",
height,
aspectRatio: width && height ? width / height : 1,
}}
contentFit={isFullScreen ? "contain" : "cover"}

View File

@ -1066,9 +1066,6 @@ importers:
react-native-uikit-colors:
specifier: 0.5.1
version: 0.5.1(27f1c20b5429d566f2f56a15bc4a2371)
react-native-video:
specifier: 6.13.0
version: 6.13.0(react-native@0.77.2(@babel/core@7.26.10)(@babel/preset-env@7.26.9(@babel/core@7.26.10))(@types/react@18.3.12)(bufferutil@4.0.9)(react@18.3.1))(react@18.3.1)
react-native-volume-manager:
specifier: 2.0.8
version: 2.0.8(react-native@0.77.2(@babel/core@7.26.10)(@babel/preset-env@7.26.9(@babel/core@7.26.10))(@types/react@18.3.12)(bufferutil@4.0.9)(react@18.3.1))(react@18.3.1)
@ -12891,12 +12888,6 @@ packages:
react-native: '>=0.76.0'
tailwindcss: '>=3.0.0'
react-native-video@6.13.0:
resolution: {integrity: sha512-eY6jgLcmYKAAlAZhsZbp8wfCVrGu7jmUYTTspn8udN8j4jqr4Fq90ROOM/QegGkwNs4waclL0IkzGuq61kT4DQ==}
peerDependencies:
react: 18.3.1
react-native: '*'
react-native-volume-manager@2.0.8:
resolution: {integrity: sha512-aZM47/mYkdQ4CbXpKYO6Ajiczv7fxbQXZ9c0H8gRuQUaS3OCz/MZABer6o9aDWq0KMNsQ7q7GVFLRPnSSeeMmw==}
peerDependencies:
@ -20174,7 +20165,7 @@ snapshots:
debug: 2.6.9
invariant: 2.2.4
metro: 0.81.4(bufferutil@4.0.9)
metro-config: 0.81.4(bufferutil@4.0.9)
metro-config: 0.81.4(bufferutil@4.0.9)(utf-8-validate@6.0.5)
metro-core: 0.81.4
readline: 1.3.0
semver: 7.7.1
@ -27389,21 +27380,6 @@ snapshots:
flow-enums-runtime: 0.0.6
metro-core: 0.81.4
metro-config@0.81.4(bufferutil@4.0.9):
dependencies:
connect: 3.7.0
cosmiconfig: 5.2.1
flow-enums-runtime: 0.0.6
jest-validate: 29.7.0
metro: 0.81.4(bufferutil@4.0.9)
metro-cache: 0.81.4
metro-core: 0.81.4
metro-runtime: 0.81.4
transitivePeerDependencies:
- bufferutil
- supports-color
- utf-8-validate
metro-config@0.81.4(bufferutil@4.0.9)(utf-8-validate@6.0.5):
dependencies:
connect: 3.7.0
@ -27418,7 +27394,6 @@ snapshots:
- bufferutil
- supports-color
- utf-8-validate
optional: true
metro-core@0.81.4:
dependencies:
@ -27530,7 +27505,6 @@ snapshots:
- bufferutil
- supports-color
- utf-8-validate
optional: true
metro@0.81.4(bufferutil@4.0.9):
dependencies:
@ -27558,7 +27532,7 @@ snapshots:
metro-babel-transformer: 0.81.4
metro-cache: 0.81.4
metro-cache-key: 0.81.4
metro-config: 0.81.4(bufferutil@4.0.9)
metro-config: 0.81.4(bufferutil@4.0.9)(utf-8-validate@6.0.5)
metro-core: 0.81.4
metro-file-map: 0.81.4
metro-resolver: 0.81.4
@ -27625,7 +27599,6 @@ snapshots:
- bufferutil
- supports-color
- utf-8-validate
optional: true
micromark-core-commonmark@2.0.3:
dependencies:
@ -29368,11 +29341,6 @@ snapshots:
tailwindcss: 3.4.17(ts-node@10.9.2(@types/node@22.14.1)(typescript@5.8.3))
tailwindcss-uikit-colors: 0.5.1
react-native-video@6.13.0(react-native@0.77.2(@babel/core@7.26.10)(@babel/preset-env@7.26.9(@babel/core@7.26.10))(@types/react@18.3.12)(bufferutil@4.0.9)(react@18.3.1))(react@18.3.1):
dependencies:
react: 18.3.1
react-native: 0.77.2(@babel/core@7.26.10)(@babel/preset-env@7.26.9(@babel/core@7.26.10))(@types/react@18.3.12)(bufferutil@4.0.9)(react@18.3.1)
react-native-volume-manager@2.0.8(react-native@0.77.2(@babel/core@7.26.10)(@babel/preset-env@7.26.9(@babel/core@7.26.10))(@types/react@18.3.12)(bufferutil@4.0.9)(react@18.3.1))(react@18.3.1):
dependencies:
react: 18.3.1