expo-duooomi-app/@share/components/Video.tsx

90 lines
2.4 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import { Image } from 'expo-image'
import { memo, useEffect, useState } from 'react'
import { type ViewStyle } from 'react-native'
import type Video from 'react-native-video'
type Props = {
url?: string
poster?: string
style?: ViewStyle
width?: number
} & React.ComponentProps<typeof Video>
const VideoBox = ({ url, poster, width = 120, style, ...videoProps }: Props) => {
const [urlFinal, setUrlFinal] = useState('')
const createUrl = (url: string) => {
return `https://modal-dev.bowong.cc/api/custom/video/converter/${encodeURI(url)}?options=compression_level=3,quality=70,loop=true,resolution=${width}x${width},fps=24`
}
const isImg = (url: any) => {
if (!url) return false
const lowerUrl = url.toLowerCase()
return lowerUrl?.match(/\.(jpg|jpeg|png|gif|webp|bmp|tiff|svg)(\?.*)?$/i)
}
async function resolveRedirect(url: string) {
const res = await fetch(url, {
method: 'GET',
headers: {
Range: 'bytes=0-0',
},
})
return res.url
}
// 自动从 URL 提取稳定的缓存键
const extractCacheKey = (url: string): string => {
try {
const urlObj = new URL(url)
// 使用路径部分作为缓存键忽略查询参数token、签名等
return urlObj.pathname
} catch {
// URL 解析失败时使用原始 URL
return url
}
}
const setRedirectUrl = async (url?: string) => {
const isImg2 = isImg(url)
if (isImg2) {
setUrlFinal(url!)
return
}
const webpUrl = createUrl(url!)
const finalUrl = await resolveRedirect(webpUrl)
// console.log('finalUrl-----------', finalUrl)
setUrlFinal(finalUrl!)
}
useEffect(() => {
if (!url) return
setRedirectUrl(url!)
// const finalUrl = createUrl(url)
// console.log('finalUrl-----------', finalUrl)
// setUrlFinal(finalUrl)
return
}, [url])
// console.log('urlFinal--------- ', urlFinal, url)
if (!url) return null
return (
// 移除 key 避免组件重建导致闪烁,使用 transition 实现平滑切换
<Image
cachePolicy="memory-disk"
source={{ uri: urlFinal, cacheKey: extractCacheKey(urlFinal) }}
style={style as any}
transition={{ duration: 200, effect: 'cross-dissolve' }}
onLoad={(event) => {
const { cacheType } = event
console.log('缓存类型:', cacheType)
}}
/>
)
}
export default memo(VideoBox)