From 4c35eafd00adfdfa1d65f0aee927351aecb59001 Mon Sep 17 00:00:00 2001 From: Serhiy Mytrovtsiy Date: Fri, 19 Jan 2024 21:05:48 +0100 Subject: [PATCH] feat: added portal view (combined view mode) to the sensors module --- Kit/module/popup.swift | 4 -- Modules/Sensors/main.swift | 7 +++ Modules/Sensors/popup.swift | 4 +- Modules/Sensors/portal.swift | 93 +++++++++++++++++++++++++++++++++ Stats.xcodeproj/project.pbxproj | 4 ++ 5 files changed, 106 insertions(+), 6 deletions(-) create mode 100644 Modules/Sensors/portal.swift diff --git a/Kit/module/popup.swift b/Kit/module/popup.swift index 77c64454..63037bdb 100644 --- a/Kit/module/popup.swift +++ b/Kit/module/popup.swift @@ -98,10 +98,6 @@ internal class PopupViewController: NSViewController { self.view = self.popup } - override func viewDidLoad() { - super.viewDidLoad() - } - override func viewWillAppear() { super.viewWillAppear() diff --git a/Modules/Sensors/main.swift b/Modules/Sensors/main.swift index 5f542de1..834ba50a 100644 --- a/Modules/Sensors/main.swift +++ b/Modules/Sensors/main.swift @@ -16,6 +16,7 @@ public class Sensors: Module { private let sensorsReader: SensorsReader private let popupView: Popup private let settingsView: Settings + private let portalView: Portal private let notificationsView: Notifications private var fanValueState: FanValue { @@ -26,16 +27,19 @@ public class Sensors: Module { self.sensorsReader = SensorsReader() self.settingsView = Settings("Sensors", list: self.sensorsReader.list.sensors) self.popupView = Popup() + self.portalView = Portal(.sensors) self.notificationsView = Notifications(.sensors) super.init( popup: self.popupView, settings: self.settingsView, + portal: self.portalView, notifications: self.notificationsView ) guard self.available else { return } self.popupView.setup(self.sensorsReader.list.sensors) + self.portalView.setup(self.sensorsReader.list.sensors) self.notificationsView.setup(self.sensorsReader.list.sensors) self.settingsView.callback = { [weak self] in @@ -49,6 +53,7 @@ public class Sensors: Module { self?.sensorsReader.HIDCallback() DispatchQueue.main.async { self?.popupView.setup(self?.sensorsReader.list.sensors) + self?.portalView.setup(self?.sensorsReader.list.sensors) self?.settingsView.setList(list: self?.sensorsReader.list.sensors ?? []) self?.notificationsView.setup(self?.sensorsReader.list.sensors) } @@ -59,6 +64,7 @@ public class Sensors: Module { self?.sensorsReader.unknownCallback() DispatchQueue.main.async { self?.popupView.setup(self?.sensorsReader.list.sensors) + self?.portalView.setup(self?.sensorsReader.list.sensors) self?.settingsView.setList(list: self?.sensorsReader.list.sensors ?? []) self?.notificationsView.setup(self?.sensorsReader.list.sensors) } @@ -117,6 +123,7 @@ public class Sensors: Module { } self.popupView.usageCallback(value.sensors) + self.portalView.usageCallback(value.sensors) self.notificationsView.usageCallback(value.sensors) self.menuBar.widgets.filter{ $0.isActive }.forEach { (w: Widget) in diff --git a/Modules/Sensors/popup.swift b/Modules/Sensors/popup.swift index 2f16a312..3b2ef270 100644 --- a/Modules/Sensors/popup.swift +++ b/Modules/Sensors/popup.swift @@ -352,11 +352,11 @@ internal class ValueSensorView: NSStackView { public var callback: (() -> Void) private var labelView: LabelField = { - let view = LabelField(frame: NSRect(x: 0, y: 0, width: 0, height: 0)) + let view = LabelField(frame: NSRect.zero) view.cell?.truncatesLastVisibleLine = true return view }() - private var valueView: ValueField = ValueField(frame: NSRect(x: 0, y: 0, width: 0, height: 0)) + private var valueView: ValueField = ValueField(frame: NSRect.zero) public init(_ sensor: Sensor_p, width: CGFloat, callback: @escaping (() -> Void)) { self.callback = callback diff --git a/Modules/Sensors/portal.swift b/Modules/Sensors/portal.swift new file mode 100644 index 00000000..082c453d --- /dev/null +++ b/Modules/Sensors/portal.swift @@ -0,0 +1,93 @@ +// +// portal.swift +// Sensors +// +// Created by Serhiy Mytrovtsiy on 14/01/2024 +// Using Swift 5.0 +// Running on macOS 14.3 +// +// Copyright © 2024 Serhiy Mytrovtsiy. All rights reserved. +// + +import AppKit +import Kit + +public class Portal: NSStackView, Portal_p { + public var name: String + + private var initialized: Bool = false + private var container: ScrollableStackView = ScrollableStackView() + + private var list: [String: NSView] = [:] + + private var unknownSensorsState: Bool { + Store.shared.bool(key: "Sensors_unknown", defaultValue: false) + } + + init(_ name: ModuleType) { + self.name = name.rawValue + + super.init(frame: NSRect( x: 0, y: 0, width: Constants.Popup.width, height: Constants.Popup.portalHeight)) + + self.wantsLayer = true + self.layer?.backgroundColor = NSColor.windowBackgroundColor.cgColor + self.layer?.cornerRadius = 3 + + self.orientation = .vertical + self.distribution = .fillEqually + self.spacing = Constants.Popup.spacing*2 + self.edgeInsets = NSEdgeInsets( + top: Constants.Popup.spacing*2, + left: Constants.Popup.spacing*2, + bottom: Constants.Popup.spacing*2, + right: Constants.Popup.spacing*2 + ) + + self.container.stackView.spacing = 0 + + self.addArrangedSubview(PortalHeader(self.name)) + self.addArrangedSubview(self.container) + + self.heightAnchor.constraint(equalToConstant: Constants.Popup.portalHeight).isActive = true + } + + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + public override func updateLayer() { + self.layer?.backgroundColor = NSColor.windowBackgroundColor.cgColor + } + + public func setup(_ values: [Sensor_p]? = nil) { + guard var list = values else { return } + if !self.unknownSensorsState { + list = list.filter({ $0.group != .unknown }) + } + + if !self.list.isEmpty { + self.container.stackView.subviews.forEach({ $0.removeFromSuperview() }) + self.list = [:] + } + + let width: CGFloat = self.frame.width - self.edgeInsets.left - self.edgeInsets.right - Constants.Popup.margins + list.forEach { s in + let v = ValueSensorView(s, width: width, callback: {}) + self.container.stackView.addArrangedSubview(v) + self.list[s.key] = v + } + } + + public func usageCallback(_ values: [Sensor_p]) { + DispatchQueue.main.async(execute: { + if self.window?.isVisible ?? false { + values.forEach { (s: Sensor_p) in + if let v = self.list[s.key] as? ValueSensorView { + v.update(s.formattedPopupValue) + } + } + } + }) + } + +} diff --git a/Stats.xcodeproj/project.pbxproj b/Stats.xcodeproj/project.pbxproj index 3d5b710b..7f92eb61 100644 --- a/Stats.xcodeproj/project.pbxproj +++ b/Stats.xcodeproj/project.pbxproj @@ -27,6 +27,7 @@ 5C5647F82A3F6B100098FFE9 /* Telemetry.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5C5647F72A3F6B100098FFE9 /* Telemetry.swift */; }; 5C621D822B4770D6004ED7AF /* process.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5C621D812B4770D6004ED7AF /* process.swift */; }; 5C8E001029269C7F0027C75A /* protocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5CFE493829265055000F2856 /* protocol.swift */; }; + 5CA518382B543FE600EBCCC4 /* portal.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5CA518372B543FE600EBCCC4 /* portal.swift */; }; 5CD342F42B2F2FB700225631 /* notifications.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5CD342F32B2F2FB700225631 /* notifications.swift */; }; 5CF2210D2B1E7EAF006C583F /* notifications.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5CF2210C2B1E7EAF006C583F /* notifications.swift */; }; 5CF221132B1E8078006C583F /* notifications.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5CF221122B1E8078006C583F /* notifications.swift */; }; @@ -405,6 +406,7 @@ 5C5647F72A3F6B100098FFE9 /* Telemetry.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Telemetry.swift; sourceTree = ""; }; 5C621D812B4770D6004ED7AF /* process.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = process.swift; sourceTree = ""; }; 5C9F90A02A76B30500D41748 /* et */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = et; path = et.lproj/Localizable.strings; sourceTree = ""; }; + 5CA518372B543FE600EBCCC4 /* portal.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = portal.swift; sourceTree = ""; }; 5CD342F32B2F2FB700225631 /* notifications.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = notifications.swift; sourceTree = ""; }; 5CF2210C2B1E7EAF006C583F /* notifications.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = notifications.swift; sourceTree = ""; }; 5CF221122B1E8078006C583F /* notifications.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = notifications.swift; sourceTree = ""; }; @@ -1024,6 +1026,7 @@ 9AE29AF1249A50CD0071B02D /* main.swift */, 9AE29AF9249A53780071B02D /* readers.swift */, 9A58DE9D24B363D800716A9F /* popup.swift */, + 5CA518372B543FE600EBCCC4 /* portal.swift */, 9A58DE9F24B363F300716A9F /* settings.swift */, 9AE29AF7249A53420071B02D /* values.swift */, 5CF2211A2B1F8CEF006C583F /* notifications.swift */, @@ -1880,6 +1883,7 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( + 5CA518382B543FE600EBCCC4 /* portal.swift in Sources */, 5CF2211B2B1F8CEF006C583F /* notifications.swift in Sources */, 9A46C05F266D85F8001A1117 /* smc.swift in Sources */, 9AB6D03926447CAA003215A5 /* reader.m in Sources */,