Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -48,8 +48,11 @@ public struct GatewayCountryDropDown: View {

let unwrappedScrollToModel = scrollToModel.wrappedValue
let selectedServer = servers.first { $0.id == unwrappedScrollToModel.serverId }
let shouldExpand = unwrappedScrollToModel.countryCode == country.code
|| selectedServer?.location?.twoLetterIsoCountryCode == country.code
let shouldExpand = unwrappedScrollToModel.shouldExpand(
countryCode: country.code,
region: nil,
server: selectedServer
)
_isExpanded = State(initialValue: shouldExpand)
let shouldSelect = unwrappedScrollToModel.countryCode == country.code && unwrappedScrollToModel.isCountry
_isCountrySelected = State(initialValue: shouldSelect)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import ConnectionTypes
import CountriesManagerTypes

public enum GatewayScrollToModel: Equatable {
case country(code: String)
Expand Down Expand Up @@ -98,4 +99,22 @@ public enum GatewayScrollToModel: Equatable {
false
}
}

func shouldExpand(countryCode: String, region: String?, server: GatewayNode?) -> Bool {
switch self {
case .country:
return false
case let .region(regionCountryCode, _):
if region != nil {
return false
} else {
return countryCode == regionCountryCode
}
case let .server(id):
return server?.id == id && server?.location?.twoLetterIsoCountryCode == countryCode
|| server?.id == id && server?.location?.region == region
case .empty:
return false
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,11 @@ public struct GatewaysRegionCell: View {

let unwrappedScrollToModel = scrollToModel.wrappedValue
let selectedServer = servers.first { $0.id == unwrappedScrollToModel.serverId }
let shouldExpand = unwrappedScrollToModel.region == region || selectedServer?.location?.region == region
let shouldExpand = unwrappedScrollToModel.shouldExpand(
countryCode: country.code,
region: region,
server: selectedServer
)
_isExpanded = State(initialValue: shouldExpand)
let shouldSelect = unwrappedScrollToModel.region == region && unwrappedScrollToModel.isRegion
_isRegionSelected = State(initialValue: shouldSelect)
Expand Down
21 changes: 21 additions & 0 deletions nym-vpn-apple/Home/Sources/Gateways/GatewaysView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ public struct GatewaysView: View {
countriesGatewaysList()
noSearchResultsView()
foundCountriesList()
foundUSRegionsList()
foundGatewaysList()
}
.scrollDismissesKeyboard(.immediately)
Expand Down Expand Up @@ -200,4 +201,24 @@ private extension GatewaysView {
)
}
}

@ViewBuilder
func foundUSRegionsList() -> some View {
if let usCountry = viewModel.gatewayManager.localizedCountry(with: "US") {
ForEach(viewModel.foundUSRegions, id: \.self) { region in
GatewaysRegionCell(
hopType: viewModel.type,
country: usCountry,
region: region,
servers: viewModel.gatewayManager.vpn.filter { $0.location?.region == region},
infoButtonTapCompletion: { _ in },
path: $viewModel.path,
entryGateway: $viewModel.connectionManager.entryGateway,
exitRouter: $viewModel.connectionManager.exitRouter,
scrollToModel: .constant(.empty)
)
}

}
}
}
23 changes: 17 additions & 6 deletions nym-vpn-apple/Home/Sources/Gateways/GatewaysViewModel.swift
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,7 @@ import GatewayManager
import UIComponents

@MainActor public class GatewaysViewModel: ObservableObject {
private let gatewayManager: GatewayManager

let gatewayManager: GatewayManager
let type: HopType
let minimumSearchSymbols = 2

Expand All @@ -17,6 +16,7 @@ import UIComponents
@Published var gateways = [GatewayNode]()
@Published var countries = [NymCountry]()
@Published var foundCountries = [NymCountry]()
@Published var foundUSRegions = [String]()
@Published var foundGateways = [GatewayNode]()
@Published var scrollToModel: GatewayScrollToModel
@Published var searchText: String = "" {
Expand Down Expand Up @@ -106,12 +106,23 @@ import UIComponents
return
}
foundCountries = countries.filter {
$0.name.lowercased().contains(searchText.lowercased())
|| $0.code.lowercased().contains(searchText.lowercased())
$0.name.lowercased().localizedCaseInsensitiveContains(searchText.lowercased())
|| $0.code.lowercased().localizedCaseInsensitiveContains(searchText.lowercased())
}

var seen = Set<String>()
foundUSRegions = gateways
.lazy
.filter { $0.location?.twoLetterIsoCountryCode.caseInsensitiveCompare("US") == .orderedSame }
.compactMap { $0.location?.region.trimmingCharacters(in: .whitespacesAndNewlines) }
.filter {
!$0.isEmpty && $0.range(of: self.searchText, options: [.caseInsensitive, .diacriticInsensitive]) != nil
}
.filter { seen.insert($0).inserted }

foundGateways = gateways.filter {
$0.moniker?.lowercased().contains(searchText.lowercased()) ?? false
|| $0.id.lowercased().contains(searchText.lowercased())
$0.moniker?.lowercased().localizedCaseInsensitiveContains(searchText.lowercased()) ?? false
|| $0.id.lowercased().localizedCaseInsensitiveContains(searchText.lowercased())
}
}
}
13 changes: 7 additions & 6 deletions nym-vpn-apple/NymVPN.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -809,6 +809,7 @@
};
D94127BD2C00AB2E009EDB7A /* Run Swiftlint */ = {
isa = PBXShellScriptBuildPhase;
alwaysOutOfDate = 1;
buildActionMask = 2147483647;
files = (
);
Expand Down Expand Up @@ -912,7 +913,7 @@
CODE_SIGN_ENTITLEMENTS = NymMixnetTunnel/NymMixnetTunnel.entitlements;
CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 418;
CURRENT_PROJECT_VERSION = 419;
DEVELOPMENT_TEAM = VW5DZLFHM5;
ENABLE_APP_SANDBOX = YES;
ENABLE_OUTGOING_NETWORK_CONNECTIONS = YES;
Expand Down Expand Up @@ -950,7 +951,7 @@
CODE_SIGN_ENTITLEMENTS = NymMixnetTunnel/NymMixnetTunnel.entitlements;
CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 418;
CURRENT_PROJECT_VERSION = 419;
DEVELOPMENT_TEAM = VW5DZLFHM5;
ENABLE_APP_SANDBOX = YES;
ENABLE_OUTGOING_NETWORK_CONNECTIONS = YES;
Expand Down Expand Up @@ -1114,7 +1115,7 @@
CODE_SIGN_ENTITLEMENTS = NymVPN/NymVPN.entitlements;
CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 418;
CURRENT_PROJECT_VERSION = 419;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
DEVELOPMENT_TEAM = VW5DZLFHM5;
ENABLE_APP_SANDBOX = YES;
Expand Down Expand Up @@ -1155,7 +1156,7 @@
CODE_SIGN_ENTITLEMENTS = NymVPN/NymVPN.entitlements;
CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 418;
CURRENT_PROJECT_VERSION = 419;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
DEVELOPMENT_TEAM = VW5DZLFHM5;
ENABLE_APP_SANDBOX = YES;
Expand Down Expand Up @@ -1196,7 +1197,7 @@
CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Manual;
COMBINE_HIDPI_IMAGES = YES;
CURRENT_PROJECT_VERSION = 120;
CURRENT_PROJECT_VERSION = 121;
DEAD_CODE_STRIPPING = YES;
DEVELOPMENT_ASSET_PATHS = "\"NymVPNDaemon/Preview Content\"";
DEVELOPMENT_TEAM = VW5DZLFHM5;
Expand Down Expand Up @@ -1233,7 +1234,7 @@
"CODE_SIGN_IDENTITY[sdk=macosx*]" = "Developer ID Application";
CODE_SIGN_STYLE = Manual;
COMBINE_HIDPI_IMAGES = YES;
CURRENT_PROJECT_VERSION = 120;
CURRENT_PROJECT_VERSION = 121;
DEAD_CODE_STRIPPING = YES;
DEVELOPMENT_ASSET_PATHS = "\"NymVPNDaemon/Preview Content\"";
DEVELOPMENT_TEAM = "";
Expand Down
59 changes: 46 additions & 13 deletions nym-vpn-apple/NymVPN/Resources/Localizable.xcstrings
Original file line number Diff line number Diff line change
Expand Up @@ -3528,6 +3528,28 @@
}
}
},
"censorship.quic.disable.alert.subtitle" : {
"extractionState" : "manual",
"localizations" : {
"en" : {
"stringUnit" : {
"state" : "translated",
"value" : "For changes to take effect, you need to reconnect."
}
}
}
},
"censorship.quic.disable.alert.title" : {
"extractionState" : "manual",
"localizations" : {
"en" : {
"stringUnit" : {
"state" : "translated",
"value" : "Are you sure you want to continue?"
}
}
}
},
"censorship.quic.link" : {
"extractionState" : "manual",
"localizations" : {
Expand Down Expand Up @@ -6570,13 +6592,13 @@
"de" : {
"stringUnit" : {
"state" : "new",
"value" : "Instead, you’re creating an account secured \u2028by a 24-word passphrase."
"value" : "Instead, you’re creating an account secured 
by a 24-word passphrase."
}
},
"en" : {
"stringUnit" : {
"state" : "translated",
"value" : "Instead, you’re creating an account secured \u2028by a 24-word passphrase."
"value" : "Instead, you’re creating an account secured 
by a 24-word passphrase."
}
},
"es" : {
Expand Down Expand Up @@ -6612,7 +6634,7 @@
"ja" : {
"stringUnit" : {
"state" : "new",
"value" : "Instead, you’re creating an account secured \u2028by a 24-word passphrase."
"value" : "Instead, you’re creating an account secured 
by a 24-word passphrase."
}
},
"pt" : {
Expand Down Expand Up @@ -18583,19 +18605,19 @@
"ar" : {
"stringUnit" : {
"state" : "new",
"value" : "NymVPN runs a background service (daemon) \u2028to keep your connection secure. It handles encryption and routing, protecting your activity even when the app is closed.\n\nFollow the steps below to install the daemon."
"value" : "NymVPN runs a background service (daemon) 
to keep your connection secure. It handles encryption and routing, protecting your activity even when the app is closed.\n\nFollow the steps below to install the daemon."
}
},
"de" : {
"stringUnit" : {
"state" : "new",
"value" : "NymVPN runs a background service (daemon) \u2028to keep your connection secure. It handles encryption and routing, protecting your activity even when the app is closed.\n\nFollow the steps below to install the daemon."
"value" : "NymVPN runs a background service (daemon) 
to keep your connection secure. It handles encryption and routing, protecting your activity even when the app is closed.\n\nFollow the steps below to install the daemon."
}
},
"en" : {
"stringUnit" : {
"state" : "translated",
"value" : "NymVPN runs a background service (daemon) \u2028to keep your connection secure. It handles encryption and routing, protecting your activity even when the app is closed.\n\nFollow the steps below to install the daemon."
"value" : "NymVPN runs a background service (daemon) 
to keep your connection secure. It handles encryption and routing, protecting your activity even when the app is closed.\n\nFollow the steps below to install the daemon."
}
},
"es" : {
Expand Down Expand Up @@ -18637,7 +18659,7 @@
"pt" : {
"stringUnit" : {
"state" : "new",
"value" : "NymVPN runs a background service (daemon) \u2028to keep your connection secure. It handles encryption and routing, protecting your activity even when the app is closed.\n\nFollow the steps below to install the daemon."
"value" : "NymVPN runs a background service (daemon) 
to keep your connection secure. It handles encryption and routing, protecting your activity even when the app is closed.\n\nFollow the steps below to install the daemon."
}
},
"pt-BR" : {
Expand Down Expand Up @@ -29503,7 +29525,7 @@
"en" : {
"stringUnit" : {
"state" : "translated",
"value" : "Retrieving your anonymous\u2028account credentials (zk-nyms)..."
"value" : "Retrieving your anonymous
account credentials (zk-nyms)..."
}
},
"es" : {
Expand All @@ -29515,7 +29537,7 @@
"fa" : {
"stringUnit" : {
"state" : "new",
"value" : "Retrieving your anonymous\u2028account credentials (zk-nyms)..."
"value" : "Retrieving your anonymous
account credentials (zk-nyms)..."
}
},
"fr" : {
Expand Down Expand Up @@ -29575,7 +29597,7 @@
"vi" : {
"stringUnit" : {
"state" : "new",
"value" : "Retrieving your anonymous\u2028account credentials (zk-nyms)..."
"value" : "Retrieving your anonymous
account credentials (zk-nyms)..."
}
},
"zh-Hans" : {
Expand Down Expand Up @@ -29604,7 +29626,7 @@
"en" : {
"stringUnit" : {
"state" : "translated",
"value" : "Saving your zk-nyms\u2028on the device..."
"value" : "Saving your zk-nyms
on the device..."
}
},
"es" : {
Expand All @@ -29616,7 +29638,7 @@
"fa" : {
"stringUnit" : {
"state" : "new",
"value" : "Saving your zk-nyms\u2028on the device..."
"value" : "Saving your zk-nyms
on the device..."
}
},
"fr" : {
Expand Down Expand Up @@ -29676,7 +29698,7 @@
"vi" : {
"stringUnit" : {
"state" : "new",
"value" : "Saving your zk-nyms\u2028on the device..."
"value" : "Saving your zk-nyms
on the device..."
}
},
"zh-Hans" : {
Expand Down Expand Up @@ -31404,6 +31426,17 @@
}
}
},
"reconnect" : {
"extractionState" : "manual",
"localizations" : {
"en" : {
"stringUnit" : {
"state" : "translated",
"value" : "Reconnect"
}
}
}
},
"retry" : {
"extractionState" : "manual",
"localizations" : {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,7 @@ extension ConnectionManager {

/// Sends connect command to lib if entry/exit gateways changed while connected,
/// to initiate reconnect
@MainActor func reconnectIfNeeded() async {
func reconnectIfNeeded() async {
do {
let newConfig = try generateConfig()
guard currentTunnelStatus == .connected || currentTunnelStatus == .connecting,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -171,6 +171,7 @@ private extension ConnectionManager {
#elseif os(macOS)
setupGRPCManagerObservers()
#endif
setupAppSettingsObservers()
setupConnectionChangeObserver()
setupConnectionErrorObserver()
configureConnectedTimeTimer()
Expand Down Expand Up @@ -211,8 +212,19 @@ private extension ConnectionManager {
// MARK: - Countries -

private extension ConnectionManager {
func setupAppSettingsObservers() {
appSettings.$isQuicEnabledPublisher
.removeDuplicates()
.sink { [weak self] value in
self?.connectionConfig?.enableBridges = value
self?.updateConnectionConfig()
}
.store(in: &cancellables)
}

func setupConnectionChangeObserver() {
$connectionType.sink { [weak self] _ in
$connectionType
.sink { [weak self] _ in
self?.updateCountries()
}
.store(in: &cancellables)
Expand Down
Loading