Addressing feedback from PR
This commit is contained in:
parent
8428dd95c2
commit
5858859838
|
@ -56,13 +56,13 @@
|
||||||
</dict>
|
</dict>
|
||||||
</dict>
|
</dict>
|
||||||
<key>NSCalendarsUsageDescription</key>
|
<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>
|
<key>NSCameraUsageDescription</key>
|
||||||
<string>Participate in conferences with video.</string>
|
<string>Participate in conferences with video.</string>
|
||||||
<key>NSLocationWhenInUseUsageDescription</key>
|
<key>NSLocationWhenInUseUsageDescription</key>
|
||||||
<string></string>
|
<string></string>
|
||||||
<key>NSMicrophoneUsageDescription</key>
|
<key>NSMicrophoneUsageDescription</key>
|
||||||
<string>Participate in conferences with audio.</string>
|
<string>Participate in conferences with voice.</string>
|
||||||
<key>UIBackgroundModes</key>
|
<key>UIBackgroundModes</key>
|
||||||
<array>
|
<array>
|
||||||
<string>audio</string>
|
<string>audio</string>
|
||||||
|
|
|
@ -35,7 +35,7 @@
|
||||||
|
|
||||||
/* Begin PBXFileReference section */
|
/* 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>"; };
|
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>"; };
|
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>"; };
|
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>"; };
|
C6F99C3F204DE6BE0001F710 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = "<group>"; };
|
||||||
|
@ -70,7 +70,7 @@
|
||||||
C6F99C38204DE6BE0001F710 /* Products */ = {
|
C6F99C38204DE6BE0001F710 /* Products */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
C6F99C37204DE6BE0001F710 /* PiPApp.app */,
|
C6F99C37204DE6BE0001F710 /* example-pip-app.app */,
|
||||||
);
|
);
|
||||||
name = Products;
|
name = Products;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
|
@ -100,9 +100,9 @@
|
||||||
/* End PBXGroup section */
|
/* End PBXGroup section */
|
||||||
|
|
||||||
/* Begin PBXNativeTarget section */
|
/* Begin PBXNativeTarget section */
|
||||||
C6F99C36204DE6BE0001F710 /* PiPApp */ = {
|
C6F99C36204DE6BE0001F710 /* example-pip-app */ = {
|
||||||
isa = PBXNativeTarget;
|
isa = PBXNativeTarget;
|
||||||
buildConfigurationList = C6F99C49204DE6BE0001F710 /* Build configuration list for PBXNativeTarget "PiPApp" */;
|
buildConfigurationList = C6F99C49204DE6BE0001F710 /* Build configuration list for PBXNativeTarget "example-pip-app" */;
|
||||||
buildPhases = (
|
buildPhases = (
|
||||||
C6A3424A204DF91D00E062DD /* Run Adjust ATS for loading JS bundle */,
|
C6A3424A204DF91D00E062DD /* Run Adjust ATS for loading JS bundle */,
|
||||||
C6F99C62204DEFFE0001F710 /* Run React Packager */,
|
C6F99C62204DEFFE0001F710 /* Run React Packager */,
|
||||||
|
@ -116,9 +116,9 @@
|
||||||
);
|
);
|
||||||
dependencies = (
|
dependencies = (
|
||||||
);
|
);
|
||||||
name = PiPApp;
|
name = example-pip-app;
|
||||||
productName = ExampleAppUsingJitsiWithPiP;
|
productName = example-pip-app;
|
||||||
productReference = C6F99C37204DE6BE0001F710 /* PiPApp.app */;
|
productReference = C6F99C37204DE6BE0001F710 /* example-pip-app.app */;
|
||||||
productType = "com.apple.product-type.application";
|
productType = "com.apple.product-type.application";
|
||||||
};
|
};
|
||||||
/* End PBXNativeTarget section */
|
/* 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";
|
compatibilityVersion = "Xcode 8.0";
|
||||||
developmentRegion = en;
|
developmentRegion = en;
|
||||||
hasScannedForEncodings = 0;
|
hasScannedForEncodings = 0;
|
||||||
|
@ -155,7 +155,7 @@
|
||||||
projectDirPath = "";
|
projectDirPath = "";
|
||||||
projectRoot = "";
|
projectRoot = "";
|
||||||
targets = (
|
targets = (
|
||||||
C6F99C36204DE6BE0001F710 /* PiPApp */,
|
C6F99C36204DE6BE0001F710 /* example-pip-app */,
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
/* End PBXProject section */
|
/* End PBXProject section */
|
||||||
|
@ -366,7 +366,7 @@
|
||||||
INFOPLIST_FILE = src/Info.plist;
|
INFOPLIST_FILE = src/Info.plist;
|
||||||
IPHONEOS_DEPLOYMENT_TARGET = 10.3;
|
IPHONEOS_DEPLOYMENT_TARGET = 10.3;
|
||||||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
|
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)";
|
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||||
SWIFT_VERSION = 4.0;
|
SWIFT_VERSION = 4.0;
|
||||||
TARGETED_DEVICE_FAMILY = "1,2";
|
TARGETED_DEVICE_FAMILY = "1,2";
|
||||||
|
@ -382,7 +382,7 @@
|
||||||
INFOPLIST_FILE = src/Info.plist;
|
INFOPLIST_FILE = src/Info.plist;
|
||||||
IPHONEOS_DEPLOYMENT_TARGET = 10.3;
|
IPHONEOS_DEPLOYMENT_TARGET = 10.3;
|
||||||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
|
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)";
|
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||||
SWIFT_VERSION = 4.0;
|
SWIFT_VERSION = 4.0;
|
||||||
TARGETED_DEVICE_FAMILY = "1,2";
|
TARGETED_DEVICE_FAMILY = "1,2";
|
||||||
|
@ -392,7 +392,7 @@
|
||||||
/* End XCBuildConfiguration section */
|
/* End XCBuildConfiguration section */
|
||||||
|
|
||||||
/* Begin XCConfigurationList section */
|
/* Begin XCConfigurationList section */
|
||||||
C6F99C32204DE6BE0001F710 /* Build configuration list for PBXProject "PiPApp" */ = {
|
C6F99C32204DE6BE0001F710 /* Build configuration list for PBXProject "example-pip-app" */ = {
|
||||||
isa = XCConfigurationList;
|
isa = XCConfigurationList;
|
||||||
buildConfigurations = (
|
buildConfigurations = (
|
||||||
C6F99C47204DE6BE0001F710 /* Debug */,
|
C6F99C47204DE6BE0001F710 /* Debug */,
|
||||||
|
@ -401,7 +401,7 @@
|
||||||
defaultConfigurationIsVisible = 0;
|
defaultConfigurationIsVisible = 0;
|
||||||
defaultConfigurationName = Release;
|
defaultConfigurationName = Release;
|
||||||
};
|
};
|
||||||
C6F99C49204DE6BE0001F710 /* Build configuration list for PBXNativeTarget "PiPApp" */ = {
|
C6F99C49204DE6BE0001F710 /* Build configuration list for PBXNativeTarget "example-pip-app" */ = {
|
||||||
isa = XCConfigurationList;
|
isa = XCConfigurationList;
|
||||||
buildConfigurations = (
|
buildConfigurations = (
|
||||||
C6F99C4A204DE6BE0001F710 /* Debug */,
|
C6F99C4A204DE6BE0001F710 /* Debug */,
|
|
@ -1,10 +1,18 @@
|
||||||
//
|
/*
|
||||||
// AppDelegate.swift
|
* Copyright @ 2017-present Atlassian Pty Ltd
|
||||||
// ExampleAppUsingJitsiWithPiP
|
*
|
||||||
//
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
// Created by Daniel Ornelas on 3/5/18.
|
* you may not use this file except in compliance with the License.
|
||||||
// Copyright © 2018 Atlassian Inc. All rights reserved.
|
* 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
|
import JitsiMeet
|
||||||
|
|
||||||
|
@ -30,6 +38,4 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
|
||||||
func application(_ application: UIApplication, open url: URL, sourceApplication: String?, annotation: Any) -> Bool {
|
func application(_ application: UIApplication, open url: URL, sourceApplication: String?, annotation: Any) -> Bool {
|
||||||
return JitsiMeetView.application(application, open: url, sourceApplication: sourceApplication, annotation: annotation)
|
return JitsiMeetView.application(application, open: url, sourceApplication: sourceApplication, annotation: annotation)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -13,17 +13,17 @@
|
||||||
<!--View Controller-->
|
<!--View Controller-->
|
||||||
<scene sceneID="tne-QT-ifu">
|
<scene sceneID="tne-QT-ifu">
|
||||||
<objects>
|
<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">
|
<view key="view" contentMode="scaleToFill" id="8bC-Xf-vdC">
|
||||||
<rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
|
<rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
|
||||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||||
<subviews>
|
<subviews>
|
||||||
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="QxY-C8-fwD">
|
<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"/>
|
<fontDescription key="fontDescription" type="system" pointSize="21"/>
|
||||||
<state key="normal" title="Start Jitsi"/>
|
<state key="normal" title="Open Jitsi Meet"/>
|
||||||
<connections>
|
<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>
|
</connections>
|
||||||
</button>
|
</button>
|
||||||
</subviews>
|
</subviews>
|
||||||
|
|
|
@ -1,10 +1,18 @@
|
||||||
//
|
/*
|
||||||
// ViewController.swift
|
* Copyright @ 2017-present Atlassian Pty Ltd
|
||||||
// ExampleAppUsingJitsiWithPiP
|
*
|
||||||
//
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
// Created by Daniel Ornelas on 3/5/18.
|
* you may not use this file except in compliance with the License.
|
||||||
// Copyright © 2018 Atlassian Inc. All rights reserved.
|
* 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 UIKit
|
||||||
import JitsiMeet
|
import JitsiMeet
|
||||||
|
@ -13,7 +21,7 @@ class ViewController: UIViewController {
|
||||||
|
|
||||||
@IBOutlet weak var videoButton: UIButton?
|
@IBOutlet weak var videoButton: UIButton?
|
||||||
|
|
||||||
private var jitsiMeetManager: JitsiMeetManager?
|
private var jitsiMeetCoordinator: JitsiMeetPresentationCoordinator?
|
||||||
|
|
||||||
override func viewDidLoad() {
|
override func viewDidLoad() {
|
||||||
super.viewDidLoad()
|
super.viewDidLoad()
|
||||||
|
@ -21,12 +29,11 @@ class ViewController: UIViewController {
|
||||||
|
|
||||||
// MARK: - Actions
|
// MARK: - Actions
|
||||||
|
|
||||||
@IBAction func startMeeting(sender: Any?) {
|
@IBAction func openJitsiMeet(sender: Any?) {
|
||||||
//let url = URL(string: "")
|
let jitsiMeetCoordinator = JitsiMeetPresentationCoordinator()
|
||||||
self.jitsiMeetManager = JitsiMeetManager()
|
self.jitsiMeetCoordinator = jitsiMeetCoordinator
|
||||||
jitsiMeetManager?.welcomeScreenEnabled = true
|
jitsiMeetCoordinator.jitsiMeetView().welcomePageEnabled = true
|
||||||
jitsiMeetManager?.load(withUrl: nil)
|
jitsiMeetCoordinator.jitsiMeetView().load(nil)
|
||||||
|
jitsiMeetCoordinator.show()
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
<Workspace
|
<Workspace
|
||||||
version = "1.0">
|
version = "1.0">
|
||||||
<FileRef
|
<FileRef
|
||||||
location = "group:example-pip-app/PiPApp.xcodeproj">
|
location = "group:example-pip-app/example-pip-app.xcodeproj">
|
||||||
</FileRef>
|
</FileRef>
|
||||||
<FileRef
|
<FileRef
|
||||||
location = "group:app/app.xcodeproj">
|
location = "group:app/app.xcodeproj">
|
||||||
|
|
|
@ -30,7 +30,7 @@
|
||||||
C6245F5D2053091D0040BE68 /* image-resize@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = C6245F5B2053091D0040BE68 /* image-resize@2x.png */; };
|
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 */; };
|
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 */; };
|
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 */; };
|
C6A34261204EF76800E062DD /* DragGestureController.swift in Sources */ = {isa = PBXBuildFile; fileRef = C6A3425E204EF76800E062DD /* DragGestureController.swift */; };
|
||||||
C6A3426D204F1C3300E062DD /* JitsiMeetViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = C6A3426C204F1C3300E062DD /* JitsiMeetViewController.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 */; };
|
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>"; };
|
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>"; };
|
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>"; };
|
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>"; };
|
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; path = "image-resize@3x.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>"; };
|
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>"; };
|
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>"; };
|
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>"; };
|
C6F99C13204DB63D0001F710 /* JitsiMeetView+Private.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "JitsiMeetView+Private.h"; sourceTree = "<group>"; };
|
||||||
|
@ -119,7 +119,7 @@
|
||||||
0BD906E71EC0C00300C8C18E /* src */ = {
|
0BD906E71EC0C00300C8C18E /* src */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
C6A3426B204F127900E062DD /* JitsiMeetManager */,
|
C6A3426B204F127900E062DD /* picture-in-picture */,
|
||||||
0BCA495C1EC4B6C600B793EE /* AudioMode.m */,
|
0BCA495C1EC4B6C600B793EE /* AudioMode.m */,
|
||||||
0BB9AD7C1F60356D001C08DB /* AppInfo.m */,
|
0BB9AD7C1F60356D001C08DB /* AppInfo.m */,
|
||||||
0BB9AD7A1F5EC8F4001C08DB /* CallKit.m */,
|
0BB9AD7A1F5EC8F4001C08DB /* CallKit.m */,
|
||||||
|
@ -161,23 +161,15 @@
|
||||||
name = Pods;
|
name = Pods;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
};
|
};
|
||||||
C6245F5A2052043F0040BE68 /* PiPWindow */ = {
|
C6A3426B204F127900E062DD /* picture-in-picture */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
C6A3425E204EF76800E062DD /* DragGestureController.swift */,
|
C6A3425E204EF76800E062DD /* DragGestureController.swift */,
|
||||||
|
C6A3425D204EF76800E062DD /* JitsiMeetPresentationCoordinator.swift */,
|
||||||
|
C6A3426C204F1C3300E062DD /* JitsiMeetViewController.swift */,
|
||||||
C6A3425C204EF76800E062DD /* PiPWindow.swift */,
|
C6A3425C204EF76800E062DD /* PiPWindow.swift */,
|
||||||
);
|
);
|
||||||
path = PiPWindow;
|
path = "picture-in-picture";
|
||||||
sourceTree = "<group>";
|
|
||||||
};
|
|
||||||
C6A3426B204F127900E062DD /* JitsiMeetManager */ = {
|
|
||||||
isa = PBXGroup;
|
|
||||||
children = (
|
|
||||||
C6245F5A2052043F0040BE68 /* PiPWindow */,
|
|
||||||
C6A3425D204EF76800E062DD /* JitsiMeetManager.swift */,
|
|
||||||
C6A3426C204F1C3300E062DD /* JitsiMeetViewController.swift */,
|
|
||||||
);
|
|
||||||
path = JitsiMeetManager;
|
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
};
|
};
|
||||||
/* End PBXGroup section */
|
/* End PBXGroup section */
|
||||||
|
@ -345,7 +337,7 @@
|
||||||
buildActionMask = 2147483647;
|
buildActionMask = 2147483647;
|
||||||
files = (
|
files = (
|
||||||
0BB9AD7B1F5EC8F4001C08DB /* CallKit.m in Sources */,
|
0BB9AD7B1F5EC8F4001C08DB /* CallKit.m in Sources */,
|
||||||
C6A34260204EF76800E062DD /* JitsiMeetManager.swift in Sources */,
|
C6A34260204EF76800E062DD /* JitsiMeetPresentationCoordinator.swift in Sources */,
|
||||||
0BB9AD7D1F60356D001C08DB /* AppInfo.m in Sources */,
|
0BB9AD7D1F60356D001C08DB /* AppInfo.m in Sources */,
|
||||||
0B93EF7F1EC9DDCD0030D24D /* RCTBridgeWrapper.m in Sources */,
|
0B93EF7F1EC9DDCD0030D24D /* RCTBridgeWrapper.m in Sources */,
|
||||||
0BA13D311EE83FF8007BEF7F /* ExternalAPI.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 {
|
final class DragGestureController {
|
||||||
|
|
||||||
|
@ -7,7 +21,8 @@ final class DragGestureController {
|
||||||
private var frameBeforeDragging: CGRect = CGRect.zero
|
private var frameBeforeDragging: CGRect = CGRect.zero
|
||||||
private weak var view: UIView?
|
private weak var view: UIView?
|
||||||
private lazy var panGesture: UIPanGestureRecognizer = {
|
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) {
|
func startDragListener(inView view: UIView) {
|
||||||
|
@ -47,7 +62,8 @@ final class DragGestureController {
|
||||||
let distanceMagnitude = magnitude(vector: distance)
|
let distanceMagnitude = magnitude(vector: distance)
|
||||||
let velocityMagnitude = magnitude(vector: velocity)
|
let velocityMagnitude = magnitude(vector: velocity)
|
||||||
let animationDuration = 0.5
|
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)
|
frame.origin = CGPoint(x: finalPos.x, y: finalPos.y)
|
||||||
|
|
||||||
|
@ -91,8 +107,14 @@ final class DragGestureController {
|
||||||
goUp = location.y < bounds.midY
|
goUp = location.y < bounds.midY
|
||||||
}
|
}
|
||||||
|
|
||||||
let finalPosX: CGFloat = goLeft ? adjustedBounds.origin.x : bounds.size.width - insets.right - currentSize.width
|
let finalPosX: CGFloat =
|
||||||
let finalPosY: CGFloat = goUp ? adjustedBounds.origin.y : bounds.size.height - insets.bottom - currentSize.height
|
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)
|
return CGPoint(x: finalPosX, y: finalPosY)
|
||||||
}
|
}
|
||||||
|
@ -101,4 +123,3 @@ final class DragGestureController {
|
||||||
return sqrt(pow(vector.x, 2) + pow(vector.y, 2))
|
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 {
|
public enum JitsiMeetPresentationUpdate {
|
||||||
|
|
||||||
|
/// The conference wants to enter Picture-in-Picture
|
||||||
|
case enterPictureInPicture
|
||||||
|
|
||||||
/// A system traitCollectionChange (usually screen rotation)
|
/// A system traitCollectionChange (usually screen rotation)
|
||||||
case traitChange
|
case traitChange
|
||||||
/// Meeting wants to enter PiP mode
|
|
||||||
case enterPiP
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public protocol JitsiMeetViewControllerDelegate: class {
|
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
|
/// - Parameter to: The presentation state that will be changed to
|
||||||
func performPresentationUpdate(to: JitsiMeetPresentationUpdate)
|
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
|
/// Wrapper ViewController of a JitsiMeetView
|
||||||
|
@ -52,7 +73,7 @@ extension JitsiMeetViewController: JitsiMeetViewDelegate {
|
||||||
|
|
||||||
open func conferenceJoined(_ data: [AnyHashable : Any]!) {
|
open func conferenceJoined(_ data: [AnyHashable : Any]!) {
|
||||||
DispatchQueue.main.async {
|
DispatchQueue.main.async {
|
||||||
self.delegate?.meetingStarted()
|
self.delegate?.conferenceStarted()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -62,13 +83,13 @@ extension JitsiMeetViewController: JitsiMeetViewDelegate {
|
||||||
|
|
||||||
open func conferenceLeft(_ data: [AnyHashable : Any]!) {
|
open func conferenceLeft(_ data: [AnyHashable : Any]!) {
|
||||||
DispatchQueue.main.async {
|
DispatchQueue.main.async {
|
||||||
self.delegate?.meetingEnded(wasFailure: true)
|
self.delegate?.conferenceEnded(didFail: true)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
open func conferenceFailed(_ data: [AnyHashable : Any]!) {
|
open func conferenceFailed(_ data: [AnyHashable : Any]!) {
|
||||||
DispatchQueue.main.async {
|
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]!) {
|
open func enterPicture(inPicture data: [AnyHashable : Any]!) {
|
||||||
DispatchQueue.main.async {
|
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
|
/// A window that allows its root view controller to be presented
|
||||||
/// in full screen or in a custom Picture in Picture mode
|
/// in full screen or in a custom Picture in Picture mode
|
||||||
open class PiPWindow: UIWindow {
|
open class PiPWindow: UIWindow {
|
||||||
|
|
||||||
/// Limits the boundries of root view position on screen when minimized
|
/// 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 {
|
didSet {
|
||||||
dragController.insets = dragBoundInsets
|
dragController.insets = dragBoundInsets
|
||||||
}
|
}
|
||||||
|
@ -24,7 +41,8 @@ open class PiPWindow: UIWindow {
|
||||||
private var exitPiPButton: UIButton?
|
private var exitPiPButton: UIButton?
|
||||||
|
|
||||||
/// Help out to bubble up the gesture detection outside of the rootVC frame
|
/// 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 {
|
guard let vc = rootViewController else {
|
||||||
return super.point(inside: point, with: event)
|
return super.point(inside: point, with: event)
|
||||||
}
|
}
|
||||||
|
@ -36,35 +54,24 @@ open class PiPWindow: UIWindow {
|
||||||
if self.isHidden || self.alpha < 1 {
|
if self.isHidden || self.alpha < 1 {
|
||||||
self.isHidden = false
|
self.isHidden = false
|
||||||
self.alpha = 0
|
self.alpha = 0
|
||||||
|
animateTransition {
|
||||||
UIView.animate(
|
|
||||||
withDuration: 0.1,
|
|
||||||
delay: 0,
|
|
||||||
options: .beginFromCurrentState,
|
|
||||||
animations: {
|
|
||||||
self.alpha = 1
|
self.alpha = 1
|
||||||
},
|
}
|
||||||
completion: nil)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// animate out the window
|
/// animate out the window
|
||||||
open func hide() {
|
open func hide() {
|
||||||
if !self.isHidden || self.alpha > 0 {
|
if !self.isHidden || self.alpha > 0 {
|
||||||
UIView.animate(
|
animateTransition {
|
||||||
withDuration: 0.1,
|
|
||||||
delay: 0,
|
|
||||||
options: .beginFromCurrentState,
|
|
||||||
animations: {
|
|
||||||
self.alpha = 0
|
self.alpha = 0
|
||||||
self.isHidden = true
|
self.isHidden = true
|
||||||
},
|
}
|
||||||
completion: nil)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Resize the root view to PiP mode
|
/// Resize the root view to PiP mode
|
||||||
open func goToPiP() {
|
open func enterPictureInPicture() {
|
||||||
guard let view = rootViewController?.view else { return }
|
guard let view = rootViewController?.view else { return }
|
||||||
isInPiP = true
|
isInPiP = true
|
||||||
animateRootViewChange()
|
animateRootViewChange()
|
||||||
|
@ -72,13 +79,15 @@ open class PiPWindow: UIWindow {
|
||||||
dragController.insets = dragBoundInsets
|
dragController.insets = dragBoundInsets
|
||||||
|
|
||||||
// add single tap gesture recognition for displaying exit PiP UI
|
// 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
|
self.tapGestureRecognizer = tapGestureRecognizer
|
||||||
view.addGestureRecognizer(tapGestureRecognizer)
|
view.addGestureRecognizer(tapGestureRecognizer)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Resize the root view to full screen
|
/// Resize the root view to full screen
|
||||||
open func goToFullScreen() {
|
open func exitPictureInPicture() {
|
||||||
isInPiP = false
|
isInPiP = false
|
||||||
animateRootViewChange()
|
animateRootViewChange()
|
||||||
dragController.stopDragListener()
|
dragController.stopDragListener()
|
||||||
|
@ -88,7 +97,8 @@ open class PiPWindow: UIWindow {
|
||||||
exitPiPButton = nil
|
exitPiPButton = nil
|
||||||
|
|
||||||
// remove gesture
|
// remove gesture
|
||||||
tapGestureRecognizer?.removeTarget(self, action: #selector(toggleExitPiP))
|
let exitSelector = #selector(toggleExitPiP)
|
||||||
|
tapGestureRecognizer?.removeTarget(self, action: exitSelector)
|
||||||
tapGestureRecognizer = nil
|
tapGestureRecognizer = nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -98,8 +108,11 @@ open class PiPWindow: UIWindow {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Customize the presentation of exit pip button
|
/// Customize the presentation of exit pip button
|
||||||
open func configureExitPiPButton(target: Any, action: Selector) -> UIButton {
|
open func configureExitPiPButton(target: Any,
|
||||||
let buttonImage = UIImage.init(named: "image-resize", in: Bundle(for: type(of: self)), compatibleWith: nil)
|
action: Selector) -> UIButton {
|
||||||
|
let buttonImage = UIImage.init(named: "image-resize",
|
||||||
|
in: Bundle(for: type(of: self)),
|
||||||
|
compatibleWith: nil)
|
||||||
let button = UIButton(type: .custom)
|
let button = UIButton(type: .custom)
|
||||||
let size: CGSize = CGSize(width: 44, height: 44)
|
let size: CGSize = CGSize(width: 44, height: 44)
|
||||||
button.setImage(buttonImage, for: .normal)
|
button.setImage(buttonImage, for: .normal)
|
||||||
|
@ -143,7 +156,9 @@ open class PiPWindow: UIWindow {
|
||||||
|
|
||||||
if exitPiPButton == nil {
|
if exitPiPButton == nil {
|
||||||
// show button
|
// show button
|
||||||
let button = configureExitPiPButton(target: self, action: #selector(exitPiP))
|
let exitSelector = #selector(exitPictureInPicture)
|
||||||
|
let button = configureExitPiPButton(target: self,
|
||||||
|
action: exitSelector)
|
||||||
view.addSubview(button)
|
view.addSubview(button)
|
||||||
exitPiPButton = button
|
exitPiPButton = button
|
||||||
|
|
||||||
|
@ -152,10 +167,19 @@ open class PiPWindow: UIWindow {
|
||||||
exitPiPButton?.removeFromSuperview()
|
exitPiPButton?.removeFromSuperview()
|
||||||
exitPiPButton = nil
|
exitPiPButton = nil
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@objc private func exitPiP() {
|
@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