Skip to content

Commit 96728c4

Browse files
KM-15917: ensure "protected" timer shows (#348)
* KM-15917: ensure "protected" timer shows * KM-15917: implement PR review suggestions * KM-17099: update label on macOS 12 * KM-15917: PR suggestions
1 parent fa32a7a commit 96728c4

9 files changed

Lines changed: 63 additions & 16 deletions

File tree

LocalPackages/PIALibrary/Sources/PIALibrary/Daemons/VPNDaemon.swift

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,10 @@ final class VPNDaemon: Daemon, DatabaseAccess, ProvidersAccess {
4646
numberOfAttempts = 0
4747
}
4848

49+
deinit {
50+
NotificationCenter.default.removeObserver(self)
51+
}
52+
4953
func start() {
5054
let nc = NotificationCenter.default
5155
nc.addObserver(self, selector: #selector(neStatusDidChange(notification:)), name: .NEVPNStatusDidChange, object: nil)

LocalPackages/PIALibrary/Sources/PIALibrary/Mock/MockVPNProvider.swift

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,8 @@ public final class MockVPNProvider: VPNProvider, ConfigurationAccess, DatabaseAc
6060
return nil
6161
}
6262

63+
public var connectionDate: Date? { nil }
64+
6365
/// :nodoc:
6466
public func prepare() {
6567
accessedDatabase.transient.isNetworkReachable = true

LocalPackages/PIALibrary/Sources/PIALibrary/VPN/DefaultVPNProvider.swift

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,8 @@ public final class DefaultVPNProvider: VPNProvider, ConfigurationAccess, Databas
6969
return nil
7070
}
7171

72+
public var connectionDate: Date? { activeProfile?.connectionDate }
73+
7274
private var vpnLog: String {
7375
return accessedDatabase.transient.vpnLog
7476
}

LocalPackages/PIALibrary/Sources/PIALibrary/VPN/IKEv2Profile.swift

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,8 @@ public final class IKEv2Profile: NetworkExtensionProfile {
5252
return currentVPN
5353
}
5454

55+
public var connectionDate: Date? { currentVPN.connection.connectedDate }
56+
5557
/// :nodoc:
5658
public func prepare() {
5759
currentVPN.loadFromPreferences { (_) in

LocalPackages/PIALibrary/Sources/PIALibrary/VPN/PIATunnelProfile.swift

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,11 @@
5252
/// :nodoc:
5353
public var native: Any?
5454

55+
public var connectionDate: Date? {
56+
guard let native = native as? NETunnelProviderManager else { return nil }
57+
return native.connection.connectedDate
58+
}
59+
5560
/// :nodoc:
5661
public func prepare() {
5762
find(completionHandler: nil)

LocalPackages/PIALibrary/Sources/PIALibrary/VPN/PIAWGTunnelProfile.swift

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,11 @@ import Foundation
121121
/// :nodoc:
122122
public var native: Any?
123123

124+
public var connectionDate: Date? {
125+
guard let native = native as? NETunnelProviderManager else { return nil }
126+
return native.connection.connectedDate
127+
}
128+
124129
/// :nodoc:
125130
public func prepare() {
126131
find(completionHandler: nil)

LocalPackages/PIALibrary/Sources/PIALibrary/VPN/VPNProfile.swift

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,9 @@ public protocol VPNProfile: AnyObject {
3737
/// The underlying native profile implementation.
3838
var native: Any? { get }
3939

40+
/// The connection date time, if connected. Otherwise nil.
41+
var connectionDate: Date? { get }
42+
4043
/**
4144
Prepares the profile for use, like synchronizing with the current VPN status and making sure that the profile is not corrupt.
4245
*/

LocalPackages/PIALibrary/Sources/PIALibrary/VPN/VPNProvider.swift

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,9 @@ public protocol VPNProvider: AnyObject {
4141
/// The `Server` associated with the current profile.
4242
var profileServer: Server? { get }
4343

44+
/// The connection date time, if connected. Otherwise nil.
45+
var connectionDate: Date? { get }
46+
4447
/**
4548
Prepares the provider for VPN operations. Normally invoked when initializing the library.
4649
*/

PIA VPN/UI/Dashboard/DashboardViewController.swift

Lines changed: 37 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -97,12 +97,31 @@ final class DashboardViewController: AutolayoutViewController {
9797

9898
private var connectionTimer: Timer?
9999

100-
private var formattedConnectionTime: String? {
101-
guard let startTime = Client.preferences.lastVPNConnectionSuccess else {
102-
return nil
100+
private func getOrUpdateConnectionTime(isConnected: Bool) -> TimeInterval? {
101+
let now: TimeInterval = Date.now.timeIntervalSince1970
102+
let connectionTime: TimeInterval?
103+
104+
// by default use the time we know we established the connection
105+
if let lastVPNConnectionSuccess = Client.preferences.lastVPNConnectionSuccess {
106+
connectionTime = now - lastVPNConnectionSuccess
107+
// as fallback use system connected time and use that as connection success
108+
} else if let connectedDate = Client.providers.vpnProvider.connectionDate {
109+
let timeInterval = connectedDate.timeIntervalSince1970
110+
Client.preferences.lastVPNConnectionSuccess = timeInterval
111+
connectionTime = now - timeInterval
112+
// last resort store current time because we know status is connected
113+
} else if isConnected {
114+
Client.preferences.lastVPNConnectionSuccess = now
115+
connectionTime = 0
116+
} else {
117+
connectionTime = nil
103118
}
104119

105-
let connectionTime = Date().timeIntervalSince1970 - startTime
120+
return connectionTime
121+
}
122+
123+
private func formatted(connectionTime: TimeInterval?) -> String? {
124+
guard let connectionTime else { return nil }
106125

107126
let formatter = DateComponentsFormatter()
108127
formatter.unitsStyle = .positional
@@ -1050,7 +1069,8 @@ final class DashboardViewController: AutolayoutViewController {
10501069

10511070
let titleLabelView = UILabel(frame: CGRect.zero)
10521071
titleLabelView.style(style: TextStyle.textStyleNavigationBarTitle)
1053-
titleLabelView.text = formattedConnectionTime
1072+
let connectionTime = getOrUpdateConnectionTime(isConnected: true)
1073+
titleLabelView.text = formatted(connectionTime: connectionTime)
10541074
setNavBarTheme(.green, with: titleLabelView)
10551075

10561076
AppPreferences.shared.todayWidgetVpnStatus = VPNStatus.connected.rawValue
@@ -1157,18 +1177,18 @@ final class DashboardViewController: AutolayoutViewController {
11571177
private func setNavBar(titleLabel: UILabel) {
11581178
navigationTitleLabel = titleLabel
11591179
#if targetEnvironment(macCatalyst)
1160-
if #available(iOS 16.0, *) {
1161-
let title = UIBarButtonItem(customView: titleLabel)
1162-
if #available(macCatalyst 26.0, *) {
1163-
title.hidesSharedBackground = true
1180+
if #available(iOS 16.0, *) {
1181+
let title = UIBarButtonItem(customView: titleLabel)
1182+
if #available(macCatalyst 26.0, *) {
1183+
title.hidesSharedBackground = true
1184+
}
1185+
let titleGroup = UIBarButtonItemGroup.fixedGroup(items: [title])
1186+
navigationItem.centerItemGroups = [titleGroup]
1187+
} else {
1188+
navigationItem.titleView = titleLabel
11641189
}
1165-
let titleGroup = UIBarButtonItemGroup.fixedGroup(items: [title])
1166-
navigationItem.centerItemGroups = [titleGroup]
1167-
} else {
1168-
navigationItem.title = titleLabel.text
1169-
}
11701190
#else
1171-
navigationItem.titleView = titleLabel
1191+
navigationItem.titleView = titleLabel
11721192
#endif
11731193
setNeedsStatusBarAppearanceUpdate()
11741194
}
@@ -1220,7 +1240,8 @@ final class DashboardViewController: AutolayoutViewController {
12201240
}
12211241

12221242
@objc private func updateConnectionTime() {
1223-
navigationTitleLabel?.text = formattedConnectionTime
1243+
let connectionTime = getOrUpdateConnectionTime(isConnected: currentStatus == .connected)
1244+
navigationTitleLabel?.text = formatted(connectionTime: connectionTime)
12241245
}
12251246

12261247
// MARK: Restylable

0 commit comments

Comments
 (0)