Signed-off-by: Matt Bruce <mbrucedogs@gmail.com>
This commit is contained in:
parent
109b2416fc
commit
32bff901c7
@ -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
|
||||
|
||||
@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user