Skip to content

Commit

Permalink
Allow mirrorables in builder if/switch expressions (#26)
Browse files Browse the repository at this point in the history
  • Loading branch information
davdroman authored Nov 8, 2022
1 parent 251fcfb commit 43a29c4
Show file tree
Hide file tree
Showing 5 changed files with 106 additions and 13 deletions.
81 changes: 81 additions & 0 deletions Sources/AtomicTransition/AtomicTransitionBuilder.swift
Original file line number Diff line number Diff line change
Expand Up @@ -110,4 +110,85 @@ public struct AtomicTransitionBuilder {
Combined(Combined(Combined(Combined(Combined(Combined(t1, t2), t3), t4), t5), t6), t7)
}
#endif

public static func buildOptional<T: AtomicTransition>(_ component: T?) -> _OptionalTransition<T> {
if let component = component {
return _OptionalTransition(component)
} else {
return _OptionalTransition(nil)
}
}

public static func buildEither<TrueTransition: AtomicTransition, FalseTransition: AtomicTransition>(first component: TrueTransition) -> _ConditionalTransition<TrueTransition, FalseTransition> {
_ConditionalTransition(trueTransition: component)
}

public static func buildEither<TrueTransition: AtomicTransition, FalseTransition: AtomicTransition>(second component: FalseTransition) -> _ConditionalTransition<TrueTransition, FalseTransition> {
_ConditionalTransition(falseTransition: component)
}
}

public struct _OptionalTransition<Transition: AtomicTransition>: AtomicTransition {
private let transition: Transition?

init(_ transition: Transition?) {
self.transition = transition
}

public func transition(_ view: TransientView, for operation: TransitionOperation, in container: Container) {
transition?.transition(view, for: operation, in: container)
}
}

extension _OptionalTransition: MirrorableAtomicTransition where Transition: MirrorableAtomicTransition {
public func mirrored() -> _OptionalTransition<Transition.Mirrored> {
.init(transition?.mirrored())
}
}

extension _OptionalTransition: Equatable where Transition: Equatable {}
extension _OptionalTransition: Hashable where Transition: Hashable {}

public struct _ConditionalTransition<TrueTransition: AtomicTransition, FalseTransition: AtomicTransition>: AtomicTransition {
private typealias Transition = _Either<TrueTransition, FalseTransition>
private let transition: Transition

init(trueTransition: TrueTransition) {
self.transition = .left(trueTransition)
}

init(falseTransition: FalseTransition) {
self.transition = .right(falseTransition)
}

public func transition(_ view: TransientView, for operation: TransitionOperation, in container: Container) {
switch transition {
case .left(let trueTransition):
trueTransition.transition(view, for: operation, in: container)
case .right(let falseTransition):
falseTransition.transition(view, for: operation, in: container)
}
}
}

extension _ConditionalTransition: MirrorableAtomicTransition where TrueTransition: MirrorableAtomicTransition, FalseTransition: MirrorableAtomicTransition {
public func mirrored() -> _ConditionalTransition<TrueTransition.Mirrored, FalseTransition.Mirrored> {
switch transition {
case .left(let trueTransition):
return .init(trueTransition: trueTransition.mirrored())
case .right(let falseTransition):
return .init(falseTransition: falseTransition.mirrored())
}
}
}

extension _ConditionalTransition: Equatable where TrueTransition: Equatable, FalseTransition: Equatable {}
extension _ConditionalTransition: Hashable where TrueTransition: Hashable, FalseTransition: Hashable {}

private enum _Either<Left, Right> {
case left(Left)
case right(Right)
}

extension _Either: Equatable where Left: Equatable, Right: Equatable {}
extension _Either: Hashable where Left: Hashable, Right: Hashable {}
4 changes: 2 additions & 2 deletions Sources/AtomicTransition/Mirror.swift
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
/// A transition that executes only on insertion.
/// A transition that executes only on insertion, but executes only on removal when mirrored.
public struct MirrorInsertion<Transition: AtomicTransition>: AtomicTransition {
private let transition: Transition

Expand Down Expand Up @@ -29,7 +29,7 @@ extension MirrorInsertion: MirrorableAtomicTransition where Transition: Mirrorab
extension MirrorInsertion: Equatable where Transition: Equatable {}
extension MirrorInsertion: Hashable where Transition: Hashable {}

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

Expand Down
6 changes: 3 additions & 3 deletions Sources/NavigationTransition/Asymmetric.swift
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import AtomicTransition

/// A composite transition that uses a different transition for insertion versus removal.
/// A composite transition that uses a different transition for push versus pop.
public struct Asymmetric<PushTransition: NavigationTransition, PopTransition: NavigationTransition>: NavigationTransition {
private let push: PushTransition
private let pop: PopTransition
Expand Down Expand Up @@ -31,7 +31,7 @@ public struct Asymmetric<PushTransition: NavigationTransition, PopTransition: Na
extension Asymmetric: Equatable where PushTransition: Equatable, PopTransition: Equatable {}
extension Asymmetric: Hashable where PushTransition: Hashable, PopTransition: Hashable {}

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

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

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

Expand Down
2 changes: 2 additions & 0 deletions Sources/NavigationTransition/Mirror.swift
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import AtomicTransition

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

Expand All @@ -17,6 +18,7 @@ public struct MirrorPush<Transition: MirrorableAtomicTransition>: NavigationTran
}
}

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

Expand Down
26 changes: 18 additions & 8 deletions Sources/NavigationTransition/NavigationTransitionBuilder.swift
Original file line number Diff line number Diff line change
Expand Up @@ -143,17 +143,15 @@ public struct _OptionalTransition<Transition: NavigationTransition>: NavigationT
}

public struct _ConditionalTransition<TrueTransition: NavigationTransition, FalseTransition: NavigationTransition>: NavigationTransition {
private let trueTransition: TrueTransition?
private let falseTransition: FalseTransition?
private typealias Transition = _Either<TrueTransition, FalseTransition>
private let transition: Transition

init(trueTransition: TrueTransition) {
self.trueTransition = trueTransition
self.falseTransition = nil
self.transition = .left(trueTransition)
}

init(falseTransition: FalseTransition) {
self.trueTransition = nil
self.falseTransition = falseTransition
self.transition = .right(falseTransition)
}

public func transition(
Expand All @@ -162,7 +160,19 @@ public struct _ConditionalTransition<TrueTransition: NavigationTransition, False
for operation: TransitionOperation,
in container: Container
) {
trueTransition?.transition(from: fromView, to: toView, for: operation, in: container)
falseTransition?.transition(from: fromView, to: toView, for: operation, in: container)
switch transition {
case .left(let trueTransition):
trueTransition.transition(from: fromView, to: toView, for: operation, in: container)
case .right(let falseTransition):
falseTransition.transition(from: fromView, to: toView, for: operation, in: container)
}
}
}

private enum _Either<Left, Right> {
case left(Left)
case right(Right)
}

extension _Either: Equatable where Left: Equatable, Right: Equatable {}
extension _Either: Hashable where Left: Hashable, Right: Hashable {}

0 comments on commit 43a29c4

Please sign in to comment.