Don't block while countries are loading

pull/203/head
nielsandriesse 5 years ago
parent 58a911c9a6
commit 887eaf3ada

@ -4,14 +4,14 @@ final class IP2Country {
private let ipv4Table = try! CSV(name: "GeoLite2-Country-Blocks-IPv4", extension: "csv", bundle: .main, delimiter: ",", encoding: .utf8, loadColumns: true)! private let ipv4Table = try! CSV(name: "GeoLite2-Country-Blocks-IPv4", extension: "csv", bundle: .main, delimiter: ",", encoding: .utf8, loadColumns: true)!
private let countryNamesTable = try! CSV(name: "GeoLite2-Country-Locations-English", extension: "csv", bundle: .main, delimiter: ",", encoding: .utf8, loadColumns: true)! private let countryNamesTable = try! CSV(name: "GeoLite2-Country-Locations-English", extension: "csv", bundle: .main, delimiter: ",", encoding: .utf8, loadColumns: true)!
private var countryNamesCache: [String:String] = [:] var countryNamesCache: [String:String] = [:]
// MARK: Lifecycle // MARK: Lifecycle
static let shared = IP2Country() static let shared = IP2Country()
private init() { private init() {
preloadCountriesIfNeeded() populateCacheIfNeeded()
NotificationCenter.default.addObserver(self, selector: #selector(preloadCountriesIfNeeded), name: .pathsBuilt, object: nil) NotificationCenter.default.addObserver(self, selector: #selector(populateCacheIfNeeded), name: .pathsBuilt, object: nil)
} }
deinit { deinit {
@ -19,7 +19,7 @@ final class IP2Country {
} }
// MARK: Implementation // MARK: Implementation
func getCountry(_ ip: String) -> String { private func cacheCountry(for ip: String) -> String {
var truncatedIP = ip var truncatedIP = ip
func getCountryInternal() -> String { func getCountryInternal() -> String {
if let country = countryNamesCache[ip] { return country } if let country = countryNamesCache[ip] { return country }
@ -42,7 +42,7 @@ final class IP2Country {
return getCountryInternal() return getCountryInternal()
} }
@objc private func preloadCountriesIfNeeded() { @objc private func populateCacheIfNeeded() {
DispatchQueue.global(qos: .userInitiated).async { DispatchQueue.global(qos: .userInitiated).async {
if OnionRequestAPI.paths.count < OnionRequestAPI.pathCount { if OnionRequestAPI.paths.count < OnionRequestAPI.pathCount {
let storage = OWSPrimaryStorage.shared() let storage = OWSPrimaryStorage.shared()
@ -53,7 +53,10 @@ final class IP2Country {
guard OnionRequestAPI.paths.count >= OnionRequestAPI.pathCount else { return } guard OnionRequestAPI.paths.count >= OnionRequestAPI.pathCount else { return }
let pathToDisplay = OnionRequestAPI.paths.first! let pathToDisplay = OnionRequestAPI.paths.first!
pathToDisplay.forEach { snode in pathToDisplay.forEach { snode in
let _ = self.getCountry(snode.ip) // Preload if needed let _ = self.cacheCountry(for: snode.ip) // Preload if needed
}
DispatchQueue.main.async {
NotificationCenter.default.post(name: .onionRequestPathCountriesLoaded, object: nil)
} }
print("[Loki] Finished preloading onion request path countries.") print("[Loki] Finished preloading onion request path countries.")
} }

@ -92,6 +92,7 @@ final class PathVC : BaseVC {
let notificationCenter = NotificationCenter.default let notificationCenter = NotificationCenter.default
notificationCenter.addObserver(self, selector: #selector(handleBuildingPathsNotification), name: .buildingPaths, object: nil) notificationCenter.addObserver(self, selector: #selector(handleBuildingPathsNotification), name: .buildingPaths, object: nil)
notificationCenter.addObserver(self, selector: #selector(handlePathsBuiltNotification), name: .pathsBuilt, object: nil) notificationCenter.addObserver(self, selector: #selector(handlePathsBuiltNotification), name: .pathsBuilt, object: nil)
notificationCenter.addObserver(self, selector: #selector(handleOnionRequestPathCountriesLoadedNotification), name: .onionRequestPathCountriesLoaded, object: nil)
} }
deinit { deinit {
@ -101,6 +102,7 @@ final class PathVC : BaseVC {
// MARK: Updating // MARK: Updating
@objc private func handleBuildingPathsNotification() { update() } @objc private func handleBuildingPathsNotification() { update() }
@objc private func handlePathsBuiltNotification() { update() } @objc private func handlePathsBuiltNotification() { update() }
@objc private func handleOnionRequestPathCountriesLoadedNotification() { update() }
private func update() { private func update() {
pathStackView.arrangedSubviews.forEach { $0.removeFromSuperview() } pathStackView.arrangedSubviews.forEach { $0.removeFromSuperview() }
@ -155,7 +157,7 @@ final class PathVC : BaseVC {
} }
private func getPathRow(snode: LokiAPITarget, location: LineView.Location, dotAnimationStartDelay: Double, dotAnimationRepeatInterval: Double, isGuardSnode: Bool) -> UIStackView { private func getPathRow(snode: LokiAPITarget, location: LineView.Location, dotAnimationStartDelay: Double, dotAnimationRepeatInterval: Double, isGuardSnode: Bool) -> UIStackView {
let country = IP2Country.shared.getCountry(snode.ip) let country = IP2Country.shared.countryNamesCache[snode.ip] ?? "Resolving..."
let title = isGuardSnode ? NSLocalizedString("Guard Node", comment: "") : NSLocalizedString("Service Node", comment: "") let title = isGuardSnode ? NSLocalizedString("Guard Node", comment: "") : NSLocalizedString("Service Node", comment: "")
return getPathRow(title: title, subtitle: country, location: location, dotAnimationStartDelay: dotAnimationStartDelay, dotAnimationRepeatInterval: dotAnimationRepeatInterval) return getPathRow(title: title, subtitle: country, location: location, dotAnimationStartDelay: dotAnimationStartDelay, dotAnimationRepeatInterval: dotAnimationRepeatInterval)
} }

@ -23,6 +23,7 @@ public extension Notification.Name {
// Onion requests // Onion requests
public static let buildingPaths = Notification.Name("buildingPaths") public static let buildingPaths = Notification.Name("buildingPaths")
public static let pathsBuilt = Notification.Name("pathsBuilt") public static let pathsBuilt = Notification.Name("pathsBuilt")
public static let onionRequestPathCountriesLoaded = Notification.Name("onionRequestPathCountriesLoaded")
} }
@objc public extension NSNotification { @objc public extension NSNotification {
@ -49,4 +50,5 @@ public extension Notification.Name {
// Onion requests // Onion requests
@objc public static let buildingPaths = Notification.Name.buildingPaths.rawValue as NSString @objc public static let buildingPaths = Notification.Name.buildingPaths.rawValue as NSString
@objc public static let pathsBuilt = Notification.Name.pathsBuilt.rawValue as NSString @objc public static let pathsBuilt = Notification.Name.pathsBuilt.rawValue as NSString
@objc public static let onionRequestPathCountriesLoaded = Notification.Name.onionRequestPathCountriesLoaded.rawValue as NSString
} }

Loading…
Cancel
Save