mirror of
https://gitcode.com/GitHub_Trending/ji/jitsi-meet.git
synced 2026-01-06 14:52:28 +00:00
Compare commits
172 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
33e484a847 | ||
|
|
67bebc0491 | ||
|
|
9186a74ae3 | ||
|
|
67d9a9819e | ||
|
|
16b88a29db | ||
|
|
9783793514 | ||
|
|
93de398a09 | ||
|
|
23e97a4284 | ||
|
|
9bb906551e | ||
|
|
b1ad82cef9 | ||
|
|
09c9f2930c | ||
|
|
74efbd7a61 | ||
|
|
1b1e7d9bce | ||
|
|
dc98fc4839 | ||
|
|
a815f97c7e | ||
|
|
8261cf2811 | ||
|
|
f2238935b5 | ||
|
|
5f12f76ada | ||
|
|
5a9464697f | ||
|
|
f44601a82b | ||
|
|
3d3de4a884 | ||
|
|
c02ad56b6d | ||
|
|
ea7c5ccd58 | ||
|
|
7ec3eae72b | ||
|
|
edf7d18308 | ||
|
|
6bf4a4e91d | ||
|
|
5fd966f042 | ||
|
|
e275f20055 | ||
|
|
ff624a34d8 | ||
|
|
c98050224c | ||
|
|
5bee373091 | ||
|
|
db4ab34ddf | ||
|
|
ef138fb5aa | ||
|
|
13bfdaed68 | ||
|
|
ff656f4e6b | ||
|
|
a27b78cef0 | ||
|
|
4fa426ace0 | ||
|
|
ac34f524fa | ||
|
|
31a4f2a4ec | ||
|
|
dc908512f9 | ||
|
|
ae983645d1 | ||
|
|
3514b22191 | ||
|
|
405af3af5f | ||
|
|
a6d333c07a | ||
|
|
0387cdc888 | ||
|
|
f670f39dd2 | ||
|
|
7262465777 | ||
|
|
75b4049529 | ||
|
|
ac6185424c | ||
|
|
9e15df8e3d | ||
|
|
83f83c17eb | ||
|
|
3e1adcd9b7 | ||
|
|
8105127571 | ||
|
|
bc99a72984 | ||
|
|
e10eaaa3d9 | ||
|
|
0e831074c0 | ||
|
|
326b694bf2 | ||
|
|
9e1f3de4e5 | ||
|
|
07a25a1f00 | ||
|
|
d6bbe07cf2 | ||
|
|
e9a8fd5392 | ||
|
|
aea9c5e79e | ||
|
|
b60210d0ad | ||
|
|
f0d2106c1a | ||
|
|
13f1cb13c5 | ||
|
|
c27ca779ab | ||
|
|
aedb43ec5b | ||
|
|
0a68eed294 | ||
|
|
3f51b10245 | ||
|
|
5260cd7e30 | ||
|
|
0d109eaf00 | ||
|
|
75c43fc8f2 | ||
|
|
532b5858c5 | ||
|
|
edc2328fd6 | ||
|
|
a603a8df06 | ||
|
|
703a4d0f34 | ||
|
|
44c1624c61 | ||
|
|
5b5e233734 | ||
|
|
5607e50b8e | ||
|
|
39c942d585 | ||
|
|
1c04f974d8 | ||
|
|
dc5142cb6b | ||
|
|
d563913499 | ||
|
|
4d0642d1a7 | ||
|
|
8d8e83cdfd | ||
|
|
6d0271338e | ||
|
|
1401eb245e | ||
|
|
27eec7b19e | ||
|
|
b0d0b3ac11 | ||
|
|
2c11b1b945 | ||
|
|
2c92ea57f0 | ||
|
|
09b696e95a | ||
|
|
d67054a550 | ||
|
|
05374e292b | ||
|
|
f038099e61 | ||
|
|
da5f2d00d4 | ||
|
|
c8a7877fdd | ||
|
|
d8da660070 | ||
|
|
4e033fff4b | ||
|
|
4861f95368 | ||
|
|
b3ee8fe127 | ||
|
|
95a6001a6f | ||
|
|
a3622a3698 | ||
|
|
4cdc193ac3 | ||
|
|
5c9b8a5a5f | ||
|
|
44bd70179c | ||
|
|
0973081fea | ||
|
|
006c491de4 | ||
|
|
24cfa7b4e1 | ||
|
|
b890aa33c3 | ||
|
|
9846228210 | ||
|
|
445eef97b3 | ||
|
|
298279a956 | ||
|
|
5ebf5adfa2 | ||
|
|
35554533d1 | ||
|
|
fb397db69f | ||
|
|
8fc295b385 | ||
|
|
ee8b62cf73 | ||
|
|
217b803652 | ||
|
|
2442a332e7 | ||
|
|
2e43706a4a | ||
|
|
e7db943b73 | ||
|
|
c1cbd37d87 | ||
|
|
ef56f1d23d | ||
|
|
2ab002650c | ||
|
|
867646da1a | ||
|
|
ff78bfb62f | ||
|
|
1827610fc1 | ||
|
|
0ae8051fb4 | ||
|
|
1b7668bbdc | ||
|
|
4c37e0d761 | ||
|
|
a6ff652a03 | ||
|
|
17f34878db | ||
|
|
37856e0fdb | ||
|
|
7c1de52f6a | ||
|
|
9e3438696b | ||
|
|
9c23cc0b70 | ||
|
|
af8157bc06 | ||
|
|
c21f84c15a | ||
|
|
1edf88e744 | ||
|
|
bad75b488e | ||
|
|
5bb3ba71d0 | ||
|
|
4e0001c9af | ||
|
|
ada6150971 | ||
|
|
62d1ee606a | ||
|
|
1e1de6acf0 | ||
|
|
e1e0fba4ff | ||
|
|
97be3fa399 | ||
|
|
fbdee85c4b | ||
|
|
b71b4c8c45 | ||
|
|
a8d123ede4 | ||
|
|
fb8e451e2e | ||
|
|
5dd7944bdb | ||
|
|
48732c6784 | ||
|
|
97146ed8a7 | ||
|
|
78b17c8d17 | ||
|
|
9732d1be86 | ||
|
|
a836187620 | ||
|
|
a0cad4c595 | ||
|
|
19b9eac84a | ||
|
|
068e33fc0f | ||
|
|
00c6bee2fd | ||
|
|
748ead7e13 | ||
|
|
174c4418fb | ||
|
|
64494cab81 | ||
|
|
50d0092e30 | ||
|
|
fdbd7239ff | ||
|
|
a30958ab23 | ||
|
|
aca55172e4 | ||
|
|
c6cce9253c | ||
|
|
c23684e11c | ||
|
|
30595584a3 |
28
.github/workflows/ci.yml
vendored
28
.github/workflows/ci.yml
vendored
@@ -88,17 +88,17 @@ jobs:
|
||||
run: |
|
||||
uname -a
|
||||
xcode-select -p
|
||||
sudo xcode-select -s /Applications/Xcode_16.0.app/Contents/Developer
|
||||
sudo xcode-select -s /Applications/Xcode_16.2.app/Contents/Developer
|
||||
xcodebuild -version
|
||||
- name: setup-cocoapods
|
||||
uses: maxim-lobanov/setup-cocoapods@v1
|
||||
uses: ruby/setup-ruby@v1
|
||||
with:
|
||||
podfile-path: ios/Podfile.lock
|
||||
ruby-version: '3.4'
|
||||
bundler-cache: true
|
||||
- run: npx react-native info
|
||||
- name: Install Pods
|
||||
run: |
|
||||
pod --version
|
||||
cd ios
|
||||
pod install --repo-update --deployment
|
||||
working-directory: ./ios
|
||||
run: bundle exec pod install --repo-update --deployment
|
||||
- run: npx react-native bundle --entry-file react/index.native.js --platform ios --bundle-output /tmp/ios.bundle --reset-cache
|
||||
android-sdk-build:
|
||||
name: Build mobile SDK (Android)
|
||||
@@ -137,17 +137,17 @@ jobs:
|
||||
run: |
|
||||
uname -a
|
||||
xcode-select -p
|
||||
sudo xcode-select -s /Applications/Xcode_16.0.app/Contents/Developer
|
||||
sudo xcode-select -s /Applications/Xcode_16.2.app/Contents/Developer
|
||||
xcodebuild -version
|
||||
- name: setup-cocoapods
|
||||
uses: maxim-lobanov/setup-cocoapods@v1
|
||||
uses: ruby/setup-ruby@v1
|
||||
with:
|
||||
podfile-path: ios/Podfile.lock
|
||||
ruby-version: '3.4'
|
||||
bundler-cache: true
|
||||
- run: npx react-native info
|
||||
- name: Install Pods
|
||||
run: |
|
||||
pod --version
|
||||
cd ios
|
||||
pod install --repo-update --deployment
|
||||
working-directory: ./ios
|
||||
run: bundle exec pod install --repo-update --deployment
|
||||
- run: |
|
||||
xcodebuild clean \
|
||||
-workspace ios/jitsi-meet.xcworkspace \
|
||||
|
||||
4
.gitignore
vendored
4
.gitignore
vendored
@@ -62,6 +62,7 @@ buck-out/
|
||||
|
||||
# fastlane
|
||||
#
|
||||
.bundle/
|
||||
**/fastlane/report.xml
|
||||
**/fastlane/Preview.html
|
||||
**/fastlane/test_output
|
||||
@@ -101,6 +102,9 @@ tsconfig.json
|
||||
react-native-sdk/*.tgz
|
||||
react-native-sdk/android/src
|
||||
!react-native-sdk/android/src/main/java/org/jitsi/meet/sdk/JitsiMeetReactNativePackage.java
|
||||
!react-native-sdk/android/src/main/java/org/jitsi/meet/sdk/JitsiMeetOngoingConferenceService.java
|
||||
!react-native-sdk/android/src/main/java/org/jitsi/meet/sdk/JMOngoingConferenceModule.java
|
||||
!react-native-sdk/android/src/main/java/org/jitsi/meet/sdk/RNOngoingNotification.java
|
||||
react-native-sdk/images
|
||||
react-native-sdk/ios
|
||||
react-native-sdk/lang
|
||||
|
||||
16
Gemfile
Normal file
16
Gemfile
Normal file
@@ -0,0 +1,16 @@
|
||||
source "https://rubygems.org"
|
||||
|
||||
ruby ">= 3.4.0"
|
||||
|
||||
gem "cocoapods", "~> 1.16"
|
||||
|
||||
# (Optional) Fastlane for automation
|
||||
gem "fastlane"
|
||||
gem "abbrev"
|
||||
gem "logger"
|
||||
gem "mutex_m"
|
||||
gem "csv"
|
||||
gem "bigdecimal"
|
||||
|
||||
# (Optional) Bundler itself to ensure consistency
|
||||
gem "bundler"
|
||||
331
Gemfile.lock
Normal file
331
Gemfile.lock
Normal file
@@ -0,0 +1,331 @@
|
||||
GEM
|
||||
remote: https://rubygems.org/
|
||||
specs:
|
||||
CFPropertyList (3.0.7)
|
||||
base64
|
||||
nkf
|
||||
rexml
|
||||
abbrev (0.1.2)
|
||||
activesupport (7.2.2.1)
|
||||
base64
|
||||
benchmark (>= 0.3)
|
||||
bigdecimal
|
||||
concurrent-ruby (~> 1.0, >= 1.3.1)
|
||||
connection_pool (>= 2.2.5)
|
||||
drb
|
||||
i18n (>= 1.6, < 2)
|
||||
logger (>= 1.4.2)
|
||||
minitest (>= 5.1)
|
||||
securerandom (>= 0.3)
|
||||
tzinfo (~> 2.0, >= 2.0.5)
|
||||
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)
|
||||
artifactory (3.0.17)
|
||||
atomos (0.1.3)
|
||||
aws-eventstream (1.3.1)
|
||||
aws-partitions (1.1050.0)
|
||||
aws-sdk-core (3.218.1)
|
||||
aws-eventstream (~> 1, >= 1.3.0)
|
||||
aws-partitions (~> 1, >= 1.992.0)
|
||||
aws-sigv4 (~> 1.9)
|
||||
base64
|
||||
jmespath (~> 1, >= 1.6.1)
|
||||
aws-sdk-kms (1.98.0)
|
||||
aws-sdk-core (~> 3, >= 3.216.0)
|
||||
aws-sigv4 (~> 1.5)
|
||||
aws-sdk-s3 (1.181.0)
|
||||
aws-sdk-core (~> 3, >= 3.216.0)
|
||||
aws-sdk-kms (~> 1)
|
||||
aws-sigv4 (~> 1.5)
|
||||
aws-sigv4 (1.11.0)
|
||||
aws-eventstream (~> 1, >= 1.0.2)
|
||||
babosa (1.0.4)
|
||||
base64 (0.2.0)
|
||||
benchmark (0.4.0)
|
||||
bigdecimal (3.1.9)
|
||||
claide (1.1.0)
|
||||
cocoapods (1.16.2)
|
||||
addressable (~> 2.8)
|
||||
claide (>= 1.0.2, < 2.0)
|
||||
cocoapods-core (= 1.16.2)
|
||||
cocoapods-deintegrate (>= 1.0.3, < 2.0)
|
||||
cocoapods-downloader (>= 2.1, < 3.0)
|
||||
cocoapods-plugins (>= 1.0.0, < 2.0)
|
||||
cocoapods-search (>= 1.0.0, < 2.0)
|
||||
cocoapods-trunk (>= 1.6.0, < 2.0)
|
||||
cocoapods-try (>= 1.1.0, < 2.0)
|
||||
colored2 (~> 3.1)
|
||||
escape (~> 0.0.4)
|
||||
fourflusher (>= 2.3.0, < 3.0)
|
||||
gh_inspector (~> 1.0)
|
||||
molinillo (~> 0.8.0)
|
||||
nap (~> 1.0)
|
||||
ruby-macho (>= 2.3.0, < 3.0)
|
||||
xcodeproj (>= 1.27.0, < 2.0)
|
||||
cocoapods-core (1.16.2)
|
||||
activesupport (>= 5.0, < 8)
|
||||
addressable (~> 2.8)
|
||||
algoliasearch (~> 1.0)
|
||||
concurrent-ruby (~> 1.1)
|
||||
fuzzy_match (~> 2.0.4)
|
||||
nap (~> 1.0)
|
||||
netrc (~> 0.11)
|
||||
public_suffix (~> 4.0)
|
||||
typhoeus (~> 1.0)
|
||||
cocoapods-deintegrate (1.0.5)
|
||||
cocoapods-downloader (2.1)
|
||||
cocoapods-plugins (1.0.0)
|
||||
nap
|
||||
cocoapods-search (1.0.1)
|
||||
cocoapods-trunk (1.6.0)
|
||||
nap (>= 0.8, < 2.0)
|
||||
netrc (~> 0.11)
|
||||
cocoapods-try (1.2.0)
|
||||
colored (1.2)
|
||||
colored2 (3.1.2)
|
||||
commander (4.6.0)
|
||||
highline (~> 2.0.0)
|
||||
concurrent-ruby (1.3.5)
|
||||
connection_pool (2.5.0)
|
||||
csv (3.3.2)
|
||||
declarative (0.0.20)
|
||||
digest-crc (0.7.0)
|
||||
rake (>= 12.0.0, < 14.0.0)
|
||||
domain_name (0.6.20240107)
|
||||
dotenv (2.8.1)
|
||||
drb (2.2.1)
|
||||
emoji_regex (3.2.3)
|
||||
escape (0.0.4)
|
||||
ethon (0.16.0)
|
||||
ffi (>= 1.15.0)
|
||||
excon (0.112.0)
|
||||
faraday (1.10.4)
|
||||
faraday-em_http (~> 1.0)
|
||||
faraday-em_synchrony (~> 1.0)
|
||||
faraday-excon (~> 1.1)
|
||||
faraday-httpclient (~> 1.0)
|
||||
faraday-multipart (~> 1.0)
|
||||
faraday-net_http (~> 1.0)
|
||||
faraday-net_http_persistent (~> 1.0)
|
||||
faraday-patron (~> 1.0)
|
||||
faraday-rack (~> 1.0)
|
||||
faraday-retry (~> 1.0)
|
||||
ruby2_keywords (>= 0.0.4)
|
||||
faraday-cookie_jar (0.0.7)
|
||||
faraday (>= 0.8.0)
|
||||
http-cookie (~> 1.0.0)
|
||||
faraday-em_http (1.0.0)
|
||||
faraday-em_synchrony (1.0.0)
|
||||
faraday-excon (1.1.0)
|
||||
faraday-httpclient (1.0.1)
|
||||
faraday-multipart (1.1.0)
|
||||
multipart-post (~> 2.0)
|
||||
faraday-net_http (1.0.2)
|
||||
faraday-net_http_persistent (1.2.0)
|
||||
faraday-patron (1.0.0)
|
||||
faraday-rack (1.0.0)
|
||||
faraday-retry (1.0.3)
|
||||
faraday_middleware (1.2.1)
|
||||
faraday (~> 1.0)
|
||||
fastimage (2.4.0)
|
||||
fastlane (2.226.0)
|
||||
CFPropertyList (>= 2.3, < 4.0.0)
|
||||
addressable (>= 2.8, < 3.0.0)
|
||||
artifactory (~> 3.0)
|
||||
aws-sdk-s3 (~> 1.0)
|
||||
babosa (>= 1.0.3, < 2.0.0)
|
||||
bundler (>= 1.12.0, < 3.0.0)
|
||||
colored (~> 1.2)
|
||||
commander (~> 4.6)
|
||||
dotenv (>= 2.1.1, < 3.0.0)
|
||||
emoji_regex (>= 0.1, < 4.0)
|
||||
excon (>= 0.71.0, < 1.0.0)
|
||||
faraday (~> 1.0)
|
||||
faraday-cookie_jar (~> 0.0.6)
|
||||
faraday_middleware (~> 1.0)
|
||||
fastimage (>= 2.1.0, < 3.0.0)
|
||||
fastlane-sirp (>= 1.0.0)
|
||||
gh_inspector (>= 1.1.2, < 2.0.0)
|
||||
google-apis-androidpublisher_v3 (~> 0.3)
|
||||
google-apis-playcustomapp_v1 (~> 0.1)
|
||||
google-cloud-env (>= 1.6.0, < 2.0.0)
|
||||
google-cloud-storage (~> 1.31)
|
||||
highline (~> 2.0)
|
||||
http-cookie (~> 1.0.5)
|
||||
json (< 3.0.0)
|
||||
jwt (>= 2.1.0, < 3)
|
||||
mini_magick (>= 4.9.4, < 5.0.0)
|
||||
multipart-post (>= 2.0.0, < 3.0.0)
|
||||
naturally (~> 2.2)
|
||||
optparse (>= 0.1.1, < 1.0.0)
|
||||
plist (>= 3.1.0, < 4.0.0)
|
||||
rubyzip (>= 2.0.0, < 3.0.0)
|
||||
security (= 0.1.5)
|
||||
simctl (~> 1.6.3)
|
||||
terminal-notifier (>= 2.0.0, < 3.0.0)
|
||||
terminal-table (~> 3)
|
||||
tty-screen (>= 0.6.3, < 1.0.0)
|
||||
tty-spinner (>= 0.8.0, < 1.0.0)
|
||||
word_wrap (~> 1.0.0)
|
||||
xcodeproj (>= 1.13.0, < 2.0.0)
|
||||
xcpretty (~> 0.4.0)
|
||||
xcpretty-travis-formatter (>= 0.0.3, < 2.0.0)
|
||||
fastlane-sirp (1.0.0)
|
||||
sysrandom (~> 1.0)
|
||||
ffi (1.17.1)
|
||||
ffi (1.17.1-aarch64-linux-gnu)
|
||||
ffi (1.17.1-aarch64-linux-musl)
|
||||
ffi (1.17.1-arm-linux-gnu)
|
||||
ffi (1.17.1-arm-linux-musl)
|
||||
ffi (1.17.1-arm64-darwin)
|
||||
ffi (1.17.1-x86-linux-gnu)
|
||||
ffi (1.17.1-x86-linux-musl)
|
||||
ffi (1.17.1-x86_64-darwin)
|
||||
ffi (1.17.1-x86_64-linux-gnu)
|
||||
ffi (1.17.1-x86_64-linux-musl)
|
||||
fourflusher (2.3.1)
|
||||
fuzzy_match (2.0.4)
|
||||
gh_inspector (1.1.3)
|
||||
google-apis-androidpublisher_v3 (0.54.0)
|
||||
google-apis-core (>= 0.11.0, < 2.a)
|
||||
google-apis-core (0.11.3)
|
||||
addressable (~> 2.5, >= 2.5.1)
|
||||
googleauth (>= 0.16.2, < 2.a)
|
||||
httpclient (>= 2.8.1, < 3.a)
|
||||
mini_mime (~> 1.0)
|
||||
representable (~> 3.0)
|
||||
retriable (>= 2.0, < 4.a)
|
||||
rexml
|
||||
google-apis-iamcredentials_v1 (0.17.0)
|
||||
google-apis-core (>= 0.11.0, < 2.a)
|
||||
google-apis-playcustomapp_v1 (0.13.0)
|
||||
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.1)
|
||||
google-cloud-env (>= 1.0, < 3.a)
|
||||
google-cloud-errors (~> 1.0)
|
||||
google-cloud-env (1.6.0)
|
||||
faraday (>= 0.17.3, < 3.0)
|
||||
google-cloud-errors (1.4.0)
|
||||
google-cloud-storage (1.47.0)
|
||||
addressable (~> 2.8)
|
||||
digest-crc (~> 0.4)
|
||||
google-apis-iamcredentials_v1 (~> 0.1)
|
||||
google-apis-storage_v1 (~> 0.31.0)
|
||||
google-cloud-core (~> 1.6)
|
||||
googleauth (>= 0.16.2, < 2.a)
|
||||
mini_mime (~> 1.0)
|
||||
googleauth (1.8.1)
|
||||
faraday (>= 0.17.3, < 3.a)
|
||||
jwt (>= 1.4, < 3.0)
|
||||
multi_json (~> 1.11)
|
||||
os (>= 0.9, < 2.0)
|
||||
signet (>= 0.16, < 2.a)
|
||||
highline (2.0.3)
|
||||
http-cookie (1.0.8)
|
||||
domain_name (~> 0.5)
|
||||
httpclient (2.8.3)
|
||||
i18n (1.14.7)
|
||||
concurrent-ruby (~> 1.0)
|
||||
jmespath (1.6.2)
|
||||
json (2.10.1)
|
||||
jwt (2.10.1)
|
||||
base64
|
||||
logger (1.6.6)
|
||||
mini_magick (4.13.2)
|
||||
mini_mime (1.1.5)
|
||||
minitest (5.25.4)
|
||||
molinillo (0.8.0)
|
||||
multi_json (1.15.0)
|
||||
multipart-post (2.4.1)
|
||||
mutex_m (0.3.0)
|
||||
nanaimo (0.4.0)
|
||||
nap (1.1.0)
|
||||
naturally (2.2.1)
|
||||
netrc (0.11.0)
|
||||
nkf (0.2.0)
|
||||
optparse (0.6.0)
|
||||
os (1.1.4)
|
||||
plist (3.7.2)
|
||||
public_suffix (4.0.7)
|
||||
rake (13.2.1)
|
||||
representable (3.2.0)
|
||||
declarative (< 0.1.0)
|
||||
trailblazer-option (>= 0.1.1, < 0.2.0)
|
||||
uber (< 0.2.0)
|
||||
retriable (3.1.2)
|
||||
rexml (3.4.1)
|
||||
rouge (3.28.0)
|
||||
ruby-macho (2.5.1)
|
||||
ruby2_keywords (0.0.5)
|
||||
rubyzip (2.4.1)
|
||||
securerandom (0.4.1)
|
||||
security (0.1.5)
|
||||
signet (0.19.0)
|
||||
addressable (~> 2.8)
|
||||
faraday (>= 0.17.5, < 3.a)
|
||||
jwt (>= 1.5, < 3.0)
|
||||
multi_json (~> 1.10)
|
||||
simctl (1.6.10)
|
||||
CFPropertyList
|
||||
naturally
|
||||
sysrandom (1.0.5)
|
||||
terminal-notifier (2.0.0)
|
||||
terminal-table (3.0.2)
|
||||
unicode-display_width (>= 1.1.1, < 3)
|
||||
trailblazer-option (0.1.2)
|
||||
tty-cursor (0.7.1)
|
||||
tty-screen (0.8.2)
|
||||
tty-spinner (0.9.3)
|
||||
tty-cursor (~> 0.7)
|
||||
typhoeus (1.4.1)
|
||||
ethon (>= 0.9.0)
|
||||
tzinfo (2.0.6)
|
||||
concurrent-ruby (~> 1.0)
|
||||
uber (0.1.0)
|
||||
unicode-display_width (2.6.0)
|
||||
word_wrap (1.0.0)
|
||||
xcodeproj (1.27.0)
|
||||
CFPropertyList (>= 2.3.3, < 4.0)
|
||||
atomos (~> 0.1.3)
|
||||
claide (>= 1.0.2, < 2.0)
|
||||
colored2 (~> 3.1)
|
||||
nanaimo (~> 0.4.0)
|
||||
rexml (>= 3.3.6, < 4.0)
|
||||
xcpretty (0.4.0)
|
||||
rouge (~> 3.28.0)
|
||||
xcpretty-travis-formatter (1.0.1)
|
||||
xcpretty (~> 0.2, >= 0.0.7)
|
||||
|
||||
PLATFORMS
|
||||
aarch64-linux-gnu
|
||||
aarch64-linux-musl
|
||||
arm-linux-gnu
|
||||
arm-linux-musl
|
||||
arm64-darwin
|
||||
ruby
|
||||
x86-linux-gnu
|
||||
x86-linux-musl
|
||||
x86_64-darwin
|
||||
x86_64-linux-gnu
|
||||
x86_64-linux-musl
|
||||
|
||||
DEPENDENCIES
|
||||
abbrev
|
||||
bigdecimal
|
||||
bundler
|
||||
cocoapods (~> 1.16)
|
||||
csv
|
||||
fastlane
|
||||
logger
|
||||
mutex_m
|
||||
|
||||
RUBY VERSION
|
||||
ruby 3.4.2p28
|
||||
|
||||
BUNDLED WITH
|
||||
2.6.3
|
||||
10
Makefile
10
Makefile
@@ -17,11 +17,11 @@ STYLES_BUNDLE = css/all.bundle.css
|
||||
STYLES_DESTINATION = css/all.css
|
||||
STYLES_MAIN = css/main.scss
|
||||
ifeq ($(OS),Windows_NT)
|
||||
WEBPACK = .\node_modules\.bin\webpack
|
||||
WEBPACK_DEV_SERVER = .\node_modules\.bin\webpack serve --mode development
|
||||
WEBPACK = .\node_modules\.bin\webpack --progress
|
||||
WEBPACK_DEV_SERVER = .\node_modules\.bin\webpack serve --mode development --progress
|
||||
else
|
||||
WEBPACK = ./node_modules/.bin/webpack
|
||||
WEBPACK_DEV_SERVER = ./node_modules/.bin/webpack serve --mode development
|
||||
WEBPACK = ./node_modules/.bin/webpack --progress
|
||||
WEBPACK_DEV_SERVER = ./node_modules/.bin/webpack serve --mode development --progress
|
||||
endif
|
||||
|
||||
all: compile deploy
|
||||
@@ -48,8 +48,6 @@ deploy-appbundle:
|
||||
$(BUILD_DIR)/external_api.min.js.map \
|
||||
$(BUILD_DIR)/alwaysontop.min.js \
|
||||
$(BUILD_DIR)/alwaysontop.min.js.map \
|
||||
$(BUILD_DIR)/analytics-ga.min.js \
|
||||
$(BUILD_DIR)/analytics-ga.min.js.map \
|
||||
$(BUILD_DIR)/face-landmarks-worker.min.js \
|
||||
$(BUILD_DIR)/face-landmarks-worker.min.js.map \
|
||||
$(BUILD_DIR)/noise-suppressor-worklet.min.js \
|
||||
|
||||
@@ -34,7 +34,7 @@ mobile apps:
|
||||
|
||||
| Android | Android (F-Droid) | iOS |
|
||||
|:-:|:-:|:-:|
|
||||
| [<img src="resources/img/google-play-badge.png" height="50">](https://play.google.com/store/apps/details?id=org.jitsi.meet) | [<img src="resources/img/f-droid-badge.png" height="50">](https://f-droid.org/en/packages/org.jitsi.meet/) | [<img src="resources/img/appstore-badge.png" height="50">](https://itunes.apple.com/us/app/jitsi-meet/id1165103905) |
|
||||
| [<img src="resources/img/google-play-badge.png" height="50">](https://play.google.com/store/apps/details?id=org.jitsi.meet) | [<img src="resources/img/f-droid-badge.png" height="50">](https://f-droid.org/packages/org.jitsi.meet/) | [<img src="resources/img/appstore-badge.png" height="50">](https://itunes.apple.com/us/app/jitsi-meet/id1165103905) |
|
||||
|
||||
If you are feeling adventurous and want to get an early scoop of the features as they are being
|
||||
developed you can also sign up for our open beta testing here:
|
||||
|
||||
@@ -20,7 +20,7 @@ ext {
|
||||
kotlinVersion = "1.9.24"
|
||||
buildToolsVersion = "34.0.0"
|
||||
compileSdkVersion = 34
|
||||
minSdkVersion = 24
|
||||
minSdkVersion = 26
|
||||
targetSdkVersion = 34
|
||||
supportLibVersion = "28.0.0"
|
||||
ndkVersion = "26.1.10909125"
|
||||
@@ -42,7 +42,7 @@ ext {
|
||||
googleServicesEnabled = project.file('app/google-services.json').exists() && !libreBuild
|
||||
|
||||
//React Native and Hermes Version
|
||||
rnVersion = "0.75.4"
|
||||
rnVersion = "0.75.5"
|
||||
}
|
||||
|
||||
allprojects {
|
||||
@@ -69,10 +69,29 @@ allprojects {
|
||||
}
|
||||
}
|
||||
|
||||
// Due to a dependency conflict between React Native and the Fresco library used by GiphySDK,
|
||||
// GIFs appear as static images instead of animating
|
||||
// https://github.com/Giphy/giphy-react-native-sdk/commit/7fe466ed6fddfaec95f9cbc959d33bd75ad8f900
|
||||
|
||||
configurations.configureEach {
|
||||
resolutionStrategy {
|
||||
forcedModules = [
|
||||
'com.facebook.fresco:fresco:3.2.0',
|
||||
'com.facebook.fresco:animated-gif:3.2.0',
|
||||
'com.facebook.fresco:animated-base:3.2.0',
|
||||
'com.facebook.fresco:animated-drawable:3.2.0',
|
||||
'com.facebook.fresco:animated-webp:3.2.0',
|
||||
'com.facebook.fresco:webpsupport:3.2.0',
|
||||
'com.facebook.fresco:imagepipeline-okhttp3:3.2.0',
|
||||
'com.facebook.fresco:middleware:3.2.0',
|
||||
'com.facebook.fresco:nativeimagetranscoder:3.2.0'
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
// Third-party react-native modules which Jitsi Meet SDK for Android depends
|
||||
// on and which are not available in third-party Maven repositories need to
|
||||
// be deployed in a Maven repository of ours.
|
||||
//
|
||||
|
||||
if (project.name.startsWith('react-native-')) {
|
||||
apply plugin: 'maven-publish'
|
||||
|
||||
@@ -18,7 +18,6 @@ package org.jitsi.meet.sdk;
|
||||
|
||||
import android.content.Context;
|
||||
import android.media.AudioManager;
|
||||
import android.os.Build;
|
||||
import android.telecom.CallAudioState;
|
||||
import androidx.annotation.RequiresApi;
|
||||
|
||||
@@ -34,7 +33,6 @@ import org.jitsi.meet.sdk.log.JitsiMeetLogger;
|
||||
* {@link AudioModeModule.AudioDeviceHandlerInterface} module implementing device handling for
|
||||
* Android versions >= O when ConnectionService is enabled.
|
||||
*/
|
||||
@RequiresApi(Build.VERSION_CODES.O)
|
||||
class AudioDeviceHandlerConnectionService implements
|
||||
AudioModeModule.AudioDeviceHandlerInterface,
|
||||
RNConnectionService.CallAudioStateListener {
|
||||
|
||||
@@ -20,7 +20,6 @@ import android.media.AudioAttributes;
|
||||
import android.media.AudioDeviceInfo;
|
||||
import android.media.AudioFocusRequest;
|
||||
import android.media.AudioManager;
|
||||
import android.os.Build;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
@@ -227,22 +226,17 @@ class AudioDeviceHandlerGeneric implements
|
||||
audioManager.setMode(AudioManager.MODE_IN_COMMUNICATION);
|
||||
audioManager.setMicrophoneMute(false);
|
||||
|
||||
int gotFocus;
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||
gotFocus = audioManager.requestAudioFocus(new AudioFocusRequest.Builder(AudioManager.AUDIOFOCUS_GAIN)
|
||||
.setAudioAttributes(
|
||||
new AudioAttributes.Builder()
|
||||
.setUsage(AudioAttributes.USAGE_VOICE_COMMUNICATION)
|
||||
.setContentType(AudioAttributes.CONTENT_TYPE_SPEECH)
|
||||
.build()
|
||||
)
|
||||
.setAcceptsDelayedFocusGain(true)
|
||||
.setOnAudioFocusChangeListener(this)
|
||||
.build()
|
||||
);
|
||||
} else {
|
||||
gotFocus = audioManager.requestAudioFocus(this, AudioManager.STREAM_VOICE_CALL, AudioManager.AUDIOFOCUS_GAIN);
|
||||
}
|
||||
int gotFocus = audioManager.requestAudioFocus(new AudioFocusRequest.Builder(AudioManager.AUDIOFOCUS_GAIN)
|
||||
.setAudioAttributes(
|
||||
new AudioAttributes.Builder()
|
||||
.setUsage(AudioAttributes.USAGE_VOICE_COMMUNICATION)
|
||||
.setContentType(AudioAttributes.CONTENT_TYPE_SPEECH)
|
||||
.build()
|
||||
)
|
||||
.setAcceptsDelayedFocusGain(true)
|
||||
.setOnAudioFocusChangeListener(this)
|
||||
.build()
|
||||
);
|
||||
|
||||
if (gotFocus == AudioManager.AUDIOFOCUS_REQUEST_FAILED) {
|
||||
JitsiMeetLogger.w(TAG + " Audio focus request failed");
|
||||
|
||||
@@ -20,7 +20,6 @@ import android.annotation.SuppressLint;
|
||||
import android.app.Activity;
|
||||
import android.content.Context;
|
||||
import android.media.AudioManager;
|
||||
import android.os.Build;
|
||||
|
||||
import com.facebook.react.bridge.Arguments;
|
||||
import com.facebook.react.bridge.Promise;
|
||||
@@ -58,7 +57,6 @@ import java.util.concurrent.Executors;
|
||||
* Before a call has started and after it has ended the
|
||||
* {@code AudioModeModule.DEFAULT} mode should be used.
|
||||
*/
|
||||
@SuppressLint("AnnotateVersionCheck")
|
||||
@ReactModule(name = AudioModeModule.NAME)
|
||||
class AudioModeModule extends ReactContextBaseJavaModule {
|
||||
public static final String NAME = "AudioMode";
|
||||
@@ -84,11 +82,10 @@ class AudioModeModule extends ReactContextBaseJavaModule {
|
||||
/**
|
||||
* Whether or not the ConnectionService is used for selecting audio devices.
|
||||
*/
|
||||
private static final boolean supportsConnectionService = Build.VERSION.SDK_INT >= Build.VERSION_CODES.O;
|
||||
private static boolean useConnectionService_ = supportsConnectionService;
|
||||
private static boolean useConnectionService_ = true;
|
||||
|
||||
static boolean useConnectionService() {
|
||||
return supportsConnectionService && useConnectionService_;
|
||||
return useConnectionService_;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -139,6 +136,11 @@ class AudioModeModule extends ReactContextBaseJavaModule {
|
||||
*/
|
||||
private String userSelectedDevice;
|
||||
|
||||
/**
|
||||
* Whether or not audio is disabled.
|
||||
*/
|
||||
private boolean audioDisabled;
|
||||
|
||||
/**
|
||||
* Initializes a new module instance. There shall be a single instance of
|
||||
* this module throughout the lifetime of the application.
|
||||
@@ -239,6 +241,12 @@ class AudioModeModule extends ReactContextBaseJavaModule {
|
||||
audioDeviceHandler.stop();
|
||||
}
|
||||
|
||||
audioDeviceHandler = null;
|
||||
|
||||
if (audioDisabled) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (useConnectionService()) {
|
||||
audioDeviceHandler = new AudioDeviceHandlerConnectionService(audioManager);
|
||||
} else {
|
||||
@@ -281,6 +289,27 @@ class AudioModeModule extends ReactContextBaseJavaModule {
|
||||
});
|
||||
}
|
||||
|
||||
@ReactMethod
|
||||
public void setDisabled(final boolean disabled, final Promise promise) {
|
||||
if (audioDisabled == disabled) {
|
||||
promise.resolve(null);
|
||||
return;
|
||||
}
|
||||
|
||||
JitsiMeetLogger.i(TAG + " audio disabled: " + disabled);
|
||||
|
||||
audioDisabled = disabled;
|
||||
setAudioDeviceHandler();
|
||||
|
||||
if (disabled) {
|
||||
mode = -1;
|
||||
availableDevices.clear();
|
||||
resetSelectedDevice();
|
||||
}
|
||||
|
||||
promise.resolve(null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Public method to set the current audio mode.
|
||||
*
|
||||
@@ -290,7 +319,12 @@ class AudioModeModule extends ReactContextBaseJavaModule {
|
||||
*/
|
||||
@ReactMethod
|
||||
public void setMode(final int mode, final Promise promise) {
|
||||
if (mode != DEFAULT && mode != AUDIO_CALL && mode != VIDEO_CALL) {
|
||||
if (audioDisabled) {
|
||||
promise.resolve(null);
|
||||
return;
|
||||
}
|
||||
|
||||
if (mode < DEFAULT || mode > VIDEO_CALL) {
|
||||
promise.reject("setMode", "Invalid audio mode " + mode);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -78,7 +78,11 @@ public class BroadcastAction {
|
||||
SEND_CHAT_MESSAGE("org.jitsi.meet.SEND_CHAT_MESSAGE"),
|
||||
SET_VIDEO_MUTED("org.jitsi.meet.SET_VIDEO_MUTED"),
|
||||
SET_CLOSED_CAPTIONS_ENABLED("org.jitsi.meet.SET_CLOSED_CAPTIONS_ENABLED"),
|
||||
TOGGLE_CAMERA("org.jitsi.meet.TOGGLE_CAMERA");
|
||||
TOGGLE_CAMERA("org.jitsi.meet.TOGGLE_CAMERA"),
|
||||
SHOW_NOTIFICATION("org.jitsi.meet.SHOW_NOTIFICATION"),
|
||||
HIDE_NOTIFICATION("org.jitsi.meet.HIDE_NOTIFICATION"),
|
||||
START_RECORDING("org.jitsi.meet.START_RECORDING"),
|
||||
STOP_RECORDING("org.jitsi.meet.STOP_RECORDING");
|
||||
|
||||
private final String action;
|
||||
|
||||
|
||||
@@ -91,7 +91,7 @@ public class BroadcastEvent {
|
||||
VIDEO_MUTED_CHANGED("org.jitsi.meet.VIDEO_MUTED_CHANGED"),
|
||||
READY_TO_CLOSE("org.jitsi.meet.READY_TO_CLOSE"),
|
||||
TRANSCRIPTION_CHUNK_RECEIVED("org.jitsi.meet.TRANSCRIPTION_CHUNK_RECEIVED"),
|
||||
CUSTOM_OVERFLOW_MENU_BUTTON_PRESSED("org.jitsi.meet.CUSTOM_OVERFLOW_MENU_BUTTON_PRESSED");
|
||||
CUSTOM_BUTTON_PRESSED("org.jitsi.meet.CUSTOM_BUTTON_PRESSED");
|
||||
|
||||
private static final String CONFERENCE_BLURRED_NAME = "CONFERENCE_BLURRED";
|
||||
private static final String CONFERENCE_FOCUSED_NAME = "CONFERENCE_FOCUSED";
|
||||
@@ -109,7 +109,7 @@ public class BroadcastEvent {
|
||||
private static final String VIDEO_MUTED_CHANGED_NAME = "VIDEO_MUTED_CHANGED";
|
||||
private static final String READY_TO_CLOSE_NAME = "READY_TO_CLOSE";
|
||||
private static final String TRANSCRIPTION_CHUNK_RECEIVED_NAME = "TRANSCRIPTION_CHUNK_RECEIVED";
|
||||
private static final String CUSTOM_OVERFLOW_MENU_BUTTON_PRESSED_NAME = "CUSTOM_OVERFLOW_MENU_BUTTON_PRESSED";
|
||||
private static final String CUSTOM_BUTTON_PRESSED_NAME = "CUSTOM_BUTTON_PRESSED";
|
||||
|
||||
private final String action;
|
||||
|
||||
@@ -164,8 +164,8 @@ public class BroadcastEvent {
|
||||
return READY_TO_CLOSE;
|
||||
case TRANSCRIPTION_CHUNK_RECEIVED_NAME:
|
||||
return TRANSCRIPTION_CHUNK_RECEIVED;
|
||||
case CUSTOM_OVERFLOW_MENU_BUTTON_PRESSED_NAME:
|
||||
return CUSTOM_OVERFLOW_MENU_BUTTON_PRESSED;
|
||||
case CUSTOM_BUTTON_PRESSED_NAME:
|
||||
return CUSTOM_BUTTON_PRESSED;
|
||||
}
|
||||
|
||||
return null;
|
||||
|
||||
@@ -1,11 +1,13 @@
|
||||
package org.jitsi.meet.sdk;
|
||||
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
|
||||
public class BroadcastIntentHelper {
|
||||
public static Intent buildSetAudioMutedIntent(boolean muted) {
|
||||
Intent intent = new Intent(BroadcastAction.Type.SET_AUDIO_MUTED.getAction());
|
||||
intent.putExtra("muted", muted);
|
||||
|
||||
return intent;
|
||||
}
|
||||
|
||||
@@ -17,18 +19,21 @@ public class BroadcastIntentHelper {
|
||||
Intent intent = new Intent(BroadcastAction.Type.SEND_ENDPOINT_TEXT_MESSAGE.getAction());
|
||||
intent.putExtra("to", to);
|
||||
intent.putExtra("message", message);
|
||||
|
||||
return intent;
|
||||
}
|
||||
|
||||
public static Intent buildToggleScreenShareIntent(boolean enabled) {
|
||||
Intent intent = new Intent(BroadcastAction.Type.TOGGLE_SCREEN_SHARE.getAction());
|
||||
intent.putExtra("enabled", enabled);
|
||||
|
||||
return intent;
|
||||
}
|
||||
|
||||
public static Intent buildOpenChatIntent(String participantId) {
|
||||
Intent intent = new Intent(BroadcastAction.Type.OPEN_CHAT.getAction());
|
||||
intent.putExtra("to", participantId);
|
||||
|
||||
return intent;
|
||||
}
|
||||
|
||||
@@ -40,28 +45,98 @@ public class BroadcastIntentHelper {
|
||||
Intent intent = new Intent(BroadcastAction.Type.SEND_CHAT_MESSAGE.getAction());
|
||||
intent.putExtra("to", participantId);
|
||||
intent.putExtra("message", message);
|
||||
|
||||
return intent;
|
||||
}
|
||||
|
||||
public static Intent buildSetVideoMutedIntent(boolean muted) {
|
||||
Intent intent = new Intent(BroadcastAction.Type.SET_VIDEO_MUTED.getAction());
|
||||
intent.putExtra("muted", muted);
|
||||
|
||||
return intent;
|
||||
}
|
||||
|
||||
public static Intent buildSetClosedCaptionsEnabledIntent(boolean enabled) {
|
||||
Intent intent = new Intent(BroadcastAction.Type.SET_CLOSED_CAPTIONS_ENABLED.getAction());
|
||||
intent.putExtra("enabled", enabled);
|
||||
|
||||
return intent;
|
||||
}
|
||||
|
||||
|
||||
public static Intent buildRetrieveParticipantsInfo(String requestId) {
|
||||
Intent intent = new Intent(BroadcastAction.Type.RETRIEVE_PARTICIPANTS_INFO.getAction());
|
||||
intent.putExtra("requestId", requestId);
|
||||
|
||||
return intent;
|
||||
}
|
||||
|
||||
public static Intent buildToggleCameraIntent() {
|
||||
return new Intent(BroadcastAction.Type.TOGGLE_CAMERA.getAction());
|
||||
}
|
||||
|
||||
public static Intent buildShowNotificationIntent(
|
||||
String appearance, String description, String timeout, String title, String uid) {
|
||||
Intent intent = new Intent(BroadcastAction.Type.SHOW_NOTIFICATION.getAction());
|
||||
intent.putExtra("appearance", appearance);
|
||||
intent.putExtra("description", description);
|
||||
intent.putExtra("timeout", timeout);
|
||||
intent.putExtra("title", title);
|
||||
intent.putExtra("uid", uid);
|
||||
|
||||
return intent;
|
||||
}
|
||||
|
||||
public static Intent buildHideNotificationIntent(String uid) {
|
||||
Intent intent = new Intent(BroadcastAction.Type.HIDE_NOTIFICATION.getAction());
|
||||
intent.putExtra("uid", uid);
|
||||
|
||||
return intent;
|
||||
}
|
||||
|
||||
public enum RecordingMode {
|
||||
FILE("file"),
|
||||
STREAM("stream");
|
||||
|
||||
private final String mode;
|
||||
|
||||
RecordingMode(String mode) {
|
||||
this.mode = mode;
|
||||
}
|
||||
|
||||
public String getMode() {
|
||||
return mode;
|
||||
}
|
||||
}
|
||||
|
||||
public static Intent buildStartRecordingIntent(
|
||||
RecordingMode mode,
|
||||
String dropboxToken,
|
||||
boolean shouldShare,
|
||||
String rtmpStreamKey,
|
||||
String rtmpBroadcastID,
|
||||
String youtubeStreamKey,
|
||||
String youtubeBroadcastID,
|
||||
Bundle extraMetadata,
|
||||
boolean transcription) {
|
||||
Intent intent = new Intent(BroadcastAction.Type.START_RECORDING.getAction());
|
||||
intent.putExtra("mode", mode.getMode());
|
||||
intent.putExtra("dropboxToken", dropboxToken);
|
||||
intent.putExtra("shouldShare", shouldShare);
|
||||
intent.putExtra("rtmpStreamKey", rtmpStreamKey);
|
||||
intent.putExtra("rtmpBroadcastID", rtmpBroadcastID);
|
||||
intent.putExtra("youtubeStreamKey", youtubeStreamKey);
|
||||
intent.putExtra("youtubeBroadcastID", youtubeBroadcastID);
|
||||
intent.putExtra("extraMetadata", extraMetadata);
|
||||
intent.putExtra("transcription", transcription);
|
||||
|
||||
return intent;
|
||||
}
|
||||
|
||||
public static Intent buildStopRecordingIntent(RecordingMode mode, boolean transcription) {
|
||||
Intent intent = new Intent(BroadcastAction.Type.STOP_RECORDING.getAction());
|
||||
intent.putExtra("mode", mode.getMode());
|
||||
intent.putExtra("transcription", transcription);
|
||||
|
||||
return intent;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -37,7 +37,6 @@ import java.util.Objects;
|
||||
*
|
||||
* @author Pawel Domas
|
||||
*/
|
||||
@RequiresApi(api = Build.VERSION_CODES.O)
|
||||
public class ConnectionService extends android.telecom.ConnectionService {
|
||||
|
||||
/**
|
||||
|
||||
@@ -97,6 +97,10 @@ class ExternalAPIModule extends ReactContextBaseJavaModule {
|
||||
constants.put("SET_VIDEO_MUTED", BroadcastAction.Type.SET_VIDEO_MUTED.getAction());
|
||||
constants.put("SET_CLOSED_CAPTIONS_ENABLED", BroadcastAction.Type.SET_CLOSED_CAPTIONS_ENABLED.getAction());
|
||||
constants.put("TOGGLE_CAMERA", BroadcastAction.Type.TOGGLE_CAMERA.getAction());
|
||||
constants.put("SHOW_NOTIFICATION", BroadcastAction.Type.SHOW_NOTIFICATION.getAction());
|
||||
constants.put("HIDE_NOTIFICATION", BroadcastAction.Type.HIDE_NOTIFICATION.getAction());
|
||||
constants.put("START_RECORDING", BroadcastAction.Type.START_RECORDING.getAction());
|
||||
constants.put("STOP_RECORDING", BroadcastAction.Type.STOP_RECORDING.getAction());
|
||||
|
||||
return constants;
|
||||
}
|
||||
|
||||
@@ -271,8 +271,8 @@ public class JitsiMeetActivity extends AppCompatActivity
|
||||
// JitsiMeetLogger.i("Transcription chunk received: " + extraData);
|
||||
// }
|
||||
|
||||
// protected void onCustomOverflowMenuButtonPressed(HashMap<String, Object> extraData) {
|
||||
// JitsiMeetLogger.i("Custom overflow menu button pressed: " + extraData);
|
||||
// protected void onCustomButtonPressed(HashMap<String, Object> extraData) {
|
||||
// JitsiMeetLogger.i("Custom button pressed: " + extraData);
|
||||
// }
|
||||
|
||||
// Activity lifecycle methods
|
||||
@@ -361,8 +361,8 @@ public class JitsiMeetActivity extends AppCompatActivity
|
||||
// case TRANSCRIPTION_CHUNK_RECEIVED:
|
||||
// onTranscriptionChunkReceived(event.getData());
|
||||
// break;
|
||||
// case CUSTOM_OVERFLOW_MENU_BUTTON_PRESSED:
|
||||
// onCustomOverflowMenuButtonPressed(event.getData());
|
||||
// case CUSTOM_BUTTON_PRESSED:
|
||||
// onCustomButtonPressed(event.getData());
|
||||
// break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -42,7 +42,7 @@ public class JitsiMeetActivityDelegate {
|
||||
/**
|
||||
* Tells whether or not the permissions request is currently in progress.
|
||||
*
|
||||
* @return {@code true} if the permssions are being requested or {@code false} otherwise.
|
||||
* @return {@code true} if the permissions are being requested or {@code false} otherwise.
|
||||
*/
|
||||
static boolean arePermissionsBeingRequested() {
|
||||
return permissionListener != null;
|
||||
|
||||
@@ -83,11 +83,7 @@ public class JitsiMeetOngoingConferenceService extends Service implements Ongoin
|
||||
ComponentName componentName;
|
||||
|
||||
try {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||
componentName = context.startForegroundService(intent);
|
||||
} else {
|
||||
componentName = context.startService(intent);
|
||||
}
|
||||
componentName = context.startForegroundService(intent);
|
||||
} catch (RuntimeException e) {
|
||||
// Avoid crashing due to ForegroundServiceStartNotAllowedException (API level 31).
|
||||
// See: https://developer.android.com/guide/components/foreground-services#background-start-restrictions
|
||||
|
||||
@@ -29,8 +29,6 @@ import android.content.Intent;
|
||||
import androidx.annotation.StringRes;
|
||||
import androidx.core.app.NotificationCompat;
|
||||
|
||||
import android.os.Build;
|
||||
|
||||
|
||||
/**
|
||||
* Helper class for creating the ongoing notification which is used with
|
||||
@@ -45,10 +43,6 @@ class OngoingNotification {
|
||||
static final String ONGOING_CONFERENCE_CHANNEL_ID = "JitsiOngoingConferenceChannel";
|
||||
|
||||
static void createNotificationChannel(Activity context) {
|
||||
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (context == null) {
|
||||
JitsiMeetLogger.w(TAG + " Cannot create notification channel: no current context");
|
||||
return;
|
||||
|
||||
@@ -20,7 +20,6 @@ import android.annotation.TargetApi;
|
||||
import android.app.Activity;
|
||||
import android.app.ActivityManager;
|
||||
import android.app.PictureInPictureParams;
|
||||
import android.os.Build;
|
||||
import android.util.Rational;
|
||||
|
||||
import com.facebook.react.bridge.Promise;
|
||||
@@ -53,7 +52,7 @@ class PictureInPictureModule extends ReactContextBaseJavaModule {
|
||||
// Android Go devices don't support PiP. There doesn't seem to be a better way to detect it than
|
||||
// to use ActivityManager.isLowRamDevice().
|
||||
// https://stackoverflow.com/questions/58340558/how-to-detect-android-go
|
||||
isSupported = Build.VERSION.SDK_INT >= Build.VERSION_CODES.O && !am.isLowRamDevice();
|
||||
isSupported = !am.isLowRamDevice();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -82,7 +81,6 @@ class PictureInPictureModule extends ReactContextBaseJavaModule {
|
||||
* including when the activity is not visible (paused or stopped), if the
|
||||
* screen is locked or if the user has an activity pinned.
|
||||
*/
|
||||
@TargetApi(Build.VERSION_CODES.O)
|
||||
public void enterPictureInPicture() {
|
||||
if (!isEnabled) {
|
||||
return;
|
||||
|
||||
@@ -3,7 +3,6 @@ package org.jitsi.meet.sdk;
|
||||
import android.annotation.SuppressLint;
|
||||
import android.content.Context;
|
||||
import android.net.Uri;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.telecom.DisconnectCause;
|
||||
import android.telecom.PhoneAccount;
|
||||
@@ -32,7 +31,6 @@ import org.jitsi.meet.sdk.log.JitsiMeetLogger;
|
||||
*
|
||||
* @author Pawel Domas
|
||||
*/
|
||||
@RequiresApi(api = Build.VERSION_CODES.O)
|
||||
@ReactModule(name = RNConnectionService.NAME)
|
||||
class RNConnectionService extends ReactContextBaseJavaModule {
|
||||
|
||||
@@ -53,7 +51,6 @@ class RNConnectionService extends ReactContextBaseJavaModule {
|
||||
* @param audioRoute the new audio route to be set. See
|
||||
* {@link android.telecom.CallAudioState} constants prefixed with "ROUTE_".
|
||||
*/
|
||||
@RequiresApi(api = Build.VERSION_CODES.O)
|
||||
static void setAudioRoute(int audioRoute) {
|
||||
for (ConnectionService.ConnectionImpl c
|
||||
: ConnectionService.getConnections()) {
|
||||
|
||||
2
app.js
2
app.js
@@ -1,4 +1,4 @@
|
||||
/* application specific logic */
|
||||
/* Jitsi Meet app main entrypoint. */
|
||||
|
||||
// Re-export jQuery
|
||||
// FIXME: Remove this requirement from torture tests.
|
||||
|
||||
@@ -172,7 +172,9 @@ let room;
|
||||
|
||||
/*
|
||||
* Logic to open a desktop picker put on the window global for
|
||||
* lib-jitsi-meet to detect and invoke
|
||||
* lib-jitsi-meet to detect and invoke.
|
||||
*
|
||||
* TODO: remove once the Electron SDK supporting gDM has been out for a while.
|
||||
*/
|
||||
window.JitsiMeetScreenObtainer = {
|
||||
openDesktopPicker(options, onSourceChoose) {
|
||||
@@ -287,7 +289,7 @@ class ConferenceConnector {
|
||||
},
|
||||
descriptionKey: 'dialog.reservationErrorMsg',
|
||||
titleKey: 'dialog.reservationError'
|
||||
}, NOTIFICATION_TIMEOUT_TYPE.LONG));
|
||||
}));
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -295,7 +297,7 @@ class ConferenceConnector {
|
||||
APP.store.dispatch(showErrorNotification({
|
||||
descriptionKey: 'dialog.gracefulShutdown',
|
||||
titleKey: 'dialog.serviceUnavailable'
|
||||
}, NOTIFICATION_TIMEOUT_TYPE.LONG));
|
||||
}));
|
||||
break;
|
||||
|
||||
// FIXME FOCUS_DISCONNECTED is a confusing event name.
|
||||
@@ -1012,7 +1014,7 @@ export default {
|
||||
},
|
||||
|
||||
/**
|
||||
* Will be filled with values only when config.debug is enabled.
|
||||
* Will be filled with values only when config.testing.testMode is true.
|
||||
* Its used by torture to check audio levels.
|
||||
*/
|
||||
audioLevelsMap: {},
|
||||
@@ -1399,28 +1401,19 @@ export default {
|
||||
/**
|
||||
* Creates desktop (screensharing) {@link JitsiLocalTrack}
|
||||
*
|
||||
* @param {Object} [options] - Screen sharing options that will be passed to
|
||||
* createLocalTracks.
|
||||
* @param {Object} [options.desktopSharing]
|
||||
* @param {Object} [options.desktopStream] - An existing desktop stream to
|
||||
* use instead of creating a new desktop stream.
|
||||
* @return {Promise.<JitsiLocalTrack>} - A Promise resolved with
|
||||
* {@link JitsiLocalTrack} for the screensharing or rejected with
|
||||
* {@link JitsiTrackError}.
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
_createDesktopTrack(options = {}) {
|
||||
_createDesktopTrack() {
|
||||
const didHaveVideo = !this.isLocalVideoMuted();
|
||||
|
||||
const getDesktopStreamPromise = options.desktopStream
|
||||
? Promise.resolve([ options.desktopStream ])
|
||||
: createLocalTracksF({
|
||||
desktopSharingSourceDevice: options.desktopSharingSources
|
||||
? null : config._desktopSharingSourceDevice,
|
||||
desktopSharingSources: options.desktopSharingSources,
|
||||
devices: [ 'desktop' ]
|
||||
});
|
||||
const getDesktopStreamPromise = createLocalTracksF({
|
||||
desktopSharingSourceDevice: config._desktopSharingSourceDevice,
|
||||
devices: [ 'desktop' ]
|
||||
});
|
||||
|
||||
return getDesktopStreamPromise.then(desktopStreams => {
|
||||
// Stores the "untoggle" handler which remembers whether was
|
||||
@@ -1597,9 +1590,9 @@ export default {
|
||||
newLvl = 0;
|
||||
}
|
||||
|
||||
if (config.debug) {
|
||||
if (config.testing?.testMode) {
|
||||
this.audioLevelsMap[id] = newLvl;
|
||||
if (config.debugAudioLevels) {
|
||||
if (config.testing?.debugAudioLevels) {
|
||||
logger.log(`AudioLevel:${id}/${newLvl}`);
|
||||
}
|
||||
}
|
||||
|
||||
142
config.js
142
config.js
@@ -84,6 +84,9 @@ var config = {
|
||||
// Allows the setting of a custom bandwidth value from the UI.
|
||||
// assumeBandwidth: true,
|
||||
|
||||
// Enables use of getDisplayMedia in electron
|
||||
// electronUseGetDisplayMedia: false,
|
||||
|
||||
// Enables the use of the codec selection API supported by the browsers .
|
||||
// enableCodecSelectionAPI: false,
|
||||
|
||||
@@ -103,6 +106,12 @@ var config = {
|
||||
|
||||
// Dump transcripts to a <transcript> element for debugging.
|
||||
// dumpTranscript: false,
|
||||
|
||||
// Log the audio levels.
|
||||
// debugAudioLevels: true,
|
||||
|
||||
// Will replace ice candidates IPs with invalid ones in order to fail ice.
|
||||
// failICE: true,
|
||||
},
|
||||
|
||||
// Disables moderator indicators.
|
||||
@@ -362,9 +371,6 @@ var config = {
|
||||
|
||||
// Recording
|
||||
|
||||
// DEPRECATED. Use recordingService.enabled instead.
|
||||
// fileRecordingsEnabled: false,
|
||||
|
||||
// Enable the dropbox integration.
|
||||
// dropbox: {
|
||||
// appKey: '<APP_KEY>', // Specify your app key here.
|
||||
@@ -459,7 +465,7 @@ var config = {
|
||||
|
||||
// // Translation languages.
|
||||
// // Available languages can be found in
|
||||
// // ./src/react/features/transcribing/translation-languages.json.
|
||||
// // ./lang/translation-languages.json.
|
||||
// translationLanguages: ['en', 'es', 'fr', 'ro'],
|
||||
|
||||
// // Important languages to show on the top of the language list.
|
||||
@@ -570,30 +576,6 @@ var config = {
|
||||
// useKSVC: true
|
||||
// },
|
||||
//
|
||||
// DEPRECATED! Use `codec specific settings` instead.
|
||||
// // Provides a way to configure the maximum bitrates that will be enforced on the simulcast streams for
|
||||
// // video tracks. The keys in the object represent the type of the stream (LD, SD or HD) and the values
|
||||
// // are the max.bitrates to be set on that particular type of stream. The actual send may vary based on
|
||||
// // the available bandwidth calculated by the browser, but it will be capped by the values specified here.
|
||||
// // This is currently not implemented on app based clients on mobile.
|
||||
// maxBitratesVideo: {
|
||||
// H264: {
|
||||
// low: 200000,
|
||||
// standard: 500000,
|
||||
// high: 1500000,
|
||||
// },
|
||||
// VP8 : {
|
||||
// low: 200000,
|
||||
// standard: 500000,
|
||||
// high: 1500000,
|
||||
// },
|
||||
// VP9: {
|
||||
// low: 100000,
|
||||
// standard: 300000,
|
||||
// high: 1200000,
|
||||
// },
|
||||
// },
|
||||
//
|
||||
// // The options can be used to override default thresholds of video thumbnail heights corresponding to
|
||||
// // the video quality levels used in the application. At the time of this writing the allowed levels are:
|
||||
// // 'low' - for the low quality level (180p at the time of this writing)
|
||||
@@ -611,22 +593,6 @@ var config = {
|
||||
//
|
||||
// // Provides a way to set the codec preference on mobile devices, both on RN and mobile browser based endpoint
|
||||
// mobileCodecPreferenceOrder: [ 'VP8', 'VP9', 'H264' ],
|
||||
//
|
||||
// // DEPRECATED! Use `codecPreferenceOrder/mobileCodecPreferenceOrder` instead.
|
||||
// // Provides a way to prevent a video codec from being negotiated on the JVB connection. The codec specified
|
||||
// // here will be removed from the list of codecs present in the SDP answer generated by the client. If the
|
||||
// // same codec is specified for both the disabled and preferred option, the disable settings will prevail.
|
||||
// // Note that 'VP8' cannot be disabled since it's a mandatory codec, the setting will be ignored in this case.
|
||||
// disabledCodec: 'H264',
|
||||
//
|
||||
// // DEPRECATED! Use `codecPreferenceOrder/mobileCodecPreferenceOrder` instead.
|
||||
// // Provides a way to set a preferred video codec for the JVB connection. If 'H264' is specified here,
|
||||
// // simulcast will be automatically disabled since JVB doesn't support H264 simulcast yet. This will only
|
||||
// // rearrange the the preference order of the codecs in the SDP answer generated by the browser only if the
|
||||
// // preferred codec specified here is present. Please ensure that the JVB offers the specified codec for this
|
||||
// // to take effect.
|
||||
// preferredCodec: 'VP8',
|
||||
//
|
||||
// },
|
||||
|
||||
// Notification timeouts
|
||||
@@ -634,6 +600,7 @@ var config = {
|
||||
// short: 2500,
|
||||
// medium: 5000,
|
||||
// long: 10000,
|
||||
// extraLong: 60000,
|
||||
// },
|
||||
|
||||
// // Options for the recording limit notification.
|
||||
@@ -785,6 +752,9 @@ var config = {
|
||||
// and microsoftApiApplicationClientID
|
||||
// enableCalendarIntegration: false,
|
||||
|
||||
// The client id for the google APIs used for the calendar integration, youtube livestreaming, etc.
|
||||
// googleApiApplicationClientID: '<client_id>',
|
||||
|
||||
// Configs for prejoin page.
|
||||
// prejoinConfig: {
|
||||
// // When 'true', it shows an intermediate page before joining, where the user can configure their devices.
|
||||
@@ -819,10 +789,6 @@ var config = {
|
||||
// set or the lobby is not enabled.
|
||||
// enableInsecureRoomNameWarning: false,
|
||||
|
||||
// Whether to automatically copy invitation URL after creating a room.
|
||||
// Document should be focused for this option to work
|
||||
// enableAutomaticUrlCopy: false,
|
||||
|
||||
// Array with avatar URL prefixes that need to use CORS.
|
||||
// corsAvatarURLs: [ 'https://www.gravatar.com/avatar/' ],
|
||||
|
||||
@@ -907,7 +873,7 @@ var config = {
|
||||
// Overrides the buttons displayed in the main toolbar. Depending on the screen size the number of displayed
|
||||
// buttons varies from 2 buttons to 8 buttons. Every array in the mainToolbarButtons array will replace the
|
||||
// corresponding default buttons configuration matched by the number of buttons specified in the array. Arrays with
|
||||
// more than 8 buttons or less then 2 buttons will be ignored. When there there isn't an override for a cerain
|
||||
// more than 8 buttons or less then 2 buttons will be ignored. When there there isn't an override for a certain
|
||||
// configuration (for example when 3 buttons are displayed) the default jitsi-meet configuration will be used.
|
||||
// The order of the buttons in the array is preserved.
|
||||
// mainToolbarButtons: [
|
||||
@@ -1120,24 +1086,12 @@ var config = {
|
||||
// { urls: 'stun:jitsi-meet.example.com:3478' },
|
||||
{ urls: 'stun:meet-jit-si-turnrelay.jitsi.net:443' },
|
||||
],
|
||||
|
||||
// DEPRECATED! Use `codecPreferenceOrder/mobileCodecPreferenceOrder` instead.
|
||||
// Provides a way to set the video codec preference on the p2p connection. Acceptable
|
||||
// codec values are 'VP8', 'VP9' and 'H264'.
|
||||
// preferredCodec: 'H264',
|
||||
|
||||
// DEPRECATED! Use `codecPreferenceOrder/mobileCodecPreferenceOrder` instead.
|
||||
// Provides a way to prevent a video codec from being negotiated on the p2p connection.
|
||||
// disabledCodec: '',
|
||||
},
|
||||
|
||||
analytics: {
|
||||
// True if the analytics should be disabled
|
||||
// disabled: false,
|
||||
|
||||
// The Google Analytics Tracking ID:
|
||||
// googleAnalyticsTrackingId: 'your-tracking-id-UA-123456-1',
|
||||
|
||||
// Matomo configuration:
|
||||
// matomoEndpoint: 'https://your-matomo-endpoint/',
|
||||
// matomoSiteID: '42',
|
||||
@@ -1175,7 +1129,6 @@ var config = {
|
||||
|
||||
// Array of script URLs to load as lib-jitsi-meet "analytics handlers".
|
||||
// scriptURLs: [
|
||||
// "libs/analytics-ga.min.js", // google-analytics
|
||||
// "https://example.com/my-custom-analytics.js",
|
||||
// ],
|
||||
|
||||
@@ -1620,19 +1573,47 @@ var config = {
|
||||
// For external entities (e. g. email), the localStorage key holding the token value for directory authentication
|
||||
// peopleSearchTokenLocation: "mytoken",
|
||||
|
||||
|
||||
// Options related to visitors.
|
||||
// visitors: {
|
||||
// // Starts audio/video when the participant is promoted from visitor.
|
||||
// enableMediaOnPromote: {
|
||||
// audio: true,
|
||||
// video: true
|
||||
// },
|
||||
// },
|
||||
// The default type of desktop sharing sources that will be used in the electron app.
|
||||
// desktopSharingSources: ['screen', 'window'],
|
||||
|
||||
// Disables the echo cancelation for local audio tracks.
|
||||
// disableAEC: true,
|
||||
|
||||
// Disables the auto gain control for local audio tracks.
|
||||
// disableAGC: true,
|
||||
|
||||
// Disables the audio processing (echo cancelation, auto gain control and noise suppression) for local audio tracks.
|
||||
// disableAP: true,
|
||||
|
||||
// Disables the anoise suppression for local audio tracks.
|
||||
// disableNS: true,
|
||||
|
||||
// Replaces the display name with the JID of the participants.
|
||||
// displayJids: true,
|
||||
|
||||
// Enables disables talk while muted detection.
|
||||
// enableTalkWhileMuted: true,
|
||||
|
||||
// Sets the peer connection ICE transport policy to "relay".
|
||||
// forceTurnRelay: true,
|
||||
|
||||
// List of undocumented settings used in jitsi-meet
|
||||
/**
|
||||
_immediateReloadThreshold
|
||||
debug
|
||||
debugAudioLevels
|
||||
deploymentInfo
|
||||
dialOutAuthUrl
|
||||
dialOutCodesUrl
|
||||
dialOutRegionUrl
|
||||
disableRemoteControl
|
||||
displayJids
|
||||
firefox_fake_device
|
||||
googleApiApplicationClientID
|
||||
iAmRecorder
|
||||
iAmSipGateway
|
||||
microsoftApiApplicationClientID
|
||||
@@ -1651,14 +1632,7 @@ var config = {
|
||||
_peerConnStatusRtcMuteTimeout
|
||||
avgRtpStatsN
|
||||
desktopSharingSources
|
||||
disableAEC
|
||||
disableAGC
|
||||
disableAP
|
||||
disableHPF
|
||||
disableLocalStats
|
||||
disableNS
|
||||
enableTalkWhileMuted
|
||||
forceTurnRelay
|
||||
hiddenDomain
|
||||
hiddenFromRecorderFeatureEnabled
|
||||
ignoreStartMuted
|
||||
@@ -1735,7 +1709,7 @@ var config = {
|
||||
// 'notify.participantsWantToJoin', // shown when lobby is enabled and participants request to join meeting
|
||||
// 'notify.passwordRemovedRemotely', // shown when a password has been removed remotely
|
||||
// 'notify.passwordSetRemotely', // shown when a password has been set remotely
|
||||
// 'notify.raisedHand', // shown when a partcipant used raise hand,
|
||||
// 'notify.raisedHand', // shown when a participant used raise hand,
|
||||
// 'notify.screenShareNoAudio', // shown when the audio could not be shared for the selected screen
|
||||
// 'notify.screenSharingAudioOnlyTitle', // shown when the best performance has been affected by screen sharing
|
||||
// 'notify.selfViewTitle', // show "You can always un-hide the self-view from settings"
|
||||
@@ -1766,7 +1740,7 @@ var config = {
|
||||
// disableFilmstripAutohiding: false,
|
||||
|
||||
// filmstrip: {
|
||||
// // Disable the vertical/horizonal filmstrip.
|
||||
// // Disable the vertical/horizontal filmstrip.
|
||||
// disabled: false,
|
||||
// // Disables user resizable filmstrip. Also, allows configuration of the filmstrip
|
||||
// // (width, tiles aspect ratios) through the interfaceConfig options.
|
||||
@@ -1825,9 +1799,10 @@ var config = {
|
||||
// //disableLogCollector: true,
|
||||
// // Individual loggers are customizable.
|
||||
// loggers: {
|
||||
// // The following are too verbose in their logging with the default level.
|
||||
// 'modules/RTC/TraceablePeerConnection.js': 'info',
|
||||
// 'modules/xmpp/strophe.util.js': 'log',
|
||||
// // The following are too verbose in their logging with the default level.
|
||||
// 'modules/RTC/TraceablePeerConnection.js': 'info',
|
||||
// 'modules/xmpp/strophe.util.js': 'log',
|
||||
// },
|
||||
// },
|
||||
|
||||
// Application logo url
|
||||
@@ -1883,13 +1858,10 @@ var config = {
|
||||
|
||||
// Hide login button on auth dialog, you may want to enable this if you are using JWT tokens to authenticate users
|
||||
// hideLoginButton: true,
|
||||
};
|
||||
|
||||
// Temporary backwards compatibility with old mobile clients.
|
||||
config.flags = config.flags || {};
|
||||
config.flags.sourceNameSignaling = true;
|
||||
config.flags.sendMultipleVideoStreams = true;
|
||||
config.flags.receiveMultipleVideoStreams = true;
|
||||
// If true remove the tint foreground on focused user camera in filmstrip
|
||||
// disableCameraTintForeground: false,
|
||||
};
|
||||
|
||||
// Set the default values for JaaS customers
|
||||
if (enableJaaS) {
|
||||
|
||||
@@ -19,11 +19,11 @@
|
||||
flex-direction: column;
|
||||
|
||||
.description {
|
||||
color: #2f3237;
|
||||
font-size: 14px;
|
||||
line-height: 18px;
|
||||
margin-bottom: 16px;
|
||||
max-width: 436px;
|
||||
color: #2f3237;
|
||||
font-size: 14px;
|
||||
line-height: 18px;
|
||||
margin-bottom: 16px;
|
||||
max-width: 436px;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -127,7 +127,8 @@
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
&.with-click-handler:hover {
|
||||
&.with-click-handler:hover,
|
||||
&.with-click-handler:focus {
|
||||
background-color: #c7ddff;
|
||||
}
|
||||
|
||||
@@ -155,14 +156,22 @@
|
||||
margin-right: 16px;
|
||||
position: absolute;
|
||||
|
||||
&> svg {
|
||||
&>svg {
|
||||
fill: #0074e0;
|
||||
}
|
||||
}
|
||||
|
||||
.item:hover, .item:focus, .item:focus-within {
|
||||
.item:hover,
|
||||
.item:focus,
|
||||
.item:focus-within {
|
||||
.delete-meeting {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.delete-meeting:hover {
|
||||
&>svg {
|
||||
fill: #4687ED;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
16
debian/jitsi-meet-web-config.postinst
vendored
16
debian/jitsi-meet-web-config.postinst
vendored
@@ -175,22 +175,6 @@ case "$1" in
|
||||
fi
|
||||
fi
|
||||
|
||||
# Fixes multi-stream flags to workaround problem with mobile joining a multi-stream call with multi-stream disabled
|
||||
FIX_MSG="// Temporary backwards compatibility with old mobile clients."
|
||||
if ! grep -q "^${FIX_MSG}" $JITSI_MEET_CONFIG; then
|
||||
echo $FIX_MSG >> $JITSI_MEET_CONFIG
|
||||
echo "config.flags = config.flags || {};" >> $JITSI_MEET_CONFIG
|
||||
fi
|
||||
if ! grep -q "^config.flags.sourceNameSignaling*" $JITSI_MEET_CONFIG; then
|
||||
echo "config.flags.sourceNameSignaling = true;" >> $JITSI_MEET_CONFIG
|
||||
fi
|
||||
if ! grep -q "^config.flags.sendMultipleVideoStreams*" $JITSI_MEET_CONFIG; then
|
||||
echo "config.flags.sendMultipleVideoStreams = true;" >> $JITSI_MEET_CONFIG
|
||||
fi
|
||||
if ! grep -q "^config.flags.receiveMultipleVideoStreams*" $JITSI_MEET_CONFIG; then
|
||||
echo "config.flags.receiveMultipleVideoStreams = true;" >> $JITSI_MEET_CONFIG
|
||||
fi
|
||||
|
||||
if [[ "$FORCE_OPENRESTY" = "true" ]]; then
|
||||
NGX_COMMON_CONF_PATH="/usr/local/openresty/nginx/conf/$JVB_HOSTNAME.conf"
|
||||
NGX_SVC_NAME=openresty
|
||||
|
||||
1
globals.d.ts
vendored
1
globals.d.ts
vendored
@@ -18,7 +18,6 @@ declare global {
|
||||
JITSI_MEET_LITE_SDK?: boolean;
|
||||
interfaceConfig?: any;
|
||||
JitsiMeetJS?: any;
|
||||
JitsiMeetElectron?: any;
|
||||
PressureObserver?: any;
|
||||
PressureRecord?: any;
|
||||
ReactNativeWebView?: any;
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 4.2 KiB After Width: | Height: | Size: 2.7 KiB |
@@ -41,14 +41,6 @@ var interfaceConfig = {
|
||||
*/
|
||||
DISABLE_PRESENCE_STATUS: false,
|
||||
|
||||
/**
|
||||
* Whether the ringing sound in the call/ring overlay is disabled. If
|
||||
* {@code undefined}, defaults to {@code false}.
|
||||
*
|
||||
* @type {boolean}
|
||||
*/
|
||||
DISABLE_RINGING: false,
|
||||
|
||||
/**
|
||||
* Whether the speech to text transcription subtitles panel is disabled.
|
||||
* If {@code undefined}, defaults to {@code false}.
|
||||
@@ -70,9 +62,6 @@ var interfaceConfig = {
|
||||
|
||||
ENABLE_DIAL_OUT: true,
|
||||
|
||||
// DEPRECATED. Animation no longer supported.
|
||||
// ENABLE_FEEDBACK_ANIMATION: false,
|
||||
|
||||
FILM_STRIP_MAX_HEIGHT: 120,
|
||||
|
||||
GENERATE_ROOMNAMES_ON_WELCOME_PAGE: true,
|
||||
@@ -227,7 +216,7 @@ var interfaceConfig = {
|
||||
/**
|
||||
* Specify custom URL for downloading f droid app.
|
||||
*/
|
||||
// MOBILE_DOWNLOAD_LINK_F_DROID: 'https://f-droid.org/en/packages/org.jitsi.meet/',
|
||||
// MOBILE_DOWNLOAD_LINK_F_DROID: 'https://f-droid.org/packages/org.jitsi.meet/',
|
||||
|
||||
// Connection indicators (
|
||||
// CONNECTION_INDICATOR_AUTO_HIDE_ENABLED,
|
||||
|
||||
@@ -1,2 +1,6 @@
|
||||
THIS_DIR=$(cd -P "$(dirname "$(readlink "${BASH_SOURCE[0]}" || echo "${BASH_SOURCE[0]}")")" && pwd)
|
||||
|
||||
. ${THIS_DIR}/../node_modules/react-native/scripts/find-node-for-xcode.sh
|
||||
|
||||
export NODE_BINARY=$(command -v node)
|
||||
export ENTRY_FILE="${PROJECT_DIR}/../../index.ios.js"
|
||||
|
||||
20
ios/Podfile
20
ios/Podfile
@@ -78,8 +78,6 @@ target 'JitsiMeetSDKLite' do
|
||||
end
|
||||
|
||||
post_install do |installer|
|
||||
|
||||
PLIST_BUDDY_PATH = '/usr/libexec/PlistBuddy'
|
||||
react_native_post_install(
|
||||
installer,
|
||||
use_native_modules![:reactNativePath],
|
||||
@@ -98,23 +96,5 @@ post_install do |installer|
|
||||
config.build_settings['IPHONEOS_DEPLOYMENT_TARGET'] = '15.1'
|
||||
config.build_settings['OTHER_SWIFT_FLAGS'] = '$(inherited) -no-verify-emitted-module-interface'
|
||||
end
|
||||
|
||||
# Can be removed when updated to RN 0.76
|
||||
# Issue https://github.com/facebook/react-native/issues/35863#issuecomment-1387465588
|
||||
if target.name == "hermes-engine"
|
||||
installer.pods_project.files.each do |fileref|
|
||||
if fileref.path.end_with? "hermes.xcframework"
|
||||
hermes_plist_file = "#{fileref.real_path}/Info.plist"
|
||||
# Patch Hermes to remove the debug symbols entry from the Info.plist (as it's not shipped with it)
|
||||
# This might be removed once Hermes starts to ship with Debug symbols or we remove our
|
||||
# direct dependency from the Main iOS target on "hermes.xcframework"
|
||||
Open3.capture3(PLIST_BUDDY_PATH, '-c', 'Delete :AvailableLibraries:0:DebugSymbolsPath', hermes_plist_file)
|
||||
Open3.capture3(PLIST_BUDDY_PATH, '-c', 'Delete :AvailableLibraries:1:DebugSymbolsPath', hermes_plist_file)
|
||||
Open3.capture3(PLIST_BUDDY_PATH, '-c', 'Delete :AvailableLibraries:2:DebugSymbolsPath', hermes_plist_file)
|
||||
Open3.capture3(PLIST_BUDDY_PATH, '-c', 'Delete :AvailableLibraries:3:DebugSymbolsPath', hermes_plist_file)
|
||||
Open3.capture3(PLIST_BUDDY_PATH, '-c', 'Delete :AvailableLibraries:4:DebugSymbolsPath', hermes_plist_file)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
578
ios/Podfile.lock
578
ios/Podfile.lock
File diff suppressed because it is too large
Load Diff
@@ -29,11 +29,19 @@
|
||||
didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
|
||||
JitsiMeet *jitsiMeet = [JitsiMeet sharedInstance];
|
||||
|
||||
#if 0
|
||||
jitsiMeet.webRtcLoggingSeverity = WebRTCLoggingSeverityVerbose;
|
||||
#endif
|
||||
|
||||
jitsiMeet.conferenceActivityType = JitsiMeetConferenceActivityType;
|
||||
jitsiMeet.customUrlScheme = @"org.jitsi.meet";
|
||||
jitsiMeet.universalLinkDomains = @[@"meet.jit.si", @"alpha.jitsi.net", @"beta.meet.jit.si"];
|
||||
|
||||
jitsiMeet.defaultConferenceOptions = [JitsiMeetConferenceOptions fromBuilder:^(JitsiMeetConferenceOptionsBuilder *builder) {
|
||||
|
||||
// For testing configOverrides a room needs to be set
|
||||
// builder.room = @"https://meet.jit.si/test0988test";
|
||||
|
||||
[builder setFeatureFlag:@"welcomepage.enabled" withBoolean:YES];
|
||||
[builder setFeatureFlag:@"ios.screensharing.enabled" withBoolean:YES];
|
||||
[builder setFeatureFlag:@"ios.recording.enabled" withBoolean:YES];
|
||||
|
||||
@@ -88,8 +88,8 @@
|
||||
[self _onJitsiMeetViewDelegateEvent:@"CONFERENCE_WILL_JOIN" withData:data];
|
||||
}
|
||||
|
||||
// - (void)customOverflowMenuButtonPressed:(NSDictionary *)data {
|
||||
// [self _onJitsiMeetViewDelegateEvent:@"CUSTOM_OVERFLOW_MENU_BUTTON_PRESSED" withData:data];
|
||||
// - (void)customButtonPressed:(NSDictionary *)data {
|
||||
// [self _onJitsiMeetViewDelegateEvent:@"CUSTOM_BUTTON_PRESSED" withData:data];
|
||||
// }
|
||||
|
||||
#if 0
|
||||
|
||||
@@ -69,7 +69,7 @@ platform :ios do
|
||||
end
|
||||
)
|
||||
|
||||
# Inrement the build number by 1
|
||||
# Increment the build number by 1
|
||||
increment_build_number(
|
||||
build_number: Time.now.to_i,
|
||||
xcodeproj: "app/app.xcodeproj"
|
||||
|
||||
@@ -54,7 +54,7 @@ pushd ${RELEASE_REPO}
|
||||
|
||||
# Put the new files in the repo
|
||||
cp -a ${PROJECT_REPO}/ios/sdk/out/JitsiMeetSDK.xcframework lite/Frameworks/
|
||||
cp -a ${PROJECT_REPO}/ios/sdk/out/hermes.xcframework lite/Frameworks/
|
||||
cp -a ${PROJECT_REPO}/ios/Pods/hermes-engine/destroot/Library/Frameworks/universal/hermes.xcframework lite/Frameworks/
|
||||
|
||||
# Add all files to git
|
||||
git add -A .
|
||||
|
||||
@@ -54,7 +54,7 @@ pushd ${RELEASE_REPO}
|
||||
|
||||
# Put the new files in the repo
|
||||
cp -a ${PROJECT_REPO}/ios/sdk/out/JitsiMeetSDK.xcframework Frameworks/
|
||||
cp -a ${PROJECT_REPO}/ios/sdk/out/hermes.xcframework Frameworks/
|
||||
cp -a ${PROJECT_REPO}/ios/Pods/hermes-engine/destroot/Library/Frameworks/universal/hermes.xcframework Frameworks/
|
||||
|
||||
# Add all files to git
|
||||
git add -A .
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
#import <WebRTC/WebRTC.h>
|
||||
|
||||
#import "JitsiAudioSession+Private.h"
|
||||
#import "callkit/JMCallKitProxy.h"
|
||||
|
||||
|
||||
// Audio mode
|
||||
@@ -54,6 +55,7 @@ static NSString * const kDeviceTypeUnknown = @"UNKNOWN";
|
||||
RTCAudioSessionConfiguration *audioCallConfig;
|
||||
RTCAudioSessionConfiguration *videoCallConfig;
|
||||
RTCAudioSessionConfiguration *earpieceConfig;
|
||||
BOOL audioDisabled;
|
||||
BOOL forceSpeaker;
|
||||
BOOL forceEarpiece;
|
||||
BOOL isSpeakerOn;
|
||||
@@ -146,9 +148,36 @@ RCT_EXPORT_MODULE();
|
||||
|
||||
#pragma mark - Exported methods
|
||||
|
||||
RCT_EXPORT_METHOD(setDisabled:(BOOL)disabled
|
||||
resolve:(RCTPromiseResolveBlock)resolve
|
||||
reject:(RCTPromiseRejectBlock)reject) {
|
||||
if (audioDisabled == disabled) {
|
||||
resolve(nil);
|
||||
return;
|
||||
}
|
||||
|
||||
RCTLogInfo(@"[AudioMode] audio disabled: %d", disabled);
|
||||
|
||||
audioDisabled = disabled;
|
||||
JMCallKitProxy.enabled = !disabled;
|
||||
|
||||
RTCAudioSession *session = JitsiAudioSession.rtcAudioSession;
|
||||
if (disabled) {
|
||||
[session removeDelegate:self];
|
||||
} else {
|
||||
[session addDelegate:self];
|
||||
}
|
||||
session.useManualAudio = disabled;
|
||||
}
|
||||
|
||||
RCT_EXPORT_METHOD(setMode:(int)mode
|
||||
resolve:(RCTPromiseResolveBlock)resolve
|
||||
reject:(RCTPromiseRejectBlock)reject) {
|
||||
if (audioDisabled) {
|
||||
resolve(nil);
|
||||
return;
|
||||
}
|
||||
|
||||
RTCAudioSessionConfiguration *config = [self configForMode:mode];
|
||||
NSError *error;
|
||||
|
||||
@@ -177,6 +206,11 @@ RCT_EXPORT_METHOD(setMode:(int)mode
|
||||
RCT_EXPORT_METHOD(setAudioDevice:(NSString *)device
|
||||
resolve:(RCTPromiseResolveBlock)resolve
|
||||
reject:(RCTPromiseRejectBlock)reject) {
|
||||
if (audioDisabled) {
|
||||
resolve(nil);
|
||||
return;
|
||||
}
|
||||
|
||||
RCTLogInfo(@"[AudioMode] Selected device: %@", device);
|
||||
|
||||
RTCAudioSession *session = JitsiAudioSession.rtcAudioSession;
|
||||
@@ -239,6 +273,10 @@ RCT_EXPORT_METHOD(setAudioDevice:(NSString *)device
|
||||
}
|
||||
|
||||
RCT_EXPORT_METHOD(updateDeviceList) {
|
||||
if (audioDisabled) {
|
||||
return;
|
||||
}
|
||||
|
||||
[self notifyDevicesChanged];
|
||||
}
|
||||
|
||||
|
||||
@@ -18,6 +18,11 @@
|
||||
|
||||
static NSString * const sendEventNotificationName = @"org.jitsi.meet.SendEvent";
|
||||
|
||||
typedef NS_ENUM(NSInteger, RecordingMode) {
|
||||
RecordingModeFile,
|
||||
RecordingModeStream
|
||||
};
|
||||
|
||||
@interface ExternalAPI : RCTEventEmitter<RCTBridgeModule>
|
||||
|
||||
- (void)sendHangUp;
|
||||
@@ -27,9 +32,13 @@ static NSString * const sendEventNotificationName = @"org.jitsi.meet.SendEvent";
|
||||
- (void)retrieveParticipantsInfo:(void (^)(NSArray*))completion;
|
||||
- (void)openChat:(NSString*)to;
|
||||
- (void)closeChat;
|
||||
- (void)sendChatMessage:(NSString*)message :(NSString*)to ;
|
||||
- (void)sendChatMessage:(NSString*)message :(NSString*)to;
|
||||
- (void)sendSetVideoMuted:(BOOL)muted;
|
||||
- (void)sendSetClosedCaptionsEnabled:(BOOL)enabled;
|
||||
- (void)toggleCamera;
|
||||
- (void)showNotification:(NSString*)appearance :(NSString*)description :(NSString*)timeout :(NSString*)title :(NSString*)uid;
|
||||
- (void)hideNotification:(NSString*)uid;
|
||||
- (void)startRecording:(RecordingMode)mode :(NSString*)dropboxToken :(BOOL)shouldShare :(NSString*)rtmpStreamKey :(NSString*)rtmpBroadcastID :(NSString*)youtubeStreamKey :(NSString*)youtubeBroadcastID :(NSDictionary*)extraMetadata :(BOOL)transcription;
|
||||
- (void)stopRecording:(RecordingMode)mode :(BOOL)transcription;
|
||||
|
||||
@end
|
||||
|
||||
@@ -28,6 +28,10 @@ static NSString * const sendChatMessageAction = @"org.jitsi.meet.SEND_CHAT_MESSA
|
||||
static NSString * const setVideoMutedAction = @"org.jitsi.meet.SET_VIDEO_MUTED";
|
||||
static NSString * const setClosedCaptionsEnabledAction = @"org.jitsi.meet.SET_CLOSED_CAPTIONS_ENABLED";
|
||||
static NSString * const toggleCameraAction = @"org.jitsi.meet.TOGGLE_CAMERA";
|
||||
static NSString * const showNotificationAction = @"org.jitsi.meet.SHOW_NOTIFICATION";
|
||||
static NSString * const hideNotificationAction = @"org.jitsi.meet.HIDE_NOTIFICATION";
|
||||
static NSString * const startRecordingAction = @"org.jitsi.meet.START_RECORDING";
|
||||
static NSString * const stopRecordingAction = @"org.jitsi.meet.STOP_RECORDING";
|
||||
|
||||
@implementation ExternalAPI
|
||||
|
||||
@@ -52,7 +56,11 @@ RCT_EXPORT_MODULE();
|
||||
@"SEND_CHAT_MESSAGE": sendChatMessageAction,
|
||||
@"SET_VIDEO_MUTED" : setVideoMutedAction,
|
||||
@"SET_CLOSED_CAPTIONS_ENABLED": setClosedCaptionsEnabledAction,
|
||||
@"TOGGLE_CAMERA": toggleCameraAction
|
||||
@"TOGGLE_CAMERA": toggleCameraAction,
|
||||
@"SHOW_NOTIFICATION": showNotificationAction,
|
||||
@"HIDE_NOTIFICATION": hideNotificationAction,
|
||||
@"START_RECORDING": startRecordingAction,
|
||||
@"STOP_RECORDING": stopRecordingAction
|
||||
};
|
||||
};
|
||||
|
||||
@@ -78,7 +86,11 @@ RCT_EXPORT_MODULE();
|
||||
sendChatMessageAction,
|
||||
setVideoMutedAction,
|
||||
setClosedCaptionsEnabledAction,
|
||||
toggleCameraAction
|
||||
toggleCameraAction,
|
||||
showNotificationAction,
|
||||
hideNotificationAction,
|
||||
startRecordingAction,
|
||||
stopRecordingAction
|
||||
];
|
||||
}
|
||||
|
||||
@@ -180,4 +192,59 @@ RCT_EXPORT_METHOD(sendEvent:(NSString *)name
|
||||
[self sendEventWithName:toggleCameraAction body:nil];
|
||||
}
|
||||
|
||||
- (void)showNotification:(NSString*)appearance :(NSString*)description :(NSString*)timeout :(NSString*)title :(NSString*)uid {
|
||||
NSMutableDictionary *data = [[NSMutableDictionary alloc] init];
|
||||
data[@"appearance"] = appearance;
|
||||
data[@"description"] = description;
|
||||
data[@"timeout"] = timeout;
|
||||
data[@"title"] = title;
|
||||
data[@"uid"] = uid;
|
||||
|
||||
[self sendEventWithName:showNotificationAction body:data];
|
||||
}
|
||||
|
||||
- (void)hideNotification:(NSString*)uid {
|
||||
NSMutableDictionary *data = [[NSMutableDictionary alloc] init];
|
||||
data[@"uid"] = uid;
|
||||
|
||||
[self sendEventWithName:hideNotificationAction body:data];
|
||||
}
|
||||
|
||||
static inline NSString *RecordingModeToString(RecordingMode mode) {
|
||||
switch (mode) {
|
||||
case RecordingModeFile:
|
||||
return @"file";
|
||||
case RecordingModeStream:
|
||||
return @"stream";
|
||||
default:
|
||||
return nil;
|
||||
}
|
||||
}
|
||||
|
||||
- (void)startRecording:(RecordingMode)mode :(NSString*)dropboxToken :(BOOL)shouldShare :(NSString*)rtmpStreamKey :(NSString*)rtmpBroadcastID :(NSString*)youtubeStreamKey :(NSString*)youtubeBroadcastID :(NSDictionary*)extraMetadata :(BOOL)transcription {
|
||||
NSString *modeString = RecordingModeToString(mode);
|
||||
NSDictionary *data = @{
|
||||
@"mode": modeString,
|
||||
@"dropboxToken": dropboxToken,
|
||||
@"shouldShare": @(shouldShare),
|
||||
@"rtmpStreamKey": rtmpStreamKey,
|
||||
@"rtmpBroadcastID": rtmpBroadcastID,
|
||||
@"youtubeStreamKey": youtubeStreamKey,
|
||||
@"youtubeBroadcastID": youtubeBroadcastID,
|
||||
@"extraMetadata": extraMetadata,
|
||||
@"transcription": @(transcription)
|
||||
};
|
||||
|
||||
[self sendEventWithName:startRecordingAction body:data];
|
||||
}
|
||||
|
||||
- (void)stopRecording:(RecordingMode)mode :(BOOL)transcription {
|
||||
NSString *modeString = RecordingModeToString(mode);
|
||||
NSDictionary *data = @{
|
||||
@"mode": modeString,
|
||||
@"transcription": @(transcription)
|
||||
};
|
||||
|
||||
[self sendEventWithName:stopRecordingAction body:data];
|
||||
}
|
||||
@end
|
||||
|
||||
@@ -24,11 +24,15 @@
|
||||
}
|
||||
|
||||
+ (void)activateWithAudioSession:(AVAudioSession *)session {
|
||||
[self.rtcAudioSession audioSessionDidActivate:session];
|
||||
if (!self.rtcAudioSession.useManualAudio) {
|
||||
[self.rtcAudioSession audioSessionDidActivate:session];
|
||||
}
|
||||
}
|
||||
|
||||
+ (void)deactivateWithAudioSession:(AVAudioSession *)session {
|
||||
[self.rtcAudioSession audioSessionDidDeactivate:session];
|
||||
if (!self.rtcAudioSession.useManualAudio) {
|
||||
[self.rtcAudioSession audioSessionDidDeactivate:session];
|
||||
}
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@@ -19,6 +19,15 @@
|
||||
|
||||
#import <JitsiMeetSDK/JitsiMeetConferenceOptions.h>
|
||||
|
||||
// Matches RTCLoggingSeverity from RTCLogging.h
|
||||
typedef NS_ENUM(NSInteger, WebRTCLoggingSeverity) {
|
||||
WebRTCLoggingSeverityVerbose,
|
||||
WebRTCLoggingSeverityInfo,
|
||||
WebRTCLoggingSeverityWarning,
|
||||
WebRTCLoggingSeverityError,
|
||||
WebRTCLoggingSeverityNone,
|
||||
};
|
||||
|
||||
@interface JitsiMeet : NSObject
|
||||
|
||||
/**
|
||||
@@ -26,20 +35,35 @@
|
||||
* SiriKit or Handoff, for example.
|
||||
*/
|
||||
@property (copy, nonatomic, nullable) NSString *conferenceActivityType;
|
||||
|
||||
/**
|
||||
* Custom URL scheme used for deep-linking.
|
||||
*/
|
||||
@property (copy, nonatomic, nullable) NSString *customUrlScheme;
|
||||
|
||||
/**
|
||||
* List of domains used for universal linking.
|
||||
*/
|
||||
@property (copy, nonatomic, nullable) NSArray<NSString *> *universalLinkDomains;
|
||||
|
||||
/**
|
||||
* Default conference options used for all conferences. These options will be merged
|
||||
* with those passed to JitsiMeetView.join when joining a conference.
|
||||
*/
|
||||
@property (nonatomic, nullable) JitsiMeetConferenceOptions *defaultConferenceOptions;
|
||||
|
||||
/**
|
||||
* Custom RTCAudioDevice implementation.
|
||||
* https://github.com/jitsi/webrtc/blob/M124/sdk/objc/components/audio/RTCAudioDevice.h
|
||||
* https://github.com/mstyura/RTCAudioDevice
|
||||
*/
|
||||
@property (nonatomic, strong, nullable) id rtcAudioDevice;
|
||||
|
||||
/**
|
||||
* Specify WebRTC logging severity.
|
||||
*/
|
||||
@property (nonatomic, assign) WebRTCLoggingSeverity webRtcLoggingSeverity;
|
||||
|
||||
#pragma mark - This class is a singleton
|
||||
|
||||
+ (instancetype _Nonnull)sharedInstance;
|
||||
|
||||
@@ -54,14 +54,9 @@
|
||||
|
||||
- (instancetype)init {
|
||||
if (self = [super init]) {
|
||||
#if 0
|
||||
// Initialize WebRTC options.
|
||||
WebRTCModuleOptions *options = [WebRTCModuleOptions sharedInstance];
|
||||
options.loggingSeverity = RTCLoggingSeverityInfo;
|
||||
#endif
|
||||
|
||||
// Initialize the one and only bridge for interfacing with React Native.
|
||||
_bridgeWrapper = [[RCTBridgeWrapper alloc] init];
|
||||
self.rtcAudioDevice = nil;
|
||||
self.webRtcLoggingSeverity = WebRTCLoggingSeverityNone;
|
||||
|
||||
// Initialize the listener for handling start/stop screensharing notifications.
|
||||
_screenshareEventEmiter = [[ScheenshareEventEmiter alloc] init];
|
||||
@@ -142,6 +137,12 @@
|
||||
return;
|
||||
};
|
||||
|
||||
// Initialize WebRTC options.
|
||||
WebRTCModuleOptions *options = [WebRTCModuleOptions sharedInstance];
|
||||
options.audioDevice = _rtcAudioDevice;
|
||||
options.loggingSeverity = (RTCLoggingSeverity)_webRtcLoggingSeverity;
|
||||
|
||||
// Initialize the one and only bridge for interfacing with React Native.
|
||||
_bridgeWrapper = [[RCTBridgeWrapper alloc] init];
|
||||
}
|
||||
|
||||
@@ -231,6 +232,9 @@
|
||||
}
|
||||
|
||||
- (void)setDefaultConferenceOptions:(JitsiMeetConferenceOptions *)defaultConferenceOptions {
|
||||
|
||||
// For testing configOverrides a room needs to be set,
|
||||
// thus the following check needs to be commented out
|
||||
if (defaultConferenceOptions != nil && defaultConferenceOptions.room != nil) {
|
||||
@throw [NSException exceptionWithName:@"RuntimeError"
|
||||
reason:@"'room' must be null in the default conference options"
|
||||
@@ -246,6 +250,8 @@
|
||||
}
|
||||
|
||||
- (RCTBridge *)getReactBridge {
|
||||
// Initialize bridge lazily.
|
||||
[self instantiateReactNativeBridge];
|
||||
return _bridgeWrapper.bridge;
|
||||
}
|
||||
|
||||
|
||||
@@ -21,6 +21,8 @@
|
||||
#import "JitsiMeetConferenceOptions.h"
|
||||
#import "JitsiMeetViewDelegate.h"
|
||||
|
||||
typedef NS_ENUM(NSInteger, RecordingMode);
|
||||
|
||||
@interface JitsiMeetView : UIView
|
||||
|
||||
@property (nonatomic, nullable, weak) id<JitsiMeetViewDelegate> delegate;
|
||||
@@ -47,5 +49,9 @@
|
||||
- (void)setVideoMuted:(BOOL)muted;
|
||||
- (void)setClosedCaptionsEnabled:(BOOL)enabled;
|
||||
- (void)toggleCamera;
|
||||
- (void)showNotification:(NSString * _Nonnull)appearance :(NSString * _Nullable)description :(NSString * _Nullable)timeout :(NSString * _Nullable)title :(NSString * _Nullable)uid;
|
||||
- (void)hideNotification:(NSString * _Nullable)uid;
|
||||
- (void)startRecording:(RecordingMode)mode :(NSString * _Nullable)dropboxToken :(BOOL)shouldShare :(NSString * _Nullable)rtmpStreamKey :(NSString * _Nullable)rtmpBroadcastID :(NSString * _Nullable)youtubeStreamKey :(NSString * _Nullable)youtubeBroadcastID :(NSString * _Nullable)extraMetadata :(BOOL)transcription;
|
||||
- (void)stopRecording:(RecordingMode)mode :(BOOL)transcription;
|
||||
|
||||
@end
|
||||
|
||||
@@ -143,6 +143,26 @@ static NSString *const PiPEnabledFeatureFlag = @"pip.enabled";
|
||||
[externalAPI toggleCamera];
|
||||
}
|
||||
|
||||
- (void)showNotification:(NSString *)appearance :(NSString *)description :(NSString *)timeout :(NSString *)title :(NSString *)uid {
|
||||
ExternalAPI *externalAPI = [[JitsiMeet sharedInstance] getExternalAPI];
|
||||
[externalAPI showNotification:appearance :description :timeout :title :uid];
|
||||
}
|
||||
|
||||
-(void)hideNotification:(NSString *)uid {
|
||||
ExternalAPI *externalAPI = [[JitsiMeet sharedInstance] getExternalAPI];
|
||||
[externalAPI hideNotification:uid];
|
||||
}
|
||||
|
||||
- (void)startRecording:(RecordingMode)mode :(NSString *)dropboxToken :(BOOL)shouldShare :(NSString *)rtmpStreamKey :(NSString *)rtmpBroadcastID :(NSString *)youtubeStreamKey :(NSString *)youtubeBroadcastID :(NSString *)extraMetadata :(BOOL)transcription {
|
||||
ExternalAPI *externalAPI = [[JitsiMeet sharedInstance] getExternalAPI];
|
||||
[externalAPI startRecording:mode :dropboxToken :shouldShare :rtmpStreamKey :rtmpBroadcastID :youtubeStreamKey :youtubeBroadcastID :extraMetadata :transcription];
|
||||
}
|
||||
|
||||
- (void)stopRecording:(RecordingMode)mode :(BOOL)transcription {
|
||||
ExternalAPI *externalAPI = [[JitsiMeet sharedInstance] getExternalAPI];
|
||||
[externalAPI stopRecording:mode :transcription];
|
||||
}
|
||||
|
||||
#pragma mark Private methods
|
||||
|
||||
- (void)registerObservers {
|
||||
|
||||
@@ -128,6 +128,6 @@
|
||||
*
|
||||
* The `data` dictionary contains a `id`, `text` key.
|
||||
*/
|
||||
- (void)customOverflowMenuButtonPressed:(NSDictionary *)data;
|
||||
- (void)customButtonPressed:(NSDictionary *)data;
|
||||
|
||||
@end
|
||||
|
||||
@@ -37,6 +37,7 @@
|
||||
"ml": "മലയാളം",
|
||||
"mn": "Монгол",
|
||||
"mr": "मराठी",
|
||||
"nb": "Norsk bokmål",
|
||||
"nl": "Nederlands",
|
||||
"oc": "Occitan",
|
||||
"pl": "Polski",
|
||||
|
||||
@@ -334,6 +334,7 @@
|
||||
"kickParticipantButton": "Expulser",
|
||||
"kickParticipantDialog": "Êtes-vous sûr(e) de vouloir expulser ce participant ?",
|
||||
"kickParticipantTitle": "Expulser ce participant ?",
|
||||
"kickSystemTitle": "Oups ! Vous avez été expulsé de la réunion",
|
||||
"kickTitle": "Oups ! vous avez été expulsé(e) par {{participantDisplayName}}",
|
||||
"linkMeeting": "Relier la conférence",
|
||||
"linkMeetingTitle": "Relier la conférence à Salesforce",
|
||||
@@ -439,7 +440,10 @@
|
||||
"shareScreenWarningD2": "vous devez arrêter le partage d'audio, démarrer le partage d'écran et cocher l'option \"Partager l'audio\".",
|
||||
"shareScreenWarningH1": "Si vous voulez partager uniquement votre écran:",
|
||||
"shareScreenWarningTitle": "Vous devez cesser de partager votre audio avant de partager votre écran",
|
||||
"shareVideoConfirmPlay": "Vous êtes sur le point d'ouvrir un site web externe. Voulez-vous continuer ?",
|
||||
"shareVideoConfirmPlayTitle": "{{name}} a partagé une vidéo avec vous.",
|
||||
"shareVideoLinkError": "Veuillez renseigner un lien de diffusion vidéo fonctionnel.",
|
||||
"shareVideoLinkStopped": "La vidéo de {{name}} a été arrêtée.",
|
||||
"shareVideoTitle": "Partager une vidéo",
|
||||
"shareYourScreen": "Partager votre écran",
|
||||
"shareYourScreenDisabled": "Le partage d'écran est désactivé.",
|
||||
@@ -638,6 +642,7 @@
|
||||
"on": "En direct",
|
||||
"onBy": "{{name}} a démarré la diffusion en direct",
|
||||
"pending": "Lancement du direct…",
|
||||
"policyError": "Vous avez essayé de démarrer une diffusion en direct trop rapidement. Veuillez réessayer plus tard !",
|
||||
"serviceName": "Service de diffusion en direct",
|
||||
"sessionAlreadyActive": "Cette session est déjà en cours d'enregistrement ou de diffusion.",
|
||||
"signIn": "Se connecter avec Google",
|
||||
@@ -736,6 +741,7 @@
|
||||
"connectedOneMember": "{{name}} a rejoint la réunion",
|
||||
"connectedThreePlusMembers": "{{name}} et {{count}} autres personnes ont rejoint la réunion",
|
||||
"connectedTwoMembers": "{{first}} et {{second}} ont rejoint la réunion",
|
||||
"connectionFailed": "Connexion échouée. Veuillez réessayer plus tard !",
|
||||
"dataChannelClosed": "Qualité vidéo dégradée",
|
||||
"dataChannelClosedDescription": "Le canal de communication avec le Bridge a été interrompu, la qualité vidéo se trouve limitée à sa valeur la plus faible.",
|
||||
"dataChannelClosedDescriptionWithAudio": "Le canal de pont est fermé, ce qui peut entraîner des perturbations de l'audio et de la vidéo.",
|
||||
@@ -750,6 +756,9 @@
|
||||
"gifsMenu": "GIPHY",
|
||||
"groupTitle": "Notifications",
|
||||
"hostAskedUnmute": "Le modérateur souhaite vous donner la parole",
|
||||
"invalidTenant": "Tenant invalide",
|
||||
"invalidTenantHyphenDescription": "Le tenant que vous utilisez est invalide (commence ou se termine par '-').",
|
||||
"invalidTenantLengthDescription": "Le tenant que vous utilisez est trop long.",
|
||||
"invitedOneMember": "{{name}} a été invité(e)",
|
||||
"invitedThreePlusMembers": "{{name}} et {{count}} autres ont été invités",
|
||||
"invitedTwoMembers": "{{first}} et {{second}} ont été invités",
|
||||
@@ -786,6 +795,7 @@
|
||||
"newDeviceAction": "Utiliser",
|
||||
"newDeviceAudioTitle": "Nouveau périphérique audio détecté",
|
||||
"newDeviceCameraTitle": "Nouvelle caméra détectée",
|
||||
"nextToSpeak": "Vous êtes le prochain à prendre la parole",
|
||||
"noiseSuppressionDesktopAudioDescription": "La suppression de bruit ne peut pas être activée en même temps que la partage audio du système, veuillez le désactiver et réessayer.",
|
||||
"noiseSuppressionFailedTitle": "Échec du démarrage de la suppression de bruit",
|
||||
"noiseSuppressionStereoDescription": "La suppression de bruit d’une source stéréo n’est pas encore supportée.",
|
||||
@@ -820,6 +830,7 @@
|
||||
"videoUnmuteBlockedDescription": "Le rétablissement de la vidéo a été bloqué temporairement en raison de limites système.",
|
||||
"videoUnmuteBlockedTitle": "Rétablissement de la caméra bloqué !",
|
||||
"viewLobby": "Voir la salle d'attente",
|
||||
"viewParticipants": "Voir les participants",
|
||||
"viewVisitors": "Voir les visiteurs",
|
||||
"waitingParticipants": "{{waitingParticipants}} personnes",
|
||||
"waitingVisitors": "Visiteurs en attente dans la file : {{waitingVisitors}}",
|
||||
@@ -839,6 +850,8 @@
|
||||
"breakoutRooms": "Salles annexes",
|
||||
"goLive": "Passer en direct",
|
||||
"invite": "Inviter quelqu'un",
|
||||
"lowerAllHands": "Abaisser toutes les mains",
|
||||
"lowerHand": "Abaisser la main",
|
||||
"moreModerationActions": "Options de modération supplémentaires",
|
||||
"moreModerationControls": "Options de modération supplémentaires",
|
||||
"moreParticipantOptions": "Options supplémentaires pour les participants",
|
||||
@@ -875,6 +888,7 @@
|
||||
"submit": "Envoyer"
|
||||
},
|
||||
"by": "Par {{ name }}",
|
||||
"closeButton": "Fermer le sondage",
|
||||
"create": {
|
||||
"addOption": "Ajouter une option",
|
||||
"answerPlaceholder": "Option {{index}}",
|
||||
@@ -914,9 +928,11 @@
|
||||
"configuringDevices": "Configuration des appareils…",
|
||||
"connectedWithAudioQ": "Êtes-vous connecté avec le microphone ?",
|
||||
"connection": {
|
||||
"failed": "Le test de connexion a échoué !",
|
||||
"good": "Votre connexion Internet est bonne !",
|
||||
"nonOptimal": "Votre connexion n'est pas optimale",
|
||||
"poor": "Vous avez une mauvaise connexion"
|
||||
"poor": "Vous avez une mauvaise connexion",
|
||||
"running": "Exécution du test de connexion…"
|
||||
},
|
||||
"connectionDetails": {
|
||||
"audioClipping": "Attendez vous à ce que votre son soit coupé.",
|
||||
@@ -925,6 +941,7 @@
|
||||
"goodQuality": "Impressionnant ! La qualité de vos médias sera excellente",
|
||||
"noMediaConnectivity": "Nous n'avons pas pu trouver un moyen d'établir une connectivité multimédia pour ce test. Cela est généralement causé par un pare-feu ou un NAT.",
|
||||
"noVideo": "Attendez vous à ce que votre qualité vidéo soit très mauvaise.",
|
||||
"testFailed": "Le test de connexion a rencontré des problèmes inattendus, mais cela pourrait ne pas affecter votre expérience.",
|
||||
"undetectable": "Si vous ne parvenez toujours pas à passer des appels dans le navigateur, nous vous recommandons de vous assurer que vos haut-parleurs, microphone et caméra sont correctement configurés, que vous avez accordé à votre navigateur les droits d'utiliser votre microphone et votre caméra et que la version de votre navigateur est à jour. Si vous rencontrez toujours des difficultés pour appeler, vous devez contacter le développeur de l'application Web.",
|
||||
"veryPoorConnection": "Attendez vous à ce que la qualité de votre appel soit très mauvaise",
|
||||
"videoFreezing": "Attendez vous à ce que votre vidéo saute, soit noire, et pixelisée.",
|
||||
@@ -1040,6 +1057,7 @@
|
||||
"onBy": "{{name}} a démarré l'enregistrement",
|
||||
"onlyRecordSelf": "Enregistrer seulement mon audio et ma vidéo.",
|
||||
"pending": "Préparation de l'enregistrement de la réunion…",
|
||||
"policyError": "Vous avez essayé de démarrer un enregistrement trop rapidement. Veuillez réessayer plus tard !",
|
||||
"recordAudioAndVideo": "Enregistrer l'audio et la vidéo",
|
||||
"recordTranscription": "Enregistrer la transcription",
|
||||
"saveLocalRecording": "Sauvegarder l’enregistrement local (Beta)",
|
||||
@@ -1088,6 +1106,7 @@
|
||||
"desktopShareWarning": "Vous devez repartager l'écran pour que ces paramètres soient utilisés.",
|
||||
"devices": "Périphériques",
|
||||
"followMe": "Tout le monde me suit",
|
||||
"followMeRecorder": "L'enregistreur me suit",
|
||||
"framesPerSecond": "images par seconde",
|
||||
"incomingMessage": "un message arrive",
|
||||
"language": "Langue",
|
||||
@@ -1234,6 +1253,7 @@
|
||||
"lobbyButton": "Activer / Désactiver le mode salle d'attente",
|
||||
"localRecording": "Activer / Désactiver les contrôles d'enregistrement local",
|
||||
"lockRoom": "Activer / Désactiver le mot de passe de la réunion",
|
||||
"love": "Cœur",
|
||||
"lowerHand": "Baisser la main",
|
||||
"moreActions": "Activer / Désactiver le menu d'actions supplémentaires",
|
||||
"moreActionsMenu": "Menu d'actions supplémentaires",
|
||||
@@ -1251,6 +1271,7 @@
|
||||
"privateMessage": "Envoyer un message privé",
|
||||
"profile": "Éditer votre profil",
|
||||
"raiseHand": "Lever la main",
|
||||
"react": "Réactions aux messages",
|
||||
"reactions": "Réactions",
|
||||
"reactionsMenu": "Ouvrir / fermer le menu réactions",
|
||||
"recording": "Activer / Désactiver l'enregistrement",
|
||||
@@ -1322,6 +1343,7 @@
|
||||
"lobbyButtonEnable": "Activer le mode salle d'attente / contrôle des participant(e)s",
|
||||
"login": "Connexion",
|
||||
"logout": "Déconnexion",
|
||||
"love": "Cœur",
|
||||
"lowerYourHand": "Baisser la main",
|
||||
"moreActions": "Plus d'actions",
|
||||
"moreOptions": "Plus d'options",
|
||||
@@ -1347,6 +1369,7 @@
|
||||
"raiseYourHand": "Lever la main",
|
||||
"reactionBoo": "Envoyer réaction huer",
|
||||
"reactionClap": "Envoyer réaction applaudir",
|
||||
"reactionHeart": "Envoyer une réaction en forme de cœur",
|
||||
"reactionLaugh": "Envoyer réaction rire",
|
||||
"reactionLike": "Envoyer réaction approuver",
|
||||
"reactionSilence": "Envoyer réaction silence",
|
||||
@@ -1380,7 +1403,7 @@
|
||||
"transcribing": {
|
||||
"ccButtonTooltip": "Activer / Désactiver les sous-titres",
|
||||
"expandedLabel": "La transcription est actuellement activée",
|
||||
"failedToStart": "Échec de démarrage de la transcription",
|
||||
"failed": "La transcription a échoué",
|
||||
"labelToolTip": "La transcription de la réunion est en cours",
|
||||
"sourceLanguageDesc": "Actuellement, la langue de la réunion est sélectionnée à <b>{{sourceLanguage}}</b>. <br/> Vous pouvez la changer à partir de ",
|
||||
"sourceLanguageHere": "ici",
|
||||
@@ -1481,10 +1504,15 @@
|
||||
},
|
||||
"visitors": {
|
||||
"chatIndicator": "(visiteur)",
|
||||
"labelTooltip": "Nombre de Visiteurs",
|
||||
"joinMeeting": {
|
||||
"description": "Vous êtes actuellement un observateur dans cette conférence.",
|
||||
"raiseHand": "Levez la main",
|
||||
"title": "Rejoindre la réunion",
|
||||
"wishToSpeak": "Si vous souhaitez prendre la parole, veuillez lever la main ci-dessous et attendre l'approbation du modérateur."
|
||||
},
|
||||
"labelTooltip": "Nombre de Visiteurs: {{count}}",
|
||||
"notification": {
|
||||
"demoteDescription": "Envoyé ici par {{actor}}, levez la main pour participer",
|
||||
"description": "Pour participer lever la main.",
|
||||
"noMainParticipantsDescription": "Un participant doit démarrer la réunion. Veuillez réessayer dans un moment.",
|
||||
"noMainParticipantsTitle": "Cette réunion n'a pas encore commencé.",
|
||||
"noVisitorLobby": "Vous ne pouvez pas rejoindre tant qu'une salle d'attente est activée pour la réunion.",
|
||||
|
||||
@@ -334,6 +334,7 @@
|
||||
"kickParticipantButton": "Izraidīt",
|
||||
"kickParticipantDialog": "Vai esat pārliecināti, ka vēlaties izraidīt šo dalībnieku?",
|
||||
"kickParticipantTitle": "Izraidīt šo dalībnieku?",
|
||||
"kickSystemTitle": "Ak! Jūs izraidīja no sapulces",
|
||||
"kickTitle": "Ak! {{participantDisplayName}} izraidīja jūs no sapulces",
|
||||
"linkMeeting": "Sasaistīt sapulci",
|
||||
"linkMeetingTitle": "Sasaistīt sapulci ar Salesforce",
|
||||
|
||||
1584
lang/main-nb.json
Normal file
1584
lang/main-nb.json
Normal file
File diff suppressed because it is too large
Load Diff
@@ -1,5 +1,8 @@
|
||||
{
|
||||
"addPeople": {
|
||||
"accessibilityLabel": {
|
||||
"meetingLink": "Mötes länk: {{url}}"
|
||||
},
|
||||
"add": "Bjud in",
|
||||
"addContacts": "Bjud in dina kontakter",
|
||||
"contacts": "Kontakter",
|
||||
@@ -39,6 +42,18 @@
|
||||
"audioOnly": {
|
||||
"audioOnly": "Enbart ljud"
|
||||
},
|
||||
"bandwidthSettings": {
|
||||
"assumedBandwidthBps": "t.ex. 10000000 för 10 Mbps",
|
||||
"assumedBandwidthBpsWarning": "Högre värden kan skapa nätverksproblem.",
|
||||
"customValue": "anpassat värde",
|
||||
"customValueEffect": "för att ställa in det faktiska bps-värdet",
|
||||
"leaveEmpty": "lämna tomt",
|
||||
"leaveEmptyEffect": "för att uppskattningar ska äga rum",
|
||||
"possibleValues": "Möjliga värden",
|
||||
"setAssumedBandwidthBps": "Uppskattat värde (bps)",
|
||||
"title": "Bandbreddsinställningar",
|
||||
"zeroEffect": "för att slå av video"
|
||||
},
|
||||
"breakoutRooms": {
|
||||
"actions": {
|
||||
"add": "Lägg till grupprum",
|
||||
@@ -48,15 +63,22 @@
|
||||
"leaveBreakoutRoom": "Lämna grupprum",
|
||||
"more": "Mer",
|
||||
"remove": "Ta bort",
|
||||
"rename": "Döp om",
|
||||
"renameBreakoutRoom": "Döp om grupprum",
|
||||
"sendToBreakoutRoom": "Skicka deltagare till grupprum:"
|
||||
},
|
||||
"breakoutList": "Grupprums lista",
|
||||
"buttonLabel": "Grupprum",
|
||||
"defaultName": "Grupprum #{{index}}",
|
||||
"hideParticipantList": "Dölj deltagarlista",
|
||||
"mainRoom": "Huvudrum",
|
||||
"notifications": {
|
||||
"joined": "Gick med i \"{{name}}\"",
|
||||
"joined": "Gick med i grupprum \"{{name}}\"",
|
||||
"joinedMainRoom": "Gick med i huvudrummet",
|
||||
"joinedTitle": "Grupprum"
|
||||
}
|
||||
},
|
||||
"showParticipantList": "Visa deltagarlista",
|
||||
"title": "Grupprum"
|
||||
},
|
||||
"calendarSync": {
|
||||
"addMeetingURL": "Lägg till en möteslänk",
|
||||
@@ -106,6 +128,7 @@
|
||||
"privateNotice": "Privat meddelande till {{recipient}}",
|
||||
"sendButton": "Skicka",
|
||||
"smileysPanel": "Emoji panel",
|
||||
"systemDisplayName": "",
|
||||
"tabs": {
|
||||
"chat": "Chatt",
|
||||
"polls": "Omröstningar"
|
||||
@@ -197,7 +220,9 @@
|
||||
"joinInBrowser": "Delta på webben",
|
||||
"launchMeetingLabel": "Hur vill du delta i detta möte?",
|
||||
"launchWebButton": "Starta på webben",
|
||||
"noDesktopApp": "",
|
||||
"noMobileApp": "Har du inte appen?",
|
||||
"or": "",
|
||||
"termsAndConditions": "Genom att fortsätta godkänner du våra <a href='{{termsAndConditionsLink}}' rel='noopener noreferrer' target='_blank'>villkor.</a>",
|
||||
"title": "Startar ditt möte i {{app}}…",
|
||||
"titleNew": "Startar ditt möte…",
|
||||
@@ -239,9 +264,13 @@
|
||||
"Share": "Dela",
|
||||
"Submit": "Skicka",
|
||||
"WaitForHostMsg": "Konferensen har inte börjat än. Autentisera konferensen om du är värd. Vänta annars på att värden startar konferensen.",
|
||||
"WaitForHostNoAuthMsg": "Konferensen har ännu inte startat eftersom ingen värd har anlänt ännu. Vänligen vänta.",
|
||||
"WaitingForHostButton": "Vänta på värd",
|
||||
"WaitingForHostTitle": "Väntar på värden…",
|
||||
"Yes": "Ja",
|
||||
"accessibilityLabel": {
|
||||
"Cancel": "Avbryt",
|
||||
"Ok": "Ok",
|
||||
"close": "Stäng",
|
||||
"liveStreaming": "Livesändning",
|
||||
"sharingTabs": "Delningsalternativ"
|
||||
@@ -250,6 +279,8 @@
|
||||
"addMeetingNote": "Mötesinformation",
|
||||
"addOptionalNote": "Ytterligare information",
|
||||
"allow": "Tillåt",
|
||||
"allowToggleCameraDialog": "Tillåter du att {{initiatorName}} får växla kamera till ansiktsläge?",
|
||||
"allowToggleCameraTitle": "Tillåt att växla kamera",
|
||||
"alreadySharedVideoMsg": "En annan deltagare delar redan en video. Konferensen tillåter bara en video-delning åt gången.",
|
||||
"alreadySharedVideoTitle": "Endast en delad video åt gången tillåts",
|
||||
"applicationWindow": "Applikationsfönster",
|
||||
@@ -276,6 +307,8 @@
|
||||
"contactSupport": "Kontakta kundtjänst",
|
||||
"copied": "Kopierad",
|
||||
"copy": "Kopiera",
|
||||
"demoteParticipantDialog": "Are you sure you want to move this participant to viewer? Är du säker på att du vill flytta denna deltagaren till tittare",
|
||||
"demoteParticipantTitle": "Flytta till tittare",
|
||||
"dismiss": "Förkasta",
|
||||
"displayNameRequired": "Hej, vad heter du?",
|
||||
"done": "Klar",
|
||||
@@ -287,6 +320,7 @@
|
||||
"embedMeeting": "Bädda in möte",
|
||||
"enterDisplayName": "Ange namn",
|
||||
"error": "Fel",
|
||||
"errorRoomCreationRestriction": "Du försökte gå med för snabbt, kom tillbaka om en stund.",
|
||||
"gracefulShutdown": "Vår tjänst är för tillfället nedstängd för underhåll. Vänligen försök senare.",
|
||||
"grantModeratorDialog": "Är du säker du vill göra denna deltagare till en moderator?",
|
||||
"grantModeratorTitle": "Godkänn moderator",
|
||||
@@ -300,6 +334,7 @@
|
||||
"kickParticipantButton": "Sparka ut",
|
||||
"kickParticipantDialog": "Vill du sparka ut den här deltagaren?",
|
||||
"kickParticipantTitle": "Tysta deltagaren?",
|
||||
"kickSystemTitle": "Aj! du blev utsparkad ur mötet",
|
||||
"kickTitle": "Aj! {{participantDisplayName}} sparkade ut dig ur mötet",
|
||||
"linkMeeting": "Länka möte",
|
||||
"linkMeetingTitle": "Länka möte till Salesforce",
|
||||
@@ -310,7 +345,8 @@
|
||||
"lockRoom": "Lägg till möte $t(lockRoomPasswordUppercase)",
|
||||
"lockTitle": "Låsning misslyckades",
|
||||
"login": "Logga in",
|
||||
"logoutQuestion": "Är du säker på att du vill logga ut och stoppa konferensen?",
|
||||
"loginQuestion": "Är du säker på att du vill logga in och lämna mötet",
|
||||
"logoutQuestion": "Är du säker på att du vill logga ut och lämna konferensen?",
|
||||
"logoutTitle": "Logga ut",
|
||||
"maxUsersLimitReached": "Gränsen för maximalt antal deltagare har nåtts. Konferensen är full. Kontakta mötesägaren eller försök igen senare!",
|
||||
"maxUsersLimitReachedTitle": "Maximal deltagarantal uppnått",
|
||||
@@ -353,8 +389,6 @@
|
||||
"permissionCameraRequiredError": "Tillåtelse krävs för att delta med kamera i denna möte. Var god skaffa detta i \"inställningar\".",
|
||||
"permissionErrorTitle": "Tillåtelse krävs",
|
||||
"permissionMicRequiredError": "Tillåtelse krävs för att delta med mikrofon i denna möte. Var god skaffa detta i \"inställningar\".",
|
||||
"popupError": "Din webbläsare blockerar pop-up-fönster från sajten. Tillåt pop-up-fönster från den här sajten i inställningarna och försök igen.",
|
||||
"popupErrorTitle": "Pop-up blockerad",
|
||||
"readMore": "Mer",
|
||||
"recentlyUsedObjects": "Dina senaste använda objekt",
|
||||
"recording": "Inspelning",
|
||||
@@ -371,6 +405,8 @@
|
||||
"removePassword": "Ta bort $t(lockRoomPassword)",
|
||||
"removeSharedVideoMsg": "Är du säker på att du vill ta bort din delade video?",
|
||||
"removeSharedVideoTitle": "Ta bort den delade videon",
|
||||
"renameBreakoutRoomLabel": "Rums namn",
|
||||
"renameBreakoutRoomTitle": "Döp om grupprum",
|
||||
"reservationError": "Fel i reservationssystemet",
|
||||
"reservationErrorMsg": "Felkod: {{code}}, meddelande: {{msg}}",
|
||||
"retry": "Försök igen",
|
||||
@@ -390,8 +426,10 @@
|
||||
"sendPrivateMessageTitle": "Skicka privat?",
|
||||
"serviceUnavailable": "Tjänsten otillgänglig",
|
||||
"sessTerminated": "Konferensen avslutades",
|
||||
"sessTerminatedReason": "",
|
||||
"sessionRestarted": "Samtal återstartat av bryggan",
|
||||
"shareAudio": "Fortsätt",
|
||||
"shareAudioAltText": "För att dela önskat innehåll, navigera till \"Webläsarfliken\", välj innehållet, aktivera \"dela ljud\"-kryssmärket och klicka sedan på \"dela\" knappen",
|
||||
"shareAudioTitle": "Hur man delar ljud",
|
||||
"shareAudioWarningD1": "Du måste avsluta din skärmdelning innan du kan dela ditt ljud",
|
||||
"shareAudioWarningD2": "Du måste starta om din skärmdelning och därefter klicka på \"ljuddelning\"",
|
||||
@@ -402,7 +440,10 @@
|
||||
"shareScreenWarningD2": "du måste avsluta ljuddelning, starta skärmdelning och sen aktivera \"ljuddelning\"",
|
||||
"shareScreenWarningH1": "Om du bara vill dela din skärm:",
|
||||
"shareScreenWarningTitle": "Du måste avsluta ljuddelning innan du kan dela in skärm",
|
||||
"shareVideoConfirmPlay": "Du är på väg att öppna en extern webbplats. Vill du fortsätta?",
|
||||
"shareVideoConfirmPlayTitle": "{{name}} har delat en video med dig.",
|
||||
"shareVideoLinkError": "Skriv in en fungerande länk.",
|
||||
"shareVideoLinkStopped": "Videon från {{name}} har avslutats.",
|
||||
"shareVideoTitle": "Ta bort en delad video",
|
||||
"shareYourScreen": "Dela din skärm",
|
||||
"shareYourScreenDisabled": "Skärmdelning har inaktiverats.",
|
||||
@@ -421,7 +462,25 @@
|
||||
"thankYou": "Tack för att du använder {{appName}}!",
|
||||
"token": "token",
|
||||
"tokenAuthFailed": "Du är inte behörig att delta i det här samtalet.",
|
||||
"tokenAuthFailedReason": {
|
||||
"audInvalid": "Ogiltigt `aud`-värde. Det ska vara `jitsi`.",
|
||||
"contextNotFound": "Objektet `context` saknas från payload.",
|
||||
"expInvalid": "Ogilting `exp` värde.",
|
||||
"featureInvalid": "Ogiltig feature: {{feature}}, mest troligt inte implementerat än.",
|
||||
"featureValueInvalid": "Felaktigt värde för feature: {{feature}}.",
|
||||
"featuresNotFound": "`Features` objektet saknas i payload.",
|
||||
"headerNotFound": "Saknar header.",
|
||||
"issInvalid": "Ogiltigt `iss`-värde. Det ska vara `chat`.",
|
||||
"kidMismatch": "Nyckel ID (kid) matchat inte sub.",
|
||||
"kidNotFound": "Nyckel ID saknas (kid).",
|
||||
"nbfFuture": "Värdet i `nbf` är i framtiden.",
|
||||
"nbfInvalid": "Ogilitigt `nbf`värde.",
|
||||
"payloadNotFound": "Payload saknas.",
|
||||
"tokenExpired": "Token har gått ut."
|
||||
},
|
||||
"tokenAuthFailedTitle": "Autentisering misslyckades",
|
||||
"tokenAuthFailedWithReasons": "Förlåt, du har inte tillåtelse att gå med i det här samtalet. Troliga anledingar: {{reason}}",
|
||||
"tokenAuthUnsupported": "Token URL är inte tillåten",
|
||||
"transcribing": "Transkriberar",
|
||||
"unlockRoom": "Ta bort möte $t(lockRoomPassword)",
|
||||
"user": "Användare",
|
||||
@@ -435,6 +494,10 @@
|
||||
"viewUpgradeOptions": "Se uppgraderings alternativ",
|
||||
"viewUpgradeOptionsContent": "För att få obegränsad tillgång till premiumfunktioner som inspelning, transkriptioner, RTMP-streaming och mer måste du uppgradera din plan.",
|
||||
"viewUpgradeOptionsTitle": "Du upptäckte en premiumfunktion!",
|
||||
"whiteboardLimitContent": "Förlåt, max antal samtidiga deltagare i whiteboard har uppnåts.",
|
||||
"whiteboardLimitReference": "För mer information besök",
|
||||
"whiteboardLimitReferenceUrl": "vår webplats",
|
||||
"whiteboardLimitTitle": "Användande av whiteboard har begränsats",
|
||||
"yourEntireScreen": "Helskärm"
|
||||
},
|
||||
"documentSharing": {
|
||||
@@ -447,6 +510,9 @@
|
||||
"title": "Bädda in möte"
|
||||
},
|
||||
"feedback": {
|
||||
"accessibilityLabel": {
|
||||
"yourChoice": "Ditt val: {{rating}}"
|
||||
},
|
||||
"average": "Medel",
|
||||
"bad": "Dåligt",
|
||||
"detailsLabel": "Berätta mer.",
|
||||
@@ -503,13 +569,16 @@
|
||||
"noNumbers": "Inga inringningsnummer.",
|
||||
"noPassword": "Inget lösenord",
|
||||
"noRoom": "Inget rum specificerades för inringning.",
|
||||
"noWhiteboard": "Kan inte ladda whiteboard.",
|
||||
"numbers": "Inringningsnummer",
|
||||
"password": "$t(lockRoomPasswordUppercase):",
|
||||
"reachedLimit": "Du har nått gränsen för din prenumeration.",
|
||||
"sip": "SIP adress",
|
||||
"sipAudioOnly": "SIP endast ljud address",
|
||||
"title": "Dela",
|
||||
"tooltip": "Dela länk och information om inringning för mötet",
|
||||
"upgradeOptions": "Vänligen kontrollera om uppgraderingsalternativen är på"
|
||||
"upgradeOptions": "Vänligen kontrollera om uppgraderingsalternativen är på",
|
||||
"whiteboardError": "Problem att ladda whiteboard, var god försök senare."
|
||||
},
|
||||
"inlineDialogFailure": {
|
||||
"msg": "Vi slirade lite.",
|
||||
@@ -542,8 +611,7 @@
|
||||
"toggleParticipantsPane": "Visa eller dölj deltagarfönstret",
|
||||
"toggleScreensharing": "Växla mellan kamera och skärmdelning",
|
||||
"toggleShortcuts": "Visa eller dölj kortkommandon",
|
||||
"videoMute": "Aktivera / inaktivera din kamera",
|
||||
"whiteboard": "Visa / dölj whiteboardtavlan"
|
||||
"videoMute": "Aktivera / inaktivera din kamera"
|
||||
},
|
||||
"largeVideo": {
|
||||
"screenIsShared": "Du delar din skärm",
|
||||
@@ -574,6 +642,7 @@
|
||||
"on": "Strömma",
|
||||
"onBy": "{{name}} startade direktströmningen",
|
||||
"pending": "Börja strömma…",
|
||||
"policyError": "",
|
||||
"serviceName": "Livesändningstjänst",
|
||||
"sessionAlreadyActive": "Den här sessionen spelas redan in eller livestreamas.",
|
||||
"signIn": "Logga in med Google",
|
||||
@@ -612,13 +681,13 @@
|
||||
"knockingParticipantList": "Väntande deltagare",
|
||||
"lobbyChatStartedNotification": "{{moderator}} startade en lobbychatt med {{attendee}}",
|
||||
"lobbyChatStartedTitle": "{{moderator}} har startat en lobbychatt med dig.",
|
||||
"lobbyClosed": "Lobbyn har stängts.",
|
||||
"nameField": "Ange ditt namn",
|
||||
"notificationLobbyAccessDenied": "{{targetParticipantName}} har nekats att delta av {{originParticipantName}}",
|
||||
"notificationLobbyAccessGranted": "{{targetParticipantName}} har godkänts att delta av {{originParticipantName}}",
|
||||
"notificationLobbyDisabled": "Väntrumsläge har inaktiverats av {{originParticipantName}}",
|
||||
"notificationLobbyEnabled": "Väntrumsläge har aktiverats av {{originParticipantName}}",
|
||||
"notificationTitle": "Väntrum",
|
||||
"passwordField": "Ange möteslösenord",
|
||||
"passwordJoinButton": "Anslut",
|
||||
"title": "Lobby",
|
||||
"toggleLabel": "Aktivera väntrum"
|
||||
@@ -651,6 +720,8 @@
|
||||
"sessionToken": "Sessionstoken",
|
||||
"start": "Starta inspelning",
|
||||
"stop": "Avsluta inspelning",
|
||||
"stopping": "Avslutar inspelning",
|
||||
"wait": "Var god vänta medans vi sparar din inspelning",
|
||||
"yes": "Ja"
|
||||
},
|
||||
"lockRoomPassword": "lösenord",
|
||||
@@ -670,9 +741,13 @@
|
||||
"connectedOneMember": "{{name}} har gått med i mötet",
|
||||
"connectedThreePlusMembers": "{{name}} och {{count}} andra har gått med i mötet",
|
||||
"connectedTwoMembers": "{{first}} och {{second}} har gått med i mötet",
|
||||
"connectionFailed": "Anslutning misslyckades. Var god försök senare!",
|
||||
"dataChannelClosed": "Försämrad videokvalitet",
|
||||
"dataChannelClosedDescription": "Bryggkanalen har kopplats bort och därmed är videokvaliteten begränsad till sin lägsta inställning",
|
||||
"dataChannelClosedDescriptionWithAudio": "Bryggkanalen har kopplats bort och därmed kan abvrott i ljud och bild uppstå.",
|
||||
"dataChannelClosedWithAudio": "Ljud och bild kvalite kan vara försämrad.",
|
||||
"disabledIframe": "Inbäddning är endast avsedd för demonstrationsändamål, så det här samtalet kommer att kopplas ner om {{timeout}} minuter.",
|
||||
"disabledIframeSecondary": "Bädda in {{domain}} är bara till för demo, så detta samtal kommer att kopplas bort inom {{timeout}} minuter. Var god använd <a href='{{jaasDomain}}' rel='nooper noreferrer' target='_blank'>Jitsi som tjänst</a> för att bädda in i produktion.",
|
||||
"disconnected": "frånkopplad",
|
||||
"displayNotifications": "Visa aviseringar för",
|
||||
"dontRemindMe": "Påminn mig inte",
|
||||
@@ -681,6 +756,9 @@
|
||||
"gifsMenu": "GIPHY",
|
||||
"groupTitle": "Notifieringar",
|
||||
"hostAskedUnmute": "Värden vill att du ska stänga av ljudet",
|
||||
"invalidTenant": "Ogiltig tenant",
|
||||
"invalidTenantHyphenDescription": "Tenant du använder har ogiltiga tecken (startar eller slutar med '-').",
|
||||
"invalidTenantLengthDescription": "Tenant du använder är för lång",
|
||||
"invitedOneMember": "{{name}} har bjudits in",
|
||||
"invitedThreePlusMembers": "{{name}} och {{count}} andra har bjudits in",
|
||||
"invitedTwoMembers": "{{first}} och {{second}} har bjudits in",
|
||||
@@ -717,9 +795,9 @@
|
||||
"newDeviceAction": "Använd",
|
||||
"newDeviceAudioTitle": "Ny ljudenhet hittad",
|
||||
"newDeviceCameraTitle": "Ny kamera hittad",
|
||||
"nextToSpeak": "Du är näst i kö för att prata",
|
||||
"noiseSuppressionDesktopAudioDescription": "Brusreducering kan inte aktiveras när du delar skrivbordsljud, vänligen inaktivera det och försök igen.",
|
||||
"noiseSuppressionFailedTitle": "Det gick inte att starta brusreducering",
|
||||
"noiseSuppressionNoTrackDescription": "Slå på mikrofonen först.",
|
||||
"noiseSuppressionStereoDescription": "Brusreducering i stereoljud stöds för närvarande inte.",
|
||||
"oldElectronClientDescription1": "Den version av Jitsi meet som används är gammal och har säkerhetsluckor. Var god uppdatera till den senaste versionen.",
|
||||
"oldElectronClientDescription2": "senast build",
|
||||
@@ -743,13 +821,22 @@
|
||||
"startSilentTitle": "Du gick med utan ljud aktiverat!",
|
||||
"suboptimalBrowserWarning": "Din mötesupplevelse kommer tyvärr inte att bli så bra. Vi letar efter sätt att förbättra detta, men fram till dess kan du försöka använda en av de <a href='{{recommendedBrowserPageLink}}' target='_blank'> fullt stödda webbläsarna </a>.",
|
||||
"suboptimalExperienceTitle": "Webbläsarvarning",
|
||||
"suggestRecordingAction": "Starta",
|
||||
"suggestRecordingDescription": "Vill du starta en inspelning?",
|
||||
"suggestRecordingTitle": "Spela in detta mötet",
|
||||
"unmute": "Slå på mikrofonen",
|
||||
"videoMutedRemotelyDescription": "Du kan alltid slå på den igen.",
|
||||
"videoMutedRemotelyTitle": "Din kamera har inaktiverats av {{participantDisplayName}}!",
|
||||
"videoUnmuteBlockedDescription": "Aktivering av kameran och delning av skrivbord har tillfälligt blockerats på grund av systembegränsningar.",
|
||||
"videoUnmuteBlockedTitle": "Aktivering av kameran och skrivbordsdelning blockerad!",
|
||||
"viewLobby": "Visa lobby",
|
||||
"waitingParticipants": "{{waitingParticipants}} personer"
|
||||
"viewParticipants": "Visa deltagare",
|
||||
"viewVisitors": "Visa besökare",
|
||||
"waitingParticipants": "{{waitingParticipants}} personer",
|
||||
"waitingVisitors": "Väntande besökare i kö: {{waitingVisitors}}",
|
||||
"waitingVisitorsTitle": "Mötet är inte live än!",
|
||||
"whiteboardLimitDescription": "Var god spara, max antal användare har snart uppnåtts och whiteboard kommer att stängas av.",
|
||||
"whiteboardLimitTitle": "Användande whiteboard"
|
||||
},
|
||||
"participantsPane": {
|
||||
"actions": {
|
||||
@@ -760,7 +847,11 @@
|
||||
"askUnmute": "Be om att aktivera ljud",
|
||||
"audioModeration": "Slå på ljudet för sig själva",
|
||||
"blockEveryoneMicCamera": "Inaktivera allas mikrofon och kamera",
|
||||
"breakoutRooms": "Grupprum",
|
||||
"goLive": "Gå live",
|
||||
"invite": "Bjud in någon",
|
||||
"lowerAllHands": "Ta ner allas händer",
|
||||
"lowerHand": "Ta ner handen",
|
||||
"moreModerationActions": "Fler modereringsalternativ",
|
||||
"moreModerationControls": "Fler modereringskontroller",
|
||||
"moreParticipantOptions": "Fler deltagaralternativ",
|
||||
@@ -777,6 +868,8 @@
|
||||
"headings": {
|
||||
"lobby": "Väntrum ({{count}})",
|
||||
"participantsList": "Mötesdeltagare ({{count}})",
|
||||
"visitorInQueue": "(väntande {{count}})",
|
||||
"visitorRequests": "(förfrågningar {{count}})",
|
||||
"visitors": "Gäster ({{count}})",
|
||||
"waitingLobby": "Väntar i väntrum ({{count}})"
|
||||
},
|
||||
@@ -789,10 +882,13 @@
|
||||
"pinnedParticipant": "Deltagaren är fäst",
|
||||
"polls": {
|
||||
"answer": {
|
||||
"edit": "Redigera",
|
||||
"send": "Skicka",
|
||||
"skip": "Avstå",
|
||||
"submit": "Skicka"
|
||||
},
|
||||
"by": "Av {{ name }}",
|
||||
"closeButton": "Stäng omröstning",
|
||||
"create": {
|
||||
"addOption": "Lägg till alternativ",
|
||||
"answerPlaceholder": "Alternativ",
|
||||
@@ -802,6 +898,7 @@
|
||||
"pollQuestion": "Fråga för omröstning",
|
||||
"questionPlaceholder": "Ställ en fråga",
|
||||
"removeOption": "Ta bort alternativ",
|
||||
"save": "Spara",
|
||||
"send": "Skicka"
|
||||
},
|
||||
"errors": {
|
||||
@@ -831,9 +928,11 @@
|
||||
"configuringDevices": "Konfigurerar enheter…",
|
||||
"connectedWithAudioQ": "Är din mikrofon ansluten?",
|
||||
"connection": {
|
||||
"failed": "Anslutningstest misslyckades!",
|
||||
"good": "Din internetanslutning fungerar bra!",
|
||||
"nonOptimal": "Din internetanslutning är inte optimal",
|
||||
"poor": "Din internetanslutning fungerar dåligt"
|
||||
"poor": "Din internetanslutning fungerar dåligt",
|
||||
"running": "Kör anslutningstest..."
|
||||
},
|
||||
"connectionDetails": {
|
||||
"audioClipping": "Ditt ljud kan upplevas hackigt.",
|
||||
@@ -842,6 +941,7 @@
|
||||
"goodQuality": "Grymt bra! Din mediekvalitet kommer att bli bra.",
|
||||
"noMediaConnectivity": "Vi kunde inte hitta ett sätt att upprätta mediaanslutning för detta test. Detta orsakas vanligtvis av en brandvägg eller NAT.",
|
||||
"noVideo": "Vi förväntar oss att din video kommer ha låg kvalitet eller inte fungera.",
|
||||
"testFailed": "Anslutningstestet stötte på oväntade problem, men det behöver inte påverka din upplevelse.",
|
||||
"undetectable": "Om du fortfarande inte kan ringa i webbläsaren rekommenderar vi att du ser till att dina högtalare, mikrofon och kamera är korrekt inställda, att du har beviljat din webbläsare rättigheter att använda din mikrofon och kamera och att din webbläsarversion är uppdaterad.",
|
||||
"veryPoorConnection": "Vi förväntar oss att din samtalskvalitet är riktigt dålig.",
|
||||
"videoFreezing": "Vi förväntar oss att din video fryser, blir svart och pixeleras.",
|
||||
@@ -874,6 +974,7 @@
|
||||
"or": "eller",
|
||||
"premeeting": "Förmöte",
|
||||
"proceedAnyway": "Fortsätt ändå",
|
||||
"recordingWarning": "",
|
||||
"screenSharingError": "Skärmdelningsfel:",
|
||||
"showScreen": "Aktivera skärmen före mötet",
|
||||
"startWithPhone": "Börja med telefonljud",
|
||||
@@ -940,7 +1041,6 @@
|
||||
"limitNotificationDescriptionNative": "På grund av stor efterfrågan är din inspelning begränsad till {{limit}} min. För obegränsade inspelningar, försök <3>{{app}}</3>.",
|
||||
"limitNotificationDescriptionWeb": "På grund av stor efterfrågan är din inspelning begränsad till {{limit}} min. För obegränsade inspelningar, prova <a href={{url}} rel='noopener noreferrer' target='_blank'>{{app}}</a>.",
|
||||
"linkGenerated": "Vi har genererat en länk till din inspelning.",
|
||||
"live": "LIVE",
|
||||
"localRecordingNoNotificationWarning": "Inspelningen kommer inte att meddelas till andra deltagare. Du måste meddela dem att mötet inspelas.",
|
||||
"localRecordingNoVideo": "Video spelas inte in",
|
||||
"localRecordingStartWarning": "Se till att du stoppar inspelningen innan du avslutar mötet för att spara det.",
|
||||
@@ -957,13 +1057,16 @@
|
||||
"onBy": "{{name}} påbörjade inspelningen",
|
||||
"onlyRecordSelf": "Spela bara in mina ljud- och videoströmmar",
|
||||
"pending": "Förbereder inspelning av mötet…",
|
||||
"rec": "REC",
|
||||
"policyError": "Du försökte starta inspelningen för fort. Var god försök senare!",
|
||||
"recordAudioAndVideo": "Spela in ljud och bild",
|
||||
"recordTranscription": "Spela in transkribiering",
|
||||
"saveLocalRecording": "Spara inspelningsfil lokalt (beta)",
|
||||
"serviceDescription": "Din inspelning kommer att sparas av inspelningstjänsten",
|
||||
"serviceDescriptionCloud": "Molninspelning",
|
||||
"serviceDescriptionCloudInfo": "Inspelade möten rensas automatiskt 24 timmar efter inspelningstiden.",
|
||||
"serviceName": "Inspelningstjänst",
|
||||
"sessionAlreadyActive": "Den här sessionen spelas redan in eller livestreamas.",
|
||||
"showAdvancedOptions": "Visa avancerade inställningar",
|
||||
"signIn": "Logga in",
|
||||
"signOut": "Logga ut",
|
||||
"surfaceError": "Välj aktuell flik.",
|
||||
@@ -1003,6 +1106,7 @@
|
||||
"desktopShareWarning": "Du måste starta om skärmdelningen för att de nya inställningarna ska träda i kraft.",
|
||||
"devices": "Enheter",
|
||||
"followMe": "Alla följer mig",
|
||||
"followMeRecorder": "Den som spelar in följer mig",
|
||||
"framesPerSecond": "bildrutor per sekund",
|
||||
"incomingMessage": "Inkommande meddelande",
|
||||
"language": "Språk",
|
||||
@@ -1040,6 +1144,7 @@
|
||||
"alertOk": "OK",
|
||||
"alertTitle": "Varning",
|
||||
"alertURLText": "Den angivna serverlänken är felaktig",
|
||||
"apply": "Tillämpa",
|
||||
"buildInfoSection": "Versionsinformation",
|
||||
"conferenceSection": "Konferens",
|
||||
"disableCallIntegration": "Tillåt inte deltagande via telefon",
|
||||
@@ -1050,12 +1155,14 @@
|
||||
"displayNamePlaceholderText": "Exempel: John Doe",
|
||||
"email": "E-post",
|
||||
"emailPlaceholderText": "mejl@exempel.se",
|
||||
"gavatarMessage": "Om din e-post är associerad med ett Gravatar konto, så kommer vi använda det för att visa din profilbild.",
|
||||
"goTo": "Gå till",
|
||||
"header": "Inställningar",
|
||||
"help": "Hjälp",
|
||||
"links": "Länkar",
|
||||
"privacy": "Sekretess",
|
||||
"profileSection": "Profil",
|
||||
"sdkVersion": "",
|
||||
"serverURL": "Serverlänk",
|
||||
"showAdvanced": "Visa avancerade inställningar",
|
||||
"startCarModeInLowBandwidthMode": "Starta billäget i lågbandbreddsläge",
|
||||
@@ -1076,6 +1183,7 @@
|
||||
"fearful": "Rädd",
|
||||
"happy": "Glad",
|
||||
"hours": "{{count}} h",
|
||||
"labelTooltip": "",
|
||||
"minutes": "{{count}} m",
|
||||
"name": "Namn",
|
||||
"neutral": "Neutral",
|
||||
@@ -1108,7 +1216,7 @@
|
||||
"audioOnly": "Slå av eller på ljudet",
|
||||
"audioRoute": "Välj ljudenhet",
|
||||
"boo": "Bua",
|
||||
"breakoutRoom": "Anslut eller lämna grupprum",
|
||||
"breakoutRooms": "Grupprum",
|
||||
"callQuality": "Hantera videokvalitet",
|
||||
"carmode": "Billäge",
|
||||
"cc": "Slå av eller på undertexter",
|
||||
@@ -1146,6 +1254,7 @@
|
||||
"lobbyButton": "Aktivera / inaktivera lobbyläge",
|
||||
"localRecording": "Växla lokala inspelningskontroller",
|
||||
"lockRoom": "Växla möteslösenord",
|
||||
"love": "Kärlek",
|
||||
"lowerHand": "Sänk din hand",
|
||||
"moreActions": "Fler åtgärder",
|
||||
"moreActionsMenu": "Menyn Fler åtgärder",
|
||||
@@ -1155,6 +1264,7 @@
|
||||
"muteEveryoneElse": "Stäng av ljudet för alla andra",
|
||||
"muteEveryoneElsesVideoStream": "Stoppa alla andras video",
|
||||
"muteEveryonesVideoStream": "Stoppa allas video",
|
||||
"muteGUMPending": "Ansluter din mikrofon",
|
||||
"noiseSuppression": "Brusdämpning",
|
||||
"openChat": "Öppna chatt",
|
||||
"participants": "Öppna deltagarfönstret",
|
||||
@@ -1162,6 +1272,7 @@
|
||||
"privateMessage": "Skicka privat meddelande",
|
||||
"profile": "Redigera din profil",
|
||||
"raiseHand": "Räck upp handen",
|
||||
"react": "Reaktioner på meddelanden",
|
||||
"reactions": "Reaktioner",
|
||||
"reactionsMenu": "Reaktionsmeny",
|
||||
"recording": "Växla inspelning",
|
||||
@@ -1188,6 +1299,7 @@
|
||||
"unmute": "Slå på ljudet",
|
||||
"videoblur": "Växla videooskärpa",
|
||||
"videomute": "Stoppa kamera",
|
||||
"videomuteGUMPending": "Ansluter din kamera",
|
||||
"videounmute": "Starta kameran"
|
||||
},
|
||||
"addPeople": "Lägg till personer i samtal",
|
||||
@@ -1232,12 +1344,14 @@
|
||||
"lobbyButtonEnable": "Aktivera väntrumsläge",
|
||||
"login": "Logga in",
|
||||
"logout": "Logga ut",
|
||||
"love": "Kärlek",
|
||||
"lowerYourHand": "Ta ner handen",
|
||||
"moreActions": "Fler handlingar",
|
||||
"moreOptions": "Visa fler alternativ",
|
||||
"mute": "Slå av/på ljud",
|
||||
"muteEveryone": "Tysta alla",
|
||||
"muteEveryonesVideo": "Inaktivera allas kamera",
|
||||
"muteGUMPending": "Ansluter din mikrofon",
|
||||
"noAudioSignalDesc": "Om du inte avsiktligt stängde av det från systeminställningar eller hårdvara, överväg att byta enhet.",
|
||||
"noAudioSignalDescSuggestion": "Om du inte avsiktligt tystade det från systeminställningar eller hårdvara, överväg att byta till den föreslagna enheten.",
|
||||
"noAudioSignalDialInDesc": "Du kan också ringa in med:",
|
||||
@@ -1254,8 +1368,9 @@
|
||||
"profile": "Redigera din profil",
|
||||
"raiseHand": "Räck upp / ta ner din hand",
|
||||
"raiseYourHand": "Räck upp handen",
|
||||
"reactionBoo": "Bua",
|
||||
"reactionClap": "Klappa",
|
||||
"reactionBoo": "Skicka Bu",
|
||||
"reactionClap": "Klappa i händerna",
|
||||
"reactionHeart": "Skicka kärlek",
|
||||
"reactionLaugh": "Skratta",
|
||||
"reactionLike": "Skicka tummen upp",
|
||||
"reactionSilence": "Skicka tyst reaktion",
|
||||
@@ -1283,16 +1398,14 @@
|
||||
"unmute": "Slå på ljud",
|
||||
"videoSettings": "Videoinställningar",
|
||||
"videomute": "Inaktivera kameran",
|
||||
"videomuteGUMPending": "Ansluter din kamera",
|
||||
"videounmute": "Aktivera kameran"
|
||||
},
|
||||
"transcribing": {
|
||||
"ccButtonTooltip": "Aktivera / Inaktivera undertexter",
|
||||
"error": "Transkriberingen misslyckades. Försök igen.",
|
||||
"expandedLabel": "Transkribering är aktiverad",
|
||||
"failedToStart": "Det gick inte att starta transkribering",
|
||||
"failed": "Transkribiering misslyckades",
|
||||
"labelToolTip": "Mötet transkriberas",
|
||||
"off": "Transkribering avslutades",
|
||||
"pending": "Förbereder transkribering av mötet…",
|
||||
"sourceLanguageDesc": "För närvarande är mötesspråket inställt på <b>{{sourceLanguage}}</b>. <br/> Du kan ändra det från ",
|
||||
"sourceLanguageHere": "här",
|
||||
"start": "Börja visa undertexter",
|
||||
@@ -1339,6 +1452,7 @@
|
||||
},
|
||||
"videothumbnail": {
|
||||
"connectionInfo": "Anslutningsinformation",
|
||||
"demote": "Gör till besökare",
|
||||
"domute": "Tysta",
|
||||
"domuteOthers": "Inaktivera ljud för alla andra",
|
||||
"domuteVideo": "Inaktivera kamera",
|
||||
@@ -1362,6 +1476,10 @@
|
||||
"videomute": "Deltagaren har stängt av kameran"
|
||||
},
|
||||
"virtualBackground": {
|
||||
"accessibilityLabel": {
|
||||
"currentBackground": "Nuvarande bakgrund: {{background}}",
|
||||
"selectBackground": "Välj bakgrund"
|
||||
},
|
||||
"addBackground": "Lägg till bakgrund",
|
||||
"apply": "Tillämpa",
|
||||
"backgroundEffectError": "Det gick inte att tillämpa bakgrundseffekt.",
|
||||
@@ -1387,11 +1505,22 @@
|
||||
},
|
||||
"visitors": {
|
||||
"chatIndicator": "(besökare)",
|
||||
"joinMeeting": {
|
||||
"description": "Du är just nu en beskökare i konferensen",
|
||||
"raiseHand": "Räck upp handen",
|
||||
"title": "Gå med i mötet",
|
||||
"wishToSpeak": "Om du vill prata, räck upp handen och vänta på att en moderator ska godkänna."
|
||||
},
|
||||
"labelTooltip": "Antal besökare: {{count}}",
|
||||
"notification": {
|
||||
"description": "Räck upp handen för att delta",
|
||||
"demoteDescription": "Skickad hit av {{actor}}, räck upphanden för att delta",
|
||||
"noMainParticipantsDescription": "En deltagare behöver starta mötet. Var god försök igen senare.",
|
||||
"noMainParticipantsTitle": "Det är mötet har inte startat än",
|
||||
"noVisitorLobby": "Du kan inte gå med medans lobby är påslagen för mötet.",
|
||||
"notAllowedPromotion": "En deltagare behöver godkänna din förfrågan först.",
|
||||
"title": "Du är en besökare i mötet"
|
||||
}
|
||||
},
|
||||
"waitingMessage": "Du kommer att komma in i mötet när det är live!"
|
||||
},
|
||||
"volumeSlider": "Volymreglage",
|
||||
"welcomepage": {
|
||||
@@ -1449,6 +1578,7 @@
|
||||
"whiteboard": {
|
||||
"accessibilityLabel": {
|
||||
"heading": "Whiteboard"
|
||||
}
|
||||
},
|
||||
"screenTitle": "Whiteboard"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -410,6 +410,7 @@
|
||||
"sendPrivateMessageTitle": "私信回复?",
|
||||
"serviceUnavailable": "服务不可用",
|
||||
"sessTerminated": "通话已结束",
|
||||
"sessTerminatedReason": "会议已经结束",
|
||||
"sessionRestarted": "由于连接问题,呼叫重新启动。",
|
||||
"shareAudio": "继续",
|
||||
"shareAudioTitle": "如何分享音频",
|
||||
|
||||
@@ -307,8 +307,8 @@
|
||||
"contactSupport": "Contact support",
|
||||
"copied": "Copied",
|
||||
"copy": "Copy",
|
||||
"demoteParticipantDialog": "Are you sure you want to move this participant to visitor?",
|
||||
"demoteParticipantTitle": "Move to visitor",
|
||||
"demoteParticipantDialog": "Are you sure you want to move this participant to viewer?",
|
||||
"demoteParticipantTitle": "Move to viewer",
|
||||
"dismiss": "Dismiss",
|
||||
"displayNameRequired": "Hi! What’s your name?",
|
||||
"done": "Done",
|
||||
@@ -831,9 +831,9 @@
|
||||
"videoUnmuteBlockedTitle": "Camera unmute and desktop sharing blocked!",
|
||||
"viewLobby": "View lobby",
|
||||
"viewParticipants": "View participants",
|
||||
"viewVisitors": "View visitors",
|
||||
"viewVisitors": "View viewers",
|
||||
"waitingParticipants": "{{waitingParticipants}} people",
|
||||
"waitingVisitors": "Visitors waiting in queue: {{waitingVisitors}}",
|
||||
"waitingVisitors": "Viewers waiting in queue: {{waitingVisitors}}",
|
||||
"waitingVisitorsTitle": "The meeting is not live yet!",
|
||||
"whiteboardLimitDescription": "Please save your progress, as the user limit will soon be reached and the whiteboard will close.",
|
||||
"whiteboardLimitTitle": "Whiteboard usage"
|
||||
@@ -870,7 +870,7 @@
|
||||
"participantsList": "Meeting participants ({{count}})",
|
||||
"visitorInQueue": " (waiting {{count}})",
|
||||
"visitorRequests": " (requests {{count}})",
|
||||
"visitors": "Visitors {{count}}",
|
||||
"visitors": "Viewers {{count}}",
|
||||
"waitingLobby": "Waiting in lobby ({{count}})"
|
||||
},
|
||||
"search": "Search participants",
|
||||
@@ -1083,7 +1083,7 @@
|
||||
"about": "You can add a $t(lockRoomPassword) to your meeting. Participants will need to provide the $t(lockRoomPassword) before they are allowed to join the meeting.",
|
||||
"aboutReadOnly": "Moderator participants can add a $t(lockRoomPassword) to the meeting. Participants will need to provide the $t(lockRoomPassword) before they are allowed to join the meeting.",
|
||||
"insecureRoomNameWarningNative": "The room name is unsafe. Unwanted participants may join your meeting. {{recommendAction}} Learn more about securing your meeting ",
|
||||
"insecureRoomNameWarningWeb": "The room name is unsafe. Unwanted participants may join your meeting. {{recommendAction}} Learn more about securing you meeting <a href=\"{{securityUrl}}\" rel=\"security\" target=\"_blank\">here</a>.",
|
||||
"insecureRoomNameWarningWeb": "The room name is unsafe. Unwanted participants may join your meeting. {{recommendAction}} Learn more about securing your meeting <a href=\"{{securityUrl}}\" rel=\"security\" target=\"_blank\">here</a>.",
|
||||
"title": "Security Options",
|
||||
"unsafeRoomActions": {
|
||||
"meeting": "Consider securing your meeting using the security button.",
|
||||
@@ -1183,6 +1183,7 @@
|
||||
"fearful": "Fearful",
|
||||
"happy": "Happy",
|
||||
"hours": "{{count}}h",
|
||||
"labelTooltip": "Number of participants: {{count}}",
|
||||
"minutes": "{{count}}m",
|
||||
"name": "Name",
|
||||
"neutral": "Neutral",
|
||||
@@ -1404,7 +1405,8 @@
|
||||
"ccButtonTooltip": "Start / Stop subtitles",
|
||||
"expandedLabel": "Transcribing is currently on",
|
||||
"failed": "Transcribing failed",
|
||||
"labelToolTip": "The meeting is being transcribed",
|
||||
"labelTooltip": "This meeting is being transcribed.",
|
||||
"labelTooltipExtra": "In addition, a transcript will be available later.",
|
||||
"sourceLanguageDesc": "Currently the meeting language is set to <b>{{sourceLanguage}}</b>. <br/> You can change it from ",
|
||||
"sourceLanguageHere": "here",
|
||||
"start": "Start showing subtitles",
|
||||
@@ -1443,7 +1445,7 @@
|
||||
"ldTooltip": "Viewing low definition video",
|
||||
"lowDefinition": "Low definition",
|
||||
"performanceSettings": "Performance settings",
|
||||
"recording": "Recording in progress",
|
||||
"recording": "This meeting is being recorded.",
|
||||
"sd": "SD",
|
||||
"sdTooltip": "Viewing standard definition video",
|
||||
"standardDefinition": "Standard definition",
|
||||
@@ -1451,7 +1453,7 @@
|
||||
},
|
||||
"videothumbnail": {
|
||||
"connectionInfo": "Connection Info",
|
||||
"demote": "Move to visitor",
|
||||
"demote": "Move to viewer",
|
||||
"domute": "Mute",
|
||||
"domuteOthers": "Mute everyone else",
|
||||
"domuteVideo": "Disable camera",
|
||||
@@ -1503,21 +1505,21 @@
|
||||
"webAssemblyWarningDescription": "WebAssembly disabled or not supported by this browser"
|
||||
},
|
||||
"visitors": {
|
||||
"chatIndicator": "(visitor)",
|
||||
"chatIndicator": "(viewer)",
|
||||
"joinMeeting": {
|
||||
"description": "You're currently an observer in this conference.",
|
||||
"description": "You're currently a viewer in this conference.",
|
||||
"raiseHand": "Raise your hand",
|
||||
"title": "Joining meeting",
|
||||
"wishToSpeak": "If you wish to speak, please raise your hand below and wait for the moderator's approval."
|
||||
},
|
||||
"labelTooltip": "Number of visitors: {{count}}",
|
||||
"labelTooltip": "Number of viewers: {{count}}",
|
||||
"notification": {
|
||||
"demoteDescription": "Sent here by {{actor}}, raise your hand to participate",
|
||||
"noMainParticipantsDescription": "A participant needs to start the meeting. Please try again in a bit.",
|
||||
"noMainParticipantsTitle": "This meeting hasn’t started yet.",
|
||||
"noVisitorLobby": "You cannot join while there is a lobby enabled for the meeting.",
|
||||
"notAllowedPromotion": "A participant needs to allow your request first.",
|
||||
"title": "You are a visitor in the meeting"
|
||||
"title": "You are a viewer in the meeting"
|
||||
},
|
||||
"waitingMessage": "You'll join the meeting as soon as it is live!"
|
||||
},
|
||||
|
||||
@@ -75,6 +75,7 @@ import {
|
||||
toggleChat
|
||||
} from '../../react/features/chat/actions';
|
||||
import { openChat } from '../../react/features/chat/actions.web';
|
||||
import { showDesktopPicker } from '../../react/features/desktop-picker/actions';
|
||||
import {
|
||||
processExternalDeviceRequest
|
||||
} from '../../react/features/device-selection/functions';
|
||||
@@ -115,7 +116,7 @@ import { toggleScreenshotCaptureSummary } from '../../react/features/screenshot-
|
||||
import { isScreenshotCaptureEnabled } from '../../react/features/screenshot-capture/functions';
|
||||
import SettingsDialog from '../../react/features/settings/components/web/SettingsDialog';
|
||||
import { SETTINGS_TABS } from '../../react/features/settings/constants';
|
||||
import { playSharedVideo, stopSharedVideo } from '../../react/features/shared-video/actions.any';
|
||||
import { playSharedVideo, stopSharedVideo } from '../../react/features/shared-video/actions';
|
||||
import { extractYoutubeIdOrURL } from '../../react/features/shared-video/functions';
|
||||
import { setRequestingSubtitles, toggleRequestingSubtitles } from '../../react/features/subtitles/actions';
|
||||
import { isAudioMuteButtonDisabled } from '../../react/features/toolbox/functions';
|
||||
@@ -491,7 +492,8 @@ function initCommands() {
|
||||
APP.store.dispatch(toggleRequestingSubtitles());
|
||||
},
|
||||
'set-subtitles': (enabled, displaySubtitles, language) => {
|
||||
APP.store.dispatch(setRequestingSubtitles(enabled, displaySubtitles, language));
|
||||
APP.store.dispatch(setRequestingSubtitles(
|
||||
enabled, displaySubtitles, language ? `translation-languages:${language}` : null));
|
||||
},
|
||||
'toggle-tile-view': () => {
|
||||
sendAnalytics(createApiEvent('tile-view.toggled'));
|
||||
@@ -590,7 +592,7 @@ function initCommands() {
|
||||
* @param { string } arg.title - Notification title.
|
||||
* @param { string } arg.description - Notification description.
|
||||
* @param { string } arg.uid - Optional unique identifier for the notification.
|
||||
* @param { string } arg.type - Notification type, either `error`, `info`, `normal`, `success` or `warning`.
|
||||
* @param { string } arg.type - Notification type, either `error`, `normal`, `success` or `warning`.
|
||||
* Defaults to "normal" if not provided.
|
||||
* @param { string } arg.timeout - Timeout type, either `short`, `medium`, `long` or `sticky`.
|
||||
* Defaults to "short" if not provided.
|
||||
@@ -851,6 +853,8 @@ function initCommands() {
|
||||
'overwrite-config': config => {
|
||||
const whitelistedConfig = getWhitelistedJSON('config', config);
|
||||
|
||||
logger.info(`Overwriting config with: ${JSON.stringify(whitelistedConfig)}`);
|
||||
|
||||
APP.store.dispatch(overwriteConfig(whitelistedConfig));
|
||||
},
|
||||
'toggle-virtual-background': () => {
|
||||
@@ -1046,6 +1050,23 @@ function initCommands() {
|
||||
}
|
||||
case '_new_electron_screensharing_supported': {
|
||||
callback(true);
|
||||
|
||||
break;
|
||||
}
|
||||
case 'open-desktop-picker': {
|
||||
const { desktopSharingSources } = APP.store.getState()['features/base/config'];
|
||||
const options = {
|
||||
desktopSharingSources: desktopSharingSources ?? [ 'screen', 'window' ]
|
||||
};
|
||||
const onSourceChoose = (_streamId, _type, screenShareAudio, source) => {
|
||||
callback({
|
||||
screenShareAudio,
|
||||
source
|
||||
});
|
||||
};
|
||||
|
||||
dispatch(showDesktopPicker(options, onSourceChoose));
|
||||
|
||||
break;
|
||||
}
|
||||
default:
|
||||
@@ -1571,8 +1592,8 @@ class API {
|
||||
formattedArgument += `${arg.toString()}: ${arg.stack}`;
|
||||
} else if (typeof arg === 'object') {
|
||||
// NOTE: The non-enumerable properties of the objects wouldn't be included in the string after
|
||||
// JSON.strigify. For example Map instance will be translated to '{}'. So I think we have to eventually
|
||||
// do something better for parsing the arguments. But since this option for strigify is part of the
|
||||
// JSON.stringify. For example Map instance will be translated to '{}'. So I think we have to eventually
|
||||
// do something better for parsing the arguments. But since this option for stringify is part of the
|
||||
// public interface and I think it could be useful in some cases I will it for now.
|
||||
try {
|
||||
formattedArgument += JSON.stringify(arg);
|
||||
|
||||
107
modules/API/external/external_api.js
vendored
107
modules/API/external/external_api.js
vendored
@@ -194,80 +194,6 @@ function changeParticipantNumber(APIInstance, number) {
|
||||
APIInstance._numberOfParticipants += number;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates the URL for the iframe.
|
||||
*
|
||||
* @param {string} domain - The domain name of the server that hosts the
|
||||
* conference.
|
||||
* @param {string} [options] - Another optional parameters.
|
||||
* @param {Object} [options.configOverwrite] - Object containing configuration
|
||||
* options defined in config.js to be overridden.
|
||||
* @param {Object} [options.interfaceConfigOverwrite] - Object containing
|
||||
* configuration options defined in interface_config.js to be overridden.
|
||||
* @param {string} [options.jwt] - The JWT token if needed by jitsi-meet for
|
||||
* authentication.
|
||||
* @param {string} [options.lang] - The meeting's default language.
|
||||
* @param {string} [options.roomName] - The name of the room to join.
|
||||
* @returns {string} The URL.
|
||||
*/
|
||||
function generateURL(domain, options = {}) {
|
||||
return urlObjectToString({
|
||||
...options,
|
||||
url: `https://${domain}/#jitsi_meet_external_api_id=${id}`
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses the arguments passed to the constructor. If the old format is used
|
||||
* the function translates the arguments to the new format.
|
||||
*
|
||||
* @param {Array} args - The arguments to be parsed.
|
||||
* @returns {Object} JS object with properties.
|
||||
*/
|
||||
function parseArguments(args) {
|
||||
if (!args.length) {
|
||||
return {};
|
||||
}
|
||||
|
||||
const firstArg = args[0];
|
||||
|
||||
switch (typeof firstArg) {
|
||||
case 'string': // old arguments format
|
||||
case 'undefined': {
|
||||
// Not sure which format but we are trying to parse the old
|
||||
// format because if the new format is used everything will be undefined
|
||||
// anyway.
|
||||
const [
|
||||
roomName,
|
||||
width,
|
||||
height,
|
||||
parentNode,
|
||||
configOverwrite,
|
||||
interfaceConfigOverwrite,
|
||||
jwt,
|
||||
onload,
|
||||
lang
|
||||
] = args;
|
||||
|
||||
return {
|
||||
roomName,
|
||||
width,
|
||||
height,
|
||||
parentNode,
|
||||
configOverwrite,
|
||||
interfaceConfigOverwrite,
|
||||
jwt,
|
||||
onload,
|
||||
lang
|
||||
};
|
||||
}
|
||||
case 'object': // new arguments format
|
||||
return args[0];
|
||||
default:
|
||||
throw new Error('Can\'t parse the arguments!');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Compute valid values for height and width. If a number is specified it's
|
||||
* treated as pixel units. If the value is expressed in px, em, pt or
|
||||
@@ -336,7 +262,7 @@ export default class JitsiMeetExternalAPI extends EventEmitter {
|
||||
* @param {string} [options.release] - The key used for specifying release if enabled on the backend.
|
||||
* @param {string} [options.sandbox] - Sandbox directive for the created iframe, if desired.
|
||||
*/
|
||||
constructor(domain, ...args) {
|
||||
constructor(domain, options = {}) {
|
||||
super();
|
||||
const {
|
||||
roomName = '',
|
||||
@@ -345,21 +271,22 @@ export default class JitsiMeetExternalAPI extends EventEmitter {
|
||||
parentNode = document.body,
|
||||
configOverwrite = {},
|
||||
interfaceConfigOverwrite = {},
|
||||
jwt = undefined,
|
||||
lang = undefined,
|
||||
onload = undefined,
|
||||
jwt,
|
||||
lang,
|
||||
onload,
|
||||
invitees,
|
||||
iceServers,
|
||||
devices,
|
||||
userInfo,
|
||||
e2eeKey,
|
||||
release,
|
||||
sandbox = ''
|
||||
} = parseArguments(args);
|
||||
sandbox
|
||||
} = options;
|
||||
const localStorageContent = jitsiLocalStorage.getItem('jitsiLocalStorage');
|
||||
|
||||
this._parentNode = parentNode;
|
||||
this._url = generateURL(domain, {
|
||||
|
||||
this._url = urlObjectToString({
|
||||
configOverwrite,
|
||||
iceServers,
|
||||
interfaceConfigOverwrite,
|
||||
@@ -371,7 +298,8 @@ export default class JitsiMeetExternalAPI extends EventEmitter {
|
||||
appData: {
|
||||
localStorageContent
|
||||
},
|
||||
release
|
||||
release,
|
||||
url: `https://${domain}/#jitsi_meet_external_api_id=${id}`
|
||||
});
|
||||
|
||||
this._createIFrame(height, width, sandbox);
|
||||
@@ -1313,6 +1241,10 @@ export default class JitsiMeetExternalAPI extends EventEmitter {
|
||||
* Returns the state of availability electron share screen via external api.
|
||||
*
|
||||
* @returns {Promise}
|
||||
*
|
||||
* TODO: should be removed after we make sure that all Electron clients use only versions
|
||||
* after with the legacy SS support was removed from the electron SDK. If we remove it now the SS for Electron
|
||||
* clients with older versions wont work.
|
||||
*/
|
||||
_isNewElectronScreensharingSupported() {
|
||||
return this._transport.sendRequest({
|
||||
@@ -1523,4 +1455,15 @@ export default class JitsiMeetExternalAPI extends EventEmitter {
|
||||
setVirtualBackground(enabled, backgroundImage) {
|
||||
this.executeCommand('setVirtualBackground', enabled, backgroundImage);
|
||||
}
|
||||
|
||||
/**
|
||||
* Opens the desktop picker. This is invoked by the Electron SDK when gDM is used.
|
||||
*
|
||||
* @returns {Promise}
|
||||
*/
|
||||
_openDesktopPicker() {
|
||||
return this._transport.sendRequest({
|
||||
name: 'open-desktop-picker'
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,2 +1,2 @@
|
||||
export default from './API';
|
||||
export { default } from './API';
|
||||
export * from './constants';
|
||||
|
||||
4482
package-lock.json
generated
4482
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
38
package.json
38
package.json
@@ -26,7 +26,7 @@
|
||||
"@jitsi/excalidraw": "https://github.com/jitsi/excalidraw/releases/download/v0.0.19/jitsi-excalidraw-0.0.19.tgz",
|
||||
"@jitsi/js-utils": "2.2.1",
|
||||
"@jitsi/logger": "2.0.2",
|
||||
"@jitsi/rnnoise-wasm": "0.1.0",
|
||||
"@jitsi/rnnoise-wasm": "0.2.1",
|
||||
"@jitsi/rtcstats": "9.5.1",
|
||||
"@matrix-org/olm": "https://gitlab.matrix.org/api/v4/projects/27/packages/npm/@matrix-org/olm/-/@matrix-org/olm-3.2.3.tgz",
|
||||
"@microsoft/microsoft-graph-client": "3.0.1",
|
||||
@@ -68,14 +68,14 @@
|
||||
"js-md5": "0.6.1",
|
||||
"js-sha512": "0.8.0",
|
||||
"jwt-decode": "2.2.0",
|
||||
"lib-jitsi-meet": "https://github.com/jitsi/lib-jitsi-meet/releases/download/v1890.0.0+144b0cab/lib-jitsi-meet.tgz",
|
||||
"lib-jitsi-meet": "https://github.com/jitsi/lib-jitsi-meet/releases/download/v1914.0.0+c040dee9/lib-jitsi-meet.tgz",
|
||||
"lodash-es": "4.17.21",
|
||||
"moment": "2.29.4",
|
||||
"moment-duration-format": "2.2.2",
|
||||
"null-loader": "4.0.1",
|
||||
"optional-require": "1.0.3",
|
||||
"pixelmatch": "5.3.0",
|
||||
"promise.allsettled": "1.0.4",
|
||||
"promise.withresolvers": "1.0.3",
|
||||
"punycode": "2.3.0",
|
||||
"react": "18.2.0",
|
||||
"react-dom": "18.2.0",
|
||||
@@ -83,7 +83,7 @@
|
||||
"react-focus-on": "3.8.1",
|
||||
"react-i18next": "10.11.4",
|
||||
"react-linkify": "1.0.0-alpha",
|
||||
"react-native": "0.75.4",
|
||||
"react-native": "0.75.5",
|
||||
"react-native-background-timer": "2.4.1",
|
||||
"react-native-calendar-events": "2.2.0",
|
||||
"react-native-default-preference": "1.4.4",
|
||||
@@ -130,18 +130,19 @@
|
||||
"devDependencies": {
|
||||
"@babel/core": "7.25.9",
|
||||
"@babel/eslint-parser": "7.25.9",
|
||||
"@babel/plugin-proposal-export-default-from": "7.25.9",
|
||||
"@babel/plugin-transform-private-methods": "7.25.9",
|
||||
"@babel/preset-env": "7.25.9",
|
||||
"@babel/preset-react": "7.25.9",
|
||||
"@jitsi/eslint-config": "4.1.10",
|
||||
"@react-native/metro-config": "0.75.4",
|
||||
"@jitsi/eslint-config": "5.0.9",
|
||||
"@react-native/metro-config": "0.75.5",
|
||||
"@stylistic/eslint-plugin": "2.12.1",
|
||||
"@types/amplitude-js": "8.16.5",
|
||||
"@types/audioworklet": "0.0.29",
|
||||
"@types/dom-screen-wake-lock": "1.0.1",
|
||||
"@types/js-md5": "0.4.3",
|
||||
"@types/jsonwebtoken": "9.0.7",
|
||||
"@types/lodash-es": "4.17.12",
|
||||
"@types/minimatch": "5.1.2",
|
||||
"@types/mocha": "10.0.10",
|
||||
"@types/moment-duration-format": "2.2.6",
|
||||
"@types/offscreencanvas": "2019.7.2",
|
||||
@@ -160,8 +161,8 @@
|
||||
"@types/w3c-image-capture": "1.0.6",
|
||||
"@types/w3c-web-hid": "1.0.3",
|
||||
"@types/zxcvbn": "4.4.1",
|
||||
"@typescript-eslint/eslint-plugin": "5.59.5",
|
||||
"@typescript-eslint/parser": "5.59.5",
|
||||
"@typescript-eslint/eslint-plugin": "8.19.1",
|
||||
"@typescript-eslint/parser": "8.19.1",
|
||||
"@wdio/allure-reporter": "9.4.3",
|
||||
"@wdio/cli": "9.4.3",
|
||||
"@wdio/globals": "9.4.3",
|
||||
@@ -172,13 +173,14 @@
|
||||
"babel-plugin-optional-require": "0.3.1",
|
||||
"circular-dependency-plugin": "5.2.0",
|
||||
"clean-css-cli": "4.3.0",
|
||||
"core-js": "3.40.0",
|
||||
"css-loader": "6.8.1",
|
||||
"eslint": "8.40.0",
|
||||
"eslint-plugin-import": "2.27.5",
|
||||
"eslint-plugin-jsdoc": "46.2.6",
|
||||
"eslint-plugin-react": "7.32.2",
|
||||
"eslint-plugin-react-native": "4.0.0",
|
||||
"eslint-plugin-typescript-sort-keys": "2.3.0",
|
||||
"eslint": "8.57.0",
|
||||
"eslint-plugin-import": "2.31.0",
|
||||
"eslint-plugin-jsdoc": "50.6.1",
|
||||
"eslint-plugin-react": "7.37.3",
|
||||
"eslint-plugin-react-native": "5.0.0",
|
||||
"eslint-plugin-typescript-sort-keys": "3.3.0",
|
||||
"jetifier": "1.6.4",
|
||||
"jsonwebtoken": "9.0.2",
|
||||
"metro-react-native-babel-preset": "0.77.0",
|
||||
@@ -220,9 +222,13 @@
|
||||
"tsc-test:native": "tsc --project tsconfig.native.json --listFilesOnly | grep -v node_modules | grep web",
|
||||
"start": "make dev",
|
||||
"test": "DOTENV_CONFIG_PATH=tests/.env wdio run tests/wdio.conf.ts",
|
||||
"test-single": "DOTENV_CONFIG_PATH=tests/.env wdio run tests/wdio.conf.ts --spec",
|
||||
"test-ff-single": "DOTENV_CONFIG_PATH=tests/.env wdio run tests/wdio.firefox.conf.ts --spec",
|
||||
"test-ff": "DOTENV_CONFIG_PATH=tests/.env wdio run tests/wdio.firefox.conf.ts",
|
||||
"test-dev": "DOTENV_CONFIG_PATH=tests/.env wdio run tests/wdio.dev.conf.ts",
|
||||
"test-grid": "DOTENV_CONFIG_PATH=tests/.env wdio run tests/wdio.grid.conf.ts"
|
||||
"test-dev-single": "DOTENV_CONFIG_PATH=tests/.env wdio run tests/wdio.dev.conf.ts --spec",
|
||||
"test-grid": "DOTENV_CONFIG_PATH=tests/.env wdio run tests/wdio.grid.conf.ts",
|
||||
"test-grid-single": "DOTENV_CONFIG_PATH=tests/.env wdio run tests/wdio.grid.conf.ts --spec"
|
||||
},
|
||||
"resolutions": {
|
||||
"@types/react": "17.0.14",
|
||||
|
||||
@@ -69,7 +69,7 @@ cd ios && pod install && cd ..
|
||||
|
||||
## Android
|
||||
|
||||
- In your build.gradle have at least `minSdkVersion = 24`
|
||||
- In your build.gradle have at least `minSdkVersion = 26`
|
||||
- In `android/app/src/debug/AndroidManifest.xml` and `android/app/src/main/AndroidManifest.xml`, under the `</application>` tag, include
|
||||
```xml
|
||||
<uses-permission android:name="android.permission.RECORD_AUDIO" />
|
||||
|
||||
@@ -0,0 +1,117 @@
|
||||
package org.jitsi.meet.sdk;
|
||||
|
||||
import static android.Manifest.permission.POST_NOTIFICATIONS;
|
||||
import static android.Manifest.permission.RECORD_AUDIO;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.os.Build;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.RequiresApi;
|
||||
|
||||
import com.facebook.react.ReactActivity;
|
||||
|
||||
import com.facebook.react.bridge.ReactApplicationContext;
|
||||
import com.facebook.react.bridge.ReactContextBaseJavaModule;
|
||||
import com.facebook.react.bridge.ReactMethod;
|
||||
import com.facebook.react.module.annotations.ReactModule;
|
||||
import com.facebook.react.modules.core.PermissionListener;
|
||||
|
||||
import org.jitsi.meet.sdk.log.JitsiMeetLogger;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
|
||||
/**
|
||||
* This class implements a ReactModule and it's
|
||||
* responsible for launching/aborting a service when a conference is in progress.
|
||||
*/
|
||||
@ReactModule(name = JMOngoingConferenceModule.NAME)
|
||||
class JMOngoingConferenceModule extends ReactContextBaseJavaModule {
|
||||
|
||||
public static final String NAME = "JMOngoingConference";
|
||||
|
||||
private static final int PERMISSIONS_REQUEST_CODE = (int) (Math.random() * Short.MAX_VALUE);
|
||||
|
||||
public JMOngoingConferenceModule(ReactApplicationContext reactContext) {
|
||||
super(reactContext);
|
||||
}
|
||||
|
||||
@ReactMethod
|
||||
public void launch() {
|
||||
Context context = getReactApplicationContext();
|
||||
ReactActivity reactActivity = (ReactActivity) getCurrentActivity();
|
||||
|
||||
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.TIRAMISU) {
|
||||
JMOngoingConferenceService.launch(context);
|
||||
|
||||
JitsiMeetLogger.i(NAME + " launch");
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
PermissionListener listener = new PermissionListener() {
|
||||
@Override
|
||||
public boolean onRequestPermissionsResult(int i, String[] strings, int[] results) {
|
||||
JitsiMeetLogger.i(NAME + " Permission callback received");
|
||||
|
||||
if (results == null || results.length == 0) {
|
||||
JitsiMeetLogger.w(NAME + " Permission results are null or empty");
|
||||
return true;
|
||||
}
|
||||
|
||||
int counter = 0;
|
||||
for (int result : results) {
|
||||
if (result == PackageManager.PERMISSION_GRANTED) {
|
||||
counter++;
|
||||
}
|
||||
}
|
||||
|
||||
JitsiMeetLogger.i(NAME + " Permissions granted: " + counter + "/" + results.length);
|
||||
|
||||
if (counter == results.length) {
|
||||
JitsiMeetLogger.i(NAME + " All permissions granted, launching service");
|
||||
JMOngoingConferenceService.launch(context);
|
||||
} else {
|
||||
JitsiMeetLogger.w(NAME + " Not all permissions were granted");
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
JitsiMeetLogger.i(NAME + " Checking Tiramisu permissions");
|
||||
|
||||
List<String> permissionsList = new ArrayList<>();
|
||||
|
||||
permissionsList.add(POST_NOTIFICATIONS);
|
||||
permissionsList.add(RECORD_AUDIO);
|
||||
|
||||
String[] permissionsArray = new String[ permissionsList.size() ];
|
||||
permissionsArray = permissionsList.toArray( permissionsArray );
|
||||
|
||||
try {
|
||||
JitsiMeetLogger.i(NAME + " Requesting permissions: " + Arrays.toString(permissionsArray));
|
||||
reactActivity.requestPermissions(permissionsArray, PERMISSIONS_REQUEST_CODE, listener);
|
||||
} catch (Exception e) {
|
||||
JitsiMeetLogger.e(e, NAME + " Error requesting permissions");
|
||||
}
|
||||
}
|
||||
|
||||
@ReactMethod
|
||||
public void abort() {
|
||||
Context context = getReactApplicationContext();
|
||||
JMOngoingConferenceService.abort(context);
|
||||
|
||||
JitsiMeetLogger.i(NAME + " abort");
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public String getName() {
|
||||
return NAME;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,107 @@
|
||||
/*
|
||||
* Copyright @ 2019-present 8x8, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.jitsi.meet.sdk;
|
||||
|
||||
import android.app.Notification;
|
||||
import android.app.Service;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
|
||||
import android.content.pm.ServiceInfo;
|
||||
|
||||
import android.os.Build;
|
||||
import android.os.IBinder;
|
||||
|
||||
import org.jitsi.meet.sdk.log.JitsiMeetLogger;
|
||||
|
||||
import java.util.Random;
|
||||
|
||||
/**
|
||||
* This class implements an Android {@link Service}, a foreground one specifically, and it's
|
||||
* responsible for presenting an ongoing notification when a conference is in progress.
|
||||
* The service will help keep the app running while in the background.
|
||||
*
|
||||
* See: https://developer.android.com/guide/components/services
|
||||
*/
|
||||
public class JMOngoingConferenceService extends Service {
|
||||
private static final String TAG = JMOngoingConferenceService.class.getSimpleName();
|
||||
|
||||
static final int NOTIFICATION_ID = new Random().nextInt(99999) + 10000;
|
||||
|
||||
public static void launch(Context context) {
|
||||
try {
|
||||
RNOngoingNotification.createOngoingConferenceNotificationChannel(context);
|
||||
JitsiMeetLogger.i(TAG + " Notification channel creation completed");
|
||||
} catch (Exception e) {
|
||||
JitsiMeetLogger.e(e, TAG + " Error creating notification channel");
|
||||
}
|
||||
|
||||
Intent intent = new Intent(context, JMOngoingConferenceService.class);
|
||||
|
||||
try {
|
||||
context.startForegroundService(intent);
|
||||
JitsiMeetLogger.i(TAG + " Starting foreground service");
|
||||
} catch (RuntimeException e) {
|
||||
// Avoid crashing due to ForegroundServiceStartNotAllowedException (API level 31).
|
||||
// See: https://developer.android.com/guide/components/foreground-services#background-start-restrictions
|
||||
JitsiMeetLogger.w(TAG + " Ongoing conference service not started", e);
|
||||
}
|
||||
}
|
||||
|
||||
public static void abort(Context context) {
|
||||
Intent intent = new Intent(context, JMOngoingConferenceService.class);
|
||||
context.stopService(intent);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreate() {
|
||||
super.onCreate();
|
||||
JitsiMeetLogger.i(TAG + " onCreate called");
|
||||
|
||||
try {
|
||||
Notification notification = RNOngoingNotification.buildOngoingConferenceNotification(this);
|
||||
JitsiMeetLogger.i(TAG + " Notification build result: " + (notification != null));
|
||||
|
||||
if (notification == null) {
|
||||
stopSelf();
|
||||
JitsiMeetLogger.w(TAG + " Couldn't start service, notification is null");
|
||||
} else {
|
||||
JitsiMeetLogger.i(TAG + " Starting service in foreground with notification");
|
||||
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
|
||||
startForeground(NOTIFICATION_ID, notification, ServiceInfo.FOREGROUND_SERVICE_TYPE_MEDIA_PLAYBACK | ServiceInfo.FOREGROUND_SERVICE_TYPE_MICROPHONE);
|
||||
} else if (Build.VERSION.SDK_INT == Build.VERSION_CODES.Q) {
|
||||
startForeground(NOTIFICATION_ID, notification, ServiceInfo.FOREGROUND_SERVICE_TYPE_MEDIA_PLAYBACK);
|
||||
} else {
|
||||
startForeground(NOTIFICATION_ID, notification);
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
JitsiMeetLogger.e(e, TAG + " Error in onCreate");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public IBinder onBind(Intent intent) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int onStartCommand(Intent intent, int flags, int startId) {
|
||||
return START_NOT_STICKY;
|
||||
}
|
||||
}
|
||||
@@ -21,6 +21,7 @@ public class JitsiMeetReactNativePackage implements ReactPackage {
|
||||
new AndroidSettingsModule(reactContext),
|
||||
new AppInfoModule(reactContext),
|
||||
new AudioModeModule(reactContext),
|
||||
new JMOngoingConferenceModule(reactContext),
|
||||
new JavaScriptSandboxModule(reactContext),
|
||||
new LocaleDetector(reactContext),
|
||||
new LogBridgeModule(reactContext),
|
||||
|
||||
@@ -0,0 +1,108 @@
|
||||
/*
|
||||
* Copyright @ 2019-present 8x8, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.jitsi.meet.sdk;
|
||||
|
||||
import android.app.Notification;
|
||||
import android.app.NotificationChannel;
|
||||
import android.app.NotificationManager;
|
||||
|
||||
import android.app.PendingIntent;
|
||||
import android.app.Service;
|
||||
import android.content.Context;
|
||||
|
||||
import android.content.Intent;
|
||||
import android.os.Build;
|
||||
|
||||
import androidx.core.app.NotificationCompat;
|
||||
|
||||
import org.jitsi.meet.sdk.log.JitsiMeetLogger;
|
||||
|
||||
|
||||
/**
|
||||
* Helper class for creating the ongoing notification which is used with
|
||||
* {@link JMOngoingConferenceService}. It allows the user to easily get back to the app
|
||||
* and to hangup from within the notification itself.
|
||||
*/
|
||||
class RNOngoingNotification {
|
||||
private static final String TAG = RNOngoingNotification.class.getSimpleName();
|
||||
|
||||
static final String RN_ONGOING_CONFERENCE_CHANNEL_ID = "OngoingConferenceChannel";
|
||||
|
||||
static void createOngoingConferenceNotificationChannel(Context context) {
|
||||
NotificationManager notificationManager = (NotificationManager) context.getSystemService(Service.NOTIFICATION_SERVICE);
|
||||
NotificationChannel channel = notificationManager.getNotificationChannel(RN_ONGOING_CONFERENCE_CHANNEL_ID);
|
||||
|
||||
if (channel != null) {
|
||||
JitsiMeetLogger.i(TAG + " Notification channel already exists");
|
||||
return;
|
||||
}
|
||||
|
||||
channel = new NotificationChannel(
|
||||
RN_ONGOING_CONFERENCE_CHANNEL_ID,
|
||||
context.getString(R.string.ongoing_notification_channel_name),
|
||||
NotificationManager.IMPORTANCE_DEFAULT
|
||||
);
|
||||
|
||||
channel.enableVibration(true);
|
||||
channel.setShowBadge(true);
|
||||
channel.setLockscreenVisibility(Notification.VISIBILITY_PUBLIC);
|
||||
|
||||
notificationManager.createNotificationChannel(channel);
|
||||
JitsiMeetLogger.i(TAG + " Notification channel created with importance: " + channel.getImportance());
|
||||
}
|
||||
|
||||
static Notification buildOngoingConferenceNotification(Context context) {
|
||||
if (context == null) {
|
||||
JitsiMeetLogger.w(TAG + " Cannot create notification: no current context");
|
||||
return null;
|
||||
}
|
||||
|
||||
JitsiMeetLogger.i(TAG + " Creating notification with context: " + context);
|
||||
|
||||
// Creating an intent to launch app's main activity
|
||||
Intent intent = context.getPackageManager()
|
||||
.getLaunchIntentForPackage(context.getPackageName());
|
||||
assert intent != null;
|
||||
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP);
|
||||
|
||||
// Creating PendingIntent
|
||||
PendingIntent pendingIntent = PendingIntent.getActivity(
|
||||
context,
|
||||
0,
|
||||
intent,
|
||||
PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE
|
||||
);
|
||||
|
||||
NotificationCompat.Builder builder = new NotificationCompat.Builder(context, RN_ONGOING_CONFERENCE_CHANNEL_ID);
|
||||
|
||||
builder
|
||||
.setCategory(NotificationCompat.CATEGORY_CALL)
|
||||
.setContentTitle(context.getString(R.string.ongoing_notification_title))
|
||||
.setContentText(context.getString(R.string.ongoing_notification_text))
|
||||
.setPriority(NotificationCompat.PRIORITY_HIGH)
|
||||
.setOngoing(true)
|
||||
.setWhen(System.currentTimeMillis())
|
||||
.setUsesChronometer(true)
|
||||
.setAutoCancel(false)
|
||||
.setVisibility(NotificationCompat.VISIBILITY_PUBLIC)
|
||||
.setOnlyAlertOnce(true)
|
||||
.setSmallIcon(context.getResources().getIdentifier("ic_notification", "drawable", context.getPackageName()))
|
||||
.setForegroundServiceBehavior(NotificationCompat.FOREGROUND_SERVICE_IMMEDIATE)
|
||||
.setContentIntent(pendingIntent);
|
||||
|
||||
return builder.build();
|
||||
}
|
||||
}
|
||||
@@ -36,6 +36,7 @@
|
||||
"moment-duration-format": "0.0.0",
|
||||
"optional-require": "0.0.0",
|
||||
"promise.allsettled": "0.0.0",
|
||||
"promise.withresolvers": "0.0.0",
|
||||
"punycode": "0.0.0",
|
||||
"react-emoji-render": "0.0.0",
|
||||
"react-i18next": "0.0.0",
|
||||
|
||||
@@ -14,24 +14,14 @@ module.exports = {
|
||||
project: [ './tsconfig.web.json', './tsconfig.native.json' ]
|
||||
},
|
||||
rules: {
|
||||
'@typescript-eslint/naming-convention': [
|
||||
'error',
|
||||
{
|
||||
'selector': 'interface',
|
||||
'format': [ 'PascalCase' ],
|
||||
'custom': {
|
||||
'regex': '^I[A-Z]',
|
||||
'match': true
|
||||
}
|
||||
}
|
||||
]
|
||||
// TODO: Remove these and fix the warnings
|
||||
'@typescript-eslint/no-unsafe-function-type': 0,
|
||||
'@typescript-eslint/no-wrapper-object-types': 0,
|
||||
|
||||
'@typescript-eslint/no-require-imports': 0
|
||||
}
|
||||
}
|
||||
],
|
||||
'rules': {
|
||||
// XXX remove this eventually.
|
||||
'react/jsx-indent-props': 0
|
||||
},
|
||||
'settings': {
|
||||
'react': {
|
||||
'version': 'detect'
|
||||
|
||||
@@ -4,8 +4,10 @@ import ReactDOM from 'react-dom';
|
||||
import AlwaysOnTop from './AlwaysOnTop';
|
||||
|
||||
// Render the main/root Component.
|
||||
/* eslint-disable-next-line react/no-deprecated */
|
||||
ReactDOM.render(<AlwaysOnTop />, document.getElementById('react'));
|
||||
|
||||
window.addEventListener(
|
||||
'beforeunload',
|
||||
/* eslint-disable-next-line react/no-deprecated */
|
||||
() => ReactDOM.unmountComponentAtNode(document.getElementById('react') ?? document.body));
|
||||
|
||||
@@ -311,7 +311,7 @@ export function createInviteDialogEvent(
|
||||
* @returns {Object}
|
||||
*/
|
||||
export function createNetworkInfoEvent({ isOnline, networkType, details }:
|
||||
{ details?: Object; isOnline: boolean; networkType?: string; }) {
|
||||
{ details?: Object; isOnline: boolean; networkType?: string; }) {
|
||||
const attributes: {
|
||||
details?: Object;
|
||||
isOnline: boolean;
|
||||
|
||||
@@ -87,7 +87,6 @@ export async function createHandlers({ getState }: IStore) {
|
||||
amplitudeIncludeUTM,
|
||||
blackListedEvents,
|
||||
scriptURLs,
|
||||
googleAnalyticsTrackingId,
|
||||
matomoEndpoint,
|
||||
matomoSiteID,
|
||||
whiteListedEvents
|
||||
@@ -98,7 +97,6 @@ export async function createHandlers({ getState }: IStore) {
|
||||
amplitudeIncludeUTM,
|
||||
blackListedEvents,
|
||||
envType: deploymentInfo?.envType || 'dev',
|
||||
googleAnalyticsTrackingId,
|
||||
matomoEndpoint,
|
||||
matomoSiteID,
|
||||
group,
|
||||
@@ -154,6 +152,30 @@ export async function createHandlers({ getState }: IStore) {
|
||||
return handlers;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether a url is a data URL or not.
|
||||
*
|
||||
* @param {string} url - The URL to be checked.
|
||||
* @returns {boolean}
|
||||
*/
|
||||
function isDataURL(url?: string): boolean {
|
||||
if (typeof url !== 'string') { // The icon will be ignored
|
||||
return false;
|
||||
}
|
||||
|
||||
try {
|
||||
const urlObject = new URL(url);
|
||||
|
||||
if (urlObject.protocol === 'data:') {
|
||||
return false;
|
||||
}
|
||||
} catch {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Inits JitsiMeetJS.analytics by setting permanent properties and setting the handlers from the loaded scripts.
|
||||
* NOTE: Has to be used after JitsiMeetJS.init. Otherwise analytics will be null.
|
||||
@@ -185,8 +207,13 @@ export function initAnalytics(store: IStore, handlers: Array<Object>): boolean {
|
||||
inIframe?: boolean;
|
||||
isPromotedFromVisitor?: boolean;
|
||||
isVisitor?: boolean;
|
||||
overwritesCustomButtonsWithURL?: boolean;
|
||||
overwritesCustomParticipantButtonsWithURL?: boolean;
|
||||
overwritesDefaultLogoUrl?: boolean;
|
||||
overwritesDeploymentUrls?: boolean;
|
||||
overwritesEtherpadBase?: boolean;
|
||||
overwritesHosts?: boolean;
|
||||
overwritesIceServers?: boolean;
|
||||
overwritesLiveStreamingUrls?: boolean;
|
||||
overwritesPeopleSearchUrl?: boolean;
|
||||
overwritesPrejoinConfigICEUrl?: boolean;
|
||||
@@ -235,6 +262,13 @@ export function initAnalytics(store: IStore, handlers: Array<Object>): boolean {
|
||||
permanentProperties.overwritesSalesforceUrl = 'config.salesforceUrl' in params;
|
||||
permanentProperties.overwritesPeopleSearchUrl = 'config.peopleSearchUrl' in params;
|
||||
permanentProperties.overwritesDefaultLogoUrl = 'config.defaultLogoUrl' in params;
|
||||
permanentProperties.overwritesEtherpadBase = 'config.etherpad_base' in params;
|
||||
const hosts = params['config.hosts'] ?? {};
|
||||
const hostsProps = [ 'anonymousdomain', 'authdomain', 'domain', 'focus', 'muc', 'visitorFocus' ];
|
||||
|
||||
permanentProperties.overwritesHosts = 'config.hosts' in params
|
||||
|| Boolean(hostsProps.find(p => `config.hosts.${p}` in params || (typeof hosts === 'object' && p in hosts)));
|
||||
|
||||
const prejoinConfig = params['config.prejoinConfig'] ?? {};
|
||||
|
||||
permanentProperties.overwritesPrejoinConfigICEUrl = ('config.prejoinConfig.preCallTestICEUrl' in params)
|
||||
@@ -260,6 +294,18 @@ export function initAnalytics(store: IStore, handlers: Array<Object>): boolean {
|
||||
)
|
||||
);
|
||||
|
||||
permanentProperties.overwritesIceServers = Boolean(Object.keys(params).find(k => k.startsWith('iceServers')));
|
||||
|
||||
const customToolbarButtons = params['config.customToolbarButtons'] ?? [];
|
||||
|
||||
permanentProperties.overwritesCustomButtonsWithURL = Boolean(
|
||||
customToolbarButtons.find(({ icon }: { icon: string; }) => isDataURL(icon)));
|
||||
|
||||
const customParticipantMenuButtons = params['config.customParticipantMenuButtons'] ?? [];
|
||||
|
||||
permanentProperties.overwritesCustomParticipantButtonsWithURL = Boolean(
|
||||
customParticipantMenuButtons.find(({ icon }: { icon: string; }) => isDataURL(icon)));
|
||||
|
||||
// Optionally, include local deployment information based on the
|
||||
// contents of window.config.deploymentInfo.
|
||||
if (deploymentInfo) {
|
||||
|
||||
@@ -14,7 +14,6 @@ interface IOptions {
|
||||
amplitudeIncludeUTM?: boolean;
|
||||
blackListedEvents?: string[];
|
||||
envType?: string;
|
||||
googleAnalyticsTrackingId?: string;
|
||||
group?: string;
|
||||
host?: string;
|
||||
matomoEndpoint?: string;
|
||||
|
||||
@@ -1,159 +0,0 @@
|
||||
/* global ga */
|
||||
|
||||
import { getJitsiMeetGlobalNS } from '../../base/util/helpers';
|
||||
|
||||
import AbstractHandler, { IEvent } from './AbstractHandler';
|
||||
|
||||
/**
|
||||
* Analytics handler for Google Analytics.
|
||||
*/
|
||||
class GoogleAnalyticsHandler extends AbstractHandler {
|
||||
_userProperties: Object;
|
||||
_userPropertiesString: string;
|
||||
|
||||
/**
|
||||
* Creates new instance of the GA analytics handler.
|
||||
*
|
||||
* @param {Object} options - The Google Analytics options.
|
||||
* @param {string} options.googleAnalyticsTrackingId - The GA track id
|
||||
* required by the GA API.
|
||||
*/
|
||||
constructor(options: any) {
|
||||
super(options);
|
||||
|
||||
this._userProperties = {};
|
||||
|
||||
if (!options.googleAnalyticsTrackingId) {
|
||||
throw new Error('Failed to initialize Google Analytics handler, no tracking ID');
|
||||
}
|
||||
|
||||
this._enabled = true;
|
||||
this._initGoogleAnalytics(options);
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes the ga object.
|
||||
*
|
||||
* @param {Object} options - The Google Analytics options.
|
||||
* @param {string} options.googleAnalyticsTrackingId - The GA track id
|
||||
* required by the GA API.
|
||||
* @returns {void}
|
||||
*/
|
||||
_initGoogleAnalytics(options: any) {
|
||||
/**
|
||||
* TODO: Keep this local, there's no need to add it to window.
|
||||
*/
|
||||
/* eslint-disable */ // @ts-ignore
|
||||
(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
|
||||
// @ts-ignore
|
||||
(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
|
||||
})(window,document,'script','//www.google-analytics.com/analytics.js','ga');
|
||||
/* eslint-enable */
|
||||
// @ts-ignore
|
||||
ga('create', options.googleAnalyticsTrackingId, 'auto');
|
||||
|
||||
// @ts-ignore
|
||||
ga('send', 'pageview');
|
||||
}
|
||||
|
||||
/**
|
||||
* Extracts the integer to use for a Google Analytics event's value field
|
||||
* from a lib-jitsi-meet analytics event.
|
||||
*
|
||||
* @param {Object} event - The lib-jitsi-meet analytics event.
|
||||
* @returns {number} - The integer to use for the 'value' of a Google
|
||||
* analytics event, or NaN if the lib-jitsi-meet event doesn't contain a
|
||||
* suitable value.
|
||||
* @private
|
||||
*/
|
||||
_extractValue(event: IEvent) {
|
||||
let value: string | number | undefined = event?.attributes?.value;
|
||||
|
||||
// Try to extract an integer from the "value" attribute.
|
||||
value = Math.round(parseFloat(value ?? ''));
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Extracts the string to use for a Google Analytics event's label field
|
||||
* from a lib-jitsi-meet analytics event.
|
||||
*
|
||||
* @param {Object} event - The lib-jitsi-meet analytics event.
|
||||
* @returns {string} - The string to use for the 'label' of a Google
|
||||
* analytics event.
|
||||
* @private
|
||||
*/
|
||||
_extractLabel(event: IEvent) {
|
||||
const { attributes = {} } = event;
|
||||
const labelsArray
|
||||
= Object.keys(attributes).map(key => `${key}=${attributes[key]}`);
|
||||
|
||||
labelsArray.push(this._userPropertiesString);
|
||||
|
||||
return labelsArray.join('&');
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the permanent properties for the current session.
|
||||
*
|
||||
* @param {Object} userProps - The permanent portperties.
|
||||
* @returns {void}
|
||||
*/
|
||||
setUserProperties(userProps: any = {}) {
|
||||
if (!this._enabled) {
|
||||
return;
|
||||
}
|
||||
|
||||
// The label field is limited to 500B. We will concatenate all
|
||||
// attributes of the event, except the user agent because it may be
|
||||
// lengthy and is probably included from elsewhere.
|
||||
const filter = [ 'user_agent', 'callstats_name' ];
|
||||
|
||||
this._userPropertiesString
|
||||
= Object.keys(userProps)
|
||||
.filter(key => filter.indexOf(key) === -1)
|
||||
.map(key => `permanent_${key}=${userProps[key]}`)
|
||||
.join('&');
|
||||
}
|
||||
|
||||
/**
|
||||
* This is the entry point of the API. The function sends an event to
|
||||
* google analytics. The format of the event is described in
|
||||
* analyticsAdapter in lib-jitsi-meet.
|
||||
*
|
||||
* @param {Object} event - The event in the format specified by
|
||||
* lib-jitsi-meet.
|
||||
* @returns {void}
|
||||
*/
|
||||
sendEvent(event: IEvent) {
|
||||
if (this._shouldIgnore(event)) {
|
||||
return;
|
||||
}
|
||||
|
||||
const gaEvent: {
|
||||
eventAction?: string;
|
||||
eventCategory: string;
|
||||
eventLabel: string;
|
||||
eventValue?: number;
|
||||
} = {
|
||||
'eventCategory': 'jitsi-meet',
|
||||
'eventAction': this._extractName(event),
|
||||
'eventLabel': this._extractLabel(event)
|
||||
};
|
||||
const value = this._extractValue(event);
|
||||
|
||||
if (!isNaN(value)) {
|
||||
gaEvent.eventValue = value;
|
||||
}
|
||||
|
||||
// @ts-ignore
|
||||
ga('send', 'event', gaEvent);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
const globalNS = getJitsiMeetGlobalNS();
|
||||
|
||||
globalNS.analyticsHandlers = globalNS.analyticsHandlers || [];
|
||||
globalNS.analyticsHandlers.push(GoogleAnalyticsHandler);
|
||||
@@ -158,4 +158,3 @@ export function maybeRedirectToTokenAuthUrl(
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -26,13 +26,6 @@ export interface IProps {
|
||||
* @abstract
|
||||
*/
|
||||
export class AbstractApp<P extends IProps = IProps> extends BaseApp<P> {
|
||||
/**
|
||||
* The deferred for the initialisation {{promise, resolve, reject}}.
|
||||
*/
|
||||
_init: {
|
||||
promise: Promise<any>;
|
||||
};
|
||||
|
||||
/**
|
||||
* Initializes the app.
|
||||
*
|
||||
|
||||
@@ -140,10 +140,7 @@ function _getWebWelcomePageRoute(state: IReduxState) {
|
||||
*
|
||||
* @returns {Object}
|
||||
*/
|
||||
function _getEmptyRoute(): {
|
||||
component: React.ReactNode;
|
||||
href?: string;
|
||||
} {
|
||||
function _getEmptyRoute(): { component: React.ReactNode; href?: string; } {
|
||||
return {
|
||||
component: BlankPage,
|
||||
href: undefined
|
||||
|
||||
@@ -113,8 +113,7 @@ function _isMaybeSplitBrainError(getState: IStore['getState'], action: AnyAction
|
||||
const { error } = action;
|
||||
const isShardChangedError = error
|
||||
&& error.message === 'item-not-found'
|
||||
&& error.details
|
||||
&& error.details.shard_changed;
|
||||
&& error.details?.shard_changed;
|
||||
|
||||
if (isShardChangedError) {
|
||||
const state = getState();
|
||||
|
||||
@@ -13,6 +13,7 @@ import '../mobile/react-native-sdk/middleware';
|
||||
import '../mobile/watchos/middleware';
|
||||
import '../share-room/middleware';
|
||||
import '../shared-video/middleware';
|
||||
import '../toolbox/middleware.native';
|
||||
import '../whiteboard/middleware.native';
|
||||
|
||||
import './middlewares.any';
|
||||
|
||||
@@ -121,7 +121,7 @@ MiddlewareRegistry.register(store => next => action => {
|
||||
if (isTokenAuthEnabled(config)
|
||||
&& config.tokenAuthUrlAutoRedirect
|
||||
&& state['features/base/jwt'].jwt) {
|
||||
// auto redirect is turned on and we have succesfully logged in
|
||||
// auto redirect is turned on and we have successfully logged in
|
||||
// let's mark that
|
||||
dispatch(setTokenAuthUrlSuccess(true));
|
||||
}
|
||||
|
||||
@@ -14,7 +14,6 @@ import PersistenceRegistry from '../../redux/PersistenceRegistry';
|
||||
import ReducerRegistry from '../../redux/ReducerRegistry';
|
||||
import StateListenerRegistry from '../../redux/StateListenerRegistry';
|
||||
import SoundCollection from '../../sounds/components/SoundCollection';
|
||||
import { createDeferred } from '../../util/helpers';
|
||||
import { appWillMount, appWillUnmount } from '../actions';
|
||||
import logger from '../logger';
|
||||
|
||||
@@ -46,9 +45,7 @@ export default class BaseApp<P> extends Component<P, IState> {
|
||||
/**
|
||||
* The deferred for the initialisation {{promise, resolve, reject}}.
|
||||
*/
|
||||
_init: {
|
||||
promise: Promise<any>;
|
||||
};
|
||||
_init: PromiseWithResolvers<any>;
|
||||
|
||||
/**
|
||||
* Initializes a new {@code BaseApp} instance.
|
||||
@@ -79,7 +76,7 @@ export default class BaseApp<P> extends Component<P, IState> {
|
||||
* @see {@link #_initStorage}
|
||||
* @type {Promise}
|
||||
*/
|
||||
this._init = createDeferred<void>();
|
||||
this._init = Promise.withResolvers();
|
||||
|
||||
try {
|
||||
await this._initStorage();
|
||||
|
||||
@@ -237,7 +237,6 @@ export function getConferenceOptions(stateful: IStateful) {
|
||||
if (options.disableThirdPartyRequests) {
|
||||
delete config.analytics?.scriptURLs;
|
||||
delete config.analytics?.amplitudeAPPKey;
|
||||
delete config.analytics?.googleAnalyticsTrackingId;
|
||||
}
|
||||
|
||||
return options;
|
||||
|
||||
@@ -177,7 +177,7 @@ function _conferenceFailed({ dispatch, getState }: IStore, next: Function, actio
|
||||
dispatch(showErrorNotification({
|
||||
description: 'Restart initiated because of a bridge failure',
|
||||
titleKey: 'dialog.sessionRestarted'
|
||||
}, NOTIFICATION_TIMEOUT_TYPE.LONG));
|
||||
}));
|
||||
}
|
||||
|
||||
break;
|
||||
@@ -190,7 +190,7 @@ function _conferenceFailed({ dispatch, getState }: IStore, next: Function, actio
|
||||
descriptionArguments: { msg },
|
||||
descriptionKey: msg ? 'dialog.connectErrorWithMsg' : 'dialog.connectError',
|
||||
titleKey: 'connection.CONNFAIL'
|
||||
}, NOTIFICATION_TIMEOUT_TYPE.LONG));
|
||||
}));
|
||||
|
||||
break;
|
||||
}
|
||||
@@ -199,7 +199,7 @@ function _conferenceFailed({ dispatch, getState }: IStore, next: Function, actio
|
||||
hideErrorSupportLink: true,
|
||||
descriptionKey: 'dialog.maxUsersLimitReached',
|
||||
titleKey: 'dialog.maxUsersLimitReachedTitle'
|
||||
}, NOTIFICATION_TIMEOUT_TYPE.LONG));
|
||||
}));
|
||||
|
||||
// In case of max users(it can be from a visitor node), let's restore
|
||||
// oldConfig if any as we will be back to the main prosody.
|
||||
@@ -236,7 +236,7 @@ function _conferenceFailed({ dispatch, getState }: IStore, next: Function, actio
|
||||
descriptionKey,
|
||||
hideErrorSupportLink: true,
|
||||
titleKey
|
||||
}, NOTIFICATION_TIMEOUT_TYPE.STICKY));
|
||||
}));
|
||||
|
||||
sendAnalytics(createNotAllowedErrorEvent(type, msg));
|
||||
|
||||
@@ -248,8 +248,7 @@ function _conferenceFailed({ dispatch, getState }: IStore, next: Function, actio
|
||||
}
|
||||
|
||||
!error.recoverable
|
||||
&& conference
|
||||
&& conference.leave(CONFERENCE_LEAVE_REASONS.UNRECOVERABLE_ERROR).catch((reason: Error) => {
|
||||
&& conference?.leave(CONFERENCE_LEAVE_REASONS.UNRECOVERABLE_ERROR).catch((reason: Error) => {
|
||||
// Even though we don't care too much about the failure, it may be
|
||||
// good to know that it happen, so log it (on the info level).
|
||||
logger.info('JitsiConference.leave() rejected with:', reason);
|
||||
@@ -417,7 +416,7 @@ function _connectionFailed({ dispatch, getState }: IStore, next: Function, actio
|
||||
descriptionKey: errors ? 'dialog.tokenAuthFailedWithReasons' : 'dialog.tokenAuthFailed',
|
||||
descriptionArguments: { reason: errors },
|
||||
titleKey: 'dialog.tokenAuthFailedTitle'
|
||||
}, NOTIFICATION_TIMEOUT_TYPE.STICKY));
|
||||
}));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -430,7 +429,7 @@ function _connectionFailed({ dispatch, getState }: IStore, next: Function, actio
|
||||
} as INotificationProps;
|
||||
|
||||
const { locationURL = { href: '' } as URL } = getState()['features/base/connection'];
|
||||
const { tenant } = parseURIString(locationURL.href) || {};
|
||||
const { tenant = '' } = parseURIString(locationURL.href) || {};
|
||||
|
||||
if (tenant.startsWith('-') || tenant.endsWith('-')) {
|
||||
notificationProps.descriptionKey = 'notify.invalidTenantHyphenDescription';
|
||||
@@ -551,7 +550,7 @@ function _pinParticipant({ getState }: IStore, next: Function, action: AnyAction
|
||||
const actionName = id ? ACTION_PINNED : ACTION_UNPINNED;
|
||||
const local
|
||||
= participantById?.local
|
||||
|| (!id && pinnedParticipant && pinnedParticipant.local);
|
||||
|| (!id && pinnedParticipant?.local);
|
||||
let participantIdForEvent;
|
||||
|
||||
if (local) {
|
||||
|
||||
@@ -495,7 +495,7 @@ function _conferenceJoined(state: IConferenceState, { conference }: { conference
|
||||
* reduction of the specified action.
|
||||
*/
|
||||
function _conferenceLeftOrWillLeave(state: IConferenceState, { conference, type }:
|
||||
{ conference: IJitsiConference; type: string; }) {
|
||||
{ conference: IJitsiConference; type: string; }) {
|
||||
const nextState = { ...state };
|
||||
|
||||
// The redux action CONFERENCE_LEFT is the last time that we should be
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
import { ToolbarButton } from '../../toolbox/types';
|
||||
import { ILoggingConfig } from '../logging/types';
|
||||
import { DesktopSharingSourceType } from '../tracks/types';
|
||||
|
||||
type ButtonsWithNotifyClick = 'camera' |
|
||||
'chat' |
|
||||
@@ -183,7 +185,6 @@ export interface IConfig {
|
||||
amplitudeIncludeUTM?: boolean;
|
||||
blackListedEvents?: string[];
|
||||
disabled?: boolean;
|
||||
googleAnalyticsTrackingId?: string;
|
||||
matomoEndpoint?: string;
|
||||
matomoSiteID?: string;
|
||||
obfuscateRoomName?: boolean;
|
||||
@@ -215,6 +216,10 @@ export interface IConfig {
|
||||
hideAutoAssignButton?: boolean;
|
||||
hideJoinRoomButton?: boolean;
|
||||
};
|
||||
bridgeChannel?: {
|
||||
ignoreDomain?: string;
|
||||
preferSctp?: boolean;
|
||||
};
|
||||
buttonsWithNotifyClick?: Array<ButtonsWithNotifyClick | {
|
||||
key: ButtonsWithNotifyClick;
|
||||
preventExecution: boolean;
|
||||
@@ -275,14 +280,19 @@ export interface IConfig {
|
||||
max?: number;
|
||||
min?: number;
|
||||
};
|
||||
desktopSharingSources?: Array<DesktopSharingSourceType>;
|
||||
dialInConfCodeUrl?: string;
|
||||
dialInNumbersUrl?: string;
|
||||
dialOutAuthUrl?: string;
|
||||
dialOutRegionUrl?: string;
|
||||
disable1On1Mode?: boolean | null;
|
||||
disableAEC?: boolean;
|
||||
disableAGC?: boolean;
|
||||
disableAP?: boolean;
|
||||
disableAddingBackgroundImages?: boolean;
|
||||
disableAudioLevels?: boolean;
|
||||
disableBeforeUnloadHandlers?: boolean;
|
||||
disableCameraTintForeground?: boolean;
|
||||
disableChatSmileys?: boolean;
|
||||
disableDeepLinking?: boolean;
|
||||
disableFilmstripAutohiding?: boolean;
|
||||
@@ -294,11 +304,13 @@ export interface IConfig {
|
||||
disableJoinLeaveSounds?: boolean;
|
||||
disableLocalVideoFlip?: boolean;
|
||||
disableModeratorIndicator?: boolean;
|
||||
disableNS?: boolean;
|
||||
disablePolls?: boolean;
|
||||
disableProfile?: boolean;
|
||||
disableReactions?: boolean;
|
||||
disableReactionsModeration?: boolean;
|
||||
disableRecordAudioNotification?: boolean;
|
||||
disableRemoteControl?: boolean;
|
||||
disableRemoteMute?: boolean;
|
||||
disableRemoveRaisedHandOnFocus?: boolean;
|
||||
disableResponsiveTiles?: boolean;
|
||||
@@ -316,6 +328,7 @@ export interface IConfig {
|
||||
disableVirtualBackground?: boolean;
|
||||
disabledNotifications?: Array<string>;
|
||||
disabledSounds?: Array<Sounds>;
|
||||
displayJids?: boolean;
|
||||
doNotFlipLocalVideo?: boolean;
|
||||
doNotStoreRoom?: boolean;
|
||||
dropbox?: {
|
||||
@@ -345,7 +358,6 @@ export interface IConfig {
|
||||
maxMessagesPerSecond?: number;
|
||||
numRequests?: number;
|
||||
};
|
||||
enableAutomaticUrlCopy?: boolean;
|
||||
enableCalendarIntegration?: boolean;
|
||||
enableClosePage?: boolean;
|
||||
enableDisplayNameInStats?: boolean;
|
||||
@@ -359,6 +371,7 @@ export interface IConfig {
|
||||
enableOpusRed?: boolean;
|
||||
enableRemb?: boolean;
|
||||
enableSaveLogs?: boolean;
|
||||
enableTalkWhileMuted?: boolean;
|
||||
enableTcc?: boolean;
|
||||
enableWebHIDFeature?: boolean;
|
||||
enableWelcomePage?: boolean;
|
||||
@@ -372,7 +385,6 @@ export interface IConfig {
|
||||
faceCenteringThreshold?: number;
|
||||
};
|
||||
feedbackPercentage?: number;
|
||||
fileRecordingsEnabled?: boolean;
|
||||
fileRecordingsServiceEnabled?: boolean;
|
||||
fileRecordingsServiceSharingEnabled?: boolean;
|
||||
filmstrip?: {
|
||||
@@ -382,11 +394,11 @@ export interface IConfig {
|
||||
disabled?: boolean;
|
||||
minParticipantCountForTopPanel?: number;
|
||||
};
|
||||
firefox_fake_device?: string;
|
||||
flags?: {
|
||||
ssrcRewritingEnabled: boolean;
|
||||
};
|
||||
focusUserJid?: string;
|
||||
forceTurnRelay?: boolean;
|
||||
gatherStats?: boolean;
|
||||
giphy?: {
|
||||
displayMode?: 'all' | 'tile' | 'chat';
|
||||
@@ -426,6 +438,7 @@ export interface IConfig {
|
||||
};
|
||||
iAmRecorder?: boolean;
|
||||
iAmSipGateway?: boolean;
|
||||
ignoreStartMuted?: boolean;
|
||||
inviteAppName?: string | null;
|
||||
inviteServiceCallFlowsUrl?: string;
|
||||
inviteServiceUrl?: string;
|
||||
@@ -458,6 +471,7 @@ export interface IConfig {
|
||||
};
|
||||
localSubject?: string;
|
||||
locationURL?: URL;
|
||||
logging?: ILoggingConfig;
|
||||
mainToolbarButtons?: Array<Array<string>>;
|
||||
maxFullResolutionParticipants?: number;
|
||||
microsoftApiApplicationClientID?: string;
|
||||
@@ -466,6 +480,7 @@ export interface IConfig {
|
||||
noiseSuppression?: INoiseSuppressionConfig;
|
||||
noticeMessage?: string;
|
||||
notificationTimeouts?: {
|
||||
extraLong?: number;
|
||||
long?: number;
|
||||
medium?: number;
|
||||
short?: number;
|
||||
@@ -479,6 +494,7 @@ export interface IConfig {
|
||||
enabled?: boolean;
|
||||
iceTransportPolicy?: string;
|
||||
mobileCodecPreferenceOrder?: Array<string>;
|
||||
mobileScreenshareCodec?: string;
|
||||
stunServers?: Array<{ urls: string; }>;
|
||||
};
|
||||
participantMenuButtonsWithNotifyClick?: Array<string | ParticipantMenuButtonsWithNotifyClick | {
|
||||
@@ -571,7 +587,9 @@ export interface IConfig {
|
||||
subject?: string;
|
||||
testing?: {
|
||||
assumeBandwidth?: boolean;
|
||||
debugAudioLevels?: boolean;
|
||||
dumpTranscript?: boolean;
|
||||
failICE?: boolean;
|
||||
noAutoPlayVideo?: boolean;
|
||||
p2pTestMode?: boolean;
|
||||
skipInterimTranscriptions?: boolean;
|
||||
@@ -619,6 +637,13 @@ export interface IConfig {
|
||||
mobileCodecPreferenceOrder?: Array<string>;
|
||||
persist?: boolean;
|
||||
};
|
||||
visitors?: {
|
||||
enableMediaOnPromote?: {
|
||||
audio?: boolean;
|
||||
video?: boolean;
|
||||
};
|
||||
queueService: string;
|
||||
};
|
||||
watchRTCConfigParams?: IWatchRTCConfiguration;
|
||||
webhookProxyUrl?: string;
|
||||
webrtcIceTcpDisable?: boolean;
|
||||
|
||||
@@ -22,6 +22,7 @@ export default [
|
||||
'apiLogLevels',
|
||||
'avgRtpStatsN',
|
||||
'backgroundAlpha',
|
||||
'brandingRoomAlias',
|
||||
'breakoutRooms',
|
||||
'bridgeChannel',
|
||||
'buttonsWithNotifyClick',
|
||||
@@ -77,9 +78,6 @@ export default [
|
||||
'connectionIndicators',
|
||||
'constraints',
|
||||
'customToolbarButtons',
|
||||
'brandingRoomAlias',
|
||||
'debug',
|
||||
'debugAudioLevels',
|
||||
'deeplinking.disabled',
|
||||
'deeplinking.desktop.enabled',
|
||||
'defaultLocalDisplayName',
|
||||
@@ -93,13 +91,13 @@ export default [
|
||||
'disableAddingBackgroundImages',
|
||||
'disableAudioLevels',
|
||||
'disableBeforeUnloadHandlers',
|
||||
'disableCameraTintForeground',
|
||||
'disableChatSmileys',
|
||||
'disableDeepLinking',
|
||||
'disabledNotifications',
|
||||
'disabledSounds',
|
||||
'disableFilmstripAutohiding',
|
||||
'disableInitialGUM',
|
||||
'disableHPF',
|
||||
'disableInviteFunctions',
|
||||
'disableIncomingMessageSound',
|
||||
'disableJoinLeaveSounds',
|
||||
@@ -148,14 +146,9 @@ export default [
|
||||
'enableNoAudioDetection',
|
||||
'enableNoisyMicDetection',
|
||||
'enableTcc',
|
||||
'enableAutomaticUrlCopy',
|
||||
'etherpad_base',
|
||||
'faceLandmarks',
|
||||
'failICE',
|
||||
'feedbackPercentage',
|
||||
'fileRecordingsEnabled',
|
||||
'filmstrip',
|
||||
'firefox_fake_device',
|
||||
'flags',
|
||||
'forceTurnRelay',
|
||||
'gatherStats',
|
||||
@@ -172,7 +165,6 @@ export default [
|
||||
'hideAddRoomButton',
|
||||
'hideEmailInSettings',
|
||||
'hideLobbyButton',
|
||||
'hosts',
|
||||
'iAmRecorder',
|
||||
'iAmSipGateway',
|
||||
'ignoreStartMuted',
|
||||
@@ -195,6 +187,7 @@ export default [
|
||||
'p2p.enabled',
|
||||
'p2p.iceTransportPolicy',
|
||||
'p2p.mobileCodecPreferenceOrder',
|
||||
'p2p.mobileScreenshareCodec',
|
||||
'participantMenuButtonsWithNotifyClick',
|
||||
'participantsPane',
|
||||
'pcStatsInterval',
|
||||
@@ -235,8 +228,18 @@ export default [
|
||||
'useHostPageLocalStorage',
|
||||
'useTurnUdp',
|
||||
'videoQuality',
|
||||
'visitors',
|
||||
'watchRTCConfigParams',
|
||||
'visitors.enableMediaOnPromote',
|
||||
'watchRTCConfigParams.allowBrowserLogCollection',
|
||||
'watchRTCConfigParams.collectionInterval',
|
||||
'watchRTCConfigParams.console',
|
||||
'watchRTCConfigParams.debug',
|
||||
'watchRTCConfigParams.keys',
|
||||
'watchRTCConfigParams.logGetStats',
|
||||
'watchRTCConfigParams.rtcApiKey',
|
||||
'watchRTCConfigParams.rtcPeerId',
|
||||
'watchRTCConfigParams.rtcRoomId',
|
||||
'watchRTCConfigParams.rtcTags',
|
||||
'watchRTCConfigParams.rtcToken',
|
||||
'webrtcIceTcpDisable',
|
||||
'webrtcIceUdpDisable',
|
||||
'whiteboard.enabled'
|
||||
|
||||
@@ -20,7 +20,6 @@ export function _cleanupConfig(config: IConfig) {
|
||||
|
||||
if (NativeModules.AppInfo.LIBRE_BUILD) {
|
||||
delete config.analytics?.amplitudeAPPKey;
|
||||
delete config.analytics?.googleAnalyticsTrackingId;
|
||||
delete config.analytics?.rtcstatsEnabled;
|
||||
delete config.analytics?.rtcstatsEndpoint;
|
||||
delete config.analytics?.rtcstatsPollInterval;
|
||||
|
||||
@@ -89,7 +89,7 @@ export function _setDeeplinkingDefaults(deeplinking: IDeeplinkingConfig) {
|
||||
android.downloadLink = android.downloadLink
|
||||
|| 'https://play.google.com/store/apps/details?id=org.jitsi.meet';
|
||||
android.appPackage = android.appPackage || 'org.jitsi.meet';
|
||||
android.fDroidUrl = android.fDroidUrl || 'https://f-droid.org/en/packages/org.jitsi.meet/';
|
||||
android.fDroidUrl = android.fDroidUrl || 'https://f-droid.org/packages/org.jitsi.meet/';
|
||||
if (android.dynamicLink) {
|
||||
android.dynamicLink.apn = android.dynamicLink.apn || 'org.jitsi.meet';
|
||||
android.dynamicLink.appCode = android.dynamicLink.appCode || 'w2atb';
|
||||
|
||||
@@ -22,15 +22,12 @@ export default [
|
||||
'DISABLE_DOMINANT_SPEAKER_INDICATOR',
|
||||
'DISABLE_FOCUS_INDICATOR',
|
||||
'DISABLE_PRIVATE_MESSAGES',
|
||||
'DISABLE_RINGING',
|
||||
'DISABLE_TRANSCRIPTION_SUBTITLES',
|
||||
'DISABLE_VIDEO_BACKGROUND',
|
||||
'DISPLAY_WELCOME_PAGE_CONTENT',
|
||||
'ENABLE_DIAL_OUT',
|
||||
'ENABLE_FEEDBACK_ANIMATION',
|
||||
'FILM_STRIP_MAX_HEIGHT',
|
||||
'GENERATE_ROOMNAMES_ON_WELCOME_PAGE',
|
||||
'HIDE_INVITE_MORE_HEADER',
|
||||
'INDICATOR_FONT_SIZES',
|
||||
'INITIAL_TOOLBAR_TIMEOUT',
|
||||
'LANG_DETECTION',
|
||||
|
||||
@@ -63,7 +63,6 @@ export interface IConfigState extends IConfig {
|
||||
analysis?: {
|
||||
obfuscateRoomName?: boolean;
|
||||
};
|
||||
disableRemoteControl?: boolean;
|
||||
error?: Error;
|
||||
oldConfig?: {
|
||||
bosh?: string;
|
||||
@@ -75,13 +74,6 @@ export interface IConfigState extends IConfig {
|
||||
p2p?: object;
|
||||
websocket?: string;
|
||||
};
|
||||
visitors?: {
|
||||
enableMediaOnPromote?: {
|
||||
audio?: boolean;
|
||||
video?: boolean;
|
||||
};
|
||||
queueService: string;
|
||||
};
|
||||
}
|
||||
|
||||
ReducerRegistry.register<IConfigState>('features/base/config', (state = _getInitialState(), action): IConfigState => {
|
||||
|
||||
@@ -1,8 +1,11 @@
|
||||
/**
|
||||
* Prefixes of devices that will be filtered from the device list.
|
||||
*
|
||||
* NOTE: Currently we filter only 'Microsoft Teams Audio Device' virtual device. It seems that it can't be set
|
||||
* NOTE: It seems that the filtered devices can't be set
|
||||
* as default device on the OS level and this use case is not handled in the code. If we add more device prefixes that
|
||||
* can be default devices we should make sure to handle the default device use case.
|
||||
*/
|
||||
export const DEVICE_LABEL_PREFIXES_TO_IGNORE = [ 'Microsoft Teams Audio Device' ];
|
||||
export const DEVICE_LABEL_PREFIXES_TO_IGNORE = [
|
||||
'Microsoft Teams Audio Device',
|
||||
'ZoomAudioDevice'
|
||||
];
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
/* eslint-disable require-jsdoc */
|
||||
|
||||
import { IReduxState, IStore } from '../../app/types';
|
||||
import JitsiMeetJS from '../lib-jitsi-meet';
|
||||
import { updateSettings } from '../settings/actions';
|
||||
@@ -157,7 +159,8 @@ export function getDevicesFromURL(state: IReduxState) {
|
||||
* @returns {Object} An object with the media devices split by type. The keys
|
||||
* are device type and the values are arrays with devices matching the device
|
||||
* type.
|
||||
*/
|
||||
*/
|
||||
// @ts-ignore
|
||||
export function groupDevicesByKind(devices: MediaDeviceInfo[]): IDevicesState['availableDevices'] {
|
||||
return {
|
||||
audioInput: devices.filter(device => device.kind === 'audioinput'),
|
||||
@@ -166,24 +169,16 @@ export function groupDevicesByKind(devices: MediaDeviceInfo[]): IDevicesState['a
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Filters audio devices from a list of MediaDeviceInfo objects.
|
||||
*
|
||||
* @param {Array<MediaDeviceInfo>} devices - Unfiltered media devices.
|
||||
* @private
|
||||
* @returns {Array<MediaDeviceInfo>} Filtered audio devices.
|
||||
*/
|
||||
export function filterAudioDevices(devices: MediaDeviceInfo[]) {
|
||||
return devices.filter(device => device.kind === 'audioinput');
|
||||
}
|
||||
|
||||
/**
|
||||
* Filters the devices that start with one of the prefixes from DEVICE_LABEL_PREFIXES_TO_IGNORE.
|
||||
*
|
||||
* @param {MediaDeviceInfo[]} devices - The devices to be filtered.
|
||||
* @returns {MediaDeviceInfo[]} - The filtered devices.
|
||||
*/
|
||||
// @ts-ignore
|
||||
export function filterIgnoredDevices(devices: MediaDeviceInfo[] = []) {
|
||||
|
||||
// @ts-ignore
|
||||
const ignoredDevices: MediaDeviceInfo[] = [];
|
||||
const filteredDevices = devices.filter(device => {
|
||||
if (!device.label) {
|
||||
@@ -212,6 +207,7 @@ export function filterIgnoredDevices(devices: MediaDeviceInfo[] = []) {
|
||||
* @param {MediaDeviceInfo[]} devices2 - Array with devices to be compared.
|
||||
* @returns {boolean} - True if the device arrays are different and false otherwise.
|
||||
*/
|
||||
// @ts-ignore
|
||||
export function areDevicesDifferent(devices1: MediaDeviceInfo[] = [], devices2: MediaDeviceInfo[] = []) {
|
||||
if (devices1.length !== devices2.length) {
|
||||
return true;
|
||||
@@ -315,6 +311,7 @@ export function getVideoDeviceIds(state: IReduxState) {
|
||||
* @param {MediaDeviceInfo[]} devices - The devices.
|
||||
* @returns {string}
|
||||
*/
|
||||
// @ts-ignore
|
||||
function devicesToStr(devices?: MediaDeviceInfo[]) {
|
||||
return devices?.map(device => `\t\t${device.label}[${device.deviceId}]`).join('\n');
|
||||
}
|
||||
@@ -326,6 +323,7 @@ function devicesToStr(devices?: MediaDeviceInfo[]) {
|
||||
* @param {string} title - The title that will be printed in the log.
|
||||
* @returns {void}
|
||||
*/
|
||||
// @ts-ignore
|
||||
export function logDevices(devices: MediaDeviceInfo[], title = '') {
|
||||
const deviceList = groupDevicesByKind(devices);
|
||||
const audioInputs = devicesToStr(deviceList.audioInput);
|
||||
|
||||
@@ -9,6 +9,7 @@ import {
|
||||
OPEN_SHEET
|
||||
} from './actionTypes';
|
||||
import { isDialogOpen } from './functions';
|
||||
import logger from './logger';
|
||||
|
||||
/**
|
||||
* Signals Dialog to close its dialog.
|
||||
@@ -23,6 +24,8 @@ import { isDialogOpen } from './functions';
|
||||
* }}
|
||||
*/
|
||||
export function hideDialog(component?: ComponentType<any>) {
|
||||
logger.info(`Hide dialog: ${getComponentDisplayName(component)}`);
|
||||
|
||||
return {
|
||||
type: HIDE_DIALOG,
|
||||
component
|
||||
@@ -55,6 +58,8 @@ export function hideSheet() {
|
||||
* }}
|
||||
*/
|
||||
export function openDialog(component: ComponentType<any>, componentProps?: Object) {
|
||||
logger.info(`Open dialog: ${getComponentDisplayName(component)}`);
|
||||
|
||||
return {
|
||||
type: OPEN_DIALOG,
|
||||
component,
|
||||
@@ -101,3 +106,21 @@ export function toggleDialog(component: ComponentType<any>, componentProps?: Obj
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Extracts a printable name for a dialog component.
|
||||
*
|
||||
* @param {Object} component - The component to extract the name for.
|
||||
*
|
||||
* @returns {string} The display name.
|
||||
*/
|
||||
function getComponentDisplayName(component?: ComponentType<any>) {
|
||||
if (!component) {
|
||||
return '';
|
||||
}
|
||||
|
||||
const name = component.displayName ?? component.name ?? 'Component';
|
||||
|
||||
return name.replace('withI18nextTranslation(Connect(', '') // dialogs with translations
|
||||
.replace('))', ''); // dialogs with translations suffix
|
||||
}
|
||||
|
||||
@@ -23,7 +23,7 @@ MiddlewareRegistry.register(store => next => action => {
|
||||
? action.value
|
||||
: store.getState()['features/dynamic-branding'];
|
||||
|
||||
if (language && labels && labels[language]) {
|
||||
if (language && labels?.[language]) {
|
||||
changeLanguageBundle(language, labels[language])
|
||||
.catch(err => {
|
||||
logger.log('Error setting dynamic language bundle', err);
|
||||
|
||||
@@ -237,7 +237,7 @@ function _undoOverwriteLocalParticipant(
|
||||
* }}
|
||||
*/
|
||||
function _user2participant({ avatar, avatarUrl, email, id, name, 'hidden-from-recorder': hiddenFromRecorder }:
|
||||
{ avatar?: string; avatarUrl?: string; email: string; 'hidden-from-recorder': string | boolean;
|
||||
{ avatar?: string; avatarUrl?: string; email: string; 'hidden-from-recorder': string | boolean;
|
||||
id: string; name: string; }) {
|
||||
const participant: {
|
||||
avatarURL?: string;
|
||||
|
||||
@@ -25,10 +25,6 @@ export function createLocalTrack(type: string, deviceId: string | null, timeout?
|
||||
JitsiMeetJS.createLocalTracks({
|
||||
cameraDeviceId: deviceId,
|
||||
devices: [ type ],
|
||||
|
||||
// eslint-disable-next-line camelcase
|
||||
firefox_fake_device:
|
||||
window.config?.firefox_fake_device,
|
||||
micDeviceId: deviceId,
|
||||
timeout,
|
||||
...additionalOptions
|
||||
|
||||
@@ -5,10 +5,11 @@ import ReducerRegistry from '../redux/ReducerRegistry';
|
||||
import { equals, set } from '../redux/functions';
|
||||
|
||||
import { SET_LOGGING_CONFIG, SET_LOG_COLLECTOR } from './actionTypes';
|
||||
import { ILoggingConfig, LogLevel } from './types';
|
||||
|
||||
const DEFAULT_LOGGING_CONFIG = {
|
||||
const DEFAULT_LOGGING_CONFIG: ILoggingConfig = {
|
||||
// default log level for the app and lib-jitsi-meet
|
||||
defaultLogLevel: 'trace' as LogLevel,
|
||||
defaultLogLevel: 'trace',
|
||||
|
||||
// Option to disable LogCollector (which stores the logs)
|
||||
// disableLogCollector: true,
|
||||
@@ -16,8 +17,8 @@ const DEFAULT_LOGGING_CONFIG = {
|
||||
loggers: {
|
||||
// The following are too verbose in their logging with the
|
||||
// {@link #defaultLogLevel}:
|
||||
'modules/RTC/TraceablePeerConnection.js': 'info' as LogLevel,
|
||||
'modules/xmpp/strophe.util.js': 'log' as LogLevel
|
||||
'modules/RTC/TraceablePeerConnection.js': 'info',
|
||||
'modules/xmpp/strophe.util.js': 'log'
|
||||
}
|
||||
};
|
||||
|
||||
@@ -39,11 +40,11 @@ const DEFAULT_STATE = {
|
||||
|
||||
// Reduce default verbosity on mobile, it kills performance.
|
||||
if (navigator.product === 'ReactNative') {
|
||||
const RN_LOGGERS = {
|
||||
'modules/sdp/SDPUtil.js': 'info' as LogLevel,
|
||||
'modules/xmpp/ChatRoom.js': 'warn' as LogLevel,
|
||||
'modules/xmpp/JingleSessionPC.js': 'info' as LogLevel,
|
||||
'modules/xmpp/strophe.jingle.js': 'info' as LogLevel
|
||||
const RN_LOGGERS: { [key: string]: LogLevel; } = {
|
||||
'modules/sdp/SDPUtil.js': 'info',
|
||||
'modules/xmpp/ChatRoom.js': 'warn',
|
||||
'modules/xmpp/JingleSessionPC.js': 'info',
|
||||
'modules/xmpp/strophe.jingle.js': 'info'
|
||||
};
|
||||
|
||||
DEFAULT_STATE.config.loggers = {
|
||||
@@ -52,16 +53,8 @@ if (navigator.product === 'ReactNative') {
|
||||
};
|
||||
}
|
||||
|
||||
type LogLevel = 'trace' | 'log' | 'info' | 'warn' | 'error';
|
||||
|
||||
export interface ILoggingState {
|
||||
config: {
|
||||
defaultLogLevel: LogLevel;
|
||||
disableLogCollector?: boolean;
|
||||
loggers: {
|
||||
[key: string]: LogLevel;
|
||||
};
|
||||
};
|
||||
config: ILoggingConfig;
|
||||
logCollector?: {
|
||||
flush: () => void;
|
||||
start: () => void;
|
||||
|
||||
9
react/features/base/logging/types.ts
Normal file
9
react/features/base/logging/types.ts
Normal file
@@ -0,0 +1,9 @@
|
||||
export type LogLevel = 'trace' | 'log' | 'info' | 'warn' | 'error';
|
||||
|
||||
export interface ILoggingConfig {
|
||||
defaultLogLevel?: LogLevel;
|
||||
disableLogCollector?: boolean;
|
||||
loggers?: {
|
||||
[key: string]: LogLevel;
|
||||
};
|
||||
}
|
||||
@@ -228,7 +228,7 @@ class AudioTrack extends Component<IProps> {
|
||||
* @returns {void}
|
||||
*/
|
||||
_detachTrack(track?: ITrack) {
|
||||
if (this._ref?.current && track && track.jitsiTrack) {
|
||||
if (this._ref?.current && track?.jitsiTrack) {
|
||||
clearTimeout(this._playTimeout);
|
||||
this._playTimeout = undefined;
|
||||
track.jitsiTrack.detach(this._ref.current);
|
||||
|
||||
@@ -358,7 +358,7 @@ class Video extends Component<IProps> {
|
||||
* @returns {void}
|
||||
*/
|
||||
_detachTrack(videoTrack?: Partial<ITrack>) {
|
||||
if (this._videoElement && videoTrack && videoTrack.jitsiTrack) {
|
||||
if (this._videoElement && videoTrack?.jitsiTrack) {
|
||||
videoTrack.jitsiTrack.detach(this._videoElement);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,11 +19,11 @@ export const MEDIA_TYPE: {
|
||||
AUDIO: MediaType;
|
||||
SCREENSHARE: MediaType;
|
||||
VIDEO: MediaType;
|
||||
} = {
|
||||
AUDIO: 'audio',
|
||||
SCREENSHARE: 'screenshare',
|
||||
VIDEO: 'video'
|
||||
};
|
||||
} = {
|
||||
AUDIO: 'audio',
|
||||
SCREENSHARE: 'screenshare',
|
||||
VIDEO: 'video'
|
||||
};
|
||||
|
||||
|
||||
/* eslint-disable no-bitwise */
|
||||
|
||||
@@ -3,7 +3,6 @@ import { AnyAction, combineReducers } from 'redux';
|
||||
import { CONFERENCE_FAILED, CONFERENCE_LEFT } from '../conference/actionTypes';
|
||||
import ReducerRegistry from '../redux/ReducerRegistry';
|
||||
import { TRACK_REMOVED } from '../tracks/actionTypes';
|
||||
import { DefferedPromise, createDeferred } from '../util/helpers';
|
||||
|
||||
import {
|
||||
GUM_PENDING,
|
||||
@@ -93,17 +92,18 @@ function _audio(state: IAudioState = _AUDIO_INITIAL_MEDIA_STATE, action: AnyActi
|
||||
// initial track creation haven't been started we would wait for it to finish before starting to join the room.
|
||||
// NOTE: The previous implementation was using the GUM promise from conference.init. But it turned out that connect
|
||||
// may finish even before conference.init is executed.
|
||||
const DEFAULT_INITIAL_PROMISE_STATE = createDeferred<IInitialGUMPromiseResult>();
|
||||
const DEFAULT_INITIAL_PROMISE_STATE = Promise.withResolvers<IInitialGUMPromiseResult>();
|
||||
|
||||
/**
|
||||
* Reducer fot the common properties in media state.
|
||||
* Reducer for the common properties in media state.
|
||||
*
|
||||
* @param {ICommonState} state - Common media state.
|
||||
* @param {Object} action - Action object.
|
||||
* @param {string} action.type - Type of action.
|
||||
* @returns {ICommonState}
|
||||
*/
|
||||
function _initialGUMPromise(state: DefferedPromise<IInitialGUMPromiseResult> | null = DEFAULT_INITIAL_PROMISE_STATE,
|
||||
function _initialGUMPromise(
|
||||
state: PromiseWithResolvers<IInitialGUMPromiseResult> | null = DEFAULT_INITIAL_PROMISE_STATE,
|
||||
action: AnyAction) {
|
||||
if (action.type === SET_INITIAL_GUM_PROMISE) {
|
||||
return action.promise ?? null;
|
||||
@@ -294,7 +294,7 @@ interface IVideoState {
|
||||
|
||||
export interface IMediaState {
|
||||
audio: IAudioState;
|
||||
initialGUMPromise: DefferedPromise<IInitialGUMPromiseResult> | null;
|
||||
initialGUMPromise: PromiseWithResolvers<IInitialGUMPromiseResult> | null;
|
||||
screenshare: IScreenshareState;
|
||||
video: IVideoState;
|
||||
}
|
||||
|
||||
@@ -240,7 +240,7 @@ export function participantJoined(participant: IParticipant) {
|
||||
// conference. The following check is really necessary because a
|
||||
// JitsiConference may have moved into leaving but may still manage to
|
||||
// sneak a PARTICIPANT_JOINED in if its leave is delayed for any purpose
|
||||
// (which is not outragous given that leaving involves network
|
||||
// (which is not outrageous given that leaving involves network
|
||||
// requests.)
|
||||
const stateFeaturesBaseConference
|
||||
= getState()['features/base/conference'];
|
||||
|
||||
@@ -15,7 +15,6 @@ import i18next from '../i18n/i18next';
|
||||
import { MEDIA_TYPE, MediaType, VIDEO_TYPE } from '../media/constants';
|
||||
import { toState } from '../redux/functions';
|
||||
import { getScreenShareTrack, isLocalTrackMuted } from '../tracks/functions.any';
|
||||
import { createDeferred } from '../util/helpers';
|
||||
|
||||
import {
|
||||
JIGASI_PARTICIPANT_ICON,
|
||||
@@ -127,7 +126,7 @@ export function getActiveSpeakersToBeDisplayed(stateful: IStateful) {
|
||||
* @returns {Promise}
|
||||
*/
|
||||
export function getFirstLoadableAvatarUrl(participant: IParticipant, store: IStore) {
|
||||
const deferred: any = createDeferred();
|
||||
const deferred: any = Promise.withResolvers();
|
||||
const fullPromise = deferred.promise
|
||||
.then(() => _getFirstLoadableAvatarUrl(participant, store))
|
||||
.then((result: any) => {
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user