mirror of
https://github.com/rive-app/rive-ios.git
synced 2026-01-18 17:11:28 +01:00
201 lines
6.3 KiB
Swift
201 lines
6.3 KiB
Swift
//
|
|
// RewardsView.swift
|
|
// Preview (iOS)
|
|
//
|
|
// Created by David Skuza on 4/21/25.
|
|
// Copyright © 2025 Rive. All rights reserved.
|
|
//
|
|
|
|
import SwiftUI
|
|
import RiveRuntime
|
|
|
|
class RewardsViewModel: RiveViewModel {
|
|
enum RewardType: String, CaseIterable {
|
|
case coin = "Coin"
|
|
case gem = "Gem"
|
|
}
|
|
|
|
private var instance: RiveDataBindingViewModel.Instance? = nil
|
|
|
|
@Published var rewardType: RewardType = .coin {
|
|
didSet {
|
|
rewardTypeProperty?.value = rewardType.rawValue
|
|
}
|
|
}
|
|
|
|
private var rewardTypeProperty: RiveDataBindingViewModel.Instance.EnumProperty? {
|
|
return instance?.enumProperty(fromPath: "Item_Selection/Item_Selection")
|
|
}
|
|
|
|
@Published var coinCount: Int = 0 {
|
|
didSet {
|
|
coinCountProperty?.value = Float(coinCount)
|
|
}
|
|
}
|
|
|
|
private var coinCountProperty: RiveDataBindingViewModel.Instance.NumberProperty? {
|
|
return instance?.numberProperty(fromPath: "Coin/Item_Value")
|
|
}
|
|
|
|
@Published var gemCount: Int = 0 {
|
|
didSet {
|
|
gemCountProperty?.value = Float(gemCount)
|
|
}
|
|
}
|
|
|
|
private var gemCountProperty: RiveDataBindingViewModel.Instance.NumberProperty? {
|
|
return instance?.numberProperty(fromPath: "Gem/Item_Value")
|
|
}
|
|
|
|
@Published var price: Int = 0 {
|
|
didSet {
|
|
priceProperty?.value = Float(price)
|
|
}
|
|
}
|
|
|
|
private var priceProperty: RiveDataBindingViewModel.Instance.NumberProperty? {
|
|
return instance?.numberProperty(fromPath: "Price_Value")
|
|
}
|
|
|
|
@Published var initialButtonText: String = "" {
|
|
didSet {
|
|
initialButtonTextProperty?.value = initialButtonText
|
|
}
|
|
}
|
|
|
|
private var initialButtonTextProperty: RiveDataBindingViewModel.Instance.StringProperty? {
|
|
return instance?.stringProperty(fromPath: "Button/State_1")
|
|
}
|
|
|
|
@Published var isPresentingAlert = false
|
|
private(set) var alertMessage: String = ""
|
|
|
|
init() {
|
|
super.init(fileName: "rewards")
|
|
|
|
riveModel?.enableAutoBind { [weak self] instance in
|
|
guard let self else { return }
|
|
self.instance = instance
|
|
|
|
// Set new default values based on the auto-bound instance
|
|
if let rewardTypeProperty, let reward = RewardType(rawValue: rewardTypeProperty.value) { rewardType = reward }
|
|
if let coinCountProperty { coinCount = Int(coinCountProperty.value) }
|
|
if let gemCountProperty { gemCount = Int(gemCountProperty.value) }
|
|
if let priceProperty { price = Int(priceProperty.value) }
|
|
if let initialButtonTextProperty { initialButtonText = initialButtonTextProperty.value }
|
|
|
|
instance.triggerProperty(fromPath: "Coin/Icon_React")?.addListener { [weak self] in
|
|
guard let self, let coins = coinCountProperty?.value else { return }
|
|
alertMessage = "You have \(coins) coins!"
|
|
isPresentingAlert = true
|
|
}
|
|
|
|
instance.triggerProperty(fromPath: "Gem/Icon_React")?.addListener { [weak self] in
|
|
guard let self, let gems = gemCountProperty?.value else { return }
|
|
alertMessage = "You have \(gems) gems!"
|
|
isPresentingAlert = true
|
|
}
|
|
}
|
|
}
|
|
|
|
override func reset() {
|
|
super.reset()
|
|
|
|
rewardType = rewardType
|
|
coinCount = coinCount
|
|
gemCount = gemCount
|
|
price = price
|
|
initialButtonText = initialButtonText
|
|
}
|
|
}
|
|
|
|
struct RewardsSettingsView: View {
|
|
@ObservedObject private var viewModel: RewardsViewModel
|
|
|
|
init(viewModel: RewardsViewModel) {
|
|
_viewModel = ObservedObject(wrappedValue: viewModel)
|
|
}
|
|
|
|
var body: some View {
|
|
Form {
|
|
Section {
|
|
Picker("Type", selection: $viewModel.rewardType) {
|
|
Text("Coin").tag(RewardsViewModel.RewardType.coin)
|
|
Text("Gem").tag(RewardsViewModel.RewardType.gem)
|
|
}
|
|
|
|
HStack {
|
|
Text("Coin Count")
|
|
TextField("Coin Count", value: $viewModel.coinCount, formatter: NumberFormatter()).multilineTextAlignment(.trailing)
|
|
}
|
|
|
|
HStack {
|
|
Text("Gem Count")
|
|
TextField("Gem Count", value: $viewModel.gemCount, formatter: NumberFormatter()).multilineTextAlignment(.trailing)
|
|
}
|
|
|
|
HStack {
|
|
Text("Price")
|
|
TextField("Price", value: $viewModel.price, formatter: NumberFormatter()).multilineTextAlignment(.trailing)
|
|
}
|
|
} header: {
|
|
Text("Reward")
|
|
}
|
|
|
|
Section {
|
|
HStack {
|
|
Text("Initial Text")
|
|
TextField("Initial Text", text: $viewModel.initialButtonText).multilineTextAlignment(.trailing)
|
|
}
|
|
} header: {
|
|
Text("Reward")
|
|
}
|
|
|
|
Section {
|
|
Button {
|
|
viewModel.reset()
|
|
} label: {
|
|
Text("Reset").foregroundColor(.red)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
struct RewardsView: DismissableView {
|
|
var dismiss: () -> Void = {}
|
|
|
|
@StateObject var rewardsViewModel: RewardsViewModel
|
|
@State var isPresentingSettings = false
|
|
|
|
init() {
|
|
let viewModel = RewardsViewModel()
|
|
_rewardsViewModel = StateObject(wrappedValue: viewModel)
|
|
}
|
|
|
|
var body: some View {
|
|
rewardsViewModel
|
|
.view()
|
|
.toolbar {
|
|
Button("Settings") {
|
|
isPresentingSettings = true
|
|
}
|
|
}
|
|
.sheet(isPresented: $isPresentingSettings) {
|
|
if #available(iOS 16, *) {
|
|
RewardsSettingsView(viewModel: rewardsViewModel)
|
|
.presentationDetents([.medium])
|
|
} else {
|
|
RewardsSettingsView(viewModel: rewardsViewModel)
|
|
}
|
|
}
|
|
.alert(isPresented: $rewardsViewModel.isPresentingAlert) {
|
|
Alert(
|
|
title: Text("Congratulations"),
|
|
message: Text(rewardsViewModel.alertMessage),
|
|
dismissButton: .default(Text("Okay"))
|
|
)
|
|
}
|
|
}
|
|
}
|