Skip to content

Commit

Permalink
feat: moved widget activation threshold slider to the input with a ba…
Browse files Browse the repository at this point in the history
…se that allows specifying the threshold more accurate
  • Loading branch information
exelban committed Apr 30, 2024
1 parent d5d70a2 commit c37585d
Show file tree
Hide file tree
Showing 3 changed files with 69 additions and 31 deletions.
25 changes: 16 additions & 9 deletions Modules/Net/main.swift
Original file line number Diff line number Diff line change
Expand Up @@ -135,8 +135,14 @@ public class Network: Module {
private let ipUpdater = NSBackgroundActivityScheduler(identifier: "eu.exelban.Stats.Network.IP")
private let usageReseter = NSBackgroundActivityScheduler(identifier: "eu.exelban.Stats.Network.Usage")

private var widgetActivationThresholdState: Bool {
Store.shared.bool(key: "\(self.config.name)_widgetActivationThresholdState", defaultValue: false)
}
private var widgetActivationThreshold: Int {
Store.shared.int(key: "\(self.config.name)_widgetActivationThreshold", defaultValue: 0) * 1_024
Store.shared.int(key: "\(self.config.name)_widgetActivationThreshold", defaultValue: 0)
}
private var widgetActivationThresholdSize: SizeUnit {
SizeUnit.fromString(Store.shared.string(key: "\(self.name)_widgetActivationThresholdSize", defaultValue: SizeUnit.MB.key))
}
private var publicIPRefreshInterval: String {
Store.shared.string(key: "\(self.name)_publicIPRefreshInterval", defaultValue: "never")
Expand Down Expand Up @@ -212,11 +218,14 @@ public class Network: Module {
self.popupView.usageCallback(value)
self.portalView.usageCallback(value)

var upload: Int64 = 0
var download: Int64 = 0
if value.bandwidth.upload >= self.widgetActivationThreshold || value.bandwidth.download >= self.widgetActivationThreshold {
upload = value.bandwidth.upload
download = value.bandwidth.download
var upload: Int64 = value.bandwidth.upload
var download: Int64 = value.bandwidth.download
if self.widgetActivationThresholdState {
let threshold = self.widgetActivationThresholdSize.toBytes(self.widgetActivationThreshold)
if value.bandwidth.upload >= threshold || value.bandwidth.download >= threshold {
upload = 0
download = 0
}
}

self.menuBar.widgets.filter{ $0.isActive }.forEach { (w: Widget) in
Expand Down Expand Up @@ -256,9 +265,7 @@ public class Network: Module {

self.ipUpdater.repeats = true
self.ipUpdater.schedule { (completion: @escaping NSBackgroundActivityScheduler.CompletionHandler) in
guard self.enabled && self.isAvailable() else {
return
}
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)
Expand Down
11 changes: 9 additions & 2 deletions Modules/Net/portal.swift
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,12 @@ public class Portal: PortalWrapper {
private var chartScale: Scale {
Scale.fromString(Store.shared.string(key: "\(self.name)_chartScale", defaultValue: Scale.none.key))
}
private var chartFixedScale: Int {
Store.shared.int(key: "\(self.name)_chartFixedScale", defaultValue: 12)
}
private var chartFixedScaleSize: SizeUnit {
SizeUnit.fromString(Store.shared.string(key: "\(self.name)_chartFixedScaleSize", defaultValue: SizeUnit.MB.key))
}

private var downloadColor: NSColor {
let v = Color.fromString(Store.shared.string(key: "\(self.name)_downloadColor", defaultValue: Color.secondBlue.key))
Expand Down Expand Up @@ -68,7 +74,8 @@ public class Portal: PortalWrapper {
reversedOrder: self.reverseOrderState,
outColor: self.uploadColor,
inColor: self.downloadColor,
scale: self.chartScale
scale: self.chartScale,
fixedScale: Double(self.chartFixedScaleSize.toBytes(self.chartFixedScale))
)
chart.base = self.base
container.addSubview(chart)
Expand All @@ -88,7 +95,7 @@ public class Portal: PortalWrapper {
chart.base = self.base
}
chart.addValue(upload: Double(value.bandwidth.upload), download: Double(value.bandwidth.download))
chart.setScale(self.chartScale, 1)
chart.setScale(self.chartScale, Double(self.chartFixedScaleSize.toBytes(self.chartFixedScale)))
chart.setColors(in: self.downloadColor, out: self.uploadColor)
}

Expand Down
64 changes: 44 additions & 20 deletions Modules/Net/settings.swift
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,9 @@ internal class Settings: NSStackView, Settings_v, NSTextFieldDelegate {
private var readerType: String = "interface"
private var usageReset: String = AppUpdateInterval.atStart.rawValue
private var VPNModeState: Bool = false
private var widgetActivationThresholdState: Bool = false
private var widgetActivationThreshold: Int = 0
private var widgetActivationThresholdSize: SizeUnit = .MB
private var ICMPHost: String = "1.1.1.1"
private var publicIPRefreshInterval: String = "never"
private var baseValue: String = "byte"
Expand All @@ -32,6 +34,7 @@ internal class Settings: NSStackView, Settings_v, NSTextFieldDelegate {
private let title: String
private var sliderView: NSView? = nil
private var section: PreferencesSection? = nil
private var widgetThresholdSection: PreferencesSection? = nil

private var list: [Network_interface] = []

Expand All @@ -48,7 +51,9 @@ internal class Settings: NSStackView, Settings_v, NSTextFieldDelegate {
self.readerType = Store.shared.string(key: "\(self.title)_reader", defaultValue: self.readerType)
self.usageReset = Store.shared.string(key: "\(self.title)_usageReset", defaultValue: self.usageReset)
self.VPNModeState = Store.shared.bool(key: "\(self.title)_VPNMode", defaultValue: self.VPNModeState)
self.widgetActivationThresholdState = Store.shared.bool(key: "\(self.title)_widgetActivationThresholdState", defaultValue: self.widgetActivationThresholdState)
self.widgetActivationThreshold = Store.shared.int(key: "\(self.title)_widgetActivationThreshold", defaultValue: self.widgetActivationThreshold)
self.widgetActivationThresholdSize = SizeUnit.fromString(Store.shared.string(key: "\(self.title)_widgetActivationThresholdSize", defaultValue: self.widgetActivationThresholdSize.key))
self.ICMPHost = Store.shared.string(key: "\(self.title)_ICMPHost", defaultValue: self.ICMPHost)
self.publicIPRefreshInterval = Store.shared.string(key: "\(self.title)_publicIPRefreshInterval", defaultValue: self.publicIPRefreshInterval)
self.baseValue = Store.shared.string(key: "\(self.title)_base", defaultValue: self.baseValue)
Expand Down Expand Up @@ -140,26 +145,37 @@ internal class Settings: NSStackView, Settings_v, NSTextFieldDelegate {
self.addArrangedSubview(section)
self.section = section

self.sliderView = sliderView(
action: #selector(self.sliderCallback),
value: self.widgetActivationThreshold,
initialValue: self.widgetActivationThreshold != 0 ? "\(self.widgetActivationThreshold) KB" : localizedString("Disabled"),
min: 0,
max: 1024,
valueWidth: 70
)
self.addArrangedSubview(PreferencesSection([
PreferencesRow(localizedString("Widget activation threshold"), component: self.sliderView!)
]))
self.widgetThresholdSection = PreferencesSection([
PreferencesRow(localizedString("Widget activation threshold"), component: switchView(
action: #selector(self.toggleWidgetActivationThreshold),
state: self.widgetActivationThresholdState
)),
PreferencesRow(localizedString("Value"), component: {
let view: NSStackView = NSStackView()
view.orientation = .horizontal
view.spacing = 2
let valueField = StepperInput(self.widgetActivationThreshold, range: NSRange(location: 1, length: 1023))
valueField.callback = self.changeWidgetActivationThreshold
valueField.widthAnchor.constraint(equalToConstant: 80).isActive = true
view.addArrangedSubview(NSView())
view.addArrangedSubview(valueField)
view.addArrangedSubview(selectView(
action: #selector(self.toggleWidgetActivationThresholdSize),
items: SizeUnit.allCases,
selected: self.widgetActivationThresholdSize.key
))
return view
}())
])
self.addArrangedSubview(self.widgetThresholdSection!)
self.widgetThresholdSection?.toggleVisibility(1, newState: self.widgetActivationThresholdState)

let valueField: NSTextField = NSTextField()
valueField.widthAnchor.constraint(equalToConstant: 250).isActive = true
valueField.font = NSFont.systemFont(ofSize: 12, weight: .regular)
valueField.textColor = .textColor
valueField.isEditable = true
valueField.isSelectable = true
valueField.isBezeled = false
valueField.canDrawSubviewsIntoLayer = true
valueField.usesSingleLineMode = true
valueField.maximumNumberOfLines = 1
valueField.focusRingType = .none
Expand Down Expand Up @@ -209,13 +225,21 @@ internal class Settings: NSStackView, Settings_v, NSTextFieldDelegate {
self.VPNModeState = controlState(sender)
Store.shared.set(key: "\(self.title)_VPNMode", value: self.VPNModeState)
}
@objc private func sliderCallback(_ sender: NSSlider) {
let value = Int(sender.doubleValue)
if let field = self.sliderView?.subviews.first(where: { $0 is NSTextField }), let view = field as? NSTextField {
view.stringValue = value == 0 ? localizedString("Disabled") : "\(value) KB"
}
self.widgetActivationThreshold = value
Store.shared.set(key: "\(self.title)_widgetActivationThreshold", value: self.widgetActivationThreshold)
@objc func toggleWidgetActivationThreshold(_ sender: NSControl) {
self.widgetActivationThresholdState = controlState(sender)
Store.shared.set(key: "\(self.title)_widgetActivationThresholdState", value: self.widgetActivationThresholdState)
self.widgetThresholdSection?.toggleVisibility(1, newState: self.widgetActivationThresholdState)
}
@objc private func changeWidgetActivationThreshold(_ newValue: Int) {
self.widgetActivationThreshold = newValue
Store.shared.set(key: "\(self.title)_widgetActivationThreshold", value: newValue)
}
@objc private func toggleWidgetActivationThresholdSize(_ sender: NSMenuItem) {
guard let key = sender.representedObject as? String,
let value = SizeUnit.allCases.first(where: { $0.key == key }) else { return }
self.widgetActivationThresholdSize = value
Store.shared.set(key: "\(self.title)_widgetActivationThresholdSize", value: key)
self.display()
}

func controlTextDidChange(_ notification: Notification) {
Expand Down

0 comments on commit c37585d

Please sign in to comment.