diff --git a/Baccarat/Baccarat/Views/Table/CardsDisplayArea.swift b/Baccarat/Baccarat/Views/Table/CardsDisplayArea.swift index 46077f3..428ffed 100644 --- a/Baccarat/Baccarat/Views/Table/CardsDisplayArea.swift +++ b/Baccarat/Baccarat/Views/Table/CardsDisplayArea.swift @@ -103,11 +103,11 @@ struct CardsDisplayArea: View { let percentage: CGFloat = isLandscape ? 0.175 : height < 700 ? 0.14 : 0.18 let cardWidth = height * percentage - // CompactHandView: cardWidth = containerWidth / divisor - let overlapRatio: CGFloat = -0.45 + // CompactHandView uses: cardWidth = (containerWidth - 2 * spacing) / 3 + // So: containerWidth = 3 * cardWidth + 2 * spacing + let spacing = Design.Spacing.medium let maxCards: CGFloat = 3 - let divisor = 1 + (maxCards - 1) * (1 + overlapRatio) - return cardWidth * divisor + return (cardWidth * maxCards) + (2 * spacing) } /// Current hand section width based on mode diff --git a/Baccarat/Baccarat/Views/Table/CompactHandView.swift b/Baccarat/Baccarat/Views/Table/CompactHandView.swift index 514a0d9..f4b632f 100644 --- a/Baccarat/Baccarat/Views/Table/CompactHandView.swift +++ b/Baccarat/Baccarat/Views/Table/CompactHandView.swift @@ -2,13 +2,13 @@ // CompactHandView.swift // Baccarat // -// A compact view showing cards in a horizontal row with overlap. +// A compact view showing cards in a horizontal row. // import SwiftUI import CasinoKit -/// A compact hand view showing cards in a row with overlap. +/// A compact hand view showing cards in a row. struct CompactHandView: View { let cards: [Card] let cardsFaceUp: [Bool] @@ -34,17 +34,14 @@ struct CompactHandView: View { // MARK: - Constants - /// Overlap ratio relative to card width (negative = overlap) - private let overlapRatio: CGFloat = -0.45 - /// Maximum number of cards in baccarat hand private let maxCards: Int = 3 /// Placeholder spacing when no cards private let placeholderSpacing: CGFloat = Design.Spacing.small - /// Spacing for interactive layout - private let spacedGap: CGFloat = Design.Spacing.medium + /// Spacing between cards + private let cardSpacing: CGFloat = Design.Spacing.medium // MARK: - Computed Properties @@ -59,18 +56,12 @@ struct CompactHandView: View { } /// Card width calculated from container width - /// Formula: containerWidth = cardWidth + (cardWidth + overlap) * 2 - /// Where overlap = cardWidth * overlapRatio + /// Formula accounts for spacing between 3 cards private var cardWidth: CGFloat { - // Use a fixed overlap ratio for sizing to keep cards large - let baseOverlapRatio: CGFloat = -0.45 - let divisor = 1 + CGFloat(maxCards - 1) * (1 + baseOverlapRatio) - return containerWidth / divisor - } - - /// Card overlap based on card width - private var cardOverlap: CGFloat { - cardWidth * overlapRatio + // containerWidth = 3 * cardWidth + 2 * spacing + // cardWidth = (containerWidth - 2 * spacing) / 3 + let spacing = cardSpacing + return max(50, (containerWidth - 2 * spacing) / CGFloat(maxCards)) } /// Card height based on aspect ratio @@ -78,26 +69,9 @@ struct CompactHandView: View { cardWidth * CasinoDesign.Size.cardAspectRatio } - /// Whether to use a spaced layout for interaction - private var useSpacedLayout: Bool { - revealStyle == .tap || revealStyle == .squeeze - } - /// The effective spacing for the card stack private var effectiveSpacing: CGFloat { - if cards.isEmpty { - return placeholderSpacing - } else if useSpacedLayout { - return spacedGap - } else { - return cardOverlap - } - } - - /// Total width required for the spaced layout - private var totalSpacedWidth: CGFloat { - let count = CGFloat(max(cards.count, 2)) - return (count * cardWidth) + ((count - 1) * effectiveSpacing) + cards.isEmpty ? placeholderSpacing : cardSpacing } // MARK: - Body @@ -106,43 +80,34 @@ struct CompactHandView: View { GeometryReader { geometry in let availableWidth = geometry.size.width - Group { - if useSpacedLayout { - // Always use ScrollView in interactive modes for stable view hierarchy - ScrollViewReader { proxy in - ScrollView(.horizontal, showsIndicators: false) { - cardsContent - .padding(.horizontal, Design.Spacing.medium) - .frame(minWidth: availableWidth, alignment: .center) - .id("cards_container") - } - .scrollDisabled(cards.count < 3) - .scrollClipDisabled(true) // Prevent clipping during deal animations - .background(Color.clear) - .onChange(of: cards.count) { _, newCount in - // When 3rd card is dealt, wait for animation then scroll - if newCount == 3 { - let lastIndex = isBottom ? 4 : 5 - DispatchQueue.main.asyncAfter(deadline: .now() + 0.8) { - withAnimation(.spring(duration: 0.5)) { - proxy.scrollTo(lastIndex, anchor: .center) - } - } - } - } - .onChange(of: currentRevealIndex) { _, newIndex in - // Scroll to the active card during interaction - if newIndex >= 4 { - withAnimation(.spring(duration: 0.5)) { - proxy.scrollTo(newIndex, anchor: .center) - } + ScrollViewReader { proxy in + ScrollView(.horizontal, showsIndicators: false) { + cardsContent + .padding(.horizontal, Design.Spacing.medium) + .frame(minWidth: availableWidth, alignment: .center) + .id("cards_container") + } + .scrollDisabled(cards.count < 3) + .scrollClipDisabled(true) // Prevent clipping during deal animations + .background(Color.clear) + .onChange(of: cards.count) { _, newCount in + // When 3rd card is dealt, wait for animation then scroll + if newCount == 3 { + let lastIndex = isBottom ? 4 : 5 + DispatchQueue.main.asyncAfter(deadline: .now() + 0.8) { + withAnimation(.spring(duration: 0.5)) { + proxy.scrollTo(lastIndex, anchor: .center) } } } - } else { - // Regular centered layout for non-interactive modes - cardsContent - .frame(maxWidth: .infinity, alignment: .center) + } + .onChange(of: currentRevealIndex) { _, newIndex in + // Scroll to the active card during interaction + if newIndex >= 4 { + withAnimation(.spring(duration: 0.5)) { + proxy.scrollTo(newIndex, anchor: .center) + } + } } } }