add nicer loading screen while OTA is loading

This commit is contained in:
Samuel Newman
2025-12-06 22:20:04 +02:00
parent 03f8020ee2
commit ad76954522
2 changed files with 43 additions and 8 deletions
+37 -7
View File
@@ -7,6 +7,7 @@ import {
fetchUpdateAsync,
isEnabled,
reloadAsync,
type ReloadScreenOptions,
setExtraParamAsync,
UpdateCheckResultNotAvailableReason,
useUpdates,
@@ -16,6 +17,7 @@ import {isNetworkError} from '#/lib/strings/errors'
import {logger} from '#/logger'
import {APP_VERSION, IS_IOS, IS_TESTFLIGHT} from '#/env'
import {device} from '#/storage'
import {useTheme} from '#/alf'
const MINIMUM_MINIMIZE_TIME = 15 * 60e3
const OTA_RECOVERY_WINDOW = 5 * 60e3
@@ -83,7 +85,7 @@ async function setExtraParamsPullRequest(channel: string) {
await setExtraParamAsync('channel', channel)
}
async function updateTestflight() {
async function updateTestflight(t: 'light' | 'dark') {
await setExtraParams()
const res = await checkForUpdateAsync()
@@ -101,7 +103,9 @@ async function updateTestflight() {
text: 'Relaunch',
style: 'default',
onPress: async () => {
await reloadAsync()
await reloadAsync({
reloadScreenOptions: splash(t),
})
},
},
],
@@ -110,6 +114,7 @@ async function updateTestflight() {
}
export function useApplyPullRequestOTAUpdate() {
const t = useTheme()
const {currentlyRunning} = useUpdates()
const [pending, setPending] = useState(false)
const currentChannel = getRunningChannel(currentlyRunning)
@@ -174,7 +179,9 @@ export function useApplyPullRequestOTAUpdate() {
* after the reload.
*/
// Linking.clearInitialURL()
await reloadAsync()
await reloadAsync({
reloadScreenOptions: splash(t.scheme),
})
} catch (e) {
device.remove(['pendingOTAUpdate'])
throw e
@@ -335,6 +342,7 @@ export function useOTAUpdateRecovery() {
export function useOTAUpdates() {
const shouldReceiveUpdates = isEnabled && !__DEV__
const t = useTheme()
const appState = useRef<AppStateStatus>('active')
const lastMinimize = useRef(0)
const ranInitialCheck = useRef(false)
@@ -366,13 +374,13 @@ export function useOTAUpdates() {
const onIsTestFlight = useCallback(async () => {
try {
await updateTestflight()
await updateTestflight(t.scheme)
} catch (err: any) {
if (!isNetworkError(err)) {
logger.error('Internal OTA Update Error', {safeMessage: err})
}
}
}, [])
}, [t.scheme])
useEffect(() => {
// We don't need to check anything if the current update is a PR update
@@ -414,7 +422,9 @@ export function useOTAUpdates() {
// chances are that there isn't anything important going on in the current session.
if (lastMinimize.current <= Date.now() - MINIMUM_MINIMIZE_TIME) {
if (isUpdatePending) {
await reloadAsync()
await reloadAsync({
reloadScreenOptions: splash(t.scheme),
})
} else {
setCheckTimeout()
}
@@ -431,5 +441,25 @@ export function useOTAUpdates() {
clearTimeout(timeout.current)
subscription.remove()
}
}, [isUpdatePending, currentChannel, setCheckTimeout])
}, [isUpdatePending, currentChannel, setCheckTimeout, t.scheme])
}
/**
* Splash screen for while the app is updating
*/
export const splash = (scheme: 'light' | 'dark') => {
return {
image:
scheme === 'light'
? require('../../../assets/splash/splash.png')
: require('../../../assets/splash/splash-dark.png'),
imageFullScreen: true,
imageResizeMode: 'cover',
backgroundColor: scheme === 'light' ? '#0c7cff' : '#0c2a49',
spinner: {
enabled: true,
color: '#ffffff',
size: 'large',
},
} satisfies ReloadScreenOptions
}
+6 -1
View File
@@ -4,6 +4,8 @@ import {useLingui} from '@lingui/react'
import {Trans} from '@lingui/react/macro'
import {useMutation, useQuery} from '@tanstack/react-query'
import {splash} from '#/lib/hooks/useOTAUpdates'
import {useTheme} from '#/alf'
import {Button, ButtonIcon, ButtonText} from '#/components/Button'
import {ArrowRotateCounterClockwise_Stroke2_Corner0_Rounded as RetryIcon} from '#/components/icons/ArrowRotate'
import {Shapes_Stroke2_Corner0_Rounded as ShapesIcon} from '#/components/icons/Shapes'
@@ -13,6 +15,7 @@ import * as SettingsList from '../components/SettingsList'
export function OTAInfo() {
const {_} = useLingui()
const t = useTheme()
const {
data: isAvailable,
isPending: isPendingInfo,
@@ -31,7 +34,9 @@ export function OTAInfo() {
useMutation({
mutationFn: async () => {
await Updates.fetchUpdateAsync()
await Updates.reloadAsync()
await Updates.reloadAsync({
reloadScreenOptions: splash(t.scheme),
})
},
onError: error =>
Toast.show(`Failed to update: ${error.message}`, {