Browse Source

Refactor PiP code into its own components

master
Daniel Ornelas 7 years ago
parent
commit
0a5f60c637

+ 13
- 5
ios/sdk/sdk.xcodeproj/project.pbxproj View File

@@ -27,7 +27,7 @@
27 27
 		0BCA496C1EC4BBF900B793EE /* jitsi.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 0BCA496B1EC4BBF900B793EE /* jitsi.ttf */; };
28 28
 		0BD906EA1EC0C00300C8C18E /* JitsiMeet.h in Headers */ = {isa = PBXBuildFile; fileRef = 0BD906E81EC0C00300C8C18E /* JitsiMeet.h */; settings = {ATTRIBUTES = (Public, ); }; };
29 29
 		0F65EECE1D95DA94561BB47E /* libPods-JitsiMeet.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 03F2ADC957FF109849B7FCA1 /* libPods-JitsiMeet.a */; };
30
-		C6A3425F204EF76800E062DD /* JitsiMeetWindow.swift in Sources */ = {isa = PBXBuildFile; fileRef = C6A3425C204EF76800E062DD /* JitsiMeetWindow.swift */; };
30
+		C6A3425F204EF76800E062DD /* PiPWindow.swift in Sources */ = {isa = PBXBuildFile; fileRef = C6A3425C204EF76800E062DD /* PiPWindow.swift */; };
31 31
 		C6A34260204EF76800E062DD /* JitsiMeetManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = C6A3425D204EF76800E062DD /* JitsiMeetManager.swift */; };
32 32
 		C6A34261204EF76800E062DD /* DragGestureController.swift in Sources */ = {isa = PBXBuildFile; fileRef = C6A3425E204EF76800E062DD /* DragGestureController.swift */; };
33 33
 		C6A3426D204F1C3300E062DD /* JitsiMeetViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = C6A3426C204F1C3300E062DD /* JitsiMeetViewController.swift */; };
@@ -60,7 +60,7 @@
60 60
 		0BD906E91EC0C00300C8C18E /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
