crossmate

A collaborative crossword app for iOS
Log | Files | Refs | LICENSE

commit 910e66bc7b6dd11fffcd9434df74320bb9fe09fb
parent 3c8891e3d4a5b49a393baf5e042a708f4db7ba55
Author: Michael Camilleri <[email protected]>
Date:   Wed, 10 Jun 2026 02:56:40 +0900

Remove engagement menu option

Diffstat:
MCrossmate/CrossmateApp.swift | 3---
MCrossmate/Services/AppServices.swift | 29+++++------------------------
MCrossmate/Services/EngagementHostEnvironment.swift | 9---------
MCrossmate/Views/PuzzleView.swift | 6------
4 files changed, 5 insertions(+), 42 deletions(-)

diff --git a/Crossmate/CrossmateApp.swift b/Crossmate/CrossmateApp.swift @@ -26,9 +26,6 @@ struct CrossmateApp: App { .environment(services.eventLog) .environment(\.syncEngine, services.syncEngine) .environment(\.engagementStatus, services.engagementStatus) - .environment(\.offerEngagement, { gameID in - await services.offerEngagement(gameID: gameID) - }) .environment(services.nytAuth) .environment(\.nytPuzzleFetcher, services.nytFetcher) .environment(\.resetDatabase, { diff --git a/Crossmate/Services/AppServices.swift b/Crossmate/Services/AppServices.swift @@ -1426,12 +1426,11 @@ final class AppServices { /// hands the desired creds to the coordinator, which connects, migrates, or /// tears down to match. `force` is the manual "start a room now" path, /// which mints and connects without waiting to see a present peer. - func reconcileEngagement(gameID: UUID, force: Bool = false) async { + func reconcileEngagement(gameID: UUID) async { guard preferences.isICloudSyncEnabled else { return } // A completed game is not a live session. Never connect (this is also // the reopen-from-Completed path, which re-runs through - // `startEngagementIfPossible`) and tear down anything still up — even - // a `force` manual offer is refused once the puzzle is done. + // `startEngagementIfPossible`) and tear down anything still up. guard !store.isCompleted(gameID: gameID) else { cancelEngagementLeaseExpiry(gameID: gameID) await engagementCoordinator.reconcile(gameID: gameID, creds: nil, hasPeer: false) @@ -1458,7 +1457,7 @@ final class AppServices { gameID: gameID, localAuthorID: identity.currentID ) - let hasPeer = force || soonestLease != nil + let hasPeer = soonestLease != nil var creds = EngagementRoomCredentials.decode(store.engagement(for: gameID)) if creds == nil, hasPeer { if let minted = try? EngagementRoomCredentials.fresh(), @@ -1476,7 +1475,7 @@ final class AppServices { // onto the new horizon if one did. That instant is the lease plus the // presence grace, not the bare lease — a peer stays present through the // grace, so tearing down at the raw lease would race it. The 30s - // reconnect tick remains the coarse backstop. A force/no-peer reconcile + // reconnect tick remains the coarse backstop. A no-peer reconcile // has no lease to watch, so this just clears any prior wake. scheduleEngagementLeaseExpiry( gameID: gameID, @@ -1484,24 +1483,6 @@ final class AppServices { ) } - func offerEngagement(gameID: UUID) async { - cancelScheduledEngagementEnd(gameID: gameID) - guard preferences.isICloudSyncEnabled else { - syncMonitor.note("engagement: manual offer skipped, iCloud sync is disabled") - return - } - guard await ensureICloudSyncStarted() else { - syncMonitor.note("engagement: manual offer skipped, iCloud sync is unavailable") - return - } - syncMonitor.note( - "engagement: manual offer requested for \(gameID.uuidString) " + - "device=\(RecordSerializer.localDeviceID.prefix(8))" - ) - await reconcileEngagement(gameID: gameID, force: true) - startEngagementReconnectRetry(gameID: gameID) - } - func startEngagementIfPossible(gameID: UUID) async { cancelScheduledEngagementEnd(gameID: gameID) guard preferences.isICloudSyncEnabled else { return } @@ -1596,7 +1577,7 @@ final class AppServices { /// peer's lease lapses — replacing any prior wake for this game. When it /// fires, `reconcileEngagement` tears the channel down if no renewal landed /// (so the bolt drops at expiry, not up to a tick later) or reschedules - /// onto the renewed horizon. `nil` (force/no-peer) just clears the wake. + /// onto the renewed horizon. `nil` (no-peer) just clears the wake. private func scheduleEngagementLeaseExpiry(gameID: UUID, at expiry: Date?) { engagementLeaseExpiryTasks[gameID]?.cancel() engagementLeaseExpiryTasks[gameID] = nil diff --git a/Crossmate/Services/EngagementHostEnvironment.swift b/Crossmate/Services/EngagementHostEnvironment.swift @@ -22,18 +22,9 @@ private struct EngagementStatusKey: EnvironmentKey { static let defaultValue: EngagementStatus? = nil } -private struct OfferEngagementKey: EnvironmentKey { - static let defaultValue: (@Sendable (UUID) async -> Void)? = nil -} - extension EnvironmentValues { var engagementStatus: EngagementStatus? { get { self[EngagementStatusKey.self] } set { self[EngagementStatusKey.self] = newValue } } - - var offerEngagement: (@Sendable (UUID) async -> Void)? { - get { self[OfferEngagementKey.self] } - set { self[OfferEngagementKey.self] = newValue } - } } diff --git a/Crossmate/Views/PuzzleView.swift b/Crossmate/Views/PuzzleView.swift @@ -792,7 +792,6 @@ private struct PuzzleToolbarModifier: ViewModifier { @Binding var pendingRevealScope: RevealScope @Binding var isShowingShareSheet: Bool @Environment(PlayerPreferences.self) private var preferences - @Environment(\.offerEngagement) private var offerEngagement @AppStorage("debugMode") private var debugMode = false func body(content: Content) -> some View { @@ -858,11 +857,6 @@ private struct PuzzleToolbarModifier: ViewModifier { } label: { Text("Diagnostics Log") } - - Button("Force Engagement") { - Task { await offerEngagement?(session.mutator.gameID) } - } - .disabled(offerEngagement == nil) } }