crossmate

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

commit f2bb8d4bb07f3c7d279b83a22969bafb182ef6a4
parent 27a82347e54054650909ebe863501cd15acf2920
Author: Michael Camilleri <[email protected]>
Date:   Tue, 28 Apr 2026 18:05:55 +0900

Add poll-based synchronisation when inside puzzle

Diffstat:
MCrossmate/CrossmateApp.swift | 22++++++++++++++++++++++
MCrossmate/Services/AppServices.swift | 8++++++++
2 files changed, 30 insertions(+), 0 deletions(-)

diff --git a/Crossmate/CrossmateApp.swift b/Crossmate/CrossmateApp.swift @@ -172,6 +172,11 @@ private extension UIApplication { /// Loads a game when navigated to. private struct PuzzleDisplayView: View { + private static let sharedPuzzlePollingInterval: Duration = .seconds(5) + private var sharedID: UUID? { + session?.mutator.isShared == true ? gameID : nil + } + let gameID: UUID let store: GameStore let shareController: ShareController @@ -201,6 +206,10 @@ private struct PuzzleDisplayView: View { } .navigationTitle("") .navigationBarTitleDisplayMode(.inline) + .task(id: sharedID) { + guard sharedID != nil else { return } + await pollOpenSharedPuzzle() + } .task(id: gameID) { do { let (game, mutator) = try store.loadGame(id: gameID) @@ -213,4 +222,17 @@ private struct PuzzleDisplayView: View { } } } + + private func pollOpenSharedPuzzle() async { + await services.syncOpenSharedPuzzle() + while !Task.isCancelled { + do { + try await Task.sleep(for: Self.sharedPuzzlePollingInterval) + } catch { + break + } + guard !Task.isCancelled else { break } + await services.syncOpenSharedPuzzle() + } + } } diff --git a/Crossmate/Services/AppServices.swift b/Crossmate/Services/AppServices.swift @@ -170,6 +170,14 @@ final class AppServices { await moveBuffer.flush() } + func syncOpenSharedPuzzle() async { + await moveBuffer.flush() + await syncMonitor.run("open-puzzle fetch") { + try await syncEngine.fetchChanges() + } + await refreshSnapshot() + } + func makePlayerRoster(for gameID: UUID, preferences: PlayerPreferences) -> PlayerRoster { PlayerRoster( gameID: gameID,