61 61
 		98E09B5C73D9036B4ED252FC /* Pods-JitsiMeet.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-JitsiMeet.debug.xcconfig"; path = "../Pods/Target Support Files/Pods-JitsiMeet/Pods-JitsiMeet.debug.xcconfig"; sourceTree = "<group>"; };
62 62
 		9C77CA3CC919B081F1A52982 /* Pods-JitsiMeet.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-JitsiMeet.release.xcconfig"; path = "../Pods/Target Support Files/Pods-JitsiMeet/Pods-JitsiMeet.release.xcconfig"; sourceTree = "<group>"; };
63
-		C6A3425C204EF76800E062DD /* JitsiMeetWindow.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = JitsiMeetWindow.swift; sourceTree = "<group>"; };
63
+		C6A3425C204EF76800E062DD /* PiPWindow.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PiPWindow.swift; sourceTree = "<group>"; };
64 64
 		C6A3425D204EF76800E062DD /* JitsiMeetManager.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = JitsiMeetManager.swift; sourceTree = "<group>"; };
65 65
 		C6A3425E204EF76800E062DD /* DragGestureController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DragGestureController.swift; sourceTree = "<group>"; };
66 66
 		C6A3426C204F1C3300E062DD /* JitsiMeetViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = JitsiMeetViewController.swift; sourceTree = "<group>"; };
@@ -155,13 +155,21 @@
155 155
 			name = Pods;
156 156
 			sourceTree = "<group>";
157 157
 		};
158
+		C6245F5A2052043F0040BE68 /* PiPWindow */ = {
159
+			isa = PBXGroup;
160
+			children = (
161
+				C6A3425E204EF76800E062DD /* DragGestureController.swift */,
162
+				C6A3425C204EF76800E062DD /* PiPWindow.swift */,
163
+			);
164
+			path = PiPWindow;
165
+			sourceTree = "<group>";
166
+		};
158 167
 		C6A3426B204F127900E062DD /* JitsiMeetManager */ = {
159 168
 			isa = PBXGroup;
160 169
 			children = (
161
-				C6A3425C204EF76800E062DD /* JitsiMeetWindow.swift */,
170
+				C6245F5A2052043F0040BE68 /* PiPWindow */,
162 171
 				C6A3425D204EF76800E062DD /* JitsiMeetManager.swift */,
163 172
 				C6A3426C204F1C3300E062DD /* JitsiMeetViewController.swift */,
164
-				C6A3425E204EF76800E062DD /* DragGestureController.swift */,
165 173
 			);
166 174
 			path = JitsiMeetManager;
167 175
 			sourceTree = "<group>";
@@ -336,7 +344,7 @@
336 344
 				0BCA49601EC4B6C600B793EE /* POSIX.m in Sources */,
337 345
 				0B7C2CFD200F51D60060D076 /* LaunchOptions.m in Sources */,
338 346
 				C6A3426D204F1C3300E062DD /* JitsiMeetViewController.swift in Sources */,
339
-				C6A3425F204EF76800E062DD /* JitsiMeetWindow.swift in Sources */,
347
+				C6A3425F204EF76800E062DD /* PiPWindow.swift in Sources */,
340 348
 				0BCA495F1EC4B6C600B793EE /* AudioMode.m in Sources */,
341 349
 				0B44A0191F902126009D1D64 /* MPVolumeViewManager.m in Sources */,
342 350
 				0BCA49611EC4B6C600B793EE /* Proximity.m in Sources */,

+ 31
- 90
ios/sdk/src/JitsiMeetManager/JitsiMeetManager.swift View File

@@ -2,26 +2,19 @@
2 2
 
3 3
 import Foundation
4 4
 
5
-/// Creates and present a JitsiMeetView inside of an external window that can be dragged
6
-/// when minimized (if PiP mode is enabled)
5
+/// Creates and coordinates the presentation of JitsiMeetViewController inside of an external window
6
+/// which can be resized and dragged with custom PiP mode
7 7
 open class JitsiMeetManager: NSObject {
8 8
     
9
-    /// The Jitsi meet view delegate
10
-    public weak var delegate: JitsiMeetViewDelegate? = nil
11
-    /// Limits the boundries of meet view position on screen when minimized
12
-    public var dragBoundInsets: UIEdgeInsets = UIEdgeInsets(top: 25, left: 5, bottom: 5, right: 5)
13
-    /// Enables PiP mode for this jitsiMeet
14
-    public var allowPiP: Bool = true
15
-    /// The size ratio for jitsiMeetView when in PiP mode
16
-    public var pipSizeRatio: CGFloat = 0.333
17 9
     /// Defines if welcome screen should be on
18
-    public var welcomeScreenEnabled: Bool = false
19
-    
20
-    fileprivate let dragController: DragGestureController = DragGestureController()
10
+    public var welcomeScreenEnabled: Bool = false {
11
+        didSet {
12
+            meetViewController.jitsiMeetView.welcomePageEnabled = welcomeScreenEnabled
13
+        }
14
+    }
21 15
     
22 16
     fileprivate lazy var meetViewController: JitsiMeetViewController = { return self.makeMeetViewController() }()
23
-    fileprivate lazy var meetWindow: JitsiMeetWindow = { return self.makeMeetWindow() }()
24
-    fileprivate var meetingInPiP: Bool = false
17
+    fileprivate lazy var meetWindow: PiPWindow = { return self.makeMeetWindow() }()
25 18
     
26 19
     /// Presents and loads a jitsi meet view
27 20
     ///
@@ -39,29 +32,8 @@ open class JitsiMeetManager: NSObject {
39 32
         meetViewController.jitsiMeetView.loadURLObject(urlObject)
40 33
     }
41 34
     
42
-    // MARK: - Manage PiP switching
43
-    
44
-    // update size animation
45
-    fileprivate func updateMeetViewSize(isPiP: Bool) {
46
-        UIView.animate(withDuration: 0.25) {
47
-            self.meetViewController.view.frame = self.meetViewRect(isPiP: isPiP)
48
-            self.meetViewController.view.setNeedsLayout()
49
-        }
50
-    }
51
-
52
-    private func meetViewRect(isPiP: Bool) -> CGRect {
53
-        guard isPiP else {
54
-            return meetWindow.bounds
55
-        }
56
-        let bounds = meetWindow.bounds
57
-
58
-        // resize to suggested ratio and position to the bottom right
59
-        let adjustedBounds = UIEdgeInsetsInsetRect(bounds, dragBoundInsets)
60
-        let size = CGSize(width: bounds.size.width * pipSizeRatio,
61
-                          height: bounds.size.height * pipSizeRatio)
62
-        let x: CGFloat = adjustedBounds.maxX - size.width
63
-        let y: CGFloat = adjustedBounds.maxY - size.height
64
-        return CGRect(x: x, y: y, width: size.width, height: size.height)
35
+    deinit {
36
+        cleanUp()
65 37
     }
66 38
     
67 39
     // MARK: - helpers
@@ -69,20 +41,20 @@ open class JitsiMeetManager: NSObject {
69 41
     fileprivate func cleanUp() {
70 42
         // TODO: more clean up work on this
71 43
         
72
-        dragController.stopDragListener()
73 44
         meetWindow.isHidden = true
45
+        meetWindow.stopDragGesture()
74 46
     }
75 47
     
76 48
     private func makeMeetViewController() -> JitsiMeetViewController {
77 49
         let vc = JitsiMeetViewController()
78
-        vc.jitsiMeetView.delegate = self
79 50
         vc.jitsiMeetView.welcomePageEnabled = self.welcomeScreenEnabled
80
-        vc.jitsiMeetView.pictureInPictureEnabled = self.allowPiP
51
+        vc.jitsiMeetView.pictureInPictureEnabled = true
52
+        vc.delegate = self
81 53
         return vc
82 54
     }
83 55
     
84
-    private func makeMeetWindow() -> JitsiMeetWindow {
85
-        let window = JitsiMeetWindow(frame: UIScreen.main.bounds)
56
+    private func makeMeetWindow() -> PiPWindow {
57
+        let window = PiPWindow(frame: UIScreen.main.bounds)
86 58
         window.backgroundColor = .clear
87 59
         window.windowLevel = UIWindowLevelStatusBar + 100
88 60
         window.rootViewController = self.meetViewController
@@ -90,57 +62,26 @@ open class JitsiMeetManager: NSObject {
90 62
     }
91 63
 }
92 64
 
93
-extension JitsiMeetManager: JitsiMeetViewDelegate {
94
-    
95
-    public func conferenceWillJoin(_ data: [AnyHashable : Any]!) {
96
-        DispatchQueue.main.async {
97
-            self.delegate?.conferenceWillJoin!(data)
98
-        }
99
-    }
100
-
101
-    public func conferenceJoined(_ data: [AnyHashable : Any]!) {
102
-        DispatchQueue.main.async {
103
-            self.delegate?.conferenceJoined!(data)
65
+extension JitsiMeetManager: JitsiMeetViewControllerDelegate {
66
+    
67
+    open func performPresentationUpdate(to: JitsiMeetPresentationUpdate) {
68
+        switch to {
69
+        case .enterPiP:
70
+            meetWindow.goToPiP()
71
+        case .traitChange:
72
+            // resize to full screen if rotation happens
73
+            if meetWindow.isInPiP {
74
+                meetWindow.goToFullScreen()
75
+            }
104 76
         }
105 77
     }
106 78
     
107
-    public func conferenceWillLeave(_ data: [AnyHashable : Any]!) {
108
-        DispatchQueue.main.async {
109
-            self.delegate?.conferenceWillLeave!(data)
110
-        }
111
-    }
112
-
113
-    public func conferenceLeft(_ data: [AnyHashable : Any]!) {
114
-        DispatchQueue.main.async {
115
-            self.cleanUp()
116
-            
117
-            self.delegate?.conferenceLeft!(data)
118
-        }
79
+    open func meetingStarted() {
80
+        // do something
119 81
     }
120 82
     
121
-    public func conferenceFailed(_ data: [AnyHashable : Any]!) {
122
-        DispatchQueue.main.async {
123
-            self.cleanUp()
124
-
125
-            self.delegate?.conferenceFailed!(data)
126
-        }
127
-    }
128
-    
129
-    public func loadConfigError(_ data: [AnyHashable : Any]!) {
130
-        DispatchQueue.main.async {
131
-            self.delegate?.loadConfigError!(data)
132
-        }
133
-    }
134
-    
135
-    public func enterPicture(inPicture data: [AnyHashable : Any]!) {
136
-        DispatchQueue.main.async {
137
-            self.dragController.startDragListener(inView: self.meetViewController.view)
138
-            self.dragController.insets = self.dragBoundInsets
139
-            
140
-            self.meetingInPiP = true
141
-            self.updateMeetViewSize(isPiP: true)
142
-            
143
-            self.delegate?.enterPicture!(inPicture: data)
144
-        }
83
+    open func meetingEnded(wasFailure: Bool) {
84
+        cleanUp()
145 85
     }
146 86
 }
87
+

+ 70
- 2
ios/sdk/src/JitsiMeetManager/JitsiMeetViewController.swift View File

@@ -1,16 +1,84 @@
1 1
 //  Copyright © 2018 Jitsi. All rights reserved.
2 2
 
3
+public enum JitsiMeetPresentationUpdate {
4
+    
5
+    /// A system traitCollectionChange (usually screen rotation)
6
+    case traitChange
7
+    /// Meeting wants to enter PiP mode
8
+    case enterPiP
9
+}
10
+
11
+public protocol JitsiMeetViewControllerDelegate: class {
12
+    
13
+    /// Notifies a change of the meeting presentation style.
14
+    ///
15
+    /// - Parameter to: The presentation state that will be changed to
16
+    func performPresentationUpdate(to: JitsiMeetPresentationUpdate)
17
+    func meetingStarted()
18
+    func meetingEnded(wasFailure: Bool)
19
+}
3 20
 
4 21
 /// Wrapper ViewController of a JitsiMeetView
5 22
 ///
6
-/// TODO: should consider refactor and move out several logic of the JitsiMeetView to
7
-/// this class
23
+/// Is suggested to override this class and implement some customization
24
+/// on how to handle the JitsiMeetView delegate events
8 25
 open class JitsiMeetViewController: UIViewController {
9 26
     
27
+    open weak var delegate: JitsiMeetViewControllerDelegate?
28
+    
10 29
     private(set) var jitsiMeetView: JitsiMeetView = JitsiMeetView()
11 30
     
12 31
     override open func loadView() {
13 32
         super.loadView()
14 33
         self.view = jitsiMeetView
15 34
     }
35
+    
36
+    open override func viewDidLoad() {
37
+        super.viewDidLoad()
38
+        
39
+        jitsiMeetView.delegate = self
40
+    }
41
+    
42
+    open override func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) {
43
+        delegate?.performPresentationUpdate(to: .traitChange)
44
+    }
45
+}
46
+
47
+extension JitsiMeetViewController: JitsiMeetViewDelegate {
48
+    
49
+    open func conferenceWillJoin(_ data: [AnyHashable : Any]!) {
50
+        // do something
51
+    }
52
+    
53
+    open func conferenceJoined(_ data: [AnyHashable : Any]!) {
54
+        DispatchQueue.main.async {
55
+            self.delegate?.meetingStarted()
56
+        }
57
+    }
58
+    
59
+    open func conferenceWillLeave(_ data: [AnyHashable : Any]!) {
60
+        // do something
61
+    }
62
+    
63
+    open func conferenceLeft(_ data: [AnyHashable : Any]!) {
64
+        DispatchQueue.main.async {
65
+            self.delegate?.meetingEnded(wasFailure: true)
66
+        }
67
+    }
68
+    
69
+    open func conferenceFailed(_ data: [AnyHashable : Any]!) {
70
+        DispatchQueue.main.async {
71
+            self.delegate?.meetingEnded(wasFailure: true)
72
+        }
73
+    }
74
+    
75
+    open func loadConfigError(_ data: [AnyHashable : Any]!) {
76
+        // do something
77
+    }
78
+    
79
+    open func enterPicture(inPicture data: [AnyHashable : Any]!) {
80
+        DispatchQueue.main.async {
81
+            self.delegate?.performPresentationUpdate(to: .enterPiP)
82
+        }
83
+    }
16 84
 }

+ 0
- 45
ios/sdk/src/JitsiMeetManager/JitsiMeetWindow.swift View File

@@ -1,45 +0,0 @@
1
-//  Copyright © 2018 Jitsi. All rights reserved.
2
-
3
-open class JitsiMeetWindow: UIWindow {
4
-    
5
-    /// Help out to bubble up the gesture detection outside of the rootVC frame
6
-    open override func point(inside point: CGPoint, with event: UIEvent?) -> Bool {
7
-        guard let vc = rootViewController else {
8
-            return super.point(inside: point, with: event)
9
-        }
10
-        return vc.view.frame.contains(point)
11
-    }
12
-    
13
-    /// animate in the window
14
-    open func show() {
15
-        if self.isHidden || self.alpha < 1 {
16
-            self.isHidden = false
17
-            self.alpha = 0
18
-            
19
-            UIView.animate(
20
-                withDuration: 0.1,
21
-                delay: 0,
22
-                options: .beginFromCurrentState,
23
-                animations: {
24
-                    self.alpha = 1
25
-            },
26
-                completion: nil)
27
-        }
28
-    }
29
-    
30
-    /// animate out the window
31
-    open func hide() {
32
-        if !self.isHidden || self.alpha > 0 {
33
-            UIView.animate(
34
-                withDuration: 0.1,
35
-                delay: 0,
36
-                options: .beginFromCurrentState,
37
-                animations: {
38
-                    self.alpha = 0
39
-                    self.isHidden = true
40
-            },
41
-                completion: nil)
42
-        }
43
-    }
44
-}
45
-

ios/sdk/src/JitsiMeetManager/DragGestureController.swift → ios/sdk/src/JitsiMeetManager/PiPWindow/DragGestureController.swift View File


+ 105
- 0
ios/sdk/src/JitsiMeetManager/PiPWindow/PiPWindow.swift View File

@@ -0,0 +1,105 @@
1
+//  Copyright © 2018 Jitsi. All rights reserved.
2
+
3
+/// A window that allows its root view controller to be presented
4
+/// in full screen or in a custom Picture in Picture mode
5
+open class PiPWindow: UIWindow {
6
+    
7
+    /// Limits the boundries of root view position on screen when minimized
8
+    public var dragBoundInsets: UIEdgeInsets = UIEdgeInsets(top: 25, left: 5, bottom: 5, right: 5) {
9
+        didSet {
10
+            dragController.insets = dragBoundInsets
11
+        }
12
+    }
13
+    
14
+    /// The size ratio for root view controller view when in PiP mode
15
+    public var pipSizeRatio: CGFloat = 0.333
16
+    
17
+    /// The PiP state of this contents of the window
18
+    private(set) var isInPiP: Bool = false
19
+    
20
+    private let dragController: DragGestureController = DragGestureController()
21
+    
22
+    /// Help out to bubble up the gesture detection outside of the rootVC frame
23
+    open override func point(inside point: CGPoint, with event: UIEvent?) -> Bool {
24
+        guard let vc = rootViewController else {
25
+            return super.point(inside: point, with: event)
26
+        }
27
+        return vc.view.frame.contains(point)
28
+    }
29
+    
30
+    /// animate in the window
31
+    open func show() {
32
+        if self.isHidden || self.alpha < 1 {
33
+            self.isHidden = false
34
+            self.alpha = 0
35
+            
36
+            UIView.animate(
37
+                withDuration: 0.1,
38
+                delay: 0,
39
+                options: .beginFromCurrentState,
40
+                animations: {
41
+                    self.alpha = 1
42
+            },
43
+                completion: nil)
44
+        }
45
+    }
46
+    
47
+    /// animate out the window
48
+    open func hide() {
49
+        if !self.isHidden || self.alpha > 0 {
50
+            UIView.animate(
51
+                withDuration: 0.1,
52
+                delay: 0,
53
+                options: .beginFromCurrentState,
54
+                animations: {
55
+                    self.alpha = 0
56
+                    self.isHidden = true
57
+            },
58
+                completion: nil)
59
+        }
60
+    }
61
+    
62
+    /// Resize the root view to PiP mode
63
+    open func goToPiP() {
64
+        guard let view = rootViewController?.view else { return }
65
+        isInPiP = true
66
+        animateRootViewChange()
67
+        dragController.startDragListener(inView: view)
68
+        dragController.insets = dragBoundInsets
69
+    }
70
+    
71
+    /// Resize the root view to full screen
72
+    open func goToFullScreen() {
73
+        isInPiP = false
74
+        animateRootViewChange()
75
+        dragController.stopDragListener()
76
+    }
77
+    
78
+    /// Stop the dragging gesture of the root view
79
+    public func stopDragGesture() {
80
+        dragController.stopDragListener()
81
+    }
82
+    
83
+    // MARK: - Manage presentation switching
84
+    
85
+    private func animateRootViewChange() {
86
+        UIView.animate(withDuration: 0.25) {
87
+            self.rootViewController?.view.frame = self.changeRootViewRect()
88
+            self.rootViewController?.view.setNeedsLayout()
89
+        }
90
+    }
91
+    
92
+    private func changeRootViewRect() -> CGRect {
93
+        guard isInPiP else {
94
+            return self.bounds
95
+        }
96
+        
97
+        // resize to suggested ratio and position to the bottom right
98
+        let adjustedBounds = UIEdgeInsetsInsetRect(self.bounds, dragBoundInsets)
99
+        let size = CGSize(width: bounds.size.width * pipSizeRatio,
100
+                          height: bounds.size.height * pipSizeRatio)
101
+        let x: CGFloat = adjustedBounds.maxX - size.width
102
+        let y: CGFloat = adjustedBounds.maxY - size.height
103
+        return CGRect(x: x, y: y, width: size.width, height: size.height)
104
+    }
105
+}

Loading…
Cancel
Save