add claude
This commit is contained in:
190
ios/AiCard/AiCard/Views/GachaView.swift
Normal file
190
ios/AiCard/AiCard/Views/GachaView.swift
Normal file
@@ -0,0 +1,190 @@
|
||||
import SwiftUI
|
||||
|
||||
struct GachaView: View {
|
||||
@EnvironmentObject var authManager: AuthManager
|
||||
@EnvironmentObject var cardManager: CardManager
|
||||
@State private var showingAnimation = false
|
||||
|
||||
var body: some View {
|
||||
ZStack {
|
||||
// Background
|
||||
LinearGradient(
|
||||
gradient: Gradient(colors: [
|
||||
Color(hex: "0a0a0a"),
|
||||
Color(hex: "1a1a1a")
|
||||
]),
|
||||
startPoint: .top,
|
||||
endPoint: .bottom
|
||||
)
|
||||
.ignoresSafeArea()
|
||||
|
||||
VStack(spacing: 40) {
|
||||
// Title
|
||||
VStack(spacing: 16) {
|
||||
Text("カードを引く")
|
||||
.font(.largeTitle)
|
||||
.fontWeight(.bold)
|
||||
.foregroundColor(.white)
|
||||
|
||||
if let user = authManager.currentUser {
|
||||
Text("@\(user.handle)")
|
||||
.font(.subheadline)
|
||||
.foregroundColor(Color(hex: "fff700"))
|
||||
}
|
||||
}
|
||||
|
||||
Spacer()
|
||||
|
||||
// Gacha buttons
|
||||
VStack(spacing: 20) {
|
||||
GachaButton(
|
||||
title: "通常ガチャ",
|
||||
subtitle: "無料でカードを1枚引く",
|
||||
colors: [Color(hex: "667eea"), Color(hex: "764ba2")],
|
||||
action: {
|
||||
drawCard(isPaid: false)
|
||||
},
|
||||
isLoading: cardManager.isDrawing
|
||||
)
|
||||
|
||||
GachaButton(
|
||||
title: "プレミアムガチャ",
|
||||
subtitle: "レア確率アップ!",
|
||||
colors: [Color(hex: "f093fb"), Color(hex: "f5576c")],
|
||||
action: {
|
||||
drawCard(isPaid: true)
|
||||
},
|
||||
isLoading: cardManager.isDrawing,
|
||||
isPremium: true
|
||||
)
|
||||
}
|
||||
.padding(.horizontal, 32)
|
||||
|
||||
if let errorMessage = cardManager.errorMessage {
|
||||
Text(errorMessage)
|
||||
.font(.caption)
|
||||
.foregroundColor(.red)
|
||||
.padding()
|
||||
}
|
||||
|
||||
Spacer()
|
||||
}
|
||||
.padding()
|
||||
|
||||
// Gacha animation overlay
|
||||
if let currentDraw = cardManager.currentDraw {
|
||||
GachaAnimationView(
|
||||
drawResult: currentDraw,
|
||||
onComplete: {
|
||||
cardManager.completeCardDraw()
|
||||
}
|
||||
)
|
||||
.transition(.opacity)
|
||||
.zIndex(1000)
|
||||
}
|
||||
}
|
||||
.onAppear {
|
||||
if let userDid = authManager.currentUser?.did {
|
||||
cardManager.loadUserCards(userDid: userDid)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private func drawCard(isPaid: Bool) {
|
||||
guard let userDid = authManager.currentUser?.did else { return }
|
||||
cardManager.drawCard(userDid: userDid, isPaid: isPaid)
|
||||
}
|
||||
}
|
||||
|
||||
struct GachaButton: View {
|
||||
let title: String
|
||||
let subtitle: String
|
||||
let colors: [Color]
|
||||
let action: () -> Void
|
||||
let isLoading: Bool
|
||||
let isPremium: Bool
|
||||
|
||||
init(title: String, subtitle: String, colors: [Color], action: @escaping () -> Void, isLoading: Bool, isPremium: Bool = false) {
|
||||
self.title = title
|
||||
self.subtitle = subtitle
|
||||
self.colors = colors
|
||||
self.action = action
|
||||
self.isLoading = isLoading
|
||||
self.isPremium = isPremium
|
||||
}
|
||||
|
||||
var body: some View {
|
||||
Button(action: action) {
|
||||
VStack(spacing: 8) {
|
||||
Text(title)
|
||||
.font(.title2)
|
||||
.fontWeight(.bold)
|
||||
.foregroundColor(.white)
|
||||
|
||||
Text(subtitle)
|
||||
.font(.caption)
|
||||
.foregroundColor(.white.opacity(0.8))
|
||||
}
|
||||
.frame(maxWidth: .infinity)
|
||||
.frame(height: 80)
|
||||
.background(
|
||||
ZStack {
|
||||
LinearGradient(
|
||||
gradient: Gradient(colors: colors),
|
||||
startPoint: .leading,
|
||||
endPoint: .trailing
|
||||
)
|
||||
|
||||
if isPremium {
|
||||
// Shimmer effect for premium
|
||||
ShimmerView()
|
||||
}
|
||||
}
|
||||
)
|
||||
.cornerRadius(16)
|
||||
.shadow(color: colors.first?.opacity(0.3) ?? .clear, radius: 10, x: 0, y: 5)
|
||||
.overlay(
|
||||
Group {
|
||||
if isLoading {
|
||||
ProgressView()
|
||||
.progressViewStyle(CircularProgressViewStyle(tint: .white))
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
.disabled(isLoading)
|
||||
.scaleEffect(isLoading ? 0.95 : 1.0)
|
||||
.animation(.easeInOut(duration: 0.1), value: isLoading)
|
||||
}
|
||||
}
|
||||
|
||||
struct ShimmerView: View {
|
||||
@State private var phase: CGFloat = 0
|
||||
|
||||
var body: some View {
|
||||
LinearGradient(
|
||||
gradient: Gradient(colors: [
|
||||
.clear,
|
||||
.white.opacity(0.2),
|
||||
.clear
|
||||
]),
|
||||
startPoint: .leading,
|
||||
endPoint: .trailing
|
||||
)
|
||||
.rotationEffect(.degrees(45))
|
||||
.offset(x: phase)
|
||||
.onAppear {
|
||||
withAnimation(.linear(duration: 2).repeatForever(autoreverses: false)) {
|
||||
phase = 300
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct GachaView_Previews: PreviewProvider {
|
||||
static var previews: some View {
|
||||
GachaView()
|
||||
.environmentObject(AuthManager())
|
||||
.environmentObject(CardManager())
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user