mirror of
https://github.com/pointfreeco/swift-composable-architecture.git
synced 2025-12-24 12:14:25 +01:00
* more main actor audit * wip * wip * fix * better task result == * task result tests * wip * wip * wip * wip * wip * wip * wip * wip * wip * fix merge conflicts * wip * wip * lots of doc fixes and modernizations * lots more docs and better hashable conformance for TaskResult * more docs * clean up * more tests and docs * clean up * wip * wip * wip * wip * wip * wip * wip * wip * wip * wip * small clean up * wip * wip * wip * wip * wip * wip * wip * explicit * wip * fix bug in TestStore.receive * wip * wip * wip * wip * wip * wip * wip * wip * wip * wip * wip * wip * wip * wip * fixes * wip * tools for non-deterministic TestStore.receive * fix * wip * wip * remove inAnyOrder stuff * wip * wip * wip * wip * wip * wip * wip * convert download case study to use async/await * animations * fix tests * remove executor experiment * wip * wip * wip * wip * wip * speech simplification * wip * wip * wip * wip * wip * wip * add a few todos * wrote some tests * simplify speech recognizer * fix tests * update some docs about error throwing behavior * wip * wip * fix * wip * wip * wip * wip * wip * wip * wip * wip * wip * wip * Swift 5.5.2 fixes * wip * Bump timeout * wip * wip * Finesse * proper way to detect main queue * extra guard * revert main queue check * move stuff around * docs * fixed a bunch of warnings * Fix references * clean up * clean up * fix a bunch of warnings * clean up * un-soft deprecate concatenate * async teststore.send * fix uikit tests * drop sendable * wip * wip * wip * wip * wip * clean up * clean up * reorganize, remove extra task cancellation handler * wip * wip * wip * wip * wip * wip * Make TestStore.send async (#1190) * async teststore.send * fix uikit tests * Converted all tests to async * clean up * added docs * Update Sources/ComposableArchitecture/TestStore.swift Co-authored-by: Stephen Celis <stephen@stephencelis.com> * Update Sources/ComposableArchitecture/TestStore.swift Co-authored-by: Stephen Celis <stephen@stephencelis.com> * docs and readme update * Update README.md * Update Tests/ComposableArchitectureTests/StoreTests.swift Co-authored-by: Stephen Celis <stephen@stephencelis.com> * fix * Update Sources/ComposableArchitecture/TestStore.swift Co-authored-by: Stephen Celis <stephen@stephencelis.com> * Update Sources/ComposableArchitecture/TestStore.swift Co-authored-by: Stephen Celis <stephen@stephencelis.com> * Update Sources/ComposableArchitecture/TestStore.swift Co-authored-by: Stephen Celis <stephen@stephencelis.com> * clean up Co-authored-by: Stephen Celis <stephen@stephencelis.com> * wip * wip * wip * make fetchNumber throwing and fix tests * effect basics clean up * use local state for isLoading in refreshable case study * clean up * fix test * wip * wip * wip * wip * wip * wip * fixes * clean up * clean up * Simplify * wip * clean up * wip * AsyncStream.finished() * give Send a public initializer * make send public * temporarily make box public * remove concurrency flag * wip * wip * wip * wip * wip * docs * speech * simplify * clean up; * unchecked sendable * clean up * clean up * wip * docs * docs * more docs * lots of docs * wip * wip * wip * more docs for streamWithContinuation * wip * wip * wip * Make internal, too * wip * Remove sendability detection It breaks things, like: let request = UncheckedSendable( SKProductsRequest(productIdentifiers: [] ) // UncheckedSendable<NSObject> // *not* _<SKProductsRequest> * wip * doc clean up; * fixed some todos * docs * wip * remove thread safety FAQ from readme * fix test * wip * docs clean up * docs clean up * added a testing article and fixed some docs * rearrange * docs clean up * wip * Update Sources/ComposableArchitecture/Documentation.docc/Articles/Testing.md Co-authored-by: Thomas Grapperon <35562418+tgrapperon@users.noreply.github.com> * Update Sources/ComposableArchitecture/Effects/ConcurrencySupport.swift Co-authored-by: Thomas Grapperon <35562418+tgrapperon@users.noreply.github.com> * Update Sources/ComposableArchitecture/Effects/ConcurrencySupport.swift Co-authored-by: Thomas Grapperon <35562418+tgrapperon@users.noreply.github.com> * Update Sources/ComposableArchitecture/Effects/ConcurrencySupport.swift Co-authored-by: Thomas Grapperon <35562418+tgrapperon@users.noreply.github.com> * Update Sources/ComposableArchitecture/Effects/ConcurrencySupport.swift Co-authored-by: Thomas Grapperon <35562418+tgrapperon@users.noreply.github.com> * Update Sources/ComposableArchitecture/Documentation.docc/Articles/Testing.md Co-authored-by: Thomas Grapperon <35562418+tgrapperon@users.noreply.github.com> * Update Sources/ComposableArchitecture/Documentation.docc/Articles/Testing.md Co-authored-by: Thomas Grapperon <35562418+tgrapperon@users.noreply.github.com> * Update Sources/ComposableArchitecture/Documentation.docc/Articles/Testing.md Co-authored-by: Thomas Grapperon <35562418+tgrapperon@users.noreply.github.com> * Update Sources/ComposableArchitecture/Documentation.docc/Articles/Testing.md Co-authored-by: Thomas Grapperon <35562418+tgrapperon@users.noreply.github.com> * Update Sources/ComposableArchitecture/Documentation.docc/Articles/Testing.md Co-authored-by: Thomas Grapperon <35562418+tgrapperon@users.noreply.github.com> * Update Sources/ComposableArchitecture/Documentation.docc/Articles/Testing.md Co-authored-by: Thomas Grapperon <35562418+tgrapperon@users.noreply.github.com> * Update Sources/ComposableArchitecture/Documentation.docc/Articles/Testing.md Co-authored-by: Thomas Grapperon <35562418+tgrapperon@users.noreply.github.com> * wip * wip * wip Co-authored-by: Stephen Celis <stephen@stephencelis.com> Co-authored-by: Thomas Grapperon <35562418+tgrapperon@users.noreply.github.com>
116 lines
2.9 KiB
Swift
116 lines
2.9 KiB
Swift
import Combine
|
|
import ComposableArchitecture
|
|
import SwiftUI
|
|
import UIKit
|
|
|
|
private let readMe = """
|
|
This screen demonstrates navigation that depends on loading optional state.
|
|
|
|
Tapping "Load optional counter" simultaneously navigates to a screen that depends on optional \
|
|
counter state and fires off an effect that will load this state a second later.
|
|
"""
|
|
|
|
struct NavigateAndLoadState: Equatable {
|
|
var isNavigationActive = false
|
|
var optionalCounter: CounterState?
|
|
}
|
|
|
|
enum NavigateAndLoadAction: Equatable {
|
|
case optionalCounter(CounterAction)
|
|
case setNavigation(isActive: Bool)
|
|
case setNavigationIsActiveDelayCompleted
|
|
}
|
|
|
|
struct NavigateAndLoadEnvironment {
|
|
var mainQueue: AnySchedulerOf<DispatchQueue>
|
|
}
|
|
|
|
let navigateAndLoadReducer =
|
|
counterReducer
|
|
.optional()
|
|
.pullback(
|
|
state: \.optionalCounter,
|
|
action: /NavigateAndLoadAction.optionalCounter,
|
|
environment: { _ in CounterEnvironment() }
|
|
)
|
|
.combined(
|
|
with: Reducer<
|
|
NavigateAndLoadState, NavigateAndLoadAction, NavigateAndLoadEnvironment
|
|
> { state, action, environment in
|
|
|
|
enum CancelID {}
|
|
|
|
switch action {
|
|
case .setNavigation(isActive: true):
|
|
state.isNavigationActive = true
|
|
return .task {
|
|
try await environment.mainQueue.sleep(for: 1)
|
|
return .setNavigationIsActiveDelayCompleted
|
|
}
|
|
.cancellable(id: CancelID.self)
|
|
|
|
case .setNavigation(isActive: false):
|
|
state.isNavigationActive = false
|
|
state.optionalCounter = nil
|
|
return .cancel(id: CancelID.self)
|
|
|
|
case .setNavigationIsActiveDelayCompleted:
|
|
state.optionalCounter = CounterState()
|
|
return .none
|
|
|
|
case .optionalCounter:
|
|
return .none
|
|
}
|
|
}
|
|
)
|
|
|
|
struct NavigateAndLoadView: View {
|
|
let store: Store<NavigateAndLoadState, NavigateAndLoadAction>
|
|
|
|
var body: some View {
|
|
WithViewStore(self.store) { viewStore in
|
|
Form {
|
|
Section {
|
|
AboutView(readMe: readMe)
|
|
}
|
|
NavigationLink(
|
|
destination: IfLetStore(
|
|
self.store.scope(
|
|
state: \.optionalCounter,
|
|
action: NavigateAndLoadAction.optionalCounter
|
|
)
|
|
) {
|
|
CounterView(store: $0)
|
|
} else: {
|
|
ProgressView()
|
|
},
|
|
isActive: viewStore.binding(
|
|
get: \.isNavigationActive,
|
|
send: NavigateAndLoadAction.setNavigation(isActive:)
|
|
)
|
|
) {
|
|
Text("Load optional counter")
|
|
}
|
|
}
|
|
}
|
|
.navigationTitle("Navigate and load")
|
|
}
|
|
}
|
|
|
|
struct NavigateAndLoadView_Previews: PreviewProvider {
|
|
static var previews: some View {
|
|
NavigationView {
|
|
NavigateAndLoadView(
|
|
store: Store(
|
|
initialState: NavigateAndLoadState(),
|
|
reducer: navigateAndLoadReducer,
|
|
environment: NavigateAndLoadEnvironment(
|
|
mainQueue: .main
|
|
)
|
|
)
|
|
)
|
|
}
|
|
.navigationViewStyle(.stack)
|
|
}
|
|
}
|