From 612fedccc07fb83fe1b3b9ac989bf427f6b73627 Mon Sep 17 00:00:00 2001 From: LMZ Date: Tue, 21 Apr 2026 11:28:19 +0800 Subject: [PATCH] feat: show actionable temperature hint when reading fails (issue #12) --- .../Resources/en.lproj/Localizable.strings | 3 +++ .../Resources/zh-Hans.lproj/Localizable.strings | 3 +++ .../ProcessBarMonitor/SystemMetricsProvider.swift | 13 +++++++++++++ Sources/ProcessBarMonitor/SystemModels.swift | 4 ++++ Sources/ProcessBarMonitor/Views.swift | 6 ++++++ 5 files changed, 29 insertions(+) diff --git a/Sources/ProcessBarMonitor/Resources/en.lproj/Localizable.strings b/Sources/ProcessBarMonitor/Resources/en.lproj/Localizable.strings index bcb93f9..de6f4dd 100644 --- a/Sources/ProcessBarMonitor/Resources/en.lproj/Localizable.strings +++ b/Sources/ProcessBarMonitor/Resources/en.lproj/Localizable.strings @@ -59,6 +59,9 @@ "note.temperature.arm64_unavailable" = "Apple Silicon HID sensors were checked for %@, but no valid value was exposed right now."; "note.temperature.intel_hint" = "Intel: install osx-cpu-temp or istats to show a real CPU temperature."; "note.temperature.no_source" = "No valid CPU temperature source found."; +"hint.temperature.intel_install" = "Intel Mac: install osx-cpu-temp or istats to show CPU temperature."; +"hint.temperature.arm64_read_failed" = "Apple Silicon: temperature reading failed. Check System Settings > Privacy & Security."; +"note.temperature.available" = "Temperature mode: %@. Source: Apple Silicon HID sensors first, helper fallback second."; "button.copy_diagnostics" = "Copy Diagnostics"; "status.diagnostics_copied" = "Diagnostics copied to clipboard."; "status.diagnostics_copy_failed" = "Failed to copy diagnostics."; diff --git a/Sources/ProcessBarMonitor/Resources/zh-Hans.lproj/Localizable.strings b/Sources/ProcessBarMonitor/Resources/zh-Hans.lproj/Localizable.strings index 41069a1..3230ecd 100644 --- a/Sources/ProcessBarMonitor/Resources/zh-Hans.lproj/Localizable.strings +++ b/Sources/ProcessBarMonitor/Resources/zh-Hans.lproj/Localizable.strings @@ -59,6 +59,9 @@ "note.temperature.arm64_unavailable" = "已检查 %@ 的 Apple Silicon HID 传感器,但当前未返回有效值。"; "note.temperature.intel_hint" = "Intel 机型:安装 osx-cpu-temp 或 istats 以显示真实 CPU 温度。"; "note.temperature.no_source" = "未找到有效的 CPU 温度来源。"; +"hint.temperature.intel_install" = "Intel Mac:安装 osx-cpu-temp 或 istats 即可显示 CPU 温度。"; +"hint.temperature.arm64_read_failed" = "Apple Silicon:温度读取失败。请检查 系统设置 > 隐私与安全性。"; +"note.temperature.available" = "温度模式:%@。来源:优先 Apple Silicon HID 传感器,其次为辅助工具。"; "button.copy_diagnostics" = "复制诊断信息"; "status.diagnostics_copied" = "诊断信息已复制到剪贴板。"; "status.diagnostics_copy_failed" = "复制诊断信息失败。"; diff --git a/Sources/ProcessBarMonitor/SystemMetricsProvider.swift b/Sources/ProcessBarMonitor/SystemMetricsProvider.swift index aa1659f..9a0478d 100644 --- a/Sources/ProcessBarMonitor/SystemMetricsProvider.swift +++ b/Sources/ProcessBarMonitor/SystemMetricsProvider.swift @@ -37,6 +37,7 @@ actor SystemMetricsProvider { thermalState: ProcessInfo.processInfo.thermalState, cpuTemperatureC: temperature, architectureNote: architectureAndTemperatureNote(temperatureAvailable: temperature != nil, mode: temperatureMode), + temperatureHint: temperatureHint(temperatureAvailable: temperature != nil), updatedAt: Date() ) } @@ -203,4 +204,16 @@ actor SystemMetricsProvider { return L10n.string("note.temperature.no_source") #endif } + + /// Returns an actionable hint string when temperature is unavailable, nil when temperature is present. + private func temperatureHint(temperatureAvailable: Bool) -> String? { + guard !temperatureAvailable else { return nil } + #if arch(arm64) + return L10n.string("hint.temperature.arm64_read_failed") + #elseif arch(x86_64) + return L10n.string("hint.temperature.intel_install") + #else + return nil + #endif + } } diff --git a/Sources/ProcessBarMonitor/SystemModels.swift b/Sources/ProcessBarMonitor/SystemModels.swift index 73026d8..e130821 100644 --- a/Sources/ProcessBarMonitor/SystemModels.swift +++ b/Sources/ProcessBarMonitor/SystemModels.swift @@ -134,6 +134,9 @@ struct SystemSummary { let thermalState: ProcessInfo.ThermalState let cpuTemperatureC: Double? let architectureNote: String + /// Actionable hint shown when temperature is unavailable (nil). + /// - Intel without tool: install hint; Apple Silicon read-fail: permission check hint. + let temperatureHint: String? let updatedAt: Date var memoryPressurePercent: Double { @@ -149,6 +152,7 @@ struct SystemSummary { thermalState: .nominal, cpuTemperatureC: nil, architectureNote: "", + temperatureHint: nil, updatedAt: Date() ) } diff --git a/Sources/ProcessBarMonitor/Views.swift b/Sources/ProcessBarMonitor/Views.swift index eff7677..2ea468c 100644 --- a/Sources/ProcessBarMonitor/Views.swift +++ b/Sources/ProcessBarMonitor/Views.swift @@ -175,6 +175,12 @@ struct MenuBarContentView: View { .font(.caption) .foregroundStyle(.secondary) .lineLimit(2) + if viewModel.summary.cpuTemperatureC == nil, let hint = viewModel.summary.temperatureHint { + Text(hint) + .font(.caption.weight(.medium)) + .foregroundStyle(.orange) + .lineLimit(2) + } } HStack(spacing: 8) {