Skip to content

Commit 9776180

Browse files
committed
ios: react to change in connectivity.
Use NwPathMonitor to monitor change in connectivity, and trigger the offline banner when going offline, and a manual reconnection when going back online.
1 parent 1346f90 commit 9776180

File tree

6 files changed

+44
-29
lines changed

6 files changed

+44
-29
lines changed

backend/backend.go

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -279,9 +279,6 @@ func NewBackend(arguments *arguments.Arguments, environment Environment) (*Backe
279279
log: log,
280280

281281
testing: backendConfig.AppConfig().Backend.StartInTestnet || arguments.Testing(),
282-
283-
// TODO: remove when connectivity check is present on all platforms
284-
isOnline: true,
285282
}
286283
// TODO: remove when connectivity check is present on all platforms
287284
backend.isOnline.Store(true)

backend/mobileserver/mobileserver.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -157,6 +157,11 @@ func UsingMobileDataChanged() {
157157
bridgecommon.UsingMobileDataChanged()
158158
}
159159

160+
// SetOnline exposes `bridgecommon.SetOnline` to Java/Kotlin.
161+
func SetOnline(online bool) {
162+
bridgecommon.SetOnline(online)
163+
}
164+
160165
// UsbUpdate exposes `bridgecommon.UsbUpdate` to Java/Kotlin.
161166
func UsbUpdate() {
162167
bridgecommon.UsbUpdate()

frontends/ios/BitBoxApp/BitBoxApp.xcodeproj/project.pbxproj

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@
77
objects = {
88

99
/* Begin PBXBuildFile section */
10+
8E1846EB2E0AFF6000802D8B /* NetworkMonitor.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8E1846EA2E0AFF5B00802D8B /* NetworkMonitor.swift */; };
11+
8E1846EC2E0AFF6000802D8B /* NetworkMonitor.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8E1846EA2E0AFF5B00802D8B /* NetworkMonitor.swift */; };
1012
D700B5F62C884C34000496D4 /* Mobileserver.xcframework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = D76518BB2B1F8F7400DC03A9 /* Mobileserver.xcframework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
1113
D700B5FD2CA2FFAF000496D4 /* WebView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D76516322B1F3D1A00DC03A9 /* WebView.swift */; };
1214
D700B5FE2CA2FFAF000496D4 /* BitBoxAppApp.swift in Sources */ = {isa = PBXBuildFile; fileRef = D76516082B1F3B1300DC03A9 /* BitBoxAppApp.swift */; };
@@ -71,6 +73,7 @@
7173
/* End PBXCopyFilesBuildPhase section */
7274

