import semver from 'semver' ; import { createSelector } from 'reselect' ; import { HEALTH_STATUS_OK , getViewableRobots , getRobotApiVersion , getRobotByName , } from '../discovery' ; import * as Constants from './constants' ; import type { State } from '../types' ; import type { ViewableRobot } from '../discovery/types' ; import type { BuildrootUpdateInfo , BuildrootUpdateSession , BuildrootUpdateType , RobotSystemType , } from './types' ; const UPDATE_SERVER_UNAVAILABLE = "Unable to update because your robot's update server is not responding." ; const OTHER_ROBOT_UPDATING = 'Unable to update because the app is currently updating a different robot.' ; const NO_UPDATE_FILES = 'Unable to retrieve update for this robot. Ensure your computer is connected to the internet and try again later.' ; const UNAVAILABLE = 'Update unavailable' ; export function getBuildrootUpdateVersion ( state ) { return state . buildroot . version || null ; } export function getBuildrootUpdateInfo ( state ) { return state . buildroot . info || null ; } export function getBuildrootTargetVersion ( state ) { return ( state . buildroot . session ?. userFileInfo ?. version || state . buildroot . version || null ) ; } export function getBuildrootUpdateSeen ( state ) { return state . buildroot . seen || false ; } export function getBuildrootUpdateInProgress ( state , robot ) { const session = getBuildrootSession ( state ) ; const brRobot = getBuildrootRobot ( state ) ; return ( robot === brRobot && session ?. step !== Constants . FINISHED && session ?. error === null ) ; } export function getBuildrootDownloadProgress ( state ) { return state . buildroot . downloadProgress ; } export function getBuildrootDownloadError ( state ) { return state . buildroot . downloadError ; } export function getBuildrootSession ( state ) { return state . buildroot . session ; } export function getBuildrootRobotName ( state ) { return state . buildroot . session ?. robotName || null ; } export const getBuildrootRobot = createSelector ( getViewableRobots , getBuildrootRobotName , ( robots , robotName ) => { if ( robotName === null ) return null ; return ( robots . find ( robot => { const searchName = robot . serverHealth ?. capabilities ?. buildrootUpdate != null ? robotName . replace ( /^opentrons-/ , '' ) : robotName ; return robot . name === searchName ; } ) || null ) ; } ) ; const getBuildrootUpdateType = ( currentVersion , updateVersion ) : BuildrootUpdateType | null => { const validCurrent = semver . valid ( currentVersion ) ; const validUpdate = semver . valid ( updateVersion ) ; let type = null ; if ( validUpdate && validCurrent ) { if ( semver . gt ( validUpdate , validCurrent ) ) { type = Constants . UPGRADE ; } else if ( semver . lt ( validUpdate , validCurrent ) ) { type = Constants . DOWNGRADE ; } else if ( semver . eq ( validUpdate , validCurrent ) ) { type = Constants . REINSTALL ; } } return type ; } ; export function getBuildrootUpdateAvailable ( state , robot ) { const currentVersion = getRobotApiVersion ( robot ) ; const updateVersion = getBuildrootUpdateVersion ( state ) ; return getBuildrootUpdateType ( currentVersion , updateVersion ) ; } export const getBuildrootUpdateDisplayInfo = createSelector ( getRobotByName , state => getBuildrootRobot ( state ) , state => getBuildrootUpdateVersion ( state ) , ( robot , currentUpdatingRobot , updateVersion ) => { const robotVersion = robot ? getRobotApiVersion ( robot ) : null ; const autoUpdateType = getBuildrootUpdateType ( robotVersion , updateVersion ) ; const autoUpdateAction = autoUpdateType ?? UNAVAILABLE ; let autoUpdateDisabledReason = null ; let updateFromFileDisabledReason = null ; if ( robot ?. serverHealthStatus !== HEALTH_STATUS_OK ) { autoUpdateDisabledReason = UPDATE_SERVER_UNAVAILABLE ; updateFromFileDisabledReason = UPDATE_SERVER_UNAVAILABLE ; } else if ( currentUpdatingRobot !== null && currentUpdatingRobot . name !== robot ?. name ) { autoUpdateDisabledReason = OTHER_ROBOT_UPDATING ; updateFromFileDisabledReason = OTHER_ROBOT_UPDATING ; } else if ( autoUpdateType === null ) { autoUpdateDisabledReason = NO_UPDATE_FILES ; } return { autoUpdateAction , autoUpdateDisabledReason , updateFromFileDisabledReason , } ; } ) ; export function getRobotSystemType ( robot ) { const { serverHealth } = robot ; if ( serverHealth ) { const { capabilities } = serverHealth ; if ( ! capabilities || capabilities . balenaUpdate ) { return Constants . BALENA ; } return Constants . BUILDROOT ; } return null ; }