crossmate

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

commit 99380cca5615528148ccdf247fe98c84efd95ffa
parent c9beaa643ce5ca3374387e3775b15d444fd3f156
Author: Michael Camilleri <[email protected]>
Date:   Tue, 19 May 2026 10:38:25 +0900

Use invitation animations in short list as well

Diffstat:
MCrossmate/Views/GameShareItem.swift | 35+++++++++++++++++------------------
1 file changed, 17 insertions(+), 18 deletions(-)

diff --git a/Crossmate/Views/GameShareItem.swift b/Crossmate/Views/GameShareItem.swift @@ -162,27 +162,17 @@ struct GameShareSheet: View { @ViewBuilder private func friendInviteButton(for friend: FriendEntity) -> some View { let authorID = friend.authorID ?? "" - let isInviting = invitingAuthorID == authorID let wasInvited = invitedAuthorIDs.contains(authorID) Button { Task { await invite(authorID) } } label: { VStack(spacing: 8) { - ZStack { - FriendAvatarView(authorID: authorID, size: 40) - if isInviting { - ProgressView() - .controlSize(.small) - .background(.background, in: Circle()) - } else if wasInvited { - Image(systemName: "checkmark.circle.fill") - .font(.caption) - .foregroundStyle(.secondary) - .background(.background, in: Circle()) - .offset(x: 12, y: -10) - } - } + FriendAvatarView( + authorID: authorID, + size: 40, + invitePhase: invitePhase(authorID: authorID, invited: wasInvited) + ) Text(displayName(for: friend)) .font(.callout.weight(.medium)) .lineLimit(1) @@ -193,6 +183,15 @@ struct GameShareSheet: View { .disabled(authorID.isEmpty || invitingAuthorID != nil || wasInvited) } + /// Maps the row's invite state to the avatar's animation phase. Sending + /// is checked first so the glyph keeps wiggling right up until the work + /// finishes, then resolves straight into the spin-to-checkmark. + private func invitePhase(authorID: String, invited: Bool) -> FriendAvatarView.InvitePhase? { + if invitingAuthorID == authorID { return .sending } + if invited { return .sent } + return nil + } + private func displayName(for friend: FriendEntity) -> String { if let name = friend.displayName?.trimmingCharacters(in: .whitespacesAndNewlines), !name.isEmpty { @@ -203,13 +202,13 @@ struct GameShareSheet: View { private func invite(_ authorID: String) async { guard !authorID.isEmpty, let inviteFriend else { return } - invitingAuthorID = authorID + withAnimation(.snappy) { invitingAuthorID = authorID } errorMessage = nil - defer { invitingAuthorID = nil } + defer { withAnimation(.snappy) { invitingAuthorID = nil } } do { try await inviteFriend(gameID, authorID) - invitedAuthorIDs.insert(authorID) + withAnimation(.snappy) { invitedAuthorIDs.insert(authorID) } } catch { errorMessage = describe(error) }