95 lines
2.6 KiB
TypeScript
95 lines
2.6 KiB
TypeScript
import * as Sentry from '@sentry/react-native'
|
|
import * as Updates from 'expo-updates'
|
|
import { useUpdates } from 'expo-updates'
|
|
import { useCallback, useEffect, useState } from 'react'
|
|
|
|
import { Block, Text } from '@/@share/components'
|
|
import { useUpdateChecker } from '@/hooks/use-update-checker'
|
|
|
|
import { ProgressLine } from './progress'
|
|
|
|
export const HotUpdate = () => {
|
|
const { hasUpdate = true } = useUpdateChecker()
|
|
const [showUpdate, setShowUpdate] = useState(hasUpdate)
|
|
const { isDownloading, isUpdatePending } = useUpdates()
|
|
const [downloadProgress, setDownloadProgress] = useState(0)
|
|
|
|
useEffect(() => {
|
|
setShowUpdate(hasUpdate)
|
|
}, [hasUpdate])
|
|
|
|
useEffect(() => {
|
|
Sentry.captureMessage('HotUpdate', {
|
|
tags: {
|
|
component: 'HotUpdate',
|
|
},
|
|
contexts: {
|
|
update: {
|
|
hasUpdate,
|
|
isDownloading,
|
|
isUpdatePending,
|
|
},
|
|
},
|
|
})
|
|
if (isDownloading) {
|
|
const interval = setInterval(() => {
|
|
setDownloadProgress((prev) => {
|
|
if (prev >= 95) return prev
|
|
const next = Number((prev + Math.random() * 10).toFixed(2))
|
|
return Math.min(next, 100)
|
|
})
|
|
}, 300)
|
|
return () => clearInterval(interval)
|
|
}
|
|
}, [isDownloading])
|
|
|
|
useEffect(() => {
|
|
if (isUpdatePending) {
|
|
setDownloadProgress(100)
|
|
setTimeout(() => {
|
|
Updates.reloadAsync()
|
|
}, 2000)
|
|
}
|
|
}, [isUpdatePending])
|
|
|
|
const downloadAndApplyUpdate = useCallback(async () => {
|
|
try {
|
|
setDownloadProgress(0)
|
|
await Updates.fetchUpdateAsync()
|
|
} catch (error) {
|
|
console.error('更新失败:', error)
|
|
setShowUpdate(false)
|
|
|
|
Sentry.captureMessage('HotUpdateError', {
|
|
tags: {
|
|
component: 'HotUpdate',
|
|
},
|
|
contexts: {
|
|
update: {
|
|
error: error instanceof Error ? error.message : '更新失败',
|
|
},
|
|
},
|
|
})
|
|
}
|
|
}, [])
|
|
|
|
useEffect(() => {
|
|
if (showUpdate) {
|
|
downloadAndApplyUpdate()
|
|
}
|
|
}, [showUpdate, downloadAndApplyUpdate])
|
|
|
|
if (!showUpdate) return null
|
|
return (
|
|
<Block className="bg-white p-[10px]">
|
|
<ProgressLine className="h-[5px] w-full" progress={downloadProgress} progressClassName="h-[5px]" />
|
|
<Block className="mt-1 flex-row items-center justify-between bg-white px-1">
|
|
<Text className="text-[12px] text-black">
|
|
{isDownloading ? '更新中' : downloadProgress >= 100 ? '更新成功' : '更新失败'}
|
|
</Text>
|
|
<Text className="text-[12px] text-black">{downloadProgress}%</Text>
|
|
</Block>
|
|
</Block>
|
|
)
|
|
}
|