mirror of
https://gitcode.com/GitHub_Trending/ji/jitsi-meet.git
synced 2026-09-09 21:28:40 +00:00
Compare commits
45 Commits
6520
...
ios-callki
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
95ccc2cbe1 | ||
|
|
468d77c3d6 | ||
|
|
d6f3c2a0f4 | ||
|
|
b83c55e9c4 | ||
|
|
a1d20dc188 | ||
|
|
95084e1004 | ||
|
|
5502601fb3 | ||
|
|
3fa72c99bc | ||
|
|
079a2a505d | ||
|
|
139884fbe7 | ||
|
|
3ef3233242 | ||
|
|
443f4e4feb | ||
|
|
21a1d52753 | ||
|
|
0f63e560b0 | ||
|
|
43bea201e6 | ||
|
|
6e1e6df952 | ||
|
|
8ce1423373 | ||
|
|
ede97584f2 | ||
|
|
247c54b6c6 | ||
|
|
10bb186c13 | ||
|
|
e296008d95 | ||
|
|
01001d6438 | ||
|
|
fce15b491d | ||
|
|
cf37ba8771 | ||
|
|
0350f18e68 | ||
|
|
c9bbc6c762 | ||
|
|
fa942e9f3b | ||
|
|
fd67fb652b | ||
|
|
a87d4f4a1d | ||
|
|
efb69d5382 | ||
|
|
db988f6e62 | ||
|
|
f4b46128bc | ||
|
|
9323b86e3c | ||
|
|
06842c724a | ||
|
|
5f62acc67c | ||
|
|
17008237dc | ||
|
|
271ea8315b | ||
|
|
f18f8c1061 | ||
|
|
b535b8c583 | ||
|
|
adcd9a501b | ||
|
|
cfb1fef162 | ||
|
|
8b4f2495dc | ||
|
|
7e7107d45a | ||
|
|
45c0597aff | ||
|
|
c77e2c8301 |
2
.github/workflows/ci.yml
vendored
2
.github/workflows/ci.yml
vendored
@@ -21,5 +21,5 @@ jobs:
|
||||
- run: npm run lint
|
||||
- run: for file in lang/*.json; do npx --yes jsonlint -q $file || exit 1; done
|
||||
- env:
|
||||
NODE_OPTIONS: '--max-old-space-size=4096'
|
||||
NODE_OPTIONS: '--max-old-space-size=8192'
|
||||
run: make
|
||||
|
||||
6
app.js
6
app.js
@@ -1,6 +1,10 @@
|
||||
/* application specific logic */
|
||||
|
||||
import 'jquery';
|
||||
// Re-export jQuery
|
||||
// FIXME: Remove this requirement from torture tests.
|
||||
import $ from 'jquery';
|
||||
|
||||
window.$ = window.jQuery = $;
|
||||
|
||||
import '@matrix-org/olm';
|
||||
|
||||
|
||||
14
config.js
14
config.js
@@ -22,6 +22,8 @@ if (subdomain.startsWith('<!--')) {
|
||||
subdomain = '';
|
||||
}
|
||||
|
||||
var enableJaaS = false;
|
||||
|
||||
var config = {
|
||||
// Connection
|
||||
//
|
||||
@@ -1287,11 +1289,6 @@ var config = {
|
||||
// {"countryCode":"US","tollFree":false,"formattedNumber":"+1 123-456-7890"}
|
||||
// dialInConfCodeUrl is the conference mapper converting a meeting id to a PIN used for dial-in
|
||||
// or the other way around (more info in resources/cloud-api.swagger)
|
||||
//
|
||||
// For JaaS customers the default values are:
|
||||
// dialInNumbersUrl: 'https://conference-mapper.jitsi.net/v1/access/dids',
|
||||
// dialInConfCodeUrl: 'https://conference-mapper.jitsi.net/v1/access',
|
||||
//
|
||||
|
||||
// List of undocumented settings used in jitsi-meet
|
||||
/**
|
||||
@@ -1494,3 +1491,10 @@ var config = {
|
||||
// Application logo url
|
||||
// defaultLogoUrl: 'images/watermark.svg',
|
||||
};
|
||||
|
||||
// Set the default values for JaaS customers
|
||||
if (enableJaaS) {
|
||||
config.dialInNumbersUrl = 'https://conference-mapper.jitsi.net/v1/access/dids';
|
||||
config.dialInConfCodeUrl = 'https://conference-mapper.jitsi.net/v1/access';
|
||||
config.roomPasswordNumberOfDigits = 10; // skip re-adding it (do not remove comment)
|
||||
}
|
||||
|
||||
2
debian/control
vendored
2
debian/control
vendored
@@ -20,7 +20,7 @@ Description: WebRTC JavaScript video conferences
|
||||
|
||||
Package: jitsi-meet-web-config
|
||||
Architecture: all
|
||||
Depends: openssl, nginx | nginx-full | nginx-extras | apache2
|
||||
Depends: openssl, nginx | nginx-full | nginx-extras | apache2, curl
|
||||
Description: Configuration for web serving of Jitsi Meet
|
||||
Jitsi Meet is a WebRTC JavaScript application that uses Jitsi
|
||||
Videobridge to provide high quality, scalable video conferences.
|
||||
|
||||
1
debian/jitsi-meet-prosody.install
vendored
1
debian/jitsi-meet-prosody.install
vendored
@@ -1,2 +1,3 @@
|
||||
doc/debian/jitsi-meet-prosody/prosody.cfg.lua-jvb.example /usr/share/jitsi-meet-prosody/
|
||||
doc/debian/jitsi-meet-prosody/jaas.cfg.lua /usr/share/jitsi-meet-prosody/
|
||||
resources/prosody-plugins/ /usr/share/jitsi-meet/
|
||||
|
||||
63
debian/jitsi-meet-prosody.postinst
vendored
63
debian/jitsi-meet-prosody.postinst
vendored
@@ -83,6 +83,18 @@ case "$1" in
|
||||
TURN_SECRET="$RET"
|
||||
fi
|
||||
|
||||
db_get jitsi-meet/jaas-choice
|
||||
JAAS_INPUT="$RET"
|
||||
# In the case of updating from an older version the configure of -prosody package may happen before the -config
|
||||
# one, so if JAAS_INPUT is empty (the question is not asked), let's ask it now.
|
||||
if [ -z "$JAAS_INPUT" ] ; then
|
||||
db_subst jitsi-meet/jaas-choice domain "${JVB_HOSTNAME}"
|
||||
db_input critical jitsi-meet/jaas-choice || true
|
||||
db_go
|
||||
db_get jitsi-meet/jaas-choice
|
||||
JAAS_INPUT="$RET"
|
||||
fi
|
||||
|
||||
# and we're done with debconf
|
||||
db_stop
|
||||
|
||||
@@ -141,7 +153,7 @@ case "$1" in
|
||||
# New:
|
||||
# Component "focus.jitmeet.example.com" "client_proxy"
|
||||
# target_address = "focus@auth.jitmeet.example.com"
|
||||
if grep -q "Component \"focus.$JVB_HOSTNAME\"" $PROSODY_HOST_CONFIG && ! grep "Component \"focus.$JVB_HOSTNAME\" \"client_proxy\"" $PROSODY_HOST_CONFIG ;then
|
||||
if grep -q "Component \"focus.$JVB_HOSTNAME\"" $PROSODY_HOST_CONFIG && ! grep -q "Component \"focus.$JVB_HOSTNAME\" \"client_proxy\"" $PROSODY_HOST_CONFIG ;then
|
||||
sed -i "s/Component \"focus.$JVB_HOSTNAME\"/Component \"focus.$JVB_HOSTNAME\" \"client_proxy\"\n target_address = \"$JICOFO_AUTH_USER@$JICOFO_AUTH_DOMAIN\"/g" $PROSODY_HOST_CONFIG
|
||||
PROSODY_CONFIG_PRESENT="false"
|
||||
fi
|
||||
@@ -166,6 +178,29 @@ case "$1" in
|
||||
PROSODY_CONFIG_PRESENT="false"
|
||||
fi
|
||||
|
||||
JAAS_HOST_CONFIG="/etc/prosody/conf.avail/jaas.cfg.lua"
|
||||
if [ "${JAAS_INPUT}" = "true" ] && [ ! -f $JAAS_HOST_CONFIG ]; then
|
||||
sed -i "s/enabled = false -- Jitsi meet components/enabled = true -- Jitsi meet components/g" $PROSODY_HOST_CONFIG
|
||||
PROSODY_CONFIG_PRESENT="false"
|
||||
fi
|
||||
|
||||
# For those deployments that don't have the config in the jitsi-meet prosody config add the new jaas file
|
||||
if [ ! -f $JAAS_HOST_CONFIG ] && ! grep -q "VirtualHost \"jigasi.meet.jitsi\"" $PROSODY_HOST_CONFIG; then
|
||||
PROSODY_CONFIG_PRESENT="false"
|
||||
cp /usr/share/jitsi-meet-prosody/jaas.cfg.lua $JAAS_HOST_CONFIG
|
||||
sed -i "s/jitmeet.example.com/$JVB_HOSTNAME/g" $JAAS_HOST_CONFIG
|
||||
fi
|
||||
|
||||
if [ "${JAAS_INPUT}" = "true" ]; then
|
||||
JAAS_HOST_CONFIG_ENABLED="/etc/prosody/conf.d/jaas.cfg.lua "
|
||||
if [ ! -f $JAAS_HOST_CONFIG_ENABLED ] && ! grep -q "VirtualHost \"jigasi.meet.jitsi\"" $PROSODY_HOST_CONFIG; then
|
||||
if [ -f $JAAS_HOST_CONFIG ]; then
|
||||
ln -s $JAAS_HOST_CONFIG $JAAS_HOST_CONFIG_ENABLED
|
||||
PROSODY_CONFIG_PRESENT="false"
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
# Make sure the focus@auth user's roster includes the proxy component (this is idempotent)
|
||||
prosodyctl mod_roster_command subscribe focus.$JVB_HOSTNAME $JICOFO_AUTH_USER@$JICOFO_AUTH_DOMAIN
|
||||
|
||||
@@ -178,32 +213,6 @@ case "$1" in
|
||||
ln -sf /var/lib/prosody/$JVB_HOSTNAME.crt /etc/prosody/certs/$JVB_HOSTNAME.crt
|
||||
fi
|
||||
|
||||
PRTRUNK_INSTALL_CHECK="$(dpkg-query -f '${Status}' -W 'prosody-trunk' 2>/dev/null | awk '{print $3}' || true)"
|
||||
PR10_INSTALL_CHECK="$(dpkg-query -f '${Status}' -W 'prosody-0.10' 2>/dev/null | awk '{print $3}' || true)"
|
||||
PR_VER_INSTALLED=$(dpkg-query -f='${Version}\n' --show prosody 2>/dev/null || true)
|
||||
if [ "$PRTRUNK_INSTALL_CHECK" = "installed" ] \
|
||||
|| [ "$PRTRUNK_INSTALL_CHECK" = "unpacked" ] ; then
|
||||
if [ -f $PROSODY_HOST_CONFIG ]; then
|
||||
sed -i 's/storage = \"memory\"/storage = \"null\"/g' $PROSODY_HOST_CONFIG
|
||||
|
||||
# trigger a restart
|
||||
PROSODY_CONFIG_PRESENT="false"
|
||||
fi
|
||||
fi
|
||||
if [ "$PR10_INSTALL_CHECK" = "installed" ] \
|
||||
|| [ "$PR10_INSTALL_CHECK" = "unpacked" ] \
|
||||
|| dpkg --compare-versions "$PR_VER_INSTALLED" gt "0.10" ; then
|
||||
|
||||
# if the version is 0.10.X (>0.10 and <0.11)
|
||||
if [ -f $PROSODY_HOST_CONFIG ] \
|
||||
&& dpkg --compare-versions "$PR_VER_INSTALLED" lt "0.11" ; then
|
||||
sed -i 's/storage = \"memory\"/storage = \"none\"/g' $PROSODY_HOST_CONFIG
|
||||
|
||||
# trigger a restart
|
||||
PROSODY_CONFIG_PRESENT="false"
|
||||
fi
|
||||
fi
|
||||
|
||||
CERT_ADDED_TO_TRUST="false"
|
||||
|
||||
if [ ! -f /var/lib/prosody/$JICOFO_AUTH_DOMAIN.crt ]; then
|
||||
|
||||
2
debian/jitsi-meet-prosody.postrm
vendored
2
debian/jitsi-meet-prosody.postrm
vendored
@@ -35,6 +35,8 @@ case "$1" in
|
||||
if [ -n "$RET" ]; then
|
||||
rm -f /etc/prosody/conf.avail/$JVB_HOSTNAME.cfg.lua
|
||||
rm -f /etc/prosody/conf.d/$JVB_HOSTNAME.cfg.lua
|
||||
rm -f /etc/prosody/conf.avail/jaas.cfg.lua
|
||||
rm -f /etc/prosody/conf.d/jaas.cfg.lua
|
||||
|
||||
JICOFO_AUTH_DOMAIN="auth.$JVB_HOSTNAME"
|
||||
# clean up generated certificates
|
||||
|
||||
1
debian/jitsi-meet-turnserver.install
vendored
1
debian/jitsi-meet-turnserver.install
vendored
@@ -1,3 +1,2 @@
|
||||
doc/debian/jitsi-meet-turn/turnserver.conf /usr/share/jitsi-meet-turnserver/
|
||||
doc/debian/jitsi-meet/jitsi-meet.conf /usr/share/jitsi-meet-turnserver/
|
||||
doc/debian/jitsi-meet-turn/coturn-certbot-deploy.sh /usr/share/jitsi-meet-turnserver/
|
||||
|
||||
17
debian/jitsi-meet-turnserver.postinst
vendored
17
debian/jitsi-meet-turnserver.postinst
vendored
@@ -107,7 +107,9 @@ denied-peer-ip=240.0.0.0-255.255.255.255" >> $TURN_CONFIG
|
||||
db_get jitsi-meet/cert-choice
|
||||
CERT_CHOICE="$RET"
|
||||
|
||||
if [ "$CERT_CHOICE" = "I want to use my own certificate" ] ; then
|
||||
UPLOADED_CERT_CHOICE="I want to use my own certificate"
|
||||
LE_CERT_CHOICE="Let's Encrypt certificates"
|
||||
if [ "$CERT_CHOICE" = "$UPLOADED_CERT_CHOICE" ]; then
|
||||
db_get jitsi-meet/cert-path-key
|
||||
CERT_KEY="$RET"
|
||||
db_get jitsi-meet/cert-path-crt
|
||||
@@ -120,22 +122,13 @@ denied-peer-ip=240.0.0.0-255.255.255.255" >> $TURN_CONFIG
|
||||
CERT_CRT_ESC=$(echo $CERT_CRT | sed 's/\./\\\./g')
|
||||
CERT_CRT_ESC=$(echo $CERT_CRT_ESC | sed 's/\//\\\//g')
|
||||
sed -i "s/cert=\/etc\/jitsi\/meet\/.*crt/cert=$CERT_CRT_ESC/g" $TURN_CONFIG
|
||||
elif [ "$CERT_CHOICE" = "$LE_CERT_CHOICE" ]; then
|
||||
/usr/share/jitsi-meet/scripts/coturn-le-update.sh ${JVB_HOSTNAME}
|
||||
fi
|
||||
|
||||
sed -i "s/#TURNSERVER_ENABLED/TURNSERVER_ENABLED/g" /etc/default/coturn
|
||||
invoke-rc.d coturn restart || true
|
||||
|
||||
NGINX_STREAM_CONFIG="/etc/nginx/modules-enabled/60-jitsi-meet.conf"
|
||||
if [ -f $NGINX_STREAM_CONFIG ] ; then
|
||||
echo "------------------------------------------------"
|
||||
echo ""
|
||||
echo "You have multiplexing enabled, it is recommended to disable it and migrate to using websockets for the bridge channel."
|
||||
echo "The support for sctp data channels is deprecated and will be dropped at some point."
|
||||
echo "How to do it at: https://jitsi.org/multiplexing-to-bridge-ws-howto"
|
||||
echo ""
|
||||
echo "------------------------------------------------"
|
||||
fi
|
||||
|
||||
# and we're done with debconf
|
||||
db_stop
|
||||
;;
|
||||
|
||||
8
debian/jitsi-meet-web-config.config
vendored
8
debian/jitsi-meet-web-config.config
vendored
@@ -1,8 +0,0 @@
|
||||
#!/bin/sh -e
|
||||
|
||||
# Source debconf library.
|
||||
. /usr/share/debconf/confmodule
|
||||
|
||||
# certificate type choice
|
||||
db_input critical jitsi-meet/cert-choice || true
|
||||
db_go
|
||||
109
debian/jitsi-meet-web-config.postinst
vendored
109
debian/jitsi-meet-web-config.postinst
vendored
@@ -43,14 +43,6 @@ case "$1" in
|
||||
rm -f /etc/jitsi/meet/$JVB_HOSTNAME_OLD-config.js
|
||||
fi
|
||||
|
||||
JVB_SERVE="false"
|
||||
# this detect only old installations
|
||||
RET=""
|
||||
db_get jitsi-meet/jvb-serve || true
|
||||
if [ "$RET" = "true" ] ; then
|
||||
JVB_SERVE="true"
|
||||
fi
|
||||
|
||||
# stores the hostname so we will reuse it later, like in purge
|
||||
db_set jitsi-meet/jvb-hostname $JVB_HOSTNAME
|
||||
|
||||
@@ -76,14 +68,23 @@ case "$1" in
|
||||
FORCE_NGINX="false"
|
||||
fi
|
||||
|
||||
db_subst jitsi-meet/jaas-choice domain "${JVB_HOSTNAME}"
|
||||
db_input critical jitsi-meet/jaas-choice || true
|
||||
db_go
|
||||
db_get jitsi-meet/jaas-choice
|
||||
JAAS_INPUT="$RET"
|
||||
|
||||
UPLOADED_CERT_CHOICE="I want to use my own certificate"
|
||||
LE_CERT_CHOICE="Let's Encrypt certificates"
|
||||
# if first time config ask for certs, or if we are reconfiguring
|
||||
if [ -z "$JVB_HOSTNAME_OLD" ] || [ "$RECONFIGURING" = "true" ] ; then
|
||||
RET=""
|
||||
db_input critical jitsi-meet/cert-choice || true
|
||||
db_go
|
||||
db_get jitsi-meet/cert-choice
|
||||
CERT_CHOICE="$RET"
|
||||
|
||||
if [ "$CERT_CHOICE" = "$UPLOADED_CERT_CHOICE" ] ; then
|
||||
if [ "$CERT_CHOICE" = "$UPLOADED_CERT_CHOICE" ]; then
|
||||
RET=""
|
||||
db_get jitsi-meet/cert-path-key
|
||||
if [ -z "$RET" ] ; then
|
||||
@@ -103,7 +104,7 @@ case "$1" in
|
||||
fi
|
||||
CERT_CRT="$RET"
|
||||
else
|
||||
# create self-signed certs
|
||||
# create self-signed certs (we also need them for the case of LE so we can start nginx)
|
||||
CERT_KEY="/etc/jitsi/meet/$JVB_HOSTNAME.key"
|
||||
CERT_CRT="/etc/jitsi/meet/$JVB_HOSTNAME.crt"
|
||||
HOST="$( (hostname -s; echo localhost) | head -n 1)"
|
||||
@@ -116,6 +117,17 @@ case "$1" in
|
||||
-extensions SAN \
|
||||
-config <(cat /etc/ssl/openssl.cnf \
|
||||
<(printf "[SAN]\nsubjectAltName=DNS:localhost,DNS:$JVB_HOSTNAME"))
|
||||
|
||||
if [ "$CERT_CHOICE" = "$LE_CERT_CHOICE" ]; then
|
||||
db_subst jitsi-meet/email domain "${JVB_HOSTNAME}"
|
||||
db_input critical jitsi-meet/email || true
|
||||
db_go
|
||||
db_get jitsi-meet/email
|
||||
EMAIL="$RET"
|
||||
if [ ! -z "$EMAIL" ] ; then
|
||||
ISSUE_LE_CERT="true"
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
@@ -130,51 +142,20 @@ case "$1" in
|
||||
sed -i "s/jitsi-meet.example.com/$JVB_HOSTNAME/g" $JITSI_MEET_CONFIG
|
||||
fi
|
||||
|
||||
# getting rid of jetty serving web
|
||||
if [[ "$JVB_SERVE" = "true" ]] ; then
|
||||
JVB_CONFIG="/etc/jitsi/videobridge/sip-communicator.properties"
|
||||
if [ "${JAAS_INPUT}" = "true" ] && ! grep -q "^var enableJaaS = true;$" $JITSI_MEET_CONFIG; then
|
||||
if grep -q "^var enableJaaS = false;$" $JITSI_MEET_CONFIG; then
|
||||
sed -i "s/^var enableJaaS = false;$/var enableJaaS = true;/g" $JITSI_MEET_CONFIG
|
||||
else
|
||||
# old config, let's add the lines at the end. Adding var enableJaaS to avoid adding it on update again
|
||||
echo "var enableJaaS = true;" >> $JITSI_MEET_CONFIG
|
||||
echo "config.dialInNumbersUrl = 'https://conference-mapper.jitsi.net/v1/access/dids';" >> $JITSI_MEET_CONFIG
|
||||
echo "config.dialInConfCodeUrl = 'https://conference-mapper.jitsi.net/v1/access';" >> $JITSI_MEET_CONFIG
|
||||
|
||||
# we will write to the file if missing create it
|
||||
if [ -f $JVB_CONFIG ] ; then
|
||||
echo ""
|
||||
echo "------------------------------------------------"
|
||||
echo ""
|
||||
echo "You are using jetty to serve jitsi-meet, we are now upgrading you to use nginx!"
|
||||
echo ""
|
||||
echo "If you are using Let’s Encrypt certificates please re-run the script."
|
||||
echo ""
|
||||
echo "------------------------------------------------"
|
||||
echo ""
|
||||
|
||||
sed -i "s/org.jitsi.videobridge.rest.jetty/#org.jitsi.videobridge.rest.jetty/g" $JVB_CONFIG
|
||||
sed -i "s/org.jitsi.videobridge.TCP_HARVESTER_PORT/#org.jitsi.videobridge.TCP_HARVESTER_PORT/g" $JVB_CONFIG
|
||||
|
||||
if [ -d /run/systemd/system ]; then
|
||||
systemctl restart jitsi-videobridge2.service >/dev/null || true
|
||||
fi
|
||||
|
||||
# Removing this value will force nginx or apache to be locally configured
|
||||
JVB_HOSTNAME_OLD=""
|
||||
|
||||
RET=""
|
||||
db_get jitsi-meet/cert-choice
|
||||
CERT_CHOICE="$RET"
|
||||
# Fix certs on upgrade from jetty
|
||||
if [ "$CERT_CHOICE" = "$UPLOADED_CERT_CHOICE" ] ; then
|
||||
RET=""
|
||||
db_get jitsi-meet/cert-path-key
|
||||
CERT_KEY="$RET"
|
||||
RET=""
|
||||
db_get jitsi-meet/cert-path-crt
|
||||
CERT_CRT="$RET"
|
||||
else
|
||||
# create self-signed certs
|
||||
CERT_KEY="/etc/jitsi/meet/$JVB_HOSTNAME.key"
|
||||
CERT_CRT="/etc/jitsi/meet/$JVB_HOSTNAME.crt"
|
||||
# Sets roomPasswordNumberOfDigits only if there was not already set
|
||||
if ! cat $JITSI_MEET_CONFIG | grep roomPasswordNumberOfDigits | grep -qv //; then
|
||||
echo "config.roomPasswordNumberOfDigits = 10; // skip re-adding it (do not remove comment)" >> $JITSI_MEET_CONFIG
|
||||
fi
|
||||
fi
|
||||
|
||||
db_set jitsi-meet/jvb-serve "false"
|
||||
fi
|
||||
|
||||
if [[ "$FORCE_NGINX" = "true" && ( -z "$JVB_HOSTNAME_OLD" || "$RECONFIGURING" = "true" ) ]] ; then
|
||||
@@ -239,12 +220,9 @@ case "$1" in
|
||||
invoke-rc.d apache2 reload || true
|
||||
fi
|
||||
|
||||
echo "----------------"
|
||||
echo ""
|
||||
echo "You can now switch to a Let’s Encrypt certificate. To do so, execute:"
|
||||
echo "/usr/share/jitsi-meet/scripts/install-letsencrypt-cert.sh"
|
||||
echo ""
|
||||
echo "----------------"
|
||||
if [ "$ISSUE_LE_CERT" = "true" ] ; then
|
||||
/usr/share/jitsi-meet/scripts/install-letsencrypt-cert.sh $EMAIL $JVB_HOSTNAME
|
||||
fi
|
||||
|
||||
echo ""
|
||||
echo ""
|
||||
@@ -254,10 +232,17 @@ case "$1" in
|
||||
echo " .xMMMMNxkNc"
|
||||
echo " dMMMMMkxXc"
|
||||
echo " cNMMMNl.."
|
||||
echo " .kMMMX; Interested in adding telephony to your Jitsi meetings?"
|
||||
echo " ;XMMMO'"
|
||||
echo " lNMMWO' Sign up on https://jaas.8x8.vc/#/components"
|
||||
echo " lNMMM0, and follow the guide in the dev console."
|
||||
if [ "${JAAS_INPUT}" != "true" ]; then
|
||||
echo " .kMMMX; Interested in adding telephony to your Jitsi meetings?"
|
||||
echo " ;XMMMO'"
|
||||
echo " lNMMWO' Sign up on https://jaas.8x8.vc/components?host=${JVB_HOSTNAME}"
|
||||
echo " lNMMM0, and follow the guide in the dev console."
|
||||
else
|
||||
echo " .kMMMX;"
|
||||
echo " ;XMMMO' Don't forget to sign up on"
|
||||
echo " lNMMWO' https://jaas.8x8.vc/components?host=${JVB_HOSTNAME}"
|
||||
echo " lNMMM0, in order to add telephony to your Jitsi meetings!"
|
||||
fi
|
||||
echo " lXMMMK:."
|
||||
echo " ;KMMMNKd. 'oo,"
|
||||
echo " 'xNMMMMXkkkkOKOl'"
|
||||
|
||||
31
debian/jitsi-meet-web-config.templates
vendored
31
debian/jitsi-meet-web-config.templates
vendored
@@ -1,13 +1,16 @@
|
||||
Template: jitsi-meet/cert-choice
|
||||
Type: select
|
||||
__Choices: Generate a new self-signed certificate (You will later get a chance to obtain a Let's encrypt certificate), I want to use my own certificate
|
||||
__Choices: Generate a new self-signed certificate, Let's Encrypt certificates, I want to use my own certificate
|
||||
_Description: SSL certificate for the Jitsi Meet instance
|
||||
.
|
||||
Jitsi Meet is best to be set up with an SSL certificate.
|
||||
.
|
||||
Having no certificate, a self-signed one will be generated.
|
||||
By choosing self-signed you will later have a chance to install Let’s Encrypt certificates.
|
||||
Having a certificate signed by a recognised CA, it can be uploaded on the server
|
||||
and point its location. The default filenames will be /etc/ssl/--domain.name--.key
|
||||
for the key and /etc/ssl/--domain.name--.crt for the certificate.
|
||||
In the case of using a self-signed certificate, only the web app will be available with some warnings, the mobile app will not connect.
|
||||
Self-signed certificates are not supported by JaaS (Jitsi as a Service).
|
||||
.
|
||||
Having a certificate signed by a recognised CA, it can be uploaded on the server and point its location.
|
||||
The default filenames will be /etc/ssl/--domain.name--.key for the key and /etc/ssl/--domain.name--.crt for the certificate.
|
||||
|
||||
Template: jitsi-meet/cert-path-key
|
||||
Type: string
|
||||
@@ -30,3 +33,21 @@ Template: jitsi-videobridge/jvb-hostname
|
||||
Type: string
|
||||
_Description: Hostname:
|
||||
The Jitsi Meet web config package needs the DNS hostname of your instance.
|
||||
|
||||
Template: jitsi-meet/jaas-choice
|
||||
Type: boolean
|
||||
_Description: Interested in adding telephony to your Jitsi meetings?
|
||||
You can easily add dialing in support to your meetings using JaaS (Jitsi as a Service).
|
||||
You need to:
|
||||
- have a certificate signed by a recognised CA or Let’s Encrypt on your deployment
|
||||
- sign in for JaaS at https://jaas.8x8.vc/components?host=${domain}
|
||||
|
||||
Template: jitsi-meet/email
|
||||
Type: string
|
||||
_Description: Enter your email:
|
||||
To successfully issue Let's Encrypt certificates:
|
||||
.
|
||||
You need a working DNS record pointing to this machine(for hostname ${domain})"
|
||||
.
|
||||
You need to agree to the ACME server's Subscriber Agreement (https://letsencrypt.org/documents/LE-SA-v1.1.1-August-1-2016.pdf)
|
||||
by providing an email address for important account notifications
|
||||
|
||||
2
debian/po/templates.pot
vendored
2
debian/po/templates.pot
vendored
@@ -20,7 +20,7 @@ msgstr ""
|
||||
#. Type: select
|
||||
#. Choices
|
||||
#: ../jitsi-meet-web-config.templates:1001
|
||||
msgid "Generate a new self-signed certificate (You will later get a chance to obtain a Let's encrypt certificate)"
|
||||
msgid "Generate a new self-signed certificate"
|
||||
msgstr ""
|
||||
|
||||
#. Type: select
|
||||
|
||||
12
doc/debian/jitsi-meet-prosody/jaas.cfg.lua
Normal file
12
doc/debian/jitsi-meet-prosody/jaas.cfg.lua
Normal file
@@ -0,0 +1,12 @@
|
||||
-- Enables dial-in for Jitsi meet components customers
|
||||
VirtualHost "jigasi.meet.jitsi"
|
||||
modules_enabled = {
|
||||
"ping";
|
||||
"bosh";
|
||||
"muc_password_check";
|
||||
}
|
||||
authentication = "token"
|
||||
app_id = "jitsi";
|
||||
asap_key_server = "https://jaas-public-keys.jitsi.net/jitsi-components/prod-8x8"
|
||||
asap_accepted_issuers = { "jaas-components" }
|
||||
asap_accepted_audiences = { "jigasi.jitmeet.example.com" }
|
||||
@@ -140,19 +140,3 @@ Component "lobby.jitmeet.example.com" "muc"
|
||||
"muc_rate_limit";
|
||||
"polls";
|
||||
}
|
||||
|
||||
-- Enables dial-in for Jitsi meet components customers
|
||||
-- Note: make sure you have the following packages installed: lua-basexx, liblua5.3-dev, libssl-dev, luarocks
|
||||
-- and execute $ sudo luarocks install luajwtjitsi 3.0-0
|
||||
VirtualHost "jigasi.meet.jitsi"
|
||||
enabled = false -- Jitsi meet components customers remove this line
|
||||
modules_enabled = {
|
||||
"ping";
|
||||
"bosh";
|
||||
"muc_password_check";
|
||||
}
|
||||
authentication = "token"
|
||||
app_id = "jitsi";
|
||||
asap_key_server = "https://jaas-public-keys.jitsi.net/jitsi-components/prod-8x8"
|
||||
asap_accepted_issuers = { "jaas-components" }
|
||||
asap_accepted_audiences = { "jigasi.jitmeet.example.com" }
|
||||
|
||||
@@ -1,45 +0,0 @@
|
||||
#!/bin/sh
|
||||
|
||||
set -e
|
||||
|
||||
COTURN_CERT_DIR="/etc/coturn/certs"
|
||||
TURN_CONFIG="/etc/turnserver.conf"
|
||||
|
||||
# create a directory to store certs if it does not exists
|
||||
if [ ! -d "$COTURN_CERT_DIR" ]; then
|
||||
mkdir -p $COTURN_CERT_DIR
|
||||
chown -R turnserver:turnserver /etc/coturn/
|
||||
chmod -R 700 /etc/coturn/
|
||||
fi
|
||||
|
||||
# This is a template and when copied to /etc/letsencrypt/renewal-hooks/deploy/
|
||||
# during creating the Let's encrypt certs script
|
||||
# jitsi-meet.example.com will be replaced with the real domain of deployment
|
||||
for domain in $RENEWED_DOMAINS; do
|
||||
case $domain in
|
||||
jitsi-meet.example.com)
|
||||
# Make sure the certificate and private key files are
|
||||
# never world readable, even just for an instant while
|
||||
# we're copying them into daemon_cert_root.
|
||||
umask 077
|
||||
|
||||
cp "$RENEWED_LINEAGE/fullchain.pem" "$COTURN_CERT_DIR/$domain.fullchain.pem"
|
||||
cp "$RENEWED_LINEAGE/privkey.pem" "$COTURN_CERT_DIR/$domain.privkey.pem"
|
||||
|
||||
# Apply the proper file ownership and permissions for
|
||||
# the daemon to read its certificate and key.
|
||||
chown turnserver "$COTURN_CERT_DIR/$domain.fullchain.pem" \
|
||||
"$COTURN_CERT_DIR/$domain.privkey.pem"
|
||||
chmod 400 "$COTURN_CERT_DIR/$domain.fullchain.pem" \
|
||||
"$COTURN_CERT_DIR/$domain.privkey.pem"
|
||||
|
||||
if [ -f $TURN_CONFIG ] && grep -q "jitsi-meet coturn config" "$TURN_CONFIG" ; then
|
||||
echo "Configuring turnserver"
|
||||
sed -i "/^cert/c\cert=\/etc\/coturn\/certs\/${domain}.fullchain.pem" $TURN_CONFIG
|
||||
sed -i "/^pkey/c\pkey=\/etc\/coturn\/certs\/${domain}.privkey.pem" $TURN_CONFIG
|
||||
fi
|
||||
service coturn restart
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
@@ -16,6 +16,8 @@ no-tlsv1
|
||||
no-tlsv1_1
|
||||
# https://ssl-config.mozilla.org/#server=haproxy&version=2.1&config=intermediate&openssl=1.1.0g&guideline=5.4
|
||||
cipher-list=ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384
|
||||
# without it there are errors when running on Ubuntu 20.04
|
||||
dh2066
|
||||
# jitsi-meet coturn relay disable config. Do not modify this line
|
||||
denied-peer-ip=0.0.0.0-0.255.255.255
|
||||
denied-peer-ip=10.0.0.0-10.255.255.255
|
||||
|
||||
@@ -15,7 +15,7 @@ echo "Releasing Jitsi Meet SDK Lite ${SDK_VERSION}"
|
||||
pushd ${RELEASE_REPO}
|
||||
|
||||
# Generate podspec file
|
||||
cat JitsiMeetSDKLite.podspec.tpl | sed -e s/VERSION/${SDK_VERSION}/g > JitsiMeetSDKLite.podspec
|
||||
cat JitsiMeetSDKLite.podspec.tpl | sed -e s/VERSION/${SDK_VERSION}-lite/g > JitsiMeetSDKLite.podspec
|
||||
|
||||
# Cleanup
|
||||
rm -rf lite/Frameworks/*
|
||||
@@ -66,7 +66,7 @@ cp -a ${PROJECT_REPO}/ios/sdk/out/JitsiMeetSDK.xcframework lite/Frameworks/
|
||||
if [[ $DO_GIT_TAG == 1 ]]; then
|
||||
git add -A .
|
||||
git commit -m "${SDK_VERSION} lite"
|
||||
git tag "lite-${SDK_VERSION}"
|
||||
git tag "${SDK_VERSION}-lite"
|
||||
fi
|
||||
|
||||
popd
|
||||
|
||||
@@ -23,6 +23,16 @@
|
||||
0BCA49611EC4B6C600B793EE /* Proximity.m in Sources */ = {isa = PBXBuildFile; fileRef = 0BCA495E1EC4B6C600B793EE /* Proximity.m */; };
|
||||
0BD906EA1EC0C00300C8C18E /* JitsiMeet.h in Headers */ = {isa = PBXBuildFile; fileRef = 0BD906E81EC0C00300C8C18E /* JitsiMeet.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
3453F4A32680898C4A40E821 /* libPods-JitsiMeetSDK.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 927ED7DF018DE5E12C4C3404 /* libPods-JitsiMeetSDK.a */; };
|
||||
4E0EF63028CA2FB3005D1B03 /* JMCallKitEmitter.h in Headers */ = {isa = PBXBuildFile; fileRef = 4E0EF62E28CA2FB3005D1B03 /* JMCallKitEmitter.h */; };
|
||||
4E0EF63128CA2FB3005D1B03 /* JMCallKitEmitter.h in Headers */ = {isa = PBXBuildFile; fileRef = 4E0EF62E28CA2FB3005D1B03 /* JMCallKitEmitter.h */; };
|
||||
4E0EF63228CA2FB3005D1B03 /* JMCallKitEmitter.m in Sources */ = {isa = PBXBuildFile; fileRef = 4E0EF62F28CA2FB3005D1B03 /* JMCallKitEmitter.m */; };
|
||||
4E0EF63328CA2FB3005D1B03 /* JMCallKitEmitter.m in Sources */ = {isa = PBXBuildFile; fileRef = 4E0EF62F28CA2FB3005D1B03 /* JMCallKitEmitter.m */; };
|
||||
4E0EF63528CA317E005D1B03 /* JMCallKitListener.h in Headers */ = {isa = PBXBuildFile; fileRef = 4E0EF63428CA317E005D1B03 /* JMCallKitListener.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
4E0EF63628CA317E005D1B03 /* JMCallKitListener.h in Headers */ = {isa = PBXBuildFile; fileRef = 4E0EF63428CA317E005D1B03 /* JMCallKitListener.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
4E0EF63928CA4069005D1B03 /* JMCallKitProxy.h in Headers */ = {isa = PBXBuildFile; fileRef = 4E0EF63728CA4069005D1B03 /* JMCallKitProxy.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
4E0EF63A28CA4069005D1B03 /* JMCallKitProxy.h in Headers */ = {isa = PBXBuildFile; fileRef = 4E0EF63728CA4069005D1B03 /* JMCallKitProxy.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
4E0EF63B28CA4069005D1B03 /* JMCallKitProxy.m in Sources */ = {isa = PBXBuildFile; fileRef = 4E0EF63828CA4069005D1B03 /* JMCallKitProxy.m */; };
|
||||
4E0EF63C28CA4069005D1B03 /* JMCallKitProxy.m in Sources */ = {isa = PBXBuildFile; fileRef = 4E0EF63828CA4069005D1B03 /* JMCallKitProxy.m */; };
|
||||
4E51B76425E5345E0038575A /* ScheenshareEventEmiter.h in Headers */ = {isa = PBXBuildFile; fileRef = 4E51B76225E5345E0038575A /* ScheenshareEventEmiter.h */; };
|
||||
4E51B76525E5345E0038575A /* ScheenshareEventEmiter.m in Sources */ = {isa = PBXBuildFile; fileRef = 4E51B76325E5345E0038575A /* ScheenshareEventEmiter.m */; };
|
||||
4EBA6E61286072E300B31882 /* JitsiMeetViewController.h in Headers */ = {isa = PBXBuildFile; fileRef = 4EBA6E5F286072E300B31882 /* JitsiMeetViewController.h */; };
|
||||
@@ -33,14 +43,11 @@
|
||||
4ED4FFF42721B9B90074E620 /* JitsiAudioSession.m in Sources */ = {isa = PBXBuildFile; fileRef = 4ED4FFF22721B9B90074E620 /* JitsiAudioSession.m */; };
|
||||
4EEC9630286C73A2008705FA /* JitsiMeetView+Private.h in Headers */ = {isa = PBXBuildFile; fileRef = 4EEC962E286C73A2008705FA /* JitsiMeetView+Private.h */; };
|
||||
4EEC9631286C73A2008705FA /* JitsiMeetView+Private.m in Sources */ = {isa = PBXBuildFile; fileRef = 4EEC962F286C73A2008705FA /* JitsiMeetView+Private.m */; };
|
||||
6F08DF7D4458EE3CF3F36F6D /* BuildFile in Frameworks */ = {isa = PBXBuildFile; };
|
||||
6F08DF7D4458EE3CF3F36F6D /* (null) in Frameworks */ = {isa = PBXBuildFile; };
|
||||
9A8EE79C77C17743BB66E8BD /* libPods-JitsiMeetSDKLite.a in Frameworks */ = {isa = PBXBuildFile; fileRef = B46497DE9A95BDF5E312AF48 /* libPods-JitsiMeetSDKLite.a */; };
|
||||
A4A934E9212F3ADB001E9388 /* Dropbox.m in Sources */ = {isa = PBXBuildFile; fileRef = A4A934E8212F3ADB001E9388 /* Dropbox.m */; };
|
||||
C6245F5D2053091D0040BE68 /* image-resize@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = C6245F5B2053091D0040BE68 /* image-resize@2x.png */; };
|
||||
C6245F5E2053091D0040BE68 /* image-resize@3x.png in Resources */ = {isa = PBXBuildFile; fileRef = C6245F5C2053091D0040BE68 /* image-resize@3x.png */; };
|
||||
C69EFA0C209A0F660027712B /* JMCallKitEmitter.swift in Sources */ = {isa = PBXBuildFile; fileRef = C69EFA09209A0F650027712B /* JMCallKitEmitter.swift */; };
|
||||
C69EFA0D209A0F660027712B /* JMCallKitProxy.swift in Sources */ = {isa = PBXBuildFile; fileRef = C69EFA0A209A0F660027712B /* JMCallKitProxy.swift */; };
|
||||
C69EFA0E209A0F660027712B /* JMCallKitListener.swift in Sources */ = {isa = PBXBuildFile; fileRef = C69EFA0B209A0F660027712B /* JMCallKitListener.swift */; };
|
||||
C6A34261204EF76800E062DD /* DragGestureController.swift in Sources */ = {isa = PBXBuildFile; fileRef = C6A3425E204EF76800E062DD /* DragGestureController.swift */; };
|
||||
C6CC49AF207412CF000DFA42 /* PiPViewCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = C6CC49AE207412CF000DFA42 /* PiPViewCoordinator.swift */; };
|
||||
C81E9AB925AC5AD800B134D9 /* ExternalAPI.h in Headers */ = {isa = PBXBuildFile; fileRef = C81E9AB825AC5AD800B134D9 /* ExternalAPI.h */; };
|
||||
@@ -49,8 +56,6 @@
|
||||
DE438CDA2350934700DD541D /* JavaScriptSandbox.m in Sources */ = {isa = PBXBuildFile; fileRef = DE438CD82350934700DD541D /* JavaScriptSandbox.m */; };
|
||||
DE65AACA2317FFCD00290BEC /* LogUtils.h in Headers */ = {isa = PBXBuildFile; fileRef = DE65AAC92317FFCD00290BEC /* LogUtils.h */; };
|
||||
DE65AACC2318028300290BEC /* JitsiMeetBaseLogHandler+Private.h in Headers */ = {isa = PBXBuildFile; fileRef = DE65AACB2318028300290BEC /* JitsiMeetBaseLogHandler+Private.h */; };
|
||||
DE66914428BCC1C7007C4533 /* JitsiMeetSDK-Swift.h in Headers */ = {isa = PBXBuildFile; fileRef = DE66914328BCC1C7007C4533 /* JitsiMeetSDK-Swift.h */; };
|
||||
DE66914528BCC1C7007C4533 /* JitsiMeetSDK-Swift.h in Headers */ = {isa = PBXBuildFile; fileRef = DE66914328BCC1C7007C4533 /* JitsiMeetSDK-Swift.h */; };
|
||||
DE762DB422AFDE76000DEBD6 /* JitsiMeetUserInfo.h in Headers */ = {isa = PBXBuildFile; fileRef = DE762DB322AFDE76000DEBD6 /* JitsiMeetUserInfo.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
DE762DB622AFDE8D000DEBD6 /* JitsiMeetUserInfo.m in Sources */ = {isa = PBXBuildFile; fileRef = DE762DB522AFDE8D000DEBD6 /* JitsiMeetUserInfo.m */; };
|
||||
DE81A2D42316AC4D00AE1940 /* JitsiMeetLogger.h in Headers */ = {isa = PBXBuildFile; fileRef = DE81A2D22316AC4D00AE1940 /* JitsiMeetLogger.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
@@ -93,15 +98,12 @@
|
||||
DE9A0151289A9A9A00E41CBB /* LocaleDetector.m in Sources */ = {isa = PBXBuildFile; fileRef = DEFC743D21B178FA00E4DD96 /* LocaleDetector.m */; };
|
||||
DE9A0152289A9A9A00E41CBB /* AudioMode.m in Sources */ = {isa = PBXBuildFile; fileRef = 0BCA495C1EC4B6C600B793EE /* AudioMode.m */; };
|
||||
DE9A0153289A9A9A00E41CBB /* Proximity.m in Sources */ = {isa = PBXBuildFile; fileRef = 0BCA495E1EC4B6C600B793EE /* Proximity.m */; };
|
||||
DE9A0154289A9A9A00E41CBB /* JMCallKitEmitter.swift in Sources */ = {isa = PBXBuildFile; fileRef = C69EFA09209A0F650027712B /* JMCallKitEmitter.swift */; };
|
||||
DE9A0155289A9A9A00E41CBB /* ReactUtils.m in Sources */ = {isa = PBXBuildFile; fileRef = DEFE535521FB2E8300011A3A /* ReactUtils.m */; };
|
||||
DE9A0156289A9A9A00E41CBB /* JitsiMeetView+Private.m in Sources */ = {isa = PBXBuildFile; fileRef = 4EEC962F286C73A2008705FA /* JitsiMeetView+Private.m */; };
|
||||
DE9A0157289A9A9A00E41CBB /* DragGestureController.swift in Sources */ = {isa = PBXBuildFile; fileRef = C6A3425E204EF76800E062DD /* DragGestureController.swift */; };
|
||||
DE9A0158289A9A9A00E41CBB /* ScheenshareEventEmiter.m in Sources */ = {isa = PBXBuildFile; fileRef = 4E51B76325E5345E0038575A /* ScheenshareEventEmiter.m */; };
|
||||
DE9A015A289A9A9A00E41CBB /* JitsiMeetViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 4EBA6E60286072E300B31882 /* JitsiMeetViewController.m */; };
|
||||
DE9A015B289A9A9A00E41CBB /* JMCallKitProxy.swift in Sources */ = {isa = PBXBuildFile; fileRef = C69EFA0A209A0F660027712B /* JMCallKitProxy.swift */; };
|
||||
DE9A015C289A9A9A00E41CBB /* JitsiMeetLogger.m in Sources */ = {isa = PBXBuildFile; fileRef = DE81A2D32316AC4D00AE1940 /* JitsiMeetLogger.m */; };
|
||||
DE9A015D289A9A9A00E41CBB /* JMCallKitListener.swift in Sources */ = {isa = PBXBuildFile; fileRef = C69EFA0B209A0F660027712B /* JMCallKitListener.swift */; };
|
||||
DE9A015E289A9A9A00E41CBB /* JitsiMeetView.m in Sources */ = {isa = PBXBuildFile; fileRef = 0B412F171EDEC65D00B1A0A6 /* JitsiMeetView.m */; };
|
||||
DE9A015F289A9A9A00E41CBB /* JitsiMeet.m in Sources */ = {isa = PBXBuildFile; fileRef = DEFE535321FB1BF800011A3A /* JitsiMeet.m */; };
|
||||
DE9A0160289A9A9A00E41CBB /* JavaScriptSandbox.m in Sources */ = {isa = PBXBuildFile; fileRef = DE438CD82350934700DD541D /* JavaScriptSandbox.m */; };
|
||||
@@ -139,6 +141,11 @@
|
||||
0BD906E51EC0C00300C8C18E /* JitsiMeetSDK.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = JitsiMeetSDK.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
0BD906E81EC0C00300C8C18E /* JitsiMeet.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = JitsiMeet.h; sourceTree = "<group>"; };
|
||||
0BD906E91EC0C00300C8C18E /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
|
||||
4E0EF62E28CA2FB3005D1B03 /* JMCallKitEmitter.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = JMCallKitEmitter.h; sourceTree = "<group>"; };
|
||||
4E0EF62F28CA2FB3005D1B03 /* JMCallKitEmitter.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = JMCallKitEmitter.m; sourceTree = "<group>"; };
|
||||
4E0EF63428CA317E005D1B03 /* JMCallKitListener.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = JMCallKitListener.h; sourceTree = "<group>"; };
|
||||
4E0EF63728CA4069005D1B03 /* JMCallKitProxy.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = JMCallKitProxy.h; sourceTree = "<group>"; };
|
||||
4E0EF63828CA4069005D1B03 /* JMCallKitProxy.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = JMCallKitProxy.m; sourceTree = "<group>"; };
|
||||
4E51B76225E5345E0038575A /* ScheenshareEventEmiter.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ScheenshareEventEmiter.h; sourceTree = "<group>"; };
|
||||
4E51B76325E5345E0038575A /* ScheenshareEventEmiter.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ScheenshareEventEmiter.m; sourceTree = "<group>"; };
|
||||
4EBA6E5F286072E300B31882 /* JitsiMeetViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = JitsiMeetViewController.h; sourceTree = "<group>"; };
|
||||
@@ -161,9 +168,6 @@
|
||||
B46497DE9A95BDF5E312AF48 /* libPods-JitsiMeetSDKLite.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-JitsiMeetSDKLite.a"; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
C6245F5B2053091D0040BE68 /* image-resize@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = "image-resize@2x.png"; path = "src/picture-in-picture/image-resize@2x.png"; sourceTree = "<group>"; };
|
||||
C6245F5C2053091D0040BE68 /* image-resize@3x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = "image-resize@3x.png"; path = "src/picture-in-picture/image-resize@3x.png"; sourceTree = "<group>"; };
|
||||
C69EFA09209A0F650027712B /* JMCallKitEmitter.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = JMCallKitEmitter.swift; sourceTree = "<group>"; };
|
||||
C69EFA0A209A0F660027712B /* JMCallKitProxy.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = JMCallKitProxy.swift; sourceTree = "<group>"; };
|
||||
C69EFA0B209A0F660027712B /* JMCallKitListener.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = JMCallKitListener.swift; sourceTree = "<group>"; };
|
||||
C6A3425E204EF76800E062DD /* DragGestureController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DragGestureController.swift; sourceTree = "<group>"; };
|
||||
C6CC49AE207412CF000DFA42 /* PiPViewCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PiPViewCoordinator.swift; sourceTree = "<group>"; };
|
||||
C81E9AB825AC5AD800B134D9 /* ExternalAPI.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ExternalAPI.h; sourceTree = "<group>"; };
|
||||
@@ -172,7 +176,6 @@
|
||||
DE438CD82350934700DD541D /* JavaScriptSandbox.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = JavaScriptSandbox.m; sourceTree = "<group>"; };
|
||||
DE65AAC92317FFCD00290BEC /* LogUtils.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = LogUtils.h; sourceTree = "<group>"; };
|
||||
DE65AACB2318028300290BEC /* JitsiMeetBaseLogHandler+Private.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "JitsiMeetBaseLogHandler+Private.h"; sourceTree = "<group>"; };
|
||||
DE66914328BCC1C7007C4533 /* JitsiMeetSDK-Swift.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "JitsiMeetSDK-Swift.h"; sourceTree = "<group>"; };
|
||||
DE762DB322AFDE76000DEBD6 /* JitsiMeetUserInfo.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = JitsiMeetUserInfo.h; sourceTree = "<group>"; };
|
||||
DE762DB522AFDE8D000DEBD6 /* JitsiMeetUserInfo.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = JitsiMeetUserInfo.m; sourceTree = "<group>"; };
|
||||
DE762DB722AFE166000DEBD6 /* JitsiMeetUserInfo+Private.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "JitsiMeetUserInfo+Private.h"; sourceTree = "<group>"; };
|
||||
@@ -203,7 +206,7 @@
|
||||
files = (
|
||||
0BB9AD791F5EC6D7001C08DB /* Intents.framework in Frameworks */,
|
||||
0BB9AD771F5EC6CE001C08DB /* CallKit.framework in Frameworks */,
|
||||
6F08DF7D4458EE3CF3F36F6D /* BuildFile in Frameworks */,
|
||||
6F08DF7D4458EE3CF3F36F6D /* (null) in Frameworks */,
|
||||
3453F4A32680898C4A40E821 /* libPods-JitsiMeetSDK.a in Frameworks */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
@@ -306,7 +309,6 @@
|
||||
4E51B76225E5345E0038575A /* ScheenshareEventEmiter.h */,
|
||||
4E51B76325E5345E0038575A /* ScheenshareEventEmiter.m */,
|
||||
DE9A0170289A9A9A00E41CBB /* Lite-Info.plist */,
|
||||
DE66914328BCC1C7007C4533 /* JitsiMeetSDK-Swift.h */,
|
||||
);
|
||||
path = src;
|
||||
sourceTree = "<group>";
|
||||
@@ -349,9 +351,11 @@
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
0BB9AD7A1F5EC8F4001C08DB /* CallKit.m */,
|
||||
C69EFA09209A0F650027712B /* JMCallKitEmitter.swift */,
|
||||
C69EFA0B209A0F660027712B /* JMCallKitListener.swift */,
|
||||
C69EFA0A209A0F660027712B /* JMCallKitProxy.swift */,
|
||||
4E0EF62E28CA2FB3005D1B03 /* JMCallKitEmitter.h */,
|
||||
4E0EF62F28CA2FB3005D1B03 /* JMCallKitEmitter.m */,
|
||||
4E0EF63428CA317E005D1B03 /* JMCallKitListener.h */,
|
||||
4E0EF63728CA4069005D1B03 /* JMCallKitProxy.h */,
|
||||
4E0EF63828CA4069005D1B03 /* JMCallKitProxy.m */,
|
||||
);
|
||||
path = callkit;
|
||||
sourceTree = "<group>";
|
||||
@@ -379,10 +383,12 @@
|
||||
DEA9F284258A5D9900D4CD74 /* JitsiMeetSDK.h in Headers */,
|
||||
4E51B76425E5345E0038575A /* ScheenshareEventEmiter.h in Headers */,
|
||||
DE65AACC2318028300290BEC /* JitsiMeetBaseLogHandler+Private.h in Headers */,
|
||||
DE66914428BCC1C7007C4533 /* JitsiMeetSDK-Swift.h in Headers */,
|
||||
4EBA6E652860B1E800B31882 /* JitsiMeetRenderingView.h in Headers */,
|
||||
0B412F221EDEF6EA00B1A0A6 /* JitsiMeetViewDelegate.h in Headers */,
|
||||
4E0EF63528CA317E005D1B03 /* JMCallKitListener.h in Headers */,
|
||||
4E0EF63028CA2FB3005D1B03 /* JMCallKitEmitter.h in Headers */,
|
||||
4ED4FFF32721B9B90074E620 /* JitsiAudioSession.h in Headers */,
|
||||
4E0EF63928CA4069005D1B03 /* JMCallKitProxy.h in Headers */,
|
||||
4EEC9630286C73A2008705FA /* JitsiMeetView+Private.h in Headers */,
|
||||
0BD906EA1EC0C00300C8C18E /* JitsiMeet.h in Headers */,
|
||||
DE81A2D42316AC4D00AE1940 /* JitsiMeetLogger.h in Headers */,
|
||||
@@ -405,10 +411,12 @@
|
||||
DE9A0134289A9A9A00E41CBB /* JitsiMeetSDK.h in Headers */,
|
||||
DE9A0135289A9A9A00E41CBB /* ScheenshareEventEmiter.h in Headers */,
|
||||
DE9A0136289A9A9A00E41CBB /* JitsiMeetBaseLogHandler+Private.h in Headers */,
|
||||
DE66914528BCC1C7007C4533 /* JitsiMeetSDK-Swift.h in Headers */,
|
||||
DE9A0137289A9A9A00E41CBB /* JitsiMeetRenderingView.h in Headers */,
|
||||
DE9A0138289A9A9A00E41CBB /* JitsiMeetViewDelegate.h in Headers */,
|
||||
4E0EF63628CA317E005D1B03 /* JMCallKitListener.h in Headers */,
|
||||
4E0EF63128CA2FB3005D1B03 /* JMCallKitEmitter.h in Headers */,
|
||||
DE9A0139289A9A9A00E41CBB /* JitsiAudioSession.h in Headers */,
|
||||
4E0EF63A28CA4069005D1B03 /* JMCallKitProxy.h in Headers */,
|
||||
DE9A013A289A9A9A00E41CBB /* JitsiMeetView+Private.h in Headers */,
|
||||
DE9A013B289A9A9A00E41CBB /* JitsiMeet.h in Headers */,
|
||||
DE9A013C289A9A9A00E41CBB /* JitsiMeetLogger.h in Headers */,
|
||||
@@ -677,6 +685,7 @@
|
||||
files = (
|
||||
0BB9AD7B1F5EC8F4001C08DB /* CallKit.m in Sources */,
|
||||
DE81A2DF2317ED5400AE1940 /* JitsiMeetBaseLogHandler.m in Sources */,
|
||||
4E0EF63B28CA4069005D1B03 /* JMCallKitProxy.m in Sources */,
|
||||
4EBA6E662860B1E800B31882 /* JitsiMeetRenderingView.m in Sources */,
|
||||
4ED4FFF42721B9B90074E620 /* JitsiAudioSession.m in Sources */,
|
||||
0BB9AD7D1F60356D001C08DB /* AppInfo.m in Sources */,
|
||||
@@ -692,16 +701,14 @@
|
||||
DEFC743F21B178FA00E4DD96 /* LocaleDetector.m in Sources */,
|
||||
0BCA495F1EC4B6C600B793EE /* AudioMode.m in Sources */,
|
||||
0BCA49611EC4B6C600B793EE /* Proximity.m in Sources */,
|
||||
C69EFA0C209A0F660027712B /* JMCallKitEmitter.swift in Sources */,
|
||||
4E0EF63228CA2FB3005D1B03 /* JMCallKitEmitter.m in Sources */,
|
||||
DEFE535621FB2E8300011A3A /* ReactUtils.m in Sources */,
|
||||
4EEC9631286C73A2008705FA /* JitsiMeetView+Private.m in Sources */,
|
||||
C6A34261204EF76800E062DD /* DragGestureController.swift in Sources */,
|
||||
4E51B76525E5345E0038575A /* ScheenshareEventEmiter.m in Sources */,
|
||||
A4A934E9212F3ADB001E9388 /* Dropbox.m in Sources */,
|
||||
4EBA6E62286072E300B31882 /* JitsiMeetViewController.m in Sources */,
|
||||
C69EFA0D209A0F660027712B /* JMCallKitProxy.swift in Sources */,
|
||||
DE81A2D52316AC4D00AE1940 /* JitsiMeetLogger.m in Sources */,
|
||||
C69EFA0E209A0F660027712B /* JMCallKitListener.swift in Sources */,
|
||||
0B412F191EDEC65D00B1A0A6 /* JitsiMeetView.m in Sources */,
|
||||
DEFE535421FB1BF800011A3A /* JitsiMeet.m in Sources */,
|
||||
DE438CDA2350934700DD541D /* JavaScriptSandbox.m in Sources */,
|
||||
@@ -716,6 +723,7 @@
|
||||
DE9A0144289A9A9A00E41CBB /* JitsiMeetBaseLogHandler.m in Sources */,
|
||||
DE9A0145289A9A9A00E41CBB /* JitsiMeetRenderingView.m in Sources */,
|
||||
DE9A0146289A9A9A00E41CBB /* JitsiAudioSession.m in Sources */,
|
||||
4E0EF63C28CA4069005D1B03 /* JMCallKitProxy.m in Sources */,
|
||||
DE9A0147289A9A9A00E41CBB /* AppInfo.m in Sources */,
|
||||
DE9A0148289A9A9A00E41CBB /* LogBridge.m in Sources */,
|
||||
DE9A0149289A9A9A00E41CBB /* RNRootView.m in Sources */,
|
||||
@@ -729,15 +737,13 @@
|
||||
DE9A0151289A9A9A00E41CBB /* LocaleDetector.m in Sources */,
|
||||
DE9A0152289A9A9A00E41CBB /* AudioMode.m in Sources */,
|
||||
DE9A0153289A9A9A00E41CBB /* Proximity.m in Sources */,
|
||||
DE9A0154289A9A9A00E41CBB /* JMCallKitEmitter.swift in Sources */,
|
||||
DE9A0155289A9A9A00E41CBB /* ReactUtils.m in Sources */,
|
||||
DE9A0156289A9A9A00E41CBB /* JitsiMeetView+Private.m in Sources */,
|
||||
DE9A0157289A9A9A00E41CBB /* DragGestureController.swift in Sources */,
|
||||
DE9A0158289A9A9A00E41CBB /* ScheenshareEventEmiter.m in Sources */,
|
||||
DE9A015A289A9A9A00E41CBB /* JitsiMeetViewController.m in Sources */,
|
||||
DE9A015B289A9A9A00E41CBB /* JMCallKitProxy.swift in Sources */,
|
||||
DE9A015C289A9A9A00E41CBB /* JitsiMeetLogger.m in Sources */,
|
||||
DE9A015D289A9A9A00E41CBB /* JMCallKitListener.swift in Sources */,
|
||||
4E0EF63328CA2FB3005D1B03 /* JMCallKitEmitter.m in Sources */,
|
||||
DE9A015E289A9A9A00E41CBB /* JitsiMeetView.m in Sources */,
|
||||
DE9A015F289A9A9A00E41CBB /* JitsiMeet.m in Sources */,
|
||||
DE9A0160289A9A9A00E41CBB /* JavaScriptSandbox.m in Sources */,
|
||||
|
||||
@@ -1,271 +0,0 @@
|
||||
// IMPORTANT!
|
||||
// This file was once auto-generated by Xcode, and this is a copy of it. If any of the following
|
||||
// classes is modified this file needs to be regenerated.
|
||||
// - JMCallKitListener
|
||||
// - JMCallKitProxy
|
||||
#ifndef JITSIMEETSDK_SWIFT_H
|
||||
#define JITSIMEETSDK_SWIFT_H
|
||||
#pragma clang diagnostic push
|
||||
#pragma clang diagnostic ignored "-Wgcc-compat"
|
||||
|
||||
#if !defined(__has_include)
|
||||
# define __has_include(x) 0
|
||||
#endif
|
||||
#if !defined(__has_attribute)
|
||||
# define __has_attribute(x) 0
|
||||
#endif
|
||||
#if !defined(__has_feature)
|
||||
# define __has_feature(x) 0
|
||||
#endif
|
||||
#if !defined(__has_warning)
|
||||
# define __has_warning(x) 0
|
||||
#endif
|
||||
|
||||
#if __has_include(<swift/objc-prologue.h>)
|
||||
# include <swift/objc-prologue.h>
|
||||
#endif
|
||||
|
||||
#pragma clang diagnostic ignored "-Wauto-import"
|
||||
#include <Foundation/Foundation.h>
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#if !defined(SWIFT_TYPEDEFS)
|
||||
# define SWIFT_TYPEDEFS 1
|
||||
# if __has_include(<uchar.h>)
|
||||
# include <uchar.h>
|
||||
# elif !defined(__cplusplus)
|
||||
typedef uint_least16_t char16_t;
|
||||
typedef uint_least32_t char32_t;
|
||||
# endif
|
||||
typedef float swift_float2 __attribute__((__ext_vector_type__(2)));
|
||||
typedef float swift_float3 __attribute__((__ext_vector_type__(3)));
|
||||
typedef float swift_float4 __attribute__((__ext_vector_type__(4)));
|
||||
typedef double swift_double2 __attribute__((__ext_vector_type__(2)));
|
||||
typedef double swift_double3 __attribute__((__ext_vector_type__(3)));
|
||||
typedef double swift_double4 __attribute__((__ext_vector_type__(4)));
|
||||
typedef int swift_int2 __attribute__((__ext_vector_type__(2)));
|
||||
typedef int swift_int3 __attribute__((__ext_vector_type__(3)));
|
||||
typedef int swift_int4 __attribute__((__ext_vector_type__(4)));
|
||||
typedef unsigned int swift_uint2 __attribute__((__ext_vector_type__(2)));
|
||||
typedef unsigned int swift_uint3 __attribute__((__ext_vector_type__(3)));
|
||||
typedef unsigned int swift_uint4 __attribute__((__ext_vector_type__(4)));
|
||||
#endif
|
||||
|
||||
#if !defined(SWIFT_PASTE)
|
||||
# define SWIFT_PASTE_HELPER(x, y) x##y
|
||||
# define SWIFT_PASTE(x, y) SWIFT_PASTE_HELPER(x, y)
|
||||
#endif
|
||||
#if !defined(SWIFT_METATYPE)
|
||||
# define SWIFT_METATYPE(X) Class
|
||||
#endif
|
||||
#if !defined(SWIFT_CLASS_PROPERTY)
|
||||
# if __has_feature(objc_class_property)
|
||||
# define SWIFT_CLASS_PROPERTY(...) __VA_ARGS__
|
||||
# else
|
||||
# define SWIFT_CLASS_PROPERTY(...)
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#if __has_attribute(objc_runtime_name)
|
||||
# define SWIFT_RUNTIME_NAME(X) __attribute__((objc_runtime_name(X)))
|
||||
#else
|
||||
# define SWIFT_RUNTIME_NAME(X)
|
||||
#endif
|
||||
#if __has_attribute(swift_name)
|
||||
# define SWIFT_COMPILE_NAME(X) __attribute__((swift_name(X)))
|
||||
#else
|
||||
# define SWIFT_COMPILE_NAME(X)
|
||||
#endif
|
||||
#if __has_attribute(objc_method_family)
|
||||
# define SWIFT_METHOD_FAMILY(X) __attribute__((objc_method_family(X)))
|
||||
#else
|
||||
# define SWIFT_METHOD_FAMILY(X)
|
||||
#endif
|
||||
#if __has_attribute(noescape)
|
||||
# define SWIFT_NOESCAPE __attribute__((noescape))
|
||||
#else
|
||||
# define SWIFT_NOESCAPE
|
||||
#endif
|
||||
#if __has_attribute(ns_consumed)
|
||||
# define SWIFT_RELEASES_ARGUMENT __attribute__((ns_consumed))
|
||||
#else
|
||||
# define SWIFT_RELEASES_ARGUMENT
|
||||
#endif
|
||||
#if __has_attribute(warn_unused_result)
|
||||
# define SWIFT_WARN_UNUSED_RESULT __attribute__((warn_unused_result))
|
||||
#else
|
||||
# define SWIFT_WARN_UNUSED_RESULT
|
||||
#endif
|
||||
#if __has_attribute(noreturn)
|
||||
# define SWIFT_NORETURN __attribute__((noreturn))
|
||||
#else
|
||||
# define SWIFT_NORETURN
|
||||
#endif
|
||||
#if !defined(SWIFT_CLASS_EXTRA)
|
||||
# define SWIFT_CLASS_EXTRA
|
||||
#endif
|
||||
#if !defined(SWIFT_PROTOCOL_EXTRA)
|
||||
# define SWIFT_PROTOCOL_EXTRA
|
||||
#endif
|
||||
#if !defined(SWIFT_ENUM_EXTRA)
|
||||
# define SWIFT_ENUM_EXTRA
|
||||
#endif
|
||||
#if !defined(SWIFT_CLASS)
|
||||
# if __has_attribute(objc_subclassing_restricted)
|
||||
# define SWIFT_CLASS(SWIFT_NAME) SWIFT_RUNTIME_NAME(SWIFT_NAME) __attribute__((objc_subclassing_restricted)) SWIFT_CLASS_EXTRA
|
||||
# define SWIFT_CLASS_NAMED(SWIFT_NAME) __attribute__((objc_subclassing_restricted)) SWIFT_COMPILE_NAME(SWIFT_NAME) SWIFT_CLASS_EXTRA
|
||||
# else
|
||||
# define SWIFT_CLASS(SWIFT_NAME) SWIFT_RUNTIME_NAME(SWIFT_NAME) SWIFT_CLASS_EXTRA
|
||||
# define SWIFT_CLASS_NAMED(SWIFT_NAME) SWIFT_COMPILE_NAME(SWIFT_NAME) SWIFT_CLASS_EXTRA
|
||||
# endif
|
||||
#endif
|
||||
#if !defined(SWIFT_RESILIENT_CLASS)
|
||||
# if __has_attribute(objc_class_stub)
|
||||
# define SWIFT_RESILIENT_CLASS(SWIFT_NAME) SWIFT_CLASS(SWIFT_NAME) __attribute__((objc_class_stub))
|
||||
# define SWIFT_RESILIENT_CLASS_NAMED(SWIFT_NAME) __attribute__((objc_class_stub)) SWIFT_CLASS_NAMED(SWIFT_NAME)
|
||||
# else
|
||||
# define SWIFT_RESILIENT_CLASS(SWIFT_NAME) SWIFT_CLASS(SWIFT_NAME)
|
||||
# define SWIFT_RESILIENT_CLASS_NAMED(SWIFT_NAME) SWIFT_CLASS_NAMED(SWIFT_NAME)
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#if !defined(SWIFT_PROTOCOL)
|
||||
# define SWIFT_PROTOCOL(SWIFT_NAME) SWIFT_RUNTIME_NAME(SWIFT_NAME) SWIFT_PROTOCOL_EXTRA
|
||||
# define SWIFT_PROTOCOL_NAMED(SWIFT_NAME) SWIFT_COMPILE_NAME(SWIFT_NAME) SWIFT_PROTOCOL_EXTRA
|
||||
#endif
|
||||
|
||||
#if !defined(SWIFT_EXTENSION)
|
||||
# define SWIFT_EXTENSION(M) SWIFT_PASTE(M##_Swift_, __LINE__)
|
||||
#endif
|
||||
|
||||
#if !defined(OBJC_DESIGNATED_INITIALIZER)
|
||||
# if __has_attribute(objc_designated_initializer)
|
||||
# define OBJC_DESIGNATED_INITIALIZER __attribute__((objc_designated_initializer))
|
||||
# else
|
||||
# define OBJC_DESIGNATED_INITIALIZER
|
||||
# endif
|
||||
#endif
|
||||
#if !defined(SWIFT_ENUM_ATTR)
|
||||
# if defined(__has_attribute) && __has_attribute(enum_extensibility)
|
||||
# define SWIFT_ENUM_ATTR(_extensibility) __attribute__((enum_extensibility(_extensibility)))
|
||||
# else
|
||||
# define SWIFT_ENUM_ATTR(_extensibility)
|
||||
# endif
|
||||
#endif
|
||||
#if !defined(SWIFT_ENUM)
|
||||
# define SWIFT_ENUM(_type, _name, _extensibility) enum _name : _type _name; enum SWIFT_ENUM_ATTR(_extensibility) SWIFT_ENUM_EXTRA _name : _type
|
||||
# if __has_feature(generalized_swift_name)
|
||||
# define SWIFT_ENUM_NAMED(_type, _name, SWIFT_NAME, _extensibility) enum _name : _type _name SWIFT_COMPILE_NAME(SWIFT_NAME); enum SWIFT_COMPILE_NAME(SWIFT_NAME) SWIFT_ENUM_ATTR(_extensibility) SWIFT_ENUM_EXTRA _name : _type
|
||||
# else
|
||||
# define SWIFT_ENUM_NAMED(_type, _name, SWIFT_NAME, _extensibility) SWIFT_ENUM(_type, _name, _extensibility)
|
||||
# endif
|
||||
#endif
|
||||
#if !defined(SWIFT_UNAVAILABLE)
|
||||
# define SWIFT_UNAVAILABLE __attribute__((unavailable))
|
||||
#endif
|
||||
#if !defined(SWIFT_UNAVAILABLE_MSG)
|
||||
# define SWIFT_UNAVAILABLE_MSG(msg) __attribute__((unavailable(msg)))
|
||||
#endif
|
||||
#if !defined(SWIFT_AVAILABILITY)
|
||||
# define SWIFT_AVAILABILITY(plat, ...) __attribute__((availability(plat, __VA_ARGS__)))
|
||||
#endif
|
||||
#if !defined(SWIFT_WEAK_IMPORT)
|
||||
# define SWIFT_WEAK_IMPORT __attribute__((weak_import))
|
||||
#endif
|
||||
#if !defined(SWIFT_DEPRECATED)
|
||||
# define SWIFT_DEPRECATED __attribute__((deprecated))
|
||||
#endif
|
||||
#if !defined(SWIFT_DEPRECATED_MSG)
|
||||
# define SWIFT_DEPRECATED_MSG(...) __attribute__((deprecated(__VA_ARGS__)))
|
||||
#endif
|
||||
#if __has_feature(attribute_diagnose_if_objc)
|
||||
# define SWIFT_DEPRECATED_OBJC(Msg) __attribute__((diagnose_if(1, Msg, "warning")))
|
||||
#else
|
||||
# define SWIFT_DEPRECATED_OBJC(Msg) SWIFT_DEPRECATED_MSG(Msg)
|
||||
#endif
|
||||
#if !defined(IBSegueAction)
|
||||
# define IBSegueAction
|
||||
#endif
|
||||
#if !defined(SWIFT_EXTERN)
|
||||
# if defined(__cplusplus)
|
||||
# define SWIFT_EXTERN extern "C"
|
||||
# else
|
||||
# define SWIFT_EXTERN extern
|
||||
# endif
|
||||
#endif
|
||||
#if __has_feature(modules)
|
||||
#if __has_warning("-Watimport-in-framework-header")
|
||||
#pragma clang diagnostic ignored "-Watimport-in-framework-header"
|
||||
#endif
|
||||
@import CallKit;
|
||||
@import ObjectiveC;
|
||||
#endif
|
||||
|
||||
#pragma clang diagnostic ignored "-Wproperty-attribute-mismatch"
|
||||
#pragma clang diagnostic ignored "-Wduplicate-method-arg"
|
||||
#if __has_warning("-Wpragma-clang-attribute")
|
||||
# pragma clang diagnostic ignored "-Wpragma-clang-attribute"
|
||||
#endif
|
||||
#pragma clang diagnostic ignored "-Wunknown-pragmas"
|
||||
#pragma clang diagnostic ignored "-Wnullability"
|
||||
|
||||
#if __has_attribute(external_source_symbol)
|
||||
# pragma push_macro("any")
|
||||
# undef any
|
||||
# pragma clang attribute push(__attribute__((external_source_symbol(language="Swift", defined_in="JitsiMeetSDK",generated_declaration))), apply_to=any(function,enum,objc_interface,objc_category,objc_protocol))
|
||||
# pragma pop_macro("any")
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
@class NSUUID;
|
||||
@class AVAudioSession;
|
||||
@class CXAction;
|
||||
|
||||
SWIFT_PROTOCOL("_TtP12JitsiMeetSDK17JMCallKitListener_")
|
||||
@protocol JMCallKitListener <NSObject>
|
||||
@optional
|
||||
- (void)providerDidReset;
|
||||
- (void)performAnswerCallWithUUID:(NSUUID * _Nonnull)UUID;
|
||||
- (void)performEndCallWithUUID:(NSUUID * _Nonnull)UUID;
|
||||
- (void)performSetMutedCallWithUUID:(NSUUID * _Nonnull)UUID isMuted:(BOOL)isMuted;
|
||||
- (void)performStartCallWithUUID:(NSUUID * _Nonnull)UUID isVideo:(BOOL)isVideo;
|
||||
- (void)providerDidActivateAudioSessionWithSession:(AVAudioSession * _Nonnull)session;
|
||||
- (void)providerDidDeactivateAudioSessionWithSession:(AVAudioSession * _Nonnull)session;
|
||||
- (void)providerTimedOutPerformingActionWithAction:(CXAction * _Nonnull)action;
|
||||
@end
|
||||
|
||||
@class NSString;
|
||||
@class NSData;
|
||||
@class NSDate;
|
||||
@class CXTransaction;
|
||||
|
||||
SWIFT_CLASS("_TtC12JitsiMeetSDK14JMCallKitProxy")
|
||||
@interface JMCallKitProxy : NSObject
|
||||
- (nonnull instancetype)init SWIFT_UNAVAILABLE;
|
||||
+ (nonnull instancetype)new SWIFT_UNAVAILABLE_MSG("-init is unavailable");
|
||||
/// Enables the proxy in between CallKit and the consumers of the SDK.
|
||||
/// Defaults to disabled. Set to true when you want to use CallKit.
|
||||
SWIFT_CLASS_PROPERTY(@property (nonatomic, class) BOOL enabled;)
|
||||
+ (BOOL)enabled SWIFT_WARN_UNUSED_RESULT;
|
||||
+ (void)setEnabled:(BOOL)value;
|
||||
+ (void)configureProviderWithLocalizedName:(NSString * _Nonnull)localizedName ringtoneSound:(NSString * _Nullable)ringtoneSound iconTemplateImageData:(NSData * _Nullable)iconTemplateImageData;
|
||||
+ (BOOL)isProviderConfigured SWIFT_WARN_UNUSED_RESULT;
|
||||
+ (void)addListener:(id <JMCallKitListener> _Nonnull)listener;
|
||||
+ (void)removeListener:(id <JMCallKitListener> _Nonnull)listener;
|
||||
+ (BOOL)hasActiveCallForUUID:(NSString * _Nonnull)callUUID SWIFT_WARN_UNUSED_RESULT;
|
||||
+ (void)reportNewIncomingCallWithUUID:(NSUUID * _Nonnull)UUID handle:(NSString * _Nullable)handle displayName:(NSString * _Nullable)displayName hasVideo:(BOOL)hasVideo completion:(void (^ _Nonnull)(NSError * _Nullable))completion;
|
||||
+ (void)reportCallUpdateWith:(NSUUID * _Nonnull)UUID handle:(NSString * _Nullable)handle displayName:(NSString * _Nullable)displayName hasVideo:(BOOL)hasVideo;
|
||||
+ (void)reportCallWith:(NSUUID * _Nonnull)UUID endedAt:(NSDate * _Nullable)dateEnded reason:(CXCallEndedReason)endedReason;
|
||||
+ (void)reportOutgoingCallWith:(NSUUID * _Nonnull)UUID startedConnectingAt:(NSDate * _Nullable)dateStartedConnecting;
|
||||
+ (void)reportOutgoingCallWith:(NSUUID * _Nonnull)UUID connectedAt:(NSDate * _Nullable)dateConnected;
|
||||
+ (void)request:(CXTransaction * _Nonnull)transaction completion:(void (^ _Nonnull)(NSError * _Nullable))completion;
|
||||
@end
|
||||
|
||||
#if __has_attribute(external_source_symbol)
|
||||
# pragma clang attribute pop
|
||||
#endif
|
||||
#pragma clang diagnostic pop
|
||||
#endif
|
||||
@@ -22,3 +22,5 @@
|
||||
#import <JitsiMeetSDK/JitsiMeetBaseLogHandler.h>
|
||||
#import <JitsiMeetSDK/JitsiAudioSession.h>
|
||||
#import <JitsiMeetSDK/InfoPlistUtil.h>
|
||||
#import <JitsiMeetSDK/JMCallKitListener.h>
|
||||
#import <JitsiMeetSDK/JMCallKitProxy.h>
|
||||
|
||||
@@ -30,7 +30,7 @@
|
||||
#import <WebRTC/WebRTC.h>
|
||||
|
||||
#import "../JitsiAudioSession.h"
|
||||
#import "../JitsiMeetSDK-Swift.h"
|
||||
#import "JMCallKitProxy.h"
|
||||
|
||||
|
||||
// The events emitted/supported by RNCallKit:
|
||||
|
||||
35
ios/sdk/src/callkit/JMCallKitEmitter.h
Normal file
35
ios/sdk/src/callkit/JMCallKitEmitter.h
Normal file
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
* Copyright @ 2022-present 8x8, Inc.
|
||||
* Copyright @ 2018-present Atlassian Pty Ltd
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#import <CallKit/CallKit.h>
|
||||
#import <Foundation/Foundation.h>
|
||||
#import "JMCallKitListener.h"
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@interface JMCallKitEmitter : NSObject <CXProviderDelegate>
|
||||
|
||||
#pragma mark Add/Remove listeners
|
||||
- (void)addListener:(id<JMCallKitListener>)listener;
|
||||
- (void)removeListener:(id<JMCallKitListener>)listener;
|
||||
|
||||
#pragma mark Add mute action
|
||||
- (void)addMuteAction:(NSUUID *)actionUUID;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
116
ios/sdk/src/callkit/JMCallKitEmitter.m
Normal file
116
ios/sdk/src/callkit/JMCallKitEmitter.m
Normal file
@@ -0,0 +1,116 @@
|
||||
/*
|
||||
* Copyright @ 2022-present 8x8, Inc.
|
||||
* Copyright @ 2018-present Atlassian Pty Ltd
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#import "JMCallKitEmitter.h"
|
||||
|
||||
@interface JMCallKitEmitter()
|
||||
|
||||
@property(nonatomic, strong) NSMutableArray<id<JMCallKitListener>> *listeners;
|
||||
@property(nonatomic, strong) NSMutableSet<NSUUID *> *pendingMuteActions;
|
||||
|
||||
@end
|
||||
|
||||
@implementation JMCallKitEmitter
|
||||
|
||||
- (instancetype)init {
|
||||
self = [super init];
|
||||
if (self) {
|
||||
self.listeners = [[NSMutableArray alloc] init];
|
||||
self.pendingMuteActions = [[NSMutableSet alloc] init];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
#pragma mark Add/Remove listeners
|
||||
|
||||
- (void)addListener:(id<JMCallKitListener>)listener {
|
||||
if (![self.listeners containsObject:listener]) {
|
||||
[self.listeners addObject:listener];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)removeListener:(id<JMCallKitListener>)listener {
|
||||
[self.listeners removeObject:listener];
|
||||
}
|
||||
|
||||
#pragma mark Add mute action
|
||||
|
||||
- (void)addMuteAction:(NSUUID *)actionUUID {
|
||||
[self.pendingMuteActions addObject:actionUUID];
|
||||
}
|
||||
|
||||
#pragma mark CXProviderDelegate
|
||||
|
||||
- (void)providerDidReset:(CXProvider *)provider {
|
||||
for (id listener in self.listeners) {
|
||||
[listener providerDidReset];
|
||||
}
|
||||
[self.pendingMuteActions removeAllObjects];
|
||||
}
|
||||
|
||||
- (void)provider:(CXProvider *)provider performAnswerCallAction:(CXAnswerCallAction *)action {
|
||||
for (id listener in self.listeners) {
|
||||
[listener performAnswerCallWithUUID:action.callUUID];
|
||||
}
|
||||
[action fulfill];
|
||||
}
|
||||
|
||||
- (void)provider:(CXProvider *)provider performEndCallAction:(CXEndCallAction *)action {
|
||||
for (id listener in self.listeners) {
|
||||
[listener performEndCallWithUUID:action.callUUID];
|
||||
}
|
||||
[action fulfill];
|
||||
}
|
||||
|
||||
- (void)provider:(CXProvider *)provider performSetMutedCallAction:(CXSetMutedCallAction *)action {
|
||||
NSUUID *uuid = ([self.pendingMuteActions containsObject:action.UUID]) ? action.UUID : nil;
|
||||
[self.pendingMuteActions removeObject:action.UUID];
|
||||
|
||||
// Avoid mute actions ping-pong: if the mute action was caused by
|
||||
// the JS side (we requested a transaction) don't call the delegate
|
||||
// method. If it was called by the provider itself (when the user presses
|
||||
// the mute button in the CallKit view) then call the delegate method.
|
||||
//
|
||||
// NOTE: don't try to be clever and remove this. Been there, done that.
|
||||
// Won't work.
|
||||
if (uuid == nil) {
|
||||
for (id listener in self.listeners) {
|
||||
[listener performSetMutedCallWithUUID:action.callUUID isMuted:action.isMuted];
|
||||
}
|
||||
}
|
||||
[action fulfill];
|
||||
}
|
||||
|
||||
- (void)provider:(CXProvider *)provider performStartCallAction:(CXStartCallAction *)action {
|
||||
for (id listener in self.listeners) {
|
||||
[listener performStartCallWithUUID:action.callUUID isVideo:action.isVideo];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)provider:(CXProvider *)provider didActivateAudioSession:(AVAudioSession *)audioSession {
|
||||
for (id listener in self.listeners) {
|
||||
[listener providerDidActivateAudioSessionWithSession:audioSession];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)provider:(CXProvider *)provider didDeactivateAudioSession:(AVAudioSession *)audioSession {
|
||||
for (id listener in self.listeners) {
|
||||
[listener providerDidDeactivateAudioSessionWithSession:audioSession];
|
||||
}
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -1,118 +0,0 @@
|
||||
/*
|
||||
* Copyright @ 2018-present Atlassian Pty Ltd
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import AVKit
|
||||
import CallKit
|
||||
import Foundation
|
||||
|
||||
internal final class JMCallKitEmitter: NSObject, CXProviderDelegate {
|
||||
|
||||
private let listeners = NSMutableArray()
|
||||
private var pendingMuteActions = Set<UUID>()
|
||||
|
||||
internal override init() {}
|
||||
|
||||
// MARK: - Add/remove listeners
|
||||
|
||||
func addListener(_ listener: JMCallKitListener) {
|
||||
if (!listeners.contains(listener)) {
|
||||
listeners.add(listener)
|
||||
}
|
||||
}
|
||||
|
||||
func removeListener(_ listener: JMCallKitListener) {
|
||||
listeners.remove(listener)
|
||||
}
|
||||
|
||||
// MARK: - Add mute action
|
||||
|
||||
func addMuteAction(_ actionUUID: UUID) {
|
||||
pendingMuteActions.insert(actionUUID)
|
||||
}
|
||||
|
||||
// MARK: - CXProviderDelegate
|
||||
|
||||
func providerDidReset(_ provider: CXProvider) {
|
||||
listeners.forEach {
|
||||
let listener = $0 as! JMCallKitListener
|
||||
listener.providerDidReset?()
|
||||
}
|
||||
pendingMuteActions.removeAll()
|
||||
}
|
||||
|
||||
func provider(_ provider: CXProvider, perform action: CXAnswerCallAction) {
|
||||
listeners.forEach {
|
||||
let listener = $0 as! JMCallKitListener
|
||||
listener.performAnswerCall?(UUID: action.callUUID)
|
||||
}
|
||||
|
||||
action.fulfill()
|
||||
}
|
||||
|
||||
func provider(_ provider: CXProvider, perform action: CXEndCallAction) {
|
||||
listeners.forEach {
|
||||
let listener = $0 as! JMCallKitListener
|
||||
listener.performEndCall?(UUID: action.callUUID)
|
||||
}
|
||||
|
||||
action.fulfill()
|
||||
}
|
||||
|
||||
func provider(_ provider: CXProvider, perform action: CXSetMutedCallAction) {
|
||||
let uuid = pendingMuteActions.remove(action.uuid)
|
||||
|
||||
// Avoid mute actions ping-pong: if the mute action was caused by
|
||||
// the JS side (we requested a transaction) don't call the delegate
|
||||
// method. If it was called by the provider itself (when the user presses
|
||||
// the mute button in the CallKit view) then call the delegate method.
|
||||
//
|
||||
// NOTE: don't try to be clever and remove this. Been there, done that.
|
||||
// Won't work.
|
||||
if (uuid == nil) {
|
||||
listeners.forEach {
|
||||
let listener = $0 as! JMCallKitListener
|
||||
listener.performSetMutedCall?(UUID: action.callUUID, isMuted: action.isMuted)
|
||||
}
|
||||
}
|
||||
|
||||
action.fulfill()
|
||||
}
|
||||
|
||||
func provider(_ provider: CXProvider, perform action: CXStartCallAction) {
|
||||
listeners.forEach {
|
||||
let listener = $0 as! JMCallKitListener
|
||||
listener.performStartCall?(UUID: action.callUUID, isVideo: action.isVideo)
|
||||
}
|
||||
|
||||
action.fulfill()
|
||||
}
|
||||
|
||||
func provider(_ provider: CXProvider,
|
||||
didActivate audioSession: AVAudioSession) {
|
||||
listeners.forEach {
|
||||
let listener = $0 as! JMCallKitListener
|
||||
listener.providerDidActivateAudioSession?(session: audioSession)
|
||||
}
|
||||
}
|
||||
|
||||
func provider(_ provider: CXProvider,
|
||||
didDeactivate audioSession: AVAudioSession) {
|
||||
listeners.forEach {
|
||||
let listener = $0 as! JMCallKitListener
|
||||
listener.providerDidDeactivateAudioSession?(session: audioSession)
|
||||
}
|
||||
}
|
||||
}
|
||||
34
ios/sdk/src/callkit/JMCallKitListener.h
Normal file
34
ios/sdk/src/callkit/JMCallKitListener.h
Normal file
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
* Copyright @ 2022-present 8x8, Inc.
|
||||
* Copyright @ 2018-present Atlassian Pty Ltd
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#import <AVKit/AVKit.h>
|
||||
#import <CallKit/CallKit.h>
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
@protocol JMCallKitListener <NSObject>
|
||||
|
||||
@optional
|
||||
- (void)providerDidReset;
|
||||
- (void)performAnswerCallWithUUID:(nonnull NSUUID *)UUID;
|
||||
- (void)performEndCallWithUUID:(nonnull NSUUID *)UUID;
|
||||
- (void)performSetMutedCallWithUUID:(nonnull NSUUID *)UUID isMuted:(BOOL)isMuted;
|
||||
- (void)performStartCallWithUUID:(nonnull NSUUID *)UUID isVideo:(BOOL)isVideo;
|
||||
- (void)providerDidActivateAudioSessionWithSession:(nonnull AVAudioSession *)session;
|
||||
- (void)providerDidDeactivateAudioSessionWithSession:(nonnull AVAudioSession *)session;
|
||||
- (void)providerTimedOutPerformingActionWithAction:(nonnull CXAction *)action;
|
||||
|
||||
@end
|
||||
@@ -1,38 +0,0 @@
|
||||
/*
|
||||
* Copyright @ 2018-present Atlassian Pty Ltd
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import AVKit
|
||||
import CallKit
|
||||
import Foundation
|
||||
|
||||
@objc public protocol JMCallKitListener: NSObjectProtocol {
|
||||
|
||||
@objc optional func providerDidReset()
|
||||
|
||||
@objc optional func performAnswerCall(UUID: UUID)
|
||||
|
||||
@objc optional func performEndCall(UUID: UUID)
|
||||
|
||||
@objc optional func performSetMutedCall(UUID: UUID, isMuted: Bool)
|
||||
|
||||
@objc optional func performStartCall(UUID: UUID, isVideo: Bool)
|
||||
|
||||
@objc optional func providerDidActivateAudioSession(session: AVAudioSession)
|
||||
|
||||
@objc optional func providerDidDeactivateAudioSession(session: AVAudioSession)
|
||||
|
||||
@objc optional func providerTimedOutPerformingAction(action: CXAction)
|
||||
}
|
||||
87
ios/sdk/src/callkit/JMCallKitProxy.h
Normal file
87
ios/sdk/src/callkit/JMCallKitProxy.h
Normal file
@@ -0,0 +1,87 @@
|
||||
/*
|
||||
* Copyright @ 2022-present 8x8, Inc.
|
||||
* Copyright @ 2018-present Atlassian Pty Ltd
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#import <CallKit/CallKit.h>
|
||||
#import <Foundation/Foundation.h>
|
||||
#import "JMCallKitListener.h"
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@protocol CXProviderProtocol <NSObject>
|
||||
|
||||
@property (nonatomic, readwrite, copy) CXProviderConfiguration* configuration;
|
||||
|
||||
- (void)setDelegate:(nullable id<CXProviderDelegate>)delegate queue:(nullable dispatch_queue_t)queue;
|
||||
- (void)reportNewIncomingCallWithUUID:(NSUUID *)uuid update:(CXCallUpdate *)update completion:(void (^)(NSError *))completion;
|
||||
- (void)reportCallWithUUID:(NSUUID *)uuid updated:(CXCallUpdate *)update;
|
||||
- (void)reportCallWithUUID:(NSUUID *)uuid endedAtDate:(NSDate *)dateEnded reason:(CXCallEndedReason)endedReason;
|
||||
- (void)reportOutgoingCallWithUUID:(NSUUID *)uuid startedConnectingAtDate:(NSDate *)dateStartedConnecting;
|
||||
- (void)reportOutgoingCallWithUUID:(NSUUID *)uuid connectedAtDate:(NSDate *)dateConnected;
|
||||
- (void)invalidate;
|
||||
|
||||
@end
|
||||
|
||||
#pragma mark -
|
||||
@protocol CXCallControllerProtocol <NSObject>
|
||||
|
||||
@property (nonatomic, readonly) NSArray<CXCall*> *calls;
|
||||
|
||||
- (void)requestTransaction:(CXTransaction *)transaction completion:(void (^)(NSError *_Nullable))completion;
|
||||
|
||||
@end
|
||||
|
||||
#pragma mark -
|
||||
|
||||
/// JitsiMeet CallKit proxy
|
||||
// NOTE: The methods this class exposes are meant to be called in the UI thread.
|
||||
// All delegate methods called by JMCallKitEmitter will be called in the UI thread.
|
||||
@interface JMCallKitProxy : NSObject
|
||||
|
||||
/// Enables the proxy in between CallKit and the consumers of the SDK.
|
||||
/// Defaults to disabled. Set to true when you want to use CallKit.
|
||||
@property (class) BOOL enabled;
|
||||
@property (class) id<CXProviderProtocol> callKitProvider;
|
||||
@property (class) id<CXCallControllerProtocol> callKitCallController;
|
||||
|
||||
+ (void)configureProviderWithLocalizedName:(nonnull NSString *)localizedName
|
||||
ringtoneSound:(nullable NSString *)ringtoneSound
|
||||
iconTemplateImageData:(nullable NSData*)imageData
|
||||
NS_SWIFT_NAME(configureProvider(localizedName:ringtoneSound:iconTemplateImageData:));
|
||||
+ (BOOL)isProviderConfigured;
|
||||
+ (void)addListener:(nonnull id<JMCallKitListener>)listener NS_SWIFT_NAME(addListener(_:));
|
||||
+ (void)removeListener:(nonnull id<JMCallKitListener>)listener NS_SWIFT_NAME(removeListener(_:));
|
||||
+ (BOOL)hasActiveCallForUUID:(nonnull NSString *)callUUID NS_SWIFT_NAME(hasActiveCallForUUID(_:));
|
||||
+ (void)reportNewIncomingCallWithUUID:(nonnull NSUUID *)uuid
|
||||
handle:(nullable NSString*)handle
|
||||
displayName:(nullable NSString*)displayName
|
||||
hasVideo:(BOOL)hasVideo
|
||||
completion:(nonnull void (^)(NSError *_Nullable))completion
|
||||
NS_SWIFT_NAME(reportNewIncomingCall(UUID:handle:displayName:hasVideo:completion:));
|
||||
+ (void)reportCallUpdateWith:(nonnull NSUUID *)uuid
|
||||
handle:(nullable NSString *)handle
|
||||
displayName:(nullable NSString *)displayName
|
||||
hasVideo:(BOOL)hasVideo;
|
||||
+ (void)reportCallWith:(nonnull NSUUID *)uuid
|
||||
endedAt:(nullable NSDate *)dateEnded
|
||||
reason:(CXCallEndedReason)endedReason;
|
||||
+ (void)reportOutgoingCallWith:(nonnull NSUUID *)uuid startedConnectingAt:(nullable NSDate *)dateStartedConnecting;
|
||||
+ (void)reportOutgoingCallWith:(nonnull NSUUID *)uuid connectedAt:(nullable NSDate *)dateConnected;
|
||||
+ (void)request:(nonnull CXTransaction *)transaction completion:(nonnull void (^)(NSError *_Nullable))completion;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
284
ios/sdk/src/callkit/JMCallKitProxy.m
Normal file
284
ios/sdk/src/callkit/JMCallKitProxy.m
Normal file
@@ -0,0 +1,284 @@
|
||||
/*
|
||||
* Copyright @ 2022-present 8x8, Inc.
|
||||
* Copyright @ 2018-present Atlassian Pty Ltd
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#import "JMCallKitProxy.h"
|
||||
#import "JMCallKitEmitter.h"
|
||||
|
||||
#pragma mark -
|
||||
@interface CXProvider(CXProviderProtocol) <CXProviderProtocol>
|
||||
@end
|
||||
|
||||
@implementation CXProvider(CXProviderProtocol)
|
||||
@end
|
||||
|
||||
#pragma mark -
|
||||
@interface CXCallController(CXCallControllerProtocol) <CXCallControllerProtocol>
|
||||
|
||||
@property (nonatomic, readonly) NSArray<CXCall*> *calls;
|
||||
|
||||
@end
|
||||
|
||||
@implementation CXCallController(CXCallControllerProtocol)
|
||||
|
||||
@dynamic calls;
|
||||
|
||||
- (NSArray<CXCall*> *)calls {
|
||||
return self.callObserver.calls;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
#pragma mark -
|
||||
@interface JMCallKitProxy ()
|
||||
|
||||
@property (class) CXProvider *defaultProvider;
|
||||
@property (class) CXProviderConfiguration *providerConfiguration;
|
||||
|
||||
@end
|
||||
|
||||
@interface JMCallKitProxy (Helpers)
|
||||
|
||||
+ (CXCallUpdate *)makeCXUpdateWithHandle:(nullable NSString *)handle displayName:(nullable NSString *)displayName hasVideo:(BOOL)hasVideo;
|
||||
|
||||
@end
|
||||
|
||||
@implementation JMCallKitProxy
|
||||
|
||||
@dynamic callKitProvider, callKitCallController, enabled;
|
||||
@dynamic defaultProvider, providerConfiguration;
|
||||
|
||||
static id<CXProviderProtocol> _callKitProvider = nil;
|
||||
static id<CXCallControllerProtocol> _callKitCallController = nil;
|
||||
static BOOL _enabled = false;
|
||||
static CXProvider *_defaultProvider = nil;
|
||||
static CXProviderConfiguration *_providerConfiguration = nil;
|
||||
|
||||
#pragma mark CallJit proxy
|
||||
|
||||
+ (id<CXProviderProtocol>)callKitProvider {
|
||||
return _callKitProvider;
|
||||
}
|
||||
|
||||
+ (void)setCallKitProvider:(id<CXProviderProtocol>)callKitProvider {
|
||||
if (_callKitProvider != callKitProvider) {
|
||||
_callKitProvider = callKitProvider;
|
||||
}
|
||||
}
|
||||
|
||||
+ (id<CXCallControllerProtocol>)callKitCallController {
|
||||
return _callKitCallController;
|
||||
}
|
||||
|
||||
+ (void)setCallKitCallController:(id<CXCallControllerProtocol>)callKitCallController {
|
||||
if (_callKitCallController != callKitCallController) {
|
||||
_callKitCallController = callKitCallController;
|
||||
}
|
||||
}
|
||||
|
||||
+ (BOOL)enabled {
|
||||
return _enabled;
|
||||
}
|
||||
|
||||
+ (void)setEnabled:(BOOL)enabled {
|
||||
_enabled = enabled ;
|
||||
|
||||
if (!self.callKitProvider) {
|
||||
[self.provider invalidate];
|
||||
}
|
||||
|
||||
if (enabled) {
|
||||
CXProviderConfiguration *configuration = self.providerConfiguration? self.providerConfiguration : [[CXProviderConfiguration alloc] initWithLocalizedName:@""];
|
||||
if (!self.callKitProvider) {
|
||||
self.defaultProvider = [[CXProvider alloc] initWithConfiguration: configuration];
|
||||
}
|
||||
|
||||
[self.provider setDelegate:self.emitter queue:nil];
|
||||
} else {
|
||||
[self.provider setDelegate:nil queue:nil];
|
||||
}
|
||||
}
|
||||
|
||||
+ (CXProvider *)defaultProvider {
|
||||
return _defaultProvider;
|
||||
}
|
||||
|
||||
+ (void)setDefaultProvider:(CXProvider *)defaultProvider {
|
||||
if (_defaultProvider != defaultProvider) {
|
||||
_defaultProvider = defaultProvider;
|
||||
}
|
||||
}
|
||||
|
||||
+ (id<CXProviderProtocol>)provider {
|
||||
return self.callKitProvider != nil ? self.callKitProvider : self.defaultProvider;
|
||||
}
|
||||
|
||||
+ (id<CXCallControllerProtocol>)callController {
|
||||
return self.callKitCallController != nil ? self.callKitCallController : self.defaultCallController;
|
||||
}
|
||||
|
||||
+ (CXProviderConfiguration *)providerConfiguration {
|
||||
return _providerConfiguration;
|
||||
}
|
||||
|
||||
+ (void)setProviderConfiguration:(CXProviderConfiguration *)providerConfiguration {
|
||||
if (_providerConfiguration != providerConfiguration) {
|
||||
_providerConfiguration = providerConfiguration;
|
||||
|
||||
if (providerConfiguration) {
|
||||
self.provider.configuration = providerConfiguration;
|
||||
[self.provider setDelegate:self.emitter queue:nil];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+ (CXCallController *)defaultCallController {
|
||||
static dispatch_once_t once;
|
||||
static CXCallController *defaultCallController;
|
||||
dispatch_once(&once, ^{
|
||||
defaultCallController = [[CXCallController alloc] init];
|
||||
});
|
||||
|
||||
return defaultCallController;
|
||||
}
|
||||
|
||||
+ (JMCallKitEmitter *)emitter {
|
||||
static dispatch_once_t once;
|
||||
static JMCallKitEmitter *emitter;
|
||||
dispatch_once(&once, ^{
|
||||
emitter = [[JMCallKitEmitter alloc] init];
|
||||
});
|
||||
|
||||
return emitter;
|
||||
}
|
||||
|
||||
+ (void)configureProviderWithLocalizedName:(nonnull NSString *)localizedName
|
||||
ringtoneSound:(nullable NSString *)ringtoneSound
|
||||
iconTemplateImageData:(nullable NSData*)imageData {
|
||||
if (!self.enabled) {
|
||||
return;
|
||||
}
|
||||
|
||||
CXProviderConfiguration *configuration = [[CXProviderConfiguration alloc] initWithLocalizedName:localizedName];
|
||||
configuration.iconTemplateImageData = imageData;
|
||||
configuration.maximumCallGroups = 1;
|
||||
configuration.maximumCallsPerCallGroup = 1;
|
||||
configuration.ringtoneSound = ringtoneSound;
|
||||
configuration.supportedHandleTypes = [NSSet setWithArray:@[@(CXHandleTypeGeneric)]];
|
||||
configuration.supportsVideo = true;
|
||||
|
||||
self.providerConfiguration = configuration;
|
||||
}
|
||||
|
||||
+ (BOOL)isProviderConfigured {
|
||||
return self.providerConfiguration != nil;
|
||||
}
|
||||
|
||||
+ (void)addListener:(nonnull id<JMCallKitListener>)listener {
|
||||
[self.emitter addListener:listener];
|
||||
}
|
||||
|
||||
+ (void)removeListener:(nonnull id<JMCallKitListener>)listener {
|
||||
[self.emitter removeListener:listener];
|
||||
}
|
||||
|
||||
+ (BOOL)hasActiveCallForUUID:(nonnull NSString *)callUUID {
|
||||
CXCall *activeCallForUUID = [[self.callController calls] filteredArrayUsingPredicate:[NSPredicate predicateWithBlock:^BOOL(CXCall *evaluatedObject, NSDictionary<NSString *,id> *bindings) {
|
||||
return evaluatedObject.UUID.UUIDString == callUUID;
|
||||
}]].firstObject;
|
||||
|
||||
if (!activeCallForUUID) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
+ (void)reportNewIncomingCallWithUUID:(nonnull NSUUID *)uuid
|
||||
handle:(nullable NSString*)handle
|
||||
displayName:(nullable NSString*)displayName
|
||||
hasVideo:(BOOL)hasVideo
|
||||
completion:(nonnull void (^)(NSError *_Nullable))completion {
|
||||
if (!self.enabled) {
|
||||
return;
|
||||
}
|
||||
|
||||
CXCallUpdate *callUpdate = [self makeCXUpdateWithHandle:handle displayName:displayName hasVideo:hasVideo];
|
||||
[self.provider reportNewIncomingCallWithUUID:uuid update:callUpdate completion:completion];
|
||||
}
|
||||
|
||||
+ (void)reportCallUpdateWith:(nonnull NSUUID *)uuid
|
||||
handle:(nullable NSString *)handle
|
||||
displayName:(nullable NSString *)displayName
|
||||
hasVideo:(BOOL)hasVideo {
|
||||
if (!self.enabled) {
|
||||
return;
|
||||
}
|
||||
|
||||
CXCallUpdate *callUpdate = [self makeCXUpdateWithHandle:handle displayName:displayName hasVideo:hasVideo];
|
||||
[self.provider reportCallWithUUID:uuid updated:callUpdate];
|
||||
}
|
||||
|
||||
+ (void)reportCallWith:(nonnull NSUUID *)uuid
|
||||
endedAt:(nullable NSDate *)dateEnded
|
||||
reason:(CXCallEndedReason)endedReason {
|
||||
[self.provider reportCallWithUUID:uuid endedAtDate:dateEnded reason:endedReason];
|
||||
}
|
||||
|
||||
+ (void)reportOutgoingCallWith:(nonnull NSUUID *)uuid startedConnectingAt:(nullable NSDate *)dateStartedConnecting {
|
||||
[self.provider reportOutgoingCallWithUUID:uuid startedConnectingAtDate:dateStartedConnecting];
|
||||
}
|
||||
|
||||
+ (void)reportOutgoingCallWith:(nonnull NSUUID *)uuid connectedAt:(nullable NSDate *)dateConnected {
|
||||
[self.provider reportOutgoingCallWithUUID:uuid connectedAtDate:dateConnected];
|
||||
}
|
||||
|
||||
+ (void)request:(nonnull CXTransaction *)transaction completion:(nonnull void (^)(NSError *_Nullable))completion {
|
||||
if (!self.enabled) {
|
||||
return;
|
||||
}
|
||||
|
||||
// XXX keep track of muted actions to avoid "ping-pong"ing. See
|
||||
// JMCallKitEmitter for details on the CXSetMutedCallAction handling.
|
||||
for (CXAction *action in transaction.actions) {
|
||||
if ([CXAction isKindOfClass:[CXSetMutedCallAction class]]) {
|
||||
[self.emitter addMuteAction:action.UUID];
|
||||
}
|
||||
}
|
||||
|
||||
[self.callController requestTransaction:transaction completion:completion];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@implementation JMCallKitProxy (Helpers)
|
||||
|
||||
+ (CXCallUpdate *)makeCXUpdateWithHandle:(nullable NSString *)handle displayName:(nullable NSString *)displayName hasVideo:(BOOL)hasVideo {
|
||||
CXCallUpdate *update = [[CXCallUpdate alloc] init];
|
||||
update.supportsDTMF = false;
|
||||
update.supportsHolding = false;
|
||||
update.supportsGrouping = false;
|
||||
update.supportsUngrouping = false;
|
||||
update.hasVideo = hasVideo;
|
||||
update.localizedCallerName = displayName;
|
||||
|
||||
if (handle) {
|
||||
update.remoteHandle = [[CXHandle alloc] initWithType:CXHandleTypeGeneric value:handle];
|
||||
}
|
||||
|
||||
return update;
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -1,231 +0,0 @@
|
||||
/*
|
||||
* Copyright @ 2018-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.
|
||||
*/
|
||||
|
||||
import CallKit
|
||||
import Foundation
|
||||
|
||||
public protocol CXProviderProtocol: AnyObject {
|
||||
var configuration: CXProviderConfiguration { get set }
|
||||
func setDelegate(_ delegate: CXProviderDelegate?, queue: DispatchQueue?)
|
||||
func reportNewIncomingCall(with UUID: UUID, update: CXCallUpdate, completion: @escaping (Error?) -> Void)
|
||||
func reportCall(with UUID: UUID, updated update: CXCallUpdate)
|
||||
func reportCall(with UUID: UUID, endedAt dateEnded: Date?, reason endedReason: CXCallEndedReason)
|
||||
func reportOutgoingCall(with UUID: UUID, startedConnectingAt dateStartedConnecting: Date?)
|
||||
func reportOutgoingCall(with UUID: UUID, connectedAt dateConnected: Date?)
|
||||
func invalidate()
|
||||
}
|
||||
|
||||
public protocol CXCallControllerProtocol: AnyObject {
|
||||
var calls: [CXCall] { get }
|
||||
func request(_ transaction: CXTransaction, completion: @escaping (Error?) -> Swift.Void)
|
||||
}
|
||||
|
||||
extension CXProvider: CXProviderProtocol {}
|
||||
extension CXCallController: CXCallControllerProtocol {
|
||||
public var calls: [CXCall] {
|
||||
return callObserver.calls
|
||||
}
|
||||
}
|
||||
|
||||
/// JitsiMeet CallKit proxy
|
||||
// NOTE: The methods this class exposes are meant to be called in the UI thread.
|
||||
// All delegate methods called by JMCallKitEmitter will be called in the UI thread.
|
||||
@objc public final class JMCallKitProxy: NSObject {
|
||||
|
||||
private override init() {}
|
||||
|
||||
// MARK: - CallKit proxy
|
||||
|
||||
public static var callKitProvider: CXProviderProtocol?
|
||||
public static var callKitCallController: CXCallControllerProtocol?
|
||||
|
||||
private static var defaultProvider: CXProvider?
|
||||
|
||||
private static var provider: CXProviderProtocol? {
|
||||
callKitProvider ?? defaultProvider
|
||||
}
|
||||
|
||||
private static var callController: CXCallControllerProtocol {
|
||||
callKitCallController ?? defaultCallController
|
||||
}
|
||||
|
||||
private static var providerConfiguration: CXProviderConfiguration? {
|
||||
didSet {
|
||||
guard let configuration = providerConfiguration else { return }
|
||||
provider?.configuration = configuration
|
||||
provider?.setDelegate(emitter, queue: nil)
|
||||
}
|
||||
}
|
||||
|
||||
private static let defaultCallController: CXCallController = {
|
||||
return CXCallController()
|
||||
}()
|
||||
|
||||
private static let emitter: JMCallKitEmitter = {
|
||||
return JMCallKitEmitter()
|
||||
}()
|
||||
|
||||
/// Enables the proxy in between CallKit and the consumers of the SDK.
|
||||
/// Defaults to disabled. Set to true when you want to use CallKit.
|
||||
@objc public static var enabled: Bool = false {
|
||||
didSet {
|
||||
if callKitProvider == nil {
|
||||
provider?.invalidate()
|
||||
}
|
||||
|
||||
if enabled {
|
||||
let configuration = providerConfiguration ?? CXProviderConfiguration(localizedName: "")
|
||||
if callKitProvider == nil {
|
||||
defaultProvider = CXProvider(configuration: configuration)
|
||||
}
|
||||
|
||||
provider?.setDelegate(emitter, queue: nil)
|
||||
} else {
|
||||
provider?.setDelegate(nil, queue: nil)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@objc public static func configureProvider(localizedName: String,
|
||||
ringtoneSound: String?,
|
||||
iconTemplateImageData: Data?) {
|
||||
guard enabled else { return }
|
||||
|
||||
let configuration = CXProviderConfiguration(localizedName: localizedName)
|
||||
configuration.iconTemplateImageData = iconTemplateImageData
|
||||
configuration.maximumCallGroups = 1
|
||||
configuration.maximumCallsPerCallGroup = 1
|
||||
configuration.ringtoneSound = ringtoneSound
|
||||
configuration.supportedHandleTypes = [CXHandle.HandleType.generic]
|
||||
configuration.supportsVideo = true
|
||||
|
||||
providerConfiguration = configuration
|
||||
}
|
||||
|
||||
@objc public static func isProviderConfigured() -> Bool {
|
||||
return providerConfiguration != nil
|
||||
}
|
||||
|
||||
@objc public static func addListener(_ listener: JMCallKitListener) {
|
||||
emitter.addListener(listener)
|
||||
}
|
||||
|
||||
@objc public static func removeListener(_ listener: JMCallKitListener) {
|
||||
emitter.removeListener(listener)
|
||||
}
|
||||
|
||||
@objc public static func hasActiveCallForUUID(_ callUUID: String) -> Bool {
|
||||
let activeCallForUUID = callController.calls.first {
|
||||
$0.uuid == UUID(uuidString: callUUID)
|
||||
}
|
||||
guard activeCallForUUID != nil else { return false }
|
||||
return true
|
||||
}
|
||||
|
||||
@objc public static func reportNewIncomingCall(UUID: UUID,
|
||||
handle: String?,
|
||||
displayName: String?,
|
||||
hasVideo: Bool,
|
||||
completion: @escaping (Error?) -> Void) {
|
||||
guard enabled else { return }
|
||||
|
||||
let callUpdate = makeCXUpdate(handle: handle,
|
||||
displayName: displayName,
|
||||
hasVideo: hasVideo)
|
||||
provider?.reportNewIncomingCall(with: UUID,
|
||||
update: callUpdate,
|
||||
completion: completion)
|
||||
}
|
||||
|
||||
@objc public static func reportCallUpdate(with UUID: UUID,
|
||||
handle: String?,
|
||||
displayName: String?,
|
||||
hasVideo: Bool) {
|
||||
guard enabled else { return }
|
||||
|
||||
let callUpdate = makeCXUpdate(handle: handle,
|
||||
displayName: displayName,
|
||||
hasVideo: hasVideo)
|
||||
provider?.reportCall(with: UUID, updated: callUpdate)
|
||||
}
|
||||
|
||||
@objc public static func reportCall(
|
||||
with UUID: UUID,
|
||||
endedAt dateEnded: Date?,
|
||||
reason endedReason: CXCallEndedReason) {
|
||||
guard enabled else { return }
|
||||
provider?.reportCall(with: UUID,
|
||||
endedAt: dateEnded,
|
||||
reason: endedReason)
|
||||
}
|
||||
|
||||
@objc public static func reportOutgoingCall(
|
||||
with UUID: UUID,
|
||||
startedConnectingAt dateStartedConnecting: Date?) {
|
||||
guard enabled else { return }
|
||||
provider?.reportOutgoingCall(with: UUID,
|
||||
startedConnectingAt: dateStartedConnecting)
|
||||
}
|
||||
|
||||
@objc public static func reportOutgoingCall(
|
||||
with UUID: UUID,
|
||||
connectedAt dateConnected: Date?) {
|
||||
guard enabled else { return }
|
||||
|
||||
provider?.reportOutgoingCall(with: UUID, connectedAt: dateConnected)
|
||||
}
|
||||
|
||||
@objc public static func request(
|
||||
_ transaction: CXTransaction,
|
||||
completion: @escaping (Error?) -> Swift.Void) {
|
||||
guard enabled else { return }
|
||||
|
||||
// XXX keep track of muted actions to avoid "ping-pong"ing. See
|
||||
// JMCallKitEmitter for details on the CXSetMutedCallAction handling.
|
||||
for action in transaction.actions {
|
||||
if (action as? CXSetMutedCallAction) != nil {
|
||||
emitter.addMuteAction(action.uuid)
|
||||
}
|
||||
}
|
||||
|
||||
callController.request(transaction, completion: completion)
|
||||
}
|
||||
|
||||
// MARK: - Callkit Proxy helpers
|
||||
|
||||
private static func makeCXUpdate(handle: String?,
|
||||
displayName: String?,
|
||||
hasVideo: Bool) -> CXCallUpdate {
|
||||
let update = CXCallUpdate()
|
||||
update.supportsDTMF = false
|
||||
update.supportsHolding = false
|
||||
update.supportsGrouping = false
|
||||
update.supportsUngrouping = false
|
||||
update.hasVideo = hasVideo
|
||||
|
||||
if let handle = handle {
|
||||
update.remoteHandle = CXHandle(type: .generic,
|
||||
value: handle)
|
||||
}
|
||||
|
||||
if let displayName = displayName {
|
||||
update.localizedCallerName = displayName
|
||||
}
|
||||
|
||||
return update
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,7 +11,6 @@
|
||||
"defaultEmail": "بريدك الافتراضي",
|
||||
"disabled": "لا يمكنك دعوة أحد.",
|
||||
"failedToAdd": "فشل إضافة مشاركين",
|
||||
"footerText": "الاتصال لدعوة الغير مُعطَّل.",
|
||||
"googleEmail": "بريد غوغل",
|
||||
"inviteMoreHeader": "أنت بمفردك في هذا المُلتقى",
|
||||
"inviteMoreMailSubject": "ضم {{appName}} للمُلتقى",
|
||||
@@ -97,6 +96,7 @@
|
||||
"messageAccessibleTitleMe": "أنا أقول:",
|
||||
"messageTo": "أرسل رسالة خاصة إلى {{recipient}}",
|
||||
"messagebox": "اكتب رسالة",
|
||||
"newMessages": "رسائل جديدة",
|
||||
"nickname": {
|
||||
"popover": "اختر لقبًا",
|
||||
"title": "اكتب لقبًا لاعتماده في المحادثة",
|
||||
@@ -146,7 +146,6 @@
|
||||
"bridgeCount": "عدد المخدِّمات: ",
|
||||
"codecs": "المرماز (A/V): ",
|
||||
"connectedTo": "وصل إلى:",
|
||||
"e2e_rtt": "E2E RTT:",
|
||||
"framerate": "مُعدَّل الإطارات:",
|
||||
"less": "اخف",
|
||||
"localaddress": "العنوان المحلي:",
|
||||
@@ -198,8 +197,8 @@
|
||||
"deviceError": {
|
||||
"cameraError": "فشل الوصول إلى كاميرتك",
|
||||
"cameraPermission": "خطأ في تحصيل إذن استخدام كاميرتك",
|
||||
"microphoneError": "فشل الوصول إلى مجهارك (المايكروفون)",
|
||||
"microphonePermission": "خطأ في تحصيل إذن استخدام المجهار (المايكروفون)"
|
||||
"microphoneError": "فشل الوصول إلى المايكروفون",
|
||||
"microphonePermission": "خطأ في تحصيل إذن استخدام المايكروفون"
|
||||
},
|
||||
"deviceSelection": {
|
||||
"noPermission": "لم يُمنَح الإذن",
|
||||
@@ -285,7 +284,6 @@
|
||||
"linkMeetingTitle": "ربط المُلتقى بـ Salesforce",
|
||||
"liveStreaming": "البث المباشر الحي",
|
||||
"liveStreamingDisabledBecauseOfActiveRecordingTooltip": "غير ممكن أثناء التسجيل",
|
||||
"liveStreamingDisabledTooltip": "بدء بثٍ حيٍّ مُعطَّل",
|
||||
"localUserControls": "ضوابط المستخدم المحلي",
|
||||
"lockMessage": "فشل جعل المؤتمر مغلقًا.",
|
||||
"lockRoom": "أضف المُلتقى $t(lockRoomPasswordUppercase)",
|
||||
@@ -295,11 +293,11 @@
|
||||
"logoutTitle": "الخروج",
|
||||
"maxUsersLimitReached": "وصل عدد المشاركين إلى الحد الأقصى. المؤتمر مكتمل الحضور. اتصل رجاءً براعي المؤتمر أو جرب مرة أخرى لاحقًا.",
|
||||
"maxUsersLimitReachedTitle": "وصل عدد المشاركين إلى الحد الأقصى",
|
||||
"micConstraintFailedError": "لا يوافق المجهار (المايكروفون) لديك بعض القيود المطلوبة.",
|
||||
"micNotFoundError": "لم يُعثَر على أي مجهار (مايكروفون)",
|
||||
"micNotSendingData": "اذهب إلى إعدادات حاسوبك لإلغاء كتم المجهار (المايكروفون) وضبط مستواه",
|
||||
"micNotSendingDataTitle": "كتم ضبط الإعدادات لديك المجهار (المايكروفون)",
|
||||
"micPermissionDeniedError": "لم تعط إذن استعمال المجهار (المايكروفون) الخاص بك. ما يزال بإمكانك الإنضمام إلى المؤتمر ولكن دون أن يسمعك الآخرون. جرب استعمال زر الكاميرا في شريط العنوان لإصلاح هذه المشكلة.",
|
||||
"micConstraintFailedError": "لا يوافق المايكروفون لديك بعض القيود المطلوبة.",
|
||||
"micNotFoundError": "لم يُعثَر على أي مايكروفون",
|
||||
"micNotSendingData": "اذهب إلى إعدادات حاسوبك لإلغاء كتم المايكروفون وضبط مستواه",
|
||||
"micNotSendingDataTitle": "كتم ضبط الإعدادات لديك المايكروفون",
|
||||
"micPermissionDeniedError": "لم تعط إذن استعمال المايكروفون الخاص بك. ما يزال بإمكانك الإنضمام إلى المؤتمر ولكن دون أن يسمعك الآخرون. جرب استعمال زر الكاميرا في شريط العنوان لإصلاح هذه المشكلة.",
|
||||
"micTimeoutError": "تعذر بدء مصدر الصوت. انقضت المهلة!",
|
||||
"micUnknownError": "لا يمكن استخدام الميكروفون لسبب غير معروف.",
|
||||
"moderationAudioLabel": "السماح للحاضرين بإعادة الصوت بأنفسهم",
|
||||
@@ -340,7 +338,6 @@
|
||||
"recentlyUsedObjects": "الأشياء المستخدمة مؤخرًا",
|
||||
"recording": "قيد التسجيل",
|
||||
"recordingDisabledBecauseOfActiveLiveStreamingTooltip": "ليس بالإمكان ما دمت قيد البث المباشر",
|
||||
"recordingDisabledTooltip": "عملية التسجيل معطلة.",
|
||||
"rejoinNow": "انضم مجدَّدًا الآن",
|
||||
"remoteControlAllowedMessage": "قبل {{user}} طلب إمكانية التحكم البعيد!",
|
||||
"remoteControlDeniedMessage": "رفض {{user}} طلب إمكانية التحكم البعيد!",
|
||||
@@ -506,7 +503,7 @@
|
||||
"giphyMenu": "تبديل قائمة GIPHY",
|
||||
"keyboardShortcuts": "اختصارات لوحة المفاتيح",
|
||||
"localRecording": "اظهِر أو اخفِ التحكم بالتسجيل المحلي",
|
||||
"mute": "اكتم أو ألغ كتم المجهار (المايكروفون) الخاص بك",
|
||||
"mute": "اكتم أو ألغ كتم المايكروفون الخاص بك",
|
||||
"pushToTalk": "اضغط للتحدث",
|
||||
"raiseHand": "ارفع/اخفض يدك",
|
||||
"showSpeakerStats": "اظهر حالة مكبر الصوت",
|
||||
@@ -517,6 +514,10 @@
|
||||
"toggleShortcuts": "أظهِر/اخفِ اختصارات لوحة المفاتيح",
|
||||
"videoMute": "ابدأ/أوقف كاميرتك"
|
||||
},
|
||||
"largeVideo": {
|
||||
"screenIsShared": "أنت تشارك شاشتك",
|
||||
"showMeWhatImSharing": "أرني ما أشاركه"
|
||||
},
|
||||
"liveStreaming": {
|
||||
"busy": "نعمل على تحرير موارد البث. حاول مرة أخرى رجاءً بعض بضعة دقائق.",
|
||||
"busyTitle": "جميع من يبث الفيديو مشغولون حاليًا",
|
||||
@@ -646,7 +647,7 @@
|
||||
"focusFail": "إنَّ {{component}} غير متاح. ستعاد المحاولة مرة أخرى خلال {{ms}} ثانية.",
|
||||
"gifsMenu": "GIPHY",
|
||||
"groupTitle": "إشعارات",
|
||||
"hostAskedUnmute": "The moderator would like you to speak",
|
||||
"hostAskedUnmute": "يريدك مدير اللقاء أن تتحدث.",
|
||||
"invitedOneMember": "دُعِي {{name}}",
|
||||
"invitedThreePlusMembers": "دُعِي {{name}} وعدد {{count}} آخرين",
|
||||
"invitedTwoMembers": "دُعِي {{first}} و {{second}}",
|
||||
@@ -707,8 +708,8 @@
|
||||
"suboptimalBrowserWarning": "نخشى أن لا تكون تجربة المُلتقى جيدة. نعمل على تحسين الكثير من الأمور، لكن ننصحك حتى ذلك الحين باستعمال باستعمال أحد <a href='static/recommendedBrowsers.html' target='_blank'>المتصفحات المدعومة</a>.",
|
||||
"suboptimalExperienceTitle": "تحذير من المتصفح",
|
||||
"unmute": "إلغاء الكتم",
|
||||
"videoMutedRemotelyDescription": "You can always turn it on again.",
|
||||
"videoMutedRemotelyTitle": "Your video has been turned off by {{participantDisplayName}}",
|
||||
"videoMutedRemotelyDescription": "يمكنك دائمًا تشغيله مرة أخرى.",
|
||||
"videoMutedRemotelyTitle": "تم إيقاف الفيديو الخاص بك بواسطة {{participantDisplayName}}",
|
||||
"videoUnmuteBlockedDescription": "تم حظر عملية إلغاء كتم الكاميرا مؤقتًا بسبب قيود النظام.",
|
||||
"videoUnmuteBlockedTitle": "تم حظر إعادة الكاميرا!",
|
||||
"viewLobby": "مشاهدة اللوبي",
|
||||
@@ -797,7 +798,7 @@
|
||||
"goodQuality": "رائع! الجودة في تحسن للأفضل!",
|
||||
"noMediaConnectivity": "لم نتمكن من إيجاد وسيلة لإنشاء اتصال لهذه التجربة، وسبب هذا عائد إلى الجدار الناري أو مترجم عناوين الشبكة NAT في أغلب الأحيان.",
|
||||
"noVideo": "نتوقع أن تكون جودة الفيديو تعيسة.",
|
||||
"undetectable": "إن مازلت غير قادر على إجراء اتصالات من المتصفح، ننصح بالتأكد من حالة مكبرات الصوت والمجهار (المايكروفون) والكاميرا، وأنَّك منحت المتصفح إذن الوصول إليها وأن المتصفح محدَّث إلى أحدث إصدار. إن ما زلت تواجه مشاكل في الاتصال بعد ذلك، حاول التواصل مع مطوري تطبيق الويب.",
|
||||
"undetectable": "إن مازلت غير قادر على إجراء اتصالات من المتصفح، ننصح بالتأكد من حالة مكبرات الصوت والمايكروفون والكاميرا، وأنَّك منحت المتصفح إذن الوصول إليها وأن المتصفح محدَّث إلى أحدث إصدار. إن ما زلت تواجه مشاكل في الاتصال بعد ذلك، حاول التواصل مع مطوري تطبيق الويب.",
|
||||
"veryPoorConnection": "نتوقع أن تكون جودة الاتصال تعيسة.",
|
||||
"videoFreezing": "نتوقع حصول جمود في الفيديو أو تحول الصورة للسواد",
|
||||
"videoHighQuality": "نتوقع أن تكون جودة الفيديو جيدة",
|
||||
@@ -825,7 +826,7 @@
|
||||
"joinWithoutAudio": "انضم دون صوت",
|
||||
"keyboardShortcuts": "تفعيل اختصارات لوحة المفاتيح",
|
||||
"linkCopied": "نُسِخ الرابط",
|
||||
"lookGood": "يبدو أن المجهار لديك تعيس",
|
||||
"lookGood": "يبدو أن الميكروفون لديك سيء",
|
||||
"or": "أو",
|
||||
"premeeting": "ما قبل المُلتقى",
|
||||
"screenSharingError": "خطأ في مشاركة الشاشة:",
|
||||
@@ -955,7 +956,7 @@
|
||||
"language": "اللغة",
|
||||
"loggedIn": "الدخول باسم {{name}}",
|
||||
"maxStageParticipants": "الحد الأقصى لعدد المشاركين الذين يمكن تثبيتهم في المرحلة الرئيسية",
|
||||
"microphones": "المجهار (المايكروفون)",
|
||||
"microphones": "المايكروفون",
|
||||
"moderator": "رئيس الجلسة",
|
||||
"more": "المزيد",
|
||||
"name": "الاسم",
|
||||
@@ -969,7 +970,7 @@
|
||||
"screenTitle": "إعدادات",
|
||||
"selectAudioOutput": "خرج الصوت",
|
||||
"selectCamera": "الكاميرا",
|
||||
"selectMic": "المجهار (المايكروفون)",
|
||||
"selectMic": "المايكروفون",
|
||||
"selfView": "عرض ذاتي",
|
||||
"sounds": "اصوات",
|
||||
"speakers": "المذياع (مكبر الصوت)",
|
||||
@@ -1032,7 +1033,7 @@
|
||||
"startupoverlay": {
|
||||
"genericTitle": "يحتاج المُلتقى إلى استخدام الميكروفون والكاميرا.",
|
||||
"policyText": " ",
|
||||
"title": "يريد {{app}} استعمال المجهار والكاميرا خاصَّتك."
|
||||
"title": "يريد {{app}} استعمال الميكروفون والكاميرا خاصَّتك."
|
||||
},
|
||||
"suspendedoverlay": {
|
||||
"rejoinKeyTitle": "المنطقة",
|
||||
@@ -1061,6 +1062,7 @@
|
||||
"document": "اظهِر/اخفِ الملف المشارك",
|
||||
"download": "نزِّل التطبيق",
|
||||
"embedMeeting": "ضمِّن المُلتقى",
|
||||
"endConference": "End meeting for all",
|
||||
"expand": "وسّع",
|
||||
"feedback": "أبدِ رأيك",
|
||||
"fullScreen": "استعمل/اخرج من وضع الشاشة الكاملة",
|
||||
@@ -1134,6 +1136,7 @@
|
||||
"download": "نزِّل التطبيق",
|
||||
"e2ee": "تعمية طرف-لطرف",
|
||||
"embedMeeting": "ضمِّن المُلتقى",
|
||||
"endConference": "إنهاء الاجتماع للجميع",
|
||||
"enterFullScreen": "تعمية طرف-لطرف",
|
||||
"enterTileView": "عرض بشاشة كاملة",
|
||||
"exitFullScreen": "أدخل عنوان العرض",
|
||||
@@ -1163,10 +1166,10 @@
|
||||
"noAudioSignalDescSuggestion": "إن لم تكتمه عمدًا من إعدادات النظام لديك أو من الجهاز نفسه، بدِّله إلى الجهاز الموصى به.",
|
||||
"noAudioSignalDialInDesc": "يمكن أيضًا الاتصال باستعمال:",
|
||||
"noAudioSignalDialInLinkDesc": "أرقام الاتصال",
|
||||
"noAudioSignalTitle": "لا يصلنا شيئًا من المجهار (المايكروفون) الخاص بك",
|
||||
"noAudioSignalTitle": "لا يصلنا شيئًا من المايكروفون الخاص بك",
|
||||
"noiseSuppression": "قمع الضوضاء",
|
||||
"noisyAudioInputDesc": "يبدو أنَّ المجهار (المايكروفون) لديك يصدر الكثير من الضجة، اكتمه رجاءً أو استعمل مجهارًا آخر.",
|
||||
"noisyAudioInputTitle": "يبدو أنَّ المجهار (المايكروفون) لديك يصدر الكثير من الضجة!",
|
||||
"noisyAudioInputDesc": "يبدو أنَّ المايكروفون لديك يلتقط الكثير من الضجة، اكتمه رجاءً أو استعمل ميكروفونًا آخر.",
|
||||
"noisyAudioInputTitle": "يبدو أنَّ المايكروفون لديك يلتقط الكثير من الضجة!",
|
||||
"openChat": "فتح الدرشة",
|
||||
"openReactionsMenu": "افتح قائمة التفاعلات",
|
||||
"participants": "مشاركون",
|
||||
@@ -1196,7 +1199,7 @@
|
||||
"stopSharedVideo": "أوقف فيديو يوتيوب المشارك",
|
||||
"stopSubtitles": "أخفِ الترجمة",
|
||||
"surprised": "مندهش",
|
||||
"talkWhileMutedPopup": "أتحاول التحدث؟ المجهار مكتوم لديك.",
|
||||
"talkWhileMutedPopup": "أتحاول التحدث؟ الميكروفون لديك مكتوم.",
|
||||
"tileViewToggle": "بدِّل عنوان العرض",
|
||||
"toggleCamera": "بدِّل الكاميرا",
|
||||
"undock": "فك في نافذة منفصلة",
|
||||
@@ -1213,16 +1216,18 @@
|
||||
"pending": "التحضير لإذاعة المُلتقى...",
|
||||
"start": "بدء إظهار الترجمة",
|
||||
"stop": "إيقاف عرض الترجمة",
|
||||
"subtitles": "ترجمات",
|
||||
"subtitlesOff": "إيقاف",
|
||||
"tr": "يذاع"
|
||||
},
|
||||
"userMedia": {
|
||||
"androidGrantPermissions": "اختر <b><i>السماح</i></b> عندما يطلب المتصفح الأذونات.",
|
||||
"chromeGrantPermissions": "اختر <b><i>السماح</i></b> عندما يطلب المتصفح الأذونات.",
|
||||
"edgeGrantPermissions": "اختر <b><i>نعم</i></b> عندما يطلب المتصفح الأذونات.",
|
||||
"electronGrantPermissions": "امنح إذنًا باستعمال الكاميرا والمجهار (المايكروفون).",
|
||||
"electronGrantPermissions": "امنح إذنًا باستعمال الكاميرا والمايكروفون.",
|
||||
"firefoxGrantPermissions": "اختر <b><i>مشاركة الجهاز المحدَّد</i></b> عندما يطل بالمتصفح الأذونات.",
|
||||
"iexplorerGrantPermissions": "اختر <b><i>تمام</i></b> عندما يطلب المتصفح الأذونات.",
|
||||
"nwjsGrantPermissions": "امنح إذنًا باستعمال الكاميرا والمجهار (المايكروفون).",
|
||||
"nwjsGrantPermissions": "امنح إذنًا باستعمال الكاميرا والمايكروفون.",
|
||||
"operaGrantPermissions": "اختر <b><i>السماح</i></b> عندما يطلب المتصفح الأذونات.",
|
||||
"react-nativeGrantPermissions": "اختر <b><i>السماح</i></b> عندما يطلب المتصفح الأذونات.",
|
||||
"safariGrantPermissions": "اختر <b><i>تمام</i></b> عندما يطلب المتصفح الأذونات."
|
||||
|
||||
@@ -90,7 +90,6 @@
|
||||
"bitrate": "Бітрэйт:",
|
||||
"bridgeCount": "Колькасць сервераў: ",
|
||||
"connectedTo": "Падключаны да:",
|
||||
"e2e_rtt": "E2E RTT:",
|
||||
"framerate": "Частата кадраў:",
|
||||
"less": "Кароткая інфармацыя",
|
||||
"localaddress_0": "Мясцовы адрас:",
|
||||
|
||||
@@ -145,7 +145,6 @@
|
||||
"bridgeCount": "Nombre de servidors: ",
|
||||
"codecs": "Còdecs (A/V):",
|
||||
"connectedTo": "Connectat a:",
|
||||
"e2e_rtt": "E2E RTT:",
|
||||
"framerate": "Taxa de fotogrames:",
|
||||
"less": "Menys informació",
|
||||
"localaddress": "Adreça local:",
|
||||
|
||||
@@ -108,7 +108,6 @@
|
||||
"bridgeCount": "Počet serverů: ",
|
||||
"codecs": "Kodeky (A/V): ",
|
||||
"connectedTo": "Připojeno k:",
|
||||
"e2e_rtt": "E2E RTT:",
|
||||
"framerate": "Rychlost snímkování:",
|
||||
"less": "Zobrazit méně",
|
||||
"localaddress_0": "Místní adresa:",
|
||||
|
||||
@@ -90,7 +90,6 @@
|
||||
"bitrate": "Bitrate:",
|
||||
"bridgeCount": "Server antal: ",
|
||||
"connectedTo": "Forbundet til:",
|
||||
"e2e_rtt": "E2E RTT:",
|
||||
"framerate": "Frame rate:",
|
||||
"less": "Vis mindre",
|
||||
"localaddress": "Lokal adresse:",
|
||||
|
||||
@@ -11,7 +11,6 @@
|
||||
"defaultEmail": "Ihre Standard-E-Mail",
|
||||
"disabled": "Sie können keine Personen einladen.",
|
||||
"failedToAdd": "Fehler beim Hinzufügen von Personen",
|
||||
"footerText": "Abgehender Ruf ist deaktiviert.",
|
||||
"googleEmail": "Google-E-Mail",
|
||||
"inviteMoreHeader": "Sie sind alleine in der Sitzung",
|
||||
"inviteMoreMailSubject": "An {{appName}} Meeting teilnehmen",
|
||||
@@ -97,6 +96,7 @@
|
||||
"messageAccessibleTitleMe": "Ich sage:",
|
||||
"messageTo": "Private Nachricht an {{recipient}}",
|
||||
"messagebox": "Nachricht eingeben",
|
||||
"newMessages": "Neue Nachrichten",
|
||||
"nickname": {
|
||||
"popover": "Wähle einen Alias",
|
||||
"title": "Geben Sie einen Alias zum Chatten ein",
|
||||
@@ -146,7 +146,6 @@
|
||||
"bridgeCount": "Serverzahl: ",
|
||||
"codecs": "Codecs (A/V): ",
|
||||
"connectedTo": "Verbunden mit:",
|
||||
"e2e_rtt": "Ende-zu-Ende-Paketumlaufzeit:",
|
||||
"framerate": "Bildwiederholrate:",
|
||||
"less": "Weniger anzeigen",
|
||||
"localaddress": "Lokale Adresse:",
|
||||
@@ -285,7 +284,6 @@
|
||||
"linkMeetingTitle": "Konferenz mit Salesforce verlinken",
|
||||
"liveStreaming": "Livestreaming",
|
||||
"liveStreamingDisabledBecauseOfActiveRecordingTooltip": "Während einer Aufnahme nicht möglich",
|
||||
"liveStreamingDisabledTooltip": "Starten des Livestreams deaktiviert.",
|
||||
"localUserControls": "Lokale Benutzersteuerung",
|
||||
"lockMessage": "Die Konferenz konnte nicht gesperrt werden.",
|
||||
"lockRoom": "Konferenz$t(lockRoomPassword) hinzufügen",
|
||||
@@ -340,7 +338,6 @@
|
||||
"recentlyUsedObjects": "Ihre zuletzt verwendeten Objekte",
|
||||
"recording": "Aufnahme",
|
||||
"recordingDisabledBecauseOfActiveLiveStreamingTooltip": "Während eines Livestreams nicht möglich",
|
||||
"recordingDisabledTooltip": "Start der Aufzeichnung deaktiviert.",
|
||||
"rejoinNow": "Jetzt erneut beitreten",
|
||||
"remoteControlAllowedMessage": "{{user}} hat die Anfrage zur Fernsteuerung angenommen!",
|
||||
"remoteControlDeniedMessage": "{{user}} hat die Anfrage zur Fernsteuerung verweigert!",
|
||||
@@ -517,6 +514,10 @@
|
||||
"toggleShortcuts": "Tastenkombinationen ein- oder ausblenden",
|
||||
"videoMute": "Kamera starten oder stoppen"
|
||||
},
|
||||
"largeVideo": {
|
||||
"screenIsShared": "Ihr Bildschirm wird freigegeben",
|
||||
"showMeWhatImSharing": "Anzeigen, was freigegeben wird"
|
||||
},
|
||||
"liveStreaming": {
|
||||
"busy": "Es werden Ressourcen zum Streamen bereitgestellt. Bitte in ein paar Minuten erneut versuchen.",
|
||||
"busyTitle": "Alle Streaming-Instanzen sind in Gebrauch",
|
||||
@@ -993,12 +994,17 @@
|
||||
"displayName": "Anzeigename",
|
||||
"displayNamePlaceholderText": "z.B. Erika Musterfrau",
|
||||
"email": "E-Mail",
|
||||
"goTo": "Gehe zu",
|
||||
"header": "Einstellungen",
|
||||
"help": "Hilfe",
|
||||
"links": "Links",
|
||||
"privacy": "Datenschutz",
|
||||
"profileSection": "Profil",
|
||||
"serverURL": "Server-URL",
|
||||
"showAdvanced": "Erweiterte Einstellungen anzeigen",
|
||||
"startWithAudioMuted": "Stumm beitreten",
|
||||
"startWithVideoMuted": "Ohne Video beitreten",
|
||||
"terms": "Nutzungsbedingungen",
|
||||
"version": "Version"
|
||||
},
|
||||
"share": {
|
||||
@@ -1055,6 +1061,7 @@
|
||||
"document": "Geteiltes Dokument schließen",
|
||||
"download": "Unsere Apps herunterladen",
|
||||
"embedMeeting": "Konferenz einbetten",
|
||||
"endConference": "Konferenz für alle beenden",
|
||||
"expand": "Ausklappen",
|
||||
"feedback": "Feedback hinterlassen",
|
||||
"fullScreen": "Vollbildmodus ein-/ausschalten",
|
||||
@@ -1128,6 +1135,7 @@
|
||||
"download": "Unsere Apps herunterladen",
|
||||
"e2ee": "Ende-zu-Ende-Verschlüsselung",
|
||||
"embedMeeting": "Konferenz einbetten",
|
||||
"endConference": "Konferenz für alle beenden",
|
||||
"enterFullScreen": "Vollbildmodus",
|
||||
"enterTileView": "Kachelansicht einschalten",
|
||||
"exitFullScreen": "Vollbildmodus verlassen",
|
||||
@@ -1207,6 +1215,8 @@
|
||||
"pending": "Transkribieren des Meetings wird vorbereitet…",
|
||||
"start": "Anzeige der Untertitel starten",
|
||||
"stop": "Anzeige der Untertitel stoppen",
|
||||
"subtitles": "Untertitel",
|
||||
"subtitlesOff": "Ausschalten",
|
||||
"tr": "TR"
|
||||
},
|
||||
"userMedia": {
|
||||
|
||||
@@ -105,7 +105,6 @@
|
||||
"bitrate": "Ρυθμός μετάδοσης:",
|
||||
"bridgeCount": "Αριθμός server: ",
|
||||
"connectedTo": "Συνδεδεμένος με:",
|
||||
"e2e_rtt": "E2E RTT:",
|
||||
"framerate": "Ρυθμός ανανέωσης:",
|
||||
"less": "Δείξε λιγότερα",
|
||||
"localaddress": "Τοπική διεύθυνση:",
|
||||
|
||||
@@ -92,7 +92,6 @@
|
||||
"bridgeCount": "Server count: ",
|
||||
"codecs": "Codecs (A/V): ",
|
||||
"connectedTo": "Connected to:",
|
||||
"e2e_rtt": "",
|
||||
"framerate": "Frame rate:",
|
||||
"less": "Show less",
|
||||
"localaddress": "Local address:",
|
||||
|
||||
@@ -90,7 +90,6 @@
|
||||
"bitrate": "Bitrate:",
|
||||
"bridgeCount": "Server count: ",
|
||||
"connectedTo": "Connected to:",
|
||||
"e2e_rtt": "E2E RTT:",
|
||||
"framerate": "Frame rate:",
|
||||
"less": "Show less",
|
||||
"localaddress": "Local address:",
|
||||
|
||||
@@ -114,7 +114,6 @@
|
||||
"bridgeCount": "Contador del servidor: ",
|
||||
"codecs": "Codecs (A/V):",
|
||||
"connectedTo": "Conectado a:",
|
||||
"e2e_rtt": "E2E RTT:",
|
||||
"framerate": "Fotogramas por segundo:",
|
||||
"less": "Mostrar menos",
|
||||
"localaddress": "Dirección local:",
|
||||
|
||||
@@ -122,7 +122,6 @@
|
||||
"bridgeCount": "Contador del servidor: ",
|
||||
"codecs": "Codecs (A/V):",
|
||||
"connectedTo": "Conectado a:",
|
||||
"e2e_rtt": "E2E RTT:",
|
||||
"framerate": "Fotogramas por segundo:",
|
||||
"less": "Mostrar menos",
|
||||
"localaddress": "Dirección local:",
|
||||
|
||||
@@ -90,7 +90,6 @@
|
||||
"bitrate": "Andmeedastuskiirus:",
|
||||
"bridgeCount": "Serverite arv: ",
|
||||
"connectedTo": "Ühendatud:",
|
||||
"e2e_rtt": "E2E RTT:",
|
||||
"framerate": "Ekraani eraldusvõime:",
|
||||
"less": "Näita vähem",
|
||||
"localaddress": "Lokaalne aadress:",
|
||||
|
||||
@@ -110,7 +110,6 @@
|
||||
"bridgeCount": "Zerbitzari kopurua: ",
|
||||
"codecs": "Kodekak (A/B): ",
|
||||
"connectedTo": "Konektatua hona:",
|
||||
"e2e_rtt": "E2E RTT:",
|
||||
"framerate": "Marko-abiadura:",
|
||||
"less": "Erakutsi gutxiago",
|
||||
"localaddress": "Helbide lokala:",
|
||||
|
||||
@@ -134,7 +134,6 @@
|
||||
"bridgeCount": "تعداد سرور: ",
|
||||
"codecs": "کدکها (A/V): ",
|
||||
"connectedTo": "متصل به:",
|
||||
"e2e_rtt": "E2E RTT:",
|
||||
"framerate": "نرخ فریم:",
|
||||
"less": "خلاصه",
|
||||
"localaddress": "نشانی داخلی:",
|
||||
|
||||
@@ -134,7 +134,6 @@
|
||||
"bridgeCount": "Nombre de serveurs :",
|
||||
"codecs": "Codecs (A/V) :",
|
||||
"connectedTo": "Connecté à :",
|
||||
"e2e_rtt": "E2E RTT :",
|
||||
"framerate": "Images par seconde :",
|
||||
"less": "Cacher les détails",
|
||||
"localaddress": "Adresse locale :",
|
||||
|
||||
@@ -90,7 +90,6 @@
|
||||
"bitrate": "קצב סיביות:",
|
||||
"bridgeCount": "מספר שרתים: ",
|
||||
"connectedTo": "מחובר אל:",
|
||||
"e2e_rtt": "E2E RTT:",
|
||||
"framerate": "קצב מסגרת:",
|
||||
"less": "הצג פחות",
|
||||
"localaddress": "כתובת מקומית:",
|
||||
|
||||
@@ -109,7 +109,6 @@
|
||||
"bridgeCount": "सर्वर गणना: ",
|
||||
"codecs": "कोडेक (ए/वी): ",
|
||||
"connectedTo": "से जुड़ा हुआ है :",
|
||||
"e2e_rtt": "ई.2ई. आर.टी.टी.:",
|
||||
"framerate": "फ्रेम दर:",
|
||||
"less": "कम दिखाएं",
|
||||
"localaddress": "स्थानीय पता:",
|
||||
|
||||
@@ -147,7 +147,6 @@
|
||||
"bridgeCount": "Broj poslužitelja: ",
|
||||
"codecs": "Kodeki (A/V): ",
|
||||
"connectedTo": "Povezan na:",
|
||||
"e2e_rtt": "E2E RTT:",
|
||||
"framerate": "Broj sličica u sekundi:",
|
||||
"less": "Pokaži manje",
|
||||
"localaddress": "Adresa lokalnog uređaja:",
|
||||
|
||||
@@ -145,7 +145,6 @@
|
||||
"bridgeCount": "ličba serwera: ",
|
||||
"codecs": "kody (A/V): ",
|
||||
"connectedTo": "zwjazane z:",
|
||||
"e2e_rtt": "E2E RTT:",
|
||||
"framerate": " wobrazowospjetna frekwenca:",
|
||||
"less": "mjenje pokazać",
|
||||
"localaddress": "lokalna adresa:",
|
||||
|
||||
@@ -91,7 +91,6 @@
|
||||
"bitrate": "Bitsebesség:",
|
||||
"bridgeCount": "Kiszolgáló száma: ",
|
||||
"connectedTo": "Kapcsolódva ehhez:",
|
||||
"e2e_rtt": "E2E RTT:",
|
||||
"framerate": "Képkockasebesség:",
|
||||
"less": "Kevesebb megjelenítése",
|
||||
"localaddress": "Helyi cím:",
|
||||
|
||||
@@ -90,7 +90,6 @@
|
||||
"bitrate": "Bitrate:",
|
||||
"bridgeCount": "Server count: ",
|
||||
"connectedTo": "Connected to:",
|
||||
"e2e_rtt": "E2E RTT:",
|
||||
"framerate": "Frame rate:",
|
||||
"less": "Show less",
|
||||
"localaddress": "Local address:",
|
||||
|
||||
@@ -90,7 +90,6 @@
|
||||
"bitrate": "Bitahraði:",
|
||||
"bridgeCount": "Fjöldi netþjóna: ",
|
||||
"connectedTo": "Tengt við:",
|
||||
"e2e_rtt": "E2E RTT:",
|
||||
"framerate": "Rammatíðni:",
|
||||
"less": "Sýna minna",
|
||||
"localaddress": "Staðvært vistfang:",
|
||||
|
||||
@@ -145,7 +145,6 @@
|
||||
"bridgeCount": "Conteggio server:",
|
||||
"codecs": "Codec (A/V): ",
|
||||
"connectedTo": "Connesso a:",
|
||||
"e2e_rtt": "E2E RTT:",
|
||||
"framerate": "Fotogrammi al secondo:",
|
||||
"less": "Mostra meno",
|
||||
"localaddress": "Indirizzo locale:",
|
||||
|
||||
@@ -136,7 +136,6 @@
|
||||
"bridgeCount": "サーバー数:",
|
||||
"codecs": "コーデック (A/V): ",
|
||||
"connectedTo": "接続先:",
|
||||
"e2e_rtt": "E2E RTT:",
|
||||
"framerate": "フレームレート:",
|
||||
"less": "表示を減らす",
|
||||
"localaddress": "ローカルアドレス:",
|
||||
|
||||
@@ -114,7 +114,6 @@
|
||||
"bridgeCount": "Amḍan n uqeddac: ",
|
||||
"codecs": "Codecs (A/V) : ",
|
||||
"connectedTo": "Yeqqen ɣer:",
|
||||
"e2e_rtt": "E2E RTT:",
|
||||
"framerate": "Afmiḍi n ukatar:",
|
||||
"less": "Sken-d drus",
|
||||
"localaddress": "Tansa tadigant:",
|
||||
|
||||
@@ -90,7 +90,6 @@
|
||||
"bitrate": "Bitrate:",
|
||||
"bridgeCount": "Serverių skaičius: ",
|
||||
"connectedTo": "Prijungta prie:",
|
||||
"e2e_rtt": "E2E RTT:",
|
||||
"framerate": "Kadrų dažnis:",
|
||||
"less": "Rodyti mažiau",
|
||||
"localaddress": "Vietinis adresas:",
|
||||
|
||||
@@ -90,7 +90,6 @@
|
||||
"bitrate": "Bitreits:",
|
||||
"bridgeCount": "Serveru skaits:",
|
||||
"connectedTo": "Pieslēdzies pie:",
|
||||
"e2e_rtt": "E2E RTT:",
|
||||
"framerate": "Kadru ātrums/skaits:",
|
||||
"less": "Tikai kodolīga informācija",
|
||||
"localaddress": "Lokālā adrese:",
|
||||
|
||||
@@ -106,7 +106,6 @@
|
||||
"bridgeCount": "Server count: ",
|
||||
"codecs": "Codecs (A/V): ",
|
||||
"connectedTo": "Connected to:",
|
||||
"e2e_rtt": "E2E RTT:",
|
||||
"framerate": "Frame rate:",
|
||||
"less": "Show less",
|
||||
"localaddress": "Local address:",
|
||||
|
||||
@@ -90,7 +90,6 @@
|
||||
"bitrate": "Битрат:",
|
||||
"bridgeCount": "Серверийн тоо: ",
|
||||
"connectedTo": "Холбогдсон:",
|
||||
"e2e_rtt": "E2E RTT:",
|
||||
"framerate": "Нягтаршил:",
|
||||
"less": "Хураах",
|
||||
"localaddress": "Дотоод хаяг:",
|
||||
|
||||
@@ -90,7 +90,6 @@
|
||||
"bitrate": "बिटरेट:",
|
||||
"bridgeCount": "सर्व्हर संख्या:",
|
||||
"connectedTo": "यांना जोडलेले:",
|
||||
"e2e_rtt": "E2E आरटीटी:",
|
||||
"framerate": "फ्रेम दर:",
|
||||
"less": "कमी दाखवा",
|
||||
"localaddress": "स्थानिक पत्ता:",
|
||||
|
||||
@@ -134,7 +134,6 @@
|
||||
"bridgeCount": "Aantal servers: ",
|
||||
"codecs": "Codecs (A/V): ",
|
||||
"connectedTo": "Verbonden met:",
|
||||
"e2e_rtt": "E2E RTT:",
|
||||
"framerate": "Framesnelheid:",
|
||||
"less": "Minder weergeven",
|
||||
"localaddress": "Lokaal adres:",
|
||||
@@ -960,6 +959,7 @@
|
||||
"noAudioSignalDialInDesc": "U kunt ook inbellen met:",
|
||||
"noAudioSignalDialInLinkDesc": "Inbelnummers",
|
||||
"noAudioSignalTitle": "Er komt geen invoer van uw microfoon!",
|
||||
"noiseSuppression": "Ruisonderdrukking",
|
||||
"noisyAudioInputDesc": "Het klinkt alsof uw microfoon ruis veroorzaakt. Overweeg te dempen of van apparaat te wisselen.",
|
||||
"noisyAudioInputTitle": "Uw microfoon lijkt ruis te veroorzaken!",
|
||||
"openChat": "Chat openen",
|
||||
|
||||
@@ -136,7 +136,6 @@
|
||||
"bridgeCount": "Nombre de servidor : ",
|
||||
"codecs": "Codecs (A/V) : ",
|
||||
"connectedTo": "Connectat a :",
|
||||
"e2e_rtt": "E2E RTT :",
|
||||
"framerate": "Frequéncia imatge :",
|
||||
"less": "Amagar lo detalh",
|
||||
"localaddress": "Adreça locala :",
|
||||
|
||||
@@ -146,7 +146,6 @@
|
||||
"bridgeCount": "Liczba serwerów: ",
|
||||
"codecs": "Kodeki (A/V): ",
|
||||
"connectedTo": "Podłączone do:",
|
||||
"e2e_rtt": "E2E RTT:",
|
||||
"framerate": "Klatek na sekundę:",
|
||||
"less": "Pokaż mniej",
|
||||
"localaddress": "Adres lokalny:",
|
||||
|
||||
@@ -146,7 +146,6 @@
|
||||
"bridgeCount": "Servidores: ",
|
||||
"codecs": "Codecs (A/V): ",
|
||||
"connectedTo": "Ligado a:",
|
||||
"e2e_rtt": "E2E RTT:",
|
||||
"framerate": "Taxa de frames:",
|
||||
"less": "Mostrar menos",
|
||||
"localaddress": "Endereço local:",
|
||||
|
||||
@@ -114,7 +114,6 @@
|
||||
"bridgeCount": "Servidores: ",
|
||||
"codecs": "Codecs (A/V): ",
|
||||
"connectedTo": "Conectado a:",
|
||||
"e2e_rtt": "E2E RTT:",
|
||||
"framerate": "Taxa de quadros:",
|
||||
"less": "Mostrar menos",
|
||||
"localaddress": "Endereço local:",
|
||||
|
||||
@@ -91,7 +91,6 @@
|
||||
"bitrate": "Bitrate:",
|
||||
"bridgeCount": "Numărul de servere: ",
|
||||
"connectedTo": "Conectat la:",
|
||||
"e2e_rtt": "",
|
||||
"framerate": "Rată cadre:",
|
||||
"less": "Arătați mai puțin",
|
||||
"localaddress": "Adresă locala:",
|
||||
|
||||
@@ -41,11 +41,11 @@
|
||||
},
|
||||
"breakoutRooms": {
|
||||
"actions": {
|
||||
"add": "Добавить комнату отдыха",
|
||||
"autoAssign": "Auto assign to breakout roomsAuto assign to breakout rooms",
|
||||
"add": "Добавить переговорную",
|
||||
"autoAssign": "Привязать к переговорной автоматически",
|
||||
"close": "Закрыть",
|
||||
"join": "Присоединиться",
|
||||
"leaveBreakoutRoom": "Покинуть комнату отдыха",
|
||||
"leaveBreakoutRoom": "Покинуть переговорную",
|
||||
"more": "Больше",
|
||||
"remove": "Удалить",
|
||||
"sendToBreakoutRoom": "Отправить участника к:"
|
||||
@@ -76,6 +76,16 @@
|
||||
"refresh": "Обновить календарь",
|
||||
"today": "Сегодня"
|
||||
},
|
||||
"carmode": {
|
||||
"actions": {
|
||||
"selectSoundDevice": "Выбор аудиоустройства"
|
||||
},
|
||||
"labels": {
|
||||
"buttonLabel": "Упрощенный режим",
|
||||
"title": "Упрощенный режим",
|
||||
"videoStopped": "Видео остановлено"
|
||||
}
|
||||
},
|
||||
"chat": {
|
||||
"enter": "Войди в комнату",
|
||||
"error": "Ошибка: Ваше сообщение не было отправлено. Причина: {{error}}",
|
||||
@@ -134,7 +144,6 @@
|
||||
"bridgeCount": "Количество серверов: ",
|
||||
"codecs": "Кодеки (A/V): ",
|
||||
"connectedTo": "Подключен к:",
|
||||
"e2e_rtt": "E2E RTT:",
|
||||
"framerate": "Частота кадров:",
|
||||
"less": "Краткая информация",
|
||||
"localaddress": "Локальный адрес:",
|
||||
@@ -640,11 +649,11 @@
|
||||
"leftThreePlusMembers": "{{name}} и многие другие покинули встречу",
|
||||
"leftTwoMembers": "{{first}} и {{second}} покинули встречу",
|
||||
"linkToSalesforce": "Ссылка на Salesforce",
|
||||
"linkToSalesforceDescription": "Вы можете отправить ссылку на сводку митинга Salesforce объекту.",
|
||||
"linkToSalesforceError": "Ошибка отправки ссылки на митинг для Salesforce",
|
||||
"linkToSalesforceKey": "Отправить сслку а эот митинг",
|
||||
"linkToSalesforceProgress": "Отправка ссылки на митинг для Salesforce...",
|
||||
"linkToSalesforceSuccess": "Ссылка на этот митинг была отправлена Salesforce",
|
||||
"linkToSalesforceDescription": "Вы можете отправить ссылку на сводку встречи Salesforce объекту.",
|
||||
"linkToSalesforceError": "Ошибка отправки ссылки на встречу для Salesforce",
|
||||
"linkToSalesforceKey": "Отправить ссылку на встречу для Salesforce",
|
||||
"linkToSalesforceProgress": "Отправка ссылки на встречу для Salesforce...",
|
||||
"linkToSalesforceSuccess": "Ссылка на эту встречу для Salesforce была отправлена",
|
||||
"me": "Я",
|
||||
"moderationInEffectCSDescription": "Пожалуйста, поднимите руку, если вы хотите поделиться своим экраном.",
|
||||
"moderationInEffectCSTitle": "Демонстрация экрана заблокирована модератором",
|
||||
@@ -668,8 +677,8 @@
|
||||
"oldElectronClientDescription1": "Похоже, вы используете старую версию клиента {{app}}, которая имеет известные уязвимости в системе безопасности. Убедитесь, что вы обновили до нашей ",
|
||||
"oldElectronClientDescription2": "последней версии",
|
||||
"oldElectronClientDescription3": " сейчас!",
|
||||
"participantWantsToJoin": "Хочет присоединиться к митингу",
|
||||
"participantsWantToJoin": "Хотят присоединиться к митингу",
|
||||
"participantWantsToJoin": "Хочет присоединиться к встрече",
|
||||
"participantsWantToJoin": "Хотят присоединиться к встрече",
|
||||
"passwordRemovedRemotely": "$t(lockRoomPasswordUppercase) удален другим участником.",
|
||||
"passwordSetRemotely": "Другой участник установил $t(lockRoomPasswordUppercase)",
|
||||
"raiseHandAction": "Поднять руку",
|
||||
@@ -799,7 +808,8 @@
|
||||
"iWantToDialIn": "Я хочу дозвониться",
|
||||
"initiated": "Вызов инициирован",
|
||||
"joinAudioByPhone": "Подключиться с телефонной связью",
|
||||
"joinMeeting": "Присоединиться ко встрече",
|
||||
"joinMeeting": "Присоединиться к встрече",
|
||||
"joinMeetingInLowBandwidthMode": "Присоединиться без видео",
|
||||
"joinWithoutAudio": "Присоединиться без звука",
|
||||
"keyboardShortcuts": "Включить сочетания клавиш",
|
||||
"linkCopied": "Ссылка скопирована в буфер обмена",
|
||||
@@ -841,7 +851,7 @@
|
||||
"raisedHandsLabel": "Количество поднятых рук",
|
||||
"record": {
|
||||
"already": {
|
||||
"linked": "Ссылка на митинг уже оправлена Salesforce объекту."
|
||||
"linked": "Ссылка на встречу уже оправлена Salesforce объекту."
|
||||
},
|
||||
"type": {
|
||||
"account": "Аккаунт",
|
||||
@@ -869,7 +879,7 @@
|
||||
"highlightMoment": "Основной момент",
|
||||
"highlightMomentDisabled": "Вы можее обозначить важные моменты когда начнётся запись",
|
||||
"highlightMomentSuccess": "Моменты выделены",
|
||||
"highlightMomentSucessDescription": "Ваши выделенные моменты будут добавлены в итоги митинга.",
|
||||
"highlightMomentSucessDescription": "Ваши выделенные моменты будут добавлены в итоги встречи.",
|
||||
"inProgress": "Идет запись или прямая трансляция",
|
||||
"limitNotificationDescriptionNative": "Из-за высокой нагрузки ваша запись будет ограничена {{limit}} мин. Для неограниченного количества записей попробуйте <3> {{app}} </3>.",
|
||||
"limitNotificationDescriptionWeb": "Из-за высокой нагрузки ваша запись будет ограничена {{limit}} мин. Для неограниченного количества записей попробуйте <a href={{url}} rel='noopener noreferrer' target='_blank'>{{app}}</a>.",
|
||||
@@ -899,7 +909,7 @@
|
||||
"security": {
|
||||
"about": "Вы можете добавить к собранию $t(lockRoomPassword). Участникам необходимо будет предоставить $t(lockRoomPassword), прежде чем им будет разрешено присоединиться к собранию.",
|
||||
"aboutReadOnly": "Участники-модераторы могут добавить к собранию $t(lockRoomPassword). Участникам необходимо будет предоставить $t(lockRoomPassword), прежде чем им будет разрешено присоединиться к собранию.",
|
||||
"header": "",
|
||||
"header": "Настройки безопасности",
|
||||
"insecureRoomNameWarning": "Имя комнаты небезопасно. Нежелательные участники могут присоединиться к вашей конференции. Подумайте о том, чтобы защитить вашу встречу используя настройки безопасности."
|
||||
},
|
||||
"settings": {
|
||||
@@ -1005,8 +1015,9 @@
|
||||
"audioOnly": "Вкл/Выкл только звук",
|
||||
"audioRoute": "Выбрать аудиоустройство",
|
||||
"boo": "Бу",
|
||||
"breakoutRoom": "Присоединиться/выйти из комнаты обсуждения",
|
||||
"breakoutRoom": "Присоединиться/выйти из переговорной",
|
||||
"callQuality": "Качество связи",
|
||||
"carmode": "Упрощенный режим",
|
||||
"cc": "Вкл/Выкл субтитры",
|
||||
"chat": "Показать/скрыть окно чата",
|
||||
"clap": "Хлопок",
|
||||
@@ -1024,7 +1035,8 @@
|
||||
"invite": "Пригласить",
|
||||
"kick": "Отключить участника",
|
||||
"laugh": "Смех",
|
||||
"like": "Пальцы вверх",
|
||||
"leaveConference": "Покинуть встречу",
|
||||
"like": "Палец вверх",
|
||||
"linkToSalesforce": "Ссылка на Salesforce",
|
||||
"lobbyButton": "Вкл/Выкл режим лобби",
|
||||
"localRecording": "Вкл/Выкл кнопки записи",
|
||||
@@ -1065,8 +1077,8 @@
|
||||
"videomute": "Вкл/Выкл видео"
|
||||
},
|
||||
"addPeople": "Добавить людей к вашему сеансу связи",
|
||||
"audioOnlyOff": "Отключить режим экономии пропускной способности",
|
||||
"audioOnlyOn": "Включить режим экономии пропускной способности",
|
||||
"audioOnlyOff": "Включить видео (стандартный режим)",
|
||||
"audioOnlyOn": "Выключить видео (экономичный режим)",
|
||||
"audioRoute": "Выбрать аудиоустройство",
|
||||
"audioSettings": "Настройка звука",
|
||||
"authenticate": "Аутентифицировать",
|
||||
@@ -1091,9 +1103,10 @@
|
||||
"hangup": "Выход",
|
||||
"help": "Справка",
|
||||
"invite": "Пригласить",
|
||||
"joinBreakoutRoom": "Присоединяйтесь к комнате обсуждения",
|
||||
"joinBreakoutRoom": "Войти в переговорную",
|
||||
"laugh": "Смеяться",
|
||||
"leaveBreakoutRoom": "Выйти из комнаты отдыха",
|
||||
"leaveBreakoutRoom": "Покинуть переговорную",
|
||||
"leaveConference": "Покинуть встречу",
|
||||
"like": "Мне нравится",
|
||||
"linkToSalesforce": "Ссылка на Salesforce",
|
||||
"lobbyButtonDisable": "Отключить режим лобби",
|
||||
|
||||
@@ -90,7 +90,6 @@
|
||||
"bitrate": "Velotzidade de bits:",
|
||||
"bridgeCount": "Nùmeru de servidores: ",
|
||||
"connectedTo": "Connessione cun:",
|
||||
"e2e_rtt": "E2E RTT:",
|
||||
"framerate": "Velotzidade de fotogrammas:",
|
||||
"less": "Prus pagu informatziones",
|
||||
"localaddress": "Indiritzu locale:",
|
||||
|
||||
@@ -105,7 +105,6 @@
|
||||
"bitrate": "Prenos. rýchlosť:",
|
||||
"bridgeCount": "Počet serverov: ",
|
||||
"connectedTo": "Spojenie s:",
|
||||
"e2e_rtt": "E2E RTT:",
|
||||
"framerate": "Rýchlosť snímkovania:",
|
||||
"less": "Zobraziť menej",
|
||||
"localaddress": "Lokálna adresa:",
|
||||
|
||||
@@ -114,7 +114,6 @@
|
||||
"bridgeCount": "Število strežnikov: ",
|
||||
"codecs": "Kodeki (A/V): ",
|
||||
"connectedTo": "Povezan v:",
|
||||
"e2e_rtt": "E2E RTT:",
|
||||
"framerate": "Frekvenca slik:",
|
||||
"less": "Prikaži manj",
|
||||
"localaddress": "Lokalni naslov:",
|
||||
|
||||
@@ -136,7 +136,6 @@
|
||||
"bridgeCount": "Numër shërbyesish: ",
|
||||
"codecs": "Kodekë (A/V): ",
|
||||
"connectedTo": "Lidhur te:",
|
||||
"e2e_rtt": "E2E RTT:",
|
||||
"framerate": "Shpejtësi kuadrosh:",
|
||||
"less": "Shfaq më pak",
|
||||
"localaddress": "Adresë vendore:",
|
||||
|
||||
@@ -122,7 +122,6 @@
|
||||
"bridgeCount": "Serverantal: ",
|
||||
"codecs": "Codecs (A/V):",
|
||||
"connectedTo": "Ansluten till:",
|
||||
"e2e_rtt": "E2E RTT:",
|
||||
"framerate": "Bildfrekvens:",
|
||||
"less": "Visa mindre",
|
||||
"localaddress": "Lokal adress:",
|
||||
|
||||
@@ -109,7 +109,6 @@
|
||||
"bridgeCount": "సేవికల సంఖ్య: ",
|
||||
"codecs": "కోడెక్స్ (A/V): ",
|
||||
"connectedTo": "దీనికి అనుసంధానమైంది:",
|
||||
"e2e_rtt": "E2E RTT:",
|
||||
"framerate": "ఫ్రేమ్ రేటు:",
|
||||
"less": "తక్కువ చూపించు",
|
||||
"localaddress": "స్థానిక చిరునామా:",
|
||||
|
||||
@@ -123,7 +123,6 @@
|
||||
"bridgeCount": "Sunucu sayısı: ",
|
||||
"codecs": "Kodekler (A/V): ",
|
||||
"connectedTo": "Bağlandı şuna:",
|
||||
"e2e_rtt": "E2E RTT:",
|
||||
"framerate": "Çerçeve hızı:",
|
||||
"less": "Daha az göster",
|
||||
"localaddress": "Yerel adres:",
|
||||
|
||||
@@ -7,11 +7,10 @@
|
||||
"copyLink": "Скопіювати посилання на зустріч",
|
||||
"copyStream": "Скопіювати посилання на трансляцію наживо",
|
||||
"countryNotSupported": "Дзвінки в цю країну поки що не підтримуються.",
|
||||
"countryReminder": "Дзвінок за межі США? Перевірте наявність коду країни у зазначеному номері!",
|
||||
"countryReminder": "Дзвінок за межі США? Перевірте наявність коду країни в зазначеному номері!",
|
||||
"defaultEmail": "Ваша електронна пошта",
|
||||
"disabled": "Ви не можете запрошувати учасників.",
|
||||
"failedToAdd": "Не вдалося запросити учасника",
|
||||
"footerText": "Вихідні дзвінки вимкнені.",
|
||||
"googleEmail": "Електронна пошта Google",
|
||||
"inviteMoreHeader": "Ви одні на цій зустрічі",
|
||||
"inviteMoreMailSubject": "Приєднатися до зустрічі {{appName}}",
|
||||
@@ -79,7 +78,6 @@
|
||||
},
|
||||
"carmode": {
|
||||
"actions": {
|
||||
"leaveMeeting": " Покинути зустріч",
|
||||
"selectSoundDevice": "Вибрати звуковий пристрій"
|
||||
},
|
||||
"labels": {
|
||||
@@ -98,6 +96,7 @@
|
||||
"messageAccessibleTitleMe": "я пишу:",
|
||||
"messageTo": "Приватне повідомлення для {{recipient}}",
|
||||
"messagebox": "Напишіть повідомлення",
|
||||
"newMessages": "нові повідомлення",
|
||||
"nickname": {
|
||||
"popover": "Виберіть ім'я",
|
||||
"title": "Зазначте ім'я, щоб використовувати чат",
|
||||
@@ -147,7 +146,6 @@
|
||||
"bridgeCount": "Кількість серверів: ",
|
||||
"codecs": "Кодеки (A/V): ",
|
||||
"connectedTo": "З'єднано з:",
|
||||
"e2e_rtt": "E2E RTT:",
|
||||
"framerate": "Частота кадрів:",
|
||||
"less": "Показати менше",
|
||||
"localaddress": "Локальна адреса:",
|
||||
@@ -286,7 +284,6 @@
|
||||
"linkMeetingTitle": "Пов'язати зустріч із Salesforce",
|
||||
"liveStreaming": "Трансляція наживо",
|
||||
"liveStreamingDisabledBecauseOfActiveRecordingTooltip": "Послуга недоступна під час запису",
|
||||
"liveStreamingDisabledTooltip": "Трансляцію наживо вимкнено.",
|
||||
"localUserControls": "Команди керування видом на себе",
|
||||
"lockMessage": "Не вдалося обмежити сторонній доступ",
|
||||
"lockRoom": "Додати $t(lockRoomPassword)",
|
||||
@@ -341,7 +338,6 @@
|
||||
"recentlyUsedObjects": "Нещодавно використані об'єкти",
|
||||
"recording": "Запис",
|
||||
"recordingDisabledBecauseOfActiveLiveStreamingTooltip": "Послуга недоступна під час трансляції наживо",
|
||||
"recordingDisabledTooltip": "Запис вимкнено.",
|
||||
"rejoinNow": "Приєднатися знову",
|
||||
"remoteControlAllowedMessage": "{{user}} погодився на дистанційне керування!",
|
||||
"remoteControlDeniedMessage": "{{user}} відхилив ваш запит на дистанційне керування!",
|
||||
@@ -390,7 +386,7 @@
|
||||
"shareYourScreen": "Спільний перегляд екрана",
|
||||
"shareYourScreenDisabled": "Спільний перегляд екрана вимкнено.",
|
||||
"sharedVideoDialogError": "Помилка: недійсна URL-адреса",
|
||||
"sharedVideoLinkPlaceholder": "Посилання на YouTube або посилання на файл відео",
|
||||
"sharedVideoLinkPlaceholder": "Посилання на YouTube або на файл відео",
|
||||
"start": "Почати ",
|
||||
"startLiveStreaming": "Почати трансляцію наживо",
|
||||
"startRecording": "Почати запис",
|
||||
@@ -646,7 +642,7 @@
|
||||
"connectedThreePlusMembers": "{{name}} та {{count}} інших учасників приєдналися до зустрічі",
|
||||
"connectedTwoMembers": "{{first}} та {{second}} приєдналися до зустрічі",
|
||||
"disconnected": "з'єднання розірване",
|
||||
"displayNotifications": "Показувати сповіщення для",
|
||||
"displayNotifications": "Показувати сповіщення:",
|
||||
"focus": "Фокус зустрічі",
|
||||
"focusFail": "{{component}} недоступний - повторіть спробу через {{ms}} мс",
|
||||
"gifsMenu": "GIPHY",
|
||||
@@ -763,7 +759,7 @@
|
||||
"create": "Створити опитування",
|
||||
"pollOption": "Варіант відповіді {{index}}",
|
||||
"pollQuestion": "Питання",
|
||||
"questionPlaceholder": "Задайте питання",
|
||||
"questionPlaceholder": "Поставте запитання",
|
||||
"removeOption": "Вилучити",
|
||||
"send": "Надіслати"
|
||||
},
|
||||
@@ -939,7 +935,7 @@
|
||||
"about": "Ви можете додати $t(lockRoomPassword) для захисту вашої зустрічі. Учасникам потрібно буде ввести $t(lockRoomPassword), перш ніж їм буде дозволено приєднатися до зустрічі.",
|
||||
"aboutReadOnly": "Модератори можуть додати $t(lockRoomPassword) для захисту зустрічі. Учасникам потрібно буде ввести $t(lockRoomPassword), перш ніж їм буде дозволено приєднатися до зустрічі.",
|
||||
"header": "Параметри безпеки",
|
||||
"insecureRoomNameWarning": "Назва кімнати не є безпечною. Сторонні можуть приєднатися до вашої зустрічі. Подбайте про захист вашої зустрічі за допомогою налаштувань параметрів безпеки."
|
||||
"insecureRoomNameWarning": "Назва кімнати не є безпечною. Сторонні люди можуть приєднатися до вашої зустрічі. Подбайте про додатковий захист вашої зустрічі за допомогою налаштувань параметрів безпеки."
|
||||
},
|
||||
"settings": {
|
||||
"buttonLabel": "Налаштування",
|
||||
@@ -969,7 +965,7 @@
|
||||
"participantKnocking": "Учасник зайшов у приймальну",
|
||||
"participantLeft": "Учасник покинув зустріч",
|
||||
"playSounds": "Увімкнути звукові сповіщення:",
|
||||
"reactions": "Реакції під час зустрічі",
|
||||
"reactions": "Емоційна реакція",
|
||||
"sameAsSystem": "Системний пристрій ({{label}})",
|
||||
"screenTitle": "Налаштування",
|
||||
"selectAudioOutput": "Вивід звуку",
|
||||
@@ -1066,6 +1062,7 @@
|
||||
"document": "Відкрити/закрити спільний документ",
|
||||
"download": "Звантажити мобільний застосунок",
|
||||
"embedMeeting": "Вставити зустріч",
|
||||
"endConference": "Завершити зустріч для всіх",
|
||||
"expand": "Розгорнути",
|
||||
"feedback": "Залишити відгук",
|
||||
"fullScreen": "На весь екран",
|
||||
@@ -1076,6 +1073,7 @@
|
||||
"invite": "Запросити на зустріч",
|
||||
"kick": "Від'єднати учасника",
|
||||
"laugh": "Сміюся",
|
||||
"leaveConference": "Покинути зустріч",
|
||||
"like": "Подобається",
|
||||
"linkToSalesforce": "Пов'язати з Salesforce",
|
||||
"lobbyButton": "Увімкнути/вимкнути приймальну",
|
||||
@@ -1138,6 +1136,7 @@
|
||||
"download": "Звантажити мобільний застосунок",
|
||||
"e2ee": "Наскрізне шифрування",
|
||||
"embedMeeting": "Вставити зустріч",
|
||||
"endConference": "Завершити зустріч для всіх",
|
||||
"enterFullScreen": "На весь екран",
|
||||
"enterTileView": "Режим плиток",
|
||||
"exitFullScreen": "Вийти з повноекранного режиму",
|
||||
@@ -1150,6 +1149,7 @@
|
||||
"joinBreakoutRoom": "Приєднатися до кімнати підгрупи",
|
||||
"laugh": "сміюся",
|
||||
"leaveBreakoutRoom": "Вийти з кімнати підгрупи",
|
||||
"leaveConference": "Покинути зустріч",
|
||||
"like": "подобається",
|
||||
"linkToSalesforce": "Пов'язати з Salesforce",
|
||||
"lobbyButtonDisable": "Вимкнути приймальну",
|
||||
@@ -1181,7 +1181,7 @@
|
||||
"reactionBoo": "Надіслати реакцію «невдоволення»",
|
||||
"reactionClap": "Надіслати реакцію «овації»",
|
||||
"reactionLaugh": "Надіслати реакцію «сміюся»",
|
||||
"reactionLike": "Надіслати реакцію \"подобається\"",
|
||||
"reactionLike": "Надіслати реакцію «подобається»",
|
||||
"reactionSilence": "Надіслати реакцію «тиша»",
|
||||
"reactionSurprised": "Надіслати реакцію «подив»",
|
||||
"security": "Параметри безпеки",
|
||||
@@ -1193,7 +1193,7 @@
|
||||
"silence": "тиша",
|
||||
"speakerStats": "Статистика спілкування",
|
||||
"startScreenSharing": "Увімкнути спільний перегляд екрана",
|
||||
"startSubtitles": "Показувати субтитри",
|
||||
"startSubtitles": "Субтитри • {{language}}",
|
||||
"stopAudioSharing": "Зупинити спільне аудіо",
|
||||
"stopScreenSharing": "Вимкнути спільний перегляд екрана",
|
||||
"stopSharedVideo": "Зупинити спільне відео",
|
||||
@@ -1216,6 +1216,8 @@
|
||||
"pending": "Підготовка до транскрибування зустрічі...",
|
||||
"start": "Показувати субтитри",
|
||||
"stop": "Припинити показ субтитрів",
|
||||
"subtitles": "Субтитри",
|
||||
"subtitlesOff": "Вимкнені",
|
||||
"tr": "TR"
|
||||
},
|
||||
"userMedia": {
|
||||
@@ -1341,7 +1343,7 @@
|
||||
"mobileDownLoadLinkAndroid": "Завантажте мобільний застосунок для Android",
|
||||
"mobileDownLoadLinkFDroid": "Завантажте мобільний застосунок для F-Droid",
|
||||
"mobileDownLoadLinkIos": "Завантажте мобільний застосунок для iOS",
|
||||
"moderatedMessage": "Або <a href=\"{{url}}\" rel=\"noopener noreferrer\" target=\"_blank\">організуйте модеровану зустріч</a>, і розпочніть її як модератор.",
|
||||
"moderatedMessage": "Або <a href=\"{{url}}\" rel=\"noopener noreferrer\" target=\"_blank\">організуйте модеровану зустріч</a> і розпочніть її як модератор.",
|
||||
"privacy": "Конфіденційність",
|
||||
"recentList": "Нещодавні",
|
||||
"recentListDelete": "Вилучити",
|
||||
|
||||
@@ -106,7 +106,6 @@
|
||||
"bridgeCount": "服务器数量:",
|
||||
"codecs": "编解码器(A / V):",
|
||||
"connectedTo": "连接到:",
|
||||
"e2e_rtt": "端到端时延 RTT:",
|
||||
"framerate": "帧率:",
|
||||
"less": "显示更少",
|
||||
"localaddress": "本地地址:",
|
||||
|
||||
@@ -135,7 +135,6 @@
|
||||
"bridgeCount": "伺服器數量:",
|
||||
"codecs": "編碼 (A/V):",
|
||||
"connectedTo": "已連接至:",
|
||||
"e2e_rtt": "E2E RTT:",
|
||||
"framerate": "影格率:",
|
||||
"less": "顯示較少",
|
||||
"localaddress": "本機位址:",
|
||||
|
||||
@@ -146,7 +146,6 @@
|
||||
"bridgeCount": "Server count: ",
|
||||
"codecs": "Codecs (A/V): ",
|
||||
"connectedTo": "Connected to:",
|
||||
"e2e_rtt": "E2E RTT:",
|
||||
"framerate": "Frame rate:",
|
||||
"less": "Show less",
|
||||
"localaddress": "Local address:",
|
||||
|
||||
@@ -55,7 +55,7 @@ import {
|
||||
removeBreakoutRoom,
|
||||
sendParticipantToRoom
|
||||
} from '../../react/features/breakout-rooms/actions';
|
||||
import { getBreakoutRooms } from '../../react/features/breakout-rooms/functions';
|
||||
import { getBreakoutRooms, getRoomsInfo } from '../../react/features/breakout-rooms/functions';
|
||||
import {
|
||||
sendMessage,
|
||||
setPrivateMessageRecipient,
|
||||
@@ -68,7 +68,7 @@ import {
|
||||
import { appendSuffix } from '../../react/features/display-name';
|
||||
import { isEnabled as isDropboxEnabled } from '../../react/features/dropbox';
|
||||
import { setMediaEncryptionKey, toggleE2EE } from '../../react/features/e2ee/actions';
|
||||
import { setVolume } from '../../react/features/filmstrip';
|
||||
import { resizeFilmStrip, setVolume } from '../../react/features/filmstrip/actions.web';
|
||||
import { invite } from '../../react/features/invite';
|
||||
import {
|
||||
selectParticipantInLargeVideo
|
||||
@@ -308,6 +308,16 @@ function initCommands() {
|
||||
sendAnalytics(createApiEvent('film.strip.toggled'));
|
||||
APP.UI.toggleFilmstrip();
|
||||
},
|
||||
|
||||
/*
|
||||
* @param {Object} options - Additional details of how to perform
|
||||
* the action.
|
||||
* @param {number} options.width - width value for film strip.
|
||||
*/
|
||||
'resize-film-strip': (options = {}) => {
|
||||
sendAnalytics(createApiEvent('film.strip.resize'));
|
||||
APP.store.dispatch(resizeFilmStrip(options.width));
|
||||
},
|
||||
'toggle-camera': () => {
|
||||
if (!isToggleCameraEnabled(APP.store.getState())) {
|
||||
return;
|
||||
@@ -846,6 +856,10 @@ function initCommands() {
|
||||
callback(getBreakoutRooms(APP.store.getState()));
|
||||
break;
|
||||
}
|
||||
case 'rooms-info': {
|
||||
callback(getRoomsInfo(APP.store.getState()));
|
||||
break;
|
||||
}
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
@@ -1783,7 +1797,7 @@ class API {
|
||||
/**
|
||||
* Notify external application that the breakout rooms changed.
|
||||
*
|
||||
* @param {Array} rooms - Array of breakout rooms.
|
||||
* @param {Array} rooms - Array containing the breakout rooms and main room.
|
||||
* @returns {void}
|
||||
*/
|
||||
notifyBreakoutRoomsUpdated(rooms) {
|
||||
|
||||
40
modules/API/external/external_api.js
vendored
40
modules/API/external/external_api.js
vendored
@@ -52,6 +52,7 @@ const commands = {
|
||||
pinParticipant: 'pin-participant',
|
||||
rejectParticipant: 'reject-participant',
|
||||
removeBreakoutRoom: 'remove-breakout-room',
|
||||
resizeFilmStrip: 'resize-film-strip',
|
||||
resizeLargeVideo: 'resize-large-video',
|
||||
sendChatMessage: 'send-chat-message',
|
||||
sendEndpointTextMessage: 'send-endpoint-text-message',
|
||||
@@ -619,6 +620,9 @@ export default class JitsiMeetExternalAPI extends EventEmitter {
|
||||
case 'video-quality-changed':
|
||||
this._videoQuality = data.videoQuality;
|
||||
break;
|
||||
case 'breakout-rooms-updated':
|
||||
this.updateNumberOfParticipants(data.rooms);
|
||||
break;
|
||||
case 'local-storage-changed':
|
||||
jitsiLocalStorage.setItem('jitsiLocalStorage', data.localStorageContent);
|
||||
|
||||
@@ -638,6 +642,40 @@ export default class JitsiMeetExternalAPI extends EventEmitter {
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Update number of participants based on all rooms.
|
||||
*
|
||||
* @param {Object} rooms - Rooms available rooms in the conference.
|
||||
* @returns {void}
|
||||
*/
|
||||
updateNumberOfParticipants(rooms) {
|
||||
if (!rooms || !Object.keys(rooms).length) {
|
||||
return;
|
||||
}
|
||||
|
||||
const allParticipants = Object.keys(rooms).reduce((prev, roomItemKey) => {
|
||||
if (rooms[roomItemKey]?.participants) {
|
||||
return Object.keys(rooms[roomItemKey].participants).length + prev;
|
||||
}
|
||||
|
||||
return prev;
|
||||
}, 0);
|
||||
|
||||
this._numberOfParticipants = allParticipants;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the rooms info in the conference.
|
||||
*
|
||||
* @returns {Object} Rooms info.
|
||||
*/
|
||||
async getRoomsInfo() {
|
||||
return this._transport.sendRequest({
|
||||
name: 'rooms-info'
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds event listener to Meet Jitsi.
|
||||
*
|
||||
@@ -1101,7 +1139,7 @@ export default class JitsiMeetExternalAPI extends EventEmitter {
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the number of participants in the conference. The local
|
||||
* Returns the number of participants in the conference from all rooms. The local
|
||||
* participant is included.
|
||||
*
|
||||
* @returns {int} The number of participants in the conference.
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
/* global APP, $, config */
|
||||
/* global APP, config */
|
||||
|
||||
|
||||
const UI = {};
|
||||
|
||||
import Logger from '@jitsi/logger';
|
||||
import EventEmitter from 'events';
|
||||
import $ from 'jquery';
|
||||
|
||||
import { isMobileBrowser } from '../../react/features/base/environment/utils';
|
||||
import { setColorAlpha } from '../../react/features/base/util';
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
/* global $, APP, interfaceConfig */
|
||||
/* global APP, interfaceConfig */
|
||||
|
||||
import $ from 'jquery';
|
||||
|
||||
import { getSharedDocumentUrl, setDocumentEditingState } from '../../../react/features/etherpad';
|
||||
import { getToolboxHeight } from '../../../react/features/toolbox/functions.web';
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* global $ */
|
||||
import $ from 'jquery';
|
||||
|
||||
/**
|
||||
* Created by hristo on 12/22/14.
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
/* global $, APP, interfaceConfig */
|
||||
/* global APP, interfaceConfig */
|
||||
|
||||
import $ from 'jquery';
|
||||
|
||||
import { getVerticalFilmstripVisibleAreaWidth, isFilmstripVisible } from '../../../react/features/filmstrip';
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
/* global $, APP */
|
||||
/* global APP */
|
||||
/* eslint-disable no-unused-vars */
|
||||
import Logger from '@jitsi/logger';
|
||||
import $ from 'jquery';
|
||||
import React from 'react';
|
||||
import ReactDOM from 'react-dom';
|
||||
import { I18nextProvider } from 'react-i18next';
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
/* global $, APP, interfaceConfig */
|
||||
/* global APP, interfaceConfig */
|
||||
|
||||
/* eslint-disable no-unused-vars */
|
||||
import $ from 'jquery';
|
||||
import React from 'react';
|
||||
import ReactDOM from 'react-dom';
|
||||
|
||||
@@ -8,6 +9,7 @@ import { browser } from '../../../react/features/base/lib-jitsi-meet';
|
||||
import { isTestModeEnabled } from '../../../react/features/base/testing';
|
||||
import { FILMSTRIP_BREAKPOINT } from '../../../react/features/filmstrip';
|
||||
import { ORIENTATION, LargeVideoBackground, updateLastLargeVideoMediaEvent } from '../../../react/features/large-video';
|
||||
import { setLargeVideoDimensions } from '../../../react/features/large-video/actions.any';
|
||||
import { LAYOUTS, getCurrentLayout } from '../../../react/features/video-layout';
|
||||
/* eslint-enable no-unused-vars */
|
||||
import UIUtil from '../util/UIUtil';
|
||||
@@ -445,6 +447,8 @@ export class VideoContainer extends LargeContainer {
|
||||
const { horizontalIndent, verticalIndent }
|
||||
= this.getVideoPosition(width, height, containerWidth, containerHeight, verticalFilmstripWidth);
|
||||
|
||||
APP.store.dispatch(setLargeVideoDimensions(height, width));
|
||||
|
||||
this.$wrapper.animate({
|
||||
width,
|
||||
height,
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
import Logger from '@jitsi/logger';
|
||||
|
||||
import { getSourceNameSignalingFeatureFlag } from '../../../react/features/base/config';
|
||||
import { getMultipleVideoSupportFeatureFlag } from '../../../react/features/base/config';
|
||||
import { MEDIA_TYPE, VIDEO_TYPE } from '../../../react/features/base/media';
|
||||
import {
|
||||
getPinnedParticipant,
|
||||
@@ -95,7 +95,7 @@ const VideoLayout = {
|
||||
return VIDEO_TYPE.CAMERA;
|
||||
}
|
||||
|
||||
if (getSourceNameSignalingFeatureFlag(state) && participant?.isVirtualScreenshareParticipant) {
|
||||
if (getMultipleVideoSupportFeatureFlag(state) && participant?.isVirtualScreenshareParticipant) {
|
||||
return VIDEO_TYPE.DESKTOP;
|
||||
}
|
||||
|
||||
@@ -190,7 +190,7 @@ const VideoLayout = {
|
||||
|
||||
let videoTrack;
|
||||
|
||||
if (getSourceNameSignalingFeatureFlag(state) && participant?.isVirtualScreenshareParticipant) {
|
||||
if (getMultipleVideoSupportFeatureFlag(state) && participant?.isVirtualScreenshareParticipant) {
|
||||
videoTrack = getVirtualScreenshareParticipantTrack(tracks, id);
|
||||
} else {
|
||||
videoTrack = getTrackByMediaTypeAndParticipant(tracks, MEDIA_TYPE.VIDEO, id);
|
||||
@@ -218,7 +218,6 @@ const VideoLayout = {
|
||||
if (!isOnLarge || forceUpdate) {
|
||||
const videoType = this.getRemoteVideoType(id);
|
||||
|
||||
|
||||
largeVideo.updateLargeVideo(
|
||||
id,
|
||||
videoStream,
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
/* @flow */
|
||||
|
||||
import $ from 'jquery';
|
||||
import jqueryI18next from 'jquery-i18next';
|
||||
|
||||
import { i18next } from '../../react/features/base/i18n';
|
||||
|
||||
declare var $: Function;
|
||||
|
||||
type DocumentElement = {
|
||||
lang: string
|
||||
|
||||
1937
package-lock.json
generated
1937
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
18
package.json
18
package.json
@@ -28,6 +28,8 @@
|
||||
"@atlaskit/tabs": "12.1.2",
|
||||
"@atlaskit/theme": "11.0.2",
|
||||
"@atlaskit/tooltip": "17.1.2",
|
||||
"@emotion/react": "11.10.0",
|
||||
"@emotion/styled": "11.10.0",
|
||||
"@giphy/js-fetch-api": "4.1.2",
|
||||
"@giphy/react-components": "5.6.0",
|
||||
"@giphy/react-native-sdk": "1.7.0",
|
||||
@@ -35,10 +37,11 @@
|
||||
"@jitsi/js-utils": "2.0.3",
|
||||
"@jitsi/logger": "2.0.0",
|
||||
"@jitsi/rnnoise-wasm": "0.1.0",
|
||||
"@jitsi/rtcstats": "9.2.0",
|
||||
"@material-ui/core": "4.11.3",
|
||||
"@jitsi/rtcstats": "9.3.0",
|
||||
"@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",
|
||||
"@mui/material": "5.10.2",
|
||||
"@mui/styles": "5.10.2",
|
||||
"@react-native-async-storage/async-storage": "1.15.14",
|
||||
"@react-native-community/clipboard": "1.5.1",
|
||||
"@react-native-community/netinfo": "7.1.7",
|
||||
@@ -54,6 +57,7 @@
|
||||
"@tensorflow/tfjs-backend-wasm": "3.13.0",
|
||||
"@tensorflow/tfjs-core": "3.13.0",
|
||||
"@types/audioworklet": "0.0.29",
|
||||
"@types/w3c-image-capture": "1.0.6",
|
||||
"@vladmandic/human": "2.6.5",
|
||||
"@vladmandic/human-models": "2.5.9",
|
||||
"@xmldom/xmldom": "0.7.5",
|
||||
@@ -70,12 +74,12 @@
|
||||
"i18next-browser-languagedetector": "3.0.1",
|
||||
"i18next-xhr-backend": "3.0.0",
|
||||
"image-capture": "0.4.0",
|
||||
"jquery": "3.5.1",
|
||||
"jquery": "3.6.1",
|
||||
"jquery-i18next": "1.2.1",
|
||||
"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/v1494.0.0+c9be46e2/lib-jitsi-meet.tgz",
|
||||
"lib-jitsi-meet": "https://github.com/jitsi/lib-jitsi-meet/releases/download/v1498.0.0+bc3aae02/lib-jitsi-meet.tgz",
|
||||
"lodash": "4.17.21",
|
||||
"moment": "2.29.4",
|
||||
"moment-duration-format": "2.2.2",
|
||||
@@ -123,10 +127,11 @@
|
||||
"react-window": "1.8.6",
|
||||
"react-youtube": "7.13.1",
|
||||
"redux": "4.0.4",
|
||||
"redux-thunk": "2.2.0",
|
||||
"redux-thunk": "2.4.1",
|
||||
"resemblejs": "4.0.0",
|
||||
"seamless-scroll-polyfill": "2.1.8",
|
||||
"styled-components": "3.4.9",
|
||||
"tss-react": "4.0.0",
|
||||
"util": "0.12.1",
|
||||
"uuid": "8.3.2",
|
||||
"wasm-check": "2.0.1",
|
||||
@@ -142,7 +147,7 @@
|
||||
"@babel/preset-flow": "7.16.0",
|
||||
"@babel/preset-react": "7.16.0",
|
||||
"@babel/runtime": "7.16.0",
|
||||
"@jitsi/eslint-config": "4.0.0",
|
||||
"@jitsi/eslint-config": "4.1.2",
|
||||
"@types/js-md5": "0.4.3",
|
||||
"@types/lodash": "4.14.182",
|
||||
"@types/react": "17.0.14",
|
||||
@@ -166,7 +171,6 @@
|
||||
"eslint-plugin-react": "7.26.1",
|
||||
"eslint-plugin-react-native": "3.11.0",
|
||||
"eslint-plugin-typescript-sort-keys": "2.1.0",
|
||||
"expose-loader": "3.0.0",
|
||||
"imports-loader": "0.7.1",
|
||||
"jetifier": "1.6.4",
|
||||
"metro-react-native-babel-preset": "0.67.0",
|
||||
|
||||
@@ -9,25 +9,7 @@ module.exports = {
|
||||
'overrides': [
|
||||
{
|
||||
'files': [ '*.ts', '*.tsx' ],
|
||||
parser: '@typescript-eslint/parser',
|
||||
rules: {
|
||||
'no-undef': 'off',
|
||||
'no-use-before-define': 'off',
|
||||
'@typescript-eslint/ban-ts-comment': 'off',
|
||||
'@typescript-eslint/no-empty-function': 'off',
|
||||
'@typescript-eslint/ban-types': 'off',
|
||||
'@typescript-eslint/no-explicit-any': 'off',
|
||||
'no-prototype-builtins': 'off',
|
||||
'no-shadow': 'off',
|
||||
'@typescript-eslint/no-shadow': [ 'error' ],
|
||||
'typescript-sort-keys/interface': 'error',
|
||||
'typescript-sort-keys/string-enum': 'error'
|
||||
},
|
||||
'plugins': [ '@typescript-eslint', 'typescript-sort-keys' ],
|
||||
'extends': [
|
||||
'plugin:@typescript-eslint/eslint-recommended',
|
||||
'plugin:@typescript-eslint/recommended'
|
||||
]
|
||||
extends: [ '@jitsi/eslint-config/typescript' ]
|
||||
}
|
||||
],
|
||||
'rules': {
|
||||
|
||||
@@ -72,13 +72,13 @@ export const VIDEO_MUTE = 'video.mute';
|
||||
* Creates an event which indicates that a certain action was requested through
|
||||
* the jitsi-meet API.
|
||||
*
|
||||
* @param {Object} action - The action which was requested through the
|
||||
* @param {string} action - The action which was requested through the
|
||||
* jitsi-meet API.
|
||||
* @param {Object} attributes - Attributes to attach to the event.
|
||||
* @returns {Object} The event in a format suitable for sending via
|
||||
* sendAnalytics.
|
||||
*/
|
||||
export function createApiEvent(action, attributes = {}) {
|
||||
export function createApiEvent(action: string, attributes = {}) {
|
||||
return {
|
||||
action,
|
||||
attributes,
|
||||
@@ -93,7 +93,7 @@ export function createApiEvent(action, attributes = {}) {
|
||||
* @returns {Object} The event in a format suitable for sending via
|
||||
* sendAnalytics.
|
||||
*/
|
||||
export function createAudioOnlyChangedEvent(enabled) {
|
||||
export function createAudioOnlyChangedEvent(enabled: boolean) {
|
||||
return {
|
||||
action: `audio.only.${enabled ? 'enabled' : 'disabled'}`
|
||||
};
|
||||
@@ -107,7 +107,7 @@ export function createAudioOnlyChangedEvent(enabled) {
|
||||
* @returns {Object} The event in a format suitable for sending via
|
||||
* sendAnalytics.
|
||||
*/
|
||||
export function createConnectionEvent(action, attributes = {}) {
|
||||
export function createConnectionEvent(action: string, attributes = {}) {
|
||||
return {
|
||||
action,
|
||||
actionSubject: 'connection',
|
||||
@@ -124,7 +124,7 @@ export function createConnectionEvent(action, attributes = {}) {
|
||||
* @returns {Object} The event in a format suitable for sending via
|
||||
* sendAnalytics.
|
||||
*/
|
||||
export function createCalendarClickedEvent(eventName, attributes = {}) {
|
||||
export function createCalendarClickedEvent(eventName: string, attributes = {}) {
|
||||
return {
|
||||
action: 'clicked',
|
||||
actionSubject: eventName,
|
||||
@@ -175,7 +175,7 @@ export function createCalendarConnectedEvent(attributes = {}) {
|
||||
* @returns {Object} The event in a format suitable for sending via
|
||||
* sendAnalytics.
|
||||
*/
|
||||
export function createRecentClickedEvent(eventName, attributes = {}) {
|
||||
export function createRecentClickedEvent(eventName: string, attributes = {}) {
|
||||
return {
|
||||
action: 'clicked',
|
||||
actionSubject: eventName,
|
||||
@@ -193,7 +193,7 @@ export function createRecentClickedEvent(eventName, attributes = {}) {
|
||||
* @returns {Object} The event in a format suitable for sending via
|
||||
* sendAnalytics.
|
||||
*/
|
||||
export function createChromeExtensionBannerEvent(installPressed, attributes = {}) {
|
||||
export function createChromeExtensionBannerEvent(installPressed: boolean, attributes = {}) {
|
||||
return {
|
||||
action: installPressed ? 'install' : 'cancel',
|
||||
attributes,
|
||||
@@ -229,7 +229,7 @@ export function createRecentSelectedEvent(attributes = {}) {
|
||||
* sendAnalytics.
|
||||
*/
|
||||
export function createDeepLinkingPageEvent(
|
||||
action, actionSubject, attributes = {}) {
|
||||
action: string, actionSubject: string, attributes = {}) {
|
||||
return {
|
||||
action,
|
||||
actionSubject,
|
||||
@@ -247,7 +247,7 @@ export function createDeepLinkingPageEvent(
|
||||
* @returns {Object} The event in a format suitable for sending via
|
||||
* sendAnalytics.
|
||||
*/
|
||||
export function createDeviceChangedEvent(mediaType, deviceType) {
|
||||
export function createDeviceChangedEvent(mediaType: string, deviceType: string) {
|
||||
return {
|
||||
action: 'device.changed',
|
||||
attributes: {
|
||||
@@ -264,7 +264,7 @@ export function createDeviceChangedEvent(mediaType, deviceType) {
|
||||
* @returns {Object} The event in a format suitable for sending via
|
||||
* sendAnalytics.
|
||||
*/
|
||||
export function createE2EEEvent(action) {
|
||||
export function createE2EEEvent(action: string) {
|
||||
return {
|
||||
action,
|
||||
actionSubject: 'e2ee'
|
||||
@@ -293,7 +293,7 @@ export function createFeedbackOpenEvent() {
|
||||
* sendAnalytics.
|
||||
*/
|
||||
export function createInviteDialogEvent(
|
||||
action, actionSubject, attributes = {}) {
|
||||
action: string, actionSubject: string, attributes = {}) {
|
||||
return {
|
||||
action,
|
||||
actionSubject,
|
||||
@@ -310,8 +310,13 @@ export function createInviteDialogEvent(
|
||||
* @param {Object} [details] - Extra info, see {@code NetworkInfo} type defined by the 'base/net-info' feature.
|
||||
* @returns {Object}
|
||||
*/
|
||||
export function createNetworkInfoEvent({ isOnline, networkType, details }) {
|
||||
const attributes = { isOnline };
|
||||
export function createNetworkInfoEvent({ isOnline, networkType, details }:
|
||||
{ details?: Object; isOnline: boolean; networkType?: string; }) {
|
||||
const attributes: {
|
||||
details?: Object;
|
||||
isOnline: boolean;
|
||||
networkType?: string;
|
||||
} = { isOnline };
|
||||
|
||||
// Do no include optional stuff or Amplitude handler will log warnings.
|
||||
networkType && (attributes.networkType = networkType);
|
||||
@@ -345,7 +350,7 @@ export function createOfferAnswerFailedEvent() {
|
||||
* @returns {Object} The event in a format suitable for sending via
|
||||
* sendAnalytics.
|
||||
*/
|
||||
export function createPageReloadScheduledEvent(reason, timeout, details) {
|
||||
export function createPageReloadScheduledEvent(reason: string, timeout: number, details: Object) {
|
||||
return {
|
||||
action: 'page.reload.scheduled',
|
||||
attributes: {
|
||||
@@ -365,7 +370,7 @@ export function createPageReloadScheduledEvent(reason, timeout, details) {
|
||||
* @returns {Object} The event in a format suitable for sending via
|
||||
* sendAnalytics.
|
||||
*/
|
||||
export function createPinnedEvent(action, participantId, attributes) {
|
||||
export function createPinnedEvent(action: string, participantId: string, attributes = {}) {
|
||||
return {
|
||||
type: TYPE_TRACK,
|
||||
action,
|
||||
@@ -392,7 +397,7 @@ export function createPinnedEvent(action, participantId, attributes) {
|
||||
* @param {string} action - The action.
|
||||
* @returns {Object}
|
||||
*/
|
||||
export function createPollEvent(action) {
|
||||
export function createPollEvent(action: string) {
|
||||
return {
|
||||
action: `poll.${action}`
|
||||
};
|
||||
@@ -407,7 +412,7 @@ export function createPollEvent(action) {
|
||||
* @returns {Object} The event in a format suitable for sending via
|
||||
* sendAnalytics.
|
||||
*/
|
||||
export function createProfilePanelButtonEvent(buttonName, attributes = {}) {
|
||||
export function createProfilePanelButtonEvent(buttonName: string, attributes = {}) {
|
||||
return {
|
||||
action: 'clicked',
|
||||
actionSubject: buttonName,
|
||||
@@ -429,7 +434,7 @@ export function createProfilePanelButtonEvent(buttonName, attributes = {}) {
|
||||
* sendAnalytics.
|
||||
*/
|
||||
export function createRecordingDialogEvent(
|
||||
dialogName, buttonName, attributes = {}) {
|
||||
dialogName: string, buttonName: string, attributes = {}) {
|
||||
return {
|
||||
action: 'clicked',
|
||||
actionSubject: buttonName,
|
||||
@@ -449,7 +454,7 @@ export function createRecordingDialogEvent(
|
||||
* @returns {Object} The event in a format suitable for sending via
|
||||
* sendAnalytics.
|
||||
*/
|
||||
export function createLiveStreamingDialogEvent(dialogName, buttonName) {
|
||||
export function createLiveStreamingDialogEvent(dialogName: string, buttonName: string) {
|
||||
return {
|
||||
action: 'clicked',
|
||||
actionSubject: buttonName,
|
||||
@@ -465,7 +470,14 @@ export function createLiveStreamingDialogEvent(dialogName, buttonName) {
|
||||
* @returns {Object} The event in a format suitable for sending via
|
||||
* sendAnalytics.
|
||||
*/
|
||||
export function createLocalTracksDurationEvent(duration) {
|
||||
export function createLocalTracksDurationEvent(duration: {
|
||||
audio: { value: number; };
|
||||
conference: { value: number; };
|
||||
video: {
|
||||
camera: { value: number; };
|
||||
desktop: { value: number; };
|
||||
};
|
||||
}) {
|
||||
const { audio, video, conference } = duration;
|
||||
const { camera, desktop } = video;
|
||||
|
||||
@@ -491,7 +503,7 @@ export function createLocalTracksDurationEvent(duration) {
|
||||
* @returns {Object} The event in a format suitable for sending via
|
||||
* sendAnalytics.
|
||||
*/
|
||||
export function createRecordingEvent(action, type, value) {
|
||||
export function createRecordingEvent(action: string, type: string, value: number) {
|
||||
return {
|
||||
action,
|
||||
actionSubject: `recording.${type}`,
|
||||
@@ -509,7 +521,11 @@ export function createRecordingEvent(action, type, value) {
|
||||
* @param {number} timeSinceLeft - How many seconds since the last conference was left.
|
||||
* @returns {Object} The event in a format suitable for sending via sendAnalytics.
|
||||
*/
|
||||
export function createRejoinedEvent({ url, lastConferenceDuration, timeSinceLeft }) {
|
||||
export function createRejoinedEvent({ url, lastConferenceDuration, timeSinceLeft }: {
|
||||
lastConferenceDuration: number;
|
||||
timeSinceLeft: number;
|
||||
url: string;
|
||||
}) {
|
||||
return {
|
||||
action: 'rejoined',
|
||||
attributes: {
|
||||
@@ -530,7 +546,7 @@ export function createRejoinedEvent({ url, lastConferenceDuration, timeSinceLeft
|
||||
* @returns {Object} The event in a format suitable for sending via
|
||||
* sendAnalytics.
|
||||
*/
|
||||
export function createRemoteMuteConfirmedEvent(participantId, mediaType) {
|
||||
export function createRemoteMuteConfirmedEvent(participantId: string, mediaType: string) {
|
||||
return {
|
||||
action: 'clicked',
|
||||
attributes: {
|
||||
@@ -551,7 +567,7 @@ export function createRemoteMuteConfirmedEvent(participantId, mediaType) {
|
||||
* @returns {Object} The event in a format suitable for sending via
|
||||
* sendAnalytics.
|
||||
*/
|
||||
export function createRemoteVideoMenuButtonEvent(buttonName, attributes) {
|
||||
export function createRemoteVideoMenuButtonEvent(buttonName: string, attributes = {}) {
|
||||
return {
|
||||
action: 'clicked',
|
||||
actionSubject: buttonName,
|
||||
@@ -569,8 +585,13 @@ export function createRemoteVideoMenuButtonEvent(buttonName, attributes) {
|
||||
* @returns {Object} The event in a format suitable for sending via
|
||||
* sendAnalytics.
|
||||
*/
|
||||
export function createRTCStatsTraceCloseEvent(closeEvent) {
|
||||
const event = {
|
||||
export function createRTCStatsTraceCloseEvent(closeEvent: { code: string; reason: string; }) {
|
||||
const event: {
|
||||
action: string;
|
||||
code?: string;
|
||||
reason?: string;
|
||||
source: string;
|
||||
} = {
|
||||
action: 'trace.onclose',
|
||||
source: 'rtcstats'
|
||||
};
|
||||
@@ -590,7 +611,7 @@ export function createRTCStatsTraceCloseEvent(closeEvent) {
|
||||
* @returns {Object} The event in a format suitable for sending via
|
||||
* sendAnalytics.
|
||||
*/
|
||||
export function createScreenSharingEvent(action, value = null) {
|
||||
export function createScreenSharingEvent(action: string, value = null) {
|
||||
return {
|
||||
action,
|
||||
actionSubject: 'screen.sharing',
|
||||
@@ -606,7 +627,7 @@ export function createScreenSharingEvent(action, value = null) {
|
||||
* @param {Object} attributes - Additional information that describes the issue.
|
||||
* @returns {Object} The event in a format suitable for sending via sendAnalytics.
|
||||
*/
|
||||
export function createScreenSharingIssueEvent(attributes) {
|
||||
export function createScreenSharingIssueEvent(attributes = {}) {
|
||||
return {
|
||||
action: 'screen.sharing.issue',
|
||||
attributes
|
||||
@@ -621,7 +642,7 @@ export function createScreenSharingIssueEvent(attributes) {
|
||||
* @returns {Object} The event in a format suitable for sending via
|
||||
* sendAnalytics.
|
||||
*/
|
||||
export function createSharedVideoEvent(action, attributes = {}) {
|
||||
export function createSharedVideoEvent(action: string, attributes = {}) {
|
||||
return {
|
||||
action,
|
||||
attributes,
|
||||
@@ -646,7 +667,7 @@ export function createSharedVideoEvent(action, attributes = {}) {
|
||||
* sendAnalytics.
|
||||
*/
|
||||
export function createShortcutEvent(
|
||||
shortcut,
|
||||
shortcut: string,
|
||||
action = ACTION_SHORTCUT_TRIGGERED,
|
||||
attributes = {},
|
||||
source = 'keyboard.shortcut') {
|
||||
@@ -666,7 +687,7 @@ export function createShortcutEvent(
|
||||
* @returns {Object} The event in a format suitable for sending via
|
||||
* sendAnalytics.
|
||||
*/
|
||||
export function createStartAudioOnlyEvent(audioOnly) {
|
||||
export function createStartAudioOnlyEvent(audioOnly: boolean) {
|
||||
return {
|
||||
action: 'start.audio.only',
|
||||
attributes: {
|
||||
@@ -693,7 +714,7 @@ export function createStartSilentEvent() {
|
||||
* @param {string} elementID - The ID of the HTMLAudioElement.
|
||||
* @returns {Object} The event in a format suitable for sending via sendAnalytics.
|
||||
*/
|
||||
export function createAudioPlayErrorEvent(elementID) {
|
||||
export function createAudioPlayErrorEvent(elementID: string) {
|
||||
return {
|
||||
action: 'audio.play.error',
|
||||
attributes: {
|
||||
@@ -708,7 +729,7 @@ export function createAudioPlayErrorEvent(elementID) {
|
||||
* @param {string} elementID - The ID of the HTMLAudioElement.
|
||||
* @returns {Object} The event in a format suitable for sending via sendAnalytics.
|
||||
*/
|
||||
export function createAudioPlaySuccessEvent(elementID) {
|
||||
export function createAudioPlaySuccessEvent(elementID: string) {
|
||||
return {
|
||||
action: 'audio.play.success',
|
||||
attributes: {
|
||||
@@ -731,9 +752,9 @@ export function createAudioPlaySuccessEvent(elementID) {
|
||||
* sendAnalytics.
|
||||
*/
|
||||
export function createStartMutedConfigurationEvent(
|
||||
source,
|
||||
audioMute,
|
||||
videoMute) {
|
||||
source: string,
|
||||
audioMute: boolean,
|
||||
videoMute: boolean) {
|
||||
return {
|
||||
action: 'start.muted.configuration',
|
||||
attributes: {
|
||||
@@ -754,7 +775,7 @@ export function createStartMutedConfigurationEvent(
|
||||
* @returns {Object} The event in a format suitable for sending via
|
||||
* sendAnalytics.
|
||||
*/
|
||||
export function createSyncTrackStateEvent(mediaType, muted) {
|
||||
export function createSyncTrackStateEvent(mediaType: string, muted: boolean) {
|
||||
return {
|
||||
action: 'sync.track.state',
|
||||
attributes: {
|
||||
@@ -776,7 +797,7 @@ export function createSyncTrackStateEvent(mediaType, muted) {
|
||||
* @returns {Object} The event in a format suitable for sending via
|
||||
* sendAnalytics.
|
||||
*/
|
||||
export function createToolbarEvent(buttonName, attributes = {}) {
|
||||
export function createToolbarEvent(buttonName: string, attributes = {}) {
|
||||
return {
|
||||
action: 'clicked',
|
||||
actionSubject: buttonName,
|
||||
@@ -794,7 +815,7 @@ export function createToolbarEvent(buttonName, attributes = {}) {
|
||||
* @returns {Object} The event in a format suitable for sending via
|
||||
* sendAnalytics.
|
||||
*/
|
||||
export function createReactionMenuEvent(buttonName) {
|
||||
export function createReactionMenuEvent(buttonName: string) {
|
||||
return {
|
||||
action: 'clicked',
|
||||
actionSubject: 'button',
|
||||
@@ -830,7 +851,7 @@ export function createReactionSoundsDisabledEvent() {
|
||||
* @returns {Object} The event in a format suitable for sending via
|
||||
* sendAnalytics.
|
||||
*/
|
||||
export function createTrackMutedEvent(mediaType, reason, muted = true) {
|
||||
export function createTrackMutedEvent(mediaType: string, reason: string, muted = true) {
|
||||
return {
|
||||
action: 'track.muted',
|
||||
attributes: {
|
||||
@@ -848,7 +869,7 @@ export function createTrackMutedEvent(mediaType, reason, muted = true) {
|
||||
* @returns {Object} The event in a format suitable for sending via
|
||||
* sendAnalytics.
|
||||
*/
|
||||
export function createVpaasConferenceJoinedEvent(tenant) {
|
||||
export function createVpaasConferenceJoinedEvent(tenant: string) {
|
||||
return {
|
||||
action: 'vpaas.conference.joined',
|
||||
attributes: {
|
||||
@@ -866,7 +887,7 @@ export function createVpaasConferenceJoinedEvent(tenant) {
|
||||
* @returns {Object} The event in a format suitable for sending via
|
||||
* sendAnalytics.
|
||||
*/
|
||||
export function createWelcomePageEvent(action, actionSubject, attributes = {}) {
|
||||
export function createWelcomePageEvent(action: string, actionSubject: string, attributes = {}) {
|
||||
return {
|
||||
action,
|
||||
actionSubject,
|
||||
@@ -894,7 +915,7 @@ export function createScreensharingCaptureTakenEvent() {
|
||||
* @returns {Object} The event in a format suitable for sending via
|
||||
* sendAnalytics.
|
||||
*/
|
||||
export function createBreakoutRoomsEvent(actionSubject) {
|
||||
export function createBreakoutRoomsEvent(actionSubject: string) {
|
||||
return {
|
||||
action: 'clicked',
|
||||
actionSubject: `${actionSubject}.button`,
|
||||
@@ -1,7 +1,10 @@
|
||||
// @flow
|
||||
|
||||
/* eslint-disable lines-around-comment */
|
||||
// @ts-ignore
|
||||
import { API_ID } from '../../../modules/API/constants';
|
||||
// @ts-ignore
|
||||
import { getName as getAppName } from '../app/functions';
|
||||
import { IStore } from '../app/types';
|
||||
// @ts-ignore
|
||||
import { getAnalyticsRoomName } from '../base/conference';
|
||||
import {
|
||||
checkChromeExtensionsInstalled,
|
||||
@@ -11,11 +14,16 @@ import JitsiMeetJS, {
|
||||
analytics,
|
||||
browser
|
||||
} from '../base/lib-jitsi-meet';
|
||||
// @ts-ignore
|
||||
import { isAnalyticsEnabled } from '../base/lib-jitsi-meet/functions';
|
||||
import { getJitsiMeetGlobalNS, loadScript, parseURIString } from '../base/util';
|
||||
// @ts-ignore
|
||||
import { loadScript } from '../base/util';
|
||||
import { getJitsiMeetGlobalNS } from '../base/util/helpers';
|
||||
import { inIframe } from '../base/util/iframeUtils';
|
||||
import { parseURIString } from '../base/util/uri';
|
||||
|
||||
import { AmplitudeHandler, MatomoHandler } from './handlers';
|
||||
import AmplitudeHandler from './handlers/AmplitudeHandler';
|
||||
import MatomoHandler from './handlers/MatomoHandler';
|
||||
import logger from './logger';
|
||||
|
||||
/**
|
||||
@@ -59,7 +67,7 @@ export function resetAnalytics() {
|
||||
* @param {Store} store - The redux store in which the specified {@code action} is being dispatched.
|
||||
* @returns {Promise} Resolves with the handlers that have been successfully loaded.
|
||||
*/
|
||||
export async function createHandlers({ getState }: { getState: Function }) {
|
||||
export async function createHandlers({ getState }: { getState: Function; }) {
|
||||
getJitsiMeetGlobalNS().analyticsHandlers = [];
|
||||
|
||||
if (!isAnalyticsEnabled(getState)) {
|
||||
@@ -90,15 +98,15 @@ export async function createHandlers({ getState }: { getState: Function }) {
|
||||
const handlerConstructorOptions = {
|
||||
amplitudeAPPKey,
|
||||
blackListedEvents,
|
||||
envType: (deploymentInfo && deploymentInfo.envType) || 'dev',
|
||||
envType: deploymentInfo?.envType || 'dev',
|
||||
googleAnalyticsTrackingId,
|
||||
matomoEndpoint,
|
||||
matomoSiteID,
|
||||
group,
|
||||
host,
|
||||
product: deploymentInfo && deploymentInfo.product,
|
||||
subproduct: deploymentInfo && deploymentInfo.environment,
|
||||
user: user && user.id,
|
||||
product: deploymentInfo?.product,
|
||||
subproduct: deploymentInfo?.environment,
|
||||
user: user?.id,
|
||||
version: JitsiMeetJS.version,
|
||||
whiteListedEvents
|
||||
};
|
||||
@@ -155,7 +163,7 @@ export async function createHandlers({ getState }: { getState: Function }) {
|
||||
* @param {Array<Object>} handlers - The analytics handlers.
|
||||
* @returns {void}
|
||||
*/
|
||||
export function initAnalytics(store: Store, handlers: Array<Object>) {
|
||||
export function initAnalytics(store: IStore, handlers: Array<Object>) {
|
||||
const { getState, dispatch } = store;
|
||||
|
||||
if (!isAnalyticsEnabled(getState) || handlers.length === 0) {
|
||||
@@ -168,9 +176,9 @@ export function initAnalytics(store: Store, handlers: Array<Object>) {
|
||||
deploymentInfo
|
||||
} = config;
|
||||
const { group, server } = state['features/base/jwt'];
|
||||
const { locationURL = {} } = state['features/base/connection'];
|
||||
const { locationURL = { href: '' } } = state['features/base/connection'];
|
||||
const { tenant } = parseURIString(locationURL.href) || {};
|
||||
const permanentProperties = {};
|
||||
const permanentProperties: any = {};
|
||||
|
||||
if (server) {
|
||||
permanentProperties.server = server;
|
||||
@@ -199,7 +207,7 @@ export function initAnalytics(store: Store, handlers: Array<Object>) {
|
||||
if (deploymentInfo) {
|
||||
for (const key in deploymentInfo) {
|
||||
if (deploymentInfo.hasOwnProperty(key)) {
|
||||
permanentProperties[key] = deploymentInfo[key];
|
||||
permanentProperties[key] = deploymentInfo[key as keyof typeof deploymentInfo];
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -232,7 +240,7 @@ export function initAnalytics(store: Store, handlers: Array<Object>) {
|
||||
* @returns {Promise} Resolves with the handlers that have been successfully loaded and rejects if there are no handlers
|
||||
* loaded or the analytics is disabled.
|
||||
*/
|
||||
function _loadHandlers(scriptURLs = [], handlerConstructorOptions) {
|
||||
function _loadHandlers(scriptURLs: any[] = [], handlerConstructorOptions: Object) {
|
||||
const promises = [];
|
||||
|
||||
for (const url of scriptURLs) {
|
||||
@@ -241,7 +249,7 @@ function _loadHandlers(scriptURLs = [], handlerConstructorOptions) {
|
||||
() => {
|
||||
return { type: 'success' };
|
||||
},
|
||||
error => {
|
||||
(error: Error) => {
|
||||
return {
|
||||
type: 'error',
|
||||
error,
|
||||
@@ -1,13 +1,44 @@
|
||||
export interface IEvent {
|
||||
action?: string;
|
||||
actionSubject?: string;
|
||||
attributes?: {
|
||||
[key: string]: string | undefined;
|
||||
};
|
||||
name?: string;
|
||||
source?: string;
|
||||
type?: string;
|
||||
}
|
||||
|
||||
interface Options {
|
||||
amplitudeAPPKey?: string;
|
||||
blackListedEvents?: string[];
|
||||
envType?: string;
|
||||
googleAnalyticsTrackingId?: string;
|
||||
group?: string;
|
||||
host?: string;
|
||||
matomoEndpoint?: string;
|
||||
matomoSiteID?: string;
|
||||
product?: string;
|
||||
subproduct?: string;
|
||||
user?: string;
|
||||
version?: string;
|
||||
whiteListedEvents?: string[];
|
||||
}
|
||||
|
||||
/**
|
||||
* Abstract implementation of analytics handler.
|
||||
*/
|
||||
export default class AbstractHandler {
|
||||
_enabled: boolean;
|
||||
_whiteListedEvents: Array<string> | undefined;
|
||||
_blackListedEvents: Array<string> | undefined;
|
||||
|
||||
/**
|
||||
* Creates new instance.
|
||||
*
|
||||
* @param {Object} options - Optional parameters.
|
||||
*/
|
||||
constructor(options = {}) {
|
||||
constructor(options: Options = {}) {
|
||||
this._enabled = false;
|
||||
this._whiteListedEvents = options.whiteListedEvents;
|
||||
|
||||
@@ -28,7 +59,7 @@ export default class AbstractHandler {
|
||||
* @param {Object} event - The analytics event.
|
||||
* @returns {string} - The extracted name.
|
||||
*/
|
||||
_extractName(event) {
|
||||
_extractName(event: IEvent) {
|
||||
// Page events have a single 'name' field.
|
||||
if (event.type === 'page') {
|
||||
return event.name;
|
||||
@@ -65,12 +96,12 @@ export default class AbstractHandler {
|
||||
* @param {Object} event - The event.
|
||||
* @returns {boolean}
|
||||
*/
|
||||
_shouldIgnore(event) {
|
||||
_shouldIgnore(event: IEvent) {
|
||||
if (!event || !this._enabled) {
|
||||
return true;
|
||||
}
|
||||
|
||||
const name = this._extractName(event);
|
||||
const name = this._extractName(event) ?? '';
|
||||
|
||||
if (Array.isArray(this._whiteListedEvents)) {
|
||||
return this._whiteListedEvents.indexOf(name) === -1;
|
||||
@@ -1,13 +1,18 @@
|
||||
/* eslint-disable lines-around-comment */
|
||||
import logger from '../logger';
|
||||
|
||||
import AbstractHandler from './AbstractHandler';
|
||||
import AbstractHandler, { IEvent } from './AbstractHandler';
|
||||
// @ts-ignore
|
||||
import { fixDeviceID } from './amplitude/fixDeviceID';
|
||||
// @ts-ignore
|
||||
import amplitude from './amplitude/lib';
|
||||
|
||||
/**
|
||||
* Analytics handler for Amplitude.
|
||||
*/
|
||||
export default class AmplitudeHandler extends AbstractHandler {
|
||||
_deviceId: string;
|
||||
_userId: Object;
|
||||
/**
|
||||
* Creates new instance of the Amplitude analytics handler.
|
||||
*
|
||||
@@ -15,14 +20,14 @@ export default class AmplitudeHandler extends AbstractHandler {
|
||||
* @param {string} options.amplitudeAPPKey - The Amplitude app key required
|
||||
* by the Amplitude API.
|
||||
*/
|
||||
constructor(options) {
|
||||
constructor(options: any) {
|
||||
super(options);
|
||||
|
||||
const { amplitudeAPPKey, user } = options;
|
||||
|
||||
this._enabled = true;
|
||||
|
||||
const onError = e => {
|
||||
const onError = (e: Error) => {
|
||||
logger.error('Error initializing Amplitude', e);
|
||||
this._enabled = false;
|
||||
};
|
||||
@@ -31,7 +36,7 @@ export default class AmplitudeHandler extends AbstractHandler {
|
||||
amplitude.getInstance().init(amplitudeAPPKey);
|
||||
fixDeviceID(amplitude.getInstance()).then(() => {
|
||||
amplitude.getInstance().getDeviceId()
|
||||
.then(deviceId => {
|
||||
.then((deviceId: string) => {
|
||||
this._deviceId = deviceId;
|
||||
});
|
||||
});
|
||||
@@ -57,7 +62,7 @@ export default class AmplitudeHandler extends AbstractHandler {
|
||||
* @param {Object} userProps - The user portperties.
|
||||
* @returns {void}
|
||||
*/
|
||||
setUserProperties(userProps) {
|
||||
setUserProperties(userProps: Object) {
|
||||
if (this._enabled) {
|
||||
amplitude.getInstance().setUserProperties(userProps);
|
||||
}
|
||||
@@ -71,7 +76,7 @@ export default class AmplitudeHandler extends AbstractHandler {
|
||||
* lib-jitsi-meet.
|
||||
* @returns {void}
|
||||
*/
|
||||
sendEvent(event) {
|
||||
sendEvent(event: IEvent) {
|
||||
if (this._shouldIgnore(event)) {
|
||||
return;
|
||||
}
|
||||
@@ -1,13 +1,15 @@
|
||||
/* global ga */
|
||||
|
||||
import { getJitsiMeetGlobalNS } from '../../base/util';
|
||||
import { getJitsiMeetGlobalNS } from '../../base/util/helpers';
|
||||
|
||||
import AbstractHandler from './AbstractHandler';
|
||||
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.
|
||||
@@ -16,7 +18,7 @@ class GoogleAnalyticsHandler extends AbstractHandler {
|
||||
* @param {string} options.googleAnalyticsTrackingId - The GA track id
|
||||
* required by the GA API.
|
||||
*/
|
||||
constructor(options) {
|
||||
constructor(options: any) {
|
||||
super(options);
|
||||
|
||||
this._userProperties = {};
|
||||
@@ -37,16 +39,20 @@ class GoogleAnalyticsHandler extends AbstractHandler {
|
||||
* required by the GA API.
|
||||
* @returns {void}
|
||||
*/
|
||||
_initGoogleAnalytics(options) {
|
||||
_initGoogleAnalytics(options: any) {
|
||||
/**
|
||||
* TODO: Keep this local, there's no need to add it to window.
|
||||
*/
|
||||
/* eslint-disable */
|
||||
/* 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');
|
||||
}
|
||||
|
||||
@@ -60,11 +66,11 @@ class GoogleAnalyticsHandler extends AbstractHandler {
|
||||
* suitable value.
|
||||
* @private
|
||||
*/
|
||||
_extractValue(event) {
|
||||
let value = event && event.attributes && event.attributes.value;
|
||||
_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));
|
||||
value = Math.round(parseFloat(value ?? ''));
|
||||
|
||||
return value;
|
||||
}
|
||||
@@ -78,7 +84,7 @@ class GoogleAnalyticsHandler extends AbstractHandler {
|
||||
* analytics event.
|
||||
* @private
|
||||
*/
|
||||
_extractLabel(event) {
|
||||
_extractLabel(event: IEvent) {
|
||||
const { attributes = {} } = event;
|
||||
const labelsArray
|
||||
= Object.keys(attributes).map(key => `${key}=${attributes[key]}`);
|
||||
@@ -94,7 +100,7 @@ class GoogleAnalyticsHandler extends AbstractHandler {
|
||||
* @param {Object} userProps - The permanent portperties.
|
||||
* @returns {void}
|
||||
*/
|
||||
setUserProperties(userProps = {}) {
|
||||
setUserProperties(userProps: any = {}) {
|
||||
if (!this._enabled) {
|
||||
return;
|
||||
}
|
||||
@@ -120,12 +126,17 @@ class GoogleAnalyticsHandler extends AbstractHandler {
|
||||
* lib-jitsi-meet.
|
||||
* @returns {void}
|
||||
*/
|
||||
sendEvent(event) {
|
||||
sendEvent(event: IEvent) {
|
||||
if (this._shouldIgnore(event)) {
|
||||
return;
|
||||
}
|
||||
|
||||
const gaEvent = {
|
||||
const gaEvent: {
|
||||
eventAction?: string;
|
||||
eventCategory: string;
|
||||
eventLabel: string;
|
||||
eventValue?: number;
|
||||
} = {
|
||||
'eventCategory': 'jitsi-meet',
|
||||
'eventAction': this._extractName(event),
|
||||
'eventLabel': this._extractLabel(event)
|
||||
@@ -136,6 +147,7 @@ class GoogleAnalyticsHandler extends AbstractHandler {
|
||||
gaEvent.eventValue = value;
|
||||
}
|
||||
|
||||
// @ts-ignore
|
||||
ga('send', 'event', gaEvent);
|
||||
}
|
||||
|
||||
@@ -1,13 +1,14 @@
|
||||
/* global _paq */
|
||||
|
||||
import { getJitsiMeetGlobalNS } from '../../base/util';
|
||||
import { getJitsiMeetGlobalNS } from '../../base/util/helpers';
|
||||
|
||||
import AbstractHandler from './AbstractHandler';
|
||||
import AbstractHandler, { IEvent } from './AbstractHandler';
|
||||
|
||||
/**
|
||||
* Analytics handler for Matomo.
|
||||
*/
|
||||
export default class MatomoHandler extends AbstractHandler {
|
||||
_userProperties: Object;
|
||||
|
||||
/**
|
||||
* Creates new instance of the Matomo handler.
|
||||
@@ -16,7 +17,7 @@ export default class MatomoHandler extends AbstractHandler {
|
||||
* @param {string} options.matomoEndpoint - The Matomo endpoint.
|
||||
* @param {string} options.matomoSiteID - The site ID.
|
||||
*/
|
||||
constructor(options) {
|
||||
constructor(options: any) {
|
||||
super(options);
|
||||
this._userProperties = {};
|
||||
|
||||
@@ -43,9 +44,11 @@ export default class MatomoHandler extends AbstractHandler {
|
||||
* @param {string} options.matomoSiteID - The site ID.
|
||||
* @returns {void}
|
||||
*/
|
||||
_initMatomo(options) {
|
||||
_initMatomo(options: any) {
|
||||
// @ts-ignore
|
||||
const _paq = window._paq || [];
|
||||
|
||||
// @ts-ignore
|
||||
window._paq = _paq;
|
||||
|
||||
_paq.push([ 'trackPageView' ]);
|
||||
@@ -70,7 +73,7 @@ export default class MatomoHandler extends AbstractHandler {
|
||||
g.async = true;
|
||||
g.defer = true;
|
||||
g.src = `${u}matomo.js`;
|
||||
s.parentNode.insertBefore(g, s);
|
||||
s.parentNode?.insertBefore(g, s);
|
||||
})();
|
||||
}
|
||||
|
||||
@@ -84,11 +87,11 @@ export default class MatomoHandler extends AbstractHandler {
|
||||
* suitable value.
|
||||
* @private
|
||||
*/
|
||||
_extractValue(event) {
|
||||
const value = event && event.attributes && event.attributes.value;
|
||||
_extractValue(event: IEvent) {
|
||||
const value = event?.attributes?.value;
|
||||
|
||||
// Try to extract an integer from the 'value' attribute.
|
||||
return Math.round(parseFloat(value));
|
||||
return Math.round(parseFloat(value ?? ''));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -97,7 +100,7 @@ export default class MatomoHandler extends AbstractHandler {
|
||||
* @param {Object} userProps - The permanent properties.
|
||||
* @returns {void}
|
||||
*/
|
||||
setUserProperties(userProps = {}) {
|
||||
setUserProperties(userProps: any = {}) {
|
||||
if (!this._enabled) {
|
||||
return;
|
||||
}
|
||||
@@ -108,6 +111,7 @@ export default class MatomoHandler extends AbstractHandler {
|
||||
Object.keys(userProps)
|
||||
.filter(key => visitScope.indexOf(key) === -1)
|
||||
.forEach((key, index) => {
|
||||
// @ts-ignore
|
||||
_paq.push([
|
||||
'setCustomVariable',
|
||||
1 + index,
|
||||
@@ -122,6 +126,7 @@ export default class MatomoHandler extends AbstractHandler {
|
||||
Object.keys(userProps)
|
||||
.filter(key => visitScope.indexOf(key) !== -1)
|
||||
.forEach((key, index) => {
|
||||
// @ts-ignore
|
||||
_paq.push([
|
||||
'setCustomVariable',
|
||||
1 + index,
|
||||
@@ -141,18 +146,20 @@ export default class MatomoHandler extends AbstractHandler {
|
||||
* lib-jitsi-meet.
|
||||
* @returns {void}
|
||||
*/
|
||||
sendEvent(event) {
|
||||
sendEvent(event: IEvent) {
|
||||
if (this._shouldIgnore(event)) {
|
||||
return;
|
||||
}
|
||||
|
||||
const value = this._extractValue(event);
|
||||
const matomoEvent = [ 'trackEvent', 'jitsi-meet', this._extractName(event) ];
|
||||
const matomoEvent: Array<string | number | undefined> = [
|
||||
'trackEvent', 'jitsi-meet', this._extractName(event) ];
|
||||
|
||||
if (!isNaN(value)) {
|
||||
matomoEvent.push(value);
|
||||
}
|
||||
|
||||
// @ts-ignore
|
||||
_paq.push(matomoEvent);
|
||||
}
|
||||
}
|
||||
@@ -7,7 +7,7 @@ import DeviceInfo from 'react-native-device-info';
|
||||
* @param {AmplitudeClient} amplitude - The amplitude instance.
|
||||
* @returns {void}
|
||||
*/
|
||||
export async function fixDeviceID(amplitude) {
|
||||
export async function fixDeviceID(amplitude: any) {
|
||||
await DefaultPreference.setName('jitsi-preferences');
|
||||
|
||||
const current = await DefaultPreference.get('amplitudeDeviceId');
|
||||
@@ -4,6 +4,6 @@
|
||||
* @param {AmplitudeClient} amplitude - The amplitude instance.
|
||||
* @returns {void}
|
||||
*/
|
||||
export function fixDeviceID(amplitude) { // eslint-disable-line no-unused-vars
|
||||
export function fixDeviceID(amplitude: any) { // eslint-disable-line @typescript-eslint/no-unused-vars
|
||||
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user