Skip to content

Commit 43a29c4

Browse files
authored
Allow mirrorables in builder if/switch expressions (#26)
1 parent 251fcfb commit 43a29c4

File tree

5 files changed

+106
-13
lines changed

5 files changed

+106
-13
lines changed

Sources/AtomicTransition/AtomicTransitionBuilder.swift

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,4 +110,85 @@ public struct AtomicTransitionBuilder {
110110
Combined(Combined(Combined(Combined(Combined(Combined(t1, t2), t3), t4), t5), t6), t7)
111111
}
112112
#endif
113+
114+
public static func buildOptional<T: AtomicTransition>(_ component: T?) -> _OptionalTransition<T> {
115+
if let component = component {
116+
return _OptionalTransition(component)
117+
} else {
118+
return _OptionalTransition(nil)
119+
}
120+
}
121+
122+
public static func buildEither<TrueTransition: AtomicTransition, FalseTransition: AtomicTransition>(first component: TrueTransition) -> _ConditionalTransition<TrueTransition, FalseTransition> {
123+
_ConditionalTransition(trueTransition: component)
124+
}
125+
126+
public static func buildEither<TrueTransition: AtomicTransition, FalseTransition: AtomicTransition>(second component: FalseTransition) -> _ConditionalTransition<TrueTransition, FalseTransition> {
127+
_ConditionalTransition(falseTransition: component)
128+
}
129+
}
130+
131+
public struct _OptionalTransition<Transition: AtomicTransition>: AtomicTransition {
132+
private let transition: Transition?
133+
134+
init(_ transition: Transition?) {
135+
self.transition = transition
136+
}
137+
138+
public func transition(_ view: TransientView, for operation: TransitionOperation, in container: Container) {
139+
transition?.transition(view, for: operation, in: container)
140+
}
113141
}
142+
143+
extension _OptionalTransition: MirrorableAtomicTransition where Transition: MirrorableAtomicTransition {
144+
public func mirrored() -> _OptionalTransition<Transition.Mirrored> {
145+
.init(transition?.mirrored())
146+
}
147+
}
148+
149+
extension _OptionalTransition: Equatable where Transition: Equatable {}
150+
extension _OptionalTransition: Hashable where Transition: Hashable {}
151+
152+
public struct _ConditionalTransition<TrueTransition: AtomicTransition, FalseTransition: AtomicTransition>: AtomicTransition {
153+
private typealias Transition = _Either<TrueTransition, FalseTransition>
154+
private let transition: Transition
155+
156+
init(trueTransition: TrueTransition) {
157+
self.transition = .left(trueTransition)
158+
}
159+
160+
init(falseTransition: FalseTransition) {
161+
self.transition = .right(falseTransition)
162+
}
163+
164+
public func transition(_ view: TransientView, for operation: TransitionOperation, in container: Container) {
165+
switch transition {
166+
case .left(let trueTransition):
167+
trueTransition.transition(view, for: operation, in: container)
168+
case .right(let falseTransition):
169+
falseTransition.transition(view, for: operation, in: container)
170+
}
171+
}
172+
}
173+
174+
extension _ConditionalTransition: MirrorableAtomicTransition where TrueTransition: MirrorableAtomicTransition, FalseTransition: MirrorableAtomicTransition {
175+
public func mirrored() -> _ConditionalTransition<TrueTransition.Mirrored, FalseTransition.Mirrored> {
176+
switch transition {
177+
case .left(let trueTransition):
178+
return .init(trueTransition: trueTransition.mirrored())
179+
case .right(let falseTransition):
180+
return .init(falseTransition: falseTransition.mirrored())
181+
}
182+
}
183+
}
184+
185+
extension _ConditionalTransition: Equatable where TrueTransition: Equatable, FalseTransition: Equatable {}
186+
extension _ConditionalTransition: Hashable where TrueTransition: Hashable, FalseTransition: Hashable {}
187+
188+
private enum _Either<Left, Right> {
189+
case left(Left)
190+
case right(Right)
191+
}
192+
193+
extension _Either: Equatable where Left: Equatable, Right: Equatable {}
194+
extension _Either: Hashable where Left: Hashable, Right: Hashable {}

