mirror of
https://github.com/openclaw/openclaw.git
synced 2026-07-05 13:53:33 +00:00
* feat(ios): align brand color tokens with design guide (PR1) * fix(ios): preserve brand contrast * fix(ios): cover tinted palette surfaces * chore(ios): sync native i18n inventory * chore(ios): sync native i18n inventory * chore(ios): sync native i18n inventory --------- Co-authored-by: Peter Steinberger <steipete@gmail.com>
84 lines
3.1 KiB
Swift
84 lines
3.1 KiB
Swift
import OpenClawKit
|
|
import OpenClawProtocol
|
|
import SwiftUI
|
|
|
|
extension AgentProTab {
|
|
var usageTotalsCard: some View {
|
|
ProCard(radius: AgentLayout.cardRadius) {
|
|
VStack(alignment: .leading, spacing: 12) {
|
|
HStack {
|
|
Text("Totals")
|
|
.font(.headline)
|
|
Spacer()
|
|
ProValuePill(
|
|
value: "\(self.overview?.usage?.days ?? 31)d",
|
|
color: OpenClawBrand.accentForeground)
|
|
}
|
|
HStack(spacing: 10) {
|
|
self.detailMetric(label: "Cost", value: self.usageValue)
|
|
self.detailMetric(label: "Tokens", value: self.usageTokenValue)
|
|
self.detailMetric(label: "Cache", value: self.usageCacheValue)
|
|
}
|
|
}
|
|
}
|
|
.padding(.horizontal, OpenClawProMetric.pagePadding)
|
|
}
|
|
|
|
var usageTokenValue: String {
|
|
guard let tokens = self.overview?.usage?.totalTokens else { return "0" }
|
|
return Self.compactNumber(tokens)
|
|
}
|
|
|
|
var usageCacheValue: String {
|
|
guard let cacheStatus = self.normalized(self.overview?.usage?.cacheStatus?["status"]?.value as? String) else {
|
|
return "n/a"
|
|
}
|
|
return cacheStatus
|
|
}
|
|
|
|
var usageDailyList: some View {
|
|
VStack(alignment: .leading, spacing: 8) {
|
|
ProSectionHeader(title: "Daily")
|
|
ProCard(padding: 0, radius: AgentLayout.cardRadius) {
|
|
let days = self.overview?.usage?.daily ?? []
|
|
if days.isEmpty {
|
|
self.emptyDetailRow(
|
|
icon: "chart.bar",
|
|
title: "No daily usage yet",
|
|
detail: "The gateway returned totals without daily session cost rows.")
|
|
.padding(14)
|
|
} else {
|
|
VStack(spacing: 0) {
|
|
ForEach(Array(days.prefix(14).enumerated()), id: \.element.date) { index, day in
|
|
self.usageDayRow(day)
|
|
if index < min(days.count, 14) - 1 {
|
|
Divider().padding(.leading, 60)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
.padding(.horizontal, OpenClawProMetric.pagePadding)
|
|
}
|
|
}
|
|
|
|
func usageDayRow(_ day: CostUsageDailyEntryLite) -> some View {
|
|
HStack(spacing: 12) {
|
|
ProIconBadge(systemName: "calendar", color: OpenClawBrand.accent)
|
|
VStack(alignment: .leading, spacing: 3) {
|
|
Text(day.date)
|
|
.font(.subheadline.weight(.semibold))
|
|
Text("\(Self.compactNumber(day.totalTokens ?? 0)) tokens")
|
|
.font(.caption)
|
|
.foregroundStyle(.secondary)
|
|
}
|
|
Spacer(minLength: 8)
|
|
Text(Self.currency(day.totalCost ?? 0))
|
|
.font(.caption2.weight(.semibold))
|
|
.foregroundStyle(OpenClawBrand.accent)
|
|
}
|
|
.padding(.vertical, 10)
|
|
.padding(.horizontal, 14)
|
|
}
|
|
}
|