Working lock screen stuff

This commit is contained in:
Hariharan Mudaliar 2025-10-27 00:40:03 +05:30
commit 5a722373ce
5 changed files with 171 additions and 72 deletions

View file

@ -85,7 +85,20 @@ final class LockScreenWeatherManager: ObservableObject {
return snapshot
} catch {
NSLog("LockScreenWeatherManager: failed to fetch weather - \(error.localizedDescription)")
return snapshot
let fallback = LockScreenWeatherSnapshot(
temperatureText: snapshot?.temperatureText ?? "--",
symbolName: snapshot?.symbolName ?? "cloud.fill",
description: snapshot?.description ?? "",
locationName: snapshot?.locationName,
charging: Defaults[.lockScreenWeatherShowsCharging] ? makeChargingInfo() : nil,
bluetooth: Defaults[.lockScreenWeatherShowsBluetooth] ? makeBluetoothInfo() : nil,
showsLocation: snapshot?.showsLocation ?? false
)
self.snapshot = fallback
deliver(fallback, forceShow: false)
return fallback
}
}
@ -177,15 +190,17 @@ final class LockScreenWeatherManager: ObservableObject {
private func makeChargingInfo() -> LockScreenWeatherSnapshot.ChargingInfo? {
let battery = BatteryStatusViewModel.shared
let isPluggedIn = battery.isPluggedIn
let isCharging = battery.isCharging
let macStatus = MacBatteryManager.shared.currentStatus()
let isPluggedIn = battery.isPluggedIn || battery.isCharging
let isCharging = macStatus.isCharging || battery.isCharging
guard isPluggedIn || isCharging else {
return nil
}
let minutes = battery.timeToFullCharge
let remaining = minutes > 0 ? minutes : nil
let rawMinutes = macStatus.timeRemainingMinutes ?? (battery.timeToFullCharge > 0 ? battery.timeToFullCharge : nil)
let remaining = (rawMinutes ?? 0) > 0 ? rawMinutes : nil
return LockScreenWeatherSnapshot.ChargingInfo(
minutesRemaining: remaining,
@ -234,7 +249,7 @@ struct LockScreenWeatherSnapshot: Equatable {
return "bolt.fill"
}
if isPluggedIn {
return "powerplug.fill"
return "powerplug.portrait.fill"
}
return ""
}

View file

@ -0,0 +1,65 @@
import Foundation
import IOKit.ps
/// Lightweight helper for querying macOS battery charging status and ETA.
final class MacBatteryManager {
static let shared = MacBatteryManager()
private init() {}
struct BatteryStatus {
let timeRemainingMinutes: Int?
let isCharging: Bool
let percentage: Int?
}
func currentStatus() -> BatteryStatus {
guard let sourcesInfo = IOPSCopyPowerSourcesInfo()?.takeRetainedValue(),
let sourcesList = IOPSCopyPowerSourcesList(sourcesInfo)?.takeRetainedValue() as? [CFTypeRef] else {
return BatteryStatus(timeRemainingMinutes: nil, isCharging: false, percentage: nil)
}
for source in sourcesList {
guard let description = IOPSGetPowerSourceDescription(sourcesInfo, source)?.takeUnretainedValue() as? [String: Any],
let type = description[kIOPSTypeKey] as? String,
type == kIOPSInternalBatteryType else {
continue
}
let isCharging = description[kIOPSIsChargingKey] as? Bool ?? false
let timeRemaining = description[kIOPSTimeToFullChargeKey] as? Int
let currentCapacity = description[kIOPSCurrentCapacityKey] as? Int
let maxCapacity = description[kIOPSMaxCapacityKey] as? Int
let percentage: Int?
if let current = currentCapacity, let max = maxCapacity, max > 0 {
percentage = (current * 100) / max
} else {
percentage = nil
}
return BatteryStatus(
timeRemainingMinutes: timeRemaining,
isCharging: isCharging,
percentage: percentage
)
}
return BatteryStatus(timeRemainingMinutes: nil, isCharging: false, percentage: nil)
}
func formattedTimeToFullCharge() -> String? {
let status = currentStatus()
guard status.isCharging, let minutes = status.timeRemainingMinutes, minutes > 0 else {
return nil
}
let hours = minutes / 60
let remainingMinutes = minutes % 60
if hours > 0 {
return "\(hours)h \(remainingMinutes)m"
}
return "\(remainingMinutes)m"
}
}