Skip to content

Commit

Permalink
Fix 0.48.1 cherry pick
Browse files Browse the repository at this point in the history
## Changes

Previous 0.48.1 cherry pick somehow wasn't properly done (possibly
due to `git rerere`) and some changes were missing.

This commit contains all upstream changes from 0.47.2 ... 0.48.1 which
were then reapplied on top of `master`. This should hopefully now
include all changes. To avoid issues with `git rerere` I cleared its
cache before doing this operation.

## Automatic git commit

(cherry picked from commit 1c19319aed7ab85e10e07de570f6160e46140d2b)

Apostrocide. (#1701)

(cherry picked from commit 937a716d1af205f5e9b6f512c88012d7ad3e3f02)

Typo (#1702)

wow!

(cherry picked from commit 1c50ffcf440de19e15e3a8b94e7347df0895a6ce)

Base `OpenURL` dependency on SwiftUI (#1714)

* Base `OpenURL` dependency on SwiftUI

* indent

(cherry picked from commit fbd70bf4d01284a9788d88cba4b6c70827f104e4)

Fix ButtonRole and Button deprecations (#1715)

Replaced AlertState<Action>.ButtonRole with ButtonState<Action>.Role
Replaced AlertState<Action>.Button with ButtonState<Action>

(cherry picked from commit 907eb1866a9de2c506a05edee9d277b856a7171c)

# Conflicts:
#	Package.resolved

Run swift-format

(cherry picked from commit f56a0d1973d92fa82066ed3bd7f9ba7375fca5fe)

add await (#1725)

(cherry picked from commit 47465c3f265cf058447c32c58a6676216ed76590)

# Conflicts:
#	Sources/Dependencies/Dependencies/MainQueue.swift

Fix a possible typo (#1762)

(cherry picked from commit d0b1444393d9e209307dcad066cb8d19a667eda9)

Bump SwiftUINavigation and update examples (#1760)

* bump navigation

* bump swiftui-navigation

* Add SearchView preview

* make login sendable

* use button state builder

* format

* bump swift and platform version

* remove unused test clock

* Add quotes to scheme

(cherry picked from commit fe5603ec380e2a312cbf8ff45e12e81eea5c072b)

Fix minor document error (#1764)

(cherry picked from commit b555bfeac62c8c95cb54b002442bb8068aa99311)

Fix code typo (#1773)

Signed-off-by: Daeyoung Kim <[email protected]>

Signed-off-by: Daeyoung Kim <[email protected]>
(cherry picked from commit 315d935fcd2021828310294c2d85fc747f3de332)

Update latest version documentation link. (#1776)

(cherry picked from commit 43291b21dc24e1981d2bc8e1b715a5ce733c3e23)

Add @_unsafeInheritExecutor to withTaskCancellation(id:) (#1779)

* Add @_unsafeInheritExecutor to withTaskCancellation(id:)

* wip

(cherry picked from commit 48f0cc66000a23690ebbd7b65ea57fb7e7769825)

# Conflicts:
#	Sources/ComposableArchitecture/Effects/Cancellation.swift

resolve binding key path crash (#1784)

(cherry picked from commit fbe68471a3cf4eef6f0501d07642ee70b5bc3e84)

# Conflicts:
#	Sources/ComposableArchitecture/ViewStore.swift

Run swift-format

(cherry picked from commit 8f19bf88aeb67c33e41e14eefa30f9074ddca013)

Simplify/fix #1784 (#1785)

* Simplify/fix #1784

This PR works on top of #1784 and:

  * Reduces the number of moving parts
  * Restores implicit animations by directly producing the binding from
    the observable object
  * Strongly retains the store in the binding to avoid losing writes

* Move

(cherry picked from commit 626c35c7dea962bd3246e1f019d91cbfe419e695)

Make TestStore.receive actually match the action predicate (#1780)

* Assert that TestStore.receive(...) actually calls its predicate

* Fix TestStore.receive to respect its action predicate

* Update TestStore failure tests to use new description strings

(cherry picked from commit 5f294b9dc9a047b1e6b6766752da2856a158750e)

# Conflicts:
#	Tests/ComposableArchitectureTests/TestStoreTests.swift

Run swift-format

(cherry picked from commit 5a8df942237aa1ff59b7abccfe18bff74d1bbe4a)

Fix TestStore docs (#1787)

* Fix TestStore docs

* fix

* wip

(cherry picked from commit ea9cc86779038a0e1d38aa080bdc636e236190b6)

# Conflicts:
#	Sources/ComposableArchitecture/TestStore.swift

Deprecate 'Effect' for 'EffectTask' (#1788)

* Deprecate 'Effect' for 'EffectTask'

This is to allow reclaiming 'Effect' at a later time without the
'Failure' generic in the near future.

* wip

(cherry picked from commit 32f967c0b84099e29dc5bce062aa9f45493d2688)

# Conflicts:
#	Sources/ComposableArchitecture/Effect.swift

Soft-deprecate EffectPublisher (#1791)

* Soft-deprecate EffectPublisher in favor of EffectTask.

* wip

(cherry picked from commit 4266744f047734de8eb8bc73730d7f7d25cbd775)

# Conflicts:
#	Sources/ComposableArchitecture/Documentation.docc/ComposableArchitecture.md
#	Sources/ComposableArchitecture/Documentation.docc/Extensions/Effect.md
#	Sources/ComposableArchitecture/Effect.swift

Run swift-format

(cherry picked from commit ce196d7c152172cc924dcc875338a6459fcd568a)

Deprecate async version of withValue and introduce sync version. (#1792)

(cherry picked from commit 5eedf980b72dd6fcd3a65c01dfd644a929d2223b)

# Conflicts:
#	Sources/ComposableArchitecture/Effects/ConcurrencySupport.swift
#	Sources/ComposableArchitecture/Internal/Deprecations.swift

Run swift-format

(cherry picked from commit ad714bacb9dd1b3addfb27d5021ca8ad33b62009)

Wrong cancel id on testNestedCancels (#1793)

(cherry picked from commit 1a65878210b8bfccc7c73436718195582562c314)

# Conflicts:
#	Tests/ComposableArchitectureTests/EffectCancellationTests.swift

Allow `BindingReducer` to work with `ViewState` (#1790)

* Simpler bindable view state

* wip

* wip

* Remove `BindingStore`

* wip

* wip

* wip

* wip

* wip

* wip

* wip

* wip

* wip

* Make BindingState conditionally sendable.

* Fixed tests

* Update bindings article

* Add some additional contextual information to the runtime warnings

* update some docs

* lots more docs

* test clean up

* Improve diagnostic

* Put back `BindingReducer()` in the form study

* clean up

* Improve DocC references

* Remove DocC references for `@`'d property wrappers.

* wip

Co-authored-by: Stephen Celis <[email protected]>
Co-authored-by: Brandon Williams <[email protected]>
(cherry picked from commit c719fa1d3921533f25a6aa6c41016ce5d41a250d)

# Conflicts:
#	Sources/ComposableArchitecture/Internal/Deprecations.swift
#	Sources/ComposableArchitecture/SwiftUI/Binding.swift
#	Tests/ComposableArchitectureTests/BindingTests.swift
#	Tests/ComposableArchitectureTests/DebugTests.swift

Run swift-format

(cherry picked from commit d1c2e5b6d1c4e3b2f46c4fa1983b6ed4acab9173)

Revert #1790 (#1795)

It occurred to us that this solution unfortunately is incompatible with
view actions. We have an alternate solution that works, so I'll PR that
in the future if no others materialize!

(cherry picked from commit 30015d13a3ca0988b4674a83eccebbea747fe1f8)

# Conflicts:
#	Sources/ComposableArchitecture/Internal/Deprecations.swift
#	Sources/ComposableArchitecture/SwiftUI/Binding.swift

Revert #1784: Resolve binding key path crash (#1799)

* Revert "Simplify/fix #1784 (#1785)"

This reverts commit 626c35c7dea962bd3246e1f019d91cbfe419e695.

* Revert "resolve binding key path crash (#1784)"

This reverts commit fbe68471a3cf4eef6f0501d07642ee70b5bc3e84.

(cherry picked from commit cbf8a45fa97ca4afb858f6cd99730bb67952813a)

# Conflicts:
#	Sources/ComposableArchitecture/ViewStore.swift
  • Loading branch information
mbrandonw authored and p4checo committed Jan 16, 2023
1 parent a95532b commit 226cdd9
Show file tree
Hide file tree
Showing 16 changed files with 389 additions and 334 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,6 @@ struct FocusDemoView: View {
VStack {
TextField("Username", text: viewStore.binding(\.$username))
.focused($focusedField, equals: .username)

SecureField("Password", text: viewStore.binding(\.$password))
.focused($focusedField, equals: .password)
Button("Sign In") {
Expand Down
4 changes: 2 additions & 2 deletions Package.resolved
Original file line number Diff line number Diff line change
Expand Up @@ -86,8 +86,8 @@
"kind" : "remoteSourceControl",
"location" : "https://github.com/pointfreeco/swiftui-navigation",
"state" : {
"revision" : "ddc01cdcddfd30ef7a966049b2e1d251e224ad93",
"version" : "0.5.0"
"revision" : "46acf5ecc1cabdb28d7fe03289f6c8b13a023f52",
"version" : "0.4.5"
}
},
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
### State management

- ``ReducerProtocol``
- ``EffectProducer``
- ``EffectTask``
- ``Store``
- ``ViewStore``

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,9 +33,5 @@ Avoid using deprecated APIs in your app. Select a method to see the replacement
- ``WithViewStore/Action``
- ``WithViewStore/State``

### View state

- ``ActionSheetState``

<!--DocC: Can't currently document `View` extensions-->
<!--### View Modifiers-->
Original file line number Diff line number Diff line change
@@ -1,39 +1,39 @@
# ``ComposableArchitecture/EffectProducer``
# ``ComposableArchitecture/EffectTask``

## Topics

### Creating an effect

- ``none``
- ``task(priority:operation:catch:file:fileID:line:)``
- ``run(priority:operation:catch:file:fileID:line:)``
- ``fireAndForget(priority:_:)``
- ``EffectProducer/none``
- ``EffectProducer/task(priority:operation:catch:file:fileID:line:)``
- ``EffectProducer/run(priority:operation:catch:file:fileID:line:)``
- ``EffectProducer/fireAndForget(priority:_:)``
- ``TaskResult``

### Cancellation

- ``cancellable(id:cancelInFlight:)-29q60``
- ``cancel(id:)-6hzsl``
- ``cancel(ids:)-1cqqx``
- ``EffectProducer/cancellable(id:cancelInFlight:)-29q60``
- ``EffectProducer/cancel(id:)-6hzsl``
- ``EffectProducer/cancel(ids:)-1cqqx``
- ``withTaskCancellation(id:cancelInFlight:operation:)-4dtr6``

### Composition

- ``map(_:)-yn70``
- ``merge(_:)-45guh``
- ``merge(_:)-3d54p``
- ``EffectProducer/map(_:)-yn70``
- ``EffectProducer/merge(_:)-45guh``
- ``EffectProducer/merge(_:)-3d54p``

### Concurrency

- ``UncheckedSendable``

### Testing

- ``unimplemented(_:)``
- ``EffectProducer/unimplemented(_:)``

### SwiftUI integration

- ``animation(_:)``
- ``EffectProducer/animation(_:)``

### Deprecations

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

### Creating a test store

- ``init(initialState:reducer:file:line:)``
- ``init(initialState:reducer:prepareDependencies:file:line:)``

### Configuring a test store

Expand All @@ -18,7 +18,7 @@
- ``receive(_:timeout:assert:file:line:)-1rwdd``
- ``receive(_:timeout:assert:file:line:)-4e4m0``
- ``receive(_:timeout:assert:file:line:)-3myco``
- ``finish(timeout:file:line:)``
- ``finish(timeout:file:line:)-53gi5``
- ``TestStoreTask``

### Methods for skipping actions and effects
Expand Down
169 changes: 85 additions & 84 deletions Sources/ComposableArchitecture/Effect.swift
Original file line number Diff line number Diff line change
Expand Up @@ -6,35 +6,55 @@ import XCTestDynamicOverlay
import SwiftUI
#endif

/// A type that encapsulates a unit of work that can be run in the outside world, and can feed
/// actions back to the ``Store``.
///
/// Effects are the perfect place to do side effects, such as network requests, saving/loading
/// from disk, creating timers, interacting with dependencies, and more. They are returned from
/// reducers so that the ``Store`` can perform the effects after the reducer is done running.
///
/// There are 2 distinct ways to create an `Effect`: one using Swift's native concurrency tools, and
/// the other using ReactiveSwift framework:
///
/// * If using Swift's native structured concurrency tools then there are 3 main ways to create an
/// effect, depending on if you want to emit one single action back into the system, or any number
/// of actions, or just execute some work without emitting any actions:
/// * ``EffectProducer/task(priority:operation:catch:file:fileID:line:)``
/// * ``EffectProducer/run(priority:operation:catch:file:fileID:line:)``
/// * ``EffectProducer/fireAndForget(priority:_:)``
/// * If using ReactiveSwift in your application, in particular for the dependencies of your feature
/// then you can create effects by making use of any of ReactiveSwift's operators, and then erasing the
/// publisher type to ``EffectProducer`` with either `eraseToEffect` or `catchToEffect`. Note that
/// the ReactiveSwift interface to ``EffectProducer`` is considered soft deprecated, and you should
/// eventually port to Swift's native concurrency tools.
///
/// > Important: ``Store`` is not thread safe, and so all effects must receive values on the same
/// thread. This is typically the main thread, **and** if the store is being used to drive UI then
/// it must receive values on the main thread.
/// >
/// > This is only an issue if using the ReactiveSwift interface of ``EffectProducer`` as mentioned
/// above. If you are using Swift's concurrency tools and the `.task`, `.run` and `.fireAndForget`
/// functions on ``EffectTask``, then threading is automatically handled for you.
/// This type is deprecated in favor of ``EffectTask``. See its documentation for more information.
@available(
iOS,
deprecated: 9999.0,
message:
"""
'EffectProducer' has been deprecated in favor of 'EffectTask'.
You are encouraged to use `EffectTask<Action>` to model the ouput of your reducers, and to use Swift concurrency to model asynchrony in dependencies.
See the migration roadmap for more information: https://github.com/pointfreeco/swift-composable-architecture/discussions/1477
"""
)
@available(
macOS,
deprecated: 9999.0,
message:
"""
'EffectProducer' has been deprecated in favor of 'EffectTask'.
You are encouraged to use `EffectTask<Action>` to model the ouput of your reducers, and to use Swift concurrency to model asynchrony in dependencies.
See the migration roadmap for more information: https://github.com/pointfreeco/swift-composable-architecture/discussions/1477
"""
)
@available(
tvOS,
deprecated: 9999.0,
message:
"""
'EffectProducer' has been deprecated in favor of 'EffectTask'.
You are encouraged to use `EffectTask<Action>` to model the ouput of your reducers, and to use Swift concurrency to model asynchrony in dependencies.
See the migration roadmap for more information: https://github.com/pointfreeco/swift-composable-architecture/discussions/1477
"""
)
@available(
watchOS,
deprecated: 9999.0,
message:
"""
'EffectProducer' has been deprecated in favor of 'EffectTask'.
You are encouraged to use `EffectTask<Action>` to model the ouput of your reducers, and to use Swift concurrency to model asynchrony in dependencies.
See the migration roadmap for more information: https://github.com/pointfreeco/swift-composable-architecture/discussions/1477
"""
)
public struct EffectProducer<Action, Failure: Error> {
@usableFromInline
enum Operation {
Expand Down Expand Up @@ -63,20 +83,38 @@ extension EffectProducer {
}
}

/// A convenience type alias for referring to an effect that can never fail, like the kind of
/// ``EffectProducer`` returned by a reducer after processing an action.
/// A type that encapsulates a unit of work that can be run in the outside world, and can feed
/// actions back to the ``Store``.
///
/// Instead of specifying `Never` as `Failure`:
/// Effects are the perfect place to do side effects, such as network requests, saving/loading
/// from disk, creating timers, interacting with dependencies, and more. They are returned from
/// reducers so that the ``Store`` can perform the effects after the reducer is done running.
///
/// ```swift
/// func reduce(into state: inout State, action: Action) -> EffectProducer<Action, Never> { … }
/// ```
/// There are 2 distinct ways to create an `Effect`: one using Swift's native concurrency tools, and
/// the other using Apple's Combine framework:
///
/// You can specify a single generic:
/// * If using Swift's native structured concurrency tools then there are 3 main ways to create an
/// effect, depending on if you want to emit one single action back into the system, or any number
/// of actions, or just execute some work without emitting any actions:
/// * ``EffectProducer/task(priority:operation:catch:file:fileID:line:)``
/// * ``EffectProducer/run(priority:operation:catch:file:fileID:line:)``
/// * ``EffectProducer/fireAndForget(priority:_:)``
/// * If using Combine in your application, in particular for the dependencies of your feature
/// then you can create effects by making use of any of Combine's operators, and then erasing the
/// publisher type to ``EffectProducer`` with either `eraseToEffect` or `catchToEffect`. Note that
/// the Combine interface to ``EffectProducer`` is considered soft deprecated, and you should
/// eventually port to Swift's native concurrency tools.
///
/// ```swift
/// func reduce(into state: inout State, action: Action) -> EffectTask<Action> { … }
/// ```
/// > Important: The publisher interface to ``EffectTask`` is considered deperecated, and you should
/// try converting any uses of that interface to Swift's native concurrency tools.
/// >
/// > Also, ``Store`` is not thread safe, and so all effects must receive values on the same
/// thread. This is typically the main thread, **and** if the store is being used to drive UI then
/// it must receive values on the main thread.
/// >
/// > This is only an issue if using the Combine interface of ``EffectProducer`` as mentioned
/// above. If you are using Swift's concurrency tools and the `.task`, `.run` and `.fireAndForget`
/// functions on ``EffectTask``, then threading is automatically handled for you.
public typealias EffectTask<Action> = Effect<Action, Never>

extension EffectProducer where Failure == Never {
Expand Down Expand Up @@ -614,57 +652,20 @@ extension EffectProducer {
}

@available(
iOS,
deprecated: 9999.0,
*,
message:
"""
'Effect' has been deprecated in favor of 'EffectTask' when `Failure == Never`, or
`EffectProducer<Output, Failure>` in general.
'Effect' has been deprecated in favor of 'EffectTask' when 'Failure == Never', or 'EffectProducer<Output, Failure>' in general.
You are encouraged to use `EffectTask<Action>` to model the ouput of your reducers, and to Swift
concurrency to model failable streams of values.
You are encouraged to use 'EffectTask<Action>' to model the output of your reducers, and to use Swift concurrency to model failable streams of values.
See the migration roadmap for more information: https://github.com/pointfreeco/swift-composable-architecture/discussions/1477
"""
)
@available(
macOS,
deprecated: 9999.0,
message:
"""
'Effect' has been deprecated in favor of 'EffectTask' when `Failure == Never`, or
`EffectProducer<Output, Failure>` in general.
You are encouraged to use `EffectTask<Action>` to model the ouput of your reducers, and to Swift
concurrency to model failable streams of values.
To find and replace instances of 'Effect<Action, Never>' to 'EffectTask<Action, Never>' in your codebase, use the following regular expression:
See the migration roadmap for more information: https://github.com/pointfreeco/swift-composable-architecture/discussions/1477
"""
)
@available(
tvOS,
deprecated: 9999.0,
message:
"""
'Effect' has been deprecated in favor of 'EffectTask' when `Failure == Never`, or
`EffectProducer<Output, Failure>` in general.
You are encouraged to use `EffectTask<Action>` to model the ouput of your reducers, and to Swift
concurrency to model failable streams of values.
Find:
Effect<([^,]+), Never>
See the migration roadmap for more information: https://github.com/pointfreeco/swift-composable-architecture/discussions/1477
"""
)
@available(
watchOS,
deprecated: 9999.0,
message:
"""
'Effect' has been deprecated in favor of 'EffectTask' when `Failure == Never`, or
`EffectProducer<Output, Failure>` in general.
You are encouraged to use `EffectTask<Action>` to model the ouput of your reducers, and to Swift
concurrency to model failable streams of values.
Replace:
EffectTask<$1>
See the migration roadmap for more information: https://github.com/pointfreeco/swift-composable-architecture/discussions/1477
"""
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -326,11 +326,11 @@
/// - Parameters: operation: An operation to be performed on the actor with the underlying value.
/// - Returns: The result of the operation.
public func withValue<T: Sendable>(
_ operation: @Sendable (inout Value) async throws -> T
) async rethrows -> T {
_ operation: @Sendable (inout Value) throws -> T
) rethrows -> T {
var value = self.value
defer { self.value = value }
return try await operation(&value)
return try operation(&value)
}

/// Overwrite the isolated value with a new value.
Expand Down
17 changes: 17 additions & 0 deletions Sources/ComposableArchitecture/Internal/Deprecations.swift
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,23 @@ import XCTestDynamicOverlay
import os
#endif

// MARK: - Deprecated after 0.47.2

extension ActorIsolated {
@available(
*,
deprecated,
message: "Use the non-async version of 'withValue'."
)
public func withValue<T: Sendable>(
_ operation: @Sendable (inout Value) async throws -> T
) async rethrows -> T {
var value = self.value
defer { self.value = value }
return try await operation(&value)
}
}

// MARK: - Deprecated after 0.45.0:

#if canImport(SwiftUI)
Expand Down
12 changes: 5 additions & 7 deletions Sources/ComposableArchitecture/SwiftUI/Binding.swift
Original file line number Diff line number Diff line change
Expand Up @@ -82,12 +82,11 @@ extension BindableState: CustomReflectable {
}
}

// Until we can use swift-custom-dump this has to be commented out
// extension BindableState: CustomDumpRepresentable {
// public var customDumpValue: Any {
// self.wrappedValue
// }
// }
extension BindableState: CustomDumpRepresentable {
public var customDumpValue: Any {
self.wrappedValue
}
}

extension BindableState: CustomDebugStringConvertible where Value: CustomDebugStringConvertible {
public var debugDescription: String {
Expand Down Expand Up @@ -157,7 +156,6 @@ extension BindableAction {
)
}
}

#endif

/// An action that describes simple mutations to some root state at a writable key path.
Expand Down
Loading

0 comments on commit 226cdd9

Please sign in to comment.