diff --git a/DuckDuckGo/NetworkProtectionStatusView.swift b/DuckDuckGo/NetworkProtectionStatusView.swift index 7cde520992..dca5efc04a 100644 --- a/DuckDuckGo/NetworkProtectionStatusView.swift +++ b/DuckDuckGo/NetworkProtectionStatusView.swift @@ -134,14 +134,22 @@ struct NetworkProtectionStatusView: View { private func locationDetails() -> some View { Section { if let location = statusModel.location { + var locationAttributedString: AttributedString { + var attributedString = AttributedString(statusModel.preferredLocation.isNearest ? "\(location) (Nearest)" : location) + attributedString.foregroundColor = .init(designSystemColor: .textPrimary) + if let range = attributedString.range(of: "(Nearest)") { + attributedString[range].foregroundColor = Color(.init(designSystemColor: .textSecondary)) + } + return attributedString + } + NavigationLink(destination: NetworkProtectionVPNLocationView()) { - let title = statusModel.preferredLocation.isNearest ? "\(location) (Nearest)" : location - NetworkProtectionLocationItemView(title: title) + NetworkProtectionLocationItemView(title: locationAttributedString) } } else { NavigationLink(destination: NetworkProtectionVPNLocationView()) { NetworkProtectionLocationItemView( - title: statusModel.preferredLocation.title + title: AttributedString(statusModel.preferredLocation.title) ) } } @@ -257,14 +265,14 @@ private struct NetworkProtectionErrorView: View { } } +@available(iOS 15.0, *) private struct NetworkProtectionLocationItemView: View { - let title: String + let title: AttributedString var body: some View { HStack(spacing: 16) { Text(title) .daxBodyRegular() - .foregroundColor(.init(designSystemColor: .textPrimary)) } .listRowBackground(Color(designSystemColor: .surface)) } @@ -301,16 +309,16 @@ private struct NetworkProtectionThroughputItemView: View { Spacer(minLength: 2) - Image("VPNUpload") + Image("VPNDownload") .foregroundColor(.init(designSystemColor: .textSecondary)) - Text(uploadSpeed) + Text(downloadSpeed) .daxBodyRegular() .foregroundColor(.init(designSystemColor: .textSecondary)) - Image("VPNDownload") + Image("VPNUpload") .foregroundColor(.init(designSystemColor: .textSecondary)) .padding(.leading, 4) - Text(downloadSpeed) + Text(uploadSpeed) .daxBodyRegular() .foregroundColor(.init(designSystemColor: .textSecondary)) } diff --git a/DuckDuckGo/NetworkProtectionStatusViewModel.swift b/DuckDuckGo/NetworkProtectionStatusViewModel.swift index b018f0a693..1fab88cb0e 100644 --- a/DuckDuckGo/NetworkProtectionStatusViewModel.swift +++ b/DuckDuckGo/NetworkProtectionStatusViewModel.swift @@ -174,6 +174,18 @@ final class NetworkProtectionStatusViewModel: ObservableObject { .map(Self.statusImageID(connected:)) .assign(to: \.statusImageID, onWeaklyHeld: self) .store(in: &cancellables) + isConnectedPublisher + .sink { [weak self] isConnected in + if !isConnected { + self?.uploadTotal = Constants.defaultUploadVolume + self?.downloadTotal = Constants.defaultDownloadVolume + self?.throughputUpdateTimer?.invalidate() + self?.throughputUpdateTimer = nil + } else { + self?.setUpThroughputRefreshTimer() + } + } + .store(in: &cancellables) } private func setUpToggledStatePublisher() { @@ -273,6 +285,11 @@ final class NetworkProtectionStatusViewModel: ObservableObject { } private func setUpThroughputRefreshTimer() { + if let throughputUpdateTimer, throughputUpdateTimer.isValid { + // Prevent the timer from being set up multiple times + return + } + Task { // Refresh as soon as the timer is set up, rather than waiting for 1 second: await self.refreshDataVolumeTotals()