mirror of
https://gitcode.com/GitHub_Trending/ji/jitsi-meet.git
synced 2026-09-13 21:58:51 +00:00
Compare commits
1 Commits
6916
...
token-veri
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a49b6140e0 |
7
.github/workflows/ci.yml
vendored
7
.github/workflows/ci.yml
vendored
@@ -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
|
||||
|
||||
@@ -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>
|
||||
@@ -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>
|
||||
@@ -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>
|
||||
@@ -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 {
|
||||
|
||||
@@ -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(),
|
||||
|
||||
141
conference.js
141
conference.js
@@ -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(() => {
|
||||
|
||||
87
config.js
87
config.js
@@ -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,
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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%;
|
||||
|
||||
7
debian/jitsi-meet-prosody.postinst
vendored
7
debian/jitsi-meet-prosody.postinst
vendored
@@ -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
|
||||
|
||||
6
debian/jitsi-meet-prosody.templates
vendored
6
debian/jitsi-meet-prosody.templates
vendored
@@ -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:
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
509
package-lock.json
generated
@@ -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",
|
||||
|
||||
23
package.json
23
package.json
@@ -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",
|
||||
|
||||
13
patches/react-native-gesture-handler+2.1.0.patch
Normal file
13
patches/react-native-gesture-handler+2.1.0.patch
Normal 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
|
||||
}
|
||||
@@ -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';
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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}`;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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',
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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';
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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 };
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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
|
||||
});
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -23,7 +23,7 @@ export default StyleSheet.create({
|
||||
|
||||
videoTransformedViewContainerWide: {
|
||||
overflow: 'hidden',
|
||||
paddingRight: '16%'
|
||||
paddingRight: '14%'
|
||||
},
|
||||
|
||||
/**
|
||||
|
||||
@@ -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));
|
||||
|
||||
29
react/features/base/modal/components/JitsiScreenWebView.js
Normal file
29
react/features/base/modal/components/JitsiScreenWebView.js
Normal 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;
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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 }
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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'];
|
||||
|
||||
@@ -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: {
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -55,7 +55,6 @@ export default {
|
||||
buttonLabelTertiary: {
|
||||
...buttonLabel,
|
||||
color: BaseTheme.palette.text01,
|
||||
margin: BaseTheme.spacing[3],
|
||||
textAlign: 'center'
|
||||
},
|
||||
|
||||
|
||||
@@ -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.
|
||||
*/
|
||||
|
||||
@@ -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' }>
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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
|
||||
};
|
||||
}
|
||||
@@ -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));
|
||||
|
||||
@@ -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
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
};
|
||||
|
||||
@@ -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'
|
||||
}
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -183,7 +183,6 @@ const ConferenceNavigationContainer = () => {
|
||||
name = { screen.settings.main }
|
||||
options = { settingsNavigationContainerScreenOptions } />
|
||||
<ConferenceStack.Screen
|
||||
// @ts-ignore
|
||||
component = { CarMode }
|
||||
name = { screen.conference.carmode }
|
||||
options = {{
|
||||
|
||||
@@ -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>
|
||||
);
|
||||
|
||||
@@ -26,6 +26,14 @@ export const fullScreenOptions = {
|
||||
headerShown: false
|
||||
};
|
||||
|
||||
export const linkScreenOptions = {
|
||||
gestureEnabled: true,
|
||||
headerShown: true,
|
||||
headerTitleStyle: {
|
||||
color: BaseTheme.palette.text01
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Navigation container theme.
|
||||
*/
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
};
|
||||
}
|
||||
|
||||
@@ -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 }
|
||||
|
||||
@@ -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>
|
||||
);
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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: {
|
||||
|
||||
95
react/features/prejoin/components/web/DropdownButton.tsx
Normal file
95
react/features/prejoin/components/web/DropdownButton.tsx
Normal 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;
|
||||
@@ -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,
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
@@ -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]
|
||||
}
|
||||
};
|
||||
|
||||
85
react/features/settings/components/native/HelpView.tsx
Normal file
85
react/features/settings/components/native/HelpView.tsx
Normal 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);
|
||||
48
react/features/settings/components/native/PrivacyView.tsx
Normal file
48
react/features/settings/components/native/PrivacyView.tsx
Normal 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;
|
||||
@@ -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),
|
||||
|
||||
48
react/features/settings/components/native/TermsView.tsx
Normal file
48
react/features/settings/components/native/TermsView.tsx
Normal 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;
|
||||
@@ -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.
|
||||
*/
|
||||
|
||||
@@ -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';
|
||||
|
||||
@@ -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
|
||||
};
|
||||
}
|
||||
|
||||
@@ -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
|
||||
};
|
||||
}
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
});
|
||||
@@ -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));
|
||||
|
||||
|
||||
@@ -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.
|
||||
*
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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'];
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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'
|
||||
|
||||
@@ -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(),
|
||||
|
||||
@@ -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 />
|
||||
});
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user