95 lines
3.3 KiB
Swift
95 lines
3.3 KiB
Swift
import SwiftUI
|
|
|
|
/// The emotional centerpiece of the app: the **reveal moment**.
|
|
///
|
|
/// Two strangers who were physically near each other both chose to be seen.
|
|
/// Their silhouettes resolve into people. This screen is deliberately
|
|
/// ceremonial — it's the payoff for being present in the real world, and it
|
|
/// should feel like it.
|
|
///
|
|
/// The interaction is framed as a physical act: you were *near* this person,
|
|
/// you both *waved*, and now you *see* each other. The copy and motion are
|
|
/// designed to make this feel significant, not like a notification.
|
|
struct RevealView: View {
|
|
@EnvironmentObject private var revealFlow: RevealFlow
|
|
@Environment(\.dismiss) private var dismiss
|
|
|
|
@State private var isRevealing = false
|
|
@State private var showProfileImport = false
|
|
|
|
var body: some View {
|
|
VStack(spacing: 32) {
|
|
Spacer()
|
|
|
|
// The two avatars converging.
|
|
ZStack {
|
|
// "You" avatar (left)
|
|
avatar(systemImage: "person.fill", offset: isRevealing ? -70 : -110)
|
|
// "Them" avatar (right) — resolves from silhouette to person.
|
|
avatar(systemImage: "person.fill", offset: isRevealing ? 70 : 110)
|
|
}
|
|
.frame(height: 160)
|
|
|
|
// Status text
|
|
VStack(spacing: 12) {
|
|
Text(isRevealing ? "You both waved." : "You're connected.")
|
|
.font(.title.bold())
|
|
Text(isRevealing
|
|
? "Two people who were near each other chose to be seen."
|
|
: "You can now say hello.")
|
|
.font(.subheadline)
|
|
.foregroundColor(.secondary)
|
|
.multilineTextAlignment(.center)
|
|
.padding(.horizontal)
|
|
}
|
|
|
|
Spacer()
|
|
|
|
// Actions
|
|
VStack(spacing: 12) {
|
|
Button {
|
|
revealFlow.proceedToConversation()
|
|
showProfileImport = true
|
|
} label: {
|
|
Label("Say hello", systemImage: "bubble.left.and.bubble.right")
|
|
.frame(maxWidth: .infinity)
|
|
.padding()
|
|
}
|
|
.buttonStyle(.borderedProminent)
|
|
.tint(.green)
|
|
|
|
Button("Not now") {
|
|
dismiss()
|
|
}
|
|
.foregroundColor(.secondary)
|
|
}
|
|
.padding(.horizontal)
|
|
.padding(.bottom, 24)
|
|
}
|
|
.onAppear {
|
|
// Animate the convergence on appear.
|
|
withAnimation(.easeInOut(duration: 1.2)) {
|
|
isRevealing = true
|
|
}
|
|
}
|
|
.sheet(isPresented: $showProfileImport) {
|
|
if let connection = revealFlow.revealedConnection {
|
|
ProfileImportSheet(connection: connection)
|
|
}
|
|
}
|
|
}
|
|
|
|
private func avatar(systemImage: String, offset: CGFloat) -> some View {
|
|
ZStack {
|
|
Circle()
|
|
.fill(Color.green.opacity(0.2))
|
|
.frame(width: 110, height: 110)
|
|
Image(systemName: systemImage)
|
|
.font(.system(size: 48))
|
|
.foregroundColor(.green)
|
|
}
|
|
.offset(x: offset)
|
|
.animation(.easeInOut(duration: 1.2), value: isRevealing)
|
|
}
|
|
}
|