
Standard Loadout Upgrade View
Standard Loadout Upgrade View
The upgrade view for a standard loadout should look like:
- Which is represented by a Swift UI view
- The body consists of Text and Symbol segments
- The upgrade text is taken from the Blank Signature sides.ability node in upgrades/sensor.json
findDelimitedSubstrings(input:) -> [String]
returns an array of the substrings. This function is a member of UpgradeTextView class (Views/UpgradeView.swift)
Index | Value |
---|---|
0 | “While defending, if you are “ |
1 | “[Charge]” |
2 | ” to change 1 “ |
3 | “[Focus]” |
4 | ” result to an “ |
5 | “[Evade]” |
6 | ” result.” |
createSubstringArray(input:) -> [SubstringType]
converts the string array into a[SubstringType]
array
|Index|Value| |-|-| |0|SubstringType.Text(“While defending, if you are “)| |1|SubstringType.Symbol(“[Charge]”)| more…
- Merge any contiguous substrings, if needed.
For the cases where the string is “ perform a [1 [Straight]] “ in the sides.ability node of the upgrade.
mergeSameSubstringTypes(_ input: [SubstringType]) -> [SubstringType]
- Build a SwiftUI view from the
[SubstringType]
array.
func buildViews(_ input: [SubstringType]) -> some View {
func buildView(_ type: SubstringType) -> Text {
switch(type) {
case .text(let val):
return Text(val)
case .symbol(let val):
return Text(getSymbol(val))
.font(.custom("xwing-miniatures", size: 18))
}
}
return VStack(alignment: .center) {
input.reduce(Text(""), { $0 + buildView($1) } )
}
}
getSymbol(val:)
returns a character from the xwing-miniatures font that corresponds to the associated type of the symbol in the[SubstringType]
array. (SubstringType.Symbol("[Charge]")
corresponds to theg
character in the xwing-miniatures font)
flowchart TD
A[Redux_ShipView.body.content] --> B[Redux_ShipView.imageOverlayView]
B --> C[Redux_ShipView.imageOverlayView.upgradeImageOverlay]
C --> D[Redux_ShipView.imageOverlayView.upgradeImageOverlay.upgradeCardImage]
D --> E[UpgradeCardFlipView]
D -->|selectedUpgrade.upgrade.isStandardLoadoutUpgrade| F[UpgradeTextView]
classDiagram
class Redux_ShipView {
var viewModel: Redux_ShipViewModel
"@State var showImageOverlay: Bool = false"
"@State var selectedUpgrade: UpgradeView.UpgradeViewModel? = nil"
}
class UpgradesView {
let upgrades: [Upgrade]
@Binding var showImageOverlay: Bool
"@Binding var selectedUpgrade: UpgradeView.UpgradeViewModel?"
}
The UpgradesView
is built, passing in the [Upgrades]
and any @State
variables which are used as @Binding
variables in UpgradesView
.
Redux_ShipView.body.content.footer
:
var footer: some View {
UpgradesView(upgrades: viewModel.shipPilot.upgrades,
showImageOverlay: $showImageOverlay,
imageOverlayUrl: $imageOverlayUrl,
imageOverlayUrlBack: $imageOverlayUrlBack,
selectedUpgrade: $selectedUpgrade)
.environmentObject(viewModel)
}
UpgradesView.swift:
ForEach(upgrades) {
UpgradeView(viewModel: UpgradeView.UpgradeViewModel(upgrade: $0))
{ upgradeViewModel in
self.showImageOverlay = true
self.imageOverlayUrl = upgradeViewModel.imageUrl
self.imageOverlayUrlBack = upgradeViewModel.imageUrlBack
self.selectedUpgrade = upgradeViewModel
}
.environmentObject(viewModel)
}
The closure passed into UpgradeView
is executed when an upgrade button is tapped.
- The
showImageOverlay
is set to true when the upgrade button is tapped - The
selectedUpgrade
is set when the upgrade button in the footer of the ship view is tapped. It is set to theUpgradeView.UpgradeViewModel
which is initialized from theUpgrade
The body
of Redux_ShipView
adds the imageOverlayView
as an overlay:
Redux_ShipView.body
:
return VStack(alignment: .leading) {
headerView
bodyContent
footer
}
.padding()
.overlay(imageOverlayView)
The showImageOverlay
toggles whether the upgradeImageOverlay
or the defaultView
is displayed:
Redux_ShipView.imageOverlayView
:
if (self.showImageOverlay == true) {
return AnyView(upgradeImageOverlay)
} else {
return defaultView
}
The upgradeImageOverlay
references the upgradeCardImage
which displays the UpgradeCardFlipView
:
if (self.imageOverlayUrlBack != "") {
guard let selectedUpgrade = self.selectedUpgrade else { return emptyView }
guard let upgradeState = getUpgradeStateData(upgrade: selectedUpgrade.upgrade) else { return emptyView }
// if not standard loadout upgrade
ret =
UpgradeCardFlipView(
side: (upgradeState.selected_side == 0) ? false : true,
frontUrl: self.imageOverlayUrl,
backUrl: self.imageOverlayUrlBack,
viewModel: self.viewModel) { side in
self.viewModel.update(
type: PilotStatePropertyType.selectedSide(upgradeState,
side), active: -1, inactive: -1
)
}.eraseToAnyView()
// if standard loadout upgrade
// ret = UpgradeTextView
}
flowchart TD
A[Redux_ShipView.body.content.footer] -->|Upgrades, selectedUpgrade| B[UpgradesView]
B -->|UpgradeViewModel| C[UpgradeView]
C -->|selectedUpgrade, showImageOverlay| D[Redux_ShipView.imageOverlayView]
D --> E[upgradeImageOverlay]
E --> F[UpgradeCardFlipView]
E -->|selectedUpgrade.isStandardLoadout| G[UpgradeTextView]
Tasks
- Add
var isStandardLoadout: Bool = false
toUpgrade
- Set
isStandardLoadout
when building theRedux_ShipViewModel.shipPilot.upgrades
that is injected intoRedux_ShipView
fromContentView.Redux_buildView()
. which is triggered from tapping a ship card on the squad view.
ContentView.swift
func Redux_buildView(type: ViewType) -> AnyView {
case .shipViewNew(let shipPilot, let squad):
return buildShipView(shipPilot: shipPilot, squad: squad)
}
func buildShipView(shipPilot: ShipPilot, squad: Squad) -> AnyView {
let viewModel = Redux_ShipViewModel(moc: self.moc,
shipPilot: shipPilot,
squad: squad,
pilotStateService: self.diContainer.pilotStateService,
store: store)
return AnyView(Redux_ShipView(viewModel: viewModel)
.environmentObject(self)
)
}
flowchart TD
A[Ship card tap on SquadView] -->|"ViewType.shipViewNew(shipPilot,squad)"| B["buildShipView(shipPilot, squad)"]
B -->|"shipPilot, squad"| C[Redux_ShipViewModel]
C -->|"viewModel"| D[Redux_ShipView]
flowchart TD
Y["Redux_SquadViewNewViewModel.loadShips(squad, squadData)"] --> W["squadReducer.getShips(squad,data)"]
W -->|squad, SquadData| C["SquadService.getShips"]
Z["Redux_SquadView.loadShips"] --> A
V["Redux_SquadView.content.onAppear"] --> Z
A["factionReducer(.getShips(SquadData))"] -->|SquadData| C["SquadService.getShips"]
B["squadReducer(.flipDialFix)"] -->|squad, SquadData| C["SquadService.getShips"]
C -->|squad, squadPilot, pilotState| D["CacheService.getShip"]
D -->|squad, squadPilot, pilotState| E["CacheService.getShipV1"]
E -->|inout Ship| F["CacheService.getShipV1.getPilot"]
F --> G["CacheService.getShipV1.getPilot.getUpgradesFromCache"]
G --> H["CacheService.getShipV1.getPilot.getUpgradesFromCache.getUpgrade(key:)"]
H --> I["UpgradeUtility.getUpgrades(upgradeCategory)"]