diff --git a/.swiftlint.yml b/.swiftlint.yml index f6f81ef7..73be131d 100644 --- a/.swiftlint.yml +++ b/.swiftlint.yml @@ -36,6 +36,7 @@ identifier_name: - FanValues - CombinedModulesSpacings - BatteryInfo + - PublicIPAddressRefreshIntervals line_length: 200 diff --git a/Kit/types.swift b/Kit/types.swift index dd81a9ff..e9fa43a5 100644 --- a/Kit/types.swift +++ b/Kit/types.swift @@ -66,6 +66,14 @@ public let CombinedModulesSpacings: [KeyValue_t] = [ KeyValue_t(key: "8", value: "8", additional: 8) ] +public let PublicIPAddressRefreshIntervals: [KeyValue_t] = [ + KeyValue_t(key: "never", value: "Never"), + KeyValue_t(key: "separator", value: "separator"), + KeyValue_t(key: "hour", value: "Every hour"), + KeyValue_t(key: "12", value: "Every 12 hours"), + KeyValue_t(key: "24", value: "Every 24 hours") +] + public enum DataSizeBase: String { case bit case byte diff --git a/Modules/Net/main.swift b/Modules/Net/main.swift index 0b748ef5..19c4ac68 100644 --- a/Modules/Net/main.swift +++ b/Modules/Net/main.swift @@ -113,6 +113,9 @@ public class Network: Module { private var widgetActivationThreshold: Int { Store.shared.int(key: "\(self.config.name)_widgetActivationThreshold", defaultValue: 0) * 1_024 } + private var publicIPRefreshInterval: String { + Store.shared.string(key: "\(self.name)_publicIPRefreshInterval", defaultValue: "never") + } public init() { self.settingsView = Settings("Network") @@ -167,6 +170,9 @@ public class Network: Module { self.connectivityCallback(false) } } + self.settingsView.publicIPRefreshIntervalCallback = { [unowned self] in + self.setIPUpdater() + } if let reader = self.usageReader { self.addReader(reader) @@ -230,13 +236,23 @@ public class Network: Module { } private func setIPUpdater() { - self.ipUpdater.interval = 60 * 60 + self.ipUpdater.invalidate() + + switch self.publicIPRefreshInterval { + case "hour": + self.ipUpdater.interval = 60 * 60 + case "12": + self.ipUpdater.interval = 60 * 60 * 12 + case "24": + self.ipUpdater.interval = 60 * 60 * 24 + default: return + } + self.ipUpdater.repeats = true self.ipUpdater.schedule { (completion: @escaping NSBackgroundActivityScheduler.CompletionHandler) in guard self.enabled && self.isAvailable() else { return } - debug("going to automatically refresh IP address...") NotificationCenter.default.post(name: .refreshPublicIP, object: nil, userInfo: nil) completion(NSBackgroundActivityScheduler.Result.finished) diff --git a/Modules/Net/settings.swift b/Modules/Net/settings.swift index cf2924d9..a425ad80 100644 --- a/Modules/Net/settings.swift +++ b/Modules/Net/settings.swift @@ -20,11 +20,13 @@ internal class Settings: NSStackView, Settings_v, NSTextFieldDelegate { private var VPNModeState: Bool = false private var widgetActivationThreshold: Int = 0 private var ICMPHost: String = "1.1.1.1" + private var publicIPRefreshInterval: String = "never" public var callback: (() -> Void) = {} public var callbackWhenUpdateNumberOfProcesses: (() -> Void) = {} public var usageResetCallback: (() -> Void) = {} public var ICMPHostCallback: ((_ newState: Bool) -> Void) = { _ in } + public var publicIPRefreshIntervalCallback: (() -> Void) = {} private let title: String private var button: NSPopUpButton? @@ -47,6 +49,7 @@ internal class Settings: NSStackView, Settings_v, NSTextFieldDelegate { self.VPNModeState = Store.shared.bool(key: "\(self.title)_VPNMode", defaultValue: self.VPNModeState) self.widgetActivationThreshold = Store.shared.int(key: "\(self.title)_widgetActivationThreshold", defaultValue: self.widgetActivationThreshold) self.ICMPHost = Store.shared.string(key: "\(self.title)_ICMPHost", defaultValue: self.ICMPHost) + self.publicIPRefreshInterval = Store.shared.string(key: "\(self.title)_publicIPRefreshInterval", defaultValue: self.publicIPRefreshInterval) super.init(frame: NSRect(x: 0, y: 0, width: 0, height: 0)) @@ -98,6 +101,13 @@ internal class Settings: NSStackView, Settings_v, NSTextFieldDelegate { selected: self.readerType )) + self.addArrangedSubview(selectSettingsRow( + title: localizedString("Auto-refresh public IP address"), + action: #selector(toggleRefreshIPInterval), + items: PublicIPAddressRefreshIntervals, + selected: self.publicIPRefreshInterval + )) + self.addArrangedSubview(self.interfaceSelector()) if self.vpnConnection { @@ -273,9 +283,7 @@ internal class Settings: NSStackView, Settings_v, NSTextFieldDelegate { } @objc private func changeReaderType(_ sender: NSMenuItem) { - guard let key = sender.representedObject as? String else { - return - } + guard let key = sender.representedObject as? String else { return } self.readerType = key Store.shared.set(key: "\(self.title)_reader", value: key) self.button?.isEnabled = self.readerType == "interface" @@ -284,23 +292,14 @@ internal class Settings: NSStackView, Settings_v, NSTextFieldDelegate { } @objc private func toggleUsageReset(_ sender: NSMenuItem) { - guard let key = sender.representedObject as? String else { - return - } + guard let key = sender.representedObject as? String else { return } self.usageReset = key Store.shared.set(key: "\(self.title)_usageReset", value: key) self.usageResetCallback() } @objc func toggleVPNMode(_ sender: NSControl) { - var state: NSControl.StateValue? = nil - if #available(OSX 10.15, *) { - state = sender is NSSwitch ? (sender as! NSSwitch).state: nil - } else { - state = sender is NSButton ? (sender as! NSButton).state: nil - } - - self.VPNModeState = state! == .on ? true : false + self.VPNModeState = controlState(sender) Store.shared.set(key: "\(self.title)_VPNMode", value: self.VPNModeState) } @@ -314,7 +313,7 @@ internal class Settings: NSStackView, Settings_v, NSTextFieldDelegate { valueField.stringValue = "\(value) KB" } self.widgetActivationThreshold = value - Store.shared.set(key: "\(self.title)_widgetActivationThreshold", value: widgetActivationThreshold) + Store.shared.set(key: "\(self.title)_widgetActivationThreshold", value: self.widgetActivationThreshold) } func controlTextDidChange(_ notification: Notification) { @@ -324,4 +323,11 @@ internal class Settings: NSStackView, Settings_v, NSTextFieldDelegate { self.ICMPHostCallback(self.ICMPHost.isEmpty) } } + + @objc private func toggleRefreshIPInterval(_ sender: NSMenuItem) { + guard let key = sender.representedObject as? String else { return } + self.publicIPRefreshInterval = key + Store.shared.set(key: "\(self.title)_publicIPRefreshInterval", value: self.publicIPRefreshInterval) + self.publicIPRefreshIntervalCallback() + } }