You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

140 lines
4.4 KiB

//
// NewGameView.swift
// App
//
// Created by etudiant2 on 21/05/2025.
//
import SwiftUI
import PhotosUI
struct NewGameView: View {
@StateObject
private var vm: NewGameVM = NewGameVM()
@StateObject
private var p1: PlayerSettingsVM = PlayerSettingsVM(type: .Human)
@StateObject
private var p2: PlayerSettingsVM = PlayerSettingsVM(type: .AISimpleNegaMax)
var body: some View {
VStack {
Form {
PlayerSectionView("generic.player1.name", color: .piece1, settings: p1)
PlayerSectionView("generic.player2.name", color: .piece2, settings: p2)
HStack {
Picker("newGame.rules.title", systemImage: "slider.horizontal.3", selection: $vm.rulesType) {
ForEach(RulesType.allCases) {
Text($0.baseTranslationKey).tag($0)
}
}
// TODO: info button
// Button(action: {
// // TODO
// }) {
// Image(systemName: "questionmark.circle")
// }
}
Section(header: Label("newGame.dimensions", systemImage: "crop")) {
Stepper("newGame.dimensions.width \(vm.width)", value: $vm.width)
Stepper("newGame.dimensions.height \(vm.height)", value: $vm.height)
Stepper("newGame.dimensions.alignedTokens \(vm.alignedTokens)", value: $vm.alignedTokens)
}
// Section(header: Label("newGame.timeLimit", systemImage: "stopwatch")) {
//
// }
}
}.toolbar {
NavigationLink {
NavigationLazyView(IngameView(settings: vm, player1: p1, player2: p2))
} label: {
Label("newGame.play", systemImage: "play")
}
}
}
}
// https://stackoverflow.com/questions/57594159/swiftui-navigationlink-loads-destination-view-immediately-without-clicking/61234030#61234030
struct NavigationLazyView<Content: View>: View {
let build: () -> Content
init(_ build: @autoclosure @escaping () -> Content) {
self.build = build
}
var body: Content {
build()
}
}
private struct PlayerSectionView: View {
private let sectionLabel: LocalizedStringKey
private let pieceColor: Color
@ObservedObject
private var settings: PlayerSettingsVM
@State private var photo: PhotosPickerItem? = nil
var body: some View {
Section(header: Label {
Text(sectionLabel)
} icon: {
Circle().fill(self.pieceColor)
}.fixedSize(horizontal: true, vertical: false)) {
Picker("newGame.player.type", selection: $settings.type) {
ForEach(PlayerType.allCases) {
Text(LocalizedStringKey($0.baseTranslationKey)).tag($0)
}
}
if (settings.type == .Human) {
TextField("newGame.player.name", text: $settings.name)
// TODO: MacOS
//.textInputSuggestions(isEnabled: true) {
//
//}
}
// // TODO: actual photo support
// Image(systemName: "camera.viewfinder").overlay {
// PhotosPicker(selection: $photo) {
// Text("newGame.player.photo.picker")
// }
// }
}
}
init(_ sectionLabel: LocalizedStringKey, color pieceColor: Color, settings: PlayerSettingsVM) {
self.sectionLabel = sectionLabel
self.pieceColor = pieceColor
self.settings = settings
}
}
extension PlayerType {
var baseTranslationKey: String {
return switch (self) {
case .Human: "generic.player.type.human"
case .AIRandom: "generic.player.type.aiRandom"
case .AIFinnishHim: "generic.player.type.aiFinnishHim"
case .AISimpleNegaMax: "generic.player.type.aiSimpleNegaMax"
}
}
}
extension RulesType {
var baseTranslationKey: LocalizedStringKey {
return switch (self) {
case .Classic: "generic.rules.classic.name"
case .TicTacToe: "generic.rules.tictactoe.name"
case .PopOut: "generic.rules.popout.name"
}
}
}
#Preview {
NewGameView()
}