From bf2501615b6c41ca0d04a534e739b7a795401f3e Mon Sep 17 00:00:00 2001 From: Gao Sun Date: Wed, 2 Dec 2020 00:16:43 +0800 Subject: [PATCH] Add fan status component config --- Resource/ar.lproj/Localizable.strings | 1 + Resource/de.lproj/Localizable.strings | 1 + Resource/en.lproj/Localizable.strings | 1 + Resource/es.lproj/Localizable.strings | 1 + Resource/fr.lproj/Localizable.strings | 1 + Resource/ja.lproj/Localizable.strings | 1 + Resource/ko.lproj/Localizable.strings | 1 + Resource/mn.lproj/Localizable.strings | 1 + Resource/pt.lproj/Localizable.strings | 1 + Resource/ru.lproj/Localizable.strings | 1 + Resource/zh-Hans.lproj/Localizable.strings | 1 + eul.xcodeproj/project.pbxproj | 16 +++ eul/AppDelegate.swift | 2 +- eul/Extension/Array.swift | 15 +++ eul/Schema/EulComponent.swift | 7 +- eul/Schema/FanData.swift | 29 +++++ eul/Schema/TemperatureData.swift | 20 ++++ .../TextComponents/FanTextComponent.swift | 48 ++++++++ eul/Store/FanStore.swift | 2 +- eul/Store/SharedStore.swift | 5 + eul/Utilities/SmcControl.swift | 107 ++++++++++-------- .../PreferenceComponentConfigView.swift | 6 +- eul/Views/StatusBar/FanView.swift | 23 +++- 23 files changed, 232 insertions(+), 59 deletions(-) create mode 100644 eul/Extension/Array.swift create mode 100644 eul/Schema/FanData.swift create mode 100644 eul/Schema/TemperatureData.swift create mode 100644 eul/Schema/TextComponents/FanTextComponent.swift diff --git a/Resource/ar.lproj/Localizable.strings b/Resource/ar.lproj/Localizable.strings index 0f1bd8db..a514c117 100644 --- a/Resource/ar.lproj/Localizable.strings +++ b/Resource/ar.lproj/Localizable.strings @@ -170,6 +170,7 @@ "text_component.loadAverage1Min" = "Load Average (1 min)"; "text_component.loadAverage5Min" = "Load Average (5 min)"; "text_component.loadAverage15Min" = "Load Average (15 min)"; +"text_component.average" = "Average"; // MARK: CPU Display Mode "cpu_display_mode" = "CPU Display Mode"; diff --git a/Resource/de.lproj/Localizable.strings b/Resource/de.lproj/Localizable.strings index f8ec1ba6..fd072128 100644 --- a/Resource/de.lproj/Localizable.strings +++ b/Resource/de.lproj/Localizable.strings @@ -169,6 +169,7 @@ "text_component.loadAverage1Min" = "Load Average (1 min)"; "text_component.loadAverage5Min" = "Load Average (5 min)"; "text_component.loadAverage15Min" = "Load Average (15 min)"; +"text_component.average" = "Average"; // MARK: CPU Display Mode "cpu_display_mode" = "CPU Display Mode"; diff --git a/Resource/en.lproj/Localizable.strings b/Resource/en.lproj/Localizable.strings index 155d60d2..b9f5fcf2 100644 --- a/Resource/en.lproj/Localizable.strings +++ b/Resource/en.lproj/Localizable.strings @@ -168,6 +168,7 @@ "text_component.loadAverage1Min" = "Load Average (1 min)"; "text_component.loadAverage5Min" = "Load Average (5 min)"; "text_component.loadAverage15Min" = "Load Average (15 min)"; +"text_component.average" = "Average"; // MARK: CPU Display Mode "cpu_display_mode" = "CPU Display Mode"; diff --git a/Resource/es.lproj/Localizable.strings b/Resource/es.lproj/Localizable.strings index 63f6fd84..05983976 100644 --- a/Resource/es.lproj/Localizable.strings +++ b/Resource/es.lproj/Localizable.strings @@ -168,6 +168,7 @@ "text_component.loadAverage1Min" = "Load Average (1 min)"; "text_component.loadAverage5Min" = "Load Average (5 min)"; "text_component.loadAverage15Min" = "Load Average (15 min)"; +"text_component.average" = "Average"; // MARK: CPU Display Mode "cpu_display_mode" = "CPU Display Mode"; diff --git a/Resource/fr.lproj/Localizable.strings b/Resource/fr.lproj/Localizable.strings index 1709e1ee..5a85f5b9 100644 --- a/Resource/fr.lproj/Localizable.strings +++ b/Resource/fr.lproj/Localizable.strings @@ -169,6 +169,7 @@ "text_component.loadAverage1Min" = "Load Average (1 min)"; "text_component.loadAverage5Min" = "Load Average (5 min)"; "text_component.loadAverage15Min" = "Load Average (15 min)"; +"text_component.average" = "Average"; // MARK: CPU Display Mode "cpu_display_mode" = "CPU Display Mode"; diff --git a/Resource/ja.lproj/Localizable.strings b/Resource/ja.lproj/Localizable.strings index 56c8b0ad..e05e2ce9 100644 --- a/Resource/ja.lproj/Localizable.strings +++ b/Resource/ja.lproj/Localizable.strings @@ -169,6 +169,7 @@ "text_component.loadAverage1Min" = "Load Average (1 min)"; "text_component.loadAverage5Min" = "Load Average (5 min)"; "text_component.loadAverage15Min" = "Load Average (15 min)"; +"text_component.average" = "Average"; // MARK: CPU Display Mode "cpu_display_mode" = "CPU Display Mode"; diff --git a/Resource/ko.lproj/Localizable.strings b/Resource/ko.lproj/Localizable.strings index ac05402d..1f1604fb 100644 --- a/Resource/ko.lproj/Localizable.strings +++ b/Resource/ko.lproj/Localizable.strings @@ -170,6 +170,7 @@ "text_component.loadAverage1Min" = "Load Average (1 min)"; "text_component.loadAverage5Min" = "Load Average (5 min)"; "text_component.loadAverage15Min" = "Load Average (15 min)"; +"text_component.average" = "Average"; // MARK: CPU Display Mode "cpu_display_mode" = "CPU Display Mode"; diff --git a/Resource/mn.lproj/Localizable.strings b/Resource/mn.lproj/Localizable.strings index a6d7562e..6b61a34f 100644 --- a/Resource/mn.lproj/Localizable.strings +++ b/Resource/mn.lproj/Localizable.strings @@ -170,6 +170,7 @@ "text_component.loadAverage1Min" = "Load Average (1 min)"; "text_component.loadAverage5Min" = "Load Average (5 min)"; "text_component.loadAverage15Min" = "Load Average (15 min)"; +"text_component.average" = "Average"; // MARK: CPU Display Mode "cpu_display_mode" = "CPU Display Mode"; diff --git a/Resource/pt.lproj/Localizable.strings b/Resource/pt.lproj/Localizable.strings index 1029c203..337552c5 100644 --- a/Resource/pt.lproj/Localizable.strings +++ b/Resource/pt.lproj/Localizable.strings @@ -168,6 +168,7 @@ "text_component.loadAverage1Min" = "Load Average (1 min)"; "text_component.loadAverage5Min" = "Load Average (5 min)"; "text_component.loadAverage15Min" = "Load Average (15 min)"; +"text_component.average" = "Average"; // MARK: CPU Display Mode "cpu_display_mode" = "CPU Display Mode"; diff --git a/Resource/ru.lproj/Localizable.strings b/Resource/ru.lproj/Localizable.strings index 9c223374..d5299a89 100644 --- a/Resource/ru.lproj/Localizable.strings +++ b/Resource/ru.lproj/Localizable.strings @@ -168,6 +168,7 @@ "text_component.loadAverage1Min" = "Load Average (1 min)"; "text_component.loadAverage5Min" = "Load Average (5 min)"; "text_component.loadAverage15Min" = "Load Average (15 min)"; +"text_component.average" = "Average"; // MARK: CPU Display Mode "cpu_display_mode" = "CPU Display Mode"; diff --git a/Resource/zh-Hans.lproj/Localizable.strings b/Resource/zh-Hans.lproj/Localizable.strings index 326cbb77..6aaf6240 100644 --- a/Resource/zh-Hans.lproj/Localizable.strings +++ b/Resource/zh-Hans.lproj/Localizable.strings @@ -168,6 +168,7 @@ "text_component.loadAverage1Min" = "平均负载 (1分钟)"; "text_component.loadAverage5Min" = "平均负载 (5分钟)"; "text_component.loadAverage15Min" = "平均负载 (15分钟)"; +"text_component.average" = "平均"; // MARK: CPU Display Mode "cpu_display_mode" = "CPU 显示"; diff --git a/eul.xcodeproj/project.pbxproj b/eul.xcodeproj/project.pbxproj index bf9aecc5..bc50931b 100644 --- a/eul.xcodeproj/project.pbxproj +++ b/eul.xcodeproj/project.pbxproj @@ -147,6 +147,10 @@ 6C9A10CC2556C502000459E1 /* SharedLibrary.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 6C2688EE2556762B00FB7306 /* SharedLibrary.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; 6CAEED6524A62DF800C39597 /* SMC.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6CAEED6424A62DF800C39597 /* SMC.swift */; }; 6CC0798C250CD793000D7DAC /* PreferenceGeneralView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6CC0798B250CD793000D7DAC /* PreferenceGeneralView.swift */; }; + 6CC1EBB725769B1F00BC05CA /* FanData.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6CC1EBB625769B1F00BC05CA /* FanData.swift */; }; + 6CC1EBBA25769B4400BC05CA /* TemperatureData.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6CC1EBB925769B4400BC05CA /* TemperatureData.swift */; }; + 6CC1EBBD25769E2400BC05CA /* FanTextComponent.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6CC1EBBC25769E2400BC05CA /* FanTextComponent.swift */; }; + 6CC1EBC02576A0E200BC05CA /* Array.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6CC1EBBF2576A0E200BC05CA /* Array.swift */; }; 6CC73857256A9E4D003A15AC /* PreferenceComponentConfigView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6CC73856256A9E4D003A15AC /* PreferenceComponentConfigView.swift */; }; 6CC7385E256BEABA003A15AC /* Dict.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6CC7385D256BEABA003A15AC /* Dict.swift */; }; 6CDBB4C1254462B100D01EA0 /* PreferenceSectionView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6CDBB4C0254462B100D01EA0 /* PreferenceSectionView.swift */; }; @@ -436,6 +440,10 @@ 6CB260AF250DF1A900328DAA /* BatteryIconView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BatteryIconView.swift; sourceTree = ""; }; 6CB26F7824E8310900E809FE /* SectionView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SectionView.swift; sourceTree = ""; }; 6CC0798B250CD793000D7DAC /* PreferenceGeneralView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PreferenceGeneralView.swift; sourceTree = ""; }; + 6CC1EBB625769B1F00BC05CA /* FanData.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FanData.swift; sourceTree = ""; }; + 6CC1EBB925769B4400BC05CA /* TemperatureData.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TemperatureData.swift; sourceTree = ""; }; + 6CC1EBBC25769E2400BC05CA /* FanTextComponent.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FanTextComponent.swift; sourceTree = ""; }; + 6CC1EBBF2576A0E200BC05CA /* Array.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Array.swift; sourceTree = ""; }; 6CC7384E2566C07D003A15AC /* mn */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = mn; path = mn.lproj/Localizable.strings; sourceTree = ""; }; 6CC738502566C140003A15AC /* ko */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ko; path = ko.lproj/Localizable.strings; sourceTree = ""; }; 6CC73856256A9E4D003A15AC /* PreferenceComponentConfigView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PreferenceComponentConfigView.swift; sourceTree = ""; }; @@ -581,6 +589,7 @@ 6C3A002C256FF62F0030AB70 /* NetworkTextComponent.swift */, 6C3A0033256FF7510030AB70 /* BatteryTextComponent.swift */, 6C3A0036256FFB330030AB70 /* DiskTextComponent.swift */, + 6CC1EBBC25769E2400BC05CA /* FanTextComponent.swift */, ); path = TextComponents; sourceTree = ""; @@ -617,6 +626,8 @@ 6CEF48A5255C366A002E4D73 /* SizePreferenceKey.swift */, 6C7DB6E724E82C7700133B06 /* StringEnum.swift */, 6C19253E256FEBE5006B0D73 /* LocalizedStringConvertible.swift */, + 6CC1EBB625769B1F00BC05CA /* FanData.swift */, + 6CC1EBB925769B4400BC05CA /* TemperatureData.swift */, ); path = Schema; sourceTree = ""; @@ -817,6 +828,7 @@ 6C4CCCF0250BA68B00590E0E /* View.swift */, 6C387DC4253AF46000CBB81B /* NSRunningApplication.swift */, 6C15933E257241DB00FDE7EA /* Collection.swift */, + 6CC1EBBF2576A0E200BC05CA /* Array.swift */, ); path = Extension; sourceTree = ""; @@ -1284,8 +1296,10 @@ 6C16BF10255428EF00CCF5B7 /* StableWidth.swift in Sources */, 6C7DB6E624E82C5A00133B06 /* Preference.swift in Sources */, 6C993B8E2517909200586C6B /* MiniSectionView.swift in Sources */, + 6CC1EBC02576A0E200BC05CA /* Array.swift in Sources */, 6C1FA3F824A70DF300CA7F71 /* CpuView.swift in Sources */, 6C1FA40024A712AA00CA7F71 /* SmcControl.swift in Sources */, + 6CC1EBBD25769E2400BC05CA /* FanTextComponent.swift in Sources */, 6C33CECD25177CE300345977 /* CpuMenuBlockView.swift in Sources */, 6CF28D0D251758EE00EBE9CB /* StatusBarView.swift in Sources */, 6C1FA3FA24A70E6700CA7F71 /* CpuStore.swift in Sources */, @@ -1311,10 +1325,12 @@ 6C19252F256D56BF006B0D73 /* JSONCodable.swift in Sources */, 6C3A002D256FF62F0030AB70 /* NetworkTextComponent.swift in Sources */, 6CDBB4C325447B7500D01EA0 /* EulMenuComponent.swift in Sources */, + 6CC1EBB725769B1F00BC05CA /* FanData.swift in Sources */, 6CDBB4C1254462B100D01EA0 /* PreferenceSectionView.swift in Sources */, 6C7DB6E824E82C7700133B06 /* StringEnum.swift in Sources */, 6CC0798C250CD793000D7DAC /* PreferenceGeneralView.swift in Sources */, 6C572D81254EFD5B00EF9904 /* DiskList.swift in Sources */, + 6CC1EBBA25769B4400BC05CA /* TemperatureData.swift in Sources */, 6C1FA40724AA127E00CA7F71 /* MemoryView.swift in Sources */, 6CDE6C7424F0047600463114 /* SizeChangeView.swift in Sources */, 6C45751125568DCC00A2AD84 /* MemoryWidget.intentdefinition in Sources */, diff --git a/eul/AppDelegate.swift b/eul/AppDelegate.swift index dbefa025..8cbece5c 100644 --- a/eul/AppDelegate.swift +++ b/eul/AppDelegate.swift @@ -75,7 +75,7 @@ class AppDelegate: NSObject, NSApplicationDelegate, NSWindowDelegate { // window.makeKeyAndOrderFront(nil) // NSApp.activate(ignoringOtherApps: true) - SmcControl.shared.start() + SmcControl.shared.subscribe() StatusBarManager.shared.checkVisibilityIfNeeded() wakeUp() diff --git a/eul/Extension/Array.swift b/eul/Extension/Array.swift new file mode 100644 index 00000000..5b81db27 --- /dev/null +++ b/eul/Extension/Array.swift @@ -0,0 +1,15 @@ +// +// Array.swift +// eul +// +// Created by Gao Sun on 2020/12/2. +// Copyright © 2020 Gao Sun. All rights reserved. +// + +import Foundation + +extension Array { + func appending(_ newElement: Element, condition: Bool = true) -> [Element] { + condition ? self + [newElement] : self + } +} diff --git a/eul/Schema/EulComponent.swift b/eul/Schema/EulComponent.swift index 3fad9004..27d7fc27 100644 --- a/eul/Schema/EulComponent.swift +++ b/eul/Schema/EulComponent.swift @@ -51,8 +51,11 @@ enum EulComponent: String, CaseIterable, Identifiable, Codable, JSONCodabble, Lo case Disk static var allCases: [EulComponent] { - let components: [EulComponent] = [.CPU, .Fan, .Memory, .Network, .Disk] - return SharedStore.battery.isValid ? components + [.Battery] : components + [.CPU, .Memory] + .appending(.Fan, condition: SmcControl.shared.isFanValid) + .appending(.Network) + .appending(.Battery, condition: SharedStore.battery.isValid) + .appending(.Disk) } } diff --git a/eul/Schema/FanData.swift b/eul/Schema/FanData.swift new file mode 100644 index 00000000..8ba8de88 --- /dev/null +++ b/eul/Schema/FanData.swift @@ -0,0 +1,29 @@ +// +// FanData.swift +// eul +// +// Created by Gao Sun on 2020/12/1. +// Copyright © 2020 Gao Sun. All rights reserved. +// + +import Foundation +import SharedLibrary +import SwiftyJSON + +class FanData: Identifiable { + let fan: Fan + var speed: Int + + var id: Int { + fan.id + } + + var percentage: Double { + Double(speed) / Double(fan.maxSpeed) * 100 + } + + init(fan: Fan, speed: Int = 0) { + self.fan = fan + self.speed = speed + } +} diff --git a/eul/Schema/TemperatureData.swift b/eul/Schema/TemperatureData.swift new file mode 100644 index 00000000..a07a80cb --- /dev/null +++ b/eul/Schema/TemperatureData.swift @@ -0,0 +1,20 @@ +// +// TemperatureData.swift +// eul +// +// Created by Gao Sun on 2020/12/1. +// Copyright © 2020 Gao Sun. All rights reserved. +// + +import Foundation +import SharedLibrary + +class TemperatureData { + let sensor: TemperatureSensor + var temp: Double + + init(sensor: TemperatureSensor, temp: Double = 0) { + self.sensor = sensor + self.temp = temp + } +} diff --git a/eul/Schema/TextComponents/FanTextComponent.swift b/eul/Schema/TextComponents/FanTextComponent.swift new file mode 100644 index 00000000..21865e39 --- /dev/null +++ b/eul/Schema/TextComponents/FanTextComponent.swift @@ -0,0 +1,48 @@ +// +// FanTextComponent.swift +// eul +// +// Created by Gao Sun on 2020/12/1. +// Copyright © 2020 Gao Sun. All rights reserved. +// + +import SwiftUI +import SwiftyJSON + +struct FanTextComponent: Hashable { + var id: Int + + var isAverage: Bool { + id == -1 + } +} + +extension FanTextComponent: CaseIterable { + static var allCases: [Self] + = defaultComponents + [FanTextComponent(id: -1)] + + static var defaultComponents: [Self] { + SmcControl.shared.fans.map { FanTextComponent(id: $0.id) } + } +} + +extension FanTextComponent: JSONCodabble { + init?(json: JSON) { + guard let id = json["id"].int else { + return nil + } + self.id = id + } + + var json: JSON { + JSON([ + "id": id, + ]) + } +} + +extension FanTextComponent: LocalizedStringConvertible { + var localizedDescription: String { + id == -1 ? "text_component.average".localized() : "fan".localized() + " \(id + 1)" + } +} diff --git a/eul/Store/FanStore.swift b/eul/Store/FanStore.swift index 334be731..fc2565ed 100644 --- a/eul/Store/FanStore.swift +++ b/eul/Store/FanStore.swift @@ -9,7 +9,7 @@ import Foundation class FanStore: ObservableObject, Refreshable { - @Published var fans: [SmcControl.FanData] = [] + @Published var fans: [FanData] = [] @objc func refresh() { fans = SmcControl.shared.fans diff --git a/eul/Store/SharedStore.swift b/eul/Store/SharedStore.swift index 42b9b650..4bab2e75 100644 --- a/eul/Store/SharedStore.swift +++ b/eul/Store/SharedStore.swift @@ -42,6 +42,10 @@ enum SharedStore { defaultComponents: DiskTextComponent.defaultComponents, onDidChange: visibilityCheckClosure ) + static let fanTextComponents = ComponentsStore( + defaultComponents: FanTextComponent.defaultComponents, + onDidChange: visibilityCheckClosure + ) } extension View { @@ -64,5 +68,6 @@ extension View { .environmentObject(SharedStore.networkTextComponents) .environmentObject(SharedStore.batteryTextComponents) .environmentObject(SharedStore.diskTextComponents) + .environmentObject(SharedStore.fanTextComponents) } } diff --git a/eul/Utilities/SmcControl.swift b/eul/Utilities/SmcControl.swift index 3e5beae1..b9bad431 100644 --- a/eul/Utilities/SmcControl.swift +++ b/eul/Utilities/SmcControl.swift @@ -8,57 +8,11 @@ import Foundation import SharedLibrary - -extension TemperatureUnit { - var description: String { - switch self { - case .celius: - return "temp.celsius".localized() - case .fahrenheit: - return "temp.fahrenheit".localized() - case .kelvin: - return "temp.kelvin".localized() - } - } -} - -extension Double { - var temperatureString: String { - SmcControl.shared.formatTemp(self) - } -} +import SwiftyJSON class SmcControl: Refreshable { static var shared = SmcControl() - class TemperatureData { - let sensor: TemperatureSensor - var temp: Double - - init(sensor: TemperatureSensor, temp: Double = 0) { - self.sensor = sensor - self.temp = temp - } - } - - class FanData: Identifiable { - let fan: Fan - var speed: Int - - var id: Int { - fan.id - } - - var percentage: Double { - Double(speed) / Double(fan.maxSpeed) * 100 - } - - init(fan: Fan, speed: Int = 0) { - self.fan = fan - self.speed = speed - } - } - var sensors: [TemperatureData] = [] var fans: [FanData] = [] var tempUnit: TemperatureUnit = .celius @@ -74,12 +28,15 @@ class SmcControl: Refreshable { sensors.first(where: { $0.sensor.name == "MEM_SLOTS_PROXIMITY" })?.temp } + var isFanValid: Bool { + fans.count > 0 + } + func formatTemp(_ value: Double) -> String { String(format: "%.0f°\(tempUnit == .celius ? "C" : "F")", value) } - // must call a function explicitly to init shared instance - func start() { + init() { do { try SMCKit.open() sensors = try SMCKit.allKnownTemperatureSensors().map { .init(sensor: $0) } @@ -94,6 +51,13 @@ class SmcControl: Refreshable { } catch { print("SMC init error", error) } + } + + deinit { + NotificationCenter.default.removeObserver(self) + } + + func subscribe() { initObserver(for: .SMCShouldRefresh) } @@ -121,3 +85,48 @@ class SmcControl: Refreshable { NotificationCenter.default.post(name: .StoreShouldRefresh, object: nil) } } + +extension TemperatureUnit { + var description: String { + switch self { + case .celius: + return "temp.celsius".localized() + case .fahrenheit: + return "temp.fahrenheit".localized() + case .kelvin: + return "temp.kelvin".localized() + } + } +} + +extension Fan: JSONCodabble { + init?(json: JSON) { + guard + let id = json["id"].int, + let name = json["name"].string, + let minSpeed = json["id"].int, + let maxSpeed = json["id"].int + else { + return nil + } + self.id = id + self.name = name + self.minSpeed = minSpeed + self.maxSpeed = maxSpeed + } + + var json: JSON { + JSON([ + "id": id, + "name": name, + "minSpeed": minSpeed, + "maxSpeed": maxSpeed, + ]) + } +} + +extension Double { + var temperatureString: String { + SmcControl.shared.formatTemp(self) + } +} diff --git a/eul/Views/Preference/PreferenceComponentConfigView.swift b/eul/Views/Preference/PreferenceComponentConfigView.swift index dc61f653..78232b9c 100644 --- a/eul/Views/Preference/PreferenceComponentConfigView.swift +++ b/eul/Views/Preference/PreferenceComponentConfigView.swift @@ -34,6 +34,7 @@ extension Preference { } struct ComponentConfigView: View { + @EnvironmentObject var batteryStore: BatteryStore @EnvironmentObject var componentConfigStore: ComponentConfigStore var component: EulComponent @@ -62,10 +63,13 @@ extension Preference { if component == .Memory { ComponentTextConfigView() } + if SmcControl.shared.isFanValid, component == .Fan { + ComponentTextConfigView() + } if component == .Network { ComponentTextConfigView() } - if component == .Battery { + if batteryStore.isValid, component == .Battery { ComponentTextConfigView() } if component == .Disk { diff --git a/eul/Views/StatusBar/FanView.swift b/eul/Views/StatusBar/FanView.swift index b7061765..fc21520c 100644 --- a/eul/Views/StatusBar/FanView.swift +++ b/eul/Views/StatusBar/FanView.swift @@ -11,13 +11,26 @@ import SwiftUI struct FanView: View { @EnvironmentObject var fanStore: FanStore @EnvironmentObject var componentConfigStore: ComponentConfigStore + @EnvironmentObject var textStore: ComponentsStore var config: EulComponentConfig { componentConfigStore[.Fan] } + var averageRpm: String { + "\(fanStore.fans.reduce(0) { $0 + $1.speed } / fanStore.fans.count) rpm" + } + var texts: [String] { - fanStore.fans.map { "\($0.speed.description) rpm" } + textStore.activeComponents.compactMap { component in + if component.isAverage { + return averageRpm + } + guard let fan = fanStore.fans.first(where: { $0.id == component.id }) else { + return nil + } + return "\(fan.speed) rpm" + } } var body: some View { @@ -27,10 +40,10 @@ struct FanView: View { .resizable() .frame(width: 13, height: 13) } -// if config.showText { - StatusBarTextView(texts: texts) - .stableWidth() -// } + if textStore.showComponents { + StatusBarTextView(texts: texts) + .stableWidth() + } } } }