This commit is contained in:
6
ios/app/watchos/extension/Assets.xcassets/Contents.json
Normal file
6
ios/app/watchos/extension/Assets.xcassets/Contents.json
Normal file
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"info" : {
|
||||
"version" : 1,
|
||||
"author" : "xcode"
|
||||
}
|
||||
}
|
||||
21
ios/app/watchos/extension/Assets.xcassets/jitsi.imageset/Contents.json
vendored
Normal file
21
ios/app/watchos/extension/Assets.xcassets/jitsi.imageset/Contents.json
vendored
Normal file
@@ -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"
|
||||
}
|
||||
}
|
||||
BIN
ios/app/watchos/extension/Assets.xcassets/jitsi.imageset/jitsi@2x.png
vendored
Normal file
BIN
ios/app/watchos/extension/Assets.xcassets/jitsi.imageset/jitsi@2x.png
vendored
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 2.0 KiB |
81
ios/app/watchos/extension/ComplicationController.swift
Normal file
81
ios/app/watchos/extension/ComplicationController.swift
Normal file
@@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
103
ios/app/watchos/extension/ExtensionDelegate.swift
Normal file
103
ios/app/watchos/extension/ExtensionDelegate.swift
Normal file
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
109
ios/app/watchos/extension/InCallController.swift
Normal file
109
ios/app/watchos/extension/InCallController.swift
Normal file
@@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
44
ios/app/watchos/extension/Info.plist
Normal file
44
ios/app/watchos/extension/Info.plist
Normal file
@@ -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>99.0.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>
|
||||
94
ios/app/watchos/extension/InterfaceController.swift
Normal file
94
ios/app/watchos/extension/InterfaceController.swift
Normal file
@@ -0,0 +1,94 @@
|
||||
/*
|
||||
* 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 WatchConnectivity
|
||||
import Foundation
|
||||
|
||||
|
||||
class InterfaceController: WKInterfaceController {
|
||||
|
||||
@IBOutlet var infoLabel: WKInterfaceLabel!
|
||||
@IBOutlet var table: WKInterfaceTable!
|
||||
|
||||
override func didAppear(){
|
||||
self.updateUI(ExtensionDelegate.currentJitsiMeetContext)
|
||||
}
|
||||
|
||||
func updateUI(_ newContext:JitsiMeetContext) {
|
||||
if (newContext.recentURLs == nil || newContext.recentURLs!.count == 0) {
|
||||
infoLabel.setText("There are no recent meetings. Please use the app on the phone to start a new call.")
|
||||
|
||||
table.setHidden(true)
|
||||
infoLabel.setHidden(false)
|
||||
} else {
|
||||
updateRecents(withRecents: newContext.recentURLs!, currentContext: newContext)
|
||||
|
||||
table.setHidden(false)
|
||||
infoLabel.setHidden(true)
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
27
ios/app/watchos/extension/JitsiMeetCommands.swift
Normal file
27
ios/app/watchos/extension/JitsiMeetCommands.swift
Normal file
@@ -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";
|
||||
}
|
||||
71
ios/app/watchos/extension/JitsiMeetContext.swift
Normal file
71
ios/app/watchos/extension/JitsiMeetContext.swift
Normal file
@@ -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)) "
|
||||
}
|
||||
}
|
||||
27
ios/app/watchos/extension/MeetingRowController.swift
Normal file
27
ios/app/watchos/extension/MeetingRowController.swift
Normal file
@@ -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!
|
||||
}
|
||||
Reference in New Issue
Block a user