Files
OpenStats/Packages/OpenStatsKit/Sources/Metrics/Formatting.swift
T
gentpan 1205483b5e 新增清理与系统维护,修复面板抖动,更换应用图标
- 清理:应用缓存、日志、浏览器缓存、Xcode/模拟器/npm 缓存、下载残留、安装包、废纸篓;
  白名单目录 + 安全守卫,运行中的应用自动跳过,执行前逐项复核,操作日志
- 系统维护:刷新 DNS 缓存、释放内存(辅助工具或管理员授权)
- 面板:去掉打开后的二次调整高度与窗口高度动画,内容放得下时不回弹,
  修复点击菜单栏图标关闭时被重新打开
- 更换应用图标,面板与关于页使用应用图标作为 Logo
- 清理未使用的组件、格式化方法、设计 token 与辅助工具接口
2026-09-13 03:03:08 +05:00

91 lines
3.2 KiB
Swift

import Foundation
public struct History<Element: Sendable>: Sendable {
public let capacity: Int
public private(set) var elements: [Element] = []
public init(capacity: Int) {
self.capacity = max(1, capacity)
elements.reserveCapacity(self.capacity)
}
public mutating func append(_ element: Element) {
if elements.count == capacity { elements.removeFirst() }
elements.append(element)
}
}
public enum Format {
public enum ByteBase: Sendable {
case binary // 内存:1 GB = 1024³,与活动监视器一致
case decimal // 磁盘:1 GB = 1000³,与访达一致
}
private static let units = ["B", "KB", "MB", "GB", "TB", "PB"]
public static func bytes(_ value: UInt64, base: ByteBase = .binary) -> String {
bytes(Double(value), base: base)
}
public static func bytes(_ value: Double, base: ByteBase = .binary) -> String {
let step: Double = base == .binary ? 1024 : 1000
var amount = max(0, value)
var index = 0
while amount >= step, index < units.count - 1 {
amount /= step
index += 1
}
if index == 0 { return "\(Int(amount)) B" }
let digits = amount >= 100 ? 0 : 1
return "\(amount.formatted(.number.precision(.fractionLength(digits)))) \(units[index])"
}
/// 菜单栏网速:保留完整单位,数字最多 3 位,宽度稳定
/// 例:512 B/s、12 KB/s、154 KB/s、1.2 MB/s、12 MB/s、1.1 GB/s
public static func menuBarRate(_ bytesPerSecond: Double) -> String {
let units = ["B/s", "KB/s", "MB/s", "GB/s"]
var value = max(0, bytesPerSecond)
var index = 0
// 超过 999 就进位,避免出现 1023 KB/s 这种 4 位数
while value >= 999.5, index < units.count - 1 {
value /= 1024
index += 1
}
let text = index >= 2 && value < 9.95
? value.formatted(.number.precision(.fractionLength(1)))
: String(Int(value.rounded()))
return "\(text) \(units[index])"
}
public static func percent(_ fraction: Double) -> String {
"\(Int((min(1, max(0, fraction)) * 100).rounded()))%"
}
public static func temperature(_ celsius: Double, fahrenheit: Bool = false) -> String {
fahrenheit ? "\(Int((celsius * 9 / 5 + 32).rounded()))°F" : "\(Int(celsius.rounded()))°C"
}
public static func rpm(_ value: Double) -> String {
"\(Int(value.rounded())) RPM"
}
public static func duration(minutes: Int) -> String {
let hours = minutes / 60
let rest = minutes % 60
switch (hours, rest) {
case (0, _): return "\(rest) 分钟"
case (_, 0): return "\(hours) 小时"
default: return "\(hours) 小时 \(rest) 分钟"
}
}
public static func uptime(since date: Date, now: Date = Date()) -> String {
let minutes = max(0, Int(now.timeIntervalSince(date) / 60))
let days = minutes / (60 * 24)
let hours = (minutes / 60) % 24
if days > 0 { return hours > 0 ? "\(days) 天 \(hours) 小时" : "\(days) 天" }
if hours > 0 { return "\(hours) 小时" }
return "\(minutes) 分钟"
}
}