* Add modal state provider, replace usage except methods * Replace easy spots * Fix sticky spots * Replace final usages * Memorize context objects * Add more warnings
78 lines
2.6 KiB
TypeScript
78 lines
2.6 KiB
TypeScript
import * as Updates from 'expo-updates'
|
|
import {useCallback, useEffect} from 'react'
|
|
import {AppState} from 'react-native'
|
|
import {logger} from '#/logger'
|
|
import {useModalControls} from '#/state/modals'
|
|
|
|
export function useOTAUpdate() {
|
|
const {openModal} = useModalControls()
|
|
|
|
// HELPER FUNCTIONS
|
|
const showUpdatePopup = useCallback(() => {
|
|
openModal({
|
|
name: 'confirm',
|
|
title: 'Update Available',
|
|
message:
|
|
'A new version of the app is available. Please update to continue using the app.',
|
|
onPressConfirm: async () => {
|
|
Updates.reloadAsync().catch(err => {
|
|
throw err
|
|
})
|
|
},
|
|
})
|
|
}, [openModal])
|
|
const checkForUpdate = useCallback(async () => {
|
|
logger.debug('useOTAUpdate: Checking for update...')
|
|
try {
|
|
// Check if new OTA update is available
|
|
const update = await Updates.checkForUpdateAsync()
|
|
// If updates aren't available stop the function execution
|
|
if (!update.isAvailable) {
|
|
return
|
|
}
|
|
// Otherwise fetch the update in the background, so even if the user rejects switching to latest version it will be done automatically on next relaunch.
|
|
await Updates.fetchUpdateAsync()
|
|
// show a popup modal
|
|
showUpdatePopup()
|
|
} catch (e) {
|
|
logger.error('useOTAUpdate: Error while checking for update', {
|
|
error: e,
|
|
})
|
|
}
|
|
}, [showUpdatePopup])
|
|
const updateEventListener = useCallback(
|
|
(event: Updates.UpdateEvent) => {
|
|
logger.debug('useOTAUpdate: Listening for update...')
|
|
if (event.type === Updates.UpdateEventType.ERROR) {
|
|
logger.error('useOTAUpdate: Error while listening for update', {
|
|
message: event.message,
|
|
})
|
|
} else if (event.type === Updates.UpdateEventType.NO_UPDATE_AVAILABLE) {
|
|
// Handle no update available
|
|
// do nothing
|
|
} else if (event.type === Updates.UpdateEventType.UPDATE_AVAILABLE) {
|
|
// Handle update available
|
|
// open modal, ask for user confirmation, and reload the app
|
|
showUpdatePopup()
|
|
}
|
|
},
|
|
[showUpdatePopup],
|
|
)
|
|
|
|
useEffect(() => {
|
|
// ADD EVENT LISTENERS
|
|
const updateEventSubscription = Updates.addListener(updateEventListener)
|
|
const appStateSubscription = AppState.addEventListener('change', state => {
|
|
if (state === 'active' && !__DEV__) {
|
|
checkForUpdate()
|
|
}
|
|
})
|
|
|
|
// REMOVE EVENT LISTENERS (CLEANUP)
|
|
return () => {
|
|
updateEventSubscription.remove()
|
|
appStateSubscription.remove()
|
|
}
|
|
}, []) // eslint-disable-line react-hooks/exhaustive-deps
|
|
// disable exhaustive deps because we don't want to run this effect again
|
|
}
|