Addressing feedback from PR
This commit is contained in:
parent
8428dd95c2
commit
5858859838
|
@ -56,13 +56,13 @@
|
|||
</dict>
|
||||
</dict>
|
||||
<key>NSCalendarsUsageDescription</key>
|
||||
<string>Displays the user's meetings in the app.</string>
|
||||
<string>See your scheduled conferences in the app.</string>
|
||||
<key>NSCameraUsageDescription</key>
|
||||
<string>Participate in conferences with video.</string>
|
||||
<key>NSLocationWhenInUseUsageDescription</key>
|
||||
<string></string>
|
||||
<key>NSMicrophoneUsageDescription</key>
|
||||
<string>Participate in conferences with audio.</string>
|
||||
<string>Participate in conferences with voice.</string>
|
||||
<key>UIBackgroundModes</key>
|
||||
<array>
|
||||
<string>audio</string>
|
||||
|
|
|
@ -35,7 +35,7 @@
|
|||
|
||||
/* Begin PBXFileReference section */
|
||||
C6A34247204DF18000E062DD /* WebRTC.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = WebRTC.framework; path = "../../node_modules/react-native-webrtc/ios/WebRTC.framework"; sourceTree = "<group>"; };
|
||||
C6F99C37204DE6BE0001F710 /* PiPApp.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = PiPApp.app; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
C6F99C37204DE6BE0001F710 /* example-pip-app.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = example-pip-app.app; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
C6F99C3A204DE6BE0001F710 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
|
||||
C6F99C3C204DE6BE0001F710 /* ViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewController.swift; sourceTree = "<group>"; };
|
||||
C6F99C3F204DE6BE0001F710 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = "<group>"; };
|
||||
|
@ -70,7 +70,7 @@
|
|||
C6F99C38204DE6BE0001F710 /* Products */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
C6F99C37204DE6BE0001F710 /* PiPApp.app */,
|
||||
C6F99C37204DE6BE0001F710 /* example-pip-app.app */,
|
||||
);
|
||||
name = Products;
|
||||
sourceTree = "<group>";
|
||||
|
@ -100,9 +100,9 @@
|
|||
/* End PBXGroup section */
|
||||
|
||||
/* Begin PBXNativeTarget section */
|
||||
C6F99C36204DE6BE0001F710 /* PiPApp */ = {
|
||||
C6F99C36204DE6BE0001F710 /* example-pip-app */ = {
|
||||
isa = PBXNativeTarget;
|
||||
buildConfigurationList = C6F99C49204DE6BE0001F710 /* Build configuration list for PBXNativeTarget "PiPApp" */;
|
||||
buildConfigurationList = C6F99C49204DE6BE0001F710 /* Build configuration list for PBXNativeTarget "example-pip-app" */;
|
||||
buildPhases = (
|
||||
C6A3424A204DF91D00E062DD /* Run Adjust ATS for loading JS bundle */,
|
||||
C6F99C62204DEFFE0001F710 /* Run React Packager */,
|
||||
|
@ -116,9 +116,9 @@
|
|||
);
|
||||
dependencies = (
|
||||
);
|
||||
name = PiPApp;
|
||||
productName = ExampleAppUsingJitsiWithPiP;
|
||||
productReference = C6F99C37204DE6BE0001F710 /* PiPApp.app */;
|
||||
name = example-pip-app;
|
||||
productName = example-pip-app;
|
||||
productReference = C6F99C37204DE6BE0001F710 /* example-pip-app.app */;
|
||||
productType = "com.apple.product-type.application";
|
||||
};
|
||||
/* End PBXNativeTarget section */
|
||||
|
@ -142,7 +142,7 @@
|
|||
};
|
||||
};
|
||||
};
|
||||
buildConfigurationList = C6F99C32204DE6BE0001F710 /* Build configuration list for PBXProject "PiPApp" */;
|
||||
buildConfigurationList = C6F99C32204DE6BE0001F710 /* Build configuration list for PBXProject "example-pip-app" */;
|
||||
compatibilityVersion = "Xcode 8.0";
|
||||
developmentRegion = en;
|
||||
hasScannedForEncodings = 0;
|
||||
|
@ -155,7 +155,7 @@
|
|||
projectDirPath = "";
|
||||
projectRoot = "";
|
||||
targets = (
|
||||
C6F99C36204DE6BE0001F710 /* PiPApp */,
|
||||
C6F99C36204DE6BE0001F710 /* example-pip-app */,
|
||||
);
|
||||
};
|
||||
/* End PBXProject section */
|
||||
|
@ -366,7 +366,7 @@
|
|||
INFOPLIST_FILE = src/Info.plist;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 10.3;
|
||||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
|
||||
PRODUCT_BUNDLE_IDENTIFIER = com.jitsi.PiPApp;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = com.jitsi.example-pip-app;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SWIFT_VERSION = 4.0;
|
||||
TARGETED_DEVICE_FAMILY = "1,2";
|
||||
|
@ -382,7 +382,7 @@
|
|||
INFOPLIST_FILE = src/Info.plist;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 10.3;
|
||||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
|
||||
PRODUCT_BUNDLE_IDENTIFIER = com.jitsi.PiPApp;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = com.jitsi.example-pip-app;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SWIFT_VERSION = 4.0;
|
||||
TARGETED_DEVICE_FAMILY = "1,2";
|
||||
|
@ -392,7 +392,7 @@
|
|||
/* End XCBuildConfiguration section */
|
||||
|
||||
/* Begin XCConfigurationList section */
|
||||
C6F99C32204DE6BE0001F710 /* Build configuration list for PBXProject "PiPApp" */ = {
|
||||
C6F99C32204DE6BE0001F710 /* Build configuration list for PBXProject "example-pip-app" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
C6F99C47204DE6BE0001F710 /* Debug */,
|
||||
|
@ -401,7 +401,7 @@
|
|||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Release;
|
||||
};
|
||||
C6F99C49204DE6BE0001F710 /* Build configuration list for PBXNativeTarget "PiPApp" */ = {
|
||||
C6F99C49204DE6BE0001F710 /* Build configuration list for PBXNativeTarget "example-pip-app" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
C6F99C4A204DE6BE0001F710 /* Debug */,
|
|
@ -1,10 +1,18 @@
|
|||
//
|
||||
// AppDelegate.swift
|
||||
// ExampleAppUsingJitsiWithPiP
|
||||
//
|
||||
// Created by Daniel Ornelas on 3/5/18.
|
||||
// Copyright © 2018 Atlassian Inc. All rights reserved.
|
||||
//
|
||||
/*
|
||||
* Copyright @ 2017-present Atlassian Pty Ltd
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import JitsiMeet
|
||||
|
||||
|
@ -30,6 +38,4 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
|
|||
func application(_ application: UIApplication, open url: URL, sourceApplication: String?, annotation: Any) -> Bool {
|
||||
return JitsiMeetView.application(application, open: url, sourceApplication: sourceApplication, annotation: annotation)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -13,17 +13,17 @@
|
|||
<!--View Controller-->
|
||||
<scene sceneID="tne-QT-ifu">
|
||||
<objects>
|
||||
<viewController id="BYZ-38-t0r" customClass="ViewController" customModule="PiPApp" customModuleProvider="target" sceneMemberID="viewController">
|
||||
<viewController id="BYZ-38-t0r" customClass="ViewController" customModule="example-pip-app" customModuleProvider="target" sceneMemberID="viewController">
|
||||
<view key="view" contentMode="scaleToFill" id="8bC-Xf-vdC">
|
||||
<rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
<subviews>
|
||||
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="QxY-C8-fwD">
|
||||
<rect key="frame" x="144.5" y="324.5" width="86" height="38"/>
|
||||
<rect key="frame" x="116" y="324.5" width="143" height="38"/>
|
||||
<fontDescription key="fontDescription" type="system" pointSize="21"/>
|
||||
<state key="normal" title="Start Jitsi"/>
|
||||
<state key="normal" title="Open Jitsi Meet"/>
|
||||
<connections>
|
||||
<action selector="startMeetingWithSender:" destination="BYZ-38-t0r" eventType="touchUpInside" id="79C-XR-05w"/>
|
||||
<action selector="openJitsiMeetWithSender:" destination="BYZ-38-t0r" eventType="touchUpInside" id="79C-XR-05w"/>
|
||||
</connections>
|
||||
</button>
|
||||
</subviews>
|
||||
|
|
|
@ -1,10 +1,18 @@
|
|||
//
|
||||
// ViewController.swift
|
||||
// ExampleAppUsingJitsiWithPiP
|
||||
//
|
||||
// Created by Daniel Ornelas on 3/5/18.
|
||||
// Copyright © 2018 Atlassian Inc. All rights reserved.
|
||||
//
|
||||
/*
|
||||
* Copyright @ 2017-present Atlassian Pty Ltd
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import UIKit
|
||||
import JitsiMeet
|
||||
|
@ -13,7 +21,7 @@ class ViewController: UIViewController {
|
|||
|
||||
@IBOutlet weak var videoButton: UIButton?
|
||||
|
||||
private var jitsiMeetManager: JitsiMeetManager?
|
||||
private var jitsiMeetCoordinator: JitsiMeetPresentationCoordinator?
|
||||
|
||||
override func viewDidLoad() {
|
||||
super.viewDidLoad()
|
||||
|
@ -21,12 +29,11 @@ class ViewController: UIViewController {
|
|||
|
||||
// MARK: - Actions
|
||||
|
||||
@IBAction func startMeeting(sender: Any?) {
|
||||
//let url = URL(string: "")
|
||||
self.jitsiMeetManager = JitsiMeetManager()
|
||||
jitsiMeetManager?.welcomeScreenEnabled = true
|
||||
jitsiMeetManager?.load(withUrl: nil)
|
||||
@IBAction func openJitsiMeet(sender: Any?) {
|
||||
let jitsiMeetCoordinator = JitsiMeetPresentationCoordinator()
|
||||
self.jitsiMeetCoordinator = jitsiMeetCoordinator
|
||||
jitsiMeetCoordinator.jitsiMeetView().welcomePageEnabled = true
|
||||
jitsiMeetCoordinator.jitsiMeetView().load(nil)
|
||||
jitsiMeetCoordinator.show()
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
<Workspace
|
||||
version = "1.0">
|
||||
<FileRef
|
||||
location = "group:example-pip-app/PiPApp.xcodeproj">
|
||||
location = "group:example-pip-app/example-pip-app.xcodeproj">
|
||||
</FileRef>
|
||||
<FileRef
|
||||
location = "group:app/app.xcodeproj">
|
||||
|
|
|
@ -30,7 +30,7 @@
|
|||
C6245F5D2053091D0040BE68 /* image-resize@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = C6245F5B2053091D0040BE68 /* image-resize@2x.png */; };
|
||||
C6245F5E2053091D0040BE68 /* image-resize@3x.png in Resources */ = {isa = PBXBuildFile; fileRef = C6245F5C2053091D0040BE68 /* image-resize@3x.png */; };
|
||||
C6A3425F204EF76800E062DD /* PiPWindow.swift in Sources */ = {isa = PBXBuildFile; fileRef = C6A3425C204EF76800E062DD /* PiPWindow.swift */; };
|
||||
C6A34260204EF76800E062DD /* JitsiMeetManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = C6A3425D204EF76800E062DD /* JitsiMeetManager.swift */; };
|
||||
C6A34260204EF76800E062DD /* JitsiMeetPresentationCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = C6A3425D204EF76800E062DD /* JitsiMeetPresentationCoordinator.swift */; };
|
||||
C6A34261204EF76800E062DD /* DragGestureController.swift in Sources */ = {isa = PBXBuildFile; fileRef = C6A3425E204EF76800E062DD /* DragGestureController.swift */; };
|
||||
C6A3426D204F1C3300E062DD /* JitsiMeetViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = C6A3426C204F1C3300E062DD /* JitsiMeetViewController.swift */; };
|
||||
C6F99C15204DB63E0001F710 /* JitsiMeetView+Private.h in Headers */ = {isa = PBXBuildFile; fileRef = C6F99C13204DB63D0001F710 /* JitsiMeetView+Private.h */; };
|
||||
|
@ -62,10 +62,10 @@
|
|||
0BD906E91EC0C00300C8C18E /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
|
||||
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>"; };
|
||||
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>"; };
|
||||
C6245F5B2053091D0040BE68 /* image-resize@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "image-resize@2x.png"; sourceTree = "<group>"; };
|
||||
C6245F5C2053091D0040BE68 /* image-resize@3x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "image-resize@3x.png"; sourceTree = "<group>"; };
|
||||
C6245F5B2053091D0040BE68 /* image-resize@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = "image-resize@2x.png"; path = "src/picture-in-picture/image-resize@2x.png"; sourceTree = "<group>"; };
|
||||
C6245F5C2053091D0040BE68 /* image-resize@3x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = "image-resize@3x.png"; path = "src/picture-in-picture/image-resize@3x.png"; sourceTree = "<group>"; };
|
||||
C6A3425C204EF76800E062DD /* PiPWindow.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PiPWindow.swift; sourceTree = "<group>"; };
|
||||
C6A3425D204EF76800E062DD /* JitsiMeetManager.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = JitsiMeetManager.swift; sourceTree = "<group>"; };
|
||||
C6A3425D204EF76800E062DD /* JitsiMeetPresentationCoordinator.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = JitsiMeetPresentationCoordinator.swift; sourceTree = "<group>"; };
|
||||
C6A3425E204EF76800E062DD /* DragGestureController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DragGestureController.swift; sourceTree = "<group>"; };
|
||||
C6A3426C204F1C3300E062DD /* JitsiMeetViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = JitsiMeetViewController.swift; sourceTree = "<group>"; };
|
||||
C6F99C13204DB63D0001F710 /* JitsiMeetView+Private.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "JitsiMeetView+Private.h"; sourceTree = "<group>"; };
|
||||
|
@ -119,7 +119,7 @@
|
|||
0BD906E71EC0C00300C8C18E /* src */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
C6A3426B204F127900E062DD /* JitsiMeetManager */,
|
||||
C6A3426B204F127900E062DD /* picture-in-picture */,
|
||||
0BCA495C1EC4B6C600B793EE /* AudioMode.m */,
|
||||
0BB9AD7C1F60356D001C08DB /* AppInfo.m */,
|
||||
0BB9AD7A1F5EC8F4001C08DB /* CallKit.m */,
|
||||
|
@ -161,23 +161,15 @@
|
|||
name = Pods;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
C6245F5A2052043F0040BE68 /* PiPWindow */ = {
|
||||
C6A3426B204F127900E062DD /* picture-in-picture */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
C6A3425E204EF76800E062DD /* DragGestureController.swift */,
|
||||
C6A3425D204EF76800E062DD /* JitsiMeetPresentationCoordinator.swift */,
|
||||
C6A3426C204F1C3300E062DD /* JitsiMeetViewController.swift */,
|
||||
C6A3425C204EF76800E062DD /* PiPWindow.swift */,
|
||||
);
|
||||
path = PiPWindow;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
C6A3426B204F127900E062DD /* JitsiMeetManager */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
C6245F5A2052043F0040BE68 /* PiPWindow */,
|
||||
C6A3425D204EF76800E062DD /* JitsiMeetManager.swift */,
|
||||
C6A3426C204F1C3300E062DD /* JitsiMeetViewController.swift */,
|
||||
);
|
||||
path = JitsiMeetManager;
|
||||
path = "picture-in-picture";
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
/* End PBXGroup section */
|
||||
|
@ -345,7 +337,7 @@
|
|||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
0BB9AD7B1F5EC8F4001C08DB /* CallKit.m in Sources */,
|
||||
C6A34260204EF76800E062DD /* JitsiMeetManager.swift in Sources */,
|
||||
C6A34260204EF76800E062DD /* JitsiMeetPresentationCoordinator.swift in Sources */,
|
||||
0BB9AD7D1F60356D001C08DB /* AppInfo.m in Sources */,
|
||||
0B93EF7F1EC9DDCD0030D24D /* RCTBridgeWrapper.m in Sources */,
|
||||
0BA13D311EE83FF8007BEF7F /* ExternalAPI.m in Sources */,
|
||||
|
|
|
@ -1,101 +0,0 @@
|
|||
// Copyright © 2018 Jitsi. All rights reserved.
|
||||
|
||||
import Foundation
|
||||
|
||||
/// Creates and coordinates the presentation of JitsiMeetViewController inside of an external window
|
||||
/// which can be resized and dragged with custom PiP mode
|
||||
open class JitsiMeetManager: NSObject {
|
||||
|
||||
/// Defines if welcome screen should be on
|
||||
public var welcomeScreenEnabled: Bool = false {
|
||||
didSet {
|
||||
meetViewController?.jitsiMeetView.welcomePageEnabled = welcomeScreenEnabled
|
||||
}
|
||||
}
|
||||
|
||||
private(set) var meetViewController: JitsiMeetViewController?
|
||||
private(set) var meetWindow: PiPWindow?
|
||||
|
||||
override public init() {
|
||||
super.init()
|
||||
self.meetViewController = makeMeetViewController()
|
||||
self.meetWindow = makeMeetWindow()
|
||||
}
|
||||
|
||||
public init(meetViewController: JitsiMeetViewController? = nil, meetWindow: PiPWindow? = nil) {
|
||||
super.init()
|
||||
self.meetViewController = meetViewController ?? makeMeetViewController()
|
||||
self.meetWindow = meetWindow ?? makeMeetWindow()
|
||||
}
|
||||
|
||||
/// Presents and loads a jitsi meet view
|
||||
///
|
||||
/// - Parameter url: The url of the presentation
|
||||
public func load(withUrl url: URL?) {
|
||||
meetWindow?.show()
|
||||
meetViewController?.jitsiMeetView.load(url)
|
||||
}
|
||||
|
||||
/// Presents and loads a jitsi meet view with configuration
|
||||
///
|
||||
/// - Parameter urlObject: A dictionary of keys to be used for configuration
|
||||
public func load(withUrlObject urlObject: [AnyHashable : Any]?) {
|
||||
meetWindow?.show()
|
||||
meetViewController?.jitsiMeetView.loadURLObject(urlObject)
|
||||
}
|
||||
|
||||
deinit {
|
||||
cleanUp()
|
||||
}
|
||||
|
||||
// MARK: - helpers
|
||||
|
||||
fileprivate func cleanUp() {
|
||||
// TODO: more clean up work on this
|
||||
|
||||
meetWindow?.isHidden = true
|
||||
meetWindow?.stopDragGesture()
|
||||
}
|
||||
|
||||
private func makeMeetViewController() -> JitsiMeetViewController {
|
||||
let vc = JitsiMeetViewController()
|
||||
vc.jitsiMeetView.welcomePageEnabled = self.welcomeScreenEnabled
|
||||
vc.jitsiMeetView.pictureInPictureEnabled = true
|
||||
vc.delegate = self
|
||||
return vc
|
||||
}
|
||||
|
||||
private func makeMeetWindow() -> PiPWindow {
|
||||
let window = PiPWindow(frame: UIScreen.main.bounds)
|
||||
window.backgroundColor = .clear
|
||||
window.windowLevel = UIWindowLevelStatusBar + 100
|
||||
window.rootViewController = self.meetViewController
|
||||
return window
|
||||
}
|
||||
}
|
||||
|
||||
extension JitsiMeetManager: JitsiMeetViewControllerDelegate {
|
||||
|
||||
open func performPresentationUpdate(to: JitsiMeetPresentationUpdate) {
|
||||
guard let meetWindow = self.meetWindow else { return }
|
||||
|
||||
switch to {
|
||||
case .enterPiP:
|
||||
meetWindow.goToPiP()
|
||||
case .traitChange:
|
||||
// resize to full screen if rotation happens
|
||||
if meetWindow.isInPiP {
|
||||
meetWindow.goToFullScreen()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
open func meetingStarted() {
|
||||
// do something
|
||||
}
|
||||
|
||||
open func meetingEnded(wasFailure: Bool) {
|
||||
cleanUp()
|
||||
}
|
||||
}
|
||||
|
|
@ -1,4 +1,18 @@
|
|||
// Copyright © 2018 Jitsi. All rights reserved.
|
||||
/*
|
||||
* Copyright @ 2017-present Atlassian Pty Ltd
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
final class DragGestureController {
|
||||
|
||||
|
@ -7,7 +21,8 @@ final class DragGestureController {
|
|||
private var frameBeforeDragging: CGRect = CGRect.zero
|
||||
private weak var view: UIView?
|
||||
private lazy var panGesture: UIPanGestureRecognizer = {
|
||||
return UIPanGestureRecognizer(target: self, action: #selector(handlePan(gesture:)))
|
||||
return UIPanGestureRecognizer(target: self,
|
||||
action: #selector(handlePan(gesture:)))
|
||||
}()
|
||||
|
||||
func startDragListener(inView view: UIView) {
|
||||
|
@ -47,7 +62,8 @@ final class DragGestureController {
|
|||
let distanceMagnitude = magnitude(vector: distance)
|
||||
let velocityMagnitude = magnitude(vector: velocity)
|
||||
let animationDuration = 0.5
|
||||
let initialSpringVelocity = velocityMagnitude / distanceMagnitude / CGFloat(animationDuration)
|
||||
let initialSpringVelocity =
|
||||
velocityMagnitude / distanceMagnitude / CGFloat(animationDuration)
|
||||
|
||||
frame.origin = CGPoint(x: finalPos.x, y: finalPos.y)
|
||||
|
||||
|
@ -91,8 +107,14 @@ final class DragGestureController {
|
|||
goUp = location.y < bounds.midY
|
||||
}
|
||||
|
||||
let finalPosX: CGFloat = goLeft ? adjustedBounds.origin.x : bounds.size.width - insets.right - currentSize.width
|
||||
let finalPosY: CGFloat = goUp ? adjustedBounds.origin.y : bounds.size.height - insets.bottom - currentSize.height
|
||||
let finalPosX: CGFloat =
|
||||
goLeft
|
||||
? adjustedBounds.origin.x
|
||||
: bounds.size.width - insets.right - currentSize.width
|
||||
let finalPosY: CGFloat =
|
||||
goUp
|
||||
? adjustedBounds.origin.y
|
||||
: bounds.size.height - insets.bottom - currentSize.height
|
||||
|
||||
return CGPoint(x: finalPosX, y: finalPosY)
|
||||
}
|
||||
|
@ -101,4 +123,3 @@ final class DragGestureController {
|
|||
return sqrt(pow(vector.x, 2) + pow(vector.y, 2))
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,97 @@
|
|||
/*
|
||||
* Copyright @ 2017-present Atlassian Pty Ltd
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import Foundation
|
||||
|
||||
/// Coordinates the presentation of JitsiMeetViewController inside of
|
||||
/// an external window that can be resized and dragged with custom PiP mode
|
||||
open class JitsiMeetPresentationCoordinator: NSObject {
|
||||
|
||||
fileprivate let meetViewController: JitsiMeetViewController
|
||||
fileprivate let meetWindow: PiPWindow
|
||||
|
||||
public init(meetViewController: JitsiMeetViewController? = nil,
|
||||
meetWindow: PiPWindow? = nil) {
|
||||
self.meetViewController = meetViewController ?? JitsiMeetViewController()
|
||||
self.meetWindow = meetWindow ?? PiPWindow(frame: UIScreen.main.bounds)
|
||||
|
||||
super.init()
|
||||
|
||||
configureMeetWindow()
|
||||
configureMeetViewController()
|
||||
}
|
||||
|
||||
public func jitsiMeetView() -> JitsiMeetView {
|
||||
return meetViewController.jitsiMeetView
|
||||
}
|
||||
|
||||
public func show() {
|
||||
meetWindow.show()
|
||||
}
|
||||
|
||||
public func hide() {
|
||||
meetWindow.hide()
|
||||
}
|
||||
|
||||
deinit {
|
||||
cleanUp()
|
||||
}
|
||||
|
||||
// MARK: - helpers
|
||||
|
||||
fileprivate func cleanUp() {
|
||||
// TODO: more clean up work on this
|
||||
|
||||
meetWindow.isHidden = true
|
||||
meetWindow.stopDragGesture()
|
||||
}
|
||||
|
||||
private func configureMeetViewController() {
|
||||
meetViewController.jitsiMeetView.pictureInPictureEnabled = true
|
||||
meetViewController.delegate = self
|
||||
}
|
||||
|
||||
private func configureMeetWindow() {
|
||||
meetWindow.backgroundColor = .clear
|
||||
meetWindow.windowLevel = UIWindowLevelStatusBar + 100
|
||||
meetWindow.rootViewController = self.meetViewController
|
||||
}
|
||||
}
|
||||
|
||||
extension JitsiMeetPresentationCoordinator: JitsiMeetViewControllerDelegate {
|
||||
|
||||
open func performPresentationUpdate(to: JitsiMeetPresentationUpdate) {
|
||||
switch to {
|
||||
case .enterPictureInPicture:
|
||||
meetWindow.enterPictureInPicture()
|
||||
case .traitChange:
|
||||
// resize to full screen if rotation happens
|
||||
if meetWindow.isInPiP {
|
||||
meetWindow.exitPictureInPicture()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
open func conferenceStarted() {
|
||||
if meetWindow.isHidden {
|
||||
meetWindow.show()
|
||||
}
|
||||
}
|
||||
|
||||
open func conferenceEnded(didFail: Bool) {
|
||||
cleanUp()
|
||||
}
|
||||
}
|
|
@ -1,21 +1,42 @@
|
|||
// Copyright © 2018 Jitsi. All rights reserved.
|
||||
/*
|
||||
* Copyright @ 2017-present Atlassian Pty Ltd
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
public enum JitsiMeetPresentationUpdate {
|
||||
|
||||
/// The conference wants to enter Picture-in-Picture
|
||||
case enterPictureInPicture
|
||||
|
||||
/// A system traitCollectionChange (usually screen rotation)
|
||||
case traitChange
|
||||
/// Meeting wants to enter PiP mode
|
||||
case enterPiP
|
||||
}
|
||||
|
||||
public protocol JitsiMeetViewControllerDelegate: class {
|
||||
|
||||
/// Notifies a change of the meeting presentation style.
|
||||
/// Notifies a change of the conference presentation style.
|
||||
///
|
||||
/// - Parameter to: The presentation state that will be changed to
|
||||
func performPresentationUpdate(to: JitsiMeetPresentationUpdate)
|
||||
func meetingStarted()
|
||||
func meetingEnded(wasFailure: Bool)
|
||||
|
||||
/// The conference started
|
||||
func conferenceStarted()
|
||||
|
||||
/// The conference ended
|
||||
///
|
||||
/// - Parameter didFail: The reason of ending the conference
|
||||
func conferenceEnded(didFail: Bool)
|
||||
}
|
||||
|
||||
/// Wrapper ViewController of a JitsiMeetView
|
||||
|
@ -52,7 +73,7 @@ extension JitsiMeetViewController: JitsiMeetViewDelegate {
|
|||
|
||||
open func conferenceJoined(_ data: [AnyHashable : Any]!) {
|
||||
DispatchQueue.main.async {
|
||||
self.delegate?.meetingStarted()
|
||||
self.delegate?.conferenceStarted()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -62,13 +83,13 @@ extension JitsiMeetViewController: JitsiMeetViewDelegate {
|
|||
|
||||
open func conferenceLeft(_ data: [AnyHashable : Any]!) {
|
||||
DispatchQueue.main.async {
|
||||
self.delegate?.meetingEnded(wasFailure: true)
|
||||
self.delegate?.conferenceEnded(didFail: true)
|
||||
}
|
||||
}
|
||||
|
||||
open func conferenceFailed(_ data: [AnyHashable : Any]!) {
|
||||
DispatchQueue.main.async {
|
||||
self.delegate?.meetingEnded(wasFailure: true)
|
||||
self.delegate?.conferenceEnded(didFail: true)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -78,7 +99,7 @@ extension JitsiMeetViewController: JitsiMeetViewDelegate {
|
|||
|
||||
open func enterPicture(inPicture data: [AnyHashable : Any]!) {
|
||||
DispatchQueue.main.async {
|
||||
self.delegate?.performPresentationUpdate(to: .enterPiP)
|
||||
self.delegate?.performPresentationUpdate(to: .enterPictureInPicture)
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,11 +1,28 @@
|
|||
// Copyright © 2018 Jitsi. All rights reserved.
|
||||
/*
|
||||
* Copyright @ 2017-present Atlassian Pty Ltd
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/// A window that allows its root view controller to be presented
|
||||
/// in full screen or in a custom Picture in Picture mode
|
||||
open class PiPWindow: UIWindow {
|
||||
|
||||
/// Limits the boundries of root view position on screen when minimized
|
||||
public var dragBoundInsets: UIEdgeInsets = UIEdgeInsets(top: 25, left: 5, bottom: 5, right: 5) {
|
||||
public var dragBoundInsets: UIEdgeInsets = UIEdgeInsets(top: 25,
|
||||
left: 5,
|
||||
bottom: 5,
|
||||
right: 5) {
|
||||
didSet {
|
||||
dragController.insets = dragBoundInsets
|
||||
}
|
||||
|
@ -24,7 +41,8 @@ open class PiPWindow: UIWindow {
|
|||
private var exitPiPButton: UIButton?
|
||||
|
||||
/// Help out to bubble up the gesture detection outside of the rootVC frame
|
||||
open override func point(inside point: CGPoint, with event: UIEvent?) -> Bool {
|
||||
open override func point(inside point: CGPoint,
|
||||
with event: UIEvent?) -> Bool {
|
||||
guard let vc = rootViewController else {
|
||||
return super.point(inside: point, with: event)
|
||||
}
|
||||
|
@ -36,35 +54,24 @@ open class PiPWindow: UIWindow {
|
|||
if self.isHidden || self.alpha < 1 {
|
||||
self.isHidden = false
|
||||
self.alpha = 0
|
||||
|
||||
UIView.animate(
|
||||
withDuration: 0.1,
|
||||
delay: 0,
|
||||
options: .beginFromCurrentState,
|
||||
animations: {
|
||||
animateTransition {
|
||||
self.alpha = 1
|
||||
},
|
||||
completion: nil)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// animate out the window
|
||||
open func hide() {
|
||||
if !self.isHidden || self.alpha > 0 {
|
||||
UIView.animate(
|
||||
withDuration: 0.1,
|
||||
delay: 0,
|
||||
options: .beginFromCurrentState,
|
||||
animations: {
|
||||
animateTransition {
|
||||
self.alpha = 0
|
||||
self.isHidden = true
|
||||
},
|
||||
completion: nil)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Resize the root view to PiP mode
|
||||
open func goToPiP() {
|
||||
open func enterPictureInPicture() {
|
||||
guard let view = rootViewController?.view else { return }
|
||||
isInPiP = true
|
||||
animateRootViewChange()
|
||||
|
@ -72,13 +79,15 @@ open class PiPWindow: UIWindow {
|
|||
dragController.insets = dragBoundInsets
|
||||
|
||||
// add single tap gesture recognition for displaying exit PiP UI
|
||||
let tapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(toggleExitPiP))
|
||||
let exitSelector = #selector(toggleExitPiP)
|
||||
let tapGestureRecognizer = UITapGestureRecognizer(target: self,
|
||||
action: exitSelector)
|
||||
self.tapGestureRecognizer = tapGestureRecognizer
|
||||
view.addGestureRecognizer(tapGestureRecognizer)
|
||||
}
|
||||
|
||||
/// Resize the root view to full screen
|
||||
open func goToFullScreen() {
|
||||
open func exitPictureInPicture() {
|
||||
isInPiP = false
|
||||
animateRootViewChange()
|
||||
dragController.stopDragListener()
|
||||
|
@ -88,7 +97,8 @@ open class PiPWindow: UIWindow {
|
|||
exitPiPButton = nil
|
||||
|
||||
// remove gesture
|
||||
tapGestureRecognizer?.removeTarget(self, action: #selector(toggleExitPiP))
|
||||
let exitSelector = #selector(toggleExitPiP)
|
||||
tapGestureRecognizer?.removeTarget(self, action: exitSelector)
|
||||
tapGestureRecognizer = nil
|
||||
}
|
||||
|
||||
|
@ -98,8 +108,11 @@ open class PiPWindow: UIWindow {
|
|||
}
|
||||
|
||||
/// Customize the presentation of exit pip button
|
||||
open func configureExitPiPButton(target: Any, action: Selector) -> UIButton {
|
||||
let buttonImage = UIImage.init(named: "image-resize", in: Bundle(for: type(of: self)), compatibleWith: nil)
|
||||
open func configureExitPiPButton(target: Any,
|
||||
action: Selector) -> UIButton {
|
||||
let buttonImage = UIImage.init(named: "image-resize",
|
||||
in: Bundle(for: type(of: self)),
|
||||
compatibleWith: nil)
|
||||
let button = UIButton(type: .custom)
|
||||
let size: CGSize = CGSize(width: 44, height: 44)
|
||||
button.setImage(buttonImage, for: .normal)
|
||||
|
@ -143,7 +156,9 @@ open class PiPWindow: UIWindow {
|
|||
|
||||
if exitPiPButton == nil {
|
||||
// show button
|
||||
let button = configureExitPiPButton(target: self, action: #selector(exitPiP))
|
||||
let exitSelector = #selector(exitPictureInPicture)
|
||||
let button = configureExitPiPButton(target: self,
|
||||
action: exitSelector)
|
||||
view.addSubview(button)
|
||||
exitPiPButton = button
|
||||
|
||||
|
@ -152,10 +167,19 @@ open class PiPWindow: UIWindow {
|
|||
exitPiPButton?.removeFromSuperview()
|
||||
exitPiPButton = nil
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@objc private func exitPiP() {
|
||||
goToFullScreen()
|
||||
exitPictureInPicture()
|
||||
}
|
||||
|
||||
// MARK: - Animation transition
|
||||
|
||||
private func animateTransition(animations: @escaping () -> Void) {
|
||||
UIView.animate(withDuration: 0.1,
|
||||
delay: 0,
|
||||
options: .beginFromCurrentState,
|
||||
animations: animations,
|
||||
completion: nil)
|
||||
}
|
||||
}
|
Before Width: | Height: | Size: 509 B After Width: | Height: | Size: 509 B |
Before Width: | Height: | Size: 724 B After Width: | Height: | Size: 724 B |
Loading…
Reference in New Issue