Files
Nearfield_Friends/Proximity/Views/SilhouetteRow.swift

75 lines
2.3 KiB
Swift
Raw Normal View History

import SwiftUI
/// A single anonymous encounter in the feed.
///
/// Until mutual consent, the other person is a **silhouette** a shape, not
/// a profile. This visual language is the privacy promise made visible: you
/// know a human was here, but you don't know who until they choose to be seen.
struct SilhouetteRow: View {
let encounter: Encounter
/// Called when the user taps "Wave" on a silhouette.
var onWave: () -> Void
var body: some View {
HStack(spacing: 16) {
// Silhouette avatar deliberately anonymous.
ZStack {
Circle()
.fill(Color.gray.opacity(0.25))
.frame(width: 48, height: 48)
Image(systemName: "person.fill")
.foregroundColor(.gray)
}
VStack(alignment: .leading, spacing: 4) {
Text(title)
.font(.headline)
Text(subtitle)
.font(.caption)
.foregroundColor(.secondary)
}
Spacer()
// Action depends on status.
switch encounter.status {
case .silhouette:
Button("Wave", action: onWave)
.buttonStyle(.borderedProminent)
.tint(.green)
case .waved:
Text("Waved ✓")
.font(.caption)
.foregroundColor(.green)
case .mutual:
Image(systemName: "checkmark.circle.fill")
.foregroundColor(.green)
case .declined:
Image(systemName: "xmark.circle.fill")
.foregroundColor(.red)
}
}
.padding()
.background(
RoundedRectangle(cornerRadius: 16)
.fill(Color(.secondarySystemBackground))
)
}
private var title: String {
switch encounter.status {
case .mutual:
return "Connected"
default:
return "Someone nearby"
}
}
private var subtitle: String {
var parts: [String] = [encounter.tier.title]
if let place = encounter.placeHint { parts.append(place) }
parts.append(encounter.timestamp.formatted(.relative(presentation: .named)))
return parts.joined(separator: " · ")
}
}