Skip to content

Commit

Permalink
Merge pull request #402 from somia/develop
Browse files Browse the repository at this point in the history
Release version 0.8.0 with Jitsi in web view
  • Loading branch information
andreiqvik authored Oct 25, 2023
2 parents 9a9862e + 8644d3f commit 3541fd1
Show file tree
Hide file tree
Showing 14 changed files with 369 additions and 137 deletions.
17 changes: 0 additions & 17 deletions JitsiMeetSDK.podspec

This file was deleted.

4 changes: 2 additions & 2 deletions NinchatSDKSwift.podspec
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

Pod::Spec.new do |s|
s.name = "NinchatSDKSwift"
s.version = "0.7.0"
s.version = "0.8.0"
s.summary = "iOS SDK for Ninchat, Swift version"
s.description = "For building iOS applications using Ninchat messaging."
s.homepage = "https://ninchat.com/"
Expand Down Expand Up @@ -40,7 +40,7 @@ Pod::Spec.new do |s|
}

# Cocoapods dependencies
s.dependency "JitsiMeetSDK", "~> 0.7.0"
s.dependency "JitsiWebRTC", "106.0.0"
s.dependency 'AnyCodable-FlightSchool', '~> 0.2.3'
s.dependency "AutoLayoutSwift", "4.0.0"
s.dependency "NinchatLowLevelClient", "~> 0.6.0"
Expand Down
8 changes: 5 additions & 3 deletions NinchatSDKSwift.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
archiveVersion = 1;
classes = {
};
objectVersion = 51;
objectVersion = 54;
objects = {

/* Begin PBXBuildFile section */
Expand All @@ -17,6 +17,7 @@
5C7A2AF227D20AF90067F2F1 /* QuestionnaireCellForm.xib in Resources */ = {isa = PBXBuildFile; fileRef = 5C7A2AF127D20AF90067F2F1 /* QuestionnaireCellForm.xib */; };
5CD4F1C82540CAAF009856AC /* Notification+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5CD4F1C62540CAAF009856AC /* Notification+Extension.swift */; };
5CD4F1C92540CAAF009856AC /* KeyboardHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5CD4F1C72540CAAF009856AC /* KeyboardHandler.swift */; };
75990FEF2AD7E95500EBC306 /* JitsiVideoWebView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 75990FEE2AD7E95500EBC306 /* JitsiVideoWebView.swift */; };
7C44F1A84C25C4445CF3B955 /* Pods_NinchatSDKSwift.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 495ADA60487CD354EDC07332 /* Pods_NinchatSDKSwift.framework */; };
851E359923B1214E000FA966 /* AutolayouTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 851E359823B1214E000FA966 /* AutolayouTests.swift */; };
851ECF6423969297006D332F /* README.md in Resources */ = {isa = PBXBuildFile; fileRef = 851ECF6323969297006D332F /* README.md */; };
Expand Down Expand Up @@ -265,6 +266,7 @@
5CD4F1C62540CAAF009856AC /* Notification+Extension.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "Notification+Extension.swift"; sourceTree = "<group>"; };
5CD4F1C72540CAAF009856AC /* KeyboardHandler.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = KeyboardHandler.swift; sourceTree = "<group>"; };
62C8D99D572F0DB4B5E6D255 /* Pods-NinchatSDKSwiftUITests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-NinchatSDKSwiftUITests.release.xcconfig"; path = "Target Support Files/Pods-NinchatSDKSwiftUITests/Pods-NinchatSDKSwiftUITests.release.xcconfig"; sourceTree = "<group>"; };
75990FEE2AD7E95500EBC306 /* JitsiVideoWebView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = JitsiVideoWebView.swift; sourceTree = "<group>"; };
7B50C1E321841F3749D5D05A /* Pods-NinchatSDKSwiftServerTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-NinchatSDKSwiftServerTests.release.xcconfig"; path = "Target Support Files/Pods-NinchatSDKSwiftServerTests/Pods-NinchatSDKSwiftServerTests.release.xcconfig"; sourceTree = "<group>"; };
832BEC3E467C0EEE45282F1B /* Pods-NinchatSDKSwiftTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-NinchatSDKSwiftTests.debug.xcconfig"; path = "Target Support Files/Pods-NinchatSDKSwiftTests/Pods-NinchatSDKSwiftTests.debug.xcconfig"; sourceTree = "<group>"; };
851E359823B1214E000FA966 /* AutolayouTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AutolayouTests.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -481,7 +483,6 @@
FA026FE8299BAC6100C4D3E4 /* JoinVideoButton.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = JoinVideoButton.swift; sourceTree = "<group>"; };
FA026FEA299BAC7A00C4D3E4 /* NINGroupChatViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NINGroupChatViewController.swift; sourceTree = "<group>"; };
FA026FEC299BAC8C00C4D3E4 /* NINGroupChatViewModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NINGroupChatViewModel.swift; sourceTree = "<group>"; };
FA7958B329FBB821006527A7 /* JitsiMeetSDK.podspec */ = {isa = PBXFileReference; lastKnownFileType = text; path = JitsiMeetSDK.podspec; sourceTree = "<group>"; };
/* End PBXFileReference section */

