initial commit: Proximity iOS app proposal, full Swift code scaffold, reference backend, testing docs, generated Xcode project
This commit is contained in:
74
Proximity/Views/SilhouetteRow.swift
Normal file
74
Proximity/Views/SilhouetteRow.swift
Normal file
@@ -0,0 +1,74 @@
|
||||
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: " · ")
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user