diff --git a/core/frontend/src/components/app/InternetTrayMenu.vue b/core/frontend/src/components/app/InternetTrayMenu.vue index 42648ad04b..f3b84bde70 100644 --- a/core/frontend/src/components/app/InternetTrayMenu.vue +++ b/core/frontend/src/components/app/InternetTrayMenu.vue @@ -20,7 +20,7 @@ color="white" :title="tooltip" > - {{ helper.has_internet ? 'mdi-web' : 'mdi-web-off' }} + {{ icon }} @@ -42,6 +42,7 @@ import Vue from 'vue' import settings from '@/libs/settings' import helper from '@/store/helper' +import { InternetConnectionState } from '@/types/helper' import NetworkInterfaceMenu from './NetworkInterfaceMenu.vue' @@ -51,13 +52,37 @@ export default Vue.extend({ NetworkInterfaceMenu, }, data: () => ({ - helper, settings, show_menu: false, }), computed: { tooltip() { - return helper.has_internet ? 'Vehicle has internet access.' : 'Internet connection is not available.' + switch (helper.has_internet) { + case InternetConnectionState.ONLINE: + return 'Vehicle has internet access.' + case InternetConnectionState.OFFLINE: + return 'Internet connection is not available.' + case InternetConnectionState.LIMITED: + return 'Internet connection is limited.' + case InternetConnectionState.UNKNOWN: + return 'Internet connection status is unknown.' + default: + return 'Internet connection is not available.' + } + }, + icon(): string { + switch (helper.has_internet) { + case InternetConnectionState.ONLINE: + return 'mdi-web' + case InternetConnectionState.OFFLINE: + return 'mdi-web-off' + case InternetConnectionState.LIMITED: + return 'mdi-web-minus' + case InternetConnectionState.UNKNOWN: + return 'mdi-web-refresh' + default: + return 'mdi-web-off' + } }, }, }) diff --git a/core/frontend/src/components/kraken/BackAlleyTab.vue b/core/frontend/src/components/kraken/BackAlleyTab.vue index b479890ee5..a06613c3b6 100644 --- a/core/frontend/src/components/kraken/BackAlleyTab.vue +++ b/core/frontend/src/components/kraken/BackAlleyTab.vue @@ -276,6 +276,7 @@ import SpinningLogo from '@/components/common/SpinningLogo.vue' import StoreExtensionCard, { ImgProcessedResult } from '@/components/kraken/cards/StoreExtensionCard.vue' import { getLatestVersion } from '@/components/kraken/Utils' import helper from '@/store/helper' +import { InternetConnectionState } from '@/types/helper' import { ExtensionData, InstalledExtensionData } from '@/types/kraken' enum AvailableSorts { @@ -328,7 +329,7 @@ export default Vue.extend({ return this.manifest_is_loading || this.manifest_has_error }, internet_offline(): boolean { - return !helper.has_internet + return helper.has_internet === InternetConnectionState.OFFLINE }, show_info_card(): boolean { return this.is_manifest_invalid || this.internet_offline diff --git a/core/frontend/src/components/kraken/BazaarTab.vue b/core/frontend/src/components/kraken/BazaarTab.vue index 9188877a2a..2faf5208e0 100644 --- a/core/frontend/src/components/kraken/BazaarTab.vue +++ b/core/frontend/src/components/kraken/BazaarTab.vue @@ -56,6 +56,7 @@ import BrIframe from '@/components/utils/BrIframe.vue' import { OneMoreTime } from '@/one-more-time' import bag from '@/store/bag' import helper from '@/store/helper' +import { InternetConnectionState } from '@/types/helper' export default Vue.extend({ name: 'BazaarTab', @@ -76,7 +77,7 @@ export default Vue.extend({ return this.bazaar_url_loading || this.bazaar_url_error !== undefined }, internet_offline(): boolean { - return !helper.has_internet + return helper.has_internet === InternetConnectionState.OFFLINE }, major_tom_not_configured(): boolean { return this.bazaar_url === undefined && !this.internet_offline diff --git a/core/frontend/src/components/speedtest/InternetSpeedTest.vue b/core/frontend/src/components/speedtest/InternetSpeedTest.vue index 8881373af9..13e81c0555 100644 --- a/core/frontend/src/components/speedtest/InternetSpeedTest.vue +++ b/core/frontend/src/components/speedtest/InternetSpeedTest.vue @@ -9,7 +9,7 @@ width="100%" absolute opacity="0.92" - :value="!helper.has_internet" + :value="helper.has_internet === InternetConnectionState.OFFLINE" > Waiting for internet connection.. diff --git a/core/frontend/src/components/version-chooser/VersionCard.vue b/core/frontend/src/components/version-chooser/VersionCard.vue index c7e8834d03..2c091457b1 100644 --- a/core/frontend/src/components/version-chooser/VersionCard.vue +++ b/core/frontend/src/components/version-chooser/VersionCard.vue @@ -168,6 +168,7 @@ import Vue, { PropType } from 'vue' import settings from '@/libs/settings' import helper from '@/store/helper' import { Dictionary } from '@/types/common' +import { InternetConnectionState } from '@/types/helper' import { DEFAULT_REMOTE_IMAGE } from '@/utils/version_chooser' import SpinningLogo from '../common/SpinningLogo.vue' @@ -248,7 +249,8 @@ export default Vue.extend({ return this.image.repository === 'bluerobotics/blueos-core' }, showBootstrapUpdate(): boolean { - if (!this.bootstrapVersion || !helper.has_internet) { + if (!this.bootstrapVersion || helper.has_internet === InternetConnectionState.OFFLINE + || helper.has_internet === InternetConnectionState.UNKNOWN) { return false } return this.settings.is_pirate_mode && this.current && !this.updateAvailable && this.isFromBR diff --git a/core/frontend/src/components/version-chooser/VersionChooser.vue b/core/frontend/src/components/version-chooser/VersionChooser.vue index 04543d3082..4e40b2af25 100644 --- a/core/frontend/src/components/version-chooser/VersionChooser.vue +++ b/core/frontend/src/components/version-chooser/VersionChooser.vue @@ -201,6 +201,7 @@ import Notifier from '@/libs/notifier' import settings from '@/libs/settings' import helper from '@/store/helper' import { version_chooser_service } from '@/types/frontend_services' +import { InternetConnectionState } from '@/types/helper' import { isServerResponse, LocalVersionsQuery, Version, VersionsQuery, VersionType, @@ -270,7 +271,7 @@ export default Vue.extend({ return 'File is required' }, has_internet(): boolean { - return helper.has_internet + return helper.has_internet !== InternetConnectionState.OFFLINE }, }, watch: { diff --git a/core/frontend/src/store/helper.ts b/core/frontend/src/store/helper.ts index a32dccc75e..9f4cf58cc6 100644 --- a/core/frontend/src/store/helper.ts +++ b/core/frontend/src/store/helper.ts @@ -7,7 +7,7 @@ import Notifier from '@/libs/notifier' import { OneMoreTime } from '@/one-more-time' import store from '@/store' import { helper_service } from '@/types/frontend_services' -import { Service, SpeedTestResult } from '@/types/helper' +import { InternetConnectionState, Service, SpeedTestResult } from '@/types/helper' import back_axios, { isBackendOffline } from '@/utils/api' const notifier = new Notifier(helper_service) @@ -29,7 +29,7 @@ type SiteStatus = Record class PingStore extends VuexModule { API_URL = '/helper/latest' - has_internet = false + has_internet: InternetConnectionState = InternetConnectionState.UNKNOWN services: Service[] = [] @@ -42,7 +42,7 @@ class PingStore extends VuexModule { ) @Mutation - setHasInternet(has_internet: boolean): void { + setHasInternet(has_internet: InternetConnectionState): void { this.has_internet = has_internet } @@ -59,13 +59,27 @@ class PingStore extends VuexModule { timeout: 10000, }) .then((response) => { - const has_internet = !Object.values(response.data as SiteStatus) - .filter((item) => item.online) - .isEmpty() - - this.setHasInternet(has_internet) + const sites = Object.values(response.data as SiteStatus) + const online_sites = sites.filter((item) => item.online) + + // If no sites are reachable, we're offline + if (online_sites.length === 0) { + this.setHasInternet(InternetConnectionState.OFFLINE) + return + } + + // If all sites are reachable, we're fully online + if (online_sites.length === sites.length) { + this.setHasInternet(InternetConnectionState.ONLINE) + return + } + + // If some sites are reachable but not all, we have limited connectivity + this.setHasInternet(InternetConnectionState.LIMITED) }) .catch((error) => { + // If we can't even reach the backend, we're in an unknown state + this.setHasInternet(InternetConnectionState.UNKNOWN) notifier.pushBackError('INTERNET_CHECK_FAIL', error) }) } diff --git a/core/frontend/src/types/helper.ts b/core/frontend/src/types/helper.ts index b72b982016..dcd6ab28be 100644 --- a/core/frontend/src/types/helper.ts +++ b/core/frontend/src/types/helper.ts @@ -62,3 +62,10 @@ export interface SpeedTestResult { share: string | null client: SpeedtestClient } + +export enum InternetConnectionState { + OFFLINE = 0, + UNKNOWN = 1, + LIMITED = 2, + ONLINE = 3, +}