crossmate

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

commit 615f5c38dd7b8e242a52e478c8f55e4c274b9ba9
parent eb7b36cb8990f00f52624a13572b0ac603adb8fc
Author: Michael Camilleri <[email protected]>
Date:   Thu, 30 Apr 2026 14:00:22 +0900

Make game list styling dependent on scene size

Diffstat:
MCrossmate/Views/GameListView.swift | 97++++++++++++++++++++++++++++++++++++++++++++++++-------------------------------
1 file changed, 59 insertions(+), 38 deletions(-)

diff --git a/Crossmate/Views/GameListView.swift b/Crossmate/Views/GameListView.swift @@ -7,6 +7,7 @@ struct GameListView: View { @Binding var navigationPath: NavigationPath @Environment(\.managedObjectContext) private var viewContext + @Environment(\.dynamicTypeSize) private var dynamicTypeSize @FetchRequest( sortDescriptors: [], animation: .default @@ -33,36 +34,8 @@ struct GameListView: View { } var body: some View { - Group { - if games.isEmpty { - ContentUnavailableView { - Label("No Puzzles", systemImage: "square.grid.3x3") - } description: { - Text("Tap the + button to start a new puzzle.") - } - } else { - List { - if !inProgress.isEmpty { - Section { - ForEach(inProgress) { game in - rowView(for: game) - } - } header: { - Text("In Progress") - } - } - - if !completed.isEmpty { - Section { - ForEach(completed) { game in - rowView(for: game) - } - } header: { - Text("Completed") - } - } - } - } + GeometryReader { geometry in + content(usesRoomierType: usesRoomierType(for: geometry.size)) } .navigationTitle("") .navigationBarTitleDisplayMode(.inline) @@ -136,10 +109,46 @@ struct GameListView: View { } @ViewBuilder - private func rowView(for game: GameSummary) -> some View { + private func content(usesRoomierType: Bool) -> some View { + Group { + if games.isEmpty { + ContentUnavailableView { + Label("No Puzzles", systemImage: "square.grid.3x3") + } description: { + Text("Tap the + button to start a new puzzle.") + } + } else { + List { + if !inProgress.isEmpty { + Section { + ForEach(inProgress) { game in + rowView(for: game, usesRoomierType: usesRoomierType) + } + } header: { + Text("In Progress") + } + } + + if !completed.isEmpty { + Section { + ForEach(completed) { game in + rowView(for: game, usesRoomierType: usesRoomierType) + } + } header: { + Text("Completed") + } + } + } + } + } + } + + @ViewBuilder + private func rowView(for game: GameSummary, usesRoomierType: Bool) -> some View { GameRowView( game: game, shareController: shareController, + usesRoomierType: usesRoomierType, onResume: { navigationPath.append(game.id) }, onLeave: { leaveTarget = game }, onResign: { resignTarget = game }, @@ -165,6 +174,10 @@ struct GameListView: View { leaveTarget = nil } } + + private func usesRoomierType(for size: CGSize) -> Bool { + size.height >= 800 && dynamicTypeSize <= .medium + } } // MARK: - Row @@ -172,6 +185,7 @@ struct GameListView: View { private struct GameRowView: View { let game: GameSummary let shareController: ShareController + let usesRoomierType: Bool var onResume: () -> Void = {} var onLeave: () -> Void = {} var onResign: () -> Void = {} @@ -203,7 +217,7 @@ private struct GameRowView: View { VStack(alignment: .leading, spacing: 2) { HStack(spacing: 4) { Text(game.title) - .font(.subheadline.weight(.semibold)) + .font((usesRoomierType ? Font.headline : .subheadline).weight(.semibold)) .lineLimit(1) .minimumScaleFactor(0.8) .truncationMode(.tail) @@ -215,10 +229,11 @@ private struct GameRowView: View { } GameMetadataView( puzzleDate: game.puzzleDate, - publisher: game.publisher + publisher: game.publisher, + usesRoomierType: usesRoomierType ) if let date = game.updatedAt { - LastUpdatedView(date: date) + LastUpdatedView(date: date, usesRoomierType: usesRoomierType) } } Spacer() @@ -258,10 +273,11 @@ private struct GameRowView: View { private struct LastUpdatedView: View { let date: Date + let usesRoomierType: Bool var body: some View { Text(text) - .font(.caption) + .font(usesRoomierType ? .footnote : .caption) .foregroundStyle(.secondary) } @@ -286,6 +302,11 @@ private struct LastUpdatedView: View { private struct GameMetadataView: View { let puzzleDate: Date? let publisher: String? + let usesRoomierType: Bool + + private var font: Font { + usesRoomierType ? .subheadline : .footnote + } var body: some View { if let puzzleDate, let publisher { @@ -295,7 +316,7 @@ private struct GameMetadataView: View { Text(" • ") Text(publisher) } - .font(.footnote) + .font(font) .lineLimit(1) VStack(alignment: .leading, spacing: 2) { @@ -315,12 +336,12 @@ private struct GameMetadataView: View { private func puzzleDateView(_ puzzleDate: Date) -> some View { Text(puzzleDate, format: .dateTime.day().month(.abbreviated).year()) - .font(.footnote) + .font(font) } private func publisherView(_ publisher: String) -> some View { Text(publisher) - .font(.footnote) + .font(font) .lineLimit(1) .truncationMode(.tail) }