1import * as Updates from './Updates'; 2import type { Manifest, UpdatesNativeStateMachineContext } from './Updates.types'; 3import { UpdateInfoType, type CurrentlyRunningInfo, type UpdateInfo } from './UseUpdates.types'; 4 5// The currently running info, constructed from Updates constants 6export const currentlyRunning: CurrentlyRunningInfo = { 7 updateId: Updates.updateId ?? undefined, 8 channel: Updates.channel ?? undefined, 9 createdAt: Updates.createdAt ?? undefined, 10 isEmbeddedLaunch: Updates.isEmbeddedLaunch, 11 isEmergencyLaunch: Updates.isEmergencyLaunch, 12 manifest: Updates.manifest ?? undefined, 13 runtimeVersion: Updates.runtimeVersion ?? undefined, 14}; 15 16// Type for the state managed by useUpdates(). 17// Used internally by this module and not exported publicly. 18export type UseUpdatesStateType = { 19 availableUpdate?: UpdateInfo; 20 downloadedUpdate?: UpdateInfo; 21 checkError?: Error; 22 downloadError?: Error; 23 isUpdateAvailable: boolean; 24 isUpdatePending: boolean; 25 isChecking: boolean; 26 isDownloading: boolean; 27 lastCheckForUpdateTimeSinceRestart?: Date; 28}; 29 30// Constructs an UpdateInfo from a manifest 31export const updateFromManifest: (manifest: NonNullable<Manifest>) => UpdateInfo = (manifest) => { 32 return { 33 type: UpdateInfoType.NEW, 34 updateId: manifest.id ?? '', 35 createdAt: 36 manifest && 'createdAt' in manifest && manifest.createdAt 37 ? new Date(manifest.createdAt) 38 : manifest && 'publishedTime' in manifest && manifest.publishedTime 39 ? new Date(manifest.publishedTime) 40 : // We should never reach this if the manifest is valid and has a commit time, 41 // but leave this in so that createdAt is always defined 42 new Date(0), 43 manifest, 44 }; 45}; 46 47// Default useUpdates() state 48export const defaultUseUpdatesState: UseUpdatesStateType = { 49 isChecking: false, 50 isDownloading: false, 51 isUpdateAvailable: false, 52 isUpdatePending: false, 53}; 54 55// Transform the useUpdates() state based on native state machine context 56export const reduceUpdatesStateFromContext: ( 57 updatesState: UseUpdatesStateType, 58 context: UpdatesNativeStateMachineContext 59) => UseUpdatesStateType = (updatesState, context) => { 60 const availableUpdate = context?.latestManifest 61 ? updateFromManifest(context?.latestManifest) 62 : undefined; 63 const downloadedUpdate = context?.downloadedManifest 64 ? updateFromManifest(context?.downloadedManifest) 65 : undefined; 66 return { 67 ...updatesState, 68 isUpdateAvailable: context.isUpdateAvailable, 69 isUpdatePending: context.isUpdatePending, 70 isChecking: context.isChecking, 71 isDownloading: context.isDownloading, 72 availableUpdate, 73 downloadedUpdate, 74 checkError: context.checkError, 75 downloadError: context.downloadError, 76 lastCheckForUpdateTimeSinceRestart: context.isChecking 77 ? new Date() 78 : updatesState.lastCheckForUpdateTimeSinceRestart, 79 }; 80}; 81