mirror of
https://github.com/morgan9e/macos-stats
synced 2026-04-14 00:04:15 +09:00
feat: small codebase refactoring (mostly removed unused code and changes in access control)
This commit is contained in:
@@ -24,7 +24,7 @@ public class BatteryWidget: WidgetWrapper {
|
||||
private var _ACStatus: Bool = false
|
||||
private var _optimizedCharging: Bool = false
|
||||
|
||||
public init(title: String, config: NSDictionary?, preview: Bool = false) {
|
||||
public init(title: String, preview: Bool = false) {
|
||||
let widgetTitle: String = title
|
||||
|
||||
super.init(.battery, title: widgetTitle, frame: CGRect(
|
||||
@@ -449,7 +449,7 @@ public class BatteryDetailsWidget: WidgetWrapper {
|
||||
private var percentage: Double? = nil
|
||||
private var time: Int = 0
|
||||
|
||||
public init(title: String, config: NSDictionary?, preview: Bool = false) {
|
||||
public init(title: String, preview: Bool = false) {
|
||||
super.init(.batteryDetails, title: title, frame: CGRect(
|
||||
x: Constants.Widget.margin.x,
|
||||
y: Constants.Widget.margin.y,
|
||||
|
||||
@@ -11,10 +11,10 @@
|
||||
|
||||
import Cocoa
|
||||
|
||||
public class Label: WidgetWrapper {
|
||||
internal class Label: WidgetWrapper {
|
||||
private var label: String
|
||||
|
||||
public init(title: String, config: NSDictionary, preview: Bool = false) {
|
||||
internal init(title: String, config: NSDictionary) {
|
||||
if let title = config["Title"] as? String {
|
||||
self.label = title
|
||||
} else {
|
||||
@@ -56,12 +56,4 @@ public class Label: WidgetWrapper {
|
||||
margin.y += size.height
|
||||
}
|
||||
}
|
||||
|
||||
public func setLabel(_ new: String) {
|
||||
guard self.label != new else { return }
|
||||
self.label = new
|
||||
DispatchQueue.main.async(execute: {
|
||||
self.needsDisplay = true
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,10 +16,6 @@ public class Mini: WidgetWrapper {
|
||||
private var colorState: Color = .monochrome
|
||||
private var alignmentState: String = "left"
|
||||
|
||||
private var labelLayer: CATextLayer? = nil
|
||||
private var valueLayer: CATextLayer? = nil
|
||||
|
||||
private let onlyValueWidth: CGFloat = 40
|
||||
private var colors: [Color] = Color.allCases
|
||||
|
||||
private var _value: Double = 0
|
||||
|
||||
@@ -13,7 +13,6 @@ import Cocoa
|
||||
|
||||
public class SpeedWidget: WidgetWrapper {
|
||||
private var icon: String = "dots"
|
||||
private var state: Bool = false
|
||||
private var valueState: Bool = true
|
||||
private var unitsState: Bool = true
|
||||
private var monochromeState: Bool = false
|
||||
@@ -28,9 +27,6 @@ public class SpeedWidget: WidgetWrapper {
|
||||
|
||||
private var symbols: [String] = ["U", "D"]
|
||||
|
||||
private var uploadField: NSTextField? = nil
|
||||
private var downloadField: NSTextField? = nil
|
||||
|
||||
private var uploadValue: Int64 = 0
|
||||
private var downloadValue: Int64 = 0
|
||||
|
||||
@@ -91,10 +87,6 @@ public class SpeedWidget: WidgetWrapper {
|
||||
self.reverseOrderState = Store.shared.bool(key: "\(self.title)_\(self.type.rawValue)_reverseOrder", defaultValue: self.reverseOrderState)
|
||||
}
|
||||
|
||||
if self.valueState && self.icon != "none" {
|
||||
self.state = true
|
||||
}
|
||||
|
||||
if preview {
|
||||
self.downloadValue = 8947141
|
||||
self.uploadValue = 478678
|
||||
@@ -111,9 +103,9 @@ public class SpeedWidget: WidgetWrapper {
|
||||
var width: CGFloat = 0
|
||||
switch self.modeState {
|
||||
case "oneRow":
|
||||
width = self.drawOneRow(dirtyRect)
|
||||
width = self.drawOneRow()
|
||||
case "twoRows":
|
||||
width = self.drawTwoRows(dirtyRect)
|
||||
width = self.drawTwoRows()
|
||||
default:
|
||||
width = 0
|
||||
}
|
||||
@@ -123,7 +115,7 @@ public class SpeedWidget: WidgetWrapper {
|
||||
|
||||
// MARK: - one row
|
||||
|
||||
private func drawOneRow(_ dirtyRect: NSRect) -> CGFloat {
|
||||
private func drawOneRow() -> CGFloat {
|
||||
var width: CGFloat = Constants.Widget.margin.x
|
||||
let downloadIconColor = self.downloadValue >= 1_024 ? self.downloadColor : self.noActivityColor
|
||||
let uploadIconColor = self.uploadValue >= 1_024 ? self.uploadColor : self.noActivityColor
|
||||
@@ -279,17 +271,17 @@ public class SpeedWidget: WidgetWrapper {
|
||||
|
||||
// MARK: - two rows
|
||||
|
||||
private func drawTwoRows(_ dirtyRect: NSRect) -> CGFloat {
|
||||
private func drawTwoRows() -> CGFloat {
|
||||
var width: CGFloat = 7
|
||||
var x: CGFloat = 7
|
||||
|
||||
switch self.icon {
|
||||
case "dots":
|
||||
self.drawDots(dirtyRect)
|
||||
self.drawDots()
|
||||
case "arrows":
|
||||
self.drawArrows(dirtyRect)
|
||||
self.drawArrows()
|
||||
case "chars":
|
||||
self.drawChars(dirtyRect)
|
||||
self.drawChars()
|
||||
default:
|
||||
x = 0
|
||||
width = 0
|
||||
@@ -335,7 +327,7 @@ public class SpeedWidget: WidgetWrapper {
|
||||
return width
|
||||
}
|
||||
|
||||
private func drawDots(_ dirtyRect: NSRect) {
|
||||
private func drawDots() {
|
||||
let rowHeight: CGFloat = self.frame.height / 2
|
||||
let size: CGFloat = 6
|
||||
let y: CGFloat = (rowHeight-size)/2
|
||||
@@ -353,7 +345,7 @@ public class SpeedWidget: WidgetWrapper {
|
||||
uploadCircle.fill()
|
||||
}
|
||||
|
||||
private func drawArrows(_ dirtyRect: NSRect) {
|
||||
private func drawArrows() {
|
||||
let arrowAngle = CGFloat(Double.pi / 5)
|
||||
let half = self.frame.size.height / 2
|
||||
let scaleFactor = NSScreen.main?.backingScaleFactor ?? 1
|
||||
@@ -394,7 +386,7 @@ public class SpeedWidget: WidgetWrapper {
|
||||
uploadArrow.close()
|
||||
}
|
||||
|
||||
private func drawChars(_ dirtyRect: NSRect) {
|
||||
private func drawChars() {
|
||||
let rowHeight: CGFloat = self.frame.height / 2
|
||||
let downloadY: CGFloat = self.reverseOrderState ? rowHeight+1 : 1
|
||||
let uploadY: CGFloat = self.reverseOrderState ? 1 : rowHeight+1
|
||||
|
||||
@@ -14,7 +14,6 @@ import Cocoa
|
||||
public struct Stack_t: KeyValue_p {
|
||||
public var key: String
|
||||
public var value: String
|
||||
public var additional: Any?
|
||||
|
||||
var index: Int {
|
||||
get {
|
||||
@@ -25,10 +24,9 @@ public struct Stack_t: KeyValue_p {
|
||||
}
|
||||
}
|
||||
|
||||
public init(key: String, value: String, additional: Any? = nil) {
|
||||
public init(key: String, value: String) {
|
||||
self.key = key
|
||||
self.value = value
|
||||
self.additional = additional
|
||||
}
|
||||
}
|
||||
|
||||
@@ -280,7 +278,7 @@ private class OrderTableView: NSView, NSTableViewDelegate, NSTableViewDataSource
|
||||
private let tableView = NSTableView()
|
||||
private var dragDropType = NSPasteboard.PasteboardType(rawValue: "\(Bundle.main.bundleIdentifier!).sensors-row")
|
||||
|
||||
public var reorderCallback: () -> Void = {}
|
||||
fileprivate var reorderCallback: () -> Void = {}
|
||||
private let list: UnsafeMutablePointer<[Stack_t]>
|
||||
|
||||
init(_ list: UnsafeMutablePointer<[Stack_t]>) {
|
||||
@@ -334,7 +332,7 @@ private class OrderTableView: NSView, NSTableViewDelegate, NSTableViewDataSource
|
||||
NotificationCenter.default.removeObserver(self)
|
||||
}
|
||||
|
||||
public func update() {
|
||||
fileprivate func update() {
|
||||
self.tableView.reloadData()
|
||||
}
|
||||
|
||||
|
||||
@@ -27,7 +27,7 @@ public class Tachometer: WidgetWrapper {
|
||||
|
||||
private let size: CGFloat = Constants.Widget.height - (Constants.Widget.margin.y*2) + (Constants.Widget.margin.x*2)
|
||||
|
||||
public init(title: String, config: NSDictionary?, preview: Bool = false) {
|
||||
public init(title: String, preview: Bool = false) {
|
||||
let widgetTitle: String = title
|
||||
|
||||
super.init(.tachometer, title: widgetTitle, frame: CGRect(
|
||||
|
||||
@@ -24,17 +24,6 @@ extension String: LocalizedError {
|
||||
return size.width
|
||||
}
|
||||
|
||||
public func heightOfString(usingFont font: NSFont) -> CGFloat {
|
||||
let fontAttributes = [NSAttributedString.Key.font: font]
|
||||
let size = self.size(withAttributes: fontAttributes)
|
||||
return size.height
|
||||
}
|
||||
|
||||
public func sizeOfString(usingFont font: NSFont) -> CGSize {
|
||||
let fontAttributes = [NSAttributedString.Key.font: font]
|
||||
return self.size(withAttributes: fontAttributes)
|
||||
}
|
||||
|
||||
public func condenseWhitespace() -> String {
|
||||
let components = self.components(separatedBy: .whitespacesAndNewlines)
|
||||
return components.filter { !$0.isEmpty }.joined(separator: " ")
|
||||
@@ -162,21 +151,6 @@ public extension Double {
|
||||
}
|
||||
}
|
||||
|
||||
func percentageColor(color: Bool) -> NSColor {
|
||||
if !color {
|
||||
return NSColor.textColor
|
||||
}
|
||||
|
||||
switch self {
|
||||
case 0.6...0.8:
|
||||
return NSColor.systemOrange
|
||||
case 0.8...1:
|
||||
return NSColor.systemRed
|
||||
default:
|
||||
return NSColor.systemGreen
|
||||
}
|
||||
}
|
||||
|
||||
func batteryColor(color: Bool = false, lowPowerMode: Bool? = nil) -> NSColor {
|
||||
if let mode = lowPowerMode, mode {
|
||||
return NSColor.systemOrange
|
||||
@@ -442,17 +416,6 @@ public extension NSColor {
|
||||
}
|
||||
}
|
||||
|
||||
public extension CATransaction {
|
||||
static func disableAnimations(_ closure: () -> Void) {
|
||||
CATransaction.begin()
|
||||
CATransaction.setDisableActions(true)
|
||||
CATransaction.setValue(kCFBooleanTrue, forKey: kCATransactionDisableActions)
|
||||
CATransaction.setAnimationDuration(0)
|
||||
closure()
|
||||
CATransaction.commit()
|
||||
}
|
||||
}
|
||||
|
||||
public class FlippedStackView: NSStackView {
|
||||
public override var isFlipped: Bool { return true }
|
||||
}
|
||||
@@ -550,9 +513,6 @@ public extension Data {
|
||||
var socketAddress: sockaddr {
|
||||
return withUnsafeBytes { $0.load(as: sockaddr.self) }
|
||||
}
|
||||
var socketAddressInternet: sockaddr_in {
|
||||
return withUnsafeBytes { $0.load(as: sockaddr_in.self) }
|
||||
}
|
||||
}
|
||||
|
||||
public extension Date {
|
||||
|
||||
@@ -92,7 +92,6 @@ extension LaunchAtLogin: DeprecationWarningWorkaround {
|
||||
public protocol KeyValue_p {
|
||||
var key: String { get }
|
||||
var value: String { get }
|
||||
var additional: Any? { get }
|
||||
}
|
||||
|
||||
public struct KeyValue_t: KeyValue_p, Codable {
|
||||
@@ -431,15 +430,6 @@ public func portalWithColorRow(_ v: NSStackView, color: NSColor, title: String)
|
||||
return (colorView, valueView)
|
||||
}
|
||||
|
||||
public extension Array where Element: Equatable {
|
||||
func allEqual() -> Bool {
|
||||
if let firstElem = first {
|
||||
return !dropFirst().contains { $0 != firstElem }
|
||||
}
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
public extension Array where Element: Hashable {
|
||||
func difference(from other: [Element]) -> [Element] {
|
||||
let thisSet = Set(self)
|
||||
@@ -448,22 +438,6 @@ public extension Array where Element: Hashable {
|
||||
}
|
||||
}
|
||||
|
||||
public func findAndToggleNSControlState(_ view: NSView?, state: NSControl.StateValue) {
|
||||
if let control = view?.subviews.first(where: { $0 is NSControl && !($0 is NSTextField) }) {
|
||||
toggleNSControlState(control as? NSControl, state: state)
|
||||
}
|
||||
}
|
||||
|
||||
public func findAndToggleEnableNSControlState(_ view: NSView?, state: Bool) {
|
||||
if let control = view?.subviews.first(where: { ($0 is NSControl || $0 is NSPopUpButton) && !($0 is NSTextField) }) {
|
||||
if control is NSControl {
|
||||
toggleEnableNSControlState(control as? NSControl, state: state)
|
||||
} else if control is NSPopUpButton {
|
||||
toggleEnableNSControlState(control as? NSPopUpButton, state: state)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public func toggleNSControlState(_ control: NSControl?, state: NSControl.StateValue) {
|
||||
if #available(OSX 10.15, *) {
|
||||
if let checkbox = control as? NSSwitch {
|
||||
@@ -476,30 +450,6 @@ public func toggleNSControlState(_ control: NSControl?, state: NSControl.StateVa
|
||||
}
|
||||
}
|
||||
|
||||
public func toggleEnableNSControlState(_ control: NSControl?, state: Bool) {
|
||||
if #available(OSX 10.15, *) {
|
||||
if let checkbox = control as? NSSwitch {
|
||||
checkbox.isEnabled = state
|
||||
} else if let checkbox = control as? NSPopUpButton {
|
||||
checkbox.isEnabled = state
|
||||
}
|
||||
} else {
|
||||
if let checkbox = control as? NSButton {
|
||||
checkbox.isEnabled = state
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public func dialogOKCancel(question: String, text: String) {
|
||||
let alert = NSAlert()
|
||||
alert.messageText = question
|
||||
alert.informativeText = text
|
||||
alert.alertStyle = .warning
|
||||
alert.addButton(withTitle: "OK")
|
||||
alert.addButton(withTitle: "Cancel")
|
||||
alert.runModal()
|
||||
}
|
||||
|
||||
public func asyncShell(_ args: String) {
|
||||
let task = Process()
|
||||
task.launchPath = "/bin/sh"
|
||||
@@ -657,21 +607,6 @@ public struct TopProcess: Codable, Process_p {
|
||||
}
|
||||
}
|
||||
|
||||
public func getIOParent(_ obj: io_registry_entry_t) -> io_registry_entry_t? {
|
||||
var parent: io_registry_entry_t = 0
|
||||
|
||||
if IORegistryEntryGetParentEntry(obj, kIOServicePlane, &parent) != KERN_SUCCESS {
|
||||
return nil
|
||||
}
|
||||
|
||||
if IOObjectConformsTo(parent, "IOBlockStorageDriver") == 0 {
|
||||
IOObjectRelease(parent)
|
||||
return nil
|
||||
}
|
||||
|
||||
return parent
|
||||
}
|
||||
|
||||
public func fetchIOService(_ name: String) -> [NSDictionary]? {
|
||||
var iterator: io_iterator_t = io_iterator_t()
|
||||
var obj: io_registry_entry_t = 1
|
||||
@@ -709,7 +644,7 @@ public func getIOProperties(_ entry: io_registry_entry_t) -> NSDictionary? {
|
||||
return properties?.takeUnretainedValue()
|
||||
}
|
||||
|
||||
public func getIOName(_ entry: io_registry_entry_t) -> String? {
|
||||
internal func getIOName(_ entry: io_registry_entry_t) -> String? {
|
||||
let pointer = UnsafeMutablePointer<io_name_t>.allocate(capacity: 1)
|
||||
|
||||
let result = IORegistryEntryGetName(entry, pointer)
|
||||
@@ -721,29 +656,6 @@ public func getIOName(_ entry: io_registry_entry_t) -> String? {
|
||||
return String(cString: UnsafeRawPointer(pointer).assumingMemoryBound(to: CChar.self))
|
||||
}
|
||||
|
||||
public func getIOChildrens(_ entry: io_registry_entry_t) -> [String]? {
|
||||
var iter: io_iterator_t = io_iterator_t()
|
||||
if IORegistryEntryGetChildIterator(entry, kIOServicePlane, &iter) != kIOReturnSuccess {
|
||||
return nil
|
||||
}
|
||||
|
||||
var iterator: io_registry_entry_t = 1
|
||||
var list: [String] = []
|
||||
while iterator != 0 {
|
||||
iterator = IOIteratorNext(iter)
|
||||
|
||||
let pointer = UnsafeMutablePointer<io_name_t>.allocate(capacity: 1)
|
||||
if IORegistryEntryGetName(iterator, pointer) != kIOReturnSuccess {
|
||||
continue
|
||||
}
|
||||
|
||||
list.append(String(cString: UnsafeRawPointer(pointer).assumingMemoryBound(to: CChar.self)))
|
||||
IOObjectRelease(iterator)
|
||||
}
|
||||
|
||||
return list
|
||||
}
|
||||
|
||||
public class ColorView: NSView {
|
||||
public var inactiveColor: NSColor = NSColor.lightGray.withAlphaComponent(0.75)
|
||||
|
||||
@@ -834,38 +746,10 @@ public func sysctlByName(_ name: String) -> Int64 {
|
||||
return num
|
||||
}
|
||||
|
||||
public class CAText: CATextLayer {
|
||||
public init(fontSize: CGFloat = 12, weight: NSFont.Weight = .regular) {
|
||||
super.init()
|
||||
|
||||
self.font = NSFont.systemFont(ofSize: fontSize, weight: weight)
|
||||
self.fontSize = fontSize
|
||||
|
||||
self.allowsFontSubpixelQuantization = true
|
||||
self.contentsScale = NSScreen.main?.backingScaleFactor ?? 1
|
||||
self.rasterizationScale = NSScreen.main?.backingScaleFactor ?? 1
|
||||
|
||||
self.foregroundColor = NSColor.textColor.cgColor
|
||||
}
|
||||
|
||||
required init?(coder: NSCoder) {
|
||||
fatalError("init(coder:) has not been implemented")
|
||||
}
|
||||
|
||||
public override init(layer: Any) {
|
||||
super.init(layer: layer)
|
||||
}
|
||||
|
||||
public func getWidth(add: CGFloat = 0) -> CGFloat {
|
||||
let value = self.string as? String ?? ""
|
||||
return value.widthOfString(usingFont: self.font as! NSFont).rounded(.up) + add
|
||||
}
|
||||
}
|
||||
|
||||
public class WidgetLabelView: NSView {
|
||||
internal class WidgetLabelView: NSView {
|
||||
private var title: String
|
||||
|
||||
public init(_ title: String, height: CGFloat) {
|
||||
internal init(_ title: String, height: CGFloat) {
|
||||
self.title = title
|
||||
|
||||
super.init(frame: NSRect(
|
||||
@@ -905,32 +789,6 @@ public class WidgetLabelView: NSView {
|
||||
}
|
||||
}
|
||||
|
||||
public func isRoot() -> Bool {
|
||||
return getuid() == 0
|
||||
}
|
||||
|
||||
public func ensureRoot() {
|
||||
if isRoot() {
|
||||
return
|
||||
}
|
||||
|
||||
let pwd = Bundle.main.bundleURL.absoluteString.replacingOccurrences(of: "file://", with: "")
|
||||
guard let script = NSAppleScript(source: "do shell script \"\(pwd)/Contents/MacOS/Stats > /dev/null 2>&1 &\" with administrator privileges") else {
|
||||
return
|
||||
}
|
||||
|
||||
var err: NSDictionary? = nil
|
||||
script.executeAndReturnError(&err)
|
||||
|
||||
if err != nil {
|
||||
print("cannot run script as root: \(String(describing: err))")
|
||||
return
|
||||
}
|
||||
|
||||
NSApp.terminate(nil)
|
||||
return
|
||||
}
|
||||
|
||||
public func process(path: String, arguments: [String]) -> String? {
|
||||
let task = Process()
|
||||
task.launchPath = path
|
||||
@@ -999,13 +857,6 @@ public class SMCHelper {
|
||||
}
|
||||
}
|
||||
|
||||
public func powermetrics(_ samplers: [String], completion: @escaping (String?) -> Void) {
|
||||
guard let helper = self.helper(nil) else { return }
|
||||
helper.powermetrics(samplers) { result in
|
||||
completion(result)
|
||||
}
|
||||
}
|
||||
|
||||
public func isActive() -> Bool {
|
||||
return self.connection != nil
|
||||
}
|
||||
@@ -1187,13 +1038,13 @@ public class EmptyView: NSStackView {
|
||||
}
|
||||
}
|
||||
|
||||
public func saveNSStatusItemPosition(id: String) {
|
||||
internal func saveNSStatusItemPosition(id: String) {
|
||||
let position = Store.shared.int(key: "NSStatusItem Preferred Position \(id)", defaultValue: -1)
|
||||
if position != -1 {
|
||||
Store.shared.set(key: "NSStatusItem Restore Position \(id)", value: position)
|
||||
}
|
||||
}
|
||||
public func restoreNSStatusItemPosition(id: String) {
|
||||
internal func restoreNSStatusItemPosition(id: String) {
|
||||
let prevPosition = Store.shared.int(key: "NSStatusItem Restore Position \(id)", defaultValue: -1)
|
||||
if prevPosition != -1 {
|
||||
Store.shared.set(key: "NSStatusItem Preferred Position \(id)", value: prevPosition)
|
||||
@@ -1418,7 +1269,7 @@ public class PreferencesSection: NSStackView {
|
||||
}
|
||||
}
|
||||
|
||||
public class PreferencesSeparator: NSView {
|
||||
private class PreferencesSeparator: NSView {
|
||||
public init() {
|
||||
super.init(frame: .zero)
|
||||
self.wantsLayer = true
|
||||
@@ -1601,7 +1452,6 @@ public class PreferencesSwitch: NSStackView {
|
||||
self.spacing = Constants.Settings.margin
|
||||
|
||||
let btn = switchView(action: #selector(self.callback), state: state)
|
||||
with.widthAnchor.constraint(equalToConstant: 68).isActive = true
|
||||
with.isEnabled = state
|
||||
|
||||
self.addArrangedSubview(NSView())
|
||||
|
||||
@@ -8,18 +8,6 @@
|
||||
|
||||
import Cocoa
|
||||
|
||||
public protocol Module_p {
|
||||
var available: Bool { get }
|
||||
var enabled: Bool { get }
|
||||
|
||||
var settings: Settings_p? { get }
|
||||
|
||||
func mount()
|
||||
func unmount()
|
||||
|
||||
func terminate()
|
||||
}
|
||||
|
||||
public struct module_c {
|
||||
public var name: String = ""
|
||||
public var icon: NSImage?
|
||||
@@ -75,7 +63,7 @@ public struct module_c {
|
||||
}
|
||||
}
|
||||
|
||||
open class Module: Module_p {
|
||||
open class Module {
|
||||
public var config: module_c
|
||||
|
||||
public var available: Bool = false
|
||||
@@ -155,7 +143,6 @@ open class Module: Module_p {
|
||||
self.settings = Settings(
|
||||
config: &self.config,
|
||||
widgets: &self.menuBar.widgets,
|
||||
enabled: self.enabled,
|
||||
moduleSettings: self.settingsView,
|
||||
popupSettings: self.popupView,
|
||||
notificationsSettings: self.notificationsView
|
||||
@@ -232,13 +219,6 @@ open class Module: Module_p {
|
||||
self.readers = list.filter({ $0 != nil }).map({ $0! as Reader_p })
|
||||
}
|
||||
|
||||
// replace a popup view
|
||||
public func replacePopup(_ view: Popup_p) {
|
||||
self.popup?.setIsVisible(false)
|
||||
self.popupView = view
|
||||
self.popup = PopupWindow(title: self.config.name, view: self.popupView, visibilityCallback: self.visibilityCallback)
|
||||
}
|
||||
|
||||
// determine if module is available (can be overrided in module)
|
||||
open func isAvailable() -> Bool { return true }
|
||||
|
||||
@@ -257,9 +237,6 @@ open class Module: Module_p {
|
||||
}
|
||||
}
|
||||
|
||||
// call after widget set up
|
||||
open func widgetDidSet(_ type: widget_t) {}
|
||||
|
||||
// call when popup appear/disappear
|
||||
private func visibilityCallback(_ state: Bool) {
|
||||
self.readers.filter{ $0.popup }.forEach { (reader: Reader_p) in
|
||||
@@ -339,7 +316,7 @@ open class Module: Module_p {
|
||||
}
|
||||
}
|
||||
|
||||
@objc private func listenForMouseDownInSettings(_ notification: Notification) {
|
||||
@objc private func listenForMouseDownInSettings() {
|
||||
if let popup = self.popup, popup.isVisible && !popup.locked {
|
||||
self.popup?.setIsVisible(false)
|
||||
}
|
||||
|
||||
@@ -77,7 +77,7 @@ public class PopupWindow: NSWindow, NSWindowDelegate {
|
||||
}
|
||||
|
||||
internal class PopupViewController: NSViewController {
|
||||
public var visibilityCallback: (_ state: Bool) -> Void = {_ in }
|
||||
fileprivate var visibilityCallback: (_ state: Bool) -> Void = {_ in }
|
||||
private var popup: PopupView
|
||||
|
||||
public init() {
|
||||
@@ -112,19 +112,18 @@ internal class PopupViewController: NSViewController {
|
||||
self.visibilityCallback(false)
|
||||
}
|
||||
|
||||
public func setup(title: String, view: Popup_p?) {
|
||||
fileprivate func setup(title: String, view: Popup_p?) {
|
||||
self.title = title
|
||||
self.popup.setTitle(title)
|
||||
self.popup.setView(view)
|
||||
}
|
||||
|
||||
public func setCloseButton(_ state: Bool) {
|
||||
fileprivate func setCloseButton(_ state: Bool) {
|
||||
self.popup.setCloseButton(state)
|
||||
}
|
||||
}
|
||||
|
||||
internal class PopupView: NSView {
|
||||
private var title: String? = nil
|
||||
private var view: Popup_p? = nil
|
||||
|
||||
private var foreground: NSVisualEffectView
|
||||
@@ -190,7 +189,7 @@ internal class PopupView: NSView {
|
||||
self.background.layer?.backgroundColor = self.isDarkMode ? .clear : NSColor.white.cgColor
|
||||
}
|
||||
|
||||
public func setView(_ view: Popup_p?) {
|
||||
fileprivate func setView(_ view: Popup_p?) {
|
||||
self.view = view
|
||||
|
||||
var isScrollVisible: Bool = false
|
||||
@@ -226,12 +225,11 @@ internal class PopupView: NSView {
|
||||
}
|
||||
}
|
||||
|
||||
public func setTitle(_ newTitle: String) {
|
||||
self.title = newTitle
|
||||
fileprivate func setTitle(_ newTitle: String) {
|
||||
self.header.setTitle(newTitle)
|
||||
}
|
||||
|
||||
public func setCloseButton(_ state: Bool) {
|
||||
fileprivate func setCloseButton(_ state: Bool) {
|
||||
self.header.setCloseButton(state)
|
||||
}
|
||||
|
||||
@@ -299,7 +297,6 @@ internal class PopupView: NSView {
|
||||
internal class HeaderView: NSStackView {
|
||||
private var titleView: NSTextField? = nil
|
||||
private var activityButton: NSButton?
|
||||
private var settingsButton: NSButton?
|
||||
|
||||
private var title: String = ""
|
||||
private var isCloseAction: Bool = false
|
||||
@@ -355,7 +352,6 @@ internal class HeaderView: NSStackView {
|
||||
settings.target = self
|
||||
settings.toolTip = localizedString("Open module settings")
|
||||
settings.focusRingType = .none
|
||||
self.settingsButton = settings
|
||||
|
||||
self.addArrangedSubview(activity)
|
||||
self.addArrangedSubview(title)
|
||||
@@ -372,7 +368,7 @@ internal class HeaderView: NSStackView {
|
||||
fatalError("init(coder:) has not been implemented")
|
||||
}
|
||||
|
||||
public func setTitle(_ newTitle: String) {
|
||||
fileprivate func setTitle(_ newTitle: String) {
|
||||
self.title = newTitle
|
||||
self.titleView?.stringValue = localizedString(newTitle)
|
||||
}
|
||||
@@ -388,12 +384,12 @@ internal class HeaderView: NSStackView {
|
||||
line.stroke()
|
||||
}
|
||||
|
||||
@objc func openActivityMonitor(_ sender: Any) {
|
||||
@objc func openActivityMonitor() {
|
||||
guard let app = self.app else { return }
|
||||
NSWorkspace.shared.open([], withApplicationAt: app, configuration: NSWorkspace.OpenConfiguration())
|
||||
}
|
||||
|
||||
@objc func openSettings(_ sender: Any) {
|
||||
@objc func openSettings() {
|
||||
NotificationCenter.default.post(name: .toggleSettings, object: nil, userInfo: ["module": self.title])
|
||||
}
|
||||
|
||||
@@ -403,7 +399,7 @@ internal class HeaderView: NSStackView {
|
||||
return
|
||||
}
|
||||
|
||||
public func setCloseButton(_ state: Bool) {
|
||||
fileprivate func setCloseButton(_ state: Bool) {
|
||||
if state && !self.isCloseAction {
|
||||
self.activityButton?.image = Bundle(for: type(of: self)).image(forResource: "close")!
|
||||
self.activityButton?.toolTip = localizedString("Close popup")
|
||||
|
||||
@@ -17,7 +17,6 @@ public protocol Portal_p: NSView {
|
||||
|
||||
open class PortalWrapper: NSStackView, Portal_p {
|
||||
public var name: String
|
||||
|
||||
private let header: PortalHeader
|
||||
|
||||
public init(_ type: ModuleType, height: CGFloat = Constants.Popup.portalHeight) {
|
||||
@@ -102,7 +101,7 @@ public class PortalHeader: NSStackView {
|
||||
fatalError("init(coder:) has not been implemented")
|
||||
}
|
||||
|
||||
@objc private func openSettings(_ sender: Any) {
|
||||
@objc private func openSettings() {
|
||||
self.window?.setIsVisible(false)
|
||||
NotificationCenter.default.post(name: .toggleSettings, object: nil, userInfo: ["module": self.name])
|
||||
}
|
||||
|
||||
@@ -11,10 +11,6 @@
|
||||
|
||||
import Cocoa
|
||||
|
||||
public protocol value_t {
|
||||
var widgetValue: Double { get }
|
||||
}
|
||||
|
||||
public protocol Reader_p {
|
||||
var optional: Bool { get }
|
||||
var popup: Bool { get }
|
||||
@@ -60,7 +56,6 @@ open class Reader<T: Codable>: NSObject, ReaderInternal_p {
|
||||
private let module: ModuleType
|
||||
private var history: Bool
|
||||
private var repeatTask: Repeater?
|
||||
private var nilCallbackCounter: Int = 0
|
||||
private var locked: Bool = true
|
||||
private var initlizalized: Bool = false
|
||||
|
||||
|
||||
@@ -16,7 +16,6 @@ public protocol Settings_p: NSView {
|
||||
}
|
||||
|
||||
public protocol Settings_v: NSView {
|
||||
var callback: (() -> Void) { get set }
|
||||
func load(widgets: [widget_t])
|
||||
}
|
||||
|
||||
@@ -58,7 +57,7 @@ open class Settings: NSStackView, Settings_p {
|
||||
private var isPopupSettingsAvailable: Bool
|
||||
private var isNotificationsSettingsAvailable: Bool
|
||||
|
||||
init(config: UnsafePointer<module_c>, widgets: UnsafeMutablePointer<[Widget]>, enabled: Bool, moduleSettings: Settings_v?, popupSettings: Popup_p?, notificationsSettings: NotificationsWrapper?) {
|
||||
init(config: UnsafePointer<module_c>, widgets: UnsafeMutablePointer<[Widget]>, moduleSettings: Settings_v?, popupSettings: Popup_p?, notificationsSettings: NotificationsWrapper?) {
|
||||
self.config = config
|
||||
self.widgets = widgets.pointee
|
||||
self.moduleSettings = moduleSettings
|
||||
@@ -271,7 +270,7 @@ open class Settings: NSStackView, Settings_p {
|
||||
}
|
||||
}
|
||||
|
||||
class WidgetSelectorView: NSStackView {
|
||||
private class WidgetSelectorView: NSStackView {
|
||||
private var module: String
|
||||
private var stateCallback: () -> Void = {}
|
||||
private var moved: Bool = false
|
||||
@@ -286,7 +285,7 @@ class WidgetSelectorView: NSStackView {
|
||||
return view
|
||||
}()
|
||||
|
||||
public init(module: String, widgets: [Widget], stateCallback: @escaping () -> Void) {
|
||||
fileprivate init(module: String, widgets: [Widget], stateCallback: @escaping () -> Void) {
|
||||
self.module = module
|
||||
self.stateCallback = stateCallback
|
||||
|
||||
@@ -465,7 +464,7 @@ class WidgetSelectorView: NSStackView {
|
||||
}
|
||||
}
|
||||
|
||||
internal class WidgetPreview: NSStackView {
|
||||
private class WidgetPreview: NSStackView {
|
||||
private var stateCallback: (_ status: Bool) -> Void = {_ in }
|
||||
|
||||
private let rgbImage: NSImage
|
||||
@@ -475,12 +474,12 @@ internal class WidgetPreview: NSStackView {
|
||||
private var state: Bool
|
||||
private let id: String
|
||||
|
||||
public var position: Int {
|
||||
fileprivate var position: Int {
|
||||
get { Store.shared.int(key: "\(self.id)_position", defaultValue: 0) }
|
||||
set { Store.shared.set(key: "\(self.id)_position", value: newValue) }
|
||||
}
|
||||
|
||||
public init(id: String, type: widget_t, image: NSImage, isActive: Bool, _ callback: @escaping (_ status: Bool) -> Void) {
|
||||
fileprivate init(id: String, type: widget_t, image: NSImage, isActive: Bool, _ callback: @escaping (_ status: Bool) -> Void) {
|
||||
self.id = id
|
||||
self.stateCallback = callback
|
||||
self.rgbImage = image
|
||||
@@ -531,7 +530,7 @@ internal class WidgetPreview: NSStackView {
|
||||
fatalError("init(coder:) has not been implemented")
|
||||
}
|
||||
|
||||
public func status(_ newState: Bool) {
|
||||
fileprivate func status(_ newState: Bool) {
|
||||
self.state = newState
|
||||
self.stateCallback(newState)
|
||||
self.imageView.image = newState ? self.rgbImage : self.grayImage
|
||||
@@ -555,8 +554,8 @@ internal class WidgetPreview: NSStackView {
|
||||
}
|
||||
}
|
||||
|
||||
internal class WidgetSettings: NSStackView {
|
||||
public init(title: String, image: NSImage, settingsView: NSView) {
|
||||
private class WidgetSettings: NSStackView {
|
||||
fileprivate init(title: String, image: NSImage, settingsView: NSView) {
|
||||
super.init(frame: NSRect.zero)
|
||||
|
||||
self.translatesAutoresizingMaskIntoConstraints = false
|
||||
|
||||
@@ -54,11 +54,11 @@ public enum widget_t: String {
|
||||
preview = SpeedWidget(title: module, config: widgetConfig, preview: true)
|
||||
item = SpeedWidget(title: module, config: widgetConfig, preview: false)
|
||||
case .battery:
|
||||
preview = BatteryWidget(title: module, config: widgetConfig, preview: true)
|
||||
item = BatteryWidget(title: module, config: widgetConfig, preview: false)
|
||||
preview = BatteryWidget(title: module, preview: true)
|
||||
item = BatteryWidget(title: module, preview: false)
|
||||
case .batteryDetails:
|
||||
preview = BatteryDetailsWidget(title: module, config: widgetConfig, preview: true)
|
||||
item = BatteryDetailsWidget(title: module, config: widgetConfig, preview: false)
|
||||
preview = BatteryDetailsWidget(title: module, preview: true)
|
||||
item = BatteryDetailsWidget(title: module, preview: false)
|
||||
case .stack:
|
||||
preview = StackWidget(title: module, config: widgetConfig, preview: true)
|
||||
item = StackWidget(title: module, config: widgetConfig, preview: false)
|
||||
@@ -66,11 +66,11 @@ public enum widget_t: String {
|
||||
preview = MemoryWidget(title: module, config: widgetConfig, preview: true)
|
||||
item = MemoryWidget(title: module, config: widgetConfig, preview: false)
|
||||
case .label:
|
||||
preview = Label(title: module, config: widgetConfig, preview: true)
|
||||
item = Label(title: module, config: widgetConfig, preview: false)
|
||||
preview = Label(title: module, config: widgetConfig)
|
||||
item = Label(title: module, config: widgetConfig)
|
||||
case .tachometer:
|
||||
preview = Tachometer(title: module, config: widgetConfig, preview: true)
|
||||
item = Tachometer(title: module, config: widgetConfig, preview: false)
|
||||
preview = Tachometer(title: module, preview: true)
|
||||
item = Tachometer(title: module, preview: false)
|
||||
case .state:
|
||||
preview = StateWidget(title: module, config: widgetConfig, preview: true)
|
||||
item = StateWidget(title: module, config: widgetConfig, preview: false)
|
||||
@@ -144,21 +144,15 @@ public enum widget_t: String {
|
||||
extension widget_t: CaseIterable {}
|
||||
|
||||
public protocol widget_p: NSView {
|
||||
var type: widget_t { get }
|
||||
var title: String { get }
|
||||
var position: Int { get set }
|
||||
|
||||
var widthHandler: (() -> Void)? { get set }
|
||||
var onClick: (() -> Void)? { get set }
|
||||
|
||||
func setValues(_ values: [value_t])
|
||||
func settings() -> NSView
|
||||
}
|
||||
|
||||
open class WidgetWrapper: NSView, widget_p {
|
||||
public var type: widget_t
|
||||
public var title: String
|
||||
public var position: Int = -1
|
||||
public var widthHandler: (() -> Void)? = nil
|
||||
public var onClick: (() -> Void)? = nil
|
||||
public var shadowSize: CGSize
|
||||
@@ -214,10 +208,7 @@ open class WidgetWrapper: NSView, widget_p {
|
||||
return width
|
||||
}
|
||||
|
||||
// MARK: - stubs
|
||||
|
||||
open func settings() -> NSView { return NSView() }
|
||||
open func setValues(_ values: [value_t]) {}
|
||||
|
||||
open override func mouseDown(with event: NSEvent) {
|
||||
if let f = self.onClick {
|
||||
@@ -273,7 +264,6 @@ public class Widget {
|
||||
}
|
||||
}
|
||||
|
||||
private var config: NSDictionary = NSDictionary()
|
||||
private var menuBarItem: NSStatusItem? = nil
|
||||
private var originX: CGFloat
|
||||
|
||||
@@ -363,7 +353,7 @@ public class Widget {
|
||||
}
|
||||
}
|
||||
|
||||
@objc private func togglePopup(_ sender: Any) {
|
||||
@objc private func togglePopup() {
|
||||
if let item = self.menuBarItem, let window = item.button?.window {
|
||||
NotificationCenter.default.post(name: .togglePopup, object: nil, userInfo: [
|
||||
"module": self.module,
|
||||
@@ -517,7 +507,7 @@ public class MenuBar {
|
||||
self.callback?()
|
||||
}
|
||||
|
||||
@objc private func togglePopup(_ sender: NSEvent) {
|
||||
@objc private func togglePopup() {
|
||||
if let item = self.menuBarItem, let window = item.button?.window {
|
||||
NotificationCenter.default.post(name: .togglePopup, object: nil, userInfo: [
|
||||
"module": self.moduleName,
|
||||
|
||||
@@ -21,7 +21,7 @@ public struct circle_segment {
|
||||
}
|
||||
}
|
||||
|
||||
public func scaleValue(scale: Scale = .linear, value: Double, maxValue: Double, maxHeight: CGFloat, limit: Double) -> CGFloat {
|
||||
internal func scaleValue(scale: Scale = .linear, value: Double, maxValue: Double, maxHeight: CGFloat, limit: Double) -> CGFloat {
|
||||
var value = value
|
||||
if scale == .none && value > 1 && maxValue != 0 {
|
||||
value /= maxValue
|
||||
@@ -375,8 +375,6 @@ public class LineChartView: NSView {
|
||||
}
|
||||
|
||||
public class NetworkChartView: NSView {
|
||||
public var id: String = UUID().uuidString
|
||||
|
||||
public var base: DataSizeBase = .byte
|
||||
|
||||
private var reversedOrder: Bool
|
||||
@@ -460,8 +458,6 @@ public class NetworkChartView: NSView {
|
||||
}
|
||||
|
||||
public class PieChartView: NSView {
|
||||
public var id: String = UUID().uuidString
|
||||
|
||||
private var filled: Bool = false
|
||||
private var drawValue: Bool = false
|
||||
private var nonActiveSegmentColor: NSColor = NSColor.lightGray
|
||||
@@ -633,11 +629,11 @@ public class HalfCircleGraphView: NSView {
|
||||
}
|
||||
}
|
||||
|
||||
public class TachometerGraphView: NSView {
|
||||
internal class TachometerGraphView: NSView {
|
||||
private var filled: Bool
|
||||
private var segments: [circle_segment]
|
||||
|
||||
public init(frame: NSRect, segments: [circle_segment], filled: Bool = true) {
|
||||
internal init(frame: NSRect, segments: [circle_segment], filled: Bool = true) {
|
||||
self.filled = filled
|
||||
self.segments = segments
|
||||
|
||||
@@ -682,14 +678,14 @@ public class TachometerGraphView: NSView {
|
||||
}
|
||||
}
|
||||
|
||||
public func setSegments(_ segments: [circle_segment]) {
|
||||
internal func setSegments(_ segments: [circle_segment]) {
|
||||
self.segments = segments
|
||||
if self.window?.isVisible ?? false {
|
||||
self.display()
|
||||
}
|
||||
}
|
||||
|
||||
public func setFrame(_ frame: NSRect) {
|
||||
internal func setFrame(_ frame: NSRect) {
|
||||
var original = self.frame
|
||||
original = frame
|
||||
self.frame = original
|
||||
|
||||
@@ -92,19 +92,6 @@ public class DB {
|
||||
return self.values[key] as? T
|
||||
}
|
||||
|
||||
public func findMany<T: Decodable>(_ type: T.Type, key: String) -> [T] {
|
||||
guard let values = self.lldb?.findMany(key) as? [String] else { return [] }
|
||||
|
||||
var list: [T] = []
|
||||
values.forEach({ value in
|
||||
if let value = try? JSONDecoder().decode(type, from: Data(value.utf8)) {
|
||||
list.append(value)
|
||||
}
|
||||
})
|
||||
|
||||
return list
|
||||
}
|
||||
|
||||
private func clean(_ key: String) {
|
||||
guard let keys = self.lldb?.keys(key) as? [String] else { return }
|
||||
let maxLiveTS = Date().currentTimeSeconds() - self.ttl
|
||||
|
||||
@@ -21,7 +21,6 @@ public class Reachability {
|
||||
private var isRunning = false
|
||||
private var reachability: SCNetworkReachability?
|
||||
private let reachabilitySerialQueue = DispatchQueue(label: "eu.exelban.ReachabilityQueue")
|
||||
private let log: NextLog = NextLog.shared.copy(category: "Reachability")
|
||||
|
||||
public init(start: Bool = false) {
|
||||
var zeroAddress = sockaddr()
|
||||
|
||||
@@ -11,18 +11,18 @@
|
||||
|
||||
import Foundation
|
||||
|
||||
public enum State {
|
||||
private enum RepeaterState {
|
||||
case paused
|
||||
case running
|
||||
}
|
||||
|
||||
public class Repeater {
|
||||
internal class Repeater {
|
||||
private var callback: (() -> Void)
|
||||
private var state: State = .paused
|
||||
private var state: RepeaterState = .paused
|
||||
|
||||
private var timer: DispatchSourceTimer = DispatchSource.makeTimerSource(queue: DispatchQueue(label: "eu.exelban.Stats.Repeater", qos: .default))
|
||||
|
||||
public init(seconds: Int, callback: @escaping (() -> Void)) {
|
||||
internal init(seconds: Int, callback: @escaping (() -> Void)) {
|
||||
self.callback = callback
|
||||
self.setupTimer(seconds)
|
||||
}
|
||||
@@ -43,21 +43,21 @@ public class Repeater {
|
||||
}
|
||||
}
|
||||
|
||||
public func start() {
|
||||
internal func start() {
|
||||
guard self.state == .paused else { return }
|
||||
|
||||
self.timer.resume()
|
||||
self.state = .running
|
||||
}
|
||||
|
||||
public func pause() {
|
||||
internal func pause() {
|
||||
guard self.state == .running else { return }
|
||||
|
||||
self.timer.suspend()
|
||||
self.state = .paused
|
||||
}
|
||||
|
||||
public func reset(seconds: Int, restart: Bool = false) {
|
||||
internal func reset(seconds: Int, restart: Bool = false) {
|
||||
if self.state == .running {
|
||||
self.pause()
|
||||
}
|
||||
|
||||
@@ -80,7 +80,6 @@ public struct os_s {
|
||||
|
||||
public struct core_s {
|
||||
public var id: Int32
|
||||
public var name: String
|
||||
public var type: coreType
|
||||
}
|
||||
|
||||
@@ -112,17 +111,10 @@ public struct gpu_s {
|
||||
public var cores: Int? = nil
|
||||
}
|
||||
|
||||
public struct disk_s {
|
||||
public let name: String
|
||||
public let model: String
|
||||
public let size: Int64
|
||||
}
|
||||
|
||||
public struct info_s {
|
||||
public var cpu: cpu_s? = nil
|
||||
public var ram: ram_s? = nil
|
||||
public var gpu: [gpu_s]? = nil
|
||||
public var disk: disk_s? = nil
|
||||
}
|
||||
|
||||
public struct device_s {
|
||||
@@ -139,7 +131,6 @@ public class SystemKit {
|
||||
public static let shared = SystemKit()
|
||||
|
||||
public var device: device_s = device_s()
|
||||
private let log: NextLog = NextLog.shared.copy(category: "SystemKit")
|
||||
|
||||
public init() {
|
||||
let (modelID, serialNumber) = self.modelAndSerialNumber()
|
||||
@@ -171,7 +162,6 @@ public class SystemKit {
|
||||
self.device.info.cpu = self.getCPUInfo()
|
||||
self.device.info.ram = self.getRamInfo()
|
||||
self.device.info.gpu = self.getGPUInfo()
|
||||
self.device.info.disk = self.getDiskInfo()
|
||||
|
||||
if let name = self.device.info.cpu?.name?.lowercased() {
|
||||
if name.contains("intel") {
|
||||
@@ -354,7 +344,7 @@ public class SystemKit {
|
||||
return pointer.load(as: Int32.self)
|
||||
}
|
||||
|
||||
list.append(core_s(id: id ?? -1, name: name, type: type))
|
||||
list.append(core_s(id: id ?? -1, type: type))
|
||||
} else if name.trimmed == "cpus" {
|
||||
eCores = (props.object(forKey: "e-core-count") as? Data)?.withUnsafeBytes { pointer in
|
||||
return pointer.load(as: Int32.self)
|
||||
@@ -410,51 +400,6 @@ public class SystemKit {
|
||||
return list
|
||||
}
|
||||
|
||||
private func getDiskInfo() -> disk_s? {
|
||||
var disk: DADisk? = nil
|
||||
|
||||
let keys: [URLResourceKey] = [.volumeNameKey]
|
||||
let paths = FileManager.default.mountedVolumeURLs(includingResourceValuesForKeys: keys)!
|
||||
if let session = DASessionCreate(kCFAllocatorDefault) {
|
||||
for url in paths where url.pathComponents.count == 1 {
|
||||
disk = DADiskCreateFromVolumePath(kCFAllocatorDefault, session, url as CFURL)
|
||||
}
|
||||
}
|
||||
|
||||
if disk == nil {
|
||||
error("empty disk after fetching list")
|
||||
return nil
|
||||
}
|
||||
|
||||
if let diskDescription = DADiskCopyDescription(disk!) {
|
||||
if let dict = diskDescription as? [String: AnyObject] {
|
||||
if let removable = dict[kDADiskDescriptionMediaRemovableKey as String] {
|
||||
if removable as! Bool {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
var name: String = ""
|
||||
var model: String = ""
|
||||
var size: Int64 = 0
|
||||
|
||||
if let mediaName = dict[kDADiskDescriptionMediaNameKey as String] {
|
||||
name = mediaName as! String
|
||||
}
|
||||
if let deviceModel = dict[kDADiskDescriptionDeviceModelKey as String] {
|
||||
model = (deviceModel as! String).trimmingCharacters(in: .whitespacesAndNewlines)
|
||||
}
|
||||
if let mediaSize = dict[kDADiskDescriptionMediaSizeKey as String] {
|
||||
size = Int64(truncating: mediaSize as! NSNumber)
|
||||
}
|
||||
|
||||
return disk_s(name: name, model: model, size: size)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
public func getRamInfo() -> ram_s? {
|
||||
guard let res = process(path: "/usr/sbin/system_profiler", arguments: ["SPMemoryDataType", "-json"]) else {
|
||||
return nil
|
||||
|
||||
@@ -26,7 +26,7 @@ public struct version_s {
|
||||
}
|
||||
}
|
||||
|
||||
public struct Version {
|
||||
internal struct Version {
|
||||
var major: Int = 0
|
||||
var minor: Int = 0
|
||||
var patch: Int = 0
|
||||
|
||||
@@ -231,17 +231,7 @@ public class ProcessView: NSStackView {
|
||||
self.setLock(!self.lock)
|
||||
}
|
||||
|
||||
public func set(_ process: Process_p, _ value: String) {
|
||||
if self.lock && process.pid != self.pid { return }
|
||||
|
||||
self.labelView.stringValue = process.name
|
||||
self.valueViews.first?.stringValue = value
|
||||
self.imageView.image = process.icon
|
||||
self.pid = process.pid
|
||||
self.toolTip = "pid: \(process.pid)"
|
||||
}
|
||||
|
||||
public func set(_ process: Process_p, _ values: [String]) {
|
||||
fileprivate func set(_ process: Process_p, _ values: [String]) {
|
||||
if self.lock && process.pid != self.pid { return }
|
||||
|
||||
self.labelView.stringValue = process.name
|
||||
@@ -251,7 +241,7 @@ public class ProcessView: NSStackView {
|
||||
self.toolTip = "pid: \(process.pid)"
|
||||
}
|
||||
|
||||
public func clear(_ symbol: String = "") {
|
||||
fileprivate func clear(_ symbol: String = "") {
|
||||
self.labelView.stringValue = symbol
|
||||
self.valueViews.forEach({ $0.stringValue = symbol })
|
||||
self.imageView.image = nil
|
||||
@@ -260,7 +250,7 @@ public class ProcessView: NSStackView {
|
||||
self.toolTip = symbol
|
||||
}
|
||||
|
||||
public func setLock(_ state: Bool) {
|
||||
fileprivate func setLock(_ state: Bool) {
|
||||
self.lock = state
|
||||
if self.lock {
|
||||
self.imageView.isHidden = true
|
||||
@@ -273,7 +263,7 @@ public class ProcessView: NSStackView {
|
||||
}
|
||||
}
|
||||
|
||||
@objc public func kill() {
|
||||
@objc private func kill() {
|
||||
if let pid = self.pid {
|
||||
asyncShell("kill \(pid)")
|
||||
}
|
||||
|
||||
@@ -96,20 +96,20 @@ public let SpeedBase: [KeyValue_t] = [
|
||||
KeyValue_t(key: "byte", value: "Byte", additional: DataSizeBase.byte)
|
||||
]
|
||||
|
||||
public enum StackMode: String {
|
||||
internal enum StackMode: String {
|
||||
case auto = "automatic"
|
||||
case oneRow = "oneRow"
|
||||
case twoRows = "twoRows"
|
||||
}
|
||||
|
||||
public let SensorsWidgetMode: [KeyValue_t] = [
|
||||
internal let SensorsWidgetMode: [KeyValue_t] = [
|
||||
KeyValue_t(key: StackMode.auto.rawValue, value: "Automatic"),
|
||||
KeyValue_t(key: "separator", value: "separator"),
|
||||
KeyValue_t(key: StackMode.oneRow.rawValue, value: "One row"),
|
||||
KeyValue_t(key: StackMode.twoRows.rawValue, value: "Two rows")
|
||||
]
|
||||
|
||||
public let SpeedPictogram: [KeyValue_t] = [
|
||||
internal let SpeedPictogram: [KeyValue_t] = [
|
||||
KeyValue_t(key: "none", value: "None"),
|
||||
KeyValue_t(key: "separator", value: "separator"),
|
||||
KeyValue_t(key: "dots", value: "Dots"),
|
||||
@@ -117,7 +117,7 @@ public let SpeedPictogram: [KeyValue_t] = [
|
||||
KeyValue_t(key: "chars", value: "Characters")
|
||||
]
|
||||
|
||||
public let BatteryAdditionals: [KeyValue_t] = [
|
||||
internal let BatteryAdditionals: [KeyValue_t] = [
|
||||
KeyValue_t(key: "none", value: "None"),
|
||||
KeyValue_t(key: "separator", value: "separator"),
|
||||
KeyValue_t(key: "innerPercentage", value: "Percentage inside the icon"),
|
||||
@@ -128,7 +128,7 @@ public let BatteryAdditionals: [KeyValue_t] = [
|
||||
KeyValue_t(key: "timeAndPercentage", value: "Time and percentage")
|
||||
]
|
||||
|
||||
public let BatteryInfo: [KeyValue_t] = [
|
||||
internal let BatteryInfo: [KeyValue_t] = [
|
||||
KeyValue_t(key: "percentage", value: "Percentage"),
|
||||
KeyValue_t(key: "time", value: "Time"),
|
||||
KeyValue_t(key: "percentageAndTime", value: "Percentage and time"),
|
||||
@@ -143,13 +143,12 @@ public let ShortLong: [KeyValue_t] = [
|
||||
public let ReaderUpdateIntervals: [Int] = [1, 2, 3, 5, 10, 15, 30, 60]
|
||||
public let NumbersOfProcesses: [Int] = [0, 3, 5, 8, 10, 15]
|
||||
|
||||
public typealias Bandwidth = (upload: Int64, download: Int64)
|
||||
public let NetworkReaders: [KeyValue_t] = [
|
||||
KeyValue_t(key: "interface", value: "Interface based"),
|
||||
KeyValue_t(key: "process", value: "Processes based")
|
||||
]
|
||||
|
||||
public let Alignments: [KeyValue_t] = [
|
||||
internal let Alignments: [KeyValue_t] = [
|
||||
KeyValue_t(key: "left", value: "Left alignment", additional: NSTextAlignment.left),
|
||||
KeyValue_t(key: "center", value: "Center alignment", additional: NSTextAlignment.center),
|
||||
KeyValue_t(key: "right", value: "Right alignment", additional: NSTextAlignment.right)
|
||||
@@ -226,19 +225,14 @@ extension Color: CaseIterable {
|
||||
]
|
||||
}
|
||||
|
||||
public static var random: Color {
|
||||
Color.allColors[.random(in: 0...Color.allColors.count)]
|
||||
}
|
||||
|
||||
public static func fromString(_ key: String, defaultValue: Color = .systemAccent) -> Color {
|
||||
return Color.allCases.first{ $0.key == key } ?? defaultValue
|
||||
}
|
||||
}
|
||||
|
||||
public class MonochromeColor {
|
||||
static public let base: NSColor = NSColor.textColor
|
||||
static public let red: NSColor = NSColor(red: (145), green: (145), blue: (145), alpha: 1)
|
||||
static public let blue: NSColor = NSColor(red: (113), green: (113), blue: (113), alpha: 1)
|
||||
internal class MonochromeColor {
|
||||
static internal let red: NSColor = NSColor(red: (145), green: (145), blue: (145), alpha: 1)
|
||||
static internal let blue: NSColor = NSColor(red: (113), green: (113), blue: (113), alpha: 1)
|
||||
}
|
||||
|
||||
public typealias colorZones = (orange: Double, red: Double)
|
||||
@@ -295,7 +289,6 @@ public let notificationLevels: [KeyValue_t] = [
|
||||
public struct Scale: KeyValue_p, Equatable {
|
||||
public let key: String
|
||||
public let value: String
|
||||
public var additional: Any?
|
||||
|
||||
public static func == (lhs: Scale, rhs: Scale) -> Bool {
|
||||
return lhs.key == rhs.key
|
||||
@@ -341,7 +334,6 @@ public var LineChartHistory: [KeyValue_p] = [
|
||||
public struct SizeUnit: KeyValue_p, Equatable {
|
||||
public let key: String
|
||||
public let value: String
|
||||
public var additional: Any?
|
||||
|
||||
public static func == (lhs: SizeUnit, rhs: SizeUnit) -> Bool {
|
||||
return lhs.key == rhs.key
|
||||
|
||||
@@ -13,7 +13,7 @@ import Cocoa
|
||||
import Kit
|
||||
import IOKit.ps
|
||||
|
||||
struct Battery_Usage: value_t, Codable {
|
||||
struct Battery_Usage: Codable {
|
||||
var powerSource: String = ""
|
||||
var state: String? = nil
|
||||
var isCharged: Bool = false
|
||||
@@ -37,12 +37,6 @@ struct Battery_Usage: value_t, Codable {
|
||||
var timeToEmpty: Int = 0
|
||||
var timeToCharge: Int = 0
|
||||
var timeOnACPower: Date? = nil
|
||||
|
||||
public var widgetValue: Double {
|
||||
get {
|
||||
return self.level
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class Battery: Module {
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
import Cocoa
|
||||
import Kit
|
||||
|
||||
public struct CPU_Load: value_t, Codable {
|
||||
public struct CPU_Load: Codable {
|
||||
var totalUsage: Double = 0
|
||||
var usagePerCore: [Double] = []
|
||||
var usageECores: Double? = nil
|
||||
@@ -18,12 +18,6 @@ public struct CPU_Load: value_t, Codable {
|
||||
var systemLoad: Double = 0
|
||||
var userLoad: Double = 0
|
||||
var idleLoad: Double = 0
|
||||
|
||||
public var widgetValue: Double {
|
||||
get {
|
||||
return self.totalUsage
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public struct CPU_Limit: Codable {
|
||||
|
||||
@@ -173,14 +173,7 @@ internal class Settings: NSStackView, Settings_v {
|
||||
}
|
||||
|
||||
@objc func toggleUsagePerCore(_ 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.usagePerCoreState = state! == .on ? true : false
|
||||
self.usagePerCoreState = controlState(sender)
|
||||
Store.shared.set(key: "\(self.title)_usagePerCore", value: self.usagePerCoreState)
|
||||
self.callback()
|
||||
|
||||
@@ -205,53 +198,25 @@ internal class Settings: NSStackView, Settings_v {
|
||||
}
|
||||
|
||||
@objc func toggleMultithreading(_ 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.hyperthreadState = state! == .on ? true : false
|
||||
self.hyperthreadState = controlState(sender)
|
||||
Store.shared.set(key: "\(self.title)_hyperhreading", value: self.hyperthreadState)
|
||||
self.callback()
|
||||
}
|
||||
|
||||
@objc func toggleIPG(_ 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.IPGState = state! == .on ? true : false
|
||||
self.IPGState = controlState(sender)
|
||||
Store.shared.set(key: "\(self.title)_IPG", value: self.IPGState)
|
||||
self.IPGCallback(self.IPGState)
|
||||
}
|
||||
|
||||
@objc func toggleSplitValue(_ 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.splitValueState = state! == .on ? true : false
|
||||
self.splitValueState = controlState(sender)
|
||||
Store.shared.set(key: "\(self.title)_splitValue", value: self.splitValueState)
|
||||
self.callback()
|
||||
}
|
||||
|
||||
@objc func toggleClustersGroup(_ 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.clustersGroupState = state! == .on ? true : false
|
||||
self.clustersGroupState = controlState(sender)
|
||||
Store.shared.set(key: "\(self.title)_clustersGroup", value: self.clustersGroupState)
|
||||
|
||||
self.splitValueView?.isEnabled = !(self.usagePerCoreState || self.clustersGroupState)
|
||||
|
||||
@@ -238,12 +238,6 @@ public class Disk: Module {
|
||||
self.setReaders([self.capacityReader, self.activityReader, self.processReader])
|
||||
}
|
||||
|
||||
public override func widgetDidSet(_ type: widget_t) {
|
||||
if type == .speed && self.capacityReader?.interval != 1 {
|
||||
self.settingsView.setUpdateInterval(value: 1)
|
||||
}
|
||||
}
|
||||
|
||||
private func capacityCallback(_ value: Disks) {
|
||||
guard self.enabled else { return }
|
||||
|
||||
@@ -289,8 +283,16 @@ public class Disk: Module {
|
||||
|
||||
self.menuBar.widgets.filter{ $0.isActive }.forEach { (w: Widget) in
|
||||
switch w.item {
|
||||
case let widget as SpeedWidget: widget.setValue(upload: d.activity.write, download: d.activity.read)
|
||||
case let widget as NetworkChart: widget.setValue(upload: Double(d.activity.write), download: Double(d.activity.read))
|
||||
case let widget as SpeedWidget:
|
||||
widget.setValue(upload: d.activity.write, download: d.activity.read)
|
||||
if self.capacityReader?.interval != 1 {
|
||||
self.settingsView.setUpdateInterval(value: 1)
|
||||
}
|
||||
case let widget as NetworkChart:
|
||||
widget.setValue(upload: Double(d.activity.write), download: Double(d.activity.read))
|
||||
if self.capacityReader?.interval != 1 {
|
||||
self.settingsView.setUpdateInterval(value: 1)
|
||||
}
|
||||
default: break
|
||||
}
|
||||
}
|
||||
|
||||
@@ -50,18 +50,12 @@ public struct GPU_Info: Codable {
|
||||
}
|
||||
}
|
||||
|
||||
public struct GPUs: value_t, Codable {
|
||||
public struct GPUs: Codable {
|
||||
public var list: [GPU_Info] = []
|
||||
|
||||
internal func active() -> [GPU_Info] {
|
||||
return self.list.filter{ $0.state && $0.utilization != nil }.sorted{ $0.utilization ?? 0 > $1.utilization ?? 0 }
|
||||
}
|
||||
|
||||
public var widgetValue: Double {
|
||||
get {
|
||||
return list.isEmpty ? 0 : (list[0].utilization ?? 0)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class GPU: Module {
|
||||
|
||||
@@ -66,7 +66,7 @@ public struct Bandwidth: Codable {
|
||||
var download: Int64 = 0
|
||||
}
|
||||
|
||||
public struct Network_Usage: value_t, Codable {
|
||||
public struct Network_Usage: Codable {
|
||||
var bandwidth: Bandwidth = Bandwidth()
|
||||
var total: Bandwidth = Bandwidth()
|
||||
|
||||
@@ -90,8 +90,6 @@ public struct Network_Usage: value_t, Codable {
|
||||
|
||||
self.wifiDetails.reset()
|
||||
}
|
||||
|
||||
public var widgetValue: Double = 0
|
||||
}
|
||||
|
||||
public struct Network_Connectivity: Codable {
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
import Cocoa
|
||||
import Kit
|
||||
|
||||
public struct RAM_Usage: value_t, Codable {
|
||||
public struct RAM_Usage: Codable {
|
||||
var total: Double
|
||||
var used: Double
|
||||
var free: Double
|
||||
@@ -29,12 +29,6 @@ public struct RAM_Usage: value_t, Codable {
|
||||
var rawPressureLevel: UInt
|
||||
var swap: Swap
|
||||
|
||||
public var widgetValue: Double {
|
||||
get {
|
||||
return self.usage
|
||||
}
|
||||
}
|
||||
|
||||
public var usage: Double {
|
||||
get {
|
||||
return Double((self.total - self.free) / self.total)
|
||||
|
||||
@@ -112,7 +112,7 @@ public class Sensors: Module {
|
||||
value = "\(f.percentage)%"
|
||||
}
|
||||
}
|
||||
list.append(Stack_t(key: s.key, value: value, additional: s.name))
|
||||
list.append(Stack_t(key: s.key, value: value))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -171,7 +171,7 @@ class ApplicationSettings: NSStackView {
|
||||
NotificationCenter.default.removeObserver(self, name: .fanHelperState, object: nil)
|
||||
}
|
||||
|
||||
public func viewWillAppear() {
|
||||
internal func viewWillAppear() {
|
||||
self.startAtLoginBtn?.state = LaunchAtLogin.isEnabled ? .on : .off
|
||||
self.telemetryBtn?.state = telemetry.isEnabled ? .on : .off
|
||||
|
||||
@@ -240,7 +240,7 @@ class ApplicationSettings: NSStackView {
|
||||
|
||||
// MARK: - actions
|
||||
|
||||
@objc private func updateAction(_ sender: NSObject) {
|
||||
@objc private func updateAction() {
|
||||
updater.check(force: true, completion: { result, error in
|
||||
if error != nil {
|
||||
debug("error updater.check(): \(error!.localizedDescription)")
|
||||
@@ -309,7 +309,7 @@ class ApplicationSettings: NSStackView {
|
||||
NotificationCenter.default.post(name: .combinedModulesPopup, object: nil, userInfo: nil)
|
||||
}
|
||||
|
||||
@objc private func importSettings(_ sender: NSObject) {
|
||||
@objc private func importSettings() {
|
||||
let panel = NSOpenPanel()
|
||||
panel.level = NSWindow.Level(rawValue: Int(CGWindowLevelForKey(.modalPanelWindow)))
|
||||
panel.begin { (result) in
|
||||
@@ -320,7 +320,7 @@ class ApplicationSettings: NSStackView {
|
||||
}
|
||||
}
|
||||
|
||||
@objc private func exportSettings(_ sender: NSObject) {
|
||||
@objc private func exportSettings() {
|
||||
let panel = NSSavePanel()
|
||||
panel.nameFieldStringValue = "Stats.plist"
|
||||
panel.showsTagField = false
|
||||
@@ -333,7 +333,7 @@ class ApplicationSettings: NSStackView {
|
||||
}
|
||||
}
|
||||
|
||||
@objc private func resetSettings(_ sender: NSObject) {
|
||||
@objc private func resetSettings() {
|
||||
let alert = NSAlert()
|
||||
alert.messageText = localizedString("Reset settings")
|
||||
alert.informativeText = localizedString("Reset settings text")
|
||||
@@ -482,12 +482,10 @@ private class ModuleSelectorView: NSStackView {
|
||||
}
|
||||
}
|
||||
|
||||
internal class ModulePreview: NSStackView {
|
||||
private let id: String
|
||||
private class ModulePreview: NSStackView {
|
||||
private let imageView: NSImageView
|
||||
|
||||
public init(id: String, icon: NSImage?) {
|
||||
self.id = id
|
||||
fileprivate init(id: String, icon: NSImage?) {
|
||||
self.imageView = NSImageView(frame: NSRect(origin: .zero, size: NSSize(width: Constants.Widget.height, height: Constants.Widget.height)))
|
||||
|
||||
let size: CGSize = CGSize(width: Constants.Widget.height + (Constants.Widget.spacing * 2), height: Constants.Widget.height)
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
import Cocoa
|
||||
import Kit
|
||||
|
||||
class CombinedView: NSObject, NSGestureRecognizerDelegate {
|
||||
internal class CombinedView: NSObject, NSGestureRecognizerDelegate {
|
||||
private var menuBarItem: NSStatusItem? = nil
|
||||
private var view: NSView = NSView(frame: NSRect(x: 0, y: 0, width: 0, height: Constants.Widget.height))
|
||||
private var popup: PopupWindow? = nil
|
||||
@@ -194,7 +194,8 @@ class CombinedView: NSObject, NSGestureRecognizerDelegate {
|
||||
}
|
||||
|
||||
private class Popup: NSStackView, Popup_p {
|
||||
public var sizeCallback: ((NSSize) -> Void)? = nil
|
||||
fileprivate var sizeCallback: ((NSSize) -> Void)? = nil
|
||||
let log = NextLog(writer: .file)
|
||||
|
||||
init() {
|
||||
super.init(frame: NSRect(x: 0, y: 0, width: Constants.Popup.width, height: 0))
|
||||
@@ -217,16 +218,18 @@ private class Popup: NSStackView, Popup_p {
|
||||
NotificationCenter.default.removeObserver(self, name: .toggleOneView, object: nil)
|
||||
}
|
||||
|
||||
public func settings() -> NSView? { return nil }
|
||||
public func appear() {}
|
||||
public func disappear() {}
|
||||
fileprivate func settings() -> NSView? { return nil }
|
||||
fileprivate func appear() {}
|
||||
fileprivate func disappear() {}
|
||||
|
||||
@objc private func reinit() {
|
||||
self.subviews.forEach({ $0.removeFromSuperview() })
|
||||
|
||||
let availableModules = modules.filter({ $0.enabled && $0.portal != nil })
|
||||
debug("modules: \(availableModules.count)", log: self.log)
|
||||
availableModules.forEach { (m: Module) in
|
||||
if let p = m.portal {
|
||||
debug("adding: \(m.name) portal", log: self.log)
|
||||
self.addArrangedSubview(p)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -224,6 +224,7 @@ class Dashboard: NSStackView {
|
||||
osField.alignment = .center
|
||||
osField.font = NSFont.systemFont(ofSize: 12, weight: .regular)
|
||||
osField.stringValue = "macOS \(SystemKit.shared.device.os?.name ?? localizedString("Unknown")) (\(SystemKit.shared.device.os?.version.getFullVersion() ?? ""))"
|
||||
osField.toolTip = SystemKit.shared.device.os?.build ?? localizedString("Unknown")
|
||||
osField.isSelectable = true
|
||||
|
||||
container.addRow(with: [deviceImageView])
|
||||
|
||||
@@ -211,7 +211,7 @@ class SettingsWindow: NSWindow, NSWindowDelegate, NSToolbarDelegate {
|
||||
}
|
||||
}
|
||||
|
||||
public func setModules() {
|
||||
internal func setModules() {
|
||||
self.sidebarView.setModules(modules)
|
||||
if !self.pauseState && modules.filter({ $0.enabled != false && $0.available != false && !$0.menuBar.widgets.filter({ $0.isActive }).isEmpty }).isEmpty {
|
||||
self.setIsVisible(true)
|
||||
@@ -229,7 +229,7 @@ class SettingsWindow: NSWindow, NSWindowDelegate, NSToolbarDelegate {
|
||||
// MARK: - MainView
|
||||
|
||||
private class MainView: NSView {
|
||||
public let container: NSStackView
|
||||
fileprivate let container: NSStackView
|
||||
|
||||
override init(frame: NSRect) {
|
||||
self.container = NSStackView(frame: NSRect(x: 0, y: 0, width: frame.width, height: frame.height))
|
||||
@@ -251,7 +251,7 @@ private class MainView: NSView {
|
||||
fatalError("init(coder:) has not been implemented")
|
||||
}
|
||||
|
||||
public func setView(_ view: NSView) {
|
||||
fileprivate func setView(_ view: NSView) {
|
||||
self.container.subviews.forEach{ $0.removeFromSuperview() }
|
||||
self.container.addArrangedSubview(view)
|
||||
|
||||
@@ -380,7 +380,7 @@ private class SidebarView: NSStackView {
|
||||
fatalError("init(coder:) has not been implemented")
|
||||
}
|
||||
|
||||
public func openMenu(_ title: String) {
|
||||
fileprivate func openMenu(_ title: String) {
|
||||
self.scrollView.stackView.subviews.forEach({ (m: NSView) in
|
||||
if let menu = m as? MenuItem {
|
||||
if menu.title == title {
|
||||
@@ -392,7 +392,7 @@ private class SidebarView: NSStackView {
|
||||
})
|
||||
}
|
||||
|
||||
public func setModules(_ list: [Module]) {
|
||||
fileprivate func setModules(_ list: [Module]) {
|
||||
list.reversed().forEach { (m: Module) in
|
||||
if !m.available { return }
|
||||
let menu: NSView = MenuItem(icon: m.config.icon, title: m.config.name)
|
||||
@@ -460,26 +460,7 @@ private class SidebarView: NSStackView {
|
||||
return vc
|
||||
}
|
||||
|
||||
private func supportButton(name: String, image: String, action: Selector) -> NSButton {
|
||||
let button = NSButtonWithPadding()
|
||||
button.frame = CGRect(x: 0, y: 0, width: 24, height: 24)
|
||||
button.verticalPadding = 16
|
||||
button.horizontalPadding = 16
|
||||
button.title = name
|
||||
button.toolTip = name
|
||||
button.bezelStyle = .regularSquare
|
||||
button.translatesAutoresizingMaskIntoConstraints = false
|
||||
button.imageScaling = .scaleNone
|
||||
button.image = Bundle(for: type(of: self)).image(forResource: image)!
|
||||
button.isBordered = false
|
||||
button.target = self
|
||||
button.focusRingType = .none
|
||||
button.action = action
|
||||
|
||||
return button
|
||||
}
|
||||
|
||||
@objc private func reportBug(_ sender: Any) {
|
||||
@objc private func reportBug() {
|
||||
NSWorkspace.shared.open(URL(string: "https://github.com/exelban/stats/issues/new")!)
|
||||
}
|
||||
|
||||
@@ -487,11 +468,11 @@ private class SidebarView: NSStackView {
|
||||
self.supportPopover.show(relativeTo: sender.bounds, of: sender, preferredEdge: NSRectEdge.minY)
|
||||
}
|
||||
|
||||
@objc private func closeApp(_ sender: Any) {
|
||||
@objc private func closeApp(_ sender: NSButton) {
|
||||
NSApp.terminate(sender)
|
||||
}
|
||||
|
||||
@objc private func togglePause(_ sender: NSButton) {
|
||||
@objc private func togglePause() {
|
||||
self.pauseState = !self.pauseState
|
||||
self.pauseButton?.toolTip = localizedString(self.pauseState ? "Resume the Stats" : "Pause the Stats")
|
||||
self.pauseButton?.image = self.pauseState ? self.resumeIcon : self.pauseIcon
|
||||
@@ -505,9 +486,9 @@ private class SidebarView: NSStackView {
|
||||
}
|
||||
|
||||
private class MenuItem: NSView {
|
||||
public let title: String
|
||||
public var active: Bool = false
|
||||
fileprivate let title: String
|
||||
|
||||
private var active: Bool = false
|
||||
private var imageView: NSImageView? = nil
|
||||
private var titleView: NSTextField? = nil
|
||||
|
||||
@@ -560,7 +541,7 @@ private class MenuItem: NSView {
|
||||
self.activate()
|
||||
}
|
||||
|
||||
public func activate() {
|
||||
fileprivate func activate() {
|
||||
guard !self.active else { return }
|
||||
self.active = true
|
||||
|
||||
@@ -571,7 +552,7 @@ private class MenuItem: NSView {
|
||||
self.titleView?.textColor = .white
|
||||
}
|
||||
|
||||
public func reset() {
|
||||
fileprivate func reset() {
|
||||
self.layer?.backgroundColor = .clear
|
||||
self.imageView?.contentTintColor = .labelColor
|
||||
self.titleView?.textColor = .labelColor
|
||||
|
||||
@@ -15,11 +15,11 @@ import Kit
|
||||
private let setupSize: CGSize = CGSize(width: 600, height: 400)
|
||||
|
||||
internal class SetupWindow: NSWindow, NSWindowDelegate {
|
||||
internal var finishHandler: () -> Void = {}
|
||||
|
||||
private let view: SetupContainer = SetupContainer()
|
||||
private let vc: NSViewController = NSViewController(nibName: nil, bundle: nil)
|
||||
|
||||
public var finishHandler: () -> Void = {}
|
||||
|
||||
init() {
|
||||
self.vc.view = self.view
|
||||
|
||||
@@ -44,12 +44,12 @@ internal class SetupWindow: NSWindow, NSWindowDelegate {
|
||||
windowController.loadWindow()
|
||||
}
|
||||
|
||||
public func show() {
|
||||
internal func show() {
|
||||
self.setIsVisible(true)
|
||||
self.orderFrontRegardless()
|
||||
}
|
||||
|
||||
public func hide() {
|
||||
internal func hide() {
|
||||
self.close()
|
||||
}
|
||||
|
||||
@@ -496,10 +496,10 @@ private class SetupView_end: NSStackView {
|
||||
}
|
||||
}
|
||||
|
||||
public class SupportButtonView: NSButton {
|
||||
public var callback: (() -> Void) = {}
|
||||
internal class SupportButtonView: NSButton {
|
||||
internal var callback: (() -> Void) = {}
|
||||
|
||||
public init(name: String, image: String, action: @escaping () -> Void) {
|
||||
init(name: String, image: String, action: @escaping () -> Void) {
|
||||
self.callback = action
|
||||
|
||||
super.init(frame: NSRect(x: 0, y: 0, width: 30, height: 30))
|
||||
@@ -544,7 +544,7 @@ public class SupportButtonView: NSButton {
|
||||
NSCursor.arrow.set()
|
||||
}
|
||||
|
||||
@objc private func click(_ sender: NSControl) {
|
||||
@objc private func click() {
|
||||
self.callback()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
import Cocoa
|
||||
import Kit
|
||||
|
||||
class UpdateWindow: NSWindow, NSWindowDelegate {
|
||||
internal class UpdateWindow: NSWindow, NSWindowDelegate {
|
||||
private let viewController: UpdateViewController = UpdateViewController()
|
||||
|
||||
init() {
|
||||
@@ -39,7 +39,7 @@ class UpdateWindow: NSWindow, NSWindowDelegate {
|
||||
windowController.loadWindow()
|
||||
}
|
||||
|
||||
public func open(_ v: version_s, settingButton: Bool = false) {
|
||||
internal func open(_ v: version_s, settingButton: Bool = false) {
|
||||
if !self.isVisible || settingButton {
|
||||
self.setIsVisible(true)
|
||||
self.makeKeyAndOrderFront(nil)
|
||||
@@ -68,7 +68,7 @@ private class UpdateViewController: NSViewController {
|
||||
fatalError("init(coder:) has not been implemented")
|
||||
}
|
||||
|
||||
public func open(_ v: version_s) {
|
||||
internal func open(_ v: version_s) {
|
||||
self.update.clear()
|
||||
|
||||
if v.newest {
|
||||
@@ -99,7 +99,7 @@ private class UpdateView: NSView {
|
||||
fatalError("init(coder:) has not been implemented")
|
||||
}
|
||||
|
||||
public func newVersion(_ version: version_s) {
|
||||
internal func newVersion(_ version: version_s) {
|
||||
self.version = version
|
||||
let view: NSStackView = NSStackView(frame: NSRect(
|
||||
x: Constants.Settings.margin,
|
||||
@@ -190,7 +190,7 @@ private class UpdateView: NSView {
|
||||
self.addSubview(view)
|
||||
}
|
||||
|
||||
public func noUpdates() {
|
||||
internal func noUpdates() {
|
||||
let view: NSView = NSView(frame: NSRect(x: 10, y: 10, width: self.frame.width - 20, height: self.frame.height - 20))
|
||||
|
||||
let title: NSTextField = TextView(frame: NSRect(x: 0, y: ((view.frame.height - 18)/2), width: view.frame.width, height: 34))
|
||||
@@ -209,11 +209,11 @@ private class UpdateView: NSView {
|
||||
self.addSubview(view)
|
||||
}
|
||||
|
||||
public func clear() {
|
||||
internal func clear() {
|
||||
self.subviews.filter{ !($0 is NSVisualEffectView) }.forEach{ $0.removeFromSuperview() }
|
||||
}
|
||||
|
||||
@objc private func download(_ sender: Any) {
|
||||
@objc private func download() {
|
||||
guard let urlString = self.version?.url, let url = URL(string: urlString) else {
|
||||
return
|
||||
}
|
||||
@@ -273,17 +273,17 @@ private class UpdateView: NSView {
|
||||
self.addSubview(view)
|
||||
}
|
||||
|
||||
@objc private func close(_ sender: Any) {
|
||||
@objc private func close() {
|
||||
self.window?.close()
|
||||
}
|
||||
|
||||
@objc private func changelog(_ sender: Any) {
|
||||
@objc private func changelog() {
|
||||
if let version = self.version {
|
||||
NSWorkspace.shared.open(URL(string: "https://github.com/exelban/stats/releases/tag/\(version.latest)")!)
|
||||
}
|
||||
}
|
||||
|
||||
@objc private func install(_ sender: Any) {
|
||||
@objc private func install() {
|
||||
updater.install(path: self.path) { error in
|
||||
if let error {
|
||||
showAlert("Error update Stats", error, .critical)
|
||||
|
||||
@@ -16,54 +16,54 @@ class RAM: XCTestCase {
|
||||
func testProcessReader_parseProcess() throws {
|
||||
var process = ProcessReader.parseProcess("3127 lldb-rpc-server 611M")
|
||||
XCTAssertEqual(process.pid, 3127)
|
||||
XCTAssertEqual(process.command, "lldb-rpc-server")
|
||||
XCTAssertEqual(process.name, "lldb-rpc-server")
|
||||
XCTAssertEqual(process.usage, 611 * Double(1024 * 1024))
|
||||
|
||||
process = ProcessReader.parseProcess("257 WindowServer 210M")
|
||||
XCTAssertEqual(process.pid, 257)
|
||||
XCTAssertEqual(process.command, "WindowServer")
|
||||
XCTAssertEqual(process.name, "WindowServer")
|
||||
XCTAssertEqual(process.usage, 210 * Double(1024 * 1024))
|
||||
|
||||
process = ProcessReader.parseProcess("7752 phpstorm 1819M")
|
||||
XCTAssertEqual(process.pid, 7752)
|
||||
XCTAssertEqual(process.command, "phpstorm")
|
||||
XCTAssertEqual(process.name, "phpstorm")
|
||||
XCTAssertEqual(process.usage, 1819 * Double(1024 * 1024))
|
||||
|
||||
process = ProcessReader.parseProcess("359 NotificationCent 62M")
|
||||
XCTAssertEqual(process.pid, 359)
|
||||
XCTAssertEqual(process.command, "NotificationCent")
|
||||
XCTAssertEqual(process.name, "NotificationCent")
|
||||
XCTAssertEqual(process.usage, 62 * Double(1024 * 1024))
|
||||
|
||||
process = ProcessReader.parseProcess("623 SafariCloudHisto 1608K")
|
||||
XCTAssertEqual(process.pid, 623)
|
||||
XCTAssertEqual(process.command, "SafariCloudHisto")
|
||||
XCTAssertEqual(process.name, "SafariCloudHisto")
|
||||
XCTAssertEqual(process.usage, (1608/1024) * Double(1024 * 1024))
|
||||
|
||||
process = ProcessReader.parseProcess("174 WindowServer 1442M+ ")
|
||||
XCTAssertEqual(process.pid, 174)
|
||||
XCTAssertEqual(process.command, "WindowServer")
|
||||
XCTAssertEqual(process.name, "WindowServer")
|
||||
XCTAssertEqual(process.usage, 1442 * Double(1024 * 1024))
|
||||
|
||||
process = ProcessReader.parseProcess("329 Finder 488M+ ")
|
||||
XCTAssertEqual(process.pid, 329)
|
||||
XCTAssertEqual(process.command, "Finder")
|
||||
XCTAssertEqual(process.name, "Finder")
|
||||
XCTAssertEqual(process.usage, 488 * Double(1024 * 1024))
|
||||
|
||||
process = ProcessReader.parseProcess("7163* AutoCAD LT 2023 11G ")
|
||||
XCTAssertEqual(process.pid, 7163)
|
||||
XCTAssertEqual(process.command, "AutoCAD LT 2023")
|
||||
XCTAssertEqual(process.name, "AutoCAD LT 2023")
|
||||
XCTAssertEqual(process.usage, 11 * Double(1024 * 1024 * 1024))
|
||||
}
|
||||
|
||||
func testKernelTask() throws {
|
||||
var process = ProcessReader.parseProcess("0 kernel_task 270M ")
|
||||
XCTAssertEqual(process.pid, 0)
|
||||
XCTAssertEqual(process.command, "kernel_task")
|
||||
XCTAssertEqual(process.name, "kernel_task")
|
||||
XCTAssertEqual(process.usage, 270 * Double(1024 * 1024))
|
||||
|
||||
process = ProcessReader.parseProcess("0 kernel_task 280M")
|
||||
XCTAssertEqual(process.pid, 0)
|
||||
XCTAssertEqual(process.command, "kernel_task")
|
||||
XCTAssertEqual(process.name, "kernel_task")
|
||||
XCTAssertEqual(process.usage, 280 * Double(1024 * 1024))
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user