Sources/AtomicTransition/Mirror.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
/// A transition that executes only on insertion.
1+
/// A transition that executes only on insertion, but executes only on removal when mirrored.
22
public struct MirrorInsertion<Transition: AtomicTransition>: AtomicTransition {
33
private let transition: Transition
44

@@ -29,7 +29,7 @@ extension MirrorInsertion: MirrorableAtomicTransition where Transition: Mirrorab
2929
extension MirrorInsertion: Equatable where Transition: Equatable {}
3030
extension MirrorInsertion: Hashable where Transition: Hashable {}
3131

32-
/// A transition that executes only on removal.
32+
/// A transition that executes only on removal, but executes only on insertion when mirrored.
3333
public struct MirrorRemoval<Transition: AtomicTransition>: AtomicTransition {
3434
private let transition: Transition
3535

Sources/NavigationTransition/Asymmetric.swift

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import AtomicTransition
22

3-
/// A composite transition that uses a different transition for insertion versus removal.
3+
/// A composite transition that uses a different transition for push versus pop.
44
public struct Asymmetric<PushTransition: NavigationTransition, PopTransition: NavigationTransition>: NavigationTransition {
55
private let push: PushTransition
66
private let pop: PopTransition
@@ -31,7 +31,7 @@ public struct Asymmetric<PushTransition: NavigationTransition, PopTransition: Na
3131
extension Asymmetric: Equatable where PushTransition: Equatable, PopTransition: Equatable {}
3232
extension Asymmetric: Hashable where PushTransition: Hashable, PopTransition: Hashable {}
3333

34-
/// A transition that executes only on insertion.
34+
/// Used to define a transition that executes only on push.
3535
public struct OnPush<Transition: AtomicTransition>: NavigationTransition {
3636
private let transition: Transition
3737

@@ -58,7 +58,7 @@ public struct OnPush<Transition: AtomicTransition>: NavigationTransition {
5858
extension OnPush: Equatable where Transition: Equatable {}
5959
extension OnPush: Hashable where Transition: Hashable {}
6060

61-
/// A transition that executes only on removal.
61+
/// Used to define a transition that executes only on pop.
6262
public struct OnPop<Transition: AtomicTransition>: NavigationTransition {
6363
private let transition: Transition
6464

Sources/NavigationTransition/Mirror.swift

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import AtomicTransition
22

3+
/// Used to define a transition that executes on push, and executes the mirrored version of said transition on pop.
34
public struct MirrorPush<Transition: MirrorableAtomicTransition>: NavigationTransition {
45
private let transition: Transition
56

@@ -17,6 +18,7 @@ public struct MirrorPush<Transition: MirrorableAtomicTransition>: NavigationTran
1718
}
1819
}
1920

21+
/// Used to define a transition that executes on pop, and executes the mirrored version of said transition on push.
2022
public struct MirrorPop<Transition: MirrorableAtomicTransition>: NavigationTransition {
2123
private let transition: Transition
2224

Sources/NavigationTransition/NavigationTransitionBuilder.swift

Lines changed: 18 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -143,17 +143,15 @@ public struct _OptionalTransition<Transition: NavigationTransition>: NavigationT
143143
}
144144

145145
public struct _ConditionalTransition<TrueTransition: NavigationTransition, FalseTransition: NavigationTransition>: NavigationTransition {
146-
private let trueTransition: TrueTransition?
147-
private let falseTransition: FalseTransition?
146+
private typealias Transition = _Either<TrueTransition, FalseTransition>
147+
private let transition: Transition
148148

149149
init(trueTransition: TrueTransition) {
150-
self.trueTransition = trueTransition
151-
self.falseTransition = nil
150+
self.transition = .left(trueTransition)
152151
}
153152

154153
init(falseTransition: FalseTransition) {
155-
self.trueTransition = nil
156-
self.falseTransition = falseTransition
154+
self.transition = .right(falseTransition)
157155
}
158156

159157
public func transition(
@@ -162,7 +160,19 @@ public struct _ConditionalTransition<TrueTransition: NavigationTransition, False
162160
for operation: TransitionOperation,
163161
in container: Container
164162
) {
165-
trueTransition?.transition(from: fromView, to: toView, for: operation, in: container)
166-
falseTransition?.transition(from: fromView, to: toView, for: operation, in: container)
163+
switch transition {
164+
case .left(let trueTransition):
165+
trueTransition.transition(from: fromView, to: toView, for: operation, in: container)
166+
case .right(let falseTransition):
167+
falseTransition.transition(from: fromView, to: toView, for: operation, in: container)
168+
}
167169
}
168170
}
171+
172+
private enum _Either<Left, Right> {
173+
case left(Left)
174+
case right(Right)
175+
}
176+
177+
extension _Either: Equatable where Left: Equatable, Right: Equatable {}
178+
extension _Either: Hashable where Left: Hashable, Right: Hashable {}

0 commit comments

Comments
 (0)