crossmate

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

commit 18134f4f82ee0cdbe3a1b30210e8881c3e5c9940
parent 33cbb14d87ffcb3b0656b9415bb4f0c909c03715
Author: Michael Camilleri <[email protected]>
Date:   Sun,  3 May 2026 13:20:56 +0900

Add colours to text in shared games

In shared games, it can be helpful to see which user entered which
letter. This commit adds this for shared games only.

Co-Authored-By: Claude Opus 4.7 <[email protected]>

Diffstat:
MCrossmate/Views/CellView.swift | 8++++++++
MCrossmate/Views/GridView.swift | 15++++++++++++---
2 files changed, 20 insertions(+), 3 deletions(-)

diff --git a/Crossmate/Views/CellView.swift b/Crossmate/Views/CellView.swift @@ -10,6 +10,7 @@ struct CellView: View, Equatable { let specialKind: Puzzle.Special? var remoteWordTint: Color? = nil var remoteOutline: Color? = nil + var letterColor: Color? = nil @Environment(PlayerPreferences.self) private var preferences private var playerColor: PlayerColor { preferences.color } @@ -24,6 +25,7 @@ struct CellView: View, Equatable { && lhs.specialKind == rhs.specialKind && lhs.remoteWordTint == rhs.remoteWordTint && lhs.remoteOutline == rhs.remoteOutline + && lhs.letterColor == rhs.letterColor } var body: some View { @@ -73,8 +75,14 @@ struct CellView: View, Equatable { private var entryStyle: AnyShapeStyle { switch mark { case .pencil: + if let letterColor { + return AnyShapeStyle(letterColor.opacity(0.55)) + } return AnyShapeStyle(HierarchicalShapeStyle.secondary) case .none, .pen, .revealed: + if let letterColor { + return AnyShapeStyle(letterColor) + } return AnyShapeStyle(HierarchicalShapeStyle.primary) } } diff --git a/Crossmate/Views/GridView.swift b/Crossmate/Views/GridView.swift @@ -13,6 +13,13 @@ struct GridView: View { // value it needs. Multiple peers landing on the same cell collapse // to the most recent. let (outlineByCell, tintByCell) = remoteOverlays() + // In shared games, colour each letter by its author. Single-player + // games (`roster == nil`) keep the default primary/secondary styling. + let letterColorByAuthor: [String: Color] = roster.map { roster in + Dictionary( + uniqueKeysWithValues: roster.entries.map { ($0.authorID, $0.color.tint) } + ) + } ?? [:] let relatedCells = session.puzzle.relatedCells( atRow: session.selectedRow, col: session.selectedCol, @@ -28,16 +35,18 @@ struct GridView: View { let r = index / width let c = index % width let pos = GridPosition(row: r, col: c) + let square = session.game.squares[r][c] CellView( cell: session.puzzle.cells[r][c], - entry: session.game.squares[r][c].entry, - mark: session.game.squares[r][c].mark, + entry: square.entry, + mark: square.mark, isSelected: session.selectedRow == r && session.selectedCol == c, isHighlighted: currentWordCells.contains(pos), isRelatedToFocus: relatedCells.contains(pos), specialKind: session.puzzle.specialKind, remoteWordTint: tintByCell[pos], - remoteOutline: outlineByCell[pos] + remoteOutline: outlineByCell[pos], + letterColor: square.letterAuthorID.flatMap { letterColorByAuthor[$0] } ) .equatable() .onTapGesture {