diff --git a/.githooks/README.md b/.githooks/README.md
new file mode 100644
index 00000000..78504c21
--- /dev/null
+++ b/.githooks/README.md
@@ -0,0 +1,7 @@
+# iOS UIKit Git Hooks
+
+To apply these hooks:
+
+```sh
+git config --local core.hooksPath .githooks/
+```
\ No newline at end of file
diff --git a/.githooks/pre-push b/.githooks/pre-push
new file mode 100755
index 00000000..1ec76ee6
--- /dev/null
+++ b/.githooks/pre-push
@@ -0,0 +1,40 @@
+#!/bin/zsh
+
+# An example hook script to verify what is about to be pushed. Called by "git
+# push" after it has checked the remote status, but before anything has been
+# pushed. If this script exits with a non-zero status nothing will be pushed.
+#
+# This hook is called with the following parameters:
+#
+# $1 -- Name of the remote to which the push is being done
+# $2 -- URL to which the push is being done
+#
+# If pushing without using a named remote those arguments will be equal.
+#
+# Information about the commits which are being pushed is supplied as lines to
+# the standard input in the form:
+#
+#
+#
+# This sample shows how to prevent push of commits where the log message starts
+# with "WIP" (work in progress).
+
+remote="$1"
+url="$2"
+
+zero=$(git hash-object --stdin '../'
pod 'AgoraUIKit_macOS', :path => '../'
end
diff --git a/Agora-SwiftUI-Example/Agora-SwiftUI-Example.xcodeproj/project.pbxproj b/Agora-SwiftUI-Example/Agora-SwiftUI-Example.xcodeproj/project.pbxproj
index 256f2214..3b03571f 100644
--- a/Agora-SwiftUI-Example/Agora-SwiftUI-Example.xcodeproj/project.pbxproj
+++ b/Agora-SwiftUI-Example/Agora-SwiftUI-Example.xcodeproj/project.pbxproj
@@ -7,11 +7,12 @@
objects = {
/* Begin PBXBuildFile section */
+ F327EEC928057D2A00C86D3D /* AgoraUIKit in Frameworks */ = {isa = PBXBuildFile; productRef = F327EEC828057D2A00C86D3D /* AgoraUIKit */; };
+ F327EECB28057D3200C86D3D /* AgoraRtmControl in Frameworks */ = {isa = PBXBuildFile; productRef = F327EECA28057D3200C86D3D /* AgoraRtmControl */; };
F327FCFB259B97ED00922764 /* Agora_SwiftUI_ExampleApp.swift in Sources */ = {isa = PBXBuildFile; fileRef = F327FCFA259B97ED00922764 /* Agora_SwiftUI_ExampleApp.swift */; };
F327FCFD259B97ED00922764 /* ContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = F327FCFC259B97ED00922764 /* ContentView.swift */; };
F327FCFF259B97EF00922764 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = F327FCFE259B97EF00922764 /* Assets.xcassets */; };
F327FD02259B97EF00922764 /* Preview Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = F327FD01259B97EF00922764 /* Preview Assets.xcassets */; };
- F3DDD460278D8C38003D4A16 /* AgoraUIKit_iOS in Frameworks */ = {isa = PBXBuildFile; productRef = F3DDD45F278D8C38003D4A16 /* AgoraUIKit_iOS */; };
/* End PBXBuildFile section */
/* Begin PBXFileReference section */
@@ -29,7 +30,8 @@
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
- F3DDD460278D8C38003D4A16 /* AgoraUIKit_iOS in Frameworks */,
+ F327EEC928057D2A00C86D3D /* AgoraUIKit in Frameworks */,
+ F327EECB28057D3200C86D3D /* AgoraRtmControl in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -106,7 +108,8 @@
);
name = "Agora-SwiftUI-Example";
packageProductDependencies = (
- F3DDD45F278D8C38003D4A16 /* AgoraUIKit_iOS */,
+ F327EEC828057D2A00C86D3D /* AgoraUIKit */,
+ F327EECA28057D3200C86D3D /* AgoraRtmControl */,
);
productName = "Agora-SwiftUI-Example";
productReference = F327FCF7259B97ED00922764 /* Agora-SwiftUI-Example.app */;
@@ -353,9 +356,13 @@
/* End XCConfigurationList section */
/* Begin XCSwiftPackageProductDependency section */
- F3DDD45F278D8C38003D4A16 /* AgoraUIKit_iOS */ = {
+ F327EEC828057D2A00C86D3D /* AgoraUIKit */ = {
isa = XCSwiftPackageProductDependency;
- productName = AgoraUIKit_iOS;
+ productName = AgoraUIKit;
+ };
+ F327EECA28057D3200C86D3D /* AgoraRtmControl */ = {
+ isa = XCSwiftPackageProductDependency;
+ productName = AgoraRtmControl;
};
/* End XCSwiftPackageProductDependency section */
};
diff --git a/Agora-SwiftUI-Example/Agora-SwiftUI-Example/ContentView.swift b/Agora-SwiftUI-Example/Agora-SwiftUI-Example/ContentView.swift
index e8c5652a..bc5ce278 100644
--- a/Agora-SwiftUI-Example/Agora-SwiftUI-Example/ContentView.swift
+++ b/Agora-SwiftUI-Example/Agora-SwiftUI-Example/ContentView.swift
@@ -6,7 +6,7 @@
//
import SwiftUI
-import AgoraUIKit_iOS
+import AgoraUIKit
struct ContentView: View {
@State private var connectedToChannel = false
diff --git a/Agora-UIKit-Example/Agora-UIKit-Example.xcodeproj/project.pbxproj b/Agora-UIKit-Example/Agora-UIKit-Example.xcodeproj/project.pbxproj
index b94c48d3..571134fc 100644
--- a/Agora-UIKit-Example/Agora-UIKit-Example.xcodeproj/project.pbxproj
+++ b/Agora-UIKit-Example/Agora-UIKit-Example.xcodeproj/project.pbxproj
@@ -7,7 +7,8 @@
objects = {
/* Begin PBXBuildFile section */
- F39B87D327200A8900C644C7 /* AgoraUIKit_iOS in Frameworks */ = {isa = PBXBuildFile; productRef = F39B87D227200A8900C644C7 /* AgoraUIKit_iOS */; };
+ F366512627FDF05700DDD521 /* AgoraUIKit in Frameworks */ = {isa = PBXBuildFile; productRef = F366512527FDF05700DDD521 /* AgoraUIKit */; };
+ F366512827FDF07100DDD521 /* AgoraRtmControl in Frameworks */ = {isa = PBXBuildFile; productRef = F366512727FDF07100DDD521 /* AgoraRtmControl */; };
F3C4328E256FB56C00E2AD43 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = F3C4328D256FB56C00E2AD43 /* AppDelegate.swift */; };
F3C43290256FB56C00E2AD43 /* SceneDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = F3C4328F256FB56C00E2AD43 /* SceneDelegate.swift */; };
F3C43292256FB56C00E2AD43 /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = F3C43291256FB56C00E2AD43 /* ViewController.swift */; };
@@ -16,8 +17,21 @@
F3C4329A256FB56F00E2AD43 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = F3C43298256FB56F00E2AD43 /* LaunchScreen.storyboard */; };
/* End PBXBuildFile section */
+/* Begin PBXCopyFilesBuildPhase section */
+ F33CA68E27FB3C7500541A7A /* Embed Frameworks */ = {
+ isa = PBXCopyFilesBuildPhase;
+ buildActionMask = 2147483647;
+ dstPath = "";
+ dstSubfolderSpec = 10;
+ files = (
+ );
+ name = "Embed Frameworks";
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXCopyFilesBuildPhase section */
+
/* Begin PBXFileReference section */
- F39B87D0272009FA00C644C7 /* iOS-UIKit */ = {isa = PBXFileReference; lastKnownFileType = folder; name = "iOS-UIKit"; path = ..; sourceTree = ""; };
+ F366512327FDF03F00DDD521 /* iOS-UIKit */ = {isa = PBXFileReference; lastKnownFileType = wrapper; name = "iOS-UIKit"; path = ..; sourceTree = ""; };
F3C4328A256FB56C00E2AD43 /* Agora-UIKit-Example.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "Agora-UIKit-Example.app"; sourceTree = BUILT_PRODUCTS_DIR; };
F3C4328D256FB56C00E2AD43 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; };
F3C4328F256FB56C00E2AD43 /* SceneDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SceneDelegate.swift; sourceTree = ""; };
@@ -33,35 +47,44 @@
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
- F39B87D327200A8900C644C7 /* AgoraUIKit_iOS in Frameworks */,
+ F366512627FDF05700DDD521 /* AgoraUIKit in Frameworks */,
+ F366512827FDF07100DDD521 /* AgoraRtmControl in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXFrameworksBuildPhase section */
/* Begin PBXGroup section */
- F39B87CF272009FA00C644C7 /* Packages */ = {
+ E4B1C9811C27629FB0E02419 /* Pods */ = {
isa = PBXGroup;
children = (
- F39B87D0272009FA00C644C7 /* iOS-UIKit */,
);
- name = Packages;
+ path = Pods;
sourceTree = "";
};
- F39B87D127200A8900C644C7 /* Frameworks */ = {
+ F366512427FDF05700DDD521 /* Frameworks */ = {
isa = PBXGroup;
children = (
);
name = Frameworks;
sourceTree = "";
};
+ F39B87CF272009FA00C644C7 /* Packages */ = {
+ isa = PBXGroup;
+ children = (
+ F366512327FDF03F00DDD521 /* iOS-UIKit */,
+ );
+ name = Packages;
+ sourceTree = "";
+ };
F3C43281256FB56C00E2AD43 = {
isa = PBXGroup;
children = (
F39B87CF272009FA00C644C7 /* Packages */,
F3C4328C256FB56C00E2AD43 /* Agora-UIKit-Example */,
F3C4328B256FB56C00E2AD43 /* Products */,
- F39B87D127200A8900C644C7 /* Frameworks */,
+ E4B1C9811C27629FB0E02419 /* Pods */,
+ F366512427FDF05700DDD521 /* Frameworks */,
);
sourceTree = "";
};
@@ -97,6 +120,7 @@
F3C43286256FB56C00E2AD43 /* Sources */,
F3C43287256FB56C00E2AD43 /* Frameworks */,
F3C43288256FB56C00E2AD43 /* Resources */,
+ F33CA68E27FB3C7500541A7A /* Embed Frameworks */,
);
buildRules = (
);
@@ -104,7 +128,8 @@
);
name = "Agora-UIKit-Example";
packageProductDependencies = (
- F39B87D227200A8900C644C7 /* AgoraUIKit_iOS */,
+ F366512527FDF05700DDD521 /* AgoraUIKit */,
+ F366512727FDF07100DDD521 /* AgoraRtmControl */,
);
productName = "Agora-UIKit-Example";
productReference = F3C4328A256FB56C00E2AD43 /* Agora-UIKit-Example.app */;
@@ -366,9 +391,13 @@
/* End XCConfigurationList section */
/* Begin XCSwiftPackageProductDependency section */
- F39B87D227200A8900C644C7 /* AgoraUIKit_iOS */ = {
+ F366512527FDF05700DDD521 /* AgoraUIKit */ = {
+ isa = XCSwiftPackageProductDependency;
+ productName = AgoraUIKit;
+ };
+ F366512727FDF07100DDD521 /* AgoraRtmControl */ = {
isa = XCSwiftPackageProductDependency;
- productName = AgoraUIKit_iOS;
+ productName = AgoraRtmControl;
};
/* End XCSwiftPackageProductDependency section */
};
diff --git a/Agora-UIKit-Example/Agora-UIKit-Example/ViewController.swift b/Agora-UIKit-Example/Agora-UIKit-Example/ViewController.swift
index 51dfcd5c..8997ddc8 100644
--- a/Agora-UIKit-Example/Agora-UIKit-Example/ViewController.swift
+++ b/Agora-UIKit-Example/Agora-UIKit-Example/ViewController.swift
@@ -6,9 +6,8 @@
//
import UIKit
-
import AgoraRtcKit
-import AgoraUIKit_iOS
+import AgoraUIKit
class ViewController: UIViewController {
@@ -18,6 +17,9 @@ class ViewController: UIViewController {
var agSettings = AgoraSettings()
agSettings.enabledButtons = [.cameraButton, .micButton, .flipButton]
+ agSettings.buttonPosition = .right
+ AgoraVideoViewer.printLevel = .verbose
+
let agoraView = AgoraVideoViewer(
connectionData: AgoraConnectionData(
appId: <#Agora App ID#>,
diff --git a/Agora-UIKit-Example/Podfile b/Agora-UIKit-Example/Podfile
new file mode 100644
index 00000000..c09ee1ee
--- /dev/null
+++ b/Agora-UIKit-Example/Podfile
@@ -0,0 +1,10 @@
+# Uncomment the next line to define a global platform for your project
+# platform :ios, '9.0'
+
+target 'Agora-UIKit-Example' do
+ # Comment the next line if you don't want to use dynamic frameworks
+ use_frameworks!
+
+ # Pods for Agora-UIKit-Example
+ pod 'AgoraUIKit_iOS', :path => '../'
+end
diff --git a/AgoraRtmControl_iOS.podspec b/AgoraRtmControl_iOS.podspec
new file mode 100644
index 00000000..0709a71a
--- /dev/null
+++ b/AgoraRtmControl_iOS.podspec
@@ -0,0 +1,31 @@
+#
+# Be sure to run `pod lib lint AgoraRtmControl_iOS.podspec' to ensure this is a
+# valid spec before submitting.
+#
+# Any lines starting with a # are optional, but their use is encouraged
+# To learn more about a Podspec see https://guides.cocoapods.org/syntax/podspec.html
+#
+
+Pod::Spec.new do |s|
+ s.name = 'AgoraRtmControl_iOS'
+ s.module_name = 'AgoraRtmControl'
+ s.version = ENV['LIB_VERSION'] || '1.8.0'
+ s.summary = 'Agora Real-time Messaging Wrapper.'
+
+ s.description = <<-DESC
+Use this Pod to interact with Agora Real-time messaging SDK with additional properties and commands,
+to make the usage simpler with the AgoraRtmController class.
+ DESC
+
+ s.homepage = 'https://github.com/AgoraIO-Community/iOS-UIKit'
+ s.license = { :type => 'MIT', :file => 'LICENSE' }
+ s.author = { 'Max Cobb' => 'max@agora.io' }
+ s.source = { :git => 'https://github.com/AgoraIO-Community/iOS-UIKit.git', :tag => s.version.to_s }
+
+ s.ios.deployment_target = '11.0'
+ s.swift_versions = ['5.0']
+
+ s.static_framework = true
+ s.source_files = 'Sources/AgoraRtmControl/*'
+ s.dependency 'AgoraRtm_iOS', '~> 1.4.10'
+end
diff --git a/AgoraRtmControl_macOS.podspec b/AgoraRtmControl_macOS.podspec
new file mode 100644
index 00000000..db8416d6
--- /dev/null
+++ b/AgoraRtmControl_macOS.podspec
@@ -0,0 +1,31 @@
+#
+# Be sure to run `pod lib lint AgoraRtmControl_macOS.podspec' to ensure this is a
+# valid spec before submitting.
+#
+# Any lines starting with a # are optional, but their use is encouraged
+# To learn more about a Podspec see https://guides.cocoapods.org/syntax/podspec.html
+#
+
+Pod::Spec.new do |s|
+ s.name = 'AgoraRtmControl_macOS'
+ s.module_name = 'AgoraRtmControl'
+ s.version = ENV['LIB_VERSION'] || '1.8.0'
+ s.summary = 'Agora Real-time Messaging Wrapper.'
+
+ s.description = <<-DESC
+Use this Pod to interact with Agora Real-time messaging SDK with additional properties and commands,
+to make the usage simpler with the AgoraRtmController class.
+ DESC
+
+ s.homepage = 'https://github.com/AgoraIO-Community/iOS-UIKit'
+ s.license = { :type => 'MIT', :file => 'LICENSE' }
+ s.author = { 'Max Cobb' => 'max@agora.io' }
+ s.source = { :git => 'https://github.com/AgoraIO-Community/iOS-UIKit.git', :tag => s.version.to_s }
+
+ s.macos.deployment_target = '10.14'
+ s.swift_versions = ['5.0']
+
+ s.static_framework = true
+ s.source_files = 'Sources/AgoraRtmControl/*'
+ s.dependency 'AgoraRtm_macOS', '~> 1.4.10'
+end
diff --git a/AgoraUIKit_iOS.podspec b/AgoraUIKit_iOS.podspec
index 07911d58..7bc6e129 100644
--- a/AgoraUIKit_iOS.podspec
+++ b/AgoraUIKit_iOS.podspec
@@ -8,7 +8,8 @@
Pod::Spec.new do |s|
s.name = 'AgoraUIKit_iOS'
- s.version = '1.7.6'
+ s.module_name = 'AgoraUIKit'
+ s.version = ENV['LIB_VERSION'] || '1.8.0'
s.summary = 'Agora video session UIKit template.'
s.description = <<-DESC
@@ -23,9 +24,14 @@ Use this Pod to create a video UIKit view that can be easily added to your iOS a
s.ios.deployment_target = '13.0'
s.swift_versions = ['5.0']
+ s.static_framework = true
s.source_files = 'Sources/Agora-UIKit/*'
- s.dependency 'AgoraRtcEngine_iOS/RtcBasic'
- s.dependency 'AgoraRtm_iOS', '~> 1.4.10'
+ s.dependency 'AgoraRtcEngine_iOS/RtcBasic', '~> 3.7.0'
+ s.default_subspec = 'UIKitFull'
- s.static_framework = true
+ s.subspec 'UIKitBasic' do |cs|
+ end
+ s.subspec 'UIKitFull' do |cs|
+ cs.dependency 'AgoraRtmControl_iOS', "#{s.version.to_s}"
+ end
end
diff --git a/AgoraUIKit_macOS.podspec b/AgoraUIKit_macOS.podspec
index 8ba30392..a61d1d9d 100644
--- a/AgoraUIKit_macOS.podspec
+++ b/AgoraUIKit_macOS.podspec
@@ -1,5 +1,5 @@
#
-# Be sure to run `pod lib lint Agora-UIKit.podspec' to ensure this is a
+# Be sure to run `pod lib lint AgoraUIKit_macOS.podspec' to ensure this is a
# valid spec before submitting.
#
# Any lines starting with a # are optional, but their use is encouraged
@@ -8,7 +8,8 @@
Pod::Spec.new do |s|
s.name = 'AgoraUIKit_macOS'
- s.version = '1.7.6'
+ s.module_name = 'AgoraUIKit'
+ s.version = ENV['LIB_VERSION'] || '1.8.0'
s.summary = 'Agora video session AppKit template.'
s.description = <<-DESC
@@ -20,12 +21,18 @@ Use this Pod to create a video AppKit view that can be easily added to your macO
s.author = { 'Max Cobb' => 'max@agora.io' }
s.source = { :git => 'https://github.com/AgoraIO-Community/iOS-UIKit.git', :tag => s.version.to_s }
- s.macos.deployment_target = '10.14'
+ s.macos.deployment_target = '10.15'
s.swift_versions = ['5.0']
+ s.static_framework = true
s.source_files = 'Sources/Agora-UIKit/*'
s.pod_target_xcconfig = { 'ONLY_ACTIVE_ARCH' => 'YES' }
- s.dependency 'AgoraRtcEngine_macOS/RtcBasic'
- s.dependency 'AgoraRtm_macOS', '~> 1.4.10'
- s.static_framework = false
+ s.dependency 'AgoraRtcEngine_macOS/RtcBasic', '~> 3.7.0'
+ s.default_subspec = 'UIKitFull'
+
+ s.subspec 'UIKitBasic' do |cs|
+ end
+ s.subspec 'UIKitFull' do |cs|
+ cs.dependency 'AgoraRtmControl_macOS', "#{s.version.to_s}"
+ end
end
diff --git a/Package.swift b/Package.swift
index 775dbe92..a132672e 100644
--- a/Package.swift
+++ b/Package.swift
@@ -7,27 +7,35 @@ let package = Package(
name: "AgoraUIKit_iOS",
platforms: [.iOS(.v13)],
products: [
- .library(name: "AgoraUIKit_iOS", targets: ["AgoraUIKit_iOS"])
+ .library(name: "AgoraUIKit", targets: ["AgoraUIKit"]),
+ .library(name: "AgoraRtmControl", targets: ["AgoraRtmControl"])
],
dependencies: [
.package(
name: "AgoraRtcKit",
url: "https://github.com/AgoraIO/AgoraRtcEngine_iOS",
- "3.4.5"..."3.6.2"
+ .upToNextMinor(from: Version(3, 7, 0))
),
.package(
name: "AgoraRtmKit",
url: "https://github.com/AgoraIO/AgoraRtm_iOS",
- from: "1.4.10"
+ .upToNextMinor(from: Version(1, 4, 10))
)
],
targets: [
.target(
- name: "AgoraUIKit_iOS",
- dependencies: ["AgoraRtcKit", "AgoraRtmKit"],
-// dependencies: [.product(name: "RtcBasic", package: "AgoraRtcKit"), "AgoraRtmKit"],
+ name: "AgoraUIKit",
+ dependencies: [.product(name: "RtcBasic", package: "AgoraRtcKit")],
path: "Sources/Agora-UIKit"
),
- .testTarget(name: "AgoraUIKit-Tests", dependencies: ["AgoraUIKit_iOS"], path: "Tests/Agora-UIKit-Tests")
+ .target(
+ name: "AgoraRtmControl",
+ dependencies: ["AgoraRtmKit"],
+ path: "Sources/AgoraRtmControl"
+ ),
+ .testTarget(
+ name: "AgoraUIKit-Tests", dependencies: ["AgoraUIKit", "AgoraRtmControl"],
+ path: "Tests/Agora-UIKit-Tests"
+ )
]
)
diff --git a/README.md b/README.md
index 4bca581b..061ddc4a 100644
--- a/README.md
+++ b/README.md
@@ -10,117 +10,91 @@
-
-
-
-
Instantly integrate Agora in your own application or prototype using iOS or macOS.
+[More information available on this repo\'s Wiki](https://github.com/AgoraIO-Community/iOS-UIKit/wiki)
+
+[Click here for full documentation](https://agoraio-community.github.io/iOS-UIKit/)
## Requirements
-- Device
- - Either an iOS device with 12.0 or later
- - Or a macOS computer with 10.14 or later
-- Xcode 11 or later
-- *CocoaPods (if installing with CocoaPods)
+- iOS 13.0+ or a macOS 10.15 or later
+- Xcode 12.3 or later
+- CocoaPods (if installing with CocoaPods)
- [An Agora developer account](https://www.agora.io/en/blog/how-to-get-started-with-agora?utm_source=github&utm_repo=agora-ios-uikit)
-Once you have an Agora developer account and an App ID, you're ready to use this pod.
-
-[Click here for full documentation](https://agoraio-community.github.io/iOS-UIKit/)
+Once you have an Agora developer account and an App ID, you're ready to use this package.
## Installation
-### Swift Package Manager (Recommended, iOS Only)
-
-Add the URL of this repository to your Xcode 11+ Project.
-
-Go to File > Swift Packages > Add Package Dependency, and paste in this link:
+Swift Package Manager and CocoaPods are both available offered for installation methods.
-`https://github.com/AgoraIO-Community/iOS-UIKit`
+The Pod for this package is called `AgoraUIKit_iOS` and `AgoraUIKit_macOS` for the two available platforms.
-If you are using the developer preview, add `4.0.0-preview` in the version box there, otherwise use a version from `1.0.0` up to `2.0.0`.
-
----
-
-> If you have issues installing the Swift Package:
-> In Xcode's File menu, select 'Swift Packages' and then 'Reset Package Caches'.
-
-### CocoaPods
-
-In your iOS or macOS project, add this pod to your repository by adding a file named `Podfile`, with contents similar to this:
-
-```ruby
-# Uncomment the next line to define a global platform for your project
-# platform :ios, '12.0'
-
-target 'Agora-UIKit-Example' do
- # Comment the next line if you don't want to use dynamic frameworks
- use_frameworks!
-
- # Uncomment the next line if you want to install for iOS
- # pod 'AgoraUIKit_iOS', '~> 1.0'
-
- # Uncomment the next line if you want to install for macOS
- # pod 'AgoraUIKit_macOS', '~> 1.0'
-end
-```
-
-And then install the pods using `pod install --repo-update`
-
-If any of these steps are unclear, look at ["Using Cocoapods" on cocoapods.org](https://guides.cocoapods.org/using/using-cocoapods.html).
-The installation will change slightly once this pod is out of pre-release.
+See the [Installation wiki](https://github.com/AgoraIO-Community/iOS-UIKit/wiki/Installation) page for more information on installing the package.
## Usage
Once installed, open your application `.xcodeproj` file. Or `.xcworkspace` if using CocoaPods.
-Decide where you want to add your `AgoraVideoViewer`, and in the same file import `Agora_UIKit` or `Agora_AppKit` for iOS and macOS respectively.
-Next, create an `AgoraVideoViewer` object and frame it in your scene like you would any other `UIView` or `NSView`. The `AgoraVideoViewer` object must be provided `AgoraConnectionData` and a UIViewController/NSViewController on creation.
-
-AgoraConnectionData has two values for initialising. These are appId and rtcToken, as well as an optional rtmToken.
-
-An `AgoraVideoViewer` can be created like this:
+The main view for Agora UIKit is `AgoraVideoViewer`. This is an example of a minimal creation that gives you a view similar to the one at the top of this README:
```swift
import AgoraRtcKit
-import AgoraUIKit_iOS
+import AgoraUIKit
let agoraView = AgoraVideoViewer(
connectionData: AgoraConnectionData(
- appId: "my-app-id",
- rtcToken: "my-channel-token",
- rtmToken: "my-channel-rtm-token"
- ),
- style: .grid,
- delegate: self
+ appId: "<#my-app-id#>",
+ rtcToken: "<#my-channel-token#>",
+ rtmToken: "<#my-channel-rtm-token#>"
+ ), delegate: self
)
```
-An alternative style is `.floating`, as seen in the image above.
-
-To join a channel, simply call:
+Frame your newly created AgoraVideoViewer in the app scene, then join a channel by calling:
```swift
agoraView.join(channel: "test", as: .broadcaster)
```
+[More examples available on the wiki](https://github.com/AgoraIO-Community/iOS-UIKit/wiki/Examples)
+
## Documentation
For full documentation, see our [AgoraUIKit documentation page](https://agoraio-community.github.io/iOS-UIKit/).
-### Roadmap
+## Error Handling and Troubleshooting
+
+For tips on how to overcome some common errors, [see the wiki page](https://github.com/AgoraIO-Community/iOS-UIKit/wiki/Error-Handling-and-Troubleshooting).
+
+## Roadmap
- [x] Muting/Unmuting a remote member
-- [ ] Usernames
+- [x] Usernames ([Settable value, not currently rendered](https://agoraio-community.github.io/iOS-UIKit/documentation/agorauikit_ios/agoraconnectiondata/username))
- [ ] Promoting an audience member to a broadcaster role.
- [ ] Layout for Voice Calls
- [ ] Cloud recording
## UIKits
-The plan is to grow this library and have similar offerings across all supported platforms. There are already similar libraries for [Android](https://github.com/AgoraIO-Community/Android-UIKit/), [React Native](https://github.com/AgoraIO-Community/ReactNative-UIKit), and [Flutter](https://github.com/AgoraIO-Community/Flutter-UIKit/), so be sure to check them out.
+The plan is to grow this library and have similar offerings across all supported platforms. There are already similar libraries for [Android](https://github.com/AgoraIO-Community/Android-UIKit/), [React Native](https://github.com/AgoraIO-Community/ReactNative-UIKit), [Flutter](https://github.com/AgoraIO-Community/Flutter-UIKit/) and [Web React](https://github.com/AgoraIO-Community/Web-React-UIKit) so be sure to check them out.
+
+## UML Diagrams
+
+- AgoraUIKit
+
+
+
+
+
+- AgoraRtmControl
+
+
+
+
+
+> generated with `swiftplantuml classdiagram Sources`
diff --git a/Sources/Agora-UIKit/AgoraCollectionViewer.swift b/Sources/Agora-UIKit/AgoraCollectionViewer.swift
index ea7c679f..fe3146fd 100644
--- a/Sources/Agora-UIKit/AgoraCollectionViewer.swift
+++ b/Sources/Agora-UIKit/AgoraCollectionViewer.swift
@@ -222,7 +222,7 @@ extension AgoraVideoViewer: MPCollectionViewDelegate, MPCollectionViewDataSource
internal func refreshCollectionData() {
switch self.style {
case .floating, .collection:
- if self.agSettings.showSelf {
+ if self.agoraSettings.showSelf {
self.collectionViewVideos = Array(self.userVideoLookup.values)
} else {
self.collectionViewVideos = Array(self.userVideoLookup.filter { $0.key != self.userID}.values)
diff --git a/Sources/Agora-UIKit/AgoraConnectionData.swift b/Sources/Agora-UIKit/AgoraConnectionData.swift
index 7a2bb486..349c062b 100644
--- a/Sources/Agora-UIKit/AgoraConnectionData.swift
+++ b/Sources/Agora-UIKit/AgoraConnectionData.swift
@@ -24,6 +24,7 @@ public struct AgoraConnectionData {
set { self.rtcToken = newValue }
}
+ /// Token to be used to connect to a RTM channel, can be nil.
public var rtmToken: String?
/// Channel the object is connected to. This cannot be set with the initialiser.
public var channel: String?
diff --git a/Sources/Agora-UIKit/AgoraRtmController+Helpers.swift b/Sources/Agora-UIKit/AgoraRtmController+Helpers.swift
deleted file mode 100644
index c2bfaea0..00000000
--- a/Sources/Agora-UIKit/AgoraRtmController+Helpers.swift
+++ /dev/null
@@ -1,159 +0,0 @@
-//
-// AgoraRtmController+Helpers.swift
-//
-//
-// Created by Max Cobb on 30/09/2021.
-//
-
-import AgoraRtmKit
-
-// MARK: Helper Methods
-extension AgoraRtmController {
- /// Type of decoded message coming from other users
- public enum DecodedRtmAction {
- /// Mute is when a user is requesting another user to mute or unmute a device
- case mute(_: MuteRequest)
- /// DecodedRtmAction type containing data about a user (local or remote)
- case userData(_: UserData)
- /// Message that contains a small action request, such as a ping or requesting a user's data
- case dataRequest(_: RtmDataRequest)
- }
-
- /// Decode message to a compatible DecodedRtmMessage type.
- /// - Parameters:
- /// - data: Raw data input, should be utf8 encoded JSON string of MuteRequest or UserData.
- /// - rtmId: Sender Real-time Messaging ID.
- /// - Returns: DecodedRtmMessage enum of the appropriate type.
- internal static func decodeRawRtmData(data: Data, from rtmId: String) -> DecodedRtmAction? {
- let decoder = JSONDecoder()
- if let userData = try? decoder.decode(UserData.self, from: data) {
- return .userData(userData)
- } else if let muteReq = try? decoder.decode(MuteRequest.self, from: data) {
- return .mute(muteReq)
- } else if let requestVal = try? decoder.decode(RtmDataRequest.self, from: data) {
- return .dataRequest(requestVal)
- }
- return nil
- }
-
- /// Share local UserData to all connected channels.
- /// Call this method when personal details are updated.
- open func broadcastPersonalData() {
- for channel in self.channels { self.sendPersonalData(to: channel.value) }
- }
-
- /// Share local UserData to a specific channel
- /// - Parameter channel: Channel to share UserData with.
- open func sendPersonalData(to channel: AgoraRtmChannel) {
- self.sendRaw(message: self.personalData, channel: channel) { sendMsgState in
- switch sendMsgState {
- case .errorOk:
- AgoraVideoViewer.agoraPrint(
- .verbose, message: "Personal data sent to channel successfully"
- )
- case .errorFailure, .errorTimeout, .tooOften,
- .invalidMessage, .errorNotInitialized, .notLoggedIn:
- AgoraVideoViewer.agoraPrint(
- .error, message: "Could not send message to channel \(sendMsgState.rawValue)"
- )
- @unknown default:
- AgoraVideoViewer.agoraPrint(.error, message: "Could not send message to channel (unknown)")
- }
- }
- }
-
- /// Share local UserData to a specific RTM member
- /// - Parameter member: Member to share UserData with.
- open func sendPersonalData(to member: String) {
- self.sendRaw(message: self.personalData, member: member) { sendMsgState in
- switch sendMsgState {
- case .ok:
- AgoraVideoViewer.agoraPrint(
- .verbose, message: "Personal data sent to member successfully"
- )
- case .failure, .timeout, .tooOften, .invalidMessage, .notInitialized, .notLoggedIn,
- .peerUnreachable, .cachedByServer, .invalidUserId, .imcompatibleMessage:
- AgoraVideoViewer.agoraPrint(
- .error, message: "Could not send message to channel \(sendMsgState.rawValue)"
- )
- @unknown default:
- AgoraVideoViewer.agoraPrint(.error, message: "Could not send message to channel (unknown)")
- }
- }
- }
-
- /// Send a raw codable message over RTM to the channel.
- /// - Parameters:
- /// - message: Codable message to send over RTM.
- /// - channel: String channel name to send the message to.
- /// - callback: Callback, to see if the message was sent successfully.
- public func sendRaw(
- message: Value, channel: String,
- callback: @escaping (AgoraRtmSendChannelMessageErrorCode) -> Void
- ) where Value: Codable {
- if let channel = self.channels[channel], let data = try? JSONEncoder().encode(message) {
- channel.send(
- AgoraRtmRawMessage(rawData: data, description: "AgoraUIKit"), completion: callback
- )
- }
- }
-
- /// Create raw message from codable object
- /// - Parameter codableObj: Codable object to be sent over the Real-time Messaging network.
- /// - Returns: AgoraRtmRawMessage that is ready to be sent across the Agora Real-time Messaging network.
- public static func createRawRtm(from codableObj: Value) -> AgoraRtmRawMessage? where Value: Codable {
- if let data = try? JSONEncoder().encode(codableObj) {
- return AgoraRtmRawMessage(rawData: data, description: "AgoraUIKit")
- }
- AgoraVideoViewer.agoraPrint(.error, message: "Message could not be encoded to JSON")
- return nil
- }
-
- /// Send a raw codable message over RTM to the channel
- /// - Parameters:
- /// - message: Codable message to send over RTM
- /// - channel: AgoraRtmChannel to send the message over
- /// - callback: Callback, to see if the message was sent successfully.
- public func sendRaw(
- message: Value, channel: AgoraRtmChannel,
- callback: @escaping (AgoraRtmSendChannelMessageErrorCode) -> Void
- ) where Value: Codable {
- if let rawMsg = AgoraRtmController.createRawRtm(from: message) {
- channel.send(rawMsg, completion: callback)
- return
- }
- callback(.invalidMessage)
- }
-
- /// Send a raw codable message over RTM to a member
- /// - Parameters:
- /// - message: Codable message to send over RTM
- /// - channel: member, or RTM ID to send the message to
- /// - callback: Callback, to see if the message was sent successfully.
- public func sendRaw(
- message: Value, member: String,
- callback: @escaping (AgoraRtmSendPeerMessageErrorCode) -> Void
- ) where Value: Codable {
- guard let rawMsg = AgoraRtmController.createRawRtm(from: message) else {
- callback(.imcompatibleMessage)
- return
- }
- self.rtmKit.send(rawMsg, toPeer: member, completion: callback)
- }
-
- /// Send a raw codable message over RTM to a member
- /// - Parameters:
- /// - message: Codable message to send over RTM
- /// - channel: member, or RTC User ID to send the message to
- /// - callback: Callback, to see if the message was sent successfully.
- public func sendRaw(
- message: Value, user: UInt,
- callback: @escaping (AgoraRtmSendPeerMessageErrorCode) -> Void
- ) where Value: Codable {
- if let rtmId = self.rtcLookup[user] {
- self.sendRaw(message: message, member: rtmId, callback: callback)
- } else {
- callback(.peerUnreachable)
- }
- }
-}
diff --git a/Sources/Agora-UIKit/AgoraSettings.swift b/Sources/Agora-UIKit/AgoraSettings.swift
index 4395aa1d..0390468a 100644
--- a/Sources/Agora-UIKit/AgoraSettings.swift
+++ b/Sources/Agora-UIKit/AgoraSettings.swift
@@ -6,7 +6,9 @@
//
import AgoraRtcKit
+#if canImport(AgoraRtmControl)
import AgoraRtmKit
+#endif
/// Settings used for the display and behaviour of AgoraVideoViewer
public struct AgoraSettings {
@@ -14,6 +16,7 @@ public struct AgoraSettings {
/// Delegate for Agora Rtc Engine callbacks
public weak var rtcDelegate: AgoraRtcEngineDelegate?
+ #if canImport(AgoraRtmControl)
/// Delegate for Agora RTM callbacks
public weak var rtmDelegate: AgoraRtmDelegate?
@@ -22,6 +25,7 @@ public struct AgoraSettings {
/// Whether RTM should be initialised and used
public var rtmEnabled: Bool = true
+ #endif
/// URL to fetch tokens from. If supplied, this package will automatically fetch tokens
/// when the Agora Engine indicates it will be needed.
diff --git a/Sources/Agora-UIKit/AgoraSingleVideoView+RtmDelegate.swift b/Sources/Agora-UIKit/AgoraSingleVideoView+RtmDelegate.swift
index feeb7c01..d373308c 100644
--- a/Sources/Agora-UIKit/AgoraSingleVideoView+RtmDelegate.swift
+++ b/Sources/Agora-UIKit/AgoraSingleVideoView+RtmDelegate.swift
@@ -10,11 +10,22 @@ import UIKit
#elseif os(macOS)
import AppKit
#endif
+#if canImport(AgoraRtmControl)
+import AgoraRtmControl
+#endif
/// Protocol for being able to access the AgoraRtmController and presenting alerts
public protocol SingleVideoViewDelegate: AnyObject {
+ #if canImport(AgoraRtmControl)
/// RTM Controller class for managing RTM messages
var rtmController: AgoraRtmController? { get set }
+ func createRequest(
+ to uid: UInt,
+ fromString str: String
+ ) -> Bool
+ func sendMuteRequest(to rtcId: UInt, mute: Bool, device: AgoraVideoViewer.MutingDevices, isForceful: Bool)
+
+ #endif
#if os(iOS)
/// presentAlert is a way to show any alerts that want to display.
/// These could be relating to video or audio unmuting requests.
@@ -38,6 +49,8 @@ extension SingleVideoViewDelegate {
viewCont.present(alert, animated: animated)
} else if let vidViewer = self as? AgoraVideoViewer {
vidViewer.delegate?.presentAlert(alert: alert, animated: animated)
+ } else {
+ AgoraVideoViewer.agoraPrint(.error, message: "Could not present popup")
}
}
#endif
diff --git a/Sources/Agora-UIKit/AgoraSingleVideoView+RtmOptions.swift b/Sources/Agora-UIKit/AgoraSingleVideoView+RtmOptions.swift
index e0ce72da..c6dc53b7 100644
--- a/Sources/Agora-UIKit/AgoraSingleVideoView+RtmOptions.swift
+++ b/Sources/Agora-UIKit/AgoraSingleVideoView+RtmOptions.swift
@@ -10,8 +10,30 @@ import Foundation
import UIKit
#elseif os(macOS)
import AppKit
+#if canImport(AgoraRtmControl)
+import AgoraRtmControl
#endif
+#endif
+
+extension AgoraSingleVideoView {
+ func updateUserOptions() {
+ #if os(macOS) && canImport(AgoraRtmControl)
+ if !Thread.isMainThread {
+ DispatchQueue.main.async {
+ self.updateUserOptions()
+ }
+ return
+ }
+ guard let userOptions = self.userOptions as? NSPopUpButton else {
+ return
+ }
+ userOptions.removeAllItems()
+ self.addItems(to: userOptions)
+ #endif
+ }
+}
+#if canImport(AgoraRtmControl)
extension AgoraSingleVideoView {
/// Find the string for the option ready to request the remote user to mute or unmute their mic or camera
@@ -20,7 +42,7 @@ extension AgoraSingleVideoView {
/// - isMuted: Boolean option to mute or unmute device
/// - Returns: String to be displayed in the mute/unmute option
open func userOptionsString(
- for option: AgoraRtmController.MutingDevices, isMuted: Bool
+ for option: AgoraVideoViewer.MutingDevices, isMuted: Bool
) -> String {
switch option {
case .camera:
@@ -30,21 +52,6 @@ extension AgoraSingleVideoView {
}
}
- func updateUserOptions() {
- #if os(macOS)
- if !Thread.isMainThread {
- DispatchQueue.main.async {
- self.updateUserOptions()
- }
- return
- }
- guard let userOptions = self.userOptions as? NSPopUpButton else {
- return
- }
- userOptions.removeAllItems()
- self.addItems(to: userOptions)
- #endif
- }
#if os(macOS)
open func addItems(to userOptionsBtn: NSPopUpButton) {
let actionItem = NSMenuItem()
@@ -53,7 +60,7 @@ extension AgoraSingleVideoView {
attributes: [ NSAttributedString.Key.foregroundColor: self.micFlagColor ]
)
userOptionsBtn.menu?.insertItem(actionItem, at: 0)
- AgoraRtmController.MutingDevices.allCases.forEach { enumCase in
+ AgoraVideoViewer.MutingDevices.allCases.forEach { enumCase in
var isMuted: Bool
switch enumCase {
case .camera:
@@ -71,7 +78,7 @@ extension AgoraSingleVideoView {
/// - Parameter sender: Button that was selected
@objc open func optionsBtnSelected(sender: UIButton) {
let alert = UIAlertController(title: "Request Action", message: nil, preferredStyle: .actionSheet)
- AgoraRtmController.MutingDevices.allCases.forEach { enumCase in
+ AgoraVideoViewer.MutingDevices.allCases.forEach { enumCase in
var isMuted: Bool
switch enumCase {
case .camera:
@@ -88,14 +95,18 @@ extension AgoraSingleVideoView {
)
}
alert.addAction(UIAlertAction(title: "Cancel", style: .cancel, handler: nil))
- self.singleVideoViewDelegate?.presentAlert(alert: alert, animated: true)
+ if self.singleVideoViewDelegate != nil {
+ self.singleVideoViewDelegate?.presentAlert(alert: alert, animated: true)
+ } else {
+ AgoraVideoViewer.agoraPrint(.error, message: "Could not present popup")
+ }
}
/// Action selected such as mute/unmute microphone/camera.
/// - Parameter sender: UIAlertAction that was selected.
open func optionsActionSelected(sender: UIAlertAction) {
if let actionTitle = sender.title,
- let reqError = self.singleVideoViewDelegate?.rtmController?.createRequest(
+ let reqError = self.singleVideoViewDelegate?.createRequest(
to: self.uid, fromString: actionTitle
), !reqError {
AgoraVideoViewer.agoraPrint(.error, message: "invalid action title: \(actionTitle)")
@@ -106,7 +117,7 @@ extension AgoraSingleVideoView {
/// - Parameter sender: Button that was selected
@objc public func optionsBtnSelected(sender: NSPopUpButton) {
if let actionTitle = sender.selectedItem?.title,
- let reqError = self.singleVideoViewDelegate?.rtmController?.createRequest(
+ let reqError = self.singleVideoViewDelegate?.createRequest(
to: self.uid, fromString: actionTitle
), !reqError {
AgoraVideoViewer.agoraPrint(.error, message: "invalid action title: \(actionTitle)")
@@ -115,3 +126,4 @@ extension AgoraSingleVideoView {
#endif
}
+#endif
diff --git a/Sources/Agora-UIKit/AgoraSingleVideoView.swift b/Sources/Agora-UIKit/AgoraSingleVideoView.swift
index 1e0904e6..b4151994 100644
--- a/Sources/Agora-UIKit/AgoraSingleVideoView.swift
+++ b/Sources/Agora-UIKit/AgoraSingleVideoView.swift
@@ -37,7 +37,9 @@ public class AgoraSingleVideoView: MPView {
/// Whether the options label should be visible or not.
public var showOptions: Bool = true {
didSet {
+ #if canImport(AgoraRtmControl)
self.userOptions?.isHidden = !self.showOptions
+ #endif
}
}
/// Unique ID for this user, used by the video feed.
@@ -59,6 +61,7 @@ public class AgoraSingleVideoView: MPView {
case microphone
}
+ #if canImport(AgoraRtmControl)
lazy var userOptions: MPView? = {
#if os(iOS)
let userOptionsBtn = MPButton.newToggleButton(
@@ -97,6 +100,7 @@ public class AgoraSingleVideoView: MPView {
// userOptionsBtn.isHidden = true
return userOptionsBtn
}()
+ #endif
/// Icon to show if this user is muting their microphone
lazy var mutedFlag: MPView = {
diff --git a/Sources/Agora-UIKit/AgoraUIKit+AgoraRtmController+Extensions.swift b/Sources/Agora-UIKit/AgoraUIKit+AgoraRtmController+Extensions.swift
new file mode 100644
index 00000000..ffccf5e3
--- /dev/null
+++ b/Sources/Agora-UIKit/AgoraUIKit+AgoraRtmController+Extensions.swift
@@ -0,0 +1,171 @@
+//
+// AgoraUIKit+AgoraRtmController+Extensions.swift
+//
+//
+// Created by Max Cobb on 04/04/2022.
+//
+
+import AgoraRtcKit
+#if canImport(AgoraRtmKit)
+import AgoraRtmKit
+#endif
+
+extension AgoraVideoViewer {
+ /// Data about a user (local or remote)
+ public struct UserData: Codable {
+ /// Type of message being sent
+ var messageType: String? = "UserData"
+ /// ID used in the RTM connection
+ var rtmId: String
+ /// ID used in the RTC (Video/Audio) connection
+ var rtcId: UInt?
+ /// Username to be displayed for remote users
+ var username: String?
+ /// Role of the user (broadcaster or audience)
+ var role: AgoraClientRole.RawValue
+ /// Properties about the Agora SDK versions this user is using
+ var agora: AgoraVersions = .current
+ /// Agora UIKit platform (iOS, Android, Flutter, React Native)
+ var uikit: AgoraUIKit = .current
+ func prettyPrint() -> String {
+ """
+ rtm: \(rtmId)
+ rtc: \(rtcId ?? 0)
+ username: \(username ?? "nil")
+ role: \(role)
+ agora: \n\(agora.prettyPrint())
+ uikit: \n\(uikit.prettyPrint())
+ """
+ }
+ }
+
+ /// Data about the Agora SDK versions a user is using (local or remote)
+ public struct AgoraVersions: Codable {
+ /// Versions of the local users current RTM and RTC SDKs
+ static var current: AgoraVersions {
+ var version = AgoraVersions()
+ #if canImport(AgoraRtmKit)
+ version.rtm = AgoraRtmKit.getSDKVersion()
+ #endif
+ version.rtc = AgoraRtcEngineKit.getSdkVersion()
+ return version
+ }
+ /// Version string of the RTM SDK
+ var rtm: String?
+ /// Version string of the RTC SDK
+ var rtc: String?
+ func prettyPrint() -> String {
+ """
+ rtc: \(rtc ?? "none found")
+ rtm: \(rtm ?? "none found")
+ """
+ }
+ }
+
+ public var agConnection: AgoraConnectionData {
+ get { self.connectionData }
+ set { self.connectionData = newValue }
+ }
+ public var rtcEngine: AgoraRtcEngineKit { self.agkit }
+ public var videoLookup: [UInt: AgoraSingleVideoView] { self.userVideoLookup }
+
+}
+#if canImport(AgoraRtmControl)
+import AgoraRtmKit
+import AgoraRtmControl
+
+extension AgoraVideoViewer: RtmControllerDelegate {
+
+ public func rtmStateChanged(
+ from oldState: AgoraRtmController.RTMStatus, to newState: AgoraRtmController.RTMStatus
+ ) { self.delegate?.rtmStateChanged(from: oldState, to: newState) }
+
+ /// Decode an incoming AgoraRtmMessage
+ /// - Parameters:
+ /// - message: Incoming RTM message.
+ /// - peerId: Id of the peer this message is coming from
+ public func decodeMessage(message: AgoraRtmMessage, from peerId: String) {
+ var messageData: Data!
+ if let message = message as? AgoraRtmRawMessage {
+ messageData = message.rawData
+ } else if let msgData = message.text.data(using: .utf8) {
+ messageData = msgData
+ } else {
+ return
+ }
+ if let decodedMsg = AgoraVideoViewer.decodeRtmData(
+ data: messageData, from: peerId
+ ) { self.handleDecodedMessage(decodedMsg, from: peerId) }
+ }
+
+ func handleDecodedMessage(_ rtmAction: DecodedRtmAction, from peerId: String) {
+ switch rtmAction {
+ case .mute(let muteReq):
+ self.handleMuteRequest(muteReq: muteReq)
+ case .userData(let user):
+ AgoraVideoViewer.agoraPrint(
+ .verbose, message: "Received user data: \n\(user.prettyPrint())"
+ )
+ self.rtmLookup[user.rtmId] = user
+ if let rtcId = user.rtcId {
+ self.rtcLookup[rtcId] = user.rtmId
+ self.videoLookup[rtcId]?
+ .showOptions = self.agoraSettings.showRemoteRequestOptions
+ }
+ case .dataRequest(let requestVal):
+ switch requestVal.type {
+ case .userData:
+ self.sendPersonalData(to: peerId)
+ case .ping:
+ self.rtmController?.sendCodable(
+ message: RtmDataRequest(type: .pong), member: peerId
+ ) {_ in }
+ case .pong:
+ AgoraVideoViewer.agoraPrint(
+ .verbose, message: "Received pong from \(peerId)"
+ )
+ self.handlePongRequest(from: peerId)
+ }
+ }
+ }
+
+ // MARK: RtmControllerDelegate Properties
+
+ /// Agora Real-time Messaging Identifier (Agora RTM SDK).
+ public var rtmId: String { self.connectionData.rtmId }
+ /// Agora Real-time Communication Identifier (Agora Video/Audio SDK).
+ public var rtcId: UInt? { self.connectionData.rtcId }
+ /// Agora App ID from https://agora.io
+ public var appId: String { self.connectionData.appId }
+ /// Token to be used to connect to a RTM channel, can be nil.
+ public var rtmToken: String? {
+ get { self.connectionData.rtmToken }
+ set { self.connectionData.rtmToken = newValue }
+ }
+
+ public func handlePongRequest(from peerId: String) {
+ self.delegate?.incomingPongRequest(from: peerId)
+ }
+ public func rtmChannelJoined(
+ name: String, channel: AgoraRtmChannel, code: AgoraRtmJoinChannelErrorCode
+ ) {
+ if code == .channelErrorOk {
+ self.sendPersonalData(to: channel)
+ }
+ self.delegate?.rtmChannelJoined(name: name, channel: channel, code: code)
+ }
+ public var rtmDelegate: AgoraRtmDelegate? { self.agoraSettings.rtmDelegate }
+ public var rtmChannelDelegate: AgoraRtmChannelDelegate? { self.agoraSettings.rtmChannelDelegate }
+ public func channel(_ channel: AgoraRtmChannel, memberJoined member: AgoraRtmMember) {
+ self.sendPersonalData(to: member.userId)
+ }
+ public func personalData() -> some Codable {
+ UserData(
+ rtmId: self.rtmId,
+ rtcId: self.rtcId == 0 ? nil : self.rtcId,
+ username: self.connectionData?.username,
+ role: self.userRole.rawValue
+ )
+ }
+}
+#endif
diff --git a/Sources/Agora-UIKit/AgoraRtmController+MuteRequests.swift b/Sources/Agora-UIKit/AgoraUIKit+AgoraRtmController+MuteRequests.swift
similarity index 83%
rename from Sources/Agora-UIKit/AgoraRtmController+MuteRequests.swift
rename to Sources/Agora-UIKit/AgoraUIKit+AgoraRtmController+MuteRequests.swift
index 02215ccd..66c60aee 100644
--- a/Sources/Agora-UIKit/AgoraRtmController+MuteRequests.swift
+++ b/Sources/Agora-UIKit/AgoraUIKit+AgoraRtmController+MuteRequests.swift
@@ -1,8 +1,8 @@
//
-// AgoraRtmController+MuteRequests.swift
+// AgoraUIKit+AgoraRtmController+MuteRequests.swift
//
//
-// Created by Max Cobb on 29/07/2021.
+// Created by Max Cobb on 04/04/2022.
//
#if os(iOS)
@@ -10,14 +10,25 @@ import UIKit
#elseif os(macOS)
import AppKit
#endif
+#if canImport(AgoraRtmControl)
+import AgoraRtmControl
+#endif
-extension AgoraRtmController {
+extension AgoraVideoViewer {
/// Devices that can be muted/unmuted
- public enum MutingDevices: Int, CaseIterable {
+ @objc public enum MutingDevices: Int, CaseIterable {
/// The device camera
case camera = 0
/// The device microphone
case microphone = 1
+ var strVal: String {
+ switch self {
+ case .camera:
+ return "camera"
+ case .microphone:
+ return "micropohne"
+ }
+ }
}
/// Structure that contains information about a mute request
@@ -29,7 +40,7 @@ extension AgoraRtmController {
/// Whether the request is to mute or unmute a device
public var mute: Bool
/// Device to be muted or unmuted
- public var device: AgoraRtmController.MutingDevices.RawValue
+ public var device: MutingDevices.RawValue
/// Whether this is a request or a forceful change
public var isForceful: Bool
@@ -41,7 +52,7 @@ extension AgoraRtmController {
/// - isForceful: Whether this is a request or a forceful change
public init(
rtcId: UInt, mute: Bool,
- device: AgoraRtmController.MutingDevices, isForceful: Bool
+ device: MutingDevices, isForceful: Bool
) {
self.rtcId = rtcId
self.mute = mute
@@ -68,30 +79,7 @@ extension AgoraRtmController {
public var type: DataRequestType
}
- /// Create and send request to user to mute/unmute a device
- /// - Parameters:
- /// - uid: RTM User ID to send the request to
- /// - str: String from the action label to
- /// - Returns: Boolean stating if the request was valid or not
- open func createRequest(
- to uid: UInt,
- fromString str: String
- ) -> Bool {
- switch str {
- case MPButton.unmuteCameraString:
- self.sendMuteRequest(to: uid, mute: false, device: .camera)
- case MPButton.muteCameraString:
- self.sendMuteRequest(to: uid, mute: true, device: .camera)
- case MPButton.unmuteMicString:
- self.sendMuteRequest(to: uid, mute: false, device: .microphone)
- case MPButton.muteMicString:
- self.sendMuteRequest(to: uid, mute: true, device: .microphone)
- default:
- return false
- }
- return true
- }
-
+ #if canImport(AgoraRtmControl)
/// Create and send request to mute/unmute a device
/// - Parameters:
/// - rtcId: RTC User ID to send the request to
@@ -104,7 +92,7 @@ extension AgoraRtmController {
return
}
let muteReq = MuteRequest(rtcId: rtcId, mute: mute, device: device, isForceful: isForceful)
- self.sendRaw(message: muteReq, user: rtcId) { sendStatus in
+ self.rtmController?.sendCodable(message: muteReq, user: rtcId) { sendStatus in
if sendStatus == .ok {
AgoraVideoViewer.agoraPrint(.verbose, message: "message was sent!")
} else {
@@ -112,14 +100,43 @@ extension AgoraRtmController {
}
}
}
+ #endif
}
+#if canImport(AgoraRtmControl)
+extension SingleVideoViewDelegate {
+ /// Create and send request to user to mute/unmute a device
+ /// - Parameters:
+ /// - uid: RTM User ID to send the request to
+ /// - str: String from the action label to
+ /// - Returns: Boolean stating if the request was valid or not
+ public func createRequest(
+ to uid: UInt,
+ fromString str: String
+ ) -> Bool {
+ switch str {
+ case MPButton.unmuteCameraString:
+ self.sendMuteRequest(to: uid, mute: false, device: .camera, isForceful: false)
+ case MPButton.muteCameraString:
+ self.sendMuteRequest(to: uid, mute: true, device: .camera, isForceful: false)
+ case MPButton.unmuteMicString:
+ self.sendMuteRequest(to: uid, mute: false, device: .microphone, isForceful: false)
+ case MPButton.muteMicString:
+ self.sendMuteRequest(to: uid, mute: true, device: .microphone, isForceful: false)
+ default:
+ return false
+ }
+ return true
+ }
+}
+#endif
+
extension AgoraVideoViewer {
/// Handle mute request, by showing popup or directly changing the device state
/// - Parameter muteReq: Incoming mute request data
- open func handleMuteRequest(muteReq: AgoraRtmController.MuteRequest) {
- guard let device = AgoraRtmController.MutingDevices(rawValue: muteReq.device) else {
+ open func handleMuteRequest(muteReq: MuteRequest) {
+ guard let device = MutingDevices(rawValue: muteReq.device) else {
return
}
if device == .camera, self.agoraSettings.cameraEnabled == !muteReq.mute { return }
@@ -128,7 +145,7 @@ extension AgoraVideoViewer {
AgoraVideoViewer.agoraPrint(
.error,
message: "user \(muteReq.rtcId) (self) should \(muteReq.mute ? "" : "un")mute" +
- " their \(device) by \(muteReq.isForceful ? "force" : "request")"
+ " their \(device.strVal) by \(muteReq.isForceful ? "force" : "request")"
)
func setDevice(_ sender: Any? = nil) {
switch device {
@@ -142,7 +159,7 @@ extension AgoraVideoViewer {
setDevice()
return
}
- let alertTitle = "\(muteReq.mute ? "" : "un")mute \(device)?"
+ let alertTitle = "\(muteReq.mute ? "" : "un")mute \(device.strVal)?"
#if os(iOS)
let alert = UIAlertController(
title: alertTitle, message: nil,
diff --git a/Sources/Agora-UIKit/AgoraUIKit+AgoraRtmController+SendHelpers.swift b/Sources/Agora-UIKit/AgoraUIKit+AgoraRtmController+SendHelpers.swift
new file mode 100644
index 00000000..35913386
--- /dev/null
+++ b/Sources/Agora-UIKit/AgoraUIKit+AgoraRtmController+SendHelpers.swift
@@ -0,0 +1,97 @@
+//
+// AgoraUIKit+AgoraRtmController+Extensions.swift
+//
+//
+// Created by Max Cobb on 04/04/2022.
+//
+
+import Foundation
+#if canImport(AgoraRtmControl)
+import AgoraRtmKit
+import AgoraRtmControl
+#endif
+
+extension AgoraVideoViewer {
+ /// Type of decoded message coming from other users
+ public enum DecodedRtmAction {
+ /// Mute is when a user is requesting another user to mute or unmute a device
+ case mute(_: MuteRequest)
+ /// DecodedRtmAction type containing data about a user (local or remote)
+ case userData(_: AgoraVideoViewer.UserData)
+ /// Message that contains a small action request, such as a ping or requesting a user's data
+ case dataRequest(_: RtmDataRequest)
+ }
+
+ /// Decode message to a compatible DecodedRtmMessage type.
+ /// - Parameters:
+ /// - data: Raw data input, should be utf8 encoded JSON string of MuteRequest or UserData.
+ /// - rtmId: Sender Real-time Messaging ID.
+ /// - Returns: DecodedRtmMessage enum of the appropriate type.
+ internal static func decodeRtmData(data: Data, from rtmId: String) -> DecodedRtmAction? {
+ let decoder = JSONDecoder()
+ if let userData = try? decoder.decode(AgoraVideoViewer.UserData.self, from: data) {
+ return .userData(userData)
+ } else if let muteReq = try? decoder.decode(MuteRequest.self, from: data) {
+ return .mute(muteReq)
+ } else if let requestVal = try? decoder.decode(RtmDataRequest.self, from: data) {
+ return .dataRequest(requestVal)
+ }
+ return nil
+ }
+
+ #if canImport(AgoraRtmControl)
+ /// Share local UserData to all connected channels.
+ /// Call this method when personal details are updated.
+ open func broadcastPersonalData() {
+ for channel in (self.rtmController?.channels ?? [String: AgoraRtmChannel]()) {
+ self.sendPersonalData(to: channel.value)
+ }
+ }
+
+ /// Share local UserData to a specific channel
+ /// - Parameter channel: Channel to share UserData with.
+ open func sendPersonalData(to channel: AgoraRtmChannel) {
+ if self.rtmController == nil {
+ AgoraVideoViewer.agoraPrint(
+ .warning, message: "AgoraRtmController not included, override this method to send personal data"
+ )
+ return
+ }
+ self.rtmController?.sendCodable(message: self.personalData(), channel: channel) { sendMsgState in
+ switch sendMsgState {
+ case .errorOk:
+ AgoraVideoViewer.agoraPrint(
+ .verbose, message: "Personal data sent to channel successfully"
+ )
+ case .errorFailure, .errorTimeout, .tooOften,
+ .invalidMessage, .errorNotInitialized, .notLoggedIn:
+ AgoraVideoViewer.agoraPrint(
+ .error, message: "Could not send message to channel \(sendMsgState.rawValue)"
+ )
+ @unknown default:
+ AgoraVideoViewer.agoraPrint(.error, message: "Could not send message to channel (unknown)")
+ }
+ }
+ }
+
+ /// Share local UserData to a specific RTM member
+ /// - Parameter member: Member to share UserData with.
+ open func sendPersonalData(to member: String) {
+ self.rtmController?.sendCodable(message: self.personalData(), member: member) { sendMsgState in
+ switch sendMsgState {
+ case .ok:
+ AgoraVideoViewer.agoraPrint(
+ .verbose, message: "Personal data sent to member successfully"
+ )
+ case .failure, .timeout, .tooOften, .invalidMessage, .notInitialized, .notLoggedIn,
+ .peerUnreachable, .cachedByServer, .invalidUserId, .imcompatibleMessage:
+ AgoraVideoViewer.agoraPrint(
+ .error, message: "Could not send message to channel \(sendMsgState.rawValue)"
+ )
+ @unknown default:
+ AgoraVideoViewer.agoraPrint(.error, message: "Could not send message to channel (unknown)")
+ }
+ }
+ }
+ #endif
+}
diff --git a/Sources/Agora-UIKit/AgoraUIKit.swift b/Sources/Agora-UIKit/AgoraUIKit.swift
index 61267267..3e4f7367 100644
--- a/Sources/Agora-UIKit/AgoraUIKit.swift
+++ b/Sources/Agora-UIKit/AgoraUIKit.swift
@@ -22,7 +22,7 @@ public struct AgoraUIKit: Codable {
/// Framework type of UIKit. "native", "flutter", "reactnative"
fileprivate(set) var framework: String
/// Version of UIKit being used
- static let version = "1.7.6"
+ static let version = "1.8.0"
/// Framework type of UIKit. "native", "flutter", "reactnative"
static let framework = "native"
#if os(iOS)
diff --git a/Sources/Agora-UIKit/AgoraVideoViewer+AgoraRtcEngineDelegate.swift b/Sources/Agora-UIKit/AgoraVideoViewer+AgoraRtcEngineDelegate.swift
index 61815cc3..62942f7c 100644
--- a/Sources/Agora-UIKit/AgoraVideoViewer+AgoraRtcEngineDelegate.swift
+++ b/Sources/Agora-UIKit/AgoraVideoViewer+AgoraRtcEngineDelegate.swift
@@ -28,8 +28,11 @@ extension AgoraVideoViewer: AgoraRtcEngineDelegate {
// Only show the camera options when we are a broadcaster
self.getControlContainer().isHidden = !isHost
- self.rtmController?.broadcastPersonalData()
- self.agSettings.rtcDelegate?.rtcEngine?(engine, didClientRoleChanged: oldRole, newRole: newRole)
+
+ #if canImport(AgoraRtmControl)
+ self.broadcastPersonalData()
+ #endif
+ self.agoraSettings.rtcDelegate?.rtcEngine?(engine, didClientRoleChanged: oldRole, newRole: newRole)
}
/// New User joined the channel
@@ -44,7 +47,7 @@ extension AgoraVideoViewer: AgoraRtcEngineDelegate {
) {
// Keeping track of all people in the session
self.remoteUserIDs.insert(uid)
- self.agSettings.rtcDelegate?.rtcEngine?(engine, didJoinedOfUid: uid, elapsed: elapsed)
+ self.agoraSettings.rtcDelegate?.rtcEngine?(engine, didJoinedOfUid: uid, elapsed: elapsed)
}
/// This callback indicates the state change of the local audio stream, including the state of the audio recording and encoding, and allows you to troubleshoot issues when exceptions occur.
@@ -70,7 +73,7 @@ extension AgoraVideoViewer: AgoraRtcEngineDelegate {
}
}
}
- self.agSettings.rtcDelegate?.rtcEngine?(
+ self.agoraSettings.rtcDelegate?.rtcEngine?(
engine, remoteAudioStateChangedOfUid: uid, state: state,
reason: reason, elapsed: elapsed
)
@@ -105,7 +108,7 @@ extension AgoraVideoViewer: AgoraRtcEngineDelegate {
// and remove this view from the list
self.removeUserVideo(with: uid)
}
- self.agSettings.rtcDelegate?.rtcEngine?(engine, didOfflineOfUid: uid, reason: reason)
+ self.agoraSettings.rtcDelegate?.rtcEngine?(engine, didOfflineOfUid: uid, reason: reason)
}
/**
@@ -126,7 +129,7 @@ extension AgoraVideoViewer: AgoraRtcEngineDelegate {
*/
open func rtcEngine(_ engine: AgoraRtcEngineKit, activeSpeaker speakerUid: UInt) {
self.activeSpeaker = speakerUid
- self.agSettings.rtcDelegate?.rtcEngine?(engine, activeSpeaker: speakerUid)
+ self.agoraSettings.rtcDelegate?.rtcEngine?(engine, activeSpeaker: speakerUid)
}
/**
@@ -156,7 +159,7 @@ extension AgoraVideoViewer: AgoraRtcEngineDelegate {
default:
break
}
- self.agSettings.rtcDelegate?.rtcEngine?(
+ self.agoraSettings.rtcDelegate?.rtcEngine?(
engine, remoteVideoStateChangedOfUid: uid, state: state,
reason: reason, elapsed: elapsed
)
@@ -182,7 +185,7 @@ extension AgoraVideoViewer: AgoraRtcEngineDelegate {
default:
break
}
- self.agSettings.rtcDelegate?.rtcEngine?(engine, localVideoStateChange: state, error: error)
+ self.agoraSettings.rtcDelegate?.rtcEngine?(engine, localVideoStateChange: state, error: error)
}
/**
@@ -207,7 +210,7 @@ extension AgoraVideoViewer: AgoraRtcEngineDelegate {
default:
break
}
- self.agSettings.rtcDelegate?.rtcEngine?(engine, localAudioStateChange: state, error: error)
+ self.agoraSettings.rtcDelegate?.rtcEngine?(engine, localAudioStateChange: state, error: error)
}
/**
@@ -225,7 +228,7 @@ extension AgoraVideoViewer: AgoraRtcEngineDelegate {
*/
open func rtcEngine(_ engine: AgoraRtcEngineKit, firstLocalAudioFramePublished elapsed: Int) {
self.addLocalVideo()?.audioMuted = false
- self.agSettings.rtcDelegate?.rtcEngine?(engine, firstLocalAudioFramePublished: elapsed)
+ self.agoraSettings.rtcDelegate?.rtcEngine?(engine, firstLocalAudioFramePublished: elapsed)
}
/**
@@ -244,7 +247,7 @@ extension AgoraVideoViewer: AgoraRtcEngineDelegate {
)
}
self.delegate?.tokenDidExpire(engine)
- self.agSettings.rtcDelegate?.rtcEngineRequestToken?(engine)
+ self.agoraSettings.rtcDelegate?.rtcEngineRequestToken?(engine)
}
/**
@@ -265,6 +268,6 @@ extension AgoraVideoViewer: AgoraRtcEngineDelegate {
)
}
self.delegate?.tokenWillExpire(engine, tokenPrivilegeWillExpire: token)
- self.agSettings.rtcDelegate?.rtcEngine?(engine, tokenPrivilegeWillExpire: token)
+ self.agoraSettings.rtcDelegate?.rtcEngine?(engine, tokenPrivilegeWillExpire: token)
}
}
diff --git a/Sources/Agora-UIKit/AgoraVideoViewer+Buttons.swift b/Sources/Agora-UIKit/AgoraVideoViewer+Buttons.swift
index 3ab8be14..73264b62 100644
--- a/Sources/Agora-UIKit/AgoraVideoViewer+Buttons.swift
+++ b/Sources/Agora-UIKit/AgoraVideoViewer+Buttons.swift
@@ -22,14 +22,14 @@ extension AgoraVideoViewer {
_ resizeMask: inout UIView.AutoresizingMask, _ containerSize: inout CGSize
) {
resizeMask = [.flexibleLeftMargin, .flexibleRightMargin, .flexibleTopMargin]
- switch self.agSettings.buttonPosition {
+ switch self.agoraSettings.buttonPosition {
case .top:
frameOriginY = 30
resizeMask = [.flexibleLeftMargin, .flexibleRightMargin, .flexibleBottomMargin]
case .left, .right:
containerSize = CGSize(width: containerSize.height, height: containerSize.width)
frameOriginY = (self.bounds.height - CGFloat(contWidth)) / 2
- if self.agSettings.buttonPosition == .left {
+ if self.agoraSettings.buttonPosition == .left {
frameOriginX = 30
resizeMask = [.flexibleTopMargin, .flexibleRightMargin, .flexibleBottomMargin]
} else {
@@ -45,10 +45,10 @@ extension AgoraVideoViewer {
_ frameOriginX: inout CGFloat, _ frameOriginY: inout CGFloat, _ contWidth: CGFloat,
_ resizeMask: inout NSView.AutoresizingMask, _ containerSize: inout CGSize
) {
- switch self.agSettings.buttonPosition {
+ switch self.agoraSettings.buttonPosition {
case .top, .bottom:
frameOriginX = (self.bounds.width - CGFloat(contWidth)) / 2
- if self.agSettings.buttonPosition == .top {
+ if self.agoraSettings.buttonPosition == .top {
frameOriginY = self.bounds.height - self.agoraSettings.buttonSize - 20 - 10
resizeMask = [.minXMargin, .maxXMargin, .minYMargin]
} else {
@@ -58,7 +58,7 @@ extension AgoraVideoViewer {
case .left, .right:
containerSize = CGSize(width: containerSize.height, height: containerSize.width)
frameOriginY = (self.bounds.height - CGFloat(contWidth)) / 2
- if self.agSettings.buttonPosition == .left {
+ if self.agoraSettings.buttonPosition == .left {
frameOriginX = 20
resizeMask = [.minYMargin, .maxXMargin, .maxYMargin]
} else {
diff --git a/Sources/Agora-UIKit/AgoraVideoViewer+Ordering.swift b/Sources/Agora-UIKit/AgoraVideoViewer+Ordering.swift
index c7620d93..a3a2ee44 100644
--- a/Sources/Agora-UIKit/AgoraVideoViewer+Ordering.swift
+++ b/Sources/Agora-UIKit/AgoraVideoViewer+Ordering.swift
@@ -37,7 +37,7 @@ extension AgoraVideoViewer {
uid: userId, micColor: self.agoraSettings.colors.micFlag, delegate: self
)
remoteVideoView.canvas.renderMode = self.agoraSettings.videoRenderMode
- if self.rtmController?.rtcLookup.index(forKey: userId) != nil {
+ if self.rtcLookup.index(forKey: userId) != nil {
remoteVideoView.showOptions = self.agoraSettings.showRemoteRequestOptions
}
self.agkit.setupRemoteVideo(remoteVideoView.canvas)
@@ -63,7 +63,7 @@ extension AgoraVideoViewer {
let canView = userSingleView.canvas.view else {
return
}
- self.agkit.muteRemoteVideoStream(userId, mute: true)
+// self.agkit.muteRemoteVideoStream(userId, mute: true)
userSingleView.canvas.view = nil
canView.removeFromSuperview()
self.userVideoLookup.removeValue(forKey: userId)
diff --git a/Sources/Agora-UIKit/AgoraVideoViewer+Permissions.swift b/Sources/Agora-UIKit/AgoraVideoViewer+Permissions.swift
index ebf01497..43a2a255 100644
--- a/Sources/Agora-UIKit/AgoraVideoViewer+Permissions.swift
+++ b/Sources/Agora-UIKit/AgoraVideoViewer+Permissions.swift
@@ -101,7 +101,7 @@ extension AgoraVideoViewer {
func cameraMicSettingsPopup(successHandler: @escaping () -> Void) {
#if os(iOS)
if self.delegate?.presentAlert == nil {
- AgoraVideoViewer.agoraPrint(.error, message: "Could not present settings popup")
+ AgoraVideoViewer.agoraPrint(.error, message: "Could not present popup")
// just assume the user accepted this popup and move on
successHandler()
return
diff --git a/Sources/Agora-UIKit/AgoraVideoViewer+RtcEngineDelegateOverflow.swift b/Sources/Agora-UIKit/AgoraVideoViewer+RtcEngineDelegateOverflow.swift
index ba0367db..2bab5924 100644
--- a/Sources/Agora-UIKit/AgoraVideoViewer+RtcEngineDelegateOverflow.swift
+++ b/Sources/Agora-UIKit/AgoraVideoViewer+RtcEngineDelegateOverflow.swift
@@ -9,342 +9,320 @@ import AgoraRtcKit
extension AgoraVideoViewer {
open func rtcEngineConnectionDidLost(_ engine: AgoraRtcEngineKit) {
- self.agSettings.rtcDelegate?.rtcEngineConnectionDidLost?(engine)
+ self.agoraSettings.rtcDelegate?.rtcEngineConnectionDidLost?(engine)
}
open func rtcEngineLocalAudioMixingDidFinish(_ engine: AgoraRtcEngineKit) {
- self.agSettings.rtcDelegate?.rtcEngineLocalAudioMixingDidFinish?(engine)
+ self.agoraSettings.rtcDelegate?.rtcEngineLocalAudioMixingDidFinish?(engine)
}
open func rtcEngineRemoteAudioMixingDidStart(_ engine: AgoraRtcEngineKit) {
- self.agSettings.rtcDelegate?.rtcEngineRemoteAudioMixingDidStart?(engine)
+ self.agoraSettings.rtcDelegate?.rtcEngineRemoteAudioMixingDidStart?(engine)
}
open func rtcEngineRemoteAudioMixingDidFinish(_ engine: AgoraRtcEngineKit) {
- self.agSettings.rtcDelegate?.rtcEngineRemoteAudioMixingDidFinish?(engine)
+ self.agoraSettings.rtcDelegate?.rtcEngineRemoteAudioMixingDidFinish?(engine)
}
open func rtcEngineVideoDidStop(_ engine: AgoraRtcEngineKit) {
- self.agSettings.rtcDelegate?.rtcEngineVideoDidStop?(engine)
+ self.agoraSettings.rtcDelegate?.rtcEngineVideoDidStop?(engine)
}
open func rtcEngineCameraDidReady(_ engine: AgoraRtcEngineKit) {
- self.agSettings.rtcDelegate?.rtcEngineCameraDidReady?(engine)
+ self.agoraSettings.rtcDelegate?.rtcEngineCameraDidReady?(engine)
}
open func rtcEngineTranscodingUpdated(_ engine: AgoraRtcEngineKit) {
- self.agSettings.rtcDelegate?.rtcEngineTranscodingUpdated?(engine)
+ self.agoraSettings.rtcDelegate?.rtcEngineTranscodingUpdated?(engine)
}
open func rtcEngineConnectionDidBanned(_ engine: AgoraRtcEngineKit) {
- self.agSettings.rtcDelegate?.rtcEngineConnectionDidBanned?(engine)
+ self.agoraSettings.rtcDelegate?.rtcEngineConnectionDidBanned?(engine)
}
open func rtcEngineAirPlayIsConnected(_ engine: AgoraRtcEngineKit) {
- self.agSettings.rtcDelegate?.rtcEngineAirPlayIsConnected?(engine)
+ self.agoraSettings.rtcDelegate?.rtcEngineAirPlayIsConnected?(engine)
}
open func rtcEngineMediaEngineDidLoaded(_ engine: AgoraRtcEngineKit) {
- self.agSettings.rtcDelegate?.rtcEngineMediaEngineDidLoaded?(engine)
+ self.agoraSettings.rtcDelegate?.rtcEngineMediaEngineDidLoaded?(engine)
}
open func rtcEngineConnectionDidInterrupted(_ engine: AgoraRtcEngineKit) {
- self.agSettings.rtcDelegate?.rtcEngineConnectionDidInterrupted?(engine)
+ self.agoraSettings.rtcDelegate?.rtcEngineConnectionDidInterrupted?(engine)
}
open func rtcEngineMediaEngineDidStartCall(_ engine: AgoraRtcEngineKit) {
- self.agSettings.rtcDelegate?.rtcEngineMediaEngineDidStartCall?(engine)
+ self.agoraSettings.rtcDelegate?.rtcEngineMediaEngineDidStartCall?(engine)
}
open func rtcEngine(_ engine: AgoraRtcEngineKit, didOccurWarning warningCode: AgoraWarningCode) {
- self.agSettings.rtcDelegate?.rtcEngine?(engine, didOccurWarning: warningCode)
+ self.agoraSettings.rtcDelegate?.rtcEngine?(engine, didOccurWarning: warningCode)
}
open func rtcEngine(_ engine: AgoraRtcEngineKit, didOccurError errorCode: AgoraErrorCode) {
- self.agSettings.rtcDelegate?.rtcEngine?(engine, didOccurError: errorCode)
+ self.agoraSettings.rtcDelegate?.rtcEngine?(engine, didOccurError: errorCode)
}
open func rtcEngine(_ engine: AgoraRtcEngineKit, didLeaveChannelWith stats: AgoraChannelStats) {
- self.agSettings.rtcDelegate?.rtcEngine?(engine, didLeaveChannelWith: stats)
+ self.agoraSettings.rtcDelegate?.rtcEngine?(engine, didLeaveChannelWith: stats)
}
- open func rtcEngine(_ engine: AgoraRtcEngineKit, networkTypeChangedTo type: AgoraNetworkType) {
- self.agSettings.rtcDelegate?.rtcEngine?(engine, networkTypeChangedTo: type)
+ open func rtcEngine(_ engine: AgoraRtcEngineKit, networkTypeChangedToType type: AgoraNetworkType) {
+ self.agoraSettings.rtcDelegate?.rtcEngine?(engine, networkTypeChangedToType: type)
}
+ open func rtcEngine(_ engine: AgoraRtcEngineKit, reportLocalVoicePitchFrequency pitchInHz: Int) {
+ self.agoraSettings.rtcDelegate?.rtcEngine?(engine, reportLocalVoicePitchFrequency: pitchInHz)
+ }
open func rtcEngine(_ engine: AgoraRtcEngineKit, firstLocalAudioFrame elapsed: Int) {
- self.agSettings.rtcDelegate?.rtcEngine?(engine, firstLocalAudioFrame: elapsed)
+ self.agoraSettings.rtcDelegate?.rtcEngine?(engine, firstLocalAudioFrame: elapsed)
}
open func rtcEngine(_ engine: AgoraRtcEngineKit, didLocalPublishFallbackToAudioOnly isFallbackOrRecover: Bool) {
- self.agSettings.rtcDelegate?.rtcEngine?(engine, didLocalPublishFallbackToAudioOnly: isFallbackOrRecover)
+ self.agoraSettings.rtcDelegate?.rtcEngine?(engine, didLocalPublishFallbackToAudioOnly: isFallbackOrRecover)
}
open func rtcEngine(_ engine: AgoraRtcEngineKit, didAudioRouteChanged routing: AgoraAudioOutputRouting) {
- self.agSettings.rtcDelegate?.rtcEngine?(engine, didAudioRouteChanged: routing)
+ self.agoraSettings.rtcDelegate?.rtcEngine?(engine, didAudioRouteChanged: routing)
}
#if os(iOS)
open func rtcEngine(_ engine: AgoraRtcEngineKit, cameraFocusDidChangedTo rect: CGRect) {
- self.agSettings.rtcDelegate?.rtcEngine?(engine, cameraFocusDidChangedTo: rect)
+ self.agoraSettings.rtcDelegate?.rtcEngine?(engine, cameraFocusDidChangedTo: rect)
}
open func rtcEngine(_ engine: AgoraRtcEngineKit, cameraExposureDidChangedTo rect: CGRect) {
- self.agSettings.rtcDelegate?.rtcEngine?(engine, cameraExposureDidChangedTo: rect)
+ self.agoraSettings.rtcDelegate?.rtcEngine?(engine, cameraExposureDidChangedTo: rect)
}
#elseif os(macOS)
public func rtcEngine(_ engine: AgoraRtcEngineKit, device deviceId: String, type deviceType: AgoraMediaDeviceType, stateChanged state: Int) {
- self.agSettings.rtcDelegate?.rtcEngine?(engine, device: deviceId, type: deviceType, stateChanged: state)
+ self.agoraSettings.rtcDelegate?.rtcEngine?(engine, device: deviceId, type: deviceType, stateChanged: state)
}
#endif
open func rtcEngine(_ engine: AgoraRtcEngineKit, reportRtcStats stats: AgoraChannelStats) {
- self.agSettings.rtcDelegate?.rtcEngine?(engine, reportRtcStats: stats)
+ self.agoraSettings.rtcDelegate?.rtcEngine?(engine, reportRtcStats: stats)
}
open func rtcEngine(_ engine: AgoraRtcEngineKit, lastmileQuality quality: AgoraNetworkQuality) {
- self.agSettings.rtcDelegate?.rtcEngine?(engine, lastmileQuality: quality)
+ self.agoraSettings.rtcDelegate?.rtcEngine?(engine, lastmileQuality: quality)
}
open func rtcEngine(_ engine: AgoraRtcEngineKit, lastmileProbeTest result: AgoraLastmileProbeResult) {
- self.agSettings.rtcDelegate?.rtcEngine?(engine, lastmileProbeTest: result)
+ self.agoraSettings.rtcDelegate?.rtcEngine?(engine, lastmileProbeTest: result)
}
open func rtcEngine(_ engine: AgoraRtcEngineKit, localVideoStats stats: AgoraRtcLocalVideoStats) {
- self.agSettings.rtcDelegate?.rtcEngine?(engine, localVideoStats: stats)
+ self.agoraSettings.rtcDelegate?.rtcEngine?(engine, localVideoStats: stats)
}
open func rtcEngine(_ engine: AgoraRtcEngineKit, localAudioStats stats: AgoraRtcLocalAudioStats) {
- self.agSettings.rtcDelegate?.rtcEngine?(engine, localAudioStats: stats)
+ self.agoraSettings.rtcDelegate?.rtcEngine?(engine, localAudioStats: stats)
}
open func rtcEngine(_ engine: AgoraRtcEngineKit, remoteVideoStats stats: AgoraRtcRemoteVideoStats) {
- self.agSettings.rtcDelegate?.rtcEngine?(engine, remoteVideoStats: stats)
+ self.agoraSettings.rtcDelegate?.rtcEngine?(engine, remoteVideoStats: stats)
}
open func rtcEngine(_ engine: AgoraRtcEngineKit, remoteAudioStats stats: AgoraRtcRemoteAudioStats) {
- self.agSettings.rtcDelegate?.rtcEngine?(engine, remoteAudioStats: stats)
+ self.agoraSettings.rtcDelegate?.rtcEngine?(engine, remoteAudioStats: stats)
}
open func rtcEngineDidAudioEffectFinish(_ engine: AgoraRtcEngineKit, soundId: Int) {
- self.agSettings.rtcDelegate?.rtcEngineDidAudioEffectFinish?(engine, soundId: soundId)
+ self.agoraSettings.rtcDelegate?.rtcEngineDidAudioEffectFinish?(engine, soundId: soundId)
}
open func rtcEngine(_ engine: AgoraRtcEngineKit, didReceive event: AgoraChannelMediaRelayEvent) {
- self.agSettings.rtcDelegate?.rtcEngine?(engine, didReceive: event)
+ self.agoraSettings.rtcDelegate?.rtcEngine?(engine, didReceive: event)
}
open func rtcEngine(_ engine: AgoraRtcEngineKit, streamUnpublishedWithUrl url: String) {
- self.agSettings.rtcDelegate?.rtcEngine?(engine, streamUnpublishedWithUrl: url)
+ self.agoraSettings.rtcDelegate?.rtcEngine?(engine, streamUnpublishedWithUrl: url)
}
open func rtcEngine(_ engine: AgoraRtcEngineKit, didMicrophoneEnabled enabled: Bool) {
- self.agSettings.rtcDelegate?.rtcEngine?(engine, didMicrophoneEnabled: enabled)
+ self.agoraSettings.rtcDelegate?.rtcEngine?(engine, didMicrophoneEnabled: enabled)
}
open func rtcEngine(_ engine: AgoraRtcEngineKit, firstLocalVideoFramePublished elapsed: Int) {
- self.agSettings.rtcDelegate?.rtcEngine?(engine, firstLocalVideoFramePublished: elapsed)
+ self.agoraSettings.rtcDelegate?.rtcEngine?(engine, firstLocalVideoFramePublished: elapsed)
}
open func rtcEngine(_ engine: AgoraRtcEngineKit, reportAudioVolumeIndicationOfSpeakers speakers: [AgoraRtcAudioVolumeInfo], totalVolume: Int) {
- self.agSettings.rtcDelegate?.rtcEngine?(engine, reportAudioVolumeIndicationOfSpeakers: speakers, totalVolume: totalVolume)
+ self.agoraSettings.rtcDelegate?.rtcEngine?(engine, reportAudioVolumeIndicationOfSpeakers: speakers, totalVolume: totalVolume)
}
open func rtcEngine(_ engine: AgoraRtcEngineKit, didRegisteredLocalUser userAccount: String, withUid uid: UInt) {
- self.agSettings.rtcDelegate?.rtcEngine?(engine, didRegisteredLocalUser: userAccount, withUid: uid)
+ self.agoraSettings.rtcDelegate?.rtcEngine?(engine, didRegisteredLocalUser: userAccount, withUid: uid)
}
open func rtcEngine(_ engine: AgoraRtcEngineKit, didUpdatedUserInfo userInfo: AgoraUserInfo, withUid uid: UInt) {
- self.agSettings.rtcDelegate?.rtcEngine?(engine, didUpdatedUserInfo: userInfo, withUid: uid)
+ self.agoraSettings.rtcDelegate?.rtcEngine?(engine, didUpdatedUserInfo: userInfo, withUid: uid)
}
open func rtcEngine(_ engine: AgoraRtcEngineKit, connectionChangedTo state: AgoraConnectionStateType, reason: AgoraConnectionChangedReason) {
- self.agSettings.rtcDelegate?.rtcEngine?(engine, connectionChangedTo: state, reason: reason)
+ self.agoraSettings.rtcDelegate?.rtcEngine?(engine, connectionChangedTo: state, reason: reason)
}
open func rtcEngine(_ engine: AgoraRtcEngineKit, firstLocalVideoFrameWith size: CGSize, elapsed: Int) {
- self.agSettings.rtcDelegate?.rtcEngine?(engine, firstLocalVideoFrameWith: size, elapsed: elapsed)
+ self.agoraSettings.rtcDelegate?.rtcEngine?(engine, firstLocalVideoFrameWith: size, elapsed: elapsed)
}
open func rtcEngine(_ engine: AgoraRtcEngineKit, didVideoMuted muted: Bool, byUid uid: UInt) {
- self.agSettings.rtcDelegate?.rtcEngine?(engine, didVideoMuted: muted, byUid: uid)
+ self.agoraSettings.rtcDelegate?.rtcEngine?(engine, didVideoMuted: muted, byUid: uid)
}
open func rtcEngine(_ engine: AgoraRtcEngineKit, didRemoteSubscribeFallbackToAudioOnly isFallbackOrRecover: Bool, byUid uid: UInt) {
- self.agSettings.rtcDelegate?.rtcEngine?(engine, didRemoteSubscribeFallbackToAudioOnly: isFallbackOrRecover, byUid: uid)
+ self.agoraSettings.rtcDelegate?.rtcEngine?(engine, didRemoteSubscribeFallbackToAudioOnly: isFallbackOrRecover, byUid: uid)
}
open func rtcEngine(_ engine: AgoraRtcEngineKit, localAudioMixingStateDidChanged state: AgoraAudioMixingStateCode, reason: AgoraAudioMixingReasonCode) {
- self.agSettings.rtcDelegate?.rtcEngine?(engine, localAudioMixingStateDidChanged: state, reason: reason)
+ self.agoraSettings.rtcDelegate?.rtcEngine?(engine, localAudioMixingStateDidChanged: state, reason: reason)
}
open func rtcEngine(_ engine: AgoraRtcEngineKit, channelMediaRelayStateDidChange state: AgoraChannelMediaRelayState, error: AgoraChannelMediaRelayError) {
- self.agSettings.rtcDelegate?.rtcEngine?(engine, channelMediaRelayStateDidChange: state, error: error)
+ self.agoraSettings.rtcDelegate?.rtcEngine?(engine, channelMediaRelayStateDidChange: state, error: error)
}
open func rtcEngine(_ engine: AgoraRtcEngineKit, firstRemoteAudioFrameOfUid uid: UInt, elapsed: Int) {
- self.agSettings.rtcDelegate?.rtcEngine?(engine, firstRemoteAudioFrameOfUid: uid, elapsed: elapsed)
+ self.agoraSettings.rtcDelegate?.rtcEngine?(engine, firstRemoteAudioFrameOfUid: uid, elapsed: elapsed)
}
open func rtcEngine(_ engine: AgoraRtcEngineKit, firstRemoteAudioFrameDecodedOfUid uid: UInt, elapsed: Int) {
- self.agSettings.rtcDelegate?.rtcEngine?(engine, firstRemoteAudioFrameDecodedOfUid: uid, elapsed: elapsed)
+ self.agoraSettings.rtcDelegate?.rtcEngine?(engine, firstRemoteAudioFrameDecodedOfUid: uid, elapsed: elapsed)
}
open func rtcEngine(_ engine: AgoraRtcEngineKit, didAudioMuted muted: Bool, byUid uid: UInt) {
- self.agSettings.rtcDelegate?.rtcEngine?(engine, didAudioMuted: muted, byUid: uid)
+ self.agoraSettings.rtcDelegate?.rtcEngine?(engine, didAudioMuted: muted, byUid: uid)
}
open func rtcEngine(_ engine: AgoraRtcEngineKit, streamPublishedWithUrl url: String, errorCode: AgoraErrorCode) {
- self.agSettings.rtcDelegate?.rtcEngine?(engine, streamPublishedWithUrl: url, errorCode: errorCode)
+ self.agoraSettings.rtcDelegate?.rtcEngine?(engine, streamPublishedWithUrl: url, errorCode: errorCode)
}
open func rtcEngine(_ engine: AgoraRtcEngineKit, didVideoEnabled enabled: Bool, byUid uid: UInt) {
- self.agSettings.rtcDelegate?.rtcEngine?(engine, didVideoEnabled: enabled, byUid: uid)
+ self.agoraSettings.rtcDelegate?.rtcEngine?(engine, didVideoEnabled: enabled, byUid: uid)
}
open func rtcEngine(_ engine: AgoraRtcEngineKit, didLocalVideoEnabled enabled: Bool, byUid uid: UInt) {
- self.agSettings.rtcDelegate?.rtcEngine?(engine, didLocalVideoEnabled: enabled, byUid: uid)
+ self.agoraSettings.rtcDelegate?.rtcEngine?(engine, didLocalVideoEnabled: enabled, byUid: uid)
}
open func rtcEngine(_ engine: AgoraRtcEngineKit, rtmpStreamingEventWithUrl url: String, eventCode: AgoraRtmpStreamingEvent) {
- self.agSettings.rtcDelegate?.rtcEngine?(engine, rtmpStreamingEventWithUrl: url, eventCode: eventCode)
+ self.agoraSettings.rtcDelegate?.rtcEngine?(engine, rtmpStreamingEventWithUrl: url, eventCode: eventCode)
}
open func rtcEngine(_ engine: AgoraRtcEngineKit, virtualBackgroundSourceEnabled enabled: Bool, reason: AgoraVirtualBackgroundSourceStateReason) {
- self.agSettings.rtcDelegate?.rtcEngine?(engine, virtualBackgroundSourceEnabled: enabled, reason: reason)
+ self.agoraSettings.rtcDelegate?.rtcEngine?(engine, virtualBackgroundSourceEnabled: enabled, reason: reason)
}
open func rtcEngine(_ engine: AgoraRtcEngineKit, facePositionDidChangeWidth width: Int32, previewHeight height: Int32, faces: [AgoraFacePositionInfo]?) {
- self.agSettings.rtcDelegate?.rtcEngine?(engine, facePositionDidChangeWidth: width, previewHeight: height, faces: faces)
+ self.agoraSettings.rtcDelegate?.rtcEngine?(engine, facePositionDidChangeWidth: width, previewHeight: height, faces: faces)
}
open func rtcEngine(_ engine: AgoraRtcEngineKit, didApiCallExecute error: Int, api: String, result: String) {
- self.agSettings.rtcDelegate?.rtcEngine?(engine, didApiCallExecute: error, api: api, result: result)
+ self.agoraSettings.rtcDelegate?.rtcEngine?(engine, didApiCallExecute: error, api: api, result: result)
}
open func rtcEngine(_ engine: AgoraRtcEngineKit, didJoinChannel channel: String, withUid uid: UInt, elapsed: Int) {
- self.agSettings.rtcDelegate?.rtcEngine?(engine, didJoinChannel: channel, withUid: uid, elapsed: elapsed)
+ self.agoraSettings.rtcDelegate?.rtcEngine?(engine, didJoinChannel: channel, withUid: uid, elapsed: elapsed)
}
open func rtcEngine(_ engine: AgoraRtcEngineKit, didRejoinChannel channel: String, withUid uid: UInt, elapsed: Int) {
- self.agSettings.rtcDelegate?.rtcEngine?(engine, didRejoinChannel: channel, withUid: uid, elapsed: elapsed)
+ self.agoraSettings.rtcDelegate?.rtcEngine?(engine, didRejoinChannel: channel, withUid: uid, elapsed: elapsed)
}
open func rtcEngine(_ engine: AgoraRtcEngineKit, videoSizeChangedOfUid uid: UInt, size: CGSize, rotation: Int) {
- self.agSettings.rtcDelegate?.rtcEngine?(engine, videoSizeChangedOfUid: uid, size: size, rotation: rotation)
+ self.agoraSettings.rtcDelegate?.rtcEngine?(engine, videoSizeChangedOfUid: uid, size: size, rotation: rotation)
}
open func rtcEngine(_ engine: AgoraRtcEngineKit, networkQuality uid: UInt, txQuality: AgoraNetworkQuality, rxQuality: AgoraNetworkQuality) {
- self.agSettings.rtcDelegate?.rtcEngine?(engine, networkQuality: uid, txQuality: txQuality, rxQuality: rxQuality)
+ self.agoraSettings.rtcDelegate?.rtcEngine?(engine, networkQuality: uid, txQuality: txQuality, rxQuality: rxQuality)
}
open func rtcEngine(_ engine: AgoraRtcEngineKit, rtmpStreamingChangedToState url: String, state: AgoraRtmpStreamingState, errorCode: AgoraRtmpStreamingErrorCode) {
- self.agSettings.rtcDelegate?.rtcEngine?(engine, rtmpStreamingChangedToState: url, state: state, errorCode: errorCode)
+ self.agoraSettings.rtcDelegate?.rtcEngine?(engine, rtmpStreamingChangedToState: url, state: state, errorCode: errorCode)
}
open func rtcEngine(_ engine: AgoraRtcEngineKit, streamInjectedStatusOfUrl url: String, uid: UInt, status: AgoraInjectStreamStatus) {
- self.agSettings.rtcDelegate?.rtcEngine?(engine, streamInjectedStatusOfUrl: url, uid: uid, status: status)
+ self.agoraSettings.rtcDelegate?.rtcEngine?(engine, streamInjectedStatusOfUrl: url, uid: uid, status: status)
}
open func rtcEngine(_ engine: AgoraRtcEngineKit, receiveStreamMessageFromUid uid: UInt, streamId: Int, data: Data) {
- self.agSettings.rtcDelegate?.rtcEngine?(engine, receiveStreamMessageFromUid: uid, streamId: streamId, data: data)
+ self.agoraSettings.rtcDelegate?.rtcEngine?(engine, receiveStreamMessageFromUid: uid, streamId: streamId, data: data)
}
open func rtcEngine(_ engine: AgoraRtcEngineKit, firstRemoteVideoFrameOfUid uid: UInt, size: CGSize, elapsed: Int) {
- self.agSettings.rtcDelegate?.rtcEngine?(engine, firstRemoteVideoFrameOfUid: uid, size: size, elapsed: elapsed)
+ self.agoraSettings.rtcDelegate?.rtcEngine?(engine, firstRemoteVideoFrameOfUid: uid, size: size, elapsed: elapsed)
}
open func rtcEngine(_ engine: AgoraRtcEngineKit, firstRemoteVideoDecodedOfUid uid: UInt, size: CGSize, elapsed: Int) {
- self.agSettings.rtcDelegate?.rtcEngine?(engine, firstRemoteVideoDecodedOfUid: uid, size: size, elapsed: elapsed)
+ self.agoraSettings.rtcDelegate?.rtcEngine?(engine, firstRemoteVideoDecodedOfUid: uid, size: size, elapsed: elapsed)
}
open func rtcEngine(_ engine: AgoraRtcEngineKit, uploadLogResultRequestId requestId: String, success: Bool, reason: AgoraUploadErrorReason) {
- self.agSettings.rtcDelegate?.rtcEngine?(engine, uploadLogResultRequestId: requestId, success: success, reason: reason)
+ self.agoraSettings.rtcDelegate?.rtcEngine?(engine, uploadLogResultRequestId: requestId, success: success, reason: reason)
}
open func rtcEngine(_ engine: AgoraRtcEngineKit, superResolutionEnabledOfUid uid: UInt, enabled: Bool, reason: AgoraSuperResolutionStateReason) {
- self.agSettings.rtcDelegate?.rtcEngine?(engine, superResolutionEnabledOfUid: uid, enabled: enabled, reason: reason)
+ self.agoraSettings.rtcDelegate?.rtcEngine?(engine, superResolutionEnabledOfUid: uid, enabled: enabled, reason: reason)
}
open func rtcEngine(_ engine: AgoraRtcEngineKit, audioTransportStatsOfUid uid: UInt, delay: UInt, lost: UInt, rxKBitRate: UInt) {
- self.agSettings.rtcDelegate?.rtcEngine?(engine, audioTransportStatsOfUid: uid, delay: delay, lost: lost, rxKBitRate: rxKBitRate)
+ self.agoraSettings.rtcDelegate?.rtcEngine?(engine, audioTransportStatsOfUid: uid, delay: delay, lost: lost, rxKBitRate: rxKBitRate)
}
open func rtcEngine(_ engine: AgoraRtcEngineKit, videoTransportStatsOfUid uid: UInt, delay: UInt, lost: UInt, rxKBitRate: UInt) {
- self.agSettings.rtcDelegate?.rtcEngine?(engine, videoTransportStatsOfUid: uid, delay: delay, lost: lost, rxKBitRate: rxKBitRate)
+ self.agoraSettings.rtcDelegate?.rtcEngine?(engine, videoTransportStatsOfUid: uid, delay: delay, lost: lost, rxKBitRate: rxKBitRate)
}
open func rtcEngine(_ engine: AgoraRtcEngineKit, audioQualityOfUid uid: UInt, quality: AgoraNetworkQuality, delay: UInt, lost: UInt) {
- self.agSettings.rtcDelegate?.rtcEngine?(engine, audioQualityOfUid: uid, quality: quality, delay: delay, lost: lost)
+ self.agoraSettings.rtcDelegate?.rtcEngine?(engine, audioQualityOfUid: uid, quality: quality, delay: delay, lost: lost)
}
open func rtcEngine(_ engine: AgoraRtcEngineKit, didAudioPublishStateChange channel: String, oldState: AgoraStreamPublishState, newState: AgoraStreamPublishState, elapseSinceLastState: Int) {
- self.agSettings.rtcDelegate?.rtcEngine?(engine, didAudioPublishStateChange: channel, oldState: oldState, newState: newState, elapseSinceLastState: elapseSinceLastState)
+ self.agoraSettings.rtcDelegate?.rtcEngine?(engine, didAudioPublishStateChange: channel, oldState: oldState, newState: newState, elapseSinceLastState: elapseSinceLastState)
}
open func rtcEngine(_ engine: AgoraRtcEngineKit, didVideoPublishStateChange channel: String, oldState: AgoraStreamPublishState, newState: AgoraStreamPublishState, elapseSinceLastState: Int) {
- self.agSettings.rtcDelegate?.rtcEngine?(engine, didVideoPublishStateChange: channel, oldState: oldState, newState: newState, elapseSinceLastState: elapseSinceLastState)
+ self.agoraSettings.rtcDelegate?.rtcEngine?(engine, didVideoPublishStateChange: channel, oldState: oldState, newState: newState, elapseSinceLastState: elapseSinceLastState)
}
open func rtcEngine(_ engine: AgoraRtcEngineKit, didAudioSubscribeStateChange channel: String, withUid uid: UInt, oldState: AgoraStreamSubscribeState, newState: AgoraStreamSubscribeState, elapseSinceLastState: Int) {
- self.agSettings.rtcDelegate?.rtcEngine?(engine, didAudioSubscribeStateChange: channel, withUid: uid, oldState: oldState, newState: newState, elapseSinceLastState: elapseSinceLastState)
+ self.agoraSettings.rtcDelegate?.rtcEngine?(engine, didAudioSubscribeStateChange: channel, withUid: uid, oldState: oldState, newState: newState, elapseSinceLastState: elapseSinceLastState)
}
open func rtcEngine(_ engine: AgoraRtcEngineKit, didVideoSubscribeStateChange channel: String, withUid uid: UInt, oldState: AgoraStreamSubscribeState, newState: AgoraStreamSubscribeState, elapseSinceLastState: Int) {
- self.agSettings.rtcDelegate?.rtcEngine?(engine, didVideoSubscribeStateChange: channel, withUid: uid, oldState: oldState, newState: newState, elapseSinceLastState: elapseSinceLastState)
+ self.agoraSettings.rtcDelegate?.rtcEngine?(engine, didVideoSubscribeStateChange: channel, withUid: uid, oldState: oldState, newState: newState, elapseSinceLastState: elapseSinceLastState)
}
open func rtcEngine(_ engine: AgoraRtcEngineKit, didOccurStreamMessageErrorFromUid uid: UInt, streamId: Int, error: Int, missed: Int, cached: Int) {
- self.agSettings.rtcDelegate?.rtcEngine?(engine, didOccurStreamMessageErrorFromUid: uid, streamId: streamId, error: error, missed: missed, cached: cached)
- }
-}
-
-/*
-extension AgoraVideoViewer {
- open func rtcEngineRequestToken(_ engine: AgoraRtcEngineKit) {
- self.agSettings.rtcDelegate?.rtcEngineRequestToken?(engine)
- }
-
- open func rtcEngine(_ engine: AgoraRtcEngineKit, tokenPrivilegeWillExpire token: String) {
- self.agSettings.rtcDelegate?.rtcEngine?(engine, tokenPrivilegeWillExpire: token)
- }
-
- open func rtcEngine(_ engine: AgoraRtcEngineKit, activeSpeaker speakerUid: UInt) {
- self.agSettings.rtcDelegate?.rtcEngine?(engine, activeSpeaker: speakerUid)
+ self.agoraSettings.rtcDelegate?.rtcEngine?(engine, didOccurStreamMessageErrorFromUid: uid, streamId: streamId, error: error, missed: missed, cached: cached)
}
-
- open func rtcEngine(_ engine: AgoraRtcEngineKit, firstLocalAudioFramePublished elapsed: Int) {
- self.agSettings.rtcDelegate?.rtcEngine?(engine, firstLocalAudioFramePublished: elapsed)
+ open func rtcEngine(_ engine: AgoraRtcEngineKit, contentInspectResult result: AgoraContentInspectResult) {
+ self.agoraSettings.rtcDelegate?.rtcEngine?(engine, contentInspectResult: result)
}
-
- open func rtcEngine(_ engine: AgoraRtcEngineKit, didClientRoleChanged oldRole: AgoraClientRole, newRole: AgoraClientRole) {
- self.agSettings.rtcDelegate?.rtcEngine?(engine, didClientRoleChanged: oldRole, newRole: newRole)
+ public func rtcEngine(_ engine: AgoraRtcEngineKit, didRequest info: AgoraRtcAudioFileInfo, error: AgoraAudioFileInfoError) {
+ self.agoraSettings.rtcDelegate?.rtcEngine?(engine, didRequest: info, error: error)
}
-
- open func rtcEngine(_ engine: AgoraRtcEngineKit, didJoinedOfUid uid: UInt, elapsed: Int) {
- self.agSettings.rtcDelegate?.rtcEngine?(engine, didJoinedOfUid: uid, elapsed: elapsed)
+ public func rtcEngine(_ engine: AgoraRtcEngineKit, wlAccStats currentStats: AgoraWlAccStats, averageStats: AgoraWlAccStats) {
+ self.agoraSettings.rtcDelegate?.rtcEngine?(engine, wlAccStats: currentStats, averageStats: averageStats)
}
-
- open func rtcEngine(_ engine: AgoraRtcEngineKit, didOfflineOfUid uid: UInt, reason: AgoraUserOfflineReason) {
- self.agSettings.rtcDelegate?.rtcEngine?(engine, didOfflineOfUid: uid, reason: reason)
+ public func rtcEngine(_ engine: AgoraRtcEngineKit, wlAccMessage reason: AgoraWlAccReason, action: AgoraWlAccAction, wlAccMsg: String) {
+ self.agoraSettings.rtcDelegate?.rtcEngine?(engine, wlAccMessage: reason, action: action, wlAccMsg: wlAccMsg)
}
-
- open func rtcEngine(_ engine: AgoraRtcEngineKit, localVideoStateChange state: AgoraLocalVideoStreamState, error: AgoraLocalVideoStreamError) {
- self.agSettings.rtcDelegate?.rtcEngine?(engine, localVideoStateChange: state, error: error)
+ public func rtcEngine(_ engine: AgoraRtcEngineKit, reportAudioDeviceTestVolume volumeType: AgoraAudioDeviceTestVolumeType, volume: Int) {
+ self.agoraSettings.rtcDelegate?.rtcEngine?(engine, reportAudioDeviceTestVolume: volumeType, volume: volume)
}
-
- open func rtcEngine(_ engine: AgoraRtcEngineKit, localAudioStateChange state: AgoraAudioLocalState, error: AgoraAudioLocalError) {
- self.agSettings.rtcDelegate?.rtcEngine?(engine, localAudioStateChange: state, error: error)
+ public func rtcEngine(_ engine: AgoraRtcEngineKit, didClientRoleChangeFailed reason: AgoraClientRoleChangeFailedReason, currentRole: AgoraClientRole) {
+ self.agoraSettings.rtcDelegate?.rtcEngine?(engine, didClientRoleChangeFailed: reason, currentRole: currentRole)
}
-
- open func rtcEngine(_ engine: AgoraRtcEngineKit, remoteVideoStateChangedOfUid uid: UInt, state: AgoraVideoRemoteState, reason: AgoraVideoRemoteStateReason, elapsed: Int) {
- self.agSettings.rtcDelegate?.rtcEngine?(engine, remoteVideoStateChangedOfUid: uid, state: state, reason: reason, elapsed: elapsed)
+ public func rtcEngine(_ engine: AgoraRtcEngineKit, snapshotTaken channel: String, uid: UInt, filePath: String, width: Int, height: Int, errCode: Int) {
+ self.agoraSettings.rtcDelegate?.rtcEngine?(engine, snapshotTaken: channel, uid: uid, filePath: filePath, width: width, height: height, errCode: errCode)
}
-
- open func rtcEngine(_ engine: AgoraRtcEngineKit, remoteAudioStateChangedOfUid uid: UInt, state: AgoraAudioRemoteState, reason: AgoraAudioRemoteStateReason, elapsed: Int) {
- self.agSettings.rtcDelegate?.rtcEngine?(engine, remoteAudioStateChangedOfUid: uid, state: state, reason: reason, elapsed: elapsed)
+ public func rtcEngine(_ engine: AgoraRtcEngineKit, didProxyConnected channel: String, withUid uid: UInt, proxyType: AgoraProxyType, localProxyIp: String, elapsed: Int) {
+ self.agoraSettings.rtcDelegate?.rtcEngine?(engine, didProxyConnected: channel, withUid: uid, proxyType: proxyType, localProxyIp: localProxyIp, elapsed: elapsed)
}
-
}
-*/
diff --git a/Sources/Agora-UIKit/AgoraVideoViewer+VideoControl.swift b/Sources/Agora-UIKit/AgoraVideoViewer+VideoControl.swift
index 9f73198c..16f57c3b 100644
--- a/Sources/Agora-UIKit/AgoraVideoViewer+VideoControl.swift
+++ b/Sources/Agora-UIKit/AgoraVideoViewer+VideoControl.swift
@@ -7,6 +7,9 @@
import AgoraRtcKit
import AVKit
+#if canImport(AgoraRtmControl)
+import AgoraRtmControl
+#endif
extension AgoraVideoViewer {
@@ -17,11 +20,11 @@ extension AgoraVideoViewer {
return
}
self.getControlContainer()
- if let videoSource = self.agSettings.videoSource {
+ if let videoSource = self.agoraSettings.videoSource {
self.agkit.setVideoSource(videoSource)
}
- if self.agSettings.externalAudioSettings.enabled {
- let audioSource = self.agSettings.externalAudioSettings
+ if self.agoraSettings.externalAudioSettings.enabled {
+ let audioSource = self.agoraSettings.externalAudioSettings
self.agkit.enableExternalAudioSource(
withSampleRate: .init(audioSource.sampleRate),
channelsPerFrame: .init(audioSource.channels)
@@ -146,22 +149,19 @@ extension AgoraVideoViewer {
ssButton.isSelected.toggle()
ssButton.backgroundColor = ssButton.isSelected ? .systemGreen : .systemGray
#elseif os(macOS)
- ssButton.layer?.backgroundColor = (
- ssButton.isOn ? NSColor.systemGreen : NSColor.systemGray
- ).cgColor
+ ssButton.layer?.backgroundColor = (ssButton.isOn ? NSColor.systemGreen : NSColor.systemGray).cgColor
- if ssButton.isOn {
- self.startSharingScreen()
- } else {
- self.agkit.stopScreenCapture()
- }
+ if ssButton.isOn { self.startSharingScreen()
+ } else { self.agkit.stopScreenCapture() }
#endif
}
/// Start a new screen capture (macOS only for now)
/// - Parameter displayId: The display ID of the screen to be shared. This parameter specifies which screen you want to share.
- /// For information on how to get the displayId, see [Share the Screen](https://docs.agora.io/en/Voice/screensharing_mac?platform=macOS)
- open func startSharingScreen(displayId: UInt = 0) {
+ /// - Parameter contentHint: The content hint for screen sharing, see [AgoraVideoContentHint](https://docs.agora.io/en/Interactive%20Broadcast/API%20Reference/oc/Constants/AgoraVideoContentHint.html?platform=macOS).
+ ///
+ /// For information on how to get the displayId, see [Share the Screen](https://docs.agora.io/en/Video/screensharing_mac?platform=macOS)
+ open func startSharingScreen(displayId: UInt = 0, contentHint: AgoraVideoContentHint = .none) {
#if os(macOS)
let rectangle = CGRect.zero
let parameters = AgoraScreenCaptureParameters()
@@ -170,7 +170,7 @@ extension AgoraVideoViewer {
parameters.bitrate = 1000
parameters.captureMouseCursor = true
self.agkit.startScreenCapture(byDisplayId: displayId, rectangle: rectangle, parameters: parameters)
- self.agkit.setScreenCapture(.none)
+ self.agkit.setScreenCaptureContentHint(contentHint)
#endif
}
@@ -251,14 +251,12 @@ extension AgoraVideoViewer {
channel: String, as role: AgoraClientRole = .broadcaster,
fetchToken: Bool = false, uid: UInt? = nil
) {
- if self.connectionData == nil {
- fatalError("No app ID is provided")
- }
+ if self.connectionData == nil { fatalError("No app ID is provided") }
if fetchToken {
if let tokenURL = self.agoraSettings.tokenURL {
AgoraVideoViewer.fetchToken(
- urlBase: tokenURL, channelName: channel,
- userId: self.userID) { result in
+ urlBase: tokenURL, channelName: channel, userId: self.userID
+ ) { result in
switch result {
case .success(let token):
self.join(channel: channel, with: token, as: role, uid: uid)
@@ -285,14 +283,10 @@ extension AgoraVideoViewer {
channel: String, with token: String?,
as role: AgoraClientRole = .broadcaster, uid: UInt? = nil
) {
- if self.connectionData == nil {
- fatalError("No app ID is provided")
- }
+ if self.connectionData == nil { fatalError("No app ID is provided") }
if role == .broadcaster {
if !self.checkForPermissions(self.activePermissions, callback: { error in
- if error != nil {
- return
- }
+ if error != nil { return }
DispatchQueue.main.async {
self.join(channel: channel, with: token, as: role, uid: uid)
}
@@ -318,10 +312,13 @@ extension AgoraVideoViewer {
self?.userID = uid
if self?.userRole == .broadcaster { self?.addLocalVideo() }
self?.delegate?.joinedChannel(channel: channel)
+ #if canImport(AgoraRtmControl)
self?.setupRtmController(joining: channel)
+ #endif
}
}
+ #if canImport(AgoraRtmControl)
/// Initialise RTM to send messages across the network.
open func setupRtmController(joining channel: String) {
self.setupRtmController { rtmController in
@@ -330,7 +327,7 @@ extension AgoraVideoViewer {
}
open func setupRtmController(callback: ((AgoraRtmController?) -> Void)? = nil) {
- if !self.agSettings.rtmEnabled { return }
+ if !self.agoraSettings.rtmEnabled { return }
if self.rtmController == nil {
DispatchQueue.global(qos: .utility).async {
self.rtmController = AgoraRtmController(delegate: self)
@@ -341,6 +338,7 @@ extension AgoraVideoViewer {
}
}
}
+ #endif
internal func handleAlreadyInChannel(
channel: String, with token: String?,
diff --git a/Sources/Agora-UIKit/AgoraVideoViewer.swift b/Sources/Agora-UIKit/AgoraVideoViewer.swift
index 21c63dbe..96b8f304 100644
--- a/Sources/Agora-UIKit/AgoraVideoViewer.swift
+++ b/Sources/Agora-UIKit/AgoraVideoViewer.swift
@@ -14,8 +14,9 @@ import CoreFoundation
import CommonCrypto
#endif
import AgoraRtcKit
-#if canImport(AgoraRtmKit)
+#if canImport(AgoraRtmControl)
import AgoraRtmKit
+import AgoraRtmControl
#endif
/// An interface for getting some common delegate callbacks without needing to subclass.
@@ -50,7 +51,7 @@ public protocol AgoraVideoViewerDelegate: AnyObject {
/// A pong request has just come back to the local user, indicating that someone is still present in RTM
/// - Parameter peerId: RTM ID of the remote user that sent the pong request.
func incomingPongRequest(from peerId: String)
- #if canImport(AgoraRtmKit)
+ #if canImport(AgoraRtmControl)
/// State of RTM has changed
/// - Parameters:
/// - oldState: Previous state of RTM
@@ -85,7 +86,7 @@ public extension AgoraVideoViewerDelegate {
func extraButtons() -> [NSButton] { [] }
#endif
func incomingPongRequest(from peerId: String) {}
- #if canImport(AgoraRtmKit)
+ #if canImport(AgoraRtmControl)
func rtmStateChanged(
from oldState: AgoraRtmController.RTMStatus, to newState: AgoraRtmController.RTMStatus
) {}
@@ -99,6 +100,10 @@ public extension AgoraVideoViewerDelegate {
/// View to contain all the video session objects, including camera feeds and buttons for settings
open class AgoraVideoViewer: MPView, SingleVideoViewDelegate {
+ public var rtcLookup: [UInt: String] = [:]
+
+ public var rtmLookup: [String: Codable] = [:]
+
/// Delegate for the AgoraVideoViewer, used for some important callback methods.
public weak var delegate: AgoraVideoViewerDelegate?
@@ -106,8 +111,10 @@ open class AgoraVideoViewer: MPView, SingleVideoViewDelegate {
/// as well as agora video configuration.
public internal(set) var agoraSettings: AgoraSettings
+ #if canImport(AgoraRtmControl)
/// Controller class for managing RTM messages
public var rtmController: AgoraRtmController?
+ #endif
/// The rendering mode of the video view for all active videos.
var videoRenderMode: AgoraVideoRenderMode {
@@ -167,16 +174,18 @@ open class AgoraVideoViewer: MPView, SingleVideoViewDelegate {
set { self.connectionData.rtcToken = newValue }
}
+ #if canImport(AgoraRtmControl)
/// Status of the RTM Engine
var rtmState: AgoraRtmController.RTMStatus {
if let rtmc = self.rtmController {
return rtmc.rtmStatus
- } else if self.agSettings.rtmEnabled {
+ } else if self.agoraSettings.rtmEnabled {
return .initFailed
} else {
return .offline
}
}
+ #endif
lazy internal var floatingVideoHolder: MPCollectionView = {
let collView = AgoraCollectionViewer()
@@ -335,9 +344,10 @@ open class AgoraVideoViewer: MPView, SingleVideoViewDelegate {
}
/// Used by storyboard to set the AgoraSettings tokenURL
- @IBInspectable var tokenURL: String = "" {
- didSet {
- self.agoraSettings.tokenURL = tokenURL
+ @IBInspectable public var tokenURL: String? {
+ get { self.agoraSettings.tokenURL }
+ set {
+ self.agoraSettings.tokenURL = newValue
}
}
/// Create view from NSCoder, this initialiser requires an appID key with a String value.
@@ -354,14 +364,14 @@ open class AgoraVideoViewer: MPView, SingleVideoViewDelegate {
internal var userVideosForGrid: [UInt: AgoraSingleVideoView] {
if self.style == .floating {
- if self.overrideActiveSpeaker == nil, self.activeSpeaker == nil, !self.agSettings.showSelf {
+ if self.overrideActiveSpeaker == nil, self.activeSpeaker == nil, !self.agoraSettings.showSelf {
return [:]
}
return self.userVideoLookup.filter {
$0.key == (self.overrideActiveSpeaker ?? self.activeSpeaker ?? self.userID)
}
} else if self.style == .grid {
- return self.userVideoLookup.filter { ($0.key != self.userID || self.agSettings.showSelf) }
+ return self.userVideoLookup.filter { ($0.key != self.userID || self.agoraSettings.showSelf) }
} else {
return [:]
}
diff --git a/Sources/Agora-UIKit/AgoraRtmController+AgoraRtmDelegate.swift b/Sources/AgoraRtmControl/AgoraRtmController+AgoraRtmDelegate.swift
similarity index 53%
rename from Sources/Agora-UIKit/AgoraRtmController+AgoraRtmDelegate.swift
rename to Sources/AgoraRtmControl/AgoraRtmController+AgoraRtmDelegate.swift
index 57c3b6e8..78060a49 100644
--- a/Sources/Agora-UIKit/AgoraRtmController+AgoraRtmDelegate.swift
+++ b/Sources/AgoraRtmControl/AgoraRtmController+AgoraRtmDelegate.swift
@@ -16,13 +16,13 @@ extension AgoraRtmController: AgoraRtmDelegate, AgoraRtmChannelDelegate {
/// The token used to connect to the current active channel has expired.
/// - Parameter kit: Agora RTM Engine
open func rtmKitTokenDidExpire(_ kit: AgoraRtmKit) {
- if let tokenURL = self.agoraSettings.tokenURL {
+ if let tokenURL = self.delegate?.rtmToken {
AgoraRtmController.fetchRtmToken(
- urlBase: tokenURL, userId: self.connectionData.rtmId,
+ urlBase: tokenURL, userId: self.delegate.rtmId,
callback: self.newTokenFetched(result:)
)
}
- self.delegate.agSettings.rtmDelegate?.rtmKitTokenDidExpire?(kit)
+ self.rtmDelegate?.rtmKitTokenDidExpire?(kit)
}
/**
@@ -33,10 +33,8 @@ extension AgoraRtmController: AgoraRtmDelegate, AgoraRtmChannelDelegate {
@param peerId The user ID of the sender.
*/
open func rtmKit(_ kit: AgoraRtmKit, messageReceived message: AgoraRtmMessage, fromPeer peerId: String) {
- if let rawMsg = message as? AgoraRtmRawMessage {
- self.decodeRawMessage(rawMsg: rawMsg, from: peerId)
- }
- self.delegate.agSettings.rtmDelegate?.rtmKit?(kit, messageReceived: message, fromPeer: peerId)
+ self.decodeMessage(message: message, from: peerId)
+ self.rtmDelegate?.rtmKit?(kit, messageReceived: message, fromPeer: peerId)
}
/**
@@ -52,8 +50,8 @@ extension AgoraRtmController: AgoraRtmDelegate, AgoraRtmChannelDelegate {
@param member The user joining the channel. See AgoraRtmMember.
*/
open func channel(_ channel: AgoraRtmChannel, memberJoined member: AgoraRtmMember) {
- self.sendPersonalData(to: member.userId)
- self.delegate.agSettings.rtmChannelDelegate?.channel?(channel, memberJoined: member)
+ self.delegate?.channel(channel, memberJoined: member)
+ self.rtmChannelDelegate?.channel?(channel, memberJoined: member)
}
/**
@@ -70,46 +68,15 @@ extension AgoraRtmController: AgoraRtmDelegate, AgoraRtmChannelDelegate {
messageReceived message: AgoraRtmMessage,
from member: AgoraRtmMember
) {
- if let rawMsg = message as? AgoraRtmRawMessage {
- self.decodeRawMessage(rawMsg: rawMsg, from: member.userId)
- }
- self.delegate.agSettings.rtmChannelDelegate?.channel?(channel, messageReceived: message, from: member)
+ self.decodeMessage(message: message, from: member.userId)
+ self.rtmChannelDelegate?.channel?(channel, messageReceived: message, from: member)
}
- /// Decode an incoming AgoraRtmRawMessage
+ /// Decode an incoming AgoraRtmMessage
/// - Parameters:
- /// - rawMsg: Incoming Raw message.
+ /// - message: Incoming RTM message.
/// - peerId: Id of the peer this message is coming from
- open func decodeRawMessage(rawMsg: AgoraRtmRawMessage, from peerId: String) {
- if let decodedRaw = AgoraRtmController.decodeRawRtmData(data: rawMsg.rawData, from: peerId) {
- switch decodedRaw {
- case .mute(let muteReq):
- self.delegate.handleMuteRequest(muteReq: muteReq)
- case .userData(let user):
- AgoraVideoViewer.agoraPrint(
- .verbose, message: "Received user data: \n\(user.prettyPrint())"
- )
- self.rtmLookup[user.rtmId] = user
- if let rtcId = user.rtcId {
- self.rtcLookup[rtcId] = user.rtmId
- self.delegate.videoLookup[rtcId]?
- .showOptions = self.agoraSettings.showRemoteRequestOptions
- }
- case .dataRequest(let requestVal):
- switch requestVal.type {
- case .userData:
- self.sendPersonalData(to: peerId)
- case .ping:
- self.sendRaw(
- message: RtmDataRequest(type: .pong), member: peerId
- ) {_ in }
- case .pong:
- AgoraVideoViewer.agoraPrint(
- .verbose, message: "Received pong from \(peerId)"
- )
- self.delegate.handlePongRequest(from: peerId)
- }
- }
- }
+ open func decodeMessage(message: AgoraRtmMessage, from peerId: String) {
+ self.delegate.decodeMessage(message: message, from: peerId)
}
}
diff --git a/Sources/AgoraRtmControl/AgoraRtmController+MuteRequests.swift b/Sources/AgoraRtmControl/AgoraRtmController+MuteRequests.swift
new file mode 100644
index 00000000..d846c378
--- /dev/null
+++ b/Sources/AgoraRtmControl/AgoraRtmController+MuteRequests.swift
@@ -0,0 +1,6 @@
+//
+// AgoraRtmController+MuteRequests.swift
+//
+//
+// Created by Max Cobb on 29/07/2021.
+//
diff --git a/Sources/Agora-UIKit/AgoraRtmController+RtmDelegateOverflows.swift b/Sources/AgoraRtmControl/AgoraRtmController+RtmDelegateOverflows.swift
similarity index 58%
rename from Sources/Agora-UIKit/AgoraRtmController+RtmDelegateOverflows.swift
rename to Sources/AgoraRtmControl/AgoraRtmController+RtmDelegateOverflows.swift
index 85cf60cf..23326375 100644
--- a/Sources/Agora-UIKit/AgoraRtmController+RtmDelegateOverflows.swift
+++ b/Sources/AgoraRtmControl/AgoraRtmController+RtmDelegateOverflows.swift
@@ -9,40 +9,39 @@ import AgoraRtmKit
extension AgoraRtmController {
open func rtmKit(_ kit: AgoraRtmKit, peersOnlineStatusChanged onlineStatus: [AgoraRtmPeerOnlineStatus]) {
- self.agoraSettings.rtmDelegate?.rtmKit?(kit, peersOnlineStatusChanged: onlineStatus)
+ self.rtmDelegate?.rtmKit?(kit, peersOnlineStatusChanged: onlineStatus)
}
open func rtmKit(_ kit: AgoraRtmKit, fileMessageReceived message: AgoraRtmFileMessage, fromPeer peerId: String) {
- self.agoraSettings.rtmDelegate?.rtmKit?(kit, fileMessageReceived: message, fromPeer: peerId)
+ self.rtmDelegate?.rtmKit?(kit, fileMessageReceived: message, fromPeer: peerId)
}
open func rtmKit(_ kit: AgoraRtmKit, imageMessageReceived message: AgoraRtmImageMessage, fromPeer peerId: String) {
- self.agoraSettings.rtmDelegate?.rtmKit?(kit, imageMessageReceived: message, fromPeer: peerId)
+ self.rtmDelegate?.rtmKit?(kit, imageMessageReceived: message, fromPeer: peerId)
}
open func rtmKit(_ kit: AgoraRtmKit, media requestId: Int64, uploadingProgress progress: AgoraRtmMediaOperationProgress) {
- self.agoraSettings.rtmDelegate?.rtmKit?(kit, media: requestId, uploadingProgress: progress)
+ self.rtmDelegate?.rtmKit?(kit, media: requestId, uploadingProgress: progress)
}
open func rtmKit(_ kit: AgoraRtmKit, media requestId: Int64, downloadingProgress progress: AgoraRtmMediaOperationProgress) {
- self.agoraSettings.rtmDelegate?.rtmKit?(kit, media: requestId, downloadingProgress: progress)
+ self.rtmDelegate?.rtmKit?(kit, media: requestId, downloadingProgress: progress)
}
open func rtmKit(_ kit: AgoraRtmKit, connectionStateChanged state: AgoraRtmConnectionState, reason: AgoraRtmConnectionChangeReason) {
- self.agoraSettings.rtmDelegate?.rtmKit?(kit, connectionStateChanged: state, reason: reason)
+ self.rtmDelegate?.rtmKit?(kit, connectionStateChanged: state, reason: reason)
}
}
extension AgoraRtmController {
open func channel(_ channel: AgoraRtmChannel, memberCount count: Int32) {
- self.agoraSettings.rtmChannelDelegate?.channel?(channel, memberCount: count)
+ self.rtmChannelDelegate?.channel?(channel, memberCount: count)
}
open func channel(_ channel: AgoraRtmChannel, memberLeft member: AgoraRtmMember) {
- self.agoraSettings.rtmChannelDelegate?.channel?(channel, memberLeft: member)
+ self.rtmChannelDelegate?.channel?(channel, memberLeft: member)
}
open func channel(_ channel: AgoraRtmChannel, attributeUpdate attributes: [AgoraRtmChannelAttribute]) {
- self.agoraSettings.rtmChannelDelegate?.channel?(channel, attributeUpdate: attributes)
+ self.rtmChannelDelegate?.channel?(channel, attributeUpdate: attributes)
}
open func channel(_ channel: AgoraRtmChannel, fileMessageReceived message: AgoraRtmFileMessage, from member: AgoraRtmMember) {
- self.agoraSettings.rtmChannelDelegate?.channel?(channel, fileMessageReceived: message, from: member)
+ self.rtmChannelDelegate?.channel?(channel, fileMessageReceived: message, from: member)
}
open func channel(_ channel: AgoraRtmChannel, imageMessageReceived message: AgoraRtmImageMessage, from member: AgoraRtmMember) {
- self.agoraSettings.rtmChannelDelegate?.channel?(channel, imageMessageReceived: message, from: member)
+ self.rtmChannelDelegate?.channel?(channel, imageMessageReceived: message, from: member)
}
}
-
diff --git a/Sources/AgoraRtmControl/AgoraRtmController+SendHelpers.swift b/Sources/AgoraRtmControl/AgoraRtmController+SendHelpers.swift
new file mode 100644
index 00000000..1e5d53f0
--- /dev/null
+++ b/Sources/AgoraRtmControl/AgoraRtmController+SendHelpers.swift
@@ -0,0 +1,90 @@
+//
+// AgoraRtmController+SendHelpers.swift
+//
+//
+// Created by Max Cobb on 30/09/2021.
+//
+
+import Foundation
+import AgoraRtmKit
+
+// MARK: Helper Methods
+extension AgoraRtmController {
+ /// Send a codable message over RTM to the channel.
+ /// - Parameters:
+ /// - message: Codable message to send over RTM.
+ /// - channel: String channel name to send the message to.
+ /// - callback: Callback, to see if the message was sent successfully.
+ public func sendCodable(
+ message: Value, channel: String,
+ callback: @escaping (AgoraRtmSendChannelMessageErrorCode) -> Void
+ ) where Value: Codable {
+ if let channel = self.channels[channel],
+ let data = try? JSONEncoder().encode(message),
+ let jsonString = String(data: data, encoding: .utf8) {
+ channel.send(
+ AgoraRtmMessage(text: jsonString), completion: callback
+ )
+ }
+ }
+
+ /// Create message from codable object
+ /// - Parameter codableObj: Codable object to be sent over the Real-time Messaging network.
+ /// - Returns: AgoraRtmMessage that is ready to be sent across the Agora Real-time Messaging network.
+ public static func createRtmMessage(from codableObj: Value) -> AgoraRtmMessage? where Value: Codable {
+ if let data = try? JSONEncoder().encode(codableObj),
+ let jsonString = String(data: data, encoding: .utf8) {
+ return AgoraRtmMessage(text: jsonString)
+ }
+ AgoraRtmController.agoraPrint(.error, message: "Message could not be encoded to JSON String")
+ return nil
+ }
+
+ /// Send a codable message over RTM to the channel
+ /// - Parameters:
+ /// - message: Codable message to send over RTM
+ /// - channel: AgoraRtmChannel to send the message over
+ /// - callback: Callback, to see if the message was sent successfully.
+ public func sendCodable(
+ message: Value, channel: AgoraRtmChannel,
+ callback: @escaping (AgoraRtmSendChannelMessageErrorCode) -> Void
+ ) where Value: Codable {
+ if let msg = AgoraRtmController.createRtmMessage(from: message) {
+ channel.send(msg, completion: callback)
+ return
+ }
+ callback(.invalidMessage)
+ }
+
+ /// Send a codable message over RTM to a member
+ /// - Parameters:
+ /// - message: Codable message to send over RTM
+ /// - channel: member, or RTM ID to send the message to
+ /// - callback: Callback, to see if the message was sent successfully.
+ public func sendCodable(
+ message: Value, member: String,
+ callback: @escaping (AgoraRtmSendPeerMessageErrorCode) -> Void
+ ) where Value: Codable {
+ guard let msg = AgoraRtmController.createRtmMessage(from: message) else {
+ callback(.imcompatibleMessage)
+ return
+ }
+ self.rtmKit.send(msg, toPeer: member, completion: callback)
+ }
+
+ /// Send a codable message over RTM to a member
+ /// - Parameters:
+ /// - message: Codable message to send over RTM
+ /// - channel: member, or RTC User ID to send the message to
+ /// - callback: Callback, to see if the message was sent successfully.
+ public func sendCodable(
+ message: Value, user: UInt,
+ callback: @escaping (AgoraRtmSendPeerMessageErrorCode) -> Void
+ ) where Value: Codable {
+ if let rtmId = self.delegate.rtcLookup[user] {
+ self.sendCodable(message: message, member: rtmId, callback: callback)
+ } else {
+ callback(.peerUnreachable)
+ }
+ }
+}
diff --git a/Sources/Agora-UIKit/AgoraRtmController+Tokens.swift b/Sources/AgoraRtmControl/AgoraRtmController+Tokens.swift
similarity index 91%
rename from Sources/Agora-UIKit/AgoraRtmController+Tokens.swift
rename to Sources/AgoraRtmControl/AgoraRtmController+Tokens.swift
index 98494e55..c986552c 100644
--- a/Sources/Agora-UIKit/AgoraRtmController+Tokens.swift
+++ b/Sources/AgoraRtmControl/AgoraRtmController+Tokens.swift
@@ -64,7 +64,7 @@ extension AgoraRtmController {
case .success(let token):
self.updateToken(token)
case .failure(let err):
- AgoraVideoViewer.agoraPrint(.error, message: "Could not fetch rtm token: \(err)")
+ AgoraRtmController.agoraPrint(.error, message: "Could not fetch rtm token: \(err)")
}
}
@@ -72,16 +72,16 @@ extension AgoraRtmController {
self.rtmKit.renewToken(token) { _, renewStatus in
switch renewStatus {
case .ok:
- AgoraVideoViewer.agoraPrint(.verbose, message: "token renewal success")
+ AgoraRtmController.agoraPrint(.verbose, message: "token renewal success")
case .failure, .invalidArgument, .rejected, .tooOften,
.tokenExpired, .invalidToken,
.notInitialized, .notLoggedIn:
- AgoraVideoViewer.agoraPrint(
+ AgoraRtmController.agoraPrint(
.error,
message: "cannot renew token: \(renewStatus): \(renewStatus.rawValue)"
)
@unknown default:
- AgoraVideoViewer.agoraPrint(
+ AgoraRtmController.agoraPrint(
.error,
message: "cannot renew token (unknown): \(renewStatus): \(renewStatus.rawValue)"
)
diff --git a/Sources/Agora-UIKit/AgoraRtmController.swift b/Sources/AgoraRtmControl/AgoraRtmController.swift
similarity index 51%
rename from Sources/Agora-UIKit/AgoraRtmController.swift
rename to Sources/AgoraRtmControl/AgoraRtmController.swift
index 8d2a0226..28f4d239 100644
--- a/Sources/Agora-UIKit/AgoraRtmController.swift
+++ b/Sources/AgoraRtmControl/AgoraRtmController.swift
@@ -5,29 +5,10 @@
// Created by Max Cobb on 14/07/2021.
//
-import AgoraRtcKit
import AgoraRtmKit
/// Delegate for fetching data for our RTM Controller
public protocol RtmControllerDelegate: AnyObject {
- /// Instance of the RTC Engine being used
- var rtcEngine: AgoraRtcEngineKit { get }
- /// Struct for holding data about the connection to Agora service
- var agConnection: AgoraConnectionData { get set }
- /// Settings used for the display and behaviour
- var agSettings: AgoraSettings { get }
- /// Handle mute request, by showing popup or directly changing the device state
- /// - Parameter muteReq: Incoming mute request data
- func handleMuteRequest(muteReq: AgoraRtmController.MuteRequest)
- /// A pong request has just come back to the local user, indicating that someone is still present in RTM
- /// - Parameter peerId: RTM ID of the remote user that sent the pong request.
- func handlePongRequest(from peerId: String)
- /// Property used to access all the RTC connections to other broadcasters in an RTC channel
- var videoLookup: [UInt: AgoraSingleVideoView] { get }
- /// The role for the user. Either `.audience` or `.broadcaster`.
- var userRole: AgoraClientRole { get set }
- /// Delegate for the AgoraVideoViewer, used for some important callback methods.
- var agoraViewerDelegate: AgoraVideoViewerDelegate? { get }
/// Called after AgoraRtmController joins a channel
/// - Parameters:
/// - name: name of the channel joined
@@ -37,41 +18,71 @@ public protocol RtmControllerDelegate: AnyObject {
name: String, channel: AgoraRtmChannel,
code: AgoraRtmJoinChannelErrorCode
)
-}
-public extension AgoraVideoViewer {
- var agoraViewerDelegate: AgoraVideoViewerDelegate? {
- return self.delegate
- }
-}
-
-extension AgoraVideoViewer: RtmControllerDelegate {
- public var agConnection: AgoraConnectionData {
- get { self.connectionData }
- set { self.connectionData = newValue }
- }
- public var rtcEngine: AgoraRtcEngineKit { self.agkit }
- public var agSettings: AgoraSettings { self.agoraSettings }
- public var videoLookup: [UInt: AgoraSingleVideoView] { self.userVideoLookup }
- public func handlePongRequest(from peerId: String) {
- self.delegate?.incomingPongRequest(from: peerId)
- }
- public func rtmChannelJoined(
- name: String, channel: AgoraRtmChannel, code: AgoraRtmJoinChannelErrorCode
- ) {
- self.delegate?.rtmChannelJoined(name: name, channel: channel, code: code)
- }
+ /// Lookup remote user RTM ID based on their RTC ID
+ var rtcLookup: [UInt: String] { get set }
+ /// Get remote user data from their RTM ID
+ var rtmLookup: [String: Codable] { get set }
+ /// Delegate used for RTM
+ var rtmDelegate: AgoraRtmDelegate? { get }
+ /// Delegate used for RTM channel messages
+ var rtmChannelDelegate: AgoraRtmChannelDelegate? { get }
+ /// ID used by RTM
+ var rtmId: String { get }
+ /// ID used by RTC
+ var rtcId: UInt? { get }
+ /// App ID used, found on console.agora.io
+ var appId: String { get }
+ /// Token to connect to Agora RTM
+ var rtmToken: String? { get set }
+ /// URL for fetching Agora RTM tokens
+ var tokenURL: String? { get set }
+ func channel(_ channel: AgoraRtmChannel, memberJoined member: AgoraRtmMember)
+ /// Method to catch messages incoming from RTM, used to decode them and run any relevant actions
+ /// - Parameters:
+ /// - message: Message received from RTM
+ /// - peerId: ID of the user who sent the message
+ func decodeMessage(message: AgoraRtmMessage, from peerId: String)
+ /// State of the RTM Controller has changed
+ /// - Parameters:
+ /// - oldState: Previous state of AgoraRtmController
+ /// - newState: New state of AgoraRtmController
+ func rtmStateChanged(from oldState: AgoraRtmController.RTMStatus, to newState: AgoraRtmController.RTMStatus)
}
/// Class for controlling the RTM messages
open class AgoraRtmController: NSObject {
- /// Instance of the RTC Engine being used
- var engine: AgoraRtcEngineKit { self.delegate.rtcEngine }
- /// Struct for holding data about the connection to Agora service
- var connectionData: AgoraConnectionData { self.delegate.agConnection }
- /// Settings used for the display and behaviour
- var agoraSettings: AgoraSettings { self.delegate.agSettings }
+
+ /// Print level that will be visible in the developer console, default `.error`
+ public static var printLevel: PrintType = .warning
+ /// Level for an internal print statement
+ public enum PrintType: Int {
+ /// To use when an internal error has occurred
+ case error = 0
+ /// To use when something is not being used or running correctly
+ case warning = 1
+ /// To use for debugging issues
+ case debug = 2
+ /// To use when we want all the possible logs
+ case verbose = 3
+ var printString: String {
+ switch self {
+ case .error: return "ERROR"
+ case .warning: return "WARNING"
+ case .debug: return "DEBUG"
+ case .verbose: return "INFO"
+ }
+ }
+ }
+
+ internal static func agoraPrint(_ tag: PrintType, message: Any) {
+ if tag.rawValue <= AgoraRtmController.printLevel.rawValue {
+ print("[AgoraRtmController \(tag.printString)]: \(message)")
+ }
+ }
+ var rtmDelegate: AgoraRtmDelegate? { self.delegate.rtmDelegate }
+ var rtmChannelDelegate: AgoraRtmChannelDelegate? { self.delegate.rtmChannelDelegate }
/// Delegate for fetching data for our RTM Controller
weak var delegate: RtmControllerDelegate!
@@ -95,77 +106,19 @@ open class AgoraRtmController: NSObject {
/// Status of the RTM Engine
public internal(set) var rtmStatus: RTMStatus = .initialising {
didSet {
- self.delegate.agoraViewerDelegate?.rtmStateChanged(from: oldValue, to: self.rtmStatus)
+ self.delegate.rtmStateChanged(from: oldValue, to: self.rtmStatus)
}
}
-// var videoViewer: AgoraVideoViewer
+
public internal(set) var rtmKit: AgoraRtmKit
- /// Lookup remote user RTM ID based on their RTC ID
- public internal(set) var rtcLookup: [UInt: String] = [:]
- /// Get remote user data from their RTM ID
- public internal(set) var rtmLookup: [String: UserData] = [:]
/// RTM Channels created and joined by this RTM Controller
public internal(set) var channels: [String: AgoraRtmChannel] = [:]
/// Methods to be completed after login has finished (such as joining a channel)
public internal(set) var afterLoginSteps: [() -> Void] = []
- /// Data about a user (local or remote)
- public struct UserData: Codable {
- /// Type of message being sent
- var messageType: String? = "UserData"
- /// ID used in the RTM connection
- var rtmId: String
- /// ID used in the RTC (Video/Audio) connection
- var rtcId: UInt?
- /// Username to be displayed for remote users
- var username: String?
- /// Role of the user (broadcaster or audience)
- var role: AgoraClientRole.RawValue
- /// Properties about the Agora SDK versions this user is using
- var agora: AgoraVersions = .current
- /// Agora UIKit platform (iOS, Android, Flutter, React Native)
- var uikit: AgoraUIKit = .current
- func prettyPrint() -> String {
- """
- rtm: \(rtmId)
- rtc: \(rtcId ?? 0)
- username: \(username ?? "nil")
- role: \(role)
- agora: \n\(agora.prettyPrint())
- uikit: \n\(uikit.prettyPrint())
- """
- }
- }
-
- /// Data about the Agora SDK versions a user is using (local or remote)
- public struct AgoraVersions: Codable {
- /// Versions of the local users current RTM and RTC SDKs
- static var current: AgoraVersions {
- AgoraVersions(rtm: AgoraRtmKit.getSDKVersion(), rtc: AgoraRtcEngineKit.getSdkVersion())
- }
- /// Version string of the RTM SDK
- var rtm: String
- /// Version string of the RTC SDK
- var rtc: String
- func prettyPrint() -> String {
- """
- rtc: \(rtc)
- rtm: \(rtm)
- """
- }
- }
-
- var personalData: UserData {
- UserData(
- rtmId: self.connectionData.rtmId,
- rtcId: self.connectionData.rtcId == 0 ? nil : self.connectionData.rtcId,
- username: self.connectionData.username, role: self.delegate.userRole.rawValue
- )
- }
-
- init?(delegate: RtmControllerDelegate) {
+ public init?(delegate: RtmControllerDelegate) {
self.delegate = delegate
- if let rtmKit = AgoraRtmKit(appId: delegate.agConnection.appId, delegate: nil) {
+ if let rtmKit = AgoraRtmKit(appId: delegate.appId, delegate: nil) {
self.rtmKit = rtmKit
} else { return nil }
super.init()
@@ -176,23 +129,23 @@ open class AgoraRtmController: NSObject {
func rtmLogin(completion: @escaping (AgoraRtmLoginErrorCode) -> Void) {
self.rtmStatus = .loggingIn
- if let tokenURL = self.agoraSettings.tokenURL {
- AgoraRtmController.fetchRtmToken(urlBase: tokenURL, userId: self.connectionData.rtmId) { fetchResult in
+ if let tokenURL = self.delegate.tokenURL, let rtmId = self.delegate?.rtmId {
+ AgoraRtmController.fetchRtmToken(urlBase: tokenURL, userId: rtmId) { fetchResult in
switch fetchResult {
case .success(let token):
- self.rtmKit.login(byToken: token, user: self.connectionData.rtmId
+ self.rtmKit.login(byToken: token, user: rtmId
) { errcode in
self.rtmLoggedIn(code: errcode)
completion(errcode)
}
case .failure(let failErr):
completion(.invalidToken)
- AgoraVideoViewer.agoraPrint(.error, message: "could not fetch token: \(failErr)")
+ AgoraRtmController.agoraPrint(.error, message: "could not fetch token: \(failErr)")
}
}
} else {
self.rtmKit.login(
- byToken: self.connectionData.rtmToken, user: self.connectionData.rtmId
+ byToken: self.delegate.rtmToken, user: self.delegate.rtmId
) { errcode in
self.rtmLoggedIn(code: errcode)
completion(errcode)
@@ -211,9 +164,9 @@ open class AgoraRtmController: NSObject {
case .unknown, .rejected, .invalidArgument, .invalidAppId,
.invalidToken, .tokenExpired, .notAuthorized,
.timeout, .loginTooOften, .loginNotInitialized:
- AgoraVideoViewer.agoraPrint(.error, message: "could not log into rtm: \(code.rawValue)")
+ AgoraRtmController.agoraPrint(.error, message: "could not log into rtm: \(code.rawValue)")
@unknown default:
- AgoraVideoViewer.agoraPrint(.error, message: "unknown login code")
+ AgoraRtmController.agoraPrint(.error, message: "unknown login code")
}
self.rtmStatus = .loginFailed(code)
}
@@ -234,13 +187,13 @@ open class AgoraRtmController: NSObject {
if err == .ok || err == .alreadyLogin {
self.joinChannel(named: channel, callback: callback)
} else {
- AgoraVideoViewer.agoraPrint(.error, message: "Could not login to rtm")
+ AgoraRtmController.agoraPrint(.error, message: "Could not login to rtm")
}
}
case .loggingIn:
self.afterLoginSteps.append { self.joinChannel(named: channel, callback: callback) }
case .loginFailed(let loginErr):
- AgoraVideoViewer.agoraPrint(.error, message: "login failed: \(loginErr.rawValue)")
+ AgoraRtmController.agoraPrint(.error, message: "login failed: \(loginErr.rawValue)")
case .loggedIn, .connected:
guard let newChannel = self.rtmKit.createChannel(withId: channel, delegate: self) else {
return
@@ -254,7 +207,7 @@ open class AgoraRtmController: NSObject {
self.joinChannel(named: channel, callback: callback)
}
case .initFailed:
- AgoraVideoViewer.agoraPrint(.error, message: "Cannot log into a channel if RTM failed")
+ AgoraRtmController.agoraPrint(.error, message: "Cannot log into a channel if RTM failed")
}
}
@@ -264,11 +217,11 @@ open class AgoraRtmController: NSObject {
if let rtmChannel = self.channels[channel] {
rtmChannel.leave { leaveStatus in
if leaveStatus == .ok {
- AgoraVideoViewer.agoraPrint(.verbose, message: "Successfully left RTM channel")
+ AgoraRtmController.agoraPrint(.verbose, message: "Successfully left RTM channel")
self.channels.removeValue(forKey: channel)
return
}
- AgoraVideoViewer.agoraPrint(
+ AgoraRtmController.agoraPrint(
.error, message: "Could not leave RTM channel \(channel): \(leaveStatus.rawValue)"
)
}
@@ -287,16 +240,15 @@ open class AgoraRtmController: NSObject {
switch code {
case .channelErrorOk:
self.rtmStatus = .connected
- self.sendPersonalData(to: channel)
self.channels[name] = channel
case .channelErrorFailure, .channelErrorRejected, .channelErrorInvalidArgument,
.channelErrorTimeout, .channelErrorExceedLimit, .channelErrorAlreadyJoined,
.channelErrorTooOften, .sameChannelErrorTooOften, .channelErrorNotInitialized,
.channelErrorNotLoggedIn:
- AgoraVideoViewer.agoraPrint(.error, message: "could not join channel: \(code.rawValue)")
+ AgoraRtmController.agoraPrint(.error, message: "could not join channel: \(code.rawValue)")
@unknown default:
- AgoraVideoViewer.agoraPrint(.error, message: "join channel unknown response: \(code.rawValue)")
+ AgoraRtmController.agoraPrint(.error, message: "join channel unknown response: \(code.rawValue)")
}
- self.delegate.rtmChannelJoined(name: name, channel: channel, code: code)
+ self.delegate?.rtmChannelJoined(name: name, channel: channel, code: code)
}
}
diff --git a/Tests/Agora-UIKit-Tests/RtcEncodingTests.swift b/Tests/Agora-UIKit-Tests/RtcEncodingTests.swift
index 84e99e22..a2739091 100644
--- a/Tests/Agora-UIKit-Tests/RtcEncodingTests.swift
+++ b/Tests/Agora-UIKit-Tests/RtcEncodingTests.swift
@@ -6,6 +6,8 @@
//
import XCTest
+#if canImport(AgoraRtmController) && canImport(AgoraUIKit_iOS)
+@testable import AgoraRtmController
@testable import AgoraUIKit_iOS
final class RtcEncodingTests: XCTestCase {
@@ -32,3 +34,4 @@ final class RtcEncodingTests: XCTestCase {
XCTAssertEqual(encodedeffsTest, encodedeffsTestCorrect, "UDID did not encode correctly: \(encodedeffsTest)")
}
}
+#endif
diff --git a/Tests/Agora-UIKit-Tests/RtmMessagingTests.swift b/Tests/Agora-UIKit-Tests/RtmMessagingTests.swift
index 3310bcdd..cfc641fa 100644
--- a/Tests/Agora-UIKit-Tests/RtmMessagingTests.swift
+++ b/Tests/Agora-UIKit-Tests/RtmMessagingTests.swift
@@ -1,14 +1,16 @@
import XCTest
import AgoraRtcKit
+#if canImport(AgoraRtmController) && canImport(AgoraUIKit_iOS)
import AgoraRtmKit
+import AgoraRtmController
@testable import AgoraUIKit_iOS
final class RtmMessagesTests: XCTestCase {
func testEncodeMuteReq() throws {
- let muteReq = AgoraRtmController.MuteRequest(
+ let muteReq = AgoraVideoViewer.MuteRequest(
rtcId: 999, mute: true, device: .camera, isForceful: true
)
- guard let rawMsg = AgoraRtmController.createRawRtm(from: muteReq) else {
+ guard let rawMsg = AgoraRtmController.createRtmMessage(from: muteReq) else {
return XCTFail("MuteRequest should be encodable")
}
XCTAssert(rawMsg.text == "AgoraUIKit", "Message text data should be AgoraUIKit")
@@ -27,7 +29,7 @@ final class RtmMessagesTests: XCTestCase {
+ "\"MuteRequest\",\"device\":0,\"isForceful\":true}"
XCTAssertEqual(msgText, msgTextValid, "Message text not matching mstTextValid")
- guard let decodedMsg = AgoraRtmController.decodeRawRtmData(
+ guard let decodedMsg = AgoraVideoViewer.decodeRtmData(
data: rawMsg.rawData, from: ""
) else {
return XCTFail("Failed to decode message")
@@ -47,11 +49,11 @@ final class RtmMessagesTests: XCTestCase {
}
func testEncodeUserData() throws {
- let userData = AgoraRtmController.UserData(
+ let userData = AgoraVideoViewer.UserData(
rtmId: "1234-5678", rtcId: 190, username: "username",
role: AgoraClientRole.broadcaster.rawValue, agora: .current, uikit: .current
)
- guard let rawMsg = AgoraRtmController.createRawRtm(from: userData) else {
+ guard let rawMsg = AgoraRtmController.createRtmMessage(from: userData) else {
return XCTFail("UserData should be encodable")
}
XCTAssert(rawMsg.text == "AgoraUIKit", "Message text data should be AgoraUIKit")
@@ -76,7 +78,7 @@ final class RtmMessagesTests: XCTestCase {
+ "\"messageType\":\"UserData\",\"rtcId\":190}"
XCTAssertEqual(msgText, msgTextValid, "Message text not matching msgTextValid")
- guard let decodedMsg = AgoraRtmController.decodeRawRtmData(data: rawMsg.rawData, from: "") else {
+ guard let decodedMsg = AgoraVideoViewer.decodeRtmData(data: rawMsg.rawData, from: "") else {
return XCTFail("Failed to decode message")
}
@@ -91,3 +93,4 @@ final class RtmMessagesTests: XCTestCase {
}
}
}
+#endif
diff --git a/doc_generation.md b/doc_generation.md
new file mode 100644
index 00000000..b20bcc9b
--- /dev/null
+++ b/doc_generation.md
@@ -0,0 +1,19 @@
+# Building Docc for Agora UIKit
+
+First generate the docs with Xcode via Terminal:
+
+```sh
+xcodebuild docbuild -scheme AgoraUIKit_iOS-Package \
+ -derivedDataPath 'docc' \
+ -destination generic/platform=iOS
+```
+
+Then turn the doccarchive into static docs:
+
+```sh
+$(xcrun --find docc) process-archive \
+ transform-for-static-hosting AgoraUIKit_iOS.doccarchive \
+ --output-path docs \
+ --hosting-base-path iOS-UIKit
+```
+
diff --git a/media/uml_agorartmcontrol.svg b/media/uml_agorartmcontrol.svg
new file mode 100644
index 00000000..b805ea83
--- /dev/null
+++ b/media/uml_agorartmcontrol.svg
@@ -0,0 +1,192 @@
+
\ No newline at end of file
diff --git a/media/uml_agorauikit.svg b/media/uml_agorauikit.svg
new file mode 100644
index 00000000..7a3b697c
--- /dev/null
+++ b/media/uml_agorauikit.svg
@@ -0,0 +1,814 @@
+
\ No newline at end of file