Match ring tracks and stats to HTML prototype exactly

- Ring tracks: #c2c2c2 → #ebebeb (hairline, nearly invisible like the prototype)
- Middle ring: #9e9e9e → #c8c8c8 (lighter, matches HTML)
- Outer arc: lineWidth 1.5 → 1, glow softened to match prototype subtlety
- Stats: remove card background, inline plain layout with #ebebeb dividers
- Stats value: .semibold → .light (font-weight:300), letter-spacing tightened
- Stats label: size 9 → 8pt SF Mono, tracking 1.0 (matches HTML 0.12em)

Co-Authored-By: Kutesir <kutesir@provoc.ug>
Co-Authored-By: Sentry <sentry@provoc.ug>
This commit is contained in:
Robin Kutesa
2026-05-20 19:55:23 +03:00
parent c96f28cd06
commit 92541b8d7e

View File

@@ -309,45 +309,50 @@ struct BackupView: View {
label: "NAS", label: "NAS",
color: AppTheme.interactive color: AppTheme.interactive
) )
thinDivider statDivider
compactStat( compactStat(
"\(statusService.snapshot.phoneTotal)", "\(statusService.snapshot.phoneTotal)",
label: "IPHONE", label: "iPhone",
color: AppTheme.inkSecondary color: AppTheme.inkSecondary
) )
thinDivider statDivider
compactStat( compactStat(
"\(notBackedUpDisplayCount)", "\(notBackedUpDisplayCount)",
label: "PENDING", label: "Pending",
color: Color(red: 1.0, green: 0.62, blue: 0.0) color: Color(red: 1.0, green: 0.62, blue: 0.0)
) )
thinDivider statDivider
compactStat( compactStat(
"\(alreadySafeDisplayCount)", "\(alreadySafeDisplayCount)",
label: "SAFE", label: "Safe",
color: AppTheme.positive color: AppTheme.positive
) )
} }
.frame(height: 48) .padding(.vertical, 4)
.background(AppTheme.surfaceSunken.opacity(0.85))
.clipShape(RoundedRectangle(cornerRadius: 14, style: .continuous))
} }
private func compactStat(_ value: String, label: String, color: Color) -> some View { private func compactStat(_ value: String, label: String, color: Color) -> some View {
VStack(spacing: 2) { VStack(spacing: 3) {
Text(value) Text(value)
.font(.system(size: 15, weight: .semibold)) .font(.system(size: 15, weight: .light))
.foregroundStyle(color) .foregroundStyle(color)
.monospacedDigit() .monospacedDigit()
.kerning(-0.5)
Text(label) Text(label)
.font(.system(size: 9, weight: .regular)) .font(.system(size: 8, weight: .regular, design: .monospaced))
.foregroundStyle(AppTheme.inkQuaternary) .foregroundStyle(AppTheme.inkQuaternary)
.tracking(0.2) .tracking(1.0)
} }
.frame(maxWidth: .infinity) .frame(maxWidth: .infinity)
.padding(.vertical, 6) .padding(.vertical, 6)
} }
private var statDivider: some View {
Rectangle()
.fill(Color(red: 0.922, green: 0.922, blue: 0.922))
.frame(width: 1, height: 22)
}
private var thinDivider: some View { private var thinDivider: some View {
Rectangle() Rectangle()
.fill(AppTheme.separator.opacity(0.5)) .fill(AppTheme.separator.opacity(0.5))
@@ -997,7 +1002,7 @@ private struct KisaniRingView: View {
let innerProgress: CGFloat let innerProgress: CGFloat
let innerColor: Color let innerColor: Color
private let track = Color(red: 0.76, green: 0.76, blue: 0.76) private let track = Color(red: 0.922, green: 0.922, blue: 0.922) // #ebebeb
private let nasArc = Color(red: 0.42, green: 0.52, blue: 0.68) private let nasArc = Color(red: 0.42, green: 0.52, blue: 0.68)
var body: some View { var body: some View {
@@ -1006,14 +1011,14 @@ private struct KisaniRingView: View {
Circle().stroke(track, lineWidth: 1).padding(10) Circle().stroke(track, lineWidth: 1).padding(10)
// Outer NAS progress (blue-slate + glow) // Outer NAS progress (blue-slate + glow)
Circle().trim(from: 0, to: outerProgress) Circle().trim(from: 0, to: outerProgress)
.stroke(nasArc, style: StrokeStyle(lineWidth: 1.5, lineCap: .round)) .stroke(nasArc, style: StrokeStyle(lineWidth: 1, lineCap: .round))
.shadow(color: nasArc.opacity(0.65), radius: 7, x: 0, y: 0) .shadow(color: nasArc.opacity(0.55), radius: 5, x: 0, y: 0)
.rotationEffect(.degrees(-90)) .rotationEffect(.degrees(-90))
.padding(10) .padding(10)
.animation(.spring(response: 0.7, dampingFraction: 0.8), value: outerProgress) .animation(.spring(response: 0.7, dampingFraction: 0.8), value: outerProgress)
// Middle static ring // Middle static ring #c8c8c8
Circle().stroke(Color(red: 0.62, green: 0.62, blue: 0.62), lineWidth: 1).padding(24) Circle().stroke(Color(red: 0.784, green: 0.784, blue: 0.784), lineWidth: 1).padding(24)
// Inner track // Inner track
Circle().stroke(track, lineWidth: 1.5).padding(38) Circle().stroke(track, lineWidth: 1.5).padding(38)