Skip to content

Commit

Permalink
The Composable Architecture 1.0 (#2318)
Browse files Browse the repository at this point in the history
* docs

* wip

* wip

* wip

* wip

* wip

* wip

* wip

* Fix invalid states count for 3 optionals and typos (#2094)

* wip

* wip

* more dismisseffect docs

* fixed some references

* navigation doc corrections

* more nav docs

* fix cancellation tests in release mode

* wrap some tests in #if DEBUG since they are testing expected failures

* update UUIDs in tests to use shorter initializer

* fixed a todo

* wip

* fix merge errors

* wip

* fix

* wip

* wip

* fixing a bunch of todos

* get rid of rawvalue in StackElementID

* more todos

* NavLinkStore docs

* fix swift 5.6 stuff

* fix some standups tests

* fix

* clean up

* docs fix

* fixes

* wip

* 5.6 fix

* wip

* wip

* dont parallelize tests

* updated demo readmes

* wip

* Use ObservedObject instead of StateObject for alert/dialog modifiers.

* integration tests for bad dismissal behavior

* check for runtime warnings in every integration test

* wip

* wip

* wip

* fix

* wip

* wip

* wip

* wip

* wip

* wip

* Drop a bunch of Hashables.

* some nav bug fixes

* wip

* wip

* wip

* fix

* fix

* wip

* wip

* Simplify recording test.

* add concurrent async test

* fix

* wip

* Refact how detail dismisses itself.

* fix

* 5.6 fix

* wip

* wip

* wip

* wip

* Add TestStore.assert.

* Revert "Add TestStore.assert."

This reverts commit a892ccc.

* add Ukrainian Readme.md (#2121)

* Add TestStore.assert. (#2123)

* Add TestStore.assert.

* wip

* Update Sources/ComposableArchitecture/TestStore.swift

Co-authored-by: Stephen Celis <stephen@stephencelis.com>

* Update Sources/ComposableArchitecture/Documentation.docc/Extensions/TestStore.md

Co-authored-by: Stephen Celis <stephen@stephencelis.com>

* fix tests

---------

Co-authored-by: Stephen Celis <stephen@stephencelis.com>

* Run swift-format

* push for store.finish and presentation

* wip

* move docs around

* wip

* wip

* wip

* wip

* wip

* wip

* wip

* wip

* wip

* wip

* wip

* wip

* wip

* wip

* Add case subscripts

* wip

* wip

* wip

* 5.7-only

* wip

* wip

* wip

* wip

* fix

* revert store.finish task cancellation

* wip

* wip

* wip

* wip

* wip

* wip

* wip

* wip

* wip

* wip

* wip

* wip

* wip

* wip

* wip

* wip

* wip

* wip

* wip

* wip

* add test for presentation scope

* wip

* wip

* wip

* wip

* wip

* cleanup

* wip

* wip

* wip

* wip

* wip

* wip

* wip

* wip

* wip

* wip

* wip

* wip

* Rename ReducerProtocol.swift to Reducer.swift (#2206)

* Hard-deprecate old SwitchStore initializers/overloads

* wip

* wip

* Resolve CaseStudies crash (#2258)

* wip

* wip

* wip

* wip

* wip

* wip

* wip

* wip

* Bump timeout for CI

* wip

* Remove old deprecations

* Simplify test store

* wip

* wip

* wip

* wip

* wip

* wip

* wip

* wip

* wip

* wip

* wip

* wip

* wip

* wip

* wip

* wip

* wip

* images for tutorials

* wip

* wip

* Remove deprecated alert APIs

* Bump dependencies

* wip

---------

Co-authored-by: Brandon Williams <mbrandonw@hey.com>
Co-authored-by: 유재호 <y73447jh@gmail.com>
Co-authored-by: Dmytro <barabashdmyto@gmail.com>
Co-authored-by: Brandon Williams <135203+mbrandonw@users.noreply.github.com>
Co-authored-by: mbrandonw <mbrandonw@users.noreply.github.com>
  • Loading branch information
6 people authored Jul 30, 2023
1 parent 4cf2104 commit 195284b
Show file tree
Hide file tree
Showing 130 changed files with 859 additions and 8,474 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@
"kind" : "remoteSourceControl",
"location" : "https://github.com/pointfreeco/combine-schedulers",
"state" : {
"revision" : "ec62f32d21584214a4b27c8cee2b2ad70ab2c38a",
"version" : "0.11.0"
"revision" : "9dc9cbe4bc45c65164fa653a563d8d8db61b09bb",
"version" : "1.0.0"
}
},
{
Expand All @@ -32,17 +32,17 @@
"kind" : "remoteSourceControl",
"location" : "https://github.com/pointfreeco/swift-case-paths",
"state" : {
"revision" : "fc45e7b2cfece9dd80b5a45e6469ffe67fe67984",
"version" : "0.14.1"
"revision" : "5da6989aae464f324eef5c5b52bdb7974725ab81",
"version" : "1.0.0"
}
},
{
"identity" : "swift-clocks",
"kind" : "remoteSourceControl",
"location" : "https://github.com/pointfreeco/swift-clocks",
"state" : {
"revision" : "0fbaebfc013715dab44d715a4d350ba37f297e4d",
"version" : "0.4.0"
"revision" : "d1fd837326aa719bee979bdde1f53cd5797443eb",
"version" : "1.0.0"
}
},
{
Expand All @@ -59,26 +59,26 @@
"kind" : "remoteSourceControl",
"location" : "https://github.com/pointfreeco/swift-concurrency-extras",
"state" : {
"revision" : "479750bd98fac2e813fffcf2af0728b5b0085795",
"version" : "0.1.1"
"revision" : "ea631ce892687f5432a833312292b80db238186a",
"version" : "1.0.0"
}
},
{
"identity" : "swift-custom-dump",
"kind" : "remoteSourceControl",
"location" : "https://github.com/pointfreeco/swift-custom-dump",
"state" : {
"revision" : "4a87bb75be70c983a9548597e8783236feb3401e",
"version" : "0.11.1"
"revision" : "edd66cace818e1b1c6f1b3349bb1d8e00d6f8b01",
"version" : "1.0.0"
}
},
{
"identity" : "swift-dependencies",
"kind" : "remoteSourceControl",
"location" : "https://github.com/pointfreeco/swift-dependencies",
"state" : {
"revision" : "16fd42ae04c6e7f74a6a86395d04722c641cccee",
"version" : "0.6.0"
"revision" : "4e1eb6e28afe723286d8cc60611237ffbddba7c5",
"version" : "1.0.0"
}
},
{
Expand All @@ -104,8 +104,8 @@
"kind" : "remoteSourceControl",
"location" : "https://github.com/pointfreeco/swift-identified-collections",
"state" : {
"revision" : "d01446a78fb768adc9a78cbb6df07767c8ccfc29",
"version" : "0.8.0"
"revision" : "d1e45f3e1eee2c9193f5369fa9d70a6ddad635e8",
"version" : "1.0.0"
}
},
{
Expand All @@ -122,17 +122,17 @@
"kind" : "remoteSourceControl",
"location" : "https://github.com/pointfreeco/swiftui-navigation",
"state" : {
"revision" : "2aa885e719087ee19df251c08a5980ad3e787f12",
"version" : "0.8.0"
"revision" : "f5bcdac5b6bb3f826916b14705f37a3937c2fd34",
"version" : "1.0.0"
}
},
{
"identity" : "xctest-dynamic-overlay",
"kind" : "remoteSourceControl",
"location" : "https://github.com/pointfreeco/xctest-dynamic-overlay",
"state" : {
"revision" : "50843cbb8551db836adec2290bb4bc6bac5c1865",
"version" : "0.9.0"
"revision" : "302891700c7fa3b92ebde9fe7b42933f8349f3c7",
"version" : "1.0.0"
}
}
],
Expand Down
12 changes: 0 additions & 12 deletions Examples/CaseStudies/CaseStudies.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,10 @@
/* Begin PBXBuildFile section */
433B8B762A49C9AF0035DEE4 /* 03-Navigation-Multiple-Destinations.swift in Sources */ = {isa = PBXBuildFile; fileRef = 433B8B752A49C9AF0035DEE4 /* 03-Navigation-Multiple-Destinations.swift */; };
4F5AC11F24ECC7E4009DC50B /* 01-GettingStarted-SharedStateTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4F5AC11E24ECC7E4009DC50B /* 01-GettingStarted-SharedStateTests.swift */; };
CA0C0C4724B89BEC00CBDD8A /* 04-HigherOrderReducers-LifecycleTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = CA0C0C4624B89BEC00CBDD8A /* 04-HigherOrderReducers-LifecycleTests.swift */; };
CA0C51FB245389CC00A04EAB /* 04-HigherOrderReducers-ReusableOfflineDownloadsTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = CA0C51FA245389CC00A04EAB /* 04-HigherOrderReducers-ReusableOfflineDownloadsTests.swift */; };
CA25E5D224463AD700DA666A /* 01-GettingStarted-Bindings-Basics.swift in Sources */ = {isa = PBXBuildFile; fileRef = CA25E5D124463AD700DA666A /* 01-GettingStarted-Bindings-Basics.swift */; };
CA34170824A4E89500FAF950 /* 01-GettingStarted-AnimationsTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = CA34170724A4E89500FAF950 /* 01-GettingStarted-AnimationsTests.swift */; };
CA3E421F26B8337500581ABC /* 01-GettingStarted-FocusState.swift in Sources */ = {isa = PBXBuildFile; fileRef = CA3E421E26B8337500581ABC /* 01-GettingStarted-FocusState.swift */; };
CA3E4C5B24B4FA0E00447C0B /* 04-HigherOrderReducers-Lifecycle.swift in Sources */ = {isa = PBXBuildFile; fileRef = CA3E4C5A24B4FA0E00447C0B /* 04-HigherOrderReducers-Lifecycle.swift */; };
CA410EE0247A15FE00E41798 /* 02-Effects-WebSocket.swift in Sources */ = {isa = PBXBuildFile; fileRef = CA410EDF247A15FE00E41798 /* 02-Effects-WebSocket.swift */; };
CA410EE2247C73B400E41798 /* 02-Effects-WebSocketTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = CA410EE1247C73B400E41798 /* 02-Effects-WebSocketTests.swift */; };
CA50BE6024A8F46500FE7DBA /* 01-GettingStarted-AlertsAndConfirmationDialogsTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = CA50BE5F24A8F46500FE7DBA /* 01-GettingStarted-AlertsAndConfirmationDialogsTests.swift */; };
Expand Down Expand Up @@ -72,7 +70,6 @@
DC89C45324465452006900B9 /* 03-Navigation-Lists-NavigateAndLoad.swift in Sources */ = {isa = PBXBuildFile; fileRef = DC89C45224465451006900B9 /* 03-Navigation-Lists-NavigateAndLoad.swift */; };
DC89C45524465C44006900B9 /* 02-Effects-Timers.swift in Sources */ = {isa = PBXBuildFile; fileRef = DC89C45424465C44006900B9 /* 02-Effects-Timers.swift */; };
DC9EB4172450CBD2005F413B /* UIViewRepresented.swift in Sources */ = {isa = PBXBuildFile; fileRef = DC9EB4162450CBD2005F413B /* UIViewRepresented.swift */; };
DCAC2A4F2452352E0094DEF5 /* 04-HigherOrderReducers-ElmLikeSubscriptions.swift in Sources */ = {isa = PBXBuildFile; fileRef = DCAC2A4E2452352E0094DEF5 /* 04-HigherOrderReducers-ElmLikeSubscriptions.swift */; };
DCC68EAB244666AF0037F998 /* 03-Navigation-Sheet-PresentAndLoad.swift in Sources */ = {isa = PBXBuildFile; fileRef = DCC68EAA244666AF0037F998 /* 03-Navigation-Sheet-PresentAndLoad.swift */; };
DCC68EDD2447A5B00037F998 /* 01-GettingStarted-OptionalState.swift in Sources */ = {isa = PBXBuildFile; fileRef = DCC68EDC2447A5B00037F998 /* 01-GettingStarted-OptionalState.swift */; };
DCC68EDF2447BC810037F998 /* TemplateText.swift in Sources */ = {isa = PBXBuildFile; fileRef = DCC68EDE2447BC810037F998 /* TemplateText.swift */; };
Expand Down Expand Up @@ -153,12 +150,10 @@
/* Begin PBXFileReference section */
433B8B752A49C9AF0035DEE4 /* 03-Navigation-Multiple-Destinations.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "03-Navigation-Multiple-Destinations.swift"; sourceTree = "<group>"; };
4F5AC11E24ECC7E4009DC50B /* 01-GettingStarted-SharedStateTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "01-GettingStarted-SharedStateTests.swift"; sourceTree = "<group>"; };
CA0C0C4624B89BEC00CBDD8A /* 04-HigherOrderReducers-LifecycleTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "04-HigherOrderReducers-LifecycleTests.swift"; sourceTree = "<group>"; };
CA0C51FA245389CC00A04EAB /* 04-HigherOrderReducers-ReusableOfflineDownloadsTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "04-HigherOrderReducers-ReusableOfflineDownloadsTests.swift"; sourceTree = "<group>"; };
CA25E5D124463AD700DA666A /* 01-GettingStarted-Bindings-Basics.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "01-GettingStarted-Bindings-Basics.swift"; sourceTree = "<group>"; };
CA34170724A4E89500FAF950 /* 01-GettingStarted-AnimationsTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "01-GettingStarted-AnimationsTests.swift"; sourceTree = "<group>"; };
CA3E421E26B8337500581ABC /* 01-GettingStarted-FocusState.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "01-GettingStarted-FocusState.swift"; sourceTree = "<group>"; };
CA3E4C5A24B4FA0E00447C0B /* 04-HigherOrderReducers-Lifecycle.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "04-HigherOrderReducers-Lifecycle.swift"; sourceTree = "<group>"; };
CA410EDF247A15FE00E41798 /* 02-Effects-WebSocket.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "02-Effects-WebSocket.swift"; sourceTree = "<group>"; };
CA410EE1247C73B400E41798 /* 02-Effects-WebSocketTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "02-Effects-WebSocketTests.swift"; sourceTree = "<group>"; };
CA50BE5F24A8F46500FE7DBA /* 01-GettingStarted-AlertsAndConfirmationDialogsTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "01-GettingStarted-AlertsAndConfirmationDialogsTests.swift"; sourceTree = "<group>"; };
Expand Down Expand Up @@ -225,7 +220,6 @@
DC89C45224465451006900B9 /* 03-Navigation-Lists-NavigateAndLoad.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "03-Navigation-Lists-NavigateAndLoad.swift"; sourceTree = "<group>"; };
DC89C45424465C44006900B9 /* 02-Effects-Timers.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "02-Effects-Timers.swift"; sourceTree = "<group>"; };
DC9EB4162450CBD2005F413B /* UIViewRepresented.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = UIViewRepresented.swift; sourceTree = "<group>"; };
DCAC2A4E2452352E0094DEF5 /* 04-HigherOrderReducers-ElmLikeSubscriptions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "04-HigherOrderReducers-ElmLikeSubscriptions.swift"; sourceTree = "<group>"; };
DCC68EAA244666AF0037F998 /* 03-Navigation-Sheet-PresentAndLoad.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "03-Navigation-Sheet-PresentAndLoad.swift"; sourceTree = "<group>"; };
DCC68EDC2447A5B00037F998 /* 01-GettingStarted-OptionalState.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "01-GettingStarted-OptionalState.swift"; sourceTree = "<group>"; };
DCC68EDE2447BC810037F998 /* TemplateText.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TemplateText.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -416,8 +410,6 @@
DCC68EAA244666AF0037F998 /* 03-Navigation-Sheet-PresentAndLoad.swift */,
433B8B752A49C9AF0035DEE4 /* 03-Navigation-Multiple-Destinations.swift */,
DC3C87AF29A48C4D004D9104 /* 03-NavigationStack.swift */,
DCAC2A4E2452352E0094DEF5 /* 04-HigherOrderReducers-ElmLikeSubscriptions.swift */,
CA3E4C5A24B4FA0E00447C0B /* 04-HigherOrderReducers-Lifecycle.swift */,
DCE63B70245CC0B90080A23D /* 04-HigherOrderReducers-Recursion.swift */,
DCC68EE22447C8540037F998 /* 04-HigherOrderReducers-ReusableFavoriting.swift */,
DCFE195F278DBF0600C14CCF /* CaseStudiesApp.swift */,
Expand All @@ -442,7 +434,6 @@
CABC4F3A26AEE20200D5FA2C /* 02-Effects-RefreshableTests.swift */,
DC07231624465D1E003A8B65 /* 02-Effects-TimersTests.swift */,
CA410EE1247C73B400E41798 /* 02-Effects-WebSocketTests.swift */,
CA0C0C4624B89BEC00CBDD8A /* 04-HigherOrderReducers-LifecycleTests.swift */,
CA78F0CC28DA47D70026C4AD /* 04-HigherOrderReducers-RecursionTests.swift */,
DC634B242448D15B00DAA016 /* 04-HigherOrderReducers-ReusableFavoritingTests.swift */,
CA0C51FA245389CC00A04EAB /* 04-HigherOrderReducers-ReusableOfflineDownloadsTests.swift */,
Expand Down Expand Up @@ -750,7 +741,6 @@
DCC68EE32447C8540037F998 /* 04-HigherOrderReducers-ReusableFavoriting.swift in Sources */,
CA3E421F26B8337500581ABC /* 01-GettingStarted-FocusState.swift in Sources */,
DCC68EDF2447BC810037F998 /* TemplateText.swift in Sources */,
DCAC2A4F2452352E0094DEF5 /* 04-HigherOrderReducers-ElmLikeSubscriptions.swift in Sources */,
CA6AC2672451135C00C71CB3 /* DownloadClient.swift in Sources */,
CAA9ADC624465C810003A984 /* 02-Effects-Cancellation.swift in Sources */,
CA5ECF92267A79F0002067FF /* FactClient.swift in Sources */,
Expand All @@ -760,7 +750,6 @@
DCFE1960278DBF0600C14CCF /* CaseStudiesApp.swift in Sources */,
DCD442C6286CA91F008B4EA7 /* AboutView.swift in Sources */,
CA6AC2662451135C00C71CB3 /* DownloadComponent.swift in Sources */,
CA3E4C5B24B4FA0E00447C0B /* 04-HigherOrderReducers-Lifecycle.swift in Sources */,
DC5B505125C86EBC000D8DFD /* 01-GettingStarted-Bindings-Forms.swift in Sources */,
CAA9ADC22446587C0003A984 /* 02-Effects-Basics.swift in Sources */,
DC89C41B24460F95006900B9 /* 00-RootView.swift in Sources */,
Expand Down Expand Up @@ -793,7 +782,6 @@
CA410EE2247C73B400E41798 /* 02-Effects-WebSocketTests.swift in Sources */,
CABC4F3B26AEE20200D5FA2C /* 02-Effects-RefreshableTests.swift in Sources */,
CA34170824A4E89500FAF950 /* 01-GettingStarted-AnimationsTests.swift in Sources */,
CA0C0C4724B89BEC00CBDD8A /* 04-HigherOrderReducers-LifecycleTests.swift in Sources */,
DC07231724465D1E003A8B65 /* 02-Effects-TimersTests.swift in Sources */,
CA50BE6024A8F46500FE7DBA /* 01-GettingStarted-AlertsAndConfirmationDialogsTests.swift in Sources */,
CAA9ADC424465AB00003A984 /* 02-Effects-BasicsTests.swift in Sources */,
Expand Down
10 changes: 0 additions & 10 deletions Examples/CaseStudies/SwiftUICaseStudies/00-Core.swift
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,11 @@ struct Root: Reducer {
var animation = Animations.State()
var bindingBasics = BindingBasics.State()
var bindingForm = BindingForm.State()
var clock = ClockState()
var counter = Counter.State()
var effectsBasics = EffectsBasics.State()
var effectsCancellation = EffectsCancellation.State()
var episodes = Episodes.State(episodes: .mocks)
var focusDemo = FocusDemo.State()
var lifecycle = LifecycleDemo.State()
var loadThenPresent = LoadThenPresent.State()
var longLivingEffects = LongLivingEffects.State()
var map = MapApp.State(cityMaps: .mocks)
Expand All @@ -35,13 +33,11 @@ struct Root: Reducer {
case animation(Animations.Action)
case bindingBasics(BindingBasics.Action)
case bindingForm(BindingForm.Action)
case clock(ClockAction)
case counter(Counter.Action)
case effectsBasics(EffectsBasics.Action)
case effectsCancellation(EffectsCancellation.Action)
case episodes(Episodes.Action)
case focusDemo(FocusDemo.Action)
case lifecycle(LifecycleDemo.Action)
case loadThenPresent(LoadThenPresent.Action)
case longLivingEffects(LongLivingEffects.Action)
case map(MapApp.Action)
Expand Down Expand Up @@ -86,9 +82,6 @@ struct Root: Reducer {
Scope(state: \.bindingForm, action: /Action.bindingForm) {
BindingForm()
}
Scope(state: \.clock, action: /Action.clock) {
Reduce(clockReducer, environment: ClockEnvironment(clock: self.clock))
}
Scope(state: \.counter, action: /Action.counter) {
Counter()
}
Expand All @@ -104,9 +97,6 @@ struct Root: Reducer {
Scope(state: \.focusDemo, action: /Action.focusDemo) {
FocusDemo()
}
Scope(state: \.lifecycle, action: /Action.lifecycle) {
LifecycleDemo()
}
Scope(state: \.loadThenPresent, action: /Action.loadThenPresent) {
LoadThenPresent()
}
Expand Down
20 changes: 0 additions & 20 deletions Examples/CaseStudies/SwiftUICaseStudies/00-RootView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -243,26 +243,6 @@ struct RootView: View {
)
)

NavigationLink(
"Lifecycle",
destination: LifecycleDemoView(
store: self.store.scope(
state: \.lifecycle,
action: Root.Action.lifecycle
)
)
)

NavigationLink(
"Elm-like subscriptions",
destination: ClockView(
store: self.store.scope(
state: \.clock,
action: Root.Action.clock
)
)
)

NavigationLink(
"Recursive state and actions",
destination: NestedView(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,73 +22,78 @@ private let readMe = """

struct Animations: Reducer {
struct State: Equatable {
var alert: AlertState<Action>?
@PresentationState var alert: AlertState<Action.Alert>?
var circleCenter: CGPoint?
var circleColor = Color.black
var isCircleScaled = false
}

enum Action: Equatable, Sendable {
case alertDismissed
case alert(PresentationAction<Alert>)
case circleScaleToggleChanged(Bool)
case rainbowButtonTapped
case resetButtonTapped
case resetConfirmationButtonTapped
case setColor(Color)
case tapped(CGPoint)

enum Alert: Equatable, Sendable {
case resetConfirmationButtonTapped
}
}

@Dependency(\.continuousClock) var clock

func reduce(into state: inout State, action: Action) -> Effect<Action> {
enum CancelID { case rainbow }
private enum CancelID { case rainbow }

switch action {
case .alertDismissed:
state.alert = nil
return .none
var body: some Reducer<State, Action> {
Reduce { state, action in
switch action {
case .alert(.presented(.resetConfirmationButtonTapped)):
state = State()
return .cancel(id: CancelID.rainbow)

case let .circleScaleToggleChanged(isScaled):
state.isCircleScaled = isScaled
return .none
case .alert:
return .none

case .rainbowButtonTapped:
return .run { send in
for color in [Color.red, .blue, .green, .orange, .pink, .purple, .yellow, .black] {
await send(.setColor(color), animation: .linear)
try await self.clock.sleep(for: .seconds(1))
}
}
.cancellable(id: CancelID.rainbow)

case .resetButtonTapped:
state.alert = AlertState {
TextState("Reset state?")
} actions: {
ButtonState(
role: .destructive,
action: .send(.resetConfirmationButtonTapped, animation: .default)
) {
TextState("Reset")
case let .circleScaleToggleChanged(isScaled):
state.isCircleScaled = isScaled
return .none

case .rainbowButtonTapped:
return .run { send in
for color in [Color.red, .blue, .green, .orange, .pink, .purple, .yellow, .black] {
await send(.setColor(color), animation: .linear)
try await self.clock.sleep(for: .seconds(1))
}
}
ButtonState(role: .cancel) {
TextState("Cancel")
.cancellable(id: CancelID.rainbow)

case .resetButtonTapped:
state.alert = AlertState {
TextState("Reset state?")
} actions: {
ButtonState(
role: .destructive,
action: .send(.resetConfirmationButtonTapped, animation: .default)
) {
TextState("Reset")
}
ButtonState(role: .cancel) {
TextState("Cancel")
}
}
}
return .none
return .none

case .resetConfirmationButtonTapped:
state = State()
return .cancel(id: CancelID.rainbow)
case let .setColor(color):
state.circleColor = color
return .none

case let .setColor(color):
state.circleColor = color
return .none

case let .tapped(point):
state.circleCenter = point
return .none
case let .tapped(point):
state.circleCenter = point
return .none
}
}
.ifLet(\.$alert, action: /Action.alert)
}
}

Expand Down Expand Up @@ -139,7 +144,7 @@ struct AnimationsView: View {
Button("Reset") { viewStore.send(.resetButtonTapped) }
.padding([.horizontal, .bottom])
}
.alert(self.store.scope(state: \.alert, action: { $0 }), dismiss: .alertDismissed)
.alert(store: self.store.scope(state: \.$alert, action: { .alert($0) }))
.navigationBarTitleDisplayMode(.inline)
}
}
Expand Down
Loading

0 comments on commit 195284b

Please sign in to comment.