From 132e21de5b040bdece557a5f9e880d11223584aa Mon Sep 17 00:00:00 2001
From: Alexey Alter-Pesotskiy
Date: Fri, 19 Jul 2024 18:31:05 +0100
Subject: [PATCH 01/38] [CI] Update some release-related git commands (#467)
---
fastlane/Fastfile | 7 +++++--
1 file changed, 5 insertions(+), 2 deletions(-)
diff --git a/fastlane/Fastfile b/fastlane/Fastfile
index 2d59dc76f..d6cde0494 100644
--- a/fastlane/Fastfile
+++ b/fastlane/Fastfile
@@ -503,8 +503,11 @@ lane :merge_main_to_develop do
ensure_git_status_clean
end
- sh('git checkout main && git pull')
- sh('git checkout develop && git pull')
+ sh('git checkout main')
+ sh('git pull origin main')
+ sh('git checkout develop')
+ sh('git pull origin develop')
+ sh('git log develop..main')
sh('git merge main')
sh('git push')
end
From a48a6b341bab5fd3561e61fdcab0f6ca66bea6da Mon Sep 17 00:00:00 2001
From: Ilias Pavlidakis
Date: Sat, 20 Jul 2024 15:30:29 +0300
Subject: [PATCH 02/38] [Fix]Debug menu call expiration not working as expected
(#468)
---
DemoApp/Sources/Views/Login/DebugMenu.swift | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/DemoApp/Sources/Views/Login/DebugMenu.swift b/DemoApp/Sources/Views/Login/DebugMenu.swift
index 248ff1313..bf9232bde 100644
--- a/DemoApp/Sources/Views/Login/DebugMenu.swift
+++ b/DemoApp/Sources/Views/Login/DebugMenu.swift
@@ -129,7 +129,7 @@ struct DebugMenu: View {
currentValue: callExpiration,
additionalItems: { customCallExpirationView },
label: "Call Expiration"
- ) { _ in self.callExpiration = .custom(10) }
+ ) { self.callExpiration = $0 }
makeMenu(
for: [.enabled, .disabled],
From 97ee9984e974b26a008ba3ba955739bb6826d9a5 Mon Sep 17 00:00:00 2001
From: Alexey Alter-Pesotskiy
Date: Mon, 22 Jul 2024 11:52:39 +0100
Subject: [PATCH 03/38] Resolve StreamVideo.xcframework cocoapods-related paths
(#469)
---
StreamVideo-XCFramework.podspec | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/StreamVideo-XCFramework.podspec b/StreamVideo-XCFramework.podspec
index 6e053adc1..15387b725 100644
--- a/StreamVideo-XCFramework.podspec
+++ b/StreamVideo-XCFramework.podspec
@@ -17,10 +17,10 @@ Pod::Spec.new do |spec|
spec.module_name = 'StreamVideo'
spec.source = { http: "https://github.com/GetStream/stream-video-swift/releases/download/#{spec.version}/#{spec.module_name}.zip" }
- spec.preserve_paths = "#{spec.module_name}.xcframework/*"
+ spec.vendored_frameworks = "#{spec.module_name}.xcframework", 'Frameworks/StreamWebRTC.xcframework'
+ spec.preserve_paths = "#{spec.module_name}.xcframework/*", 'Frameworks/*'
spec.dependency('SwiftProtobuf', '~> 1.18.0')
- spec.vendored_frameworks = 'Frameworks/StreamWebRTC.xcframework'
spec.prepare_command = <<-CMD
mkdir -p Frameworks/
From 562b9ce319cf0146a207c5227665bd34e6374a68 Mon Sep 17 00:00:00 2001
From: Alexey Alter-Pesotskiy
Date: Mon, 22 Jul 2024 15:58:12 +0100
Subject: [PATCH 04/38] Update git fetch-depth on release (#470)
---
.github/workflows/publish-release.yml | 2 ++
1 file changed, 2 insertions(+)
diff --git a/.github/workflows/publish-release.yml b/.github/workflows/publish-release.yml
index 879681950..96e3080bf 100644
--- a/.github/workflows/publish-release.yml
+++ b/.github/workflows/publish-release.yml
@@ -18,6 +18,8 @@ jobs:
with:
ssh-private-key: ${{ secrets.BOT_SSH_PRIVATE_KEY }}
- uses: actions/checkout@v4.1.1
+ with:
+ fetch-depth: 0
- name: Extract version from branch name (for release branches)
if: startsWith(github.event.pull_request.head.ref, 'release/')
run: |
From 0cb9aaaedb948238c661fb7243aff67e86abdcdd Mon Sep 17 00:00:00 2001
From: Alexey Alter-Pesotskiy
Date: Tue, 30 Jul 2024 10:53:32 +0100
Subject: [PATCH 05/38] [CI] Comment SDK size on every commit (#472)
---
.github/workflows/sdk-size-metrics.yml | 38 +++++++++
.github/workflows/smoke-checks.yml | 1 +
.gitignore | 3 +
fastlane/Fastfile | 103 +++++++++++++++++++++++++
fastlane/sdk_size_export_options.plist | 33 ++++++++
5 files changed, 178 insertions(+)
create mode 100644 .github/workflows/sdk-size-metrics.yml
create mode 100644 fastlane/sdk_size_export_options.plist
diff --git a/.github/workflows/sdk-size-metrics.yml b/.github/workflows/sdk-size-metrics.yml
new file mode 100644
index 000000000..50745c712
--- /dev/null
+++ b/.github/workflows/sdk-size-metrics.yml
@@ -0,0 +1,38 @@
+name: SDK Size
+
+on:
+ pull_request:
+
+ workflow_dispatch:
+
+ push:
+ branches:
+ - develop
+
+env:
+ HOMEBREW_NO_INSTALL_CLEANUP: 1 # Disable cleanup for homebrew, we don't need it on CI
+
+jobs:
+ sdk_size:
+ name: Metrics
+ runs-on: macos-14
+ env:
+ GITHUB_TOKEN: '${{ secrets.CI_BOT_GITHUB_TOKEN }}'
+ steps:
+ - name: Install Bot SSH Key
+ uses: webfactory/ssh-agent@v0.7.0
+ with:
+ ssh-private-key: ${{ secrets.BOT_SSH_PRIVATE_KEY }}
+
+ - uses: actions/checkout@v3.1.0
+
+ - uses: ./.github/actions/bootstrap
+
+ - name: Run SDK Size Metrics
+ run: bundle exec fastlane show_frameworks_sizes
+ timeout-minutes: 30
+ env:
+ GITHUB_PR_NUM: ${{ github.event.pull_request.number }}
+ GITHUB_EVENT_NAME: ${{ github.event_name }}
+ MATCH_PASSWORD: ${{ secrets.MATCH_PASSWORD }}
+ APPSTORE_API_KEY: ${{ secrets.APPSTORE_API_KEY }}
diff --git a/.github/workflows/smoke-checks.yml b/.github/workflows/smoke-checks.yml
index 71cb8b5c8..aa6978831 100644
--- a/.github/workflows/smoke-checks.yml
+++ b/.github/workflows/smoke-checks.yml
@@ -271,6 +271,7 @@ jobs:
env:
ALLURE_TOKEN: ${{ secrets.ALLURE_TOKEN }}
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+ GITHUB_PR_NUM: ${{ github.event.number }}
GITHUB_EVENT: ${{ toJson(github.event) }}
- id: get_launch_id
run: echo "launch_id=${{env.LAUNCH_ID}}" >> $GITHUB_OUTPUT
diff --git a/.gitignore b/.gitignore
index 00577aa41..dbc271087 100644
--- a/.gitignore
+++ b/.gitignore
@@ -75,6 +75,7 @@ fastlane/screenshots
fastlane/test_output
fastlane/allurectl
fastlane/xcresults
+fastlane/metrics
recordings
*.coverage.txt
vendor/bundle/
@@ -92,6 +93,8 @@ derived_data/
spm_cache/
.buildcache
buildcache
+App Thinning Size Report.txt
+app-thinning.plist
*.dmg
# Stream Video Buddy
diff --git a/fastlane/Fastfile b/fastlane/Fastfile
index d6cde0494..9dcc07c9f 100644
--- a/fastlane/Fastfile
+++ b/fastlane/Fastfile
@@ -16,6 +16,8 @@ video_buddy_port = 5678
app_secret = ENV.fetch('STREAM_VIDEO_SECRET', nil)
derived_data_path = 'derived_data'
source_packages_path = 'spm_cache'
+metrics_git = 'git@github.com:GetStream/apple-internal-metrics.git'
+sdk_size_path = "metrics/#{github_repo.split('/').last}-size.json"
buildcache_xcargs = 'CC=clang CPLUSPLUS=clang++ LD=clang LDPLUSPLUS=clang++'
gci = ENV['GOOGLE_CLIENT_ID'] || ''
reversed_gci = gci.split('.').reverse.join('.')
@@ -24,6 +26,11 @@ is_localhost = !is_ci
swiftformat_excluded_paths = ["**/Generated", "**/generated", "**/protobuf", "**/OpenApi"]
swiftformat_source_paths = ["Sources", "DemoApp", "DemoAppUIKit", "StreamVideoTests", "StreamVideoSwiftUITests", "StreamVideoUIKitTests"]
+warning_status = '🟡' # Warning if a branch is #{max_tolerance} less performant than the benchmark
+fail_status = '🔴' # Failure if a branch is more than #{max_tolerance} less performant than the benchmark
+success_status = '🟢' # Success if a branch is more performant or equals to the benchmark
+outstanding_status = '🚀' # Outstanding performance
+
before_all do |lane|
if is_ci
setup_ci
@@ -732,6 +739,7 @@ lane :sources_matrix do
swiftui_sample_apps: ['Sources', 'DemoApp', xcode_project],
uikit_sample_apps: ['Sources', 'DemoAppUIKit', xcode_project],
documentation_tests: ['Sources', 'DocumentationTests', 'docusaurus', xcode_project],
+ size: ['Sources', xcode_project],
ruby: ['fastlane']
}
end
@@ -746,6 +754,93 @@ lane :copyright do
)
end
+desc 'Show current frameworks size'
+lane :show_frameworks_sizes do |options|
+ next unless is_check_required(sources: sources_matrix[:size], force_check: @force_check)
+
+ ['metrics/'].each { |dir| FileUtils.remove_dir(dir, force: true) }
+
+ sh("git clone #{metrics_git} #{File.dirname(sdk_size_path)}")
+ develop_sizes = JSON.parse(File.read(sdk_size_path))
+ branch_sizes = options[:sizes] || frameworks_sizes
+
+ table_header = '## SDK Size'
+ markdown_table = "#{table_header}\n| `title` | `develop` | `branch` | `diff` | `status` |\n| - | - | - | - | - |\n"
+ sdk_names.each do |title|
+ benchmark_value = develop_sizes[title]
+ branch_value = branch_sizes[title.to_sym]
+ max_tolerance = 0.5 # Max Tolerance is 0.5MB
+ fine_tolerance = 0.25 # Fine Tolerance is 0.25MB
+
+ diff = (branch_value - benchmark_value).round(2)
+
+ status_emoji =
+ if diff < 0
+ outstanding_status
+ elsif diff >= max_tolerance
+ fail_status
+ elsif diff >= fine_tolerance
+ warning_status
+ else
+ success_status
+ end
+
+ markdown_table << "|#{title}|#{benchmark_value}MB|#{branch_value}MB|#{diff}MB|#{status_emoji}|\n"
+ end
+
+ FastlaneCore::PrintTable.print_values(title: 'Benchmark', config: develop_sizes)
+ FastlaneCore::PrintTable.print_values(title: 'SDK Size', config: branch_sizes)
+
+ if is_ci
+ if ENV['GITHUB_EVENT_NAME'].to_s == 'push'
+ File.write(sdk_size_path, JSON.pretty_generate(branch_sizes))
+ Dir.chdir(File.dirname(sdk_size_path)) do
+ if sh('git status -s', log: false).to_s.empty?
+ UI.important('No changes in SDK sizes benchmarks.')
+ else
+ sh('git add -A')
+ sh("git commit -m 'Update #{sdk_size_path}'")
+ sh('git push')
+ end
+ end
+ end
+
+ create_pr_comment(pr_num: ENV.fetch('GITHUB_PR_NUM'), text: markdown_table, edit_last_comment_with_text: table_header)
+ end
+
+ UI.user_error!("#{table_header} benchmark failed.") if markdown_table.include?(fail_status)
+end
+
+def frameworks_sizes
+ root_dir = 'Build/SDKSize'
+ archive_dir = "#{root_dir}/DemoApp.xcarchive"
+
+ FileUtils.rm_rf("../#{root_dir}/")
+
+ match_me
+
+ gym(
+ scheme: 'DemoAppUIKit',
+ archive_path: archive_dir,
+ export_method: 'ad-hoc',
+ export_options: 'fastlane/sdk_size_export_options.plist'
+ )
+
+ frameworks_path = "../#{archive_dir}/Products/Applications/DemoAppUIKit.app/Frameworks"
+ stream_video_size = File.size("#{frameworks_path}/StreamVideo.framework/StreamVideo")
+ stream_video_size_mb = (stream_video_size.to_f / 1024 / 1024).round(2)
+ stream_video_swiftui_size = File.size("#{frameworks_path}/StreamVideoSwiftUI.framework/StreamVideoSwiftUI")
+ stream_video_swiftui_size_mb = (stream_video_swiftui_size.to_f / 1024 / 1024).round(2)
+ stream_video_uikit_size = File.size("#{frameworks_path}/StreamVideoUIKit.framework/StreamVideoUIKit")
+ stream_video_uikit_size_mb = ((stream_video_uikit_size + stream_video_swiftui_size).to_f / 1024 / 1024).round(2)
+
+ {
+ StreamVideo: stream_video_size_mb,
+ StreamVideoSwiftUI: stream_video_swiftui_size_mb,
+ StreamVideoUIKit: stream_video_uikit_size_mb
+ }
+end
+
private_lane :create_pr do |options|
options[:base_branch] ||= 'develop'
sh("git checkout -b #{options[:head_branch]}")
@@ -763,6 +858,14 @@ private_lane :create_pr do |options|
)
end
+private_lane :create_pr_comment do |options|
+ if is_ci && !options[:pr_num].to_s.empty?
+ last_comment = sh("gh pr view #{options[:pr_num]} --json comments --jq '.comments | map(select(.author.login == \"Stream-iOS-Bot\")) | last'")
+ edit_last_comment = last_comment.include?(options[:edit_last_comment_with_text]) ? '--edit-last' : ''
+ sh("gh pr comment #{options[:pr_num]} #{edit_last_comment} -b '#{options[:text]}'")
+ end
+end
+
private_lane :current_branch do
ENV['BRANCH_NAME'].to_s.empty? ? git_branch : ENV.fetch('BRANCH_NAME')
end
diff --git a/fastlane/sdk_size_export_options.plist b/fastlane/sdk_size_export_options.plist
new file mode 100644
index 000000000..6b447de07
--- /dev/null
+++ b/fastlane/sdk_size_export_options.plist
@@ -0,0 +1,33 @@
+
+
+
+
+ compileBitcode
+
+ destination
+ export
+ method
+ release-testing
+ provisioningProfiles
+
+ io.getstream.iOS.VideoDemoApp
+ match AdHoc io.getstream.iOS.VideoDemoApp
+ io.getstream.iOS.DemoAppUIKit
+ match AdHoc io.getstream.iOS.DemoAppUIKit
+ io.getstream.iOS.VideoDemoApp.CallIntent
+ match AdHoc io.getstream.iOS.VideoDemoApp.CallIntent
+ io.getstream.iOS.VideoDemoApp.ScreenSharing
+ match AdHoc io.getstream.iOS.VideoDemoApp.ScreenSharing
+
+ signingCertificate
+ Apple Distribution
+ signingStyle
+ manual
+ stripSwiftSymbols
+
+ teamID
+ EHV7XZLAHA
+ thinning
+ iPhone15,2
+
+
From 7453211702a37d1b04fac85c020e050df8f32e54 Mon Sep 17 00:00:00 2001
From: Alexey Alter-Pesotskiy
Date: Tue, 30 Jul 2024 12:48:28 +0100
Subject: [PATCH 06/38] [CI] Automatically update SDK size badges in README.md
(#473)
---
README.md | 5 +++--
fastlane/Fastfile | 28 ++++++++++++++++++++++++++++
2 files changed, 31 insertions(+), 2 deletions(-)
diff --git a/README.md b/README.md
index cfeac14eb..67e34053b 100644
--- a/README.md
+++ b/README.md
@@ -9,8 +9,9 @@
-
-
+
+
+
![Stream Video for iOS Header image](https://github.com/GetStream/stream-video-swift/assets/12433593/e4a44ae5-a8eb-4ac7-8910-28187aa011f6)
diff --git a/fastlane/Fastfile b/fastlane/Fastfile
index 9dcc07c9f..a8cf09556 100644
--- a/fastlane/Fastfile
+++ b/fastlane/Fastfile
@@ -59,6 +59,9 @@ lane :release do |options|
# Set the framework version in SystemEnvironment+Version.swift
new_content = File.read(swift_environment_path).gsub!(previous_version_number, release_version)
File.open(swift_environment_path, 'w') { |f| f.puts(new_content) }
+
+ # Update sdk sizes
+ Dir.chdir('fastlane') { update_img_shields_sdk_sizes }
end
pod_lint
@@ -811,6 +814,31 @@ lane :show_frameworks_sizes do |options|
UI.user_error!("#{table_header} benchmark failed.") if markdown_table.include?(fail_status)
end
+desc 'Update img shields SDK size labels'
+lane :update_img_shields_sdk_sizes do
+ sizes = frameworks_sizes
+
+ # Read the file into a string
+ readme_path = '../README.md'
+ readme_content = File.read(readme_path)
+
+ # Define the new value for the badge
+ stream_video_size = "#{sizes[:StreamVideo]}MB"
+ stream_video_swiftui_size = "#{sizes[:StreamVideoSwiftUI]}MB"
+ stream_video_uikit_size = "#{sizes[:StreamVideoUIKit]}MB"
+
+ # Replace the value in the badge URL
+ readme_content.gsub!(%r{(https://img.shields.io/badge/StreamVideo-)(.*?)(-blue)}, "\\1#{stream_video_size}\\3")
+ readme_content.gsub!(%r{(https://img.shields.io/badge/StreamVideoSwiftUI-)(.*?)(-blue)}, "\\1#{stream_video_swiftui_size}\\3")
+ readme_content.gsub!(%r{(https://img.shields.io/badge/StreamVideoUIKit-)(.*?)(-blue)}, "\\1#{stream_video_uikit_size}\\3")
+
+ # Write the updated content back to the file
+ File.write(readme_path, readme_content)
+
+ # Notify success
+ UI.success('Successfully updated the SDK size labels in README.md!')
+end
+
def frameworks_sizes
root_dir = 'Build/SDKSize'
archive_dir = "#{root_dir}/DemoApp.xcarchive"
From 5997914b02edbe6aa7401eb3a8eda05ea5d98cd7 Mon Sep 17 00:00:00 2001
From: Alexey Alter-Pesotskiy
Date: Tue, 30 Jul 2024 17:30:58 +0100
Subject: [PATCH 07/38] [CI] Adjust sdk size report on release PRs (#474)
---
.github/workflows/sdk-size-metrics.yml | 5 +++++
fastlane/Fastfile | 16 ++++++++++------
2 files changed, 15 insertions(+), 6 deletions(-)
diff --git a/.github/workflows/sdk-size-metrics.yml b/.github/workflows/sdk-size-metrics.yml
index 50745c712..e88d63c67 100644
--- a/.github/workflows/sdk-size-metrics.yml
+++ b/.github/workflows/sdk-size-metrics.yml
@@ -28,10 +28,15 @@ jobs:
- uses: ./.github/actions/bootstrap
+ - name: Get branch name
+ id: get_branch_name
+ run: echo "branch=${GITHUB_REF#refs/heads/}" >> $GITHUB_OUTPUT
+
- name: Run SDK Size Metrics
run: bundle exec fastlane show_frameworks_sizes
timeout-minutes: 30
env:
+ BRANCH_NAME: ${{ steps.get_branch_name.outputs.branch }}
GITHUB_PR_NUM: ${{ github.event.pull_request.number }}
GITHUB_EVENT_NAME: ${{ github.event_name }}
MATCH_PASSWORD: ${{ secrets.MATCH_PASSWORD }}
diff --git a/fastlane/Fastfile b/fastlane/Fastfile
index a8cf09556..20160808a 100644
--- a/fastlane/Fastfile
+++ b/fastlane/Fastfile
@@ -764,13 +764,16 @@ lane :show_frameworks_sizes do |options|
['metrics/'].each { |dir| FileUtils.remove_dir(dir, force: true) }
sh("git clone #{metrics_git} #{File.dirname(sdk_size_path)}")
- develop_sizes = JSON.parse(File.read(sdk_size_path))
+ is_release = current_branch.include?('release/')
+ benchmark_config = JSON.parse(File.read(sdk_size_path))
+ benchmark_key = is_release ? 'release' : 'develop'
+ benchmark_sizes = benchmark_config[benchmark_key]
branch_sizes = options[:sizes] || frameworks_sizes
table_header = '## SDK Size'
- markdown_table = "#{table_header}\n| `title` | `develop` | `branch` | `diff` | `status` |\n| - | - | - | - | - |\n"
+ markdown_table = "#{table_header}\n| `title` | `#{is_release ? 'previous release' : 'develop'}` | `#{is_release ? 'current release' : 'branch'}` | `diff` | `status` |\n| - | - | - | - | - |\n"
sdk_names.each do |title|
- benchmark_value = develop_sizes[title]
+ benchmark_value = benchmark_sizes[title]
branch_value = branch_sizes[title.to_sym]
max_tolerance = 0.5 # Max Tolerance is 0.5MB
fine_tolerance = 0.25 # Fine Tolerance is 0.25MB
@@ -791,12 +794,13 @@ lane :show_frameworks_sizes do |options|
markdown_table << "|#{title}|#{benchmark_value}MB|#{branch_value}MB|#{diff}MB|#{status_emoji}|\n"
end
- FastlaneCore::PrintTable.print_values(title: 'Benchmark', config: develop_sizes)
+ FastlaneCore::PrintTable.print_values(title: 'Benchmark', config: benchmark_sizes)
FastlaneCore::PrintTable.print_values(title: 'SDK Size', config: branch_sizes)
if is_ci
- if ENV['GITHUB_EVENT_NAME'].to_s == 'push'
- File.write(sdk_size_path, JSON.pretty_generate(branch_sizes))
+ if is_release || ENV['GITHUB_EVENT_NAME'].to_s == 'push'
+ benchmark_config[benchmark_key] = branch_sizes
+ File.write(sdk_size_path, JSON.pretty_generate(benchmark_config))
Dir.chdir(File.dirname(sdk_size_path)) do
if sh('git status -s', log: false).to_s.empty?
UI.important('No changes in SDK sizes benchmarks.')
From 11f1940c8e2ceeede8778e843dde49feced11525 Mon Sep 17 00:00:00 2001
From: Martin Mitrevski
Date: Wed, 31 Jul 2024 13:10:03 +0200
Subject: [PATCH 08/38] Update the notification docs (#475)
---
docusaurus/docs/iOS/06-advanced/02-push-notifications.mdx | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/docusaurus/docs/iOS/06-advanced/02-push-notifications.mdx b/docusaurus/docs/iOS/06-advanced/02-push-notifications.mdx
index 39b024094..2fe9fa4a9 100644
--- a/docusaurus/docs/iOS/06-advanced/02-push-notifications.mdx
+++ b/docusaurus/docs/iOS/06-advanced/02-push-notifications.mdx
@@ -5,6 +5,11 @@ description: Push Notifications setup
The `StreamVideo` SDK supports two types of push notifications: regular and VoIP notifications. You can use one of them, or both, depending on your use-case.
+Push notifications are sent in the following scenarios:
+- you create a call with the `ring` value set to true. In this case, a VoIP notification that shows a ringing screen is sent.
+- you create a call with the `notify` value set to true. In this case, a regular push notification is sent.
+- you haven't answered a call. In this case, a missed call notification is sent (regular push notification).
+
### StreamVideo setup
The push notification config is provided optionally, when the SDK is initalized. By default, the config uses `apn` as a push provider, for both VoIP and regular push. The push provider name for regular push is "apn", while for VoIP, the name is "voip".
From 41b35ef030579115501f4af5dd8acefe448e0419 Mon Sep 17 00:00:00 2001
From: Ilias Pavlidakis
Date: Wed, 31 Jul 2024 17:07:50 +0300
Subject: [PATCH 09/38] [Fix]Recording state when failed (#476)
---
Sources/StreamVideo/CallState.swift | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/Sources/StreamVideo/CallState.swift b/Sources/StreamVideo/CallState.swift
index 9ba5f4f36..2a523034c 100644
--- a/Sources/StreamVideo/CallState.swift
+++ b/Sources/StreamVideo/CallState.swift
@@ -214,7 +214,7 @@ public class CallState: ObservableObject {
case .typeCallHLSBroadcastingFailedEvent:
break
case .typeCallRecordingFailedEvent:
- break
+ recordingState = .noRecording
case .typeCallRecordingReadyEvent:
break
case .typeClosedCaptionEvent:
From 7b863b4c00bc6fb41e48a6b10dad0b2f9ab1d60b Mon Sep 17 00:00:00 2001
From: Alexey Alter-Pesotskiy
Date: Wed, 31 Jul 2024 18:20:15 +0100
Subject: [PATCH 10/38] [CI] Correctly retrieve a git branch on CI (#477)
---
.github/workflows/cron-checks.yml | 11 +++++-----
.github/workflows/publish-release.yml | 2 +-
.github/workflows/sdk-size-metrics.yml | 8 +------
.github/workflows/smoke-checks.yml | 29 +++++--------------------
.github/workflows/start-new-release.yml | 2 +-
.github/workflows/testflight.yml | 9 ++++----
fastlane/Allurefile | 5 ++---
fastlane/Fastfile | 11 ++++++++--
8 files changed, 29 insertions(+), 48 deletions(-)
diff --git a/.github/workflows/cron-checks.yml b/.github/workflows/cron-checks.yml
index e84661c09..d986e5ec5 100644
--- a/.github/workflows/cron-checks.yml
+++ b/.github/workflows/cron-checks.yml
@@ -12,6 +12,7 @@ concurrency:
env:
HOMEBREW_NO_INSTALL_CLEANUP: 1 # Disable cleanup for homebrew, we don't need it on CI
+ GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
jobs:
build-test-app-and-frameworks:
@@ -58,7 +59,6 @@ jobs:
runs-on: ${{ matrix.os }}
env:
GITHUB_EVENT: ${{ toJson(github.event) }}
- GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
ALLURE_TOKEN: ${{ secrets.ALLURE_TOKEN }}
XCODE_VERSION: ${{ matrix.xcode }}
IOS_SIMULATOR_DEVICE: "${{ matrix.device }} (${{ matrix.ios }})" # For the Allure report
@@ -147,7 +147,6 @@ jobs:
fail-fast: false
runs-on: ${{ matrix.os }}
env:
- GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
XCODE_VERSION: ${{ matrix.xcode }}
STREAM_VIDEO_SECRET: ${{ secrets.STREAM_VIDEO_SECRET }}
steps:
@@ -213,6 +212,10 @@ jobs:
env:
XCODE_VERSION: "15.0.1"
steps:
+ - name: Connect iOS Bot
+ uses: webfactory/ssh-agent@v0.7.0
+ with:
+ ssh-private-key: ${{ secrets.BOT_SSH_PRIVATE_KEY }}
- uses: actions/checkout@v3.1.0
- uses: ./.github/actions/ruby-cache
- name: List Xcode versions
@@ -225,10 +228,6 @@ jobs:
- name: Build UIKit
run: bundle exec fastlane test_uikit device:"iPhone 15" build_for_testing:true
timeout-minutes: 25
- - name: Install Bot SSH Key
- uses: webfactory/ssh-agent@v0.7.0
- with:
- ssh-private-key: ${{ secrets.BOT_SSH_PRIVATE_KEY }}
- name: Build XCFrameworks
run: bundle exec fastlane build_xcframeworks
timeout-minutes: 40
diff --git a/.github/workflows/publish-release.yml b/.github/workflows/publish-release.yml
index 96e3080bf..93f1ad60f 100644
--- a/.github/workflows/publish-release.yml
+++ b/.github/workflows/publish-release.yml
@@ -13,7 +13,7 @@ jobs:
runs-on: macos-13
if: github.event.pull_request.merged == true # only merged pull requests must trigger this job
steps:
- - name: Install Bot SSH Key
+ - name: Connect iOS Bot
uses: webfactory/ssh-agent@v0.7.0
with:
ssh-private-key: ${{ secrets.BOT_SSH_PRIVATE_KEY }}
diff --git a/.github/workflows/sdk-size-metrics.yml b/.github/workflows/sdk-size-metrics.yml
index e88d63c67..16e1d1e1c 100644
--- a/.github/workflows/sdk-size-metrics.yml
+++ b/.github/workflows/sdk-size-metrics.yml
@@ -19,7 +19,7 @@ jobs:
env:
GITHUB_TOKEN: '${{ secrets.CI_BOT_GITHUB_TOKEN }}'
steps:
- - name: Install Bot SSH Key
+ - name: Connect iOS Bot
uses: webfactory/ssh-agent@v0.7.0
with:
ssh-private-key: ${{ secrets.BOT_SSH_PRIVATE_KEY }}
@@ -28,16 +28,10 @@ jobs:
- uses: ./.github/actions/bootstrap
- - name: Get branch name
- id: get_branch_name
- run: echo "branch=${GITHUB_REF#refs/heads/}" >> $GITHUB_OUTPUT
-
- name: Run SDK Size Metrics
run: bundle exec fastlane show_frameworks_sizes
timeout-minutes: 30
env:
- BRANCH_NAME: ${{ steps.get_branch_name.outputs.branch }}
GITHUB_PR_NUM: ${{ github.event.pull_request.number }}
- GITHUB_EVENT_NAME: ${{ github.event_name }}
MATCH_PASSWORD: ${{ secrets.MATCH_PASSWORD }}
APPSTORE_API_KEY: ${{ secrets.APPSTORE_API_KEY }}
diff --git a/.github/workflows/smoke-checks.yml b/.github/workflows/smoke-checks.yml
index aa6978831..3dd502d91 100644
--- a/.github/workflows/smoke-checks.yml
+++ b/.github/workflows/smoke-checks.yml
@@ -29,6 +29,8 @@ concurrency:
env:
HOMEBREW_NO_INSTALL_CLEANUP: 1 # Disable cleanup for homebrew, we don't need it on CI
IOS_SIMULATOR_DEVICE: "iPhone 15 Pro (17.4)"
+ GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+ GITHUB_PR_NUM: ${{ github.event.pull_request.number }}
jobs:
test-llc-debug:
@@ -36,8 +38,6 @@ jobs:
runs-on: macos-14
if: ${{ github.event.inputs.swiftui_snapshots != 'true' && github.event.inputs.uikit_snapshots != 'true' }}
env:
- GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- GITHUB_PR_NUM: ${{ github.event.number }}
STREAM_VIDEO_SECRET: ${{ secrets.STREAM_VIDEO_SECRET }}
steps:
- uses: actions/checkout@v4.1.1
@@ -53,13 +53,9 @@ jobs:
env:
XCODE_VERSION: "15.2" # the most stable pair of Xcode
IOS_SIMULATOR_DEVICE: "iPhone 15 Pro (17.2)" # and iOS
- - name: Get branch name
- id: get_branch_name
- run: echo "branch=${GITHUB_REF#refs/heads/}" >> $GITHUB_OUTPUT
- name: Run Sonar analysis
run: bundle exec fastlane sonar_upload
env:
- BRANCH_NAME: ${{ steps.get_branch_name.outputs.branch }}
SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL }}
SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
- uses: actions/upload-artifact@v4
@@ -97,7 +93,6 @@ jobs:
if: ${{ github.event_name != 'push' && github.event.inputs.swiftui_snapshots != 'false' }}
env:
GITHUB_TOKEN: ${{ secrets.CI_BOT_GITHUB_TOKEN }} # to open a PR
- GITHUB_PR_NUM: ${{ github.event.number }}
steps:
- uses: actions/checkout@v4.1.1
- uses: ./.github/actions/bootstrap
@@ -129,7 +124,6 @@ jobs:
if: ${{ github.event_name != 'push' && github.event.inputs.uikit_snapshots != 'false' }}
env:
GITHUB_TOKEN: ${{ secrets.CI_BOT_GITHUB_TOKEN }} # to open a PR
- GITHUB_PR_NUM: ${{ github.event.number }}
steps:
- uses: actions/checkout@v4.1.1
- uses: ./.github/actions/bootstrap
@@ -161,8 +155,6 @@ jobs:
runs-on: macos-13
env:
XCODE_VERSION: "15.0.1"
- GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- GITHUB_PR_NUM: ${{ github.event.number }}
if: ${{ github.event_name != 'push' && github.event.inputs.swiftui_snapshots != 'true' && github.event.inputs.uikit_snapshots != 'true' }}
steps:
- uses: actions/checkout@v4.1.1
@@ -186,9 +178,11 @@ jobs:
if: ${{ github.event_name != 'push' && github.event.inputs.snapshots != 'true' }}
env:
XCODE_VERSION: "15.0.1"
- GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- GITHUB_PR_NUM: ${{ github.event.number }}
steps:
+ - name: Connect iOS Bot
+ uses: webfactory/ssh-agent@v0.7.0
+ with:
+ ssh-private-key: ${{ secrets.BOT_SSH_PRIVATE_KEY }}
- uses: actions/checkout@v3.1.0
- uses: ./.github/actions/ruby-cache
- name: List Xcode versions
@@ -201,10 +195,6 @@ jobs:
- name: Build UIKit
run: bundle exec fastlane test_uikit device:"iPhone 15" build_for_testing:true
timeout-minutes: 25
- - name: Install Bot SSH Key
- uses: webfactory/ssh-agent@v0.7.0
- with:
- ssh-private-key: ${{ secrets.BOT_SSH_PRIVATE_KEY }}
- name: Build XCFrameworks
run: bundle exec fastlane build_xcframeworks
timeout-minutes: 40
@@ -238,9 +228,6 @@ jobs:
runs-on: macos-14
needs: build-test-app-and-frameworks
if: ${{ github.event_name != 'push' && github.event.inputs.swiftui_snapshots != 'true' && github.event.inputs.uikit_snapshots != 'true' }}
- env:
- GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- GITHUB_PR_NUM: ${{ github.event.number }}
steps:
- uses: actions/checkout@v4.1.1
- uses: actions/download-artifact@v4
@@ -270,8 +257,6 @@ jobs:
run: bundle exec fastlane allure_launch
env:
ALLURE_TOKEN: ${{ secrets.ALLURE_TOKEN }}
- GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- GITHUB_PR_NUM: ${{ github.event.number }}
GITHUB_EVENT: ${{ toJson(github.event) }}
- id: get_launch_id
run: echo "launch_id=${{env.LAUNCH_ID}}" >> $GITHUB_OUTPUT
@@ -286,8 +271,6 @@ jobs:
- build-test-app-and-frameworks
env:
LAUNCH_ID: ${{ needs.allure_testops_launch.outputs.launch_id }}
- GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- GITHUB_PR_NUM: ${{ github.event.number }}
ALLURE_TOKEN: ${{ secrets.ALLURE_TOKEN }}
strategy:
matrix:
diff --git a/.github/workflows/start-new-release.yml b/.github/workflows/start-new-release.yml
index 1f434bee8..e66a1eac5 100644
--- a/.github/workflows/start-new-release.yml
+++ b/.github/workflows/start-new-release.yml
@@ -13,7 +13,7 @@ jobs:
name: Start new release
runs-on: macos-14
steps:
- - name: Install Bot SSH Key
+ - name: Connect iOS Bot
uses: webfactory/ssh-agent@v0.7.0
with:
ssh-private-key: ${{ secrets.BOT_SSH_PRIVATE_KEY }}
diff --git a/.github/workflows/testflight.yml b/.github/workflows/testflight.yml
index 820f0b501..7b4572c1a 100644
--- a/.github/workflows/testflight.yml
+++ b/.github/workflows/testflight.yml
@@ -1,10 +1,9 @@
name: Test Flight Deploy DemoApp
on:
- # TODO: commented until `develop` branch is in place
- # pull_request:
- # branches:
- # - 'main'
+ pull_request:
+ branches:
+ - 'main'
release:
types: [published]
@@ -32,7 +31,7 @@ jobs:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
GITHUB_PR_NUM: ${{ github.event.number }}
steps:
- - name: Install Bot SSH Key
+ - name: Connect iOS Bot
uses: webfactory/ssh-agent@v0.7.0
with:
ssh-private-key: ${{ secrets.BOT_SSH_PRIVATE_KEY }}
diff --git a/fastlane/Allurefile b/fastlane/Allurefile
index c40298403..6f7014b45 100755
--- a/fastlane/Allurefile
+++ b/fastlane/Allurefile
@@ -8,11 +8,10 @@ allure_results_path = 'allure-results'
desc 'Upload test results to Allure TestOps'
lane :allure_upload do |options|
- branch = github_run_details['head_branch']
allure_args = "-e #{allure_url} --project-id #{allure_project_id} --launch-id #{options[:launch_id]}"
sh("./xcresults export test_output/DemoApp.xcresult #{allure_results_path} || true")
sh("./allurectl launch reopen #{options[:launch_id]} || true") # to prevent allure from uploading results to a closed launch
- sh("env BRANCH_NAME='#{branch}' ./allurectl upload #{allure_args} #{allure_results_path} || true")
+ sh("env BRANCH_NAME='#{current_branch}' ./allurectl upload #{allure_args} #{allure_results_path} || true")
UI.success("Check out test results in Allure TestOps: #{allure_url}/launch/#{options[:launch_id]} 🎉")
end
@@ -54,6 +53,6 @@ def github_run_details
return nil unless is_ci
github_path = "#{ENV.fetch('GITHUB_API_URL', nil)}/repos/#{ENV.fetch('GITHUB_REPOSITORY', nil)}/actions/runs/#{ENV.fetch('GITHUB_RUN_ID', nil)}"
- output = sh(command: "curl -s -H 'authorization: Bearer #{ENV.fetch('GITHUB_TOKEN', nil)}' -X GET -G #{github_path}", log: false)
+ output = sh(command: "curl -s -H 'authorization: Bearer #{ENV.fetch('GITHUB_TOKEN', nil)}' -X GET -G #{github_path}")
JSON.parse(output)
end
diff --git a/fastlane/Fastfile b/fastlane/Fastfile
index 20160808a..2108872a3 100644
--- a/fastlane/Fastfile
+++ b/fastlane/Fastfile
@@ -898,6 +898,13 @@ private_lane :create_pr_comment do |options|
end
end
-private_lane :current_branch do
- ENV['BRANCH_NAME'].to_s.empty? ? git_branch : ENV.fetch('BRANCH_NAME')
+lane :current_branch do
+ branch = if ENV['GITHUB_PR_NUM'].to_s.empty?
+ git_branch
+ else
+ sh("gh pr view #{ENV.fetch('GITHUB_PR_NUM')} --json headRefName -q .headRefName").strip
+ end
+
+ UI.important("Current branch: #{branch} 🕊️")
+ branch
end
From bb6d8277c2dc87d761277b6425d3adef7d33177e Mon Sep 17 00:00:00 2001
From: Alexey Alter-Pesotskiy
Date: Thu, 1 Aug 2024 15:25:25 +0100
Subject: [PATCH 11/38] [CI] Automate the merge of the release branches (#478)
---
.github/workflows/release-merge.yml | 31 +++++++++++
...ublish-release.yml => release-publish.yml} | 4 ++
...tart-new-release.yml => release-start.yml} | 4 ++
fastlane/Fastfile | 51 +++++++++++--------
4 files changed, 69 insertions(+), 21 deletions(-)
create mode 100644 .github/workflows/release-merge.yml
rename .github/workflows/{publish-release.yml => release-publish.yml} (99%)
rename .github/workflows/{start-new-release.yml => release-start.yml} (99%)
diff --git a/.github/workflows/release-merge.yml b/.github/workflows/release-merge.yml
new file mode 100644
index 000000000..05785d093
--- /dev/null
+++ b/.github/workflows/release-merge.yml
@@ -0,0 +1,31 @@
+name: "Merge release"
+
+on:
+ issue_comment:
+ types: [created]
+
+ workflow_dispatch:
+
+jobs:
+ merge-comment:
+ name: Merge release to main
+ runs-on: macos-14
+ if: github.event_name == 'workflow_dispatch' || (github.event.issue.pull_request && github.event.issue.state == 'open' && github.event.comment.body == '/merge release')
+ steps:
+ - name: Connect iOS Bot
+ uses: webfactory/ssh-agent@v0.7.0
+ with:
+ ssh-private-key: ${{ secrets.BOT_SSH_PRIVATE_KEY }}
+
+ - uses: actions/checkout@v4.1.1
+ with:
+ fetch-depth: 0
+
+ - uses: ./.github/actions/ruby-cache
+
+ - name: Merge
+ run: bundle exec fastlane merge_release_to_main author:"$USER_LOGIN" --verbose
+ env:
+ GITHUB_TOKEN: ${{ secrets.ADMIN_API_TOKEN }} # A token with the "admin:org" scope to get the list of the team members on GitHub
+ GITHUB_PR_NUM: ${{ github.event.issue.number }}
+ USER_LOGIN: ${{ github.event.comment.user.login != null && github.event.comment.user.login || github.event.sender.login }}
diff --git a/.github/workflows/publish-release.yml b/.github/workflows/release-publish.yml
similarity index 99%
rename from .github/workflows/publish-release.yml
rename to .github/workflows/release-publish.yml
index 93f1ad60f..80113e243 100644
--- a/.github/workflows/publish-release.yml
+++ b/.github/workflows/release-publish.yml
@@ -17,16 +17,20 @@ jobs:
uses: webfactory/ssh-agent@v0.7.0
with:
ssh-private-key: ${{ secrets.BOT_SSH_PRIVATE_KEY }}
+
- uses: actions/checkout@v4.1.1
with:
fetch-depth: 0
+
- name: Extract version from branch name (for release branches)
if: startsWith(github.event.pull_request.head.ref, 'release/')
run: |
BRANCH_NAME="${{ github.event.pull_request.head.ref }}"
VERSION=${BRANCH_NAME#release/}
echo "RELEASE_VERSION=$VERSION" >> $GITHUB_ENV
+
- uses: ./.github/actions/ruby-cache
+
- name: "Fastlane - Publish Release"
if: startsWith(github.event.pull_request.head.ref, 'release/')
env:
diff --git a/.github/workflows/start-new-release.yml b/.github/workflows/release-start.yml
similarity index 99%
rename from .github/workflows/start-new-release.yml
rename to .github/workflows/release-start.yml
index e66a1eac5..a03592c30 100644
--- a/.github/workflows/start-new-release.yml
+++ b/.github/workflows/release-start.yml
@@ -17,11 +17,15 @@ jobs:
uses: webfactory/ssh-agent@v0.7.0
with:
ssh-private-key: ${{ secrets.BOT_SSH_PRIVATE_KEY }}
+
- uses: actions/checkout@v4.1.1
with:
fetch-depth: 0 # to fetch git tags
+
- uses: ./.github/actions/ruby-cache
+
- uses: ./.github/actions/xcode-cache
+
- name: Create Release PR
run: bundle exec fastlane release version:"${{ github.event.inputs.version }}" --verbose
env:
diff --git a/fastlane/Fastfile b/fastlane/Fastfile
index 2108872a3..6175d8bbe 100644
--- a/fastlane/Fastfile
+++ b/fastlane/Fastfile
@@ -34,6 +34,7 @@ outstanding_status = '🚀' # Outstanding performance
before_all do |lane|
if is_ci
setup_ci
+ sh('git config --global user.name "Stream Bot"')
xcversion(version: xcode_version) unless [:publish_release, :allure_launch, :allure_upload, :pod_lint, :stop_e2e_helpers].include?(lane)
elsif lane == :test_e2e
stop_e2e_helpers
@@ -489,37 +490,46 @@ private_lane :build_example_app do |options|
)
end
-lane :merge_release_to_main do
+lane :merge_release_to_main do |options|
ensure_git_status_clean
- sh('git checkout main')
- sh('git pull')
- # Grep all remote release branches and ensure there's only one
- release_branches = sh(command: 'git branch -a', log: false).delete(' ').split("\n").grep(%r(origin/.*release/))
- UI.user_error!("Expected 1 release branch, found #{release_branches.size}") if release_branches.size != 1
+ release_branch =
+ if is_ci
+ # This API operation needs the "admin:org" scope.
+ ios_team = sh('gh api orgs/GetStream/teams/ios-developers/members -q ".[].login"', log: false).split
+ UI.user_error!("#{options[:author]} is not a member of the iOS Team") unless ios_team.include?(options[:author])
+
+ current_branch
+ else
+ release_branches = sh(command: 'git branch -a', log: false).delete(' ').split("\n").grep(%r(origin/.*release/))
+ UI.user_error!("Expected 1 release branch, found #{release_branches.size}") if release_branches.size != 1
+
+ release_branches.first
+ end
+
+ UI.user_error!("`#{release_branch}`` branch does not match the release branch pattern: `release/*`") unless release_branch.start_with?('release/')
+
+ sh('git checkout origin/main')
+ sh('git pull origin main')
# Merge release branch to main. For more info, read: https://notion.so/iOS-Branching-Strategy-37c10127dc26493e937769d44b1d6d9a
- sh("git merge #{release_branches.first} --ff-only")
- UI.user_error!('Not pushing changes') unless prompt(text: 'Will push changes. All looking good?', boolean: true)
- sh('git push')
- UI.important('Please, wait for the `Publish new release` workflow to pass on GitHub Actions: ' \
- "https://github.com/#{github_repo}/actions/workflows/publish-release.yml")
+ sh("git merge #{release_branch} --ff-only")
+ sh('git push origin main')
+
+ comment = "[Publication of the release](https://github.com/#{github_repo}/actions/workflows/release-publish.yml) has been launched 👍"
+ UI.important(comment)
+ create_pr_comment(pr_num: ENV.fetch('GITHUB_PR_NUM'), text: comment)
end
lane :merge_main_to_develop do
- if is_ci
- sh('git reset --hard')
- else
- ensure_git_status_clean
- end
-
+ ensure_git_status_clean
sh('git checkout main')
sh('git pull origin main')
- sh('git checkout develop')
+ sh('git checkout origin/develop')
sh('git pull origin develop')
sh('git log develop..main')
sh('git merge main')
- sh('git push')
+ sh('git push origin develop')
end
desc 'Compresses the XCFrameworks into zip files'
@@ -594,7 +604,6 @@ private_lane :update_spm do |options|
File.open('./Package.swift', 'w') { |file| file << file_data }
# Update the repo
- sh('git config --global user.name "Stream Bot"')
sh('git add -A')
sh("git commit -m 'Bump #{version}'")
sh('git push')
@@ -893,7 +902,7 @@ end
private_lane :create_pr_comment do |options|
if is_ci && !options[:pr_num].to_s.empty?
last_comment = sh("gh pr view #{options[:pr_num]} --json comments --jq '.comments | map(select(.author.login == \"Stream-iOS-Bot\")) | last'")
- edit_last_comment = last_comment.include?(options[:edit_last_comment_with_text]) ? '--edit-last' : ''
+ edit_last_comment = options[:edit_last_comment_with_text] && last_comment.include?(options[:edit_last_comment_with_text]) ? '--edit-last' : ''
sh("gh pr comment #{options[:pr_num]} #{edit_last_comment} -b '#{options[:text]}'")
end
end
From 05d23d525cefeb438911a9ffdba056d78fd9ea3c Mon Sep 17 00:00:00 2001
From: Martin Mitrevski
Date: Tue, 6 Aug 2024 10:54:27 +0200
Subject: [PATCH 12/38] Removed clean reconnect from reconnect strategies
(#481)
---
.../protobuf/sfu/models/models.pb.swift | 24 +++++++------------
1 file changed, 8 insertions(+), 16 deletions(-)
diff --git a/Sources/StreamVideo/protobuf/sfu/models/models.pb.swift b/Sources/StreamVideo/protobuf/sfu/models/models.pb.swift
index ea62ab464..66d016a88 100644
--- a/Sources/StreamVideo/protobuf/sfu/models/models.pb.swift
+++ b/Sources/StreamVideo/protobuf/sfu/models/models.pb.swift
@@ -567,16 +567,12 @@ enum Stream_Video_Sfu_Models_WebsocketReconnectStrategy: SwiftProtobuf.Enum {
/// and establish a new WebSocket connection.
case fast // = 2
- /// SDK should drop existing pc instances and creates a fresh WebSocket connection,
- /// ensuring a clean state for the reconnection.
- case clean // = 3
-
/// SDK should obtain new credentials from the coordinator, drops existing pc instances, set a new session_id and initializes
/// a completely new WebSocket connection, ensuring a comprehensive reset.
- case rejoin // = 4
+ case rejoin // = 3
/// SDK should migrate to a new SFU instance
- case migrate // = 5
+ case migrate // = 4
case UNRECOGNIZED(Int)
init() {
@@ -588,9 +584,8 @@ enum Stream_Video_Sfu_Models_WebsocketReconnectStrategy: SwiftProtobuf.Enum {
case 0: self = .unspecified
case 1: self = .disconnect
case 2: self = .fast
- case 3: self = .clean
- case 4: self = .rejoin
- case 5: self = .migrate
+ case 3: self = .rejoin
+ case 4: self = .migrate
default: self = .UNRECOGNIZED(rawValue)
}
}
@@ -600,9 +595,8 @@ enum Stream_Video_Sfu_Models_WebsocketReconnectStrategy: SwiftProtobuf.Enum {
case .unspecified: return 0
case .disconnect: return 1
case .fast: return 2
- case .clean: return 3
- case .rejoin: return 4
- case .migrate: return 5
+ case .rejoin: return 3
+ case .migrate: return 4
case .UNRECOGNIZED(let i): return i
}
}
@@ -617,7 +611,6 @@ extension Stream_Video_Sfu_Models_WebsocketReconnectStrategy: CaseIterable {
.unspecified,
.disconnect,
.fast,
- .clean,
.rejoin,
.migrate,
]
@@ -1223,9 +1216,8 @@ extension Stream_Video_Sfu_Models_WebsocketReconnectStrategy: SwiftProtobuf._Pro
0: .same(proto: "WEBSOCKET_RECONNECT_STRATEGY_UNSPECIFIED"),
1: .same(proto: "WEBSOCKET_RECONNECT_STRATEGY_DISCONNECT"),
2: .same(proto: "WEBSOCKET_RECONNECT_STRATEGY_FAST"),
- 3: .same(proto: "WEBSOCKET_RECONNECT_STRATEGY_CLEAN"),
- 4: .same(proto: "WEBSOCKET_RECONNECT_STRATEGY_REJOIN"),
- 5: .same(proto: "WEBSOCKET_RECONNECT_STRATEGY_MIGRATE"),
+ 3: .same(proto: "WEBSOCKET_RECONNECT_STRATEGY_REJOIN"),
+ 4: .same(proto: "WEBSOCKET_RECONNECT_STRATEGY_MIGRATE"),
]
}
From a4ebfd2fda13f464e98e86849ada9f9ea4afdce8 Mon Sep 17 00:00:00 2001
From: Alexey Alter-Pesotskiy
Date: Tue, 6 Aug 2024 14:01:57 +0100
Subject: [PATCH 13/38] [CI] Update gems (#482)
---
Gemfile.lock | 79 +++++++++++++++++++++++++---------------------------
1 file changed, 38 insertions(+), 41 deletions(-)
diff --git a/Gemfile.lock b/Gemfile.lock
index cfc99e2d3..0ec3d13ab 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -5,7 +5,7 @@ GEM
base64
nkf
rexml
- activesupport (7.1.3.3)
+ activesupport (7.1.3.4)
base64
bigdecimal
concurrent-ruby (~> 1.0, >= 1.0.2)
@@ -15,8 +15,8 @@ GEM
minitest (>= 5.1)
mutex_m
tzinfo (~> 2.0)
- addressable (2.8.6)
- public_suffix (>= 2.0.2, < 6.0)
+ addressable (2.8.7)
+ public_suffix (>= 2.0.2, < 7.0)
algoliasearch (1.27.5)
httpclient (~> 2.8, >= 2.8.3)
json (>= 1.5.1)
@@ -24,20 +24,20 @@ GEM
ast (2.4.2)
atomos (0.1.3)
aws-eventstream (1.3.0)
- aws-partitions (1.937.0)
- aws-sdk-core (3.196.1)
+ aws-partitions (1.962.0)
+ aws-sdk-core (3.201.3)
aws-eventstream (~> 1, >= 1.3.0)
aws-partitions (~> 1, >= 1.651.0)
aws-sigv4 (~> 1.8)
jmespath (~> 1, >= 1.6.1)
- aws-sdk-kms (1.82.0)
- aws-sdk-core (~> 3, >= 3.193.0)
- aws-sigv4 (~> 1.1)
- aws-sdk-s3 (1.151.0)
- aws-sdk-core (~> 3, >= 3.194.0)
+ aws-sdk-kms (1.88.0)
+ aws-sdk-core (~> 3, >= 3.201.0)
+ aws-sigv4 (~> 1.5)
+ aws-sdk-s3 (1.157.0)
+ aws-sdk-core (~> 3, >= 3.201.0)
aws-sdk-kms (~> 1)
- aws-sigv4 (~> 1.8)
- aws-sigv4 (1.8.0)
+ aws-sigv4 (~> 1.5)
+ aws-sigv4 (1.9.1)
aws-eventstream (~> 1, >= 1.0.2)
babosa (1.0.4)
badge (0.13.0)
@@ -94,11 +94,11 @@ GEM
colored2 (3.1.2)
commander (4.6.0)
highline (~> 2.0.0)
- concurrent-ruby (1.3.1)
+ concurrent-ruby (1.3.3)
connection_pool (2.4.1)
cork (0.3.0)
colored2 (~> 3.1)
- danger (9.4.3)
+ danger (9.5.0)
claide (~> 1.0)
claide-plugins (>= 0.9.2)
colored2 (~> 3.1)
@@ -108,7 +108,6 @@ GEM
git (~> 1.13)
kramdown (~> 2.3)
kramdown-parser-gfm (~> 1.0)
- no_proxy_fix
octokit (>= 4.0)
terminal-table (>= 1, < 4)
danger-commit_lint (0.0.7)
@@ -125,7 +124,7 @@ GEM
escape (0.0.4)
ethon (0.16.0)
ffi (>= 1.15.0)
- excon (0.110.0)
+ excon (0.111.0)
faraday (1.10.3)
faraday-em_http (~> 1.0)
faraday-em_synchrony (~> 1.0)
@@ -149,7 +148,7 @@ GEM
faraday-httpclient (1.0.1)
faraday-multipart (1.0.4)
multipart-post (~> 2)
- faraday-net_http (1.0.1)
+ faraday-net_http (1.0.2)
faraday-net_http_persistent (1.2.0)
faraday-patron (1.0.0)
faraday-rack (1.0.0)
@@ -157,7 +156,7 @@ GEM
faraday_middleware (1.2.0)
faraday (~> 1.0)
fastimage (2.3.1)
- fastlane (2.220.0)
+ fastlane (2.222.0)
CFPropertyList (>= 2.3, < 4.0.0)
addressable (>= 2.8, < 3.0.0)
artifactory (~> 3.0)
@@ -206,7 +205,7 @@ GEM
fastlane-plugin-stream_actions (0.3.38)
xctest_list (= 1.2.1)
fastlane-plugin-versioning (0.5.2)
- ffi (1.16.3)
+ ffi (1.17.0)
fourflusher (2.3.1)
fuzzy_match (2.0.4)
gh_inspector (1.1.3)
@@ -229,7 +228,7 @@ GEM
google-apis-core (>= 0.11.0, < 2.a)
google-apis-storage_v1 (0.31.0)
google-apis-core (>= 0.11.0, < 2.a)
- google-cloud-core (1.7.0)
+ google-cloud-core (1.7.1)
google-cloud-env (>= 1.0, < 3.a)
google-cloud-errors (~> 1.0)
google-cloud-env (1.6.0)
@@ -250,24 +249,24 @@ GEM
os (>= 0.9, < 2.0)
signet (>= 0.16, < 2.a)
highline (2.0.3)
- http-cookie (1.0.5)
+ http-cookie (1.0.6)
domain_name (~> 0.5)
httpclient (2.8.3)
i18n (1.14.5)
concurrent-ruby (~> 1.0)
- jazzy (0.15.0)
+ jazzy (0.15.1)
cocoapods (~> 1.5)
mustache (~> 1.1)
open4 (~> 1.3)
redcarpet (~> 3.4)
- rexml (~> 3.2)
+ rexml (>= 3.2.7, < 4.0)
rouge (>= 2.0.6, < 5.0)
sassc (~> 2.1)
sqlite3 (~> 1.3)
xcinvoke (~> 0.3.0)
jmespath (1.6.2)
json (2.7.2)
- jwt (2.8.1)
+ jwt (2.8.2)
base64
kramdown (2.4.0)
rexml
@@ -275,15 +274,15 @@ GEM
kramdown (~> 2.0)
liferaft (0.0.6)
method_source (1.1.0)
- mini_magick (4.12.0)
+ mini_magick (4.13.2)
mini_mime (1.1.5)
- mini_portile2 (2.8.6)
- minitest (5.23.1)
+ mini_portile2 (2.8.7)
+ minitest (5.24.1)
molinillo (0.8.0)
multi_json (1.15.0)
multipart-post (2.4.1)
mustache (1.1.1)
- mustermann (3.0.0)
+ mustermann (3.0.1)
ruby2_keywords (~> 0.0.1)
mutex_m (0.2.0)
nanaimo (0.3.0)
@@ -292,19 +291,17 @@ GEM
netrc (0.11.0)
nio4r (2.7.3)
nkf (0.2.0)
- no_proxy_fix (0.1.2)
- nokogiri (1.16.5)
+ nokogiri (1.16.7)
mini_portile2 (~> 2.8.2)
racc (~> 1.4)
- octokit (8.1.0)
- base64
+ octokit (9.1.0)
faraday (>= 1, < 3)
sawyer (~> 0.9)
open4 (1.3.4)
optparse (0.5.0)
os (1.1.4)
- parallel (1.24.0)
- parser (3.3.2.0)
+ parallel (1.25.1)
+ parser (3.3.4.0)
ast (~> 2.4.1)
racc
plist (3.7.1)
@@ -314,8 +311,8 @@ GEM
public_suffix (4.0.7)
puma (6.4.2)
nio4r (~> 2.0)
- racc (1.8.0)
- rack (3.0.11)
+ racc (1.8.1)
+ rack (3.1.7)
rack-protection (4.0.0)
base64 (>= 0.1.0)
rack (>= 3.0.0, < 4)
@@ -334,8 +331,8 @@ GEM
trailblazer-option (>= 0.1.1, < 0.2.0)
uber (< 0.2.0)
retriable (3.1.2)
- rexml (3.2.8)
- strscan (>= 3.0.9)
+ rexml (3.2.9)
+ strscan
rouge (2.0.7)
rubocop (1.38.0)
json (~> 2.3)
@@ -347,7 +344,7 @@ GEM
rubocop-ast (>= 1.23.0, < 2.0)
ruby-progressbar (~> 1.7)
unicode-display_width (>= 1.4.0, < 3.0)
- rubocop-ast (1.31.3)
+ rubocop-ast (1.32.0)
parser (>= 3.3.1.0)
rubocop-performance (1.19.1)
rubocop (>= 1.7.0, < 2.0)
@@ -378,7 +375,7 @@ GEM
rack-protection (= 4.0.0)
rack-session (>= 2.0.0, < 3)
tilt (~> 2.0)
- slather (2.8.0)
+ slather (2.8.3)
CFPropertyList (>= 2.2, < 4)
activesupport
clamp (~> 1.3)
@@ -390,7 +387,7 @@ GEM
terminal-notifier (2.0.0)
terminal-table (3.0.2)
unicode-display_width (>= 1.1.1, < 3)
- tilt (2.3.0)
+ tilt (2.4.0)
trailblazer-option (0.1.2)
tty-cursor (0.7.1)
tty-screen (0.8.2)
From 8ebe1f07275fbe9daa0f7d90cda8dbd3e0474878 Mon Sep 17 00:00:00 2001
From: Martin Mitrevski
Date: Thu, 8 Aug 2024 11:50:28 +0200
Subject: [PATCH 14/38] Remove unused code (#483)
---
.../OpenApi/generated/Extensions.swift | 99 -------------------
1 file changed, 99 deletions(-)
diff --git a/Sources/StreamVideo/OpenApi/generated/Extensions.swift b/Sources/StreamVideo/OpenApi/generated/Extensions.swift
index 557638320..fd01f2647 100644
--- a/Sources/StreamVideo/OpenApi/generated/Extensions.swift
+++ b/Sources/StreamVideo/OpenApi/generated/Extensions.swift
@@ -120,102 +120,3 @@ extension String: CodingKey {
}
}
-
-extension KeyedEncodingContainerProtocol {
-
- public mutating func encodeArray(_ values: [T], forKey key: Self.Key) throws where T: Encodable {
- var arrayContainer = nestedUnkeyedContainer(forKey: key)
- try arrayContainer.encode(contentsOf: values)
- }
-
- public mutating func encodeArrayIfPresent(_ values: [T]?, forKey key: Self.Key) throws where T: Encodable {
- if let values = values {
- try encodeArray(values, forKey: key)
- }
- }
-
- public mutating func encodeMap(_ pairs: [Self.Key: T]) throws where T: Encodable {
- for (key, value) in pairs {
- try encode(value, forKey: key)
- }
- }
-
- public mutating func encodeMapIfPresent(_ pairs: [Self.Key: T]?) throws where T: Encodable {
- if let pairs = pairs {
- try encodeMap(pairs)
- }
- }
-
- public mutating func encode(_ value: Decimal, forKey key: Self.Key) throws {
- var mutableValue = value
- let stringValue = NSDecimalString(&mutableValue, Locale(identifier: "en_US"))
- try encode(stringValue, forKey: key)
- }
-
- public mutating func encodeIfPresent(_ value: Decimal?, forKey key: Self.Key) throws {
- if let value = value {
- try encode(value, forKey: key)
- }
- }
-}
-
-extension KeyedDecodingContainerProtocol {
-
- public func decodeArray(_ type: T.Type, forKey key: Self.Key) throws -> [T] where T: Decodable {
- var tmpArray = [T]()
-
- var nestedContainer = try nestedUnkeyedContainer(forKey: key)
- while !nestedContainer.isAtEnd {
- let arrayValue = try nestedContainer.decode(T.self)
- tmpArray.append(arrayValue)
- }
-
- return tmpArray
- }
-
- public func decodeArrayIfPresent(_ type: T.Type, forKey key: Self.Key) throws -> [T]? where T: Decodable {
- var tmpArray: [T]?
-
- if contains(key) {
- tmpArray = try decodeArray(T.self, forKey: key)
- }
-
- return tmpArray
- }
-
- public func decodeMap(_ type: T.Type, excludedKeys: Set) throws -> [Self.Key: T] where T: Decodable {
- var map: [Self.Key: T] = [:]
-
- for key in allKeys {
- if !excludedKeys.contains(key) {
- let value = try decode(T.self, forKey: key)
- map[key] = value
- }
- }
-
- return map
- }
-
- public func decode(_ type: Decimal.Type, forKey key: Self.Key) throws -> Decimal {
- let stringValue = try decode(String.self, forKey: key)
- guard let decimalValue = Decimal(string: stringValue) else {
- let context = DecodingError.Context(codingPath: [key], debugDescription: "The key \(key) couldn't be converted to a Decimal value")
- throw DecodingError.typeMismatch(type, context)
- }
-
- return decimalValue
- }
-
- public func decodeIfPresent(_ type: Decimal.Type, forKey key: Self.Key) throws -> Decimal? {
- guard let stringValue = try decodeIfPresent(String.self, forKey: key) else {
- return nil
- }
- guard let decimalValue = Decimal(string: stringValue) else {
- let context = DecodingError.Context(codingPath: [key], debugDescription: "The key \(key) couldn't be converted to a Decimal value")
- throw DecodingError.typeMismatch(type, context)
- }
-
- return decimalValue
- }
-
-}
From 3d1ff034817e980a010074dad95942f2c951f3c2 Mon Sep 17 00:00:00 2001
From: Alexey Alter-Pesotskiy
Date: Fri, 9 Aug 2024 13:46:19 +0100
Subject: [PATCH 15/38] [CI] Rename bot on CI
---
.github/workflows/cron-checks.yml | 2 +-
.github/workflows/release-merge.yml | 2 +-
.github/workflows/release-publish.yml | 2 +-
.github/workflows/release-start.yml | 2 +-
.github/workflows/sdk-size-metrics.yml | 2 +-
.github/workflows/smoke-checks.yml | 2 +-
.github/workflows/testflight.yml | 2 +-
fastlane/Fastfile | 2 +-
8 files changed, 8 insertions(+), 8 deletions(-)
diff --git a/.github/workflows/cron-checks.yml b/.github/workflows/cron-checks.yml
index d986e5ec5..e409b46fe 100644
--- a/.github/workflows/cron-checks.yml
+++ b/.github/workflows/cron-checks.yml
@@ -212,7 +212,7 @@ jobs:
env:
XCODE_VERSION: "15.0.1"
steps:
- - name: Connect iOS Bot
+ - name: Connect Bot
uses: webfactory/ssh-agent@v0.7.0
with:
ssh-private-key: ${{ secrets.BOT_SSH_PRIVATE_KEY }}
diff --git a/.github/workflows/release-merge.yml b/.github/workflows/release-merge.yml
index 05785d093..a100effec 100644
--- a/.github/workflows/release-merge.yml
+++ b/.github/workflows/release-merge.yml
@@ -12,7 +12,7 @@ jobs:
runs-on: macos-14
if: github.event_name == 'workflow_dispatch' || (github.event.issue.pull_request && github.event.issue.state == 'open' && github.event.comment.body == '/merge release')
steps:
- - name: Connect iOS Bot
+ - name: Connect Bot
uses: webfactory/ssh-agent@v0.7.0
with:
ssh-private-key: ${{ secrets.BOT_SSH_PRIVATE_KEY }}
diff --git a/.github/workflows/release-publish.yml b/.github/workflows/release-publish.yml
index 80113e243..712c0fca7 100644
--- a/.github/workflows/release-publish.yml
+++ b/.github/workflows/release-publish.yml
@@ -13,7 +13,7 @@ jobs:
runs-on: macos-13
if: github.event.pull_request.merged == true # only merged pull requests must trigger this job
steps:
- - name: Connect iOS Bot
+ - name: Connect Bot
uses: webfactory/ssh-agent@v0.7.0
with:
ssh-private-key: ${{ secrets.BOT_SSH_PRIVATE_KEY }}
diff --git a/.github/workflows/release-start.yml b/.github/workflows/release-start.yml
index a03592c30..6900e055c 100644
--- a/.github/workflows/release-start.yml
+++ b/.github/workflows/release-start.yml
@@ -13,7 +13,7 @@ jobs:
name: Start new release
runs-on: macos-14
steps:
- - name: Connect iOS Bot
+ - name: Connect Bot
uses: webfactory/ssh-agent@v0.7.0
with:
ssh-private-key: ${{ secrets.BOT_SSH_PRIVATE_KEY }}
diff --git a/.github/workflows/sdk-size-metrics.yml b/.github/workflows/sdk-size-metrics.yml
index 16e1d1e1c..b2245193b 100644
--- a/.github/workflows/sdk-size-metrics.yml
+++ b/.github/workflows/sdk-size-metrics.yml
@@ -19,7 +19,7 @@ jobs:
env:
GITHUB_TOKEN: '${{ secrets.CI_BOT_GITHUB_TOKEN }}'
steps:
- - name: Connect iOS Bot
+ - name: Connect Bot
uses: webfactory/ssh-agent@v0.7.0
with:
ssh-private-key: ${{ secrets.BOT_SSH_PRIVATE_KEY }}
diff --git a/.github/workflows/smoke-checks.yml b/.github/workflows/smoke-checks.yml
index 3dd502d91..af34b7bb1 100644
--- a/.github/workflows/smoke-checks.yml
+++ b/.github/workflows/smoke-checks.yml
@@ -179,7 +179,7 @@ jobs:
env:
XCODE_VERSION: "15.0.1"
steps:
- - name: Connect iOS Bot
+ - name: Connect Bot
uses: webfactory/ssh-agent@v0.7.0
with:
ssh-private-key: ${{ secrets.BOT_SSH_PRIVATE_KEY }}
diff --git a/.github/workflows/testflight.yml b/.github/workflows/testflight.yml
index 7b4572c1a..951a73a97 100644
--- a/.github/workflows/testflight.yml
+++ b/.github/workflows/testflight.yml
@@ -31,7 +31,7 @@ jobs:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
GITHUB_PR_NUM: ${{ github.event.number }}
steps:
- - name: Connect iOS Bot
+ - name: Connect Bot
uses: webfactory/ssh-agent@v0.7.0
with:
ssh-private-key: ${{ secrets.BOT_SSH_PRIVATE_KEY }}
diff --git a/fastlane/Fastfile b/fastlane/Fastfile
index 6175d8bbe..2acbe985a 100644
--- a/fastlane/Fastfile
+++ b/fastlane/Fastfile
@@ -901,7 +901,7 @@ end
private_lane :create_pr_comment do |options|
if is_ci && !options[:pr_num].to_s.empty?
- last_comment = sh("gh pr view #{options[:pr_num]} --json comments --jq '.comments | map(select(.author.login == \"Stream-iOS-Bot\")) | last'")
+ last_comment = sh("gh pr view #{options[:pr_num]} --json comments --jq '.comments | map(select(.author.login == \"Stream-SDK-Bot\")) | last'")
edit_last_comment = options[:edit_last_comment_with_text] && last_comment.include?(options[:edit_last_comment_with_text]) ? '--edit-last' : ''
sh("gh pr comment #{options[:pr_num]} #{edit_last_comment} -b '#{options[:text]}'")
end
From 4ca2bdad425fcd287fd359dfedb4be21cb221751 Mon Sep 17 00:00:00 2001
From: Alexey Alter-Pesotskiy
Date: Mon, 12 Aug 2024 11:13:15 +0100
Subject: [PATCH 16/38] [CI] Rename metrics repo
---
fastlane/Fastfile | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/fastlane/Fastfile b/fastlane/Fastfile
index 2acbe985a..441bb5747 100644
--- a/fastlane/Fastfile
+++ b/fastlane/Fastfile
@@ -16,7 +16,7 @@ video_buddy_port = 5678
app_secret = ENV.fetch('STREAM_VIDEO_SECRET', nil)
derived_data_path = 'derived_data'
source_packages_path = 'spm_cache'
-metrics_git = 'git@github.com:GetStream/apple-internal-metrics.git'
+metrics_git = 'git@github.com:GetStream/stream-internal-metrics.git'
sdk_size_path = "metrics/#{github_repo.split('/').last}-size.json"
buildcache_xcargs = 'CC=clang CPLUSPLUS=clang++ LD=clang LDPLUSPLUS=clang++'
gci = ENV['GOOGLE_CLIENT_ID'] || ''
From ee1f20964671785bcd04a9bf034c9fe060c220bc Mon Sep 17 00:00:00 2001
From: Alexey Alter-Pesotskiy
Date: Wed, 14 Aug 2024 09:09:10 +0100
Subject: [PATCH 17/38] [CI] Share fastlane lanes across platforms (#487)
---
.github/workflows/cron-checks.yml | 5 +-
.gitignore | 2 +-
Gemfile.lock | 4 +-
fastlane/Fastfile | 165 ++++--------------------------
fastlane/Pluginfile | 2 +-
5 files changed, 26 insertions(+), 152 deletions(-)
diff --git a/.github/workflows/cron-checks.yml b/.github/workflows/cron-checks.yml
index e409b46fe..3fd9ceb10 100644
--- a/.github/workflows/cron-checks.yml
+++ b/.github/workflows/cron-checks.yml
@@ -2,8 +2,9 @@ name: Cron Checks
on:
schedule:
- # Runs "At 01:00 every night"
- - cron: '0 1 * * *'
+ # Runs "At 01:00 every night except weekends"
+ - cron: '0 1 * * 1-5'
+
workflow_dispatch:
concurrency:
diff --git a/.gitignore b/.gitignore
index dbc271087..60500fe5e 100644
--- a/.gitignore
+++ b/.gitignore
@@ -75,7 +75,7 @@ fastlane/screenshots
fastlane/test_output
fastlane/allurectl
fastlane/xcresults
-fastlane/metrics
+**/metrics/
recordings
*.coverage.txt
vendor/bundle/
diff --git a/Gemfile.lock b/Gemfile.lock
index 0ec3d13ab..7e5cacab2 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -202,7 +202,7 @@ GEM
bundler
fastlane
pry
- fastlane-plugin-stream_actions (0.3.38)
+ fastlane-plugin-stream_actions (0.3.57)
xctest_list (= 1.2.1)
fastlane-plugin-versioning (0.5.2)
ffi (1.17.0)
@@ -430,7 +430,7 @@ DEPENDENCIES
fastlane
fastlane-plugin-create_xcframework
fastlane-plugin-lizard
- fastlane-plugin-stream_actions (= 0.3.38)
+ fastlane-plugin-stream_actions (= 0.3.57)
fastlane-plugin-versioning
jazzy
json
diff --git a/fastlane/Fastfile b/fastlane/Fastfile
index 441bb5747..8bf29877c 100644
--- a/fastlane/Fastfile
+++ b/fastlane/Fastfile
@@ -16,8 +16,6 @@ video_buddy_port = 5678
app_secret = ENV.fetch('STREAM_VIDEO_SECRET', nil)
derived_data_path = 'derived_data'
source_packages_path = 'spm_cache'
-metrics_git = 'git@github.com:GetStream/stream-internal-metrics.git'
-sdk_size_path = "metrics/#{github_repo.split('/').last}-size.json"
buildcache_xcargs = 'CC=clang CPLUSPLUS=clang++ LD=clang LDPLUSPLUS=clang++'
gci = ENV['GOOGLE_CLIENT_ID'] || ''
reversed_gci = gci.split('.').reverse.join('.')
@@ -26,15 +24,10 @@ is_localhost = !is_ci
swiftformat_excluded_paths = ["**/Generated", "**/generated", "**/protobuf", "**/OpenApi"]
swiftformat_source_paths = ["Sources", "DemoApp", "DemoAppUIKit", "StreamVideoTests", "StreamVideoSwiftUITests", "StreamVideoUIKitTests"]
-warning_status = '🟡' # Warning if a branch is #{max_tolerance} less performant than the benchmark
-fail_status = '🔴' # Failure if a branch is more than #{max_tolerance} less performant than the benchmark
-success_status = '🟢' # Success if a branch is more performant or equals to the benchmark
-outstanding_status = '🚀' # Outstanding performance
-
before_all do |lane|
if is_ci
setup_ci
- sh('git config --global user.name "Stream Bot"')
+ setup_git_config
xcversion(version: xcode_version) unless [:publish_release, :allure_launch, :allure_upload, :pod_lint, :stop_e2e_helpers].include?(lane)
elsif lane == :test_e2e
stop_e2e_helpers
@@ -292,7 +285,7 @@ private_lane :test_ui do |options|
png_files.each { |png| sh("git add #{png}") || true }
sh('git restore .')
- create_pr(
+ pr_create(
title: '[CI] Snapshots',
base_branch: current_branch,
head_branch: "#{current_branch}-snapshots"
@@ -518,7 +511,7 @@ lane :merge_release_to_main do |options|
comment = "[Publication of the release](https://github.com/#{github_repo}/actions/workflows/release-publish.yml) has been launched 👍"
UI.important(comment)
- create_pr_comment(pr_num: ENV.fetch('GITHUB_PR_NUM'), text: comment)
+ pr_comment(text: comment)
end
lane :merge_main_to_develop do
@@ -713,21 +706,7 @@ lane :run_swift_format do |options|
end
lane :install_runtime do |options|
- runtimes = `xcrun simctl runtime list -j`
- UI.message("👉 Runtime list:\n#{runtimes}")
- simulators = JSON.parse(runtimes).select do |_, sim|
- sim['platformIdentifier'].end_with?('iphonesimulator') && sim['version'] == options[:ios] && sim['state'] == 'Ready'
- end
-
- if simulators.empty?
- Dir.chdir('..') do
- sh("echo 'iOS #{options[:ios]} Simulator' | ipsw download xcode --sim") if Dir['*.dmg'].first.nil?
- sh("./Scripts/install_ios_runtime.sh #{Dir['*.dmg'].first}")
- UI.success("iOS #{options[:ios]} Runtime successfuly installed")
- end
- else
- UI.important("iOS #{options[:ios]} Runtime already exists")
- end
+ install_ios_runtime(version: options[:ios], custom_script: 'Scripts/install_ios_runtime.sh')
end
desc 'Remove UI Snapshots'
@@ -760,96 +739,26 @@ lane :copyright do
update_copyright(ignore: [derived_data_path, source_packages_path, 'vendor/'])
next unless is_ci
- create_pr(
+ pr_create(
title: '[CI] Update Copyright',
head_branch: "ci/update-copyright-#{Time.now.to_i}"
)
end
-desc 'Show current frameworks size'
lane :show_frameworks_sizes do |options|
next unless is_check_required(sources: sources_matrix[:size], force_check: @force_check)
- ['metrics/'].each { |dir| FileUtils.remove_dir(dir, force: true) }
-
- sh("git clone #{metrics_git} #{File.dirname(sdk_size_path)}")
- is_release = current_branch.include?('release/')
- benchmark_config = JSON.parse(File.read(sdk_size_path))
- benchmark_key = is_release ? 'release' : 'develop'
- benchmark_sizes = benchmark_config[benchmark_key]
- branch_sizes = options[:sizes] || frameworks_sizes
-
- table_header = '## SDK Size'
- markdown_table = "#{table_header}\n| `title` | `#{is_release ? 'previous release' : 'develop'}` | `#{is_release ? 'current release' : 'branch'}` | `diff` | `status` |\n| - | - | - | - | - |\n"
- sdk_names.each do |title|
- benchmark_value = benchmark_sizes[title]
- branch_value = branch_sizes[title.to_sym]
- max_tolerance = 0.5 # Max Tolerance is 0.5MB
- fine_tolerance = 0.25 # Fine Tolerance is 0.25MB
-
- diff = (branch_value - benchmark_value).round(2)
-
- status_emoji =
- if diff < 0
- outstanding_status
- elsif diff >= max_tolerance
- fail_status
- elsif diff >= fine_tolerance
- warning_status
- else
- success_status
- end
-
- markdown_table << "|#{title}|#{benchmark_value}MB|#{branch_value}MB|#{diff}MB|#{status_emoji}|\n"
- end
-
- FastlaneCore::PrintTable.print_values(title: 'Benchmark', config: benchmark_sizes)
- FastlaneCore::PrintTable.print_values(title: 'SDK Size', config: branch_sizes)
-
- if is_ci
- if is_release || ENV['GITHUB_EVENT_NAME'].to_s == 'push'
- benchmark_config[benchmark_key] = branch_sizes
- File.write(sdk_size_path, JSON.pretty_generate(benchmark_config))
- Dir.chdir(File.dirname(sdk_size_path)) do
- if sh('git status -s', log: false).to_s.empty?
- UI.important('No changes in SDK sizes benchmarks.')
- else
- sh('git add -A')
- sh("git commit -m 'Update #{sdk_size_path}'")
- sh('git push')
- end
- end
- end
-
- create_pr_comment(pr_num: ENV.fetch('GITHUB_PR_NUM'), text: markdown_table, edit_last_comment_with_text: table_header)
- end
-
- UI.user_error!("#{table_header} benchmark failed.") if markdown_table.include?(fail_status)
+ sizes = options[:sizes] || frameworks_sizes
+ show_sdk_size(branch_sizes: sizes, github_repo: github_repo)
+ update_img_shields_sdk_sizes(sizes: sizes, open_pr: options[:open_pr]) if options[:update_readme]
end
-desc 'Update img shields SDK size labels'
lane :update_img_shields_sdk_sizes do
- sizes = frameworks_sizes
-
- # Read the file into a string
- readme_path = '../README.md'
- readme_content = File.read(readme_path)
-
- # Define the new value for the badge
- stream_video_size = "#{sizes[:StreamVideo]}MB"
- stream_video_swiftui_size = "#{sizes[:StreamVideoSwiftUI]}MB"
- stream_video_uikit_size = "#{sizes[:StreamVideoUIKit]}MB"
-
- # Replace the value in the badge URL
- readme_content.gsub!(%r{(https://img.shields.io/badge/StreamVideo-)(.*?)(-blue)}, "\\1#{stream_video_size}\\3")
- readme_content.gsub!(%r{(https://img.shields.io/badge/StreamVideoSwiftUI-)(.*?)(-blue)}, "\\1#{stream_video_swiftui_size}\\3")
- readme_content.gsub!(%r{(https://img.shields.io/badge/StreamVideoUIKit-)(.*?)(-blue)}, "\\1#{stream_video_uikit_size}\\3")
-
- # Write the updated content back to the file
- File.write(readme_path, readme_content)
-
- # Notify success
- UI.success('Successfully updated the SDK size labels in README.md!')
+ update_sdk_size_in_readme(
+ open_pr: options[:open_pr] || false,
+ readme_path: 'README.md',
+ sizes: options[:sizes] || frameworks_sizes
+ )
end
def frameworks_sizes
@@ -869,51 +778,15 @@ def frameworks_sizes
frameworks_path = "../#{archive_dir}/Products/Applications/DemoAppUIKit.app/Frameworks"
stream_video_size = File.size("#{frameworks_path}/StreamVideo.framework/StreamVideo")
- stream_video_size_mb = (stream_video_size.to_f / 1024 / 1024).round(2)
+ stream_video_size_kb = stream_video_size.to_f / 1024
stream_video_swiftui_size = File.size("#{frameworks_path}/StreamVideoSwiftUI.framework/StreamVideoSwiftUI")
- stream_video_swiftui_size_mb = (stream_video_swiftui_size.to_f / 1024 / 1024).round(2)
+ stream_video_swiftui_size_kb = stream_video_swiftui_size.to_f / 1024
stream_video_uikit_size = File.size("#{frameworks_path}/StreamVideoUIKit.framework/StreamVideoUIKit")
- stream_video_uikit_size_mb = ((stream_video_uikit_size + stream_video_swiftui_size).to_f / 1024 / 1024).round(2)
+ stream_video_uikit_size_kb = (stream_video_uikit_size + stream_video_swiftui_size).to_f / 1024
{
- StreamVideo: stream_video_size_mb,
- StreamVideoSwiftUI: stream_video_swiftui_size_mb,
- StreamVideoUIKit: stream_video_uikit_size_mb
+ StreamVideo: stream_video_size_kb,
+ StreamVideoSwiftUI: stream_video_swiftui_size_kb,
+ StreamVideoUIKit: stream_video_uikit_size_kb
}
end
-
-private_lane :create_pr do |options|
- options[:base_branch] ||= 'develop'
- sh("git checkout -b #{options[:head_branch]}")
- sh('git add -A')
- sh("git commit -m '#{options[:title]}'")
- push_to_git_remote(tags: false)
-
- create_pull_request(
- api_token: ENV.fetch('GITHUB_TOKEN', nil),
- repo: github_repo,
- title: options[:title],
- head: options[:head_branch],
- base: options[:base_branch],
- body: 'This PR was created automatically by CI.'
- )
-end
-
-private_lane :create_pr_comment do |options|
- if is_ci && !options[:pr_num].to_s.empty?
- last_comment = sh("gh pr view #{options[:pr_num]} --json comments --jq '.comments | map(select(.author.login == \"Stream-SDK-Bot\")) | last'")
- edit_last_comment = options[:edit_last_comment_with_text] && last_comment.include?(options[:edit_last_comment_with_text]) ? '--edit-last' : ''
- sh("gh pr comment #{options[:pr_num]} #{edit_last_comment} -b '#{options[:text]}'")
- end
-end
-
-lane :current_branch do
- branch = if ENV['GITHUB_PR_NUM'].to_s.empty?
- git_branch
- else
- sh("gh pr view #{ENV.fetch('GITHUB_PR_NUM')} --json headRefName -q .headRefName").strip
- end
-
- UI.important("Current branch: #{branch} 🕊️")
- branch
-end
diff --git a/fastlane/Pluginfile b/fastlane/Pluginfile
index 0b9f84e1a..a2e380539 100644
--- a/fastlane/Pluginfile
+++ b/fastlane/Pluginfile
@@ -1,3 +1,3 @@
gem 'fastlane-plugin-versioning'
-gem 'fastlane-plugin-stream_actions', '0.3.38'
+gem 'fastlane-plugin-stream_actions', '0.3.57'
gem 'fastlane-plugin-create_xcframework'
From e65f5e8119a3b8739f00758cd176880b2584ac65 Mon Sep 17 00:00:00 2001
From: Alexey Alter-Pesotskiy
Date: Wed, 14 Aug 2024 10:08:49 +0100
Subject: [PATCH 18/38] [CI] Measure the size of StreamWebRTC (#485)
---
README.md | 1 +
fastlane/Fastfile | 5 ++++-
2 files changed, 5 insertions(+), 1 deletion(-)
diff --git a/README.md b/README.md
index 67e34053b..fc74182b0 100644
--- a/README.md
+++ b/README.md
@@ -12,6 +12,7 @@
+
![Stream Video for iOS Header image](https://github.com/GetStream/stream-video-swift/assets/12433593/e4a44ae5-a8eb-4ac7-8910-28187aa011f6)
diff --git a/fastlane/Fastfile b/fastlane/Fastfile
index 8bf29877c..38d0d9f58 100644
--- a/fastlane/Fastfile
+++ b/fastlane/Fastfile
@@ -783,10 +783,13 @@ def frameworks_sizes
stream_video_swiftui_size_kb = stream_video_swiftui_size.to_f / 1024
stream_video_uikit_size = File.size("#{frameworks_path}/StreamVideoUIKit.framework/StreamVideoUIKit")
stream_video_uikit_size_kb = (stream_video_uikit_size + stream_video_swiftui_size).to_f / 1024
+ stream_web_rtc_size = File.size("#{frameworks_path}/StreamWebRTC.framework/StreamWebRTC")
+ stream_web_rtc_size_kb = stream_web_rtc_size.to_f / 1024
{
StreamVideo: stream_video_size_kb,
StreamVideoSwiftUI: stream_video_swiftui_size_kb,
- StreamVideoUIKit: stream_video_uikit_size_kb
+ StreamVideoUIKit: stream_video_uikit_size_kb,
+ StreamWebRTC: stream_web_rtc_size_kb
}
end
From babef4d5edb0da94795df0c398225ff8a1f54f1a Mon Sep 17 00:00:00 2001
From: Alexey Alter-Pesotskiy
Date: Wed, 14 Aug 2024 10:13:21 +0100
Subject: [PATCH 19/38] [CI] Add space to SDK size badge
---
Gemfile.lock | 4 ++--
README.md | 8 ++++----
fastlane/Fastfile | 16 ++++++++--------
fastlane/Pluginfile | 2 +-
4 files changed, 15 insertions(+), 15 deletions(-)
diff --git a/Gemfile.lock b/Gemfile.lock
index 7e5cacab2..b819143ba 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -202,7 +202,7 @@ GEM
bundler
fastlane
pry
- fastlane-plugin-stream_actions (0.3.57)
+ fastlane-plugin-stream_actions (0.3.59)
xctest_list (= 1.2.1)
fastlane-plugin-versioning (0.5.2)
ffi (1.17.0)
@@ -430,7 +430,7 @@ DEPENDENCIES
fastlane
fastlane-plugin-create_xcframework
fastlane-plugin-lizard
- fastlane-plugin-stream_actions (= 0.3.57)
+ fastlane-plugin-stream_actions (= 0.3.59)
fastlane-plugin-versioning
jazzy
json
diff --git a/README.md b/README.md
index fc74182b0..0fb82306e 100644
--- a/README.md
+++ b/README.md
@@ -9,10 +9,10 @@
-
-
-
-
+
+
+
+
![Stream Video for iOS Header image](https://github.com/GetStream/stream-video-swift/assets/12433593/e4a44ae5-a8eb-4ac7-8910-28187aa011f6)
diff --git a/fastlane/Fastfile b/fastlane/Fastfile
index 38d0d9f58..d0e9646a2 100644
--- a/fastlane/Fastfile
+++ b/fastlane/Fastfile
@@ -778,18 +778,18 @@ def frameworks_sizes
frameworks_path = "../#{archive_dir}/Products/Applications/DemoAppUIKit.app/Frameworks"
stream_video_size = File.size("#{frameworks_path}/StreamVideo.framework/StreamVideo")
- stream_video_size_kb = stream_video_size.to_f / 1024
+ stream_video_size_kb = stream_video_size / 1024.0
stream_video_swiftui_size = File.size("#{frameworks_path}/StreamVideoSwiftUI.framework/StreamVideoSwiftUI")
- stream_video_swiftui_size_kb = stream_video_swiftui_size.to_f / 1024
+ stream_video_swiftui_size_kb = stream_video_swiftui_size / 1024.0
stream_video_uikit_size = File.size("#{frameworks_path}/StreamVideoUIKit.framework/StreamVideoUIKit")
- stream_video_uikit_size_kb = (stream_video_uikit_size + stream_video_swiftui_size).to_f / 1024
+ stream_video_uikit_size_kb = (stream_video_uikit_size + stream_video_swiftui_size) / 1024.0
stream_web_rtc_size = File.size("#{frameworks_path}/StreamWebRTC.framework/StreamWebRTC")
- stream_web_rtc_size_kb = stream_web_rtc_size.to_f / 1024
+ stream_web_rtc_size_kb = stream_web_rtc_size / 1024.0
{
- StreamVideo: stream_video_size_kb,
- StreamVideoSwiftUI: stream_video_swiftui_size_kb,
- StreamVideoUIKit: stream_video_uikit_size_kb,
- StreamWebRTC: stream_web_rtc_size_kb
+ StreamVideo: stream_video_size_kb.round(0),
+ StreamVideoSwiftUI: stream_video_swiftui_size_kb.round(0),
+ StreamVideoUIKit: stream_video_uikit_size_kb.round(0),
+ StreamWebRTC: stream_web_rtc_size_kb.round(0)
}
end
diff --git a/fastlane/Pluginfile b/fastlane/Pluginfile
index a2e380539..b2ef25af9 100644
--- a/fastlane/Pluginfile
+++ b/fastlane/Pluginfile
@@ -1,3 +1,3 @@
gem 'fastlane-plugin-versioning'
-gem 'fastlane-plugin-stream_actions', '0.3.57'
+gem 'fastlane-plugin-stream_actions', '0.3.59'
gem 'fastlane-plugin-create_xcframework'
From 3679c135c29ffae7ebf016ccb781e6f6bef2cf8f Mon Sep 17 00:00:00 2001
From: Martin Mitrevski
Date: Wed, 14 Aug 2024 14:39:31 +0200
Subject: [PATCH 20/38] Removed unused code (#486)
---
DemoApp/Sources/Models/CallKitState.swift | 11 -----
.../generated/JSONEncodingHelper.swift | 45 -------------------
.../OpenApi/generated/Models.swift | 38 ----------------
.../Models/BackstageSettingsResponse.swift | 33 --------------
.../WebSockets/Client/WebSocketClient.swift | 6 ---
.../Client/WebSocketConstants.swift | 11 -----
StreamVideo.xcodeproj/project.pbxproj | 18 --------
7 files changed, 162 deletions(-)
delete mode 100644 DemoApp/Sources/Models/CallKitState.swift
delete mode 100644 Sources/StreamVideo/OpenApi/generated/JSONEncodingHelper.swift
delete mode 100644 Sources/StreamVideo/OpenApi/generated/Models/BackstageSettingsResponse.swift
delete mode 100644 Sources/StreamVideo/WebSockets/Client/WebSocketConstants.swift
diff --git a/DemoApp/Sources/Models/CallKitState.swift b/DemoApp/Sources/Models/CallKitState.swift
deleted file mode 100644
index 5e5f0a140..000000000
--- a/DemoApp/Sources/Models/CallKitState.swift
+++ /dev/null
@@ -1,11 +0,0 @@
-//
-// Copyright © 2024 Stream.io Inc. All rights reserved.
-//
-
-import Foundation
-
-enum CallKitState {
- case idle
- case joining
- case inCall
-}
diff --git a/Sources/StreamVideo/OpenApi/generated/JSONEncodingHelper.swift b/Sources/StreamVideo/OpenApi/generated/JSONEncodingHelper.swift
deleted file mode 100644
index 02f78ffb4..000000000
--- a/Sources/StreamVideo/OpenApi/generated/JSONEncodingHelper.swift
+++ /dev/null
@@ -1,45 +0,0 @@
-//
-// JSONEncodingHelper.swift
-//
-// Generated by openapi-generator
-// https://openapi-generator.tech
-//
-
-import Foundation
-
-open class JSONEncodingHelper {
-
- open class func encodingParameters(forEncodableObject encodableObj: T?) -> [String: Any]? {
- var params: [String: Any]?
-
- // Encode the Encodable object
- if let encodableObj = encodableObj {
- let encodeResult = CodableHelper.encode(encodableObj)
- do {
- let data = try encodeResult.get()
- params = JSONDataEncoding.encodingParameters(jsonData: data)
- } catch {
- print(error.localizedDescription)
- }
- }
-
- return params
- }
-
- open class func encodingParameters(forEncodableObject encodableObj: Any?) -> [String: Any]? {
- var params: [String: Any]?
-
- if let encodableObj = encodableObj {
- do {
- let data = try JSONSerialization.data(withJSONObject: encodableObj, options: .prettyPrinted)
- params = JSONDataEncoding.encodingParameters(jsonData: data)
- } catch {
- print(error.localizedDescription)
- return nil
- }
- }
-
- return params
- }
-
-}
diff --git a/Sources/StreamVideo/OpenApi/generated/Models.swift b/Sources/StreamVideo/OpenApi/generated/Models.swift
index b49cf8d12..9092bd661 100644
--- a/Sources/StreamVideo/OpenApi/generated/Models.swift
+++ b/Sources/StreamVideo/OpenApi/generated/Models.swift
@@ -62,26 +62,6 @@ extension NullEncodable: Codable where Wrapped: Codable {
}
}
-public enum ErrorResponse: Error {
- case error(Int, Data?, URLResponse?, Error)
-}
-
-public enum DownloadException: Error {
- case responseDataMissing
- case responseFailed
- case requestMissing
- case requestMissingPath
- case requestMissingURL
-}
-
-public enum DecodableRequestBuilderError: Error {
- case emptyDataResponse
- case nilHTTPResponse
- case unsuccessfulHTTPStatusCode
- case jsonDecoding(DecodingError)
- case generalError(Error)
-}
-
open class Response {
public let statusCode: Int
public let header: [String: String]
@@ -106,21 +86,3 @@ open class Response {
self.init(statusCode: response.statusCode, header: header, body: body, bodyData: bodyData)
}
}
-
-public final class RequestTask: @unchecked Sendable {
- private var lock = NSRecursiveLock()
- private var task: URLSessionTask?
-
- internal func set(task: URLSessionTask) {
- lock.lock()
- defer { lock.unlock() }
- self.task = task
- }
-
- public func cancel() {
- lock.lock()
- defer { lock.unlock() }
- task?.cancel()
- task = nil
- }
-}
diff --git a/Sources/StreamVideo/OpenApi/generated/Models/BackstageSettingsResponse.swift b/Sources/StreamVideo/OpenApi/generated/Models/BackstageSettingsResponse.swift
deleted file mode 100644
index 2cd2bb307..000000000
--- a/Sources/StreamVideo/OpenApi/generated/Models/BackstageSettingsResponse.swift
+++ /dev/null
@@ -1,33 +0,0 @@
-//
-// BackstageSettingsResponse.swift
-//
-// Generated by openapi-generator
-// https://openapi-generator.tech
-//
-
-import Foundation
-
-
-public struct BackstageSettingsResponse: Codable, JSONEncodable, Hashable {
- public var enabled: Bool
- public var joinAheadTimeSeconds: Int?
-
- public init(enabled: Bool, joinAheadTimeSeconds: Int? = nil) {
- self.enabled = enabled
- self.joinAheadTimeSeconds = joinAheadTimeSeconds
- }
-
- public enum CodingKeys: String, CodingKey, CaseIterable {
- case enabled
- case joinAheadTimeSeconds = "join_ahead_time_seconds"
- }
-
- // Encodable protocol methods
-
- public func encode(to encoder: Encoder) throws {
- var container = encoder.container(keyedBy: CodingKeys.self)
- try container.encode(enabled, forKey: .enabled)
- try container.encodeIfPresent(joinAheadTimeSeconds, forKey: .joinAheadTimeSeconds)
- }
-}
-
diff --git a/Sources/StreamVideo/WebSockets/Client/WebSocketClient.swift b/Sources/StreamVideo/WebSockets/Client/WebSocketClient.swift
index 5a88e2c3e..06e022620 100644
--- a/Sources/StreamVideo/WebSockets/Client/WebSocketClient.swift
+++ b/Sources/StreamVideo/WebSockets/Client/WebSocketClient.swift
@@ -317,11 +317,5 @@ extension ClientError {
public class WebSocket: ClientError {}
}
-/// WebSocket Error
-struct WebSocketErrorContainer: Decodable {
- /// A server error was received.
- let error: ErrorPayload
-}
-
struct WSDisconnected: Event {}
struct WSConnected: Event {}
diff --git a/Sources/StreamVideo/WebSockets/Client/WebSocketConstants.swift b/Sources/StreamVideo/WebSockets/Client/WebSocketConstants.swift
deleted file mode 100644
index ed560941d..000000000
--- a/Sources/StreamVideo/WebSockets/Client/WebSocketConstants.swift
+++ /dev/null
@@ -1,11 +0,0 @@
-//
-// Copyright © 2024 Stream.io Inc. All rights reserved.
-//
-
-import Foundation
-
-enum WebSocketConstants {
- static let callId = "callId"
- static let callType = "callType"
- static let sessionId = "sessionId"
-}
diff --git a/StreamVideo.xcodeproj/project.pbxproj b/StreamVideo.xcodeproj/project.pbxproj
index 514aa82b7..5335505ee 100644
--- a/StreamVideo.xcodeproj/project.pbxproj
+++ b/StreamVideo.xcodeproj/project.pbxproj
@@ -156,7 +156,6 @@
4069A0052AD985D3009A3A06 /* CallParticipant_Mock.swift in Sources */ = {isa = PBXBuildFile; fileRef = 406303412AD848000091AE77 /* CallParticipant_Mock.swift */; };
406A8E8D2AA1D78C001F598A /* AppEnvironment.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4030E59F2A9DF5BD003E8CBA /* AppEnvironment.swift */; };
406A8E8E2AA1D79D001F598A /* UserState.swift in Sources */ = {isa = PBXBuildFile; fileRef = 40F445AD2A9DFC34004BE3DA /* UserState.swift */; };
- 406A8E922AA1D7B3001F598A /* CallKitState.swift in Sources */ = {isa = PBXBuildFile; fileRef = 40F445AF2A9DFC58004BE3DA /* CallKitState.swift */; };
406A8E932AA1D7BF001F598A /* LoginViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8456E6C3287EB43A004E180E /* LoginViewModel.swift */; };
406A8E942AA1D7C5001F598A /* UserCredentials.swift in Sources */ = {isa = PBXBuildFile; fileRef = 40F445AB2A9DFC13004BE3DA /* UserCredentials.swift */; };
406A8E952AA1D7CB001F598A /* AddUserView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84201792288AB699004964B3 /* AddUserView.swift */; };
@@ -358,7 +357,6 @@
40F18B8E2BEBB65100ADF76E /* View+OptionalPublisher.swift in Sources */ = {isa = PBXBuildFile; fileRef = 40F18B8D2BEBB65100ADF76E /* View+OptionalPublisher.swift */; };
40F445AC2A9DFC13004BE3DA /* UserCredentials.swift in Sources */ = {isa = PBXBuildFile; fileRef = 40F445AB2A9DFC13004BE3DA /* UserCredentials.swift */; };
40F445AE2A9DFC34004BE3DA /* UserState.swift in Sources */ = {isa = PBXBuildFile; fileRef = 40F445AD2A9DFC34004BE3DA /* UserState.swift */; };
- 40F445B02A9DFC58004BE3DA /* CallKitState.swift in Sources */ = {isa = PBXBuildFile; fileRef = 40F445AF2A9DFC58004BE3DA /* CallKitState.swift */; };
40F445B22A9DFFBB004BE3DA /* User+Demo.swift in Sources */ = {isa = PBXBuildFile; fileRef = 40F445B12A9DFFBB004BE3DA /* User+Demo.swift */; };
40F445B42A9E01B2004BE3DA /* AuthenticationProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 40F445B32A9E01B2004BE3DA /* AuthenticationProvider.swift */; };
40F445BE2A9E0823004BE3DA /* RobotVoiceFilter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 40F445BD2A9E0823004BE3DA /* RobotVoiceFilter.swift */; };
@@ -674,7 +672,6 @@
8442993A29422BEA0037232A /* BackportStateObject.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8442993929422BEA0037232A /* BackportStateObject.swift */; };
8442993C294232360037232A /* IncomingCallView_iOS13.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8442993B294232360037232A /* IncomingCallView_iOS13.swift */; };
844299412942394C0037232A /* VideoView_iOS13.swift in Sources */ = {isa = PBXBuildFile; fileRef = 844299402942394C0037232A /* VideoView_iOS13.swift */; };
- 844542F02C296AAB001D5ADF /* BackstageSettingsResponse.swift in Sources */ = {isa = PBXBuildFile; fileRef = 844542EF2C296AAA001D5ADF /* BackstageSettingsResponse.swift */; };
8446AF912A4D84F4002AB07B /* Retries_Tests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8446AF902A4D84F4002AB07B /* Retries_Tests.swift */; };
844ADA652AD3F1AB00769F6A /* GoogleSignInSwift in Frameworks */ = {isa = PBXBuildFile; productRef = 844ADA642AD3F1AB00769F6A /* GoogleSignInSwift */; };
844ADA672AD3F21000769F6A /* GoogleSignIn.plist in Resources */ = {isa = PBXBuildFile; fileRef = 844ADA662AD3F21000769F6A /* GoogleSignIn.plist */; };
@@ -883,7 +880,6 @@
84D6E53A2B3AD10000D0056C /* RepeatingTimer_Tests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84D6E5392B3AD10000D0056C /* RepeatingTimer_Tests.swift */; };
84DC382D29A8B9EC00946713 /* CallParticipantMenuAction.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84DC382C29A8B9EC00946713 /* CallParticipantMenuAction.swift */; };
84DC382F29A8BB8D00946713 /* CallParticipantsInfoViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84DC382E29A8BB8D00946713 /* CallParticipantsInfoViewModel.swift */; };
- 84DC388E29ADFCFD00946713 /* JSONEncodingHelper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84DC383C29ADFCFB00946713 /* JSONEncodingHelper.swift */; };
84DC388F29ADFCFD00946713 /* CodableHelper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84DC383D29ADFCFB00946713 /* CodableHelper.swift */; };
84DC389029ADFCFD00946713 /* SendEventResponse.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84DC383F29ADFCFC00946713 /* SendEventResponse.swift */; };
84DC389129ADFCFD00946713 /* VideoSettings.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84DC384029ADFCFC00946713 /* VideoSettings.swift */; };
@@ -976,7 +972,6 @@
84EA5D4328C1E944004D3531 /* AudioSession.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84EA5D4228C1E944004D3531 /* AudioSession.swift */; };
84EBA4A22A72B81100577297 /* BroadcastBufferConnection.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84EBA4A12A72B81100577297 /* BroadcastBufferConnection.swift */; };
84ED240D286C9515002A3186 /* DemoCallContainerView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84ED240C286C9515002A3186 /* DemoCallContainerView.swift */; };
- 84F3B0DA289083E70088751D /* WebSocketConstants.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84F3B0D9289083E70088751D /* WebSocketConstants.swift */; };
84F3B0DE28913E0F0088751D /* CallControlsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84F3B0DD28913E0E0088751D /* CallControlsView.swift */; };
84F3B0E0289150B10088751D /* CallParticipant.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84F3B0DF289150B10088751D /* CallParticipant.swift */; };
84F3B0E228916FF20088751D /* CallParticipantsInfoView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84F3B0E128916FF20088751D /* CallParticipantsInfoView.swift */; };
@@ -1431,7 +1426,6 @@
40F18B8D2BEBB65100ADF76E /* View+OptionalPublisher.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "View+OptionalPublisher.swift"; sourceTree = ""; };
40F445AB2A9DFC13004BE3DA /* UserCredentials.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserCredentials.swift; sourceTree = ""; };
40F445AD2A9DFC34004BE3DA /* UserState.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserState.swift; sourceTree = ""; };
- 40F445AF2A9DFC58004BE3DA /* CallKitState.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CallKitState.swift; sourceTree = ""; };
40F445B12A9DFFBB004BE3DA /* User+Demo.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "User+Demo.swift"; sourceTree = ""; };
40F445B32A9E01B2004BE3DA /* AuthenticationProvider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AuthenticationProvider.swift; sourceTree = ""; };
40F445BD2A9E0823004BE3DA /* RobotVoiceFilter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RobotVoiceFilter.swift; sourceTree = ""; };
@@ -1696,7 +1690,6 @@
8442993929422BEA0037232A /* BackportStateObject.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BackportStateObject.swift; sourceTree = ""; };
8442993B294232360037232A /* IncomingCallView_iOS13.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IncomingCallView_iOS13.swift; sourceTree = ""; };
844299402942394C0037232A /* VideoView_iOS13.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VideoView_iOS13.swift; sourceTree = ""; };
- 844542EF2C296AAA001D5ADF /* BackstageSettingsResponse.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BackstageSettingsResponse.swift; sourceTree = ""; };
8446AF902A4D84F4002AB07B /* Retries_Tests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Retries_Tests.swift; sourceTree = ""; };
844ADA662AD3F21000769F6A /* GoogleSignIn.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = GoogleSignIn.plist; sourceTree = ""; };
844ADA682AD3F78F00769F6A /* GoogleHelper.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GoogleHelper.swift; sourceTree = ""; };
@@ -1906,7 +1899,6 @@
84D6E5392B3AD10000D0056C /* RepeatingTimer_Tests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RepeatingTimer_Tests.swift; sourceTree = ""; };
84DC382C29A8B9EC00946713 /* CallParticipantMenuAction.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CallParticipantMenuAction.swift; sourceTree = ""; };
84DC382E29A8BB8D00946713 /* CallParticipantsInfoViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CallParticipantsInfoViewModel.swift; sourceTree = ""; };
- 84DC383C29ADFCFB00946713 /* JSONEncodingHelper.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = JSONEncodingHelper.swift; sourceTree = ""; };
84DC383D29ADFCFB00946713 /* CodableHelper.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CodableHelper.swift; sourceTree = ""; };
84DC383F29ADFCFC00946713 /* SendEventResponse.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SendEventResponse.swift; sourceTree = ""; };
84DC384029ADFCFC00946713 /* VideoSettings.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = VideoSettings.swift; sourceTree = ""; };
@@ -1996,7 +1988,6 @@
84EBA4A12A72B81100577297 /* BroadcastBufferConnection.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BroadcastBufferConnection.swift; sourceTree = ""; };
84EBAA92288C137E00BE3176 /* Modifiers.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Modifiers.swift; sourceTree = ""; };
84ED240C286C9515002A3186 /* DemoCallContainerView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DemoCallContainerView.swift; sourceTree = ""; };
- 84F3B0D9289083E70088751D /* WebSocketConstants.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WebSocketConstants.swift; sourceTree = ""; };
84F3B0DD28913E0E0088751D /* CallControlsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CallControlsView.swift; sourceTree = ""; };
84F3B0DF289150B10088751D /* CallParticipant.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CallParticipant.swift; sourceTree = ""; };
84F3B0E128916FF20088751D /* CallParticipantsInfoView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CallParticipantsInfoView.swift; sourceTree = ""; };
@@ -2243,7 +2234,6 @@
401A64B02A9DF83200534ED1 /* TokenResponse.swift */,
40F445AB2A9DFC13004BE3DA /* UserCredentials.swift */,
40F445AD2A9DFC34004BE3DA /* UserState.swift */,
- 40F445AF2A9DFC58004BE3DA /* CallKitState.swift */,
40F445D32A9E2051004BE3DA /* Reaction.swift */,
);
path = Models;
@@ -3467,7 +3457,6 @@
84A7E1952883661A00526C98 /* BackgroundTaskScheduler.swift */,
84A7E1852883632100526C98 /* ConnectionStatus.swift */,
84A7E1A92883E4AD00526C98 /* APIKey.swift */,
- 84F3B0D9289083E70088751D /* WebSocketConstants.swift */,
);
path = Client;
sourceTree = "";
@@ -3944,7 +3933,6 @@
84DC383D29ADFCFB00946713 /* CodableHelper.swift */,
84DC388929ADFCFC00946713 /* Extensions.swift */,
84DC388A29ADFCFC00946713 /* JSONDataEncoding.swift */,
- 84DC383C29ADFCFB00946713 /* JSONEncodingHelper.swift */,
84DC388C29ADFCFC00946713 /* Models.swift */,
84DC388829ADFCFC00946713 /* OpenISO8601DateFormatter.swift */,
);
@@ -4070,7 +4058,6 @@
84DC383E29ADFCFC00946713 /* Models */ = {
isa = PBXGroup;
children = (
- 844542EF2C296AAA001D5ADF /* BackstageSettingsResponse.swift */,
845C09962C11AAA100F725B3 /* RejectCallRequest.swift */,
845C09822C0DEB5C00F725B3 /* LimitsSettingsRequest.swift */,
845C09832C0DEB5C00F725B3 /* LimitsSettingsResponse.swift */,
@@ -5086,7 +5073,6 @@
84093811288A90390089A35B /* DetailedCallingView.swift in Sources */,
84ED240D286C9515002A3186 /* DemoCallContainerView.swift in Sources */,
40F445B22A9DFFBB004BE3DA /* User+Demo.swift in Sources */,
- 40F445B02A9DFC58004BE3DA /* CallKitState.swift in Sources */,
40D946452AA5F67E00C8861B /* DemoCallingTopView.swift in Sources */,
847B47B72A260CF1000714CE /* CustomCallView.swift in Sources */,
40F445EA2A9E297B004BE3DA /* CallStateResponseFields+Identifiable.swift in Sources */,
@@ -5229,7 +5215,6 @@
407F29FF2AA6011500C3EAF8 /* MemoryLogViewer.swift in Sources */,
40AB35572B738C7100E465CC /* CallsViewModel.swift in Sources */,
408D29AE2B6D681000885473 /* SnapshotTrigger.swift in Sources */,
- 406A8E922AA1D7B3001F598A /* CallKitState.swift in Sources */,
406A8E8D2AA1D78C001F598A /* AppEnvironment.swift in Sources */,
40AB35442B738C4100E465CC /* DemoReactionButton.swift in Sources */,
849322612908385C0013C029 /* HomeViewController.swift in Sources */,
@@ -5270,7 +5255,6 @@
8409465B29AF4EEC007AF5BF /* ListRecordingsResponse.swift in Sources */,
8490DD21298D4ADF007E53D2 /* StreamJsonDecoder.swift in Sources */,
84C4004229E3F446007B69C2 /* ConnectedEvent.swift in Sources */,
- 844542F02C296AAB001D5ADF /* BackstageSettingsResponse.swift in Sources */,
84DC389C29ADFCFD00946713 /* GetOrCreateCallResponse.swift in Sources */,
4065839B2B877ADA00B4F979 /* CIImage+Sendable.swift in Sources */,
84DCA2242A3A0F0D000C3411 /* HTTPClient.swift in Sources */,
@@ -5292,7 +5276,6 @@
84DCA21F2A39DA15000C3411 /* APIHelper.swift in Sources */,
84DC38D329ADFCFD00946713 /* CallEndedEvent.swift in Sources */,
84A737D028F4716E001A6769 /* models.pb.swift in Sources */,
- 84DC388E29ADFCFD00946713 /* JSONEncodingHelper.swift in Sources */,
846D16222A52B8D00036CE4C /* MicrophoneManager.swift in Sources */,
842E70DB2B91BE1700D2D68B /* ListTranscriptionsResponse.swift in Sources */,
4012B1902BFCA4D3006B0031 /* StreamCallStateMachine+AcceptedStage.swift in Sources */,
@@ -5414,7 +5397,6 @@
4012B1942BFCAC1C006B0031 /* StreamCallStateMachine+RejectingStage.swift in Sources */,
84DCA2152A38A79E000C3411 /* Token.swift in Sources */,
40FB151B2BF77EEE00D5E580 /* StreamCallStateMachine+JoiningStage.swift in Sources */,
- 84F3B0DA289083E70088751D /* WebSocketConstants.swift in Sources */,
840F59902A77FDCB00EF3EB2 /* UnpinRequest.swift in Sources */,
8440861E2901A1700027849C /* SfuMiddleware.swift in Sources */,
40FB15172BF77EA600D5E580 /* StreamCallStateMachine.swift in Sources */,
From f2c3de3f3294fea981432efb9e9a92ee1b740a12 Mon Sep 17 00:00:00 2001
From: Alexey Alter-Pesotskiy
Date: Thu, 15 Aug 2024 16:48:07 +0100
Subject: [PATCH 21/38] Bump fastlane plugin version
---
Gemfile.lock | 4 ++--
fastlane/Pluginfile | 2 +-
2 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/Gemfile.lock b/Gemfile.lock
index b819143ba..d82a70999 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -202,7 +202,7 @@ GEM
bundler
fastlane
pry
- fastlane-plugin-stream_actions (0.3.59)
+ fastlane-plugin-stream_actions (0.3.60)
xctest_list (= 1.2.1)
fastlane-plugin-versioning (0.5.2)
ffi (1.17.0)
@@ -430,7 +430,7 @@ DEPENDENCIES
fastlane
fastlane-plugin-create_xcframework
fastlane-plugin-lizard
- fastlane-plugin-stream_actions (= 0.3.59)
+ fastlane-plugin-stream_actions (= 0.3.60)
fastlane-plugin-versioning
jazzy
json
diff --git a/fastlane/Pluginfile b/fastlane/Pluginfile
index b2ef25af9..f02744589 100644
--- a/fastlane/Pluginfile
+++ b/fastlane/Pluginfile
@@ -1,3 +1,3 @@
gem 'fastlane-plugin-versioning'
-gem 'fastlane-plugin-stream_actions', '0.3.59'
gem 'fastlane-plugin-create_xcframework'
+gem 'fastlane-plugin-stream_actions', '0.3.60'
From a5b78f071960d16398d778927c58b44882d3f683 Mon Sep 17 00:00:00 2001
From: Alexey Alter-Pesotskiy
Date: Fri, 16 Aug 2024 17:32:24 +0100
Subject: [PATCH 22/38] [CI] Update release-related fastlane lanes
---
.github/workflows/release-merge.yml | 2 +-
.github/workflows/release-publish.yml | 29 +++++++++++++----
Gemfile.lock | 4 +--
fastlane/Fastfile | 46 +++------------------------
fastlane/Pluginfile | 2 +-
5 files changed, 30 insertions(+), 53 deletions(-)
diff --git a/.github/workflows/release-merge.yml b/.github/workflows/release-merge.yml
index a100effec..c8c29253c 100644
--- a/.github/workflows/release-merge.yml
+++ b/.github/workflows/release-merge.yml
@@ -24,7 +24,7 @@ jobs:
- uses: ./.github/actions/ruby-cache
- name: Merge
- run: bundle exec fastlane merge_release_to_main author:"$USER_LOGIN" --verbose
+ run: bundle exec fastlane merge_release author:"$USER_LOGIN" --verbose
env:
GITHUB_TOKEN: ${{ secrets.ADMIN_API_TOKEN }} # A token with the "admin:org" scope to get the list of the team members on GitHub
GITHUB_PR_NUM: ${{ github.event.issue.number }}
diff --git a/.github/workflows/release-publish.yml b/.github/workflows/release-publish.yml
index 712c0fca7..e1b18635a 100644
--- a/.github/workflows/release-publish.yml
+++ b/.github/workflows/release-publish.yml
@@ -7,11 +7,18 @@ on:
types:
- closed
+ workflow_dispatch:
+ inputs:
+ version:
+ description: 'Release version'
+ type: string
+ required: true
+
jobs:
release:
name: Publish new release
runs-on: macos-13
- if: github.event.pull_request.merged == true # only merged pull requests must trigger this job
+ if: ${{ github.event_name == 'workflow_dispatch' || github.event.pull_request.merged == true }} # only merged pull requests must trigger this job
steps:
- name: Connect Bot
uses: webfactory/ssh-agent@v0.7.0
@@ -19,20 +26,28 @@ jobs:
ssh-private-key: ${{ secrets.BOT_SSH_PRIVATE_KEY }}
- uses: actions/checkout@v4.1.1
- with:
- fetch-depth: 0
+
+ - uses: ./.github/actions/ruby-cache
+
+ - name: Extract version from input (for workflow dispatch)
+ if: ${{ github.event_name == 'workflow_dispatch' }}
+ run: |
+ BRANCH_NAME=$(git rev-parse --abbrev-ref HEAD)
+ if [ "$BRANCH_NAME" != "main" ]; then
+ echo "This workflow can only be run on the main branch."
+ exit 1
+ fi
+ echo "RELEASE_VERSION=${{ github.event.inputs.version }}" >> $GITHUB_ENV
- name: Extract version from branch name (for release branches)
- if: startsWith(github.event.pull_request.head.ref, 'release/')
+ if: ${{ github.event_name == 'pull_request' && startsWith(github.event.pull_request.head.ref, 'release/') }}
run: |
BRANCH_NAME="${{ github.event.pull_request.head.ref }}"
VERSION=${BRANCH_NAME#release/}
echo "RELEASE_VERSION=$VERSION" >> $GITHUB_ENV
- - uses: ./.github/actions/ruby-cache
-
- name: "Fastlane - Publish Release"
- if: startsWith(github.event.pull_request.head.ref, 'release/')
+ if: ${{ github.event_name == 'workflow_dispatch' || startsWith(github.event.pull_request.head.ref, 'release/') }}
env:
GITHUB_TOKEN: ${{ secrets.CI_BOT_GITHUB_TOKEN }}
COCOAPODS_TRUNK_TOKEN: ${{ secrets.COCOAPODS_TRUNK_TOKEN }}
diff --git a/Gemfile.lock b/Gemfile.lock
index d82a70999..9cdb7e098 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -202,7 +202,7 @@ GEM
bundler
fastlane
pry
- fastlane-plugin-stream_actions (0.3.60)
+ fastlane-plugin-stream_actions (0.3.63)
xctest_list (= 1.2.1)
fastlane-plugin-versioning (0.5.2)
ffi (1.17.0)
@@ -430,7 +430,7 @@ DEPENDENCIES
fastlane
fastlane-plugin-create_xcframework
fastlane-plugin-lizard
- fastlane-plugin-stream_actions (= 0.3.60)
+ fastlane-plugin-stream_actions (= 0.3.63)
fastlane-plugin-versioning
jazzy
json
diff --git a/fastlane/Fastfile b/fastlane/Fastfile
index d0e9646a2..6af6c1841 100644
--- a/fastlane/Fastfile
+++ b/fastlane/Fastfile
@@ -70,6 +70,10 @@ lane :release do |options|
)
end
+lane :merge_release do |options|
+ merge_release_to_main(author: options[:author])
+end
+
desc "Publish a new release to GitHub and CocoaPods"
lane :publish_release do |options|
xcversion(version: '15.0.1')
@@ -483,48 +487,6 @@ private_lane :build_example_app do |options|
)
end
-lane :merge_release_to_main do |options|
- ensure_git_status_clean
-
- release_branch =
- if is_ci
- # This API operation needs the "admin:org" scope.
- ios_team = sh('gh api orgs/GetStream/teams/ios-developers/members -q ".[].login"', log: false).split
- UI.user_error!("#{options[:author]} is not a member of the iOS Team") unless ios_team.include?(options[:author])
-
- current_branch
- else
- release_branches = sh(command: 'git branch -a', log: false).delete(' ').split("\n").grep(%r(origin/.*release/))
- UI.user_error!("Expected 1 release branch, found #{release_branches.size}") if release_branches.size != 1
-
- release_branches.first
- end
-
- UI.user_error!("`#{release_branch}`` branch does not match the release branch pattern: `release/*`") unless release_branch.start_with?('release/')
-
- sh('git checkout origin/main')
- sh('git pull origin main')
-
- # Merge release branch to main. For more info, read: https://notion.so/iOS-Branching-Strategy-37c10127dc26493e937769d44b1d6d9a
- sh("git merge #{release_branch} --ff-only")
- sh('git push origin main')
-
- comment = "[Publication of the release](https://github.com/#{github_repo}/actions/workflows/release-publish.yml) has been launched 👍"
- UI.important(comment)
- pr_comment(text: comment)
-end
-
-lane :merge_main_to_develop do
- ensure_git_status_clean
- sh('git checkout main')
- sh('git pull origin main')
- sh('git checkout origin/develop')
- sh('git pull origin develop')
- sh('git log develop..main')
- sh('git merge main')
- sh('git push origin develop')
-end
-
desc 'Compresses the XCFrameworks into zip files'
lane :compress_frameworks do
Dir.chdir('..') do
diff --git a/fastlane/Pluginfile b/fastlane/Pluginfile
index f02744589..5ac3f66f1 100644
--- a/fastlane/Pluginfile
+++ b/fastlane/Pluginfile
@@ -1,3 +1,3 @@
gem 'fastlane-plugin-versioning'
gem 'fastlane-plugin-create_xcframework'
-gem 'fastlane-plugin-stream_actions', '0.3.60'
+gem 'fastlane-plugin-stream_actions', '0.3.63'
From 6edf57d5c594af430cfe05ce4e09db0f71817d3c Mon Sep 17 00:00:00 2001
From: Martin Mitrevski
Date: Mon, 19 Aug 2024 10:18:15 +0200
Subject: [PATCH 23/38] Updates to the livestream docs (#484)
---
.../03-call-and-participant-state.mdx | 21 ++++++++++++++++--
.../05-ui-cookbook/14-livestream-player.mdx | 22 ++++++++++++++++++-
2 files changed, 40 insertions(+), 3 deletions(-)
diff --git a/docusaurus/docs/iOS/03-guides/03-call-and-participant-state.mdx b/docusaurus/docs/iOS/03-guides/03-call-and-participant-state.mdx
index d68640e05..ced3ccce4 100644
--- a/docusaurus/docs/iOS/03-guides/03-call-and-participant-state.mdx
+++ b/docusaurus/docs/iOS/03-guides/03-call-and-participant-state.mdx
@@ -63,15 +63,32 @@ The following fields are available on the call:
### Participant State
-The `CallParticipant` is the most essential component used to render a participant in a call. It contains all of the information to render a participant, such as audio & video renderers, availabilities of audio & video, the screen sharing session, reactions, and etc. Here's how you iterate over the participants:
+The `CallParticipant` is the most essential component used to render a participant in a call. It contains all of the information to render a participant, such as audio & video tracks, availabilities of audio & video, the screen sharing session, reactions, and etc. Here's how you can subscribe to participants updates:
```swift
// all participants
let cancellable = call.state.$participants.sink { participants in
// ..
}
+```
+
+Filtering of the participants is also supported. You can get all the participants with the role "host", with the following code:
+
+```swift
+var hosts: [CallParticipant] {
+ call.state.participants.filter { $0.roles.contains("host") }
+}
+```
-// you
+When you join a call with many participants, maximum of 250 participants are returned in the join response. The list of participants is updated dynamically when there are join call events.
+
+The participants that are publishing video, audio or screensharing are prioritized over the other participants in the list.
+
+The total number of participants is updated realtime via health check events. This value is available from the call state's `participantCount` property.
+
+You can get the current user with the following code:
+
+```swift
let localParticipant: CallParticipant? = call.state.localParticipant
```
diff --git a/docusaurus/docs/iOS/05-ui-cookbook/14-livestream-player.mdx b/docusaurus/docs/iOS/05-ui-cookbook/14-livestream-player.mdx
index 5e34b3e4b..d66d0403b 100644
--- a/docusaurus/docs/iOS/05-ui-cookbook/14-livestream-player.mdx
+++ b/docusaurus/docs/iOS/05-ui-cookbook/14-livestream-player.mdx
@@ -45,4 +45,24 @@ Apart from the required parameters, you can also specify some optional ones in t
- `muted`: `Bool` - whether the livestream audio should be on when joining the stream (default is `false`).
- `showParticipantCount`: `Bool` - whether the participant count should be shown (default is `true`).
-- `onFullScreenStateChange`: `((Bool) -> ())?` - closure that is invoked when the full screen state changes. Useful if you use the livestream component as part of your custom views, since this is the chance to update the visibility of your custom UI elements.
\ No newline at end of file
+- `onFullScreenStateChange`: `((Bool) -> ())?` - closure that is invoked when the full screen state changes. Useful if you use the livestream component as part of your custom views, since this is the chance to update the visibility of your custom UI elements.
+
+## Accessing the livestream track
+
+You can also build your own version of a livestream player, depending on your requirements. In those cases, you need to have access to the livestream track (or tracks).
+
+If there is only one video track (you only have one person livestreaming), you can get it with the following code:
+
+```swift
+let livestream = call.state.participants.first(where: { $0.track != nil })
+```
+
+If you have multiple hosts that are livestreaming, and you want to show them all, you can fetch the hosts by role:
+
+```swift
+var hosts: [CallParticipant] {
+ call.state.participants.filter { $0.roles.contains("host") }
+}
+```
+
+Then, you can access the video track they are streaming, with the `track` property.
\ No newline at end of file
From d560e0657d7ce18272a91504fb216abfb384659d Mon Sep 17 00:00:00 2001
From: Martin Mitrevski
Date: Tue, 20 Aug 2024 12:52:17 +0200
Subject: [PATCH 24/38] Generated RTMP-related code (#488)
---
Sources/StreamVideo/CallState.swift | 10 +-
.../OpenApi/generated/APIs/DefaultAPI.swift | 811 ++++++++++++------
.../generated/Models/CallMissedEvent.swift | 60 ++
.../CallRtmpBroadcastStartedEvent.swift | 42 +
.../CallRtmpBroadcastStoppedEvent.swift | 42 +
.../generated/Models/CallUserMutedEvent.swift | 46 +
.../generated/Models/DeleteCallRequest.swift | 30 +
.../generated/Models/DeleteCallResponse.swift | 38 +
.../Models/DeleteRecordingResponse.swift | 29 +
.../Models/DeleteTranscriptionResponse.swift | 29 +
.../generated/Models/GoLiveRequest.swift | 6 +-
.../generated/Models/LayoutSettings.swift | 48 ++
.../Models/StartRTMPBroadcastsRequest.swift | 53 ++
.../Models/StartRTMPBroadcastsResponse.swift | 30 +
.../StopAllRTMPBroadcastsResponse.swift | 30 +
.../Models/StopRTMPBroadcastsResponse.swift | 30 +
.../OpenApi/generated/Models/WSEvent.swift | 70 +-
Sources/StreamVideo/StreamVideo.swift | 2 +-
StreamVideo.xcodeproj/project.pbxproj | 52 ++
19 files changed, 1161 insertions(+), 297 deletions(-)
create mode 100644 Sources/StreamVideo/OpenApi/generated/Models/CallMissedEvent.swift
create mode 100644 Sources/StreamVideo/OpenApi/generated/Models/CallRtmpBroadcastStartedEvent.swift
create mode 100644 Sources/StreamVideo/OpenApi/generated/Models/CallRtmpBroadcastStoppedEvent.swift
create mode 100644 Sources/StreamVideo/OpenApi/generated/Models/CallUserMutedEvent.swift
create mode 100644 Sources/StreamVideo/OpenApi/generated/Models/DeleteCallRequest.swift
create mode 100644 Sources/StreamVideo/OpenApi/generated/Models/DeleteCallResponse.swift
create mode 100644 Sources/StreamVideo/OpenApi/generated/Models/DeleteRecordingResponse.swift
create mode 100644 Sources/StreamVideo/OpenApi/generated/Models/DeleteTranscriptionResponse.swift
create mode 100644 Sources/StreamVideo/OpenApi/generated/Models/LayoutSettings.swift
create mode 100644 Sources/StreamVideo/OpenApi/generated/Models/StartRTMPBroadcastsRequest.swift
create mode 100644 Sources/StreamVideo/OpenApi/generated/Models/StartRTMPBroadcastsResponse.swift
create mode 100644 Sources/StreamVideo/OpenApi/generated/Models/StopAllRTMPBroadcastsResponse.swift
create mode 100644 Sources/StreamVideo/OpenApi/generated/Models/StopRTMPBroadcastsResponse.swift
diff --git a/Sources/StreamVideo/CallState.swift b/Sources/StreamVideo/CallState.swift
index 2a523034c..b3b03c0fa 100644
--- a/Sources/StreamVideo/CallState.swift
+++ b/Sources/StreamVideo/CallState.swift
@@ -207,8 +207,6 @@ public class CallState: ObservableObject {
case .typeHealthCheckEvent:
// note: health checks are not relevant for call state sync'ing
break
- case .typeCallUserMuted:
- break
case .typeCallDeletedEvent:
break
case .typeCallHLSBroadcastingFailedEvent:
@@ -227,6 +225,14 @@ public class CallState: ObservableObject {
transcribing = true
case .typeCallTranscriptionStoppedEvent:
transcribing = false
+ case .typeCallMissedEvent:
+ break
+ case .typeCallRtmpBroadcastStartedEvent:
+ break
+ case .typeCallRtmpBroadcastStoppedEvent:
+ break
+ case .typeCallUserMutedEvent:
+ break
}
}
diff --git a/Sources/StreamVideo/OpenApi/generated/APIs/DefaultAPI.swift b/Sources/StreamVideo/OpenApi/generated/APIs/DefaultAPI.swift
index 0c2208c27..b5331d9db 100644
--- a/Sources/StreamVideo/OpenApi/generated/APIs/DefaultAPI.swift
+++ b/Sources/StreamVideo/OpenApi/generated/APIs/DefaultAPI.swift
@@ -157,12 +157,11 @@ open class DefaultAPI: DefaultAPIEndpoints, @unchecked Sendable {
return r
}
-
/**
Accept Call
- - parameter type: (path)
- - parameter id: (path)
+ - parameter type: (path)
+ - parameter id: (path)
- returns: AcceptCallResponse
*/
@@ -186,19 +185,19 @@ open class DefaultAPI: DefaultAPIEndpoints, @unchecked Sendable {
/**
Accept Call
- POST /video/call/{type}/{id}/accept
- - Sends events: - call.accepted Required permissions: - JoinCall
- - parameter type: (path)
- - parameter id: (path)
- - returns: RequestBuilder
+ - Sends events: - call.accepted Required permissions: - JoinCall
+ - parameter type: (path)
+ - parameter id: (path)
+ - returns: RequestBuilder
*/
/**
Block user on a call
- - parameter type: (path)
- - parameter id: (path)
- - parameter blockUserRequest: (body)
+ - parameter type: (path)
+ - parameter id: (path)
+ - parameter blockUserRequest: (body)
- returns: BlockUserResponse
*/
@@ -223,21 +222,21 @@ open class DefaultAPI: DefaultAPIEndpoints, @unchecked Sendable {
/**
Block user on a call
- POST /video/call/{type}/{id}/block
- - Block a user, preventing them from joining the call until they are unblocked. Sends events: - call.blocked_user Required permissions: - BlockUser
- - parameter type: (path)
- - parameter id: (path)
- - parameter blockUserRequest: (body)
- - returns: RequestBuilder
+ - Block a user, preventing them from joining the call until they are unblocked. Sends events: - call.blocked_user Required permissions: - BlockUser
+ - parameter type: (path)
+ - parameter id: (path)
+ - parameter blockUserRequest: (body)
+ - returns: RequestBuilder
*/
/**
Collect user feedback
- - parameter type: (path)
- - parameter id: (path)
- - parameter session: (path)
- - parameter collectUserFeedbackRequest: (body)
+ - parameter type: (path)
+ - parameter id: (path)
+ - parameter session: (path)
+ - parameter collectUserFeedbackRequest: (body)
- returns: CollectUserFeedbackResponse
*/
@@ -262,11 +261,22 @@ open class DefaultAPI: DefaultAPIEndpoints, @unchecked Sendable {
try self.jsonDecoder.decode(CollectUserFeedbackResponse.self, from: $0)
}
}
-
+ /**
+ Collect user feedback
+ - POST /video/call/{type}/{id}/feedback/{session}
+ - Required permissions: - JoinCall
+ - parameter type: (path)
+ - parameter id: (path)
+ - parameter session: (path)
+ - parameter collectUserFeedbackRequest: (body)
+ - returns: RequestBuilder
+ */
+
+
/**
Create device
- - parameter createDeviceRequest: (body)
+ - parameter createDeviceRequest: (body)
- returns: ModelResponse
*/
@@ -285,16 +295,16 @@ open class DefaultAPI: DefaultAPIEndpoints, @unchecked Sendable {
/**
Create device
- POST /video/devices
- - Adds a new device to a user, if the same device already exists the call will have no effect
- - parameter createDeviceRequest: (body)
- - returns: RequestBuilder
+ - Adds a new device to a user, if the same device already exists the call will have no effect
+ - parameter createDeviceRequest: (body)
+ - returns: RequestBuilder
*/
/**
Create Guest
- - parameter createGuestRequest: (body)
+ - parameter createGuestRequest: (body)
- returns: CreateGuestResponse
*/
@@ -313,25 +323,61 @@ open class DefaultAPI: DefaultAPIEndpoints, @unchecked Sendable {
/**
Create Guest
- POST /video/guest
- -
- - parameter createGuestRequest: (body)
- - returns: RequestBuilder
+ -
+ - parameter createGuestRequest: (body)
+ - returns: RequestBuilder
+ */
+
+
+ /**
+ Delete Call
+
+ - parameter type: (path)
+ - parameter id: (path)
+ - parameter deleteCallRequest: (body)
+ - returns: DeleteCallResponse
+ */
+
+ open func deleteCall(type: String, id: String, deleteCallRequest: DeleteCallRequest) async throws -> DeleteCallResponse {
+ var localVariablePath = "/video/call/{type}/{id}/delete"
+ let typePreEscape = "\(APIHelper.mapValueToPathItem(type))"
+ let typePostEscape = typePreEscape.addingPercentEncoding(withAllowedCharacters: .urlPathAllowed) ?? ""
+ localVariablePath = localVariablePath.replacingOccurrences(of: "{type}", with: typePostEscape, options: .literal, range: nil)
+ let idPreEscape = "\(APIHelper.mapValueToPathItem(id))"
+ let idPostEscape = idPreEscape.addingPercentEncoding(withAllowedCharacters: .urlPathAllowed) ?? ""
+ localVariablePath = localVariablePath.replacingOccurrences(of: "{id}", with: idPostEscape, options: .literal, range: nil)
+
+ let urlRequest = try makeRequest(
+ uriPath: localVariablePath,
+ httpMethod: "POST",
+ request: deleteCallRequest
+ )
+ return try await send(request: urlRequest) {
+ try self.jsonDecoder.decode(DeleteCallResponse.self, from: $0)
+ }
+ }
+ /**
+ Delete Call
+ - POST /video/call/{type}/{id}/delete
+ - Sends events: - call.deleted Required permissions: - DeleteCall
+ - parameter type: (path)
+ - parameter id: (path)
+ - parameter deleteCallRequest: (body)
+ - returns: RequestBuilder
*/
/**
Delete device
- - parameter id: (query) (optional)
- - parameter userId: (query) (optional)
+ - parameter id: (query)
- returns: ModelResponse
*/
- open func deleteDevice(id: String? = nil, userId: String? = nil) async throws -> ModelResponse {
+ open func deleteDevice(id: String) async throws -> ModelResponse {
let localVariablePath = "/video/devices"
let queryParams = APIHelper.mapValuesToQueryItems([
- "id": (wrappedValue: id?.encodeToJSON(), isExplode: true),
- "user_id": (wrappedValue: userId?.encodeToJSON(), isExplode: true),
+ "id": (wrappedValue: id.encodeToJSON(), isExplode: true),
])
let urlRequest = try makeRequest(
uriPath: localVariablePath,
@@ -345,18 +391,107 @@ open class DefaultAPI: DefaultAPIEndpoints, @unchecked Sendable {
/**
Delete device
- DELETE /video/devices
- - Deletes one device
- - parameter id: (query) (optional)
- - parameter userId: (query) (optional)
- - returns: RequestBuilder
+ - Deletes one device
+ - parameter id: (query)
+ - returns: RequestBuilder
+ */
+
+
+ /**
+ Delete recording
+
+ - parameter type: (path)
+ - parameter id: (path)
+ - parameter session: (path)
+ - parameter filename: (path)
+ - returns: DeleteRecordingResponse
+ */
+
+ open func deleteRecording(type: String, id: String, session: String, filename: String) async throws -> DeleteRecordingResponse {
+ var localVariablePath = "/video/call/{type}/{id}/{session}/recordings/{filename}"
+ let typePreEscape = "\(APIHelper.mapValueToPathItem(type))"
+ let typePostEscape = typePreEscape.addingPercentEncoding(withAllowedCharacters: .urlPathAllowed) ?? ""
+ localVariablePath = localVariablePath.replacingOccurrences(of: "{type}", with: typePostEscape, options: .literal, range: nil)
+ let idPreEscape = "\(APIHelper.mapValueToPathItem(id))"
+ let idPostEscape = idPreEscape.addingPercentEncoding(withAllowedCharacters: .urlPathAllowed) ?? ""
+ localVariablePath = localVariablePath.replacingOccurrences(of: "{id}", with: idPostEscape, options: .literal, range: nil)
+ let sessionPreEscape = "\(APIHelper.mapValueToPathItem(session))"
+ let sessionPostEscape = sessionPreEscape.addingPercentEncoding(withAllowedCharacters: .urlPathAllowed) ?? ""
+ localVariablePath = localVariablePath.replacingOccurrences(of: "{session}", with: sessionPostEscape, options: .literal, range: nil)
+ let filenamePreEscape = "\(APIHelper.mapValueToPathItem(filename))"
+ let filenamePostEscape = filenamePreEscape.addingPercentEncoding(withAllowedCharacters: .urlPathAllowed) ?? ""
+ localVariablePath = localVariablePath.replacingOccurrences(of: "{filename}", with: filenamePostEscape, options: .literal, range: nil)
+
+ let urlRequest = try makeRequest(
+ uriPath: localVariablePath,
+ httpMethod: "DELETE"
+ )
+ return try await send(request: urlRequest) {
+ try self.jsonDecoder.decode(DeleteRecordingResponse.self, from: $0)
+ }
+ }
+ /**
+ Delete recording
+ - DELETE /video/call/{type}/{id}/{session}/recordings/{filename}
+ - Deletes recording Required permissions: - DeleteRecording
+ - parameter type: (path)
+ - parameter id: (path)
+ - parameter session: (path)
+ - parameter filename: (path)
+ - returns: RequestBuilder
+ */
+
+
+ /**
+ Delete transcription
+
+ - parameter type: (path)
+ - parameter id: (path)
+ - parameter session: (path)
+ - parameter filename: (path)
+ - returns: DeleteTranscriptionResponse
+ */
+
+ open func deleteTranscription(type: String, id: String, session: String, filename: String) async throws -> DeleteTranscriptionResponse {
+ var localVariablePath = "/video/call/{type}/{id}/{session}/transcriptions/{filename}"
+ let typePreEscape = "\(APIHelper.mapValueToPathItem(type))"
+ let typePostEscape = typePreEscape.addingPercentEncoding(withAllowedCharacters: .urlPathAllowed) ?? ""
+ localVariablePath = localVariablePath.replacingOccurrences(of: "{type}", with: typePostEscape, options: .literal, range: nil)
+ let idPreEscape = "\(APIHelper.mapValueToPathItem(id))"
+ let idPostEscape = idPreEscape.addingPercentEncoding(withAllowedCharacters: .urlPathAllowed) ?? ""
+ localVariablePath = localVariablePath.replacingOccurrences(of: "{id}", with: idPostEscape, options: .literal, range: nil)
+ let sessionPreEscape = "\(APIHelper.mapValueToPathItem(session))"
+ let sessionPostEscape = sessionPreEscape.addingPercentEncoding(withAllowedCharacters: .urlPathAllowed) ?? ""
+ localVariablePath = localVariablePath.replacingOccurrences(of: "{session}", with: sessionPostEscape, options: .literal, range: nil)
+ let filenamePreEscape = "\(APIHelper.mapValueToPathItem(filename))"
+ let filenamePostEscape = filenamePreEscape.addingPercentEncoding(withAllowedCharacters: .urlPathAllowed) ?? ""
+ localVariablePath = localVariablePath.replacingOccurrences(of: "{filename}", with: filenamePostEscape, options: .literal, range: nil)
+
+ let urlRequest = try makeRequest(
+ uriPath: localVariablePath,
+ httpMethod: "DELETE"
+ )
+ return try await send(request: urlRequest) {
+ try self.jsonDecoder.decode(DeleteTranscriptionResponse.self, from: $0)
+ }
+ }
+ /**
+ Delete transcription
+ - DELETE /video/call/{type}/{id}/{session}/transcriptions/{filename}
+ - Deletes transcription Required permissions: - DeleteTranscription
+ - parameter type: (path)
+ - parameter id: (path)
+ - parameter session: (path)
+ - parameter filename: (path)
+ - returns: RequestBuilder
*/
/**
End call
- - parameter type: (path)
- - parameter id: (path)
+ - parameter type: (path)
+ - parameter id: (path)
- returns: EndCallResponse
*/
@@ -380,26 +515,27 @@ open class DefaultAPI: DefaultAPIEndpoints, @unchecked Sendable {
/**
End call
- POST /video/call/{type}/{id}/mark_ended
- - Sends events: - call.ended Required permissions: - EndCall
- - parameter type: (path)
- - parameter id: (path)
- - returns: RequestBuilder
+ - Sends events: - call.ended Required permissions: - EndCall
+ - parameter type: (path)
+ - parameter id: (path)
+ - returns: RequestBuilder
*/
/**
Get Call
- - parameter type: (path)
- - parameter id: (path)
+ - parameter type: (path)
+ - parameter id: (path)
- parameter connectionId: (query) (optional)
- parameter membersLimit: (query) (optional)
- parameter ring: (query) (optional)
- parameter notify: (query) (optional)
+ - parameter video: (query) (optional)
- returns: GetCallResponse
*/
- open func getCall(type: String, id: String, connectionId: String? = nil, membersLimit: Int? = nil, ring: Bool? = nil, notify: Bool? = nil) async throws -> GetCallResponse {
+ open func getCall(type: String, id: String, connectionId: String? = nil, membersLimit: Int? = nil, ring: Bool? = nil, notify: Bool? = nil, video: Bool? = nil) async throws -> GetCallResponse {
var localVariablePath = "/video/call/{type}/{id}"
let typePreEscape = "\(APIHelper.mapValueToPathItem(type))"
let typePostEscape = typePreEscape.addingPercentEncoding(withAllowedCharacters: .urlPathAllowed) ?? ""
@@ -412,6 +548,7 @@ open class DefaultAPI: DefaultAPIEndpoints, @unchecked Sendable {
"members_limit": (wrappedValue: membersLimit?.encodeToJSON(), isExplode: true),
"ring": (wrappedValue: ring?.encodeToJSON(), isExplode: true),
"notify": (wrappedValue: notify?.encodeToJSON(), isExplode: true),
+ "video": (wrappedValue: video?.encodeToJSON(), isExplode: true),
])
let urlRequest = try makeRequest(
uriPath: localVariablePath,
@@ -425,23 +562,24 @@ open class DefaultAPI: DefaultAPIEndpoints, @unchecked Sendable {
/**
Get Call
- GET /video/call/{type}/{id}
- - Required permissions: - ReadCall
- - parameter type: (path)
- - parameter id: (path)
+ - Required permissions: - ReadCall
+ - parameter type: (path)
+ - parameter id: (path)
- parameter connectionId: (query) (optional)
- parameter membersLimit: (query) (optional)
- parameter ring: (query) (optional)
- parameter notify: (query) (optional)
- - returns: RequestBuilder
+ - parameter video: (query) (optional)
+ - returns: RequestBuilder
*/
/**
Get Call Stats
- - parameter type: (path)
- - parameter id: (path)
- - parameter session: (path)
+ - parameter type: (path)
+ - parameter id: (path)
+ - parameter session: (path)
- returns: GetCallStatsResponse
*/
@@ -468,11 +606,11 @@ open class DefaultAPI: DefaultAPIEndpoints, @unchecked Sendable {
/**
Get Call Stats
- GET /video/call/{type}/{id}/stats/{session}
- - Required permissions: - ReadCallStats
- - parameter type: (path)
- - parameter id: (path)
- - parameter session: (path)
- - returns: RequestBuilder
+ - Required permissions: - ReadCallStats
+ - parameter type: (path)
+ - parameter id: (path)
+ - parameter session: (path)
+ - returns: RequestBuilder
*/
@@ -496,17 +634,17 @@ open class DefaultAPI: DefaultAPIEndpoints, @unchecked Sendable {
/**
Get Edges
- GET /video/edges
- - Returns the list of all edges available for video calls.
- - returns: RequestBuilder
+ - Returns the list of all edges available for video calls.
+ - returns: RequestBuilder
*/
/**
Get or create a call
- - parameter type: (path)
- - parameter id: (path)
- - parameter getOrCreateCallRequest: (body)
+ - parameter type: (path)
+ - parameter id: (path)
+ - parameter getOrCreateCallRequest: (body)
- parameter connectionId: (query) (optional)
- returns: GetOrCreateCallResponse
*/
@@ -535,21 +673,21 @@ open class DefaultAPI: DefaultAPIEndpoints, @unchecked Sendable {
/**
Get or create a call
- POST /video/call/{type}/{id}
- - Gets or creates a new call Sends events: - call.created - call.notification - call.ring Required permissions: - CreateCall - ReadCall - UpdateCallSettings
- - parameter type: (path)
- - parameter id: (path)
- - parameter getOrCreateCallRequest: (body)
+ - Gets or creates a new call Sends events: - call.created - call.notification - call.ring Required permissions: - CreateCall - ReadCall - UpdateCallSettings
+ - parameter type: (path)
+ - parameter id: (path)
+ - parameter getOrCreateCallRequest: (body)
- parameter connectionId: (query) (optional)
- - returns: RequestBuilder
+ - returns: RequestBuilder
*/
/**
Set call as live
- - parameter type: (path)
- - parameter id: (path)
- - parameter goLiveRequest: (body)
+ - parameter type: (path)
+ - parameter id: (path)
+ - parameter goLiveRequest: (body)
- returns: GoLiveResponse
*/
@@ -574,20 +712,20 @@ open class DefaultAPI: DefaultAPIEndpoints, @unchecked Sendable {
/**
Set call as live
- POST /video/call/{type}/{id}/go_live
- - Sends events: - call.live_started Required permissions: - UpdateCall
- - parameter type: (path)
- - parameter id: (path)
- - parameter goLiveRequest: (body)
- - returns: RequestBuilder
+ - Sends events: - call.live_started Required permissions: - UpdateCall
+ - parameter type: (path)
+ - parameter id: (path)
+ - parameter goLiveRequest: (body)
+ - returns: RequestBuilder
*/
/**
Join call
- - parameter type: (path)
- - parameter id: (path)
- - parameter joinCallRequest: (body)
+ - parameter type: (path)
+ - parameter id: (path)
+ - parameter joinCallRequest: (body)
- parameter connectionId: (query) (optional)
- returns: JoinCallResponse
*/
@@ -616,30 +754,26 @@ open class DefaultAPI: DefaultAPIEndpoints, @unchecked Sendable {
/**
Join call
- POST /video/call/{type}/{id}/join
- - Request to join a call Required permissions: - CreateCall - JoinCall
- - parameter type: (path)
- - parameter id: (path)
- - parameter joinCallRequest: (body)
+ - Request to join a call Required permissions: - CreateCall - JoinCall
+ - parameter type: (path)
+ - parameter id: (path)
+ - parameter joinCallRequest: (body)
- parameter connectionId: (query) (optional)
- - returns: RequestBuilder
+ - returns: RequestBuilder
*/
/**
List devices
- - parameter userId: (query) (optional)
- returns: ListDevicesResponse
*/
- open func listDevices(userId: String? = nil) async throws -> ListDevicesResponse {
+ open func listDevices() async throws -> ListDevicesResponse {
let localVariablePath = "/video/devices"
- let queryParams = APIHelper.mapValuesToQueryItems([
- "user_id": (wrappedValue: userId?.encodeToJSON(), isExplode: true),
- ])
+
let urlRequest = try makeRequest(
uriPath: localVariablePath,
- queryParams: queryParams ?? [],
httpMethod: "GET"
)
return try await send(request: urlRequest) {
@@ -649,17 +783,16 @@ open class DefaultAPI: DefaultAPIEndpoints, @unchecked Sendable {
/**
List devices
- GET /video/devices
- - Returns all available devices
- - parameter userId: (query) (optional)
- - returns: RequestBuilder
+ - Returns all available devices
+ - returns: RequestBuilder
*/
/**
List recordings
- - parameter type: (path)
- - parameter id: (path)
+ - parameter type: (path)
+ - parameter id: (path)
- returns: ListRecordingsResponse
*/
@@ -683,18 +816,18 @@ open class DefaultAPI: DefaultAPIEndpoints, @unchecked Sendable {
/**
List recordings
- GET /video/call/{type}/{id}/recordings
- - Lists recordings Required permissions: - ListRecordings
- - parameter type: (path)
- - parameter id: (path)
- - returns: RequestBuilder
+ - Lists recordings Required permissions: - ListRecordings
+ - parameter type: (path)
+ - parameter id: (path)
+ - returns: RequestBuilder
*/
/**
List transcriptions
- - parameter type: (path)
- - parameter id: (path)
+ - parameter type: (path)
+ - parameter id: (path)
- returns: ListTranscriptionsResponse
*/
@@ -718,19 +851,19 @@ open class DefaultAPI: DefaultAPIEndpoints, @unchecked Sendable {
/**
List transcriptions
- GET /video/call/{type}/{id}/transcriptions
- - Lists transcriptions Required permissions: - ListTranscriptions
- - parameter type: (path)
- - parameter id: (path)
- - returns: RequestBuilder
+ - Lists transcriptions Required permissions: - ListTranscriptions
+ - parameter type: (path)
+ - parameter id: (path)
+ - returns: RequestBuilder
*/
/**
Mute users
- - parameter type: (path)
- - parameter id: (path)
- - parameter muteUsersRequest: (body)
+ - parameter type: (path)
+ - parameter id: (path)
+ - parameter muteUsersRequest: (body)
- returns: MuteUsersResponse
*/
@@ -755,18 +888,46 @@ open class DefaultAPI: DefaultAPIEndpoints, @unchecked Sendable {
/**
Mute users
- POST /video/call/{type}/{id}/mute_users
- - Mutes users in a call Required permissions: - MuteUsers
- - parameter type: (path)
- - parameter id: (path)
- - parameter muteUsersRequest: (body)
- - returns: RequestBuilder
+ - Mutes users in a call Required permissions: - MuteUsers
+ - parameter type: (path)
+ - parameter id: (path)
+ - parameter muteUsersRequest: (body)
+ - returns: RequestBuilder
+ */
+
+
+ /**
+ Query call members
+
+ - parameter queryMembersRequest: (body)
+ - returns: QueryMembersResponse
+ */
+
+ open func queryMembers(queryMembersRequest: QueryMembersRequest) async throws -> QueryMembersResponse {
+ let localVariablePath = "/video/call/members"
+
+ let urlRequest = try makeRequest(
+ uriPath: localVariablePath,
+ httpMethod: "POST",
+ request: queryMembersRequest
+ )
+ return try await send(request: urlRequest) {
+ try self.jsonDecoder.decode(QueryMembersResponse.self, from: $0)
+ }
+ }
+ /**
+ Query call members
+ - POST /video/call/members
+ - Query call members with filter query Required permissions: - ReadCall
+ - parameter queryCallMembersRequest: (body)
+ - returns: RequestBuilder
*/
/**
Query Call Stats
- - parameter queryCallStatsRequest: (body)
+ - parameter queryCallStatsRequest: (body)
- returns: QueryCallStatsResponse
*/
@@ -785,16 +946,16 @@ open class DefaultAPI: DefaultAPIEndpoints, @unchecked Sendable {
/**
Query Call Stats
- POST /video/call/stats
- - Required permissions: - ReadCallStats
- - parameter queryCallStatsRequest: (body)
- - returns: RequestBuilder
+ - Required permissions: - ReadCallStats
+ - parameter queryCallStatsRequest: (body)
+ - returns: RequestBuilder
*/
/**
Query call
- - parameter queryCallsRequest: (body)
+ - parameter queryCallsRequest: (body)
- parameter connectionId: (query) (optional)
- returns: QueryCallsResponse
*/
@@ -817,38 +978,10 @@ open class DefaultAPI: DefaultAPIEndpoints, @unchecked Sendable {
/**
Query call
- POST /video/calls
- - Query calls with filter query Required permissions: - ReadCall
- - parameter queryCallsRequest: (body)
+ - Query calls with filter query Required permissions: - ReadCall
+ - parameter queryCallsRequest: (body)
- parameter connectionId: (query) (optional)
- - returns: RequestBuilder
- */
-
-
- /**
- Query call members
-
- - parameter queryMembersRequest: (body)
- - returns: QueryMembersResponse
- */
-
- open func queryMembers(queryMembersRequest: QueryMembersRequest) async throws -> QueryMembersResponse {
- let localVariablePath = "/video/call/members"
-
- let urlRequest = try makeRequest(
- uriPath: localVariablePath,
- httpMethod: "POST",
- request: queryMembersRequest
- )
- return try await send(request: urlRequest) {
- try self.jsonDecoder.decode(QueryMembersResponse.self, from: $0)
- }
- }
- /**
- Query call members
- - POST /video/call/members
- - Query call members with filter query Required permissions: - ReadCall
- - parameter queryMembersRequest: (body)
- - returns: RequestBuilder
+ - returns: RequestBuilder
*/
@@ -879,13 +1012,23 @@ open class DefaultAPI: DefaultAPIEndpoints, @unchecked Sendable {
try self.jsonDecoder.decode(RejectCallResponse.self, from: $0)
}
}
+ /**
+ Reject Call
+ - POST /video/call/{type}/{id}/reject
+ - Sends events: - call.rejected Required permissions: - JoinCall
+ - parameter type: (path)
+ - parameter id: (path)
+ - parameter rejectCallRequest: (body)
+ - returns: RequestBuilder
+ */
+
/**
Request permission
- - parameter type: (path)
- - parameter id: (path)
- - parameter requestPermissionRequest: (body)
+ - parameter type: (path)
+ - parameter id: (path)
+ - parameter requestPermissionRequest: (body)
- returns: RequestPermissionResponse
*/
@@ -910,11 +1053,11 @@ open class DefaultAPI: DefaultAPIEndpoints, @unchecked Sendable {
/**
Request permission
- POST /video/call/{type}/{id}/request_permission
- - Request permission to perform an action Sends events: - call.permission_request
- - parameter type: (path)
- - parameter id: (path)
- - parameter requestPermissionRequest: (body)
- - returns: RequestBuilder
+ - Request permission to perform an action Sends events: - call.permission_request
+ - parameter type: (path)
+ - parameter id: (path)
+ - parameter requestPermissionRequest: (body)
+ - returns: RequestBuilder
*/
@@ -948,20 +1091,20 @@ open class DefaultAPI: DefaultAPIEndpoints, @unchecked Sendable {
/**
Send custom event
- POST /video/call/{type}/{id}/event
- - Sends custom event to the call Sends events: - custom Required permissions: - SendEvent
- - parameter type: (path)
- - parameter id: (path)
- - parameter sendEventRequest: (body)
- - returns: RequestBuilder
+ - Sends custom event to the call Sends events: - custom Required permissions: - SendEvent
+ - parameter type: (path)
+ - parameter id: (path)
+ - parameter sendCallEventRequest: (body)
+ - returns: RequestBuilder
*/
/**
Send reaction to the call
- - parameter type: (path)
- - parameter id: (path)
- - parameter sendReactionRequest: (body)
+ - parameter type: (path)
+ - parameter id: (path)
+ - parameter sendReactionRequest: (body)
- returns: SendReactionResponse
*/
@@ -986,19 +1129,19 @@ open class DefaultAPI: DefaultAPIEndpoints, @unchecked Sendable {
/**
Send reaction to the call
- POST /video/call/{type}/{id}/reaction
- - Sends reaction to the call Sends events: - call.reaction_new Required permissions: - CreateCallReaction
- - parameter type: (path)
- - parameter id: (path)
- - parameter sendReactionRequest: (body)
- - returns: RequestBuilder
+ - Sends reaction to the call Sends events: - call.reaction_new Required permissions: - CreateCallReaction
+ - parameter type: (path)
+ - parameter id: (path)
+ - parameter sendReactionRequest: (body)
+ - returns: RequestBuilder
*/
/**
Start HLS broadcasting
- - parameter type: (path)
- - parameter id: (path)
+ - parameter type: (path)
+ - parameter id: (path)
- returns: StartHLSBroadcastingResponse
*/
@@ -1022,19 +1165,57 @@ open class DefaultAPI: DefaultAPIEndpoints, @unchecked Sendable {
/**
Start HLS broadcasting
- POST /video/call/{type}/{id}/start_broadcasting
- - Starts HLS broadcasting Required permissions: - StartBroadcasting
- - parameter type: (path)
- - parameter id: (path)
- - returns: RequestBuilder
+ - Starts HLS broadcasting Required permissions: - StartBroadcasting
+ - parameter type: (path)
+ - parameter id: (path)
+ - returns: RequestBuilder
+ */
+
+
+ /**
+ Start RTMP broadcasts
+
+ - parameter type: (path)
+ - parameter id: (path)
+ - parameter startRTMPBroadcastsRequest: (body)
+ - returns: StartRTMPBroadcastsResponse
+ */
+
+ open func startRTMPBroadcast(type: String, id: String, startRTMPBroadcastsRequest: StartRTMPBroadcastsRequest) async throws -> StartRTMPBroadcastsResponse {
+ var localVariablePath = "/video/call/{type}/{id}/rtmp_broadcasts"
+ let typePreEscape = "\(APIHelper.mapValueToPathItem(type))"
+ let typePostEscape = typePreEscape.addingPercentEncoding(withAllowedCharacters: .urlPathAllowed) ?? ""
+ localVariablePath = localVariablePath.replacingOccurrences(of: "{type}", with: typePostEscape, options: .literal, range: nil)
+ let idPreEscape = "\(APIHelper.mapValueToPathItem(id))"
+ let idPostEscape = idPreEscape.addingPercentEncoding(withAllowedCharacters: .urlPathAllowed) ?? ""
+ localVariablePath = localVariablePath.replacingOccurrences(of: "{id}", with: idPostEscape, options: .literal, range: nil)
+
+ let urlRequest = try makeRequest(
+ uriPath: localVariablePath,
+ httpMethod: "POST",
+ request: startRTMPBroadcastsRequest
+ )
+ return try await send(request: urlRequest) {
+ try self.jsonDecoder.decode(StartRTMPBroadcastsResponse.self, from: $0)
+ }
+ }
+ /**
+ Start RTMP broadcasts
+ - POST /video/call/{type}/{id}/rtmp_broadcasts
+ - Starts RTMP broadcasts for the provided RTMP destinations Required permissions: - StartBroadcasting
+ - parameter type: (path)
+ - parameter id: (path)
+ - parameter startRTMPBroadcastsRequest: (body)
+ - returns: RequestBuilder
*/
/**
Start recording
- - parameter type: (path)
- - parameter id: (path)
- - parameter startRecordingRequest: (body)
+ - parameter type: (path)
+ - parameter id: (path)
+ - parameter startRecordingRequest: (body)
- returns: StartRecordingResponse
*/
@@ -1059,20 +1240,20 @@ open class DefaultAPI: DefaultAPIEndpoints, @unchecked Sendable {
/**
Start recording
- POST /video/call/{type}/{id}/start_recording
- - Starts recording Sends events: - call.recording_started Required permissions: - StartRecording
- - parameter type: (path)
- - parameter id: (path)
- - parameter startRecordingRequest: (body)
- - returns: RequestBuilder
+ - Starts recording Sends events: - call.recording_started Required permissions: - StartRecording
+ - parameter type: (path)
+ - parameter id: (path)
+ - parameter startRecordingRequest: (body)
+ - returns: RequestBuilder
*/
/**
Start transcription
- - parameter type: (path)
- - parameter id: (path)
- - parameter startTranscriptionRequest: (body)
+ - parameter type: (path)
+ - parameter id: (path)
+ - parameter startTranscriptionRequest: (body)
- returns: StartTranscriptionResponse
*/
@@ -1097,19 +1278,54 @@ open class DefaultAPI: DefaultAPIEndpoints, @unchecked Sendable {
/**
Start transcription
- POST /video/call/{type}/{id}/start_transcription
- - Starts transcription Required permissions: - StartTranscription
- - parameter type: (path)
- - parameter id: (path)
- - parameter startTranscriptionRequest: (body)
- - returns: RequestBuilder
+ - Starts transcription Required permissions: - StartTranscription
+ - parameter type: (path)
+ - parameter id: (path)
+ - parameter startTranscriptionRequest: (body)
+ - returns: RequestBuilder
+ */
+
+
+ /**
+ Stop all RTMP broadcasts for a call
+
+ - parameter type: (path)
+ - parameter id: (path)
+ - returns: StopAllRTMPBroadcastsResponse
+ */
+
+ open func stopAllRTMPBroadcasts(type: String, id: String) async throws -> StopAllRTMPBroadcastsResponse {
+ var localVariablePath = "/video/call/{type}/{id}/rtmp_broadcasts/stop"
+ let typePreEscape = "\(APIHelper.mapValueToPathItem(type))"
+ let typePostEscape = typePreEscape.addingPercentEncoding(withAllowedCharacters: .urlPathAllowed) ?? ""
+ localVariablePath = localVariablePath.replacingOccurrences(of: "{type}", with: typePostEscape, options: .literal, range: nil)
+ let idPreEscape = "\(APIHelper.mapValueToPathItem(id))"
+ let idPostEscape = idPreEscape.addingPercentEncoding(withAllowedCharacters: .urlPathAllowed) ?? ""
+ localVariablePath = localVariablePath.replacingOccurrences(of: "{id}", with: idPostEscape, options: .literal, range: nil)
+
+ let urlRequest = try makeRequest(
+ uriPath: localVariablePath,
+ httpMethod: "POST"
+ )
+ return try await send(request: urlRequest) {
+ try self.jsonDecoder.decode(StopAllRTMPBroadcastsResponse.self, from: $0)
+ }
+ }
+ /**
+ Stop all RTMP broadcasts for a call
+ - POST /video/call/{type}/{id}/rtmp_broadcasts/stop
+ - Stop all RTMP broadcasts for the provided call Required permissions: - StopBroadcasting
+ - parameter type: (path)
+ - parameter id: (path)
+ - returns: RequestBuilder
*/
/**
Stop HLS broadcasting
- - parameter type: (path)
- - parameter id: (path)
+ - parameter type: (path)
+ - parameter id: (path)
- returns: StopHLSBroadcastingResponse
*/
@@ -1133,18 +1349,18 @@ open class DefaultAPI: DefaultAPIEndpoints, @unchecked Sendable {
/**
Stop HLS broadcasting
- POST /video/call/{type}/{id}/stop_broadcasting
- - Stops HLS broadcasting Required permissions: - StopBroadcasting
- - parameter type: (path)
- - parameter id: (path)
- - returns: RequestBuilder
+ - Stops HLS broadcasting Required permissions: - StopBroadcasting
+ - parameter type: (path)
+ - parameter id: (path)
+ - returns: RequestBuilder
*/
/**
Set call as not live
- - parameter type: (path)
- - parameter id: (path)
+ - parameter type: (path)
+ - parameter id: (path)
- returns: StopLiveResponse
*/
@@ -1168,18 +1384,61 @@ open class DefaultAPI: DefaultAPIEndpoints, @unchecked Sendable {
/**
Set call as not live
- POST /video/call/{type}/{id}/stop_live
- - Sends events: - call.updated Required permissions: - UpdateCall
- - parameter type: (path)
- - parameter id: (path)
- - returns: RequestBuilder
+ - Sends events: - call.updated Required permissions: - UpdateCall
+ - parameter type: (path)
+ - parameter id: (path)
+ - returns: RequestBuilder
+ */
+
+
+ /**
+ Stop RTMP broadcasts
+
+ - parameter type: (path)
+ - parameter id: (path)
+ - parameter name: (path)
+ - parameter body: (body)
+ - returns: StopRTMPBroadcastsResponse
+ */
+
+ open func stopRTMPBroadcast(type: String, id: String, name: String, body: [String: RawJSON]) async throws -> StopRTMPBroadcastsResponse {
+ var localVariablePath = "/video/call/{type}/{id}/rtmp_broadcasts/{name}/stop"
+ let typePreEscape = "\(APIHelper.mapValueToPathItem(type))"
+ let typePostEscape = typePreEscape.addingPercentEncoding(withAllowedCharacters: .urlPathAllowed) ?? ""
+ localVariablePath = localVariablePath.replacingOccurrences(of: "{type}", with: typePostEscape, options: .literal, range: nil)
+ let idPreEscape = "\(APIHelper.mapValueToPathItem(id))"
+ let idPostEscape = idPreEscape.addingPercentEncoding(withAllowedCharacters: .urlPathAllowed) ?? ""
+ localVariablePath = localVariablePath.replacingOccurrences(of: "{id}", with: idPostEscape, options: .literal, range: nil)
+ let namePreEscape = "\(APIHelper.mapValueToPathItem(name))"
+ let namePostEscape = namePreEscape.addingPercentEncoding(withAllowedCharacters: .urlPathAllowed) ?? ""
+ localVariablePath = localVariablePath.replacingOccurrences(of: "{name}", with: namePostEscape, options: .literal, range: nil)
+
+ let urlRequest = try makeRequest(
+ uriPath: localVariablePath,
+ httpMethod: "POST",
+ request: body
+ )
+ return try await send(request: urlRequest) {
+ try self.jsonDecoder.decode(StopRTMPBroadcastsResponse.self, from: $0)
+ }
+ }
+ /**
+ Stop RTMP broadcasts
+ - POST /video/call/{type}/{id}/rtmp_broadcasts/{name}/stop
+ - Stop RTMP broadcasts for the provided RTMP destinations Required permissions: - StopBroadcasting
+ - parameter type: (path)
+ - parameter id: (path)
+ - parameter name: (path)
+ - parameter body: (body)
+ - returns: RequestBuilder
*/
/**
Stop recording
- - parameter type: (path)
- - parameter id: (path)
+ - parameter type: (path)
+ - parameter id: (path)
- returns: StopRecordingResponse
*/
@@ -1203,18 +1462,18 @@ open class DefaultAPI: DefaultAPIEndpoints, @unchecked Sendable {
/**
Stop recording
- POST /video/call/{type}/{id}/stop_recording
- - Stops recording Sends events: - call.recording_stopped Required permissions: - StopRecording
- - parameter type: (path)
- - parameter id: (path)
- - returns: RequestBuilder
+ - Stops recording Sends events: - call.recording_stopped Required permissions: - StopRecording
+ - parameter type: (path)
+ - parameter id: (path)
+ - returns: RequestBuilder
*/
/**
Stop transcription
- - parameter type: (path)
- - parameter id: (path)
+ - parameter type: (path)
+ - parameter id: (path)
- returns: StopTranscriptionResponse
*/
@@ -1238,19 +1497,19 @@ open class DefaultAPI: DefaultAPIEndpoints, @unchecked Sendable {
/**
Stop transcription
- POST /video/call/{type}/{id}/stop_transcription
- - Stops transcription Sends events: - call.transcription_stopped Required permissions: - StopTranscription
- - parameter type: (path)
- - parameter id: (path)
- - returns: RequestBuilder
+ - Stops transcription Sends events: - call.transcription_stopped Required permissions: - StopTranscription
+ - parameter type: (path)
+ - parameter id: (path)
+ - returns: RequestBuilder
*/
/**
Unblocks user on a call
- - parameter type: (path)
- - parameter id: (path)
- - parameter unblockUserRequest: (body)
+ - parameter type: (path)
+ - parameter id: (path)
+ - parameter unblockUserRequest: (body)
- returns: UnblockUserResponse
*/
@@ -1275,20 +1534,20 @@ open class DefaultAPI: DefaultAPIEndpoints, @unchecked Sendable {
/**
Unblocks user on a call
- POST /video/call/{type}/{id}/unblock
- - Removes the block for a user on a call. The user will be able to join the call again. Sends events: - call.unblocked_user Required permissions: - BlockUser
- - parameter type: (path)
- - parameter id: (path)
- - parameter unblockUserRequest: (body)
- - returns: RequestBuilder
+ - Removes the block for a user on a call. The user will be able to join the call again. Sends events: - call.unblocked_user Required permissions: - BlockUser
+ - parameter type: (path)
+ - parameter id: (path)
+ - parameter unblockUserRequest: (body)
+ - returns: RequestBuilder
*/
/**
Update Call
- - parameter type: (path)
- - parameter id: (path)
- - parameter updateCallRequest: (body)
+ - parameter type: (path)
+ - parameter id: (path)
+ - parameter updateCallRequest: (body)
- returns: UpdateCallResponse
*/
@@ -1313,20 +1572,20 @@ open class DefaultAPI: DefaultAPIEndpoints, @unchecked Sendable {
/**
Update Call
- PATCH /video/call/{type}/{id}
- - Sends events: - call.updated Required permissions: - UpdateCall
- - parameter type: (path)
- - parameter id: (path)
- - parameter updateCallRequest: (body)
- - returns: RequestBuilder
+ - Sends events: - call.updated Required permissions: - UpdateCall
+ - parameter type: (path)
+ - parameter id: (path)
+ - parameter updateCallRequest: (body)
+ - returns: RequestBuilder
*/
/**
Update Call Member
- - parameter type: (path)
- - parameter id: (path)
- - parameter updateCallMembersRequest: (body)
+ - parameter type: (path)
+ - parameter id: (path)
+ - parameter updateCallMembersRequest: (body)
- returns: UpdateCallMembersResponse
*/
@@ -1351,20 +1610,20 @@ open class DefaultAPI: DefaultAPIEndpoints, @unchecked Sendable {
/**
Update Call Member
- POST /video/call/{type}/{id}/members
- - Sends events: - call.member_added - call.member_removed - call.member_updated Required permissions: - RemoveCallMember - UpdateCallMember - UpdateCallMemberRole
- - parameter type: (path)
- - parameter id: (path)
- - parameter updateCallMembersRequest: (body)
- - returns: RequestBuilder
+ - Sends events: - call.member_added - call.member_removed - call.member_updated Required permissions: - RemoveCallMember - UpdateCallMember - UpdateCallMemberRole
+ - parameter type: (path)
+ - parameter id: (path)
+ - parameter updateCallMembersRequest: (body)
+ - returns: RequestBuilder
*/
/**
Update user permissions
- - parameter type: (path)
- - parameter id: (path)
- - parameter updateUserPermissionsRequest: (body)
+ - parameter type: (path)
+ - parameter id: (path)
+ - parameter updateUserPermissionsRequest: (body)
- returns: UpdateUserPermissionsResponse
*/
@@ -1389,20 +1648,20 @@ open class DefaultAPI: DefaultAPIEndpoints, @unchecked Sendable {
/**
Update user permissions
- POST /video/call/{type}/{id}/user_permissions
- - Updates user permissions Sends events: - call.permissions_updated Required permissions: - UpdateCallPermissions
- - parameter type: (path)
- - parameter id: (path)
- - parameter updateUserPermissionsRequest: (body)
- - returns: RequestBuilder
+ - Updates user permissions Sends events: - call.permissions_updated Required permissions: - UpdateCallPermissions
+ - parameter type: (path)
+ - parameter id: (path)
+ - parameter updateUserPermissionsRequest: (body)
+ - returns: RequestBuilder
*/
/**
Pin
- - parameter type: (path)
- - parameter id: (path)
- - parameter pinRequest: (body)
+ - parameter type: (path)
+ - parameter id: (path)
+ - parameter pinRequest: (body)
- returns: PinResponse
*/
@@ -1427,20 +1686,20 @@ open class DefaultAPI: DefaultAPIEndpoints, @unchecked Sendable {
/**
Pin
- POST /video/call/{type}/{id}/pin
- - Pins a track for all users in the call. Required permissions: - PinCallTrack
- - parameter type: (path)
- - parameter id: (path)
- - parameter pinRequest: (body)
- - returns: RequestBuilder
+ - Pins a track for all users in the call. Required permissions: - PinCallTrack
+ - parameter type: (path)
+ - parameter id: (path)
+ - parameter pinRequest: (body)
+ - returns: RequestBuilder
*/
/**
Unpin
- - parameter type: (path)
- - parameter id: (path)
- - parameter unpinRequest: (body)
+ - parameter type: (path)
+ - parameter id: (path)
+ - parameter unpinRequest: (body)
- returns: UnpinResponse
*/
@@ -1462,16 +1721,6 @@ open class DefaultAPI: DefaultAPIEndpoints, @unchecked Sendable {
try self.jsonDecoder.decode(UnpinResponse.self, from: $0)
}
}
- /**
- Unpin
- - POST /video/call/{type}/{id}/unpin
- - Unpins a track for all users in the call. Required permissions: - PinCallTrack
- - parameter type: (path)
- - parameter id: (path)
- - parameter unpinRequest: (body)
- - returns: RequestBuilder
- */
-
}
protocol DefaultAPIEndpoints {
@@ -1492,13 +1741,22 @@ protocol DefaultAPIEndpoints {
func createGuest(createGuestRequest: CreateGuestRequest) async throws -> CreateGuestResponse
- func deleteDevice(id: String?, userId: String?) async throws -> ModelResponse
+ func deleteCall(type: String, id: String, deleteCallRequest: DeleteCallRequest) async throws -> DeleteCallResponse
+
+
+ func deleteDevice(id: String) async throws -> ModelResponse
+
+
+ func deleteRecording(type: String, id: String, session: String, filename: String) async throws -> DeleteRecordingResponse
+
+
+ func deleteTranscription(type: String, id: String, session: String, filename: String) async throws -> DeleteTranscriptionResponse
func endCall(type: String, id: String) async throws -> EndCallResponse
- func getCall(type: String, id: String, connectionId: String?, membersLimit: Int?, ring: Bool?, notify: Bool?) async throws -> GetCallResponse
+ func getCall(type: String, id: String, connectionId: String?, membersLimit: Int?, ring: Bool?, notify: Bool?, video: Bool?) async throws -> GetCallResponse
func getCallStats(type: String, id: String, session: String) async throws -> GetCallStatsResponse
@@ -1516,7 +1774,7 @@ protocol DefaultAPIEndpoints {
func joinCall(type: String, id: String, joinCallRequest: JoinCallRequest, connectionId: String?) async throws -> JoinCallResponse
- func listDevices(userId: String?) async throws -> ListDevicesResponse
+ func listDevices() async throws -> ListDevicesResponse
func listRecordings(type: String, id: String) async throws -> ListRecordingsResponse
@@ -1552,18 +1810,27 @@ protocol DefaultAPIEndpoints {
func startHLSBroadcasting(type: String, id: String) async throws -> StartHLSBroadcastingResponse
+ func startRTMPBroadcast(type: String, id: String, startRTMPBroadcastsRequest: StartRTMPBroadcastsRequest) async throws -> StartRTMPBroadcastsResponse
+
+
func startRecording(type: String, id: String, startRecordingRequest: StartRecordingRequest) async throws -> StartRecordingResponse
func startTranscription(type: String, id: String, startTranscriptionRequest: StartTranscriptionRequest) async throws -> StartTranscriptionResponse
+ func stopAllRTMPBroadcasts(type: String, id: String) async throws -> StopAllRTMPBroadcastsResponse
+
+
func stopHLSBroadcasting(type: String, id: String) async throws -> StopHLSBroadcastingResponse
func stopLive(type: String, id: String) async throws -> StopLiveResponse
+ func stopRTMPBroadcast(type: String, id: String, name: String, body: [String: RawJSON]) async throws -> StopRTMPBroadcastsResponse
+
+
func stopRecording(type: String, id: String) async throws -> StopRecordingResponse
diff --git a/Sources/StreamVideo/OpenApi/generated/Models/CallMissedEvent.swift b/Sources/StreamVideo/OpenApi/generated/Models/CallMissedEvent.swift
new file mode 100644
index 000000000..374688f87
--- /dev/null
+++ b/Sources/StreamVideo/OpenApi/generated/Models/CallMissedEvent.swift
@@ -0,0 +1,60 @@
+//
+// CallMissedEvent.swift
+//
+// Generated by openapi-generator
+// https://openapi-generator.tech
+//
+
+import Foundation
+/** This event is sent to call members who did not accept/reject/join the call to notify they missed the call */
+
+public struct CallMissedEvent: @unchecked Sendable, Event, Codable, JSONEncodable, Hashable, WSCallEvent {
+ public var call: CallResponse
+ public var callCid: String
+ public var createdAt: Date
+ /** List of members who missed the call */
+ public var members: [MemberResponse]
+ public var notifyUser: Bool
+ /** Call session ID */
+ public var sessionId: String
+ /** The type of event: \"call.notification\" in this case */
+ public var type: String = "call.missed"
+ public var user: UserResponse
+
+ public init(call: CallResponse, callCid: String, createdAt: Date, members: [MemberResponse], notifyUser: Bool, sessionId: String, type: String = "call.missed", user: UserResponse) {
+ self.call = call
+ self.callCid = callCid
+ self.createdAt = createdAt
+ self.members = members
+ self.notifyUser = notifyUser
+ self.sessionId = sessionId
+ self.type = type
+ self.user = user
+ }
+
+ public enum CodingKeys: String, CodingKey, CaseIterable {
+ case call
+ case callCid = "call_cid"
+ case createdAt = "created_at"
+ case members
+ case notifyUser = "notify_user"
+ case sessionId = "session_id"
+ case type
+ case user
+ }
+
+ // Encodable protocol methods
+
+ public func encode(to encoder: Encoder) throws {
+ var container = encoder.container(keyedBy: CodingKeys.self)
+ try container.encode(call, forKey: .call)
+ try container.encode(callCid, forKey: .callCid)
+ try container.encode(createdAt, forKey: .createdAt)
+ try container.encode(members, forKey: .members)
+ try container.encode(notifyUser, forKey: .notifyUser)
+ try container.encode(sessionId, forKey: .sessionId)
+ try container.encode(type, forKey: .type)
+ try container.encode(user, forKey: .user)
+ }
+}
+
diff --git a/Sources/StreamVideo/OpenApi/generated/Models/CallRtmpBroadcastStartedEvent.swift b/Sources/StreamVideo/OpenApi/generated/Models/CallRtmpBroadcastStartedEvent.swift
new file mode 100644
index 000000000..bfb6e30de
--- /dev/null
+++ b/Sources/StreamVideo/OpenApi/generated/Models/CallRtmpBroadcastStartedEvent.swift
@@ -0,0 +1,42 @@
+//
+// CallRtmpBroadcastStartedEvent.swift
+//
+// Generated by openapi-generator
+// https://openapi-generator.tech
+//
+
+import Foundation
+/** This event is sent when RTMP broadcast has started */
+
+public struct CallRtmpBroadcastStartedEvent: @unchecked Sendable, Event, Codable, JSONEncodable, Hashable, WSCallEvent {
+ public var callCid: String
+ public var createdAt: Date
+ public var name: String
+ /** The type of event: \"call.rtmp_broadcast_started\" in this case */
+ public var type: String = "call.rtmp_broadcast_started"
+
+ public init(callCid: String, createdAt: Date, name: String, type: String = "call.rtmp_broadcast_started") {
+ self.callCid = callCid
+ self.createdAt = createdAt
+ self.name = name
+ self.type = type
+ }
+
+ public enum CodingKeys: String, CodingKey, CaseIterable {
+ case callCid = "call_cid"
+ case createdAt = "created_at"
+ case name
+ case type
+ }
+
+ // Encodable protocol methods
+
+ public func encode(to encoder: Encoder) throws {
+ var container = encoder.container(keyedBy: CodingKeys.self)
+ try container.encode(callCid, forKey: .callCid)
+ try container.encode(createdAt, forKey: .createdAt)
+ try container.encode(name, forKey: .name)
+ try container.encode(type, forKey: .type)
+ }
+}
+
diff --git a/Sources/StreamVideo/OpenApi/generated/Models/CallRtmpBroadcastStoppedEvent.swift b/Sources/StreamVideo/OpenApi/generated/Models/CallRtmpBroadcastStoppedEvent.swift
new file mode 100644
index 000000000..23a390c36
--- /dev/null
+++ b/Sources/StreamVideo/OpenApi/generated/Models/CallRtmpBroadcastStoppedEvent.swift
@@ -0,0 +1,42 @@
+//
+// CallRtmpBroadcastStoppedEvent.swift
+//
+// Generated by openapi-generator
+// https://openapi-generator.tech
+//
+
+import Foundation
+/** This event is sent when RTMP broadcast has stopped */
+
+public struct CallRtmpBroadcastStoppedEvent: @unchecked Sendable, Event, Codable, JSONEncodable, Hashable, WSCallEvent {
+ public var callCid: String
+ public var createdAt: Date
+ public var name: String
+ /** The type of event: \"call.rtmp_broadcast_stopped\" in this case */
+ public var type: String = "call.rtmp_broadcast_stopped"
+
+ public init(callCid: String, createdAt: Date, name: String, type: String = "call.rtmp_broadcast_stopped") {
+ self.callCid = callCid
+ self.createdAt = createdAt
+ self.name = name
+ self.type = type
+ }
+
+ public enum CodingKeys: String, CodingKey, CaseIterable {
+ case callCid = "call_cid"
+ case createdAt = "created_at"
+ case name
+ case type
+ }
+
+ // Encodable protocol methods
+
+ public func encode(to encoder: Encoder) throws {
+ var container = encoder.container(keyedBy: CodingKeys.self)
+ try container.encode(callCid, forKey: .callCid)
+ try container.encode(createdAt, forKey: .createdAt)
+ try container.encode(name, forKey: .name)
+ try container.encode(type, forKey: .type)
+ }
+}
+
diff --git a/Sources/StreamVideo/OpenApi/generated/Models/CallUserMutedEvent.swift b/Sources/StreamVideo/OpenApi/generated/Models/CallUserMutedEvent.swift
new file mode 100644
index 000000000..8dae55d65
--- /dev/null
+++ b/Sources/StreamVideo/OpenApi/generated/Models/CallUserMutedEvent.swift
@@ -0,0 +1,46 @@
+//
+// CallUserMutedEvent.swift
+//
+// Generated by openapi-generator
+// https://openapi-generator.tech
+//
+
+import Foundation
+/** This event is sent when a call member is muted */
+
+public struct CallUserMutedEvent: @unchecked Sendable, Event, Codable, JSONEncodable, Hashable, WSCallEvent {
+ public var callCid: String
+ public var createdAt: Date
+ public var fromUserId: String
+ public var mutedUserIds: [String]
+ /** The type of event: \"call.user_muted\" in this case */
+ public var type: String = "call.user_muted"
+
+ public init(callCid: String, createdAt: Date, fromUserId: String, mutedUserIds: [String], type: String = "call.user_muted") {
+ self.callCid = callCid
+ self.createdAt = createdAt
+ self.fromUserId = fromUserId
+ self.mutedUserIds = mutedUserIds
+ self.type = type
+ }
+
+ public enum CodingKeys: String, CodingKey, CaseIterable {
+ case callCid = "call_cid"
+ case createdAt = "created_at"
+ case fromUserId = "from_user_id"
+ case mutedUserIds = "muted_user_ids"
+ case type
+ }
+
+ // Encodable protocol methods
+
+ public func encode(to encoder: Encoder) throws {
+ var container = encoder.container(keyedBy: CodingKeys.self)
+ try container.encode(callCid, forKey: .callCid)
+ try container.encode(createdAt, forKey: .createdAt)
+ try container.encode(fromUserId, forKey: .fromUserId)
+ try container.encode(mutedUserIds, forKey: .mutedUserIds)
+ try container.encode(type, forKey: .type)
+ }
+}
+
diff --git a/Sources/StreamVideo/OpenApi/generated/Models/DeleteCallRequest.swift b/Sources/StreamVideo/OpenApi/generated/Models/DeleteCallRequest.swift
new file mode 100644
index 000000000..5ae8074b5
--- /dev/null
+++ b/Sources/StreamVideo/OpenApi/generated/Models/DeleteCallRequest.swift
@@ -0,0 +1,30 @@
+//
+// DeleteCallRequest.swift
+//
+// Generated by openapi-generator
+// https://openapi-generator.tech
+//
+
+import Foundation
+
+
+public struct DeleteCallRequest: Codable, JSONEncodable, Hashable {
+ /** if true the call will be hard deleted along with all related data */
+ public var hard: Bool?
+
+ public init(hard: Bool? = nil) {
+ self.hard = hard
+ }
+
+ public enum CodingKeys: String, CodingKey, CaseIterable {
+ case hard
+ }
+
+ // Encodable protocol methods
+
+ public func encode(to encoder: Encoder) throws {
+ var container = encoder.container(keyedBy: CodingKeys.self)
+ try container.encodeIfPresent(hard, forKey: .hard)
+ }
+}
+
diff --git a/Sources/StreamVideo/OpenApi/generated/Models/DeleteCallResponse.swift b/Sources/StreamVideo/OpenApi/generated/Models/DeleteCallResponse.swift
new file mode 100644
index 000000000..6b7dae0a6
--- /dev/null
+++ b/Sources/StreamVideo/OpenApi/generated/Models/DeleteCallResponse.swift
@@ -0,0 +1,38 @@
+//
+// DeleteCallResponse.swift
+//
+// Generated by openapi-generator
+// https://openapi-generator.tech
+//
+
+import Foundation
+
+
+public struct DeleteCallResponse: Codable, JSONEncodable, Hashable {
+ public var call: CallResponse
+ /** Duration of the request in milliseconds */
+ public var duration: String
+ public var taskId: String?
+
+ public init(call: CallResponse, duration: String, taskId: String? = nil) {
+ self.call = call
+ self.duration = duration
+ self.taskId = taskId
+ }
+
+ public enum CodingKeys: String, CodingKey, CaseIterable {
+ case call
+ case duration
+ case taskId = "task_id"
+ }
+
+ // Encodable protocol methods
+
+ public func encode(to encoder: Encoder) throws {
+ var container = encoder.container(keyedBy: CodingKeys.self)
+ try container.encode(call, forKey: .call)
+ try container.encode(duration, forKey: .duration)
+ try container.encodeIfPresent(taskId, forKey: .taskId)
+ }
+}
+
diff --git a/Sources/StreamVideo/OpenApi/generated/Models/DeleteRecordingResponse.swift b/Sources/StreamVideo/OpenApi/generated/Models/DeleteRecordingResponse.swift
new file mode 100644
index 000000000..8bb982434
--- /dev/null
+++ b/Sources/StreamVideo/OpenApi/generated/Models/DeleteRecordingResponse.swift
@@ -0,0 +1,29 @@
+//
+// DeleteRecordingResponse.swift
+//
+// Generated by openapi-generator
+// https://openapi-generator.tech
+//
+
+import Foundation
+
+
+public struct DeleteRecordingResponse: Codable, JSONEncodable, Hashable {
+ public var duration: String
+
+ public init(duration: String) {
+ self.duration = duration
+ }
+
+ public enum CodingKeys: String, CodingKey, CaseIterable {
+ case duration
+ }
+
+ // Encodable protocol methods
+
+ public func encode(to encoder: Encoder) throws {
+ var container = encoder.container(keyedBy: CodingKeys.self)
+ try container.encode(duration, forKey: .duration)
+ }
+}
+
diff --git a/Sources/StreamVideo/OpenApi/generated/Models/DeleteTranscriptionResponse.swift b/Sources/StreamVideo/OpenApi/generated/Models/DeleteTranscriptionResponse.swift
new file mode 100644
index 000000000..62f5b5ef8
--- /dev/null
+++ b/Sources/StreamVideo/OpenApi/generated/Models/DeleteTranscriptionResponse.swift
@@ -0,0 +1,29 @@
+//
+// DeleteTranscriptionResponse.swift
+//
+// Generated by openapi-generator
+// https://openapi-generator.tech
+//
+
+import Foundation
+
+
+public struct DeleteTranscriptionResponse: Codable, JSONEncodable, Hashable {
+ public var duration: String
+
+ public init(duration: String) {
+ self.duration = duration
+ }
+
+ public enum CodingKeys: String, CodingKey, CaseIterable {
+ case duration
+ }
+
+ // Encodable protocol methods
+
+ public func encode(to encoder: Encoder) throws {
+ var container = encoder.container(keyedBy: CodingKeys.self)
+ try container.encode(duration, forKey: .duration)
+ }
+}
+
diff --git a/Sources/StreamVideo/OpenApi/generated/Models/GoLiveRequest.swift b/Sources/StreamVideo/OpenApi/generated/Models/GoLiveRequest.swift
index b1836568e..dc06eb434 100644
--- a/Sources/StreamVideo/OpenApi/generated/Models/GoLiveRequest.swift
+++ b/Sources/StreamVideo/OpenApi/generated/Models/GoLiveRequest.swift
@@ -12,13 +12,15 @@ public struct GoLiveRequest: Codable, JSONEncodable, Hashable {
public var recordingStorageName: String?
public var startHls: Bool?
public var startRecording: Bool?
+ public var startRtmpBroadcasts: Bool?
public var startTranscription: Bool?
public var transcriptionStorageName: String?
- public init(recordingStorageName: String? = nil, startHls: Bool? = nil, startRecording: Bool? = nil, startTranscription: Bool? = nil, transcriptionStorageName: String? = nil) {
+ public init(recordingStorageName: String? = nil, startHls: Bool? = nil, startRecording: Bool? = nil, startRtmpBroadcasts: Bool? = nil, startTranscription: Bool? = nil, transcriptionStorageName: String? = nil) {
self.recordingStorageName = recordingStorageName
self.startHls = startHls
self.startRecording = startRecording
+ self.startRtmpBroadcasts = startRtmpBroadcasts
self.startTranscription = startTranscription
self.transcriptionStorageName = transcriptionStorageName
}
@@ -27,6 +29,7 @@ public struct GoLiveRequest: Codable, JSONEncodable, Hashable {
case recordingStorageName = "recording_storage_name"
case startHls = "start_hls"
case startRecording = "start_recording"
+ case startRtmpBroadcasts = "start_rtmp_broadcasts"
case startTranscription = "start_transcription"
case transcriptionStorageName = "transcription_storage_name"
}
@@ -38,6 +41,7 @@ public struct GoLiveRequest: Codable, JSONEncodable, Hashable {
try container.encodeIfPresent(recordingStorageName, forKey: .recordingStorageName)
try container.encodeIfPresent(startHls, forKey: .startHls)
try container.encodeIfPresent(startRecording, forKey: .startRecording)
+ try container.encodeIfPresent(startRtmpBroadcasts, forKey: .startRtmpBroadcasts)
try container.encodeIfPresent(startTranscription, forKey: .startTranscription)
try container.encodeIfPresent(transcriptionStorageName, forKey: .transcriptionStorageName)
}
diff --git a/Sources/StreamVideo/OpenApi/generated/Models/LayoutSettings.swift b/Sources/StreamVideo/OpenApi/generated/Models/LayoutSettings.swift
new file mode 100644
index 000000000..1ec07c2f1
--- /dev/null
+++ b/Sources/StreamVideo/OpenApi/generated/Models/LayoutSettings.swift
@@ -0,0 +1,48 @@
+//
+// LayoutSettings.swift
+//
+// Generated by openapi-generator
+// https://openapi-generator.tech
+//
+
+import Foundation
+
+
+public struct LayoutSettings: Codable, JSONEncodable, Hashable {
+ public enum Name: String, Codable, CaseIterable {
+ case spotlight = "spotlight"
+ case grid = "grid"
+ case singleParticipant = "single-participant"
+ case mobile = "mobile"
+ case custom = "custom"
+ }
+ public var externalAppUrl: String?
+ public var externalCssUrl: String?
+ public var name: Name
+ public var options: [String: RawJSON]?
+
+ public init(externalAppUrl: String? = nil, externalCssUrl: String? = nil, name: Name, options: [String: RawJSON]? = nil) {
+ self.externalAppUrl = externalAppUrl
+ self.externalCssUrl = externalCssUrl
+ self.name = name
+ self.options = options
+ }
+
+ public enum CodingKeys: String, CodingKey, CaseIterable {
+ case externalAppUrl = "external_app_url"
+ case externalCssUrl = "external_css_url"
+ case name
+ case options
+ }
+
+ // Encodable protocol methods
+
+ public func encode(to encoder: Encoder) throws {
+ var container = encoder.container(keyedBy: CodingKeys.self)
+ try container.encodeIfPresent(externalAppUrl, forKey: .externalAppUrl)
+ try container.encodeIfPresent(externalCssUrl, forKey: .externalCssUrl)
+ try container.encode(name, forKey: .name)
+ try container.encodeIfPresent(options, forKey: .options)
+ }
+}
+
diff --git a/Sources/StreamVideo/OpenApi/generated/Models/StartRTMPBroadcastsRequest.swift b/Sources/StreamVideo/OpenApi/generated/Models/StartRTMPBroadcastsRequest.swift
new file mode 100644
index 000000000..46861c6af
--- /dev/null
+++ b/Sources/StreamVideo/OpenApi/generated/Models/StartRTMPBroadcastsRequest.swift
@@ -0,0 +1,53 @@
+//
+// StartRTMPBroadcastsRequest.swift
+//
+// Generated by openapi-generator
+// https://openapi-generator.tech
+//
+
+import Foundation
+
+
+public struct StartRTMPBroadcastsRequest: Codable, JSONEncodable, Hashable {
+ public var layout: LayoutSettings?
+ public var name: String
+ public var password: String?
+ public var quality: String?
+ public var streamKey: String?
+ public var streamUrl: String
+ public var username: String?
+
+ public init(layout: LayoutSettings? = nil, name: String, password: String? = nil, quality: String? = nil, streamKey: String? = nil, streamUrl: String, username: String? = nil) {
+ self.layout = layout
+ self.name = name
+ self.password = password
+ self.quality = quality
+ self.streamKey = streamKey
+ self.streamUrl = streamUrl
+ self.username = username
+ }
+
+ public enum CodingKeys: String, CodingKey, CaseIterable {
+ case layout
+ case name
+ case password
+ case quality
+ case streamKey = "stream_key"
+ case streamUrl = "stream_url"
+ case username
+ }
+
+ // Encodable protocol methods
+
+ public func encode(to encoder: Encoder) throws {
+ var container = encoder.container(keyedBy: CodingKeys.self)
+ try container.encodeIfPresent(layout, forKey: .layout)
+ try container.encode(name, forKey: .name)
+ try container.encodeIfPresent(password, forKey: .password)
+ try container.encodeIfPresent(quality, forKey: .quality)
+ try container.encodeIfPresent(streamKey, forKey: .streamKey)
+ try container.encode(streamUrl, forKey: .streamUrl)
+ try container.encodeIfPresent(username, forKey: .username)
+ }
+}
+
diff --git a/Sources/StreamVideo/OpenApi/generated/Models/StartRTMPBroadcastsResponse.swift b/Sources/StreamVideo/OpenApi/generated/Models/StartRTMPBroadcastsResponse.swift
new file mode 100644
index 000000000..a016247cf
--- /dev/null
+++ b/Sources/StreamVideo/OpenApi/generated/Models/StartRTMPBroadcastsResponse.swift
@@ -0,0 +1,30 @@
+//
+// StartRTMPBroadcastsResponse.swift
+//
+// Generated by openapi-generator
+// https://openapi-generator.tech
+//
+
+import Foundation
+
+
+public struct StartRTMPBroadcastsResponse: Codable, JSONEncodable, Hashable {
+ /** Duration of the request in milliseconds */
+ public var duration: String
+
+ public init(duration: String) {
+ self.duration = duration
+ }
+
+ public enum CodingKeys: String, CodingKey, CaseIterable {
+ case duration
+ }
+
+ // Encodable protocol methods
+
+ public func encode(to encoder: Encoder) throws {
+ var container = encoder.container(keyedBy: CodingKeys.self)
+ try container.encode(duration, forKey: .duration)
+ }
+}
+
diff --git a/Sources/StreamVideo/OpenApi/generated/Models/StopAllRTMPBroadcastsResponse.swift b/Sources/StreamVideo/OpenApi/generated/Models/StopAllRTMPBroadcastsResponse.swift
new file mode 100644
index 000000000..7c0a6beb7
--- /dev/null
+++ b/Sources/StreamVideo/OpenApi/generated/Models/StopAllRTMPBroadcastsResponse.swift
@@ -0,0 +1,30 @@
+//
+// StopAllRTMPBroadcastsResponse.swift
+//
+// Generated by openapi-generator
+// https://openapi-generator.tech
+//
+
+import Foundation
+
+
+public struct StopAllRTMPBroadcastsResponse: Codable, JSONEncodable, Hashable {
+ /** Duration of the request in milliseconds */
+ public var duration: String
+
+ public init(duration: String) {
+ self.duration = duration
+ }
+
+ public enum CodingKeys: String, CodingKey, CaseIterable {
+ case duration
+ }
+
+ // Encodable protocol methods
+
+ public func encode(to encoder: Encoder) throws {
+ var container = encoder.container(keyedBy: CodingKeys.self)
+ try container.encode(duration, forKey: .duration)
+ }
+}
+
diff --git a/Sources/StreamVideo/OpenApi/generated/Models/StopRTMPBroadcastsResponse.swift b/Sources/StreamVideo/OpenApi/generated/Models/StopRTMPBroadcastsResponse.swift
new file mode 100644
index 000000000..b75325b35
--- /dev/null
+++ b/Sources/StreamVideo/OpenApi/generated/Models/StopRTMPBroadcastsResponse.swift
@@ -0,0 +1,30 @@
+//
+// StopRTMPBroadcastsResponse.swift
+//
+// Generated by openapi-generator
+// https://openapi-generator.tech
+//
+
+import Foundation
+
+
+public struct StopRTMPBroadcastsResponse: Codable, JSONEncodable, Hashable {
+ /** Duration of the request in milliseconds */
+ public var duration: String
+
+ public init(duration: String) {
+ self.duration = duration
+ }
+
+ public enum CodingKeys: String, CodingKey, CaseIterable {
+ case duration
+ }
+
+ // Encodable protocol methods
+
+ public func encode(to encoder: Encoder) throws {
+ var container = encoder.container(keyedBy: CodingKeys.self)
+ try container.encode(duration, forKey: .duration)
+ }
+}
+
diff --git a/Sources/StreamVideo/OpenApi/generated/Models/WSEvent.swift b/Sources/StreamVideo/OpenApi/generated/Models/WSEvent.swift
index 507c4ec4e..29efbdc3b 100644
--- a/Sources/StreamVideo/OpenApi/generated/Models/WSEvent.swift
+++ b/Sources/StreamVideo/OpenApi/generated/Models/WSEvent.swift
@@ -28,6 +28,7 @@ public enum VideoEvent: Codable, JSONEncodable, Hashable {
case typeCallMemberRemovedEvent(CallMemberRemovedEvent)
case typeCallMemberUpdatedEvent(CallMemberUpdatedEvent)
case typeCallMemberUpdatedPermissionEvent(CallMemberUpdatedPermissionEvent)
+ case typeCallMissedEvent(CallMissedEvent)
case typeCallNotificationEvent(CallNotificationEvent)
case typeCallReactionEvent(CallReactionEvent)
case typeCallRecordingFailedEvent(CallRecordingFailedEvent)
@@ -36,6 +37,8 @@ public enum VideoEvent: Codable, JSONEncodable, Hashable {
case typeCallRecordingStoppedEvent(CallRecordingStoppedEvent)
case typeCallRejectedEvent(CallRejectedEvent)
case typeCallRingEvent(CallRingEvent)
+ case typeCallRtmpBroadcastStartedEvent(CallRtmpBroadcastStartedEvent)
+ case typeCallRtmpBroadcastStoppedEvent(CallRtmpBroadcastStoppedEvent)
case typeCallSessionEndedEvent(CallSessionEndedEvent)
case typeCallSessionParticipantJoinedEvent(CallSessionParticipantJoinedEvent)
case typeCallSessionParticipantLeftEvent(CallSessionParticipantLeftEvent)
@@ -45,14 +48,13 @@ public enum VideoEvent: Codable, JSONEncodable, Hashable {
case typeCallTranscriptionStartedEvent(CallTranscriptionStartedEvent)
case typeCallTranscriptionStoppedEvent(CallTranscriptionStoppedEvent)
case typeCallUpdatedEvent(CallUpdatedEvent)
- case typeCallUserMuted(CallUserMuted)
+ case typeCallUserMutedEvent(CallUserMutedEvent)
case typeClosedCaptionEvent(ClosedCaptionEvent)
case typeConnectedEvent(ConnectedEvent)
case typeConnectionErrorEvent(ConnectionErrorEvent)
case typePermissionRequestEvent(PermissionRequestEvent)
case typeUnblockedUserEvent(UnblockedUserEvent)
case typeUpdatedCallPermissionsEvent(UpdatedCallPermissionsEvent)
-
public var type: String {
switch self {
case .typeBlockedUserEvent(let value):
@@ -81,6 +83,8 @@ public enum VideoEvent: Codable, JSONEncodable, Hashable {
return value.type
case .typeCallMemberUpdatedPermissionEvent(let value):
return value.type
+ case .typeCallMissedEvent(let value):
+ return value.type
case .typeCallNotificationEvent(let value):
return value.type
case .typeCallReactionEvent(let value):
@@ -97,6 +101,10 @@ public enum VideoEvent: Codable, JSONEncodable, Hashable {
return value.type
case .typeCallRingEvent(let value):
return value.type
+ case .typeCallRtmpBroadcastStartedEvent(let value):
+ return value.type
+ case .typeCallRtmpBroadcastStoppedEvent(let value):
+ return value.type
case .typeCallSessionEndedEvent(let value):
return value.type
case .typeCallSessionParticipantJoinedEvent(let value):
@@ -115,7 +123,7 @@ public enum VideoEvent: Codable, JSONEncodable, Hashable {
return value.type
case .typeCallUpdatedEvent(let value):
return value.type
- case .typeCallUserMuted(let value):
+ case .typeCallUserMutedEvent(let value):
return value.type
case .typeClosedCaptionEvent(let value):
return value.type
@@ -123,16 +131,16 @@ public enum VideoEvent: Codable, JSONEncodable, Hashable {
return value.type
case .typeConnectionErrorEvent(let value):
return value.type
+ case .typeCustomVideoEvent(let value):
+ return value.type
+ case .typeHealthCheckEvent(let value):
+ return value.type
case .typePermissionRequestEvent(let value):
return value.type
case .typeUnblockedUserEvent(let value):
return value.type
case .typeUpdatedCallPermissionsEvent(let value):
return value.type
- case .typeHealthCheckEvent(let value):
- return value.type
- case .typeCustomVideoEvent(let value):
- return value.type
}
}
public var rawValue: Event {
@@ -163,6 +171,8 @@ public enum VideoEvent: Codable, JSONEncodable, Hashable {
return value
case .typeCallMemberUpdatedPermissionEvent(let value):
return value
+ case .typeCallMissedEvent(let value):
+ return value
case .typeCallNotificationEvent(let value):
return value
case .typeCallReactionEvent(let value):
@@ -179,6 +189,10 @@ public enum VideoEvent: Codable, JSONEncodable, Hashable {
return value
case .typeCallRingEvent(let value):
return value
+ case .typeCallRtmpBroadcastStartedEvent(let value):
+ return value
+ case .typeCallRtmpBroadcastStoppedEvent(let value):
+ return value
case .typeCallSessionEndedEvent(let value):
return value
case .typeCallSessionParticipantJoinedEvent(let value):
@@ -197,7 +211,7 @@ public enum VideoEvent: Codable, JSONEncodable, Hashable {
return value
case .typeCallUpdatedEvent(let value):
return value
- case .typeCallUserMuted(let value):
+ case .typeCallUserMutedEvent(let value):
return value
case .typeClosedCaptionEvent(let value):
return value
@@ -205,16 +219,16 @@ public enum VideoEvent: Codable, JSONEncodable, Hashable {
return value
case .typeConnectionErrorEvent(let value):
return value
+ case .typeCustomVideoEvent(let value):
+ return value
+ case .typeHealthCheckEvent(let value):
+ return value
case .typePermissionRequestEvent(let value):
return value
case .typeUnblockedUserEvent(let value):
return value
case .typeUpdatedCallPermissionsEvent(let value):
return value
- case .typeHealthCheckEvent(let value):
- return value
- case .typeCustomVideoEvent(let value):
- return value
}
}
public func encode(to encoder: Encoder) throws {
@@ -246,6 +260,8 @@ public enum VideoEvent: Codable, JSONEncodable, Hashable {
try container.encode(value)
case .typeCallMemberUpdatedPermissionEvent(let value):
try container.encode(value)
+ case .typeCallMissedEvent(let value):
+ try container.encode(value)
case .typeCallNotificationEvent(let value):
try container.encode(value)
case .typeCallReactionEvent(let value):
@@ -262,6 +278,10 @@ public enum VideoEvent: Codable, JSONEncodable, Hashable {
try container.encode(value)
case .typeCallRingEvent(let value):
try container.encode(value)
+ case .typeCallRtmpBroadcastStartedEvent(let value):
+ try container.encode(value)
+ case .typeCallRtmpBroadcastStoppedEvent(let value):
+ try container.encode(value)
case .typeCallSessionEndedEvent(let value):
try container.encode(value)
case .typeCallSessionParticipantJoinedEvent(let value):
@@ -280,7 +300,7 @@ public enum VideoEvent: Codable, JSONEncodable, Hashable {
try container.encode(value)
case .typeCallUpdatedEvent(let value):
try container.encode(value)
- case .typeCallUserMuted(let value):
+ case .typeCallUserMutedEvent(let value):
try container.encode(value)
case .typeClosedCaptionEvent(let value):
try container.encode(value)
@@ -288,16 +308,16 @@ public enum VideoEvent: Codable, JSONEncodable, Hashable {
try container.encode(value)
case .typeConnectionErrorEvent(let value):
try container.encode(value)
+ case .typeCustomVideoEvent(let value):
+ try container.encode(value)
+ case .typeHealthCheckEvent(let value):
+ try container.encode(value)
case .typePermissionRequestEvent(let value):
try container.encode(value)
case .typeUnblockedUserEvent(let value):
try container.encode(value)
case .typeUpdatedCallPermissionsEvent(let value):
try container.encode(value)
- case .typeHealthCheckEvent(let value):
- try container.encode(value)
- case .typeCustomVideoEvent(let value):
- try container.encode(value)
}
}
@@ -346,6 +366,9 @@ public enum VideoEvent: Codable, JSONEncodable, Hashable {
} else if dto.type == "call.member_updated_permission" {
let value = try container.decode(CallMemberUpdatedPermissionEvent.self)
self = .typeCallMemberUpdatedPermissionEvent(value)
+ } else if dto.type == "call.missed" {
+ let value = try container.decode(CallMissedEvent.self)
+ self = .typeCallMissedEvent(value)
} else if dto.type == "call.notification" {
let value = try container.decode(CallNotificationEvent.self)
self = .typeCallNotificationEvent(value)
@@ -376,6 +399,12 @@ public enum VideoEvent: Codable, JSONEncodable, Hashable {
} else if dto.type == "call.ring" {
let value = try container.decode(CallRingEvent.self)
self = .typeCallRingEvent(value)
+ } else if dto.type == "call.rtmp_broadcast_started" {
+ let value = try container.decode(CallRtmpBroadcastStartedEvent.self)
+ self = .typeCallRtmpBroadcastStartedEvent(value)
+ } else if dto.type == "call.rtmp_broadcast_stopped" {
+ let value = try container.decode(CallRtmpBroadcastStoppedEvent.self)
+ self = .typeCallRtmpBroadcastStoppedEvent(value)
} else if dto.type == "call.session_ended" {
let value = try container.decode(CallSessionEndedEvent.self)
self = .typeCallSessionEndedEvent(value)
@@ -407,8 +436,8 @@ public enum VideoEvent: Codable, JSONEncodable, Hashable {
let value = try container.decode(CallUpdatedEvent.self)
self = .typeCallUpdatedEvent(value)
} else if dto.type == "call.user_muted" {
- let value = try container.decode(CallUserMuted.self)
- self = .typeCallUserMuted(value)
+ let value = try container.decode(CallUserMutedEvent.self)
+ self = .typeCallUserMutedEvent(value)
} else if dto.type == "connection.error" {
let value = try container.decode(ConnectionErrorEvent.self)
self = .typeConnectionErrorEvent(value)
@@ -421,8 +450,7 @@ public enum VideoEvent: Codable, JSONEncodable, Hashable {
} else if dto.type == "health.check" {
let value = try container.decode(HealthCheckEvent.self)
self = .typeHealthCheckEvent(value)
- }
- else {
+ } else {
throw DecodingError.typeMismatch(Self.Type.self, .init(codingPath: decoder.codingPath, debugDescription: "Unable to decode instance of WSEvent"))
}
}
diff --git a/Sources/StreamVideo/StreamVideo.swift b/Sources/StreamVideo/StreamVideo.swift
index b633d3ea4..ee0c2b92e 100644
--- a/Sources/StreamVideo/StreamVideo.swift
+++ b/Sources/StreamVideo/StreamVideo.swift
@@ -272,7 +272,7 @@ public class StreamVideo: ObservableObject, @unchecked Sendable {
/// - Parameter id: the id of the device that will be deleted.
@discardableResult
public func deleteDevice(id: String) async throws -> ModelResponse {
- try await coordinatorClient.deleteDevice(id: id, userId: user.id)
+ try await coordinatorClient.deleteDevice(id: id)
}
/// Lists the devices registered for the user.
diff --git a/StreamVideo.xcodeproj/project.pbxproj b/StreamVideo.xcodeproj/project.pbxproj
index 5335505ee..868bc70b3 100644
--- a/StreamVideo.xcodeproj/project.pbxproj
+++ b/StreamVideo.xcodeproj/project.pbxproj
@@ -547,6 +547,7 @@
8415D3E1290B2AF2006E53CB /* outgoing.m4a in Resources */ = {isa = PBXBuildFile; fileRef = 8415D3E0290B2AF2006E53CB /* outgoing.m4a */; };
8415D3E3290BC882006E53CB /* Sounds.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8415D3E2290BC882006E53CB /* Sounds.swift */; };
841947982886D9CD0007B36E /* BundleExtensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 841947972886D9CD0007B36E /* BundleExtensions.swift */; };
+ 841AE18A2C738CCC005B6560 /* LayoutSettings.swift in Sources */ = {isa = PBXBuildFile; fileRef = 841AE1892C738CCC005B6560 /* LayoutSettings.swift */; };
841BAA312BD15CDE000C73E4 /* VideoQuality.swift in Sources */ = {isa = PBXBuildFile; fileRef = 841BAA182BD15CDC000C73E4 /* VideoQuality.swift */; };
841BAA322BD15CDE000C73E4 /* CallTranscriptionStoppedEvent.swift in Sources */ = {isa = PBXBuildFile; fileRef = 841BAA192BD15CDC000C73E4 /* CallTranscriptionStoppedEvent.swift */; };
841BAA332BD15CDE000C73E4 /* SFULocationResponse.swift in Sources */ = {isa = PBXBuildFile; fileRef = 841BAA1A2BD15CDC000C73E4 /* SFULocationResponse.swift */; };
@@ -673,6 +674,14 @@
8442993C294232360037232A /* IncomingCallView_iOS13.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8442993B294232360037232A /* IncomingCallView_iOS13.swift */; };
844299412942394C0037232A /* VideoView_iOS13.swift in Sources */ = {isa = PBXBuildFile; fileRef = 844299402942394C0037232A /* VideoView_iOS13.swift */; };
8446AF912A4D84F4002AB07B /* Retries_Tests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8446AF902A4D84F4002AB07B /* Retries_Tests.swift */; };
+ 844982472C738A830029734D /* DeleteRecordingResponse.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8449823F2C738A830029734D /* DeleteRecordingResponse.swift */; };
+ 844982482C738A830029734D /* DeleteCallResponse.swift in Sources */ = {isa = PBXBuildFile; fileRef = 844982402C738A830029734D /* DeleteCallResponse.swift */; };
+ 844982492C738A830029734D /* StartRTMPBroadcastsRequest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 844982412C738A830029734D /* StartRTMPBroadcastsRequest.swift */; };
+ 8449824A2C738A830029734D /* StopRTMPBroadcastsResponse.swift in Sources */ = {isa = PBXBuildFile; fileRef = 844982422C738A830029734D /* StopRTMPBroadcastsResponse.swift */; };
+ 8449824B2C738A830029734D /* DeleteCallRequest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 844982432C738A830029734D /* DeleteCallRequest.swift */; };
+ 8449824C2C738A830029734D /* DeleteTranscriptionResponse.swift in Sources */ = {isa = PBXBuildFile; fileRef = 844982442C738A830029734D /* DeleteTranscriptionResponse.swift */; };
+ 8449824D2C738A830029734D /* StartRTMPBroadcastsResponse.swift in Sources */ = {isa = PBXBuildFile; fileRef = 844982452C738A830029734D /* StartRTMPBroadcastsResponse.swift */; };
+ 8449824E2C738A830029734D /* StopAllRTMPBroadcastsResponse.swift in Sources */ = {isa = PBXBuildFile; fileRef = 844982462C738A830029734D /* StopAllRTMPBroadcastsResponse.swift */; };
844ADA652AD3F1AB00769F6A /* GoogleSignInSwift in Frameworks */ = {isa = PBXBuildFile; productRef = 844ADA642AD3F1AB00769F6A /* GoogleSignInSwift */; };
844ADA672AD3F21000769F6A /* GoogleSignIn.plist in Resources */ = {isa = PBXBuildFile; fileRef = 844ADA662AD3F21000769F6A /* GoogleSignIn.plist */; };
844ADA692AD3F78F00769F6A /* GoogleHelper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 844ADA682AD3F78F00769F6A /* GoogleHelper.swift */; };
@@ -861,6 +870,10 @@
84CBBE0B29228BA900D0DA61 /* StreamVideoTestCase.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8492B8722908024800006649 /* StreamVideoTestCase.swift */; };
84CC05892A530C3F00EE9815 /* SpeakerManager_Tests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84CC05882A530C3F00EE9815 /* SpeakerManager_Tests.swift */; };
84CC058B2A531B0B00EE9815 /* CallSettingsManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84CC058A2A531B0B00EE9815 /* CallSettingsManager.swift */; };
+ 84CD12162C73831000056640 /* CallRtmpBroadcastStartedEvent.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84CD12082C73830F00056640 /* CallRtmpBroadcastStartedEvent.swift */; };
+ 84CD12202C73831000056640 /* CallMissedEvent.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84CD12122C73831000056640 /* CallMissedEvent.swift */; };
+ 84CD12222C73831000056640 /* CallRtmpBroadcastStoppedEvent.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84CD12142C73831000056640 /* CallRtmpBroadcastStoppedEvent.swift */; };
+ 84CD12252C73840300056640 /* CallUserMutedEvent.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84CD12242C73840300056640 /* CallUserMutedEvent.swift */; };
84D114DA29F092E700BCCB0C /* CallController_Tests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84D114D929F092E700BCCB0C /* CallController_Tests.swift */; };
84D2E37629DC856D001D2118 /* CallMemberRemovedEvent.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84D2E37029DC856C001D2118 /* CallMemberRemovedEvent.swift */; };
84D2E37729DC856D001D2118 /* CallMemberUpdatedEvent.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84D2E37129DC856C001D2118 /* CallMemberUpdatedEvent.swift */; };
@@ -1566,6 +1579,7 @@
8415D3E0290B2AF2006E53CB /* outgoing.m4a */ = {isa = PBXFileReference; lastKnownFileType = file; path = outgoing.m4a; sourceTree = ""; };
8415D3E2290BC882006E53CB /* Sounds.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Sounds.swift; sourceTree = ""; };
841947972886D9CD0007B36E /* BundleExtensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BundleExtensions.swift; sourceTree = ""; };
+ 841AE1892C738CCC005B6560 /* LayoutSettings.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LayoutSettings.swift; sourceTree = ""; };
841BAA182BD15CDC000C73E4 /* VideoQuality.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = VideoQuality.swift; sourceTree = ""; };
841BAA192BD15CDC000C73E4 /* CallTranscriptionStoppedEvent.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CallTranscriptionStoppedEvent.swift; sourceTree = ""; };
841BAA1A2BD15CDC000C73E4 /* SFULocationResponse.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SFULocationResponse.swift; sourceTree = ""; };
@@ -1691,6 +1705,14 @@
8442993B294232360037232A /* IncomingCallView_iOS13.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IncomingCallView_iOS13.swift; sourceTree = ""; };
844299402942394C0037232A /* VideoView_iOS13.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VideoView_iOS13.swift; sourceTree = ""; };
8446AF902A4D84F4002AB07B /* Retries_Tests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Retries_Tests.swift; sourceTree = ""; };
+ 8449823F2C738A830029734D /* DeleteRecordingResponse.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DeleteRecordingResponse.swift; sourceTree = ""; };
+ 844982402C738A830029734D /* DeleteCallResponse.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DeleteCallResponse.swift; sourceTree = ""; };
+ 844982412C738A830029734D /* StartRTMPBroadcastsRequest.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = StartRTMPBroadcastsRequest.swift; sourceTree = ""; };
+ 844982422C738A830029734D /* StopRTMPBroadcastsResponse.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = StopRTMPBroadcastsResponse.swift; sourceTree = ""; };
+ 844982432C738A830029734D /* DeleteCallRequest.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DeleteCallRequest.swift; sourceTree = ""; };
+ 844982442C738A830029734D /* DeleteTranscriptionResponse.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DeleteTranscriptionResponse.swift; sourceTree = ""; };
+ 844982452C738A830029734D /* StartRTMPBroadcastsResponse.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = StartRTMPBroadcastsResponse.swift; sourceTree = ""; };
+ 844982462C738A830029734D /* StopAllRTMPBroadcastsResponse.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = StopAllRTMPBroadcastsResponse.swift; sourceTree = ""; };
844ADA662AD3F21000769F6A /* GoogleSignIn.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = GoogleSignIn.plist; sourceTree = ""; };
844ADA682AD3F78F00769F6A /* GoogleHelper.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GoogleHelper.swift; sourceTree = ""; };
844ADA6A2AD4439D00769F6A /* DemoCallsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DemoCallsView.swift; sourceTree = ""; };
@@ -1880,6 +1902,10 @@
84C4003E29E3F446007B69C2 /* ConnectedEvent.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ConnectedEvent.swift; sourceTree = ""; };
84CC05882A530C3F00EE9815 /* SpeakerManager_Tests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SpeakerManager_Tests.swift; sourceTree = ""; };
84CC058A2A531B0B00EE9815 /* CallSettingsManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CallSettingsManager.swift; sourceTree = ""; };
+ 84CD12082C73830F00056640 /* CallRtmpBroadcastStartedEvent.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CallRtmpBroadcastStartedEvent.swift; sourceTree = ""; };
+ 84CD12122C73831000056640 /* CallMissedEvent.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CallMissedEvent.swift; sourceTree = ""; };
+ 84CD12142C73831000056640 /* CallRtmpBroadcastStoppedEvent.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CallRtmpBroadcastStoppedEvent.swift; sourceTree = ""; };
+ 84CD12242C73840300056640 /* CallUserMutedEvent.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CallUserMutedEvent.swift; sourceTree = ""; };
84D114D929F092E700BCCB0C /* CallController_Tests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CallController_Tests.swift; sourceTree = ""; };
84D2E37029DC856C001D2118 /* CallMemberRemovedEvent.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CallMemberRemovedEvent.swift; sourceTree = ""; };
84D2E37129DC856C001D2118 /* CallMemberUpdatedEvent.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CallMemberUpdatedEvent.swift; sourceTree = ""; };
@@ -4058,6 +4084,19 @@
84DC383E29ADFCFC00946713 /* Models */ = {
isa = PBXGroup;
children = (
+ 841AE1892C738CCC005B6560 /* LayoutSettings.swift */,
+ 844982432C738A830029734D /* DeleteCallRequest.swift */,
+ 844982402C738A830029734D /* DeleteCallResponse.swift */,
+ 8449823F2C738A830029734D /* DeleteRecordingResponse.swift */,
+ 844982442C738A830029734D /* DeleteTranscriptionResponse.swift */,
+ 844982412C738A830029734D /* StartRTMPBroadcastsRequest.swift */,
+ 844982452C738A830029734D /* StartRTMPBroadcastsResponse.swift */,
+ 844982462C738A830029734D /* StopAllRTMPBroadcastsResponse.swift */,
+ 844982422C738A830029734D /* StopRTMPBroadcastsResponse.swift */,
+ 84CD12242C73840300056640 /* CallUserMutedEvent.swift */,
+ 84CD12122C73831000056640 /* CallMissedEvent.swift */,
+ 84CD12082C73830F00056640 /* CallRtmpBroadcastStartedEvent.swift */,
+ 84CD12142C73831000056640 /* CallRtmpBroadcastStoppedEvent.swift */,
845C09962C11AAA100F725B3 /* RejectCallRequest.swift */,
845C09822C0DEB5C00F725B3 /* LimitsSettingsRequest.swift */,
845C09832C0DEB5C00F725B3 /* LimitsSettingsResponse.swift */,
@@ -5250,6 +5289,7 @@
8454A3192AAB374B00A012C6 /* CallStatsReport.swift in Sources */,
84E5C51C2A013C440003A27A /* PushNotificationsConfig.swift in Sources */,
84A7E184288362DF00526C98 /* Atomic.swift in Sources */,
+ 8449824E2C738A830029734D /* StopAllRTMPBroadcastsResponse.swift in Sources */,
84D2E37729DC856D001D2118 /* CallMemberUpdatedEvent.swift in Sources */,
40149DD02B7E839500473176 /* AudioSessionProtocol.swift in Sources */,
8409465B29AF4EEC007AF5BF /* ListRecordingsResponse.swift in Sources */,
@@ -5316,11 +5356,13 @@
841BAA332BD15CDE000C73E4 /* SFULocationResponse.swift in Sources */,
84DC38D129ADFCFD00946713 /* Credentials.swift in Sources */,
84A7E1B02883E73100526C98 /* EventBatcher.swift in Sources */,
+ 84CD12222C73831000056640 /* CallRtmpBroadcastStoppedEvent.swift in Sources */,
40FB15212BF78FA100D5E580 /* Publisher+NextValue.swift in Sources */,
84BAD77C2A6BFF4300733156 /* BroadcastBufferReaderConnection.swift in Sources */,
84DC38DB29ADFCFD00946713 /* JSONDataEncoding.swift in Sources */,
40FB15112BF77D5800D5E580 /* StreamStateMachineStage.swift in Sources */,
8496A9A629CC500F00F15FF1 /* StreamVideoCaptureHandler.swift in Sources */,
+ 84CD12162C73831000056640 /* CallRtmpBroadcastStartedEvent.swift in Sources */,
8411925E28C5E5D00074EF88 /* DefaultRTCConfiguration.swift in Sources */,
8409465929AF4EEC007AF5BF /* SendReactionResponse.swift in Sources */,
8412903729DDD1ED00C70A6D /* UpdateCallMembersResponse.swift in Sources */,
@@ -5330,6 +5372,7 @@
406583992B877AB400B4F979 /* CIImage+Resize.swift in Sources */,
84EA5D4328C1E944004D3531 /* AudioSession.swift in Sources */,
841BAA382BD15CDE000C73E4 /* CallTimeline.swift in Sources */,
+ 8449824D2C738A830029734D /* StartRTMPBroadcastsResponse.swift in Sources */,
84DC38C629ADFCFD00946713 /* CallRejectedEvent.swift in Sources */,
84DC38B729ADFCFD00946713 /* CallRecordingStartedEvent.swift in Sources */,
40F161AB2A4C6B5C00846E3E /* ScreenSharingSession.swift in Sources */,
@@ -5349,6 +5392,7 @@
406AF2012AF3D98F00ED4D0C /* SimulatorScreenCapturer.swift in Sources */,
84A7E18A2883638200526C98 /* URLSessionWebSocketEngine.swift in Sources */,
40C4DF492C1C2C210035DBC2 /* Publisher+WeakAssign.swift in Sources */,
+ 844982472C738A830029734D /* DeleteRecordingResponse.swift in Sources */,
408679F72BD12F1000D027E0 /* AudioFilter.swift in Sources */,
8456E6D2287EC343004E180E /* ConsoleLogDestination.swift in Sources */,
84DC38A529ADFCFD00946713 /* SFUResponse.swift in Sources */,
@@ -5357,6 +5401,7 @@
4089378B2C062B17000EEB69 /* StreamUUIDFactory.swift in Sources */,
84DC38A829ADFCFD00946713 /* QueryCallsResponse.swift in Sources */,
840F59912A77FDCB00EF3EB2 /* HLSSettingsRequest.swift in Sources */,
+ 8449824C2C738A830029734D /* DeleteTranscriptionResponse.swift in Sources */,
842B8E1B2A2DFED900863A87 /* CallSessionStartedEvent.swift in Sources */,
40FA12F22B76AC8300CE3EC9 /* RTCCVPixelBuffer+Convenience.swift in Sources */,
8490032629D308A000AD9BB4 /* TranscriptionSettings.swift in Sources */,
@@ -5367,6 +5412,7 @@
84B9A56D29112F39004DE31A /* EndpointConfig.swift in Sources */,
8469593829BB6B4E00134EA0 /* GetEdgesResponse.swift in Sources */,
84DC389A29ADFCFD00946713 /* APIError.swift in Sources */,
+ 8449824B2C738A830029734D /* DeleteCallRequest.swift in Sources */,
84AF64DB287C7A2C0012A503 /* ErrorPayload.swift in Sources */,
84A7E1812883629700526C98 /* WebSocketPingController.swift in Sources */,
84DCA2232A39E432000C3411 /* AuthMiddlewares.swift in Sources */,
@@ -5391,6 +5437,7 @@
842E70D62B91BE1700D2D68B /* StartRecordingRequest.swift in Sources */,
840042CB2A701C2000917B30 /* BroadcastUtils.swift in Sources */,
844ECF4F2A33458A0023263C /* Member.swift in Sources */,
+ 84CD12252C73840300056640 /* CallUserMutedEvent.swift in Sources */,
84DC38AC29ADFCFD00946713 /* CallAcceptedEvent.swift in Sources */,
84FC2C2828AD350100181490 /* WebRTCEvents.swift in Sources */,
84DC38A129ADFCFD00946713 /* BlockUserResponse.swift in Sources */,
@@ -5402,6 +5449,7 @@
40FB15172BF77EA600D5E580 /* StreamCallStateMachine.swift in Sources */,
84DC38C829ADFCFD00946713 /* Device.swift in Sources */,
8412903629DDD1ED00C70A6D /* UpdateCallMembersRequest.swift in Sources */,
+ 8449824A2C738A830029734D /* StopRTMPBroadcastsResponse.swift in Sources */,
84CC058B2A531B0B00EE9815 /* CallSettingsManager.swift in Sources */,
84DC38B929ADFCFD00946713 /* MemberRequest.swift in Sources */,
84DC38BE29ADFCFD00946713 /* CallSettingsRequest.swift in Sources */,
@@ -5524,6 +5572,7 @@
847BE09C29DADE0100B55D21 /* Call.swift in Sources */,
848CCCEF2AB8ED8F002E83A2 /* ThumbnailsSettings.swift in Sources */,
40C4DF4D2C1C2CD80035DBC2 /* DefaultParticipantAutoLeavePolicy.swift in Sources */,
+ 844982492C738A830029734D /* StartRTMPBroadcastsRequest.swift in Sources */,
84FC2C2228ACF2E000181490 /* PeerConnection.swift in Sources */,
401A0F032AB1C1B600BE2DBD /* ThermalStateObserver.swift in Sources */,
84D2E37929DC856D001D2118 /* CallMemberAddedEvent.swift in Sources */,
@@ -5540,6 +5589,7 @@
84530C6C2A3C4E0700F2678E /* CallState.swift in Sources */,
84DC38C729ADFCFD00946713 /* UpdateCallResponse.swift in Sources */,
84A7E1AA2883E4AD00526C98 /* APIKey.swift in Sources */,
+ 841AE18A2C738CCC005B6560 /* LayoutSettings.swift in Sources */,
848CCCEE2AB8ED8F002E83A2 /* CallUserMuted.swift in Sources */,
435F01B32A501148009CD0BD /* OwnCapability+Identifiable.swift in Sources */,
40FB150F2BF77CEC00D5E580 /* StreamStateMachine.swift in Sources */,
@@ -5547,6 +5597,7 @@
84E4F7D1294CB5F300DD4CE3 /* ConnectionQuality.swift in Sources */,
848CCCE72AB8ED8F002E83A2 /* ThumbnailsSettingsRequest.swift in Sources */,
8206D8532A5FF3260099F5EC /* SystemEnvironment+Version.swift in Sources */,
+ 84CD12202C73831000056640 /* CallMissedEvent.swift in Sources */,
842B8E1C2A2DFED900863A87 /* AcceptCallResponse.swift in Sources */,
40F18B8E2BEBB65100ADF76E /* View+OptionalPublisher.swift in Sources */,
842B8E262A2DFED900863A87 /* CallParticipantResponse.swift in Sources */,
@@ -5572,6 +5623,7 @@
8490032429D308A000AD9BB4 /* RingSettings.swift in Sources */,
840F598E2A77FDCB00EF3EB2 /* BroadcastSettingsRequest.swift in Sources */,
842B8E272A2DFED900863A87 /* CallSessionEndedEvent.swift in Sources */,
+ 844982482C738A830029734D /* DeleteCallResponse.swift in Sources */,
84DC38CF29ADFCFD00946713 /* QueryCallsRequest.swift in Sources */,
84A7E1822883629700526C98 /* RetryStrategy.swift in Sources */,
841BAA402BD15CDE000C73E4 /* UserStats.swift in Sources */,
From b257cc68889a6dadddf11783c8fb0c6dcbd951a9 Mon Sep 17 00:00:00 2001
From: Martin Mitrevski
Date: Wed, 21 Aug 2024 10:48:03 +0200
Subject: [PATCH 25/38] Added muted property to announced tracks data (#490)
---
Sources/StreamVideo/protobuf/sfu/models/models.pb.swift | 8 ++++++++
1 file changed, 8 insertions(+)
diff --git a/Sources/StreamVideo/protobuf/sfu/models/models.pb.swift b/Sources/StreamVideo/protobuf/sfu/models/models.pb.swift
index 66d016a88..9f0e4f987 100644
--- a/Sources/StreamVideo/protobuf/sfu/models/models.pb.swift
+++ b/Sources/StreamVideo/protobuf/sfu/models/models.pb.swift
@@ -869,6 +869,8 @@ struct Stream_Video_Sfu_Models_TrackInfo {
var red: Bool = false
+ var muted: Bool = false
+
var unknownFields = SwiftProtobuf.UnknownStorage()
init() {}
@@ -1711,6 +1713,7 @@ extension Stream_Video_Sfu_Models_TrackInfo: SwiftProtobuf.Message, SwiftProtobu
7: .same(proto: "dtx"),
8: .same(proto: "stereo"),
9: .same(proto: "red"),
+ 10: .same(proto: "muted"),
]
mutating func decodeMessage(decoder: inout D) throws {
@@ -1726,6 +1729,7 @@ extension Stream_Video_Sfu_Models_TrackInfo: SwiftProtobuf.Message, SwiftProtobu
case 7: try { try decoder.decodeSingularBoolField(value: &self.dtx) }()
case 8: try { try decoder.decodeSingularBoolField(value: &self.stereo) }()
case 9: try { try decoder.decodeSingularBoolField(value: &self.red) }()
+ case 10: try { try decoder.decodeSingularBoolField(value: &self.muted) }()
default: break
}
}
@@ -1753,6 +1757,9 @@ extension Stream_Video_Sfu_Models_TrackInfo: SwiftProtobuf.Message, SwiftProtobu
if self.red != false {
try visitor.visitSingularBoolField(value: self.red, fieldNumber: 9)
}
+ if self.muted != false {
+ try visitor.visitSingularBoolField(value: self.muted, fieldNumber: 10)
+ }
try unknownFields.traverse(visitor: &visitor)
}
@@ -1764,6 +1771,7 @@ extension Stream_Video_Sfu_Models_TrackInfo: SwiftProtobuf.Message, SwiftProtobu
if lhs.dtx != rhs.dtx {return false}
if lhs.stereo != rhs.stereo {return false}
if lhs.red != rhs.red {return false}
+ if lhs.muted != rhs.muted {return false}
if lhs.unknownFields != rhs.unknownFields {return false}
return true
}
From c691dac5b3f5f5da302a6d238bf13fceaf227609 Mon Sep 17 00:00:00 2001
From: Alexey Alter-Pesotskiy
Date: Thu, 22 Aug 2024 11:33:34 +0100
Subject: [PATCH 26/38] [CI] Update publish release flow (#492)
---
.github/workflows/release-publish.yml | 30 ++------------------------
fastlane/Fastfile | 31 +++++++--------------------
2 files changed, 10 insertions(+), 51 deletions(-)
diff --git a/.github/workflows/release-publish.yml b/.github/workflows/release-publish.yml
index e1b18635a..b5986f7b7 100644
--- a/.github/workflows/release-publish.yml
+++ b/.github/workflows/release-publish.yml
@@ -1,24 +1,16 @@
name: "Publish new release"
on:
- pull_request:
+ push:
branches:
- main
- types:
- - closed
workflow_dispatch:
- inputs:
- version:
- description: 'Release version'
- type: string
- required: true
jobs:
release:
name: Publish new release
runs-on: macos-13
- if: ${{ github.event_name == 'workflow_dispatch' || github.event.pull_request.merged == true }} # only merged pull requests must trigger this job
steps:
- name: Connect Bot
uses: webfactory/ssh-agent@v0.7.0
@@ -29,28 +21,10 @@ jobs:
- uses: ./.github/actions/ruby-cache
- - name: Extract version from input (for workflow dispatch)
- if: ${{ github.event_name == 'workflow_dispatch' }}
- run: |
- BRANCH_NAME=$(git rev-parse --abbrev-ref HEAD)
- if [ "$BRANCH_NAME" != "main" ]; then
- echo "This workflow can only be run on the main branch."
- exit 1
- fi
- echo "RELEASE_VERSION=${{ github.event.inputs.version }}" >> $GITHUB_ENV
-
- - name: Extract version from branch name (for release branches)
- if: ${{ github.event_name == 'pull_request' && startsWith(github.event.pull_request.head.ref, 'release/') }}
- run: |
- BRANCH_NAME="${{ github.event.pull_request.head.ref }}"
- VERSION=${BRANCH_NAME#release/}
- echo "RELEASE_VERSION=$VERSION" >> $GITHUB_ENV
-
- name: "Fastlane - Publish Release"
- if: ${{ github.event_name == 'workflow_dispatch' || startsWith(github.event.pull_request.head.ref, 'release/') }}
env:
GITHUB_TOKEN: ${{ secrets.CI_BOT_GITHUB_TOKEN }}
COCOAPODS_TRUNK_TOKEN: ${{ secrets.COCOAPODS_TRUNK_TOKEN }}
MATCH_PASSWORD: ${{ secrets.MATCH_PASSWORD }}
APPSTORE_API_KEY: ${{ secrets.APPSTORE_API_KEY }}
- run: bundle exec fastlane publish_release version:${{ env.RELEASE_VERSION }} --verbose
+ run: bundle exec fastlane publish_release --verbose
diff --git a/fastlane/Fastfile b/fastlane/Fastfile
index 6af6c1841..274ddfc66 100644
--- a/fastlane/Fastfile
+++ b/fastlane/Fastfile
@@ -21,6 +21,7 @@ gci = ENV['GOOGLE_CLIENT_ID'] || ''
reversed_gci = gci.split('.').reverse.join('.')
is_localhost = !is_ci
@force_check = false
+swift_environment_path = File.absolute_path('../Sources/StreamVideo/Generated/SystemEnvironment+Version.swift')
swiftformat_excluded_paths = ["**/Generated", "**/generated", "**/protobuf", "**/OpenApi"]
swiftformat_source_paths = ["Sources", "DemoApp", "DemoAppUIKit", "StreamVideoTests", "StreamVideoSwiftUITests", "StreamVideoUIKitTests"]
@@ -43,7 +44,6 @@ desc "Release a new version"
lane :release do |options|
previous_version_number = last_git_tag
artifacts_path = File.absolute_path('../StreamVideoArtifacts.json')
- swift_environment_path = File.absolute_path('../Sources/StreamVideo/Generated/SystemEnvironment+Version.swift')
extra_changes = lambda do |release_version|
# Set the framework version on the artifacts
artifacts = JSON.parse(File.read(artifacts_path))
@@ -76,8 +76,12 @@ end
desc "Publish a new release to GitHub and CocoaPods"
lane :publish_release do |options|
- xcversion(version: '15.0.1')
+ release_version = File.read(swift_environment_path).match(/String\s+=\s+"([\d.]+)"/)[1]
+ UI.user_error!("Release #{release_version} has already been published.") if git_tag_exists(tag: release_version, remote: true)
+ UI.user_error!('Release version cannot be empty') if release_version.to_s.empty?
+ ensure_git_branch(branch: 'main')
+ xcversion(version: '15.0.1')
clean_products
build_xcframeworks
compress_frameworks
@@ -85,14 +89,14 @@ lane :publish_release do |options|
publish_ios_sdk(
skip_git_status_check: false,
- version: options[:version],
+ version: release_version,
sdk_names: sdk_names,
podspec_names: podspec_names,
github_repo: github_repo,
upload_assets: ['Products/StreamVideo.zip', 'Products/StreamVideoSwiftUI.zip', 'Products/StreamVideoUIKit.zip', 'Products/StreamVideo-All.zip']
)
- update_spm(version: options[:version])
+ update_spm(version: release_version)
merge_main_to_develop
end
@@ -583,25 +587,6 @@ lane :code_generation do
sync_xcodeproj_references
end
-private_lane :git_status do |options|
- UI.user_error!('Extension should be provided') unless options[:ext]
-
- untracked_files = sh('git status -s', log: false).split("\n").map(&:strip)
- UI.important("Git Status: #{untracked_files}")
-
- deleted_files = select_files_from(files: untracked_files, with_extension: options[:ext], that_start_with: 'D')
- added_files = select_files_from(files: untracked_files, with_extension: options[:ext], that_start_with: ['A', '??'])
- renamed_files = select_files_from(files: untracked_files, with_extension: options[:ext], that_start_with: 'R')
- modified_files = select_files_from(files: untracked_files, with_extension: options[:ext], that_start_with: 'M')
-
- renamed_files.each do |renamed_file|
- content = renamed_file.split.drop(1).join.split('->').map(&:strip)
- deleted_files << content.first
- added_files << content.last
- end
- { a: added_files, d: deleted_files, m: modified_files }
-end
-
lane :sync_xcodeproj_references do
Dir.chdir('..') do
project = Xcodeproj::Project.open(xcode_project)
From d5bf2ed60a1441240a1d1e7a3d667431bc6c30ff Mon Sep 17 00:00:00 2001
From: Ilias Pavlidakis
Date: Thu, 22 Aug 2024 13:58:26 +0300
Subject: [PATCH 27/38] Enhancement/custom call settings when joining from
callkit (#491)
---
.../06-advanced/03-callkit-integration.swift | 6 +++
.../StreamVideo/CallKit/CallKitAdapter.swift | 6 +++
.../StreamVideo/CallKit/CallKitService.swift | 4 +-
.../CallKit/CallKitAdapterTests.swift | 10 +++++
.../CallKit/CallKitServiceTests.swift | 38 +++++++++++++++++++
.../Controllers/CallsController_Tests.swift | 6 +--
StreamVideoTests/Mock/MockCall.swift | 24 +++++++++++-
StreamVideoTests/StreamVideoTestCase.swift | 6 +--
.../06-advanced/03-callkit-integration.mdx | 10 +++++
9 files changed, 100 insertions(+), 10 deletions(-)
diff --git a/DocumentationTests/DocumentationTests/DocumentationTests/06-advanced/03-callkit-integration.swift b/DocumentationTests/DocumentationTests/DocumentationTests/06-advanced/03-callkit-integration.swift
index 8a8ac510e..319bf4c94 100644
--- a/DocumentationTests/DocumentationTests/DocumentationTests/06-advanced/03-callkit-integration.swift
+++ b/DocumentationTests/DocumentationTests/DocumentationTests/06-advanced/03-callkit-integration.swift
@@ -139,6 +139,12 @@ fileprivate func content() {
}
}
+ container {
+ @Injected(\.callKitAdapter) var callKitAdapter
+
+ callKitAdapter.callSettings = CallSettings(audioOn: true, videoOn: false)
+ }
+
container {
@Injected(\.callKitService) var callKitService
diff --git a/Sources/StreamVideo/CallKit/CallKitAdapter.swift b/Sources/StreamVideo/CallKit/CallKitAdapter.swift
index ac6ee23df..6e9137f45 100644
--- a/Sources/StreamVideo/CallKit/CallKitAdapter.swift
+++ b/Sources/StreamVideo/CallKit/CallKitAdapter.swift
@@ -20,6 +20,12 @@ open class CallKitAdapter {
set { callKitService.iconTemplateImageData = newValue }
}
+ /// The callSettings to use when joining a call (after accepting it on CallKit)
+ /// default: nil
+ open var callSettings: CallSettings? {
+ didSet { callKitService.callSettings = callSettings }
+ }
+
/// The currently active StreamVideo client.
/// - Important: We need to update it whenever a user logins.
public var streamVideo: StreamVideo? {
diff --git a/Sources/StreamVideo/CallKit/CallKitService.swift b/Sources/StreamVideo/CallKit/CallKitService.swift
index 0c6d7ca49..a7978da6a 100644
--- a/Sources/StreamVideo/CallKit/CallKitService.swift
+++ b/Sources/StreamVideo/CallKit/CallKitService.swift
@@ -58,6 +58,8 @@ open class CallKitService: NSObject, CXProviderDelegate, @unchecked Sendable {
/// - Note: defaults to `false`.
open var supportsVideo: Bool = false
+ var callSettings: CallSettings?
+
/// The call controller used for managing calls.
open internal(set) lazy var callController = CXCallController()
/// The call provider responsible for handling call-related actions.
@@ -307,7 +309,7 @@ open class CallKitService: NSObject, CXProviderDelegate, @unchecked Sendable {
}
do {
- try await callToJoinEntry.call.join()
+ try await callToJoinEntry.call.join(callSettings: callSettings)
action.fulfill()
} catch {
callToJoinEntry.call.leave()
diff --git a/StreamVideoTests/CallKit/CallKitAdapterTests.swift b/StreamVideoTests/CallKit/CallKitAdapterTests.swift
index 530648a29..5e9c6cd26 100644
--- a/StreamVideoTests/CallKit/CallKitAdapterTests.swift
+++ b/StreamVideoTests/CallKit/CallKitAdapterTests.swift
@@ -67,6 +67,16 @@ final class CallKitAdapterTests: XCTestCase {
XCTAssertTrue(callKitPushNotificationAdapter.unregisterWasCalled)
}
+ // MARK: - callSettings updated
+
+ func test_callSettings_callKitServiceReceivedTheUpdatedValue() {
+ let callSettings = CallSettings(audioOn: false, videoOn: true)
+
+ subject.callSettings = callSettings
+
+ XCTAssertEqual(callKitService.callSettings, callSettings)
+ }
+
// MARK: - Private Helpers
private func makeStreamVideo() async throws -> StreamVideo {
diff --git a/StreamVideoTests/CallKit/CallKitServiceTests.swift b/StreamVideoTests/CallKit/CallKitServiceTests.swift
index 432628f04..4f6912c8e 100644
--- a/StreamVideoTests/CallKit/CallKitServiceTests.swift
+++ b/StreamVideoTests/CallKit/CallKitServiceTests.swift
@@ -276,6 +276,44 @@ final class CallKitServiceTests: XCTestCase, @unchecked Sendable {
}
}
+ // MARK: - accept
+
+ @MainActor
+ func test_accept_callWasJoinedAsExpected() async throws {
+ let customCallSettings = CallSettings(audioOn: false, videoOn: true)
+ subject.callSettings = customCallSettings
+
+ let firstCallUUID = UUID()
+ uuidFactory.getResult = firstCallUUID
+ let call = stubCall(response: defaultGetCallResponse)
+ subject.streamVideo = mockedStreamVideo
+
+ subject.reportIncomingCall(
+ cid,
+ localizedCallerName: localizedCallerName,
+ callerId: callerId
+ ) { _ in }
+
+ await waitExpectation(timeout: 1)
+
+ // Accept call
+ subject.provider(
+ callProvider,
+ perform: CXAnswerCallAction(
+ call: firstCallUUID
+ )
+ )
+
+ await waitExpectation(timeout: 1)
+
+ XCTAssertEqual(call.stubbedFunctionInput[.join]?.count, 1)
+ let input = try XCTUnwrap(call.stubbedFunctionInput[.join]?.first)
+ switch input {
+ case let .join(_, _, _, _, callSettings):
+ XCTAssertEqual(callSettings, customCallSettings)
+ }
+ }
+
// MARK: - callAccepted
@MainActor
diff --git a/StreamVideoTests/Controllers/CallsController_Tests.swift b/StreamVideoTests/Controllers/CallsController_Tests.swift
index 22cda991e..8ce56a0c3 100644
--- a/StreamVideoTests/Controllers/CallsController_Tests.swift
+++ b/StreamVideoTests/Controllers/CallsController_Tests.swift
@@ -75,11 +75,7 @@ final class CallsController_Tests: ControllerTestCase {
streamVideo?.state.connection = .disconnected()
try await waitForCallEvent()
streamVideo?.state.connection = .connected
- try await waitForCallEvent()
-
- // Then
- // Calls should be rewatched
- XCTAssertEqual(httpClient.requestCounter, 2)
+ try await fulfillment { self.httpClient.requestCounter == 2 }
}
func test_callsController_noWatchingCalls() async throws {
diff --git a/StreamVideoTests/Mock/MockCall.swift b/StreamVideoTests/Mock/MockCall.swift
index 1b336e642..7ff484e01 100644
--- a/StreamVideoTests/Mock/MockCall.swift
+++ b/StreamVideoTests/Mock/MockCall.swift
@@ -9,14 +9,27 @@ final class MockCall: Call, Mockable {
typealias FunctionKey = MockCallFunctionKey
- enum MockCallFunctionKey: Hashable {
+ enum MockCallFunctionKey: Hashable, CaseIterable {
case get
case accept
case join
}
+ enum MockCallFunctionInputKey {
+ case join(
+ create: Bool,
+ options: CreateCallOptions?,
+ ring: Bool,
+ notify: Bool,
+ callSettings: CallSettings?
+ )
+ }
+
var stubbedProperty: [String: Any]
var stubbedFunction: [FunctionKey: Any] = [:]
+ @Atomic var stubbedFunctionInput: [FunctionKey: [MockCallFunctionInputKey]] = MockCallFunctionKey
+ .allCases
+ .reduce(into: [FunctionKey: [MockCallFunctionInputKey]]()) { $0[$1] = [] }
override var state: CallState {
get { self[dynamicMember: \.state] }
@@ -66,6 +79,15 @@ final class MockCall: Call, Mockable {
notify: Bool = false,
callSettings: CallSettings? = nil
) async throws -> JoinCallResponse {
+ stubbedFunctionInput[.join]?.append(
+ .join(
+ create: create,
+ options: options,
+ ring: ring,
+ notify: notify,
+ callSettings: callSettings
+ )
+ )
if let stub = stubbedFunction[.join] as? JoinCallResponse {
return stub
} else {
diff --git a/StreamVideoTests/StreamVideoTestCase.swift b/StreamVideoTests/StreamVideoTestCase.swift
index 6edbfb631..537a1299b 100644
--- a/StreamVideoTests/StreamVideoTestCase.swift
+++ b/StreamVideoTests/StreamVideoTestCase.swift
@@ -7,14 +7,14 @@ import XCTest
open class StreamVideoTestCase: XCTestCase {
- public var streamVideo: StreamVideo!
+ public internal(set) var streamVideo: StreamVideo!
var httpClient: HTTPClient_Mock! = HTTPClient_Mock()
override open func setUp() {
super.setUp()
streamVideo = StreamVideo.mock(httpClient: httpClient)
}
-
+
override open func tearDown() async throws {
try await super.tearDown()
await streamVideo?.disconnect()
@@ -29,7 +29,7 @@ open class StreamVideoTestCase: XCTestCase {
}
// TODO: replace this with something a bit better
- func waitForCallEvent(nanoseconds: UInt64 = 500_000_000) async throws {
+ func waitForCallEvent(nanoseconds: UInt64 = 5_000_000_000) async throws {
try await Task.sleep(nanoseconds: nanoseconds)
}
}
diff --git a/docusaurus/docs/iOS/06-advanced/03-callkit-integration.mdx b/docusaurus/docs/iOS/06-advanced/03-callkit-integration.mdx
index a038cd70a..3fa064790 100644
--- a/docusaurus/docs/iOS/06-advanced/03-callkit-integration.mdx
+++ b/docusaurus/docs/iOS/06-advanced/03-callkit-integration.mdx
@@ -161,6 +161,16 @@ If none of the fields above are being set, the property will be an empty string.
- **created_by_display_name**
The property is always set and contains the name of the user who created the call.
+#### Call Settings when accepting a call
+
+Depending on your business logic, you may need users to join call with different `CallSettings`(e.g auioOn=true while videoOn=false). In order to achieve that when using the `CallKitAdapter` you can provide your custom `CallSettings` at any point before you receive a call:
+
+```swift
+@Injected(\.callKitAdapter) var callKitAdapter
+
+callKitAdapter.callSettings = CallSettings(audioOn: true, videoOn: false)
+```
+
#### Call's type suffix
Depending on the `Call` type `CallKit` adds a suffix in the push notification's subtitle (which contains the application name). That suffix can either be `Audio` or `Video`. `CallKitService` allows you to configure what the supported call types are, by setting the `CallKitService.supportsVideo` property like below:
From 03c3a308b68e700288438443df08bc0011c2e856 Mon Sep 17 00:00:00 2001
From: Ilias Pavlidakis
Date: Thu, 22 Aug 2024 18:50:32 +0300
Subject: [PATCH 28/38] [Fix]Ensure Call.state.startedAt is non-nil when
session is valid (#493)
---
Sources/StreamVideo/CallState.swift | 13 ++++++++++---
1 file changed, 10 insertions(+), 3 deletions(-)
diff --git a/Sources/StreamVideo/CallState.swift b/Sources/StreamVideo/CallState.swift
index b3b03c0fa..f6b486200 100644
--- a/Sources/StreamVideo/CallState.swift
+++ b/Sources/StreamVideo/CallState.swift
@@ -427,10 +427,17 @@ public class CallState: ObservableObject {
}
private func didUpdate(_ session: CallSessionResponse?) {
- if startedAt != session?.liveStartedAt {
- startedAt = session?.liveStartedAt
+ guard let session else { return }
+ if let startedAt = session.startedAt {
+ self.startedAt = startedAt
+ } else if let liveStartedAt = session.liveStartedAt {
+ startedAt = liveStartedAt
+ } else if startedAt == nil {
+ /// If we don't receive a value from the SFU we start the timer on the current date.
+ startedAt = Date()
}
- if session?.liveEndedAt != nil {
+
+ if session.liveEndedAt != nil {
resetTimer()
}
}
From 0e8e550ae55ece37ac633957c5970a403083e377 Mon Sep 17 00:00:00 2001
From: Martin Mitrevski
Date: Mon, 26 Aug 2024 17:09:08 +0200
Subject: [PATCH 29/38] Generated code for participant count session event
(#494)
---
Sources/StreamVideo/CallState.swift | 4 ++
.../Models/CallRtmpBroadcastFailedEvent.swift | 45 ++++++++++++++++
...SessionParticipantCountsUpdatedEvent.swift | 51 +++++++++++++++++++
.../Models/CallSessionResponse.swift | 11 +++-
.../OpenApi/generated/Models/WSEvent.swift | 21 +++++++-
StreamVideo.xcodeproj/project.pbxproj | 8 +++
.../Mock/MockResponseBuilder.swift | 2 +
.../Dummy/CallSessionResponse+Dummy.swift | 2 +
8 files changed, 142 insertions(+), 2 deletions(-)
create mode 100644 Sources/StreamVideo/OpenApi/generated/Models/CallRtmpBroadcastFailedEvent.swift
create mode 100644 Sources/StreamVideo/OpenApi/generated/Models/CallSessionParticipantCountsUpdatedEvent.swift
diff --git a/Sources/StreamVideo/CallState.swift b/Sources/StreamVideo/CallState.swift
index f6b486200..754785c1d 100644
--- a/Sources/StreamVideo/CallState.swift
+++ b/Sources/StreamVideo/CallState.swift
@@ -233,6 +233,10 @@ public class CallState: ObservableObject {
break
case .typeCallUserMutedEvent:
break
+ case .typeCallRtmpBroadcastFailedEvent:
+ break
+ case .typeCallSessionParticipantCountsUpdatedEvent:
+ break
}
}
diff --git a/Sources/StreamVideo/OpenApi/generated/Models/CallRtmpBroadcastFailedEvent.swift b/Sources/StreamVideo/OpenApi/generated/Models/CallRtmpBroadcastFailedEvent.swift
new file mode 100644
index 000000000..24e503d2a
--- /dev/null
+++ b/Sources/StreamVideo/OpenApi/generated/Models/CallRtmpBroadcastFailedEvent.swift
@@ -0,0 +1,45 @@
+//
+// CallRtmpBroadcastFailedEvent.swift
+//
+// Generated by openapi-generator
+// https://openapi-generator.tech
+//
+
+import Foundation
+/** This event is sent when a call RTMP broadcast has failed */
+
+public struct CallRtmpBroadcastFailedEvent: @unchecked Sendable, Event, Codable, JSONEncodable, Hashable, WSCallEvent {
+ /** The unique identifier for a call (:) */
+ public var callCid: String
+ /** Date/time of creation */
+ public var createdAt: Date
+ /** Name of the given RTMP broadcast */
+ public var name: String
+ /** The type of event: \"call.rtmp_broadcast_failed\" in this case */
+ public var type: String = "call.rtmp_broadcast_failed"
+
+ public init(callCid: String, createdAt: Date, name: String, type: String = "call.rtmp_broadcast_failed") {
+ self.callCid = callCid
+ self.createdAt = createdAt
+ self.name = name
+ self.type = type
+ }
+
+ public enum CodingKeys: String, CodingKey, CaseIterable {
+ case callCid = "call_cid"
+ case createdAt = "created_at"
+ case name
+ case type
+ }
+
+ // Encodable protocol methods
+
+ public func encode(to encoder: Encoder) throws {
+ var container = encoder.container(keyedBy: CodingKeys.self)
+ try container.encode(callCid, forKey: .callCid)
+ try container.encode(createdAt, forKey: .createdAt)
+ try container.encode(name, forKey: .name)
+ try container.encode(type, forKey: .type)
+ }
+}
+
diff --git a/Sources/StreamVideo/OpenApi/generated/Models/CallSessionParticipantCountsUpdatedEvent.swift b/Sources/StreamVideo/OpenApi/generated/Models/CallSessionParticipantCountsUpdatedEvent.swift
new file mode 100644
index 000000000..90ad4ce67
--- /dev/null
+++ b/Sources/StreamVideo/OpenApi/generated/Models/CallSessionParticipantCountsUpdatedEvent.swift
@@ -0,0 +1,51 @@
+//
+// CallSessionParticipantCountsUpdatedEvent.swift
+//
+// Generated by openapi-generator
+// https://openapi-generator.tech
+//
+
+import Foundation
+/** This event is sent when the participant counts in a call session are updated */
+
+public struct CallSessionParticipantCountsUpdatedEvent: @unchecked Sendable, Event, Codable, JSONEncodable, Hashable, WSCallEvent {
+ public var anonymousParticipantCount: Int
+ public var callCid: String
+ public var createdAt: Date
+ public var participantsCountByRole: [String: Int]
+ /** Call session ID */
+ public var sessionId: String
+ /** The type of event: \"call.session_participant_count_updated\" in this case */
+ public var type: String = "call.session_participant_count_updated"
+
+ public init(anonymousParticipantCount: Int, callCid: String, createdAt: Date, participantsCountByRole: [String: Int], sessionId: String, type: String = "call.session_participant_count_updated") {
+ self.anonymousParticipantCount = anonymousParticipantCount
+ self.callCid = callCid
+ self.createdAt = createdAt
+ self.participantsCountByRole = participantsCountByRole
+ self.sessionId = sessionId
+ self.type = type
+ }
+
+ public enum CodingKeys: String, CodingKey, CaseIterable {
+ case anonymousParticipantCount = "anonymous_participant_count"
+ case callCid = "call_cid"
+ case createdAt = "created_at"
+ case participantsCountByRole = "participants_count_by_role"
+ case sessionId = "session_id"
+ case type
+ }
+
+ // Encodable protocol methods
+
+ public func encode(to encoder: Encoder) throws {
+ var container = encoder.container(keyedBy: CodingKeys.self)
+ try container.encode(anonymousParticipantCount, forKey: .anonymousParticipantCount)
+ try container.encode(callCid, forKey: .callCid)
+ try container.encode(createdAt, forKey: .createdAt)
+ try container.encode(participantsCountByRole, forKey: .participantsCountByRole)
+ try container.encode(sessionId, forKey: .sessionId)
+ try container.encode(type, forKey: .type)
+ }
+}
+
diff --git a/Sources/StreamVideo/OpenApi/generated/Models/CallSessionResponse.swift b/Sources/StreamVideo/OpenApi/generated/Models/CallSessionResponse.swift
index ec8369917..504eda601 100644
--- a/Sources/StreamVideo/OpenApi/generated/Models/CallSessionResponse.swift
+++ b/Sources/StreamVideo/OpenApi/generated/Models/CallSessionResponse.swift
@@ -10,22 +10,26 @@ import Foundation
public struct CallSessionResponse: Codable, JSONEncodable, Hashable {
public var acceptedBy: [String: Date]
+ public var anonymousParticipantCount: Int?
public var endedAt: Date?
public var id: String
public var liveEndedAt: Date?
public var liveStartedAt: Date?
+ public var missedBy: [String: Date]?
public var participants: [CallParticipantResponse]
public var participantsCountByRole: [String: Int]
public var rejectedBy: [String: Date]
public var startedAt: Date?
public var timerEndsAt: Date?
- public init(acceptedBy: [String: Date], endedAt: Date? = nil, id: String, liveEndedAt: Date? = nil, liveStartedAt: Date? = nil, participants: [CallParticipantResponse], participantsCountByRole: [String: Int], rejectedBy: [String: Date], startedAt: Date? = nil, timerEndsAt: Date? = nil) {
+ public init(acceptedBy: [String: Date], anonymousParticipantCount: Int?, endedAt: Date? = nil, id: String, liveEndedAt: Date? = nil, liveStartedAt: Date? = nil, missedBy: [String: Date]?, participants: [CallParticipantResponse], participantsCountByRole: [String: Int], rejectedBy: [String: Date], startedAt: Date? = nil, timerEndsAt: Date? = nil) {
self.acceptedBy = acceptedBy
+ self.anonymousParticipantCount = anonymousParticipantCount
self.endedAt = endedAt
self.id = id
self.liveEndedAt = liveEndedAt
self.liveStartedAt = liveStartedAt
+ self.missedBy = missedBy
self.participants = participants
self.participantsCountByRole = participantsCountByRole
self.rejectedBy = rejectedBy
@@ -35,10 +39,12 @@ public struct CallSessionResponse: Codable, JSONEncodable, Hashable {
public enum CodingKeys: String, CodingKey, CaseIterable {
case acceptedBy = "accepted_by"
+ case anonymousParticipantCount = "anonymous_participant_count"
case endedAt = "ended_at"
case id
case liveEndedAt = "live_ended_at"
case liveStartedAt = "live_started_at"
+ case missedBy = "missed_by"
case participants
case participantsCountByRole = "participants_count_by_role"
case rejectedBy = "rejected_by"
@@ -51,10 +57,12 @@ public struct CallSessionResponse: Codable, JSONEncodable, Hashable {
public func encode(to encoder: Encoder) throws {
var container = encoder.container(keyedBy: CodingKeys.self)
try container.encode(acceptedBy, forKey: .acceptedBy)
+ try container.encodeIfPresent(anonymousParticipantCount, forKey: .anonymousParticipantCount)
try container.encodeIfPresent(endedAt, forKey: .endedAt)
try container.encode(id, forKey: .id)
try container.encodeIfPresent(liveEndedAt, forKey: .liveEndedAt)
try container.encodeIfPresent(liveStartedAt, forKey: .liveStartedAt)
+ try container.encodeIfPresent(missedBy, forKey: .missedBy)
try container.encode(participants, forKey: .participants)
try container.encode(participantsCountByRole, forKey: .participantsCountByRole)
try container.encode(rejectedBy, forKey: .rejectedBy)
@@ -62,3 +70,4 @@ public struct CallSessionResponse: Codable, JSONEncodable, Hashable {
try container.encodeIfPresent(timerEndsAt, forKey: .timerEndsAt)
}
}
+
diff --git a/Sources/StreamVideo/OpenApi/generated/Models/WSEvent.swift b/Sources/StreamVideo/OpenApi/generated/Models/WSEvent.swift
index 29efbdc3b..f8903974c 100644
--- a/Sources/StreamVideo/OpenApi/generated/Models/WSEvent.swift
+++ b/Sources/StreamVideo/OpenApi/generated/Models/WSEvent.swift
@@ -37,9 +37,11 @@ public enum VideoEvent: Codable, JSONEncodable, Hashable {
case typeCallRecordingStoppedEvent(CallRecordingStoppedEvent)
case typeCallRejectedEvent(CallRejectedEvent)
case typeCallRingEvent(CallRingEvent)
+ case typeCallRtmpBroadcastFailedEvent(CallRtmpBroadcastFailedEvent)
case typeCallRtmpBroadcastStartedEvent(CallRtmpBroadcastStartedEvent)
case typeCallRtmpBroadcastStoppedEvent(CallRtmpBroadcastStoppedEvent)
case typeCallSessionEndedEvent(CallSessionEndedEvent)
+ case typeCallSessionParticipantCountsUpdatedEvent(CallSessionParticipantCountsUpdatedEvent)
case typeCallSessionParticipantJoinedEvent(CallSessionParticipantJoinedEvent)
case typeCallSessionParticipantLeftEvent(CallSessionParticipantLeftEvent)
case typeCallSessionStartedEvent(CallSessionStartedEvent)
@@ -101,12 +103,16 @@ public enum VideoEvent: Codable, JSONEncodable, Hashable {
return value.type
case .typeCallRingEvent(let value):
return value.type
+ case .typeCallRtmpBroadcastFailedEvent(let value):
+ return value.type
case .typeCallRtmpBroadcastStartedEvent(let value):
return value.type
case .typeCallRtmpBroadcastStoppedEvent(let value):
return value.type
case .typeCallSessionEndedEvent(let value):
return value.type
+ case .typeCallSessionParticipantCountsUpdatedEvent(let value):
+ return value.type
case .typeCallSessionParticipantJoinedEvent(let value):
return value.type
case .typeCallSessionParticipantLeftEvent(let value):
@@ -189,12 +195,16 @@ public enum VideoEvent: Codable, JSONEncodable, Hashable {
return value
case .typeCallRingEvent(let value):
return value
+ case .typeCallRtmpBroadcastFailedEvent(let value):
+ return value
case .typeCallRtmpBroadcastStartedEvent(let value):
return value
case .typeCallRtmpBroadcastStoppedEvent(let value):
return value
case .typeCallSessionEndedEvent(let value):
return value
+ case .typeCallSessionParticipantCountsUpdatedEvent(let value):
+ return value
case .typeCallSessionParticipantJoinedEvent(let value):
return value
case .typeCallSessionParticipantLeftEvent(let value):
@@ -278,12 +288,16 @@ public enum VideoEvent: Codable, JSONEncodable, Hashable {
try container.encode(value)
case .typeCallRingEvent(let value):
try container.encode(value)
+ case .typeCallRtmpBroadcastFailedEvent(let value):
+ try container.encode(value)
case .typeCallRtmpBroadcastStartedEvent(let value):
try container.encode(value)
case .typeCallRtmpBroadcastStoppedEvent(let value):
try container.encode(value)
case .typeCallSessionEndedEvent(let value):
try container.encode(value)
+ case .typeCallSessionParticipantCountsUpdatedEvent(let value):
+ try container.encode(value)
case .typeCallSessionParticipantJoinedEvent(let value):
try container.encode(value)
case .typeCallSessionParticipantLeftEvent(let value):
@@ -399,6 +413,9 @@ public enum VideoEvent: Codable, JSONEncodable, Hashable {
} else if dto.type == "call.ring" {
let value = try container.decode(CallRingEvent.self)
self = .typeCallRingEvent(value)
+ } else if dto.type == "call.rtmp_broadcast_failed" {
+ let value = try container.decode(CallRtmpBroadcastFailedEvent.self)
+ self = .typeCallRtmpBroadcastFailedEvent(value)
} else if dto.type == "call.rtmp_broadcast_started" {
let value = try container.decode(CallRtmpBroadcastStartedEvent.self)
self = .typeCallRtmpBroadcastStartedEvent(value)
@@ -408,6 +425,9 @@ public enum VideoEvent: Codable, JSONEncodable, Hashable {
} else if dto.type == "call.session_ended" {
let value = try container.decode(CallSessionEndedEvent.self)
self = .typeCallSessionEndedEvent(value)
+ } else if dto.type == "call.session_participant_count_updated" {
+ let value = try container.decode(CallSessionParticipantCountsUpdatedEvent.self)
+ self = .typeCallSessionParticipantCountsUpdatedEvent(value)
} else if dto.type == "call.session_participant_joined" {
let value = try container.decode(CallSessionParticipantJoinedEvent.self)
self = .typeCallSessionParticipantJoinedEvent(value)
@@ -456,4 +476,3 @@ public enum VideoEvent: Codable, JSONEncodable, Hashable {
}
}
-
diff --git a/StreamVideo.xcodeproj/project.pbxproj b/StreamVideo.xcodeproj/project.pbxproj
index 868bc70b3..1af1e3221 100644
--- a/StreamVideo.xcodeproj/project.pbxproj
+++ b/StreamVideo.xcodeproj/project.pbxproj
@@ -891,6 +891,8 @@
84D6494429E9AD08002CA428 /* CallIngressResponse.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84D6494229E9AD08002CA428 /* CallIngressResponse.swift */; };
84D6494729E9F2D0002CA428 /* WebRTCClient_Tests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84D6494629E9F2D0002CA428 /* WebRTCClient_Tests.swift */; };
84D6E53A2B3AD10000D0056C /* RepeatingTimer_Tests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84D6E5392B3AD10000D0056C /* RepeatingTimer_Tests.swift */; };
+ 84D91E9C2C7CB0AA00B163A0 /* CallSessionParticipantCountsUpdatedEvent.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84D91E9A2C7CB0AA00B163A0 /* CallSessionParticipantCountsUpdatedEvent.swift */; };
+ 84D91E9D2C7CB0AA00B163A0 /* CallRtmpBroadcastFailedEvent.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84D91E9B2C7CB0AA00B163A0 /* CallRtmpBroadcastFailedEvent.swift */; };
84DC382D29A8B9EC00946713 /* CallParticipantMenuAction.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84DC382C29A8B9EC00946713 /* CallParticipantMenuAction.swift */; };
84DC382F29A8BB8D00946713 /* CallParticipantsInfoViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84DC382E29A8BB8D00946713 /* CallParticipantsInfoViewModel.swift */; };
84DC388F29ADFCFD00946713 /* CodableHelper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84DC383D29ADFCFB00946713 /* CodableHelper.swift */; };
@@ -1923,6 +1925,8 @@
84D6494229E9AD08002CA428 /* CallIngressResponse.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CallIngressResponse.swift; sourceTree = ""; };
84D6494629E9F2D0002CA428 /* WebRTCClient_Tests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WebRTCClient_Tests.swift; sourceTree = ""; };
84D6E5392B3AD10000D0056C /* RepeatingTimer_Tests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RepeatingTimer_Tests.swift; sourceTree = ""; };
+ 84D91E9A2C7CB0AA00B163A0 /* CallSessionParticipantCountsUpdatedEvent.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CallSessionParticipantCountsUpdatedEvent.swift; sourceTree = ""; };
+ 84D91E9B2C7CB0AA00B163A0 /* CallRtmpBroadcastFailedEvent.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CallRtmpBroadcastFailedEvent.swift; sourceTree = ""; };
84DC382C29A8B9EC00946713 /* CallParticipantMenuAction.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CallParticipantMenuAction.swift; sourceTree = ""; };
84DC382E29A8BB8D00946713 /* CallParticipantsInfoViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CallParticipantsInfoViewModel.swift; sourceTree = ""; };
84DC383D29ADFCFB00946713 /* CodableHelper.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CodableHelper.swift; sourceTree = ""; };
@@ -4084,6 +4088,8 @@
84DC383E29ADFCFC00946713 /* Models */ = {
isa = PBXGroup;
children = (
+ 84D91E9B2C7CB0AA00B163A0 /* CallRtmpBroadcastFailedEvent.swift */,
+ 84D91E9A2C7CB0AA00B163A0 /* CallSessionParticipantCountsUpdatedEvent.swift */,
841AE1892C738CCC005B6560 /* LayoutSettings.swift */,
844982432C738A830029734D /* DeleteCallRequest.swift */,
844982402C738A830029734D /* DeleteCallResponse.swift */,
@@ -5315,6 +5321,7 @@
8409465629AF4EEC007AF5BF /* CallReactionEvent.swift in Sources */,
84DCA21F2A39DA15000C3411 /* APIHelper.swift in Sources */,
84DC38D329ADFCFD00946713 /* CallEndedEvent.swift in Sources */,
+ 84D91E9D2C7CB0AA00B163A0 /* CallRtmpBroadcastFailedEvent.swift in Sources */,
84A737D028F4716E001A6769 /* models.pb.swift in Sources */,
846D16222A52B8D00036CE4C /* MicrophoneManager.swift in Sources */,
842E70DB2B91BE1700D2D68B /* ListTranscriptionsResponse.swift in Sources */,
@@ -5345,6 +5352,7 @@
8490DD1F298D39D9007E53D2 /* JsonEventDecoder.swift in Sources */,
40FB15192BF77EE700D5E580 /* StreamCallStateMachine+IdleStage.swift in Sources */,
84BAD7842A6C01AF00733156 /* BroadcastBufferReader.swift in Sources */,
+ 84D91E9C2C7CB0AA00B163A0 /* CallSessionParticipantCountsUpdatedEvent.swift in Sources */,
846E4AF529CDEA66003733AB /* ConnectUserDetailsRequest.swift in Sources */,
846D16262A52CE8C0036CE4C /* SpeakerManager.swift in Sources */,
841BAA3A2BD15CDE000C73E4 /* Location.swift in Sources */,
diff --git a/StreamVideoTests/Mock/MockResponseBuilder.swift b/StreamVideoTests/Mock/MockResponseBuilder.swift
index d4355c2de..61ee1bccd 100644
--- a/StreamVideoTests/Mock/MockResponseBuilder.swift
+++ b/StreamVideoTests/Mock/MockResponseBuilder.swift
@@ -175,10 +175,12 @@ class MockResponseBuilder {
) -> CallSessionResponse {
CallSessionResponse(
acceptedBy: acceptedBy,
+ anonymousParticipantCount: 0,
endedAt: liveEndedAt,
id: cid,
liveEndedAt: liveEndedAt,
liveStartedAt: liveStartedAt,
+ missedBy: [:],
participants: [],
participantsCountByRole: [:],
rejectedBy: rejectedBy,
diff --git a/StreamVideoTests/Utilities/Dummy/CallSessionResponse+Dummy.swift b/StreamVideoTests/Utilities/Dummy/CallSessionResponse+Dummy.swift
index a4b53b249..91490d7f8 100644
--- a/StreamVideoTests/Utilities/Dummy/CallSessionResponse+Dummy.swift
+++ b/StreamVideoTests/Utilities/Dummy/CallSessionResponse+Dummy.swift
@@ -19,10 +19,12 @@ extension CallSessionResponse {
) -> CallSessionResponse {
.init(
acceptedBy: acceptedBy,
+ anonymousParticipantCount: 0,
endedAt: endedAt,
id: id,
liveEndedAt: liveEndedAt,
liveStartedAt: liveStartedAt,
+ missedBy: [:],
participants: participants,
participantsCountByRole: participantsCountByRole,
rejectedBy: rejectedBy,
From 7544d4602d879f48c429bdcd42c8291ee7ff50d7 Mon Sep 17 00:00:00 2001
From: Martin Mitrevski
Date: Tue, 27 Aug 2024 17:21:11 +0200
Subject: [PATCH 30/38] Updated the docs structure and content (#495)
---
.../03-guides/02-joining-creating-calls.mdx | 66 ++++++++-
.../iOS/03-guides/07-dependency-injection.mdx | 54 -------
.../docs/iOS/03-guides/10-view-slots.mdx | 135 ------------------
.../docs/iOS/03-guides/11-call-lifecycle.mdx | 21 ---
.../iOS/03-guides/13-ui-customization.mdx | 35 -----
.../docs/iOS/04-ui-components/01-overview.mdx | 87 ++++++++++-
.../02-swiftui-vs-uikit.mdx} | 0
.../04-ui-components/04-customizing-views.mdx | 130 ++++++++++++++++-
...deo-renderer.mdx => 07-video-renderer.mdx} | 0
.../01-call-container.mdx | 0
.../{07-call => 08-call}/02-outgoing-call.mdx | 0
.../{07-call => 08-call}/03-incoming-call.mdx | 0
.../{07-call => 08-call}/04-active-call.mdx | 0
.../{07-call => 08-call}/05-call-controls.mdx | 0
.../{07-call => 08-call}/06-call-app-bar.mdx | 0
.../07-screen-share-content.mdx | 0
.../{07-call => 08-call}/_category_.json | 0
.../01-call-participant.mdx | 0
.../02-call-participants.mdx | 0
.../03-call-participants-info-menu.mdx | 0
.../04-local-video.mdx | 0
.../_category_.json | 0
.../02-sound-indicator.mdx | 0
.../{09-utility => 10-utility}/03-avatars.mdx | 0
.../04-connection-quality-indicator.mdx | 0
.../05-call-background.mdx | 0
.../_category_.json | 0
.../iOS/06-advanced/15-sdk-size-impact.mdx | 31 +---
.../16-migration-from-dolby.mdx} | 0
.../iOS/assets/call_member-grant-joincall.png | Bin 0 -> 116550 bytes
.../docs/iOS/assets/user-revoke-joincall.png | Bin 0 -> 122551 bytes
31 files changed, 282 insertions(+), 277 deletions(-)
delete mode 100644 docusaurus/docs/iOS/03-guides/07-dependency-injection.mdx
delete mode 100644 docusaurus/docs/iOS/03-guides/10-view-slots.mdx
delete mode 100644 docusaurus/docs/iOS/03-guides/11-call-lifecycle.mdx
delete mode 100644 docusaurus/docs/iOS/03-guides/13-ui-customization.mdx
rename docusaurus/docs/iOS/{03-guides/14-swiftui-vs-uikit.mdx => 04-ui-components/02-swiftui-vs-uikit.mdx} (100%)
rename docusaurus/docs/iOS/04-ui-components/{02-video-renderer.mdx => 07-video-renderer.mdx} (100%)
rename docusaurus/docs/iOS/04-ui-components/{07-call => 08-call}/01-call-container.mdx (100%)
rename docusaurus/docs/iOS/04-ui-components/{07-call => 08-call}/02-outgoing-call.mdx (100%)
rename docusaurus/docs/iOS/04-ui-components/{07-call => 08-call}/03-incoming-call.mdx (100%)
rename docusaurus/docs/iOS/04-ui-components/{07-call => 08-call}/04-active-call.mdx (100%)
rename docusaurus/docs/iOS/04-ui-components/{07-call => 08-call}/05-call-controls.mdx (100%)
rename docusaurus/docs/iOS/04-ui-components/{07-call => 08-call}/06-call-app-bar.mdx (100%)
rename docusaurus/docs/iOS/04-ui-components/{07-call => 08-call}/07-screen-share-content.mdx (100%)
rename docusaurus/docs/iOS/04-ui-components/{07-call => 08-call}/_category_.json (100%)
rename docusaurus/docs/iOS/04-ui-components/{08-participants => 09-participants}/01-call-participant.mdx (100%)
rename docusaurus/docs/iOS/04-ui-components/{08-participants => 09-participants}/02-call-participants.mdx (100%)
rename docusaurus/docs/iOS/04-ui-components/{08-participants => 09-participants}/03-call-participants-info-menu.mdx (100%)
rename docusaurus/docs/iOS/04-ui-components/{08-participants => 09-participants}/04-local-video.mdx (100%)
rename docusaurus/docs/iOS/04-ui-components/{08-participants => 09-participants}/_category_.json (100%)
rename docusaurus/docs/iOS/04-ui-components/{09-utility => 10-utility}/02-sound-indicator.mdx (100%)
rename docusaurus/docs/iOS/04-ui-components/{09-utility => 10-utility}/03-avatars.mdx (100%)
rename docusaurus/docs/iOS/04-ui-components/{09-utility => 10-utility}/04-connection-quality-indicator.mdx (100%)
rename docusaurus/docs/iOS/04-ui-components/{09-utility => 10-utility}/05-call-background.mdx (100%)
rename docusaurus/docs/iOS/04-ui-components/{09-utility => 10-utility}/_category_.json (100%)
rename docusaurus/docs/iOS/{03-guides/15-migration-from-dolby.mdx => 06-advanced/16-migration-from-dolby.mdx} (100%)
create mode 100644 docusaurus/docs/iOS/assets/call_member-grant-joincall.png
create mode 100644 docusaurus/docs/iOS/assets/user-revoke-joincall.png
diff --git a/docusaurus/docs/iOS/03-guides/02-joining-creating-calls.mdx b/docusaurus/docs/iOS/03-guides/02-joining-creating-calls.mdx
index d87d7cbf1..3452e47a8 100644
--- a/docusaurus/docs/iOS/03-guides/02-joining-creating-calls.mdx
+++ b/docusaurus/docs/iOS/03-guides/02-joining-creating-calls.mdx
@@ -31,6 +31,33 @@ let call = streamVideo.call(callType: "default", callId: "123")
let result = try await call.join()
```
+### Create and join a call
+
+For convenience, you can create and join a call in a single operation. One of the flags you can provide there is `create`.
+Set this to `true` if you want to enable creating new call. Set it to `false` if you only want to join an existing call.
+
+```swift
+try await call.join(create: true)
+```
+
+### Leave call
+
+To leave a call, you can use the `leave` method:
+
+```swift
+call.leave()
+```
+
+### End call
+
+Ending a call requires a [special permission](../permissions-and-moderation). This action terminates the call for everyone.
+
+```typescript
+try await call.end()
+```
+
+Only users with special permission can join an ended call.
+
### Call CRUD
Basic CRUD operations are available on the call object
@@ -131,4 +158,41 @@ You can filter the member list on these fields, and sort on the selected fields.
| `role` | The member's role. | No |
| `custom` | The custom data on the member. | No |
| `created_at` | When the member was created. | Yes |
-| `updated_at` | When the member was last updated. | No |
\ No newline at end of file
+| `updated_at` | When the member was last updated. | No |
+
+## Restricting access
+
+You can restrict access to a call by tweaking the [Call Type](../configuring-call-types/) permissions and roles.
+A typical use case is to restrict access to a call to a specific set of users -> call members.
+
+#### Step 1: Set up the roles and permissions
+
+On our [dashboard](https://dashboard.getstream.io/), navigate to the **Video & Audio -> Roles & Permissions** section and select the appropriate role and scope.
+In this example, we will use `my-call-type` scope.
+
+By default, all users unless specified otherwise, have the `user` role.
+
+We start by removing the `JoinCall` permission from the `user` role for the `my-call-type` scope.
+It will prevent regular users from joining a call of this type.
+
+![Revoke JoinCall for user role](../assets/user-revoke-joincall.png)
+
+Next, let's ensure that the `call_member` role has the `JoinCall` permission for the `my-call-type` scope.
+It will allow users with the `call_member` role to join a call of this type.
+
+![Grant JoinCall for call_member role](../assets/call_member-grant-joincall.png)
+
+Once this is set, we can proceed with setting up a `call` instance.
+
+#### Step 2: Set up the call
+
+```swift
+let call = streamVideo.call(callType: "my-call-type", callId: "my-call-id")
+try await call.create(members: [.init(role: "call_member", userId: "alice")])
+
+// and if necessary, to grant access to more users
+try await call.addMembers(members: [.init(role: "call_member", userId: "charlie")])
+
+// or, to remove access from some users
+try await call.removeMembers(ids: ["charlie"])
+```
\ No newline at end of file
diff --git a/docusaurus/docs/iOS/03-guides/07-dependency-injection.mdx b/docusaurus/docs/iOS/03-guides/07-dependency-injection.mdx
deleted file mode 100644
index d08991528..000000000
--- a/docusaurus/docs/iOS/03-guides/07-dependency-injection.mdx
+++ /dev/null
@@ -1,54 +0,0 @@
----
-title: Dependency Injection
----
-
-For injecting dependencies in the SwiftUI SDK, we are using an approach based on [this article](https://www.avanderlee.com/swift/dependency-injection/). It works similarly to the @Environment in SwiftUI, but it also allows access to the dependencies in non-view related code.
-
-When you initialize the SDK (by creating the `StreamVideoUI` object), all the dependencies are created too, and you can use them anywhere in your code. In order to access a particular type, you need to use the `@Injected(\.keyPath)` property wrapper:
-
-```swift
-@Injected(\.streamVideo) var streamVideo
-@Injected(\.fonts) var fonts
-@Injected(\.colors) var colors
-@Injected(\.images) var images
-@Injected(\.sounds) var sounds
-@Injected(\.utils) var utils
-```
-
-### Extending the DI with Custom Types
-
-In some cases, you might also need to extend our DI mechanism with your own types. For example, you may want to be able to access your custom types like this:
-
-```swift
-@Injected(\.customType) var customType
-```
-
-In order to achieve this, you first need to define your own `InjectionKey`, and define it's `currentValue`, which basically creates the new instance of your type.
-
-```swift
-class CustomType {
- // your custom logic here
-}
-
-struct CustomInjectionKey: InjectionKey {
- static var currentValue: CustomType = CustomType()
-}
-```
-
-Next, you need to extend our `InjectedValues` with your own custom type, by defining its getter and setter.
-
-```swift
-extension InjectedValues {
- /// Provides access to the `CustomType` instance in the views and view models.
- var customType: CustomType {
- get {
- Self[CustomInjectionKey.self]
- }
- set {
- Self[CustomInjectionKey.self] = newValue
- }
- }
-}
-```
-
-With these few simple steps, you can now access your custom functionality in both your app code and in your custom implementations of the views used throughout the SDK.
diff --git a/docusaurus/docs/iOS/03-guides/10-view-slots.mdx b/docusaurus/docs/iOS/03-guides/10-view-slots.mdx
deleted file mode 100644
index b41dea366..000000000
--- a/docusaurus/docs/iOS/03-guides/10-view-slots.mdx
+++ /dev/null
@@ -1,135 +0,0 @@
----
-title: View Slots
----
-
-You can swap certain views in the SwiftUI SDK, by implementing your own version of the `ViewFactory` protocol. Here's a list of the supported slots that can be swapped with your custom views.
-
-In most of these slots, the whole `CallViewModel` is provided, allowing you to update the state from these views.
-
-### Outgoing Call View
-
-In order to swap the outgoing call view, we will need to implement the `makeOutgoingCallView(viewModel: CallViewModel) -> some View` in the `ViewFactory`:
-
-```swift
-
-class CustomViewFactory: ViewFactory {
-
- func makeOutgoingCallView(viewModel: CallViewModel) -> some View {
- CustomOutgoingCallView(viewModel: viewModel)
- }
-
-}
-```
-
-### Incoming Call View
-
-Similarly, the incoming call view can be replaced by implementing the `makeIncomingCallView(viewModel: CallViewModel, callInfo: IncomingCall) -> some View` in the `ViewFactory`:
-
-```swift
-public func makeIncomingCallView(viewModel: CallViewModel, callInfo: IncomingCall) -> some View {
- CustomIncomingCallView(callInfo: callInfo, viewModel: viewModel)
-}
-```
-
-### Call View
-
-When the call state change to `.inCall`, the call view slot is shown. The default implementation provides several customizable parts, such as the video participants, the call controls (mute/unmute, hang up) and the top trailing view (which by default displays participants' info).
-
-In order to swap the default call view, you will need to implement the `makeCallView(viewModel: CallViewModel) -> some View`:
-
-```swift
-public func makeCallView(viewModel: CallViewModel) -> some View {
- CustomCallView(viewModel: viewModel)
-}
-```
-
-Apart from the main call view, you can also swap its building blocks.
-
-#### Call Controls View
-
-The call controls view by default displays controls for hiding/showing the camera, muting/unmuting the microphone, changing the camera source (front/back) and hanging up. If you want to change these controls, you will need to implement the `makeCallControlsView(viewModel: CallViewModel) -> some View` method:
-
-```swift
-func makeCallControlsView(viewModel: CallViewModel) -> some View {
- CustomCallControlsView(viewModel: viewModel)
-}
-```
-
-#### Video Participants View
-
-The video participants view slot presents the grid of users that are in the call. If you want to provide a different variation of the participants display, you will need to implement the `makeVideoParticipantsView` in the `ViewFactory`:
-
-```swift
-public func makeVideoParticipantsView(
- viewModel: CallViewModel,
- availableFrame: CGRect,
- onChangeTrackVisibility: @escaping @MainActor(CallParticipant, Bool) -> Void
-) -> some View {
- VideoParticipantsView(
- viewFactory: self,
- viewModel: viewModel,
- availableFrame: availableFrame,
- onChangeTrackVisibility: onChangeTrackVisibility
- )
-}
-```
-
-In the method, the following parameters are provided:
-
-- `viewModel` - the viewModel that manages the call.
-- `availableFrame` - the available frame for the participants view.
-- `onChangeTrackVisibility` - callback when the track changes its visibility.
-
-#### Video Participant View
-
-If you want to customize one particular participant view, you can change it via the method `makeVideoParticipantView`:
-
-```swift
-func makeVideoParticipantView(
- participant: CallParticipant,
- id: String,
- availableFrame: CGRect,
- contentMode: UIView.ContentMode,
- customData: [String: RawJSON],
- call: Call?
-) -> some View {
- VideoCallParticipantView(
- participant: participant,
- id: id,
- availableFrame: availableFrame,
- contentMode: contentMode,
- customData: customData,
- call: call
- )
-}
-```
-
-Additionally, you can change the modifier applied to the view, by implementing the `makeVideoCallParticipantModifier`:
-
-```swift
-public func makeVideoCallParticipantModifier(
- participant: CallParticipant,
- call: Call?,
- availableFrame: CGRect,
- ratio: CGFloat,
- showAllInfo: Bool
-) -> some ViewModifier {
- VideoCallParticipantModifier(
- participant: participant,
- call: call,
- availableFrame: availableFrame,
- ratio: ratio,
- showAllInfo: showAllInfo
- )
-}
-```
-
-#### Top View
-
-This is the view presented in the top area of the call view. By default, it displays a back button (to go in minimized mode) and a button that shows the list of participants. You can swap this view with your own implementation, by implementing the `makeCallTopView` in the `ViewFactory`:
-
-```swift
-public func makeCallTopView(viewModel: CallViewModel) -> some View {
- CallTopView(viewModel: viewModel)
-}
-```
diff --git a/docusaurus/docs/iOS/03-guides/11-call-lifecycle.mdx b/docusaurus/docs/iOS/03-guides/11-call-lifecycle.mdx
deleted file mode 100644
index a3123e210..000000000
--- a/docusaurus/docs/iOS/03-guides/11-call-lifecycle.mdx
+++ /dev/null
@@ -1,21 +0,0 @@
----
-title: Call Lifecycle
----
-
-## Call
-
-The `Call` object manages everything related to a particular call, such as creating, joining a call, performing actions for a user (mute/unmute, camera change, invite, etc) and listening to events.
-
-When a call starts, the iOS SDK communicates with our backend infrastructure, to find the best Selective Forwarding Unit (SFU) to host the call, based on the locations of the participants. It then establishes the connection with that SFU and provides updates on all events related to a call.
-
-You can create a new call via the `StreamVideo`'s method `func call(callType: String, callId: String)`.
-
-It's a lower-level component than the stateful `CallViewModel`, and it's suitable if you want to create your own presentation logic and state handling.
-
-The `Call` object should exist while the call is active. Afterwards, you should clean up all the state related to the call (provided you don't use our `CallViewModel`), by calling the `leave` method and de-allocating the instance.
-
-Every call has a call id and type. You can join a call with the same id as many times as you need. However, the call sends ringing events only the first time. If you want to receive ring events, you should always use a unique call id.
-
-## Web Socket Connection
-
-The web socket connection with our backend is established when the `StreamVideo` object is being created. If you go into the background, and come back, the SDK tries to re-establish this connection. The web socket connection is persisted in order to listen to events such as incoming calls, that can be presented in-app (if you're not using CallKit).
diff --git a/docusaurus/docs/iOS/03-guides/13-ui-customization.mdx b/docusaurus/docs/iOS/03-guides/13-ui-customization.mdx
deleted file mode 100644
index 06dfb1e90..000000000
--- a/docusaurus/docs/iOS/03-guides/13-ui-customization.mdx
+++ /dev/null
@@ -1,35 +0,0 @@
----
-title: UI customization
----
-
-## UI components vs Custom
-
-StreamVideo provides both ready made components to use directly in your app, as well as extension points that you can use to inject your own custom UI. If you just need the calling functionality and completely custom UI, you can use only our low-level client.
-
-Let's explore the different possibilities and how they would impact your app and the integration efforts.
-
-## Using only the low-level client
-
-If your app needs a completely custom UI and calling flow, you can use only our low-level client that implements the WebRTC protocol and communicates with our backend services. If you go with this approach, you can either use our stateful `CallViewModel` that allows you to observe the call state (list of participants, camera & microphone state, etc), or use our lower level `Call` object and implement your own presentation objects.
-
-Additionally, if you go with this approach, you can still use some components from our UI SDKs (if they fit your use-case), to facilitate your development. We have several examples for this in [our cookbook](../../ui-cookbook/overview).
-
-This approach would require some familiarity with our low-level client, and the highest development efforts compared to the other two options. On the other hand, it gives you a maximum flexibility to customize the calling flow according to your needs.
-
-In any case, our view components are highly customizable and flexible for many video/audio calling cases, and they can save big development efforts. Therefore, we recommend that you consider the other two options below, before deciding on starting from scratch.
-
-## Mix & match
-
-The mix & match approach is ideal if you need one of the standard calling flows, but with a possibility to replace parts of the UI with your own implementation. Our UI SDK allows you to completely swap views with your own custom interface elements.
-
-For example, if you are building an app with incoming / outgoing calling screens, you can easily swap only those screens. For building your custom screens, you can still reuse our lower level components.
-
-This approach provides a nice balance between levels of customization and development efforts. Find examples and extension slots to get started in our docs [here](../view-slots).
-
-## Simple theming
-
-If you need a standard video calling experience that needs to match the rest of your app's look and feel, you can use our theming customizations.
-
-This is the fastest way to add calling support to your app, just setup our video client and attach our `CallModifier` to your hosting view. You can change the fonts, colors, icons, texts and sounds used in the SDK, by interacting with our `Appearance` class.
-
-You can find more details about how to customize the theming [here](../../ui-components/overview).
diff --git a/docusaurus/docs/iOS/04-ui-components/01-overview.mdx b/docusaurus/docs/iOS/04-ui-components/01-overview.mdx
index 2a0a543be..a461382f1 100644
--- a/docusaurus/docs/iOS/04-ui-components/01-overview.mdx
+++ b/docusaurus/docs/iOS/04-ui-components/01-overview.mdx
@@ -5,10 +5,40 @@ description: Overview of the UI components
## Introduction
-The StreamVideo SDK provides UI components to facilitate the integration of video capabilities into your apps. You can either use our out-of-the-box solution (and customize theming and some views), or completely build your own UI, while reusing our lower-level components whenever you see them fit.
+The StreamVideo SDK provides UI components to facilitate the integration of video capabilities into your apps.
The UI components are provided in SwiftUI. If you use UIKit, we also provide UIKit wrappers, that can make it easier for you to integrate video in UIKit-based apps.
+## UI components vs Custom
+
+StreamVideo provides both ready made components to use directly in your app, as well as extension points that you can use to inject your own custom UI. If you only need the calling functionality to support your (custom built) UI, you can simply rely on our low-level client.
+
+Let's explore the different possibilities and how they would impact your app and the integration efforts.
+
+## Using only the low-level client
+
+If your app needs a completely custom UI and calling flow, you can use only our low-level client that implements the WebRTC protocol and communicates with our backend services. If you go with this approach, you can either use our stateful `CallViewModel` that allows you to observe the call state (list of participants, camera & microphone state, etc), or use our lower level `Call` object and implement your own presentation objects.
+
+Additionally, if you go with this approach, you can still use some components from our UI SDKs (if they fit your use-case), to facilitate your development. We have several examples for this in [our cookbook](../../ui-cookbook/overview).
+
+This approach would require some familiarity with our low-level client, and the highest development efforts compared to the other two options. On the other hand, it gives you maximum flexibility to customize the calling flow according to your needs.
+
+In any case, our view components are highly customizable and flexible for many video/audio calling cases, and they can save big development efforts. Therefore, we recommend that you consider the other two options below, before deciding on starting from scratch.
+
+## Mix & match
+
+The mix & match approach is ideal if you need one of the standard calling flows, but with a possibility to replace parts of the UI with your own implementation. Our UI SDK allows you to completely swap views with your own interface elements.
+
+For example, if you are building an app with incoming / outgoing calling screens, you can easily swap only those screens. For building your custom screens, you can still reuse our lower level components.
+
+This approach provides a nice balance between levels of customization and development efforts. Find examples and extension slots to get started in our docs [here](../view-slots).
+
+## Simple theming
+
+If you need a standard video calling experience that needs to match the rest of your app's look and feel, you can use our theming customizations.
+
+This is the fastest way to add calling support to your app, just setup our video client and attach our `CallModifier` to your hosting view. You can change the fonts, colors, icons, texts and sounds used in the SDK, by interacting with our `Appearance` class.
+
## StreamVideoUI object
The UI SDK provides a context provider object that allows simple access to functionalities exposed by the SDK, such as branding, presentation logic, icons, and the low-level video client.
@@ -55,3 +85,58 @@ Find more details on how to do this on [this page](../video-theme).
### Changing Views
Apart from the basic theming customizations, you can also swap certain views, with your implementation. You can find more details on how to do that on this [page](../customizing-views).
+
+## Dependency Injection
+
+For injecting dependencies in the SwiftUI SDK, we are using an approach based on [this article](https://www.avanderlee.com/swift/dependency-injection/). It works similarly to the @Environment in SwiftUI, but it also allows access to the dependencies in non-view related code.
+
+When you initialize the SDK (by creating the `StreamVideoUI` object), all the dependencies are created too, and you can use them anywhere in your code. In order to access a particular type, you need to use the `@Injected(\.keyPath)` property wrapper:
+
+```swift
+@Injected(\.streamVideo) var streamVideo
+@Injected(\.fonts) var fonts
+@Injected(\.colors) var colors
+@Injected(\.images) var images
+@Injected(\.sounds) var sounds
+@Injected(\.utils) var utils
+```
+
+### Extending the DI with Custom Types
+
+In some cases, you might also need to extend our DI mechanism with your own types. For example, you may want to be able to access your custom types like this:
+
+```swift
+@Injected(\.customType) var customType
+```
+
+In order to achieve this, you first need to define your own `InjectionKey`, and define it's `currentValue`, which basically creates the new instance of your type.
+
+```swift
+class CustomType {
+ // your custom logic here
+}
+
+struct CustomInjectionKey: InjectionKey {
+ static var currentValue: CustomType = CustomType()
+}
+```
+
+Next, you need to extend our `InjectedValues` with your own custom type, by defining its getter and setter.
+
+```swift
+extension InjectedValues {
+ /// Provides access to the `CustomType` instance in the views and view models.
+ var customType: CustomType {
+ get {
+ Self[CustomInjectionKey.self]
+ }
+ set {
+ Self[CustomInjectionKey.self] = newValue
+ }
+ }
+}
+```
+
+With these few simple steps, you can now access your custom functionality in both your app code and in your custom implementations of the views used throughout the SDK.
+
+Additionally, DI entries can be accessed by using the `InjectedValues[\.]` syntax (for example `InjectedValues[\.customType]`). This approach can be useful in case you want to override our default injected values.
\ No newline at end of file
diff --git a/docusaurus/docs/iOS/03-guides/14-swiftui-vs-uikit.mdx b/docusaurus/docs/iOS/04-ui-components/02-swiftui-vs-uikit.mdx
similarity index 100%
rename from docusaurus/docs/iOS/03-guides/14-swiftui-vs-uikit.mdx
rename to docusaurus/docs/iOS/04-ui-components/02-swiftui-vs-uikit.mdx
diff --git a/docusaurus/docs/iOS/04-ui-components/04-customizing-views.mdx b/docusaurus/docs/iOS/04-ui-components/04-customizing-views.mdx
index 9bf22050c..ef24738ca 100644
--- a/docusaurus/docs/iOS/04-ui-components/04-customizing-views.mdx
+++ b/docusaurus/docs/iOS/04-ui-components/04-customizing-views.mdx
@@ -35,4 +35,132 @@ var body: some View {
}
```
-For the full list of supported view slots that can be swapped, please refer to this [page](../../guides/view-slots).
+Here are all the slots available for customization in the SwiftUI SDK.
+
+### Outgoing Call View
+
+In order to swap the outgoing call view, we will need to implement the `makeOutgoingCallView(viewModel: CallViewModel) -> some View` in the `ViewFactory`:
+
+```swift
+
+class CustomViewFactory: ViewFactory {
+
+ func makeOutgoingCallView(viewModel: CallViewModel) -> some View {
+ CustomOutgoingCallView(viewModel: viewModel)
+ }
+
+}
+```
+
+### Incoming Call View
+
+Similarly, the incoming call view can be replaced by implementing the `makeIncomingCallView(viewModel: CallViewModel, callInfo: IncomingCall) -> some View` in the `ViewFactory`:
+
+```swift
+public func makeIncomingCallView(viewModel: CallViewModel, callInfo: IncomingCall) -> some View {
+ CustomIncomingCallView(callInfo: callInfo, viewModel: viewModel)
+}
+```
+
+### Call View
+
+When the call state change to `.inCall`, the call view slot is shown. The default implementation provides several customizable parts, such as the video participants, the call controls (mute/unmute, hang up) and the top trailing view (which by default displays participants' info).
+
+In order to swap the default call view, you will need to implement the `makeCallView(viewModel: CallViewModel) -> some View`:
+
+```swift
+public func makeCallView(viewModel: CallViewModel) -> some View {
+ CustomCallView(viewModel: viewModel)
+}
+```
+
+Apart from the main call view, you can also swap its building blocks.
+
+#### Call Controls View
+
+The call controls view by default displays controls for hiding/showing the camera, muting/unmuting the microphone, changing the camera source (front/back) and hanging up. If you want to change these controls, you will need to implement the `makeCallControlsView(viewModel: CallViewModel) -> some View` method:
+
+```swift
+func makeCallControlsView(viewModel: CallViewModel) -> some View {
+ CustomCallControlsView(viewModel: viewModel)
+}
+```
+
+#### Video Participants View
+
+The video participants view slot presents the grid of users that are in the call. If you want to provide a different variation of the participants display, you will need to implement the `makeVideoParticipantsView` in the `ViewFactory`:
+
+```swift
+public func makeVideoParticipantsView(
+ viewModel: CallViewModel,
+ availableFrame: CGRect,
+ onChangeTrackVisibility: @escaping @MainActor(CallParticipant, Bool) -> Void
+) -> some View {
+ VideoParticipantsView(
+ viewFactory: self,
+ viewModel: viewModel,
+ availableFrame: availableFrame,
+ onChangeTrackVisibility: onChangeTrackVisibility
+ )
+}
+```
+
+In the method, the following parameters are provided:
+
+- `viewModel` - the viewModel that manages the call.
+- `availableFrame` - the available frame for the participants view.
+- `onChangeTrackVisibility` - callback when the track changes its visibility.
+
+#### Video Participant View
+
+If you want to customize one particular participant view, you can change it via the method `makeVideoParticipantView`:
+
+```swift
+func makeVideoParticipantView(
+ participant: CallParticipant,
+ id: String,
+ availableFrame: CGRect,
+ contentMode: UIView.ContentMode,
+ customData: [String: RawJSON],
+ call: Call?
+) -> some View {
+ VideoCallParticipantView(
+ participant: participant,
+ id: id,
+ availableFrame: availableFrame,
+ contentMode: contentMode,
+ customData: customData,
+ call: call
+ )
+}
+```
+
+Additionally, you can change the modifier applied to the view, by implementing the `makeVideoCallParticipantModifier`:
+
+```swift
+public func makeVideoCallParticipantModifier(
+ participant: CallParticipant,
+ call: Call?,
+ availableFrame: CGRect,
+ ratio: CGFloat,
+ showAllInfo: Bool
+) -> some ViewModifier {
+ VideoCallParticipantModifier(
+ participant: participant,
+ call: call,
+ availableFrame: availableFrame,
+ ratio: ratio,
+ showAllInfo: showAllInfo
+ )
+}
+```
+
+#### Top View
+
+This is the view presented in the top area of the call view. By default, it displays a back button (to go in minimized mode) and a button that shows the list of participants. You can swap this view with your own implementation, by implementing the `makeCallTopView` in the `ViewFactory`:
+
+```swift
+public func makeCallTopView(viewModel: CallViewModel) -> some View {
+ CallTopView(viewModel: viewModel)
+}
+```
\ No newline at end of file
diff --git a/docusaurus/docs/iOS/04-ui-components/02-video-renderer.mdx b/docusaurus/docs/iOS/04-ui-components/07-video-renderer.mdx
similarity index 100%
rename from docusaurus/docs/iOS/04-ui-components/02-video-renderer.mdx
rename to docusaurus/docs/iOS/04-ui-components/07-video-renderer.mdx
diff --git a/docusaurus/docs/iOS/04-ui-components/07-call/01-call-container.mdx b/docusaurus/docs/iOS/04-ui-components/08-call/01-call-container.mdx
similarity index 100%
rename from docusaurus/docs/iOS/04-ui-components/07-call/01-call-container.mdx
rename to docusaurus/docs/iOS/04-ui-components/08-call/01-call-container.mdx
diff --git a/docusaurus/docs/iOS/04-ui-components/07-call/02-outgoing-call.mdx b/docusaurus/docs/iOS/04-ui-components/08-call/02-outgoing-call.mdx
similarity index 100%
rename from docusaurus/docs/iOS/04-ui-components/07-call/02-outgoing-call.mdx
rename to docusaurus/docs/iOS/04-ui-components/08-call/02-outgoing-call.mdx
diff --git a/docusaurus/docs/iOS/04-ui-components/07-call/03-incoming-call.mdx b/docusaurus/docs/iOS/04-ui-components/08-call/03-incoming-call.mdx
similarity index 100%
rename from docusaurus/docs/iOS/04-ui-components/07-call/03-incoming-call.mdx
rename to docusaurus/docs/iOS/04-ui-components/08-call/03-incoming-call.mdx
diff --git a/docusaurus/docs/iOS/04-ui-components/07-call/04-active-call.mdx b/docusaurus/docs/iOS/04-ui-components/08-call/04-active-call.mdx
similarity index 100%
rename from docusaurus/docs/iOS/04-ui-components/07-call/04-active-call.mdx
rename to docusaurus/docs/iOS/04-ui-components/08-call/04-active-call.mdx
diff --git a/docusaurus/docs/iOS/04-ui-components/07-call/05-call-controls.mdx b/docusaurus/docs/iOS/04-ui-components/08-call/05-call-controls.mdx
similarity index 100%
rename from docusaurus/docs/iOS/04-ui-components/07-call/05-call-controls.mdx
rename to docusaurus/docs/iOS/04-ui-components/08-call/05-call-controls.mdx
diff --git a/docusaurus/docs/iOS/04-ui-components/07-call/06-call-app-bar.mdx b/docusaurus/docs/iOS/04-ui-components/08-call/06-call-app-bar.mdx
similarity index 100%
rename from docusaurus/docs/iOS/04-ui-components/07-call/06-call-app-bar.mdx
rename to docusaurus/docs/iOS/04-ui-components/08-call/06-call-app-bar.mdx
diff --git a/docusaurus/docs/iOS/04-ui-components/07-call/07-screen-share-content.mdx b/docusaurus/docs/iOS/04-ui-components/08-call/07-screen-share-content.mdx
similarity index 100%
rename from docusaurus/docs/iOS/04-ui-components/07-call/07-screen-share-content.mdx
rename to docusaurus/docs/iOS/04-ui-components/08-call/07-screen-share-content.mdx
diff --git a/docusaurus/docs/iOS/04-ui-components/07-call/_category_.json b/docusaurus/docs/iOS/04-ui-components/08-call/_category_.json
similarity index 100%
rename from docusaurus/docs/iOS/04-ui-components/07-call/_category_.json
rename to docusaurus/docs/iOS/04-ui-components/08-call/_category_.json
diff --git a/docusaurus/docs/iOS/04-ui-components/08-participants/01-call-participant.mdx b/docusaurus/docs/iOS/04-ui-components/09-participants/01-call-participant.mdx
similarity index 100%
rename from docusaurus/docs/iOS/04-ui-components/08-participants/01-call-participant.mdx
rename to docusaurus/docs/iOS/04-ui-components/09-participants/01-call-participant.mdx
diff --git a/docusaurus/docs/iOS/04-ui-components/08-participants/02-call-participants.mdx b/docusaurus/docs/iOS/04-ui-components/09-participants/02-call-participants.mdx
similarity index 100%
rename from docusaurus/docs/iOS/04-ui-components/08-participants/02-call-participants.mdx
rename to docusaurus/docs/iOS/04-ui-components/09-participants/02-call-participants.mdx
diff --git a/docusaurus/docs/iOS/04-ui-components/08-participants/03-call-participants-info-menu.mdx b/docusaurus/docs/iOS/04-ui-components/09-participants/03-call-participants-info-menu.mdx
similarity index 100%
rename from docusaurus/docs/iOS/04-ui-components/08-participants/03-call-participants-info-menu.mdx
rename to docusaurus/docs/iOS/04-ui-components/09-participants/03-call-participants-info-menu.mdx
diff --git a/docusaurus/docs/iOS/04-ui-components/08-participants/04-local-video.mdx b/docusaurus/docs/iOS/04-ui-components/09-participants/04-local-video.mdx
similarity index 100%
rename from docusaurus/docs/iOS/04-ui-components/08-participants/04-local-video.mdx
rename to docusaurus/docs/iOS/04-ui-components/09-participants/04-local-video.mdx
diff --git a/docusaurus/docs/iOS/04-ui-components/08-participants/_category_.json b/docusaurus/docs/iOS/04-ui-components/09-participants/_category_.json
similarity index 100%
rename from docusaurus/docs/iOS/04-ui-components/08-participants/_category_.json
rename to docusaurus/docs/iOS/04-ui-components/09-participants/_category_.json
diff --git a/docusaurus/docs/iOS/04-ui-components/09-utility/02-sound-indicator.mdx b/docusaurus/docs/iOS/04-ui-components/10-utility/02-sound-indicator.mdx
similarity index 100%
rename from docusaurus/docs/iOS/04-ui-components/09-utility/02-sound-indicator.mdx
rename to docusaurus/docs/iOS/04-ui-components/10-utility/02-sound-indicator.mdx
diff --git a/docusaurus/docs/iOS/04-ui-components/09-utility/03-avatars.mdx b/docusaurus/docs/iOS/04-ui-components/10-utility/03-avatars.mdx
similarity index 100%
rename from docusaurus/docs/iOS/04-ui-components/09-utility/03-avatars.mdx
rename to docusaurus/docs/iOS/04-ui-components/10-utility/03-avatars.mdx
diff --git a/docusaurus/docs/iOS/04-ui-components/09-utility/04-connection-quality-indicator.mdx b/docusaurus/docs/iOS/04-ui-components/10-utility/04-connection-quality-indicator.mdx
similarity index 100%
rename from docusaurus/docs/iOS/04-ui-components/09-utility/04-connection-quality-indicator.mdx
rename to docusaurus/docs/iOS/04-ui-components/10-utility/04-connection-quality-indicator.mdx
diff --git a/docusaurus/docs/iOS/04-ui-components/09-utility/05-call-background.mdx b/docusaurus/docs/iOS/04-ui-components/10-utility/05-call-background.mdx
similarity index 100%
rename from docusaurus/docs/iOS/04-ui-components/09-utility/05-call-background.mdx
rename to docusaurus/docs/iOS/04-ui-components/10-utility/05-call-background.mdx
diff --git a/docusaurus/docs/iOS/04-ui-components/09-utility/_category_.json b/docusaurus/docs/iOS/04-ui-components/10-utility/_category_.json
similarity index 100%
rename from docusaurus/docs/iOS/04-ui-components/09-utility/_category_.json
rename to docusaurus/docs/iOS/04-ui-components/10-utility/_category_.json
diff --git a/docusaurus/docs/iOS/06-advanced/15-sdk-size-impact.mdx b/docusaurus/docs/iOS/06-advanced/15-sdk-size-impact.mdx
index d08e772d5..fb845a3ca 100644
--- a/docusaurus/docs/iOS/06-advanced/15-sdk-size-impact.mdx
+++ b/docusaurus/docs/iOS/06-advanced/15-sdk-size-impact.mdx
@@ -2,33 +2,6 @@
When developing a mobile app, one crucial performance metric is app size. An app’s size can be difficult to accurately measure with multiple variants and device spreads. Once measured, it’s even more difficult to understand and identify what’s contributing to size bloat.
-This document provides an analysis of the impact of adding StreamVideo and StreamVideoSwiftUI iOS SDKs to an existing mobile application. The analysis includes the size of the SDKs and the impact on the app's binary size.
+We track and update the SDK size on every commit to our `develop` branch. The sizes of all SDKs that are part of our video product are shown with badges, at the top of our GitHub [repo](https://github.com/GetStream/stream-video-swift).
-## SDK Information
-
-| | StreamVideo | StreamVideoSwiftUI |
-| ------------------- | :---------: | :----------------: |
-| **Download Size:** | 4.20 MB | 2.85 MB |
-| **Installed Size:** | 4.74 MB | 3.35 MB |
-
-### Analysis
-
-The following analysis was conducted using the `mdls -n kMDItemPhysicalSize` command in the Terminal after building the app with and without the SDK.
-
-1. **SwiftVideo**
-
- | | w/o framework | with framework | difference |
- | ------------------ | :-----------: | :------------: | :--------: |
- | App Size (Release) | 13_463_552 | 18_440_192 | 4_976_640 |
-
-2. **StreamVideoSwiftUI**
-
- | | w/o framework | with framework | difference |
- | ------------------ | :-----------: | :------------: | :--------: |
- | App Size (Release) | 13_463_552 | 16_986_112 | 3_522_560 |
-
-The tables above show the impact of integrating the SDKs on the app's binary size, in bytes.
-
-## Conclusion
-
-Based on the analysis conducted, both StreamVideo and StreamVideoSwiftUI SDKs are lightweight and optimized for optimal performance. We are confident that our Video SDKs will enhance the functionality of your app without compromising its performance or increasing its binary size significantly.
+Therefore, please check our repo to get the up-to date sizes of our video SDKs.
diff --git a/docusaurus/docs/iOS/03-guides/15-migration-from-dolby.mdx b/docusaurus/docs/iOS/06-advanced/16-migration-from-dolby.mdx
similarity index 100%
rename from docusaurus/docs/iOS/03-guides/15-migration-from-dolby.mdx
rename to docusaurus/docs/iOS/06-advanced/16-migration-from-dolby.mdx
diff --git a/docusaurus/docs/iOS/assets/call_member-grant-joincall.png b/docusaurus/docs/iOS/assets/call_member-grant-joincall.png
new file mode 100644
index 0000000000000000000000000000000000000000..d950f9b309891bc5334350ac3f258b57634794f8
GIT binary patch
literal 116550
zcmeFYWmFvL8b1gGf+WEuA-D$(4vo9JdvJGm2-dh0+=9CVw*+^BJ0w^G4K(iZZ|2U-
zy}LVS&wSXA+ozf;s_M1pedPB@hbziUyg|W7fq{W}BPA)S3TP@MnV9
z!H6#DH+->rsDJ9heM8h0@CpX=g(ILkAOrD42UdIMrk-h?gO?IbA_PH>leWu
zdD!N|j>*`?BPaT4a>4|!Hq>E~RJjNosbIhRhUwz)d;mGK_aYQk&5D87~Q#}T88>JbP
zR^KILiWUh!x#H$j{v1$^tjA0sEfTcRr;v>Jtchb3_Br#~A!ICdgI;|mE?N_lI(nU8
zgRAo+gmwbhYBq62@<@Ci8tAj@amZ*dDWTtw
z1z=vw@pYikX^Zj1b$72v$T*^sp1
ztT_Uqi->@=B+31H48edCJFk_K=?VAIJCOJ+>Yv6w6!7cI#mggjCrDvg1gt%f*>^8RLJ40U4d!m3lLD!Nf
z@UPqNMD8Jesm;Xa2QRf!$m}fDcLgk;Y+nlSz6l{*jE_o?hNo+l+nARXK9g*G~Vd;zJ%z2pWu!{A*NHqMPxMESOI@h%1j_UCwi_ulE#R{<=4;
z64j*uIqZeNtYca^6z{>3e|lN*+b1)S=lJC#2~u#NMI4OschR@LxVj*tj|ihM&O#q(
z5J$dS)ezah>HLtdK|DZ={zb!uF#cI4_k}K^`>*{ySSCRM4@7=)Bw^taq&JfyQ5dg!
zQ60tK0+}#_MM)ebQ4&H;$b>~dj|%RPZV#fE@YNxd3SE+h#j6Y=6kxT4@Ctgx&ks^#
zi>N6w%%C@jN_>5t6dw8&c^94yD=P~3>)9mbuJ$+l)o6~~;-50RuHWAK2BLm~QR#R2
zh&4)N{E40(U#5@cBQwV(1{z`x#$Z+Vn;Ihp1o#1-5+@#WaE9*oAt+i
z*Iqu4CzS|KZYnumyp;{6Od&FdY6VB$4FA_qgMin
z9GHsG>%*tRBg5YVFM1Pu%Bqu3QOXF0fwI!D1079+8`=q{#%IYlY
zPU
zxh5(*%5%#5H0Ct!AMBHoljV~6l8uuQhMkkIe
z4V=q&EXO3+qRhmNC!4={ezX0?`i+PoKP4Gghfb$l*E&|cO}(qJsIlBF;ZpTb`p|f3
z6_6TJh^j-aVO~1!m-QZyBmOq#Q_QbeO}2cy-ee4jtHk~-_|$d81?*Z4_M7?&M%dfl
zWtg{~X)BHeFYgcRD@?AJ_=|Vh7tBdQ;#cBL$**GDZ3FNZ@O$6MaxPf?H2e6;!sM+H
z4U4Y1$5PFNkO49u0B9p>W9#;K;Ml`PiGU`|esShgHPeQUqv&o)152J1A99mh913X@Ii
zw&6y^N6gh*)osd+%C*be=2Wc(z(aGhbMrPpj@KCk8E-fU8%ruPY*TCt4^4Sy##iM(
zHT|e^#x_g>(flsiSJJzry_CHpyVJfyLhI1@H;
zuQ^V+pg7YyTDf^0+JHx0t6VyFgk6!{(hjG#PKRg5lOe5>7e(*K7^Z9kbt0EF+|k@?
zy|cWl!&)TLC6XoZL?SVIG)K80Qpc~4GY>sy&c1$W)5x3mtL|z)>~L;(_Y`<<%pNLW
zwwx-#U&K$4!@$4V>9WqYKGwPFN99M*Wz`k-X!gkaboi){#xZKMW4AK`GXUfGJul#j
zo@q{YZb*>+BSj5;4WA?{4YP&s&xcRbzeay8{dz=iirXWl7D3MYoi`%Vwh(H=*cQ4<
zyo15PTEVVM$;7Poij~D5Z>6D3kKaAxLc}YwC}1m0P)<~CDn^ZZh2P|*JK@oEQn+a^Ta*6LwL2vI7R#BMD5HQQoOMqSpOk^y
zR$~cIo~<~YHEvwKS{eeXYqoA?@_1}lYuE2Y^GA5H3{~ilh%!&(Porb?uD`FNt-FP%
z|Katc{NU$-+#J^$rzi4)kHWaGMa<3dK3N@<#kd<%~znEnivb%A|Uzocb!V
zr*HXH+-GD2xe)DRiB35qh8wZd+`*=jy4{|nf)9vARpG@Wb}TOal?#Ty|Up&Ra^-(l>$E}yQp_9xU$
zs4egvuC)!Fak3aNZSDLjwUY;HrxFfl{K%$lxwKtVi>PJ4!PicQsS6*)OzCViL3-nIk
zKL9t*fM>oy5WFe9b09Ly?#BMtk0~#rUbrGMpsEw*6Vh4>;uo=>bDFWcaTc<<5~1>}
zOdYKH>;ik@2_@uW)QP6~8_&76ukSa5s3R0!XJTg^@FaWgD~%MS@DvYZch2E2FZog3
zkKWY(FjvSi&gOAk1Km%)(#JzJFwwPX-|{QX8>>A039;)UwsN<(Z$5BrDebBM+Ttt=
zI-&E^kk@i+x4pznAtDd|R+ldNQ4EK0Xn1`SQw*m-wn3
z6tdd~>YNf_f2{Dbd^r7O@aW%g5qk*nr1WFI_Bwgr!O64M+G+a^_^$bh5wZ%pG9^Ce
zKe!*f_Bc{GEiTR}_96Avx|`jxK5II*cSk&Xi6}aZKwSuOfcoL2~%>J(@ZyVzKwmrB{5Dt&~&$m{au)sXHxL?SMcwc@4
zT+|b@=n6xSCSWs+JBvVtLH;UR=HtX0k1YtwY8uDRcTAr2KE7fNs=-i?BEnQt%1llU
zh8B8_1OpF?4}$=`f`xwhVc-9KEe=Zq^Wu;Da4;}omN4*tz9SDkKY!w&-{&^}Ilo8<
zg+YY=2X$3oJaXawdK(d#`{J+b7evr!FhVLKQc}>fim{WashzWhy~|;rjW6^DvV)|S
zGYkwa|O-N}1vq+W)+zs-}ykoGifD-j>nO1d6Q~J!~DG`+?#006;HoOrvLNk|K3#1
z+0;qI-WEEh3;%!j>(6oj_u-!nd6}M<{y(Jn51s$G3ner^3NO>&o5qiV8%g7Am`XO07L1#J6^3tg9e+a_B|H~tSHxL`CSIjSlSr8ot_Fo+zkpxNlLtx-Y{@oFV
z42#qoHY94C`Y#)hzy!XXhd~PXcLxC#JPA566;`z2=YQ8A00!Pj_r<@Ri$f}UfS^yR
zEL$k@zg;jo(DBW`oP5A{Ltz-W6GN8Cw^aXj!BFC}|2xV<*ZBVv|Nn(4{=X%@CwyIf
zxZBZ49v`BU#gkBeP?!@<1nN@=rYK;DO2I@G*=7GMs1Ih6ceKNggRwY&iX(
z%ECZd$^<`ZuB<=|K!YRs^&&9e$$!1W8?92iBW3QPp2(;MZ63J{KCmY_0NC#eo+%1_
zv#-?RWQz9cH98P2(z2gK=${l#CQ`+Eid=?!XvlA;LS@NE>0+$H`Y_uQ)ne8}Z+|mf
zrI+54kP(ul4uOGd74kB5(hw^Rd3pDZ9#{U^6~jN|Ozh&Z(_@H5yVl9o;&ZursqAc-
zT44mvuu2+BVX0_1CIuPV>t_|Wf+SfGC=!M`xz=%KF)*(8&GQU*sm@hrH>p1wU-67Q
zBeXGc9|e9RA5i}m@1G&qLypMaXw*EugN^wkI!quOrsU;ao5!0cZhwr!m4*=#r7l0co{?&sG!_Jk
zpy_AQkbL=`-QgX*3vWGF!Rn?;W01Y{%}%MHBb*d{b06`a)GgNm(!n-C58cxk$LXs`
zbnRj%l;q#M?H|bu&n6mmf9sxVa+E32AKQG)X?A)Z;d_Q4%i4OA?YfZj&NyrPgJ_MV
zqbh5eYH9w}CndON5*d-yWI?ziAGNJ~;>eVc0d5vD$&tH!h;WXt@sQ+U|7jAE`fwYT
ztv(`ET)MTgDC{NKnR!VM*@3eeb(RBb1eo#7Qk6!5V=_@U=XcVA4^TBD7A;t}vfk%>
zJ)h?M+Ob)E41cD|mM%Ds(F%{e{{EjJ7$7bKQ
zxjE8L@1NJ}LwS5heD)?@Gat_dGS@fXi1O75sW(K3(Dok<1U5?G#d4kH**F1tmz^TQ
zgfQ&pR0-y%ay7}krQ{$=Ok;jMD%3D&zk=U`1mhr($S?F?ap*J>kyuw__FhjI#Cv%~v7hw5ZG;
zuLDZ+!r(1jo;rC4VL4;|iygGWKgJCgRD?h
z?`G4YI1gW&JA-mw5h?ne-%aj64F?lQg09&{nbCMSo=3Z_Qev0<$+P=qV5|=Dob6aq
zWt&rpQww&P2K(ECk2!X%p~lY^GFO5Gcy)F2>M_3o{Frxp0ah-@9lLn>S^4?lFRVa>
zNZjdkc5sRQDqyB{R*AnM;o6E6ojRLa8~&fBAo(%S#w{SL3ov5Q;JKtIKyYQ+g)FXnD|x{9eh28(5|Y19Uho$*AmcQPe`|d*MTTQ`TZ0aKdc3pOZgsH?
zWL$LG9#*>8pDp!juu{!466;BB7sPq_YfG=qZStGtw63>un>vHla#fb~JAx=CSmYcQ
z>pA+{$2*ASMVZ<+yH&tajp2*rYQ;c&HVZ-5{h7RMKChoA)R}^NdwVCgyb((jDmV_15Yl
zd82LpJbkmM3RU;%vy8e-HlybBtU%{K#4uYh?g%nnG*OUszjmAYl}D*i8t0HFs^gi=
zai8Fpn;^OGy2gr7wntR1?DQ~KS_Q@kap6vesIx>j2V!ICgidAvpiF0r!8lUYCcD+<
zxvY}m-syv>JQ2N&w&U(smIv0=Eh#^KT%!-}z)RbA-ca#9tvG+PS!9`z-u@b59fnr?
zywlRjwA)(zYY2W17aD*ncSy53-Nuz=agIFb)V|yoF*q)qZUsh-!}r!@f4Ml;Jhstp
zS-eo@%O$;gGj?1oGwo>@nf@iAzwQ*zc$Zu?haQKxb)vf)_#gIG>gRS>EM5-G^1Z}lXvu&oc3$HODeBa*U$nNR`QDEGNumQSA;-W?%AH4bCEEC
zc>Pg%@#GR-F`{GyF1rhp^(()XKRw>xWO^6ZgB)@^HjrD7ZozybdH;j|2<+f@DotDy
zD{a4a<8UNqc`I_gEF>P{&)F4th6XfnLM_#PS3U3vNRcn(cXcT8J!m^Mp+VE4qW-{rR#9&;x;rUu;og8YvPJdLZiNfq@30{|C_s=Pe7Cym
zF(37CS>ov1;%7md7YJ?7ocEt202zL}&%I7T{2ylh2)WCNVtm6}o3oFf^30FuNN{3@
zkMMz9<6n|Ju>8*sn^fyehPdVlp7u%52XZXGu}d?~krrnPV{w^V2vxd*=h!Syw}L~q
zjGk!5a}*4UI6iMd^E-h!I=G
z*e9a{H%C}gmh?Thaa#BK-y3t!US?9~ctwOd>u-o^k|7wqiw(}q{^1!rlJp@F_&e`S
z4zjMp4}|l@;v7KZ>4I_W9eH%)UKQ`9XVnJv7;m_ITF!taXc!e`|oGa&8
z#VRyFXWPR(r(IWHU#d2e@(rpKHOmLxvx8H!yFS4d7TxBk&`rYCzE(fQi1pr#_Sx)@
z*&?q=>bJ{)dv(aqsc>icclwSBy;pHk9Z8A6Ia
zvLIksJ^dpH(cAF*2?c3QfPh6Rr#;aSB9^K2m!k2^*f#wRFR7`!Zg9~SeNLa}fIDQ-
z*d^a~xp4+6vE5*F?f(LwKnfD{B)oO0fZ>Knq2F(l{F=MFg`VRLl4Q?v2W1MXa7I`c
zoIh}uQk#Gf$#}+br|;cV14o{xJ7h^rr_rvEyWV_y-oRh3%^h;tEZQB`H?71=6l4Vj
zS?*@pI}ShH^aFPESDh#LTeGEY}XW((D!{9
z|7=PV$a#-$Z*=MwL$qq)_*LkVKv
zB)jqMwZhbgghFk1r5)+u{-vMb`bF`1CycaK5F9858OZ!*RFEx=QA~{$ECc&YA3)
z_GJP?t*=oAa?i=NKo}2yYz6jug;=XH{Z^ftq@a0{6!+
z-f(YYH|(|Qc9^|UtJYs_h+6$oQ9-}d?D+M!R!epV-TcY=I3Z7o^lX`Gu{
zm_l_P4OCrLp-lLOqXXS-*6q&qctz(cbtIlnQ>Uhnc`4*3?{@x2dAH^sm=>C9`uYmfN)Z5*Uo
z_r0m!Esxa3HS+pX;hCQwaa9*UX{xn!$izW7xbk8XWjor-bftJ1U9O}x8;6iX-5
zsi<`lZFA0c`g+rj<;55`RQg1>MCaKo)~P1@4-AWvJoz5!YS+1ZsQiR>5*374${U6w
z07Z?vGt=@aeNlxPtI4$L1t|CCjlOr6lVp!?fK8YCv*l86XY79l;B(kWGQ$ROWeac$L(&hTGj^*v
zwxutP;FAvOIo==MTm|R2RnuczYgG3}wJ+|4!tVJwY!(Fj>%&0Wm$M1xs82(D^^8w_
zOa8OemLmMEPIc*{GCQL-PKS)z-+*(c_8N~7ICSDp0!fd9>=ko?|Fr9hzr-0Yt;j^*0{?C6L`<^Cqn
zH-P6Z5BJ~;`AQP?j&JEgJNc|2n+MXaBBMM1PKNyvX!0g9pq0aML-aO6B-a0IjB|-}
zgvV`Pl>FK_;sXVvH!giIGY+IX?G$MipstKWqSiRORZQUzNjQb
zyAZrOApT((r&F~Lv=_av_^HbWv*mbtp4-W64nK2!gsWOIS6dwb+gpi;s3DgRqufhv
zZiiMjkd>B13YSM#1%X3AlM``QXwDd(^Etu|%m;Ou6m!Xn%^uG`-3kXTtY^b%k`wd?
z6D0WZPx?PIh$8%FCj$m6xTuXtN~i%k#iFsgqDJcVoHzLfS6jt(IaHi8_3K9vU-dov
zfhE0g$QF0ZETfsDN-v4tL=|)+$f!Clm#oh}Mydif8dtf*uDyT#Kr}ujzz&^ijG|M=
zn%n`PKG6T}7t1}JZWop{@b7tZe!UqB0(Vz7tyv+t-JotA#?|a#uC3TlKfFm5ldtAC
zH8)pbecTmlf3+$rZ1YrbauSHtL$1{vb>U9=c{<2PZf^$@Z(>%RL8sLN_bS7z~j3vuMiZba|#ieFA>5
zS5G4Kp27wc$o+gs?FY!Wn8*BDPZeeOd7(Yma+xehzqSyh6?}!FoP8AG
z;W50I4iu%X$NR+lRyu?1^&^XG8Ahmj6WU~o_h~rw?wU8ml~+zQM$G>~3^PG9?YQG$
zN@muqv#>^|FW*8)m;zKjV;DvZSIg!K^>*J8<8!fDAEex9jT=>Dgu5T5nP*~ru@?42
zoT$gE3|4bvCH$=dzmd3TtUsUvzzx*o1t{?T4laRbXQ!gXl#$$-=4yAX$S(&v2Q?GR
z7xhRGM6AS~0(#)XVYk&q<`;8m{3vV{n8gSkBsiXY5iri<|-ip@W
zhlJayW0Y4stJUWG^cuMWJ~IdkdXphOqA
z-2K|A3*H#JqkT1zus%0LL0li~d3EaI4p_JCy02Plv<7KX5W&^1C{*ptz!TTLB~nO4
z
zXRqM?aw2c(HSbp$U-u0aZ}V=y)<>zoZJhfsALH>>gr+g!$8(&W7YTm5QyUvT)pSH7
z?!HB9nkriA@zXP+6Un7n$r=4diVm6ts*~Uv=7tZ*n3rmIS4uA^^CbGDndkU6uI4o#
zoDKU|oF%Nukl^OsH*dy7YQ>%6@5Zh
zTvP7H{ZciKj0u0Uru(H0l&CZzwFBnEb%=Y*AB0fP^c54qm%qb^8!N@l>FwZ73=Xu`
z^L)LRTQ_T`DB~XR47`HN;e8Cz&nIrNSX7
zF|%M^@1>Lb{>`uCEn%@wd(_f$at((HECM1nh{0KZngbZPDtOF`4ISj>4N}^o#>y-e
zqnrbG%=@HV8q>`EAwB^|qN4B(noXzr-1DBw*d1f0`z!R0<8|4yDxfPk?1lc>q05-4
zYQ&pohXC;gbkb!|Z?V^E1L)9j1mwF(2YPkcx}*96xH*09-VGEfZ#yBBR|{rIB_swp
z8OY(nnt>Y+V_5H&N4aALMiFC=Qh7)o;;jmhIj(F
zyF4FTpfcS$8Lcqu4rC_u9rIgqCvjKUOAxKsXY3ZhH
z^*gB;Z>%aDc`RbkXsS=Z+1l0yB(=w%wbn6=rBJAp$v5clI^`VE|
zsZu@zx)x&Q{`#!$3YmvXtdnKgUM{G5P>K;JS!=MyyVzaR8&R?6k3^PRkeRXB;P%>&
zBR%gy6G(OEsfv_Xbo9Md%vx%&gyL8>XaL&QP^%lre|Avc=n8HxaK{3=3R9GaiXCu=
z@s+-Zx)ov9q5QEu3(`oIgw7f7Psp(Cg_*$1O-y=FR5FtpB6i}XKMJ}Z+<1VxNMKi5
z&v3$QoM!C7;oK9lwg^j(_qV$}?mqS_@fr9O}%N$nojg@YGRzsFd
z4_|n9H`4gS&)~r6I_WQo`bm4{CAj%lmZmFuS*H?gvA8
zJO%=ySfCv*^VZ}_W&V((&KmePT!31m&pJ5?7Yl9l{Q~znD}(SXp<#>+Lgtq-M}2p$
z6T}54&h4PFn8|64;>lcNqnv?p4Z_^jJ12w!tR~mLQA){TA+MucpY3CyZpA$!MsL9>n+^2&$