Update the template screen to use the new(ish) Observation framework. (#4077)

* Update the template screen to use the new(ish) Observation framework.

* Add a variant of deferFulfillment that supports observables.

* Update snapshot fulfilment to work with either a publisher or a stream.
This commit is contained in:
Doug
2025-04-30 16:49:23 +01:00
committed by GitHub
parent 0620bd45fc
commit 61a427b8e5
12 changed files with 297 additions and 25 deletions
@@ -9,7 +9,7 @@ import Compound
import SwiftUI
struct TemplateScreen: View {
@ObservedObject var context: TemplateScreenViewModel.Context
@Bindable var context: TemplateScreenViewModel.Context
var body: some View {
Form {
@@ -18,9 +18,19 @@ struct TemplateScreen: View {
kind: .textField(text: $context.composerText))
ListRow(label: .centeredAction(title: L10n.actionDone,
systemIcon: .doorLeftHandClosed),
icon: \.leave),
kind: .button { context.send(viewAction: .done) })
}
Section {
ListRow(label: .default(title: "Counter", icon: \.chart),
details: .counter(context.viewState.counter),
kind: .label)
ListRow(label: .default(title: "Increment", icon: \.plus),
kind: .button { context.send(viewAction: .incrementCounter) })
ListRow(label: .default(title: "Decrement", icon: \.minus),
kind: .button { context.send(viewAction: .decrementCounter) })
}
}
.compoundList()
.navigationTitle(context.viewState.title)
@@ -33,10 +43,29 @@ struct TemplateScreen: View {
// MARK: - Previews
struct TemplateScreen_Previews: PreviewProvider, TestablePreview {
static let viewModel = TemplateScreenViewModel()
static let viewModel = makeViewModel()
static let incrementedViewModel = makeViewModel(counterValue: 1)
static var previews: some View {
NavigationStack {
TemplateScreen(context: viewModel.context)
}
.previewDisplayName("Initial")
NavigationStack {
TemplateScreen(context: incrementedViewModel.context)
}
.previewDisplayName("Incremented")
.snapshotPreferences(expect: incrementedViewModel.context.observe(\.viewState.counter).map { $0 == 1 }.eraseToStream())
}
static func makeViewModel(counterValue: Int = 0) -> TemplateScreenViewModel {
let viewModel = TemplateScreenViewModel()
for _ in 0..<counterValue {
viewModel.context.send(viewAction: .incrementCounter)
}
return viewModel
}
}