11import Combine
2+ import SwiftUI
23
34public protocol StoreProtocol : ObservableObject , Subscriber {
45 associatedtype BaseState
@@ -9,12 +10,12 @@ public protocol StoreProtocol: ObservableObject, Subscriber {
910 var state : SubState { get }
1011 var statePublisher : Published < SubState > . Publisher { get }
1112 var underlying : BaseStore < BaseState , RawAction , BaseRefinedAction > { get }
12- var keyPath : KeyPath < BaseState , SubState > { get }
13+ var stateLens : ( BaseState ) -> SubState { get }
1314 var actionPromotion : ( SubRefinedAction ) -> BaseRefinedAction { get }
1415 func dispatch< S: Sequence > ( raw: S ) where S. Element == RawAction
1516 func dispatch< S: Sequence > ( refined: S ) where S. Element == SubRefinedAction
1617 func lensing< NewState, NewAction> (
17- state keyPath : KeyPath < SubState , NewState > ,
18+ state lens : @escaping ( SubState ) -> NewState ,
1819 actions transform: @escaping ( NewAction ) -> SubRefinedAction
1920 ) -> LensedStore <
2021 BaseState ,
@@ -27,30 +28,109 @@ public protocol StoreProtocol: ObservableObject, Subscriber {
2728}
2829
2930public extension StoreProtocol {
30- func lensing< NewState, NewAction > (
31- actions transform : @escaping ( NewAction ) -> SubRefinedAction
31+ func lensing< NewState> (
32+ state lens : @escaping ( SubState ) -> NewState
3233 ) -> LensedStore <
3334 BaseState ,
3435 NewState ,
3536 RawAction ,
3637 BaseRefinedAction ,
38+ SubRefinedAction
39+ > {
40+ lensing ( state: lens, actions: { $0 } )
41+ }
42+
43+ func lensing< NewState> (
44+ state keyPath: KeyPath < SubState , NewState >
45+ ) -> LensedStore <
46+ BaseState ,
47+ NewState ,
48+ RawAction ,
49+ BaseRefinedAction ,
50+ SubRefinedAction
51+ > {
52+ lensing ( state: { $0 [ keyPath: keyPath] } )
53+ }
54+
55+ func lensing< NewAction> (
56+ actions transform: @escaping ( NewAction ) -> SubRefinedAction
57+ ) -> LensedStore <
58+ BaseState ,
59+ SubState ,
60+ RawAction ,
61+ BaseRefinedAction ,
3762 NewAction
38- > where NewState == SubState {
39- lensing ( state: \ . self , actions: transform)
63+ > {
64+ lensing ( state: { $0 } , actions: transform)
4065 }
4166
4267 func lensing< NewState, NewAction> (
43- state keyPath: KeyPath < SubState , NewState >
68+ state keyPath: KeyPath < SubState , NewState > ,
69+ actions transform: @escaping ( NewAction ) -> SubRefinedAction
4470 ) -> LensedStore <
4571 BaseState ,
4672 NewState ,
4773 RawAction ,
4874 BaseRefinedAction ,
4975 NewAction
50- > where NewAction == SubRefinedAction {
51- lensing ( state: keyPath , actions : { $0 } )
76+ > {
77+ lensing ( state: { $0 [ keyPath : keyPath ] } , actions : transform )
5278 }
79+ }
5380
81+ public extension StoreProtocol {
82+ /// Create a SwiftUI Binding from a lensing function and a `SubRefinedAction`.
83+ /// - Parameters:
84+ /// - lens: A lens to the state property.
85+ /// - action: The refined action which will be called when the value is changed.
86+ /// - Returns: A `Binding` whose getter is the property and whose setter dispatches the refined action.
87+ func binding< Value> (
88+ state lens: @escaping ( SubState ) -> Value ,
89+ actions transform: @escaping ( Value ) -> SubRefinedAction
90+ ) -> Binding < Value > {
91+ . init(
92+ get: { lens ( self . state) } ,
93+ set: { self . dispatch ( refined: transform ( $0) ) }
94+ )
95+ }
96+
97+ /// Create a SwiftUI Binding from the `SubState` of the store and a `SubRefinedAction`.
98+ /// - Parameters:
99+ /// - actions: The refined action which will be called when the value is changed.
100+ /// - Returns: A `Binding` whose getter is the state and whose setter dispatches the refined action.
101+ func binding(
102+ actions transform: @escaping ( SubState ) -> SubRefinedAction
103+ ) -> Binding < SubState > {
104+ . init(
105+ get: { self . state } ,
106+ set: { self . dispatch ( refined: transform ( $0) ) }
107+ )
108+ }
109+
110+ /// Create a SwiftUI Binding from a lensing function when the value of that function is equivalent to `SubRefinedAction`.
111+ /// - Parameters:
112+ /// - lens: A lens to the state property.
113+ /// - Returns: A `Binding` whose getter is the property and whose setter dispatches the store's refined action.
114+ func binding< Value> (
115+ state lens: @escaping ( SubState ) -> Value
116+ ) -> Binding < Value > where SubRefinedAction == Value {
117+ . init(
118+ get: { lens ( self . state) } ,
119+ set: { self . dispatch ( refined: $0) }
120+ )
121+ }
122+
123+ /// Create a SwiftUI Binding from the `SubState` when its value is equivalent to `SubRefinedAction`.
124+ /// - Returns: A `Binding` whose getter is the state and whose setter dispatches the store's refined action.
125+ func binding( ) -> Binding < SubState > where SubRefinedAction == SubState {
126+ . init(
127+ get: { self . state } ,
128+ set: { self . dispatch ( refined: $0) }
129+ )
130+ }
131+ }
132+
133+ public extension StoreProtocol {
54134 func dispatch( refined actions: SubRefinedAction ... ) {
55135 dispatch ( refined: actions)
56136 }
@@ -64,12 +144,12 @@ public extension StoreProtocol {
64144 }
65145}
66146
67- extension StoreProtocol {
68- public func receive( subscription: Subscription ) {
147+ public extension StoreProtocol {
148+ func receive( subscription: Subscription ) {
69149 subscription. request ( . unlimited)
70150 }
71151
72- public func receive( _ input: ActionStrata < RawAction , SubRefinedAction > ) -> Subscribers . Demand {
152+ func receive( _ input: ActionStrata < RawAction , SubRefinedAction > ) -> Subscribers . Demand {
73153 switch input {
74154 case let . raw( action) :
75155 dispatch ( raw: action)
@@ -79,5 +159,5 @@ extension StoreProtocol {
79159 return . unlimited
80160 }
81161
82- public func receive( completion: Subscribers . Completion < Never > ) { }
162+ func receive( completion: Subscribers . Completion < Never > ) { }
83163}
0 commit comments