1 //  Copyright (c) 2018, Applidium. All rights reserved
2 //  OverlayAnimationCoordinator.swift
3 //  OverlayContainer
4 //
5 //  Created by Gaétan Zanella on 14/11/2018.
6 //
7 
8 import UIKit
9 
10 /// A protocol that provides information about the current overlay translation.
11 public protocol OverlayContainerTransitionContext {
12     /// A Boolean value that indicates whether the user is currently dragging the overlay.
13     var isDragging: Bool { get }
14     /// The overlay velocity.
15     var velocity: CGPoint { get }
16     /// The current translation height.
17     var overlayTranslationHeight: CGFloat { get }
18     /// The notch indexes.
19     var notchIndexes: Range<Int> { get }
20     /// The reachable indexes. Some indexes might be disabled by the `canReachNotchAt` delegate method.
21     var reachableIndexes: [Int] { get }
22     /// Returns the height of the specified notch.
heightnull23     func height(forNotchAt index: Int) -> CGFloat
24 }
25 
26 public extension OverlayContainerTransitionContext {
27 
28     func minimumReachableHeight() -> CGFloat {
29         return reachableIndexes.first.flatMap { height(forNotchAt: $0) } ?? 0
30     }
31 
32     func maximumReachableHeight() -> CGFloat {
33         return reachableIndexes.last.flatMap { height(forNotchAt: $0) } ?? 0
34     }
35 
36     func minimumHeight() -> CGFloat {
37         return notchIndexes.first.flatMap { height(forNotchAt: $0) } ?? 0
38     }
39 
40     func maximumHeight() -> CGFloat {
41         return notchIndexes.last.flatMap { height(forNotchAt: $0) } ?? 0
42     }
43 }
44 
45 
46 /// A protocol that provides information about an in-progress translation.
47 /// Do not adopt this protocol in your own classes. Use the one provided by the `OverlayContainerTransitionCoordinator`.
48 public protocol OverlayContainerTransitionCoordinatorContext: OverlayContainerTransitionContext {
49     /// A Boolean value indicating whether the transition is explicitly animated.
50     var isAnimated: Bool { get }
51     /// A Boolean value indicating whether the transition was cancelled.
52     var isCancelled: Bool { get }
53     /// The overlay height the container expects to reach.
54     var targetTranslationHeight: CGFloat { get }
55 }
56 
57 /// A protocol that provides support for animations associated with an overlay translation.
58 ///
59 /// Do not adopt this procotol in your own classes. Use the one provided by the `OverlayContainerDelegate` to
60 /// add any extra animations alongside the translation animations.
61 public protocol OverlayContainerTransitionCoordinator: OverlayContainerTransitionCoordinatorContext {
62     /// Runs the specified animations at the same time as overlay translation end animations.
63     func animate(alongsideTransition animation: ((OverlayContainerTransitionCoordinatorContext) -> Void)?,
64                  completion: ((OverlayContainerTransitionCoordinatorContext) -> Void)?)
65 }
66 
67 public extension OverlayContainerTransitionCoordinatorContext {
68 
translationProgressnull69     func translationProgress() -> CGFloat {
70         let maximum = maximumReachableHeight()
71         let minimum = minimumReachableHeight()
72         return maximum != minimum ? (targetTranslationHeight - minimum) / (maximum - minimum) : 0
73     }
74 
overallTranslationProgressnull75     func overallTranslationProgress() -> CGFloat {
76         let maximum = maximumHeight()
77         let minimum = minimumHeight()
78         return maximum != minimum ? (targetTranslationHeight - minimum) / (maximum - minimum) : 0
79     }
80 }
81