Fit the Status usage bars to the phone width
This commit is contained in:
@@ -293,8 +293,34 @@ private struct RateLimits: View {
|
||||
} else {
|
||||
ViewThatFits(in: .horizontal) {
|
||||
grid
|
||||
ScrollView(.horizontal) {
|
||||
grid
|
||||
stacked
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private var stacked: some View {
|
||||
VStack(alignment: .leading, spacing: 0) {
|
||||
ForEach(limits.keys.sorted(), id: \.self) { vendor in
|
||||
let usage = limits[vendor]!
|
||||
vendorHeader(vendor, usage)
|
||||
Divider().overlay(Palette.border)
|
||||
ForEach(Array(usage.windows.enumerated()), id: \.offset) { _, w in
|
||||
let used = usedFraction(w)
|
||||
let elapsed = elapsedFraction(w)
|
||||
VStack(alignment: .leading, spacing: 4) {
|
||||
HStack(alignment: .firstTextBaseline, spacing: 10) {
|
||||
Text(w.label)
|
||||
Text(amountText(w)).foregroundStyle(Palette.muted)
|
||||
Spacer(minLength: 0)
|
||||
Text(usedText(w, used)).foregroundStyle(usedColor(used))
|
||||
}
|
||||
PaceBar(used: used, elapsed: elapsed)
|
||||
Text("Elapsed \(elapsed.map { percentText($0 * 100) } ?? "—") · resets \(w.resetsAt.map(resetText) ?? "—")")
|
||||
.font(Fonts.font(11))
|
||||
.foregroundStyle(Palette.muted)
|
||||
}
|
||||
.padding(.vertical, 6)
|
||||
Divider().overlay(Palette.border)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -320,28 +346,40 @@ private struct RateLimits: View {
|
||||
Text(title).font(Fonts.font(11)).foregroundStyle(Palette.muted)
|
||||
}
|
||||
|
||||
@ViewBuilder
|
||||
private func vendorRows(_ vendor: String, _ usage: VendorUsage) -> some View {
|
||||
private func vendorHeader(_ vendor: String, _ usage: VendorUsage) -> some View {
|
||||
let rejected = usage.rejected != nil || usage.windows.contains { w in w.limit.map { w.used >= $0 } ?? false }
|
||||
let reason = usage.rejected.flatMap { $0.isEmpty ? nil : $0 }
|
||||
return HStack(alignment: .firstTextBaseline, spacing: 10) {
|
||||
Text(vendor).font(Fonts.font(13, weight: 700)).foregroundStyle(Palette.text)
|
||||
Text(rejected ? "rejected\(reason.map { ": \($0)" } ?? "")" : "allowed").font(Fonts.font(11, weight: 700)).foregroundStyle(rejected ? Palette.danger : Palette.ok)
|
||||
Text("as of \(since(usage.updatedAt))").font(Fonts.font(11)).foregroundStyle(Palette.muted)
|
||||
}
|
||||
.padding(.top, 12)
|
||||
}
|
||||
|
||||
private func usedFraction(_ w: UsageWindow) -> Double? {
|
||||
w.limit.flatMap { $0 > 0 && (w.used / $0).isFinite ? w.used / $0 : nil }
|
||||
}
|
||||
|
||||
private func usedColor(_ used: Double?) -> Color {
|
||||
used.map { $0 >= 0.9 ? Palette.danger : $0 >= 0.7 ? Palette.warn : Palette.text } ?? Palette.text
|
||||
}
|
||||
|
||||
@ViewBuilder
|
||||
private func vendorRows(_ vendor: String, _ usage: VendorUsage) -> some View {
|
||||
GridRow {
|
||||
HStack(alignment: .firstTextBaseline, spacing: 10) {
|
||||
Text(vendor).font(Fonts.font(13, weight: 700)).foregroundStyle(Palette.text)
|
||||
Text(rejected ? "rejected\(reason.map { ": \($0)" } ?? "")" : "allowed").font(Fonts.font(11, weight: 700)).foregroundStyle(rejected ? Palette.danger : Palette.ok)
|
||||
Text("as of \(since(usage.updatedAt))").font(Fonts.font(11)).foregroundStyle(Palette.muted)
|
||||
}
|
||||
.padding(.top, 12)
|
||||
.gridCellColumns(6)
|
||||
vendorHeader(vendor, usage)
|
||||
.gridCellColumns(6)
|
||||
}
|
||||
Divider().overlay(Palette.border)
|
||||
ForEach(Array(usage.windows.enumerated()), id: \.offset) { _, w in
|
||||
let used = w.limit.flatMap { $0 > 0 && (w.used / $0).isFinite ? w.used / $0 : nil }
|
||||
let used = usedFraction(w)
|
||||
let elapsed = elapsedFraction(w)
|
||||
GridRow {
|
||||
Text(w.label).fixedSize()
|
||||
Text(amountText(w)).fixedSize()
|
||||
Text(usedText(w, used))
|
||||
.foregroundStyle(used.map { $0 >= 0.9 ? Palette.danger : $0 >= 0.7 ? Palette.warn : Palette.text } ?? Palette.text)
|
||||
.foregroundStyle(usedColor(used))
|
||||
.fixedSize()
|
||||
Text(elapsed.map { percentText($0 * 100) } ?? "—").fixedSize()
|
||||
PaceBar(used: used, elapsed: elapsed)
|
||||
|
||||
Reference in New Issue
Block a user