Makes MonsterDetail use a MonsterViewModel instead of the core data type Monster.

This commit is contained in:
2021-04-04 00:30:55 -07:00
parent 568485a62e
commit 68a6051dca
5 changed files with 74 additions and 47 deletions

View File

@@ -34,7 +34,7 @@ public class AbilityViewModel: NSObject, ObservableObject, Identifiable, NSSecur
}
}
public func renderedText(_ monster: Monster) -> String {
func renderedText(_ monster: MonsterViewModel) -> String {
let strSave = monster.strengthModifier + monster.proficiencyBonus + 8
let dexSave = monster.dexterityModifier + monster.proficiencyBonus + 8
let conSave = monster.constitutionModifier + monster.proficiencyBonus + 8

View File

@@ -125,4 +125,25 @@ class SkillViewModel: ObservableObject, Comparable, Hashable, Identifiable {
newSkill.wrappedAdvantage = advantage
return newSkill
}
func modifier(forMonster: MonsterViewModel) -> Int {
let proficiencyBonus = Double(forMonster.proficiencyBonus)
let abilityScoreModifier = Double(forMonster.abilityModifierForAbilityScore(abilityScore))
switch proficiency {
case .none:
return Int(abilityScoreModifier)
case .proficient:
return Int(abilityScoreModifier + proficiencyBonus)
case .expertise:
return Int(abilityScoreModifier + 2 * proficiencyBonus)
}
}
func skillDescription(forMonster: MonsterViewModel) -> String {
var advantageLabel = Monster.advantageLabelStringForType(advantage)
if (advantageLabel != "") {
advantageLabel = " " + advantageLabel
}
return String(format: "%@ %+d%@", name, modifier(forMonster: forMonster), advantageLabel)
}
}

View File

@@ -20,7 +20,7 @@ struct Library: View {
var body: some View {
NavigationView{
List(allMonsters) { monster in
NavigationLink(destination: MonsterDetail(monster: monster)) {
NavigationLink(destination: MonsterDetailWrapper(monster: monster)) {
Text(monster.name ?? "")
}
}

View File

@@ -72,7 +72,7 @@ struct SmallAbilityScore: View {
}
struct BasicInfoView: View {
@ObservedObject var monster: Monster
@ObservedObject var monster: MonsterViewModel
var body: some View {
let monsterMeta = monster.meta
@@ -113,7 +113,7 @@ struct BasicInfoView: View {
}
struct AbilityScoresView: View {
@ObservedObject var monster: Monster
@ObservedObject var monster: MonsterViewModel
var body: some View {
SectionDivider()
@@ -131,7 +131,7 @@ struct AbilityScoresView: View {
}
struct ResistancesAndImmunitiesView: View {
@ObservedObject var monster: Monster
@ObservedObject var monster: MonsterViewModel
var body: some View {
let monsterDamageVulnerabilitiesDescription = monster.damageVulnerabilitiesDescription
@@ -178,7 +178,7 @@ struct ResistancesAndImmunitiesView: View {
}
struct SavingThrowsAndSkillsView: View {
@ObservedObject var monster: Monster
@ObservedObject var monster: MonsterViewModel
var body: some View {
let savingThrowsDescription = monster.savingThrowsDescription
@@ -200,37 +200,28 @@ struct SavingThrowsAndSkillsView: View {
}
}
struct MonsterDetail: View {
let kTextColor: Color = Color(hex: 0x982818)
struct MonsterDetailView: View {
let kTextColor = Color(hex: 0x982818)
@ObservedObject var monster: Monster
var viewModel: MonsterViewModel
var body: some View {
let monsterLanguagesDescription = viewModel.languagesDescription
let monsterChallengeRatingDescription = viewModel.challengeRatingDescription
ScrollView {
// TODO: Consider adding an inmage here at the top
VStack (alignment: .leading) {
let monsterLanguagesDescription = monster.languagesDescription
let monsterChallengeRatingDescription = monster.challengeRatingDescription
let monsterAbilities: [AbilityViewModel] = monster.abilities ?? []
let monsterActions: [AbilityViewModel] = monster.actions ?? []
let monsterLegendaryActions: [AbilityViewModel] = monster.legendaryActions ?? []
BasicInfoView(monster: monster)
// TODO: Find a way to hide unnecessarry dividiers.
// if sections 0, 1, 2, and 3 are present there should be a divider between each of them
// if section 1 is not present there should be one and only one divider between sections 0 and 2 as well as the one between 2 and 3
// if sections 1 and 2 are not present there should be a single divider between sections 0 and 3
AbilityScoresView(monster: monster)
BasicInfoView(monster: viewModel)
AbilityScoresView(monster: viewModel)
SectionDivider()
SavingThrowsAndSkillsView(monster: monster)
ResistancesAndImmunitiesView(monster: monster)
SavingThrowsAndSkillsView(monster: viewModel)
ResistancesAndImmunitiesView(monster: viewModel)
Group {
// Languages
if (!monsterLanguagesDescription.isEmpty) {
@@ -248,27 +239,27 @@ struct MonsterDetail: View {
// Proficiency Bonus
LabeledField("Proficiency Bonus") {
Text(String(monster.proficiencyBonus))
Text(String(viewModel.proficiencyBonus))
}
// Abilities
if (monsterAbilities.count > 0) {
ForEach(monsterAbilities) { ability in
if (viewModel.abilities.count > 0) {
ForEach(viewModel.abilities) { ability in
VStack {
Markdown(Document(ability.renderedText(monster)))
Markdown(Document(ability.renderedText(viewModel)))
Divider()
}
}
}
// Actions
if (monsterActions.count > 0) {
if (viewModel.actions.count > 0) {
VStack(alignment: .leading) {
Text("Actions")
.font(.system(size: 24, weight: .bold))
ForEach(monsterActions) { action in
ForEach(viewModel.actions) { action in
VStack {
Markdown(Document(action.renderedText(monster)))
Markdown(Document(action.renderedText(viewModel)))
Divider()
}
}
@@ -276,13 +267,13 @@ struct MonsterDetail: View {
}
// Legendary Actions
if (monsterLegendaryActions.count > 0) {
if (viewModel.legendaryActions.count > 0) {
VStack(alignment: .leading) {
Text("Legendary Actions")
.font(.system(size: 20, weight: .bold))
ForEach(monsterLegendaryActions) { action in
ForEach(viewModel.legendaryActions) { action in
VStack {
Markdown(Document(action.renderedText(monster)))
Markdown(Document(action.renderedText(viewModel)))
Divider()
}
}
@@ -293,13 +284,28 @@ struct MonsterDetail: View {
.padding(.horizontal)
.foregroundColor(kTextColor)
}
.toolbar(content: {
ToolbarItem(placement: .primaryAction) {
NavigationLink("Edit", destination: EditMonster(monster: monster))
}
})
.navigationTitle(monster.name ?? "")
.navigationBarTitleDisplayMode(.inline)
}
}
struct MonsterDetailWrapper: View {
let kTextColor: Color = Color(hex: 0x982818)
@ObservedObject var monster: Monster
@StateObject private var viewModel = MonsterViewModel()
var body: some View {
MonsterDetailView(viewModel: viewModel)
.onAppear(perform: {
viewModel.copyFromMonster(monster: monster)
})
.toolbar(content: {
ToolbarItem(placement: .primaryAction) {
NavigationLink("Edit", destination: EditMonster(monster: monster))
}
})
.navigationTitle(monster.name ?? "")
.navigationBarTitleDisplayMode(.inline)
}
private func editMonster() {
@@ -307,7 +313,7 @@ struct MonsterDetail: View {
}
}
struct MonsterDetail_Previews: PreviewProvider {
struct MonsterDetailWrapper_Previews: PreviewProvider {
static var previews: some View {
let context = PersistenceController.preview.container.viewContext
let monster = Monster.init(context: context)
@@ -352,10 +358,10 @@ struct MonsterDetail_Previews: PreviewProvider {
]
return Group {
MonsterDetail(monster: monster)
MonsterDetailWrapper(monster: monster)
.environment(\.managedObjectContext, context)
.previewDevice("iPod touch (7th generation)")
MonsterDetail(monster: monster)
MonsterDetailWrapper(monster: monster)
.environment(\.managedObjectContext, context)
.previewDevice("iPad Pro (11-inch) (2nd generation)")
}

View File

@@ -59,7 +59,7 @@ struct Search: View {
return false
})) { monster in
NavigationLink(destination: MonsterDetail(monster: monster)) {
NavigationLink(destination: MonsterDetailWrapper(monster: monster)) {
Text(monster.name ?? "")
}
}