Skip to content

Commit 0ac3c1a

Browse files
authored
Pick Transition (#27)
1 parent 43a29c4 commit 0ac3c1a

File tree

7 files changed

+65
-107
lines changed

7 files changed

+65
-107
lines changed

Sources/AtomicTransition/Asymmetric.swift renamed to Sources/AtomicTransition/On.swift

Lines changed: 0 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -1,41 +1,5 @@
11
import class UIKit.UIView
22

3-
/// A composite transition that uses a different transition for push versus pop.
4-
public struct Asymmetric<InsertionTransition: AtomicTransition, RemovalTransition: AtomicTransition>: AtomicTransition {
5-
private let insertion: InsertionTransition
6-
private let removal: RemovalTransition
7-
8-
private init(insertion: InsertionTransition, removal: RemovalTransition) {
9-
self.insertion = insertion
10-
self.removal = removal
11-
}
12-
13-
public init(
14-
@AtomicTransitionBuilder insertion: () -> InsertionTransition,
15-
@AtomicTransitionBuilder removal: () -> RemovalTransition
16-
) {
17-
self.init(insertion: insertion(), removal: removal())
18-
}
19-
20-
public func transition(_ view: TransientView, for operation: TransitionOperation, in container: Container) {
21-
switch operation {
22-
case .insertion:
23-
insertion.transition(view, for: operation, in: container)
24-
case .removal:
25-
removal.transition(view, for: operation, in: container)
26-
}
27-
}
28-
}
29-
30-
extension Asymmetric: MirrorableAtomicTransition where InsertionTransition: MirrorableAtomicTransition, RemovalTransition: MirrorableAtomicTransition {
31-
public func mirrored() -> Asymmetric<InsertionTransition.Mirrored, RemovalTransition.Mirrored> {
32-
return .init(insertion: insertion.mirrored(), removal: removal.mirrored())
33-
}
34-
}
35-
36-
extension Asymmetric: Equatable where InsertionTransition: Equatable, RemovalTransition: Equatable {}
37-
extension Asymmetric: Hashable where InsertionTransition: Hashable, RemovalTransition: Hashable {}
38-
393
/// A transition that executes only on insertion.
404
public struct OnInsertion<Transition: AtomicTransition>: AtomicTransition {
415
private let transition: Transition

Sources/NavigationTransition/Combined.swift

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,14 @@ extension AnyNavigationTransition {
44
public func combined(with other: Self) -> Self {
55
switch (self.handler, other.handler) {
66
case (.transient(let lhsHandler), .transient(let rhsHandler)):
7+
struct Erased: NavigationTransition {
8+
let handler: AnyNavigationTransition.TransientHandler
9+
10+
@inlinable
11+
func transition(from fromView: TransientView, to toView: TransientView, for operation: TransitionOperation, in container: Container) {
12+
handler(fromView, toView, operation, container)
13+
}
14+
}
715
return AnyNavigationTransition(
816
Combined(Erased(handler: lhsHandler), Erased(handler: rhsHandler))
917
)

Sources/NavigationTransition/Erased.swift

Lines changed: 0 additions & 18 deletions
This file was deleted.

Sources/NavigationTransition/Mirror.swift

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,9 @@ public struct MirrorPush<Transition: MirrorableAtomicTransition>: NavigationTran
1818
}
1919
}
2020

21+
extension MirrorPush: Equatable where Transition: Equatable {}
22+
extension MirrorPush: Hashable where Transition: Hashable {}
23+
2124
/// Used to define a transition that executes on pop, and executes the mirrored version of said transition on push.
2225
public struct MirrorPop<Transition: MirrorableAtomicTransition>: NavigationTransition {
2326
private let transition: Transition
@@ -35,3 +38,6 @@ public struct MirrorPop<Transition: MirrorableAtomicTransition>: NavigationTrans
3538
}
3639
}
3740
}
41+
42+
extension MirrorPop: Equatable where Transition: Equatable {}
43+
extension MirrorPop: Hashable where Transition: Hashable {}

Sources/NavigationTransition/Asymmetric.swift renamed to Sources/NavigationTransition/On.swift

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

3-
/// A composite transition that uses a different transition for push versus pop.
4-
public struct Asymmetric<PushTransition: NavigationTransition, PopTransition: NavigationTransition>: NavigationTransition {
5-
private let push: PushTransition
6-
private let pop: PopTransition
7-
8-
public init(
9-
@AtomicTransitionBuilder push: () -> PushTransition,
10-
@AtomicTransitionBuilder pop: () -> PopTransition
11-
) {
12-
self.push = push()
13-
self.pop = pop()
14-
}
15-
16-
public func transition(
17-
from fromView: TransientView,
18-
to toView: TransientView,
19-
for operation: TransitionOperation,
20-
in container: Container
21-
) {
22-
switch operation {
23-
case .push:
24-
push.transition(from: fromView, to: toView, for: operation, in: container)
25-
case .pop:
26-
pop.transition(from: fromView, to: toView, for: operation, in: container)
27-
}
28-
}
29-
}
30-
31-
extension Asymmetric: Equatable where PushTransition: Equatable, PopTransition: Equatable {}
32-
extension Asymmetric: Hashable where PushTransition: Hashable, PopTransition: Hashable {}
33-
343
/// Used to define a transition that executes only on push.
354
public struct OnPush<Transition: AtomicTransition>: NavigationTransition {
365
private let transition: Transition
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
/// Used to isolate the push portion of a full `NavigationTransition` and execute it on push, ignoring the pop portion.
2+
public struct PickPush<Transition: NavigationTransition>: NavigationTransition {
3+
private let transition: Transition
4+
5+
public init(@NavigationTransitionBuilder transition: () -> Transition) {
6+
self.transition = transition()
7+
}
8+
9+
public func transition(
10+
from fromView: TransientView,
11+
to toView: TransientView,
12+
for operation: TransitionOperation,
13+
in container: Container
14+
) {
15+
switch operation {
16+
case .push:
17+
transition.transition(from: fromView, to: toView, for: operation, in: container)
18+
case .pop:
19+
return
20+
}
21+
}
22+
}
23+
24+
extension PickPush: Equatable where Transition: Equatable {}
25+
extension PickPush: Hashable where Transition: Hashable {}
26+
27+
/// Used to isolate the pop portion of a full `NavigationTransition` and execute it on pop, ignoring the push portion.
28+
public struct PickPop<Transition: NavigationTransition>: NavigationTransition {
29+
private let transition: Transition
30+
31+
public init(@NavigationTransitionBuilder transition: () -> Transition) {
32+
self.transition = transition()
33+
}
34+
35+
public func transition(
36+
from fromView: TransientView,
37+
to toView: TransientView,
38+
for operation: TransitionOperation,
39+
in container: Container
40+
) {
41+
switch operation {
42+
case .push:
43+
return
44+
case .pop:
45+
transition.transition(from: fromView, to: toView, for: operation, in: container)
46+
}
47+
}
48+
}
49+
50+
extension PickPop: Equatable where Transition: Equatable {}
51+
extension PickPop: Hashable where Transition: Hashable {}

Tests/AtomicTransitionTests/AsymmetricTests.swift renamed to Tests/AtomicTransitionTests/OnTests.swift

Lines changed: 0 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,6 @@
11
@_spi(package) import AtomicTransition
22
import TestUtils
33

4-
final class AsymmetricTests: XCTestCase {
5-
func testInsertion() {
6-
let expectation = expectation(description: "Handler called")
7-
let sut = Asymmetric(
8-
insertion: { Spy { expectation.fulfill() } },
9-
removal: { Spy { XCTFail() } }
10-
)
11-
sut.transition(.unimplemented, for: .insertion, in: .unimplemented)
12-
wait(for: [expectation], timeout: 0)
13-
}
14-
15-
func testRemoval() {
16-
let expectation = expectation(description: "Handler called")
17-
let sut = Asymmetric(
18-
insertion: { Spy { XCTFail() } },
19-
removal: { Spy { expectation.fulfill() } }
20-
)
21-
sut.transition(.unimplemented, for: .removal, in: .unimplemented)
22-
wait(for: [expectation], timeout: 0)
23-
}
24-
}
25-
264
final class OnInsertionTests: XCTestCase {
275
func testInsertion() {
286
let expectation = expectation(description: "Handler called")

0 commit comments

Comments
 (0)