Compare commits

..

1 Commits

Author SHA1 Message Date
Aaron van Meerten
a49b6140e0 feature: empty token verification allow list 2022-12-15 09:02:48 -06:00
95 changed files with 1356 additions and 1512 deletions

View File

@@ -7,7 +7,7 @@ jobs:
name: Lint
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v2
- uses: actions/setup-node@v3
with:
node-version: 16
@@ -20,11 +20,12 @@ jobs:
- name: Check if the git repository is clean
run: $(exit $(git status --porcelain --untracked-files=no | head -255 | wc -l)) || (echo "Dirty git tree"; git diff; exit 1)
- run: npm run lint:ci
- run: for file in lang/*.json; do npx --yes jsonlint -q $file || exit 1; done
linux-build:
name: Build Frontend (Linux)
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v2
- uses: actions/setup-node@v3
with:
node-version: 16
@@ -35,7 +36,7 @@ jobs:
name: Build Frontend (macOS)
runs-on: macOS-latest
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v2
- uses: actions/setup-node@v3
with:
node-version: 16

View File

@@ -1,70 +0,0 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="262.91376dp"
android:height="262.91376dp"
android:viewportWidth="262.91376"
android:viewportHeight="262.91376">
<group android:scaleX="0.75" android:scaleY="0.75" android:translateX="35" android:translateY="35">
<clip-path
android:pathData="m0,0 l262.914,-0L262.914,262.914 0,262.914 0,0Z"/>
<path
android:pathData="m142.646,105.099c0.117,0.026 0.255,0.036 0.406,0.036 3.186,-0 10.297,-4.615 11.617,-6.721l0.1,-0.17 0.153,-0.135c0.451,-0.441 1.746,-2.773 2.374,-4.17 -6.751,-2.023 -7.49,-5.677 -8.153,-8.919 -0.069,-0.376 -0.138,-0.717 -0.204,-1.019 -0.074,-0.397 -0.153,-0.8 -0.226,-1.112C138.668,86.221 135.593,88.094 133.921,89.483 133.056,90.201 132.542,92.251 135.042,97.926 136.323,100.816 140.727,104.733 142.646,105.099"
android:fillColor="#ffffff"
android:strokeColor="#00000000"
android:fillType="nonZero"/>
<path
android:pathData="m115.413,146.042c5.934,-0 18.464,-3.543 26.748,-5.887 1.21,-0.336 2.33,-0.66 3.351,-0.944 0.166,-0.046 0.321,-0.091 0.472,-0.124 -0.463,-0.461 -1.239,-1.159 -2.497,-2.216 -5.521,-3.741 -10.736,-5.484 -16.403,-5.484 -1.237,-0 -2.522,0.071 -3.923,0.231 -4.801,0.55 -8.8,1.69 -10.722,2.237 -0.967,0.284 -1.263,0.366 -1.567,0.366 -0.58,-0 -1.079,-0.341 -1.273,-0.878 -0.194,-0.534 -0.027,-1.121 0.425,-1.507l0.024,-0.011c3.316,-2.784 9.489,-7.951 21.198,-10.256 2.027,-0.401 4.202,-0.605 6.454,-0.605 5.242,-0 10.67,1.086 16.125,3.219 7.436,2.899 12.521,6.625 16.602,9.62 2.199,1.609 4.105,3.007 5.755,3.771 0.421,0.2 0.637,0.255 0.746,0.265 0.074,-0.095 0.23,-0.365 0.474,-1.069 0.066,-0.185 0.529,-2.161 -2.806,-13.374 -1.931,-6.51 -4.264,-13.156 -5.479,-16.104 -2.356,-5.711 -1.778,-9.76 -1.051,-12.125 -1.999,0.735 -4.033,1.87 -6.174,3.446L161.758,98.711C160.694,99.506 159.599,100.404 158.426,101.454 151.517,107.64 146.344,110.864 143.035,111.04l-0.093,0.004 -0.093,-0.009c-2.912,-0.245 -7.324,-4.489 -9.133,-6.634 -0.373,-0.251 -0.8,-0.366 -1.366,-0.366 -0.564,-0 -1.202,0.116 -1.82,0.235C130.086,104.354 129.623,104.441 129.167,104.489 127.708,104.632 125.668,105.106 123.694,105.561 122.746,105.777 121.762,106.005 120.864,106.189 120.851,106.19 120.463,106.272 119.774,106.454 114.903,107.891 111.228,109.55 109.432,111.111 109.414,111.127 109.352,111.174 109.266,111.242 108.048,112.105 105.124,114.567 104.248,118.762L104.237,118.795C102.398,126.516 105.187,136.087 108.892,141.554 110.636,144.125 112.513,145.727 114.048,145.959 114.437,146.015 114.891,146.042 115.413,146.042"
android:fillColor="#ffffff"
android:strokeColor="#00000000"
android:fillType="nonZero"/>
<path
android:pathData="m90.093,173.175c-1.252,-1.472 -1.783,-3.324 -1.574,-5.521 0.884,-10.642 -0.329,-13.215 -0.891,-13.829 -0.131,-0.144 -0.207,-0.144 -0.265,-0.144 -0.022,-0 -0.041,0.003 -0.064,0.003 -1.044,0.248 -8.066,5.002 -9.615,19.171 -0.749,6.845 0.561,15.63 1.679,20.974 0.897,-3.155 2.314,-6.624 5.057,-10.204 2.556,-3.326 5.345,-5.955 8.801,-8.253C92.143,174.93 90.991,174.235 90.093,173.175"
android:fillColor="#ffffff"
android:strokeColor="#00000000"
android:fillType="nonZero"/>
<path
android:pathData="m94.906,156.389c-0.03,2.229 -0.326,4.36 -0.61,6.445 -0.151,1.119 -0.314,2.286 -0.434,3.46 -0.161,2.341 0.346,3.166 0.571,3.406 0.127,0.136 0.326,0.287 0.76,0.287 0.339,-0 0.741,-0.091 1.161,-0.268 4.202,-1.756 8.195,-4.815 10.115,-6.515C103.522,161.892 98.995,159.058 94.906,156.389"
android:fillColor="#ffffff"
android:strokeColor="#00000000"
android:fillType="nonZero"/>
<path
android:pathData="m154.002,81.595c-0.031,0.074 -0.065,0.148 -0.101,0.216 -0.821,2.403 0.306,5.664 2.419,6.898 0.561,0.327 1.106,0.526 1.624,0.596 0.072,0.006 0.148,0.009 0.219,0.009 1.645,-0 2.971,-1.199 3.961,-3.561C162.752,83.959 162.836,81.827 162.37,79.904 162.003,78.409 161.057,76.627 160.453,75.738 159.332,76.509 157.111,78.207 155.585,79.553 154.518,80.582 154.136,81.229 154.002,81.595"
android:fillColor="#ffffff"
android:strokeColor="#00000000"
android:fillType="nonZero"/>
<path
android:pathData="M148.97,77.699C153.957,73.194 156.988,65.754 158.253,61.334 153.915,65.513 148.633,67.758 145.25,69.198 144.084,69.695 143.08,70.124 142.477,70.476 142.224,70.623 141.965,70.77 141.708,70.919 139.654,72.109 136.55,73.905 136.1,75.011l-0.012,0.036 -0.012,0.034c-1.406,2.956 -2.199,7.401 -2.457,9.95 3.266,-1.99 6.625,-3.322 9.416,-4.42C145.628,79.585 147.863,78.703 148.97,77.699"
android:fillColor="#ffffff"
android:strokeColor="#00000000"
android:fillType="nonZero"/>
<path
android:pathData="m164.464,51.921c-0.84,5.539 -2.205,10.799 -4.751,16.347 2.781,-3.144 4.396,-6.568 4.941,-10.401C164.886,56.275 165.097,54.756 164.464,51.921"
android:fillColor="#ffffff"
android:strokeColor="#00000000"
android:fillType="nonZero"/>
<path
android:pathData="M148.749,142.639C148.718,142.598 148.684,142.56 148.658,142.519 148.523,142.539 148.307,142.584 147.972,142.683l-0.14,0.04c-1.726,0.644 -4.899,1.708 -8.556,2.946 -4.396,1.479 -9.365,3.154 -13.526,4.649 -5.297,1.975 -7.021,2.755 -7.557,3.024 -0.098,0.266 -0.203,0.599 -0.327,0.965 -1.254,3.816 -4.125,12.541 -18.276,18.653 2.928,2.956 9.289,8.27 21.809,8.27 1.082,-0 2.21,-0.036 3.341,-0.12 9.451,-0.666 18.342,-4.855 25.026,-11.78 6.087,-6.291 9.538,-14.136 9.585,-21.7C157.876,147.509 155.367,147.135 153.043,146.033 153.014,146.02 150.361,144.745 148.749,142.639"
android:fillColor="#ffffff"
android:strokeColor="#00000000"
android:fillType="nonZero"/>
<path
android:pathData="m189.478,117.853c-0.523,9.749 -2.122,18.424 -4.744,25.8 -2.128,5.988 -4.94,11.134 -8.356,15.316 -5.676,6.931 -11.555,9.256 -12.804,9.304 -0.866,-0 -1.313,-0.309 -3.046,-1.528 -0.17,-0.114 -0.37,-0.252 -0.581,-0.4 -3.313,5.953 -8.505,11.097 -15.065,14.959 -7.079,4.144 -15.297,6.423 -23.157,6.423 -9.078,-0 -17.13,-2.924 -23.341,-8.456 -7.467,4.799 -12.31,9.074 -16.267,27.005l-1.363,6.17 -2.971,-5.564c-0.424,-0.786 -1.929,-3.731 -3.332,-8.887 -1.934,-7.104 -2.86,-15.181 -2.758,-24.01 0.117,-10.049 3.154,-16.526 5.68,-20.186 2.98,-4.314 6.837,-6.994 10.076,-6.994 0.216,-0 0.428,0.006 0.616,0.035 5.159,0.575 8.435,2.75 14.396,6.686l1.899,1.252c2.059,1.344 4.481,2.7 5.259,2.989 0.54,-0.284 1.749,-2.3 2.155,-5.271l0.069,-0.451c0.005,-0.045 0.009,-0.091 0.014,-0.131 -0.036,-0.02 -0.065,-0.029 -0.094,-0.041 -4.008,-1.375 -9.539,-7.7 -12.364,-17.134 -2.684,-9.382 -2.129,-17.185 1.644,-23.193 6.12,-9.736 19.198,-11.974 23.466,-12.702 1.331,-0.266 2.716,-0.511 4.041,-0.717 0.255,-0.061 0.469,-0.121 0.642,-0.168 -0.031,-0.126 -0.071,-0.265 -0.114,-0.43 -0.108,-0.417 -0.23,-0.891 -0.354,-1.447 -1.345,-6.035 -0.664,-11.069 0.181,-15.193 0.928,-4.546 1.489,-7.287 3.747,-9.936 3.029,-4.165 8.319,-5.936 11.479,-6.991 0.746,-0.249 1.511,-0.509 1.894,-0.689 8.988,-4.31 11.82,-8.739 12.615,-11.694 0.656,-2.451 1.699,-8.884 1.251,-13.335 -0.085,-0.805 0.129,-1.521 0.621,-2.065 0.45,-0.505 1.101,-0.794 1.778,-0.794 1.515,-0 2.82,-0 7.511,14.598 2.481,7.698 0.645,14.903 -5.45,21.424l-0.226,0.231c0.024,0.044 0.049,0.09 0.08,0.144 2.57,4.236 3.963,9.54 3.553,13.51 -0.099,0.906 -0.265,1.775 -0.419,2.549 -0.003,0.01 -0.003,0.016 -0.004,0.029 0.516,-0.032 1.119,-0.055 1.775,-0.055 3.052,-0 7.435,0.474 10.989,2.735 2.135,1.352 4.845,3.439 6.835,7.615C189.223,102.942 190.076,109.575 189.478,117.853m4.77,-23.191c-2.916,-6.1 -6.989,-9.177 -9.793,-10.96 -2.355,-1.494 -5.064,-2.584 -8.077,-3.24l-0.676,-0.146 -0.111,-0.689c-0.339,-2.119 -0.918,-4.275 -1.715,-6.406l-0.185,-0.49 0.292,-0.434c5.095,-7.594 6.323,-16.17 3.54,-24.802 -2.191,-6.824 -3.895,-11.211 -5.341,-13.799 -2.954,-5.305 -7.006,-6.417 -9.891,-6.417 -2.964,-0 -5.8,1.261 -7.789,3.457 -2.043,2.254 -2.993,5.207 -2.678,8.31 0.316,3.134 -0.494,8.516 -1.014,10.439 -0.04,0.117 -0.975,2.929 -8.201,6.428 -0.162,0.056 -0.512,0.179 -1.053,0.359 -3.729,1.246 -10.666,3.571 -15.258,9.64 -3.465,4.205 -4.332,8.441 -5.338,13.346 -0.586,2.865 -1.236,6.744 -1.079,11.344l0.026,0.841 -0.824,0.188c-11.646,2.585 -20.025,7.835 -24.909,15.605 -5.054,8.04 -5.919,18.055 -2.543,29.853 0.063,0.204 0.126,0.407 0.189,0.615l0.527,1.608 -1.665,-0.286c-0.561,-0.101 -1.135,-0.18 -1.729,-0.241 -0.493,-0.06 -1.001,-0.082 -1.509,-0.082 -5.633,-0 -11.663,3.585 -16.128,9.592 -3.451,4.641 -7.588,12.849 -7.735,25.601 -0.114,9.573 0.906,18.401 3.038,26.228 1.581,5.795 3.326,9.329 4.004,10.577l13.306,24.94 6.096,-27.619c2.454,-11.09 4.864,-15.262 7.725,-18.111l0.561,-0.563 0.679,0.411c6.605,3.977 14.466,6.084 22.73,6.084 9.286,-0 18.965,-2.682 27.259,-7.551 5.38,-3.16 9.974,-7.036 13.649,-11.531l0.45,-0.369 0.85,-0.02c2.156,-0.068 5.16,-1.164 8.222,-3.004 2.6,-1.555 6.543,-4.428 10.501,-9.262 3.997,-4.884 7.274,-10.854 9.716,-17.734 2.876,-8.073 4.625,-17.489 5.204,-28.004 0.689,-9.668 -0.434,-17.641 -3.327,-23.704"
android:fillColor="#ffffff"
android:strokeColor="#00000000"
android:fillType="nonZero"/>
<path
android:pathData="m180.026,98.414c-1.67,-2.596 -3.771,-4.206 -5.475,-4.206 -0.313,-0 -0.613,0.051 -0.895,0.161 -0.911,0.361 -2.356,4.532 -1.714,7.566 0.434,2.066 2.938,9.04 4.151,12.394 0.456,1.281 0.68,1.91 0.754,2.142 0.064,0.183 0.145,0.448 0.256,0.774 0.97,2.971 3.467,10.586 4.206,16.761 1.549,-6.579 2.424,-14.512 2.085,-23.997C183.235,105.662 182.04,101.538 180.026,98.414"
android:fillColor="#ffffff"
android:strokeColor="#00000000"
android:fillType="nonZero"/>
<path
android:pathData="M168.088,142.604C169.896,142.111 171.33,141.705 172.398,141.395 170.213,139.874 167.689,137.979 164.247,135.304c-8.418,-6.546 -17.449,-9.87 -26.839,-9.87 -5.135,-0 -9.611,0.991 -13.156,2.186 0.882,-0.05 1.779,-0.079 2.7,-0.079 1.1,-0 2.247,0.04 3.411,0.119 3.652,0.246 13.061,1.901 21.565,12.047 1.714,2.039 3.559,3.73 8.794,3.73 1.873,-0 4.051,-0.207 6.662,-0.645C167.544,142.751 167.793,142.678 168.088,142.604"
android:fillColor="#ffffff"
android:strokeColor="#00000000"
android:fillType="nonZero"/>
<path
android:pathData="m164.3,147.583c-0.122,1.563 -0.376,4.509 -0.782,6.76 -0.495,2.719 -1.31,5.02 -1.791,6.226 0.85,0.786 1.694,1.553 2.247,2.043 2.214,-1.447 9.47,-6.96 14.483,-19.474C176.847,144.229 174.59,145.178 171.671,146.018 168.701,146.861 165.82,147.357 164.3,147.583"
android:fillColor="#ffffff"
android:strokeColor="#00000000"
android:fillType="nonZero"/>
</group>
</vector>

View File

@@ -2,5 +2,4 @@
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
<background android:drawable="@color/ic_launcher_background"/>
<foreground android:drawable="@mipmap/ic_launcher_foreground"/>
<monochrome android:drawable="@drawable/ic_launcher_monochrome"/>
</adaptive-icon>

View File

@@ -2,5 +2,4 @@
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
<background android:drawable="@color/ic_launcher_background"/>
<foreground android:drawable="@mipmap/ic_launcher_foreground"/>
<monochrome android:drawable="@drawable/ic_launcher_monochrome"/>
</adaptive-icon>

View File

@@ -81,8 +81,6 @@ public class JitsiMeetView extends FrameLayout {
result.putBoolean(key, (Boolean)bValue);
} else if (valueType.contentEquals("String")) {
result.putString(key, (String)bValue);
} else if (valueType.contentEquals("Integer")) {
result.putInt(key, (int)bValue);
} else if (valueType.contentEquals("Bundle")) {
result.putBundle(key, mergeProps((Bundle)aValue, (Bundle)bValue));
} else {

View File

@@ -124,7 +124,7 @@ class ReactInstanceManagerHolder {
new com.reactnativecommunity.webview.RNCWebViewPackage(),
new com.kevinresol.react_native_default_preference.RNDefaultPreferencePackage(),
new com.learnium.RNDeviceInfo.RNDeviceInfo(),
new com.swmansion.gesturehandler.RNGestureHandlerPackage(),
new com.swmansion.gesturehandler.react.RNGestureHandlerPackage(),
new org.linusu.RNGetRandomValuesPackage(),
new com.rnimmersive.RNImmersivePackage(),
new com.swmansion.rnscreens.RNScreensPackage(),

View File

@@ -2342,7 +2342,7 @@ export default {
* @param {MediaDeviceInfo[]} devices
* @returns {Promise}
*/
async _onDeviceListChanged(devices) {
_onDeviceListChanged(devices) {
const oldDevices = APP.store.getState()['features/base/devices'].availableDevices;
const localAudio = getLocalJitsiAudioTrack(APP.store.getState());
const localVideo = getLocalJitsiVideoTrack(APP.store.getState());
@@ -2356,10 +2356,13 @@ export default {
const newDevices
= mediaDeviceHelper.getNewMediaDevicesAfterDeviceListChanged(
devices,
this.isSharingScreen,
localVideo,
localAudio,
newLabelsOnly);
const promises = [];
const audioWasMuted = this.isLocalAudioMuted();
const videoWasMuted = this.isLocalVideoMuted();
const requestedInput = {
audio: Boolean(newDevices.audioinput),
video: Boolean(newDevices.videoinput)
@@ -2371,6 +2374,7 @@ export default {
= setAudioOutputDeviceId(newDevices.audiooutput, dispatch)
.catch(); // Just ignore any errors in catch block.
promises.push(setAudioOutputPromise);
}
@@ -2387,7 +2391,8 @@ export default {
}
// Let's handle unknown/non-preferred devices
const newAvailDevices = APP.store.getState()['features/base/devices'].availableDevices;
const newAvailDevices
= APP.store.getState()['features/base/devices'].availableDevices;
let newAudioDevices = [];
let oldAudioDevices = [];
@@ -2403,85 +2408,103 @@ export default {
// check for audio
if (newAudioDevices.length > 0) {
APP.store.dispatch(checkAndNotifyForNewDevice(newAudioDevices, oldAudioDevices));
APP.store.dispatch(
checkAndNotifyForNewDevice(newAudioDevices, oldAudioDevices));
}
// check for video
if (!requestedInput.video) {
APP.store.dispatch(checkAndNotifyForNewDevice(newAvailDevices.videoInput, oldDevices.videoInput));
APP.store.dispatch(
checkAndNotifyForNewDevice(newAvailDevices.videoInput, oldDevices.videoInput));
}
// When the 'default' mic needs to be selected, we need to pass the real device id to gUM instead of 'default'
// in order to get the correct MediaStreamTrack from chrome because of the following bug.
// When the 'default' mic needs to be selected, we need to
// pass the real device id to gUM instead of 'default' in order
// to get the correct MediaStreamTrack from chrome because of the
// following bug.
// https://bugs.chromium.org/p/chromium/issues/detail?id=997689
const hasDefaultMicChanged = newDevices.audioinput === 'default';
// When the local video is muted and a preferred device is connected, update the settings and remove the track
// from the conference. A new track will be created and replaced when the user unmutes their camera.
// This is the case when the local video is muted and a preferred device is connected.
if (requestedInput.video && this.isLocalVideoMuted()) {
APP.store.dispatch(updateSettings({
// We want to avoid creating a new video track in order to prevent turning on the camera.
requestedInput.video = false;
APP.store.dispatch(updateSettings({ // Update the current selected camera for the device selection dialog.
cameraDeviceId: newDevices.videoinput
}));
requestedInput.video = false;
delete newDevices.videoinput;
// Remove the track from the conference.
if (localVideo) {
await this.useVideoStream(null);
logger.debug('_onDeviceListChanged: Removed the current video track.');
}
// Removing the current video track in order to force the unmute to select the preferred device.
logger.debug('_onDeviceListChanged: Removing the current video track.');
this.useVideoStream(null);
}
// When the local audio is muted and a preferred device is connected, update the settings and remove the track
// from the conference. A new track will be created and replaced when the user unmutes their mic.
if (requestedInput.audio && this.isLocalAudioMuted()) {
APP.store.dispatch(updateSettings({
micDeviceId: newDevices.audioinput
}));
requestedInput.audio = false;
delete newDevices.audioinput;
// Remove the track from the conference.
if (localAudio) {
await this.useAudioStream(null);
logger.debug('_onDeviceListChanged: Removed the current audio track.');
}
}
// Create the tracks and replace them only if the user is unmuted.
if (requestedInput.audio || requestedInput.video) {
let tracks = [];
try {
tracks = await mediaDeviceHelper.createLocalTracksAfterDeviceListChanged(
promises.push(
mediaDeviceHelper.createLocalTracksAfterDeviceListChanged(
createLocalTracksF,
newDevices.videoinput,
hasDefaultMicChanged
? getDefaultDeviceId(APP.store.getState(), 'audioInput')
: newDevices.audioinput);
} catch (error) {
logger.error(`Track creation failed on device change, ${error}`);
: newDevices.audioinput)
.then(tracks => {
// If audio or video muted before, or we unplugged current
// device and selected new one, then mute new track.
const muteSyncPromises = tracks.map(track => {
if ((track.isVideoTrack() && videoWasMuted)
|| (track.isAudioTrack() && audioWasMuted)) {
return track.mute();
}
return Promise.reject(error);
}
return Promise.resolve();
});
for (const track of tracks) {
if (track.isAudioTrack()) {
promises.push(
this.useAudioStream(track)
.then(() => {
hasDefaultMicChanged && (track._realDeviceId = track.deviceId = 'default');
this._updateAudioDeviceId();
}));
} else {
promises.push(
this.useVideoStream(track)
.then(() => {
this._updateVideoDeviceId();
}));
}
}
}
return Promise.all(muteSyncPromises)
.then(() =>
Promise.all(Object.keys(requestedInput).map(mediaType => {
if (requestedInput[mediaType]) {
const useStream
= mediaType === 'audio'
? this.useAudioStream.bind(this)
: this.useVideoStream.bind(this);
const track = tracks.find(t => t.getType() === mediaType) || null;
// Use the new stream or null if we failed to obtain it.
return useStream(track)
.then(() => {
if (track?.isAudioTrack() && hasDefaultMicChanged) {
// workaround for the default device to be shown as selected in the
// settings even when the real device id was passed to gUM because of
// the above mentioned chrome bug.
track._realDeviceId = track.deviceId = 'default';
}
mediaType === 'audio'
? this._updateAudioDeviceId()
: this._updateVideoDeviceId();
});
}
return Promise.resolve();
})));
})
.then(() => {
// Log and sync known mute state.
if (audioWasMuted) {
sendAnalytics(createTrackMutedEvent(
'audio',
'device list changed'));
logger.log('Audio mute: device list changed');
muteLocalAudio(true);
}
if (!this.isSharingScreen && videoWasMuted) {
sendAnalytics(createTrackMutedEvent(
'video',
'device list changed'));
logger.log('Video mute: device list changed');
muteLocalVideo(true);
}
}));
return Promise.all(promises)
.then(() => {

View File

@@ -79,6 +79,11 @@ var config = {
// This is useful when the client runs on a host with limited resources.
// noAutoPlayVideo: false,
// Whether to use fake constraints (height: 99999, width: 99999) when calling getDisplayMedia on
// Chromium based browsers. This is intended as a workaround for
// https://bugs.chromium.org/p/chromium/issues/detail?id=1056311
// setScreenSharingResolutionConstraints: true,
// Enable callstats only for a percentage of users.
// This takes a value between 0 and 100 which determines the probability for
// the callstats to be enabled.
@@ -257,6 +262,17 @@ var config = {
// applied locally. FIXME: having these 2 options is confusing.
// startWithVideoMuted: false,
// If set to true, prefer to use the H.264 video codec (if supported).
// Note that it's not recommended to do this because simulcast is not
// supported when using H.264. For 1-to-1 calls this setting is enabled by
// default and can be toggled in the p2p section.
// This option has been deprecated, use preferredCodec under videoQuality section instead.
// preferH264: true,
// If set to true, disable H.264 video codec by stripping it out of the
// SDP.
// disableH264: false,
// Desktop sharing
// Optional desktop sharing frame rate options. Default value: min:5, max:5.
@@ -418,6 +434,12 @@ var config = {
// 90: 2,
// },
// Provides a way to translate the legacy bridge signaling messages, 'LastNChangedEvent',
// 'SelectedEndpointsChangedEvent' and 'ReceiverVideoConstraint' into the new 'ReceiverVideoConstraints' message
// that invokes the new bandwidth allocation algorithm in the bridge which is described here
// - https://github.com/jitsi/jitsi-videobridge/blob/master/doc/allocation.md.
// useNewBandwidthAllocationStrategy: false,
// Specify the settings for video quality optimizations on the client.
// videoQuality: {
// // Provides a way to prevent a video codec from being negotiated on the JVB connection. The codec specified
@@ -901,10 +923,18 @@ var config = {
// If not set, the effective value is 'all'.
// iceTransportPolicy: 'all',
// If set to true, it will prefer to use H.264 for P2P calls (if H.264
// is supported). This setting is deprecated, use preferredCodec instead.
// preferH264: true,
// Provides a way to set the video codec preference on the p2p connection. Acceptable
// codec values are 'VP8', 'VP9' and 'H264'.
// preferredCodec: 'H264',
// If set to true, disable H.264 video codec by stripping it out of the
// SDP. This setting is deprecated, use disabledCodec instead.
// disableH264: false,
// Provides a way to prevent a video codec from being negotiated on the p2p connection.
// disabledCodec: '',
@@ -1061,67 +1091,10 @@ var config = {
// use only.
// _desktopSharingSourceDevice: 'sample-id-or-label',
// DEPRECATED! Use deeplinking.disabled instead.
// If true, any checks to handoff to another application will be prevented
// and instead the app will continue to display in the current browser.
// disableDeepLinking: false,
// The deeplinking config.
// For information about the properties of
// deeplinking.[ios/android].dynamicLink check:
// https://firebase.google.com/docs/dynamic-links/create-manually
// deeplinking: {
//
// // The desktop deeplinking config.
// desktop: {
// appName: 'Jitsi Meet'
// },
// // If true, any checks to handoff to another application will be prevented
// // and instead the app will continue to display in the current browser.
// disabled: false,
// // whether to hide the logo on the deep linking pages.
// hideLogo: false,
// // whether to show deeplinking image.
// showImage: false,
// // The ios deeplinking config.
// ios: {
// appName: 'Jitsi Meet',
// // Specify mobile app scheme for opening the app from the mobile browser.
// appScheme: 'org.jitsi.meet',
// // Custom URL for downloading ios mobile app.
// downloadLink: 'https://itunes.apple.com/us/app/jitsi-meet/id1165103905',
// dynamicLink: {
// apn: 'org.jitsi.meet',
// appCode: 'w2atb',
// customDomain: undefined,
// ibi: 'com.atlassian.JitsiMeet.ios',
// isi: '1165103905'
// }
// },
// // The android deeplinking config.
// android: {
// appName: 'Jitsi Meet',
// // Specify mobile app scheme for opening the app from the mobile browser.
// appScheme: 'org.jitsi.meet',
// // Custom URL for downloading android mobile app.
// downloadLink: 'https://play.google.com/store/apps/details?id=org.jitsi.meet',
// // Android app package name.
// appPackage: 'org.jitsi.meet',
// fDroidUrl: 'https://f-droid.org/en/packages/org.jitsi.meet/',
// dynamicLink: {
// apn: 'org.jitsi.meet',
// appCode: 'w2atb',
// customDomain: undefined,
// ibi: 'com.atlassian.JitsiMeet.ios',
// isi: '1165103905'
// }
// }
// },
// A property to disable the right click context menu for localVideo
// the menu has option to flip the locally seen video for local presentations
// disableLocalVideoFlip: false,

View File

@@ -126,12 +126,6 @@ form {
background-size: contain;
}
.leftwatermarknomargin {
background-position: center left;
background-repeat: no-repeat;
background-size: contain;
}
.rightwatermark {
right: 32px;
top: 32px;

View File

@@ -170,9 +170,8 @@ $welcomePageHeaderPaddingBottom: 0px;
$welcomePageHeaderTitleMaxWidth: initial;
$welcomePageHeaderTextAlign: center;
$welcomePageHeaderContainerMarginTop: 104px;
$welcomePageHeaderContainerDisplay: flex;
$welcomePageHeaderContainerMargin: $welcomePageHeaderContainerMarginTop auto 0;
$welcomePageHeaderContainerMargin: 104px 32px 0 32px;
$welcomePageHeaderTextTitleMarginBottom: 0;
$welcomePageHeaderTextTitleFontSize: 42px;

View File

@@ -29,16 +29,6 @@ body.welcome-page {
flex-direction: column;
margin: $welcomePageHeaderContainerMargin;
z-index: $zindex2;
align-items: center;
position: relative;
max-width: 688px;
}
.header-watermark-container {
position: absolute;
width: 100%;
height: 100%;
margin-top: calc(20px - #{$welcomePageHeaderContainerMarginTop});
}
.header-text-title {
@@ -133,11 +123,16 @@ body.welcome-page {
max-width: calc(100% - 40px);
padding: 16px 0 39px 0;
width: $welcomePageEnterRoomWidth;
text-align: center;
a {
color: inherit;
font-weight: 600;
p {
color: $welcomePageDescriptionColor;
float: left;
text-align: $welcomePageHeaderTextAlign;
a {
color: inherit;
font-weight: 600;
}
}
}
}
@@ -205,8 +200,8 @@ body.welcome-page {
color: $welcomePageDescriptionColor;
padding: 4px;
position: absolute;
top: calc(35px - #{$welcomePageHeaderContainerMarginTop});
right: 0;
top: 32px;
right: 32px;
z-index: $zindex2;
* {
@@ -229,11 +224,6 @@ body.welcome-page {
width: $welcomePageWatermarkWidth;
height: $welcomePageWatermarkHeight;
}
.watermark.leftwatermarknomargin {
width: $welcomePageWatermarkWidth;
height: $welcomePageWatermarkHeight;
}
}
&.without-content {
@@ -252,17 +242,10 @@ body.welcome-page {
padding-top: 40px;
}
.welcome-card-column {
.welcome-card-row {
display: flex;
justify-content: center;
flex-direction: column;
align-items: center;
max-width: 688px;
margin: auto;
> div {
margin-bottom: 16px;
}
padding: 0 32px;
}
.welcome-card-text {
@@ -270,7 +253,7 @@ body.welcome-page {
}
.welcome-card {
width: 100%;
width: 49%;
border-radius: 8px;
&--dark {
@@ -285,6 +268,10 @@ body.welcome-page {
&--grey {
background: #F2F3F4;
}
&--shadow {
box-shadow: 0px 4px 30px rgba(0, 0, 0, 0.15);
}
}
.welcome-footer {

View File

@@ -50,7 +50,7 @@
* Override default InlineDialog behaviour, since it does not play nicely with relative widths
*/
& > div:nth-child(2) {
background: #E0E0E0;
background: #fff;
padding: 0;
position: absolute !important;
width: 100%;

View File

@@ -44,7 +44,12 @@ case "$1" in
fi
JVB_SECRET="$RET"
JICOFO_AUTH_USER="focus"
db_get jicofo/jicofo-authuser
if [ -z "$RET" ] ; then
db_input critical jicofo/jicofo-authuser || true
db_go
fi
JICOFO_AUTH_USER="$RET"
db_get jicofo/jicofo-authpassword
if [ -z "$RET" ] ; then

View File

@@ -13,6 +13,12 @@ Type: password
_Description: Jitsi Videobridge Component secret:
The secret used by Jitsi Videobridge to connect to xmpp server as component.
Template: jicofo/jicofo-authuser
Type: string
Default: focus
_Description: Jicofo username:
The jicofo needs an authenticated admin user to connect to xmpp server.
Template: jicofo/jicofo-authpassword
Type: password
_Description: Jicofo user password:

View File

@@ -76,6 +76,11 @@ var interfaceConfig = {
GENERATE_ROOMNAMES_ON_WELCOME_PAGE: true,
/**
* Hide the logo on the deep linking pages.
*/
HIDE_DEEP_LINKING_LOGO: false,
/**
* Hide the invite prompt in the header when alone in the meeting.
*/
@@ -103,6 +108,23 @@ var interfaceConfig = {
*/
MOBILE_APP_PROMO: true,
/**
* Specify custom URL for downloading android mobile app.
*/
MOBILE_DOWNLOAD_LINK_ANDROID: 'https://play.google.com/store/apps/details?id=org.jitsi.meet',
/**
* Specify custom URL for downloading f droid app.
*/
MOBILE_DOWNLOAD_LINK_F_DROID: 'https://f-droid.org/en/packages/org.jitsi.meet/',
/**
* Specify URL for downloading ios mobile app.
*/
MOBILE_DOWNLOAD_LINK_IOS: 'https://itunes.apple.com/us/app/jitsi-meet/id1165103905',
NATIVE_APP_NAME: 'Jitsi Meet',
// Names of browsers which should show a warning stating the current browser
// has a suboptimal experience. Browsers which are not listed as optimal or
// unsupported are considered suboptimal. Valid values are:
@@ -137,6 +159,7 @@ var interfaceConfig = {
*/
SHOW_CHROME_EXTENSION_BANNER: false,
SHOW_DEEP_LINKING_IMAGE: false,
SHOW_JITSI_WATERMARK: true,
SHOW_POWERED_BY: false,
SHOW_PROMOTIONAL_CLOSE_PAGE: false,
@@ -177,33 +200,6 @@ var interfaceConfig = {
*/
// TILE_VIEW_MAX_COLUMNS: 5,
// List of undocumented settings
/**
INDICATOR_FONT_SIZES
PHONE_NUMBER_REGEX
*/
// -----------------DEPRECATED CONFIGS BELOW THIS LINE-----------------------------
/**
* Specify URL for downloading ios mobile app.
*/
// MOBILE_DOWNLOAD_LINK_IOS: 'https://itunes.apple.com/us/app/jitsi-meet/id1165103905',
/**
* Specify custom URL for downloading android mobile app.
*/
// MOBILE_DOWNLOAD_LINK_ANDROID: 'https://play.google.com/store/apps/details?id=org.jitsi.meet',
// SHOW_DEEP_LINKING_IMAGE: false,
/**
* Specify mobile app scheme for opening the app from the mobile browser.
*/
// APP_SCHEME: 'org.jitsi.meet',
// NATIVE_APP_NAME: 'Jitsi Meet',
/**
* Specify Firebase dynamic link properties for the mobile apps.
*/
@@ -216,19 +212,22 @@ var interfaceConfig = {
// },
/**
* Hide the logo on the deep linking pages.
* Specify mobile app scheme for opening the app from the mobile browser.
*/
// HIDE_DEEP_LINKING_LOGO: false,
// APP_SCHEME: 'org.jitsi.meet',
/**
* Specify the Android app package name.
*/
// ANDROID_APP_PACKAGE: 'org.jitsi.meet',
// List of undocumented settings
/**
* Specify custom URL for downloading f droid app.
*/
// MOBILE_DOWNLOAD_LINK_F_DROID: 'https://f-droid.org/en/packages/org.jitsi.meet/',
INDICATOR_FONT_SIZES
PHONE_NUMBER_REGEX
*/
// -----------------DEPRECATED CONFIGS BELOW THIS LINE-----------------------------
// Connection indicators (
// CONNECTION_INDICATOR_AUTO_HIDE_ENABLED,

View File

@@ -373,12 +373,8 @@ PODS:
- React-Core
- react-native-performance (2.1.0):
- React-Core
- react-native-safe-area-context (4.4.1):
- RCT-Folly
- RCTRequired
- RCTTypeSafety
- react-native-safe-area-context (3.3.2):
- React-Core
- ReactCommon/turbomodule/core
- react-native-slider (4.1.12):
- React-Core
- react-native-splash-screen (3.3.0):
@@ -389,7 +385,7 @@ PODS:
- react-native-video/Video (6.0.0-alpha.1):
- PromisesSwift
- React-Core
- react-native-webrtc (106.0.3):
- react-native-webrtc (106.0.0):
- JitsiWebRTC (~> 106.0.0)
- React-Core
- react-native-webview (11.15.1):
@@ -471,7 +467,7 @@ PODS:
- React-Core
- RNDeviceInfo (8.4.8):
- React-Core
- RNGestureHandler (2.8.0):
- RNGestureHandler (2.1.0):
- React-Core
- RNGoogleSignin (7.0.4):
- GoogleSignIn (~> 6.0.0)
@@ -755,11 +751,11 @@ SPEC CHECKSUMS:
react-native-orientation-locker: 851f6510d8046ea2f14aa169b1e01fcd309a94ba
react-native-pager-view: 3ee7d4c7697fb3ef788346e834a60cca97ed8540
react-native-performance: f4b6604a9d5a8a7407e34a82fab6c641d9a3ec12
react-native-safe-area-context: 99b24a0c5acd0d5dcac2b1a7f18c49ea317be99a
react-native-safe-area-context: 584dc04881deb49474363f3be89e4ca0e854c057
react-native-slider: 6e9b86e76cce4b9e35b3403193a6432ed07e0c81
react-native-splash-screen: 4312f786b13a81b5169ef346d76d33bc0c6dc457
react-native-video: bb6f12a7198db53b261fefb5d609dc77417acc8b
react-native-webrtc: 3018e24970f1cc1b37f2dcbe38034e5b41133a70
react-native-webrtc: 0a407105bf428c9157f2e8d4d6f7c844dc185933
react-native-webview: ea4899a1056c782afa96dd082179a66cbebf5504
React-perflogger: 0458a87ea9a7342079e7a31b0d32b3734fb8415f
React-RCTActionSheet: 22538001ea2926dea001111dd2846c13a0730bc9
@@ -779,7 +775,7 @@ SPEC CHECKSUMS:
RNCMaskedView: c298b644a10c0c142055b3ae24d83879ecb13ccd
RNDefaultPreference: 08bdb06cfa9188d5da97d4642dac745218d7fb31
RNDeviceInfo: 0400a6d0c94186d1120c3cbd97b23abc022187a9
RNGestureHandler: 62232ba8f562f7dea5ba1b3383494eb5bf97a4d3
RNGestureHandler: e5c7cab5f214503dcefd6b2b0cefb050e1f51c4a
RNGoogleSignin: c4381751eefd73c552b923ba347a9bfc6f18771c
RNScreens: 40a2cb40a02a609938137a1e0acfbf8fc9eebf19
RNSound: 27e8268bdb0a1f191f219a33267f7e0445e8d62f

View File

@@ -147,7 +147,6 @@
"bridgeCount": "Serverzahl: ",
"codecs": "Codecs (A/V): ",
"connectedTo": "Verbunden mit:",
"e2eeVerified": "E2EE verifiziert:",
"framerate": "Bildwiederholrate:",
"less": "Weniger anzeigen",
"localaddress": "Lokale Adresse:",
@@ -409,10 +408,6 @@
"user": "Anmeldename",
"userIdentifier": "Benutzername",
"userPassword": "Passwort",
"verifyParticipantConfirm": "Sie stimmen überein",
"verifyParticipantDismiss": "Sie stimmen nicht überein",
"verifyParticipantQuestion": "EXPERIMENTELL: Frage Person {{participantName}} ob sie den selben Inhalt in der selben Reihenfolge sieht.",
"verifyParticipantTitle": "Personsverifikation",
"videoLink": "Video-Link",
"viewUpgradeOptions": "Upgradeoptionen anzeigen",
"viewUpgradeOptionsContent": "Sie müssen Ihren Tarif erweitern, um Premium-Features wie Aufnahme, Transkription, RTMP-Streaming und mehr zu nutzen.",
@@ -442,6 +437,9 @@
"noResults": "Keine Ergebnisse :(",
"search": "GIPHY durchsuchen"
},
"helpView": {
"title": "Hilfecenter"
},
"incomingCall": {
"answer": "Antworten",
"audioCallTitle": "Eingehender Anruf",
@@ -565,6 +563,7 @@
"lobby": {
"admit": "Zulassen",
"admitAll": "Alle zulassen",
"allow": "Annehmen",
"backToKnockModeButton": "Kein Passwort, stattdessen Beitritt anfragen",
"chat": "Chat",
"dialogTitle": "Lobbymodus",
@@ -650,8 +649,6 @@
"connectedOneMember": "{{name}} nimmt am Meeting teil",
"connectedThreePlusMembers": "{{name}} und {{count}} andere Personen nehmen am Meeting teil",
"connectedTwoMembers": "{{first}} und {{second}} nehmen am Meeting teil",
"dataChannelClosed": "Schlechte Videoqualität",
"dataChannelClosedDescription": "Die Steuerungsverbindung (Bridge Channel) wurde unterbrochen, daher ist die Videoqulität auf die schlechteste Stufe limitiert.",
"disconnected": "getrennt",
"displayNotifications": "Benachrichtigungen anzeigen für",
"focus": "Konferenzleitung",
@@ -712,8 +709,6 @@
"reactionSoundsForAll": "Interaktionstöne für alle deaktivieren",
"screenShareNoAudio": "Die Option \"Audio freigeben\" wurde bei der Auswahl des Fensters nicht ausgewählt.",
"screenShareNoAudioTitle": "Share audio was not checked",
"screenSharingAudioOnlyDescription": "Durch die Bildschirmfreigabe wird der Modus \"Beste Leistung\" beeinflusst und daher mehr Datenrate benötigt.",
"screenSharingAudioOnlyTitle": "Modus \"Beste Leistung\"",
"selfViewTitle": "Sie können die eigene Ansicht immer in den Einstellungen reaktivieren",
"somebody": "Jemand",
"startSilentDescription": "Treten Sie dem Meeting noch einmal bei, um Ihr Audio zu aktivieren",
@@ -863,6 +858,9 @@
"rejected": "Abgelehnt",
"ringing": "Es klingelt …"
},
"privacyView": {
"title": "Datenschutz"
},
"profile": {
"avatar": "Benutzerbild",
"setDisplayNameLabel": "Anzeigename festlegen",
@@ -1005,7 +1003,6 @@
"displayName": "Anzeigename",
"displayNamePlaceholderText": "z.B. Erika Musterfrau",
"email": "E-Mail",
"emailPlaceholderText": "email@beispiel.de",
"goTo": "Gehe zu",
"header": "Einstellungen",
"help": "Hilfe",
@@ -1014,7 +1011,6 @@
"profileSection": "Profil",
"serverURL": "Server-URL",
"showAdvanced": "Erweiterte Einstellungen anzeigen",
"startCarModeInLowBandwidthMode": "Automodus mit Datensparmodus starten",
"startWithAudioMuted": "Stumm beitreten",
"startWithVideoMuted": "Ohne Video beitreten",
"terms": "Nutzungsbedingungen",
@@ -1294,7 +1290,6 @@
"show": "Im Vordergrund anzeigen",
"showSelfView": "Eigene Ansicht anzeigen",
"unpinFromStage": "Lösen",
"verify": "Person verifizieren",
"videoMuted": "Kamera ausgeschaltet",
"videomute": "Person hat die Kamera angehalten"
},
@@ -1362,7 +1357,6 @@
"recentList": "Verlauf",
"recentListDelete": "Eintrag löschen",
"recentListEmpty": "Ihr Konferenzverlauf ist derzeit leer. Reden Sie mit Ihrem Team und Ihre vergangenen Konferenzen landen hier.",
"recentMeetings": "Ihre letzten Konferenzen",
"reducedUIText": "Willkommen bei {{app}}!",
"roomNameAllowedChars": "Der Konferenzname sollte keines der folgenden Zeichen enthalten: ?, &, :, ', \", %, #.",
"roomname": "Konferenzname eingeben",
@@ -1371,7 +1365,6 @@
"settings": "Einstellungen",
"startMeeting": "Meeting starten",
"terms": "AGB",
"title": "Sichere, voll funktionale und komplett kostenlose Videokonferenzen",
"upcomingMeetings": "Ihre zukünftigen Konferenzen"
"title": "Sichere, voll funktionale und komplett kostenlose Videokonferenzen"
}
}

View File

@@ -442,6 +442,9 @@
"noResults": "No results found :(",
"search": "Search GIPHY"
},
"helpView": {
"title": "Help center"
},
"incomingCall": {
"answer": "Answer",
"audioCallTitle": "Incoming call",
@@ -712,8 +715,6 @@
"reactionSoundsForAll": "Disable sounds for all",
"screenShareNoAudio": "Share audio box was not checked in the window selection screen.",
"screenShareNoAudioTitle": "Couldn't share system audio!",
"screenSharingAudioOnlyDescription": "Please note that by sharing your screen you're affecting the \"Best performance\" mode and you will use more bandwidth.",
"screenSharingAudioOnlyTitle": "\"Best performance\" mode",
"selfViewTitle": "You can always un-hide the self-view from settings",
"somebody": "Somebody",
"startSilentDescription": "Rejoin the meeting to enable audio",
@@ -863,6 +864,9 @@
"rejected": "Rejected",
"ringing": "Ringing..."
},
"privacyView": {
"title": "Privacy"
},
"profile": {
"avatar": "avatar",
"setDisplayNameLabel": "Set your display name",
@@ -1362,7 +1366,6 @@
"recentList": "Recent",
"recentListDelete": "Delete entry",
"recentListEmpty": "Your recent list is currently empty. Chat with your team and you will find all your recent meetings here.",
"recentMeetings": "Your recent meetings",
"reducedUIText": "Welcome to {{app}}!",
"roomNameAllowedChars": "Meeting name should not contain any of these characters: ?, &, :, ', \", %, #.",
"roomname": "Enter room name",
@@ -1371,7 +1374,6 @@
"settings": "Settings",
"startMeeting": "Start meeting",
"terms": "Terms",
"title": "Secure, fully featured, and completely free video conferencing",
"upcomingMeetings": "Your upcoming meetings"
"title": "Secure, fully featured, and completely free video conferencing"
}
}

View File

@@ -158,6 +158,7 @@ export default {
* Determines if currently selected media devices should be changed after
* list of available devices has been changed.
* @param {MediaDeviceInfo[]} newDevices
* @param {boolean} isSharingScreen
* @param {JitsiLocalTrack} localVideo
* @param {JitsiLocalTrack} localAudio
* @returns {{
@@ -168,12 +169,13 @@ export default {
*/
getNewMediaDevicesAfterDeviceListChanged( // eslint-disable-line max-params
newDevices,
isSharingScreen,
localVideo,
localAudio,
newLabels) {
return {
audioinput: getNewAudioInputDevice(newDevices, localAudio, newLabels),
videoinput: getNewVideoInputDevice(newDevices, localVideo, newLabels),
videoinput: isSharingScreen ? undefined : getNewVideoInputDevice(newDevices, localVideo, newLabels),
audiooutput: getNewAudioOutputDevice(newDevices)
};
},

509
package-lock.json generated
View File

@@ -42,11 +42,11 @@
"@react-native-community/slider": "4.1.12",
"@react-native-google-signin/google-signin": "7.0.4",
"@react-native-masked-view/masked-view": "0.2.6",
"@react-navigation/bottom-tabs": "6.5.3",
"@react-navigation/elements": "1.3.13",
"@react-navigation/material-top-tabs": "6.5.2",
"@react-navigation/native": "6.1.2",
"@react-navigation/stack": "6.3.11",
"@react-navigation/bottom-tabs": "6.0.9",
"@react-navigation/elements": "1.2.1",
"@react-navigation/material-top-tabs": "6.0.6",
"@react-navigation/native": "6.0.6",
"@react-navigation/stack": "6.2.2",
"@svgr/webpack": "6.3.1",
"@tensorflow/tfjs-backend-wasm": "3.13.0",
"@tensorflow/tfjs-core": "3.13.0",
@@ -74,7 +74,7 @@
"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/v1569.0.0+5f8d02c9/lib-jitsi-meet.tgz",
"lib-jitsi-meet": "https://github.com/jitsi/lib-jitsi-meet/releases/download/v1557.0.0+8df33524/lib-jitsi-meet.tgz",
"lodash": "4.17.21",
"moment": "2.29.4",
"moment-duration-format": "2.2.2",
@@ -96,15 +96,15 @@
"react-native-default-preference": "1.4.4",
"react-native-device-info": "8.4.8",
"react-native-dialog": "https://github.com/jitsi/react-native-dialog/releases/download/v9.2.2-jitsi.1/react-native-dialog-9.2.2.tgz",
"react-native-gesture-handler": "2.8.0",
"react-native-gesture-handler": "2.1.0",
"react-native-get-random-values": "1.7.2",
"react-native-immersive": "2.0.0",
"react-native-keep-awake": "4.0.0",
"react-native-orientation-locker": "1.5.0",
"react-native-pager-view": "5.4.9",
"react-native-paper": "5.1.2",
"react-native-paper": "4.11.1",
"react-native-performance": "2.1.0",
"react-native-safe-area-context": "4.4.1",
"react-native-safe-area-context": "3.3.2",
"react-native-screens": "3.13.1",
"react-native-sound": "0.11.1",
"react-native-splash-screen": "3.3.0",
@@ -114,7 +114,7 @@
"react-native-url-polyfill": "1.3.0",
"react-native-video": "https://git@github.com/react-native-video/react-native-video#7c48ae7c8544b2b537fb60194e9620b9fcceae52",
"react-native-watch-connectivity": "1.0.11",
"react-native-webrtc": "106.0.3",
"react-native-webrtc": "106.0.0",
"react-native-webview": "11.15.1",
"react-native-youtube-iframe": "2.2.1",
"react-redux": "7.1.0",
@@ -2928,9 +2928,9 @@
}
},
"node_modules/@callstack/react-theme-provider": {
"version": "3.0.8",
"resolved": "https://registry.npmjs.org/@callstack/react-theme-provider/-/react-theme-provider-3.0.8.tgz",
"integrity": "sha512-5U231sYY2sqQOaELX0WBCn+iluV8bFaXIS7em03k4W5Xz0AhGvKlnpLIhDGFP8im/SvNW7/2XoR0BsClhn9t6Q==",
"version": "3.0.7",
"resolved": "https://registry.npmjs.org/@callstack/react-theme-provider/-/react-theme-provider-3.0.7.tgz",
"integrity": "sha512-Ab6rbD2w4u9W3yf7LQQ8evx9m8fZNsoWxt+MFm3AyZnyKQNCJf4K7ip9tHHZgSs+HTdoj38lEqPehvFOVQKvAg==",
"dependencies": {
"deepmerge": "^3.2.0",
"hoist-non-react-statics": "^3.3.0"
@@ -5465,12 +5465,12 @@
"integrity": "sha512-K0aGNn1TjalKj+65D7ycc1//H9roAQ51GJVk5ZJQFb2teECGmzd86bYDC0aYdbRf7gtovescq4Zt6FR0tgXiHQ=="
},
"node_modules/@react-navigation/bottom-tabs": {
"version": "6.5.3",
"resolved": "https://registry.npmjs.org/@react-navigation/bottom-tabs/-/bottom-tabs-6.5.3.tgz",
"integrity": "sha512-ZA2Ko9fNwNaaSNn7738KpEk8Doi+yjRfTg8Wb/WvduIaK/28qNLAYWBCUEVjBC55y/9zJOzwc4R8Av2J2MG/4g==",
"version": "6.0.9",
"resolved": "https://registry.npmjs.org/@react-navigation/bottom-tabs/-/bottom-tabs-6.0.9.tgz",
"integrity": "sha512-uRoq6Zd7lPNnLqNQkKC28eR62tpqcDeuakZU1sO8N46FtvrcTuNLoIlssrGty3GF7ALBIxCypn4A93t3nbmMrQ==",
"dependencies": {
"@react-navigation/elements": "^1.3.13",
"color": "^4.2.3",
"@react-navigation/elements": "^1.2.1",
"color": "^3.1.3",
"warn-once": "^0.1.0"
},
"peerDependencies": {
@@ -5481,45 +5481,16 @@
"react-native-screens": ">= 3.0.0"
}
},
"node_modules/@react-navigation/bottom-tabs/node_modules/color": {
"version": "4.2.3",
"resolved": "https://registry.npmjs.org/color/-/color-4.2.3.tgz",
"integrity": "sha512-1rXeuUUiGGrykh+CeBdu5Ie7OJwinCgQY0bc7GCRxy5xVHy+moaqkpL/jqQq0MtQOeYcrqEz4abc5f0KtU7W4A==",
"dependencies": {
"color-convert": "^2.0.1",
"color-string": "^1.9.0"
},
"engines": {
"node": ">=12.5.0"
}
},
"node_modules/@react-navigation/bottom-tabs/node_modules/color-convert": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
"integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
"dependencies": {
"color-name": "~1.1.4"
},
"engines": {
"node": ">=7.0.0"
}
},
"node_modules/@react-navigation/bottom-tabs/node_modules/color-name": {
"version": "1.1.4",
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA=="
},
"node_modules/@react-navigation/core": {
"version": "6.4.6",
"resolved": "https://registry.npmjs.org/@react-navigation/core/-/core-6.4.6.tgz",
"integrity": "sha512-6zaAgUT5k4vhJlddUk2l52RZyMkMelHdrRv1cL57ALi2RZzERdgmbiMKhJerxFLn9S8E3PUe8vwxHzjHOZKG4w==",
"version": "6.1.1",
"resolved": "https://registry.npmjs.org/@react-navigation/core/-/core-6.1.1.tgz",
"integrity": "sha512-njysuiqztgvR1Z9Noxk2OGJfYtFGFDRyji5Vmm1jHzlql0m+q0wh1dUiyaIEtTyrhFXr/YNgdrKuiPaU9Jp8OA==",
"dependencies": {
"@react-navigation/routers": "^6.1.6",
"@react-navigation/routers": "^6.1.0",
"escape-string-regexp": "^4.0.0",
"nanoid": "^3.1.23",
"query-string": "^7.1.3",
"react-is": "^16.13.0",
"use-latest-callback": "^0.1.5"
"query-string": "^7.0.0",
"react-is": "^16.13.0"
},
"peerDependencies": {
"react": "*"
@@ -5531,9 +5502,9 @@
"integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ=="
},
"node_modules/@react-navigation/elements": {
"version": "1.3.13",
"resolved": "https://registry.npmjs.org/@react-navigation/elements/-/elements-1.3.13.tgz",
"integrity": "sha512-LqqK5s2ZfYHn2cQ376jC5V9dQztLH5ixkkJj9WR7JY2g4SghDd39WJhL3Jillw1Mu3F3b9sZwvAK+QkXhnDeAA==",
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/@react-navigation/elements/-/elements-1.2.1.tgz",
"integrity": "sha512-EnmAbKMsptrliRKf95rdgS6BhMjML+mIns06+G1Vdih6BrEo7/0iytThUv3WBf99AI76dyEq/cqLUwHPiFzXWg==",
"peerDependencies": {
"@react-navigation/native": "^6.0.0",
"react": "*",
@@ -5542,11 +5513,11 @@
}
},
"node_modules/@react-navigation/material-top-tabs": {
"version": "6.5.2",
"resolved": "https://registry.npmjs.org/@react-navigation/material-top-tabs/-/material-top-tabs-6.5.2.tgz",
"integrity": "sha512-i/R3bEXVE5pygWP0dOMdFNOVzrQyHXL0lbqLfQx5HZXwbvCrpUBFqOED3bWLBrBOUhHQSXfYgTuteAfIF5hzzg==",
"version": "6.0.6",
"resolved": "https://registry.npmjs.org/@react-navigation/material-top-tabs/-/material-top-tabs-6.0.6.tgz",
"integrity": "sha512-kbm/0jndRVeGdAgOd4NcDSdSQiYeA7fkctCKbPxe3mT36j9qOqpfHfmd2dbv/VbNCngdTtZ3/+QMxTIViZGy7g==",
"dependencies": {
"color": "^4.2.3",
"color": "^3.1.3",
"warn-once": "^0.1.0"
},
"peerDependencies": {
@@ -5557,42 +5528,13 @@
"react-native-tab-view": ">= 3.0.0"
}
},
"node_modules/@react-navigation/material-top-tabs/node_modules/color": {
"version": "4.2.3",
"resolved": "https://registry.npmjs.org/color/-/color-4.2.3.tgz",
"integrity": "sha512-1rXeuUUiGGrykh+CeBdu5Ie7OJwinCgQY0bc7GCRxy5xVHy+moaqkpL/jqQq0MtQOeYcrqEz4abc5f0KtU7W4A==",
"dependencies": {
"color-convert": "^2.0.1",
"color-string": "^1.9.0"
},
"engines": {
"node": ">=12.5.0"
}
},
"node_modules/@react-navigation/material-top-tabs/node_modules/color-convert": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
"integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
"dependencies": {
"color-name": "~1.1.4"
},
"engines": {
"node": ">=7.0.0"
}
},
"node_modules/@react-navigation/material-top-tabs/node_modules/color-name": {
"version": "1.1.4",
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA=="
},
"node_modules/@react-navigation/native": {
"version": "6.1.2",
"resolved": "https://registry.npmjs.org/@react-navigation/native/-/native-6.1.2.tgz",
"integrity": "sha512-qLUe0asHofr5EhxKjvUBJ9DrPPmR4535IEwmW3oU4DRb3cLbNysjajJKHL8kcYtqPvn9Bx9QZG2x0PMb2vN23A==",
"version": "6.0.6",
"resolved": "https://registry.npmjs.org/@react-navigation/native/-/native-6.0.6.tgz",
"integrity": "sha512-XzL7YPsaRRQgdCQSXbA8PJWLN2I4lhUUvSFoKQPNO4DS6y8eqZI1V8COPYlJg8+tsetGV5J8jt+jVjWL7h6ZrQ==",
"dependencies": {
"@react-navigation/core": "^6.4.6",
"@react-navigation/core": "^6.1.0",
"escape-string-regexp": "^4.0.0",
"fast-deep-equal": "^3.1.3",
"nanoid": "^3.1.23"
},
"peerDependencies": {
@@ -5601,19 +5543,19 @@
}
},
"node_modules/@react-navigation/routers": {
"version": "6.1.6",
"resolved": "https://registry.npmjs.org/@react-navigation/routers/-/routers-6.1.6.tgz",
"integrity": "sha512-Z5DeCW3pUvMafbU9Cjy1qJYC2Bvl8iy3+PfsB0DsAwQ6zZ3WAXW5FTMX4Gb9H+Jg6qHWGbMFFwlYpS3UJ3tlVQ==",
"version": "6.1.0",
"resolved": "https://registry.npmjs.org/@react-navigation/routers/-/routers-6.1.0.tgz",
"integrity": "sha512-8xJL+djIzpFdRW/sGlKojQ06fWgFk1c5jER9501HYJ12LF5DIJFr/tqBI2TJ6bk+y+QFu0nbNyeRC80OjRlmkA==",
"dependencies": {
"nanoid": "^3.1.23"
}
},
"node_modules/@react-navigation/stack": {
"version": "6.3.11",
"resolved": "https://registry.npmjs.org/@react-navigation/stack/-/stack-6.3.11.tgz",
"integrity": "sha512-GWOAyJfPEsjVwDWec1ERwWL5LvManJucCRUZetJqCBs4/mV7HXEt2x6l3SMitHxH1+K+9XuYXI+wBTbK1WDYOA==",
"version": "6.2.2",
"resolved": "https://registry.npmjs.org/@react-navigation/stack/-/stack-6.2.2.tgz",
"integrity": "sha512-P9ZfmluOXNmbs7YdG1UWS1fAh87Yse9aX8TgqOz4FlHEm5q7g5eaM35QgWByt+wif3UiqE40D8wXpqRQvMgPWg==",
"dependencies": {
"@react-navigation/elements": "^1.3.13",
"@react-navigation/elements": "^1.3.4",
"color": "^4.2.3",
"warn-once": "^0.1.0"
},
@@ -5626,6 +5568,17 @@
"react-native-screens": ">= 3.0.0"
}
},
"node_modules/@react-navigation/stack/node_modules/@react-navigation/elements": {
"version": "1.3.4",
"resolved": "https://registry.npmjs.org/@react-navigation/elements/-/elements-1.3.4.tgz",
"integrity": "sha512-O0jICpjn3jskVo4yiWzZozmj7DZy1ZBbn3O7dbenuUjZSj/cscjwaapmZZFGcI/IMmjmx8UTKsybhCFEIbGf3g==",
"peerDependencies": {
"@react-navigation/native": "^6.0.0",
"react": "*",
"react-native": "*",
"react-native-safe-area-context": ">= 3.0.0"
}
},
"node_modules/@react-navigation/stack/node_modules/color": {
"version": "4.2.3",
"resolved": "https://registry.npmjs.org/color/-/color-4.2.3.tgz",
@@ -9343,9 +9296,9 @@
}
},
"node_modules/decode-uri-component": {
"version": "0.2.2",
"resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.2.tgz",
"integrity": "sha512-FqUYQ+8o158GyGTrMFJms9qh3CqTKvAqgqsTnkLI8sKu0028orqBhxNMFkFen0zGyg6epACD32pjVk58ngIErQ==",
"version": "0.2.0",
"resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.0.tgz",
"integrity": "sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU=",
"engines": {
"node": ">=0.10"
}
@@ -11188,7 +11141,7 @@
"node_modules/filter-obj": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/filter-obj/-/filter-obj-1.1.0.tgz",
"integrity": "sha512-8rXg1ZnX7xzy2NGDVkBVaAy+lSlPNwad13BtgSlLuxfIslyt5Vg64U7tFcCt4WS1R0hvtnQybT/IyCkGZ3DpXQ==",
"integrity": "sha1-mzERErxsYSehbgFsbF1/GeCAXFs=",
"engines": {
"node": ">=0.10.0"
}
@@ -13357,9 +13310,9 @@
"dev": true
},
"node_modules/json5": {
"version": "2.2.3",
"resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz",
"integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==",
"version": "2.2.1",
"resolved": "https://registry.npmjs.org/json5/-/json5-2.2.1.tgz",
"integrity": "sha512-1hqLFMSrGHRHxav9q9gNjJ5EXznIxGVO09xQRrwplcS8qs28pZ8s8hupZAmqDwZUmVZ2Qb2jnyPOWcDH8m8dlA==",
"bin": {
"json5": "lib/cli.js"
},
@@ -13544,13 +13497,13 @@
},
"node_modules/lib-jitsi-meet": {
"version": "0.0.0",
"resolved": "https://github.com/jitsi/lib-jitsi-meet/releases/download/v1569.0.0+5f8d02c9/lib-jitsi-meet.tgz",
"integrity": "sha512-XD0YS84XjK+KnjW3qT4oZ4/+n2mSTHpJNwYqFgvvrFd1MHLL96k9UOIcTkU/yOuxkf69ZKfx9QtCnfnYrpkTIQ==",
"resolved": "https://github.com/jitsi/lib-jitsi-meet/releases/download/v1557.0.0+8df33524/lib-jitsi-meet.tgz",
"integrity": "sha512-LH24V3aCAyNxrXkYsr4Syz9G+hDyfGo7JUu3suEbh1bS5Y4w8mwzTBHyGazLnD7/NDG5F783DY19/yCzR7stSQ==",
"license": "Apache-2.0",
"dependencies": {
"@jitsi/js-utils": "2.0.0",
"@jitsi/logger": "2.0.0",
"@jitsi/sdp-interop": "git+https://github.com/jitsi/sdp-interop#3d49eb4aa26863a3f8d32d7581cdb4321244266b",
"@jitsi/sdp-interop": "https://git@github.com/jitsi/sdp-interop#3d49eb4aa26863a3f8d32d7581cdb4321244266b",
"@jitsi/sdp-simulcast": "0.4.0",
"async": "3.2.3",
"base64-js": "1.3.1",
@@ -13563,7 +13516,7 @@
"sdp-transform": "2.3.0",
"strophe.js": "1.3.4",
"strophejs-plugin-disco": "0.0.2",
"strophejs-plugin-stream-management": "git+https://github.com/jitsi/strophejs-plugin-stream-management#001cf02bef2357234e1ac5d163611b4d60bf2b6a",
"strophejs-plugin-stream-management": "https://git@github.com/jitsi/strophejs-plugin-stream-management#001cf02bef2357234e1ac5d163611b4d60bf2b6a",
"uuid": "8.1.0",
"webrtc-adapter": "8.1.1"
}
@@ -13618,9 +13571,9 @@
}
},
"node_modules/loader-utils": {
"version": "1.4.2",
"resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.4.2.tgz",
"integrity": "sha512-I5d00Pd/jwMD2QCduo657+YM/6L3KZu++pmX9VFncxaxvHcru9jx1lBaFft+r4Mt2jK0Yhp41XlRAihzPxHNCg==",
"version": "1.4.1",
"resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.4.1.tgz",
"integrity": "sha512-1Qo97Y2oKaU+Ro2xnDMR26g1BwMT29jNbem1EvcujW2jqt+j5COXyscjM7bLQkM9HaxI7pkWeW7gnI072yMI9Q==",
"dev": true,
"dependencies": {
"big.js": "^5.2.2",
@@ -13632,9 +13585,9 @@
}
},
"node_modules/loader-utils/node_modules/json5": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/json5/-/json5-1.0.2.tgz",
"integrity": "sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==",
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/json5/-/json5-1.0.1.tgz",
"integrity": "sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow==",
"dev": true,
"dependencies": {
"minimist": "^1.2.0"
@@ -14543,9 +14496,9 @@
"integrity": "sha512-xGPXiFVl4YED9Jh7Euv2V220mriG9u4B2TA6Ybjc1catrstKD2PpIdU3U0RKpkVBC2EhmL/F0sPCr9vrFTNRag=="
},
"node_modules/nanoid": {
"version": "3.3.4",
"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.4.tgz",
"integrity": "sha512-MqBkQh/OHTS2egovRtLk45wEyNXwF+cokD+1YPf9u5VfJiRdAiRwB2froX5Co9Rh20xs4siNPm8naNotSD6RBw==",
"version": "3.3.1",
"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.1.tgz",
"integrity": "sha512-n6Vs/3KGyxPQd6uO0eH4Bv0ojGSUvuLlIHtC3Y0kEO23YRge8H9x1GCzLn28YX0H66pMkxuaeESFq4tKISKwdw==",
"bin": {
"nanoid": "bin/nanoid.cjs"
},
@@ -14758,9 +14711,9 @@
}
},
"node_modules/null-loader/node_modules/loader-utils": {
"version": "2.0.4",
"resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.4.tgz",
"integrity": "sha512-xXqpXoINfFhgua9xiqD8fPFHgkoq1mmmpE92WlDbm9rNRd/EbRb+Gqf908T2DMfuHjjJlksiK2RbHVOdD/MqSw==",
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.3.tgz",
"integrity": "sha512-THWqIsn8QRnvLl0shHYVBN9syumU8pYWEHPTmkiVGd+7K5eFNVSY6AJhRvgGF70gg1Dz+l/k8WicvFCxdEs60A==",
"dependencies": {
"big.js": "^5.2.2",
"emojis-list": "^3.0.0",
@@ -15942,11 +15895,11 @@
}
},
"node_modules/query-string": {
"version": "7.1.3",
"resolved": "https://registry.npmjs.org/query-string/-/query-string-7.1.3.tgz",
"integrity": "sha512-hh2WYhq4fi8+b+/2Kg9CEge4fDPvHS534aOOvOZeQ3+Vf2mCFsaFBYj0i+iXcAq6I9Vzp5fjMFBlONvayDC1qg==",
"version": "7.1.1",
"resolved": "https://registry.npmjs.org/query-string/-/query-string-7.1.1.tgz",
"integrity": "sha512-MplouLRDHBZSG9z7fpuAAcI7aAYjDLhtsiVZsevsfaHWDS2IDdORKbSd1kWUA+V4zyva/HZoSfpwnYMMQDhb0w==",
"dependencies": {
"decode-uri-component": "^0.2.2",
"decode-uri-component": "^0.2.0",
"filter-obj": "^1.1.0",
"split-on-first": "^1.0.0",
"strict-uri-encode": "^2.0.0"
@@ -16293,19 +16246,15 @@
}
},
"node_modules/react-native-gesture-handler": {
"version": "2.8.0",
"resolved": "https://registry.npmjs.org/react-native-gesture-handler/-/react-native-gesture-handler-2.8.0.tgz",
"integrity": "sha512-poOSfz/w0IyD6Qwq7aaIRRfEaVTl1ecQFoyiIbpOpfNTjm2B1niY2FLrdVQIOtIOe+K9nH55Qal04nr4jGkHdQ==",
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/react-native-gesture-handler/-/react-native-gesture-handler-2.1.0.tgz",
"integrity": "sha512-vF4yEUrV5GMBioTkvf5Le1l3N/52dSLBnNMFC+kZ4hssnRoXB0hEQ0ReUkZckRB5L3nbHBhAyjySEtFPx4nyEA==",
"dependencies": {
"@egjs/hammerjs": "^2.0.17",
"hoist-non-react-statics": "^3.3.0",
"invariant": "^2.2.4",
"lodash": "^4.17.21",
"prop-types": "^15.7.2"
},
"peerDependencies": {
"react": "*",
"react-native": "*"
}
},
"node_modules/react-native-get-random-values": {
@@ -16332,6 +16281,14 @@
"react-native": ">=0.47.0"
}
},
"node_modules/react-native-iphone-x-helper": {
"version": "1.3.1",
"resolved": "https://registry.npmjs.org/react-native-iphone-x-helper/-/react-native-iphone-x-helper-1.3.1.tgz",
"integrity": "sha512-HOf0jzRnq2/aFUcdCJ9w9JGzN3gdEg0zFE4FyYlp4jtidqU03D5X7ZegGKfT1EWteR0gPBGp9ye5T5FvSWi9Yg==",
"peerDependencies": {
"react-native": ">=0.42.0"
}
},
"node_modules/react-native-keep-awake": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/react-native-keep-awake/-/react-native-keep-awake-4.0.0.tgz",
@@ -16357,18 +16314,17 @@
}
},
"node_modules/react-native-paper": {
"version": "5.1.2",
"resolved": "https://registry.npmjs.org/react-native-paper/-/react-native-paper-5.1.2.tgz",
"integrity": "sha512-muf70CPtji6gTukV+9ecvzOYFOflK2hi4t4GLt9y4Ynhf/YQCvXsefPTp45n7RS6bz9+ueG4jtuGg64oOY8dxA==",
"version": "4.11.1",
"resolved": "https://registry.npmjs.org/react-native-paper/-/react-native-paper-4.11.1.tgz",
"integrity": "sha512-mAQ74KUrOIcMEg1crrIsA7eXDaPk/fjvKFDLcN7gBBeV/zhhQiqc+/y6t+8STKsZutRA2U5/eB+0MBisybokmQ==",
"dependencies": {
"@callstack/react-theme-provider": "^3.0.8",
"@callstack/react-theme-provider": "^3.0.7",
"color": "^3.1.2",
"use-event-callback": "^0.1.0"
"react-native-iphone-x-helper": "^1.3.1"
},
"peerDependencies": {
"react": "*",
"react-native": "*",
"react-native-safe-area-context": "*",
"react-native-vector-icons": "*"
}
},
@@ -16381,9 +16337,9 @@
}
},
"node_modules/react-native-safe-area-context": {
"version": "4.4.1",
"resolved": "https://registry.npmjs.org/react-native-safe-area-context/-/react-native-safe-area-context-4.4.1.tgz",
"integrity": "sha512-N9XTjiuD73ZpVlejHrUWIFZc+6Z14co1K/p1IFMkImU7+avD69F3y+lhkqA2hN/+vljdZrBSiOwXPkuo43nFQA==",
"version": "3.3.2",
"resolved": "https://registry.npmjs.org/react-native-safe-area-context/-/react-native-safe-area-context-3.3.2.tgz",
"integrity": "sha512-yOwiiPJ1rk+/nfK13eafbpW6sKW0jOnsRem2C1LPJjM3tfTof6hlvV5eWHATye3XOpu2cJ7N+HdkUvUDGwFD2Q==",
"peerDependencies": {
"react": "*",
"react-native": "*"
@@ -16545,9 +16501,9 @@
}
},
"node_modules/react-native-webrtc": {
"version": "106.0.3",
"resolved": "https://registry.npmjs.org/react-native-webrtc/-/react-native-webrtc-106.0.3.tgz",
"integrity": "sha512-RB9JafC8HzK1I/yKALUU0QoKfwmIWy5eimJncWP4oSfOSogoFTPQ11B0ZaIVXrAHCVXi26sDpoV4BguAjLvGVA==",
"version": "106.0.0",
"resolved": "https://registry.npmjs.org/react-native-webrtc/-/react-native-webrtc-106.0.0.tgz",
"integrity": "sha512-nFl8WSNGMNxuIiaNAiJvILRcEC65yRxPOWTexLrM+vo44syt/4chEvzN9eOqXiPsOmsECQmwZupCUGR5XABUNg==",
"hasInstallScript": true,
"dependencies": {
"adm-zip": "0.5.9",
@@ -18169,7 +18125,7 @@
"node_modules/strict-uri-encode": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/strict-uri-encode/-/strict-uri-encode-2.0.0.tgz",
"integrity": "sha512-QwiXZgpRcKkhTj2Scnn++4PKtWsH0kpzZ62L2R6c/LUVYv7hVnZqcg2+sMuT6R7Jusu1vviK/MFsu6kNJfWlEQ==",
"integrity": "sha1-ucczDHBChi9rFC3CdLvMWGbONUY=",
"engines": {
"node": ">=4"
}
@@ -18221,9 +18177,9 @@
}
},
"node_modules/string-replace-loader/node_modules/loader-utils": {
"version": "2.0.4",
"resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.4.tgz",
"integrity": "sha512-xXqpXoINfFhgua9xiqD8fPFHgkoq1mmmpE92WlDbm9rNRd/EbRb+Gqf908T2DMfuHjjJlksiK2RbHVOdD/MqSw==",
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.3.tgz",
"integrity": "sha512-THWqIsn8QRnvLl0shHYVBN9syumU8pYWEHPTmkiVGd+7K5eFNVSY6AJhRvgGF70gg1Dz+l/k8WicvFCxdEs60A==",
"dev": true,
"dependencies": {
"big.js": "^5.2.2",
@@ -19032,9 +18988,9 @@
}
},
"node_modules/tsconfig-paths/node_modules/json5": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/json5/-/json5-1.0.2.tgz",
"integrity": "sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==",
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/json5/-/json5-1.0.1.tgz",
"integrity": "sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow==",
"dev": true,
"dependencies": {
"minimist": "^1.2.0"
@@ -19410,14 +19366,6 @@
"react": "^16.8.0 || ^17.0.0"
}
},
"node_modules/use-event-callback": {
"version": "0.1.0",
"resolved": "https://registry.npmjs.org/use-event-callback/-/use-event-callback-0.1.0.tgz",
"integrity": "sha512-5fTzY5UEXHMK5UR0NRkUz6TPfWmmX9fO8Tx3SnHrfMPdrQ7Rna0gDBy0r56SP68TwsP9DgwSBzeysCu3A/Z2NA==",
"peerDependencies": {
"react": ">=16.8"
}
},
"node_modules/use-isomorphic-layout-effect": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/use-isomorphic-layout-effect/-/use-isomorphic-layout-effect-1.1.1.tgz",
@@ -19447,11 +19395,6 @@
}
}
},
"node_modules/use-latest-callback": {
"version": "0.1.5",
"resolved": "https://registry.npmjs.org/use-latest-callback/-/use-latest-callback-0.1.5.tgz",
"integrity": "sha512-HtHatS2U4/h32NlkhupDsPlrbiD27gSH5swBdtXbCAlc6pfOFzaj0FehW/FO12rx8j2Vy4/lJScCiJyM01E+bQ=="
},
"node_modules/use-memo-one": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/use-memo-one/-/use-memo-one-1.1.2.tgz",
@@ -22549,9 +22492,9 @@
}
},
"@callstack/react-theme-provider": {
"version": "3.0.8",
"resolved": "https://registry.npmjs.org/@callstack/react-theme-provider/-/react-theme-provider-3.0.8.tgz",
"integrity": "sha512-5U231sYY2sqQOaELX0WBCn+iluV8bFaXIS7em03k4W5Xz0AhGvKlnpLIhDGFP8im/SvNW7/2XoR0BsClhn9t6Q==",
"version": "3.0.7",
"resolved": "https://registry.npmjs.org/@callstack/react-theme-provider/-/react-theme-provider-3.0.7.tgz",
"integrity": "sha512-Ab6rbD2w4u9W3yf7LQQ8evx9m8fZNsoWxt+MFm3AyZnyKQNCJf4K7ip9tHHZgSs+HTdoj38lEqPehvFOVQKvAg==",
"requires": {
"deepmerge": "^3.2.0",
"hoist-non-react-statics": "^3.3.0"
@@ -23263,7 +23206,7 @@
"@jitsi/sdp-interop": {
"version": "git+https://git@github.com/jitsi/sdp-interop.git#3d49eb4aa26863a3f8d32d7581cdb4321244266b",
"integrity": "sha512-80u69QNTBArnCd1CGbTTrl/8AsZOOMF82dQhrgXBQAnrimdpomX1fMZ82ZkxyWyYvRMPG167u43Tp8y1g2DLNA==",
"from": "@jitsi/sdp-interop@git+https://github.com/jitsi/sdp-interop#3d49eb4aa26863a3f8d32d7581cdb4321244266b",
"from": "@jitsi/sdp-interop@https://git@github.com/jitsi/sdp-interop#3d49eb4aa26863a3f8d32d7581cdb4321244266b",
"requires": {
"lodash.clonedeep": "4.5.0",
"sdp-transform": "2.14.1"
@@ -24451,50 +24394,25 @@
"integrity": "sha512-K0aGNn1TjalKj+65D7ycc1//H9roAQ51GJVk5ZJQFb2teECGmzd86bYDC0aYdbRf7gtovescq4Zt6FR0tgXiHQ=="
},
"@react-navigation/bottom-tabs": {
"version": "6.5.3",
"resolved": "https://registry.npmjs.org/@react-navigation/bottom-tabs/-/bottom-tabs-6.5.3.tgz",
"integrity": "sha512-ZA2Ko9fNwNaaSNn7738KpEk8Doi+yjRfTg8Wb/WvduIaK/28qNLAYWBCUEVjBC55y/9zJOzwc4R8Av2J2MG/4g==",
"version": "6.0.9",
"resolved": "https://registry.npmjs.org/@react-navigation/bottom-tabs/-/bottom-tabs-6.0.9.tgz",
"integrity": "sha512-uRoq6Zd7lPNnLqNQkKC28eR62tpqcDeuakZU1sO8N46FtvrcTuNLoIlssrGty3GF7ALBIxCypn4A93t3nbmMrQ==",
"requires": {
"@react-navigation/elements": "^1.3.13",
"color": "^4.2.3",
"@react-navigation/elements": "^1.2.1",
"color": "^3.1.3",
"warn-once": "^0.1.0"
},
"dependencies": {
"color": {
"version": "4.2.3",
"resolved": "https://registry.npmjs.org/color/-/color-4.2.3.tgz",
"integrity": "sha512-1rXeuUUiGGrykh+CeBdu5Ie7OJwinCgQY0bc7GCRxy5xVHy+moaqkpL/jqQq0MtQOeYcrqEz4abc5f0KtU7W4A==",
"requires": {
"color-convert": "^2.0.1",
"color-string": "^1.9.0"
}
},
"color-convert": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
"integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
"requires": {
"color-name": "~1.1.4"
}
},
"color-name": {
"version": "1.1.4",
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA=="
}
}
},
"@react-navigation/core": {
"version": "6.4.6",
"resolved": "https://registry.npmjs.org/@react-navigation/core/-/core-6.4.6.tgz",
"integrity": "sha512-6zaAgUT5k4vhJlddUk2l52RZyMkMelHdrRv1cL57ALi2RZzERdgmbiMKhJerxFLn9S8E3PUe8vwxHzjHOZKG4w==",
"version": "6.1.1",
"resolved": "https://registry.npmjs.org/@react-navigation/core/-/core-6.1.1.tgz",
"integrity": "sha512-njysuiqztgvR1Z9Noxk2OGJfYtFGFDRyji5Vmm1jHzlql0m+q0wh1dUiyaIEtTyrhFXr/YNgdrKuiPaU9Jp8OA==",
"requires": {
"@react-navigation/routers": "^6.1.6",
"@react-navigation/routers": "^6.1.0",
"escape-string-regexp": "^4.0.0",
"nanoid": "^3.1.23",
"query-string": "^7.1.3",
"react-is": "^16.13.0",
"use-latest-callback": "^0.1.5"
"query-string": "^7.0.0",
"react-is": "^16.13.0"
},
"dependencies": {
"react-is": {
@@ -24505,72 +24423,52 @@
}
},
"@react-navigation/elements": {
"version": "1.3.13",
"resolved": "https://registry.npmjs.org/@react-navigation/elements/-/elements-1.3.13.tgz",
"integrity": "sha512-LqqK5s2ZfYHn2cQ376jC5V9dQztLH5ixkkJj9WR7JY2g4SghDd39WJhL3Jillw1Mu3F3b9sZwvAK+QkXhnDeAA=="
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/@react-navigation/elements/-/elements-1.2.1.tgz",
"integrity": "sha512-EnmAbKMsptrliRKf95rdgS6BhMjML+mIns06+G1Vdih6BrEo7/0iytThUv3WBf99AI76dyEq/cqLUwHPiFzXWg=="
},
"@react-navigation/material-top-tabs": {
"version": "6.5.2",
"resolved": "https://registry.npmjs.org/@react-navigation/material-top-tabs/-/material-top-tabs-6.5.2.tgz",
"integrity": "sha512-i/R3bEXVE5pygWP0dOMdFNOVzrQyHXL0lbqLfQx5HZXwbvCrpUBFqOED3bWLBrBOUhHQSXfYgTuteAfIF5hzzg==",
"version": "6.0.6",
"resolved": "https://registry.npmjs.org/@react-navigation/material-top-tabs/-/material-top-tabs-6.0.6.tgz",
"integrity": "sha512-kbm/0jndRVeGdAgOd4NcDSdSQiYeA7fkctCKbPxe3mT36j9qOqpfHfmd2dbv/VbNCngdTtZ3/+QMxTIViZGy7g==",
"requires": {
"color": "^4.2.3",
"color": "^3.1.3",
"warn-once": "^0.1.0"
},
"dependencies": {
"color": {
"version": "4.2.3",
"resolved": "https://registry.npmjs.org/color/-/color-4.2.3.tgz",
"integrity": "sha512-1rXeuUUiGGrykh+CeBdu5Ie7OJwinCgQY0bc7GCRxy5xVHy+moaqkpL/jqQq0MtQOeYcrqEz4abc5f0KtU7W4A==",
"requires": {
"color-convert": "^2.0.1",
"color-string": "^1.9.0"
}
},
"color-convert": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
"integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
"requires": {
"color-name": "~1.1.4"
}
},
"color-name": {
"version": "1.1.4",
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA=="
}
}
},
"@react-navigation/native": {
"version": "6.1.2",
"resolved": "https://registry.npmjs.org/@react-navigation/native/-/native-6.1.2.tgz",
"integrity": "sha512-qLUe0asHofr5EhxKjvUBJ9DrPPmR4535IEwmW3oU4DRb3cLbNysjajJKHL8kcYtqPvn9Bx9QZG2x0PMb2vN23A==",
"version": "6.0.6",
"resolved": "https://registry.npmjs.org/@react-navigation/native/-/native-6.0.6.tgz",
"integrity": "sha512-XzL7YPsaRRQgdCQSXbA8PJWLN2I4lhUUvSFoKQPNO4DS6y8eqZI1V8COPYlJg8+tsetGV5J8jt+jVjWL7h6ZrQ==",
"requires": {
"@react-navigation/core": "^6.4.6",
"@react-navigation/core": "^6.1.0",
"escape-string-regexp": "^4.0.0",
"fast-deep-equal": "^3.1.3",
"nanoid": "^3.1.23"
}
},
"@react-navigation/routers": {
"version": "6.1.6",
"resolved": "https://registry.npmjs.org/@react-navigation/routers/-/routers-6.1.6.tgz",
"integrity": "sha512-Z5DeCW3pUvMafbU9Cjy1qJYC2Bvl8iy3+PfsB0DsAwQ6zZ3WAXW5FTMX4Gb9H+Jg6qHWGbMFFwlYpS3UJ3tlVQ==",
"version": "6.1.0",
"resolved": "https://registry.npmjs.org/@react-navigation/routers/-/routers-6.1.0.tgz",
"integrity": "sha512-8xJL+djIzpFdRW/sGlKojQ06fWgFk1c5jER9501HYJ12LF5DIJFr/tqBI2TJ6bk+y+QFu0nbNyeRC80OjRlmkA==",
"requires": {
"nanoid": "^3.1.23"
}
},
"@react-navigation/stack": {
"version": "6.3.11",
"resolved": "https://registry.npmjs.org/@react-navigation/stack/-/stack-6.3.11.tgz",
"integrity": "sha512-GWOAyJfPEsjVwDWec1ERwWL5LvManJucCRUZetJqCBs4/mV7HXEt2x6l3SMitHxH1+K+9XuYXI+wBTbK1WDYOA==",
"version": "6.2.2",
"resolved": "https://registry.npmjs.org/@react-navigation/stack/-/stack-6.2.2.tgz",
"integrity": "sha512-P9ZfmluOXNmbs7YdG1UWS1fAh87Yse9aX8TgqOz4FlHEm5q7g5eaM35QgWByt+wif3UiqE40D8wXpqRQvMgPWg==",
"requires": {
"@react-navigation/elements": "^1.3.13",
"@react-navigation/elements": "^1.3.4",
"color": "^4.2.3",
"warn-once": "^0.1.0"
},
"dependencies": {
"@react-navigation/elements": {
"version": "1.3.4",
"resolved": "https://registry.npmjs.org/@react-navigation/elements/-/elements-1.3.4.tgz",
"integrity": "sha512-O0jICpjn3jskVo4yiWzZozmj7DZy1ZBbn3O7dbenuUjZSj/cscjwaapmZZFGcI/IMmjmx8UTKsybhCFEIbGf3g=="
},
"color": {
"version": "4.2.3",
"resolved": "https://registry.npmjs.org/color/-/color-4.2.3.tgz",
@@ -27384,9 +27282,9 @@
"integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA="
},
"decode-uri-component": {
"version": "0.2.2",
"resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.2.tgz",
"integrity": "sha512-FqUYQ+8o158GyGTrMFJms9qh3CqTKvAqgqsTnkLI8sKu0028orqBhxNMFkFen0zGyg6epACD32pjVk58ngIErQ=="
"version": "0.2.0",
"resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.0.tgz",
"integrity": "sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU="
},
"decompress-response": {
"version": "4.2.1",
@@ -28817,7 +28715,7 @@
"filter-obj": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/filter-obj/-/filter-obj-1.1.0.tgz",
"integrity": "sha512-8rXg1ZnX7xzy2NGDVkBVaAy+lSlPNwad13BtgSlLuxfIslyt5Vg64U7tFcCt4WS1R0hvtnQybT/IyCkGZ3DpXQ=="
"integrity": "sha1-mzERErxsYSehbgFsbF1/GeCAXFs="
},
"finalhandler": {
"version": "1.1.2",
@@ -30440,9 +30338,9 @@
"dev": true
},
"json5": {
"version": "2.2.3",
"resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz",
"integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg=="
"version": "2.2.1",
"resolved": "https://registry.npmjs.org/json5/-/json5-2.2.1.tgz",
"integrity": "sha512-1hqLFMSrGHRHxav9q9gNjJ5EXznIxGVO09xQRrwplcS8qs28pZ8s8hupZAmqDwZUmVZ2Qb2jnyPOWcDH8m8dlA=="
},
"jsonfile": {
"version": "4.0.0",
@@ -30598,12 +30496,12 @@
}
},
"lib-jitsi-meet": {
"version": "https://github.com/jitsi/lib-jitsi-meet/releases/download/v1569.0.0+5f8d02c9/lib-jitsi-meet.tgz",
"integrity": "sha512-XD0YS84XjK+KnjW3qT4oZ4/+n2mSTHpJNwYqFgvvrFd1MHLL96k9UOIcTkU/yOuxkf69ZKfx9QtCnfnYrpkTIQ==",
"version": "https://github.com/jitsi/lib-jitsi-meet/releases/download/v1557.0.0+8df33524/lib-jitsi-meet.tgz",
"integrity": "sha512-LH24V3aCAyNxrXkYsr4Syz9G+hDyfGo7JUu3suEbh1bS5Y4w8mwzTBHyGazLnD7/NDG5F783DY19/yCzR7stSQ==",
"requires": {
"@jitsi/js-utils": "2.0.0",
"@jitsi/logger": "2.0.0",
"@jitsi/sdp-interop": "git+https://github.com/jitsi/sdp-interop#3d49eb4aa26863a3f8d32d7581cdb4321244266b",
"@jitsi/sdp-interop": "https://git@github.com/jitsi/sdp-interop#3d49eb4aa26863a3f8d32d7581cdb4321244266b",
"@jitsi/sdp-simulcast": "0.4.0",
"async": "3.2.3",
"base64-js": "1.3.1",
@@ -30616,7 +30514,7 @@
"sdp-transform": "2.3.0",
"strophe.js": "1.3.4",
"strophejs-plugin-disco": "0.0.2",
"strophejs-plugin-stream-management": "git+https://github.com/jitsi/strophejs-plugin-stream-management#001cf02bef2357234e1ac5d163611b4d60bf2b6a",
"strophejs-plugin-stream-management": "https://git@github.com/jitsi/strophejs-plugin-stream-management#001cf02bef2357234e1ac5d163611b4d60bf2b6a",
"uuid": "8.1.0",
"webrtc-adapter": "8.1.1"
},
@@ -30667,9 +30565,9 @@
"dev": true
},
"loader-utils": {
"version": "1.4.2",
"resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.4.2.tgz",
"integrity": "sha512-I5d00Pd/jwMD2QCduo657+YM/6L3KZu++pmX9VFncxaxvHcru9jx1lBaFft+r4Mt2jK0Yhp41XlRAihzPxHNCg==",
"version": "1.4.1",
"resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.4.1.tgz",
"integrity": "sha512-1Qo97Y2oKaU+Ro2xnDMR26g1BwMT29jNbem1EvcujW2jqt+j5COXyscjM7bLQkM9HaxI7pkWeW7gnI072yMI9Q==",
"dev": true,
"requires": {
"big.js": "^5.2.2",
@@ -30678,9 +30576,9 @@
},
"dependencies": {
"json5": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/json5/-/json5-1.0.2.tgz",
"integrity": "sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==",
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/json5/-/json5-1.0.1.tgz",
"integrity": "sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow==",
"dev": true,
"requires": {
"minimist": "^1.2.0"
@@ -31426,9 +31324,9 @@
}
},
"nanoid": {
"version": "3.3.4",
"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.4.tgz",
"integrity": "sha512-MqBkQh/OHTS2egovRtLk45wEyNXwF+cokD+1YPf9u5VfJiRdAiRwB2froX5Co9Rh20xs4siNPm8naNotSD6RBw=="
"version": "3.3.1",
"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.1.tgz",
"integrity": "sha512-n6Vs/3KGyxPQd6uO0eH4Bv0ojGSUvuLlIHtC3Y0kEO23YRge8H9x1GCzLn28YX0H66pMkxuaeESFq4tKISKwdw=="
},
"nanomatch": {
"version": "1.2.13",
@@ -31576,9 +31474,9 @@
},
"dependencies": {
"loader-utils": {
"version": "2.0.4",
"resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.4.tgz",
"integrity": "sha512-xXqpXoINfFhgua9xiqD8fPFHgkoq1mmmpE92WlDbm9rNRd/EbRb+Gqf908T2DMfuHjjJlksiK2RbHVOdD/MqSw==",
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.3.tgz",
"integrity": "sha512-THWqIsn8QRnvLl0shHYVBN9syumU8pYWEHPTmkiVGd+7K5eFNVSY6AJhRvgGF70gg1Dz+l/k8WicvFCxdEs60A==",
"requires": {
"big.js": "^5.2.2",
"emojis-list": "^3.0.0",
@@ -32456,11 +32354,11 @@
"integrity": "sha512-IhMFgUmuNpyRfxA90umL7ByLlgRXu6tIfKPpF5TmcfRLlLCckfP/g3IQmju6jjpu+Hh8rA+2p6A27ZSPOOHdKw=="
},
"query-string": {
"version": "7.1.3",
"resolved": "https://registry.npmjs.org/query-string/-/query-string-7.1.3.tgz",
"integrity": "sha512-hh2WYhq4fi8+b+/2Kg9CEge4fDPvHS534aOOvOZeQ3+Vf2mCFsaFBYj0i+iXcAq6I9Vzp5fjMFBlONvayDC1qg==",
"version": "7.1.1",
"resolved": "https://registry.npmjs.org/query-string/-/query-string-7.1.1.tgz",
"integrity": "sha512-MplouLRDHBZSG9z7fpuAAcI7aAYjDLhtsiVZsevsfaHWDS2IDdORKbSd1kWUA+V4zyva/HZoSfpwnYMMQDhb0w==",
"requires": {
"decode-uri-component": "^0.2.2",
"decode-uri-component": "^0.2.0",
"filter-obj": "^1.1.0",
"split-on-first": "^1.0.0",
"strict-uri-encode": "^2.0.0"
@@ -32711,9 +32609,9 @@
"integrity": "sha512-MKbuBbovO8eGiAM9i6o0nrdBXivhRpzPQ+aVBXGJEPMH7RrCSNUKaCoEpkjfGHlTxjZimi6WjDCjjzCRSHlV1A=="
},
"react-native-gesture-handler": {
"version": "2.8.0",
"resolved": "https://registry.npmjs.org/react-native-gesture-handler/-/react-native-gesture-handler-2.8.0.tgz",
"integrity": "sha512-poOSfz/w0IyD6Qwq7aaIRRfEaVTl1ecQFoyiIbpOpfNTjm2B1niY2FLrdVQIOtIOe+K9nH55Qal04nr4jGkHdQ==",
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/react-native-gesture-handler/-/react-native-gesture-handler-2.1.0.tgz",
"integrity": "sha512-vF4yEUrV5GMBioTkvf5Le1l3N/52dSLBnNMFC+kZ4hssnRoXB0hEQ0ReUkZckRB5L3nbHBhAyjySEtFPx4nyEA==",
"requires": {
"@egjs/hammerjs": "^2.0.17",
"hoist-non-react-statics": "^3.3.0",
@@ -32740,6 +32638,11 @@
"resolved": "https://registry.npmjs.org/react-native-immersive/-/react-native-immersive-2.0.0.tgz",
"integrity": "sha512-9TL05nTHN/x9sN1wbUlBoGyzH4NCuZ/7WEEUp5CvOoKuUABvdYosov0O0SAMbm/5J913RRoy98VB6tGNi9lRSw=="
},
"react-native-iphone-x-helper": {
"version": "1.3.1",
"resolved": "https://registry.npmjs.org/react-native-iphone-x-helper/-/react-native-iphone-x-helper-1.3.1.tgz",
"integrity": "sha512-HOf0jzRnq2/aFUcdCJ9w9JGzN3gdEg0zFE4FyYlp4jtidqU03D5X7ZegGKfT1EWteR0gPBGp9ye5T5FvSWi9Yg=="
},
"react-native-keep-awake": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/react-native-keep-awake/-/react-native-keep-awake-4.0.0.tgz",
@@ -32756,13 +32659,13 @@
"integrity": "sha512-D6tzxpwMGdl6CXgtskGWhKRc5cJakCazESRGt7PkqnpyiH3N35ft1KmR82pCSQetAFlytFiToeu3a/dG5CELvA=="
},
"react-native-paper": {
"version": "5.1.2",
"resolved": "https://registry.npmjs.org/react-native-paper/-/react-native-paper-5.1.2.tgz",
"integrity": "sha512-muf70CPtji6gTukV+9ecvzOYFOflK2hi4t4GLt9y4Ynhf/YQCvXsefPTp45n7RS6bz9+ueG4jtuGg64oOY8dxA==",
"version": "4.11.1",
"resolved": "https://registry.npmjs.org/react-native-paper/-/react-native-paper-4.11.1.tgz",
"integrity": "sha512-mAQ74KUrOIcMEg1crrIsA7eXDaPk/fjvKFDLcN7gBBeV/zhhQiqc+/y6t+8STKsZutRA2U5/eB+0MBisybokmQ==",
"requires": {
"@callstack/react-theme-provider": "^3.0.8",
"@callstack/react-theme-provider": "^3.0.7",
"color": "^3.1.2",
"use-event-callback": "^0.1.0"
"react-native-iphone-x-helper": "^1.3.1"
}
},
"react-native-performance": {
@@ -32771,9 +32674,9 @@
"integrity": "sha512-Q3dFPN7whBCY7X8nvQe7TBw4F5g1PyB78KwyKDXpJENcDrBodlFtj9/c5T2ZkRwAPb+bxr39b+lq9FyT6WQWtg=="
},
"react-native-safe-area-context": {
"version": "4.4.1",
"resolved": "https://registry.npmjs.org/react-native-safe-area-context/-/react-native-safe-area-context-4.4.1.tgz",
"integrity": "sha512-N9XTjiuD73ZpVlejHrUWIFZc+6Z14co1K/p1IFMkImU7+avD69F3y+lhkqA2hN/+vljdZrBSiOwXPkuo43nFQA=="
"version": "3.3.2",
"resolved": "https://registry.npmjs.org/react-native-safe-area-context/-/react-native-safe-area-context-3.3.2.tgz",
"integrity": "sha512-yOwiiPJ1rk+/nfK13eafbpW6sKW0jOnsRem2C1LPJjM3tfTof6hlvV5eWHATye3XOpu2cJ7N+HdkUvUDGwFD2Q=="
},
"react-native-screens": {
"version": "3.13.1",
@@ -32887,9 +32790,9 @@
}
},
"react-native-webrtc": {
"version": "106.0.3",
"resolved": "https://registry.npmjs.org/react-native-webrtc/-/react-native-webrtc-106.0.3.tgz",
"integrity": "sha512-RB9JafC8HzK1I/yKALUU0QoKfwmIWy5eimJncWP4oSfOSogoFTPQ11B0ZaIVXrAHCVXi26sDpoV4BguAjLvGVA==",
"version": "106.0.0",
"resolved": "https://registry.npmjs.org/react-native-webrtc/-/react-native-webrtc-106.0.0.tgz",
"integrity": "sha512-nFl8WSNGMNxuIiaNAiJvILRcEC65yRxPOWTexLrM+vo44syt/4chEvzN9eOqXiPsOmsECQmwZupCUGR5XABUNg==",
"requires": {
"adm-zip": "0.5.9",
"base64-js": "1.5.1",
@@ -34149,7 +34052,7 @@
"strict-uri-encode": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/strict-uri-encode/-/strict-uri-encode-2.0.0.tgz",
"integrity": "sha512-QwiXZgpRcKkhTj2Scnn++4PKtWsH0kpzZ62L2R6c/LUVYv7hVnZqcg2+sMuT6R7Jusu1vviK/MFsu6kNJfWlEQ=="
"integrity": "sha1-ucczDHBChi9rFC3CdLvMWGbONUY="
},
"string_decoder": {
"version": "1.3.0",
@@ -34183,9 +34086,9 @@
},
"dependencies": {
"loader-utils": {
"version": "2.0.4",
"resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.4.tgz",
"integrity": "sha512-xXqpXoINfFhgua9xiqD8fPFHgkoq1mmmpE92WlDbm9rNRd/EbRb+Gqf908T2DMfuHjjJlksiK2RbHVOdD/MqSw==",
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.3.tgz",
"integrity": "sha512-THWqIsn8QRnvLl0shHYVBN9syumU8pYWEHPTmkiVGd+7K5eFNVSY6AJhRvgGF70gg1Dz+l/k8WicvFCxdEs60A==",
"dev": true,
"requires": {
"big.js": "^5.2.2",
@@ -34316,7 +34219,7 @@
"strophejs-plugin-stream-management": {
"version": "git+https://git@github.com/jitsi/strophejs-plugin-stream-management.git#001cf02bef2357234e1ac5d163611b4d60bf2b6a",
"integrity": "sha512-ijQSXeEEmGl4dfLx8RcQDCvzg1UPtEArowaCHZr8ITdBOH/X6JxxGzy/DVeMLVSvSy73tH7pGK6iPjBqQajwdQ==",
"from": "strophejs-plugin-stream-management@git+https://github.com/jitsi/strophejs-plugin-stream-management#001cf02bef2357234e1ac5d163611b4d60bf2b6a"
"from": "strophejs-plugin-stream-management@https://git@github.com/jitsi/strophejs-plugin-stream-management#001cf02bef2357234e1ac5d163611b4d60bf2b6a"
},
"style-loader": {
"version": "3.3.1",
@@ -34789,9 +34692,9 @@
},
"dependencies": {
"json5": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/json5/-/json5-1.0.2.tgz",
"integrity": "sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==",
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/json5/-/json5-1.0.1.tgz",
"integrity": "sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow==",
"dev": true,
"requires": {
"minimist": "^1.2.0"
@@ -35046,11 +34949,6 @@
"resolved": "https://registry.npmjs.org/use-composed-ref/-/use-composed-ref-1.2.1.tgz",
"integrity": "sha512-6+X1FLlIcjvFMAeAD/hcxDT8tmyrWnbSPMU0EnxQuDLIxokuFzWliXBiYZuGIx+mrAMLBw0WFfCkaPw8ebzAhw=="
},
"use-event-callback": {
"version": "0.1.0",
"resolved": "https://registry.npmjs.org/use-event-callback/-/use-event-callback-0.1.0.tgz",
"integrity": "sha512-5fTzY5UEXHMK5UR0NRkUz6TPfWmmX9fO8Tx3SnHrfMPdrQ7Rna0gDBy0r56SP68TwsP9DgwSBzeysCu3A/Z2NA=="
},
"use-isomorphic-layout-effect": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/use-isomorphic-layout-effect/-/use-isomorphic-layout-effect-1.1.1.tgz",
@@ -35064,11 +34962,6 @@
"use-isomorphic-layout-effect": "^1.0.0"
}
},
"use-latest-callback": {
"version": "0.1.5",
"resolved": "https://registry.npmjs.org/use-latest-callback/-/use-latest-callback-0.1.5.tgz",
"integrity": "sha512-HtHatS2U4/h32NlkhupDsPlrbiD27gSH5swBdtXbCAlc6pfOFzaj0FehW/FO12rx8j2Vy4/lJScCiJyM01E+bQ=="
},
"use-memo-one": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/use-memo-one/-/use-memo-one-1.1.2.tgz",

View File

@@ -47,11 +47,11 @@
"@react-native-community/slider": "4.1.12",
"@react-native-google-signin/google-signin": "7.0.4",
"@react-native-masked-view/masked-view": "0.2.6",
"@react-navigation/bottom-tabs": "6.5.3",
"@react-navigation/elements": "1.3.13",
"@react-navigation/material-top-tabs": "6.5.2",
"@react-navigation/native": "6.1.2",
"@react-navigation/stack": "6.3.11",
"@react-navigation/bottom-tabs": "6.0.9",
"@react-navigation/elements": "1.2.1",
"@react-navigation/material-top-tabs": "6.0.6",
"@react-navigation/native": "6.0.6",
"@react-navigation/stack": "6.2.2",
"@svgr/webpack": "6.3.1",
"@tensorflow/tfjs-backend-wasm": "3.13.0",
"@tensorflow/tfjs-core": "3.13.0",
@@ -79,7 +79,7 @@
"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/v1569.0.0+5f8d02c9/lib-jitsi-meet.tgz",
"lib-jitsi-meet": "https://github.com/jitsi/lib-jitsi-meet/releases/download/v1557.0.0+8df33524/lib-jitsi-meet.tgz",
"lodash": "4.17.21",
"moment": "2.29.4",
"moment-duration-format": "2.2.2",
@@ -101,15 +101,15 @@
"react-native-default-preference": "1.4.4",
"react-native-device-info": "8.4.8",
"react-native-dialog": "https://github.com/jitsi/react-native-dialog/releases/download/v9.2.2-jitsi.1/react-native-dialog-9.2.2.tgz",
"react-native-gesture-handler": "2.8.0",
"react-native-gesture-handler": "2.1.0",
"react-native-get-random-values": "1.7.2",
"react-native-immersive": "2.0.0",
"react-native-keep-awake": "4.0.0",
"react-native-orientation-locker": "1.5.0",
"react-native-pager-view": "5.4.9",
"react-native-paper": "5.1.2",
"react-native-paper": "4.11.1",
"react-native-performance": "2.1.0",
"react-native-safe-area-context": "4.4.1",
"react-native-safe-area-context": "3.3.2",
"react-native-screens": "3.13.1",
"react-native-sound": "0.11.1",
"react-native-splash-screen": "3.3.0",
@@ -119,7 +119,7 @@
"react-native-url-polyfill": "1.3.0",
"react-native-video": "https://git@github.com/react-native-video/react-native-video#7c48ae7c8544b2b537fb60194e9620b9fcceae52",
"react-native-watch-connectivity": "1.0.11",
"react-native-webrtc": "106.0.3",
"react-native-webrtc": "106.0.0",
"react-native-webview": "11.15.1",
"react-native-youtube-iframe": "2.2.1",
"react-redux": "7.1.0",
@@ -199,8 +199,7 @@
"tsc:web": "tsc --noEmit --project tsconfig.web.json",
"tsc:native": "tsc --noEmit --project tsconfig.native.json",
"tsc:ci": "npm run tsc:web && npm run tsc:native",
"lint:ci": "eslint --ext .js,.ts,.tsx --max-warnings 0 . && npm run tsc:ci && npm run lint:lang",
"lint:lang": "for file in lang/*.json; do npx --yes jsonlint -q $file || exit 1; done",
"lint:ci": "eslint --ext .js,.ts,.tsx --max-warnings 0 . && npm run tsc:ci",
"lang-sort": "./resources/lang-sort.sh",
"lint-fix": "eslint --ext .js,.ts,.tsx --max-warnings 0 --fix .",
"postinstall": "patch-package --error-on-fail && jetify",

View File

@@ -0,0 +1,13 @@
diff --git a/node_modules/react-native-gesture-handler/android/build.gradle b/node_modules/react-native-gesture-handler/android/build.gradle
index 8afc3d5..4b1f721 100644
--- a/node_modules/react-native-gesture-handler/android/build.gradle
+++ b/node_modules/react-native-gesture-handler/android/build.gradle
@@ -26,7 +26,7 @@ def shouldUseCommonInterfaceFromReanimated() {
def json = new JsonSlurper().parseText(inputFile.text)
def reanimatedVersion = json.version as String
def (major, minor, patch) = reanimatedVersion.tokenize('.')
- return Integer.parseInt(minor) >= 3
+ return Integer.parseInt(major) >= 2 && Integer.parseInt(minor) >= 3
} else {
return false
}

View File

@@ -6,7 +6,6 @@ import '../mobile/call-integration/reducer';
import '../mobile/external-api/reducer';
import '../mobile/full-screen/reducer';
import '../mobile/watchos/reducer';
import '../share-room/reducer';
import './reducer.native';

View File

@@ -65,7 +65,6 @@ import { IRecordingState } from '../recording/reducer';
import { IRemoteControlState } from '../remote-control/reducer';
import { IScreenShareState } from '../screen-share/reducer';
import { IScreenshotCaptureState } from '../screenshot-capture/reducer';
import { IShareRoomState } from '../share-room/reducer';
import { ISharedVideoState } from '../shared-video/reducer';
import { ISpeakerStatsState } from '../speaker-stats/reducer';
import { ISubtitlesState } from '../subtitles/reducer';
@@ -149,7 +148,6 @@ export interface IReduxState {
'features/screen-share': IScreenShareState;
'features/screenshot-capture': IScreenshotCaptureState;
'features/settings': ISettingsState;
'features/share-room': IShareRoomState;
'features/shared-video': ISharedVideoState;
'features/speaker-stats': ISpeakerStatsState;
'features/subtitles': ISubtitlesState;

View File

@@ -15,11 +15,7 @@ import {
import { getLocalParticipant } from '../participants/functions';
import { toState } from '../redux/functions';
import { getJitsiMeetGlobalNS } from '../util/helpers';
import {
appendURLParam,
getBackendSafePath,
safeDecodeURIComponent
} from '../util/uri';
import { getBackendSafePath, safeDecodeURIComponent } from '../util/uri';
import { setObfuscatedRoom } from './actions';
import {
@@ -257,7 +253,7 @@ export function getConferenceOptions(stateful: IStateful) {
}
/**
* Override the global config (that is, window.config) with XMPP configuration required to join as a visitor.
* Returns an object aggregating the conference options.
*
* @param {IStateful} stateful - The redux store state.
* @param {Array<string>} params - The received parameters.
@@ -278,17 +274,10 @@ export function generateVisitorConfig(stateful: IStateful, params: Array<string>
config.hosts.domain = `${vnode}.meet.jitsi`;
config.hosts.muc = config.hosts.muc.replace(oldDomain, config.hosts.domain);
config.focusUserJid = focusJid;
config.hosts.visitorFocus = focusJid;
// This flag disables sending the initial conference request
config.disableFocus = true;
if (config.bosh) {
config.bosh = appendURLParam(config.bosh, 'vnode', vnode);
}
if (config.websocket) {
config.websocket = appendURLParam(config.websocket, 'vnode', vnode);
}
config.bosh += `?vnode=${vnode}`;
config.websocket += `?vnode=${vnode}`;
}
/**

View File

@@ -88,36 +88,6 @@ export type Sounds = 'ASKED_TO_UNMUTE_SOUND' |
'RECORDING_ON_SOUND' |
'TALK_WHILE_MUTED_SOUND';
export interface IMobileDynamicLink {
apn: string;
appCode: string;
customDomain?: string;
ibi: string;
isi: string;
}
export interface IDeeplinkingPlatformConfig {
appName: string;
}
export interface IDeeplinkingMobileConfig extends IDeeplinkingPlatformConfig {
appPackage?: string;
appScheme: string;
downloadLink: string;
dynamicLink?: IMobileDynamicLink;
fDroidUrl?: string;
}
export interface IDeeplinkingConfig {
android?: IDeeplinkingMobileConfig;
desktop?: IDeeplinkingPlatformConfig;
disabled: boolean;
hideLogo: boolean;
ios?: IDeeplinkingMobileConfig;
showImage: boolean;
}
export interface IConfig {
_desktopSharingSourceDevice?: string;
analytics?: {
@@ -189,7 +159,6 @@ export interface IConfig {
alwaysVisible?: Array<string>;
autoHide?: Array<string>;
};
conferenceRequestUrl?: string;
connectionIndicators?: {
autoHide?: boolean;
autoHideTimeout?: number;
@@ -207,7 +176,6 @@ export interface IConfig {
};
};
corsAvatarURLs?: Array<string>;
deeplinking?: IDeeplinkingConfig;
defaultLanguage?: string;
defaultLocalDisplayName?: string;
defaultLogoUrl?: string;
@@ -234,7 +202,7 @@ export interface IConfig {
disableChatSmileys?: boolean;
disableDeepLinking?: boolean;
disableFilmstripAutohiding?: boolean;
disableFocus?: boolean;
disableH264?: boolean;
disableIncomingMessageSound?: boolean;
disableInitialGUM?: boolean;
disableInviteFunctions?: boolean;
@@ -415,10 +383,12 @@ export interface IConfig {
opusMaxAverageBitrate?: number;
p2p?: {
backToP2PDelay?: number;
disableH264?: boolean;
disabledCodec?: string;
enableUnifiedOnChrome?: boolean;
enabled?: boolean;
iceTransportPolicy?: string;
preferH264?: boolean;
preferredCodec?: string;
stunServers?: Array<{ urls: string; }>;
};
@@ -429,6 +399,7 @@ export interface IConfig {
};
pcStatsInterval?: number;
peopleSearchUrl?: string;
preferH264?: boolean;
preferredTranscribeLanguage?: string;
prejoinConfig?: {
enabled?: boolean;
@@ -483,10 +454,12 @@ export interface IConfig {
subject?: string;
testing?: {
callStatsThreshold?: number;
capScreenshareBitrate?: number;
disableE2EE?: boolean;
mobileXmppWsThreshold?: number;
noAutoPlayVideo?: boolean;
p2pTestMode?: boolean;
setScreenSharingResolutionConstraints?: boolean;
testMode?: boolean;
};
tileView?: {
@@ -512,6 +485,7 @@ export interface IConfig {
useAppLanguage?: boolean;
};
useHostPageLocalStorage?: boolean;
useNewBandwidthAllocationStrategy?: boolean;
useTurnUdp?: boolean;
videoQuality?: {
disabledCodec?: string;

View File

@@ -81,8 +81,6 @@ export default [
'brandingRoomAlias',
'debug',
'debugAudioLevels',
'deeplinking.disabled',
'deeplinking.showImage',
'defaultLocalDisplayName',
'defaultRemoteDisplayName',
'deploymentUrls',
@@ -101,6 +99,7 @@ export default [
'disabledSounds',
'disableFilmstripAutohiding',
'disableInitialGUM',
'disableH264',
'disableHPF',
'disableInviteFunctions',
'disableIncomingMessageSound',
@@ -198,6 +197,7 @@ export default [
'p2p',
'participantsPane',
'pcStatsInterval',
'preferH264',
'preferredCodec',
'prejoinConfig',
'prejoinPageEnabled',

View File

@@ -4,7 +4,7 @@ import { IReduxState } from '../../app/types';
import { REPLACE_PARTICIPANT } from '../flags/constants';
import { getFeatureFlag } from '../flags/functions';
import { IConfig, IDeeplinkingConfig } from './configType';
import { IConfig } from './configType';
export * from './functions.any';
@@ -15,18 +15,11 @@ export * from './functions.any';
* @returns {void}
*/
export function _cleanupConfig(config: IConfig) {
config.analytics = config.analytics ?? {};
config.analytics = {};
config.analytics.scriptURLs = [];
if (NativeModules.AppInfo.LIBRE_BUILD) {
delete config.analytics?.amplitudeAPPKey;
delete config.analytics?.googleAnalyticsTrackingId;
delete config.analytics?.rtcstatsEnabled;
delete config.analytics?.rtcstatsEndpoint;
delete config.analytics?.rtcstatsPollInterval;
delete config.analytics?.rtcstatsSendSdp;
delete config.analytics?.rtcstatsUseLegacy;
delete config.analytics?.obfuscateRoomName;
delete config.callStatsID;
delete config.callStatsSecret;
config.giphy = { enabled: false };
@@ -42,14 +35,3 @@ export function _cleanupConfig(config: IConfig) {
export function getReplaceParticipant(state: IReduxState): string {
return getFeatureFlag(state, REPLACE_PARTICIPANT, false);
}
/**
* Sets the defaults for deeplinking.
*
* @param {IDeeplinkingConfig} _deeplinking - The deeplinking config.
* @returns {void}
*/
export function _setDeeplinkingDefaults(_deeplinking: IDeeplinkingConfig) {
return;
}

View File

@@ -1,6 +1,6 @@
import { IReduxState } from '../../app/types';
import { IConfig, IDeeplinkingConfig, IDeeplinkingMobileConfig, IDeeplinkingPlatformConfig } from './configType';
import { IConfig } from './configType';
import { TOOLBAR_BUTTONS } from './constants';
export * from './functions.any';
@@ -8,11 +8,10 @@ export * from './functions.any';
/**
* Removes all analytics related options from the given configuration, in case of a libre build.
*
* @param {*} _config - The configuration which needs to be cleaned up.
* @param {*} config - The configuration which needs to be cleaned up.
* @returns {void}
*/
export function _cleanupConfig(_config: IConfig) {
return;
export function _cleanupConfig(config: IConfig) { // eslint-disable-line @typescript-eslint/no-unused-vars
}
/**
@@ -61,43 +60,3 @@ export function areAudioLevelsEnabled(state: IReduxState): boolean {
// Default to false for React Native as audio levels are of no interest to the mobile app.
return navigator.product !== 'ReactNative' && !state['features/base/config'].disableAudioLevels;
}
/**
* Sets the defaults for deeplinking.
*
* @param {IDeeplinkingConfig} deeplinking - The deeplinking config.
* @returns {void}
*/
export function _setDeeplinkingDefaults(deeplinking: IDeeplinkingConfig) {
const {
desktop = {} as IDeeplinkingPlatformConfig,
android = {} as IDeeplinkingMobileConfig,
ios = {} as IDeeplinkingMobileConfig
} = deeplinking;
desktop.appName = desktop.appName || 'Jitsi Meet';
ios.appName = ios.appName || 'Jitsi Meet';
ios.appScheme = ios.appScheme || 'org.jitsi.meet';
ios.downloadLink = ios.downloadLink
|| 'https://itunes.apple.com/us/app/jitsi-meet/id1165103905';
if (ios.dynamicLink) {
ios.dynamicLink.apn = ios.dynamicLink.apn || 'org.jitsi.meet';
ios.dynamicLink.appCode = ios.dynamicLink.appCode || 'w2atb';
ios.dynamicLink.ibi = ios.dynamicLink.ibi || 'com.atlassian.JitsiMeet.ios';
ios.dynamicLink.isi = ios.dynamicLink.isi || '1165103905';
}
android.appName = android.appName || 'Jitsi Meet';
android.appScheme = android.appScheme || 'org.jitsi.meet';
android.downloadLink = android.downloadLink
|| 'https://play.google.com/store/apps/details?id=org.jitsi.meet';
android.appPackage = android.appPackage || 'org.jitsi.meet';
android.fDroidUrl = android.fDroidUrl || 'https://f-droid.org/en/packages/org.jitsi.meet/';
if (android.dynamicLink) {
android.dynamicLink.apn = android.dynamicLink.apn || 'org.jitsi.meet';
android.dynamicLink.appCode = android.dynamicLink.appCode || 'w2atb';
android.dynamicLink.ibi = android.dynamicLink.ibi || 'com.atlassian.JitsiMeet.ios';
android.dynamicLink.isi = android.dynamicLink.isi || '1165103905';
}
}

View File

@@ -2,6 +2,7 @@ import { AnyAction } from 'redux';
import { IStore } from '../../app/types';
import { getFeatureFlag } from '../flags/functions';
import Platform from '../react/Platform';
import MiddlewareRegistry from '../redux/MiddlewareRegistry';
import { updateSettings } from '../settings/actions';
@@ -52,9 +53,7 @@ function _setConfig({ dispatch, getState }: IStore, next: Function, action: AnyA
const settings = state['features/base/settings'];
const config: IConfig = {};
// FIXME: P2P is currently temporality disabled on mobile.
// eslint-disable-next-line no-constant-condition
if (false && typeof settings.disableP2P !== 'undefined') {
if (Platform.OS !== 'android' && typeof settings.disableP2P !== 'undefined') {
config.p2p = { enabled: !settings.disableP2P };
}

View File

@@ -1,6 +1,7 @@
import _ from 'lodash';
import { CONFERENCE_INFO } from '../../conference/components/constants';
import Platform from '../react/Platform';
import ReducerRegistry from '../redux/ReducerRegistry';
import { equals } from '../redux/functions';
@@ -11,14 +12,8 @@ import {
SET_CONFIG,
UPDATE_CONFIG
} from './actionTypes';
import {
IConfig,
IDeeplinkingConfig,
IDeeplinkingMobileConfig,
IDeeplinkingPlatformConfig,
IMobileDynamicLink
} from './configType';
import { _cleanupConfig, _setDeeplinkingDefaults } from './functions';
import { IConfig } from './configType';
import { _cleanupConfig } from './functions';
/**
* The initial state of the feature base/config when executing in a
@@ -53,18 +48,16 @@ const INITIAL_RN_STATE: IConfig = {
// fastest to merely disable them.
disableAudioLevels: true,
// FIXME: Mobile codecs should probably be configurable separately, rather
// than requiring this override here...
p2p: {
// Temporarily disable P2P on mobile while we sort out some (codec?) issues.
enabled: false,
disabledCodec: 'vp9',
// Temporarily disable P2P on Android while we sort out some (codec?) issues.
...(Platform.OS === 'android' ? { enabled: false } : {}), // eslint-disable-line no-extra-parens
preferredCodec: 'h264'
},
videoQuality: {
disabledCodec: 'vp9',
// FIXME: Mobile codecs should probably be configurable separately, rather
// than requiring this override here...
enforcePreferredCodec: true,
preferredCodec: 'vp8'
}
};
@@ -298,57 +291,6 @@ function _translateInterfaceConfig(oldValue: IConfig) {
}
}
// if we have `deeplinking` defined, ignore deprecated values, except `disableDeepLinking`.
// Otherwise, compose the config.
if (oldValue.deeplinking && newValue.deeplinking) { // make TS happy
newValue.deeplinking.disabled = oldValue.deeplinking.hasOwnProperty('disabled')
? oldValue.deeplinking.disabled
: Boolean(oldValue.disableDeepLinking);
} else {
const disabled = Boolean(oldValue.disableDeepLinking);
const deeplinking: IDeeplinkingConfig = {
desktop: {} as IDeeplinkingPlatformConfig,
hideLogo: false,
disabled,
showImage: false,
android: {} as IDeeplinkingMobileConfig,
ios: {} as IDeeplinkingMobileConfig
};
if (typeof interfaceConfig === 'object') {
const mobileDynamicLink = interfaceConfig.MOBILE_DYNAMIC_LINK;
const dynamicLink: IMobileDynamicLink | undefined = mobileDynamicLink ? {
apn: mobileDynamicLink.APN,
appCode: mobileDynamicLink.APP_CODE,
ibi: mobileDynamicLink.IBI,
isi: mobileDynamicLink.ISI,
customDomain: mobileDynamicLink.CUSTOM_DOMAIN
} : undefined;
if (deeplinking.desktop) {
deeplinking.desktop.appName = interfaceConfig.NATIVE_APP_NAME;
}
deeplinking.hideLogo = Boolean(interfaceConfig.HIDE_DEEP_LINKING_LOGO);
deeplinking.showImage = interfaceConfig.SHOW_DEEP_LINKING_IMAGE;
deeplinking.android = {
appName: interfaceConfig.NATIVE_APP_NAME,
appScheme: interfaceConfig.APP_SCHEME,
downloadLink: interfaceConfig.MOBILE_DOWNLOAD_LINK_ANDROID,
appPackage: interfaceConfig.ANDROID_APP_PACKAGE,
fDroidUrl: interfaceConfig.MOBILE_DOWNLOAD_LINK_F_DROID,
dynamicLink
};
deeplinking.ios = {
appName: interfaceConfig.NATIVE_APP_NAME,
appScheme: interfaceConfig.APP_SCHEME,
downloadLink: interfaceConfig.MOBILE_DOWNLOAD_LINK_IOS,
dynamicLink
};
}
newValue.deeplinking = deeplinking;
}
return newValue;
}
@@ -537,8 +479,6 @@ function _translateLegacyConfig(oldValue: IConfig) {
};
}
_setDeeplinkingDefaults(newValue.deeplinking as IDeeplinkingConfig);
return newValue;
}

View File

@@ -189,9 +189,6 @@ export function constructOptions(state: IReduxState) {
if (options.websocketKeepAliveUrl) {
options.websocketKeepAliveUrl = appendURLParam(options.websocketKeepAliveUrl, 'room', roomName ?? '');
}
if (options.conferenceRequestUrl) {
options.conferenceRequestUrl = appendURLParam(options.conferenceRequestUrl, 'room', roomName ?? '');
}
}
return options;

View File

@@ -5,6 +5,7 @@ import { SET_FILMSTRIP_ENABLED } from '../../filmstrip/actionTypes';
import { SELECT_LARGE_VIDEO_PARTICIPANT } from '../../large-video/actionTypes';
import { APP_STATE_CHANGED } from '../../mobile/background/actionTypes';
import {
SCREEN_SHARE_REMOTE_PARTICIPANTS_UPDATED,
SET_CAR_MODE,
SET_TILE_VIEW,
VIRTUAL_SCREENSHARE_REMOTE_PARTICIPANTS_UPDATED
@@ -101,6 +102,7 @@ MiddlewareRegistry.register(store => next => action => {
case PARTICIPANT_JOINED:
case PARTICIPANT_KICKED:
case PARTICIPANT_LEFT:
case SCREEN_SHARE_REMOTE_PARTICIPANTS_UPDATED:
case SELECT_LARGE_VIDEO_PARTICIPANT:
case SET_AUDIO_ONLY:
case SET_CAR_MODE:

View File

@@ -17,6 +17,7 @@ import {
} from './actionTypes';
import {
MEDIA_TYPE,
type MediaType,
SCREENSHARE_MUTISM_AUTHORITY,
VIDEO_MUTISM_AUTHORITY
} from './constants';
@@ -94,12 +95,14 @@ export function setCameraFacingMode(cameraFacingMode: string) {
* Action to set the muted state of the local screenshare.
*
* @param {boolean} muted - True if the local screenshare is to be enabled or false otherwise.
* @param {MEDIA_TYPE} mediaType - The type of media.
* @param {number} authority - The {@link SCREENSHARE_MUTISM_AUTHORITY} which is muting/unmuting the local screenshare.
* @param {boolean} ensureTrack - True if we want to ensure that a new track is created if missing.
* @returns {Function}
*/
export function setScreenshareMuted(
muted: boolean,
mediaType: MediaType = MEDIA_TYPE.SCREENSHARE,
authority: number = SCREENSHARE_MUTISM_AUTHORITY.USER,
ensureTrack = false) {
return (dispatch: IStore['dispatch'], getState: IStore['getState']) => {
@@ -122,6 +125,7 @@ export function setScreenshareMuted(
return dispatch({
type: SET_SCREENSHARE_MUTED,
authority,
mediaType,
ensureTrack,
muted: newValue
});
@@ -150,6 +154,7 @@ export function setVideoAvailable(available: boolean) {
*
* @param {boolean} muted - True if the local video is to be muted or false if
* the local video is to be unmuted.
* @param {MEDIA_TYPE} mediaType - The type of media.
* @param {number} authority - The {@link VIDEO_MUTISM_AUTHORITY} which is
* muting/unmuting the local video.
* @param {boolean} ensureTrack - True if we want to ensure that a new track is
@@ -158,6 +163,7 @@ export function setVideoAvailable(available: boolean) {
*/
export function setVideoMuted(
muted: boolean,
mediaType: string = MEDIA_TYPE.VIDEO,
authority: number = VIDEO_MUTISM_AUTHORITY.USER,
ensureTrack = false) {
return (dispatch: IStore['dispatch'], getState: IStore['getState']) => {
@@ -180,6 +186,7 @@ export function setVideoMuted(
return dispatch({
type: SET_VIDEO_MUTED,
authority,
mediaType,
ensureTrack,
muted: newValue
});

View File

@@ -1,17 +1,15 @@
// @flow
import React, { Component } from 'react';
import { PanResponder, PixelRatio, View } from 'react-native';
import { SafeAreaView } from 'react-native-safe-area-context';
import { type Dispatch } from 'redux';
import { IReduxState } from '../../../../app/types';
import { connect } from '../../../redux/functions';
import { ASPECT_RATIO_WIDE } from '../../../responsive-ui/constants';
import { connect } from '../../../redux';
import { ASPECT_RATIO_WIDE } from '../../../responsive-ui';
import { storeVideoTransform } from '../../actions';
// @ts-ignore
import styles from './styles';
/**
* The default/initial transform (= no transform).
*/
@@ -57,9 +55,9 @@ const TAP_TIMEOUT_MS = 400;
* Type of a transform object this component is capable of handling.
*/
type Transform = {
scale: number;
translateX: number;
translateY: number;
scale: number,
translateX: number,
translateY: number
};
type Props = {
@@ -67,43 +65,43 @@ type Props = {
/**
* The current aspect ratio of the screen.
*/
_aspectRatio: Symbol;
_aspectRatio: Symbol,
/**
* Action to dispatch when the component is unmounted.
* The children components of this view.
*/
_onUnmount: Function;
children: Object,
/**
* Transformation is only enabled when this flag is true.
*/
enabled: boolean,
/**
* Function to invoke when a press event is detected.
*/
onPress?: Function,
/**
* The id of the current stream that is displayed.
*/
streamId: string,
/**
* Style of the top level transformable view.
*/
style: Object,
/**
* The stored transforms retrieved from Redux to be initially applied
* to different streams.
*/
_transforms: Object;
_transforms: Object,
/**
* The children components of this view.
* Action to dispatch when the component is unmounted.
*/
children: Object;
/**
* Transformation is only enabled when this flag is true.
*/
enabled: boolean;
/**
* Function to invoke when a press event is detected.
*/
onPress?: Function;
/**
* The id of the current stream that is displayed.
*/
streamId: string;
/**
* Style of the top level transformable view.
*/
style: Object;
_onUnmount: Function
};
type State = {
@@ -111,12 +109,12 @@ type State = {
/**
* The current (non-transformed) layout of the View.
*/
layout: any;
layout: ?Object,
/**
* The current transform that is applied.
*/
transform: Transform;
transform: Transform
};
/**
@@ -131,14 +129,14 @@ class VideoTransform extends Component<Props, State> {
/**
* The initial distance of the fingers on pinch start.
*/
initialDistance: number;
initialDistance: ?number;
/**
* The initial position of the finger on touch start.
*/
initialPosition: {
x: number;
y: number;
x: number,
y: number
};
/**
@@ -235,17 +233,14 @@ class VideoTransform extends Component<Props, State> {
videoTransformedViewContainerStyles,
style
] }
// @ts-ignore
{ ...this.gestureHandlers.panHandlers }>
<SafeAreaView
edges = { [ 'bottom', 'left' ] }
<View
style = { [
styles.videoTranformedView,
this._getTransformStyle()
] }>
{ children }
</SafeAreaView>
</View>
</View>
);
}
@@ -286,13 +281,15 @@ class VideoTransform extends Component<Props, State> {
};
}
_didMove: Object => boolean;
/**
* Determines if there was large enough movement to be handled.
*
* @param {Object} gestureState - The gesture state.
* @returns {boolean}
*/
_didMove({ dx, dy }: any) {
_didMove({ dx, dy }) {
return Math.abs(dx) > this.moveThreshold
|| Math.abs(dy) > this.moveThreshold;
}
@@ -305,13 +302,14 @@ class VideoTransform extends Component<Props, State> {
* @private
* @returns {Object | null}
*/
_getSavedTransform(streamId: string) {
_getSavedTransform(streamId) {
const { enabled, _transforms } = this.props;
// @ts-ignore
return (enabled && _transforms[streamId]) || null;
}
_getTouchDistance: Object => number;
/**
* Calculates the touch distance on a pinch event.
*
@@ -319,13 +317,15 @@ class VideoTransform extends Component<Props, State> {
* @private
* @returns {number}
*/
_getTouchDistance({ nativeEvent: { touches } }: any) {
_getTouchDistance({ nativeEvent: { touches } }) {
const dx = Math.abs(touches[0].pageX - touches[1].pageX);
const dy = Math.abs(touches[0].pageY - touches[1].pageY);
return Math.sqrt(Math.pow(dx, 2) + Math.pow(dy, 2));
}
_getTouchPosition: Object => Object;
/**
* Calculates the position of the touch event.
*
@@ -333,13 +333,15 @@ class VideoTransform extends Component<Props, State> {
* @private
* @returns {Object}
*/
_getTouchPosition({ nativeEvent: { touches } }: any) {
_getTouchPosition({ nativeEvent: { touches } }) {
return {
x: touches[0].pageX,
y: touches[0].pageY
};
}
_getTransformStyle: () => Object;
/**
* Generates a transform style object to be used on the component.
*
@@ -471,6 +473,8 @@ class VideoTransform extends Component<Props, State> {
}
}
_onGesture: (string, ?Object | number) => void;
/**
* Handles gestures and converts them to transforms.
*
@@ -490,7 +494,7 @@ class VideoTransform extends Component<Props, State> {
* @param {?Object | number} value - The value of the gesture, if any.
* @returns {void}
*/
_onGesture(type: string, value: any) {
_onGesture(type, value) {
let transform;
switch (type) {
@@ -524,6 +528,8 @@ class VideoTransform extends Component<Props, State> {
this.lastTap = 0;
}
_onLayout: Object => void;
/**
* Callback for the onLayout of the component.
*
@@ -531,7 +537,7 @@ class VideoTransform extends Component<Props, State> {
* @private
* @returns {void}
*/
_onLayout({ nativeEvent: { layout: { x, y, width, height } } }: any) {
_onLayout({ nativeEvent: { layout: { x, y, width, height } } }) {
this.setState({
layout: {
x,
@@ -542,6 +548,8 @@ class VideoTransform extends Component<Props, State> {
});
}
_onMoveShouldSetPanResponder: (Object, Object) => boolean;
/**
* Function to decide whether the responder should respond to a move event.
*
@@ -550,12 +558,14 @@ class VideoTransform extends Component<Props, State> {
* @private
* @returns {boolean}
*/
_onMoveShouldSetPanResponder(evt: Object, gestureState: any) {
_onMoveShouldSetPanResponder(evt, gestureState) {
return this.props.enabled
&& (this._didMove(gestureState)
|| gestureState.numberActiveTouches === 2);
}
_onPanResponderGrant: (Object, Object) => void;
/**
* Calculates the initial touch distance.
*
@@ -564,7 +574,7 @@ class VideoTransform extends Component<Props, State> {
* @private
* @returns {void}
*/
_onPanResponderGrant(evt: Object, { numberActiveTouches }: any) {
_onPanResponderGrant(evt, { numberActiveTouches }) {
if (numberActiveTouches === 1) {
this.initialPosition = this._getTouchPosition(evt);
this.lastTap = Date.now();
@@ -574,6 +584,8 @@ class VideoTransform extends Component<Props, State> {
}
}
_onPanResponderMove: (Object, Object) => void;
/**
* Handles the PanResponder move (touch move) event.
*
@@ -582,7 +594,7 @@ class VideoTransform extends Component<Props, State> {
* @private
* @returns {void}
*/
_onPanResponderMove(evt: Object, gestureState: any) {
_onPanResponderMove(evt, gestureState) {
if (gestureState.numberActiveTouches === 2) {
// this is a zoom event
if (
@@ -616,6 +628,8 @@ class VideoTransform extends Component<Props, State> {
}
}
_onPanResponderRelease: () => void;
/**
* Handles the PanResponder gesture end event.
*
@@ -624,11 +638,8 @@ class VideoTransform extends Component<Props, State> {
*/
_onPanResponderRelease() {
if (this.lastTap && Date.now() - this.lastTap < TAP_TIMEOUT_MS) {
// @ts-ignore
this._onGesture('press');
}
// @ts-ignore
delete this.initialDistance;
this.initialPosition = {
x: 0,
@@ -636,6 +647,8 @@ class VideoTransform extends Component<Props, State> {
};
}
_onStartShouldSetPanResponder: () => boolean;
/**
* Function to decide whether the responder should respond to a start
* (touch) event.
@@ -655,7 +668,7 @@ class VideoTransform extends Component<Props, State> {
* @private
* @returns {void}
*/
_restoreTransform(streamId: string) {
_restoreTransform(streamId) {
const savedTransform = this._getSavedTransform(streamId);
if (savedTransform) {
@@ -674,7 +687,7 @@ class VideoTransform extends Component<Props, State> {
* @private
* @returns {void}
*/
_storeTransform(streamId: string, transform: Transform) {
_storeTransform(streamId, transform) {
const { _onUnmount, enabled } = this.props;
if (enabled) {
@@ -702,7 +715,7 @@ function _mapDispatchToProps(dispatch: Dispatch<any>) {
* @private
* @returns {void}
*/
_onUnmount(streamId: string, transform: Transform) {
_onUnmount(streamId, transform) {
dispatch(storeVideoTransform(streamId, transform));
}
};
@@ -717,7 +730,7 @@ function _mapDispatchToProps(dispatch: Dispatch<any>) {
* _transforms: Object
* }}
*/
function _mapStateToProps(state: IReduxState) {
function _mapStateToProps(state) {
return {
_aspectRatio: state['features/base/responsive-ui'].aspectRatio,

View File

@@ -23,7 +23,7 @@ export default StyleSheet.create({
videoTransformedViewContainerWide: {
overflow: 'hidden',
paddingRight: '16%'
paddingRight: '14%'
},
/**

View File

@@ -166,7 +166,7 @@ function _appStateChanged({ dispatch, getState }, next, action) {
sendAnalytics(createTrackMutedEvent('video', 'background mode', mute));
dispatch(setVideoMuted(mute, VIDEO_MUTISM_AUTHORITY.BACKGROUND));
dispatch(setVideoMuted(mute, MEDIA_TYPE.VIDEO, VIDEO_MUTISM_AUTHORITY.BACKGROUND));
}
return next(action);
@@ -191,9 +191,9 @@ function _setAudioOnly({ dispatch, getState }, next, action) {
sendAnalytics(createTrackMutedEvent('video', 'audio-only mode', audioOnly));
// Make sure we mute both the desktop and video tracks.
dispatch(setVideoMuted(audioOnly, VIDEO_MUTISM_AUTHORITY.AUDIO_ONLY));
dispatch(setVideoMuted(audioOnly, MEDIA_TYPE.VIDEO, VIDEO_MUTISM_AUTHORITY.AUDIO_ONLY));
if (getMultipleVideoSendingSupportFeatureFlag(state)) {
dispatch(setScreenshareMuted(audioOnly, SCREENSHARE_MUTISM_AUTHORITY.AUDIO_ONLY));
dispatch(setScreenshareMuted(audioOnly, MEDIA_TYPE.SCREENSHARE, SCREENSHARE_MUTISM_AUTHORITY.AUDIO_ONLY));
}
return next(action);
@@ -273,10 +273,7 @@ function _setRoom({ dispatch, getState }, next, action) {
// The following don't have complications around whether
// they are defined or not:
jwt: false,
// We need to look for 'startAudioOnly' in settings only for react native clients. Otherwise, the
// default value from ISettingsState (false) will override the value set in config for web clients.
settings: typeof APP === 'undefined'
settings: true
}));
sendAnalytics(createStartAudioOnlyEvent(audioOnly));

View File

@@ -0,0 +1,29 @@
// @flow
import React from 'react';
import WebView from 'react-native-webview';
import JitsiScreen from './JitsiScreen';
type Props = {
/**
* The URL to display.
*/
source: string,
/**
* The component's external style.
*/
style: Object
}
const JitsiScreenWebView = ({ source, style }: Props) => (
<JitsiScreen
disableForcedKeyboardDismiss = { true }
style = { style }>
<WebView source = {{ uri: source }} />
</JitsiScreen>
);
export default JitsiScreenWebView;

View File

@@ -351,11 +351,11 @@ export function isWhiteboardParticipant(participant?: IParticipant): boolean {
* features/base/participants.
* @returns {number}
*/
export function getRemoteParticipantCountWithFake(stateful: IStateful) {
export function getRemoteParticipantCount(stateful: IStateful) {
const state = toState(stateful);
const participantsState = state['features/base/participants'];
return participantsState.remote.size;
return participantsState.remote.size - participantsState.sortedRemoteVirtualScreenshareParticipants.size;
}
/**

View File

@@ -1,3 +1,6 @@
import {
SCREEN_SHARE_REMOTE_PARTICIPANTS_UPDATED
} from '../../video-layout/actionTypes';
import ReducerRegistry from '../redux/ReducerRegistry';
import { set } from '../redux/functions';
@@ -71,6 +74,7 @@ const DEFAULT_STATE = {
remote: new Map(),
sortedRemoteVirtualScreenshareParticipants: new Map(),
sortedRemoteParticipants: new Map(),
sortedRemoteScreenshares: new Map(),
speakersList: new Map()
};
@@ -85,6 +89,7 @@ export interface IParticipantsState {
raisedHandsQueue: Array<{ id: string; raisedHandTimestamp: number; }>;
remote: Map<string, IParticipant>;
sortedRemoteParticipants: Map<string, string>;
sortedRemoteScreenshares: Map<string, string>;
sortedRemoteVirtualScreenshareParticipants: Map<string, string>;
speakersList: Map<string, string>;
}
@@ -380,6 +385,29 @@ ReducerRegistry.register<IParticipantsState>('features/base/participants',
raisedHandsQueue: action.queue
};
}
case SCREEN_SHARE_REMOTE_PARTICIPANTS_UPDATED: {
const { participantIds } = action;
const sortedSharesList = [];
for (const participant of participantIds) {
const remoteParticipant = state.remote.get(participant);
if (remoteParticipant) {
const displayName
= _getDisplayName(state, remoteParticipant.name);
sortedSharesList.push([ participant, displayName ]);
}
}
// Keep the remote screen share list sorted alphabetically.
sortedSharesList.length && sortedSharesList.sort((a, b) => a[1].localeCompare(b[1]));
// @ts-ignore
state.sortedRemoteScreenshares = new Map(sortedSharesList);
return { ...state };
}
case OVERWRITE_PARTICIPANT_NAME: {
const { id, name } = action;

View File

@@ -38,11 +38,6 @@ type Props = {
*/
_showJitsiWatermark: boolean,
/**
* Whether the watermark should have a `top` and `left` value.
*/
noMargins: boolean;
/**
* The default value for the Jitsi logo URL.
*/
@@ -165,9 +160,7 @@ class Watermarks extends Component<Props, State> {
_logoUrl,
_showJitsiWatermark
} = this.props;
const { noMargins, t } = this.props;
const className = `watermark ${noMargins ? 'leftwatermarknomargin' : 'leftwatermark'}`;
const { t } = this.props;
let reactElement = null;
if (_showJitsiWatermark) {
@@ -179,14 +172,14 @@ class Watermarks extends Component<Props, State> {
};
reactElement = (<div
className = { className }
className = 'watermark leftwatermark'
style = { style } />);
if (_logoLink) {
reactElement = (
<a
aria-label = { t('jitsiHome', { logo: interfaceConfig.APP_NAME }) }
className = { className }
className = 'watermark leftwatermark'
href = { _logoLink }
target = '_new'>
{ reactElement }

View File

@@ -2,14 +2,16 @@ import { IReduxState, IStore } from '../../app/types';
// eslint-disable-next-line lines-around-comment
// @ts-ignore
import { setPictureInPictureEnabled } from '../../mobile/picture-in-picture/functions';
import { showNotification } from '../../notifications/actions';
import { NOTIFICATION_TIMEOUT_TYPE } from '../../notifications/constants';
import { setAudioOnly } from '../audio-only/actions';
import JitsiMeetJS from '../lib-jitsi-meet';
import {
setScreenshareMuted,
setVideoMuted
} from '../media/actions';
import { VIDEO_MUTISM_AUTHORITY } from '../media/constants';
import {
MEDIA_TYPE,
VIDEO_MUTISM_AUTHORITY
} from '../media/constants';
import { addLocalTrack, replaceLocalTrack } from './actions.any';
import { getLocalDesktopTrack, getTrackState, isLocalVideoTrackDesktop } from './functions.native';
@@ -38,7 +40,7 @@ export function toggleScreensharing(enabled: boolean, _ignore1?: boolean, _ignor
}
} else {
dispatch(setScreenshareMuted(true));
dispatch(setVideoMuted(false, VIDEO_MUTISM_AUTHORITY.SCREEN_SHARE));
dispatch(setVideoMuted(false, MEDIA_TYPE.VIDEO, VIDEO_MUTISM_AUTHORITY.SCREEN_SHARE));
setPictureInPictureEnabled(true);
}
};
@@ -71,16 +73,12 @@ async function _startScreenSharing(dispatch: Function, state: IReduxState) {
dispatch(addLocalTrack(track));
}
dispatch(setVideoMuted(true, VIDEO_MUTISM_AUTHORITY.SCREEN_SHARE));
dispatch(setVideoMuted(true, MEDIA_TYPE.VIDEO, VIDEO_MUTISM_AUTHORITY.SCREEN_SHARE));
const { enabled: audioOnly } = state['features/base/audio-only'];
if (audioOnly) {
dispatch(showNotification({
titleKey: 'notify.screenSharingAudioOnlyTitle',
descriptionKey: 'notify.screenSharingAudioOnlyDescription',
maxLines: 3
}, NOTIFICATION_TIMEOUT_TYPE.LONG));
dispatch(setAudioOnly(false));
}
} catch (error: any) {
console.log('ERROR creating ScreeSharing stream ', error);

View File

@@ -14,6 +14,7 @@ import { isAudioOnlySharing, isScreenVideoShared } from '../../screen-share/func
import { isScreenshotCaptureEnabled, toggleScreenshotCaptureSummary } from '../../screenshot-capture';
// @ts-ignore
import { AudioMixerEffect } from '../../stream-effects/audio-mixer/AudioMixerEffect';
import { setAudioOnly } from '../audio-only/actions';
import { getCurrentConference } from '../conference/functions';
import { JitsiTrackErrors, JitsiTrackEvents } from '../lib-jitsi-meet';
import { setScreenshareMuted } from '../media/actions';
@@ -226,15 +227,12 @@ async function _toggleScreenSharing(
}
}
// Show notification about more bandwidth usage in audio-only mode if the user starts screensharing. This
// doesn't apply to audio-only screensharing.
// Disable audio-only or best performance mode if the user starts screensharing. This doesn't apply to
// audio-only screensharing.
const { enabled: bestPerformanceMode } = state['features/base/audio-only'];
if (bestPerformanceMode && !audioOnly) {
dispatch(showNotification({
titleKey: 'notify.screenSharingAudioOnlyTitle',
descriptionKey: 'notify.screenSharingAudioOnlyDescription'
}, NOTIFICATION_TIMEOUT_TYPE.LONG));
dispatch(setAudioOnly(false));
}
} else {
const { desktopAudioTrack } = state['features/screen-share'];

View File

@@ -79,7 +79,7 @@ MiddlewareRegistry.register(store => next => action => {
}
case SET_SCREENSHARE_MUTED:
_setMuted(store, action, MEDIA_TYPE.SCREENSHARE);
_setMuted(store, action, action.mediaType);
break;
case SET_VIDEO_MUTED:
@@ -88,7 +88,7 @@ MiddlewareRegistry.register(store => next => action => {
return;
}
_setMuted(store, action, MEDIA_TYPE.VIDEO);
_setMuted(store, action, action.mediaType);
break;
case TOGGLE_CAMERA_FACING_MODE: {

View File

@@ -90,8 +90,8 @@ const Button: React.FC<IProps> = ({
return (
<NativePaperButton
accessibilityLabel = { t(accessibilityLabel ?? '') }
buttonColor = { color }
children = { t(labelKey ?? '') }
color = { color }
contentStyle = { [
styles.buttonContent,
contentStyle

View File

@@ -55,7 +55,6 @@ export default {
buttonLabelTertiary: {
...buttonLabel,
color: BaseTheme.palette.text01,
margin: BaseTheme.spacing[3],
textAlign: 'center'
},

View File

@@ -34,11 +34,6 @@ export interface IButtonProps {
*/
onClick?: (e?: React.MouseEvent<HTMLButtonElement> | GestureResponderEvent) => void;
/**
* Key press callback.
*/
onKeyPress?: (e?: React.KeyboardEvent<HTMLButtonElement>) => void;
/**
* The type of button to be displayed.
*/

View File

@@ -187,7 +187,6 @@ const Button = React.forwardRef<any, any>(({
label,
labelKey,
onClick = () => null,
onKeyPress = () => null,
size = 'medium',
testId,
type = BUTTON_TYPES.PRIMARY
@@ -207,7 +206,6 @@ const Button = React.forwardRef<any, any>(({
disabled = { disabled }
{ ...(id ? { id } : {}) }
onClick = { onClick }
onKeyPress = { onKeyPress }
ref = { ref }
title = { accessibilityLabel }
type = { isSubmit ? 'submit' : 'button' }>

View File

@@ -1,13 +1,6 @@
import { parseURLParams } from './parseURLParams';
import { normalizeNFKC } from './strings';
/**
* Http status codes.
*/
export enum StatusCode {
PaymentRequired = 402
}
/**
* The app linking scheme.
* TODO: This should be read from the manifest files later.

View File

@@ -1,62 +1,47 @@
/* eslint-disable lines-around-comment */
import React, { PureComponent } from 'react';
import { WithTranslation } from 'react-i18next';
import { Text, View } from 'react-native';
import { IReduxState } from '../../../app/types';
// @ts-ignore
import { INVITE_ENABLED, getFeatureFlag } from '../../../base/flags/';
import { translate } from '../../../base/i18n/functions';
// @ts-ignore
import { INVITE_ENABLED, getFeatureFlag } from '../../../base/flags';
import { translate } from '../../../base/i18n';
import { Icon, IconAddUser } from '../../../base/icons';
import { getParticipantCountWithFake } from '../../../base/participants/functions';
import { connect } from '../../../base/redux/functions';
import { getParticipantCountWithFake } from '../../../base/participants';
import { connect } from '../../../base/redux';
import Button from '../../../base/ui/components/native/Button';
import { BUTTON_TYPES } from '../../../base/ui/constants.native';
import { isInBreakoutRoom } from '../../../breakout-rooms/functions';
import { doInvitePeople } from '../../../invite/actions.native';
import { toggleShareDialog } from '../../../share-room/actions';
import { getInviteOthersControl } from '../../../share-room/functions';
// @ts-ignore
import styles from './styles';
/**
* Props type of the component.
*/
type Props = WithTranslation & {
/**
* Control for invite other button.
*/
_inviteOthersControl: any;
type Props = {
/**
* True if currently in a breakout room.
*/
_isInBreakoutRoom: boolean;
_isInBreakoutRoom: boolean,
/**
* True if the invite functions (dial out, invite, share...etc) are disabled.
*/
_isInviteFunctionsDisabled: boolean;
_isInviteFunctionsDiabled: boolean,
/**
* True if it's a lonely meeting (participant count excluding fakes is 1).
*/
_isLonelyMeeting: boolean;
_isLonelyMeeting: boolean,
/**
* The Redux Dispatch function.
*/
dispatch: Function;
dispatch: Function,
/**
* Function to be used to translate i18n labels.
*/
t: Function;
t: Function
};
/**
@@ -74,6 +59,19 @@ class LonelyMeetingExperience extends PureComponent<Props> {
this._onPress = this._onPress.bind(this);
}
/**
* Renders the "add people" icon.
*
* @returns {ReactElement}
*/
_renderAddPeopleIcon() {
return (
<Icon
size = { 20 }
src = { IconAddUser } />
);
}
/**
* Implements {@code PureComponent#render}.
*
@@ -81,13 +79,11 @@ class LonelyMeetingExperience extends PureComponent<Props> {
*/
render() {
const {
_inviteOthersControl,
_isInBreakoutRoom,
_isInviteFunctionsDisabled,
_isInviteFunctionsDiabled,
_isLonelyMeeting,
t
} = this.props;
const { color, shareDialogVisible } = _inviteOthersControl;
if (!_isLonelyMeeting) {
return null;
@@ -98,17 +94,10 @@ class LonelyMeetingExperience extends PureComponent<Props> {
<Text style = { styles.lonelyMessage }>
{ t('lonelyMeetingExperience.youAreAlone') }
</Text>
{ !_isInviteFunctionsDisabled && !_isInBreakoutRoom && (
{ !_isInviteFunctionsDiabled && !_isInBreakoutRoom && (
<Button
accessibilityLabel = 'lonelyMeetingExperience.button'
disabled = { shareDialogVisible }
// eslint-disable-next-line react/jsx-no-bind
icon = { () => (
<Icon
color = { color }
size = { 20 }
src = { IconAddUser } />
) }
icon = { this._renderAddPeopleIcon }
labelKey = 'lonelyMeetingExperience.button'
onClick = { this._onPress }
type = { BUTTON_TYPES.PRIMARY } />
@@ -123,7 +112,6 @@ class LonelyMeetingExperience extends PureComponent<Props> {
* @returns {void}
*/
_onPress() {
this.props.dispatch(toggleShareDialog(true));
this.props.dispatch(doInvitePeople());
}
}
@@ -135,17 +123,15 @@ class LonelyMeetingExperience extends PureComponent<Props> {
* @private
* @returns {Props}
*/
function _mapStateToProps(state: IReduxState) {
function _mapStateToProps(state) {
const { disableInviteFunctions } = state['features/base/config'];
const { conference } = state['features/base/conference'];
const _inviteOthersControl = getInviteOthersControl(state);
const flag = getFeatureFlag(state, INVITE_ENABLED, true);
const _isInBreakoutRoom = isInBreakoutRoom(state);
return {
_inviteOthersControl,
_isInBreakoutRoom,
_isInviteFunctionsDisabled: !flag || disableInviteFunctions,
_isInviteFunctionsDiabled: !flag || disableInviteFunctions,
_isLonelyMeeting: conference && getParticipantCountWithFake(state) === 1
};
}

View File

@@ -5,7 +5,6 @@ import React, { Component } from 'react';
import type { Dispatch } from 'redux';
import { createDeepLinkingPageEvent, sendAnalytics } from '../../analytics';
import { IDeeplinkingConfig } from '../../base/config/configType';
import { isSupportedBrowser } from '../../base/environment';
import { translate } from '../../base/i18n';
import { connect } from '../../base/redux';
@@ -17,17 +16,14 @@ import {
} from '../actions';
import { _TNS } from '../constants';
declare var interfaceConfig: Object;
/**
* The type of the React {@code Component} props of
* {@link DeepLinkingDesktopPage}.
*/
type Props = {
/**
* The deeplinking config.
*/
_deeplinkingCfg: IDeeplinkingConfig,
/**
* Used to dispatch actions from the buttons.
*/
@@ -76,10 +72,10 @@ class DeepLinkingDesktopPage<P : Props> extends Component<P> {
* @returns {ReactElement}
*/
render() {
const { t, _deeplinkingCfg: { desktop = {}, hideLogo, showImage } } = this.props;
const { appName } = desktop;
const { t } = this.props;
const { HIDE_DEEP_LINKING_LOGO, NATIVE_APP_NAME, SHOW_DEEP_LINKING_IMAGE } = interfaceConfig;
const rightColumnStyle
= showImage ? null : { width: '100%' };
= SHOW_DEEP_LINKING_IMAGE ? null : { width: '100%' };
return (
@@ -88,7 +84,7 @@ class DeepLinkingDesktopPage<P : Props> extends Component<P> {
<div className = 'deep-linking-desktop'>
<div className = 'header'>
{
hideLogo
HIDE_DEEP_LINKING_LOGO
? null
: <img
alt = { t('welcomepage.logo.logoDeepLinking') }
@@ -98,7 +94,7 @@ class DeepLinkingDesktopPage<P : Props> extends Component<P> {
</div>
<div className = 'content'>
{
showImage
SHOW_DEEP_LINKING_IMAGE
? <div className = 'leftColumn'>
<div className = 'leftColumnContent'>
<div className = 'image' />
@@ -112,7 +108,7 @@ class DeepLinkingDesktopPage<P : Props> extends Component<P> {
<h1 className = 'title'>
{
t(`${_TNS}.title`,
{ app: appName })
{ app: NATIVE_APP_NAME })
}
</h1>
<p className = 'description'>
@@ -121,7 +117,7 @@ class DeepLinkingDesktopPage<P : Props> extends Component<P> {
`${_TNS}.${isSupportedBrowser()
? 'description'
: 'descriptionWithoutWeb'}`,
{ app: appName }
{ app: NATIVE_APP_NAME }
)
}
</p>
@@ -175,18 +171,4 @@ class DeepLinkingDesktopPage<P : Props> extends Component<P> {
}
}
/**
* Maps (parts of) the Redux state to the associated props for the
* {@code DeepLinkingDesktopPage} component.
*
* @param {Object} state - The Redux state.
* @private
* @returns {Props}
*/
function _mapStateToProps(state) {
return {
_deeplinkingCfg: state['features/base/config'].deeplinking || {}
};
}
export default translate(connect(_mapStateToProps)(DeepLinkingDesktopPage));
export default translate(connect()(DeepLinkingDesktopPage));

View File

@@ -4,7 +4,6 @@ import React, { Component } from 'react';
import type { Dispatch } from 'redux';
import { createDeepLinkingPageEvent, sendAnalytics } from '../../analytics';
import { IDeeplinkingConfig, IDeeplinkingMobileConfig } from '../../base/config/configType';
import { isSupportedMobileBrowser } from '../../base/environment';
import { translate } from '../../base/i18n';
import { Platform } from '../../base/react';
@@ -15,6 +14,8 @@ import { _TNS } from '../constants';
import { generateDeepLinkingURL } from '../functions';
import { renderPromotionalFooter } from '../renderPromotionalFooter';
declare var interfaceConfig: Object;
/**
* The namespace of the CSS styles of DeepLinkingMobilePage.
*
@@ -30,19 +31,9 @@ const _SNS = 'deep-linking-mobile';
type Props = {
/**
* The deeplinking config.
* Application download URL.
*/
_deeplinkingCfg: IDeeplinkingConfig,
/**
* Application mobile deeplinking config.
*/
_mobileConfig: IDeeplinkingMobileConfig,
/**
* The deeplinking url.
*/
_deepLinkingUrl: string,
_downloadUrl: ?string,
/**
* The name of the conference attempting to being joined.
@@ -104,19 +95,13 @@ class DeepLinkingMobilePage extends Component<Props> {
* @returns {ReactElement}
*/
render() {
const {
_deeplinkingCfg: { hideLogo, showImage },
_mobileConfig: { downloadLink, appName },
_room,
t,
_url,
_deepLinkingUrl
} = this.props;
const { _downloadUrl, _room, t, _url } = this.props;
const { HIDE_DEEP_LINKING_LOGO, NATIVE_APP_NAME, SHOW_DEEP_LINKING_IMAGE } = interfaceConfig;
const downloadButtonClassName
= `${_SNS}__button ${_SNS}__button_primary`;
const onOpenLinkProperties = downloadLink
const onOpenLinkProperties = _downloadUrl
? {
// When opening a link to the download page, we want to let the
// OS itself handle intercepting and opening the appropriate
@@ -136,7 +121,7 @@ class DeepLinkingMobilePage extends Component<Props> {
<div className = { _SNS }>
<div className = 'header'>
{
hideLogo
HIDE_DEEP_LINKING_LOGO
? null
: <img
alt = { t('welcomepage.logo.logoDeepLinking') }
@@ -146,7 +131,7 @@ class DeepLinkingMobilePage extends Component<Props> {
</div>
<div className = { `${_SNS}__body` }>
{
showImage
SHOW_DEEP_LINKING_IMAGE
? <img
alt = { t('welcomepage.logo.logoDeepLinking') }
className = 'image'
@@ -154,7 +139,7 @@ class DeepLinkingMobilePage extends Component<Props> {
: null
}
<p className = { `${_SNS}__text` }>
{ t(`${_TNS}.appNotInstalled`, { app: appName }) }
{ t(`${_TNS}.appNotInstalled`, { app: NATIVE_APP_NAME }) }
</p>
<p className = { `${_SNS}__text` }>
{ t(`${_TNS}.ifHaveApp`) }
@@ -162,7 +147,7 @@ class DeepLinkingMobilePage extends Component<Props> {
<a
{ ...onOpenLinkProperties }
className = { `${_SNS}__href` }
href = { _deepLinkingUrl }
href = { generateDeepLinkingURL() }
onClick = { this._onOpenApp }
target = '_top'>
<button className = { `${_SNS}__button ${_SNS}__button_primary` }>
@@ -215,28 +200,32 @@ class DeepLinkingMobilePage extends Component<Props> {
* @returns {string} - The URL for downloading the app.
*/
_generateDownloadURL() {
const { _mobileConfig: { downloadLink, dynamicLink, appScheme } } = this.props;
const { _downloadUrl: url } = this.props;
if (downloadLink && typeof dynamicLink === 'undefined') {
return downloadLink;
if (url && typeof interfaceConfig.MOBILE_DYNAMIC_LINK === 'undefined') {
return url;
}
// For information about the properties of
// interfaceConfig.MOBILE_DYNAMIC_LINK check:
// https://firebase.google.com/docs/dynamic-links/create-manually
const {
apn,
appCode,
customDomain,
ibi,
isi
} = dynamicLink || {};
APN = 'org.jitsi.meet',
APP_CODE = 'w2atb',
CUSTOM_DOMAIN = undefined,
IBI = 'com.atlassian.JitsiMeet.ios',
ISI = '1165103905'
} = interfaceConfig.MOBILE_DYNAMIC_LINK || {};
const domain = customDomain ?? `https://${appCode}.app.goo.gl`;
const domain = CUSTOM_DOMAIN ?? `https://${APP_CODE}.app.goo.gl`;
const IUS = interfaceConfig.APP_SCHEME || 'org.jitsi.meet';
return `${domain}/?link=${
encodeURIComponent(window.location.href)}&apn=${
apn}&ibi=${
ibi}&isi=${
isi}&ius=${
appScheme}&efr=1`;
APN}&ibi=${
IBI}&isi=${
ISI}&ius=${
IUS}&efr=1`;
}
_onDownloadApp: () => void;
@@ -292,15 +281,11 @@ class DeepLinkingMobilePage extends Component<Props> {
*/
function _mapStateToProps(state) {
const { locationURL = {} } = state['features/base/connection'];
const { deeplinking } = state['features/base/config'];
const mobileConfig = deeplinking?.[Platform.OS] || {};
return {
_deeplinkingCfg: deeplinking || {},
_mobileConfig: mobileConfig,
_downloadUrl: interfaceConfig[`MOBILE_DOWNLOAD_LINK_${Platform.OS.toUpperCase()}`],
_room: decodeURIComponent(state['features/base/conference'].room),
_url: locationURL,
_deepLinkingUrl: generateDeepLinkingURL(state)
_url: locationURL
};
}

View File

@@ -3,28 +3,15 @@
import React, { Component } from 'react';
import { createDeepLinkingPageEvent, sendAnalytics } from '../../analytics';
import { IDeeplinkingConfig } from '../../base/config/configType';
import { connect } from '../../base/redux';
/**
* The type of the React {@code Component} props of
* {@link NoMobileApp}.
*/
type Props = {
/**
* The deeplinking config.
*/
_deeplinkingCfg: IDeeplinkingConfig,
};
declare var interfaceConfig: Object;
/**
* React component representing no mobile app page.
*
* @class NoMobileApp
*/
class NoMobileApp<P : Props> extends Component<P> {
export default class NoMobileApp extends Component<*> {
/**
* Implements the Component's componentDidMount method.
*
@@ -43,7 +30,6 @@ class NoMobileApp<P : Props> extends Component<P> {
*/
render() {
const ns = 'no-mobile-app';
const { desktop: { appName } } = this.props._deeplinkingCfg;
return (
<div className = { ns }>
@@ -51,26 +37,10 @@ class NoMobileApp<P : Props> extends Component<P> {
Video chat isn't available on mobile.
</h2>
<p className = { `${ns}__description` }>
Please use { appName } on desktop to
Please use { interfaceConfig.NATIVE_APP_NAME } on desktop to
join calls.
</p>
</div>
);
}
}
/**
* Maps (parts of) the Redux state to the associated props for the
* {@code NoMobileApp} component.
*
* @param {Object} state - The Redux state.
* @private
* @returns {Props}
*/
function _mapStateToProps(state) {
return {
_deeplinkingCfg: state['features/base/config'].deeplinking || {}
};
}
export default connect(_mapStateToProps)(NoMobileApp);

View File

@@ -15,31 +15,27 @@ import { _openDesktopApp } from './openDesktopApp';
/**
* Generates a deep linking URL based on the current window URL.
*
* @param {Object} state - Object containing current redux state.
*
* @returns {string} - The generated URL.
*/
export function generateDeepLinkingURL(state) {
export function generateDeepLinkingURL() {
// If the user installed the app while this Component was displayed
// (e.g. the user clicked the Download the App button), then we would
// like to open the current URL in the mobile app. The only way to do it
// appears to be a link with an app-specific scheme, not a Universal
// Link.
const appScheme = interfaceConfig.APP_SCHEME || 'org.jitsi.meet';
const { href } = window.location;
const regex = new RegExp(URI_PROTOCOL_PATTERN, 'gi');
const mobileConfig = state['features/base/config'].deeplinking?.[Platform.OS] || {};
const { appScheme, appPackage } = mobileConfig;
// Android: use an intent link, custom schemes don't work in all browsers.
// https://developer.chrome.com/multidevice/android/intents
if (Platform.OS === 'android') {
// https://meet.jit.si/foo -> meet.jit.si/foo
const url = href.replace(regex, '').substr(2);
const pkg = interfaceConfig.ANDROID_APP_PACKAGE || 'org.jitsi.meet';
return `intent://${url}#Intent;scheme=${appScheme};package=${appPackage};end`;
return `intent://${url}#Intent;scheme=${appScheme};package=${pkg};end`;
}
// iOS: Replace the protocol part with the app scheme.
@@ -56,13 +52,12 @@ export function generateDeepLinkingURL(state) {
export function getDeepLinkingPage(state) {
const { room } = state['features/base/conference'];
const { launchInWeb } = state['features/deep-linking'];
const deeplinking = state['features/base/config'].deeplinking || {};
const { appScheme } = deeplinking?.[Platform.OS] || {};
const appScheme = typeof interfaceConfig !== 'undefined' && interfaceConfig.APP_SCHEME;
// Show only if we are about to join a conference.
if (launchInWeb
|| !room
|| state['features/base/config'].deeplinking?.disabled
|| state['features/base/config'].disableDeepLinking
|| (isVpaasMeeting(state) && (!appScheme || appScheme === 'com.8x8.meet'))) {
return Promise.resolve();
}

View File

@@ -305,20 +305,13 @@ class FaceLandmarksDetector {
private async sendDataToWorker(faceCenteringThreshold = 10): Promise<boolean> {
if (!this.imageCapture
|| !this.worker
|| !this.imageCapture) {
|| !this.imageCapture?.track
|| this.imageCapture?.track.readyState !== 'live') {
logger.log('Environment not ready! Could not send data to worker');
return false;
}
// if ImageCapture is polyfilled then it would not have the track,
// so there would be no point in checking for its readyState
if (this.imageCapture.track && this.imageCapture.track.readyState !== 'live') {
logger.log('Track not ready! Could not send data to worker');
return false;
}
let imageBitmap;
let image;

View File

@@ -3,7 +3,7 @@ import { pinParticipant } from '../base/participants/actions';
import {
getLocalParticipant,
getParticipantById,
getRemoteParticipantCountWithFake
getRemoteParticipantCount
} from '../base/participants/functions';
import { shouldHideSelfView } from '../base/settings/functions.web';
import { getMaxColumnCount } from '../video-layout/functions.web';
@@ -149,7 +149,7 @@ export function setVerticalViewDimensions() {
const disableSelfView = shouldHideSelfView(state);
const resizableFilmstrip = isFilmstripResizable(state);
const _verticalViewGrid = showGridInVerticalView(state);
const numberOfRemoteParticipants = getRemoteParticipantCountWithFake(state);
const numberOfRemoteParticipants = getRemoteParticipantCount(state);
const { localScreenShare } = state['features/base/participants'];
let gridView = {};
@@ -261,7 +261,7 @@ export function setHorizontalViewDimensions() {
= clientWidth - (disableSelfView ? 0 : thumbnails?.local?.width) - HORIZONTAL_FILMSTRIP_MARGIN;
const remoteVideosContainerHeight
= thumbnails?.local?.height + TILE_VERTICAL_MARGIN + STAGE_VIEW_THUMBNAIL_VERTICAL_BORDER + SCROLL_SIZE;
const numberOfRemoteParticipants = getRemoteParticipantCountWithFake(state);
const numberOfRemoteParticipants = getRemoteParticipantCount(state);
const hasScroll
= remoteVideosContainerHeight
< (thumbnails?.remote.width + TILE_HORIZONTAL_MARGIN) * numberOfRemoteParticipants;

View File

@@ -10,8 +10,8 @@ import { translate } from '../../../../base/i18n/functions';
import { JitsiRecordingConstants } from '../../../../base/lib-jitsi-meet';
import { connect } from '../../../../base/redux/functions';
import Dialog from '../../../../base/ui/components/web/Dialog';
import { StatusCode } from '../../../../base/util/uri';
import { isDynamicBrandingDataLoaded } from '../../../../dynamic-branding/functions.any';
import { isVpaasMeeting } from '../../../../jaas/functions';
import { getActiveSession } from '../../../../recording/functions';
// @ts-ignore
import { updateDialInNumbers } from '../../../actions';
@@ -80,9 +80,9 @@ interface IProps extends WithTranslation {
_inviteUrl: string;
/**
* Whether the dial in limit has been exceeded.
* Whether or not the current meeting belongs to a JaaS user.
*/
_isDialInOverLimit?: boolean;
_isVpaasMeeting: boolean;
/**
* The current known URL for a live stream in progress.
@@ -120,7 +120,7 @@ function AddPeopleDialog({
_inviteAppName,
_inviteContactsVisible,
_inviteUrl,
_isDialInOverLimit,
_isVpaasMeeting,
_liveStreamViewURL,
_phoneNumber,
t,
@@ -182,7 +182,7 @@ function AddPeopleDialog({
&& <DialInSection phoneNumber = { _phoneNumber } />
}
{
!_phoneNumber && _dialInVisible && _isDialInOverLimit && <DialInLimit />
!_phoneNumber && _dialInVisible && _isVpaasMeeting && <DialInLimit />
}
</div>
</Dialog>
@@ -207,7 +207,6 @@ function mapStateToProps(state: IReduxState, ownProps: Partial<IProps>) {
const hideInviteContacts = iAmRecorder || (!addPeopleEnabled && !dialOutEnabled);
const dialIn = state['features/invite']; // @ts-ignore
const phoneNumber = dialIn?.numbers ? _getDefaultPhoneNumber(dialIn.numbers) : undefined;
const isDialInOverLimit = dialIn?.error?.status === StatusCode.PaymentRequired;
return {
_dialIn: dialIn,
@@ -223,7 +222,7 @@ function mapStateToProps(state: IReduxState, ownProps: Partial<IProps>) {
_inviteAppName: inviteAppName,
_inviteContactsVisible: interfaceConfig.ENABLE_DIAL_OUT && !hideInviteContacts,
_inviteUrl: getInviteURL(state),
_isDialInOverLimit: isDialInOverLimit,
_isVpaasMeeting: isVpaasMeeting(state),
_liveStreamViewURL: currentLiveStreamingSession?.liveStreamViewURL,
_phoneNumber: phoneNumber
};

View File

@@ -14,11 +14,11 @@ const useStyles = makeStyles()(theme => {
padding: '8px 16px'
},
limitInfo: {
color: theme.palette.text.primary,
color: theme.palette.field01,
...withPixelLineHeight(theme.typography.bodyShortRegular)
},
link: {
color: `${theme.palette.text.primary} !important`,
color: theme.palette.field01,
fontWeight: 'bold',
textDecoration: 'underline'
}

View File

@@ -9,11 +9,7 @@ import { JitsiRecordingConstants } from '../base/lib-jitsi-meet';
import { getLocalParticipant, isLocalParticipantModerator } from '../base/participants/functions';
import { toState } from '../base/redux/functions';
import { parseURLParams } from '../base/util/parseURLParams';
import {
StatusCode,
appendURLParam,
parseURIString
} from '../base/util/uri';
import { appendURLParam, parseURIString } from '../base/util/uri';
import { isVpaasMeeting } from '../jaas/functions';
import { getActiveSession } from '../recording/functions';
@@ -21,8 +17,7 @@ import { getDialInConferenceID, getDialInNumbers } from './_utils';
import {
DIAL_IN_INFO_PAGE_PATH_NAME,
INVITE_TYPES,
SIP_ADDRESS_REGEX,
UPGRADE_OPTIONS_TEXT
SIP_ADDRESS_REGEX
} from './constants';
import logger from './logger';
@@ -519,7 +514,6 @@ export function getShareInfoText(state: IReduxState, inviteUrl: string, useHtml?
if (includeDialInfo) {
const { room } = parseURIString(inviteUrl);
let numbersPromise;
let hasPaymentError = false;
if (state['features/invite'].numbers
&& state['features/invite'].conferenceID) {
@@ -566,19 +560,9 @@ export function getShareInfoText(state: IReduxState, inviteUrl: string, useHtml?
i18next.t('info.dialInConferenceID')} ${
conferenceID}#\n\n`;
})
.catch(error => {
logger.error('Error fetching numbers or conferenceID', error);
hasPaymentError = error?.status === StatusCode.PaymentRequired;
})
.catch(error =>
logger.error('Error fetching numbers or conferenceID', error))
.then(defaultDialInNumber => {
if (hasPaymentError) {
infoText += `${
i18next.t('info.dialInNumber')} ${i18next.t('info.reachedLimit')} ${
i18next.t('info.upgradeOptions')} ${UPGRADE_OPTIONS_TEXT}`;
return infoText;
}
let dialInfoPageUrl = getDialInfoPageURL(state, room);
if (useHtml) {

View File

@@ -26,9 +26,7 @@ const DEFAULT_STATE = {
export interface IInviteState {
calleeInfoVisible?: boolean;
conferenceID?: string | number;
error?: {
status: number;
};
error?: Error;
initialCalleeInfo?: Object;
numbers?: string[];
numbersEnabled: boolean;
@@ -75,7 +73,6 @@ ReducerRegistry.register<IInviteState>('features/invite', (state = DEFAULT_STATE
return {
...state,
conferenceID: action.conferenceID,
error: undefined,
numbers: action.dialInNumbers,
sipUri: action.sipUri,
numbersEnabled: true,
@@ -91,7 +88,6 @@ ReducerRegistry.register<IInviteState>('features/invite', (state = DEFAULT_STATE
return {
...state,
conferenceID: action.conferenceID,
error: undefined,
numbers: action.dialInNumbers,
numbersEnabled,
numbersFetched: true

View File

@@ -183,7 +183,6 @@ const ConferenceNavigationContainer = () => {
name = { screen.settings.main }
options = { settingsNavigationContainerScreenOptions } />
<ConferenceStack.Screen
// @ts-ignore
component = { CarMode }
name = { screen.conference.carmode }
options = {{

View File

@@ -3,10 +3,14 @@ import { createStackNavigator } from '@react-navigation/stack';
import React, { useCallback } from 'react';
import { useTranslation } from 'react-i18next';
import HelpView from '../../../../../settings/components/native/HelpView';
import PrivacyView from '../../../../../settings/components/native/PrivacyView';
import SettingsView
from '../../../../../settings/components/native/SettingsView';
import TermsView from '../../../../../settings/components/native/TermsView';
import { screen } from '../../../routes';
import {
linkScreenOptions,
navigationContainerTheme,
settingsScreenOptions,
welcomeScreenOptions
@@ -57,6 +61,27 @@ const SettingsNavigationContainer = ({ isInWelcomePage }: Props) => {
}}>
{ SettingsScreen }
</SettingsStack.Screen>
<SettingsStack.Screen
component = { HelpView }
name = { screen.settings.links.help }
options = {{
...linkScreenOptions,
title: t('helpView.title')
}} />
<SettingsStack.Screen
component = { TermsView }
name = { screen.settings.links.terms }
options = {{
...linkScreenOptions,
title: t('termsView.title')
}} />
<SettingsStack.Screen
component = { PrivacyView }
name = { screen.settings.links.privacy }
options = {{
...linkScreenOptions,
title: t('privacyView.title')
}} />
</SettingsStack.Navigator>
</NavigationContainer>
);

View File

@@ -26,6 +26,14 @@ export const fullScreenOptions = {
headerShown: false
};
export const linkScreenOptions = {
gestureEnabled: true,
headerShown: true,
headerTitleStyle: {
color: BaseTheme.palette.text01
}
};
/**
* Navigation container theme.
*/

View File

@@ -1,11 +1,43 @@
import { registerGlobals } from 'react-native-webrtc';
import {
MediaStream,
MediaStreamTrack,
RTCIceCandidate,
RTCSessionDescription,
mediaDevices,
permissions
} from 'react-native-webrtc';
import RTCPeerConnection from './RTCPeerConnection';
registerGlobals();
(global => {
// Override with ours.
// TODO: consider dropping our override.
global.RTCPeerConnection = RTCPeerConnection;
if (typeof global.MediaStream === 'undefined') {
global.MediaStream = MediaStream;
}
if (typeof global.MediaStreamTrack === 'undefined') {
global.MediaStreamTrack = MediaStreamTrack;
}
if (typeof global.RTCIceCandidate === 'undefined') {
global.RTCIceCandidate = RTCIceCandidate;
}
if (typeof global.RTCPeerConnection === 'undefined') {
global.RTCPeerConnection = RTCPeerConnection;
}
if (typeof global.RTCPeerConnection === 'undefined') {
global.webkitRTCPeerConnection = RTCPeerConnection;
}
if (typeof global.RTCSessionDescription === 'undefined') {
global.RTCSessionDescription = RTCSessionDescription;
}
const navigator = global.navigator;
if (navigator) {
if (typeof navigator.mediaDevices === 'undefined') {
navigator.mediaDevices = mediaDevices;
}
if (typeof navigator.permissions === 'undefined') {
navigator.permissions = permissions;
}
}
})(global || window || this); // eslint-disable-line no-invalid-this

View File

@@ -1,108 +1,92 @@
/* eslint-disable lines-around-comment */
// @flow
import React, { PureComponent } from 'react';
import { WithTranslation } from 'react-i18next';
import { FlatList } from 'react-native';
import { IReduxState } from '../../../app/types';
import { translate } from '../../../base/i18n/functions';
// @ts-ignore
import { translate } from '../../../base/i18n';
import { Icon, IconAddUser } from '../../../base/icons';
import {
getLocalParticipant,
getParticipantCountWithFake,
getRemoteParticipants
} from '../../../base/participants/functions';
import { connect } from '../../../base/redux/functions';
import { getLocalParticipant, getParticipantCountWithFake, getRemoteParticipants } from '../../../base/participants';
import { connect } from '../../../base/redux';
import Button from '../../../base/ui/components/native/Button';
import Input from '../../../base/ui/components/native/Input';
import { BUTTON_TYPES } from '../../../base/ui/constants.native';
import { getBreakoutRooms, getCurrentRoomId } from '../../../breakout-rooms/functions';
import { doInvitePeople } from '../../../invite/actions.native';
import { toggleShareDialog } from '../../../share-room/actions';
import { getInviteOthersControl } from '../../../share-room/functions';
import { participantMatchesSearch, shouldRenderInviteButton } from '../../functions';
// @ts-ignore
import CollapsibleList from './CollapsibleList';
// @ts-ignore
import MeetingParticipantItem from './MeetingParticipantItem';
// @ts-ignore
import styles from './styles';
type Props = WithTranslation & {
type Props = {
/**
* Current breakout room, if we are in one.
*/
_currentRoom: any;
/**
* Control for invite other button.
*/
_inviteOthersControl: any;
_currentRoom: ?Object,
/**
* The local participant.
*/
_localParticipant: any;
_localParticipant: Object,
/**
* The number of participants in the conference.
*/
_participantsCount: number;
_participantsCount: number,
/**
* The remote participants.
*/
_remoteParticipants: Map<string, Object>;
_remoteParticipants: Map<string, Object>,
/**
* Whether or not to show the invite button.
*/
_showInviteButton: boolean;
_showInviteButton: boolean,
/**
* The remote participants.
*/
_sortedRemoteParticipants: Map<string, string>;
_sortedRemoteParticipants: Map<string, string>,
/**
* List of breakout rooms that were created.
*/
breakoutRooms: ArrayLike<any>;
breakoutRooms: Array,
/**
* The redux dispatch function.
*/
dispatch: Function;
dispatch: Function,
/**
* Is the local participant moderator?
*/
isLocalModerator: boolean;
isLocalModerator: boolean,
/**
* List of participants waiting in lobby.
*/
lobbyParticipants: ArrayLike<any>;
lobbyParticipants: Array,
/**
* Participants search string.
*/
searchString: string;
searchString: string,
/**
* Function to update the search string.
*/
setSearchString: Function;
setSearchString: Function,
/**
* Translation function.
*/
t: Function;
};
t: Function
}
/**
* The meeting participant list component.
@@ -123,26 +107,44 @@ class MeetingParticipantList extends PureComponent<Props> {
this._onSearchStringChange = this._onSearchStringChange.bind(this);
}
_keyExtractor: Function;
/**
* Returns a key for a passed item of the list.
*
* @param {string} item - The user ID.
* @returns {string} - The user ID.
*/
_keyExtractor(item: string) {
_keyExtractor(item) {
return item;
}
_onInvite: () => void;
/**
* Handles ivite button presses.
*
* @returns {void}
*/
_onInvite() {
this.props.dispatch(toggleShareDialog(true));
this.props.dispatch(doInvitePeople());
}
/**
* Renders the "invite more" icon.
*
* @returns {ReactElement}
*/
_renderInviteMoreIcon() {
return (
<Icon
size = { 20 }
src = { IconAddUser } />
);
}
_renderParticipant: Object => Object;
/**
* Renders a participant.
*
@@ -150,7 +152,7 @@ class MeetingParticipantList extends PureComponent<Props> {
* @param {string} flatListItem.item - The ID of the participant.
* @returns {ReactElement}
*/
_renderParticipant({ item/* , index, separators */ }: any) {
_renderParticipant({ item/* , index, separators */ }) {
const { _localParticipant, _remoteParticipants, searchString } = this.props;
const participant = item === _localParticipant?.id ? _localParticipant : _remoteParticipants.get(item);
@@ -165,6 +167,8 @@ class MeetingParticipantList extends PureComponent<Props> {
return null;
}
_onSearchStringChange: (text: string) => void;
/**
* Handles search string changes.
*
@@ -184,7 +188,6 @@ class MeetingParticipantList extends PureComponent<Props> {
render() {
const {
_currentRoom,
_inviteOthersControl,
_localParticipant,
_participantsCount,
_showInviteButton,
@@ -216,7 +219,6 @@ class MeetingParticipantList extends PureComponent<Props> {
? containerStyleModerator : styles.notLocalModeratorContainer;
const finalContainerStyle
= _participantsCount > 6 && containerStyle;
const { color, shareDialogVisible } = _inviteOthersControl;
return (
<CollapsibleList
@@ -226,14 +228,7 @@ class MeetingParticipantList extends PureComponent<Props> {
_showInviteButton
&& <Button
accessibilityLabel = 'participantsPane.actions.invite'
disabled = { shareDialogVisible }
// eslint-disable-next-line react/jsx-no-bind
icon = { () => (
<Icon
color = { color }
size = { 20 }
src = { IconAddUser } />
) }
icon = { this._renderInviteMoreIcon }
labelKey = 'participantsPane.actions.invite'
onClick = { this._onInvite }
style = { styles.inviteButton }
@@ -241,7 +236,6 @@ class MeetingParticipantList extends PureComponent<Props> {
}
<Input
clearable = { true }
// @ts-ignore
customStyles = {{
container: styles.inputContainer,
input: styles.centerInput }}
@@ -269,11 +263,9 @@ class MeetingParticipantList extends PureComponent<Props> {
* @private
* @returns {Props}
*/
function _mapStateToProps(state: IReduxState): Object {
function _mapStateToProps(state): Object {
const _participantsCount = getParticipantCountWithFake(state);
const { remoteParticipants } = state['features/filmstrip'];
const { shareDialogVisible } = state['features/share-room'];
const _inviteOthersControl = getInviteOthersControl(state);
const _showInviteButton = shouldRenderInviteButton(state);
const _remoteParticipants = getRemoteParticipants(state);
const currentRoomId = getCurrentRoomId(state);
@@ -281,13 +273,11 @@ function _mapStateToProps(state: IReduxState): Object {
return {
_currentRoom,
_inviteOthersControl,
_participantsCount,
_remoteParticipants,
_showInviteButton,
_sortedRemoteParticipants: remoteParticipants,
_localParticipant: getLocalParticipant(state),
_shareDialogVisible: shareDialogVisible
_localParticipant: getLocalParticipant(state)
};
}

View File

@@ -1,6 +1,6 @@
import React, { useCallback, useEffect, useRef, useState } from 'react';
import { FlatList, Platform, View } from 'react-native';
import { Divider } from 'react-native-paper';
import { FlatList, Platform, Text, View } from 'react-native';
import { Divider, TouchableRipple } from 'react-native-paper';
import Button from '../../../base/ui/components/native/Button';
import Input from '../../../base/ui/components/native/Input';
@@ -52,7 +52,7 @@ const PollCreate = (props: AbstractProps) => {
* about whether a newly created input field has been rendered yet or not.
*/
const [ lastFocus, requestFocus ] = useState(null);
const { PRIMARY, SECONDARY, TERTIARY } = BUTTON_TYPES;
const { PRIMARY, SECONDARY } = BUTTON_TYPES;
useEffect(() => {
if (lastFocus === null) {
@@ -85,12 +85,13 @@ const PollCreate = (props: AbstractProps) => {
/* eslint-disable react/no-multi-comp */
const createRemoveOptionButton = onPress => (
<Button
labelKey = 'polls.create.removeOption'
labelStyle = { dialogStyles.optionRemoveButtonText }
onClick = { onPress }
style = { dialogStyles.optionRemoveButton }
type = { TERTIARY } />
<TouchableRipple
onPress = { onPress }
rippleColor = { 'transparent' } >
<Text style = { dialogStyles.optionRemoveButtonText }>
{ t('polls.create.removeOption') }
</Text>
</TouchableRipple>
);
@@ -119,8 +120,6 @@ const PollCreate = (props: AbstractProps) => {
);
const buttonRowStyles = Platform.OS === 'android'
? chatStyles.buttonRowAndroid : chatStyles.buttonRowIos;
const pollCreateButtonsContainerStyles = Platform.OS === 'android'
? chatStyles.pollCreateButtonsContainerAndroid : chatStyles.pollCreateButtonsContainerIos;
return (
<View style = { chatStyles.pollCreateContainer }>
@@ -144,7 +143,7 @@ const PollCreate = (props: AbstractProps) => {
keyExtractor = { (item, index) => index.toString() }
ref = { answerListRef }
renderItem = { renderListItem } />
<View style = { pollCreateButtonsContainerStyles }>
<View style = { chatStyles.pollCreateButtonsContainer }>
<Button
accessibilityLabel = 'polls.create.addOption'
disabled = { answers.length >= ANSWERS_LIMIT }

View File

@@ -1,12 +1,10 @@
// @flow
import React, { useCallback } from 'react';
import { FlatList, Text, View } from 'react-native';
import { FlatList, Text, TouchableOpacity, View } from 'react-native';
import { useSelector } from 'react-redux';
import { getLocalParticipant } from '../../../base/participants';
import Button from '../../../base/ui/components/native/Button';
import { BUTTON_TYPES } from '../../../base/ui/constants.native';
import AbstractPollResults from '../AbstractPollResults';
import type { AbstractProps, AnswerInfo } from '../AbstractPollResults';
@@ -103,24 +101,26 @@ const PollResults = (props: AbstractProps) => {
keyExtractor = { (item, index) => index.toString() }
renderItem = { answer => renderRow(answer.item) } />
<View style = { chatStyles.bottomLinks }>
<Button
labelKey = {
showDetails
? 'polls.results.hideDetailedResults'
: 'polls.results.showDetailedResults'
}
labelStyle = { chatStyles.toggleText }
onClick = { toggleIsDetailed }
type = { BUTTON_TYPES.TERTIARY } />
<Button
labelKey = {
haveVoted
? 'polls.results.changeVote'
: 'polls.results.vote'
}
labelStyle = { chatStyles.toggleText }
onClick = { changeVote }
type = { BUTTON_TYPES.TERTIARY } />
<TouchableOpacity onPress = { toggleIsDetailed }>
<Text
style = { chatStyles.toggleText }>
{
showDetails
? t('polls.results.hideDetailedResults')
: t('polls.results.showDetailedResults')
}
</Text>
</TouchableOpacity>
<TouchableOpacity onPress = { changeVote }>
<Text
style = { chatStyles.toggleText }>
{
haveVoted
? t('polls.results.changeVote')
: t('polls.results.vote')
}
</Text>
</TouchableOpacity>
</View>
</View>
);

View File

@@ -2,7 +2,6 @@
import { useNavigation } from '@react-navigation/native';
import React, { useEffect } from 'react';
import { Platform } from 'react-native';
import { useSelector } from 'react-redux';
import JitsiScreen from '../../../base/modal/components/JitsiScreen';
@@ -40,9 +39,6 @@ const PollsPane = (props: AbstractProps) => {
}, [ isPollsTabFocused, nbUnreadPolls ]);
const createPollButtonStyles = Platform.OS === 'android'
? chatStyles.createPollButtonAndroid : chatStyles.createPollButtonIos;
return (
<JitsiScreen
contentContainerStyle = { chatStyles.pollPane }
@@ -60,7 +56,7 @@ const PollsPane = (props: AbstractProps) => {
accessibilityLabel = 'polls.create.create'
labelKey = 'polls.create.create'
onClick = { onCreate }
style = { createPollButtonStyles }
style = { chatStyles.createPollButton }
type = { BUTTON_TYPES.PRIMARY } />
}
</JitsiScreen>

View File

@@ -13,14 +13,15 @@ export const dialogStyles = createStyleSheet({
questionText: {
...BaseTheme.typography.bodyShortBold,
color: BaseTheme.palette.text01,
marginLeft: BaseTheme.spacing[1]
marginBottom: BaseTheme.spacing[2],
marginLeft: BaseTheme.spacing[2]
},
questionOwnerText: {
...BaseTheme.typography.bodyShortBold,
color: BaseTheme.palette.text03,
marginBottom: BaseTheme.spacing[2],
marginLeft: BaseTheme.spacing[1]
marginLeft: BaseTheme.spacing[2]
},
optionContainer: {
@@ -29,11 +30,6 @@ export const dialogStyles = createStyleSheet({
marginHorizontal: BaseTheme.spacing[3]
},
optionRemoveButton: {
marginTop: BaseTheme.spacing[2],
width: 128
},
optionRemoveButtonText: {
color: BaseTheme.palette.actionDangerActive
},
@@ -86,7 +82,7 @@ export const resultsStyles = createStyleSheet({
},
answerContainer: {
marginHorizontal: BaseTheme.spacing[1],
marginHorizontal: BaseTheme.spacing[2],
marginVertical: BaseTheme.spacing[3],
maxWidth: '100%'
},
@@ -130,7 +126,7 @@ export const chatStyles = createStyleSheet({
},
pollItemContainer: {
backgroundColor: BaseTheme.palette.uiBackground,
backgroundColor: BaseTheme.palette.ui02,
borderColor: BaseTheme.palette.border05,
borderRadius: BaseTheme.shape.borderRadius,
boxShadow: BaseTheme.shape.boxShadow,
@@ -148,14 +144,14 @@ export const chatStyles = createStyleSheet({
marginTop: BaseTheme.spacing[3]
},
pollCreateButtonsContainerAndroid: {
marginBottom: BaseTheme.spacing[8],
marginHorizontal: BaseTheme.spacing[3]
pollCreateButtonsContainer: {
marginHorizontal: BaseTheme.spacing[3],
marginVertical: '8%'
},
pollCreateButtonsContainerIos: {
marginBottom: BaseTheme.spacing[5],
marginHorizontal: BaseTheme.spacing[3]
pollCreateButton: {
flex: 1,
marginHorizontal: BaseTheme.spacing[1]
},
pollSendLabel: {
@@ -169,22 +165,20 @@ export const chatStyles = createStyleSheet({
},
buttonRow: {
flexDirection: 'row',
justifyContent: 'center'
flexDirection: 'row'
},
buttonRowAndroid: {
flexDirection: 'row',
justifyContent: 'space-between'
marginBottom: BaseTheme.spacing[3]
},
buttonRowIos: {
flexDirection: 'row',
justifyContent: 'space-between'
flexDirection: 'row'
},
answerContent: {
marginBottom: BaseTheme.spacing[2]
paddingBottom: 8
},
switchRow: {
@@ -203,27 +197,19 @@ export const chatStyles = createStyleSheet({
marginVertical: BaseTheme.spacing[2]
},
pollCreateButton: {
marginHorizontal: BaseTheme.spacing[1],
width: 160
},
toggleText: {
color: BaseTheme.palette.action01
color: BaseTheme.palette.action01,
paddingTop: BaseTheme.spacing[3]
},
createPollButtonIos: {
marginHorizontal: 20,
marginVertical: BaseTheme.spacing[5]
},
createPollButtonAndroid: {
marginHorizontal: 20
createPollButton: {
marginHorizontal: BaseTheme.spacing[3],
marginVertical: 34
},
pollPane: {
flex: 1,
padding: BaseTheme.spacing[2]
padding: 8
},
pollPaneContainer: {
@@ -234,7 +220,7 @@ export const chatStyles = createStyleSheet({
bottomLinks: {
flexDirection: 'row',
justifyContent: 'space-between',
marginHorizontal: BaseTheme.spacing[1]
marginHorizontal: BaseTheme.spacing[2]
},
unreadPollsCounterContainer: {

View File

@@ -0,0 +1,95 @@
import React from 'react';
import { makeStyles } from 'tss-react/mui';
import Icon from '../../../base/icons/components/Icon';
interface IProps {
/**
* Attribute used in automated testing.
*/
dataTestId: string;
/**
* The button's icon.
*/
icon: Function;
/**
* The button's label.
*/
label: string;
/**
* Function to be called when button is clicked.
*/
onButtonClick: (e?: React.MouseEvent) => void;
/**
* Function to be called on key pressed.
*/
onKeyPressed: (e?: React.KeyboardEvent) => void;
}
const useStyles = makeStyles()(theme => {
return {
prejoinPreviewDropdownBtn: {
alignItems: 'center',
color: '#1C2025',
cursor: 'pointer',
display: 'flex',
height: 40,
fontSize: 15,
lineHeight: '24px',
padding: '0 16px', // @ts-ignore
backgroundColor: theme.palette.field02,
'&:hover': { // @ts-ignore
backgroundColor: theme.palette.field02Hover
}
},
prejoinPreviewDropdownIcon: {
display: 'inline-block',
marginRight: 16,
'& > svg': {
fill: '#1C2025'
}
}
};
});
/**
* Buttons used for pre meeting actions.
*
* @returns {ReactElement}
*/
const DropdownButton = ({
dataTestId,
icon,
onButtonClick,
onKeyPressed,
label
}: IProps) => {
const { classes } = useStyles();
return (
<div
className = { classes.prejoinPreviewDropdownBtn }
data-testid = { dataTestId }
onClick = { onButtonClick }
onKeyPress = { onKeyPressed }
role = 'button'
tabIndex = { 0 }>
<Icon
className = { classes.prejoinPreviewDropdownIcon }
color = '#1C2025'
size = { 24 }
src = { icon } />
{label}
</div>
);
};
export default DropdownButton;

View File

@@ -13,8 +13,6 @@ import { ActionButton, InputField, PreMeetingScreen } from '../../../base/premee
import { connect } from '../../../base/redux';
import { getDisplayName, updateSettings } from '../../../base/settings';
import { getLocalJitsiVideoTrack } from '../../../base/tracks';
import Button from '../../../base/ui/components/web/Button';
import { BUTTON_TYPES } from '../../../base/ui/constants.any';
import {
joinConference as joinConferenceAction,
joinConferenceWithoutAudio as joinConferenceWithoutAudioAction,
@@ -28,6 +26,7 @@ import {
isPrejoinDisplayNameVisible
} from '../../functions';
import DropdownButton from './DropdownButton';
import JoinByPhoneDialog from './dialogs/JoinByPhoneDialog';
type Props = {
@@ -57,11 +56,6 @@ type Props = {
*/
joinConferenceWithoutAudio: Function,
/**
* Whether conference join is in progress.
*/
joiningInProgress: boolean,
/**
* The name of the user that is about to join.
*/
@@ -120,6 +114,11 @@ type Props = {
type State = {
/**
* Flag controlling the visibility of the error label.
*/
showError: boolean,
/**
* Flag controlling the visibility of the 'join by phone' buttons.
*/
@@ -139,6 +138,7 @@ class Prejoin extends Component<Props, State> {
super(props);
this.state = {
showError: false,
showJoinByPhoneButtons: false
};
@@ -165,8 +165,14 @@ class Prejoin extends Component<Props, State> {
*/
_onJoinButtonClick() {
if (this.props.showErrorOnJoin) {
this.setState({
showError: true
});
return;
}
this.setState({ showError: false });
this.props.joinConference();
}
@@ -298,20 +304,20 @@ class Prejoin extends Component<Props, State> {
const noAudio = {
key: 'no-audio',
testId: 'prejoin.joinWithoutAudio',
dataTestId: 'prejoin.joinWithoutAudio',
icon: IconVolumeOff,
label: t('prejoin.joinWithoutAudio'),
onClick: joinConferenceWithoutAudio,
onKeyPress: this._onJoinConferenceWithoutAudioKeyPress
onButtonClick: joinConferenceWithoutAudio,
onKeyPressed: this._onJoinConferenceWithoutAudioKeyPress
};
const byPhone = {
key: 'by-phone',
testId: 'prejoin.joinByPhone',
dataTestId: 'prejoin.joinByPhone',
icon: IconPhoneRinging,
label: t('prejoin.joinAudioByPhone'),
onClick: this._showDialog,
onKeyPress: this._showDialogKeyPress
onButtonClick: this._showDialog,
onKeyPressed: this._showDialogKeyPress
};
return {
@@ -332,14 +338,12 @@ class Prejoin extends Component<Props, State> {
hasJoinByPhoneButton,
joinConference,
joinConferenceWithoutAudio,
joiningInProgress,
name,
participantId,
prejoinConfig,
readOnlyName,
showCameraPreview,
showDialog,
showErrorOnJoin,
t,
videoTrack
} = this.props;
@@ -355,7 +359,7 @@ class Prejoin extends Component<Props, State> {
extraButtonsToRender = extraButtonsToRender.filter((btn: Object) => btn.key !== 'by-phone');
}
const hasExtraJoinButtons = Boolean(extraButtonsToRender.length);
const { showJoinByPhoneButtons } = this.state;
const { showJoinByPhoneButtons, showError } = this.state;
return (
<PreMeetingScreen
@@ -369,8 +373,8 @@ class Prejoin extends Component<Props, State> {
{this.showDisplayNameField ? (<InputField
autoComplete = { 'name' }
autoFocus = { true }
className = { showErrorOnJoin ? 'error' : '' }
hasError = { showErrorOnJoin }
className = { showError ? 'error' : '' }
hasError = { showError }
onChange = { _setName }
onSubmit = { joinConference }
placeHolder = { t('dialog.enterDisplayName') }
@@ -387,7 +391,7 @@ class Prejoin extends Component<Props, State> {
</div>
)}
{showErrorOnJoin && <div
{showError && <div
className = 'prejoin-error'
data-testid = 'prejoin.errorMessage'>{t('prejoin.errorMissingName')}</div>}
@@ -395,11 +399,8 @@ class Prejoin extends Component<Props, State> {
<InlineDialog
content = { hasExtraJoinButtons && <div className = 'prejoin-preview-dropdown-btns'>
{extraButtonsToRender.map(({ key, ...rest }: Object) => (
<Button
disabled = { joiningInProgress }
fullWidth = { true }
<DropdownButton
key = { key }
type = { BUTTON_TYPES.SECONDARY }
{ ...rest } />
))}
</div> }
@@ -410,7 +411,6 @@ class Prejoin extends Component<Props, State> {
ariaDropDownLabel = { t('prejoin.joinWithoutAudio') }
ariaLabel = { t('prejoin.joinMeeting') }
ariaPressed = { showJoinByPhoneButtons }
disabled = { joiningInProgress }
hasOptions = { hasExtraJoinButtons }
onClick = { _onJoinButtonClick }
onKeyPress = { _onJoinKeyPress }
@@ -444,13 +444,11 @@ function mapStateToProps(state): Object {
const name = getDisplayName(state);
const showErrorOnJoin = isDisplayNameRequired(state) && !name;
const { id: participantId } = getLocalParticipant(state);
const { joiningInProgress } = state['features/prejoin'];
return {
canEditDisplayName: isPrejoinDisplayNameVisible(state),
deviceStatusVisible: isDeviceStatusVisible(state),
hasJoinByPhoneButton: isJoinByPhoneButtonVisible(state),
joiningInProgress,
name,
participantId,
prejoinConfig: state['features/base/config'].prejoinConfig,

View File

@@ -278,7 +278,7 @@ const LocalRecordingManager: ILocalRecordingManager = {
this.recordingData.push(e.data);
this.totalSize -= e.data.size;
if (this.totalSize <= 0) {
dispatch(stopLocalVideoRecording());
this.stopLocalRecording();
}
}
});

View File

@@ -61,6 +61,7 @@ export default {
savedPasswordContainer: {
flexDirection: 'row',
marginTop: 14,
width: 208
},
@@ -78,7 +79,8 @@ export default {
},
passwordSetupButtonLabel: {
color: BaseTheme.palette.link01
color: BaseTheme.palette.link01,
marginTop: BaseTheme.spacing[3]
},
passwordSetRemotelyContainer: {
@@ -88,10 +90,12 @@ export default {
},
passwordSetRemotelyText: {
color: BaseTheme.palette.text01
color: BaseTheme.palette.text01,
marginTop: BaseTheme.spacing[3]
},
passwordSetRemotelyTextDisabled: {
color: BaseTheme.palette.text02
color: BaseTheme.palette.text02,
marginTop: BaseTheme.spacing[3]
}
};

View File

@@ -0,0 +1,85 @@
/* eslint-disable lines-around-comment */
import React, { PureComponent } from 'react';
import { IReduxState } from '../../../app/types';
// @ts-ignore
import JitsiScreenWebView from '../../../base/modal/components/JitsiScreenWebView';
import { connect } from '../../../base/redux/functions';
// @ts-ignore
import { renderArrowBackButton }
// @ts-ignore
from '../../../mobile/navigation/components/welcome/functions';
// @ts-ignore
import styles from './styles';
const DEFAULT_HELP_CENTRE_URL = 'https://web-cdn.jitsi.net/faq/meet-faq.html';
interface IProps {
/**
* The URL to display in the Help Centre.
*/
_url: string;
/**
* Default prop for navigating between screen components(React Navigation).
*/
navigation: Object;
}
/**
* Implements a page that renders the help content for the app.
*/
class HelpView extends PureComponent<IProps> {
/**
* Implements React's {@link Component#componentDidMount()}. Invoked
* immediately after mounting occurs.
*
* @inheritdoc
* @returns {void}
*/
componentDidMount() {
const {
navigation
} = this.props;
// @ts-ignore
navigation.setOptions({
headerLeft: () =>
renderArrowBackButton(() =>
// @ts-ignore
navigation.goBack())
});
}
/**
* Implements {@code PureComponent#render()}.
*
* @inheritdoc
* @returns {ReactElement}
*/
render() {
return (
<JitsiScreenWebView
source = { this.props._url }
style = { styles.screenContainer } />
);
}
}
/**
* Maps part of the Redux state to the props of this component.
*
* @param {Object} state - The Redux state.
* @returns {IProps}
*/
function _mapStateToProps(state: IReduxState) {
return {
_url: state['features/base/config'].helpCentreURL || DEFAULT_HELP_CENTRE_URL
};
}
export default connect(_mapStateToProps)(HelpView);

View File

@@ -0,0 +1,48 @@
/* eslint-disable lines-around-comment */
import React, { useEffect } from 'react';
// @ts-ignore
import JitsiScreenWebView from '../../../base/modal/components/JitsiScreenWebView';
// @ts-ignore
import { renderArrowBackButton }
// @ts-ignore
from '../../../mobile/navigation/components/welcome/functions';
// @ts-ignore
import styles from './styles';
interface IProps {
/**
* Default prop for navigating between screen components(React Navigation).
*/
navigation: Object;
}
/**
* The URL at which the privacy policy is available to the user.
*/
const PRIVACY_URL = 'https://jitsi.org/meet/privacy';
const PrivacyView = ({ navigation }: IProps) => {
useEffect(() => {
// @ts-ignore
navigation.setOptions({
headerLeft: () =>
renderArrowBackButton(() =>
// @ts-ignore
navigation.goBack())
});
});
return (
<JitsiScreenWebView
source = { PRIVACY_URL }
style = { styles.screenContainer } />
);
};
export default PrivacyView;

View File

@@ -1,11 +1,11 @@
/* eslint-disable lines-around-comment */
import { Link } from '@react-navigation/native';
import _ from 'lodash';
import React, { Component } from 'react';
import { WithTranslation } from 'react-i18next';
import {
Alert,
Linking,
NativeModules,
Platform,
ScrollView,
@@ -14,7 +14,6 @@ import {
} from 'react-native';
import { Divider } from 'react-native-paper';
import { getDefaultURL } from '../../../app/functions.native';
import { IReduxState } from '../../../app/types';
// @ts-ignore
@@ -25,11 +24,10 @@ import JitsiScreen from '../../../base/modal/components/JitsiScreen';
import { getLocalParticipant } from '../../../base/participants/functions';
import { connect } from '../../../base/redux/functions';
import { updateSettings } from '../../../base/settings/actions';
import Button from '../../../base/ui/components/native/Button';
import Input from '../../../base/ui/components/native/Input';
import Switch from '../../../base/ui/components/native/Switch';
// @ts-ignore
import { BUTTON_TYPES } from '../../../base/ui/constants.any';
import { screen } from '../../../mobile/navigation/routes';
// @ts-ignore
import { AVATAR_SIZE } from '../../../welcome/components/styles';
import { isServerURLChangeEnabled, normalizeUserInputURL } from '../../functions.native';
@@ -46,18 +44,6 @@ import styles from './styles';
*/
const { AppInfo } = NativeModules;
/**
* The URL at which the terms (of service/use) are available to the user.
*/
const TERMS_URL = 'https://jitsi.org/meet/terms';
/**
* The URL at which the privacy policy is available to the user.
*/
const PRIVACY_URL = 'https://jitsi.org/meet/privacy';
const DEFAULT_HELP_CENTRE_URL = 'https://web-cdn.jitsi.net/faq/meet-faq.html';
interface IState {
@@ -118,13 +104,6 @@ interface IState {
*/
interface IProps extends WithTranslation {
/**
* The URL for when the help link.
*
* @protected
*/
_helpCentreUrl: string;
/**
* The ID of the local participant.
*/
@@ -246,9 +225,6 @@ class SettingsView extends Component<IProps, IState> {
this._onStartVideoMutedChange
= this._onStartVideoMutedChange.bind(this);
this._setURLFieldReference = this._setURLFieldReference.bind(this);
this._onShowHelpPressed = this._onShowHelpPressed.bind(this);
this._onShowPrivacyPressed = this._onShowPrivacyPressed.bind(this);
this._onShowTermsPressed = this._onShowTermsPressed.bind(this);
this._showURLAlert = this._showURLAlert.bind(this);
}
@@ -315,7 +291,6 @@ class SettingsView extends Component<IProps, IState> {
placeholder = { t('settingsView.displayNamePlaceholderText') }
textContentType = { 'name' } // iOS only
value = { displayName } />
{/* @ts-ignore */}
<Divider style = { styles.fieldSeparator } />
<Input
// @ts-ignore
@@ -342,7 +317,6 @@ class SettingsView extends Component<IProps, IState> {
placeholder = { this.props._serverURL }
textContentType = { 'URL' } // iOS only
value = { serverURL } />
{/* @ts-ignore */}
<Divider style = { styles.fieldSeparator } />
<FormRow label = 'settingsView.startCarModeInLowBandwidthMode'>
<Switch
@@ -350,7 +324,6 @@ class SettingsView extends Component<IProps, IState> {
// @ts-ignore
onChange = { this._onStartCarmodeInLowBandwidthMode } />
</FormRow>
{/* @ts-ignore */}
<Divider style = { styles.fieldSeparator } />
<FormRow
label = 'settingsView.startWithAudioMuted'>
@@ -359,7 +332,6 @@ class SettingsView extends Component<IProps, IState> {
// @ts-ignore
onChange = { this._onStartAudioMutedChange } />
</FormRow>
{/* @ts-ignore */}
<Divider style = { styles.fieldSeparator } />
<FormRow label = 'settingsView.startWithVideoMuted'>
<Switch
@@ -367,7 +339,6 @@ class SettingsView extends Component<IProps, IState> {
// @ts-ignore
onChange = { this._onStartVideoMutedChange } />
</FormRow>
{/* @ts-ignore */}
<Divider style = { styles.fieldSeparator } />
<FormRow label = 'videothumbnail.hideSelfView'>
<Switch
@@ -378,25 +349,26 @@ class SettingsView extends Component<IProps, IState> {
</FormSectionAccordion>
<FormSectionAccordion
label = 'settingsView.links'>
<Button
accessibilityLabel = 'settingsView.help'
labelKey = 'settingsView.help'
onClick = { this._onShowHelpPressed }
type = { BUTTON_TYPES.TERTIARY } />
{/* @ts-ignore */}
<Link
style = { styles.sectionLink }
// @ts-ignore
to = {{ screen: screen.settings.links.help }}>
{ t('settingsView.help') }
</Link>
<Divider style = { styles.fieldSeparator } />
<Button
accessibilityLabel = 'settingsView.terms'
labelKey = 'settingsView.terms'
onClick = { this._onShowTermsPressed }
type = { BUTTON_TYPES.TERTIARY } />
{/* @ts-ignore */}
<Link
style = { styles.sectionLink }
// @ts-ignore
to = {{ screen: screen.settings.links.terms }}>
{ t('settingsView.terms') }
</Link>
<Divider style = { styles.fieldSeparator } />
<Button
accessibilityLabel = 'settingsView.privacy'
labelKey = 'settingsView.privacy'
onClick = { this._onShowPrivacyPressed }
type = { BUTTON_TYPES.TERTIARY } />
<Link
style = { styles.sectionLink }
// @ts-ignore
to = {{ screen: screen.settings.links.privacy }}>
{ t('settingsView.privacy') }
</Link>
</FormSectionAccordion>
<FormSectionAccordion
label = 'settingsView.buildInfoSection'>
@@ -418,7 +390,6 @@ class SettingsView extends Component<IProps, IState> {
// @ts-ignore
onChange = { this._onDisableCallIntegration } />
</FormRow>
{/* @ts-ignore */}
<Divider style = { styles.fieldSeparator } />
</>
)}
@@ -429,7 +400,6 @@ class SettingsView extends Component<IProps, IState> {
// @ts-ignore
onChange = { this._onDisableP2P } />
</FormRow>
{/* @ts-ignore */}
<Divider style = { styles.fieldSeparator } />
{AppInfo.GOOGLE_SERVICES_ENABLED && (
<FormRow
@@ -698,33 +668,6 @@ class SettingsView extends Component<IProps, IState> {
);
}
/**
* Opens the help url into the browser.
*
* @returns {void}
*/
_onShowHelpPressed() {
Linking.openURL(this.props._helpCentreUrl);
}
/**
* Opens the privacy url into the browser.
*
* @returns {void}
*/
_onShowPrivacyPressed() {
Linking.openURL(PRIVACY_URL);
}
/**
* Opens the terms url into the browser.
*
* @returns {void}
*/
_onShowTermsPressed() {
Linking.openURL(TERMS_URL);
}
/**
* Shows an alert warning the user about disabling crash reporting.
*
@@ -789,7 +732,6 @@ function _mapStateToProps(state: IReduxState) {
const localParticipant = getLocalParticipant(state);
return {
_helpCentreUrl: state['features/base/config'].helpCentreURL || DEFAULT_HELP_CENTRE_URL,
_localParticipantId: localParticipant?.id,
_serverURL: getDefaultURL(state),
_serverURLChangeEnabled: isServerURLChangeEnabled(state),

View File

@@ -0,0 +1,48 @@
/* eslint-disable lines-around-comment */
import React, { useEffect } from 'react';
// @ts-ignore
import JitsiScreenWebView from '../../../base/modal/components/JitsiScreenWebView';
// @ts-ignore
import { renderArrowBackButton }
// @ts-ignore
from '../../../mobile/navigation/components/welcome/functions';
// @ts-ignore
import styles from './styles';
interface IProps {
/**
* Default prop for navigating between screen components(React Navigation).
*/
navigation: Object;
}
/**
* The URL at which the terms (of service/use) are available to the user.
*/
const TERMS_URL = 'https://jitsi.org/meet/terms';
const TermsView = ({ navigation }: IProps) => {
useEffect(() => {
// @ts-ignore
navigation.setOptions({
headerLeft: () =>
renderArrowBackButton(() =>
// @ts-ignore
navigation.goBack())
});
});
return (
<JitsiScreenWebView
source = { TERMS_URL }
style = { styles.screenContainer } />
);
};
export default TermsView;

View File

@@ -109,6 +109,23 @@ export default {
fontSize: 14
},
sectionLink: {
...BaseTheme.typography.bodyShortBoldLarge,
color: BaseTheme.palette.link01,
margin: BaseTheme.spacing[3],
textAlign: 'center'
},
sectionLinkContainer: {
margin: BaseTheme.spacing[3]
},
sectionLinkText: {
...BaseTheme.typography.bodyShortBoldLarge,
color: BaseTheme.palette.link01,
textAlign: 'center'
},
/**
* Global {@code Text} color for the components.
*/

View File

@@ -21,13 +21,3 @@ export const BEGIN_SHARE_ROOM = 'BEGIN_SHARE_ROOM';
* }
*/
export const END_SHARE_ROOM = 'END_SHARE_ROOM';
/**
* The type of (redux) action which toggles the share meeting url dialog visibility.
*
* {
* type: TOGGLE_SHARE_DIALOG,
* visible: boolean
* }
*/
export const TOGGLE_SHARE_DIALOG = 'TOGGLE_SHARE_DIALOG';

View File

@@ -1,11 +1,7 @@
import { IStore } from '../app/types';
import { getInviteURL } from '../base/connection/functions';
import {
BEGIN_SHARE_ROOM,
END_SHARE_ROOM,
TOGGLE_SHARE_DIALOG
} from './actionTypes';
import { BEGIN_SHARE_ROOM, END_SHARE_ROOM } from './actionTypes';
/**
* Begins the UI procedure to share the URL for the current conference/room.
@@ -20,8 +16,7 @@ export function beginShareRoom(roomURL?: string) {
// eslint-disable-next-line no-param-reassign
roomURL = getInviteURL(getState);
}
dispatch({
roomURL && dispatch({
type: BEGIN_SHARE_ROOM,
roomURL
});
@@ -48,22 +43,3 @@ export function endShareRoom(roomURL: string, shared: boolean) {
shared
};
}
/**
* UI procedure for sharing conference room URL inside a dialog.
*
* @param {boolean} visible - True if share dialog is visible; false,
* otherwise.
* @public
* @returns {{
* type: TOGGLE_SHARE_DIALOG,
* visible: boolean
* }}
*/
export function toggleShareDialog(visible: boolean) {
return {
type: TOGGLE_SHARE_DIALOG,
visible
};
}

View File

@@ -1,18 +0,0 @@
import { IReduxState } from '../app/types';
import BaseTheme from '../base/ui/components/BaseTheme.native';
/**
* Control for invite others button enabling.
*
* @param {IReduxState} state - State object.
* @returns {Object}
*/
export function getInviteOthersControl(state: IReduxState) {
const { shareDialogVisible } = state['features/share-room'];
const { icon01, icon03 } = BaseTheme.palette;
return {
color: shareDialogVisible ? icon03 : icon01,
shareDialogVisible
};
}

View File

@@ -6,7 +6,7 @@ import MiddlewareRegistry from '../base/redux/MiddlewareRegistry';
import { getShareInfoText } from '../invite/functions';
import { BEGIN_SHARE_ROOM } from './actionTypes';
import { endShareRoom, toggleShareDialog } from './actions';
import { endShareRoom } from './actions';
import logger from './logger';
/**
@@ -53,10 +53,8 @@ function _shareRoom(roomURL: string, { dispatch, getState }: IStore) {
.then(
/* onFulfilled */ value => {
onFulfilled(value.action === Share.sharedAction);
dispatch(toggleShareDialog(false));
},
/* onRejected */ reason => {
dispatch(toggleShareDialog(false));
logger.error(
`Failed to share conference/room URL ${roomURL}:`,
reason);

View File

@@ -1,23 +0,0 @@
import ReducerRegistry from '../base/redux/ReducerRegistry';
import { TOGGLE_SHARE_DIALOG } from './actionTypes';
const DEFAULT_STATE = {
shareDialogVisible: false
};
export interface IShareRoomState {
shareDialogVisible: boolean;
}
ReducerRegistry.register<IShareRoomState>('features/share-room', (state = DEFAULT_STATE, action): IShareRoomState => {
switch (action.type) {
case TOGGLE_SHARE_DIALOG:
return {
...state,
shareDialogVisible: action.visible
};
}
return state;
});

View File

@@ -5,7 +5,7 @@ import { sendAnalytics } from '../analytics/functions';
import { IStore } from '../app/types';
import { setAudioOnly } from '../base/audio-only/actions';
import { setVideoMuted } from '../base/media/actions';
import { VIDEO_MUTISM_AUTHORITY } from '../base/media/constants';
import { MEDIA_TYPE, VIDEO_MUTISM_AUTHORITY } from '../base/media/constants';
import {
SET_TOOLBOX_ENABLED,
@@ -96,6 +96,7 @@ export function handleToggleVideoMuted(muted: boolean, showUI: boolean, ensureTr
dispatch(
setVideoMuted(
muted,
MEDIA_TYPE.VIDEO,
VIDEO_MUTISM_AUTHORITY.USER,
ensureTrack));

View File

@@ -1,3 +1,15 @@
/**
* The type of the action which sets the list of known remote participant IDs which
* have an active screen share.
*
* @returns {{
* type: SCREEN_SHARE_REMOTE_PARTICIPANTS_UPDATED,
* participantIds: Array<string>
* }}
*/
export const SCREEN_SHARE_REMOTE_PARTICIPANTS_UPDATED
= 'SCREEN_SHARE_REMOTE_PARTICIPANTS_UPDATED';
/**
* The type of the action which tells whether we are in carmode.
*

View File

@@ -1,11 +1,30 @@
import { IStore } from '../app/types';
import {
SCREEN_SHARE_REMOTE_PARTICIPANTS_UPDATED,
SET_TILE_VIEW,
VIRTUAL_SCREENSHARE_REMOTE_PARTICIPANTS_UPDATED
} from './actionTypes';
import { shouldDisplayTileView } from './functions';
/**
* Creates a (redux) action which signals that the list of known remote participants
* with screen shares has changed.
*
* @param {string} participantIds - The remote participants which currently have active
* screen share streams.
* @returns {{
* type: SCREEN_SHARE_REMOTE_PARTICIPANTS_UPDATED,
* participantId: string
* }}
*/
export function setRemoteParticipantsWithScreenShare(participantIds: Array<string>) {
return {
type: SCREEN_SHARE_REMOTE_PARTICIPANTS_UPDATED,
participantIds
};
}
/**
* Creates a (redux) action which signals that the list of known remote virtual screen share participant ids has
* changed.

View File

@@ -1,16 +1,18 @@
import { IStore } from '../app/types';
import { getCurrentConference } from '../base/conference/functions';
import { VIDEO_TYPE } from '../base/media/constants';
import { PARTICIPANT_LEFT, PIN_PARTICIPANT } from '../base/participants/actionTypes';
import { pinParticipant } from '../base/participants/actions';
import { getParticipantById, getPinnedParticipant } from '../base/participants/functions';
import MiddlewareRegistry from '../base/redux/MiddlewareRegistry';
import StateListenerRegistry from '../base/redux/StateListenerRegistry';
import { TRACK_REMOVED } from '../base/tracks/actionTypes';
import { SET_DOCUMENT_EDITING_STATUS } from '../etherpad/actionTypes';
import { isStageFilmstripEnabled } from '../filmstrip/functions';
import { isFollowMeActive } from '../follow-me/functions';
import { SET_TILE_VIEW } from './actionTypes';
import { setTileView } from './actions';
import { setRemoteParticipantsWithScreenShare, setTileView } from './actions';
import { getAutoPinSetting, updateAutoPinnedParticipant } from './functions';
import './subscriber';
@@ -72,6 +74,31 @@ MiddlewareRegistry.register(store => next => action => {
}
break;
}
// Update the remoteScreenShares.
// Because of the debounce in the subscriber which updates the remoteScreenShares we need to handle
// removal of screen shares separately here. Otherwise it is possible to have screen sharing
// participant that has already left in the remoteScreenShares array. This can lead to rendering
// a thumbnails for already left participants since the remoteScreenShares array is used for
// building the ordered list of remote participants.
case TRACK_REMOVED: {
const { jitsiTrack } = action.track;
if (jitsiTrack?.isVideoTrack() && jitsiTrack?.getVideoType() === VIDEO_TYPE.DESKTOP) {
const participantId = jitsiTrack.getParticipantId();
const oldScreenShares = store.getState()['features/video-layout'].remoteScreenShares || [];
const newScreenShares = oldScreenShares.filter(id => id !== participantId);
if (oldScreenShares.length !== newScreenShares.length) { // the participant was removed
store.dispatch(setRemoteParticipantsWithScreenShare(newScreenShares));
updateAutoPinnedParticipant(oldScreenShares, store);
}
}
break;
}
}
if (shouldUpdateAutoPin) {

View File

@@ -1,5 +1,5 @@
import { setVideoMuted } from '../base/media/actions';
import { VIDEO_MUTISM_AUTHORITY } from '../base/media/constants';
import { MEDIA_TYPE, VIDEO_MUTISM_AUTHORITY } from '../base/media/constants';
import MiddlewareRegistry from '../base/redux/MiddlewareRegistry';
import { CLIENT_RESIZED } from '../base/responsive-ui/actionTypes';
import { setLargeVideoDimensions } from '../large-video/actions.any';
@@ -19,7 +19,7 @@ MiddlewareRegistry.register(store => next => action => {
switch (action.type) {
case SET_CAR_MODE:
dispatch(setVideoMuted(action.enabled, VIDEO_MUTISM_AUTHORITY.CAR_MODE));
dispatch(setVideoMuted(action.enabled, MEDIA_TYPE.VIDEO, VIDEO_MUTISM_AUTHORITY.CAR_MODE));
break;
case CLIENT_RESIZED: {
const { clientHeight, clientWidth } = store.getState()['features/base/responsive-ui'];

View File

@@ -1,6 +1,7 @@
import ReducerRegistry from '../base/redux/ReducerRegistry';
import {
SCREEN_SHARE_REMOTE_PARTICIPANTS_UPDATED,
SET_CAR_MODE,
SET_TILE_VIEW,
VIRTUAL_SCREENSHARE_REMOTE_PARTICIPANTS_UPDATED
@@ -40,6 +41,7 @@ const STORE_NAME = 'features/video-layout';
ReducerRegistry.register<IVideoLayoutState>(STORE_NAME, (state = DEFAULT_STATE, action): IVideoLayoutState => {
switch (action.type) {
case SCREEN_SHARE_REMOTE_PARTICIPANTS_UPDATED:
case VIRTUAL_SCREENSHARE_REMOTE_PARTICIPANTS_UPDATED:
return {
...state,

View File

@@ -52,7 +52,7 @@ export function muteLocal(enable: boolean, mediaType: MediaType, stopScreenShari
sendAnalytics(createToolbarEvent(isAudio ? AUDIO_MUTE : VIDEO_MUTE, { enable }));
dispatch(isAudio ? setAudioMuted(enable, /* ensureTrack */ true)
: setVideoMuted(enable, VIDEO_MUTISM_AUTHORITY.USER, /* ensureTrack */ true));
: setVideoMuted(enable, mediaType, VIDEO_MUTISM_AUTHORITY.USER, /* ensureTrack */ true));
// FIXME: The old conference logic still relies on this event being emitted.
typeof APP === 'undefined'

View File

@@ -6,7 +6,6 @@ import type { Dispatch } from 'redux';
import { createWelcomePageEvent, sendAnalytics } from '../../analytics';
import { appNavigate } from '../../app/actions';
import { IDeeplinkingConfig } from '../../base/config/configType';
import isInsecureRoomName from '../../base/util/isInsecureRoomName';
import { isCalendarEnabled } from '../../calendar-sync';
import { isRecentListEnabled } from '../../recent-list/functions';
@@ -21,11 +20,6 @@ export type Props = {
*/
_calendarEnabled: boolean,
/**
* The deeplinking config.
*/
_deeplinkingCfg: IDeeplinkingConfig,
/**
* Whether the insecure room name functionality is enabled or not.
*/
@@ -274,7 +268,6 @@ export class AbstractWelcomePage<P: Props> extends Component<P, *> {
export function _mapStateToProps(state: Object) {
return {
_calendarEnabled: isCalendarEnabled(state),
_deeplinkingCfg: state['features/base/config'].deeplinking || {},
_enableInsecureRoomNameWarning: state['features/base/config'].enableInsecureRoomNameWarning || false,
_moderatedRoomServiceUrl: state['features/base/config'].moderatedRoomServiceUrl,
_recentListEnabled: isRecentListEnabled(),

View File

@@ -184,27 +184,24 @@ class WelcomePage extends AbstractWelcomePage {
<div
className = { `welcome ${contentClassName} ${footerClassName}` }
id = 'welcome_page'>
<div className = 'welcome-watermark'>
<Watermarks defaultJitsiLogoURL = { DEFAULT_WELCOME_PAGE_LOGO_URL } />
</div>
<div className = 'header'>
<div className = 'welcome-page-settings'>
<SettingsButton
defaultTab = { SETTINGS_TABS.CALENDAR }
isDisplayedOnWelcomePage = { true } />
{ showAdditionalToolbarContent
? <div
className = 'settings-toolbar-content'
ref = { this._setAdditionalToolbarContentRef } />
: null
}
</div>
<div className = 'header-image' />
<div className = 'header-container'>
<div className = 'header-watermark-container'>
<div className = 'welcome-watermark'>
<Watermarks
defaultJitsiLogoURL = { DEFAULT_WELCOME_PAGE_LOGO_URL }
noMargins = { true } />
</div>
</div>
<div className = 'welcome-page-settings'>
<SettingsButton
defaultTab = { SETTINGS_TABS.CALENDAR }
isDisplayedOnWelcomePage = { true } />
{ showAdditionalToolbarContent
? <div
className = 'settings-toolbar-content'
ref = { this._setAdditionalToolbarContentRef } />
: null
}
</div>
<h1 className = 'header-text-title'>
{ t('welcomepage.headerTitle') }
</h1>
@@ -249,16 +246,18 @@ class WelcomePage extends AbstractWelcomePage {
{ _moderatedRoomServiceUrl && (
<div id = 'moderated-meetings'>
{
translateToHTML(
t, 'welcomepage.moderatedMessage', { url: _moderatedRoomServiceUrl })
}
<p>
{
translateToHTML(
t, 'welcomepage.moderatedMessage', { url: _moderatedRoomServiceUrl })
}
</p>
</div>)}
</div>
</div>
<div className = 'welcome-cards-container'>
<div className = 'welcome-card-column'>
<div className = 'welcome-card-row'>
<div className = 'welcome-tabs welcome-card welcome-card--blue'>
{ this._renderTabs() }
</div>
@@ -344,17 +343,12 @@ class WelcomePage extends AbstractWelcomePage {
* @returns {ReactElement}
*/
_renderFooter() {
const { t } = this.props;
const {
t,
_deeplinkingCfg: {
ios = {},
android = {}
}
} = this.props;
const { downloadLink: iosDownloadLink } = ios;
const { fDroidUrl, downloadLink: androidDownloadLink } = android;
MOBILE_DOWNLOAD_LINK_ANDROID,
MOBILE_DOWNLOAD_LINK_F_DROID,
MOBILE_DOWNLOAD_LINK_IOS
} = interfaceConfig;
return (<footer className = 'welcome-footer'>
<div className = 'welcome-footer-centered'>
@@ -363,21 +357,21 @@ class WelcomePage extends AbstractWelcomePage {
<div className = 'welcome-footer-row-1-text'>{t('welcomepage.jitsiOnMobile')}</div>
<a
className = 'welcome-badge'
href = { iosDownloadLink }>
href = { MOBILE_DOWNLOAD_LINK_IOS }>
<img
alt = { t('welcomepage.mobileDownLoadLinkIos') }
src = './images/app-store-badge.png' />
</a>
<a
className = 'welcome-badge'
href = { androidDownloadLink }>
href = { MOBILE_DOWNLOAD_LINK_ANDROID }>
<img
alt = { t('welcomepage.mobileDownLoadLinkAndroid') }
src = './images/google-play-badge.png' />
</a>
<a
className = 'welcome-badge'
href = { fDroidUrl }>
href = { MOBILE_DOWNLOAD_LINK_F_DROID }>
<img
alt = { t('welcomepage.mobileDownLoadLinkFDroid') }
src = './images/f-droid-badge.png' />
@@ -405,14 +399,14 @@ class WelcomePage extends AbstractWelcomePage {
if (_calendarEnabled) {
tabs.push({
label: t('welcomepage.upcomingMeetings'),
label: t('welcomepage.calendar'),
content: <CalendarList />
});
}
if (_recentListEnabled) {
tabs.push({
label: t('welcomepage.recentMeetings'),
label: t('welcomepage.recentList'),
content: <RecentList />
});
}

View File

@@ -21,9 +21,6 @@ local proxy_listener = { default_port = nil, default_mode = "*a", default_interf
function proxy_listener.onconnect(conn)
local session = sessions[conn];
-- needed in mod_rate_limit
session.ip = conn:ip();
-- Now the real s2s listener can take over the connection.
local listener = portmanager.get_service("s2s").listener;

View File

@@ -5,6 +5,7 @@ local log = module._log;
local host = module.host;
local st = require "util.stanza";
local um_is_admin = require "core.usermanager".is_admin;
local jid_split = require "util.jid".split;
local function is_admin(jid)
@@ -39,8 +40,11 @@ log("debug",
-- option to disable room modification (sending muc config form) for guest that do not provide token
local require_token_for_moderation;
-- option to not require tokens for certain users and domains
local token_empty_allow_list;
local function load_config()
require_token_for_moderation = module:get_option_boolean("token_verification_require_token_for_moderation");
token_empty_allow_list = module:get_option_set("token_verification_empty_allow_list");
end
load_config();
@@ -57,6 +61,19 @@ local function verify_user(session, stanza)
return true;
end
-- if token is empty and user matches allow list, skip verification and allow user to join
local user, domain, res = jid_split(user_jid);
if session.auth_token == nil and user ~= nil and domain ~= nil and token_empty_allow_list then
if token_empty_allow_list:contains(domain) then
log("debug", "Token not required from user: %s in allowed domain: %s", user_jid, domain);
return true;
end
if token_empty_allow_list:contains(user..'@'..domain) then
log("debug", "Token not required from user in allowed list: %s", user_jid);
return true;
end
end
log("debug",
"Will verify token for user: %s, room: %s ", user_jid, stanza.attr.to);
if not token_util:verify_room(session, stanza.attr.to) then

View File

@@ -10,14 +10,13 @@ if [ -z "${DOMAIN}" ] || [ -z "${EMAIL}" ]; then
exit 1
fi
JITSI_INSTALLATION="DEBIAN"
JAAS_ENDPOINT="https://account-provisioning.cloudflare.jitsi.net/operations"
CHALLENGE_FILE="/usr/share/jitsi-meet/.well-known/jitsi-challenge.txt"
SUPPORT_MSG="Reach out to JaaS support or retry with /usr/share/jitsi-meet/scripts/register-jaas-account.sh"
create_error=0
create_data=$(curl -s -f -X 'POST' "${JAAS_ENDPOINT}" -H 'Content-Type: application/json' -H 'accept: */*' \
-d "{ \"domain\": \"${DOMAIN}\", \"email\": \"${EMAIL}\", \"jitsiInstallation\": \"${JITSI_INSTALLATION}\" }") || create_error=$?
-d "{ \"domain\": \"${DOMAIN}\", \"email\": \"${EMAIL}\" }") || create_error=$?
if [ ${create_error} -ne 0 ]; then
echo "Account creation failed. Status: ${create_error}, response: ${create_data}"
exit 2