7375
/* Begin PBXFileReference section */
76+
8E1846EA2E0AFF5B00802D8B /* NetworkMonitor.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NetworkMonitor.swift; sourceTree = "<group>"; };
7477
D700B5F82C888CB9000496D4 /* Config.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Config.xcconfig; sourceTree = "<group>"; };
7578
D700B5F92C986A3C000496D4 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist; path = Info.plist; sourceTree = "<group>"; };
7679
D700B60A2CA2FFAF000496D4 /* BitBoxApp Testnet.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "BitBoxApp Testnet.app"; sourceTree = BUILT_PRODUCTS_DIR; };
@@ -151,6 +154,7 @@
151154
D76516072B1F3B1300DC03A9 /* BitBoxApp */ = {
152155
isa = PBXGroup;
153156
children = (
157+
8E1846EA2E0AFF5B00802D8B /* NetworkMonitor.swift */,
154158
D700B5F92C986A3C000496D4 /* Info.plist */,
155159
D76518B52B1F45B300DC03A9 /* assets */,
156160
D76516082B1F3B1300DC03A9 /* BitBoxAppApp.swift */,
@@ -400,6 +404,7 @@
400404
buildActionMask = 2147483647;
401405
files = (
402406
D700B5FD2CA2FFAF000496D4 /* WebView.swift in Sources */,
407+
8E1846EC2E0AFF6000802D8B /* NetworkMonitor.swift in Sources */,
403408
D721B20E2D36A00000767080 /* Bluetooth.swift in Sources */,
404409
D700B5FE2CA2FFAF000496D4 /* BitBoxAppApp.swift in Sources */,
405410
);
@@ -410,6 +415,7 @@
410415
buildActionMask = 2147483647;
411416
files = (
412417
D76516332B1F3D1B00DC03A9 /* WebView.swift in Sources */,
418+
8E1846EB2E0AFF6000802D8B /* NetworkMonitor.swift in Sources */,
413419
D721B20D2D369EC100767080 /* Bluetooth.swift in Sources */,
414420
D76516092B1F3B1300DC03A9 /* BitBoxAppApp.swift in Sources */,
415421
);
@@ -464,7 +470,7 @@
464470
INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES;
465471
INFOPLIST_KEY_UILaunchScreen_Generation = YES;
466472
INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight";
467-
INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = "UIInterfaceOrientationPortrait";
473+
INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = UIInterfaceOrientationPortrait;
468474
IPHONEOS_DEPLOYMENT_TARGET = 16.0;
469475
LD_RUNPATH_SEARCH_PATHS = (
470476
"$(inherited)",
@@ -496,7 +502,7 @@
496502
INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES;
497503
INFOPLIST_KEY_UILaunchScreen_Generation = YES;
498504
INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight";
499-
INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = "UIInterfaceOrientationPortrait";
505+
INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = UIInterfaceOrientationPortrait;
500506
IPHONEOS_DEPLOYMENT_TARGET = 16.0;
501507
LD_RUNPATH_SEARCH_PATHS = (
502508
"$(inherited)",
@@ -644,7 +650,7 @@
644650
INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES;
645651
INFOPLIST_KEY_UILaunchScreen_Generation = YES;
646652
INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight";
647-
INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = "UIInterfaceOrientationPortrait";
653+
INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = UIInterfaceOrientationPortrait;
648654
IPHONEOS_DEPLOYMENT_TARGET = 16.0;
649655
LD_RUNPATH_SEARCH_PATHS = (
650656
"$(inherited)",
@@ -675,7 +681,7 @@
675681
INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES;
676682
INFOPLIST_KEY_UILaunchScreen_Generation = YES;
677683
INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight";
678-
INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = "UIInterfaceOrientationPortrait";
684+
INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = UIInterfaceOrientationPortrait;
679685
IPHONEOS_DEPLOYMENT_TARGET = 16.0;
680686
LD_RUNPATH_SEARCH_PATHS = (
681687
"$(inherited)",

frontends/ios/BitBoxApp/BitBoxApp/BitBoxAppApp.swift

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
import SwiftUI
99
import Mobileserver
1010
import LocalAuthentication
11+
import Network
1112

1213
protocol MessageHandlersProtocol {
1314
func callResponseHandler(queryID: Int, response: String)
@@ -184,6 +185,10 @@ struct BitBoxAppApp: App {
184185
.edgesIgnoringSafeArea(.all)
185186
.onAppear {
186187
setupGoAPI(goAPI: goAPI)
188+
_ = NetworkMonitor.shared
189+
// Manual trigger at startup
190+
let isOnline = NWPathMonitor().currentPath.status == .satisfied
191+
MobileserverSetOnline(isOnline)
187192
}
188193
.onReceive(NotificationCenter.default.publisher(for: UIApplication.willEnterForegroundNotification)) { _ in
189194
MobileserverManualReconnect()
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
//
2+
// NetworkMonitor.swift
3+
// BitBoxApp
4+
//
5+
// Created by Nikolas De Giorgis on 24/06/2025.
6+
//
7+
8+
import Network
9+
import Mobileserver
10+
11+
class NetworkMonitor {
12+
static let shared = NetworkMonitor()
13+
private let monitor = NWPathMonitor()
14+
private let queue = DispatchQueue(label: "NetworkMonitor")
15+
16+
private init() {
17+
monitor.pathUpdateHandler = { path in
18+
let isOnline = path.status == .satisfied
19+
print("Network status changed: \(isOnline)")
20+
MobileServerSetOnline(isOnline)
21+
}
22+
monitor.start(queue: queue)
23+
}
24+
}

frontends/qt/network.cpp

Lines changed: 0 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,41 +1,29 @@
11
#include <QNetworkInformation>
22
#include "libserver.h"
3-
<<<<<<< HEAD
43
#include "network.h"
5-
=======
6-
>>>>>>> b8afb2139 (frontend/qt: react to change in connectivity status.)
74

85
void setupReachabilityNotifier() {
96
auto loaded = QNetworkInformation::loadBackendByFeatures(QNetworkInformation::Feature::Reachability);
107
if (!loaded) {
11-
<<<<<<< HEAD
128
goLog("can't load QNetworkInformation backend");
139
// If we can't load the backend, we can't determine whether or not to show the banner.
1410
setOnline(true);
15-
=======
16-
>>>>>>> b8afb2139 (frontend/qt: react to change in connectivity status.)
1711
return;
1812
}
1913
QNetworkInformation* info = QNetworkInformation::instance();
2014
if (info) {
2115
QObject::connect(info, &QNetworkInformation::reachabilityChanged, [](QNetworkInformation::Reachability reachability){
22-
<<<<<<< HEAD
2316
// We include Reachability::Unknown here as we prefer not include false positives. If QT can't determine whether
2417
// we are online, we do not show the banner.
2518
bool isReachable = (reachability == QNetworkInformation::Reachability::Online || reachability == QNetworkInformation::Reachability::Unknown);
2619
setOnline(isReachable);
27-
=======
28-
bool isReachable = (reachability == QNetworkInformation::Reachability::Online);
29-
onlineStatusChanged(isReachable);
30-
>>>>>>> b8afb2139 (frontend/qt: react to change in connectivity status.)
3120
});
3221
}
3322
}
3423

3524
bool isReachable() {
3625
auto loaded = QNetworkInformation::loadBackendByFeatures(QNetworkInformation::Feature::Reachability);
3726
if (!loaded) {
38-
<<<<<<< HEAD
3927
goLog("can't load QNetworkInformation backend");
4028
return true;
4129
}
@@ -45,14 +33,4 @@ bool isReachable() {
4533
}
4634
// Same as above, if we can't obtain information, we don't show any banner at all.
4735
return true;
48-
=======
49-
return false;
50-
}
51-
QNetworkInformation* info = QNetworkInformation::instance();
52-
if (info) {
53-
return info->reachability() == QNetworkInformation::Reachability::Online;
54-
} else {
55-
return false;
56-
}
57-
>>>>>>> b8afb2139 (frontend/qt: react to change in connectivity status.)
5836
}

0 commit comments

Comments
 (0)