initial commit: Proximity iOS app proposal, full Swift code scaffold, reference backend, testing docs, generated Xcode project
This commit is contained in:
60
Proximity/ViewModels/PresenceViewModel.swift
Normal file
60
Proximity/ViewModels/PresenceViewModel.swift
Normal file
@@ -0,0 +1,60 @@
|
||||
import Foundation
|
||||
import Combine
|
||||
|
||||
/// View model for the presence experience.
|
||||
///
|
||||
/// Exposes the state the UI needs to render the "am I present?" moment, the
|
||||
/// radius tier picker, and the live feed of encounters (silhouettes).
|
||||
@MainActor
|
||||
final class PresenceViewModel: ObservableObject {
|
||||
|
||||
@Published var isPresent: Bool = false
|
||||
@Published var radiusTier: DistanceTier = .rightHere
|
||||
@Published private(set) var activeEngines: Set<ProximityEngine> = []
|
||||
@Published private(set) var encounters: [Encounter] = []
|
||||
@Published private(set) var lastScan: Date?
|
||||
|
||||
private let engine: PresenceEngine
|
||||
private var cancellables = Set<AnyCancellable>()
|
||||
|
||||
init(engine: PresenceEngine) {
|
||||
self.engine = engine
|
||||
|
||||
engine.$isPresent
|
||||
.assign(to: &$isPresent)
|
||||
engine.$radiusTier
|
||||
.assign(to: &$radiusTier)
|
||||
engine.$activeEngines
|
||||
.assign(to: &$activeEngines)
|
||||
engine.$recentEncounters
|
||||
.assign(to: &$encounters)
|
||||
engine.$lastScan
|
||||
.assign(to: &$lastScan)
|
||||
}
|
||||
|
||||
// MARK: - User actions
|
||||
|
||||
func togglePresence() {
|
||||
isPresent.toggle()
|
||||
Task { await engine.setPresent(isPresent) }
|
||||
}
|
||||
|
||||
func setRadius(_ tier: DistanceTier) {
|
||||
radiusTier = tier
|
||||
Task { await engine.setRadiusTier(tier) }
|
||||
}
|
||||
|
||||
/// Send a "wave" to a silhouette — the first step toward mutual reveal.
|
||||
func wave(to encounter: Encounter) {
|
||||
// In production: POST /v1/wave with the encounter token.
|
||||
Task {
|
||||
await engine.wave(to: encounter)
|
||||
}
|
||||
}
|
||||
|
||||
func block(_ encounter: Encounter) {
|
||||
Task {
|
||||
await engine.block(encounter)
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user