/* Begin PBXFrameworksBuildPhase section */
Expand Down Expand Up @@ -611,6 +612,7 @@
8530EC8223AD405200BAA52A /* Video View */ = {
isa = PBXGroup;
children = (
75990FEE2AD7E95500EBC306 /* JitsiVideoWebView.swift */,
8530EC8423AD405200BAA52A /* VideoView.swift */,
8530EC8323AD405200BAA52A /* VideoView.xib */,
);
Expand Down Expand Up @@ -675,7 +677,6 @@
children = (
855B9F9D238ED9DC0081A9C6 /* Podfile */,
852751D8238EE67000B6A44A /* NinchatSDKSwift.podspec */,
FA7958B329FBB821006527A7 /* JitsiMeetSDK.podspec */,
852751DA238EE67800B6A44A /* BUILDING.md */,
851ECF6323969297006D332F /* README.md */,
855B9F13238ECDB30081A9C6 /* NinchatSDKSwift */,
Expand Down Expand Up @@ -1548,6 +1549,7 @@
91A16D46F4A792C00EC23086 /* ComposeMessage.swift in Sources */,
91A165F76F51AC329049D95E /* Dictionary+Extension.swift in Sources */,
91A1637BC9B1BCF029EE608F /* Queue.swift in Sources */,
75990FEF2AD7E95500EBC306 /* JitsiVideoWebView.swift in Sources */,
91A166157BBD01A10A8A6520 /* WebRTCServerInfo.swift in Sources */,
91A161BA5B39C92B92F6B56B /* RTCSessionDescription+Extension.swift in Sources */,
91A164EF2633C3EEEC657848 /* RTCIceCandidate+Extension.swift in Sources */,
Expand Down
1 change: 1 addition & 0 deletions NinchatSDKSwift/Implementations/Constants.swift
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ public enum ColorConstants {
case ninchatColorChatBubbleRightTint
case ninchatColorChatBubbleComposeTint
case ninchatColorTextareaText
case ninchatColorTextareaSelectedText
case ninchatColorTextareaPlaceholder
case ninchatColorTextareaSubmitText
case ninchatColorChatBubbleLeftLink
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,7 @@ extension NINLowLevelClientProps: NINLowLevelSessionProps {
}

func setAction(_ action: NINLowLevelClientActions) {
debugger("set action: \(action)")
self.set(value: action.rawValue, forKey: "action")
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -386,7 +386,7 @@ extension NINChatWebRTCClientImpl {
@objc
private func didSessionRouteChange(_ notification: Notification) {
if let userInfo = notification.userInfo, let reasonKey = userInfo[AVAudioSessionRouteChangeReasonKey] as? UInt, let reason = AVAudioSession.RouteChangeReason(rawValue: reasonKey) {
print("Route Changed: \(userInfo)")
debugger("Route Changed: \(userInfo)")

/// Force Speaker in case the app tries to use earning as the output
if RTCAudioSession.sharedInstance().currentRoute.outputs.first?.portType.rawValue ?? "" == "Receiver" || AVAudioSession.sharedInstance().currentRoute.outputs.first?.portType.rawValue ?? "" == "Receiver" {
Expand Down
140 changes: 64 additions & 76 deletions NinchatSDKSwift/Implementations/View Model/NINGroupChatViewModel.swift
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,7 @@
// license that can be found in the LICENSE file.
//

import Foundation
import JitsiMeetSDK
import UIKit

protocol NINGroupChatViewModel: AnyObject, NINChatStateProtocol, NINChatMessageProtocol, NINChatPermissionsProtocol, NINChatAttachmentProtocol {
var hasJoinedVideo: Bool { get }
Expand All @@ -22,16 +21,16 @@ protocol NINGroupChatViewModel: AnyObject, NINChatStateProtocol, NINChatMessageP
func leaveVideoCall()
}

final class NINGroupChatViewModelImpl: NSObject, NINGroupChatViewModel, JitsiMeetViewDelegate {
final class NINGroupChatViewModelImpl: NSObject, NINGroupChatViewModel {
private weak var sessionManager: NINChatSessionManager?
private var pipViewCoordinator: PiPViewCoordinator?
private var jitsiView: JitsiMeetView?
private var jitsiVideoWebView: JitsiVideoWebView?
private var typingStatus = false
private var typingStatusQueue: DispatchWorkItem?
private var isSelectingMedia = false

var hasJoinedVideo: Bool {
jitsiView?.delegate != nil
jitsiVideoWebView != nil
// jitsiView?.delegate != nil
}

var backlogMessages: String? {
Expand Down Expand Up @@ -114,88 +113,76 @@ final class NINGroupChatViewModelImpl: NSObject, NINGroupChatViewModel, JitsiMee
case let .failure(error):
completion(error)
case let .success(credentials):
let avatarConfig = AvatarConfig(forUser: sessionManager)
// User
let user = sessionManager.myUser
let iconURL = avatarConfig.imageOverrideURL ?? user?.iconURL

// Use imageOverrideURL or iconURL (if available) or default to nil if both are absent.
let avatarConfig = AvatarConfig(forUser: sessionManager)
let iconURLString = avatarConfig.imageOverrideURL ?? user?.iconURL

// Choose nameOverride if available, otherwise use user's displayName or a default "Guest" label.
let userName = !avatarConfig.nameOverride.isEmpty
? avatarConfig.nameOverride
: (user?.displayName ?? "Guest".localized)

// Get server address
var serverAddress: String = sessionManager.serverAddress
let apiPrefix = "api."
if serverAddress.hasPrefix(apiPrefix) {
let endIdx = serverAddress.index(serverAddress.startIndex, offsetBy: apiPrefix.count)
serverAddress.removeSubrange(serverAddress.startIndex ..< endIdx)
}

// Construct Jitsi server address and extract domain.
let jitsiServerAddress = "https://jitsi-www." + serverAddress
let options = JitsiMeetConferenceOptions.fromBuilder {
$0.serverURL = URL(string: jitsiServerAddress)
$0.userInfo = .init(
displayName: userName,
andEmail: nil,
andAvatar: iconURL.flatMap { URL(string: $0) }
)
$0.room = credentials.room
$0.token = credentials.token

$0.setFeatureFlag("add-people.enabled", withBoolean: false)
$0.setFeatureFlag("audio-mute.enabled", withBoolean: true)
$0.setFeatureFlag("calendar.enabled", withBoolean: false)
$0.setFeatureFlag("call-integration.enabled", withBoolean: true) // android: false
$0.setFeatureFlag("car-mode.enabled", withBoolean: false)
$0.setFeatureFlag("close-captions.enabled", withBoolean: false)
$0.setFeatureFlag("conference-timer.enabled", withBoolean: true)
$0.setFeatureFlag("chat.enabled", withBoolean: false)
$0.setFeatureFlag("filmstrip.enabled", withBoolean: true)
$0.setFeatureFlag("fullscreen.enabled", withBoolean: true)
$0.setFeatureFlag("invite.enabled", withBoolean: false)
$0.setFeatureFlag("ios.screensharing.enabled", withBoolean: false)
$0.setFeatureFlag("speakerstats.enabled", withBoolean: false)
$0.setFeatureFlag("kick-out.enabled", withBoolean: false)
$0.setFeatureFlag("live-streaming.enabled", withBoolean: false)
$0.setFeatureFlag("meeting-name.enabled", withBoolean: false)
$0.setFeatureFlag("meeting-password.enabled", withBoolean: false)
$0.setFeatureFlag("notifications.enabled", withBoolean: false)
$0.setFeatureFlag("overflow-menu.enabled", withBoolean: true)
$0.setFeatureFlag("pip.enabled", withBoolean: false)
$0.setFeatureFlag("pip-while-screen-sharing.enabled", withBoolean: false)
$0.setFeatureFlag("prejoinpage.enabled", withBoolean: true)
$0.setFeatureFlag("prejoinpage.hide-display-name.enabled", withBoolean: true)
$0.setFeatureFlag("raise-hand.enabled", withBoolean: false)
$0.setFeatureFlag("recording.enabled", withBoolean: false)
$0.setFeatureFlag("server-url-change.enabled", withBoolean: false)
$0.setFeatureFlag("settings.enabled", withBoolean: true)
$0.setFeatureFlag("tile-view.enabled", withBoolean: true)
$0.setFeatureFlag("toolbox.alwaysVisible", withBoolean: false)
$0.setFeatureFlag("toolbox.enabled", withBoolean: true)
$0.setFeatureFlag("video-mute.enabled", withBoolean: true)
$0.setFeatureFlag("video-share.enabled", withBoolean: false)
$0.setFeatureFlag("welcomepage.enabled", withBoolean: false)
$0.setFeatureFlag("help.enabled", withBoolean: false)
$0.setFeatureFlag("lobby-mode.enabled", withBoolean: false)
$0.setFeatureFlag("reactions.enabled", withBoolean: false)
$0.setFeatureFlag("security-options.enabled", withBoolean: true)
$0.setFeatureFlag("settings.profile-section.enabled", withBoolean: false)
$0.setFeatureFlag("settings.conference-section-only-self-view.enabled", withBoolean: true)
$0.setFeatureFlag("settings.links-section.enabled", withBoolean: false)
$0.setFeatureFlag("settings.build-info-section.enabled", withBoolean: false)
$0.setFeatureFlag("settings.advanced-section.enabled", withBoolean: false)
$0.setFeatureFlag("participants.enabled", withValue: false)
let domain = jitsiServerAddress.replacingOccurrences(of: "https://", with: "")

// Prepare other necessary variables.
let room = credentials.room
let jwt = credentials.token
let displayName = userName.addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed)

// Determine the appropriate language.
let supportedLanguages = ["fi", "sv", "en"]
let currentLanguage = Locale.current.languageCode ?? "en"
let language = supportedLanguages.contains(currentLanguage) ? currentLanguage : "en"

// Construct the URL query items, adding displayName and avatarURL if available.
var queryItems: [URLQueryItem] = [
URLQueryItem(name: "jwt", value: jwt),
URLQueryItem(name: "roomName", value: room),
URLQueryItem(name: "domain", value: domain),
URLQueryItem(name: "lang", value: language)
]

if let encodedDisplayName = displayName {
queryItems.append(URLQueryItem(name: "displayName", value: encodedDisplayName))
}
let jitsiMeetView = self.jitsiView ?? JitsiMeetView()
jitsiMeetView.delegate = self
jitsiMeetView.join(options)

if self.pipViewCoordinator == nil {
self.pipViewCoordinator = PiPViewCoordinator(withView: jitsiMeetView)
if let iconURLString = iconURLString, let avatarUrl = URL(string: iconURLString) {
queryItems.append(URLQueryItem(name: "avatarURL", value: avatarUrl.absoluteString))
}
self.pipViewCoordinator?.configureAsStickyView(withParentView: parentView)

jitsiMeetView.alpha = 0
// Build the final URL.
var urlComponents = URLComponents(string: "https://ninchat.com/new/jitsi-meet.html")
urlComponents?.queryItems = queryItems

self.jitsiView = jitsiMeetView
self.pipViewCoordinator?.show()
// Validate and use the final URL.
guard let finalUrl = urlComponents?.url else {
completion(NinchatError(type: "unknown", props: nil))
return
}

// If we're here, it means the URL is valid, and we can create the URLRequest.
let urlRequest = URLRequest(url: finalUrl)

// Add JitsiVideoWebView
let jitsiVideoWebView = parentView.subviews.filter { $0 is JitsiVideoWebView }.first as? JitsiVideoWebView
self.jitsiVideoWebView = jitsiVideoWebView
jitsiVideoWebView?.eventsDelegate = self

// Load url request
jitsiVideoWebView?.loadJitsiMeeting(for: urlRequest)
completion(nil)
}
}
Expand All @@ -212,11 +199,12 @@ final class NINGroupChatViewModelImpl: NSObject, NINGroupChatViewModel, JitsiMee
guard hasJoinedVideo else {
return
}
pipViewCoordinator?.hide()

if force {
jitsiView?.hangUp()
jitsiVideoWebView?.hangUp()
}
jitsiView?.delegate = nil
self.jitsiVideoWebView?.eventsDelegate = nil
self.jitsiVideoWebView = nil
}
}

Expand Down Expand Up @@ -379,10 +367,10 @@ extension NINGroupChatViewModelImpl {
}
}

// MARK: - Jitsi Delegate
// MARK: - JitsiVideoWebViewDelegate

extension NINGroupChatViewModelImpl {
func ready(toClose data: [AnyHashable : Any]!) {
extension NINGroupChatViewModelImpl: JitsiVideoWebViewEventsDelegate {
func readyToClose() {
leaveVideoCall(force: false)
onGroupVideoReadyToClose?()
}
Expand Down
Loading

0 comments on commit 3541fd1

Please sign in to comment.