Skip to content

Commit 3335c9e

Browse files
tcobbs-bentleypmconneCopilot
authored
Mobile: reachability updates (#8786)
Co-authored-by: Paul Connelly <[email protected]> Co-authored-by: Copilot <[email protected]>
1 parent 82d361c commit 3335c9e

File tree

8 files changed

+76
-5
lines changed

8 files changed

+76
-5
lines changed

common/api/core-mobile.api.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ export interface CancelRequest {
4141
}
4242

4343
// @beta (undocumented)
44-
export type DeviceEvents = "memoryWarning" | "orientationChanged" | "enterForeground" | "enterBackground" | "willTerminate" | "authAccessTokenChanged";
44+
export type DeviceEvents = "memoryWarning" | "orientationChanged" | "enterForeground" | "enterBackground" | "willTerminate" | "authAccessTokenChanged" | "online" | "offline";
4545

4646
// @internal
4747
export class DownloadFailed extends BentleyError {
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
{
2+
"changes": [
3+
{
4+
"packageName": "@itwin/core-backend",
5+
"comment": "Mobile: don't do workspace update checks when offline",
6+
"type": "none"
7+
}
8+
],
9+
"packageName": "@itwin/core-backend"
10+
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
{
2+
"changes": [
3+
{
4+
"packageName": "@itwin/core-mobile",
5+
"comment": "Added online and offline device events for network reachability monitoring.",
6+
"type": "none"
7+
}
8+
],
9+
"packageName": "@itwin/core-mobile"
10+
}

core/backend/src/NativeHost.ts

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
*/
88

99
import { join } from "path";
10-
import { AccessToken, assert, BeEvent, GuidString } from "@itwin/core-bentley";
10+
import { AccessToken, assert, BeEvent, GuidString, ProcessDetector } from "@itwin/core-bentley";
1111
import {
1212
BriefcaseProps, InternetConnectivityStatus, LocalBriefcaseProps, NativeAppFunctions, nativeAppIpcStrings, NativeAppNotifications,
1313
OverriddenBy, RequestNewBriefcaseProps, StorageValue,
@@ -18,6 +18,7 @@ import { IModelHost } from "./IModelHost";
1818
import { IpcHandler, IpcHost, IpcHostOpts, throttleProgressCallback } from "./IpcHost";
1919
import { NativeAppStorage } from "./NativeAppStorage";
2020
import { CatalogIModelHandler } from "./CatalogDb";
21+
import { setOnlineStatus } from "./internal/OnlineStatus";
2122

2223
/**
2324
* Implementation of NativeAppFunctions
@@ -199,6 +200,12 @@ export class NativeHost {
199200
if (this._reachability !== status) {
200201
this._reachability = status;
201202
this.onInternetConnectivityChanged.raiseEvent(status);
203+
if (ProcessDetector.isMobileAppBackend) {
204+
// Merely referencing NativeHost from a non-native backend causes a runtime exception (even
205+
// inside an if statement that checks that the backend is a mobile backend). This allows code
206+
// that needs to check connectivity to do so without referencing NativeHost directly.
207+
setOnlineStatus(status === InternetConnectivityStatus.Online);
208+
}
202209
}
203210
}
204211
}
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
/*---------------------------------------------------------------------------------------------
2+
* Copyright (c) Bentley Systems, Incorporated. All rights reserved.
3+
* See LICENSE.md in the project root for license terms and full copyright notice.
4+
*--------------------------------------------------------------------------------------------*/
5+
6+
let isOnline = true;
7+
8+
/**
9+
* Sets the online status of the backend that will be returned by `getOnlineStatus`.
10+
* @param online The new online status.
11+
* @internal
12+
*/
13+
export function setOnlineStatus(online: boolean) {
14+
isOnline = online;
15+
}
16+
17+
/**
18+
* Determine whether the backend is currently considered online.
19+
* @note This only works if `setOnlineStatus` has been called by something to update the status.
20+
* `NativeHost` does this whenever the connectivity changes. If `setOnlineStatus` has never been
21+
* called, this will return `true`.
22+
* @internal
23+
*/
24+
export function getOnlineStatus(): boolean {
25+
return isOnline;
26+
}

core/backend/src/internal/workspace/WorkspaceImpl.ts

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
import { createHash } from "crypto";
1010
import * as fs from "fs-extra";
1111
import { dirname, extname, join } from "path";
12-
import { AccessToken, assert, BeEvent, DbResult, Mutable, OpenMode } from "@itwin/core-bentley";
12+
import { AccessToken, assert, BeEvent, DbResult, Mutable, OpenMode, ProcessDetector } from "@itwin/core-bentley";
1313
import { CloudSqliteError, FilePropertyProps, LocalDirName, LocalFileName, WorkspaceError } from "@itwin/core-common";
1414
import { CloudSqlite } from "../../CloudSqlite";
1515
import { IModelHost, KnownLocations } from "../../IModelHost";
@@ -27,6 +27,7 @@ import { CreateNewWorkspaceContainerArgs, CreateNewWorkspaceDbVersionArgs, Edita
2727
import { WorkspaceSqliteDb } from "./WorkspaceSqliteDb";
2828
import { SettingsImpl } from "./SettingsImpl";
2929
import { _implementationProhibited, _nativeDb } from "../Symbols";
30+
import { getOnlineStatus } from "../OnlineStatus";
3031

3132
function workspaceDbNameWithDefault(dbName?: WorkspaceDbName): WorkspaceDbName {
3233
return dbName ?? "workspace-db";
@@ -119,6 +120,17 @@ class WorkspaceContainerImpl implements WorkspaceContainer {
119120
// sharedConnect returns true if we just connected (if the container is shared, it may have already been connected)
120121
if (cloudContainer.sharedConnect() && false !== props.syncOnConnect) {
121122
try {
123+
if (ProcessDetector.isMobileAppBackend || ProcessDetector.isElectronAppBackend) {
124+
// Even though we've already confirmed that we are running in a native app backend,
125+
// having code here that references NativeHost causes a runtime exception. So we use
126+
// getOnlineStatus to determine whether we're online, which NativeHost keeps up to date.
127+
if (!getOnlineStatus()) {
128+
// If running in a native app and we're offline, don't check for changes.
129+
// Doing so will fail and be caught below, but it has to wait for the network
130+
// timeout.
131+
return;
132+
}
133+
}
122134
cloudContainer.checkForChanges();
123135
} catch {
124136
// must be offline

core/mobile/src/backend/MobileHost.ts

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55

66
import { AccessToken, BeEvent, BriefcaseStatus } from "@itwin/core-bentley";
77
import { IpcHandler, IpcHost, NativeHost, NativeHostOpts } from "@itwin/core-backend";
8-
import { IpcWebSocketBackend, RpcInterfaceDefinition } from "@itwin/core-common";
8+
import { InternetConnectivityStatus, IpcWebSocketBackend, OverriddenBy, RpcInterfaceDefinition } from "@itwin/core-common";
99
import { CancelRequest, DownloadFailed, UserCancelledError } from "./MobileFileHandler";
1010
import { ProgressCallback } from "./Request";
1111
import { mobileAppStrings } from "../common/MobileAppChannel";
@@ -58,6 +58,12 @@ export abstract class MobileDevice {
5858
case "authAccessTokenChanged":
5959
MobileHost.onAuthAccessTokenChanged.raiseEvent(args[0], args[1]);
6060
break;
61+
case "online":
62+
NativeHost.overrideInternetConnectivity(OverriddenBy.Browser, InternetConnectivityStatus.Online);
63+
break;
64+
case "offline":
65+
NativeHost.overrideInternetConnectivity(OverriddenBy.Browser, InternetConnectivityStatus.Offline);
66+
break;
6167
}
6268
}
6369

core/mobile/src/common/MobileAppProps.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ export interface MobileNotifications {
3333
}
3434

3535
/** @beta */
36-
export type DeviceEvents = "memoryWarning" | "orientationChanged" | "enterForeground" | "enterBackground" | "willTerminate" | "authAccessTokenChanged";
36+
export type DeviceEvents = "memoryWarning" | "orientationChanged" | "enterForeground" | "enterBackground" | "willTerminate" | "authAccessTokenChanged" | "online" | "offline";
3737

3838
/**
3939
* The methods that may be invoked via Ipc from the frontend of a Mobile App that are implemented on its backend.

0 commit comments

Comments
 (0)