watchos: add watchOS app
Co-authored-by: Pawel Domas <pawel.domas@jitsi.org>
|
@ -51,6 +51,7 @@ target 'JitsiMeet' do
|
||||||
:path => '../node_modules/react-native-google-signin'
|
:path => '../node_modules/react-native-google-signin'
|
||||||
pod 'RNSound', :path => '../node_modules/react-native-sound'
|
pod 'RNSound', :path => '../node_modules/react-native-sound'
|
||||||
pod 'RNVectorIcons', :path => '../node_modules/react-native-vector-icons'
|
pod 'RNVectorIcons', :path => '../node_modules/react-native-vector-icons'
|
||||||
|
pod 'RNWatch', :path => '../node_modules/react-native-watch-connectivity'
|
||||||
pod 'react-native-calendar-events',
|
pod 'react-native-calendar-events',
|
||||||
:path => '../node_modules/react-native-calendar-events'
|
:path => '../node_modules/react-native-calendar-events'
|
||||||
end
|
end
|
||||||
|
|
|
@ -156,6 +156,8 @@ PODS:
|
||||||
- React/Core
|
- React/Core
|
||||||
- RNVectorIcons (6.0.2):
|
- RNVectorIcons (6.0.2):
|
||||||
- React
|
- React
|
||||||
|
- RNWatch (0.2.0):
|
||||||
|
- React
|
||||||
- SDWebImage/Core (4.4.6)
|
- SDWebImage/Core (4.4.6)
|
||||||
- SDWebImage/GIF (4.4.6):
|
- SDWebImage/GIF (4.4.6):
|
||||||
- FLAnimatedImage (~> 1.0)
|
- FLAnimatedImage (~> 1.0)
|
||||||
|
@ -191,6 +193,7 @@ DEPENDENCIES:
|
||||||
- RNGoogleSignin (from `../node_modules/react-native-google-signin`)
|
- RNGoogleSignin (from `../node_modules/react-native-google-signin`)
|
||||||
- RNSound (from `../node_modules/react-native-sound`)
|
- RNSound (from `../node_modules/react-native-sound`)
|
||||||
- RNVectorIcons (from `../node_modules/react-native-vector-icons`)
|
- RNVectorIcons (from `../node_modules/react-native-vector-icons`)
|
||||||
|
- RNWatch (from `../node_modules/react-native-watch-connectivity`)
|
||||||
- yoga (from `../node_modules/react-native/ReactCommon/yoga`)
|
- yoga (from `../node_modules/react-native/ReactCommon/yoga`)
|
||||||
|
|
||||||
SPEC REPOS:
|
SPEC REPOS:
|
||||||
|
@ -242,6 +245,8 @@ EXTERNAL SOURCES:
|
||||||
:path: "../node_modules/react-native-sound"
|
:path: "../node_modules/react-native-sound"
|
||||||
RNVectorIcons:
|
RNVectorIcons:
|
||||||
:path: "../node_modules/react-native-vector-icons"
|
:path: "../node_modules/react-native-vector-icons"
|
||||||
|
RNWatch:
|
||||||
|
:path: "../node_modules/react-native-watch-connectivity"
|
||||||
yoga:
|
yoga:
|
||||||
:path: "../node_modules/react-native/ReactCommon/yoga"
|
:path: "../node_modules/react-native/ReactCommon/yoga"
|
||||||
|
|
||||||
|
@ -277,9 +282,10 @@ SPEC CHECKSUMS:
|
||||||
RNGoogleSignin: 361174d9a3090d295b06257162b560d8efc8a6ed
|
RNGoogleSignin: 361174d9a3090d295b06257162b560d8efc8a6ed
|
||||||
RNSound: e157320f503bdd4f4ee6d8542e948d54f90c3c3a
|
RNSound: e157320f503bdd4f4ee6d8542e948d54f90c3c3a
|
||||||
RNVectorIcons: d819334932bcda3332deb3d2c8ea4d069e0b98f9
|
RNVectorIcons: d819334932bcda3332deb3d2c8ea4d069e0b98f9
|
||||||
|
RNWatch: 09738b339eceb66e4d80a2371633ca5fb380fa42
|
||||||
SDWebImage: 3f3f0c02f09798048c47a5ed0a13f17b063572d8
|
SDWebImage: 3f3f0c02f09798048c47a5ed0a13f17b063572d8
|
||||||
yoga: 2e571f113e8cbeb0eb752aeebc86c1bfe7a8200c
|
yoga: 2e571f113e8cbeb0eb752aeebc86c1bfe7a8200c
|
||||||
|
|
||||||
PODFILE CHECKSUM: 4a11c3d66127a9845d4a5b2c7fad49f58a9c7a89
|
PODFILE CHECKSUM: 8e6caba6dab554c16a3d89d1fa8b69c70c5452d0
|
||||||
|
|
||||||
COCOAPODS: 1.6.1
|
COCOAPODS: 1.6.1
|
||||||
|
|
|
@ -11,16 +11,45 @@
|
||||||
0B26BE6F1EC5BC3C00EEFB41 /* JitsiMeet.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 0B26BE6D1EC5BC3C00EEFB41 /* JitsiMeet.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
|
0B26BE6F1EC5BC3C00EEFB41 /* JitsiMeet.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 0B26BE6D1EC5BC3C00EEFB41 /* JitsiMeet.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
|
||||||
0B412F1F1EDEE6E800B1A0A6 /* ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 0B412F1E1EDEE6E800B1A0A6 /* ViewController.m */; };
|
0B412F1F1EDEE6E800B1A0A6 /* ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 0B412F1E1EDEE6E800B1A0A6 /* ViewController.m */; };
|
||||||
0B412F211EDEE95300B1A0A6 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 0B412F201EDEE95300B1A0A6 /* Main.storyboard */; };
|
0B412F211EDEE95300B1A0A6 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 0B412F201EDEE95300B1A0A6 /* Main.storyboard */; };
|
||||||
|
0B5418471F7C5D8C00A2DD86 /* MeetingRowController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0B5418461F7C5D8C00A2DD86 /* MeetingRowController.swift */; };
|
||||||
|
0B7001701F7C51CC005944F4 /* InCallController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0B70016F1F7C51CC005944F4 /* InCallController.swift */; };
|
||||||
0BD6B4371EF82A6B00D1F4CD /* WebRTC.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0BD6B4361EF82A6B00D1F4CD /* WebRTC.framework */; };
|
0BD6B4371EF82A6B00D1F4CD /* WebRTC.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0BD6B4361EF82A6B00D1F4CD /* WebRTC.framework */; };
|
||||||
0BD6B4381EF82A6B00D1F4CD /* WebRTC.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 0BD6B4361EF82A6B00D1F4CD /* WebRTC.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
|
0BD6B4381EF82A6B00D1F4CD /* WebRTC.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 0BD6B4361EF82A6B00D1F4CD /* WebRTC.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
|
||||||
|
0BEA5C291F7B8F73000D0AB4 /* Interface.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 0BEA5C271F7B8F73000D0AB4 /* Interface.storyboard */; };
|
||||||
|
0BEA5C2B1F7B8F73000D0AB4 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 0BEA5C2A1F7B8F73000D0AB4 /* Assets.xcassets */; };
|
||||||
|
0BEA5C321F7B8F73000D0AB4 /* JitsiMeetCompanion Extension.appex in Embed App Extensions */ = {isa = PBXBuildFile; fileRef = 0BEA5C311F7B8F73000D0AB4 /* JitsiMeetCompanion Extension.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; };
|
||||||
|
0BEA5C371F7B8F73000D0AB4 /* InterfaceController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0BEA5C361F7B8F73000D0AB4 /* InterfaceController.swift */; };
|
||||||
|
0BEA5C391F7B8F73000D0AB4 /* ExtensionDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0BEA5C381F7B8F73000D0AB4 /* ExtensionDelegate.swift */; };
|
||||||
|
0BEA5C3B1F7B8F73000D0AB4 /* ComplicationController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0BEA5C3A1F7B8F73000D0AB4 /* ComplicationController.swift */; };
|
||||||
|
0BEA5C3D1F7B8F73000D0AB4 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 0BEA5C3C1F7B8F73000D0AB4 /* Assets.xcassets */; };
|
||||||
|
0BEA5C411F7B8F73000D0AB4 /* JitsiMeetCompanion.app in Embed Watch Content */ = {isa = PBXBuildFile; fileRef = 0BEA5C251F7B8F73000D0AB4 /* JitsiMeetCompanion.app */; };
|
||||||
13B07FBC1A68108700A75B9A /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 13B07FB01A68108700A75B9A /* AppDelegate.m */; };
|
13B07FBC1A68108700A75B9A /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 13B07FB01A68108700A75B9A /* AppDelegate.m */; };
|
||||||
13B07FBD1A68108700A75B9A /* LaunchScreen.xib in Resources */ = {isa = PBXBuildFile; fileRef = 13B07FB11A68108700A75B9A /* LaunchScreen.xib */; };
|
13B07FBD1A68108700A75B9A /* LaunchScreen.xib in Resources */ = {isa = PBXBuildFile; fileRef = 13B07FB11A68108700A75B9A /* LaunchScreen.xib */; };
|
||||||
13B07FBF1A68108700A75B9A /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 13B07FB51A68108700A75B9A /* Images.xcassets */; };
|
13B07FBF1A68108700A75B9A /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 13B07FB51A68108700A75B9A /* Images.xcassets */; };
|
||||||
13B07FC11A68108700A75B9A /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 13B07FB71A68108700A75B9A /* main.m */; };
|
13B07FC11A68108700A75B9A /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 13B07FB71A68108700A75B9A /* main.m */; };
|
||||||
695AF3ED6F686F9C5EE40F9A /* libPods-jitsi-meet.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 489E8EFE2C720D10F5961AEF /* libPods-jitsi-meet.a */; };
|
695AF3ED6F686F9C5EE40F9A /* libPods-jitsi-meet.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 489E8EFE2C720D10F5961AEF /* libPods-jitsi-meet.a */; };
|
||||||
DE4C456121DE1E4E00EA0709 /* FIRUtilities.m in Sources */ = {isa = PBXBuildFile; fileRef = DE4C455F21DE1E4E00EA0709 /* FIRUtilities.m */; };
|
DE4C456121DE1E4E00EA0709 /* FIRUtilities.m in Sources */ = {isa = PBXBuildFile; fileRef = DE4C455F21DE1E4E00EA0709 /* FIRUtilities.m */; };
|
||||||
|
E588011722789D43008B0561 /* JitsiMeetContext.swift in Sources */ = {isa = PBXBuildFile; fileRef = E58801132278944E008B0561 /* JitsiMeetContext.swift */; };
|
||||||
|
E5C97B63227A1EB400199214 /* JitsiMeetCommands.swift in Sources */ = {isa = PBXBuildFile; fileRef = E5C97B62227A1EB400199214 /* JitsiMeetCommands.swift */; };
|
||||||
/* End PBXBuildFile section */
|
/* End PBXBuildFile section */
|
||||||
|
|
||||||
|
/* Begin PBXContainerItemProxy section */
|
||||||
|
0BEA5C331F7B8F73000D0AB4 /* PBXContainerItemProxy */ = {
|
||||||
|
isa = PBXContainerItemProxy;
|
||||||
|
containerPortal = 83CBB9F71A601CBA00E9B192 /* Project object */;
|
||||||
|
proxyType = 1;
|
||||||
|
remoteGlobalIDString = 0BEA5C301F7B8F73000D0AB4;
|
||||||
|
remoteInfo = "JitsiMeetCompanion Extension";
|
||||||
|
};
|
||||||
|
0BEA5C3F1F7B8F73000D0AB4 /* PBXContainerItemProxy */ = {
|
||||||
|
isa = PBXContainerItemProxy;
|
||||||
|
containerPortal = 83CBB9F71A601CBA00E9B192 /* Project object */;
|
||||||
|
proxyType = 1;
|
||||||
|
remoteGlobalIDString = 0BEA5C241F7B8F73000D0AB4;
|
||||||
|
remoteInfo = JitsiMeetCompanion;
|
||||||
|
};
|
||||||
|
/* End PBXContainerItemProxy section */
|
||||||
|
|
||||||
/* Begin PBXCopyFilesBuildPhase section */
|
/* Begin PBXCopyFilesBuildPhase section */
|
||||||
0B26BE701EC5BC3C00EEFB41 /* Embed Frameworks */ = {
|
0B26BE701EC5BC3C00EEFB41 /* Embed Frameworks */ = {
|
||||||
isa = PBXCopyFilesBuildPhase;
|
isa = PBXCopyFilesBuildPhase;
|
||||||
|
@ -34,6 +63,28 @@
|
||||||
name = "Embed Frameworks";
|
name = "Embed Frameworks";
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
};
|
};
|
||||||
|
0BEA5C471F7B8F73000D0AB4 /* Embed App Extensions */ = {
|
||||||
|
isa = PBXCopyFilesBuildPhase;
|
||||||
|
buildActionMask = 2147483647;
|
||||||
|
dstPath = "";
|
||||||
|
dstSubfolderSpec = 13;
|
||||||
|
files = (
|
||||||
|
0BEA5C321F7B8F73000D0AB4 /* JitsiMeetCompanion Extension.appex in Embed App Extensions */,
|
||||||
|
);
|
||||||
|
name = "Embed App Extensions";
|
||||||
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
|
};
|
||||||
|
0BEA5C491F7B8F73000D0AB4 /* Embed Watch Content */ = {
|
||||||
|
isa = PBXCopyFilesBuildPhase;
|
||||||
|
buildActionMask = 2147483647;
|
||||||
|
dstPath = "$(CONTENTS_FOLDER_PATH)/Watch";
|
||||||
|
dstSubfolderSpec = 16;
|
||||||
|
files = (
|
||||||
|
0BEA5C411F7B8F73000D0AB4 /* JitsiMeetCompanion.app in Embed Watch Content */,
|
||||||
|
);
|
||||||
|
name = "Embed Watch Content";
|
||||||
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
|
};
|
||||||
/* End PBXCopyFilesBuildPhase section */
|
/* End PBXCopyFilesBuildPhase section */
|
||||||
|
|
||||||
/* Begin PBXFileReference section */
|
/* Begin PBXFileReference section */
|
||||||
|
@ -42,8 +93,20 @@
|
||||||
0B412F1D1EDEE6E800B1A0A6 /* ViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ViewController.h; sourceTree = "<group>"; };
|
0B412F1D1EDEE6E800B1A0A6 /* ViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ViewController.h; sourceTree = "<group>"; };
|
||||||
0B412F1E1EDEE6E800B1A0A6 /* ViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ViewController.m; sourceTree = "<group>"; };
|
0B412F1E1EDEE6E800B1A0A6 /* ViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ViewController.m; sourceTree = "<group>"; };
|
||||||
0B412F201EDEE95300B1A0A6 /* Main.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; name = Main.storyboard; path = Base.lproj/Main.storyboard; sourceTree = "<group>"; };
|
0B412F201EDEE95300B1A0A6 /* Main.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; name = Main.storyboard; path = Base.lproj/Main.storyboard; sourceTree = "<group>"; };
|
||||||
|
0B5418461F7C5D8C00A2DD86 /* MeetingRowController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MeetingRowController.swift; sourceTree = "<group>"; };
|
||||||
|
0B70016F1F7C51CC005944F4 /* InCallController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InCallController.swift; sourceTree = "<group>"; };
|
||||||
0BBD021F212EB69D00CCB19F /* Types.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = Types.h; sourceTree = "<group>"; };
|
0BBD021F212EB69D00CCB19F /* Types.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = Types.h; sourceTree = "<group>"; };
|
||||||
0BD6B4361EF82A6B00D1F4CD /* WebRTC.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = WebRTC.framework; path = "../../node_modules/react-native-webrtc/ios/WebRTC.framework"; sourceTree = "<group>"; };
|
0BD6B4361EF82A6B00D1F4CD /* WebRTC.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = WebRTC.framework; path = "../../node_modules/react-native-webrtc/ios/WebRTC.framework"; sourceTree = "<group>"; };
|
||||||
|
0BEA5C251F7B8F73000D0AB4 /* JitsiMeetCompanion.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = JitsiMeetCompanion.app; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||||
|
0BEA5C281F7B8F73000D0AB4 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Interface.storyboard; sourceTree = "<group>"; };
|
||||||
|
0BEA5C2A1F7B8F73000D0AB4 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
|
||||||
|
0BEA5C2C1F7B8F73000D0AB4 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
|
||||||
|
0BEA5C311F7B8F73000D0AB4 /* JitsiMeetCompanion Extension.appex */ = {isa = PBXFileReference; explicitFileType = "wrapper.app-extension"; includeInIndex = 0; path = "JitsiMeetCompanion Extension.appex"; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||||
|
0BEA5C361F7B8F73000D0AB4 /* InterfaceController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InterfaceController.swift; sourceTree = "<group>"; };
|
||||||
|
0BEA5C381F7B8F73000D0AB4 /* ExtensionDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ExtensionDelegate.swift; sourceTree = "<group>"; };
|
||||||
|
0BEA5C3A1F7B8F73000D0AB4 /* ComplicationController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ComplicationController.swift; sourceTree = "<group>"; };
|
||||||
|
0BEA5C3C1F7B8F73000D0AB4 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
|
||||||
|
0BEA5C3E1F7B8F73000D0AB4 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
|
||||||
13B07F961A680F5B00A75B9A /* jitsi-meet.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "jitsi-meet.app"; sourceTree = BUILT_PRODUCTS_DIR; };
|
13B07F961A680F5B00A75B9A /* jitsi-meet.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "jitsi-meet.app"; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||||
13B07FAF1A68108700A75B9A /* AppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = "<group>"; };
|
13B07FAF1A68108700A75B9A /* AppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = "<group>"; };
|
||||||
13B07FB01A68108700A75B9A /* AppDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = "<group>"; };
|
13B07FB01A68108700A75B9A /* AppDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = "<group>"; };
|
||||||
|
@ -56,9 +119,18 @@
|
||||||
B3B083EB1D4955FF0069CEE7 /* app.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = app.entitlements; sourceTree = "<group>"; };
|
B3B083EB1D4955FF0069CEE7 /* app.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = app.entitlements; sourceTree = "<group>"; };
|
||||||
DE4C455F21DE1E4E00EA0709 /* FIRUtilities.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FIRUtilities.m; sourceTree = "<group>"; };
|
DE4C455F21DE1E4E00EA0709 /* FIRUtilities.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FIRUtilities.m; sourceTree = "<group>"; };
|
||||||
DE4C456021DE1E4E00EA0709 /* FIRUtilities.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FIRUtilities.h; sourceTree = "<group>"; };
|
DE4C456021DE1E4E00EA0709 /* FIRUtilities.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FIRUtilities.h; sourceTree = "<group>"; };
|
||||||
|
E58801132278944E008B0561 /* JitsiMeetContext.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = JitsiMeetContext.swift; sourceTree = "<group>"; };
|
||||||
|
E5C97B62227A1EB400199214 /* JitsiMeetCommands.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = JitsiMeetCommands.swift; sourceTree = "<group>"; };
|
||||||
/* End PBXFileReference section */
|
/* End PBXFileReference section */
|
||||||
|
|
||||||
/* Begin PBXFrameworksBuildPhase section */
|
/* Begin PBXFrameworksBuildPhase section */
|
||||||
|
0BEA5C2E1F7B8F73000D0AB4 /* Frameworks */ = {
|
||||||
|
isa = PBXFrameworksBuildPhase;
|
||||||
|
buildActionMask = 2147483647;
|
||||||
|
files = (
|
||||||
|
);
|
||||||
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
|
};
|
||||||
13B07F8C1A680F5B00A75B9A /* Frameworks */ = {
|
13B07F8C1A680F5B00A75B9A /* Frameworks */ = {
|
||||||
isa = PBXFrameworksBuildPhase;
|
isa = PBXFrameworksBuildPhase;
|
||||||
buildActionMask = 2147483647;
|
buildActionMask = 2147483647;
|
||||||
|
@ -69,6 +141,13 @@
|
||||||
);
|
);
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
};
|
};
|
||||||
|
1F021A8A5B056078665DE530 /* Frameworks */ = {
|
||||||
|
isa = PBXFrameworksBuildPhase;
|
||||||
|
buildActionMask = 2147483647;
|
||||||
|
files = (
|
||||||
|
);
|
||||||
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
|
};
|
||||||
/* End PBXFrameworksBuildPhase section */
|
/* End PBXFrameworksBuildPhase section */
|
||||||
|
|
||||||
/* Begin PBXGroup section */
|
/* Begin PBXGroup section */
|
||||||
|
@ -82,6 +161,34 @@
|
||||||
name = Frameworks;
|
name = Frameworks;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
};
|
};
|
||||||
|
0BEA5C261F7B8F73000D0AB4 /* Watch app */ = {
|
||||||
|
isa = PBXGroup;
|
||||||
|
children = (
|
||||||
|
0BEA5C271F7B8F73000D0AB4 /* Interface.storyboard */,
|
||||||
|
0BEA5C2A1F7B8F73000D0AB4 /* Assets.xcassets */,
|
||||||
|
0BEA5C2C1F7B8F73000D0AB4 /* Info.plist */,
|
||||||
|
);
|
||||||
|
name = "Watch app";
|
||||||
|
path = watchos/app;
|
||||||
|
sourceTree = "<group>";
|
||||||
|
};
|
||||||
|
0BEA5C351F7B8F73000D0AB4 /* WatchKit extension */ = {
|
||||||
|
isa = PBXGroup;
|
||||||
|
children = (
|
||||||
|
0BEA5C361F7B8F73000D0AB4 /* InterfaceController.swift */,
|
||||||
|
0BEA5C381F7B8F73000D0AB4 /* ExtensionDelegate.swift */,
|
||||||
|
0BEA5C3A1F7B8F73000D0AB4 /* ComplicationController.swift */,
|
||||||
|
0BEA5C3C1F7B8F73000D0AB4 /* Assets.xcassets */,
|
||||||
|
0BEA5C3E1F7B8F73000D0AB4 /* Info.plist */,
|
||||||
|
0B70016F1F7C51CC005944F4 /* InCallController.swift */,
|
||||||
|
0B5418461F7C5D8C00A2DD86 /* MeetingRowController.swift */,
|
||||||
|
E58801132278944E008B0561 /* JitsiMeetContext.swift */,
|
||||||
|
E5C97B62227A1EB400199214 /* JitsiMeetCommands.swift */,
|
||||||
|
);
|
||||||
|
name = "WatchKit extension";
|
||||||
|
path = watchos/extension;
|
||||||
|
sourceTree = "<group>";
|
||||||
|
};
|
||||||
13B07FAE1A68108700A75B9A /* src */ = {
|
13B07FAE1A68108700A75B9A /* src */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
|
@ -118,6 +225,8 @@
|
||||||
83CBBA001A601CBA00E9B192 /* Products */,
|
83CBBA001A601CBA00E9B192 /* Products */,
|
||||||
13B07FAE1A68108700A75B9A /* src */,
|
13B07FAE1A68108700A75B9A /* src */,
|
||||||
5E96ADD5E49F3B3822EF9A52 /* Pods */,
|
5E96ADD5E49F3B3822EF9A52 /* Pods */,
|
||||||
|
0BEA5C261F7B8F73000D0AB4 /* Watch app */,
|
||||||
|
0BEA5C351F7B8F73000D0AB4 /* WatchKit extension */,
|
||||||
);
|
);
|
||||||
indentWidth = 2;
|
indentWidth = 2;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
|
@ -127,6 +236,8 @@
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
13B07F961A680F5B00A75B9A /* jitsi-meet.app */,
|
13B07F961A680F5B00A75B9A /* jitsi-meet.app */,
|
||||||
|
0BEA5C251F7B8F73000D0AB4 /* JitsiMeetCompanion.app */,
|
||||||
|
0BEA5C311F7B8F73000D0AB4 /* JitsiMeetCompanion Extension.appex */,
|
||||||
);
|
);
|
||||||
name = Products;
|
name = Products;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
|
@ -134,6 +245,41 @@
|
||||||
/* End PBXGroup section */
|
/* End PBXGroup section */
|
||||||
|
|
||||||
/* Begin PBXNativeTarget section */
|
/* Begin PBXNativeTarget section */
|
||||||
|
0BEA5C241F7B8F73000D0AB4 /* JitsiMeetCompanion */ = {
|
||||||
|
isa = PBXNativeTarget;
|
||||||
|
buildConfigurationList = 0BEA5C481F7B8F73000D0AB4 /* Build configuration list for PBXNativeTarget "JitsiMeetCompanion" */;
|
||||||
|
buildPhases = (
|
||||||
|
0BEA5C231F7B8F73000D0AB4 /* Resources */,
|
||||||
|
0BEA5C471F7B8F73000D0AB4 /* Embed App Extensions */,
|
||||||
|
1F021A8A5B056078665DE530 /* Frameworks */,
|
||||||
|
);
|
||||||
|
buildRules = (
|
||||||
|
);
|
||||||
|
dependencies = (
|
||||||
|
0BEA5C341F7B8F73000D0AB4 /* PBXTargetDependency */,
|
||||||
|
);
|
||||||
|
name = JitsiMeetCompanion;
|
||||||
|
productName = JitsiMeetCompanion;
|
||||||
|
productReference = 0BEA5C251F7B8F73000D0AB4 /* JitsiMeetCompanion.app */;
|
||||||
|
productType = "com.apple.product-type.application.watchapp2";
|
||||||
|
};
|
||||||
|
0BEA5C301F7B8F73000D0AB4 /* JitsiMeetCompanion Extension */ = {
|
||||||
|
isa = PBXNativeTarget;
|
||||||
|
buildConfigurationList = 0BEA5C461F7B8F73000D0AB4 /* Build configuration list for PBXNativeTarget "JitsiMeetCompanion Extension" */;
|
||||||
|
buildPhases = (
|
||||||
|
0BEA5C2D1F7B8F73000D0AB4 /* Sources */,
|
||||||
|
0BEA5C2E1F7B8F73000D0AB4 /* Frameworks */,
|
||||||
|
0BEA5C2F1F7B8F73000D0AB4 /* Resources */,
|
||||||
|
);
|
||||||
|
buildRules = (
|
||||||
|
);
|
||||||
|
dependencies = (
|
||||||
|
);
|
||||||
|
name = "JitsiMeetCompanion Extension";
|
||||||
|
productName = "JitsiMeetCompanion Extension";
|
||||||
|
productReference = 0BEA5C311F7B8F73000D0AB4 /* JitsiMeetCompanion Extension.appex */;
|
||||||
|
productType = "com.apple.product-type.watchkit2-extension";
|
||||||
|
};
|
||||||
13B07F861A680F5B00A75B9A /* jitsi-meet */ = {
|
13B07F861A680F5B00A75B9A /* jitsi-meet */ = {
|
||||||
isa = PBXNativeTarget;
|
isa = PBXNativeTarget;
|
||||||
buildConfigurationList = 13B07F931A680F5B00A75B9A /* Build configuration list for PBXNativeTarget "jitsi-meet" */;
|
buildConfigurationList = 13B07F931A680F5B00A75B9A /* Build configuration list for PBXNativeTarget "jitsi-meet" */;
|
||||||
|
@ -150,10 +296,12 @@
|
||||||
DEC2069321CBBD6900072F03 /* Setup Fabric */,
|
DEC2069321CBBD6900072F03 /* Setup Fabric */,
|
||||||
DE11877A21EE09640078D059 /* Setup Google reverse URL handler */,
|
DE11877A21EE09640078D059 /* Setup Google reverse URL handler */,
|
||||||
DE4F6D6E22005C0400DE699E /* Setup Dropbox */,
|
DE4F6D6E22005C0400DE699E /* Setup Dropbox */,
|
||||||
|
0BEA5C491F7B8F73000D0AB4 /* Embed Watch Content */,
|
||||||
);
|
);
|
||||||
buildRules = (
|
buildRules = (
|
||||||
);
|
);
|
||||||
dependencies = (
|
dependencies = (
|
||||||
|
0BEA5C401F7B8F73000D0AB4 /* PBXTargetDependency */,
|
||||||
);
|
);
|
||||||
name = "jitsi-meet";
|
name = "jitsi-meet";
|
||||||
productName = "Jitsi Meet";
|
productName = "Jitsi Meet";
|
||||||
|
@ -169,6 +317,16 @@
|
||||||
LastUpgradeCheck = 1020;
|
LastUpgradeCheck = 1020;
|
||||||
ORGANIZATIONNAME = Facebook;
|
ORGANIZATIONNAME = Facebook;
|
||||||
TargetAttributes = {
|
TargetAttributes = {
|
||||||
|
0BEA5C241F7B8F73000D0AB4 = {
|
||||||
|
CreatedOnToolsVersion = 9.0;
|
||||||
|
DevelopmentTeam = FC967L3QRG;
|
||||||
|
ProvisioningStyle = Automatic;
|
||||||
|
};
|
||||||
|
0BEA5C301F7B8F73000D0AB4 = {
|
||||||
|
CreatedOnToolsVersion = 9.0;
|
||||||
|
DevelopmentTeam = FC967L3QRG;
|
||||||
|
ProvisioningStyle = Automatic;
|
||||||
|
};
|
||||||
13B07F861A680F5B00A75B9A = {
|
13B07F861A680F5B00A75B9A = {
|
||||||
DevelopmentTeam = FC967L3QRG;
|
DevelopmentTeam = FC967L3QRG;
|
||||||
ProvisioningStyle = Automatic;
|
ProvisioningStyle = Automatic;
|
||||||
|
@ -197,11 +355,30 @@
|
||||||
projectRoot = "";
|
projectRoot = "";
|
||||||
targets = (
|
targets = (
|
||||||
13B07F861A680F5B00A75B9A /* jitsi-meet */,
|
13B07F861A680F5B00A75B9A /* jitsi-meet */,
|
||||||
|
0BEA5C241F7B8F73000D0AB4 /* JitsiMeetCompanion */,
|
||||||
|
0BEA5C301F7B8F73000D0AB4 /* JitsiMeetCompanion Extension */,
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
/* End PBXProject section */
|
/* End PBXProject section */
|
||||||
|
|
||||||
/* Begin PBXResourcesBuildPhase section */
|
/* Begin PBXResourcesBuildPhase section */
|
||||||
|
0BEA5C231F7B8F73000D0AB4 /* Resources */ = {
|
||||||
|
isa = PBXResourcesBuildPhase;
|
||||||
|
buildActionMask = 2147483647;
|
||||||
|
files = (
|
||||||
|
0BEA5C2B1F7B8F73000D0AB4 /* Assets.xcassets in Resources */,
|
||||||
|
0BEA5C291F7B8F73000D0AB4 /* Interface.storyboard in Resources */,
|
||||||
|
);
|
||||||
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
|
};
|
||||||
|
0BEA5C2F1F7B8F73000D0AB4 /* Resources */ = {
|
||||||
|
isa = PBXResourcesBuildPhase;
|
||||||
|
buildActionMask = 2147483647;
|
||||||
|
files = (
|
||||||
|
0BEA5C3D1F7B8F73000D0AB4 /* Assets.xcassets in Resources */,
|
||||||
|
);
|
||||||
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
|
};
|
||||||
13B07F8E1A680F5B00A75B9A /* Resources */ = {
|
13B07F8E1A680F5B00A75B9A /* Resources */ = {
|
||||||
isa = PBXResourcesBuildPhase;
|
isa = PBXResourcesBuildPhase;
|
||||||
buildActionMask = 2147483647;
|
buildActionMask = 2147483647;
|
||||||
|
@ -354,6 +531,20 @@
|
||||||
/* End PBXShellScriptBuildPhase section */
|
/* End PBXShellScriptBuildPhase section */
|
||||||
|
|
||||||
/* Begin PBXSourcesBuildPhase section */
|
/* Begin PBXSourcesBuildPhase section */
|
||||||
|
0BEA5C2D1F7B8F73000D0AB4 /* Sources */ = {
|
||||||
|
isa = PBXSourcesBuildPhase;
|
||||||
|
buildActionMask = 2147483647;
|
||||||
|
files = (
|
||||||
|
0B7001701F7C51CC005944F4 /* InCallController.swift in Sources */,
|
||||||
|
E5C97B63227A1EB400199214 /* JitsiMeetCommands.swift in Sources */,
|
||||||
|
0B5418471F7C5D8C00A2DD86 /* MeetingRowController.swift in Sources */,
|
||||||
|
E588011722789D43008B0561 /* JitsiMeetContext.swift in Sources */,
|
||||||
|
0BEA5C391F7B8F73000D0AB4 /* ExtensionDelegate.swift in Sources */,
|
||||||
|
0BEA5C371F7B8F73000D0AB4 /* InterfaceController.swift in Sources */,
|
||||||
|
0BEA5C3B1F7B8F73000D0AB4 /* ComplicationController.swift in Sources */,
|
||||||
|
);
|
||||||
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
|
};
|
||||||
13B07F871A680F5B00A75B9A /* Sources */ = {
|
13B07F871A680F5B00A75B9A /* Sources */ = {
|
||||||
isa = PBXSourcesBuildPhase;
|
isa = PBXSourcesBuildPhase;
|
||||||
buildActionMask = 2147483647;
|
buildActionMask = 2147483647;
|
||||||
|
@ -367,7 +558,28 @@
|
||||||
};
|
};
|
||||||
/* End PBXSourcesBuildPhase section */
|
/* End PBXSourcesBuildPhase section */
|
||||||
|
|
||||||
|
/* Begin PBXTargetDependency section */
|
||||||
|
0BEA5C341F7B8F73000D0AB4 /* PBXTargetDependency */ = {
|
||||||
|
isa = PBXTargetDependency;
|
||||||
|
target = 0BEA5C301F7B8F73000D0AB4 /* JitsiMeetCompanion Extension */;
|
||||||
|
targetProxy = 0BEA5C331F7B8F73000D0AB4 /* PBXContainerItemProxy */;
|
||||||
|
};
|
||||||
|
0BEA5C401F7B8F73000D0AB4 /* PBXTargetDependency */ = {
|
||||||
|
isa = PBXTargetDependency;
|
||||||
|
target = 0BEA5C241F7B8F73000D0AB4 /* JitsiMeetCompanion */;
|
||||||
|
targetProxy = 0BEA5C3F1F7B8F73000D0AB4 /* PBXContainerItemProxy */;
|
||||||
|
};
|
||||||
|
/* End PBXTargetDependency section */
|
||||||
|
|
||||||
/* Begin PBXVariantGroup section */
|
/* Begin PBXVariantGroup section */
|
||||||
|
0BEA5C271F7B8F73000D0AB4 /* Interface.storyboard */ = {
|
||||||
|
isa = PBXVariantGroup;
|
||||||
|
children = (
|
||||||
|
0BEA5C281F7B8F73000D0AB4 /* Base */,
|
||||||
|
);
|
||||||
|
name = Interface.storyboard;
|
||||||
|
sourceTree = "<group>";
|
||||||
|
};
|
||||||
13B07FB11A68108700A75B9A /* LaunchScreen.xib */ = {
|
13B07FB11A68108700A75B9A /* LaunchScreen.xib */ = {
|
||||||
isa = PBXVariantGroup;
|
isa = PBXVariantGroup;
|
||||||
children = (
|
children = (
|
||||||
|
@ -379,6 +591,140 @@
|
||||||
/* End PBXVariantGroup section */
|
/* End PBXVariantGroup section */
|
||||||
|
|
||||||
/* Begin XCBuildConfiguration section */
|
/* Begin XCBuildConfiguration section */
|
||||||
|
0BEA5C421F7B8F73000D0AB4 /* Debug */ = {
|
||||||
|
isa = XCBuildConfiguration;
|
||||||
|
buildSettings = {
|
||||||
|
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
|
||||||
|
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||||
|
CLANG_ANALYZER_NONNULL = YES;
|
||||||
|
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
|
||||||
|
CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
|
||||||
|
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
|
||||||
|
CLANG_WARN_COMMA = YES;
|
||||||
|
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
|
||||||
|
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
|
||||||
|
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
|
||||||
|
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
|
||||||
|
CLANG_WARN_STRICT_PROTOTYPES = YES;
|
||||||
|
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
|
||||||
|
CODE_SIGN_STYLE = Automatic;
|
||||||
|
DEBUG_INFORMATION_FORMAT = dwarf;
|
||||||
|
DEVELOPMENT_TEAM = FC967L3QRG;
|
||||||
|
GCC_C_LANGUAGE_STANDARD = gnu11;
|
||||||
|
IBSC_MODULE = JitsiMeetCompanion_Extension;
|
||||||
|
INFOPLIST_FILE = watchos/app/Info.plist;
|
||||||
|
PRODUCT_BUNDLE_IDENTIFIER = org.jitsi.meet.watchkit;
|
||||||
|
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||||
|
SDKROOT = watchos;
|
||||||
|
SKIP_INSTALL = YES;
|
||||||
|
SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
|
||||||
|
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
|
||||||
|
SWIFT_VERSION = 5.0;
|
||||||
|
TARGETED_DEVICE_FAMILY = 4;
|
||||||
|
WATCHOS_DEPLOYMENT_TARGET = 4.0;
|
||||||
|
};
|
||||||
|
name = Debug;
|
||||||
|
};
|
||||||
|
0BEA5C431F7B8F73000D0AB4 /* Release */ = {
|
||||||
|
isa = XCBuildConfiguration;
|
||||||
|
buildSettings = {
|
||||||
|
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
|
||||||
|
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||||
|
CLANG_ANALYZER_NONNULL = YES;
|
||||||
|
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
|
||||||
|
CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
|
||||||
|
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
|
||||||
|
CLANG_WARN_COMMA = YES;
|
||||||
|
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
|
||||||
|
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
|
||||||
|
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
|
||||||
|
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
|
||||||
|
CLANG_WARN_STRICT_PROTOTYPES = YES;
|
||||||
|
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
|
||||||
|
CODE_SIGN_STYLE = Automatic;
|
||||||
|
COPY_PHASE_STRIP = NO;
|
||||||
|
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
|
||||||
|
DEVELOPMENT_TEAM = FC967L3QRG;
|
||||||
|
GCC_C_LANGUAGE_STANDARD = gnu11;
|
||||||
|
IBSC_MODULE = JitsiMeetCompanion_Extension;
|
||||||
|
INFOPLIST_FILE = watchos/app/Info.plist;
|
||||||
|
PRODUCT_BUNDLE_IDENTIFIER = org.jitsi.meet.watchkit;
|
||||||
|
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||||
|
SDKROOT = watchos;
|
||||||
|
SKIP_INSTALL = YES;
|
||||||
|
SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule";
|
||||||
|
SWIFT_VERSION = 5.0;
|
||||||
|
TARGETED_DEVICE_FAMILY = 4;
|
||||||
|
WATCHOS_DEPLOYMENT_TARGET = 4.0;
|
||||||
|
};
|
||||||
|
name = Release;
|
||||||
|
};
|
||||||
|
0BEA5C441F7B8F73000D0AB4 /* Debug */ = {
|
||||||
|
isa = XCBuildConfiguration;
|
||||||
|
buildSettings = {
|
||||||
|
ASSETCATALOG_COMPILER_COMPLICATION_NAME = Complication;
|
||||||
|
CLANG_ANALYZER_NONNULL = YES;
|
||||||
|
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
|
||||||
|
CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
|
||||||
|
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
|
||||||
|
CLANG_WARN_COMMA = YES;
|
||||||
|
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
|
||||||
|
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
|
||||||
|
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
|
||||||
|
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
|
||||||
|
CLANG_WARN_STRICT_PROTOTYPES = YES;
|
||||||
|
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
|
||||||
|
CODE_SIGN_STYLE = Automatic;
|
||||||
|
DEBUG_INFORMATION_FORMAT = dwarf;
|
||||||
|
DEVELOPMENT_TEAM = FC967L3QRG;
|
||||||
|
GCC_C_LANGUAGE_STANDARD = gnu11;
|
||||||
|
INFOPLIST_FILE = watchos/extension/Info.plist;
|
||||||
|
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @executable_path/../../Frameworks";
|
||||||
|
PRODUCT_BUNDLE_IDENTIFIER = org.jitsi.meet.watchkit.extension;
|
||||||
|
PRODUCT_NAME = "${TARGET_NAME}";
|
||||||
|
SDKROOT = watchos;
|
||||||
|
SKIP_INSTALL = YES;
|
||||||
|
SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
|
||||||
|
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
|
||||||
|
SWIFT_VERSION = 5.0;
|
||||||
|
TARGETED_DEVICE_FAMILY = 4;
|
||||||
|
WATCHOS_DEPLOYMENT_TARGET = 4.0;
|
||||||
|
};
|
||||||
|
name = Debug;
|
||||||
|
};
|
||||||
|
0BEA5C451F7B8F73000D0AB4 /* Release */ = {
|
||||||
|
isa = XCBuildConfiguration;
|
||||||
|
buildSettings = {
|
||||||
|
ASSETCATALOG_COMPILER_COMPLICATION_NAME = Complication;
|
||||||
|
CLANG_ANALYZER_NONNULL = YES;
|
||||||
|
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
|
||||||
|
CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
|
||||||
|
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
|
||||||
|
CLANG_WARN_COMMA = YES;
|
||||||
|
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
|
||||||
|
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
|
||||||
|
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
|
||||||
|
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
|
||||||
|
CLANG_WARN_STRICT_PROTOTYPES = YES;
|
||||||
|
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
|
||||||
|
CODE_SIGN_STYLE = Automatic;
|
||||||
|
COPY_PHASE_STRIP = NO;
|
||||||
|
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
|
||||||
|
DEVELOPMENT_TEAM = FC967L3QRG;
|
||||||
|
GCC_C_LANGUAGE_STANDARD = gnu11;
|
||||||
|
INFOPLIST_FILE = watchos/extension/Info.plist;
|
||||||
|
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @executable_path/../../Frameworks";
|
||||||
|
PRODUCT_BUNDLE_IDENTIFIER = org.jitsi.meet.watchkit.extension;
|
||||||
|
PRODUCT_NAME = "${TARGET_NAME}";
|
||||||
|
SDKROOT = watchos;
|
||||||
|
SKIP_INSTALL = YES;
|
||||||
|
SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule";
|
||||||
|
SWIFT_VERSION = 5.0;
|
||||||
|
TARGETED_DEVICE_FAMILY = 4;
|
||||||
|
WATCHOS_DEPLOYMENT_TARGET = 4.0;
|
||||||
|
};
|
||||||
|
name = Release;
|
||||||
|
};
|
||||||
13B07F941A680F5B00A75B9A /* Debug */ = {
|
13B07F941A680F5B00A75B9A /* Debug */ = {
|
||||||
isa = XCBuildConfiguration;
|
isa = XCBuildConfiguration;
|
||||||
baseConfigurationReference = 4670A512A688E2DC34528282 /* Pods-jitsi-meet.debug.xcconfig */;
|
baseConfigurationReference = 4670A512A688E2DC34528282 /* Pods-jitsi-meet.debug.xcconfig */;
|
||||||
|
@ -566,6 +912,24 @@
|
||||||
/* End XCBuildConfiguration section */
|
/* End XCBuildConfiguration section */
|
||||||
|
|
||||||
/* Begin XCConfigurationList section */
|
/* Begin XCConfigurationList section */
|
||||||
|
0BEA5C461F7B8F73000D0AB4 /* Build configuration list for PBXNativeTarget "JitsiMeetCompanion Extension" */ = {
|
||||||
|
isa = XCConfigurationList;
|
||||||
|
buildConfigurations = (
|
||||||
|
0BEA5C441F7B8F73000D0AB4 /* Debug */,
|
||||||
|
0BEA5C451F7B8F73000D0AB4 /* Release */,
|
||||||
|
);
|
||||||
|
defaultConfigurationIsVisible = 0;
|
||||||
|
defaultConfigurationName = Release;
|
||||||
|
};
|
||||||
|
0BEA5C481F7B8F73000D0AB4 /* Build configuration list for PBXNativeTarget "JitsiMeetCompanion" */ = {
|
||||||
|
isa = XCConfigurationList;
|
||||||
|
buildConfigurations = (
|
||||||
|
0BEA5C421F7B8F73000D0AB4 /* Debug */,
|
||||||
|
0BEA5C431F7B8F73000D0AB4 /* Release */,
|
||||||
|
);
|
||||||
|
defaultConfigurationIsVisible = 0;
|
||||||
|
defaultConfigurationName = Release;
|
||||||
|
};
|
||||||
13B07F931A680F5B00A75B9A /* Build configuration list for PBXNativeTarget "jitsi-meet" */ = {
|
13B07F931A680F5B00A75B9A /* Build configuration list for PBXNativeTarget "jitsi-meet" */ = {
|
||||||
isa = XCConfigurationList;
|
isa = XCConfigurationList;
|
||||||
buildConfigurations = (
|
buildConfigurations = (
|
||||||
|
|
|
@ -0,0 +1,92 @@
|
||||||
|
{
|
||||||
|
"images" : [
|
||||||
|
{
|
||||||
|
"size" : "24x24",
|
||||||
|
"idiom" : "watch",
|
||||||
|
"filename" : "Icon-24@2x.png",
|
||||||
|
"scale" : "2x",
|
||||||
|
"role" : "notificationCenter",
|
||||||
|
"subtype" : "38mm"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"size" : "27.5x27.5",
|
||||||
|
"idiom" : "watch",
|
||||||
|
"filename" : "Icon-27.5@2x.png",
|
||||||
|
"scale" : "2x",
|
||||||
|
"role" : "notificationCenter",
|
||||||
|
"subtype" : "42mm"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"size" : "29x29",
|
||||||
|
"idiom" : "watch",
|
||||||
|
"filename" : "Icon-29@2x.png",
|
||||||
|
"role" : "companionSettings",
|
||||||
|
"scale" : "2x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"size" : "29x29",
|
||||||
|
"idiom" : "watch",
|
||||||
|
"filename" : "Icon-29@3x.png",
|
||||||
|
"role" : "companionSettings",
|
||||||
|
"scale" : "3x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"size" : "40x40",
|
||||||
|
"idiom" : "watch",
|
||||||
|
"filename" : "Icon-40@2x.png",
|
||||||
|
"scale" : "2x",
|
||||||
|
"role" : "appLauncher",
|
||||||
|
"subtype" : "38mm"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"size" : "44x44",
|
||||||
|
"idiom" : "watch",
|
||||||
|
"filename" : "Icon-88@2x.png",
|
||||||
|
"scale" : "2x",
|
||||||
|
"role" : "appLauncher",
|
||||||
|
"subtype" : "40mm"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"size" : "50x50",
|
||||||
|
"idiom" : "watch",
|
||||||
|
"filename" : "Icon-100@2x.png",
|
||||||
|
"scale" : "2x",
|
||||||
|
"role" : "appLauncher",
|
||||||
|
"subtype" : "44mm"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"size" : "86x86",
|
||||||
|
"idiom" : "watch",
|
||||||
|
"filename" : "Icon-86@2x.png",
|
||||||
|
"scale" : "2x",
|
||||||
|
"role" : "quickLook",
|
||||||
|
"subtype" : "38mm"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"size" : "98x98",
|
||||||
|
"idiom" : "watch",
|
||||||
|
"filename" : "Icon-98@2x.png",
|
||||||
|
"scale" : "2x",
|
||||||
|
"role" : "quickLook",
|
||||||
|
"subtype" : "42mm"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"size" : "108x108",
|
||||||
|
"idiom" : "watch",
|
||||||
|
"filename" : "Icon-216@2x.png",
|
||||||
|
"scale" : "2x",
|
||||||
|
"role" : "quickLook",
|
||||||
|
"subtype" : "44mm"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"size" : "1024x1024",
|
||||||
|
"idiom" : "watch-marketing",
|
||||||
|
"filename" : "Icon-1024@1x.png",
|
||||||
|
"scale" : "1x"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"info" : {
|
||||||
|
"version" : 1,
|
||||||
|
"author" : "xcode"
|
||||||
|
}
|
||||||
|
}
|
After Width: | Height: | Size: 8.3 KiB |
After Width: | Height: | Size: 158 KiB |
After Width: | Height: | Size: 25 KiB |
After Width: | Height: | Size: 2.5 KiB |
After Width: | Height: | Size: 3.1 KiB |
After Width: | Height: | Size: 3.3 KiB |
After Width: | Height: | Size: 5.9 KiB |
After Width: | Height: | Size: 5.2 KiB |
After Width: | Height: | Size: 15 KiB |
After Width: | Height: | Size: 7.3 KiB |
After Width: | Height: | Size: 18 KiB |
|
@ -0,0 +1,6 @@
|
||||||
|
{
|
||||||
|
"info" : {
|
||||||
|
"version" : 1,
|
||||||
|
"author" : "xcode"
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,21 @@
|
||||||
|
{
|
||||||
|
"images" : [
|
||||||
|
{
|
||||||
|
"idiom" : "universal",
|
||||||
|
"scale" : "1x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"idiom" : "universal",
|
||||||
|
"filename" : "hangup@2x.png",
|
||||||
|
"scale" : "2x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"idiom" : "universal",
|
||||||
|
"scale" : "3x"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"info" : {
|
||||||
|
"version" : 1,
|
||||||
|
"author" : "xcode"
|
||||||
|
}
|
||||||
|
}
|
After Width: | Height: | Size: 6.5 KiB |
|
@ -0,0 +1,21 @@
|
||||||
|
{
|
||||||
|
"images" : [
|
||||||
|
{
|
||||||
|
"idiom" : "universal",
|
||||||
|
"scale" : "1x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"idiom" : "universal",
|
||||||
|
"filename" : "mute-off@2x.png",
|
||||||
|
"scale" : "2x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"idiom" : "universal",
|
||||||
|
"scale" : "3x"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"info" : {
|
||||||
|
"version" : 1,
|
||||||
|
"author" : "xcode"
|
||||||
|
}
|
||||||
|
}
|
After Width: | Height: | Size: 11 KiB |
|
@ -0,0 +1,21 @@
|
||||||
|
{
|
||||||
|
"images" : [
|
||||||
|
{
|
||||||
|
"idiom" : "universal",
|
||||||
|
"scale" : "1x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"idiom" : "universal",
|
||||||
|
"filename" : "mute-on@2x.png",
|
||||||
|
"scale" : "2x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"idiom" : "universal",
|
||||||
|
"scale" : "3x"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"info" : {
|
||||||
|
"version" : 1,
|
||||||
|
"author" : "xcode"
|
||||||
|
}
|
||||||
|
}
|
After Width: | Height: | Size: 11 KiB |
|
@ -0,0 +1,83 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<document type="com.apple.InterfaceBuilder.WatchKit.Storyboard" version="3.0" toolsVersion="14490.70" targetRuntime="watchKit" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES" initialViewController="AgC-eL-Hgc">
|
||||||
|
<device id="watch38" orientation="portrait">
|
||||||
|
<adaptation id="fullscreen"/>
|
||||||
|
</device>
|
||||||
|
<dependencies>
|
||||||
|
<deployment identifier="watchOS"/>
|
||||||
|
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="14490.49"/>
|
||||||
|
<plugIn identifier="com.apple.InterfaceBuilder.IBWatchKitPlugin" version="14490.21"/>
|
||||||
|
</dependencies>
|
||||||
|
<scenes>
|
||||||
|
<!--Meetings-->
|
||||||
|
<scene sceneID="aou-V4-d1y">
|
||||||
|
<objects>
|
||||||
|
<controller title="Meetings" id="AgC-eL-Hgc" customClass="InterfaceController" customModule="JitsiMeetCompanion" customModuleProvider="target">
|
||||||
|
<items>
|
||||||
|
<table alignment="left" id="gpO-ql-Xsr">
|
||||||
|
<items>
|
||||||
|
<tableRow identifier="MeetingRowType" id="GGl-av-xeJ" customClass="MeetingRowController" customModule="JitsiMeetCompanion_Extension">
|
||||||
|
<group key="rootItem" width="1" height="0.0" alignment="left" layout="vertical" id="5XE-gq-qzG">
|
||||||
|
<items>
|
||||||
|
<label alignment="left" text="Label" id="Sij-up-N4p"/>
|
||||||
|
<label alignment="left" text="Label" id="V5K-sm-jEH">
|
||||||
|
<color key="textColor" white="0.66666666666666663" alpha="1" colorSpace="calibratedWhite"/>
|
||||||
|
<fontDescription key="font" style="UICTFontTextStyleFootnote"/>
|
||||||
|
</label>
|
||||||
|
</items>
|
||||||
|
<connections>
|
||||||
|
<segue destination="9RD-qP-1Z0" kind="push" id="Boa-6E-eZs"/>
|
||||||
|
</connections>
|
||||||
|
</group>
|
||||||
|
<connections>
|
||||||
|
<outlet property="roomLabel" destination="Sij-up-N4p" id="PdS-SO-ylc"/>
|
||||||
|
<outlet property="rowGroup" destination="5XE-gq-qzG" id="GZN-2c-2Gz"/>
|
||||||
|
<outlet property="timeLabel" destination="V5K-sm-jEH" id="fWQ-kx-vE4"/>
|
||||||
|
</connections>
|
||||||
|
</tableRow>
|
||||||
|
</items>
|
||||||
|
</table>
|
||||||
|
</items>
|
||||||
|
<connections>
|
||||||
|
<outlet property="table" destination="gpO-ql-Xsr" id="aVV-iZ-z3l"/>
|
||||||
|
</connections>
|
||||||
|
</controller>
|
||||||
|
</objects>
|
||||||
|
<point key="canvasLocation" x="-99" y="117"/>
|
||||||
|
</scene>
|
||||||
|
<!--Meetings-->
|
||||||
|
<scene sceneID="ns4-Kh-qqU">
|
||||||
|
<objects>
|
||||||
|
<controller identifier="InCallController" title="Meetings" hidesWhenLoading="NO" id="9RD-qP-1Z0" customClass="InCallController" customModule="JitsiMeetCompanion" customModuleProvider="target">
|
||||||
|
<items>
|
||||||
|
<label alignment="center" text="Label" id="vFt-lL-SNY"/>
|
||||||
|
<timer alignment="center" textAlignment="center" previewedSeconds="0" id="W8S-uZ-MPm">
|
||||||
|
<color key="textColor" red="0.024725984125768763" green="1" blue="0.24241188365329402" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||||
|
<fontDescription key="font" style="UICTFontTextStyleHeadline"/>
|
||||||
|
</timer>
|
||||||
|
<group alignment="center" verticalAlignment="bottom" spacing="10" id="Hfk-a0-uWj">
|
||||||
|
<items>
|
||||||
|
<button width="60" height="60" alignment="left" verticalAlignment="bottom" backgroundImage="hangup" id="8jF-SI-UHz">
|
||||||
|
<connections>
|
||||||
|
<action selector="hangupClicked" destination="9RD-qP-1Z0" id="cXK-lw-tsd"/>
|
||||||
|
</connections>
|
||||||
|
</button>
|
||||||
|
<button width="60" height="60" alignment="right" verticalAlignment="bottom" backgroundImage="mute-off" id="LmN-FI-aQq">
|
||||||
|
<connections>
|
||||||
|
<action selector="muteClicked" destination="9RD-qP-1Z0" id="dJg-kV-cqH"/>
|
||||||
|
</connections>
|
||||||
|
</button>
|
||||||
|
</items>
|
||||||
|
</group>
|
||||||
|
</items>
|
||||||
|
<connections>
|
||||||
|
<outlet property="mutedButton" destination="LmN-FI-aQq" id="gfi-4T-gdN"/>
|
||||||
|
<outlet property="roomLabel" destination="vFt-lL-SNY" id="cYB-Tf-Efz"/>
|
||||||
|
<outlet property="timer" destination="W8S-uZ-MPm" id="r7T-j1-9VJ"/>
|
||||||
|
</connections>
|
||||||
|
</controller>
|
||||||
|
</objects>
|
||||||
|
<point key="canvasLocation" x="213" y="117"/>
|
||||||
|
</scene>
|
||||||
|
</scenes>
|
||||||
|
</document>
|
|
@ -0,0 +1,33 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||||
|
<plist version="1.0">
|
||||||
|
<dict>
|
||||||
|
<key>CFBundleDevelopmentRegion</key>
|
||||||
|
<string>$(DEVELOPMENT_LANGUAGE)</string>
|
||||||
|
<key>CFBundleDisplayName</key>
|
||||||
|
<string>Jitsi Meet</string>
|
||||||
|
<key>CFBundleExecutable</key>
|
||||||
|
<string>$(EXECUTABLE_NAME)</string>
|
||||||
|
<key>CFBundleIdentifier</key>
|
||||||
|
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
|
||||||
|
<key>CFBundleInfoDictionaryVersion</key>
|
||||||
|
<string>6.0</string>
|
||||||
|
<key>CFBundleName</key>
|
||||||
|
<string>$(PRODUCT_NAME)</string>
|
||||||
|
<key>CFBundlePackageType</key>
|
||||||
|
<string>APPL</string>
|
||||||
|
<key>CFBundleShortVersionString</key>
|
||||||
|
<string>19.2.0</string>
|
||||||
|
<key>CFBundleVersion</key>
|
||||||
|
<string>1</string>
|
||||||
|
<key>UISupportedInterfaceOrientations</key>
|
||||||
|
<array>
|
||||||
|
<string>UIInterfaceOrientationPortrait</string>
|
||||||
|
<string>UIInterfaceOrientationPortraitUpsideDown</string>
|
||||||
|
</array>
|
||||||
|
<key>WKCompanionAppBundleIdentifier</key>
|
||||||
|
<string>org.jitsi.meet</string>
|
||||||
|
<key>WKWatchKitApp</key>
|
||||||
|
<true/>
|
||||||
|
</dict>
|
||||||
|
</plist>
|
|
@ -0,0 +1,6 @@
|
||||||
|
{
|
||||||
|
"info" : {
|
||||||
|
"version" : 1,
|
||||||
|
"author" : "xcode"
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,21 @@
|
||||||
|
{
|
||||||
|
"images" : [
|
||||||
|
{
|
||||||
|
"idiom" : "universal",
|
||||||
|
"scale" : "1x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"idiom" : "universal",
|
||||||
|
"filename" : "jitsi@2x.png",
|
||||||
|
"scale" : "2x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"idiom" : "universal",
|
||||||
|
"scale" : "3x"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"info" : {
|
||||||
|
"version" : 1,
|
||||||
|
"author" : "xcode"
|
||||||
|
}
|
||||||
|
}
|
After Width: | Height: | Size: 2.0 KiB |
|
@ -0,0 +1,81 @@
|
||||||
|
/*
|
||||||
|
* Copyright @ 2018-present 8x8, Inc.
|
||||||
|
* Copyright @ 2017-2018 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 ClockKit
|
||||||
|
|
||||||
|
|
||||||
|
class ComplicationController: NSObject, CLKComplicationDataSource {
|
||||||
|
|
||||||
|
// MARK: - Timeline Configuration
|
||||||
|
|
||||||
|
func getSupportedTimeTravelDirections(for complication: CLKComplication, withHandler handler: @escaping (CLKComplicationTimeTravelDirections) -> Void) {
|
||||||
|
handler([])
|
||||||
|
}
|
||||||
|
|
||||||
|
func getPrivacyBehavior(for complication: CLKComplication, withHandler handler: @escaping (CLKComplicationPrivacyBehavior) -> Void) {
|
||||||
|
handler(.showOnLockScreen)
|
||||||
|
}
|
||||||
|
|
||||||
|
// MARK: - Timeline Population
|
||||||
|
|
||||||
|
func getCurrentTimelineEntry(for complication: CLKComplication, withHandler handler: @escaping (CLKComplicationTimelineEntry?) -> Void) {
|
||||||
|
// Call the handler with the current timeline entry
|
||||||
|
getLocalizableSampleTemplate(for: complication) {template in
|
||||||
|
guard let template = template else {
|
||||||
|
handler(nil)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
handler(CLKComplicationTimelineEntry(date: Date(), complicationTemplate: template))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func getTimelineEntries(for complication: CLKComplication, before date: Date, limit: Int, withHandler handler: @escaping ([CLKComplicationTimelineEntry]?) -> Void) {
|
||||||
|
// Call the handler with the timeline entries prior to the given date
|
||||||
|
handler(nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
func getTimelineEntries(for complication: CLKComplication, after date: Date, limit: Int, withHandler handler: @escaping ([CLKComplicationTimelineEntry]?) -> Void) {
|
||||||
|
// Call the handler with the timeline entries after to the given date
|
||||||
|
handler(nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
// MARK: - Placeholder Templates
|
||||||
|
|
||||||
|
func getLocalizableSampleTemplate(for complication: CLKComplication, withHandler handler: @escaping (CLKComplicationTemplate?) -> Void) {
|
||||||
|
// This method will be called once per supported complication, and the results will be cached
|
||||||
|
|
||||||
|
let imageProvider = CLKImageProvider(onePieceImage: UIImage(named: "jitsi")!)
|
||||||
|
if complication.family == .circularSmall {
|
||||||
|
let small = CLKComplicationTemplateCircularSmallRingImage()
|
||||||
|
small.imageProvider = imageProvider
|
||||||
|
small.ringStyle = .closed
|
||||||
|
small.fillFraction = 0
|
||||||
|
handler(small)
|
||||||
|
} else if complication.family == .utilitarianSmall {
|
||||||
|
let utilitarian = CLKComplicationTemplateUtilitarianSmallSquare()
|
||||||
|
utilitarian.imageProvider = imageProvider
|
||||||
|
handler(utilitarian)
|
||||||
|
} else if complication.family == .modularSmall {
|
||||||
|
let modular = CLKComplicationTemplateModularSmallRingImage()
|
||||||
|
modular.imageProvider = imageProvider
|
||||||
|
modular.ringStyle = .closed
|
||||||
|
modular.fillFraction = 0
|
||||||
|
handler(modular)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,103 @@
|
||||||
|
/*
|
||||||
|
* Copyright @ 2018-present 8x8, Inc.
|
||||||
|
* Copyright @ 2017-2018 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 WatchConnectivity
|
||||||
|
import WatchKit
|
||||||
|
|
||||||
|
class ExtensionDelegate: NSObject, WCSessionDelegate, WKExtensionDelegate {
|
||||||
|
|
||||||
|
var currentContext : JitsiMeetContext = JitsiMeetContext()
|
||||||
|
|
||||||
|
static var currentJitsiMeetContext: JitsiMeetContext {
|
||||||
|
get {
|
||||||
|
return (WKExtension.shared().delegate as! ExtensionDelegate).currentContext
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func applicationDidFinishLaunching() {
|
||||||
|
// Start Watch Connectivity
|
||||||
|
if WCSession.isSupported() {
|
||||||
|
let session = WCSession.default
|
||||||
|
session.delegate = self
|
||||||
|
session.activate()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func handle(_ backgroundTasks: Set<WKRefreshBackgroundTask>) {
|
||||||
|
// Sent when the system needs to launch the application in the background to process tasks. Tasks arrive in a set, so loop through and process each one.
|
||||||
|
for task in backgroundTasks {
|
||||||
|
// Use a switch statement to check the task type
|
||||||
|
switch task {
|
||||||
|
case let backgroundTask as WKApplicationRefreshBackgroundTask:
|
||||||
|
// Be sure to complete the background task once you’re done.
|
||||||
|
backgroundTask.setTaskCompletedWithSnapshot(false)
|
||||||
|
case let snapshotTask as WKSnapshotRefreshBackgroundTask:
|
||||||
|
// Snapshot tasks have a unique completion call, make sure to set your expiration date
|
||||||
|
snapshotTask.setTaskCompleted(restoredDefaultState: true, estimatedSnapshotExpiration: Date.distantFuture, userInfo: nil)
|
||||||
|
case let connectivityTask as WKWatchConnectivityRefreshBackgroundTask:
|
||||||
|
// Be sure to complete the connectivity task once you’re done.
|
||||||
|
connectivityTask.setTaskCompletedWithSnapshot(false)
|
||||||
|
case let urlSessionTask as WKURLSessionRefreshBackgroundTask:
|
||||||
|
// Be sure to complete the URL session task once you’re done.
|
||||||
|
urlSessionTask.setTaskCompletedWithSnapshot(false)
|
||||||
|
default:
|
||||||
|
// make sure to complete unhandled task types
|
||||||
|
task.setTaskCompletedWithSnapshot(false)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func session(_ session: WCSession, activationDidCompleteWith
|
||||||
|
activationState: WCSessionActivationState, error: Error?) {
|
||||||
|
if let error = error {
|
||||||
|
print("WATCH Session activation failed with error: \(error.localizedDescription)")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
print("WATCH Session activated with state: \(activationState.rawValue)")
|
||||||
|
}
|
||||||
|
|
||||||
|
func session(_ session: WCSession, didReceiveApplicationContext applicationContext: [String : Any]) {
|
||||||
|
DispatchQueue.main.async {
|
||||||
|
let newContext = JitsiMeetContext(context: applicationContext)
|
||||||
|
|
||||||
|
print("WATCH got new context: \(newContext.description)");
|
||||||
|
|
||||||
|
// Update context on the root controller which displays the recent list
|
||||||
|
let controller = WKExtension.shared().rootInterfaceController as! InterfaceController
|
||||||
|
controller.updateUI(newContext)
|
||||||
|
|
||||||
|
// If the current controller is not the in-call controller and we have a
|
||||||
|
// conference URL, show the in-call controller
|
||||||
|
if let currentController = WKExtension.shared().visibleInterfaceController as? InterfaceController {
|
||||||
|
// Go to the in-call controller only if the conference URL has changed, because the user may have
|
||||||
|
// clicked the back button
|
||||||
|
if newContext.conferenceURL != nil
|
||||||
|
&& self.currentContext.conferenceURL != newContext.conferenceURL {
|
||||||
|
currentController.pushController(withName: "InCallController", context: newContext)
|
||||||
|
}
|
||||||
|
} else if let inCallController = WKExtension.shared().visibleInterfaceController as? InCallController {
|
||||||
|
if newContext.conferenceURL == nil {
|
||||||
|
inCallController.popToRootController()
|
||||||
|
} else {
|
||||||
|
inCallController.updateUI(newContext)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
self.currentContext = newContext;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,109 @@
|
||||||
|
/*
|
||||||
|
* Copyright @ 2018-present 8x8, Inc.
|
||||||
|
* Copyright @ 2017-2018 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 WatchConnectivity
|
||||||
|
import WatchKit
|
||||||
|
import Foundation
|
||||||
|
|
||||||
|
|
||||||
|
class InCallController: WKInterfaceController {
|
||||||
|
@IBOutlet var mutedButton: WKInterfaceButton!
|
||||||
|
@IBOutlet var roomLabel: WKInterfaceLabel!
|
||||||
|
@IBOutlet var timer: WKInterfaceTimer!
|
||||||
|
|
||||||
|
@IBAction func hangupClicked() {
|
||||||
|
sendCommand(JitsiMeetCommands.CMD_HANG_UP, message: nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
@IBAction func muteClicked() {
|
||||||
|
if var micMuted = ExtensionDelegate.currentJitsiMeetContext.micMuted {
|
||||||
|
micMuted = !micMuted;
|
||||||
|
sendCommand(
|
||||||
|
JitsiMeetCommands.CMD_SET_MUTED,
|
||||||
|
message: [
|
||||||
|
"muted": micMuted ? "true" : "false"
|
||||||
|
])
|
||||||
|
updateMutedButton(withMuted: micMuted)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func sendCommand(_ command: JitsiMeetCommands, message: [String : Any]?) {
|
||||||
|
if WCSession.isSupported() {
|
||||||
|
let session = WCSession.default
|
||||||
|
var data = [String: Any]()
|
||||||
|
|
||||||
|
if let sessionID = ExtensionDelegate.currentJitsiMeetContext.sessionID {
|
||||||
|
if message != nil {
|
||||||
|
message!.forEach { data[$0] = $1 }
|
||||||
|
}
|
||||||
|
|
||||||
|
data["command"] = command.rawValue;
|
||||||
|
data["sessionID"] = sessionID;
|
||||||
|
|
||||||
|
session.sendMessage(data, replyHandler: nil, errorHandler: nil)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func updateUI(_ newContext: JitsiMeetContext) {
|
||||||
|
var conferenceURL = newContext.conferenceURL
|
||||||
|
|
||||||
|
if let joinConferenceURL = newContext.joinConferenceURL {
|
||||||
|
sendCommand(JitsiMeetCommands.CMD_JOIN_CONFERENCE, message: [ "data" : joinConferenceURL ])
|
||||||
|
conferenceURL = joinConferenceURL
|
||||||
|
}
|
||||||
|
|
||||||
|
let newRoomName = conferenceURL != nil ? conferenceURL!.components(separatedBy: "/").last : ""
|
||||||
|
|
||||||
|
roomLabel.setText(newRoomName)
|
||||||
|
|
||||||
|
if let newTimestamp = newContext.conferenceTimestamp {
|
||||||
|
restartTimer(newTimestamp)
|
||||||
|
}
|
||||||
|
if let newMuted = newContext.micMuted {
|
||||||
|
updateMutedButton(withMuted: newMuted)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func restartTimer(_ conferenceTimestamp: Int64) {
|
||||||
|
if (conferenceTimestamp != 0) {
|
||||||
|
let newDate = Date(timeIntervalSince1970: TimeInterval(conferenceTimestamp / 1000))
|
||||||
|
timer.setDate(newDate)
|
||||||
|
timer.start();
|
||||||
|
print("WATCH timer set date to: \(newDate) and start")
|
||||||
|
} else {
|
||||||
|
print("WATCH timer stop")
|
||||||
|
timer.stop();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func updateMutedButton(withMuted isMuted: Bool) {
|
||||||
|
if isMuted {
|
||||||
|
mutedButton.setBackgroundImageNamed("mute-on.png")
|
||||||
|
} else {
|
||||||
|
mutedButton.setBackgroundImageNamed("mute-off.png")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override func awake(withContext context: Any?) {
|
||||||
|
super.awake(withContext: context)
|
||||||
|
|
||||||
|
if let data = context as? JitsiMeetContext {
|
||||||
|
updateUI(data)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,44 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||||
|
<plist version="1.0">
|
||||||
|
<dict>
|
||||||
|
<key>CFBundleDevelopmentRegion</key>
|
||||||
|
<string>$(DEVELOPMENT_LANGUAGE)</string>
|
||||||
|
<key>CFBundleDisplayName</key>
|
||||||
|
<string>Jitsi Meet Companion Extension</string>
|
||||||
|
<key>CFBundleExecutable</key>
|
||||||
|
<string>$(EXECUTABLE_NAME)</string>
|
||||||
|
<key>CFBundleIdentifier</key>
|
||||||
|
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
|
||||||
|
<key>CFBundleInfoDictionaryVersion</key>
|
||||||
|
<string>6.0</string>
|
||||||
|
<key>CFBundleName</key>
|
||||||
|
<string>$(PRODUCT_NAME)</string>
|
||||||
|
<key>CFBundlePackageType</key>
|
||||||
|
<string>XPC!</string>
|
||||||
|
<key>CFBundleShortVersionString</key>
|
||||||
|
<string>19.2.0</string>
|
||||||
|
<key>CFBundleVersion</key>
|
||||||
|
<string>1</string>
|
||||||
|
<key>CLKComplicationPrincipalClass</key>
|
||||||
|
<string>$(PRODUCT_MODULE_NAME).ComplicationController</string>
|
||||||
|
<key>CLKComplicationSupportedFamilies</key>
|
||||||
|
<array>
|
||||||
|
<string>CLKComplicationFamilyModularSmall</string>
|
||||||
|
<string>CLKComplicationFamilyUtilitarianSmall</string>
|
||||||
|
<string>CLKComplicationFamilyCircularSmall</string>
|
||||||
|
</array>
|
||||||
|
<key>NSExtension</key>
|
||||||
|
<dict>
|
||||||
|
<key>NSExtensionAttributes</key>
|
||||||
|
<dict>
|
||||||
|
<key>WKAppBundleIdentifier</key>
|
||||||
|
<string>org.jitsi.meet.watchkit</string>
|
||||||
|
</dict>
|
||||||
|
<key>NSExtensionPointIdentifier</key>
|
||||||
|
<string>com.apple.watchkit</string>
|
||||||
|
</dict>
|
||||||
|
<key>WKExtensionDelegateClassName</key>
|
||||||
|
<string>$(PRODUCT_MODULE_NAME).ExtensionDelegate</string>
|
||||||
|
</dict>
|
||||||
|
</plist>
|
|
@ -0,0 +1,80 @@
|
||||||
|
/*
|
||||||
|
* Copyright @ 2018-present 8x8, Inc.
|
||||||
|
* Copyright @ 2017-2018 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 WatchKit
|
||||||
|
import Foundation
|
||||||
|
|
||||||
|
|
||||||
|
class InterfaceController: WKInterfaceController {
|
||||||
|
|
||||||
|
@IBOutlet var table: WKInterfaceTable!
|
||||||
|
|
||||||
|
func updateUI(_ newContext:JitsiMeetContext) {
|
||||||
|
if let recentURLsArray = newContext.recentURLs {
|
||||||
|
updateRecents(withRecents: recentURLsArray, currentContext: newContext)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private func updateRecents(withRecents recents: NSArray, currentContext: JitsiMeetContext) {
|
||||||
|
// Updating the # of rows only if it actually changed prevents from blinking the UI
|
||||||
|
if (table.numberOfRows != recents.count) {
|
||||||
|
table.setNumberOfRows(recents.count, withRowType: "MeetingRowType")
|
||||||
|
}
|
||||||
|
|
||||||
|
for (index, entry) in recents.enumerated() {
|
||||||
|
let entryDict = entry as! NSDictionary
|
||||||
|
let roomURL = entryDict["conference"] as! NSString
|
||||||
|
let timestamp = entryDict["date"] as! NSNumber
|
||||||
|
|
||||||
|
// Prepare values
|
||||||
|
let room = roomURL.components(separatedBy: "/").last
|
||||||
|
let date = Date(timeIntervalSince1970: timestamp.doubleValue / 1000) // timestamp is taken with Date.now() in JS, which uses milliseconds
|
||||||
|
let dateFormatter = DateFormatter()
|
||||||
|
dateFormatter.timeZone = TimeZone.current
|
||||||
|
dateFormatter.locale = NSLocale.current
|
||||||
|
dateFormatter.dateFormat = "HH:mm yyyy-MM-dd"
|
||||||
|
let strDate = dateFormatter.string(from: date)
|
||||||
|
|
||||||
|
// Update row controller
|
||||||
|
let controller = table.rowController(at: index) as! MeetingRowController
|
||||||
|
controller.room = room
|
||||||
|
controller.roomUrl = roomURL as String
|
||||||
|
controller.roomLabel.setText(room)
|
||||||
|
controller.timeLabel.setText(strDate)
|
||||||
|
|
||||||
|
// Change the background for the active meeting
|
||||||
|
if (controller.roomUrl == currentContext.conferenceURL) {
|
||||||
|
controller.rowGroup.setBackgroundColor(UIColor(red: 0.125, green: 0.58, blue: 0.98, alpha: 1))
|
||||||
|
} else {
|
||||||
|
controller.rowGroup.setBackgroundColor(UIColor(red: 0.949, green: 0.956, blue: 1, alpha: 0.14))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override func contextForSegue(withIdentifier segueIdentifier: String, in table: WKInterfaceTable, rowIndex: Int) -> Any? {
|
||||||
|
let controller = table.rowController(at: rowIndex) as! MeetingRowController
|
||||||
|
let currentContext = ExtensionDelegate.currentJitsiMeetContext
|
||||||
|
|
||||||
|
// Copy the current context and add the joinConferenceURL to trigger the command when the in-call screen is displayed
|
||||||
|
let actionContext = JitsiMeetContext(jmContext: currentContext)
|
||||||
|
actionContext.joinConferenceURL = controller.roomUrl
|
||||||
|
|
||||||
|
print("WATCH contextForSegue: \(actionContext.description)");
|
||||||
|
|
||||||
|
return actionContext;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,27 @@
|
||||||
|
/*
|
||||||
|
* Copyright @ 2018-present 8x8, Inc.
|
||||||
|
* Copyright @ 2017-2018 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
// This needs to be in sync with features/mobile/watchos/constants.js
|
||||||
|
enum JitsiMeetCommands : String {
|
||||||
|
typealias RawValue = String
|
||||||
|
|
||||||
|
case CMD_HANG_UP = "hangup";
|
||||||
|
|
||||||
|
case CMD_JOIN_CONFERENCE = "joinConference";
|
||||||
|
|
||||||
|
case CMD_SET_MUTED = "setMuted";
|
||||||
|
}
|
|
@ -0,0 +1,71 @@
|
||||||
|
/*
|
||||||
|
* Copyright @ 2018-present 8x8, Inc.
|
||||||
|
* Copyright @ 2017-2018 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
|
||||||
|
|
||||||
|
class JitsiMeetContext {
|
||||||
|
private var dictionary : [String : Any]
|
||||||
|
|
||||||
|
var joinConferenceURL : String? = nil;
|
||||||
|
|
||||||
|
init() {
|
||||||
|
dictionary = [:]
|
||||||
|
}
|
||||||
|
|
||||||
|
init(context: [String : Any]) {
|
||||||
|
dictionary = context
|
||||||
|
}
|
||||||
|
|
||||||
|
init(jmContext: JitsiMeetContext) {
|
||||||
|
dictionary = jmContext.dictionary
|
||||||
|
joinConferenceURL = jmContext.joinConferenceURL
|
||||||
|
}
|
||||||
|
|
||||||
|
var conferenceURL : String? {
|
||||||
|
get {
|
||||||
|
return dictionary["conferenceURL"] as? String
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var conferenceTimestamp : Int64? {
|
||||||
|
get {
|
||||||
|
return dictionary["conferenceTimestamp"] as? Int64;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var sessionID : Int64? {
|
||||||
|
get {
|
||||||
|
return dictionary["sessionID"] as? Int64;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var recentURLs : NSArray? {
|
||||||
|
get {
|
||||||
|
return dictionary["recentURLs"] as? NSArray
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var micMuted : Bool? {
|
||||||
|
get {
|
||||||
|
return (dictionary["micMuted"] as? NSNumber)?.boolValue ?? nil;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public var description: String {
|
||||||
|
return "JitsiMeetContext[conferenceURL: \(String(describing: conferenceURL)), conferenceTimestamp: \(String(describing:conferenceTimestamp)), sessionID: \(String(describing:sessionID)), recentURLs: \(String(describing:recentURLs)), joinConferenceURL: \(String(describing:joinConferenceURL)) "
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,27 @@
|
||||||
|
/*
|
||||||
|
* Copyright @ 2018-present 8x8, Inc.
|
||||||
|
* Copyright @ 2017-2018 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 WatchKit
|
||||||
|
|
||||||
|
class MeetingRowController: NSObject {
|
||||||
|
@IBOutlet var roomLabel: WKInterfaceLabel!
|
||||||
|
@IBOutlet var timeLabel: WKInterfaceLabel!
|
||||||
|
@IBOutlet var rowGroup: WKInterfaceGroup!
|
||||||
|
|
||||||
|
var room: String!
|
||||||
|
var roomUrl: String!
|
||||||
|
}
|
|
@ -12260,6 +12260,11 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"react-native-watch-connectivity": {
|
||||||
|
"version": "0.2.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/react-native-watch-connectivity/-/react-native-watch-connectivity-0.2.0.tgz",
|
||||||
|
"integrity": "sha512-l3Quzbb+qa4in2U5RSt/lT0/pHrIpEChT1NnqrVAAXNrjkXjVOsxduaaEDdDhTzNJQEm/PcAcoyrFmgvGOohxw=="
|
||||||
|
},
|
||||||
"react-native-webrtc": {
|
"react-native-webrtc": {
|
||||||
"version": "github:jitsi/react-native-webrtc#659d2fe417b52356b1b706636de97e23bae3e9f5",
|
"version": "github:jitsi/react-native-webrtc#659d2fe417b52356b1b706636de97e23bae3e9f5",
|
||||||
"from": "github:jitsi/react-native-webrtc#659d2fe417b52356b1b706636de97e23bae3e9f5",
|
"from": "github:jitsi/react-native-webrtc#659d2fe417b52356b1b706636de97e23bae3e9f5",
|
||||||
|
|
|
@ -74,6 +74,7 @@
|
||||||
"react-native-sound": "0.10.12",
|
"react-native-sound": "0.10.12",
|
||||||
"react-native-swipeout": "2.3.6",
|
"react-native-swipeout": "2.3.6",
|
||||||
"react-native-vector-icons": "6.0.2",
|
"react-native-vector-icons": "6.0.2",
|
||||||
|
"react-native-watch-connectivity": "0.2.0",
|
||||||
"react-native-webrtc": "github:jitsi/react-native-webrtc#659d2fe417b52356b1b706636de97e23bae3e9f5",
|
"react-native-webrtc": "github:jitsi/react-native-webrtc#659d2fe417b52356b1b706636de97e23bae3e9f5",
|
||||||
"react-redux": "5.0.7",
|
"react-redux": "5.0.7",
|
||||||
"react-transition-group": "2.4.0",
|
"react-transition-group": "2.4.0",
|
||||||
|
|
|
@ -22,6 +22,7 @@ import '../../mobile/permissions';
|
||||||
import '../../mobile/picture-in-picture';
|
import '../../mobile/picture-in-picture';
|
||||||
import '../../mobile/proximity';
|
import '../../mobile/proximity';
|
||||||
import '../../mobile/wake-lock';
|
import '../../mobile/wake-lock';
|
||||||
|
import '../../mobile/watchos';
|
||||||
|
|
||||||
import { AbstractApp } from './AbstractApp';
|
import { AbstractApp } from './AbstractApp';
|
||||||
import type { Props as AbstractAppProps } from './AbstractApp';
|
import type { Props as AbstractAppProps } from './AbstractApp';
|
||||||
|
|
|
@ -0,0 +1,28 @@
|
||||||
|
// @flow
|
||||||
|
|
||||||
|
/**
|
||||||
|
* See {@link setConferenceTimestamp} for more details.
|
||||||
|
* {
|
||||||
|
* type: SET_CONFERENCE_TIMESTAMP,
|
||||||
|
* conferenceTimestamp: number
|
||||||
|
* }
|
||||||
|
*/
|
||||||
|
export const SET_CONFERENCE_TIMESTAMP = Symbol('WATCH_OS_SET_CONFERENCE_TIMESTAMP');
|
||||||
|
|
||||||
|
/**
|
||||||
|
* See {@link setSessionId} action for more details.
|
||||||
|
* {
|
||||||
|
* type: SET_SESSION_ID,
|
||||||
|
* sessionID: number
|
||||||
|
* }
|
||||||
|
*/
|
||||||
|
export const SET_SESSION_ID = Symbol('WATCH_OS_SET_SESSION_ID');
|
||||||
|
|
||||||
|
/**
|
||||||
|
* See {@link setWatchReachable} for more details.
|
||||||
|
* {
|
||||||
|
* type: SET_WATCH_REACHABLE,
|
||||||
|
* watchReachable: boolean
|
||||||
|
* }
|
||||||
|
*/
|
||||||
|
export const SET_WATCH_REACHABLE = Symbol('WATCH_OS_SET_WATCH_REACHABLE');
|
|
@ -0,0 +1,55 @@
|
||||||
|
// @flow
|
||||||
|
|
||||||
|
import { SET_CONFERENCE_TIMESTAMP, SET_SESSION_ID, SET_WATCH_REACHABLE } from './actionTypes';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Stores a timestamp when the conference is joined, so that the watch counterpart can start counting from when
|
||||||
|
* the meeting has really started.
|
||||||
|
*
|
||||||
|
* @param {number} conferenceTimestamp - A timestamp retrieved with {@code newDate.getTime()}.
|
||||||
|
* @returns {{
|
||||||
|
* type: SET_CONFERENCE_TIMESTAMP,
|
||||||
|
* conferenceTimestamp: number
|
||||||
|
* }}
|
||||||
|
*/
|
||||||
|
export function setConferenceTimestamp(conferenceTimestamp: number) {
|
||||||
|
return {
|
||||||
|
type: SET_CONFERENCE_TIMESTAMP,
|
||||||
|
conferenceTimestamp
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Updates the session ID which is sent to the Watch app and then used by the app to send commands. Commands from
|
||||||
|
* the watch are accepted only if the 'sessionID' passed by the Watch matches the one currently stored in Redux. It is
|
||||||
|
* supposed to prevent from processing outdated commands.
|
||||||
|
*
|
||||||
|
* @returns {{
|
||||||
|
* type: SET_SESSION_ID,
|
||||||
|
* sessionID: number
|
||||||
|
* }}
|
||||||
|
*/
|
||||||
|
export function setSessionId() {
|
||||||
|
return {
|
||||||
|
type: SET_SESSION_ID,
|
||||||
|
sessionID: new Date().getTime()
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Updates the reachable status of the watch. It's used to get in sync with the watch counterpart when it gets
|
||||||
|
* reconnected, but also to prevent from sending updates if the app is not installed at all (which would fail with
|
||||||
|
* an error).
|
||||||
|
*
|
||||||
|
* @param {boolean} isReachable - Indicates whether the watch is currently reachable or not.
|
||||||
|
* @returns {{
|
||||||
|
* type: SET_WATCH_REACHABLE,
|
||||||
|
* watchReachable: boolean
|
||||||
|
* }}
|
||||||
|
*/
|
||||||
|
export function setWatchReachable(isReachable: boolean) {
|
||||||
|
return {
|
||||||
|
type: SET_WATCH_REACHABLE,
|
||||||
|
watchReachable: isReachable
|
||||||
|
};
|
||||||
|
}
|
|
@ -0,0 +1,11 @@
|
||||||
|
// @flow
|
||||||
|
|
||||||
|
// NOTE When changing any of the commands make sure to update JitsiMeetCommands enum in the WatchKit extension code.
|
||||||
|
|
||||||
|
export const CMD_HANG_UP = 'hangup';
|
||||||
|
|
||||||
|
export const CMD_JOIN_CONFERENCE = 'joinConference';
|
||||||
|
|
||||||
|
export const CMD_SET_MUTED = 'setMuted';
|
||||||
|
|
||||||
|
export const MAX_RECENT_URLS = 10;
|
|
@ -0,0 +1,2 @@
|
||||||
|
import './middleware';
|
||||||
|
import './reducer';
|
|
@ -0,0 +1,225 @@
|
||||||
|
// @flow
|
||||||
|
|
||||||
|
import { Platform } from 'react-native';
|
||||||
|
import * as watch from 'react-native-watch-connectivity';
|
||||||
|
|
||||||
|
import { appNavigate } from '../../app';
|
||||||
|
|
||||||
|
import { APP_WILL_MOUNT } from '../../base/app';
|
||||||
|
import { CONFERENCE_JOINED } from '../../base/conference';
|
||||||
|
import { getInviteURL, isInviteURLReady } from '../../base/connection';
|
||||||
|
import { setAudioMuted } from '../../base/media';
|
||||||
|
import {
|
||||||
|
MiddlewareRegistry,
|
||||||
|
StateListenerRegistry,
|
||||||
|
toState
|
||||||
|
} from '../../base/redux';
|
||||||
|
import { toURLString } from '../../base/util';
|
||||||
|
|
||||||
|
import { setConferenceTimestamp, setSessionId, setWatchReachable } from './actions';
|
||||||
|
import { CMD_HANG_UP, CMD_JOIN_CONFERENCE, CMD_SET_MUTED, MAX_RECENT_URLS } from './constants';
|
||||||
|
|
||||||
|
const logger = require('jitsi-meet-logger').getLogger(__filename);
|
||||||
|
|
||||||
|
const watchOSEnabled = Platform.OS === 'ios';
|
||||||
|
|
||||||
|
// Handles the recent URLs state sent to the watch
|
||||||
|
watchOSEnabled && StateListenerRegistry.register(
|
||||||
|
/* selector */ state => state['features/recent-list'],
|
||||||
|
/* listener */ (recentListState, { getState }) => {
|
||||||
|
_updateApplicationContext(getState);
|
||||||
|
});
|
||||||
|
|
||||||
|
// Handles the mic muted state sent to the watch
|
||||||
|
watchOSEnabled && StateListenerRegistry.register(
|
||||||
|
/* selector */ state => _isAudioMuted(state),
|
||||||
|
/* listener */ (isAudioMuted, { getState }) => {
|
||||||
|
_updateApplicationContext(getState);
|
||||||
|
});
|
||||||
|
|
||||||
|
// Handles the conference URL state sent to the watch
|
||||||
|
watchOSEnabled && StateListenerRegistry.register(
|
||||||
|
/* selector */ state => _getCurrentConferenceUrl(state),
|
||||||
|
/* listener */ (currentUrl, { dispatch, getState }) => {
|
||||||
|
dispatch(setSessionId());
|
||||||
|
_updateApplicationContext(getState);
|
||||||
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Middleware that captures conference actions.
|
||||||
|
*
|
||||||
|
* @param {Store} store - The redux store.
|
||||||
|
* @returns {Function}
|
||||||
|
*/
|
||||||
|
watchOSEnabled && MiddlewareRegistry.register(store => next => action => {
|
||||||
|
switch (action.type) {
|
||||||
|
case APP_WILL_MOUNT:
|
||||||
|
_appWillMount(store);
|
||||||
|
break;
|
||||||
|
case CONFERENCE_JOINED:
|
||||||
|
store.dispatch(setConferenceTimestamp(new Date().getTime()));
|
||||||
|
_updateApplicationContext(store.getState());
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return next(action);
|
||||||
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Registers listeners to the react-native-watch-connectivity lib.
|
||||||
|
*
|
||||||
|
* @param {Store} store - The redux store.
|
||||||
|
* @private
|
||||||
|
* @returns {void}
|
||||||
|
*/
|
||||||
|
function _appWillMount({ dispatch, getState }) {
|
||||||
|
watch.subscribeToWatchReachability((error, reachable) => {
|
||||||
|
dispatch(setWatchReachable(reachable));
|
||||||
|
_updateApplicationContext(getState);
|
||||||
|
});
|
||||||
|
|
||||||
|
watch.subscribeToMessages((error, message) => {
|
||||||
|
if (error) {
|
||||||
|
logger.error('watch.subscribeToMessages error:', error);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const {
|
||||||
|
command,
|
||||||
|
sessionID
|
||||||
|
} = message;
|
||||||
|
const currentSessionID = _getSessionId(getState());
|
||||||
|
|
||||||
|
if (!sessionID || sessionID !== currentSessionID) {
|
||||||
|
logger.warn(
|
||||||
|
`Ignoring outdated watch command: ${message.command}`
|
||||||
|
+ ` sessionID: ${sessionID} current session ID: ${currentSessionID}`);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (command) {
|
||||||
|
case CMD_HANG_UP:
|
||||||
|
if (typeof _getCurrentConferenceUrl(getState()) !== undefined) {
|
||||||
|
dispatch(appNavigate(undefined));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case CMD_JOIN_CONFERENCE: {
|
||||||
|
const newConferenceURL = message.data;
|
||||||
|
const oldConferenceURL = _getCurrentConferenceUrl(getState());
|
||||||
|
|
||||||
|
if (oldConferenceURL !== newConferenceURL) {
|
||||||
|
dispatch(appNavigate(newConferenceURL));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case CMD_SET_MUTED:
|
||||||
|
dispatch(
|
||||||
|
setAudioMuted(
|
||||||
|
message.muted === 'true',
|
||||||
|
/* ensureTrack */ true));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Figures out what's the current conference URL which is supposed to indicate what conference is currently active.
|
||||||
|
* When not currently in any conference and not trying to join any then the 'NULL' string value is returned.
|
||||||
|
*
|
||||||
|
* @param {Object|Function} stateful - Either the whole Redux state object or the Redux store's {@code getState} method.
|
||||||
|
* @returns {string}
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
function _getCurrentConferenceUrl(stateful) {
|
||||||
|
const state = toState(stateful);
|
||||||
|
let currentUrl;
|
||||||
|
|
||||||
|
if (isInviteURLReady(state)) {
|
||||||
|
currentUrl = toURLString(getInviteURL(state));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if the URL doesn't end with a slash
|
||||||
|
if (currentUrl && currentUrl.substr(-1) === '/') {
|
||||||
|
currentUrl = undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
return currentUrl ? currentUrl : undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the current Apple Watch session's ID. A new session is started whenever the conference URL has changed. It is
|
||||||
|
* used to filter out outdated commands which may arrive very later if the Apple Watch loses the connectivity.
|
||||||
|
*
|
||||||
|
* @param {Object|Function} stateful - Either the whole Redux state object or the Redux store's {@code getState} method.
|
||||||
|
* @returns {number}
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
function _getSessionId(stateful) {
|
||||||
|
const state = toState(stateful);
|
||||||
|
|
||||||
|
return state['features/mobile/watchos'].sessionID;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the list of recent URLs to be passed over to the Watch app.
|
||||||
|
*
|
||||||
|
* @param {Object|Function} stateful - Either the whole Redux state object or the Redux store's {@code getState} method.
|
||||||
|
* @returns {Array<Object>}
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
function _getRecentUrls(stateful) {
|
||||||
|
const state = toState(stateful);
|
||||||
|
const recentURLs = state['features/recent-list'];
|
||||||
|
|
||||||
|
// Trim to MAX_RECENT_URLS and reverse the list
|
||||||
|
const reversedList = recentURLs.slice(-MAX_RECENT_URLS);
|
||||||
|
|
||||||
|
reversedList.reverse();
|
||||||
|
|
||||||
|
return reversedList;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determines the audio muted state to be sent to the apple watch.
|
||||||
|
*
|
||||||
|
* @param {Object|Function} stateful - Either the whole Redux state object or the Redux store's {@code getState} method.
|
||||||
|
* @returns {boolean}
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
function _isAudioMuted(stateful) {
|
||||||
|
const state = toState(stateful);
|
||||||
|
const { audio } = state['features/base/media'];
|
||||||
|
|
||||||
|
return audio.muted;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sends the context to the watch os app. At the time of this writing it's the entire state of
|
||||||
|
* the 'features/mobile/watchos' reducer.
|
||||||
|
*
|
||||||
|
* @param {Object|Function} stateful - Either the whole Redux state object or the Redux store's {@code getState} method.
|
||||||
|
* @private
|
||||||
|
* @returns {void}
|
||||||
|
*/
|
||||||
|
function _updateApplicationContext(stateful) {
|
||||||
|
const state = toState(stateful);
|
||||||
|
const { conferenceTimestamp, sessionID, watchReachable } = state['features/mobile/watchos'];
|
||||||
|
|
||||||
|
if (!watchReachable) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
watch.updateApplicationContext({
|
||||||
|
conferenceTimestamp,
|
||||||
|
conferenceURL: _getCurrentConferenceUrl(state),
|
||||||
|
micMuted: _isAudioMuted(state),
|
||||||
|
recentURLs: _getRecentUrls(state),
|
||||||
|
sessionID
|
||||||
|
});
|
||||||
|
} catch (error) {
|
||||||
|
logger.error('Failed to stringify or send the context', error);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,34 @@
|
||||||
|
// @flow
|
||||||
|
|
||||||
|
import { assign, ReducerRegistry } from '../../base/redux';
|
||||||
|
import { SET_CONFERENCE_TIMESTAMP, SET_SESSION_ID, SET_WATCH_REACHABLE } from './actionTypes';
|
||||||
|
|
||||||
|
const INITIAL_STATE = {
|
||||||
|
sessionID: new Date().getTime()
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reduces the Redux actions of the feature features/mobile/watchos.
|
||||||
|
*/
|
||||||
|
ReducerRegistry.register('features/mobile/watchos', (state = INITIAL_STATE, action) => {
|
||||||
|
switch (action.type) {
|
||||||
|
case SET_CONFERENCE_TIMESTAMP: {
|
||||||
|
return assign(state, {
|
||||||
|
conferenceTimestamp: action.conferenceTimestamp
|
||||||
|
});
|
||||||
|
}
|
||||||
|
case SET_SESSION_ID: {
|
||||||
|
return assign(state, {
|
||||||
|
sessionID: action.sessionID,
|
||||||
|
conferenceTimestamp: 0
|
||||||
|
});
|
||||||
|
}
|
||||||
|
case SET_WATCH_REACHABLE: {
|
||||||
|
return assign(state, {
|
||||||
|
watchReachable: action.watchReachable
|
||||||
|
});
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
return state;
|
||||||
|
}
|
||||||
|
});
|