Don't block while countries are loading

This commit is contained in:
nielsandriesse 2020-06-02 16:10:23 +10:00
parent 58a911c9a6
commit 887eaf3ada
3 changed files with 14 additions and 7 deletions

View file

@ -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 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
static let shared = IP2Country()
private init() {
preloadCountriesIfNeeded()
NotificationCenter.default.addObserver(self, selector: #selector(preloadCountriesIfNeeded), name: .pathsBuilt, object: nil)
populateCacheIfNeeded()
NotificationCenter.default.addObserver(self, selector: #selector(populateCacheIfNeeded), name: .pathsBuilt, object: nil)
}
deinit {
@ -19,7 +19,7 @@ final class IP2Country {
}
// MARK: Implementation
func getCountry(_ ip: String) -> String {
private func cacheCountry(for ip: String) -> String {
var truncatedIP = ip
func getCountryInternal() -> String {
if let country = countryNamesCache[ip] { return country }
@ -42,7 +42,7 @@ final class IP2Country {
return getCountryInternal()
}
@objc private func preloadCountriesIfNeeded() {
@objc private func populateCacheIfNeeded() {
DispatchQueue.global(qos: .userInitiated).async {
if OnionRequestAPI.paths.count < OnionRequestAPI.pathCount {
let storage = OWSPrimaryStorage.shared()
@ -53,7 +53,10 @@ final class IP2Country {
guard OnionRequestAPI.paths.count >= OnionRequestAPI.pathCount else { return }
let pathToDisplay = OnionRequestAPI.paths.first!
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.")
}

View file

@ -92,6 +92,7 @@ final class PathVC : BaseVC {
let notificationCenter = NotificationCenter.default
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(handleOnionRequestPathCountriesLoadedNotification), name: .onionRequestPathCountriesLoaded, object: nil)
}
deinit {
@ -101,6 +102,7 @@ final class PathVC : BaseVC {
// MARK: Updating
@objc private func handleBuildingPathsNotification() { update() }
@objc private func handlePathsBuiltNotification() { update() }
@objc private func handleOnionRequestPathCountriesLoadedNotification() { update() }
private func update() {
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 {
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: "")
return getPathRow(title: title, subtitle: country, location: location, dotAnimationStartDelay: dotAnimationStartDelay, dotAnimationRepeatInterval: dotAnimationRepeatInterval)
}

View file

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