mirror of
https://gitcode.com/GitHub_Trending/ji/jitsi-meet.git
synced 2026-01-03 05:12:27 +00:00
Compare commits
163 Commits
android-sd
...
fix_analyt
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a403a221ae | ||
|
|
3a836eba63 | ||
|
|
55a16f31c2 | ||
|
|
7de88f4e47 | ||
|
|
d71b827d1a | ||
|
|
3811caa8a0 | ||
|
|
32f6bc376b | ||
|
|
8b4ebe4fa3 | ||
|
|
45415ef8da | ||
|
|
99bba14628 | ||
|
|
8b8b2568e2 | ||
|
|
ca144e127c | ||
|
|
965760df41 | ||
|
|
6ab25f7bc0 | ||
|
|
701ae5b2b1 | ||
|
|
b2d6ee06df | ||
|
|
18f5bdeaf8 | ||
|
|
dd6ce33296 | ||
|
|
5a7a6bf59c | ||
|
|
20d8a403f3 | ||
|
|
0bce8e185d | ||
|
|
7f21075613 | ||
|
|
e833860fcb | ||
|
|
376b17e011 | ||
|
|
87541a63d3 | ||
|
|
109b83d6f1 | ||
|
|
3a1fc363ed | ||
|
|
71658a5de6 | ||
|
|
40ac57a5d4 | ||
|
|
a20bf845ea | ||
|
|
95943b725c | ||
|
|
0813ae0f3c | ||
|
|
a33e34c309 | ||
|
|
821cc11364 | ||
|
|
caf7df4a82 | ||
|
|
bda39ef876 | ||
|
|
9e2ed855eb | ||
|
|
3be453e76a | ||
|
|
dec54692c1 | ||
|
|
e77d19b128 | ||
|
|
a83bf98625 | ||
|
|
3307365885 | ||
|
|
341fc774a6 | ||
|
|
56673f14b5 | ||
|
|
ab08eb2f99 | ||
|
|
000458697d | ||
|
|
b0c56d8963 | ||
|
|
0ecd65777e | ||
|
|
6d02f50d09 | ||
|
|
a71143891e | ||
|
|
6fda5924a3 | ||
|
|
b09574f62f | ||
|
|
8cdde88049 | ||
|
|
9cd42b988d | ||
|
|
8b559ad4f2 | ||
|
|
192fce8740 | ||
|
|
235016d7cf | ||
|
|
27792b0be4 | ||
|
|
765fd7d766 | ||
|
|
d49a5097f0 | ||
|
|
cfcc3fdbbe | ||
|
|
fdbceb0e42 | ||
|
|
89197cbdb2 | ||
|
|
f067f07d64 | ||
|
|
4594a978e0 | ||
|
|
fcddccf018 | ||
|
|
7a9285b326 | ||
|
|
11f0ab9226 | ||
|
|
0b6705610c | ||
|
|
9d9199ba3b | ||
|
|
ff656a0625 | ||
|
|
148fc103e3 | ||
|
|
77abbee308 | ||
|
|
83c4ce98b4 | ||
|
|
898741e40d | ||
|
|
0c3e7395e7 | ||
|
|
c530bdd107 | ||
|
|
29dbcb309d | ||
|
|
8a4990d9ae | ||
|
|
0e55cbbda6 | ||
|
|
6da94aecf2 | ||
|
|
2a3c962e88 | ||
|
|
34f1eb60f4 | ||
|
|
4115ebe856 | ||
|
|
d7dadfc157 | ||
|
|
2851eeeab3 | ||
|
|
84d75f2ae8 | ||
|
|
73b3309adf | ||
|
|
e2de06f60d | ||
|
|
cdc7962d11 | ||
|
|
59242e1217 | ||
|
|
631e39d4fd | ||
|
|
4290cdf53d | ||
|
|
84c1e20216 | ||
|
|
e6caeb86b0 | ||
|
|
5854e38a09 | ||
|
|
3e9ee9451f | ||
|
|
29d02f0a2b | ||
|
|
c780f9bbba | ||
|
|
d5a0bac0a3 | ||
|
|
f0187cc0f8 | ||
|
|
4708d894cc | ||
|
|
f38d120406 | ||
|
|
53960baf76 | ||
|
|
a0f061aa6f | ||
|
|
f2fb525d0a | ||
|
|
5a59bee597 | ||
|
|
07b903d887 | ||
|
|
1a39315001 | ||
|
|
97e5f00dae | ||
|
|
bae77f21f8 | ||
|
|
24d788f333 | ||
|
|
c4d553c605 | ||
|
|
fa64e2e67c | ||
|
|
94c29180e4 | ||
|
|
b864d91572 | ||
|
|
2006182a2a | ||
|
|
8fc3de416c | ||
|
|
4c5787511e | ||
|
|
8a2e4bc628 | ||
|
|
f78ebbb9a9 | ||
|
|
4cc4c25691 | ||
|
|
d02c7dc3a7 | ||
|
|
8741ee771e | ||
|
|
006e8463cd | ||
|
|
86e295e9bc | ||
|
|
07bade2557 | ||
|
|
0becc890d8 | ||
|
|
a1ce6f1ce5 | ||
|
|
43a7d00c63 | ||
|
|
9c04ba767c | ||
|
|
7e1d10fb4d | ||
|
|
4ce2280e31 | ||
|
|
2918a89d35 | ||
|
|
8f1c83edfd | ||
|
|
106452d857 | ||
|
|
a4d3fb6c70 | ||
|
|
a7af01b9e3 | ||
|
|
f7f434ab55 | ||
|
|
09c0854779 | ||
|
|
b4d12d74f7 | ||
|
|
50b064907a | ||
|
|
b9d6a0f269 | ||
|
|
2414e57260 | ||
|
|
6c41ddb622 | ||
|
|
55e75d56fd | ||
|
|
32ac299422 | ||
|
|
cb7146f954 | ||
|
|
144c1ce4f4 | ||
|
|
2102d6eda1 | ||
|
|
1f8e3fe26f | ||
|
|
8b0285a9d7 | ||
|
|
b546d01c2d | ||
|
|
7bf3e7df1d | ||
|
|
f9ac965e18 | ||
|
|
d70412166c | ||
|
|
a843406cb0 | ||
|
|
58115477a2 | ||
|
|
e1dc573c3c | ||
|
|
c025102511 | ||
|
|
54d052de73 | ||
|
|
7e633f0136 | ||
|
|
4b4bc1c823 |
14
.github/workflows/ci.yml
vendored
14
.github/workflows/ci.yml
vendored
@@ -74,3 +74,17 @@ jobs:
|
||||
cache: 'npm'
|
||||
- run: npm install
|
||||
- run: npx react-native bundle --entry-file react/index.native.js --platform ios --bundle-output /tmp/ios.bundle --reset-cache
|
||||
debian-build:
|
||||
name: Test Debian packages build
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: 16
|
||||
cache: 'npm'
|
||||
- run: npm install
|
||||
- run: make
|
||||
- run: sudo apt-get install -y debhelper
|
||||
- run: dpkg-buildpackage -A -rfakeroot -us -uc -d
|
||||
- run: make source-package
|
||||
|
||||
4
.gitignore
vendored
4
.gitignore
vendored
@@ -99,6 +99,10 @@ tsconfig.json
|
||||
#
|
||||
react-native-sdk/*.tgz
|
||||
react-native-sdk/android/src
|
||||
!react-native-sdk/android/src/main/java/org/jitsi/meet/sdk/JitsiMeetOngoingConferenceService.java
|
||||
!react-native-sdk/android/src/main/java/org/jitsi/meet/sdk/JitsiMeetReactNativePackage.java
|
||||
!react-native-sdk/android/src/main/java/org/jitsi/meet/sdk/JMOngoingConferenceModule.java
|
||||
!react-native-sdk/android/src/main/java/org/jitsi/meet/sdk/RNOngoingNotification.java
|
||||
react-native-sdk/images
|
||||
react-native-sdk/ios
|
||||
react-native-sdk/lang
|
||||
|
||||
4
Makefile
4
Makefile
@@ -55,6 +55,8 @@ deploy-appbundle:
|
||||
$(BUILD_DIR)/face-landmarks-worker.min.js.map \
|
||||
$(BUILD_DIR)/noise-suppressor-worklet.min.js \
|
||||
$(BUILD_DIR)/noise-suppressor-worklet.min.js.map \
|
||||
$(BUILD_DIR)/screenshot-capture-worker.min.js \
|
||||
$(BUILD_DIR)/screenshot-capture-worker.min.js.map \
|
||||
$(DEPLOY_DIR)
|
||||
cp \
|
||||
$(BUILD_DIR)/close3.min.js \
|
||||
@@ -123,7 +125,7 @@ dev: deploy-init deploy-css deploy-rnnoise-binary deploy-tflite deploy-meet-mode
|
||||
|
||||
source-package:
|
||||
mkdir -p source_package/jitsi-meet/css && \
|
||||
cp -r *.js *.html resources/*.txt favicon.ico fonts images libs static sounds LICENSE lang source_package/jitsi-meet && \
|
||||
cp -r *.js *.html resources/*.txt fonts images libs static sounds LICENSE lang source_package/jitsi-meet && \
|
||||
cp css/all.css source_package/jitsi-meet/css && \
|
||||
(cd source_package ; tar cjf ../jitsi-meet.tar.bz2 jitsi-meet) && \
|
||||
rm -rf source_package
|
||||
|
||||
@@ -1,11 +1,10 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<restrictions xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
|
||||
<!-- Server URL configuration -->
|
||||
<restriction
|
||||
android:defaultValue="https://meet.jit.si"
|
||||
android:description="@string/restriction_server_url_description"
|
||||
android:key="SERVER_URL"
|
||||
android:restrictionType="string"
|
||||
android:title="@string/restriction_server_url_title"/>
|
||||
</restrictions>
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<restrictions xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
|
||||
<!-- Server URL configuration -->
|
||||
<restriction
|
||||
android:description="@string/restriction_server_url_description"
|
||||
android:key="SERVER_URL"
|
||||
android:restrictionType="string"
|
||||
android:title="@string/restriction_server_url_title"/>
|
||||
</restrictions>
|
||||
|
||||
6
app.js
6
app.js
@@ -31,12 +31,6 @@ if (window.Olm) {
|
||||
window.APP = {
|
||||
API,
|
||||
conference,
|
||||
|
||||
// Used for automated performance tests.
|
||||
connectionTimes: {
|
||||
'index.loaded': window.indexLoadedTime
|
||||
},
|
||||
|
||||
translation,
|
||||
UI
|
||||
};
|
||||
|
||||
168
conference.js
168
conference.js
@@ -65,7 +65,11 @@ import {
|
||||
updateDeviceList
|
||||
} from './react/features/base/devices/actions.web';
|
||||
import {
|
||||
areDevicesDifferent,
|
||||
filterIgnoredDevices,
|
||||
flattenAvailableDevices,
|
||||
getDefaultDeviceId,
|
||||
logDevices,
|
||||
setAudioOutputDeviceId
|
||||
} from './react/features/base/devices/functions.web';
|
||||
import {
|
||||
@@ -150,7 +154,7 @@ import {
|
||||
import { isModerationNotificationDisplayed } from './react/features/notifications/functions';
|
||||
import { mediaPermissionPromptVisibilityChanged } from './react/features/overlay/actions';
|
||||
import { suspendDetected } from './react/features/power-monitor/actions';
|
||||
import { initPrejoin, makePrecallTest } from './react/features/prejoin/actions';
|
||||
import { initPrejoin } from './react/features/prejoin/actions';
|
||||
import { isPrejoinPageVisible } from './react/features/prejoin/functions';
|
||||
import { disableReceiver, stopReceiver } from './react/features/remote-control/actions';
|
||||
import { setScreenAudioShareState } from './react/features/screen-share/actions.web';
|
||||
@@ -632,7 +636,7 @@ export default {
|
||||
// so that the user can try unmute later on and add audio/video
|
||||
// to the conference
|
||||
if (!tracks.find(t => t.isAudioTrack())) {
|
||||
this.setAudioMuteStatus(true);
|
||||
this.updateAudioIconEnabled();
|
||||
}
|
||||
|
||||
if (!tracks.find(t => t.isVideoTrack())) {
|
||||
@@ -714,8 +718,6 @@ export default {
|
||||
};
|
||||
|
||||
if (isPrejoinPageVisible(state)) {
|
||||
APP.store.dispatch(makePrecallTest(this._getConferenceOptions()));
|
||||
|
||||
const { tryCreateLocalTracks, errors } = this.createInitialLocalTracks(initialOptions);
|
||||
const localTracks = await tryCreateLocalTracks;
|
||||
|
||||
@@ -841,7 +843,7 @@ export default {
|
||||
// This will only modify base/media.audio.muted which is then synced
|
||||
// up with the track at the end of local tracks initialization.
|
||||
muteLocalAudio(mute);
|
||||
this.setAudioMuteStatus(mute);
|
||||
this.updateAudioIconEnabled();
|
||||
|
||||
return;
|
||||
} else if (this.isLocalAudioMuted() === mute) {
|
||||
@@ -1035,17 +1037,6 @@ export default {
|
||||
.filter(p => !p.isHidden() || !(config.iAmRecorder && p.isHiddenFromRecorder())).length + 1;
|
||||
},
|
||||
|
||||
/**
|
||||
* Returns true if the callstats integration is enabled, otherwise returns
|
||||
* false.
|
||||
*
|
||||
* @returns true if the callstats integration is enabled, otherwise returns
|
||||
* false.
|
||||
*/
|
||||
isCallstatsEnabled() {
|
||||
return room && room.isCallstatsEnabled();
|
||||
},
|
||||
|
||||
/**
|
||||
* Get speaker stats that track total dominant speaker time.
|
||||
*
|
||||
@@ -1057,13 +1048,6 @@ export default {
|
||||
return room.getSpeakerStats();
|
||||
},
|
||||
|
||||
/**
|
||||
* Returns the connection times stored in the library.
|
||||
*/
|
||||
getConnectionTimes() {
|
||||
return room.getConnectionTimes();
|
||||
},
|
||||
|
||||
// used by torture currently
|
||||
isJoined() {
|
||||
return room && room.isJoined();
|
||||
@@ -1390,7 +1374,7 @@ export default {
|
||||
APP.store.dispatch(
|
||||
replaceLocalTrack(oldTrack, newTrack, room))
|
||||
.then(() => {
|
||||
this.setAudioMuteStatus(this.isLocalAudioMuted());
|
||||
this.updateAudioIconEnabled();
|
||||
})
|
||||
.then(resolve)
|
||||
.catch(reject)
|
||||
@@ -2045,10 +2029,6 @@ export default {
|
||||
|
||||
return this.useVideoStream(stream);
|
||||
})
|
||||
.then(() => {
|
||||
logger.info(`Switched local video device to ${cameraDeviceId}.`);
|
||||
this._updateVideoDeviceId();
|
||||
})
|
||||
.catch(error => {
|
||||
logger.error(`Failed to switch to selected camera:${cameraDeviceId}, error:${error}`);
|
||||
|
||||
@@ -2103,8 +2083,6 @@ export default {
|
||||
// above mentioned chrome bug.
|
||||
localAudio._realDeviceId = localAudio.deviceId = 'default';
|
||||
}
|
||||
logger.info(`switched local audio input device to: ${selectedDeviceId}`);
|
||||
this._updateAudioDeviceId();
|
||||
})
|
||||
.catch(err => {
|
||||
logger.error(`Failed to switch to selected audio input device ${selectedDeviceId}, error=${err}`);
|
||||
@@ -2189,13 +2167,6 @@ export default {
|
||||
|
||||
return dispatch(getAvailableDevices())
|
||||
.then(devices => {
|
||||
// Ugly way to synchronize real device IDs with local
|
||||
// storage and settings menu. This is a workaround until
|
||||
// getConstraints() method will be implemented in browsers.
|
||||
this._updateAudioDeviceId();
|
||||
|
||||
this._updateVideoDeviceId();
|
||||
|
||||
APP.UI.onAvailableDevicesChanged(devices);
|
||||
});
|
||||
}
|
||||
@@ -2203,36 +2174,6 @@ export default {
|
||||
return Promise.resolve();
|
||||
},
|
||||
|
||||
/**
|
||||
* Updates the settings for the currently used video device, extracting
|
||||
* the device id from the used track.
|
||||
* @private
|
||||
*/
|
||||
_updateVideoDeviceId() {
|
||||
const localVideo = getLocalJitsiVideoTrack(APP.store.getState());
|
||||
|
||||
if (localVideo && localVideo.videoType === 'camera') {
|
||||
APP.store.dispatch(updateSettings({
|
||||
cameraDeviceId: localVideo.getDeviceId()
|
||||
}));
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Updates the settings for the currently used audio device, extracting
|
||||
* the device id from the used track.
|
||||
* @private
|
||||
*/
|
||||
_updateAudioDeviceId() {
|
||||
const localAudio = getLocalJitsiAudioTrack(APP.store.getState());
|
||||
|
||||
if (localAudio) {
|
||||
APP.store.dispatch(updateSettings({
|
||||
micDeviceId: localAudio.getDeviceId()
|
||||
}));
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Event listener for JitsiMediaDevicesEvents.DEVICE_LIST_CHANGED to
|
||||
* handle change of available media devices.
|
||||
@@ -2241,19 +2182,28 @@ export default {
|
||||
* @returns {Promise}
|
||||
*/
|
||||
async _onDeviceListChanged(devices) {
|
||||
const oldDevices = APP.store.getState()['features/base/devices'].availableDevices;
|
||||
const localAudio = getLocalJitsiAudioTrack(APP.store.getState());
|
||||
const localVideo = getLocalJitsiVideoTrack(APP.store.getState());
|
||||
const state = APP.store.getState();
|
||||
const { filteredDevices, ignoredDevices } = filterIgnoredDevices(devices);
|
||||
const oldDevices = state['features/base/devices'].availableDevices;
|
||||
|
||||
APP.store.dispatch(updateDeviceList(devices));
|
||||
if (!areDevicesDifferent(flattenAvailableDevices(oldDevices), filteredDevices)) {
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
||||
logDevices(ignoredDevices, 'Ignored devices on device list changed:');
|
||||
|
||||
const localAudio = getLocalJitsiAudioTrack(state);
|
||||
const localVideo = getLocalJitsiVideoTrack(state);
|
||||
|
||||
APP.store.dispatch(updateDeviceList(filteredDevices));
|
||||
|
||||
// Firefox users can choose their preferred device in the gUM prompt. In that case
|
||||
// we should respect that and not attempt to switch to the preferred device from
|
||||
// our settings.
|
||||
const newLabelsOnly = mediaDeviceHelper.newDeviceListAddedLabelsOnly(oldDevices, devices);
|
||||
const newLabelsOnly = mediaDeviceHelper.newDeviceListAddedLabelsOnly(oldDevices, filteredDevices);
|
||||
const newDevices
|
||||
= mediaDeviceHelper.getNewMediaDevicesAfterDeviceListChanged(
|
||||
devices,
|
||||
filteredDevices,
|
||||
localVideo,
|
||||
localAudio,
|
||||
newLabelsOnly);
|
||||
@@ -2372,21 +2322,17 @@ export default {
|
||||
this.useAudioStream(track)
|
||||
.then(() => {
|
||||
hasDefaultMicChanged && (track._realDeviceId = track.deviceId = 'default');
|
||||
this._updateAudioDeviceId();
|
||||
}));
|
||||
} else {
|
||||
promises.push(
|
||||
this.useVideoStream(track)
|
||||
.then(() => {
|
||||
this._updateVideoDeviceId();
|
||||
}));
|
||||
this.useVideoStream(track));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return Promise.all(promises)
|
||||
.then(() => {
|
||||
APP.UI.onAvailableDevicesChanged(devices);
|
||||
APP.UI.onAvailableDevicesChanged(filteredDevices);
|
||||
});
|
||||
},
|
||||
|
||||
@@ -2432,7 +2378,7 @@ export default {
|
||||
* @param {string} [hangupReason] the reason for leaving the meeting
|
||||
* requested
|
||||
*/
|
||||
async hangup(requestFeedback = false, hangupReason) {
|
||||
hangup(requestFeedback = false, hangupReason) {
|
||||
APP.store.dispatch(disableReceiver());
|
||||
|
||||
this._stopProxyConnection();
|
||||
@@ -2449,33 +2395,42 @@ export default {
|
||||
|
||||
APP.UI.removeAllListeners();
|
||||
|
||||
let feedbackResult = {};
|
||||
let feedbackResultPromise = Promise.resolve({});
|
||||
|
||||
if (requestFeedback) {
|
||||
try {
|
||||
feedbackResult = await APP.store.dispatch(maybeOpenFeedbackDialog(room, hangupReason));
|
||||
} catch (err) { // eslint-disable-line no-empty
|
||||
const feedbackDialogClosed = (feedbackResult = {}) => {
|
||||
if (!feedbackResult.wasDialogShown && hangupReason) {
|
||||
return APP.store.dispatch(
|
||||
openLeaveReasonDialog(hangupReason)).then(() => feedbackResult);
|
||||
}
|
||||
|
||||
return Promise.resolve(feedbackResult);
|
||||
};
|
||||
|
||||
feedbackResultPromise
|
||||
= APP.store.dispatch(maybeOpenFeedbackDialog(room, hangupReason))
|
||||
.then(feedbackDialogClosed, feedbackDialogClosed);
|
||||
}
|
||||
|
||||
const leavePromise = this.leaveRoom().catch(() => Promise.resolve());
|
||||
|
||||
Promise.allSettled([ feedbackResultPromise, leavePromise ]).then(([ feedback, _ ]) => {
|
||||
this._room = undefined;
|
||||
room = undefined;
|
||||
|
||||
/**
|
||||
* Don't call {@code notifyReadyToClose} if the promotional page flag is set
|
||||
* and let the page take care of sending the message, since there will be
|
||||
* a redirect to the page anyway.
|
||||
*/
|
||||
if (!interfaceConfig.SHOW_PROMOTIONAL_CLOSE_PAGE) {
|
||||
APP.API.notifyReadyToClose();
|
||||
}
|
||||
}
|
||||
|
||||
if (!feedbackResult.wasDialogShown && hangupReason) {
|
||||
await APP.store.dispatch(openLeaveReasonDialog(hangupReason));
|
||||
}
|
||||
APP.store.dispatch(maybeRedirectToWelcomePage(feedback.value ?? {}));
|
||||
});
|
||||
|
||||
await this.leaveRoom();
|
||||
|
||||
this._room = undefined;
|
||||
room = undefined;
|
||||
|
||||
/**
|
||||
* Don't call {@code notifyReadyToClose} if the promotional page flag is set
|
||||
* and let the page take care of sending the message, since there will be
|
||||
* a redirect to the page anyway.
|
||||
*/
|
||||
if (!interfaceConfig.SHOW_PROMOTIONAL_CLOSE_PAGE) {
|
||||
APP.API.notifyReadyToClose();
|
||||
}
|
||||
APP.store.dispatch(maybeRedirectToWelcomePage(feedbackResult));
|
||||
},
|
||||
|
||||
/**
|
||||
@@ -2485,7 +2440,7 @@ export default {
|
||||
* @param {string} reason - reason for leaving the room.
|
||||
* @returns {Promise}
|
||||
*/
|
||||
async leaveRoom(doDisconnect = true, reason = '') {
|
||||
leaveRoom(doDisconnect = true, reason = '') {
|
||||
APP.store.dispatch(conferenceWillLeave(room));
|
||||
|
||||
const maybeDisconnect = () => {
|
||||
@@ -2662,15 +2617,6 @@ export default {
|
||||
APP.UI.setVideoMuted(this.getMyUserId());
|
||||
},
|
||||
|
||||
/**
|
||||
* Sets the audio muted status.
|
||||
*
|
||||
* @param {boolean} muted - New muted status.
|
||||
*/
|
||||
setAudioMuteStatus(muted) {
|
||||
APP.UI.setAudioMuted(this.getMyUserId(), muted);
|
||||
},
|
||||
|
||||
/**
|
||||
* Dispatches the passed in feedback for submission. The submitted score
|
||||
* should be a number inclusively between 1 through 5, or -1 for no score.
|
||||
|
||||
149
config.js
149
config.js
@@ -51,6 +51,9 @@ var config = {
|
||||
// Websocket URL (XMPP)
|
||||
// websocket: 'wss://jitsi-meet.example.com/' + subdir + 'xmpp-websocket',
|
||||
|
||||
// Whether BOSH should be preferred over WebSocket if both are configured.
|
||||
// preferBosh: false,
|
||||
|
||||
// The real JID of focus participant - can be overridden here
|
||||
// Do not change username - FIXME: Make focus username configurable
|
||||
// https://github.com/jitsi/jitsi-meet/issues/7376
|
||||
@@ -94,11 +97,6 @@ var config = {
|
||||
// Disables the auto-play behavior of *all* newly created video element.
|
||||
// This is useful when the client runs on a host with limited resources.
|
||||
// noAutoPlayVideo: false,
|
||||
|
||||
// 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.
|
||||
// callStatsThreshold: 5, // enable callstats for 5% of the users.
|
||||
},
|
||||
|
||||
// Disables moderator indicators.
|
||||
@@ -215,6 +213,9 @@ var config = {
|
||||
|
||||
// Video
|
||||
|
||||
// Sets the default camera facing mode.
|
||||
// cameraFacingMode: 'user',
|
||||
|
||||
// Sets the preferred resolution (height) for local video. Defaults to 720.
|
||||
// resolution: 720,
|
||||
|
||||
@@ -288,12 +289,19 @@ var config = {
|
||||
// max: 5,
|
||||
// },
|
||||
|
||||
// This option has been deprecated since it is no longer supported as per the w3c spec.
|
||||
// https://w3c.github.io/mediacapture-screen-share/#dom-mediadevices-getdisplaymedia. If the user has not
|
||||
// interacted with the webpage before the getDisplayMedia call, the promise will be rejected by the browser. This
|
||||
// has already been implemented in Firefox and Safari and will be implemented in Chrome soon.
|
||||
// https://bugs.chromium.org/p/chromium/issues/detail?id=1198918
|
||||
// startScreenSharing: false,
|
||||
// Optional screenshare settings that give more control over screen capture in the browser.
|
||||
// screenShareSettings: {
|
||||
// // Show users the current tab is the preferred capture source, default: false.
|
||||
// desktopPreferCurrentTab: false,
|
||||
// // Allow users to select system audio, default: include.
|
||||
// desktopSystemAudio: 'include',
|
||||
// // Allow users to seamlessly switch which tab they are sharing without having to select the tab again.
|
||||
// desktopSurfaceSwitching: 'include',
|
||||
// // Allow a user to be shown a preference for what screen is to be captured, default: unset.
|
||||
// desktopDisplaySurface: undefined,
|
||||
// // Allow users to select the current tab as a capture source, default: exclude.
|
||||
// desktopSelfBrowserSurface: 'exclude'
|
||||
// },
|
||||
|
||||
// Recording
|
||||
|
||||
@@ -431,6 +439,49 @@ var config = {
|
||||
// // Provides a way to set the codec preference on desktop based endpoints.
|
||||
// codecPreferenceOrder: [ 'VP9', 'VP8', 'H264' ],
|
||||
//
|
||||
// // Codec specific settings for scalability modes and max bitrates.
|
||||
// av1: {
|
||||
// maxBitratesVideo: {
|
||||
// low: 100000,
|
||||
// standard: 300000,
|
||||
// high: 1000000,
|
||||
// ssHigh: 2500000
|
||||
// },
|
||||
// scalabilityModeEnabled: true,
|
||||
// useSimulcast: false,
|
||||
// useKSVC: true
|
||||
// },
|
||||
// h264: {
|
||||
// maxBitratesVideo: {
|
||||
// low: 200000,
|
||||
// standard: 500000,
|
||||
// high: 1500000,
|
||||
// ssHigh: 2500000
|
||||
// },
|
||||
// scalabilityModeEnabled: true
|
||||
// },
|
||||
// vp8: {
|
||||
// maxBitratesVideo: {
|
||||
// low: 200000,
|
||||
// standard: 500000,
|
||||
// high: 1500000,
|
||||
// ssHigh: 2500000
|
||||
// },
|
||||
// scalabilityModeEnabled: false
|
||||
// },
|
||||
// vp9: {
|
||||
// maxBitratesVideo: {
|
||||
// low: 100000,
|
||||
// standard: 300000,
|
||||
// high: 1200000,
|
||||
// ssHigh: 2500000
|
||||
// },
|
||||
// scalabilityModeEnabled: true,
|
||||
// useSimulcast: false,
|
||||
// useKSVC: true
|
||||
// }
|
||||
//
|
||||
// DEPRECATED! Use `codec specific settings` instead.
|
||||
// // Provides a way to configure the maximum bitrates that will be enforced on the simulcast streams for
|
||||
// // video tracks. The keys in the object represent the type of the stream (LD, SD or HD) and the values
|
||||
// // are the max.bitrates to be set on that particular type of stream. The actual send may vary based on
|
||||
@@ -632,6 +683,7 @@ var config = {
|
||||
// hideDominantSpeakerBadge: false,
|
||||
|
||||
// Default language for the user interface. Cannot be overwritten.
|
||||
// DEPRECATED! Use the `lang` iframe option directly instead.
|
||||
// defaultLanguage: 'en',
|
||||
|
||||
// Disables profile and the edit of all fields from the profile settings (display name and email)
|
||||
@@ -886,38 +938,10 @@ var config = {
|
||||
// The interval at which PeerConnection.getStats() is called. Defaults to 10000
|
||||
// pcStatsInterval: 10000,
|
||||
|
||||
// To enable sending statistics to callstats.io you must provide the
|
||||
// Application ID and Secret.
|
||||
// callStatsID: '',
|
||||
// callStatsSecret: '',
|
||||
// callStatsApplicationLogsDisabled: false,
|
||||
|
||||
// The callstats initialize config params as described in the API:
|
||||
// https://docs.callstats.io/docs/javascript#callstatsinitialize-with-app-secret
|
||||
// callStatsConfigParams: {
|
||||
// disableBeforeUnloadHandler: true, // disables callstats.js's window.onbeforeunload parameter.
|
||||
// applicationVersion: "app_version", // Application version specified by the developer.
|
||||
// disablePrecalltest: true, // disables the pre-call test, it is enabled by default.
|
||||
// siteID: "siteID", // The name/ID of the site/campus from where the call/pre-call test is made.
|
||||
// additionalIDs: { // additionalIDs object, contains application related IDs.
|
||||
// customerID: "Customer Identifier. Example, walmart.",
|
||||
// tenantID: "Tenant Identifier. Example, monster.",
|
||||
// productName: "Product Name. Example, Jitsi.",
|
||||
// meetingsName: "Meeting Name. Example, Jitsi loves callstats.",
|
||||
// serverName: "Server/MiddleBox Name. Example, jvb-prod-us-east-mlkncws12.",
|
||||
// pbxID: "PBX Identifier. Example, walmart.",
|
||||
// pbxExtensionID: "PBX Extension Identifier. Example, 5625.",
|
||||
// fqExtensionID: "Fully qualified Extension Identifier. Example, +71 (US) +5625.",
|
||||
// sessionID: "Session Identifier. Example, session-12-34",
|
||||
// },
|
||||
// collectLegacyStats: true, //enables the collection of legacy stats in chrome browser
|
||||
// collectIP: true, //enables the collection localIP address
|
||||
// },
|
||||
|
||||
// Enables sending participants' display names to callstats
|
||||
// Enables sending participants' display names to stats
|
||||
// enableDisplayNameInStats: false,
|
||||
|
||||
// Enables sending participants' emails (if available) to callstats and other analytics
|
||||
// Enables sending participants' emails (if available) to stats and other analytics
|
||||
// enableEmailInStats: false,
|
||||
|
||||
// faceLandmarks: {
|
||||
@@ -940,7 +964,7 @@ var config = {
|
||||
// captureInterval: 1000,
|
||||
// },
|
||||
|
||||
// Controls the percentage of automatic feedback shown to participants when callstats is enabled.
|
||||
// Controls the percentage of automatic feedback shown to participants.
|
||||
// The default value is 100%. If set to 0, no automatic feedback will be requested
|
||||
// feedbackPercentage: 100,
|
||||
|
||||
@@ -948,7 +972,7 @@ var config = {
|
||||
//
|
||||
|
||||
// If third party requests are disabled, no other server will be contacted.
|
||||
// This means avatars will be locally generated and callstats integration
|
||||
// This means avatars will be locally generated and external stats integration
|
||||
// will not function.
|
||||
// disableThirdPartyRequests: false,
|
||||
|
||||
@@ -1499,8 +1523,6 @@ var config = {
|
||||
_peerConnStatusOutOfLastNTimeout
|
||||
_peerConnStatusRtcMuteTimeout
|
||||
avgRtpStatsN
|
||||
callStatsConfIDNamespace
|
||||
callStatsCustomScriptUrl
|
||||
desktopSharingSources
|
||||
disableAEC
|
||||
disableAGC
|
||||
@@ -1509,7 +1531,6 @@ var config = {
|
||||
disableLocalStats
|
||||
disableNS
|
||||
enableTalkWhileMuted
|
||||
forceJVB121Ratio
|
||||
forceTurnRelay
|
||||
hiddenDomain
|
||||
hiddenFromRecorderFeatureEnabled
|
||||
@@ -1533,6 +1554,7 @@ var config = {
|
||||
*/
|
||||
// notifications: [
|
||||
// 'connection.CONNFAIL', // shown when the connection fails,
|
||||
// 'dialog.cameraConstraintFailedError', // shown when the camera failed
|
||||
// 'dialog.cameraNotSendingData', // shown when there's no feed from user's camera
|
||||
// 'dialog.kickTitle', // shown when user has been kicked
|
||||
// 'dialog.liveStreaming', // livestreaming notifications (pending, on, off, limits)
|
||||
@@ -1543,6 +1565,7 @@ var config = {
|
||||
// 'dialog.recording', // recording notifications (pending, on, off, limits)
|
||||
// 'dialog.remoteControlTitle', // remote control notifications (allowed, denied, start, stop, error)
|
||||
// 'dialog.reservationError',
|
||||
// 'dialog.screenSharingFailedTitle', // shown when the screen sharing failed
|
||||
// 'dialog.serviceUnavailable', // shown when server is not reachable
|
||||
// 'dialog.sessTerminated', // shown when there is a failed conference session
|
||||
// 'dialog.sessionRestarted', // show when a client reload is initiated because of bridge migration
|
||||
@@ -1555,37 +1578,45 @@ var config = {
|
||||
// 'liveStreaming.unavailableTitle', // shown when livestreaming service is not reachable
|
||||
// 'lobby.joinRejectedMessage', // shown when while in a lobby, user's request to join is rejected
|
||||
// 'lobby.notificationTitle', // shown when lobby is toggled and when join requests are allowed / denied
|
||||
// 'notify.audioUnmuteBlockedTitle', // shown when mic unmute blocked
|
||||
// 'notify.chatMessages', // shown when receiving chat messages while the chat window is closed
|
||||
// 'notify.disconnected', // shown when a participant has left
|
||||
// 'notify.connectedOneMember', // show when a participant joined
|
||||
// 'notify.connectedTwoMembers', // show when two participants joined simultaneously
|
||||
// 'notify.connectedThreePlusMembers', // show when more than 2 participants joined simultaneously
|
||||
// 'notify.leftOneMember', // show when a participant left
|
||||
// 'notify.leftTwoMembers', // show when two participants left simultaneously
|
||||
// 'notify.leftThreePlusMembers', // show when more than 2 participants left simultaneously
|
||||
// 'notify.grantedTo', // shown when moderator rights were granted to a participant
|
||||
// 'notify.connectedTwoMembers', // show when two participants joined simultaneously
|
||||
// 'notify.dataChannelClosed', // shown when the bridge channel has been disconnected
|
||||
// 'notify.hostAskedUnmute', // shown to participant when host asks them to unmute
|
||||
// 'notify.invitedOneMember', // shown when 1 participant has been invited
|
||||
// 'notify.invitedThreePlusMembers', // shown when 3+ participants have been invited
|
||||
// 'notify.invitedTwoMembers', // shown when 2 participants have been invited
|
||||
// 'notify.kickParticipant', // shown when a participant is kicked
|
||||
// 'notify.leftOneMember', // show when a participant left
|
||||
// 'notify.leftThreePlusMembers', // show when more than 2 participants left simultaneously
|
||||
// 'notify.leftTwoMembers', // show when two participants left simultaneously
|
||||
// 'notify.linkToSalesforce', // shown when joining a meeting with salesforce integration
|
||||
// 'notify.moderationStartedTitle', // shown when AV moderation is activated
|
||||
// 'notify.moderationStoppedTitle', // shown when AV moderation is deactivated
|
||||
// 'notify.localRecordingStarted', // shown when the local recording has been started
|
||||
// 'notify.localRecordingStopped', // shown when the local recording has been stopped
|
||||
// 'notify.moderationInEffectCSTitle', // shown when user attempts to share content during AV moderation
|
||||
// 'notify.moderationInEffectTitle', // shown when user attempts to unmute audio during AV moderation
|
||||
// 'notify.moderationInEffectVideoTitle', // shown when user attempts to enable video during AV moderation
|
||||
// 'notify.moderationInEffectCSTitle', // shown when user attempts to share content during AV moderation
|
||||
// 'notify.moderator', // shown when user gets moderator privilege
|
||||
// 'notify.mutedRemotelyTitle', // shown when user is muted by a remote party
|
||||
// 'notify.mutedTitle', // shown when user has been muted upon joining,
|
||||
// 'notify.newDeviceAudioTitle', // prompts the user to use a newly detected audio device
|
||||
// 'notify.newDeviceCameraTitle', // prompts the user to use a newly detected camera
|
||||
// 'notify.noiseSuppressionFailedTitle', // shown when failed to start noise suppression
|
||||
// 'notify.participantWantsToJoin', // shown when lobby is enabled and participant requests to join meeting
|
||||
// 'notify.participantsWantToJoin', // shown when lobby is enabled and participants request to join meeting
|
||||
// 'notify.passwordRemovedRemotely', // shown when a password has been removed remotely
|
||||
// 'notify.passwordSetRemotely', // shown when a password has been set remotely
|
||||
// 'notify.raisedHand', // shown when a partcipant used raise hand,
|
||||
// 'notify.screenShareNoAudio', // shown when the audio could not be shared for the selected screen
|
||||
// 'notify.screenSharingAudioOnlyTitle', // shown when the best performance has been affected by screen sharing
|
||||
// 'notify.selfViewTitle', // show "You can always un-hide the self-view from settings"
|
||||
// 'notify.startSilentTitle', // shown when user joined with no audio
|
||||
// 'notify.suboptimalExperienceTitle', // show the browser warning
|
||||
// 'notify.unmute', // shown to moderator when user raises hand during AV moderation
|
||||
// 'notify.videoMutedRemotelyTitle', // shown when user's video is muted by a remote party,
|
||||
// 'notify.videoUnmuteBlockedTitle', // shown when camera unmute and desktop sharing are blocked
|
||||
// 'prejoin.errorDialOut',
|
||||
// 'prejoin.errorDialOutDisconnected',
|
||||
// 'prejoin.errorDialOutFailed',
|
||||
@@ -1665,13 +1696,12 @@ var config = {
|
||||
// logging: {
|
||||
// // Default log level for the app and lib-jitsi-meet.
|
||||
// defaultLogLevel: 'trace',
|
||||
// // Option to disable LogCollector (which stores the logs on CallStats).
|
||||
// // Option to disable LogCollector.
|
||||
// //disableLogCollector: true,
|
||||
// // Individual loggers are customizable.
|
||||
// loggers: {
|
||||
// // The following are too verbose in their logging with the default level.
|
||||
// 'modules/RTC/TraceablePeerConnection.js': 'info',
|
||||
// 'modules/statistics/CallStats.js': 'info',
|
||||
// 'modules/xmpp/strophe.util.js': 'log',
|
||||
// },
|
||||
|
||||
@@ -1685,6 +1715,11 @@ var config = {
|
||||
// // The server used to support whiteboard collaboration.
|
||||
// // https://github.com/jitsi/excalidraw-backend
|
||||
// collabServerBaseUrl: 'https://excalidraw-backend.example.com',
|
||||
// // The user access limit to the whiteboard, introduced as a means
|
||||
// // to control the performance.
|
||||
// userLimit: 25,
|
||||
// // The url for more info about the whiteboard and its usage limitations.
|
||||
// limitUrl: 'https://example.com/blog/whiteboard-limits,
|
||||
// },
|
||||
|
||||
// The watchRTC initialize config params as described :
|
||||
|
||||
@@ -115,17 +115,18 @@ form {
|
||||
}
|
||||
|
||||
.leftwatermark {
|
||||
max-width: 140px;
|
||||
max-height:70px;
|
||||
left: 32px;
|
||||
top: 32px;
|
||||
background-position: center left;
|
||||
background-repeat: no-repeat;
|
||||
background-size: contain;
|
||||
}
|
||||
|
||||
.leftwatermarknomargin {
|
||||
background-position: center left;
|
||||
background-repeat: no-repeat;
|
||||
background-size: contain;
|
||||
&.no-margin {
|
||||
left:0;
|
||||
top:0;
|
||||
}
|
||||
}
|
||||
|
||||
.rightwatermark {
|
||||
|
||||
@@ -61,6 +61,35 @@ body.welcome-page {
|
||||
|
||||
}
|
||||
|
||||
.not-allow-title-character-div {
|
||||
color: #f03e3e;
|
||||
background-color: #fff;
|
||||
font-size: 12px;
|
||||
font-weight: 600;
|
||||
margin: 10px 0px 5px 0px;
|
||||
text-align: $welcomePageHeaderTextAlign;
|
||||
border-radius: 5px;
|
||||
padding: 5px;
|
||||
.not-allow-title-character-text {
|
||||
float: right;
|
||||
line-height: 1.9;
|
||||
};
|
||||
.jitsi-icon {
|
||||
margin-right: 9px;
|
||||
float: left;
|
||||
|
||||
|
||||
svg {
|
||||
fill:#f03e3e;
|
||||
|
||||
& > *:first-child {
|
||||
fill: none !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
.insecure-room-name-warning {
|
||||
align-items: center;
|
||||
color: rgb(215, 121, 118);
|
||||
@@ -231,11 +260,6 @@ body.welcome-page {
|
||||
width: $welcomePageWatermarkWidth;
|
||||
height: $welcomePageWatermarkHeight;
|
||||
}
|
||||
|
||||
.watermark.leftwatermarknomargin {
|
||||
width: $welcomePageWatermarkWidth;
|
||||
height: $welcomePageWatermarkHeight;
|
||||
}
|
||||
}
|
||||
|
||||
&.without-content {
|
||||
|
||||
2
debian/jitsi-meet-tokens.postinst
vendored
2
debian/jitsi-meet-tokens.postinst
vendored
@@ -39,7 +39,7 @@ case "$1" in
|
||||
echo "Application secret is mandatory"
|
||||
fi
|
||||
# Not allowed unix special characters in secret: /, \, ", ', `
|
||||
if echo "$RET" | grep -q '[/\\\"\`]' ; then
|
||||
if echo "$RET" | grep -q "[/\\\"\`\']" ; then
|
||||
echo "Application secret contains invalid characters: /, \\, \", ', \`"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
1
debian/jitsi-meet-web.install
vendored
1
debian/jitsi-meet-web.install
vendored
@@ -1,6 +1,5 @@
|
||||
interface_config.js /usr/share/jitsi-meet/
|
||||
*.html /usr/share/jitsi-meet/
|
||||
*.ico /usr/share/jitsi-meet/
|
||||
libs /usr/share/jitsi-meet/
|
||||
static /usr/share/jitsi-meet/
|
||||
css/all.css /usr/share/jitsi-meet/css/
|
||||
|
||||
@@ -43,8 +43,8 @@ server {
|
||||
}
|
||||
}
|
||||
server {
|
||||
listen 443 ssl;
|
||||
listen [::]:443 ssl;
|
||||
listen 443 ssl http2;
|
||||
listen [::]:443 ssl http2;
|
||||
server_name jitsi-meet.example.com;
|
||||
|
||||
# Mozilla Guideline v5.4, nginx 1.17.7, OpenSSL 1.1.1d, intermediate configuration
|
||||
|
||||
BIN
favicon.ico
BIN
favicon.ico
Binary file not shown.
|
Before Width: | Height: | Size: 3.6 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 4.2 KiB |
13
images/favicon.svg
Normal file
13
images/favicon.svg
Normal file
File diff suppressed because one or more lines are too long
|
After Width: | Height: | Size: 8.5 KiB |
@@ -107,8 +107,8 @@ var interfaceConfig = {
|
||||
// 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:
|
||||
// chrome, chromium, edge, electron, firefox, nwjs, opera, safari
|
||||
OPTIMAL_BROWSERS: [ 'chrome', 'chromium', 'firefox', 'nwjs', 'electron', 'safari' ],
|
||||
// chrome, chromium, electron, firefox , safari, webkit
|
||||
OPTIMAL_BROWSERS: [ 'chrome', 'chromium', 'firefox', 'electron', 'safari', 'webkit' ],
|
||||
|
||||
POLICY_LOGO: null,
|
||||
PROVIDER_NAME: 'Jitsi',
|
||||
|
||||
13
ios/Podfile
13
ios/Podfile
@@ -6,8 +6,6 @@ workspace 'jitsi-meet'
|
||||
|
||||
install! 'cocoapods', :deterministic_uuids => false
|
||||
|
||||
production = ENV["PRODUCTION"] == "1"
|
||||
|
||||
target 'JitsiMeet' do
|
||||
project 'app/app.xcodeproj'
|
||||
|
||||
@@ -26,7 +24,6 @@ target 'JitsiMeetSDK' do
|
||||
flags = get_default_flags()
|
||||
use_react_native!(
|
||||
:path => config[:reactNativePath],
|
||||
:production => production,
|
||||
:hermes_enabled => false,
|
||||
:fabric_enabled => false,
|
||||
# An absolute path to your application root.
|
||||
@@ -56,24 +53,24 @@ target 'JitsiMeetSDKLite' do
|
||||
|
||||
# React Native and its dependencies
|
||||
#
|
||||
|
||||
|
||||
config = use_native_modules!
|
||||
use_react_native!(
|
||||
:path => config["reactNativePath"],
|
||||
:path => config[:reactNativePath],
|
||||
:hermes_enabled => false,
|
||||
:fabric_enabled => false,
|
||||
# An absolute path to your application root.
|
||||
:app_path => "#{Pod::Config.instance.installation_root}/.."
|
||||
)
|
||||
|
||||
|
||||
# Native pod dependencies
|
||||
#
|
||||
|
||||
|
||||
pod 'CocoaLumberjack', '3.7.2'
|
||||
end
|
||||
|
||||
post_install do |installer|
|
||||
react_native_post_install(installer)
|
||||
react_native_post_install(installer, :mac_catalyst_enabled => false)
|
||||
__apply_Xcode_12_5_M1_post_install_workaround(installer)
|
||||
installer.pods_project.targets.each do |target|
|
||||
# https://github.com/CocoaPods/CocoaPods/issues/11402
|
||||
|
||||
582
ios/Podfile.lock
582
ios/Podfile.lock
@@ -14,14 +14,14 @@ PODS:
|
||||
- CocoaLumberjack/Core (= 3.7.2)
|
||||
- CocoaLumberjack/Core (3.7.2)
|
||||
- DoubleConversion (1.1.6)
|
||||
- FBLazyVector (0.69.11)
|
||||
- FBReactNativeSpec (0.69.11):
|
||||
- RCT-Folly (= 2021.06.28.00-v2)
|
||||
- RCTRequired (= 0.69.11)
|
||||
- RCTTypeSafety (= 0.69.11)
|
||||
- React-Core (= 0.69.11)
|
||||
- React-jsi (= 0.69.11)
|
||||
- ReactCommon/turbomodule/core (= 0.69.11)
|
||||
- FBLazyVector (0.70.14)
|
||||
- FBReactNativeSpec (0.70.14):
|
||||
- RCT-Folly (= 2021.07.22.00)
|
||||
- RCTRequired (= 0.70.14)
|
||||
- RCTTypeSafety (= 0.70.14)
|
||||
- React-Core (= 0.70.14)
|
||||
- React-jsi (= 0.70.14)
|
||||
- ReactCommon/turbomodule/core (= 0.70.14)
|
||||
- Firebase/Analytics (8.15.0):
|
||||
- Firebase/Core
|
||||
- Firebase/Core (8.15.0):
|
||||
@@ -103,7 +103,7 @@ PODS:
|
||||
- GoogleUtilities/Network (~> 7.7)
|
||||
- "GoogleUtilities/NSData+zlib (~> 7.7)"
|
||||
- nanopb (~> 2.30908.0)
|
||||
- GoogleDataTransport (9.2.5):
|
||||
- GoogleDataTransport (9.3.0):
|
||||
- GoogleUtilities/Environment (~> 7.7)
|
||||
- nanopb (< 2.30910.0, >= 2.30908.0)
|
||||
- PromisesObjC (< 3.0, >= 1.2)
|
||||
@@ -111,41 +111,41 @@ PODS:
|
||||
- AppAuth (~> 1.5)
|
||||
- GTMAppAuth (< 3.0, >= 1.3)
|
||||
- GTMSessionFetcher/Core (< 4.0, >= 1.1)
|
||||
- GoogleUtilities/AppDelegateSwizzler (7.11.5):
|
||||
- GoogleUtilities/AppDelegateSwizzler (7.12.0):
|
||||
- GoogleUtilities/Environment
|
||||
- GoogleUtilities/Logger
|
||||
- GoogleUtilities/Network
|
||||
- GoogleUtilities/Environment (7.11.5):
|
||||
- GoogleUtilities/Environment (7.12.0):
|
||||
- PromisesObjC (< 3.0, >= 1.2)
|
||||
- GoogleUtilities/Logger (7.11.5):
|
||||
- GoogleUtilities/Logger (7.12.0):
|
||||
- GoogleUtilities/Environment
|
||||
- GoogleUtilities/MethodSwizzler (7.11.5):
|
||||
- GoogleUtilities/MethodSwizzler (7.12.0):
|
||||
- GoogleUtilities/Logger
|
||||
- GoogleUtilities/Network (7.11.5):
|
||||
- GoogleUtilities/Network (7.12.0):
|
||||
- GoogleUtilities/Logger
|
||||
- "GoogleUtilities/NSData+zlib"
|
||||
- GoogleUtilities/Reachability
|
||||
- "GoogleUtilities/NSData+zlib (7.11.5)"
|
||||
- GoogleUtilities/Reachability (7.11.5):
|
||||
- "GoogleUtilities/NSData+zlib (7.12.0)"
|
||||
- GoogleUtilities/Reachability (7.12.0):
|
||||
- GoogleUtilities/Logger
|
||||
- GoogleUtilities/UserDefaults (7.11.5):
|
||||
- GoogleUtilities/UserDefaults (7.12.0):
|
||||
- GoogleUtilities/Logger
|
||||
- GTMAppAuth (2.0.0):
|
||||
- AppAuth/Core (~> 1.6)
|
||||
- GTMSessionFetcher/Core (< 4.0, >= 1.5)
|
||||
- GTMSessionFetcher/Core (3.1.1)
|
||||
- JitsiWebRTC (111.0.2)
|
||||
- libwebp (1.3.1):
|
||||
- libwebp/demux (= 1.3.1)
|
||||
- libwebp/mux (= 1.3.1)
|
||||
- libwebp/sharpyuv (= 1.3.1)
|
||||
- libwebp/webp (= 1.3.1)
|
||||
- libwebp/demux (1.3.1):
|
||||
- GTMSessionFetcher/Core (3.2.0)
|
||||
- JitsiWebRTC (118.0.0)
|
||||
- libwebp (1.3.2):
|
||||
- libwebp/demux (= 1.3.2)
|
||||
- libwebp/mux (= 1.3.2)
|
||||
- libwebp/sharpyuv (= 1.3.2)
|
||||
- libwebp/webp (= 1.3.2)
|
||||
- libwebp/demux (1.3.2):
|
||||
- libwebp/webp
|
||||
- libwebp/mux (1.3.1):
|
||||
- libwebp/mux (1.3.2):
|
||||
- libwebp/demux
|
||||
- libwebp/sharpyuv (1.3.1)
|
||||
- libwebp/webp (1.3.1):
|
||||
- libwebp/sharpyuv (1.3.2)
|
||||
- libwebp/webp (1.3.2):
|
||||
- libwebp/sharpyuv
|
||||
- nanopb (2.30908.0):
|
||||
- nanopb/decode (= 2.30908.0)
|
||||
@@ -156,214 +156,214 @@ PODS:
|
||||
- PromisesObjC (2.3.1)
|
||||
- PromisesSwift (2.3.1):
|
||||
- PromisesObjC (= 2.3.1)
|
||||
- RCT-Folly (2021.06.28.00-v2):
|
||||
- RCT-Folly (2021.07.22.00):
|
||||
- boost
|
||||
- DoubleConversion
|
||||
- fmt (~> 6.2.1)
|
||||
- glog
|
||||
- RCT-Folly/Default (= 2021.06.28.00-v2)
|
||||
- RCT-Folly/Default (2021.06.28.00-v2):
|
||||
- RCT-Folly/Default (= 2021.07.22.00)
|
||||
- RCT-Folly/Default (2021.07.22.00):
|
||||
- boost
|
||||
- DoubleConversion
|
||||
- fmt (~> 6.2.1)
|
||||
- glog
|
||||
- RCTRequired (0.69.11)
|
||||
- RCTTypeSafety (0.69.11):
|
||||
- FBLazyVector (= 0.69.11)
|
||||
- RCTRequired (= 0.69.11)
|
||||
- React-Core (= 0.69.11)
|
||||
- React (0.69.11):
|
||||
- React-Core (= 0.69.11)
|
||||
- React-Core/DevSupport (= 0.69.11)
|
||||
- React-Core/RCTWebSocket (= 0.69.11)
|
||||
- React-RCTActionSheet (= 0.69.11)
|
||||
- React-RCTAnimation (= 0.69.11)
|
||||
- React-RCTBlob (= 0.69.11)
|
||||
- React-RCTImage (= 0.69.11)
|
||||
- React-RCTLinking (= 0.69.11)
|
||||
- React-RCTNetwork (= 0.69.11)
|
||||
- React-RCTSettings (= 0.69.11)
|
||||
- React-RCTText (= 0.69.11)
|
||||
- React-RCTVibration (= 0.69.11)
|
||||
- React-bridging (0.69.11):
|
||||
- RCT-Folly (= 2021.06.28.00-v2)
|
||||
- React-jsi (= 0.69.11)
|
||||
- React-callinvoker (0.69.11)
|
||||
- React-Codegen (0.69.11):
|
||||
- FBReactNativeSpec (= 0.69.11)
|
||||
- RCT-Folly (= 2021.06.28.00-v2)
|
||||
- RCTRequired (= 0.69.11)
|
||||
- RCTTypeSafety (= 0.69.11)
|
||||
- React-Core (= 0.69.11)
|
||||
- React-jsi (= 0.69.11)
|
||||
- React-jsiexecutor (= 0.69.11)
|
||||
- ReactCommon/turbomodule/core (= 0.69.11)
|
||||
- React-Core (0.69.11):
|
||||
- RCTRequired (0.70.14)
|
||||
- RCTTypeSafety (0.70.14):
|
||||
- FBLazyVector (= 0.70.14)
|
||||
- RCTRequired (= 0.70.14)
|
||||
- React-Core (= 0.70.14)
|
||||
- React (0.70.14):
|
||||
- React-Core (= 0.70.14)
|
||||
- React-Core/DevSupport (= 0.70.14)
|
||||
- React-Core/RCTWebSocket (= 0.70.14)
|
||||
- React-RCTActionSheet (= 0.70.14)
|
||||
- React-RCTAnimation (= 0.70.14)
|
||||
- React-RCTBlob (= 0.70.14)
|
||||
- React-RCTImage (= 0.70.14)
|
||||
- React-RCTLinking (= 0.70.14)
|
||||
- React-RCTNetwork (= 0.70.14)
|
||||
- React-RCTSettings (= 0.70.14)
|
||||
- React-RCTText (= 0.70.14)
|
||||
- React-RCTVibration (= 0.70.14)
|
||||
- React-bridging (0.70.14):
|
||||
- RCT-Folly (= 2021.07.22.00)
|
||||
- React-jsi (= 0.70.14)
|
||||
- React-callinvoker (0.70.14)
|
||||
- React-Codegen (0.70.14):
|
||||
- FBReactNativeSpec (= 0.70.14)
|
||||
- RCT-Folly (= 2021.07.22.00)
|
||||
- RCTRequired (= 0.70.14)
|
||||
- RCTTypeSafety (= 0.70.14)
|
||||
- React-Core (= 0.70.14)
|
||||
- React-jsi (= 0.70.14)
|
||||
- React-jsiexecutor (= 0.70.14)
|
||||
- ReactCommon/turbomodule/core (= 0.70.14)
|
||||
- React-Core (0.70.14):
|
||||
- glog
|
||||
- RCT-Folly (= 2021.06.28.00-v2)
|
||||
- React-Core/Default (= 0.69.11)
|
||||
- React-cxxreact (= 0.69.11)
|
||||
- React-jsi (= 0.69.11)
|
||||
- React-jsiexecutor (= 0.69.11)
|
||||
- React-perflogger (= 0.69.11)
|
||||
- RCT-Folly (= 2021.07.22.00)
|
||||
- React-Core/Default (= 0.70.14)
|
||||
- React-cxxreact (= 0.70.14)
|
||||
- React-jsi (= 0.70.14)
|
||||
- React-jsiexecutor (= 0.70.14)
|
||||
- React-perflogger (= 0.70.14)
|
||||
- Yoga
|
||||
- React-Core/CoreModulesHeaders (0.69.11):
|
||||
- React-Core/CoreModulesHeaders (0.70.14):
|
||||
- glog
|
||||
- RCT-Folly (= 2021.06.28.00-v2)
|
||||
- RCT-Folly (= 2021.07.22.00)
|
||||
- React-Core/Default
|
||||
- React-cxxreact (= 0.69.11)
|
||||
- React-jsi (= 0.69.11)
|
||||
- React-jsiexecutor (= 0.69.11)
|
||||
- React-perflogger (= 0.69.11)
|
||||
- React-cxxreact (= 0.70.14)
|
||||
- React-jsi (= 0.70.14)
|
||||
- React-jsiexecutor (= 0.70.14)
|
||||
- React-perflogger (= 0.70.14)
|
||||
- Yoga
|
||||
- React-Core/Default (0.69.11):
|
||||
- React-Core/Default (0.70.14):
|
||||
- glog
|
||||
- RCT-Folly (= 2021.06.28.00-v2)
|
||||
- React-cxxreact (= 0.69.11)
|
||||
- React-jsi (= 0.69.11)
|
||||
- React-jsiexecutor (= 0.69.11)
|
||||
- React-perflogger (= 0.69.11)
|
||||
- RCT-Folly (= 2021.07.22.00)
|
||||
- React-cxxreact (= 0.70.14)
|
||||
- React-jsi (= 0.70.14)
|
||||
- React-jsiexecutor (= 0.70.14)
|
||||
- React-perflogger (= 0.70.14)
|
||||
- Yoga
|
||||
- React-Core/DevSupport (0.69.11):
|
||||
- React-Core/DevSupport (0.70.14):
|
||||
- glog
|
||||
- RCT-Folly (= 2021.06.28.00-v2)
|
||||
- React-Core/Default (= 0.69.11)
|
||||
- React-Core/RCTWebSocket (= 0.69.11)
|
||||
- React-cxxreact (= 0.69.11)
|
||||
- React-jsi (= 0.69.11)
|
||||
- React-jsiexecutor (= 0.69.11)
|
||||
- React-jsinspector (= 0.69.11)
|
||||
- React-perflogger (= 0.69.11)
|
||||
- RCT-Folly (= 2021.07.22.00)
|
||||
- React-Core/Default (= 0.70.14)
|
||||
- React-Core/RCTWebSocket (= 0.70.14)
|
||||
- React-cxxreact (= 0.70.14)
|
||||
- React-jsi (= 0.70.14)
|
||||
- React-jsiexecutor (= 0.70.14)
|
||||
- React-jsinspector (= 0.70.14)
|
||||
- React-perflogger (= 0.70.14)
|
||||
- Yoga
|
||||
- React-Core/RCTActionSheetHeaders (0.69.11):
|
||||
- React-Core/RCTActionSheetHeaders (0.70.14):
|
||||
- glog
|
||||
- RCT-Folly (= 2021.06.28.00-v2)
|
||||
- RCT-Folly (= 2021.07.22.00)
|
||||
- React-Core/Default
|
||||
- React-cxxreact (= 0.69.11)
|
||||
- React-jsi (= 0.69.11)
|
||||
- React-jsiexecutor (= 0.69.11)
|
||||
- React-perflogger (= 0.69.11)
|
||||
- React-cxxreact (= 0.70.14)
|
||||
- React-jsi (= 0.70.14)
|
||||
- React-jsiexecutor (= 0.70.14)
|
||||
- React-perflogger (= 0.70.14)
|
||||
- Yoga
|
||||
- React-Core/RCTAnimationHeaders (0.69.11):
|
||||
- React-Core/RCTAnimationHeaders (0.70.14):
|
||||
- glog
|
||||
- RCT-Folly (= 2021.06.28.00-v2)
|
||||
- RCT-Folly (= 2021.07.22.00)
|
||||
- React-Core/Default
|
||||
- React-cxxreact (= 0.69.11)
|
||||
- React-jsi (= 0.69.11)
|
||||
- React-jsiexecutor (= 0.69.11)
|
||||
- React-perflogger (= 0.69.11)
|
||||
- React-cxxreact (= 0.70.14)
|
||||
- React-jsi (= 0.70.14)
|
||||
- React-jsiexecutor (= 0.70.14)
|
||||
- React-perflogger (= 0.70.14)
|
||||
- Yoga
|
||||
- React-Core/RCTBlobHeaders (0.69.11):
|
||||
- React-Core/RCTBlobHeaders (0.70.14):
|
||||
- glog
|
||||
- RCT-Folly (= 2021.06.28.00-v2)
|
||||
- RCT-Folly (= 2021.07.22.00)
|
||||
- React-Core/Default
|
||||
- React-cxxreact (= 0.69.11)
|
||||
- React-jsi (= 0.69.11)
|
||||
- React-jsiexecutor (= 0.69.11)
|
||||
- React-perflogger (= 0.69.11)
|
||||
- React-cxxreact (= 0.70.14)
|
||||
- React-jsi (= 0.70.14)
|
||||
- React-jsiexecutor (= 0.70.14)
|
||||
- React-perflogger (= 0.70.14)
|
||||
- Yoga
|
||||
- React-Core/RCTImageHeaders (0.69.11):
|
||||
- React-Core/RCTImageHeaders (0.70.14):
|
||||
- glog
|
||||
- RCT-Folly (= 2021.06.28.00-v2)
|
||||
- RCT-Folly (= 2021.07.22.00)
|
||||
- React-Core/Default
|
||||
- React-cxxreact (= 0.69.11)
|
||||
- React-jsi (= 0.69.11)
|
||||
- React-jsiexecutor (= 0.69.11)
|
||||
- React-perflogger (= 0.69.11)
|
||||
- React-cxxreact (= 0.70.14)
|
||||
- React-jsi (= 0.70.14)
|
||||
- React-jsiexecutor (= 0.70.14)
|
||||
- React-perflogger (= 0.70.14)
|
||||
- Yoga
|
||||
- React-Core/RCTLinkingHeaders (0.69.11):
|
||||
- React-Core/RCTLinkingHeaders (0.70.14):
|
||||
- glog
|
||||
- RCT-Folly (= 2021.06.28.00-v2)
|
||||
- RCT-Folly (= 2021.07.22.00)
|
||||
- React-Core/Default
|
||||
- React-cxxreact (= 0.69.11)
|
||||
- React-jsi (= 0.69.11)
|
||||
- React-jsiexecutor (= 0.69.11)
|
||||
- React-perflogger (= 0.69.11)
|
||||
- React-cxxreact (= 0.70.14)
|
||||
- React-jsi (= 0.70.14)
|
||||
- React-jsiexecutor (= 0.70.14)
|
||||
- React-perflogger (= 0.70.14)
|
||||
- Yoga
|
||||
- React-Core/RCTNetworkHeaders (0.69.11):
|
||||
- React-Core/RCTNetworkHeaders (0.70.14):
|
||||
- glog
|
||||
- RCT-Folly (= 2021.06.28.00-v2)
|
||||
- RCT-Folly (= 2021.07.22.00)
|
||||
- React-Core/Default
|
||||
- React-cxxreact (= 0.69.11)
|
||||
- React-jsi (= 0.69.11)
|
||||
- React-jsiexecutor (= 0.69.11)
|
||||
- React-perflogger (= 0.69.11)
|
||||
- React-cxxreact (= 0.70.14)
|
||||
- React-jsi (= 0.70.14)
|
||||
- React-jsiexecutor (= 0.70.14)
|
||||
- React-perflogger (= 0.70.14)
|
||||
- Yoga
|
||||
- React-Core/RCTSettingsHeaders (0.69.11):
|
||||
- React-Core/RCTSettingsHeaders (0.70.14):
|
||||
- glog
|
||||
- RCT-Folly (= 2021.06.28.00-v2)
|
||||
- RCT-Folly (= 2021.07.22.00)
|
||||
- React-Core/Default
|
||||
- React-cxxreact (= 0.69.11)
|
||||
- React-jsi (= 0.69.11)
|
||||
- React-jsiexecutor (= 0.69.11)
|
||||
- React-perflogger (= 0.69.11)
|
||||
- React-cxxreact (= 0.70.14)
|
||||
- React-jsi (= 0.70.14)
|
||||
- React-jsiexecutor (= 0.70.14)
|
||||
- React-perflogger (= 0.70.14)
|
||||
- Yoga
|
||||
- React-Core/RCTTextHeaders (0.69.11):
|
||||
- React-Core/RCTTextHeaders (0.70.14):
|
||||
- glog
|
||||
- RCT-Folly (= 2021.06.28.00-v2)
|
||||
- RCT-Folly (= 2021.07.22.00)
|
||||
- React-Core/Default
|
||||
- React-cxxreact (= 0.69.11)
|
||||
- React-jsi (= 0.69.11)
|
||||
- React-jsiexecutor (= 0.69.11)
|
||||
- React-perflogger (= 0.69.11)
|
||||
- React-cxxreact (= 0.70.14)
|
||||
- React-jsi (= 0.70.14)
|
||||
- React-jsiexecutor (= 0.70.14)
|
||||
- React-perflogger (= 0.70.14)
|
||||
- Yoga
|
||||
- React-Core/RCTVibrationHeaders (0.69.11):
|
||||
- React-Core/RCTVibrationHeaders (0.70.14):
|
||||
- glog
|
||||
- RCT-Folly (= 2021.06.28.00-v2)
|
||||
- RCT-Folly (= 2021.07.22.00)
|
||||
- React-Core/Default
|
||||
- React-cxxreact (= 0.69.11)
|
||||
- React-jsi (= 0.69.11)
|
||||
- React-jsiexecutor (= 0.69.11)
|
||||
- React-perflogger (= 0.69.11)
|
||||
- React-cxxreact (= 0.70.14)
|
||||
- React-jsi (= 0.70.14)
|
||||
- React-jsiexecutor (= 0.70.14)
|
||||
- React-perflogger (= 0.70.14)
|
||||
- Yoga
|
||||
- React-Core/RCTWebSocket (0.69.11):
|
||||
- React-Core/RCTWebSocket (0.70.14):
|
||||
- glog
|
||||
- RCT-Folly (= 2021.06.28.00-v2)
|
||||
- React-Core/Default (= 0.69.11)
|
||||
- React-cxxreact (= 0.69.11)
|
||||
- React-jsi (= 0.69.11)
|
||||
- React-jsiexecutor (= 0.69.11)
|
||||
- React-perflogger (= 0.69.11)
|
||||
- RCT-Folly (= 2021.07.22.00)
|
||||
- React-Core/Default (= 0.70.14)
|
||||
- React-cxxreact (= 0.70.14)
|
||||
- React-jsi (= 0.70.14)
|
||||
- React-jsiexecutor (= 0.70.14)
|
||||
- React-perflogger (= 0.70.14)
|
||||
- Yoga
|
||||
- React-CoreModules (0.69.11):
|
||||
- RCT-Folly (= 2021.06.28.00-v2)
|
||||
- RCTTypeSafety (= 0.69.11)
|
||||
- React-Codegen (= 0.69.11)
|
||||
- React-Core/CoreModulesHeaders (= 0.69.11)
|
||||
- React-jsi (= 0.69.11)
|
||||
- React-RCTImage (= 0.69.11)
|
||||
- ReactCommon/turbomodule/core (= 0.69.11)
|
||||
- React-cxxreact (0.69.11):
|
||||
- React-CoreModules (0.70.14):
|
||||
- RCT-Folly (= 2021.07.22.00)
|
||||
- RCTTypeSafety (= 0.70.14)
|
||||
- React-Codegen (= 0.70.14)
|
||||
- React-Core/CoreModulesHeaders (= 0.70.14)
|
||||
- React-jsi (= 0.70.14)
|
||||
- React-RCTImage (= 0.70.14)
|
||||
- ReactCommon/turbomodule/core (= 0.70.14)
|
||||
- React-cxxreact (0.70.14):
|
||||
- boost (= 1.76.0)
|
||||
- DoubleConversion
|
||||
- glog
|
||||
- RCT-Folly (= 2021.06.28.00-v2)
|
||||
- React-callinvoker (= 0.69.11)
|
||||
- React-jsi (= 0.69.11)
|
||||
- React-jsinspector (= 0.69.11)
|
||||
- React-logger (= 0.69.11)
|
||||
- React-perflogger (= 0.69.11)
|
||||
- React-runtimeexecutor (= 0.69.11)
|
||||
- React-jsi (0.69.11):
|
||||
- RCT-Folly (= 2021.07.22.00)
|
||||
- React-callinvoker (= 0.70.14)
|
||||
- React-jsi (= 0.70.14)
|
||||
- React-jsinspector (= 0.70.14)
|
||||
- React-logger (= 0.70.14)
|
||||
- React-perflogger (= 0.70.14)
|
||||
- React-runtimeexecutor (= 0.70.14)
|
||||
- React-jsi (0.70.14):
|
||||
- boost (= 1.76.0)
|
||||
- DoubleConversion
|
||||
- glog
|
||||
- RCT-Folly (= 2021.06.28.00-v2)
|
||||
- React-jsi/Default (= 0.69.11)
|
||||
- React-jsi/Default (0.69.11):
|
||||
- RCT-Folly (= 2021.07.22.00)
|
||||
- React-jsi/Default (= 0.70.14)
|
||||
- React-jsi/Default (0.70.14):
|
||||
- boost (= 1.76.0)
|
||||
- DoubleConversion
|
||||
- glog
|
||||
- RCT-Folly (= 2021.06.28.00-v2)
|
||||
- React-jsiexecutor (0.69.11):
|
||||
- RCT-Folly (= 2021.07.22.00)
|
||||
- React-jsiexecutor (0.70.14):
|
||||
- DoubleConversion
|
||||
- glog
|
||||
- RCT-Folly (= 2021.06.28.00-v2)
|
||||
- React-cxxreact (= 0.69.11)
|
||||
- React-jsi (= 0.69.11)
|
||||
- React-perflogger (= 0.69.11)
|
||||
- React-jsinspector (0.69.11)
|
||||
- React-logger (0.69.11):
|
||||
- RCT-Folly (= 2021.07.22.00)
|
||||
- React-cxxreact (= 0.70.14)
|
||||
- React-jsi (= 0.70.14)
|
||||
- React-perflogger (= 0.70.14)
|
||||
- React-jsinspector (0.70.14)
|
||||
- React-logger (0.70.14):
|
||||
- glog
|
||||
- react-native-background-timer (2.4.1):
|
||||
- React-Core
|
||||
@@ -371,9 +371,9 @@ PODS:
|
||||
- React-Core
|
||||
- react-native-keep-awake (4.0.0):
|
||||
- React
|
||||
- react-native-netinfo (9.4.1):
|
||||
- react-native-netinfo (11.1.0):
|
||||
- React-Core
|
||||
- react-native-orientation-locker (1.5.0):
|
||||
- react-native-orientation-locker (1.6.0):
|
||||
- React-Core
|
||||
- react-native-pager-view (6.2.0):
|
||||
- React-Core
|
||||
@@ -391,80 +391,80 @@ PODS:
|
||||
- react-native-video/Video (6.0.0-alpha.7):
|
||||
- PromisesSwift
|
||||
- React-Core
|
||||
- react-native-webrtc (111.0.3):
|
||||
- JitsiWebRTC (~> 111.0.0)
|
||||
- react-native-webrtc (118.0.0):
|
||||
- JitsiWebRTC (~> 118.0.0)
|
||||
- React-Core
|
||||
- react-native-webview (13.5.1):
|
||||
- React-Core
|
||||
- React-perflogger (0.69.11)
|
||||
- React-RCTActionSheet (0.69.11):
|
||||
- React-Core/RCTActionSheetHeaders (= 0.69.11)
|
||||
- React-RCTAnimation (0.69.11):
|
||||
- RCT-Folly (= 2021.06.28.00-v2)
|
||||
- RCTTypeSafety (= 0.69.11)
|
||||
- React-Codegen (= 0.69.11)
|
||||
- React-Core/RCTAnimationHeaders (= 0.69.11)
|
||||
- React-jsi (= 0.69.11)
|
||||
- ReactCommon/turbomodule/core (= 0.69.11)
|
||||
- React-RCTBlob (0.69.11):
|
||||
- RCT-Folly (= 2021.06.28.00-v2)
|
||||
- React-Codegen (= 0.69.11)
|
||||
- React-Core/RCTBlobHeaders (= 0.69.11)
|
||||
- React-Core/RCTWebSocket (= 0.69.11)
|
||||
- React-jsi (= 0.69.11)
|
||||
- React-RCTNetwork (= 0.69.11)
|
||||
- ReactCommon/turbomodule/core (= 0.69.11)
|
||||
- React-RCTImage (0.69.11):
|
||||
- RCT-Folly (= 2021.06.28.00-v2)
|
||||
- RCTTypeSafety (= 0.69.11)
|
||||
- React-Codegen (= 0.69.11)
|
||||
- React-Core/RCTImageHeaders (= 0.69.11)
|
||||
- React-jsi (= 0.69.11)
|
||||
- React-RCTNetwork (= 0.69.11)
|
||||
- ReactCommon/turbomodule/core (= 0.69.11)
|
||||
- React-RCTLinking (0.69.11):
|
||||
- React-Codegen (= 0.69.11)
|
||||
- React-Core/RCTLinkingHeaders (= 0.69.11)
|
||||
- React-jsi (= 0.69.11)
|
||||
- ReactCommon/turbomodule/core (= 0.69.11)
|
||||
- React-RCTNetwork (0.69.11):
|
||||
- RCT-Folly (= 2021.06.28.00-v2)
|
||||
- RCTTypeSafety (= 0.69.11)
|
||||
- React-Codegen (= 0.69.11)
|
||||
- React-Core/RCTNetworkHeaders (= 0.69.11)
|
||||
- React-jsi (= 0.69.11)
|
||||
- ReactCommon/turbomodule/core (= 0.69.11)
|
||||
- React-RCTSettings (0.69.11):
|
||||
- RCT-Folly (= 2021.06.28.00-v2)
|
||||
- RCTTypeSafety (= 0.69.11)
|
||||
- React-Codegen (= 0.69.11)
|
||||
- React-Core/RCTSettingsHeaders (= 0.69.11)
|
||||
- React-jsi (= 0.69.11)
|
||||
- ReactCommon/turbomodule/core (= 0.69.11)
|
||||
- React-RCTText (0.69.11):
|
||||
- React-Core/RCTTextHeaders (= 0.69.11)
|
||||
- React-RCTVibration (0.69.11):
|
||||
- RCT-Folly (= 2021.06.28.00-v2)
|
||||
- React-Codegen (= 0.69.11)
|
||||
- React-Core/RCTVibrationHeaders (= 0.69.11)
|
||||
- React-jsi (= 0.69.11)
|
||||
- ReactCommon/turbomodule/core (= 0.69.11)
|
||||
- React-runtimeexecutor (0.69.11):
|
||||
- React-jsi (= 0.69.11)
|
||||
- ReactCommon/turbomodule/core (0.69.11):
|
||||
- React-perflogger (0.70.14)
|
||||
- React-RCTActionSheet (0.70.14):
|
||||
- React-Core/RCTActionSheetHeaders (= 0.70.14)
|
||||
- React-RCTAnimation (0.70.14):
|
||||
- RCT-Folly (= 2021.07.22.00)
|
||||
- RCTTypeSafety (= 0.70.14)
|
||||
- React-Codegen (= 0.70.14)
|
||||
- React-Core/RCTAnimationHeaders (= 0.70.14)
|
||||
- React-jsi (= 0.70.14)
|
||||
- ReactCommon/turbomodule/core (= 0.70.14)
|
||||
- React-RCTBlob (0.70.14):
|
||||
- RCT-Folly (= 2021.07.22.00)
|
||||
- React-Codegen (= 0.70.14)
|
||||
- React-Core/RCTBlobHeaders (= 0.70.14)
|
||||
- React-Core/RCTWebSocket (= 0.70.14)
|
||||
- React-jsi (= 0.70.14)
|
||||
- React-RCTNetwork (= 0.70.14)
|
||||
- ReactCommon/turbomodule/core (= 0.70.14)
|
||||
- React-RCTImage (0.70.14):
|
||||
- RCT-Folly (= 2021.07.22.00)
|
||||
- RCTTypeSafety (= 0.70.14)
|
||||
- React-Codegen (= 0.70.14)
|
||||
- React-Core/RCTImageHeaders (= 0.70.14)
|
||||
- React-jsi (= 0.70.14)
|
||||
- React-RCTNetwork (= 0.70.14)
|
||||
- ReactCommon/turbomodule/core (= 0.70.14)
|
||||
- React-RCTLinking (0.70.14):
|
||||
- React-Codegen (= 0.70.14)
|
||||
- React-Core/RCTLinkingHeaders (= 0.70.14)
|
||||
- React-jsi (= 0.70.14)
|
||||
- ReactCommon/turbomodule/core (= 0.70.14)
|
||||
- React-RCTNetwork (0.70.14):
|
||||
- RCT-Folly (= 2021.07.22.00)
|
||||
- RCTTypeSafety (= 0.70.14)
|
||||
- React-Codegen (= 0.70.14)
|
||||
- React-Core/RCTNetworkHeaders (= 0.70.14)
|
||||
- React-jsi (= 0.70.14)
|
||||
- ReactCommon/turbomodule/core (= 0.70.14)
|
||||
- React-RCTSettings (0.70.14):
|
||||
- RCT-Folly (= 2021.07.22.00)
|
||||
- RCTTypeSafety (= 0.70.14)
|
||||
- React-Codegen (= 0.70.14)
|
||||
- React-Core/RCTSettingsHeaders (= 0.70.14)
|
||||
- React-jsi (= 0.70.14)
|
||||
- ReactCommon/turbomodule/core (= 0.70.14)
|
||||
- React-RCTText (0.70.14):
|
||||
- React-Core/RCTTextHeaders (= 0.70.14)
|
||||
- React-RCTVibration (0.70.14):
|
||||
- RCT-Folly (= 2021.07.22.00)
|
||||
- React-Codegen (= 0.70.14)
|
||||
- React-Core/RCTVibrationHeaders (= 0.70.14)
|
||||
- React-jsi (= 0.70.14)
|
||||
- ReactCommon/turbomodule/core (= 0.70.14)
|
||||
- React-runtimeexecutor (0.70.14):
|
||||
- React-jsi (= 0.70.14)
|
||||
- ReactCommon/turbomodule/core (0.70.14):
|
||||
- DoubleConversion
|
||||
- glog
|
||||
- RCT-Folly (= 2021.06.28.00-v2)
|
||||
- React-bridging (= 0.69.11)
|
||||
- React-callinvoker (= 0.69.11)
|
||||
- React-Core (= 0.69.11)
|
||||
- React-cxxreact (= 0.69.11)
|
||||
- React-jsi (= 0.69.11)
|
||||
- React-logger (= 0.69.11)
|
||||
- React-perflogger (= 0.69.11)
|
||||
- RCT-Folly (= 2021.07.22.00)
|
||||
- React-bridging (= 0.70.14)
|
||||
- React-callinvoker (= 0.70.14)
|
||||
- React-Core (= 0.70.14)
|
||||
- React-cxxreact (= 0.70.14)
|
||||
- React-jsi (= 0.70.14)
|
||||
- React-logger (= 0.70.14)
|
||||
- React-perflogger (= 0.70.14)
|
||||
- RNCalendarEvents (2.2.0):
|
||||
- React
|
||||
- RNCAsyncStorage (1.19.3):
|
||||
- RNCAsyncStorage (1.19.4):
|
||||
- React-Core
|
||||
- RNCClipboard (1.5.1):
|
||||
- React-Core
|
||||
@@ -474,7 +474,7 @@ PODS:
|
||||
- React-Core
|
||||
- RNGestureHandler (2.9.0):
|
||||
- React-Core
|
||||
- RNGoogleSignin (10.0.1):
|
||||
- RNGoogleSignin (10.1.0):
|
||||
- GoogleSignIn (~> 7.0)
|
||||
- React-Core
|
||||
- RNScreens (3.24.0):
|
||||
@@ -709,8 +709,8 @@ SPEC CHECKSUMS:
|
||||
boost: a7c83b31436843459a1961bfd74b96033dc77234
|
||||
CocoaLumberjack: b7e05132ff94f6ae4dfa9d5bce9141893a21d9da
|
||||
DoubleConversion: 5189b271737e1565bdce30deb4a08d647e3f5f54
|
||||
FBLazyVector: 5c0975e66853436589eae7542f4b956c7e2ef465
|
||||
FBReactNativeSpec: bb062293e84c33200005312d1807d8cb94a0d66a
|
||||
FBLazyVector: efad4471d02263013cfcb7a2f75de6ac7565692f
|
||||
FBReactNativeSpec: 9cd9542bfdcc64e07bc649f809dd621876f78619
|
||||
Firebase: 5f8193dff4b5b7c5d5ef72ae54bb76c08e2b841d
|
||||
FirebaseAnalytics: 7761cbadb00a717d8d0939363eb46041526474fa
|
||||
FirebaseCore: 5743c5785c074a794d35f2fff7ecc254a91e08b1
|
||||
@@ -721,71 +721,71 @@ SPEC CHECKSUMS:
|
||||
fmt: ff9d55029c625d3757ed641535fd4a75fedc7ce9
|
||||
Giphy: 6b5f6986c8df4f71e01a8ef86595f426b3439fb5
|
||||
giphy-react-native-sdk: fcda9639f8ca2cc47e0517b6ef11c19359db5f5a
|
||||
glog: 3d02b25ca00c2d456734d0bcff864cbc62f6ae1a
|
||||
glog: 04b94705f318337d7ead9e6d17c019bd9b1f6b1b
|
||||
GoogleAppMeasurement: 4c19f031220c72464d460c9daa1fb5d1acce958e
|
||||
GoogleDataTransport: 54dee9d48d14580407f8f5fbf2f496e92437a2f2
|
||||
GoogleDataTransport: 57c22343ab29bc686febbf7cbb13bad167c2d8fe
|
||||
GoogleSignIn: b232380cf495a429b8095d3178a8d5855b42e842
|
||||
GoogleUtilities: 13e2c67ede716b8741c7989e26893d151b2b2084
|
||||
GoogleUtilities: 0759d1a57ebb953965c2dfe0ba4c82e95ccc2e34
|
||||
GTMAppAuth: 99fb010047ba3973b7026e45393f51f27ab965ae
|
||||
GTMSessionFetcher: e8647203b65cee28c5f73d0f473d096653945e72
|
||||
JitsiWebRTC: 80f62908fcf2a1160e0d14b584323fb6e6be630b
|
||||
libwebp: 33dc822fbbf4503668d09f7885bbfedc76c45e96
|
||||
GTMSessionFetcher: 41b9ef0b4c08a6db4b7eb51a21ae5183ec99a2c8
|
||||
JitsiWebRTC: 3a41671ef65a51d7204323814b055a2690b921c7
|
||||
libwebp: 1786c9f4ff8a279e4dac1e8f385004d5fc253009
|
||||
nanopb: a0ba3315591a9ae0a16a309ee504766e90db0c96
|
||||
ObjectiveDropboxOfficial: fe206ce8c0bc49976c249d472db7fdbc53ebbd53
|
||||
PromisesObjC: c50d2056b5253dadbd6c2bea79b0674bd5a52fa4
|
||||
PromisesSwift: 28dca69a9c40779916ac2d6985a0192a5cb4a265
|
||||
RCT-Folly: b9d9fe1fc70114b751c076104e52f3b1b5e5a95a
|
||||
RCTRequired: 8e9a57dddc8f8e9e816c67c2d2537271a997137a
|
||||
RCTTypeSafety: 2b19e268e2036a2c2f6db6deb1ac03e28b1d607a
|
||||
React: f9478e6390f177ee6b67b87a3c6afea42b39523e
|
||||
React-bridging: d405ecd3ff80e1d0a4059a11063eaa9ed7a00c58
|
||||
React-callinvoker: c8ffa61f3f06f486ba6647769fc98f19e25d165a
|
||||
React-Codegen: 73acfdac1495b91ad5efdd3ab005568263c5def6
|
||||
React-Core: 7b7c75af4b73fe0ed4e5c3cdb7d79979e81148dc
|
||||
React-CoreModules: cd6e7efb38162884f08c7afa16fffaf15ff28ae4
|
||||
React-cxxreact: 51157cc600c9f436a7e623913a03b775305ef86c
|
||||
React-jsi: 3eeb345c4828d7b132fd38064a305f31b46d4ec3
|
||||
React-jsiexecutor: 5813455a4a908fb7284aa13307a9e0386e93b0bb
|
||||
React-jsinspector: 9ca5bf73ed0a195397e45fdbcd507cf7d503c428
|
||||
React-logger: 700340e325f21ba2a2d6413a61ef14268c7360aa
|
||||
RCT-Folly: 0080d0a6ebf2577475bda044aa59e2ca1f909cda
|
||||
RCTRequired: 6f42727926c2ef4836fc23169586f3d8d7f5a6e4
|
||||
RCTTypeSafety: de9b538a8f20ae8c780bf38935f37f303b083fc8
|
||||
React: 6604c02c25295898e9332c5dbe5d6f140be1e246
|
||||
React-bridging: 55de000607b776d7c9b1333f38d1991ef25bf915
|
||||
React-callinvoker: aa42aaefd72dbe9218c112fd503eff7ab782bd11
|
||||
React-Codegen: 9e13e901ac4d4c46349c2db28b8774fa4274ec18
|
||||
React-Core: b046bbaddd981014eaac20cef83de953a0405c1b
|
||||
React-CoreModules: 4f0b29e5924b06a868983952265f77fed219f349
|
||||
React-cxxreact: 818c9b06607f7972e95eeacb326389429c6a2d38
|
||||
React-jsi: 0bf359879bc4c2c908204b1cd789b0a727a7a568
|
||||
React-jsiexecutor: 03144eeee729e6a6cb8d7ff2d5653b67315f8f31
|
||||
React-jsinspector: 6538dfb58970d1fb9d89c9c34e87713ece6c3cf0
|
||||
React-logger: 4e9c3f888b4b5bb72a3ac7f1be7929e776181016
|
||||
react-native-background-timer: 17ea5e06803401a379ebf1f20505b793ac44d0fe
|
||||
react-native-get-random-values: dee677497c6a740b71e5612e8dbd83e7539ed5bb
|
||||
react-native-keep-awake: afad8a51dfef9fe9655a6344771be32c8596d774
|
||||
react-native-netinfo: fefd4e98d75cbdd6e85fc530f7111a8afdf2b0c5
|
||||
react-native-orientation-locker: 851f6510d8046ea2f14aa169b1e01fcd309a94ba
|
||||
react-native-netinfo: 3aa5637c18834966e0c932de8ae1ae56fea20a97
|
||||
react-native-orientation-locker: 4409c5b12b65f942e75449872b4f078b6f27af81
|
||||
react-native-pager-view: 0ccb8bf60e2ebd38b1f3669fa3650ecce81db2df
|
||||
react-native-performance: 47ac22ebf2aa24f324a96a5825581f6ce18c09e8
|
||||
react-native-safe-area-context: 9697629f7b2cda43cf52169bb7e0767d330648c2
|
||||
react-native-slider: 1cdd6ba29675df21f30544253bf7351d3c2d68c4
|
||||
react-native-splash-screen: 4312f786b13a81b5169ef346d76d33bc0c6dc457
|
||||
react-native-video: 967eead48aaa42c25a9e1d65c3b1ab30762a88df
|
||||
react-native-webrtc: 4d1669c2ed29767fe70b0169428b4466589ecf8b
|
||||
react-native-webrtc: c8d9ad3c152105b2720ca2851d04b49659551992
|
||||
react-native-webview: 8baa0f5c6d336d6ba488e942bcadea5bf51f050a
|
||||
React-perflogger: fdee2a0c512167ae4c19c4e230ccf6aa66a6aff0
|
||||
React-RCTActionSheet: 1cf5fef4e372f1c877969710a51bea4bb25e78fe
|
||||
React-RCTAnimation: 73816e3acd1f5e3f00166fc7eedb34f6b112f734
|
||||
React-RCTBlob: 6976c838fb14a1daf75d7c8bb23bae9cbbf726bb
|
||||
React-RCTImage: ab8a7498f215117f32271698591e4bd932dcf812
|
||||
React-RCTLinking: e8e78aed2744ab9946cc8ba5716b4938c2efb1e0
|
||||
React-RCTNetwork: 796f5aed4d932655d292bdc6b40f9502dcdb9542
|
||||
React-RCTSettings: 7e1cd2a384b45c90caf67464572abe3833b9da3b
|
||||
React-RCTText: fd6162890828f0761e03c59058fa23c3a21b2e10
|
||||
React-RCTVibration: 302cfd5cc33669d7abdb7ec6790123baba66e62e
|
||||
React-runtimeexecutor: 59407514818b2afbb1d7507e4e1ac834d24b0fbd
|
||||
ReactCommon: b8487da74723562d7368dab27135fd182f00a91c
|
||||
React-perflogger: 74b2d33200b8c26440c2c39b87a4177d8404655f
|
||||
React-RCTActionSheet: 3fdf6b3a85f2ea4b365b267efd9c82aaeb20fe33
|
||||
React-RCTAnimation: 9659d5ed57ccbd129516486b2cce38e536841337
|
||||
React-RCTBlob: 49ac98cfd9476af046814a2c9126fca1bf0cbe75
|
||||
React-RCTImage: b4d2d7d14ad9389bd645bc2daa706ccaead3fc44
|
||||
React-RCTLinking: ebf051ed2532652e5290e4fb7c017c42e4e1f0d2
|
||||
React-RCTNetwork: 1636df1f91d4c5ad8815ef93f695931af1c0a842
|
||||
React-RCTSettings: f6306171fd5d3cd8c5fa0b1803da599784ead5c5
|
||||
React-RCTText: 53c106b5fb9e263c2f1e5d6b0733049989d6c428
|
||||
React-RCTVibration: d293c50100c0927379e6a80fab86a219e08792ae
|
||||
React-runtimeexecutor: 0d01d03375f996484fcc231ccca3fe604a4a5652
|
||||
ReactCommon: dce64235f8548b6e4758647310145f5356c8d0cb
|
||||
RNCalendarEvents: 7e65eb4a94f53c1744d1e275f7fafcfaa619f7a3
|
||||
RNCAsyncStorage: c913ede1fa163a71cea118ed4670bbaaa4b511bb
|
||||
RNCAsyncStorage: 3a8f7145d17cdd9f88e7b77666c94a09e4f759c8
|
||||
RNCClipboard: 41d8d918092ae8e676f18adada19104fa3e68495
|
||||
RNDefaultPreference: 08bdb06cfa9188d5da97d4642dac745218d7fb31
|
||||
RNDeviceInfo: 02ea8b23e2280fa18e00a06d7e62804d74028579
|
||||
RNGestureHandler: 071d7a9ad81e8b83fe7663b303d132406a7d8f39
|
||||
RNGoogleSignin: ccaa4a81582cf713eea562c5dd9dc1961a715fd0
|
||||
RNGoogleSignin: a6a612cce56a45ab701c5c5c6e36f5390522d100
|
||||
RNScreens: b21dc57dfa2b710c30ec600786a3fc223b1b92e7
|
||||
RNSound: 6c156f925295bdc83e8e422e7d8b38d33bc71852
|
||||
RNSVG: ed492aaf3af9ca01bc945f7a149d76d62e73ec82
|
||||
RNWatch: fd30ca40a5b5ef58dcbc195638e68219bc455236
|
||||
Yoga: 7f5ad94937ba3fc58c151ad1b7bbada2c275b28e
|
||||
Yoga: 56413d530d1808044600320ced5baa883acedc44
|
||||
|
||||
PODFILE CHECKSUM: 90720aee51cf2cab2e12611a28dbf55a688e969c
|
||||
PODFILE CHECKSUM: c5053669414ca81c03ca4548249b11fe53a13060
|
||||
|
||||
COCOAPODS: 1.12.1
|
||||
COCOAPODS: 1.14.3
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
archiveVersion = 1;
|
||||
classes = {
|
||||
};
|
||||
objectVersion = 52;
|
||||
objectVersion = 54;
|
||||
objects = {
|
||||
|
||||
/* Begin PBXBuildFile section */
|
||||
@@ -862,7 +862,6 @@
|
||||
"$(inherited)",
|
||||
"@executable_path/Frameworks",
|
||||
);
|
||||
LIBRARY_SEARCH_PATHS = "$(inherited)";
|
||||
OTHER_LDFLAGS = (
|
||||
"$(inherited)",
|
||||
"-ObjC",
|
||||
@@ -892,7 +891,6 @@
|
||||
"$(inherited)",
|
||||
"@executable_path/Frameworks",
|
||||
);
|
||||
LIBRARY_SEARCH_PATHS = "$(inherited)";
|
||||
OTHER_LDFLAGS = (
|
||||
"$(inherited)",
|
||||
"-ObjC",
|
||||
@@ -978,7 +976,7 @@
|
||||
buildSettings = {
|
||||
ALWAYS_SEARCH_USER_PATHS = NO;
|
||||
CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES;
|
||||
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
|
||||
CLANG_CXX_LANGUAGE_STANDARD = "c++17";
|
||||
CLANG_CXX_LIBRARY = "libc++";
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CLANG_ENABLE_OBJC_ARC = YES;
|
||||
@@ -1013,6 +1011,7 @@
|
||||
GCC_PREPROCESSOR_DEFINITIONS = (
|
||||
"DEBUG=1",
|
||||
"$(inherited)",
|
||||
_LIBCPP_ENABLE_CXX17_REMOVED_UNARY_BINARY_FUNCTION,
|
||||
);
|
||||
GCC_SYMBOLS_PRIVATE_EXTERN = NO;
|
||||
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
|
||||
@@ -1028,6 +1027,10 @@
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 12.4;
|
||||
MTL_ENABLE_DEBUG_INFO = YES;
|
||||
ONLY_ACTIVE_ARCH = YES;
|
||||
OTHER_LDFLAGS = (
|
||||
"$(inherited)",
|
||||
" ",
|
||||
);
|
||||
REACT_NATIVE_PATH = "${PODS_ROOT}/../../node_modules/react-native";
|
||||
SDKROOT = iphoneos;
|
||||
TARGETED_DEVICE_FAMILY = "1,2";
|
||||
@@ -1039,7 +1042,7 @@
|
||||
buildSettings = {
|
||||
ALWAYS_SEARCH_USER_PATHS = NO;
|
||||
CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES;
|
||||
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
|
||||
CLANG_CXX_LANGUAGE_STANDARD = "c++17";
|
||||
CLANG_CXX_LIBRARY = "libc++";
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CLANG_ENABLE_OBJC_ARC = YES;
|
||||
@@ -1069,6 +1072,10 @@
|
||||
"EXCLUDED_ARCHS[sdk=iphonesimulator*]" = "";
|
||||
GCC_C_LANGUAGE_STANDARD = gnu99;
|
||||
GCC_NO_COMMON_BLOCKS = YES;
|
||||
GCC_PREPROCESSOR_DEFINITIONS = (
|
||||
"$(inherited)",
|
||||
_LIBCPP_ENABLE_CXX17_REMOVED_UNARY_BINARY_FUNCTION,
|
||||
);
|
||||
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
|
||||
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
|
||||
GCC_WARN_UNDECLARED_SELECTOR = YES;
|
||||
@@ -1081,6 +1088,10 @@
|
||||
);
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 12.4;
|
||||
MTL_ENABLE_DEBUG_INFO = NO;
|
||||
OTHER_LDFLAGS = (
|
||||
"$(inherited)",
|
||||
" ",
|
||||
);
|
||||
REACT_NATIVE_PATH = "${PODS_ROOT}/../../node_modules/react-native";
|
||||
SDKROOT = iphoneos;
|
||||
SWIFT_COMPILATION_MODE = wholemodule;
|
||||
|
||||
@@ -38,7 +38,6 @@
|
||||
[builder setFeatureFlag:@"resolution" withValue:@(360)];
|
||||
[builder setFeatureFlag:@"ios.screensharing.enabled" withBoolean:YES];
|
||||
[builder setFeatureFlag:@"ios.recording.enabled" withBoolean:YES];
|
||||
builder.serverURL = [NSURL URLWithString:@"https://meet.jit.si"];
|
||||
}];
|
||||
|
||||
[jitsiMeet application:application didFinishLaunchingWithOptions:launchOptions];
|
||||
@@ -126,7 +125,7 @@
|
||||
|
||||
- (UIInterfaceOrientationMask)application:(UIApplication *)application
|
||||
supportedInterfaceOrientationsForWindow:(UIWindow *)window {
|
||||
return [[JitsiMeet sharedInstance] application:application
|
||||
return [[JitsiMeet sharedInstance] application:application
|
||||
supportedInterfaceOrientationsForWindow:window];
|
||||
}
|
||||
|
||||
|
||||
@@ -728,7 +728,7 @@
|
||||
CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES;
|
||||
CLANG_ANALYZER_NONNULL = YES;
|
||||
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
|
||||
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
|
||||
CLANG_CXX_LANGUAGE_STANDARD = "c++17";
|
||||
CLANG_CXX_LIBRARY = "libc++";
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CLANG_ENABLE_OBJC_ARC = YES;
|
||||
@@ -766,6 +766,7 @@
|
||||
GCC_PREPROCESSOR_DEFINITIONS = (
|
||||
"DEBUG=1",
|
||||
"$(inherited)",
|
||||
_LIBCPP_ENABLE_CXX17_REMOVED_UNARY_BINARY_FUNCTION,
|
||||
);
|
||||
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
|
||||
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
|
||||
@@ -776,6 +777,10 @@
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 12.4;
|
||||
MTL_ENABLE_DEBUG_INFO = YES;
|
||||
ONLY_ACTIVE_ARCH = YES;
|
||||
OTHER_LDFLAGS = (
|
||||
"$(inherited)",
|
||||
" ",
|
||||
);
|
||||
REACT_NATIVE_PATH = "${PODS_ROOT}/../../node_modules/react-native";
|
||||
SDKROOT = iphoneos;
|
||||
TARGETED_DEVICE_FAMILY = "1,2";
|
||||
@@ -791,7 +796,7 @@
|
||||
CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES;
|
||||
CLANG_ANALYZER_NONNULL = YES;
|
||||
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
|
||||
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
|
||||
CLANG_CXX_LANGUAGE_STANDARD = "c++17";
|
||||
CLANG_CXX_LIBRARY = "libc++";
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CLANG_ENABLE_OBJC_ARC = YES;
|
||||
@@ -824,6 +829,10 @@
|
||||
"EXCLUDED_ARCHS[sdk=iphonesimulator*]" = "";
|
||||
GCC_C_LANGUAGE_STANDARD = gnu99;
|
||||
GCC_NO_COMMON_BLOCKS = YES;
|
||||
GCC_PREPROCESSOR_DEFINITIONS = (
|
||||
"$(inherited)",
|
||||
_LIBCPP_ENABLE_CXX17_REMOVED_UNARY_BINARY_FUNCTION,
|
||||
);
|
||||
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
|
||||
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
|
||||
GCC_WARN_UNDECLARED_SELECTOR = YES;
|
||||
@@ -832,6 +841,10 @@
|
||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 12.4;
|
||||
MTL_ENABLE_DEBUG_INFO = NO;
|
||||
OTHER_LDFLAGS = (
|
||||
"$(inherited)",
|
||||
" ",
|
||||
);
|
||||
REACT_NATIVE_PATH = "${PODS_ROOT}/../../node_modules/react-native";
|
||||
SDKROOT = iphoneos;
|
||||
SWIFT_COMPILATION_MODE = wholemodule;
|
||||
|
||||
@@ -67,13 +67,16 @@
|
||||
"renameBreakoutRoom": "Breakout-Raum umbenennen",
|
||||
"sendToBreakoutRoom": "Anwesende in Breakout-Raum verschieben:"
|
||||
},
|
||||
"breakoutList": "Breakout-Liste",
|
||||
"defaultName": "Breakout-Raum #{{index}}",
|
||||
"hideParticipantList": "Teilnehmerliste ausblenden",
|
||||
"mainRoom": "Hauptraum",
|
||||
"notifications": {
|
||||
"joined": "Breakout-Raum \"{{name}}\" betreten",
|
||||
"joinedMainRoom": "Hauptraum betreten",
|
||||
"joinedTitle": "Breakout-Räume"
|
||||
}
|
||||
},
|
||||
"showParticipantList": "Teilnehmerliste anzeigen"
|
||||
},
|
||||
"calendarSync": {
|
||||
"addMeetingURL": "Konferenzlink hinzufügen",
|
||||
@@ -256,6 +259,7 @@
|
||||
"Share": "Teilen",
|
||||
"Submit": "OK",
|
||||
"WaitForHostMsg": "Die Konferenz wurde noch nicht gestartet. Falls Sie die Konferenz leiten, authentifizieren Sie sich bitte. Warten Sie andernfalls, bis die Konferenz gestartet wird.",
|
||||
"WaitingForHostButton": "Auf Moderation warten",
|
||||
"WaitingForHostTitle": "Warten auf den Beginn der Konferenz …",
|
||||
"Yes": "Ja",
|
||||
"accessibilityLabel": {
|
||||
@@ -269,6 +273,8 @@
|
||||
"addMeetingNote": "Notiz zu dieser Konferenz hinzufügen",
|
||||
"addOptionalNote": "Notiz hinzufügen (optional):",
|
||||
"allow": "Erlauben",
|
||||
"allowToggleCameraDialog": "Wollen Sie {{initiatorName}} erlauben, Ihre Kameraauswahl zu ändern?",
|
||||
"allowToggleCameraTitle": "Änderung der Kamera zulassen?",
|
||||
"alreadySharedVideoMsg": "Eine andere Person gibt bereits ein Video weiter. Bei dieser Konferenz ist jeweils nur ein geteiltes Video möglich.",
|
||||
"alreadySharedVideoTitle": "Nur ein geteiltes Video gleichzeitig",
|
||||
"applicationWindow": "Anwendungsfenster",
|
||||
@@ -329,6 +335,7 @@
|
||||
"lockRoom": "Konferenz$t(lockRoomPassword) hinzufügen",
|
||||
"lockTitle": "Sperren fehlgeschlagen",
|
||||
"login": "Anmelden",
|
||||
"loginQuestion": "Sind Sie sicher, dass sie sich anmelden und die Konferenz verlassen möchten?",
|
||||
"logoutQuestion": "Sind Sie sicher, dass Sie sich abmelden und die Konferenz verlassen möchten?",
|
||||
"logoutTitle": "Abmelden",
|
||||
"maxUsersLimitReached": "Das Limit für die maximale Personenzahl ist erreicht. Die Konferenz ist voll. Bitte wenden Sie sich an die Konferenzleitung oder versuchen Sie es später noch einmal!",
|
||||
@@ -409,8 +416,10 @@
|
||||
"sendPrivateMessageTitle": "Privat antworten?",
|
||||
"serviceUnavailable": "Dienst nicht verfügbar",
|
||||
"sessTerminated": "Konferenz beendet",
|
||||
"sessTerminatedReason": "Die Konferenz wurde beendet",
|
||||
"sessionRestarted": "Konferenz neugestartet",
|
||||
"shareAudio": "Fortfahren",
|
||||
"shareAudioAltText": "Um den gewünschten Inhalt zu teilen: Navigiere zu \"Browser tab\", wähle den Inhalt, aktiviere \"Audio teilen\" Kästchen Und klicke den “Teilen” schaltfläche",
|
||||
"shareAudioTitle": "Wie kann Audio geteilt werden",
|
||||
"shareAudioWarningD1": "müssen Sie Ihre Bildschirmfreigabe stoppen, bevor Sie Audio teilen können.",
|
||||
"shareAudioWarningD2": "müssen Sie Ihre Bildschirmfreigabe neustarten und die Option \"Audio freigeben\" auswählen.",
|
||||
@@ -440,7 +449,24 @@
|
||||
"thankYou": "Danke für die Verwendung von {{appName}}!",
|
||||
"token": "Token",
|
||||
"tokenAuthFailed": "Sie sind nicht berechtigt, dieser Konferenz beizutreten.",
|
||||
"tokenAuthFailedReason": {
|
||||
"audInvalid": "Ungültiger `aud`-Wert. Erwartet wird `jitsi`.",
|
||||
"contextNotFound": "Das `context`-Objekt fehlt.",
|
||||
"expInvalid": "Ungültiger `exp`-Wert.",
|
||||
"featureInvalid": "Ungültiges Feature: {{feature}}, noch nicht implementiert.",
|
||||
"featureValueInvalid": "Ungültiger Wert für Feature: {{feature}}.",
|
||||
"featuresNotFound": "Das `features`-Objekt fehlt.",
|
||||
"headerNotFound": "Header fehlt.",
|
||||
"issInvalid": "Ungültiger `iss`-Wert. Erwartet wird `chat`.",
|
||||
"kidMismatch": "Die Key-ID (kid) passt nicht zum sub.",
|
||||
"kidNotFound": "Fehlende Key-ID (kid).",
|
||||
"nbfFuture": "Der `nbf`-Wert liegt in der Zukunft.",
|
||||
"nbfInvalid": "Ungültiger `nbf`-Wert.",
|
||||
"payloadNotFound": "Fehlende Payload.",
|
||||
"tokenExpired": "Das Token ist abgelaufen."
|
||||
},
|
||||
"tokenAuthFailedTitle": "Authentifizierung fehlgeschlagen",
|
||||
"tokenAuthFailedWithReasons": "Teilnahme an der Konferenz fehlgeschlagen. Möglicher Grund: {{reason}}",
|
||||
"tokenAuthUnsupported": "Token-Authentifizierung wird nicht unterstützt.",
|
||||
"transcribing": "Wird transkribiert",
|
||||
"unlockRoom": "Konferenz$t(lockRoomPassword) entfernen",
|
||||
@@ -530,6 +556,7 @@
|
||||
"password": "$t(lockRoomPasswordUppercase):",
|
||||
"reachedLimit": "Sie haben die Grenzen Ihres Tarifs erreicht.",
|
||||
"sip": "SIP-Adresse",
|
||||
"sipAudioOnly": "SIP-Adresse (nur Ton)",
|
||||
"title": "Teilen",
|
||||
"tooltip": "Freigabe-Link und Einwahlinformationen für dieses Meeting",
|
||||
"upgradeOptions": "Bitte prüfen Sie Ihre Upgrade-Optionen auf"
|
||||
@@ -636,13 +663,13 @@
|
||||
"knockingParticipantList": "Liste anklopfender Personen",
|
||||
"lobbyChatStartedNotification": "{{moderator}} hat einen Lobby-Chat mit {{attendee}} gestartet",
|
||||
"lobbyChatStartedTitle": "{{moderator}} hat einen Lobby-Chat mit Ihnen gestartet.",
|
||||
"lobbyClosed": "Die Lobby wurde geschlossen.",
|
||||
"nameField": "Geben Sie Ihren Namen ein",
|
||||
"notificationLobbyAccessDenied": "{{targetParticipantName}} wurde von {{originParticipantName}} der Zutritt verwehrt",
|
||||
"notificationLobbyAccessGranted": "{{targetParticipantName}} wurde von {{originParticipantName}} der Zutritt gestattet",
|
||||
"notificationLobbyDisabled": "{{originParticipantName}} hat die Lobby deaktiviert",
|
||||
"notificationLobbyEnabled": "{{originParticipantName}} hat die Lobby aktiviert",
|
||||
"notificationTitle": "Lobby",
|
||||
"passwordField": "Konferenzpasswort eingeben",
|
||||
"passwordJoinButton": "Beitreten",
|
||||
"reject": "Ablehnen",
|
||||
"rejectAll": "Alle ablehnen",
|
||||
@@ -677,6 +704,8 @@
|
||||
"sessionToken": "Sitzungs-Token",
|
||||
"start": "Aufnahme starten",
|
||||
"stop": "Aufnahme stoppen",
|
||||
"stopping": "Aufnahme wird gestoppt",
|
||||
"wait": "Bitte warten Sie während wir Ihre Aufnahme speichern",
|
||||
"yes": "Ja"
|
||||
},
|
||||
"lockRoomPassword": "Passwort",
|
||||
@@ -1059,6 +1088,7 @@
|
||||
"alertOk": "OK",
|
||||
"alertTitle": "Warnung",
|
||||
"alertURLText": "Die angegebene Server-URL ist ungültig",
|
||||
"apply": "Übernehmen",
|
||||
"buildInfoSection": "Build-Informationen",
|
||||
"conferenceSection": "Konferenz",
|
||||
"disableCallIntegration": "Native Anrufintegration deaktivieren",
|
||||
@@ -1069,6 +1099,7 @@
|
||||
"displayNamePlaceholderText": "z.B. Erika Musterfrau",
|
||||
"email": "E-Mail",
|
||||
"emailPlaceholderText": "email@beispiel.de",
|
||||
"gavatarMessage": "Wenn Sie ein Gravatar-Konto mit Ihrer Emailadresse haben, wird dieses als Ihr Profilfoto verwendet.",
|
||||
"goTo": "Gehe zu",
|
||||
"header": "Einstellungen",
|
||||
"help": "Hilfe",
|
||||
|
||||
@@ -778,7 +778,7 @@
|
||||
"moreModerationControls": "Más controles de moderación",
|
||||
"moreParticipantOptions": "Más opciones de participantes",
|
||||
"mute": "Silenciar",
|
||||
"muteAll": "Silenciar a todos los demás",
|
||||
"muteAll": "Silenciar a todos",
|
||||
"muteEveryoneElse": "Silenciar al resto",
|
||||
"stopEveryonesVideo": "Detener el vídeo de todos",
|
||||
"stopVideo": "Detener el vídeo",
|
||||
@@ -1361,7 +1361,7 @@
|
||||
"videothumbnail": {
|
||||
"connectionInfo": "Información de conexión",
|
||||
"domute": "Silenciar",
|
||||
"domuteOthers": "Silenciar a todos",
|
||||
"domuteOthers": "Silenciar a todos los demás",
|
||||
"domuteVideo": "Desactivar la cámara",
|
||||
"domuteVideoOfOthers": "Desactivar la cámara de todos los demás",
|
||||
"flip": "Voltear",
|
||||
|
||||
1226
lang/main-lv.json
1226
lang/main-lv.json
File diff suppressed because it is too large
Load Diff
@@ -67,13 +67,18 @@
|
||||
"renameBreakoutRoom": "Renomear sala",
|
||||
"sendToBreakoutRoom": "Enviar participante para:"
|
||||
},
|
||||
"breakoutList": "lista de salas",
|
||||
"buttonLabel": "Salas simultâneas",
|
||||
"defaultName": "Sala #{{index}}",
|
||||
"hideParticipantList": "Ocultar lista de participantes",
|
||||
"mainRoom": "Sala principal",
|
||||
"notifications": {
|
||||
"joined": "Entrada na sala \"{{name}}\"",
|
||||
"joinedMainRoom": "Entrada na sala principal",
|
||||
"joinedTitle": "Salas simultâneas"
|
||||
}
|
||||
},
|
||||
"showParticipantList": "Mostrar lista de participantes",
|
||||
"title": "Salas simultâneas"
|
||||
},
|
||||
"calendarSync": {
|
||||
"addMeetingURL": "Adicionar um link da reunião",
|
||||
@@ -477,6 +482,10 @@
|
||||
"viewUpgradeOptions": "Ver opções de actualização",
|
||||
"viewUpgradeOptionsContent": "Para obter acesso ilimitado a funcionalidades premium como gravação, transcrições, RTMP Streaming & mais, terá de actualizar o seu plano.",
|
||||
"viewUpgradeOptionsTitle": "Descobriu uma característica premium!",
|
||||
"whiteboardLimitContent": "Lamentamos, mas o limite de utilizadores do quadro branco foi atingido.",
|
||||
"whiteboardLimitReference": "Para mais informações consultar",
|
||||
"whiteboardLimitReferenceUrl": "o nosso sítio Web",
|
||||
"whiteboardLimitTitle": "Restrição da utilização do quadro branco",
|
||||
"yourEntireScreen": "O seu ecrã inteiro"
|
||||
},
|
||||
"documentSharing": {
|
||||
@@ -724,6 +733,7 @@
|
||||
"dataChannelClosed": "Deficiência na qualidade do vídeo",
|
||||
"dataChannelClosedDescription": "O canal de ponte foi desconectado e, portanto, a qualidade do vídeo está limitada à sua configuração mais baixa.",
|
||||
"disabledIframe": "A incorporação destina-se apenas a fins de demonstração, pelo que esta chamada será desligada em {{timeout}} minutos.",
|
||||
"disabledIframeSecondary": "A incorporação de {{domain}} destina-se apenas a fins de demonstração, pelo que esta chamada será desligada em {{timeout}} minutos. Por favor, use <a href='{{jaasDomain}}' rel='noopener noreferrer' target='_blank'>Jitsi as a Service</a> para incorporação em produção!",
|
||||
"disconnected": "desconectado",
|
||||
"displayNotifications": "Mostrar notificações para",
|
||||
"dontRemindMe": "Não me lembre",
|
||||
@@ -799,7 +809,9 @@
|
||||
"videoUnmuteBlockedDescription": "A operação de ligar a câmara e partilhar o ambiente de trabalho foi temporariamente bloqueada devido aos limites do sistema.",
|
||||
"videoUnmuteBlockedTitle": "Está bloqueado ligar a câmara e partilhar o ambiente de trabalho!",
|
||||
"viewLobby": "Ver sala de espera",
|
||||
"waitingParticipants": "{{waitingParticipants}} pessoas"
|
||||
"waitingParticipants": "{{waitingParticipants}} pessoas",
|
||||
"whiteboardLimitDescription": "Guarde o seu progresso, pois o limite de utilizadores será atingido em breve e o quadro branco será encerrado.",
|
||||
"whiteboardLimitTitle": "Utilização do quadro branco"
|
||||
},
|
||||
"participantsPane": {
|
||||
"actions": {
|
||||
@@ -808,6 +820,7 @@
|
||||
"askUnmute": "Pedir para ligar o som",
|
||||
"audioModeration": "Ligar o microfone deles",
|
||||
"blockEveryoneMicCamera": "Bloquear o microfone e a câmara de todos",
|
||||
"breakoutRooms": "Salas simultâneas",
|
||||
"invite": "Convidar alguém",
|
||||
"moreModerationActions": "Mais opções de moderação",
|
||||
"moreModerationControls": "Mais controlos de moderação",
|
||||
@@ -1154,7 +1167,7 @@
|
||||
"audioOnly": "Mudar para apenas áudio",
|
||||
"audioRoute": "Selecionar o dispositivo de som",
|
||||
"boo": "Vaia",
|
||||
"breakoutRoom": "Entrar/Sair da sala",
|
||||
"breakoutRooms": "Salas simultâneas",
|
||||
"callQuality": "Gerir a qualidade do vídeo",
|
||||
"carmode": "Modo de condução",
|
||||
"cc": "Mudar legendas",
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
{
|
||||
"addPeople": {
|
||||
"accessibilityLabel": {
|
||||
"meetingLink": "Link da reunião: {{url}}"
|
||||
},
|
||||
"add": "Convidar",
|
||||
"addContacts": "Convide seus contatos",
|
||||
"contacts": "contatos",
|
||||
@@ -39,6 +42,18 @@
|
||||
"audioOnly": {
|
||||
"audioOnly": "Largura de banda baixa"
|
||||
},
|
||||
"bandwidthSettings": {
|
||||
"assumedBandwidthBps": "Ex. 10000000 para 10 Mbps",
|
||||
"assumedBandwidthBpsWarning": "Valores mais altos podem causar erros de rede.",
|
||||
"customValue": "valor personalizado",
|
||||
"customValueEffect": "para definir o valor de bps real",
|
||||
"leaveEmpty": "deixar vazio",
|
||||
"leaveEmptyEffect": "para permitir que estimativas assumam",
|
||||
"possibleValues": "Valores possíveis",
|
||||
"setAssumedBandwidthBps": "Banda presumida (bps)",
|
||||
"title": "Configurações de banda",
|
||||
"zeroEffect": "para desabilitar o vídeo"
|
||||
},
|
||||
"breakoutRooms": {
|
||||
"actions": {
|
||||
"add": "Adicionar sala de apoio",
|
||||
@@ -48,15 +63,22 @@
|
||||
"leaveBreakoutRoom": "Sair da sala de apoio",
|
||||
"more": "Mais",
|
||||
"remove": "Remover",
|
||||
"rename": "Renomear",
|
||||
"renameBreakoutRoom": "Renomear sala de apoio",
|
||||
"sendToBreakoutRoom": "Enviar participante para:"
|
||||
},
|
||||
"breakoutList": "Lista de apoio",
|
||||
"buttonLabel": "Salas de apoio",
|
||||
"defaultName": "Sala de apoio #{{index}}",
|
||||
"hideParticipantList": "Ocultar lista de participantes",
|
||||
"mainRoom": "Sala principal",
|
||||
"notifications": {
|
||||
"joined": "Entrando na sala de apoio \"{{name}}\"",
|
||||
"joinedMainRoom": "Entrando na sala principal",
|
||||
"joinedTitle": "Salas de apoio"
|
||||
}
|
||||
},
|
||||
"showParticipantList": "Exibir lista de participantes",
|
||||
"title": "Salas de apoio"
|
||||
},
|
||||
"calendarSync": {
|
||||
"addMeetingURL": "Adicionar um link da reunião",
|
||||
@@ -239,9 +261,12 @@
|
||||
"Share": "Compartilhar",
|
||||
"Submit": "Enviar",
|
||||
"WaitForHostMsg": "A conferência ainda não começou. Se você é o anfitrião, faça a autenticação. Do contrário, aguarde a chegada do anfitrião.",
|
||||
"WaitingForHostButton": "Aguardar por anfitrião",
|
||||
"WaitingForHostTitle": "Esperando o anfitrião...",
|
||||
"Yes": "Sim",
|
||||
"accessibilityLabel": {
|
||||
"Cancel": "Cancelar (fechar janela)",
|
||||
"Ok": "OK (salvar e fechar janela)",
|
||||
"close": "Fechar janela",
|
||||
"liveStreaming": "Transmissão ao vivo",
|
||||
"sharingTabs": "Opções de compartilhamento"
|
||||
@@ -250,6 +275,8 @@
|
||||
"addMeetingNote": "Adicionar uma anotação para esta reunião",
|
||||
"addOptionalNote": "Adicionar uma anotação (opcional):",
|
||||
"allow": "Permitir",
|
||||
"allowToggleCameraDialog": "Você permite que {{initiatorName}} possa alternar entre suas câmeras?",
|
||||
"allowToggleCameraTitle": "Permitir alternar câmera?",
|
||||
"alreadySharedVideoMsg": "Outro participante já está compartilhando um vídeo. Esta conferência permite apenas um vídeo compartilhado por vez.",
|
||||
"alreadySharedVideoTitle": "Somente um vídeo compartilhado é permitido por vez",
|
||||
"applicationWindow": "Janela de aplicativo",
|
||||
@@ -310,6 +337,7 @@
|
||||
"lockRoom": "Adicionar reunião $t(lockRoomPasswordUppercase)",
|
||||
"lockTitle": "Bloqueio falhou",
|
||||
"login": "Entrar",
|
||||
"loginQuestion": "Deseja iniciar a sessão e finalizar a conferência?",
|
||||
"logoutQuestion": "Deseja encerrar a sessão e finalizar a conferência?",
|
||||
"logoutTitle": "Encerrar sessão",
|
||||
"maxUsersLimitReached": "O limite para o número máximo de participantes foi atingido. A conferência está cheia. Entre em contato com o proprietário da reunião ou tente novamente mais tarde!",
|
||||
@@ -353,8 +381,6 @@
|
||||
"permissionCameraRequiredError": "É necessário permitir acesso à câmera para participar de reuniões com vídeo. Ative a permissão nas configurações",
|
||||
"permissionErrorTitle": "Permissão necessária",
|
||||
"permissionMicRequiredError": "É necessário permitir acesso ao microfone para participar de reuniões com áudio. Ative a permissão nas configurações",
|
||||
"popupError": "Seu navegador está bloqueando janelas popup deste site. Habilite os popups nas configurações de segurança no seu navegador e tente novamente.",
|
||||
"popupErrorTitle": "Popup bloqueado",
|
||||
"readMore": "mais...",
|
||||
"recentlyUsedObjects": "Seus objetos usados recentemente",
|
||||
"recording": "Gravando",
|
||||
@@ -371,6 +397,8 @@
|
||||
"removePassword": "Remover $t(lockRoomPassword)",
|
||||
"removeSharedVideoMsg": "Deseja remover seu vídeo compartilhado?",
|
||||
"removeSharedVideoTitle": "Remover vídeo compartilhado",
|
||||
"renameBreakoutRoomLabel": "Nome da sala",
|
||||
"renameBreakoutRoomTitle": "Renomear sala de apoio",
|
||||
"reservationError": "Erro de sistema de reserva",
|
||||
"reservationErrorMsg": "Código do erro: {{code}}, mensagem: {{msg}}",
|
||||
"retry": "Tentar novamente",
|
||||
@@ -389,9 +417,11 @@
|
||||
"sendPrivateMessageOk": "Enviar em privado",
|
||||
"sendPrivateMessageTitle": "Enviar em privado?",
|
||||
"serviceUnavailable": "Serviço indisponível",
|
||||
"sessTerminated": "Chamada terminada",
|
||||
"sessionRestarted": "Chamada reiniciada pelo bridge",
|
||||
"sessTerminated": "Chamada encerrada",
|
||||
"sessTerminatedReason": "A chamada foi encerrada",
|
||||
"sessionRestarted": "Chamada reiniciada devido a um erro de conexão.",
|
||||
"shareAudio": "Continuar",
|
||||
"shareAudioAltText": "para compartilhar o conteúdo desejado, acesse \"Aba de navegador\", selecione o conteúdo, ative a caixa de \"compartilhar áudio\" e então clique no botão \"compartilhar\"",
|
||||
"shareAudioTitle": "Como compartilhar áudio",
|
||||
"shareAudioWarningD1": "você precisa parar o compartilhamento de tela antes de compartilhar seu áudio.",
|
||||
"shareAudioWarningD2": "você precisa reiniciar o compartilhamento de tela e selecionar a opção \"compartilhar áudio\".",
|
||||
@@ -421,7 +451,25 @@
|
||||
"thankYou": "Obrigado por usar o {{appName}}!",
|
||||
"token": "token",
|
||||
"tokenAuthFailed": "Desculpe, você não está autorizado a entrar nesta chamada.",
|
||||
"tokenAuthFailedReason": {
|
||||
"audInvalid": "Valor `aud` inválido. Deveria ser `jitsi`.",
|
||||
"contextNotFound": "O objeto `context` está faltando na carga.",
|
||||
"expInvalid": "Valor `exp`inválido.",
|
||||
"featureInvalid": "Recurso inválido: {{feature}}, possivelmente ainda não implementado.",
|
||||
"featureValueInvalid": "Valor inválido para recurso: {{feature}}.",
|
||||
"featuresNotFound": "O objeto `features` está faltando na carga.",
|
||||
"headerNotFound": "Cabeçalho está faltando.",
|
||||
"issInvalid": "Valor `iss` inválido. Deveria ser `chat`.",
|
||||
"kidMismatch": "Key ID (kid) não coincide com o sub.",
|
||||
"kidNotFound": "Key ID (kid) faltando.",
|
||||
"nbfFuture": "O valor `nbf` está no futuro.",
|
||||
"nbfInvalid": "Valor `nbf` inválido.",
|
||||
"payloadNotFound": "Carga faltando.",
|
||||
"tokenExpired": "O token está expirado."
|
||||
},
|
||||
"tokenAuthFailedTitle": "Falha de autenticação",
|
||||
"tokenAuthFailedWithReasons": "Desculpe, você não pode ingressar nesta chamada. Razões possíveis: {{reason}}",
|
||||
"tokenAuthUnsupported": "Token da URL não é suportada.",
|
||||
"transcribing": "Transcrevendo",
|
||||
"unlockRoom": "Remove a reunião $t(lockRoomPassword)",
|
||||
"user": "Usuário",
|
||||
@@ -435,6 +483,10 @@
|
||||
"viewUpgradeOptions": "Ver opções de atualização",
|
||||
"viewUpgradeOptionsContent": "Para obter acesso ilimitado a recursos premium tais como gravação, transcrição, streaming RTMP e muito mais, você precisa atualizar seu plano.",
|
||||
"viewUpgradeOptionsTitle": "Você descobriu um recurso premium!",
|
||||
"whiteboardLimitContent": "Desculpe, o limite de usuários de quadro-branco simultâneos foi atingido.",
|
||||
"whiteboardLimitReference": "Para mais informações por favor visite",
|
||||
"whiteboardLimitReferenceUrl": "nosso website",
|
||||
"whiteboardLimitTitle": "Restrição no uso do quadro-branco",
|
||||
"yourEntireScreen": "Toda sua tela"
|
||||
},
|
||||
"documentSharing": {
|
||||
@@ -447,6 +499,9 @@
|
||||
"title": "Reunião em formato compacto"
|
||||
},
|
||||
"feedback": {
|
||||
"accessibilityLabel": {
|
||||
"yourChoice": "Sua escolha: {{rating}}"
|
||||
},
|
||||
"average": "Média",
|
||||
"bad": "Ruim",
|
||||
"detailsLabel": "Nos conte mais sobre isso.",
|
||||
@@ -507,6 +562,7 @@
|
||||
"password": "$t(lockRoomPasswordUppercase):",
|
||||
"reachedLimit": "Você atingiu o limite do seu plano.",
|
||||
"sip": "endereço SIP",
|
||||
"sipAudioOnly": "Endereço apenas para áudio SIP",
|
||||
"title": "Compartilhar",
|
||||
"tooltip": "Compartilhar link e discagem para esta reunião",
|
||||
"upgradeOptions": "Por favor, verifique as opções de upgrade em"
|
||||
@@ -613,13 +669,13 @@
|
||||
"knockingParticipantList": "Remover lista de participantes",
|
||||
"lobbyChatStartedNotification": "{{moderator}} iniciou uma conversa na sala de espera com {{attendee}}",
|
||||
"lobbyChatStartedTitle": "{{moderator}} iniciou uma conversa na sala de espera com você.",
|
||||
"lobbyClosed": "A sala de espera foi fechada.",
|
||||
"nameField": "Informe seu nome",
|
||||
"notificationLobbyAccessDenied": "{{targetParticipantName}} foi rejeitado por {{originParticipantName}}",
|
||||
"notificationLobbyAccessGranted": "{{targetParticipantName}} foi aceito por {{originParticipantName}}",
|
||||
"notificationLobbyDisabled": "Sala de espera foi desabilitada por {{originParticipantName}}",
|
||||
"notificationLobbyEnabled": "Sala de espera foi habilitada por {{originParticipantName}}",
|
||||
"notificationTitle": "Sala de espera",
|
||||
"passwordField": "Informe a senha da conferência",
|
||||
"passwordJoinButton": "Solicitar",
|
||||
"reject": "Rejeitar",
|
||||
"rejectAll": "Rejeitar todos",
|
||||
@@ -651,9 +707,11 @@
|
||||
"participant": "Participante",
|
||||
"participantStats": "Estatísticas dos Participantes",
|
||||
"selectTabTitle": "🎥 Por favor selecione esta aba para gravar",
|
||||
"sessionToken": "Token de Sessão",
|
||||
"sessionToken": "Token de sessão",
|
||||
"start": "Iniciar gravação",
|
||||
"stop": "Parar a Gravação",
|
||||
"stop": "Parar a gravação",
|
||||
"stopping": "Parando a gravação",
|
||||
"wait": "Por favor aguarde enquanto salvamos sua gravação",
|
||||
"yes": "Sim"
|
||||
},
|
||||
"lockRoomPassword": "senha",
|
||||
@@ -676,6 +734,7 @@
|
||||
"dataChannelClosed": "Qualidade do vídeo prejudicada",
|
||||
"dataChannelClosedDescription": "O canal da ponte foi desconectado, assim a qualidade do vídeo foi limitada a sua configuração mais baixa.",
|
||||
"disabledIframe": "Incorporação destina-se apenas a fins de demonstração, assim esta chamada será desconectada em {{timeout}} minutos.",
|
||||
"disabledIframeSecondary": "Incorporação de {{domain}} é apenas destinado para fins de demonstração, então esta chamada será desconectada em {{timeout}} minutos. Por favor use o <a href='{{jaasDomain}}' rel='noopener noreferrer' target='_blank'>Jitsi as a Service</a> para incorporação em produção!",
|
||||
"disconnected": "desconectado",
|
||||
"displayNotifications": "Exibir notificações para",
|
||||
"dontRemindMe": "Não me lembrar",
|
||||
@@ -722,7 +781,6 @@
|
||||
"newDeviceCameraTitle": "Nova câmera detectada",
|
||||
"noiseSuppressionDesktopAudioDescription": "A supressão de ruído não pode ser habilitada enquanto compartilha o áudio da área de trabalho. Por favor desabilite e tente novamente.",
|
||||
"noiseSuppressionFailedTitle": "Falha ao iniciar a supressão de ruído",
|
||||
"noiseSuppressionNoTrackDescription": "Por favor ative o microfone antes.",
|
||||
"noiseSuppressionStereoDescription": "Supressão de ruído de áudio estéreo não é suportado no momento.",
|
||||
"oldElectronClientDescription1": "Você está usando um versão antiga do cliente Jitsi Meet que possui uma conhecida vulnerabilidade de segurança. Por favor tenha certeza de atulizar para a nossa ",
|
||||
"oldElectronClientDescription2": "última versão",
|
||||
@@ -752,7 +810,9 @@
|
||||
"videoUnmuteBlockedDescription": "A liberação da câmera e compartilhamento de tela foram temporariamente bloqueados devido a limites do sistema.",
|
||||
"videoUnmuteBlockedTitle": "Câmera e compartilhamento de tela bloqueados!",
|
||||
"viewLobby": "Ver sala de espera",
|
||||
"waitingParticipants": "{{waitingParticipants}} pessoas"
|
||||
"waitingParticipants": "{{waitingParticipants}} pessoas",
|
||||
"whiteboardLimitDescription": "Por favor, salve seu progresso pois o limite de usuários logo será atingido e o quadro-branco será fechado.",
|
||||
"whiteboardLimitTitle": "Uso do quadro-branco"
|
||||
},
|
||||
"participantsPane": {
|
||||
"actions": {
|
||||
@@ -761,6 +821,7 @@
|
||||
"askUnmute": "Pedir para ativar som",
|
||||
"audioModeration": "Reativarem seus sons",
|
||||
"blockEveryoneMicCamera": "Bloquear microfone e câmera de todos",
|
||||
"breakoutRooms": "Salas de apoio",
|
||||
"invite": "Convidar alguém",
|
||||
"moreModerationActions": "Mais opções de moderação",
|
||||
"moreModerationControls": "Mais controles de moderação",
|
||||
@@ -937,7 +998,7 @@
|
||||
"limitNotificationDescriptionNative": "Devido a demanda, sua gravação ficará limitada a {{limit}} minutos. Para gravação ilimitada tente <3>{{app}}</3>.",
|
||||
"limitNotificationDescriptionWeb": "Devido a demanda, sua gravação ficará limitada a {{limit}} minutos. Para gravação ilimitada tente <a href={{url}} rel='noopener noreferrer' target='_blank'>{{app}}</a>.",
|
||||
"linkGenerated": "Geramos um link para sua gravação.",
|
||||
"live": "AOVIVO",
|
||||
"live": "AO VIVO",
|
||||
"localRecordingNoNotificationWarning": "A gravação não será anunciada aos outros participantes. Você precisará avisá-los que a reunião está sendo gravada.",
|
||||
"localRecordingNoVideo": "O vídeo não está sendo gravado",
|
||||
"localRecordingStartWarning": "Por favor, certifique-se de ter parado a gravação antes de sair da reunião para garantir que será salva.",
|
||||
@@ -1037,6 +1098,7 @@
|
||||
"alertOk": "OK",
|
||||
"alertTitle": "Atenção",
|
||||
"alertURLText": "A URL digitada do servidor é inválida",
|
||||
"apply": "Aplicar",
|
||||
"buildInfoSection": "Informações de compilação",
|
||||
"conferenceSection": "Conferência",
|
||||
"disableCallIntegration": "Desativar integração de chamada nativa",
|
||||
@@ -1047,12 +1109,14 @@
|
||||
"displayNamePlaceholderText": "Ex: João Silva",
|
||||
"email": "Email",
|
||||
"emailPlaceholderText": "email@exemplo.com.br",
|
||||
"gavatarMessage": "Se seu email está associado com uma conta Gravatar, o usaremos para exibir sua foto de perfil.",
|
||||
"goTo": "Ir para",
|
||||
"header": "Configurações",
|
||||
"help": "Ajuda",
|
||||
"links": "Links",
|
||||
"privacy": "Privacidade",
|
||||
"profileSection": "Perfil",
|
||||
"sdkVersion": "Versão do SDK",
|
||||
"serverURL": "URL do servidor",
|
||||
"showAdvanced": "Mostrar configurações avançadas",
|
||||
"startCarModeInLowBandwidthMode": "Iniciar modo carro em modo de banda baixa",
|
||||
@@ -1104,7 +1168,7 @@
|
||||
"audioOnly": "Alternar para apenas áudio",
|
||||
"audioRoute": "Selecionar o dispositivo de som",
|
||||
"boo": "Vaia",
|
||||
"breakoutRoom": "Entrar/sair da sala de apoio",
|
||||
"breakoutRooms": "Entrar/sair da sala de apoio",
|
||||
"callQuality": "Gerenciar qualidade do vídeo",
|
||||
"carmode": "Modo carro",
|
||||
"cc": "Alternar legendas",
|
||||
@@ -1132,7 +1196,7 @@
|
||||
"hangup": "Sair da chamada",
|
||||
"heading": "Barra de ferramentas",
|
||||
"help": "Ajuda",
|
||||
"hideWhiteboard": "Ocultar quadro branco",
|
||||
"hideWhiteboard": "Ocultar quadro-branco",
|
||||
"invite": "Convidar pessoas",
|
||||
"kick": "Remover participante",
|
||||
"laugh": "Risada",
|
||||
@@ -1173,7 +1237,7 @@
|
||||
"sharedvideo": "Alternar compartilhamento de vídeo",
|
||||
"shortcuts": "Alternar atalhos",
|
||||
"show": "Mostrar no palco",
|
||||
"showWhiteboard": "Exibir quadro branco",
|
||||
"showWhiteboard": "Exibir quadro-branco",
|
||||
"silence": "Silenciar",
|
||||
"speakerStats": "Alternar estatísticas do apresentador",
|
||||
"stopScreenSharing": "Parar de compartilhar sua tela",
|
||||
@@ -1218,7 +1282,7 @@
|
||||
"giphy": "Alternar menu do GIPHY",
|
||||
"hangup": "Sair",
|
||||
"help": "Ajuda",
|
||||
"hideWhiteboard": "Ocultar quadro branco",
|
||||
"hideWhiteboard": "Ocultar quadro-branco",
|
||||
"invite": "Convidar pessoas",
|
||||
"joinBreakoutRoom": "Ingressar na sala de apoio",
|
||||
"laugh": "Risada",
|
||||
@@ -1266,7 +1330,7 @@
|
||||
"shareaudio": "Compartilhar áudio",
|
||||
"sharedvideo": "Compartilhar um vídeo",
|
||||
"shortcuts": "Ver atalhos",
|
||||
"showWhiteboard": "Exibir quadro branco",
|
||||
"showWhiteboard": "Exibir quadro-branco",
|
||||
"silence": "Silêncio",
|
||||
"speakerStats": "Estatísticas do Apresentador",
|
||||
"startScreenSharing": "Iniciar compart. de tela",
|
||||
@@ -1371,6 +1435,10 @@
|
||||
"videomute": "O participante parou a câmera"
|
||||
},
|
||||
"virtualBackground": {
|
||||
"accessibilityLabel": {
|
||||
"currentBackground": "Fundo atual: {{background}}",
|
||||
"selectBackground": "Selecionar um fundo"
|
||||
},
|
||||
"addBackground": "Adicionar novo fundo",
|
||||
"apply": "Aplicar",
|
||||
"backgroundEffectError": "Falha ao aplicar efeito de fundo.",
|
||||
@@ -1457,7 +1525,7 @@
|
||||
},
|
||||
"whiteboard": {
|
||||
"accessibilityLabel": {
|
||||
"heading": "Quadro branco"
|
||||
"heading": "Quadro-branco"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -391,7 +391,7 @@
|
||||
"serviceUnavailable": "Tjänsten otillgänglig",
|
||||
"sessTerminated": "Konferensen avslutades",
|
||||
"sessionRestarted": "Samtal återstartat av bryggan",
|
||||
"shareAudio": "Forstätt",
|
||||
"shareAudio": "Fortsätt",
|
||||
"shareAudioTitle": "Hur man delar ljud",
|
||||
"shareAudioWarningD1": "Du måste avsluta din skärmdelning innan du kan dela ditt ljud",
|
||||
"shareAudioWarningD2": "Du måste starta om din skärmdelning och därefter klicka på \"ljuddelning\"",
|
||||
@@ -427,13 +427,13 @@
|
||||
"user": "Användare",
|
||||
"userIdentifier": "Användar-ID",
|
||||
"userPassword": "Lösenord",
|
||||
"verifyParticipantConfirm": "Dem matchar",
|
||||
"verifyParticipantDismiss": "Dem matchar inte",
|
||||
"verifyParticipantConfirm": "De matchar",
|
||||
"verifyParticipantDismiss": "De matchar inte",
|
||||
"verifyParticipantQuestion": "EXPERIMENTELLT: Fråga deltagaren; {{participantName}} om han/hon kan se samma innehåll, i samma ordning.",
|
||||
"verifyParticipantTitle": "Användarverifikation",
|
||||
"videoLink": "Videolänk",
|
||||
"viewUpgradeOptions": "Se uppgraderings alternativ",
|
||||
"viewUpgradeOptionsContent": "För att få obegränsad tillgång till premiumfunktioner som inspelning, transkriptioner, RTMP -streaming och mer måste du uppgradera din plan.",
|
||||
"viewUpgradeOptionsContent": "För att få obegränsad tillgång till premiumfunktioner som inspelning, transkriptioner, RTMP-streaming och mer måste du uppgradera din plan.",
|
||||
"viewUpgradeOptionsTitle": "Du upptäckte en premiumfunktion!",
|
||||
"yourEntireScreen": "Helskärm"
|
||||
},
|
||||
@@ -458,7 +458,7 @@
|
||||
},
|
||||
"filmstrip": {
|
||||
"accessibilityLabel": {
|
||||
"heading": "Videomineatyrer"
|
||||
"heading": "Videominiatyrer"
|
||||
}
|
||||
},
|
||||
"giphy": {
|
||||
@@ -1278,7 +1278,7 @@
|
||||
"tileViewToggle": "Öppna eller stäng panelvyn",
|
||||
"toggleCamera": "Byta kamera",
|
||||
"unmute": "Slå på ljud",
|
||||
"videoSettings": "Video inställningar",
|
||||
"videoSettings": "Videoinställningar",
|
||||
"videomute": "Inaktivera kameran",
|
||||
"videounmute": "Aktivera kameran"
|
||||
},
|
||||
@@ -1346,9 +1346,9 @@
|
||||
"videothumbnail": {
|
||||
"connectionInfo": "Anslutningsinformation",
|
||||
"domute": "Tysta",
|
||||
"domuteOthers": "Inkativerad ljud för alla andra",
|
||||
"domuteOthers": "Inaktivera ljud för alla andra",
|
||||
"domuteVideo": "Inaktivera kamera",
|
||||
"domuteVideoOfOthers": "Inkativera kamera för alla andra",
|
||||
"domuteVideoOfOthers": "Inaktivera kamera för alla andra",
|
||||
"flip": "Vänd",
|
||||
"grantModerator": "Godkänn moderator",
|
||||
"hideSelfView": "Dölj självvyn",
|
||||
|
||||
@@ -1251,7 +1251,7 @@
|
||||
"pending": "{{displayName}} davet edildi"
|
||||
},
|
||||
"videoStatus": {
|
||||
"adjustFor": "Ayala:",
|
||||
"adjustFor": "Ayarla:",
|
||||
"audioOnly": "SES",
|
||||
"audioOnlyExpanded": "Yalnızca ses modundasınız. Bu mod bant genişliğinden tasarruf sağlar, ancak başkalarının videolarını göremezsiniz.",
|
||||
"bestPerformance": "En iyi performans",
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"addPeople": {
|
||||
"accessibilityLabel": {
|
||||
"meetingLink": "會議連結: {{url}}"
|
||||
"meetingLink": "會議連結:{{url}}"
|
||||
},
|
||||
"add": "邀請",
|
||||
"addContacts": "邀請您的聯絡人",
|
||||
@@ -16,7 +16,7 @@
|
||||
"failedToAdd": "加入與會者失敗",
|
||||
"googleEmail": "Google Email",
|
||||
"inviteMoreHeader": "目前只有您一個人在會議中",
|
||||
"inviteMoreMailSubject": "加入{{appName}}會議",
|
||||
"inviteMoreMailSubject": "加入 {{appName}} 會議",
|
||||
"inviteMorePrompt": "邀請更多人",
|
||||
"linkCopied": "已將連結複製至剪貼簿",
|
||||
"noResults": "沒有符合的搜尋結果",
|
||||
@@ -29,7 +29,7 @@
|
||||
"sipAddresses": "SIP 位址",
|
||||
"telephone": "電話號碼:{{number}}",
|
||||
"title": "邀請他人至會議",
|
||||
"yahooEmail": "Yahoo! Email"
|
||||
"yahooEmail": "Yahoo Email"
|
||||
},
|
||||
"audioDevices": {
|
||||
"bluetooth": "藍牙",
|
||||
@@ -56,24 +56,29 @@
|
||||
},
|
||||
"breakoutRooms": {
|
||||
"actions": {
|
||||
"add": "新增討論室",
|
||||
"autoAssign": "自動分配至討論室",
|
||||
"add": "新增分組討論室",
|
||||
"autoAssign": "自動分配至分組討論室",
|
||||
"close": "關閉",
|
||||
"join": "加入",
|
||||
"leaveBreakoutRoom": "離開討論室",
|
||||
"leaveBreakoutRoom": "離開分組討論室",
|
||||
"more": "更多",
|
||||
"remove": "移除",
|
||||
"rename": "重新命名",
|
||||
"renameBreakoutRoom": "重新命名討論室",
|
||||
"renameBreakoutRoom": "重新命名分組討論室",
|
||||
"sendToBreakoutRoom": "將與會者移至:"
|
||||
},
|
||||
"breakoutList": "分組討論室列表",
|
||||
"buttonLabel": "分組討論室",
|
||||
"defaultName": "分組討論室 #{{index}}",
|
||||
"hideParticipantList": "隱藏與會者列表",
|
||||
"mainRoom": "主會議室",
|
||||
"notifications": {
|
||||
"joined": "正在加入「{{name}}」分組討論室",
|
||||
"joinedMainRoom": "正在加入主會議室",
|
||||
"joinedTitle": "分組討論室"
|
||||
}
|
||||
},
|
||||
"showParticipantList": "顯示與會者列表",
|
||||
"title": "分組討論室"
|
||||
},
|
||||
"calendarSync": {
|
||||
"addMeetingURL": "增加會議連結",
|
||||
@@ -107,11 +112,11 @@
|
||||
"enter": "加入聊天室",
|
||||
"error": "錯誤:您的訊息未被傳送。原因:{{error}}",
|
||||
"fieldPlaceHolder": "在此輸入您的訊息",
|
||||
"lobbyChatMessageTo": "大廳聊天訊息傳送至{{recipient}}",
|
||||
"lobbyChatMessageTo": "大廳聊天訊息傳送至 {{recipient}}",
|
||||
"message": "訊息",
|
||||
"messageAccessibleTitle": "{{user}}:",
|
||||
"messageAccessibleTitleMe": "說:",
|
||||
"messageTo": "傳送私人訊息至{{recipient}}",
|
||||
"messageAccessibleTitleMe": "我:",
|
||||
"messageTo": "傳送私人訊息至 {{recipient}}",
|
||||
"messagebox": "輸入訊息",
|
||||
"newMessages": "新訊息",
|
||||
"nickname": {
|
||||
@@ -120,7 +125,7 @@
|
||||
"titleWithPolls": "輸入名稱來使用聊天與投票"
|
||||
},
|
||||
"noMessagesMessage": "此會議尚無訊息,在此開始對話聊天!",
|
||||
"privateNotice": "傳送私人訊息至{{recipient}}",
|
||||
"privateNotice": "傳送私人訊息至 {{recipient}}",
|
||||
"sendButton": "傳送",
|
||||
"smileysPanel": "Emoji 面板",
|
||||
"tabs": {
|
||||
@@ -133,7 +138,7 @@
|
||||
},
|
||||
"chromeExtensionBanner": {
|
||||
"buttonText": "安裝 Chrome 擴充功能",
|
||||
"buttonTextEdge": "安裝 Edge 外掛程式",
|
||||
"buttonTextEdge": "安裝 Edge 擴充功能",
|
||||
"close": "關閉",
|
||||
"dontShowAgain": "不要再問了",
|
||||
"installExtensionText": "安裝適用於 Google 行事曆及 Office 365 整合的擴充功能"
|
||||
@@ -151,14 +156,14 @@
|
||||
"DISCONNECTED": "已斷線",
|
||||
"DISCONNECTING": "中斷連接中",
|
||||
"ERROR": "錯誤",
|
||||
"FETCH_SESSION_ID": "正在取得工作階段ID...",
|
||||
"GET_SESSION_ID_ERROR": "取得工作階段ID時發生錯誤:{{code}}",
|
||||
"GOT_SESSION_ID": "正在取得工作階段ID...完成",
|
||||
"LOW_BANDWIDTH": "已關閉{{displayName}}的視訊以節省流量"
|
||||
"FETCH_SESSION_ID": "正在取得工作階段 ID...",
|
||||
"GET_SESSION_ID_ERROR": "取得工作階段 ID 時發生錯誤:{{code}}",
|
||||
"GOT_SESSION_ID": "正在取得工作階段 ID... 完成",
|
||||
"LOW_BANDWIDTH": "已關閉 {{displayName}} 的視訊以節省頻寬"
|
||||
},
|
||||
"connectionindicator": {
|
||||
"address": "位址:",
|
||||
"audio_ssrc": "音訊SSRC:",
|
||||
"audio_ssrc": "音訊 SSRC:",
|
||||
"bandwidth": "預估頻寬:",
|
||||
"bitrate": "連線速率:",
|
||||
"bridgeCount": "伺服器數量:",
|
||||
@@ -175,7 +180,7 @@
|
||||
"more": "顯示更多",
|
||||
"no": "否",
|
||||
"packetloss": "封包遺失率:",
|
||||
"participant_id": "與會者ID:",
|
||||
"participant_id": "與會者 ID:",
|
||||
"quality": {
|
||||
"good": "良好",
|
||||
"inactive": "閒置",
|
||||
@@ -192,7 +197,7 @@
|
||||
"status": "連線狀態:",
|
||||
"transport": "傳輸協定:",
|
||||
"transport_plural": "傳輸:",
|
||||
"video_ssrc": "視訊SSRC:",
|
||||
"video_ssrc": "視訊 SSRC:",
|
||||
"yes": "是"
|
||||
},
|
||||
"dateUtils": {
|
||||
@@ -201,33 +206,33 @@
|
||||
"yesterday": "昨天"
|
||||
},
|
||||
"deepLinking": {
|
||||
"appNotInstalled": "您需要在手機上安裝{{app}}行動應用程式才能加入這場會議。",
|
||||
"description": "什麼事情都沒發生?我們已嘗試在您的{{app}}桌面應用程式開啟會議。請再試一次,或是在{{app}}網路應用程式開啟會議。",
|
||||
"descriptionNew": "什麼事情都沒發生?我們已嘗試在您的{{app}}桌面應用程式開啟會議。<br /><br />您可以再試一次,或在網頁上啟動。",
|
||||
"descriptionWithoutWeb": "什麼事情都沒發生?我們已試著將您的會議在桌面應用程式{{app}}中啟動。",
|
||||
"downloadApp": "下載App",
|
||||
"downloadMobileApp": "從App Store下載",
|
||||
"ifDoNotHaveApp": "如果您尚未安裝App:",
|
||||
"ifHaveApp": "如果您已經安裝此App:",
|
||||
"joinInApp": "使用App加入會議",
|
||||
"joinInAppNew": "在APP中加入",
|
||||
"appNotInstalled": "您需要在手機上安裝 {{app}} 應用程式才能加入這場會議。",
|
||||
"description": "什麼事情都沒發生?我們已嘗試在您的 {{app}} 桌面應用程式開啟會議。請再試一次,或是在 {{app}} 網頁應用程式開啟會議。",
|
||||
"descriptionNew": "什麼事情都沒發生?我們已嘗試在您的 {{app}} 桌面應用程式開啟會議。<br /><br />您可以再試一次,或在網頁上啟動。",
|
||||
"descriptionWithoutWeb": "什麼事情都沒發生?我們已試著將您的會議在桌面應用程式 {{app}} 中啟動。",
|
||||
"downloadApp": "下載應用程式",
|
||||
"downloadMobileApp": "從 App Store 下載",
|
||||
"ifDoNotHaveApp": "如果您尚未安裝應用程式:",
|
||||
"ifHaveApp": "如果您已經安裝應用程式:",
|
||||
"joinInApp": "使用應用程式加入會議",
|
||||
"joinInAppNew": "在應用程式中加入",
|
||||
"joinInBrowser": "在瀏覽器中加入",
|
||||
"launchMeetingLabel": "您想如何加入此會議?",
|
||||
"launchWebButton": "在瀏覽器開啟",
|
||||
"noMobileApp": "您尚未安裝該APP?",
|
||||
"noMobileApp": "您尚未安裝該應用程式?",
|
||||
"termsAndConditions": "繼續操作即表示您同意我們的<a href='{{termsAndConditionsLink}}' rel='noopener noreferrer' target='_blank'>條款與條件。</a>",
|
||||
"title": "正在{{app}}發起您的會議...",
|
||||
"titleNew": "正在啟動您的會議...",
|
||||
"title": "正在 {{app}} 開啟您的會議...",
|
||||
"titleNew": "正在開啟您的會議...",
|
||||
"tryAgainButton": "在桌面上再試一次",
|
||||
"unsupportedBrowser": "您似乎正在使用我們不支援的瀏覽器"
|
||||
"unsupportedBrowser": "您似乎正在使用我們不支援的瀏覽器。"
|
||||
},
|
||||
"defaultLink": "例如{{url}}",
|
||||
"defaultNickname": "例如:Jane Pink",
|
||||
"defaultLink": "例如 {{url}}",
|
||||
"defaultNickname": "例如:王小明",
|
||||
"deviceError": {
|
||||
"cameraError": "無法存取您的網路攝影機",
|
||||
"cameraPermission": "獲取網路攝影機權限時發生錯誤",
|
||||
"cameraPermission": "取得網路攝影機權限時發生錯誤",
|
||||
"microphoneError": "無法存取您的麥克風",
|
||||
"microphonePermission": "獲取麥克風權限時發生錯誤"
|
||||
"microphonePermission": "取得麥克風權限時發生錯誤"
|
||||
},
|
||||
"deviceSelection": {
|
||||
"hid": {
|
||||
@@ -239,13 +244,13 @@
|
||||
"noPermission": "未取得權限",
|
||||
"previewUnavailable": "無法預覽",
|
||||
"selectADevice": "選擇裝置",
|
||||
"testAudio": "播放測試聲音"
|
||||
"testAudio": "測試"
|
||||
},
|
||||
"dialIn": {
|
||||
"screenTitle": "通話記錄"
|
||||
},
|
||||
"dialOut": {
|
||||
"statusMessage": "現在狀態為{{status}}"
|
||||
"statusMessage": "現在狀態為 {{status}}"
|
||||
},
|
||||
"dialog": {
|
||||
"Back": "返回",
|
||||
@@ -256,6 +261,7 @@
|
||||
"Share": "分享",
|
||||
"Submit": "送出",
|
||||
"WaitForHostMsg": "此會議尚未開始,如果您是會議主持人,請進行認證並以主持人身分開始會議。",
|
||||
"WaitingForHostButton": "等待主持人",
|
||||
"WaitingForHostTitle": "正在等候主持人加入...",
|
||||
"Yes": "是",
|
||||
"accessibilityLabel": {
|
||||
@@ -269,6 +275,8 @@
|
||||
"addMeetingNote": "新增此會議的備註",
|
||||
"addOptionalNote": "新增備註(選填):",
|
||||
"allow": "允許",
|
||||
"allowToggleCameraDialog": "您要允許 {{initiatorName}} 切換您的鏡頭朝向嗎?",
|
||||
"allowToggleCameraTitle": "要允許切換鏡頭嗎?",
|
||||
"alreadySharedVideoMsg": "其他與會者正在分享影像,同一時間只有一個與會者可以分享影像螢幕。",
|
||||
"alreadySharedVideoTitle": "同一時間只允許一位影像分享",
|
||||
"applicationWindow": "應用程式視窗",
|
||||
@@ -277,14 +285,14 @@
|
||||
"cameraNotFoundError": "找不到網路攝影機。",
|
||||
"cameraNotSendingData": "我們無法存取您的網路攝影機,請檢查是否有其他應用程式正在使用這個裝置,並從裝置選單裡選擇其他設備或者重新載入。",
|
||||
"cameraNotSendingDataTitle": "無法存取網路攝影機",
|
||||
"cameraPermissionDeniedError": "未取得網路攝影機的存取權,您仍可參加會議,但其他人無法看到你。按一下網址列中的「攝影機」圖示 ,然後選取「一律允許」選項。",
|
||||
"cameraPermissionDeniedError": "未取得網路攝影機的存取權,您仍可參加會議,但其他人無法看到您。按一下網址列中的「攝影機」圖示 ,然後選取「一律允許」選項。",
|
||||
"cameraTimeoutError": "無法啟動視訊裝置,連線逾時!",
|
||||
"cameraUnknownError": "由於不明原因,無法存取網路攝影機。",
|
||||
"cameraUnsupportedResolutionError": "您的網路攝影機不支援所需的影像解析度。",
|
||||
"close": "關閉",
|
||||
"conferenceDisconnectMsg": "請檢查一下網路連線,將在{{seconds}}秒後重新連接...",
|
||||
"conferenceDisconnectMsg": "請檢查一下網路連線,將在 {{seconds}} 秒後重新連接...",
|
||||
"conferenceDisconnectTitle": "您已經被中斷連接。",
|
||||
"conferenceReloadMsg": "我們正試著修復狀況,將在{{seconds}}秒後重新連接...",
|
||||
"conferenceReloadMsg": "我們正試著修復狀況,將在 {{seconds}} 秒後重新連接...",
|
||||
"conferenceReloadTitle": "喔哦!好像有東西壞掉囉。",
|
||||
"confirm": "確認",
|
||||
"confirmNo": "否",
|
||||
@@ -298,7 +306,7 @@
|
||||
"dismiss": "取消",
|
||||
"displayNameRequired": "嗨!請問大名?",
|
||||
"done": "完成",
|
||||
"e2eeDescription": "請注意,端對端加密目前是實驗性功能,啟用端對端加密將停用部分伺服器端提供的服務,例如:透過電話加入會議。另外,透過網頁版加入會議還需要使用支援Insertable Streams的瀏覽器。",
|
||||
"e2eeDescription": "請注意,端對端加密目前是實驗性功能,啟用端對端加密將停用部分伺服器端提供的服務,例如:透過電話加入會議。另外,透過網頁版加入會議還需要使用支援 Insertable Streams 的瀏覽器。",
|
||||
"e2eeDisabledDueToMaxModeDescription": "由於會議中的人數過多,故無法啟用端對端加密。",
|
||||
"e2eeLabel": "啟用端對端加密",
|
||||
"e2eeWarning": "警告:看來此會議中不是每位與會者都啟用了端對端加密,如果您啟用了,他們可能無法看或聽到您。",
|
||||
@@ -307,7 +315,7 @@
|
||||
"enterDisplayName": "請在此輸入您自己的名字",
|
||||
"error": "錯誤",
|
||||
"gracefulShutdown": "服務目前正在維護中,請稍後再試。",
|
||||
"grantModeratorDialog": "您確定要授予{{participantName}}主持人權限嗎?",
|
||||
"grantModeratorDialog": "您確定要授予 {{participantName}} 主持人權限嗎?",
|
||||
"grantModeratorTitle": "授予主持人權限",
|
||||
"hide": "隱藏",
|
||||
"hideShareAudioHelper": "不再顯示",
|
||||
@@ -315,16 +323,16 @@
|
||||
"incorrectRoomLockPassword": "密碼不符",
|
||||
"internalError": "喔哦!出現了點問題,發生錯誤:{{error}}",
|
||||
"internalErrorTitle": "內部錯誤",
|
||||
"kickMessage": "您可以聯絡{{participantDisplayName}}取得更詳細資訊。",
|
||||
"kickMessage": "您可以聯絡 {{participantDisplayName}} 取得更詳細資訊。",
|
||||
"kickParticipantButton": "移除",
|
||||
"kickParticipantDialog": "您確定要將這位與會者移除嗎?",
|
||||
"kickParticipantTitle": "移除這位與會者?",
|
||||
"kickTitle": "噢!{{participantDisplayName}}將您從會議中移除",
|
||||
"kickTitle": "噢!{{participantDisplayName}} 將您從會議中移除",
|
||||
"linkMeeting": "連結會議",
|
||||
"linkMeetingTitle": "將會議連結至 Salesforce",
|
||||
"liveStreaming": "直播串流中",
|
||||
"liveStreamingDisabledBecauseOfActiveRecordingTooltip": "正在錄製,無法使用",
|
||||
"localUserControls": "本地使用者控制",
|
||||
"localUserControls": "本機使用者控制",
|
||||
"lockMessage": "無法鎖定會議。",
|
||||
"lockRoom": "新增會議 $t(lockRoomPasswordUppercase)",
|
||||
"lockTitle": "鎖定失敗",
|
||||
@@ -346,9 +354,9 @@
|
||||
"muteEveryoneDialog": "與會者可以隨時解除自己的靜音狀態。",
|
||||
"muteEveryoneDialogModerationOn": "與會者可以隨時請求發言。",
|
||||
"muteEveryoneElseDialog": "靜音後,您就不能再解除對方的靜音,但對方可以隨時解除自己的靜音狀態。",
|
||||
"muteEveryoneElseTitle": "是否要讓除了{{whom}}以外的人靜音?",
|
||||
"muteEveryoneElseTitle": "是否要讓除了 {{whom}} 以外的人靜音?",
|
||||
"muteEveryoneElsesVideoDialog": "一旦停用,您就不能再重新開啟對方的網路攝影機,但對方隨時能重新開啟自己的網路攝影機。",
|
||||
"muteEveryoneElsesVideoTitle": "是否要關閉除了{{whom}}以外的人的網路攝影機?",
|
||||
"muteEveryoneElsesVideoTitle": "是否要關閉除了 {{whom}} 以外的人的網路攝影機?",
|
||||
"muteEveryoneSelf": "您自己",
|
||||
"muteEveryoneStartMuted": "現在所有人皆已靜音",
|
||||
"muteEveryoneTitle": "要將所有人靜音嗎?",
|
||||
@@ -364,12 +372,12 @@
|
||||
"muteParticipantsVideoDialog": "確定要停用這位與會者的網路攝影機?您不能再重新開啟對方的網路攝影機,但他們隨時能重新開啟。",
|
||||
"muteParticipantsVideoDialogModerationOn": "您確定要關閉此與會者的網路攝影機嗎?您和他都無法再將視訊重新開啟。",
|
||||
"muteParticipantsVideoTitle": "要關閉此與會者的網路攝影機嗎?",
|
||||
"noDropboxToken": "沒有有效的 Dropbox token",
|
||||
"noDropboxToken": "沒有有效的 Dropbox 權杖",
|
||||
"password": "密碼",
|
||||
"passwordLabel": "會議已被一位與會者鎖定,請輸入$t(lockRoomPassword)以加入。",
|
||||
"passwordNotSupported": "尚未支援設定會議$t(lockRoomPassword)。",
|
||||
"passwordNotSupportedTitle": "尚未支援$t(lockRoomPasswordUppercase)",
|
||||
"passwordRequired": "需要$t(lockRoomPasswordUppercase)",
|
||||
"passwordLabel": "會議已被一位與會者鎖定,請輸入 $t(lockRoomPassword) 以加入。",
|
||||
"passwordNotSupported": "尚未支援設定會議 $t(lockRoomPassword)。",
|
||||
"passwordNotSupportedTitle": "尚未支援 $t(lockRoomPasswordUppercase)",
|
||||
"passwordRequired": "需要 $t(lockRoomPasswordUppercase)",
|
||||
"permissionCameraRequiredError": "參與視訊會議需要存取網路攝影機,請在設定中啟用權限",
|
||||
"permissionErrorTitle": "需要權限",
|
||||
"permissionMicRequiredError": "參與音訊會議需要存取麥克風,請在設定中啟用權限",
|
||||
@@ -378,19 +386,19 @@
|
||||
"recording": "錄製中",
|
||||
"recordingDisabledBecauseOfActiveLiveStreamingTooltip": "正在直播時無法使用",
|
||||
"rejoinNow": "立即重新加入",
|
||||
"remoteControlAllowedMessage": "{{user}}接受您進行遠端控制的請求!",
|
||||
"remoteControlDeniedMessage": "{{user}}拒絕您進行遠端控制的請求!",
|
||||
"remoteControlErrorMessage": "在嘗試向{{user}}請求遠端控制權限時發生錯誤!",
|
||||
"remoteControlRequestMessage": "您要允許{{user}}遠端控制您的桌面嗎?",
|
||||
"remoteControlAllowedMessage": "{{user}} 接受您進行遠端控制的請求!",
|
||||
"remoteControlDeniedMessage": "{{user}} 拒絕您進行遠端控制的請求!",
|
||||
"remoteControlErrorMessage": "在嘗試向 {{user}} 請求遠端控制權限時發生錯誤!",
|
||||
"remoteControlRequestMessage": "您要允許 {{user}} 遠端控制您的桌面嗎?",
|
||||
"remoteControlShareScreenWarning": "請注意:如果按下「允許」您將會分享自己的螢幕!",
|
||||
"remoteControlStopMessage": "遠端控制會話已結束!",
|
||||
"remoteControlTitle": "遠端桌面控制",
|
||||
"remoteUserControls": "{{username}}的遠端使用者控制",
|
||||
"remoteUserControls": "{{username}} 的遠端使用者控制",
|
||||
"removePassword": "移除 $t(lockRoomPassword)",
|
||||
"removeSharedVideoMsg": "您確定要移除您分享的影像嗎?",
|
||||
"removeSharedVideoTitle": "移除分享的影像",
|
||||
"renameBreakoutRoomLabel": "討論室名稱",
|
||||
"renameBreakoutRoomTitle": "重新命名討論室",
|
||||
"renameBreakoutRoomLabel": "分組討論室名稱",
|
||||
"renameBreakoutRoomTitle": "重新命名分組討論室",
|
||||
"reservationError": "預約系統錯誤",
|
||||
"reservationErrorMsg": "錯誤代碼:{{code}},訊息:{{msg}}",
|
||||
"retry": "重試",
|
||||
@@ -410,6 +418,7 @@
|
||||
"sendPrivateMessageTitle": "私人回覆?",
|
||||
"serviceUnavailable": "服務無法使用",
|
||||
"sessTerminated": "通話已經終止",
|
||||
"sessTerminatedReason": "會議已經終止",
|
||||
"sessionRestarted": "通話因連線問題重新啟動。",
|
||||
"shareAudio": "繼續",
|
||||
"shareAudioTitle": "如何分享音訊",
|
||||
@@ -438,7 +447,7 @@
|
||||
"stopRecordingWarning": "確定要停用錄製嗎?",
|
||||
"stopStreamingWarning": "確定要停止直播串流嗎?",
|
||||
"streamKey": "直播串流金鑰",
|
||||
"thankYou": "感謝您使用{{appName}}!",
|
||||
"thankYou": "感謝您使用 {{appName}}!",
|
||||
"token": "token",
|
||||
"tokenAuthFailed": "抱歉,您未被允許加入這個通話。",
|
||||
"tokenAuthFailedReason": {
|
||||
@@ -450,29 +459,33 @@
|
||||
"featuresNotFound": "`context` 未在負載中找到。",
|
||||
"headerNotFound": "標頭缺失。",
|
||||
"issInvalid": "無效的`iss`值,應為`chat`。",
|
||||
"kidMismatch": "金鑰ID(kid)與子項不符。",
|
||||
"kidNotFound": "缺少金鑰ID(kid)。",
|
||||
"kidMismatch": "金鑰 ID(kid)與子項不符。",
|
||||
"kidNotFound": "缺少金鑰 ID(kid)。",
|
||||
"nbfFuture": "`nbf`值在未來。",
|
||||
"nbfInvalid": "無效的`nbf`值。",
|
||||
"payloadNotFound": "未找到負載。",
|
||||
"tokenExpired": "Token已過期。"
|
||||
"payloadNotFound": "負載缺失。",
|
||||
"tokenExpired": "權杖已過期。"
|
||||
},
|
||||
"tokenAuthFailedTitle": "驗證失敗",
|
||||
"tokenAuthFailedWithReasons": "抱歉,您無法參加這個通話,可能原因:{{reason}}",
|
||||
"tokenAuthUnsupported": "不支援的令牌位址。",
|
||||
"tokenAuthUnsupported": "不支援權杖網址。",
|
||||
"transcribing": "轉錄中",
|
||||
"unlockRoom": "移除會議 $t(lockRoomPassword)",
|
||||
"user": "使用者",
|
||||
"userIdentifier": "使用者ID",
|
||||
"userIdentifier": "使用者 ID",
|
||||
"userPassword": "使用者密碼",
|
||||
"verifyParticipantConfirm": "符合",
|
||||
"verifyParticipantDismiss": "不符合",
|
||||
"verifyParticipantQuestion": "實驗性功能:詢問與會者{{participantName}}是否以相同順序看到相同內容。",
|
||||
"verifyParticipantQuestion": "實驗性功能:詢問與會者 {{participantName}} 是否以相同順序看到相同內容。",
|
||||
"verifyParticipantTitle": "使用者驗證",
|
||||
"videoLink": "影片連結",
|
||||
"viewUpgradeOptions": "查看升級方案",
|
||||
"viewUpgradeOptionsContent": "若要不受限制地使用錄製、逐字稿、RTMP 串流等進階版功能,您需要升級您的方案。",
|
||||
"viewUpgradeOptionsTitle": "您找到了進階版功能!",
|
||||
"whiteboardLimitContent": "抱歉,已達到白板使用者限制。",
|
||||
"whiteboardLimitReference": "若要了解詳情,請前往",
|
||||
"whiteboardLimitReferenceUrl": "我們的網站",
|
||||
"whiteboardLimitTitle": "白板使用受限",
|
||||
"yourEntireScreen": "您的整個螢幕"
|
||||
},
|
||||
"documentSharing": {
|
||||
@@ -521,7 +534,7 @@
|
||||
"copyNumber": "複製號碼",
|
||||
"country": "國家",
|
||||
"dialANumber": "若要參加您的會議,請撥打以下其中一支號碼,然後輸入 PIN 碼。",
|
||||
"dialInConferenceID": "PIN碼:",
|
||||
"dialInConferenceID": "PIN 碼:",
|
||||
"dialInNotSupported": "抱歉,目前不支援電話撥入。",
|
||||
"dialInNumber": "撥入:",
|
||||
"dialInSummaryError": "目前解析撥入資訊錯誤,請稍後再試一次。",
|
||||
@@ -536,7 +549,7 @@
|
||||
"inviteTextiOSPersonal": "{{name}}邀請您加入會議。",
|
||||
"inviteTextiOSPhone": "若要透過電話加入,請使用此號碼:{{number}},,{{conferenceID}}#。如果您需要其他號碼,點擊此連結以檢視完整列表:{{didUrl}}。",
|
||||
"inviteURLFirstPartGeneral": "您受邀參加會議。",
|
||||
"inviteURLFirstPartPersonal": "{{name}}正在邀請您加入會議。\n",
|
||||
"inviteURLFirstPartPersonal": "{{name}} 正在邀請您加入會議。\n",
|
||||
"inviteURLSecondPart": "\n加入會議:\n{{url}}\n",
|
||||
"label": "撥入資訊",
|
||||
"liveStreamURL": "直播串流:",
|
||||
@@ -547,7 +560,8 @@
|
||||
"numbers": "撥入號碼",
|
||||
"password": "$t(lockRoomPasswordUppercase):",
|
||||
"reachedLimit": "您已達到您的方案上限",
|
||||
"sip": "SIP位址",
|
||||
"sip": "SIP 位址",
|
||||
"sipAudioOnly": "SIP 僅音訊位址",
|
||||
"title": "分享",
|
||||
"tooltip": "顯示此會議的連結及電話撥入號碼",
|
||||
"upgradeOptions": "請查看升級選項於"
|
||||
@@ -566,7 +580,7 @@
|
||||
"searchPlaceholder": "與會者或電話號碼",
|
||||
"send": "傳送"
|
||||
},
|
||||
"jitsiHome": "{{logo}}商標,首頁連結",
|
||||
"jitsiHome": "{{logo}} 商標,首頁連結",
|
||||
"keyboardShortcuts": {
|
||||
"focusLocal": "聚焦於自己的影像",
|
||||
"focusRemote": "聚焦於另一人的影像",
|
||||
@@ -594,11 +608,11 @@
|
||||
"busyTitle": "全部直播設備正在忙碌",
|
||||
"changeSignIn": "切換帳號",
|
||||
"choose": "選擇直播串流",
|
||||
"chooseCTA": "請選擇直播串流選項,您目前是以{{email}}身份登入。",
|
||||
"chooseCTA": "請選擇直播串流選項,您目前是以 {{email}} 身份登入。",
|
||||
"enterStreamKey": "在此輸入您的 YouTube 直播串流金鑰。",
|
||||
"error": "直播串流失敗,請重試。",
|
||||
"errorAPI": "在存取您的 YouTube 直播時發生問題,請重新登入。",
|
||||
"errorLiveStreamNotEnabled": "直播在{{email}}尚未啟用,請開啟直播串流或登入有啟用直播串流的帳號。",
|
||||
"errorLiveStreamNotEnabled": "直播在 {{email}} 尚未啟用,請開啟直播串流或登入有啟用直播串流的帳號。",
|
||||
"expandedOff": "直播已停用",
|
||||
"expandedOn": "會議目前正在 YouTube 上直播。",
|
||||
"expandedPending": "直播串流正被啟動...",
|
||||
@@ -607,12 +621,12 @@
|
||||
"googlePrivacyPolicy": "Google 隱私權政策",
|
||||
"inProgress": "正在錄製或直播",
|
||||
"invalidStreamKey": "直播串流金鑰可能不正確。",
|
||||
"limitNotificationDescriptionNative": "您的最大直播長度將被限制在{{limit}}分鐘,若要不受限的直播,請使用{{app}}。",
|
||||
"limitNotificationDescriptionWeb": "由於目前流量過大,您的最大直播長度將被限制在{{limit}}分鐘。若要不受限的直播,請使用<a href={{url}} rel='noopener noreferrer' target='_blank'>{{app}}</a>。",
|
||||
"limitNotificationDescriptionNative": "您的最大直播長度將被限制在 {{limit}} 分鐘,若要不受限的直播,請使用 {{app}}。",
|
||||
"limitNotificationDescriptionWeb": "由於目前流量過大,您的最大直播長度將被限制在 {{limit}} 分鐘。若要不受限的直播,請使用 <a href={{url}} rel='noopener noreferrer' target='_blank'>{{app}}</a>。",
|
||||
"off": "直播串流已停用",
|
||||
"offBy": "{{name}}停用了直播串流",
|
||||
"offBy": "{{name}} 停用了直播串流",
|
||||
"on": "直播串流已啟動",
|
||||
"onBy": "{{name}}啟動了直播串流",
|
||||
"onBy": "{{name}} 啟動了直播串流",
|
||||
"pending": "啟動直播串流...",
|
||||
"serviceName": "直播串流服務",
|
||||
"sessionAlreadyActive": "已在錄製或直播此工作階段。",
|
||||
@@ -652,13 +666,13 @@
|
||||
"knockButton": "請求加入",
|
||||
"knockTitle": "有人想要加入會議",
|
||||
"knockingParticipantList": "請求加入的與會者名單",
|
||||
"lobbyChatStartedNotification": "{{moderator}}與{{attendee}}開始在大廳中聊天",
|
||||
"lobbyChatStartedTitle": "{{moderator}}與您開始在大廳中聊天。",
|
||||
"lobbyChatStartedNotification": "{{moderator}} 與 {{attendee}} 開始在大廳中聊天",
|
||||
"lobbyChatStartedTitle": "{{moderator}} 與您開始在大廳中聊天。",
|
||||
"nameField": "輸入您的名字",
|
||||
"notificationLobbyAccessDenied": "{{originParticipantName}}拒絕了{{targetParticipantName}}的加入請求",
|
||||
"notificationLobbyAccessGranted": "{{originParticipantName}}同意了{{targetParticipantName}}的加入請求",
|
||||
"notificationLobbyDisabled": "{{originParticipantName}}已停用大廳模式",
|
||||
"notificationLobbyEnabled": "{{originParticipantName}}已啟用大廳模式",
|
||||
"notificationLobbyAccessDenied": "{{originParticipantName}} 拒絕了 {{targetParticipantName}} 的加入請求",
|
||||
"notificationLobbyAccessGranted": "{{originParticipantName}} 同意了 {{targetParticipantName}} 的加入請求",
|
||||
"notificationLobbyDisabled": "{{originParticipantName}} 已停用大廳模式",
|
||||
"notificationLobbyEnabled": "{{originParticipantName}} 已啟用大廳模式",
|
||||
"notificationTitle": "大廳",
|
||||
"passwordField": "輸入會議密碼",
|
||||
"passwordJoinButton": "加入",
|
||||
@@ -673,19 +687,19 @@
|
||||
"on": "開啟",
|
||||
"unknown": "未知"
|
||||
},
|
||||
"dialogTitle": "本地錄製控制",
|
||||
"dialogTitle": "本機錄製控制",
|
||||
"duration": "時長",
|
||||
"durationNA": "不適用",
|
||||
"encoding": "編碼中",
|
||||
"label": "本地錄製",
|
||||
"labelToolTip": "本地錄製已啟用",
|
||||
"localRecording": "本地錄製中",
|
||||
"label": "本機錄製",
|
||||
"labelToolTip": "本機錄製已啟用",
|
||||
"localRecording": "本機錄製中",
|
||||
"me": "我",
|
||||
"messages": {
|
||||
"engaged": "已啟用本地錄製。",
|
||||
"engaged": "已啟用本機錄製。",
|
||||
"finished": "錄製會話 {{token}} 已結束,請將傳送錄製檔案至主持人。",
|
||||
"finishedModerator": "錄製階段{{token}}已完成,本地錄製追蹤已存檔,請要求各與會者提供其錄製檔案。",
|
||||
"notModerator": "您不是主持人,無法開始或停止本地錄製。"
|
||||
"finishedModerator": "錄製階段{{token}} 已完成,本機錄製追蹤已存檔,請要求各與會者提供其錄製檔案。",
|
||||
"notModerator": "您不是主持人,無法開始或停止本機錄製。"
|
||||
},
|
||||
"moderator": "主持人",
|
||||
"no": "否",
|
||||
@@ -713,36 +727,37 @@
|
||||
"audioUnmuteBlockedDescription": "麥克風解除靜音操作由於系統限制而被暫時封鎖。",
|
||||
"audioUnmuteBlockedTitle": "麥克風解除靜音遭封鎖!",
|
||||
"chatMessages": "聊天訊息",
|
||||
"connectedOneMember": "{{name}}加入了會議",
|
||||
"connectedThreePlusMembers": "{{name}}與其他人加入了會議",
|
||||
"connectedTwoMembers": "{{first}}與{{second}}加入了會議",
|
||||
"connectedOneMember": "{{name}} 加入了會議",
|
||||
"connectedThreePlusMembers": "{{name}} 與其他人加入了會議",
|
||||
"connectedTwoMembers": "{{first}} 與{{second}} 加入了會議",
|
||||
"dataChannelClosed": "視訊品質受限",
|
||||
"dataChannelClosedDescription": "橋接通道已斷開,視訊品質降至最低設定。",
|
||||
"disabledIframe": "嵌入僅供示範使用,此通話將於 {{timeout}} 分鐘後中斷連線。",
|
||||
"disabledIframeSecondary": "內嵌 {{domain}} 僅為展示用途,此通話將在 {{timeout}} 分鐘後中斷連線。請使用在正式環境使用 <a href='{{jaasDomain}}' rel='noopener noreferrer' target='_blank'>Jitsi 服務</a>來內嵌!",
|
||||
"disconnected": "已經中斷連接",
|
||||
"displayNotifications": "顯示通知給",
|
||||
"dontRemindMe": "不要再提醒我",
|
||||
"focus": "會議焦點",
|
||||
"focusFail": "{{component}}無法使用 - {{ms}}秒後重試",
|
||||
"focusFail": "{{component}} 無法使用 - {{ms}} 秒後重試",
|
||||
"gifsMenu": "GIPHY",
|
||||
"groupTitle": "通知",
|
||||
"hostAskedUnmute": "主持人希望你發言",
|
||||
"invitedOneMember": "{{name}}已受邀請",
|
||||
"invitedThreePlusMembers": "{{name}}與{{count}}位人員已受邀請",
|
||||
"invitedTwoMembers": "{{first}}與{{second}}已受邀請",
|
||||
"hostAskedUnmute": "主持人希望您發言",
|
||||
"invitedOneMember": "{{name}} 已受邀請",
|
||||
"invitedThreePlusMembers": "{{name}} 與 {{count}} 位人員已受邀請",
|
||||
"invitedTwoMembers": "{{first}} 與 {{second}} 已受邀請",
|
||||
"joinMeeting": "加入",
|
||||
"kickParticipant": "{{kicked}}已被{{kicker}}移除會議",
|
||||
"leftOneMember": "{{name}}已離開會議",
|
||||
"leftThreePlusMembers": "{{name}}與其他人已離開會議",
|
||||
"leftTwoMembers": "{{first}}與{{second}}已離開會議",
|
||||
"kickParticipant": "{{kicked}} 已被 {{kicker}} 移除會議",
|
||||
"leftOneMember": "{{name}} 已離開會議",
|
||||
"leftThreePlusMembers": "{{name}} 與其他人已離開會議",
|
||||
"leftTwoMembers": "{{first}} 與 {{second}} 已離開會議",
|
||||
"linkToSalesforce": "連結至 Salesforce",
|
||||
"linkToSalesforceDescription": "您可以將會議摘要連結至 Salesforce 物件。",
|
||||
"linkToSalesforceError": "無法將會議連結至 Salesforce",
|
||||
"linkToSalesforceKey": "連結此會議",
|
||||
"linkToSalesforceProgress": "正在將會議連結至 Salesforce...",
|
||||
"linkToSalesforceSuccess": "會議已連結至 Salesforce",
|
||||
"localRecordingStarted": "{{name}}已啟用本地錄製",
|
||||
"localRecordingStopped": "{{name}}已停用本地錄製",
|
||||
"localRecordingStarted": "{{name}} 已啟用本機錄製",
|
||||
"localRecordingStopped": "{{name}} 已停用本機錄製",
|
||||
"me": "我",
|
||||
"moderationInEffectCSDescription": "若要分享您的螢幕,請舉手",
|
||||
"moderationInEffectCSTitle": "分享螢幕已被主持人停用",
|
||||
@@ -754,11 +769,11 @@
|
||||
"moderationRequestFromParticipant": "想要發言",
|
||||
"moderationStartedTitle": "開始主持",
|
||||
"moderationStoppedTitle": "停止主持",
|
||||
"moderationToggleDescription": "由{{participantDisplayName}}",
|
||||
"moderationToggleDescription": "由 {{participantDisplayName}}",
|
||||
"moderator": "主持人權限已經取得!",
|
||||
"muted": "您已經啟動通話,處於靜音。",
|
||||
"mutedRemotelyDescription": "當您準備好要發言,隨時可以取消靜音。當您結束之後再回復成靜音,保持會議安靜。",
|
||||
"mutedRemotelyTitle": "您已經被{{participantDisplayName}}設為靜音!",
|
||||
"mutedRemotelyTitle": "您已經被 {{participantDisplayName}} 設為靜音!",
|
||||
"mutedTitle": "您目前處於靜音!",
|
||||
"newDeviceAction": "使用",
|
||||
"newDeviceAudioTitle": "偵測到新的音效裝置",
|
||||
@@ -771,11 +786,11 @@
|
||||
"oldElectronClientDescription3": "!",
|
||||
"participantWantsToJoin": "希望加入會議",
|
||||
"participantsWantToJoin": "希望加入會議",
|
||||
"passwordRemovedRemotely": "$t(lockRoomPasswordUppercase)已被其他與會者移除",
|
||||
"passwordSetRemotely": "$t(lockRoomPasswordUppercase)由其他與會者設定",
|
||||
"passwordRemovedRemotely": "$t(lockRoomPasswordUppercase) 已被其他與會者移除",
|
||||
"passwordSetRemotely": "$t(lockRoomPasswordUppercase) 由其他與會者設定",
|
||||
"raiseHandAction": "舉手發言",
|
||||
"raisedHand": "{{name}}想要發言。",
|
||||
"raisedHands": "{{participantName}}與其他{{raisedHands}}人",
|
||||
"raisedHands": "{{participantName}} 與其他 {{raisedHands}} 人",
|
||||
"reactionSounds": "停用音效",
|
||||
"reactionSoundsForAll": "停用所有音效",
|
||||
"screenShareNoAudio": "您未在選擇視窗時勾選分享音訊",
|
||||
@@ -790,11 +805,13 @@
|
||||
"suboptimalExperienceTitle": "瀏覽器警告",
|
||||
"unmute": "取消靜音",
|
||||
"videoMutedRemotelyDescription": "您隨時可以再次啟用。",
|
||||
"videoMutedRemotelyTitle": "您的視訊已被{{participantDisplayName}}停用",
|
||||
"videoMutedRemotelyTitle": "您的視訊已被 {{participantDisplayName}} 停用",
|
||||
"videoUnmuteBlockedDescription": "啟用網路攝影機與分享螢幕由於系統限制而被暫時封鎖。",
|
||||
"videoUnmuteBlockedTitle": "啟用網路攝影機與分享螢幕遭封鎖!",
|
||||
"viewLobby": "檢視大廳",
|
||||
"waitingParticipants": "{{waitingParticipants}}人"
|
||||
"waitingParticipants": "{{waitingParticipants}} 人",
|
||||
"whiteboardLimitDescription": "由於即將超出使用者限制,白板將關閉,請儲存您的進度。",
|
||||
"whiteboardLimitTitle": "白板使用情況"
|
||||
},
|
||||
"participantsPane": {
|
||||
"actions": {
|
||||
@@ -803,6 +820,7 @@
|
||||
"askUnmute": "要求解除靜音",
|
||||
"audioModeration": "自我解除靜音",
|
||||
"blockEveryoneMicCamera": "停用所有人的麥克風和網路攝影機",
|
||||
"breakoutRooms": "分組討論室",
|
||||
"invite": "邀請他人",
|
||||
"moreModerationActions": "更多主持人選項",
|
||||
"moreModerationControls": "更多主持人操作",
|
||||
@@ -817,15 +835,15 @@
|
||||
},
|
||||
"close": "關閉",
|
||||
"headings": {
|
||||
"lobby": "大廳({{count}}人)",
|
||||
"participantsList": "會議與會者({{count}}人)",
|
||||
"visitors": "訪客({{count}}人)",
|
||||
"waitingLobby": "於大廳等候({{count}}人)"
|
||||
"lobby": "大廳({{count}} 人)",
|
||||
"participantsList": "會議與會者({{count}} 人)",
|
||||
"visitors": "訪客({{count}} 人)",
|
||||
"waitingLobby": "於大廳等候({{count}} 人)"
|
||||
},
|
||||
"search": "搜尋與會者",
|
||||
"title": "與會者"
|
||||
},
|
||||
"passwordDigitsOnly": "上限為{{number}}位數",
|
||||
"passwordDigitsOnly": "上限為 {{number}} 位數",
|
||||
"passwordSetRemotely": "由其他與會者設定",
|
||||
"pinParticipant": "{{participantName}} - 釘選",
|
||||
"pinnedParticipant": "與會者被釘選",
|
||||
@@ -834,13 +852,13 @@
|
||||
"skip": "跳過",
|
||||
"submit": "送出"
|
||||
},
|
||||
"by": "由{{ name }}",
|
||||
"by": "由 {{ name }}",
|
||||
"create": {
|
||||
"addOption": "新增選項",
|
||||
"answerPlaceholder": "選項{{index}}",
|
||||
"answerPlaceholder": "選項 {{index}}",
|
||||
"cancel": "取消",
|
||||
"create": "建立投票",
|
||||
"pollOption": "選項{{index}}",
|
||||
"pollOption": "選項 {{index}}",
|
||||
"pollQuestion": "投票問題",
|
||||
"questionPlaceholder": "詢問問題",
|
||||
"removeOption": "移除選項",
|
||||
@@ -879,7 +897,7 @@
|
||||
"audioHighQuality": "您的音訊品質極佳。",
|
||||
"audioLowNoVideo": "您的音訊品質較差,且無視訊功能。",
|
||||
"goodQuality": "太好了!您的媒體品質良好。",
|
||||
"noMediaConnectivity": "我們無法為此測試建立媒體連線,通常是防火牆或NAT的問題。",
|
||||
"noMediaConnectivity": "我們無法為此測試建立媒體連線,通常是防火牆或 NAT 的問題。",
|
||||
"noVideo": "您的視訊畫質將會很糟糕。",
|
||||
"undetectable": "如果您仍無法在瀏覽器中進行通話,我們建議您檢查喇叭、麥克風、及網路攝影機的設置,確認是否允許瀏覽器存取麥克風及網路攝影機,並將瀏覽器更新到最新版本。如果以上步驟無法解決問題,請聯絡網頁程式的開發者。",
|
||||
"veryPoorConnection": "您的通話品質將會非常糟糕。",
|
||||
@@ -958,8 +976,8 @@
|
||||
},
|
||||
"recording": {
|
||||
"authDropboxText": "上傳至 Dropbox",
|
||||
"availableSpace": "可用空間:{{spaceLeft}}MB(錄製時間大約{{duration}}分鐘)",
|
||||
"beta": "BETA",
|
||||
"availableSpace": "可用空間:{{spaceLeft}} MB(錄製時間大約 {{duration}} 分鐘)",
|
||||
"beta": "測試版",
|
||||
"busy": "我們正在釋放錄製資源,請過幾分鐘後再試。",
|
||||
"busyTitle": "全部錄製目前忙碌",
|
||||
"copyLink": "複製連結",
|
||||
@@ -976,15 +994,15 @@
|
||||
"highlightMomentSuccess": "已精選的時刻",
|
||||
"highlightMomentSucessDescription": "您的精選時刻將新增至會議摘要。",
|
||||
"inProgress": "正在錄製或直播",
|
||||
"limitNotificationDescriptionNative": "由於目前流量過大,您的錄製時間被限制在{{limit}}分鐘。若要無限制的錄製,請試試 <3>{{app}}</3>。",
|
||||
"limitNotificationDescriptionWeb": "由於目前流量過大,您的錄製時間被限制在{{limit}}分鐘。若要無限制的錄製,請試試 <a href={{url}}rel='noopener noreferrer' target='_blank'>{{app}}</a>。",
|
||||
"limitNotificationDescriptionNative": "由於目前流量過大,您的錄製時間被限制在 {{limit}} 分鐘。若要無限制的錄製,請試試 <3>{{app}}</3>。",
|
||||
"limitNotificationDescriptionWeb": "由於目前流量過大,您的錄製時間被限制在 {{limit}} 分鐘。若要無限制的錄製,請試試 <a href={{url}}rel='noopener noreferrer' target='_blank'>{{app}}</a>。",
|
||||
"linkGenerated": "我們建立了您的錄製檔案的連結。",
|
||||
"live": "直播",
|
||||
"localRecordingNoNotificationWarning": "系統不會主動知會與會者錄製已開啟,主持人需另行通知。",
|
||||
"localRecordingNoVideo": "沒有錄製的視訊",
|
||||
"localRecordingStartWarning": "請確保在退出會議之前停用錄製以便保存。",
|
||||
"localRecordingStartWarningTitle": "停用錄製以保存",
|
||||
"localRecordingVideoStop": "關閉您的視訊也將停止本地錄製,確定繼續嗎?",
|
||||
"localRecordingVideoStop": "關閉您的視訊也將停止本機錄製,確定繼續嗎?",
|
||||
"localRecordingVideoWarning": "錄製視訊必須在開始時啟用",
|
||||
"localRecordingWarning": "確保選擇目前的分頁以錄製正確的視訊和音訊。錄製目前限制為1GB,約可錄製100分鐘。",
|
||||
"loggedIn": "以 {{userName}} 登入",
|
||||
@@ -997,7 +1015,7 @@
|
||||
"onlyRecordSelf": "僅錄製我的音訊和影片串流",
|
||||
"pending": "正在準備錄製會議...",
|
||||
"rec": "錄製中",
|
||||
"saveLocalRecording": "將錄製檔案保存在本地(BETA)",
|
||||
"saveLocalRecording": "將錄製檔案保存在本機(測試版)",
|
||||
"serviceDescription": "您的錄製會由錄製服務儲存",
|
||||
"serviceDescriptionCloud": "雲端錄製",
|
||||
"serviceDescriptionCloudInfo": "已錄製的會議將在 24 小時後自動清除。",
|
||||
@@ -1007,19 +1025,19 @@
|
||||
"signOut": "登出",
|
||||
"surfaceError": "請選擇目前分頁",
|
||||
"title": "錄製中",
|
||||
"unavailable": "喔哦!{{serviceName}}目前無法使用,我們正在解決此問題,請稍後再試。",
|
||||
"unavailable": "喔哦!{{serviceName}} 目前無法使用,我們正在解決此問題,請稍後再試。",
|
||||
"unavailableTitle": "錄製無法使用",
|
||||
"uploadToCloud": "上傳至雲端"
|
||||
},
|
||||
"screenshareDisplayName": "{{name}}的螢幕",
|
||||
"screenshareDisplayName": "{{name}} 的螢幕",
|
||||
"sectionList": {
|
||||
"pullToRefresh": "下拉以重新整理"
|
||||
},
|
||||
"security": {
|
||||
"about": "您可以新增$t(lockRoomPassword)至您的會議,與會者在加入會議前必須先輸入$t(lockRoomPassword)。",
|
||||
"aboutReadOnly": "主持人可以新增$t(lockRoomPassword)至會議,與會者在加入會議前必須先輸入$t(lockRoomPassword)。",
|
||||
"insecureRoomNameWarningNative": "房間名稱不安全,任何人都可能會加入您的會議。{{recommendAction}} 了解有關保護您的會議的更多信息。",
|
||||
"insecureRoomNameWarningWeb": "房間名稱不安全,任何人都可能會加入您的會議。{{recommendAction}} 在此處了解有關保護您的會議的更多信息 <a href=\"{{securityUrl}}\" rel=\"security\" target=\"_blank\">這裡</a>。",
|
||||
"about": "您可以新增 $t(lockRoomPassword) 至您的會議,與會者在加入會議前必須先輸入$t(lockRoomPassword)。",
|
||||
"aboutReadOnly": "主持人可以新增 $t(lockRoomPassword) 至會議,與會者在加入會議前必須先輸入$t(lockRoomPassword)。",
|
||||
"insecureRoomNameWarningNative": "房間名稱不安全,任何人都可能會加入您的會議。{{recommendAction}} 了解有關保護您的會議的更多資訊。",
|
||||
"insecureRoomNameWarningWeb": "房間名稱不安全,任何人都可能會加入您的會議。{{recommendAction}} 在此處了解有關保護您的會議的更多資訊 <a href=\"{{securityUrl}}\" rel=\"security\" target=\"_blank\">這裡</a>。",
|
||||
"title": "安全性選項",
|
||||
"unsafeRoomActions": {
|
||||
"meeting": "請考慮使用安全按鈕保護您的會議。",
|
||||
@@ -1031,10 +1049,10 @@
|
||||
"audio": "音訊",
|
||||
"buttonLabel": "設定",
|
||||
"calendar": {
|
||||
"about": "{{appName}}行事曆整合功能可安全地存取您行事曆中即將舉行的活動。",
|
||||
"about": "{{appName}} 行事曆整合功能可安全地存取您行事曆中即將舉行的活動。",
|
||||
"disconnect": "中斷連接",
|
||||
"microsoftSignIn": "使用Microsoft帳號登入",
|
||||
"signedIn": "目前正在存取{{email}}的行事曆事件,點按下方中斷連接可以停用存取行事曆事件。",
|
||||
"microsoftSignIn": "使用 Microsoft 帳號登入",
|
||||
"signedIn": "目前正在存取 {{email}} 的行事曆事件,點按下方中斷連接可以停用存取行事曆事件。",
|
||||
"title": "行事曆"
|
||||
},
|
||||
"desktopShareFramerate": "桌面螢幕分享影格率",
|
||||
@@ -1079,6 +1097,7 @@
|
||||
"alertOk": "確定",
|
||||
"alertTitle": "警告",
|
||||
"alertURLText": "輸入的伺服器網址無效",
|
||||
"apply": "套用",
|
||||
"buildInfoSection": "組建資訊",
|
||||
"conferenceSection": "會議",
|
||||
"disableCallIntegration": "停用原生通話整合",
|
||||
@@ -1086,23 +1105,24 @@
|
||||
"disableCrashReportingWarning": "您確定要停用錯誤回報功能嗎?變更將在重啟應用程式後生效。",
|
||||
"disableP2P": "停用點對點模式",
|
||||
"displayName": "顯示名稱",
|
||||
"displayNamePlaceholderText": "例如:John Doe",
|
||||
"displayNamePlaceholderText": "例如:王小明",
|
||||
"email": "電子郵件",
|
||||
"emailPlaceholderText": "email@example.com",
|
||||
"gavatarMessage": "如果您的電子郵件地址與 Gravatar 帳號相關聯,我們會使用 Gravatar 上的個人檔案大頭貼。",
|
||||
"goTo": "前往",
|
||||
"header": "設定",
|
||||
"help": "協助",
|
||||
"links": "連結",
|
||||
"privacy": "隱私權",
|
||||
"profileSection": "簡介",
|
||||
"sdkVersion": "SDK版本",
|
||||
"sdkVersion": "SDK 版本",
|
||||
"serverURL": "伺服器網址",
|
||||
"showAdvanced": "顯示進階設定",
|
||||
"startCarModeInLowBandwidthMode": "同時啟用行車模式與低頻寬模式",
|
||||
"startWithAudioMuted": "啟動並靜音",
|
||||
"startWithVideoMuted": "啟動並關閉影像",
|
||||
"terms": "條款",
|
||||
"version": "APP版本"
|
||||
"version": "應用程式版本"
|
||||
},
|
||||
"share": {
|
||||
"dialInfoText": "\n\n=====\n\n只想要透過手機撥打加入嗎?\n\n撥打{{defaultDialInNumber}}或點此連結來查看此會議的電話撥入號碼\n{{dialInfoPageUrl}}",
|
||||
@@ -1146,7 +1166,7 @@
|
||||
"Settings": "切換設定",
|
||||
"audioOnly": "切換僅音訊",
|
||||
"audioRoute": "選擇音訊裝置",
|
||||
"boo": "喝倒彩",
|
||||
"boo": "倒喝彩",
|
||||
"breakoutRoom": "進入/離開分組討論室",
|
||||
"callQuality": "管理視訊品質",
|
||||
"carmode": "行車模式",
|
||||
@@ -1160,7 +1180,7 @@
|
||||
"document": "切換檔案分享",
|
||||
"documentClose": "關閉檔案分享",
|
||||
"documentOpen": "打開檔案分享",
|
||||
"download": "下載我們的APP",
|
||||
"download": "下載我們的應用程式",
|
||||
"embedMeeting": "嵌入會議",
|
||||
"endConference": "結束會議(所有人)",
|
||||
"enterFullScreen": "進入全螢幕",
|
||||
@@ -1183,7 +1203,7 @@
|
||||
"like": "比讚",
|
||||
"linkToSalesforce": "連結至 Salesforce",
|
||||
"lobbyButton": "啟用/停用大廳模式",
|
||||
"localRecording": "切換本地錄製控制",
|
||||
"localRecording": "切換本機錄製控制",
|
||||
"lockRoom": "切換會議密碼",
|
||||
"lowerHand": "放下手",
|
||||
"moreActions": "更多動作",
|
||||
@@ -1199,7 +1219,7 @@
|
||||
"openChat": "打開聊天",
|
||||
"participants": "打開與會者窗格",
|
||||
"pip": "切換子母螢幕模式",
|
||||
"privateMessage": "發送私人訊息",
|
||||
"privateMessage": "傳送私人訊息",
|
||||
"profile": "編輯您的個人檔案",
|
||||
"raiseHand": "舉手",
|
||||
"reactions": "反應",
|
||||
@@ -1237,7 +1257,7 @@
|
||||
"audioRoute": "選擇音訊裝置",
|
||||
"audioSettings": "音訊設定",
|
||||
"authenticate": "驗證",
|
||||
"boo": "喝倒彩",
|
||||
"boo": "倒喝彩",
|
||||
"callQuality": "管理影像品質",
|
||||
"chat": "開啟/關閉聊天欄",
|
||||
"clap": "鼓掌",
|
||||
@@ -1248,7 +1268,7 @@
|
||||
"disableReactionSounds": "您可以停用此會議的反應音效",
|
||||
"documentClose": "關閉分享檔案欄",
|
||||
"documentOpen": "開啟分享檔案欄",
|
||||
"download": "下載我們的APP",
|
||||
"download": "下載我們的應用程式",
|
||||
"e2ee": "端對端加密",
|
||||
"embedMeeting": "嵌入會議",
|
||||
"enableNoiseSuppression": "開啟雜訊抑制",
|
||||
@@ -1273,7 +1293,7 @@
|
||||
"lobbyButtonEnable": "啟用大廳模式",
|
||||
"login": "登入",
|
||||
"logout": "登出",
|
||||
"lowerYourHand": "放下你的手",
|
||||
"lowerYourHand": "放下您的手",
|
||||
"moreActions": "更多動作",
|
||||
"moreOptions": "更多選項",
|
||||
"mute": "靜音/解除靜音",
|
||||
@@ -1294,9 +1314,9 @@
|
||||
"pip": "進入子母螢幕模式",
|
||||
"privateMessage": "傳送私人訊息",
|
||||
"profile": "編輯您的個人資料",
|
||||
"raiseHand": "舉起/放下你的手",
|
||||
"raiseHand": "舉起/放下您的手",
|
||||
"raiseYourHand": "舉手",
|
||||
"reactionBoo": "傳送喝倒彩反應",
|
||||
"reactionBoo": "傳送倒喝彩反應",
|
||||
"reactionClap": "傳送鼓掌反應",
|
||||
"reactionLaugh": "傳送大笑反應",
|
||||
"reactionLike": "傳送比讚反應",
|
||||
@@ -1336,7 +1356,7 @@
|
||||
"labelToolTip": "此會議正在轉錄",
|
||||
"off": "轉錄已停用",
|
||||
"pending": "準備轉錄會議...",
|
||||
"sourceLanguageDesc": "會議語言目前設定為<b>{{sourceLanguage}}</b><br/>您可以在這裡",
|
||||
"sourceLanguageDesc": "會議語言目前設定為 <b>{{sourceLanguage}}</b><br/> 您可以在這裡",
|
||||
"sourceLanguageHere": "修改",
|
||||
"start": "開始顯示字幕",
|
||||
"stop": "停用顯示字幕",
|
||||
@@ -1360,12 +1380,12 @@
|
||||
"videoSIPGW": {
|
||||
"busy": "我們正在釋放資源,請過幾分鐘後再試。",
|
||||
"busyTitle": "會議室服務目前忙碌中",
|
||||
"errorAlreadyInvited": "{{displayName}}已經受邀",
|
||||
"errorAlreadyInvited": "{{displayName}} 已經受邀",
|
||||
"errorInvite": "會議尚未開始,請稍候再試。",
|
||||
"errorInviteFailed": "我們正在努力解決這個問題,請稍後再試。",
|
||||
"errorInviteFailedTitle": "邀請{{displayName}}失敗",
|
||||
"errorInviteFailedTitle": "邀請 {{displayName}} 失敗",
|
||||
"errorInviteTitle": "會議室邀請錯誤",
|
||||
"pending": "已向{{displayName}}發送邀請"
|
||||
"pending": "已向 {{displayName}} 傳送邀請"
|
||||
},
|
||||
"videoStatus": {
|
||||
"adjustFor": "調整為:",
|
||||
@@ -1415,7 +1435,7 @@
|
||||
},
|
||||
"virtualBackground": {
|
||||
"accessibilityLabel": {
|
||||
"currentBackground": "當前背景:{{background}}",
|
||||
"currentBackground": "目前背景:{{background}}",
|
||||
"selectBackground": "選擇背景"
|
||||
},
|
||||
"addBackground": "新增背景",
|
||||
@@ -1438,8 +1458,8 @@
|
||||
"slightBlur": "輕微模糊",
|
||||
"title": "虛擬背景",
|
||||
"uploadedImage": "已上傳的圖片 {{index}}",
|
||||
"webAssemblyWarning": "不支援WebAssembly",
|
||||
"webAssemblyWarningDescription": "WebAssembly已停用或不受此瀏覽器支援"
|
||||
"webAssemblyWarning": "不支援 WebAssembly",
|
||||
"webAssemblyWarningDescription": "WebAssembly 已停用或不受此瀏覽器支援"
|
||||
},
|
||||
"visitors": {
|
||||
"chatIndicator": "(訪客)",
|
||||
@@ -1456,14 +1476,14 @@
|
||||
"roomname": "輸入會議室名稱"
|
||||
},
|
||||
"addMeetingName": "新增會議名稱",
|
||||
"appDescription": "來吧,和您的整個團隊進行視訊會議。不,邀請所有您認識的人進行視訊會議。{{app}}是一套完全加密、100% 開放源始碼的視訊會議解決方案。無需註冊帳號,無時無刻不分日夜均可免費使用。",
|
||||
"appDescription": "來吧,和您的整個團隊進行視訊會議。不,邀請所有您認識的人進行視訊會議。{{app}} 是一套完全加密、100% 開放原始碼的視訊會議解決方案。無需註冊帳號,無時無刻不分日夜均可免費使用。",
|
||||
"audioVideoSwitch": {
|
||||
"audio": "音訊",
|
||||
"video": "視訊"
|
||||
},
|
||||
"calendar": "行事曆",
|
||||
"connectCalendarButton": "連接您的行事曆",
|
||||
"connectCalendarText": "連接您的行事曆來查看在{{app}}中的會議。此外,增加{{provider}}的會議至自己的行事曆,只要點按一下即可啟動。",
|
||||
"connectCalendarText": "連接您的行事曆來查看在 {{app}} 中的會議。此外,增加 {{provider}} 的會議至自己的行事曆,只要點按一下即可啟動。",
|
||||
"enterRoomTitle": "啟動新的會議",
|
||||
"getHelp": "取得協助",
|
||||
"go": "開始",
|
||||
@@ -1482,25 +1502,25 @@
|
||||
"policyLogo": "政策圖示"
|
||||
},
|
||||
"meetingsAccessibilityLabel": "會議",
|
||||
"mobileDownLoadLinkAndroid": "下載 Android 版本的手機應用程式",
|
||||
"mobileDownLoadLinkFDroid": "前往 F-Droid 下載 Android 版本的手機應用程式",
|
||||
"mobileDownLoadLinkIos": "下載 iOS 版本的手機應用程式",
|
||||
"mobileDownLoadLinkAndroid": "下載 Android 版本的應用程式",
|
||||
"mobileDownLoadLinkFDroid": "前往 F-Droid 下載 Android 版本的應用程式",
|
||||
"mobileDownLoadLinkIos": "下載 iOS 版本的應用程式",
|
||||
"moderatedMessage": "或以主持人身份<a href=\"{{url}}\" rel=\"noopener noreferrer\" target=\"_blank\">預先建立會議</a>。",
|
||||
"privacy": "隱私權",
|
||||
"recentList": "最近使用",
|
||||
"recentList": "近期",
|
||||
"recentListDelete": "刪除",
|
||||
"recentListEmpty": "目前最近使用是空白的,與您的團隊成員聊天,即會在此處找到最近使用過的會議。",
|
||||
"recentMeetings": "您的最近會議",
|
||||
"recentListEmpty": "您的近期列表目前是空白的,與您的團隊成員聊天,即可在此處找到最近參與過的會議。",
|
||||
"recentMeetings": "您近期的會議",
|
||||
"reducedUIText": "歡迎使用{{app}}!",
|
||||
"roomNameAllowedChars": "會議室名稱不應包含以下字元:? & : ' \" % #",
|
||||
"roomNameAllowedChars": "會議室名稱不應包含以下字元:?、&、:、'、\"、%、#。",
|
||||
"roomname": "輸入會議室名稱",
|
||||
"roomnameHint": "請輸入您想加入的會議室名稱或網址,您可以用一個名稱來建立會議室,只要其他人輸入相同的名稱就能加入會議室喔。",
|
||||
"roomnameHint": "請輸入您想加入的會議室名稱或網址,您可以用一個名稱來建立會議室,只要其他人輸入相同的名稱就能加入會議室。",
|
||||
"sendFeedback": "傳送回饋",
|
||||
"settings": "設定",
|
||||
"startMeeting": "開始會議",
|
||||
"terms": "條款",
|
||||
"title": "安全、功能齊全、完全免費的視訊會議",
|
||||
"upcomingMeetings": "您即將的會議"
|
||||
"upcomingMeetings": "您即將開始的會議"
|
||||
},
|
||||
"whiteboard": {
|
||||
"accessibilityLabel": {
|
||||
|
||||
@@ -67,13 +67,18 @@
|
||||
"renameBreakoutRoom": "Rename breakout room",
|
||||
"sendToBreakoutRoom": "Send participant to:"
|
||||
},
|
||||
"breakoutList": "Breakout list",
|
||||
"buttonLabel": "Breakout rooms",
|
||||
"defaultName": "Breakout room #{{index}}",
|
||||
"hideParticipantList": "Hide participant list",
|
||||
"mainRoom": "Main room",
|
||||
"notifications": {
|
||||
"joined": "Joining the \"{{name}}\" breakout room",
|
||||
"joinedMainRoom": "Joining the main room",
|
||||
"joinedTitle": "Breakout Rooms"
|
||||
}
|
||||
},
|
||||
"showParticipantList": "Show participant list",
|
||||
"title": "Breakout Rooms"
|
||||
},
|
||||
"calendarSync": {
|
||||
"addMeetingURL": "Add a meeting link",
|
||||
@@ -416,6 +421,7 @@
|
||||
"sessTerminatedReason": "The meeting has been terminated",
|
||||
"sessionRestarted": "Call restarted because of a connection issue.",
|
||||
"shareAudio": "Continue",
|
||||
"shareAudioAltText": "to share the desired content, navigate to \"Browser Tab\", select the content, activate the \"share audio\" check mark and then click \"share\" button",
|
||||
"shareAudioTitle": "How to share audio",
|
||||
"shareAudioWarningD1": "you need to stop screen sharing before sharing your audio.",
|
||||
"shareAudioWarningD2": "you need to restart your screen sharing and check the \"share audio\" option.",
|
||||
@@ -477,6 +483,10 @@
|
||||
"viewUpgradeOptions": "View upgrade options",
|
||||
"viewUpgradeOptionsContent": "To get unlimited access to premium features like recording, transcriptions, RTMP Streaming & more, you'll need to upgrade your plan.",
|
||||
"viewUpgradeOptionsTitle": "You discovered a premium feature!",
|
||||
"whiteboardLimitContent": "Sorry, the limit of conccurent whiteboard users has been reached.",
|
||||
"whiteboardLimitReference": "For more information please visit",
|
||||
"whiteboardLimitReferenceUrl": "our website",
|
||||
"whiteboardLimitTitle": "Whiteboard usage restricted",
|
||||
"yourEntireScreen": "Your entire screen"
|
||||
},
|
||||
"documentSharing": {
|
||||
@@ -724,6 +734,7 @@
|
||||
"dataChannelClosed": "Video quality impaired",
|
||||
"dataChannelClosedDescription": "The bridge channel has been disconnected and thus video quality is limited to its lowest setting.",
|
||||
"disabledIframe": "Embedding is only meant for demo purposes, so this call will disconnect in {{timeout}} minutes.",
|
||||
"disabledIframeSecondary": "Embedding {{domain}} is only meant for demo purposes, so this call will disconnect in {{timeout}} minutes. Please use <a href='{{jaasDomain}}' rel='noopener noreferrer' target='_blank'>Jitsi as a Service</a> for production embedding!",
|
||||
"disconnected": "disconnected",
|
||||
"displayNotifications": "Display notifications for",
|
||||
"dontRemindMe": "Do not remind me",
|
||||
@@ -799,7 +810,9 @@
|
||||
"videoUnmuteBlockedDescription": "Camera unmute and desktop sharing operation have been temporarily blocked because of system limits.",
|
||||
"videoUnmuteBlockedTitle": "Camera unmute and desktop sharing blocked!",
|
||||
"viewLobby": "View lobby",
|
||||
"waitingParticipants": "{{waitingParticipants}} people"
|
||||
"waitingParticipants": "{{waitingParticipants}} people",
|
||||
"whiteboardLimitDescription": "Please save your progress, as the user limit will soon be reached and the whiteboard will close.",
|
||||
"whiteboardLimitTitle": "Whiteboard usage"
|
||||
},
|
||||
"participantsPane": {
|
||||
"actions": {
|
||||
@@ -808,6 +821,7 @@
|
||||
"askUnmute": "Ask to unmute",
|
||||
"audioModeration": "Unmute themselves",
|
||||
"blockEveryoneMicCamera": "Block everyone's mic and camera",
|
||||
"breakoutRooms": "Breakout rooms",
|
||||
"invite": "Invite Someone",
|
||||
"moreModerationActions": "More moderation options",
|
||||
"moreModerationControls": "More moderation controls",
|
||||
@@ -1154,7 +1168,7 @@
|
||||
"audioOnly": "Toggle audio only",
|
||||
"audioRoute": "Select the sound device",
|
||||
"boo": "Boo",
|
||||
"breakoutRoom": "Join/leave breakout room",
|
||||
"breakoutRooms": "Breakout rooms",
|
||||
"callQuality": "Manage video quality",
|
||||
"carmode": "Car Mode",
|
||||
"cc": "Toggle subtitles",
|
||||
|
||||
@@ -244,8 +244,6 @@ function initCommands() {
|
||||
}
|
||||
},
|
||||
'pin-participant': (id, videoType) => {
|
||||
logger.debug('Pin participant command received');
|
||||
|
||||
const state = APP.store.getState();
|
||||
|
||||
// if id not provided, unpin everybody.
|
||||
@@ -303,7 +301,6 @@ function initCommands() {
|
||||
APP.store.dispatch(removeBreakoutRoom(breakoutRoomJid));
|
||||
},
|
||||
'resize-large-video': (width, height) => {
|
||||
logger.debug('Resize large video command received');
|
||||
sendAnalytics(createApiEvent('largevideo.resized'));
|
||||
APP.store.dispatch(resizeLargeVideo(width, height));
|
||||
},
|
||||
@@ -324,7 +321,6 @@ function initCommands() {
|
||||
APP.store.dispatch(setAssumedBandwidthBps(value));
|
||||
},
|
||||
'set-follow-me': value => {
|
||||
logger.debug('Set follow me command received');
|
||||
|
||||
if (value) {
|
||||
sendAnalytics(createApiEvent('follow.me.set'));
|
||||
@@ -335,7 +331,6 @@ function initCommands() {
|
||||
APP.store.dispatch(setFollowMe(value));
|
||||
},
|
||||
'set-large-video-participant': (participantId, videoType) => {
|
||||
logger.debug('Set large video participant command received');
|
||||
const { getState, dispatch } = APP.store;
|
||||
|
||||
if (!participantId) {
|
||||
@@ -373,12 +368,10 @@ function initCommands() {
|
||||
},
|
||||
'toggle-audio': () => {
|
||||
sendAnalytics(createApiEvent('toggle-audio'));
|
||||
logger.log('Audio toggle: API command received');
|
||||
APP.conference.toggleAudioMuted(false /* no UI */);
|
||||
},
|
||||
'toggle-video': () => {
|
||||
sendAnalytics(createApiEvent('toggle-video'));
|
||||
logger.log('Video toggle: API command received');
|
||||
APP.conference.toggleVideoMuted(false /* no UI */, true /* ensure track */);
|
||||
},
|
||||
'toggle-film-strip': () => {
|
||||
@@ -497,7 +490,6 @@ function initCommands() {
|
||||
APP.conference.changeLocalAvatarUrl(avatarUrl);
|
||||
},
|
||||
'send-chat-message': (message, to, ignorePrivacy = false) => {
|
||||
logger.debug('Send chat message command received');
|
||||
if (to) {
|
||||
const participant = getParticipantById(APP.store.getState(), to);
|
||||
|
||||
@@ -515,7 +507,6 @@ function initCommands() {
|
||||
APP.store.dispatch(sendMessage(message, ignorePrivacy));
|
||||
},
|
||||
'send-endpoint-text-message': (to, text) => {
|
||||
logger.debug('Send endpoint message command received');
|
||||
try {
|
||||
APP.conference.sendEndpointMessage(to, {
|
||||
name: ENDPOINT_TEXT_MESSAGE_NAME,
|
||||
@@ -538,25 +529,19 @@ function initCommands() {
|
||||
});
|
||||
},
|
||||
'overwrite-names': participantList => {
|
||||
logger.debug('Overwrite names command received');
|
||||
|
||||
APP.store.dispatch(overwriteParticipantsNames(participantList));
|
||||
},
|
||||
'toggle-e2ee': enabled => {
|
||||
logger.debug('Toggle E2EE key command received');
|
||||
APP.store.dispatch(toggleE2EE(enabled));
|
||||
},
|
||||
'set-media-encryption-key': keyInfo => {
|
||||
APP.store.dispatch(setMediaEncryptionKey(JSON.parse(keyInfo)));
|
||||
},
|
||||
'set-video-quality': frameHeight => {
|
||||
logger.debug('Set video quality command received');
|
||||
sendAnalytics(createApiEvent('set.video.quality'));
|
||||
APP.store.dispatch(setVideoQuality(frameHeight));
|
||||
},
|
||||
|
||||
'start-share-video': url => {
|
||||
logger.debug('Share video command received');
|
||||
sendAnalytics(createApiEvent('share.video.start'));
|
||||
const id = extractYoutubeIdOrURL(url);
|
||||
|
||||
@@ -564,9 +549,7 @@ function initCommands() {
|
||||
APP.store.dispatch(playSharedVideo(id));
|
||||
}
|
||||
},
|
||||
|
||||
'stop-share-video': () => {
|
||||
logger.debug('Share video command received');
|
||||
sendAnalytics(createApiEvent('share.video.stop'));
|
||||
APP.store.dispatch(stopSharedVideo());
|
||||
},
|
||||
@@ -641,6 +624,7 @@ function initCommands() {
|
||||
* Only applies to certain jitsi meet deploys.
|
||||
* @param { string } arg.youtubeStreamKey - The youtube stream key.
|
||||
* @param { string } arg.youtubeBroadcastID - The youtube broadcast ID.
|
||||
* @param { Object } arg.extraMetadata - Any extra metadata params for file recording.
|
||||
* @returns {void}
|
||||
*/
|
||||
'start-recording': ({
|
||||
@@ -651,7 +635,8 @@ function initCommands() {
|
||||
rtmpStreamKey,
|
||||
rtmpBroadcastID,
|
||||
youtubeStreamKey,
|
||||
youtubeBroadcastID
|
||||
youtubeBroadcastID,
|
||||
extraMetadata = {}
|
||||
}) => {
|
||||
const state = APP.store.getState();
|
||||
const conference = getCurrentConference(state);
|
||||
@@ -701,6 +686,7 @@ function initCommands() {
|
||||
mode: JitsiRecordingConstants.mode.FILE,
|
||||
appData: JSON.stringify({
|
||||
'file_recording_metadata': {
|
||||
...extraMetadata,
|
||||
'upload_credentials': {
|
||||
'service_name': RECORDING_TYPES.DROPBOX,
|
||||
'token': dropboxToken
|
||||
@@ -713,6 +699,7 @@ function initCommands() {
|
||||
mode: JitsiRecordingConstants.mode.FILE,
|
||||
appData: JSON.stringify({
|
||||
'file_recording_metadata': {
|
||||
...extraMetadata,
|
||||
'share': shouldShare
|
||||
}
|
||||
})
|
||||
@@ -842,11 +829,14 @@ function initCommands() {
|
||||
};
|
||||
transport.on('event', ({ data, name }) => {
|
||||
if (name && commands[name]) {
|
||||
logger.info(`API command received: ${name}`);
|
||||
commands[name](...data);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
logger.warn(`Unknown API command received: ${name}`);
|
||||
|
||||
return false;
|
||||
});
|
||||
transport.on('request', (request, callback) => {
|
||||
@@ -993,7 +983,13 @@ function initCommands() {
|
||||
callback(isP2pActive(APP.store.getState()));
|
||||
break;
|
||||
}
|
||||
case '_new_electron_screensharing_supported': {
|
||||
callback(true);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
callback({ error: new Error('UnknownRequestError') });
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -1101,7 +1097,11 @@ class API {
|
||||
this._enabled = true;
|
||||
|
||||
initCommands();
|
||||
|
||||
this.notifyBrowserSupport(isSupportedBrowser());
|
||||
|
||||
// Let the embedder know we are ready.
|
||||
this._sendEvent({ name: 'ready' });
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1279,6 +1279,19 @@ class API {
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Notify request desktop sources.
|
||||
*
|
||||
* @param {Object} options - Object with the options for desktop sources.
|
||||
* @returns {void}
|
||||
*/
|
||||
requestDesktopSources(options) {
|
||||
return transport.sendRequest({
|
||||
name: '_request-desktop-sources',
|
||||
options
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Notify external application that the video quality setting has changed.
|
||||
*
|
||||
@@ -1964,6 +1977,20 @@ class API {
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Notify external application (if API is enabled) that the user received
|
||||
* a transcription chunk.
|
||||
*
|
||||
* @param {Object} data - The event data.
|
||||
* @returns {void}
|
||||
*/
|
||||
notifyTranscriptionChunkReceived(data) {
|
||||
this._sendEvent({
|
||||
name: 'transcription-chunk-received',
|
||||
data
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Notify external application (if API is enabled) whether the used browser is supported or not.
|
||||
*
|
||||
|
||||
59
modules/API/external/external_api.js
vendored
59
modules/API/external/external_api.js
vendored
@@ -145,6 +145,7 @@ const events = {
|
||||
'prejoin-screen-loaded': 'prejoinScreenLoaded',
|
||||
'proxy-connection-event': 'proxyConnectionEvent',
|
||||
'raise-hand-updated': 'raiseHandUpdated',
|
||||
'ready': 'ready',
|
||||
'recording-link-available': 'recordingLinkAvailable',
|
||||
'recording-status-changed': 'recordingStatusChanged',
|
||||
'participant-menu-button-clicked': 'participantMenuButtonClick',
|
||||
@@ -159,9 +160,14 @@ const events = {
|
||||
'suspend-detected': 'suspendDetected',
|
||||
'tile-view-changed': 'tileViewChanged',
|
||||
'toolbar-button-clicked': 'toolbarButtonClicked',
|
||||
'transcription-chunk-received': 'transcriptionChunkReceived',
|
||||
'whiteboard-status-changed': 'whiteboardStatusChanged'
|
||||
};
|
||||
|
||||
const requests = {
|
||||
'_request-desktop-sources': '_requestDesktopSources'
|
||||
};
|
||||
|
||||
/**
|
||||
* Last id of api object.
|
||||
*
|
||||
@@ -269,10 +275,10 @@ function parseArguments(args) {
|
||||
function parseSizeParam(value) {
|
||||
let parsedValue;
|
||||
|
||||
// This regex parses values of the form 100px, 100em, 100pt or 100%.
|
||||
// This regex parses values of the form 100px, 100em, 100pt, 100vh, 100vw or 100%.
|
||||
// Values like 100 or 100px are handled outside of the regex, and
|
||||
// invalid values will be ignored and the minimum will be used.
|
||||
const re = /([0-9]*\.?[0-9]+)(em|pt|px|%)$/;
|
||||
const re = /([0-9]*\.?[0-9]+)(em|pt|px|((d|l|s)?v)(h|w)|%)$/;
|
||||
|
||||
if (typeof value === 'string' && String(value).match(re) !== null) {
|
||||
parsedValue = value;
|
||||
@@ -361,7 +367,9 @@ export default class JitsiMeetExternalAPI extends EventEmitter {
|
||||
},
|
||||
release
|
||||
});
|
||||
this._createIFrame(height, width, onload, sandbox);
|
||||
|
||||
this._createIFrame(height, width, sandbox);
|
||||
|
||||
this._transport = new Transport({
|
||||
backend: new PostMessageTransportBackend({
|
||||
postisOptions: {
|
||||
@@ -371,9 +379,12 @@ export default class JitsiMeetExternalAPI extends EventEmitter {
|
||||
}
|
||||
})
|
||||
});
|
||||
|
||||
if (Array.isArray(invitees) && invitees.length > 0) {
|
||||
this.invite(invitees);
|
||||
}
|
||||
|
||||
this._onload = onload;
|
||||
this._tmpE2EEKey = e2eeKey;
|
||||
this._isLargeVideoVisible = false;
|
||||
this._isPrejoinVideoVisible = false;
|
||||
@@ -392,14 +403,12 @@ export default class JitsiMeetExternalAPI extends EventEmitter {
|
||||
* parseSizeParam for format details.
|
||||
* @param {number|string} width - The with of the iframe. Check
|
||||
* parseSizeParam for format details.
|
||||
* @param {Function} onload - The function that will listen
|
||||
* for onload event.
|
||||
* @param {string} sandbox - Sandbox directive for the created iframe, if desired.
|
||||
* @returns {void}
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
_createIFrame(height, width, onload, sandbox) {
|
||||
_createIFrame(height, width, sandbox) {
|
||||
const frameName = `jitsiConferenceFrame${id}`;
|
||||
|
||||
this._frame = document.createElement('iframe');
|
||||
@@ -411,7 +420,8 @@ export default class JitsiMeetExternalAPI extends EventEmitter {
|
||||
'display-capture',
|
||||
'hid',
|
||||
'microphone',
|
||||
'screen-wake-lock'
|
||||
'screen-wake-lock',
|
||||
'speaker-selection'
|
||||
].join('; ');
|
||||
this._frame.name = frameName;
|
||||
this._frame.id = frameName;
|
||||
@@ -423,11 +433,6 @@ export default class JitsiMeetExternalAPI extends EventEmitter {
|
||||
this._frame.sandbox = sandbox;
|
||||
}
|
||||
|
||||
if (onload) {
|
||||
// waits for iframe resources to load
|
||||
// and fires event when it is done
|
||||
this._frame.onload = onload;
|
||||
}
|
||||
this._frame.src = this._url;
|
||||
|
||||
this._frame = this._parentNode.appendChild(this._frame);
|
||||
@@ -576,6 +581,12 @@ export default class JitsiMeetExternalAPI extends EventEmitter {
|
||||
const userID = data.id;
|
||||
|
||||
switch (name) {
|
||||
case 'ready': {
|
||||
// Fake the iframe onload event because it's not reliable.
|
||||
this._onload?.();
|
||||
|
||||
break;
|
||||
}
|
||||
case 'video-conference-joined': {
|
||||
if (typeof this._tmpE2EEKey !== 'undefined') {
|
||||
|
||||
@@ -687,6 +698,18 @@ export default class JitsiMeetExternalAPI extends EventEmitter {
|
||||
|
||||
return false;
|
||||
});
|
||||
|
||||
this._transport.on('request', (request, callback) => {
|
||||
const requestName = requests[request.name];
|
||||
const data = {
|
||||
...request,
|
||||
name: requestName
|
||||
};
|
||||
|
||||
if (requestName) {
|
||||
this.emit(requestName, data, callback);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1258,6 +1281,17 @@ export default class JitsiMeetExternalAPI extends EventEmitter {
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the state of availability electron share screen via external api.
|
||||
*
|
||||
* @returns {Promise}
|
||||
*/
|
||||
_isNewElectronScreensharingSupported() {
|
||||
return this._transport.sendRequest({
|
||||
name: '_new_electron_screensharing_supported'
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Pins a participant's video on to the stage view.
|
||||
*
|
||||
@@ -1398,6 +1432,7 @@ export default class JitsiMeetExternalAPI extends EventEmitter {
|
||||
* @param { string } options.rtmpBroadcastID - The RTMP broadcast ID.
|
||||
* @param { string } options.youtubeStreamKey - The youtube stream key.
|
||||
* @param { string } options.youtubeBroadcastID - The youtube broadcast ID.
|
||||
* @param {Object } options.extraMetadata - Any extra metadata params for file recording.
|
||||
* @returns {void}
|
||||
*/
|
||||
startRecording(options) {
|
||||
|
||||
@@ -203,16 +203,6 @@ UI.toggleFilmstrip = function() {
|
||||
APP.store.dispatch(setFilmstripVisible(!visible));
|
||||
};
|
||||
|
||||
/**
|
||||
* Sets muted audio state for participant
|
||||
*/
|
||||
UI.setAudioMuted = function(id) {
|
||||
// FIXME: Maybe this can be removed!
|
||||
if (APP.conference.isLocalId(id)) {
|
||||
APP.conference.updateAudioIconEnabled();
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Sets muted video state for participant
|
||||
*/
|
||||
|
||||
@@ -5,6 +5,7 @@ import {
|
||||
notifyMicError
|
||||
} from '../../react/features/base/devices/actions.web';
|
||||
import {
|
||||
flattenAvailableDevices,
|
||||
getAudioOutputDeviceId
|
||||
} from '../../react/features/base/devices/functions.web';
|
||||
import { updateSettings } from '../../react/features/base/settings/actions';
|
||||
@@ -186,7 +187,7 @@ export default {
|
||||
* @returns {boolean}
|
||||
*/
|
||||
newDeviceListAddedLabelsOnly(oldDevices, newDevices) {
|
||||
const oldDevicesFlattend = oldDevices.audioInput.concat(oldDevices.audioOutput).concat(oldDevices.videoInput);
|
||||
const oldDevicesFlattend = flattenAvailableDevices(oldDevices);
|
||||
|
||||
if (oldDevicesFlattend.length !== newDevices.length) {
|
||||
return false;
|
||||
|
||||
5783
package-lock.json
generated
5783
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
28
package.json
28
package.json
@@ -22,8 +22,8 @@
|
||||
"@giphy/js-fetch-api": "4.7.1",
|
||||
"@giphy/react-components": "6.8.1",
|
||||
"@giphy/react-native-sdk": "2.3.0",
|
||||
"@jitsi/excalidraw": "https://github.com/jitsi/excalidraw/releases/download/v0.0.14/jitsi-excalidraw-0.0.14.tgz",
|
||||
"@jitsi/js-utils": "2.1.3",
|
||||
"@jitsi/excalidraw": "https://github.com/jitsi/excalidraw/releases/download/v0.0.16/jitsi-excalidraw-0.0.16.tgz",
|
||||
"@jitsi/js-utils": "2.2.1",
|
||||
"@jitsi/logger": "2.0.2",
|
||||
"@jitsi/rnnoise-wasm": "0.1.0",
|
||||
"@jitsi/rtcstats": "9.5.1",
|
||||
@@ -31,11 +31,11 @@
|
||||
"@microsoft/microsoft-graph-client": "3.0.1",
|
||||
"@mui/material": "5.12.1",
|
||||
"@mui/styles": "5.12.0",
|
||||
"@react-native-async-storage/async-storage": "1.19.3",
|
||||
"@react-native-async-storage/async-storage": "1.19.4",
|
||||
"@react-native-community/clipboard": "1.5.1",
|
||||
"@react-native-community/netinfo": "9.4.1",
|
||||
"@react-native-community/netinfo": "11.1.0",
|
||||
"@react-native-community/slider": "4.4.3",
|
||||
"@react-native-google-signin/google-signin": "10.0.1",
|
||||
"@react-native-google-signin/google-signin": "10.1.0",
|
||||
"@react-navigation/bottom-tabs": "6.5.8",
|
||||
"@react-navigation/elements": "1.3.18",
|
||||
"@react-navigation/material-top-tabs": "6.6.3",
|
||||
@@ -65,12 +65,13 @@
|
||||
"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/v1691.0.0+255d8f49/lib-jitsi-meet.tgz",
|
||||
"lib-jitsi-meet": "https://github.com/jitsi/lib-jitsi-meet/releases/download/v1734.0.0+34ceebd2/lib-jitsi-meet.tgz",
|
||||
"lodash": "4.17.21",
|
||||
"moment": "2.29.4",
|
||||
"moment-duration-format": "2.2.2",
|
||||
"null-loader": "4.0.1",
|
||||
"optional-require": "1.0.3",
|
||||
"pixelmatch": "5.3.0",
|
||||
"promise.allsettled": "1.0.4",
|
||||
"punycode": "2.3.0",
|
||||
"react": "18.2.0",
|
||||
@@ -79,10 +80,9 @@
|
||||
"react-focus-on": "3.8.1",
|
||||
"react-i18next": "10.11.4",
|
||||
"react-linkify": "1.0.0-alpha",
|
||||
"react-native": "0.69.11",
|
||||
"react-native": "0.70.14",
|
||||
"react-native-background-timer": "2.4.1",
|
||||
"react-native-calendar-events": "2.2.0",
|
||||
"react-native-callstats": "3.73.22",
|
||||
"react-native-default-preference": "1.4.4",
|
||||
"react-native-device-info": "10.9.0",
|
||||
"react-native-dialog": "https://github.com/jitsi/react-native-dialog/releases/download/v9.2.2-jitsi.1/react-native-dialog-9.2.2.tgz",
|
||||
@@ -90,7 +90,7 @@
|
||||
"react-native-get-random-values": "1.9.0",
|
||||
"react-native-immersive-mode": "2.0.1",
|
||||
"react-native-keep-awake": "4.0.0",
|
||||
"react-native-orientation-locker": "1.5.0",
|
||||
"react-native-orientation-locker": "1.6.0",
|
||||
"react-native-pager-view": "6.2.0",
|
||||
"react-native-paper": "5.10.3",
|
||||
"react-native-performance": "5.0.0",
|
||||
@@ -104,7 +104,7 @@
|
||||
"react-native-url-polyfill": "2.0.0",
|
||||
"react-native-video": "6.0.0-alpha.7",
|
||||
"react-native-watch-connectivity": "1.1.0",
|
||||
"react-native-webrtc": "111.0.3",
|
||||
"react-native-webrtc": "118.0.0",
|
||||
"react-native-webview": "13.5.1",
|
||||
"react-native-youtube-iframe": "2.3.0",
|
||||
"react-redux": "7.2.9",
|
||||
@@ -113,7 +113,6 @@
|
||||
"react-youtube": "10.1.0",
|
||||
"redux": "4.0.4",
|
||||
"redux-thunk": "2.4.1",
|
||||
"resemblejs": "4.0.0",
|
||||
"seamless-scroll-polyfill": "2.1.8",
|
||||
"semver": "7.5.4",
|
||||
"tss-react": "4.4.4",
|
||||
@@ -136,16 +135,17 @@
|
||||
"@types/dom-screen-wake-lock": "1.0.1",
|
||||
"@types/js-md5": "0.4.3",
|
||||
"@types/lodash": "4.14.182",
|
||||
"@types/offscreencanvas": "2019.7.2",
|
||||
"@types/pixelmatch": "5.2.5",
|
||||
"@types/punycode": "2.1.0",
|
||||
"@types/react": "17.0.14",
|
||||
"@types/react-dom": "17.0.14",
|
||||
"@types/react-linkify": "1.0.1",
|
||||
"@types/react-native": "0.69.20",
|
||||
"@types/react-native": "0.69.22",
|
||||
"@types/react-native-keep-awake": "2.0.3",
|
||||
"@types/react-native-video": "5.0.14",
|
||||
"@types/react-redux": "7.1.24",
|
||||
"@types/react-window": "1.8.5",
|
||||
"@types/resemblejs": "^4.1.0",
|
||||
"@types/unorm": "1.3.28",
|
||||
"@types/uuid": "8.3.4",
|
||||
"@types/w3c-image-capture": "1.0.6",
|
||||
@@ -157,7 +157,7 @@
|
||||
"babel-plugin-optional-require": "0.3.1",
|
||||
"circular-dependency-plugin": "5.2.0",
|
||||
"clean-css-cli": "4.3.0",
|
||||
"css-loader": "3.6.0",
|
||||
"css-loader": "6.8.1",
|
||||
"eslint": "8.40.0",
|
||||
"eslint-plugin-import": "2.27.5",
|
||||
"eslint-plugin-jsdoc": "37.0.3",
|
||||
|
||||
@@ -2,7 +2,7 @@ diff --git a/node_modules/react-native/React/CoreModules/RCTTiming.mm b/node_mod
|
||||
index 13d0d57..00e5d4c 100644
|
||||
--- a/node_modules/react-native/React/CoreModules/RCTTiming.mm
|
||||
+++ b/node_modules/react-native/React/CoreModules/RCTTiming.mm
|
||||
@@ -127,7 +127,15 @@ - (void)setup
|
||||
@@ -127,7 +127,15 @@ RCT_EXPORT_MODULE()
|
||||
{
|
||||
_paused = YES;
|
||||
_timers = [NSMutableDictionary new];
|
||||
@@ -19,7 +19,7 @@ index 13d0d57..00e5d4c 100644
|
||||
|
||||
for (NSString *name in @[
|
||||
UIApplicationWillResignActiveNotification,
|
||||
@@ -146,6 +154,11 @@ - (void)setup
|
||||
@@ -146,6 +154,11 @@ RCT_EXPORT_MODULE()
|
||||
name:name
|
||||
object:nil];
|
||||
}
|
||||
@@ -31,7 +31,7 @@ index 13d0d57..00e5d4c 100644
|
||||
}
|
||||
|
||||
- (void)dealloc
|
||||
@@ -182,6 +195,16 @@ - (void)appDidMoveToForeground
|
||||
@@ -182,6 +195,16 @@ RCT_EXPORT_MODULE()
|
||||
[self startTimers];
|
||||
}
|
||||
|
||||
@@ -73,6 +73,13 @@ cd ios && pod install && cd ..
|
||||
<uses-permission android:name="android.permission.RECORD_AUDIO" />
|
||||
<uses-permission android:name="android.permission.CAMERA" />
|
||||
```
|
||||
- In `android/app/src/main/AndroidManifest.xml`, under the `</application>` tag, include
|
||||
```xml
|
||||
<service
|
||||
android:name="org.jitsi.meet.sdk.JitsiMeetOngoingConferenceService"
|
||||
android:foregroundServiceType="mediaProjection" />
|
||||
```
|
||||
This will take care of the screen share feature.
|
||||
|
||||
If you want to test all the steps before applying them to your app, you can check our React Native SDK sample app here:
|
||||
https://github.com/jitsi/jitsi-meet-sdk-samples/tree/master/react-native
|
||||
@@ -87,3 +94,6 @@ https://github.com/jitsi/jitsi-meet-sdk-samples/tree/master/react-native
|
||||
serverURL={'https://meet.jit.si/'}
|
||||
token={'dkhalhfajhflahlfaahalhfahfsl'} />
|
||||
```
|
||||
|
||||
For more details on how you can use React Native SDK with React Native app, you can follow this link:
|
||||
https://jitsi.github.io/handbook/docs/dev-guide/dev-guide-react-native-sdk
|
||||
|
||||
@@ -0,0 +1,44 @@
|
||||
package org.jitsi.meet.sdk;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.Context;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
import com.facebook.react.bridge.ReactApplicationContext;
|
||||
import com.facebook.react.bridge.ReactContextBaseJavaModule;
|
||||
import com.facebook.react.bridge.ReactMethod;
|
||||
import com.facebook.react.module.annotations.ReactModule;
|
||||
|
||||
|
||||
@ReactModule(name = JMOngoingConferenceModule.NAME)
|
||||
class JMOngoingConferenceModule
|
||||
extends ReactContextBaseJavaModule {
|
||||
|
||||
public static final String NAME = "JMOngoingConference";
|
||||
|
||||
public JMOngoingConferenceModule(ReactApplicationContext reactContext) {
|
||||
super(reactContext);
|
||||
}
|
||||
|
||||
@ReactMethod
|
||||
public void launch() {
|
||||
Context context = getReactApplicationContext();
|
||||
Activity currentActivity = getCurrentActivity();
|
||||
|
||||
JitsiMeetOngoingConferenceService.launch(context, currentActivity);
|
||||
}
|
||||
|
||||
@ReactMethod
|
||||
public void abort() {
|
||||
Context context = getReactApplicationContext();
|
||||
|
||||
JitsiMeetOngoingConferenceService.abort(context);
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public String getName() {
|
||||
return NAME;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,101 @@
|
||||
/*
|
||||
* Copyright @ 2019-present 8x8, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.jitsi.meet.sdk;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.app.Notification;
|
||||
import android.app.NotificationManager;
|
||||
import android.app.Service;
|
||||
import android.content.ComponentName;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.IntentFilter;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.os.IBinder;
|
||||
|
||||
import org.jitsi.meet.sdk.log.JitsiMeetLogger;
|
||||
|
||||
import java.util.HashMap;
|
||||
|
||||
/**
|
||||
* This class implements an Android {@link Service}, a foreground one specifically, and it's
|
||||
* responsible for presenting an ongoing notification when a conference is in progress.
|
||||
* The service will help keep the app running while in the background.
|
||||
*
|
||||
* See: https://developer.android.com/guide/components/services
|
||||
*/
|
||||
public class JitsiMeetOngoingConferenceService extends Service {
|
||||
private static final String TAG = JitsiMeetOngoingConferenceService.class.getSimpleName();
|
||||
|
||||
public static void launch(Context context, Activity currentActivity) {
|
||||
|
||||
RNOngoingNotification.createOngoingConferenceNotificationChannel(currentActivity);
|
||||
|
||||
Intent intent = new Intent(context, JitsiMeetOngoingConferenceService.class);
|
||||
|
||||
ComponentName componentName;
|
||||
|
||||
try {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||
componentName = context.startForegroundService(intent);
|
||||
} else {
|
||||
componentName = context.startService(intent);
|
||||
}
|
||||
} catch (RuntimeException e) {
|
||||
// Avoid crashing due to ForegroundServiceStartNotAllowedException (API level 31).
|
||||
// See: https://developer.android.com/guide/components/foreground-services#background-start-restrictions
|
||||
JitsiMeetLogger.w(TAG + " Ongoing conference service not started", e);
|
||||
return;
|
||||
}
|
||||
|
||||
if (componentName == null) {
|
||||
JitsiMeetLogger.w(TAG + " Ongoing conference service not started");
|
||||
}
|
||||
}
|
||||
|
||||
public static void abort(Context context) {
|
||||
Intent intent = new Intent(context, JitsiMeetOngoingConferenceService.class);
|
||||
context.stopService(intent);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreate() {
|
||||
super.onCreate();
|
||||
|
||||
Notification notification = RNOngoingNotification.buildOngoingConferenceNotification(this);
|
||||
|
||||
if (notification == null) {
|
||||
stopSelf();
|
||||
JitsiMeetLogger.w(TAG + " Couldn't start service, notification is null");
|
||||
} else {
|
||||
startForeground(RNOngoingNotification.NOTIFICATION_ID, notification);
|
||||
JitsiMeetLogger.i(TAG + " Service started");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public IBinder onBind(Intent intent) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int onStartCommand(Intent intent, int flags, int startId) {
|
||||
|
||||
return START_NOT_STICKY;
|
||||
}
|
||||
}
|
||||
@@ -21,6 +21,7 @@ public class JitsiMeetReactNativePackage implements ReactPackage {
|
||||
new AndroidSettingsModule(reactContext),
|
||||
new AppInfoModule(reactContext),
|
||||
new AudioModeModule(reactContext),
|
||||
new JMOngoingConferenceModule(reactContext),
|
||||
new JavaScriptSandboxModule(reactContext),
|
||||
new LocaleDetector(reactContext),
|
||||
new LogBridgeModule(reactContext),
|
||||
|
||||
@@ -0,0 +1,98 @@
|
||||
/*
|
||||
* Copyright @ 2019-present 8x8, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.jitsi.meet.sdk;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.app.Notification;
|
||||
import android.app.NotificationChannel;
|
||||
import android.app.NotificationManager;
|
||||
import android.app.PendingIntent;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.os.Build;
|
||||
|
||||
import androidx.annotation.StringRes;
|
||||
import androidx.core.app.NotificationCompat;
|
||||
|
||||
import org.jitsi.meet.sdk.log.JitsiMeetLogger;
|
||||
|
||||
import java.util.Random;
|
||||
|
||||
/**
|
||||
* Helper class for creating the ongoing notification which is used with
|
||||
* {@link JitsiMeetOngoingConferenceService}. It allows the user to easily get back to the app
|
||||
* and to hangup from within the notification itself.
|
||||
*/
|
||||
class RNOngoingNotification {
|
||||
private static final String TAG = RNOngoingNotification.class.getSimpleName();
|
||||
|
||||
static final int NOTIFICATION_ID = new Random().nextInt(99999) + 10000;
|
||||
|
||||
static void createOngoingConferenceNotificationChannel(Activity currentActivity) {
|
||||
|
||||
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (currentActivity == null) {
|
||||
JitsiMeetLogger.w(TAG + " Cannot create notification channel: no current context");
|
||||
return;
|
||||
}
|
||||
|
||||
NotificationManager notificationManager
|
||||
= (NotificationManager) currentActivity.getSystemService(Context.NOTIFICATION_SERVICE);
|
||||
|
||||
NotificationChannel channel
|
||||
= notificationManager.getNotificationChannel("JitsiOngoingConferenceChannel");
|
||||
if (channel != null) {
|
||||
// The channel was already created, no need to do it again.
|
||||
return;
|
||||
}
|
||||
|
||||
channel = new NotificationChannel("JitsiOngoingConferenceChannel", currentActivity.getString(R.string.ongoing_notification_channel_name), NotificationManager.IMPORTANCE_DEFAULT);
|
||||
channel.enableLights(false);
|
||||
channel.enableVibration(false);
|
||||
channel.setShowBadge(false);
|
||||
|
||||
notificationManager.createNotificationChannel(channel);
|
||||
}
|
||||
|
||||
static Notification buildOngoingConferenceNotification(Context context) {
|
||||
|
||||
if (context == null) {
|
||||
JitsiMeetLogger.w(TAG + " Cannot create notification: no current context");
|
||||
return null;
|
||||
}
|
||||
|
||||
NotificationCompat.Builder builder = new NotificationCompat.Builder(context, "JitsiOngoingConferenceChannel");
|
||||
|
||||
builder
|
||||
.setCategory(NotificationCompat.CATEGORY_CALL)
|
||||
.setContentTitle(context.getString(R.string.ongoing_notification_title))
|
||||
.setContentText(context.getString(R.string.ongoing_notification_text))
|
||||
.setPriority(NotificationCompat.PRIORITY_DEFAULT)
|
||||
.setOngoing(true)
|
||||
.setWhen(System.currentTimeMillis())
|
||||
.setUsesChronometer(true)
|
||||
.setAutoCancel(false)
|
||||
.setVisibility(NotificationCompat.VISIBILITY_PUBLIC)
|
||||
.setOnlyAlertOnce(true)
|
||||
.setSmallIcon(context.getResources().getIdentifier("ic_notification", "drawable", context.getPackageName()));
|
||||
|
||||
return builder.build();
|
||||
}
|
||||
}
|
||||
@@ -19,6 +19,8 @@ import { setAudioMuted, setVideoMuted } from './react/features/base/media/action
|
||||
|
||||
|
||||
interface IEventListeners {
|
||||
onAudioMutedChanged?: Function;
|
||||
onVideoMutedChanged?: Function;
|
||||
onConferenceBlurred?: Function;
|
||||
onConferenceFocused?: Function;
|
||||
onConferenceJoined?: Function;
|
||||
@@ -107,6 +109,8 @@ export const JitsiMeeting = forwardRef((props: IAppProps, ref) => {
|
||||
setAppProps({
|
||||
'flags': flags,
|
||||
'rnSdkHandlers': {
|
||||
onAudioMutedChanged: eventListeners?.onAudioMutedChanged,
|
||||
onVideoMutedChanged: eventListeners?.onVideoMutedChanged,
|
||||
onConferenceBlurred: eventListeners?.onConferenceBlurred,
|
||||
onConferenceFocused: eventListeners?.onConferenceFocused,
|
||||
onConferenceJoined: eventListeners?.onConferenceJoined,
|
||||
|
||||
120
react-native-sdk/package-lock.json
generated
120
react-native-sdk/package-lock.json
generated
@@ -154,11 +154,11 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@babel/generator": {
|
||||
"version": "7.22.15",
|
||||
"resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.22.15.tgz",
|
||||
"integrity": "sha512-Zu9oWARBqeVOW0dZOjXc3JObrzuqothQ3y/n1kUtrjCoCPLkXUwMvOo/F/TCfoHMbWIFlWwpZtkZVb9ga4U2pA==",
|
||||
"version": "7.23.0",
|
||||
"resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.23.0.tgz",
|
||||
"integrity": "sha512-lN85QRR+5IbYrMWM6Y4pE/noaQtg4pNiqeNGX60eqOfo6gtEj6uw/JagelB8vVztSd7R6M5n1+PQkDbHbBRU4g==",
|
||||
"dependencies": {
|
||||
"@babel/types": "^7.22.15",
|
||||
"@babel/types": "^7.23.0",
|
||||
"@jridgewell/gen-mapping": "^0.3.2",
|
||||
"@jridgewell/trace-mapping": "^0.3.17",
|
||||
"jsesc": "^2.5.1"
|
||||
@@ -191,20 +191,20 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@babel/helper-environment-visitor": {
|
||||
"version": "7.22.5",
|
||||
"resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.22.5.tgz",
|
||||
"integrity": "sha512-XGmhECfVA/5sAt+H+xpSg0mfrHq6FzNr9Oxh7PSEBBRUb/mL7Kz3NICXb194rCqAEdxkhPT1a88teizAFyvk8Q==",
|
||||
"version": "7.22.20",
|
||||
"resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.22.20.tgz",
|
||||
"integrity": "sha512-zfedSIzFhat/gFhWfHtgWvlec0nqB9YEIVrpuwjruLlXfUSnA8cJB0miHKwqDnQ7d32aKo2xt88/xZptwxbfhA==",
|
||||
"engines": {
|
||||
"node": ">=6.9.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@babel/helper-function-name": {
|
||||
"version": "7.22.5",
|
||||
"resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.22.5.tgz",
|
||||
"integrity": "sha512-wtHSq6jMRE3uF2otvfuD3DIvVhOsSNshQl0Qrd7qC9oQJzHvOL4qQXlQn2916+CXGywIjpGuIkoyZRRxHPiNQQ==",
|
||||
"version": "7.23.0",
|
||||
"resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.23.0.tgz",
|
||||
"integrity": "sha512-OErEqsrxjZTJciZ4Oo+eoZqeW9UIiOcuYKRJA4ZAgV9myA+pOXhhmpfNCKjEH/auVfEYVFJ6y1Tc4r0eIApqiw==",
|
||||
"dependencies": {
|
||||
"@babel/template": "^7.22.5",
|
||||
"@babel/types": "^7.22.5"
|
||||
"@babel/template": "^7.22.15",
|
||||
"@babel/types": "^7.23.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=6.9.0"
|
||||
@@ -281,9 +281,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@babel/helper-validator-identifier": {
|
||||
"version": "7.22.15",
|
||||
"resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.15.tgz",
|
||||
"integrity": "sha512-4E/F9IIEi8WR94324mbDUMo074YTheJmd7eZF5vITTeYchqAi6sYXRLHUVsmkdmY4QjfKTcB2jB7dVP3NaBElQ==",
|
||||
"version": "7.22.20",
|
||||
"resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.20.tgz",
|
||||
"integrity": "sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A==",
|
||||
"engines": {
|
||||
"node": ">=6.9.0"
|
||||
}
|
||||
@@ -323,9 +323,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@babel/parser": {
|
||||
"version": "7.22.15",
|
||||
"resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.22.15.tgz",
|
||||
"integrity": "sha512-RWmQ/sklUN9BvGGpCDgSubhHWfAx24XDTDObup4ffvxaYsptOg2P3KG0j+1eWKLxpkX0j0uHxmpq2Z1SP/VhxA==",
|
||||
"version": "7.23.0",
|
||||
"resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.23.0.tgz",
|
||||
"integrity": "sha512-vvPKKdMemU85V9WE/l5wZEmImpCtLqbnTvqDS2U1fJ96KrxoW7KrXhNsNCblQlg8Ck4b85yxdTyelsMUgFUXiw==",
|
||||
"bin": {
|
||||
"parser": "bin/babel-parser.js"
|
||||
},
|
||||
@@ -358,18 +358,18 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@babel/traverse": {
|
||||
"version": "7.22.15",
|
||||
"resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.22.15.tgz",
|
||||
"integrity": "sha512-DdHPwvJY0sEeN4xJU5uRLmZjgMMDIvMPniLuYzUVXj/GGzysPl0/fwt44JBkyUIzGJPV8QgHMcQdQ34XFuKTYQ==",
|
||||
"version": "7.23.2",
|
||||
"resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.23.2.tgz",
|
||||
"integrity": "sha512-azpe59SQ48qG6nu2CzcMLbxUudtN+dOM9kDbUqGq3HXUJRlo7i8fvPoxQUzYgLZ4cMVmuZgm8vvBpNeRhd6XSw==",
|
||||
"dependencies": {
|
||||
"@babel/code-frame": "^7.22.13",
|
||||
"@babel/generator": "^7.22.15",
|
||||
"@babel/helper-environment-visitor": "^7.22.5",
|
||||
"@babel/helper-function-name": "^7.22.5",
|
||||
"@babel/generator": "^7.23.0",
|
||||
"@babel/helper-environment-visitor": "^7.22.20",
|
||||
"@babel/helper-function-name": "^7.23.0",
|
||||
"@babel/helper-hoist-variables": "^7.22.5",
|
||||
"@babel/helper-split-export-declaration": "^7.22.6",
|
||||
"@babel/parser": "^7.22.15",
|
||||
"@babel/types": "^7.22.15",
|
||||
"@babel/parser": "^7.23.0",
|
||||
"@babel/types": "^7.23.0",
|
||||
"debug": "^4.1.0",
|
||||
"globals": "^11.1.0"
|
||||
},
|
||||
@@ -378,12 +378,12 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@babel/types": {
|
||||
"version": "7.22.15",
|
||||
"resolved": "https://registry.npmjs.org/@babel/types/-/types-7.22.15.tgz",
|
||||
"integrity": "sha512-X+NLXr0N8XXmN5ZsaQdm9U2SSC3UbIYq/doL++sueHOTisgZHoKaQtZxGuV2cUPQHMfjKEfg/g6oy7Hm6SKFtA==",
|
||||
"version": "7.23.0",
|
||||
"resolved": "https://registry.npmjs.org/@babel/types/-/types-7.23.0.tgz",
|
||||
"integrity": "sha512-0oIyUfKoI3mSqMvsxBdclDwxXKXAUA8v/apZbc+iSyARYou1o8ZGDxbUYyLFoW2arqS2jDGqJuZvv1d/io1axg==",
|
||||
"dependencies": {
|
||||
"@babel/helper-string-parser": "^7.22.5",
|
||||
"@babel/helper-validator-identifier": "^7.22.15",
|
||||
"@babel/helper-validator-identifier": "^7.22.20",
|
||||
"to-fast-properties": "^2.0.0"
|
||||
},
|
||||
"engines": {
|
||||
@@ -3866,11 +3866,11 @@
|
||||
}
|
||||
},
|
||||
"@babel/generator": {
|
||||
"version": "7.22.15",
|
||||
"resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.22.15.tgz",
|
||||
"integrity": "sha512-Zu9oWARBqeVOW0dZOjXc3JObrzuqothQ3y/n1kUtrjCoCPLkXUwMvOo/F/TCfoHMbWIFlWwpZtkZVb9ga4U2pA==",
|
||||
"version": "7.23.0",
|
||||
"resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.23.0.tgz",
|
||||
"integrity": "sha512-lN85QRR+5IbYrMWM6Y4pE/noaQtg4pNiqeNGX60eqOfo6gtEj6uw/JagelB8vVztSd7R6M5n1+PQkDbHbBRU4g==",
|
||||
"requires": {
|
||||
"@babel/types": "^7.22.15",
|
||||
"@babel/types": "^7.23.0",
|
||||
"@jridgewell/gen-mapping": "^0.3.2",
|
||||
"@jridgewell/trace-mapping": "^0.3.17",
|
||||
"jsesc": "^2.5.1"
|
||||
@@ -3896,17 +3896,17 @@
|
||||
}
|
||||
},
|
||||
"@babel/helper-environment-visitor": {
|
||||
"version": "7.22.5",
|
||||
"resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.22.5.tgz",
|
||||
"integrity": "sha512-XGmhECfVA/5sAt+H+xpSg0mfrHq6FzNr9Oxh7PSEBBRUb/mL7Kz3NICXb194rCqAEdxkhPT1a88teizAFyvk8Q=="
|
||||
"version": "7.22.20",
|
||||
"resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.22.20.tgz",
|
||||
"integrity": "sha512-zfedSIzFhat/gFhWfHtgWvlec0nqB9YEIVrpuwjruLlXfUSnA8cJB0miHKwqDnQ7d32aKo2xt88/xZptwxbfhA=="
|
||||
},
|
||||
"@babel/helper-function-name": {
|
||||
"version": "7.22.5",
|
||||
"resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.22.5.tgz",
|
||||
"integrity": "sha512-wtHSq6jMRE3uF2otvfuD3DIvVhOsSNshQl0Qrd7qC9oQJzHvOL4qQXlQn2916+CXGywIjpGuIkoyZRRxHPiNQQ==",
|
||||
"version": "7.23.0",
|
||||
"resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.23.0.tgz",
|
||||
"integrity": "sha512-OErEqsrxjZTJciZ4Oo+eoZqeW9UIiOcuYKRJA4ZAgV9myA+pOXhhmpfNCKjEH/auVfEYVFJ6y1Tc4r0eIApqiw==",
|
||||
"requires": {
|
||||
"@babel/template": "^7.22.5",
|
||||
"@babel/types": "^7.22.5"
|
||||
"@babel/template": "^7.22.15",
|
||||
"@babel/types": "^7.23.0"
|
||||
}
|
||||
},
|
||||
"@babel/helper-hoist-variables": {
|
||||
@@ -3959,9 +3959,9 @@
|
||||
"integrity": "sha512-mM4COjgZox8U+JcXQwPijIZLElkgEpO5rsERVDJTc2qfCDfERyob6k5WegS14SX18IIjv+XD+GrqNumY5JRCDw=="
|
||||
},
|
||||
"@babel/helper-validator-identifier": {
|
||||
"version": "7.22.15",
|
||||
"resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.15.tgz",
|
||||
"integrity": "sha512-4E/F9IIEi8WR94324mbDUMo074YTheJmd7eZF5vITTeYchqAi6sYXRLHUVsmkdmY4QjfKTcB2jB7dVP3NaBElQ=="
|
||||
"version": "7.22.20",
|
||||
"resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.20.tgz",
|
||||
"integrity": "sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A=="
|
||||
},
|
||||
"@babel/helper-validator-option": {
|
||||
"version": "7.22.15",
|
||||
@@ -3989,9 +3989,9 @@
|
||||
}
|
||||
},
|
||||
"@babel/parser": {
|
||||
"version": "7.22.15",
|
||||
"resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.22.15.tgz",
|
||||
"integrity": "sha512-RWmQ/sklUN9BvGGpCDgSubhHWfAx24XDTDObup4ffvxaYsptOg2P3KG0j+1eWKLxpkX0j0uHxmpq2Z1SP/VhxA=="
|
||||
"version": "7.23.0",
|
||||
"resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.23.0.tgz",
|
||||
"integrity": "sha512-vvPKKdMemU85V9WE/l5wZEmImpCtLqbnTvqDS2U1fJ96KrxoW7KrXhNsNCblQlg8Ck4b85yxdTyelsMUgFUXiw=="
|
||||
},
|
||||
"@babel/runtime": {
|
||||
"version": "7.22.5",
|
||||
@@ -4012,29 +4012,29 @@
|
||||
}
|
||||
},
|
||||
"@babel/traverse": {
|
||||
"version": "7.22.15",
|
||||
"resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.22.15.tgz",
|
||||
"integrity": "sha512-DdHPwvJY0sEeN4xJU5uRLmZjgMMDIvMPniLuYzUVXj/GGzysPl0/fwt44JBkyUIzGJPV8QgHMcQdQ34XFuKTYQ==",
|
||||
"version": "7.23.2",
|
||||
"resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.23.2.tgz",
|
||||
"integrity": "sha512-azpe59SQ48qG6nu2CzcMLbxUudtN+dOM9kDbUqGq3HXUJRlo7i8fvPoxQUzYgLZ4cMVmuZgm8vvBpNeRhd6XSw==",
|
||||
"requires": {
|
||||
"@babel/code-frame": "^7.22.13",
|
||||
"@babel/generator": "^7.22.15",
|
||||
"@babel/helper-environment-visitor": "^7.22.5",
|
||||
"@babel/helper-function-name": "^7.22.5",
|
||||
"@babel/generator": "^7.23.0",
|
||||
"@babel/helper-environment-visitor": "^7.22.20",
|
||||
"@babel/helper-function-name": "^7.23.0",
|
||||
"@babel/helper-hoist-variables": "^7.22.5",
|
||||
"@babel/helper-split-export-declaration": "^7.22.6",
|
||||
"@babel/parser": "^7.22.15",
|
||||
"@babel/types": "^7.22.15",
|
||||
"@babel/parser": "^7.23.0",
|
||||
"@babel/types": "^7.23.0",
|
||||
"debug": "^4.1.0",
|
||||
"globals": "^11.1.0"
|
||||
}
|
||||
},
|
||||
"@babel/types": {
|
||||
"version": "7.22.15",
|
||||
"resolved": "https://registry.npmjs.org/@babel/types/-/types-7.22.15.tgz",
|
||||
"integrity": "sha512-X+NLXr0N8XXmN5ZsaQdm9U2SSC3UbIYq/doL++sueHOTisgZHoKaQtZxGuV2cUPQHMfjKEfg/g6oy7Hm6SKFtA==",
|
||||
"version": "7.23.0",
|
||||
"resolved": "https://registry.npmjs.org/@babel/types/-/types-7.23.0.tgz",
|
||||
"integrity": "sha512-0oIyUfKoI3mSqMvsxBdclDwxXKXAUA8v/apZbc+iSyARYou1o8ZGDxbUYyLFoW2arqS2jDGqJuZvv1d/io1axg==",
|
||||
"requires": {
|
||||
"@babel/helper-string-parser": "^7.22.5",
|
||||
"@babel/helper-validator-identifier": "^7.22.15",
|
||||
"@babel/helper-validator-identifier": "^7.22.20",
|
||||
"to-fast-properties": "^2.0.0"
|
||||
}
|
||||
},
|
||||
|
||||
@@ -38,7 +38,6 @@
|
||||
"react-emoji-render": "1.2.4",
|
||||
"react-i18next": "10.11.4",
|
||||
"react-linkify": "1.0.0-alpha",
|
||||
"react-native-callstats": "3.73.22",
|
||||
"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-svg-transformer": "1.1.0",
|
||||
"react-native-tab-view": "3.5.2",
|
||||
@@ -97,4 +96,4 @@
|
||||
"keywords": [
|
||||
"react-native"
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
26
react-native-sdk/prepare_sdk.js
vendored
26
react-native-sdk/prepare_sdk.js
vendored
@@ -6,7 +6,9 @@ const packageJSON = require('../package.json');
|
||||
const SDKPackageJSON = require('./package.json');
|
||||
|
||||
const androidSourcePath = '../android/sdk/src/main/java/org/jitsi/meet/sdk';
|
||||
const androidMainSourcePath = '../android/sdk/src/main/res';
|
||||
const androidTargetPath = './android/src/main/java/org/jitsi/meet/sdk';
|
||||
const androidMainTargetPath = './android/src/main/res';
|
||||
const iosSrcPath = '../ios/sdk/src';
|
||||
const iosDestPath = './ios/src';
|
||||
|
||||
@@ -169,6 +171,30 @@ copyFolderRecursiveSync(
|
||||
`${androidSourcePath}/log`,
|
||||
`${androidTargetPath}/log`
|
||||
);
|
||||
copyFolderRecursiveSync(
|
||||
`${androidMainSourcePath}/values`,
|
||||
`${androidMainTargetPath}`
|
||||
);
|
||||
copyFolderRecursiveSync(
|
||||
`${androidMainSourcePath}/drawable-hdpi`,
|
||||
`${androidMainTargetPath}`
|
||||
);
|
||||
copyFolderRecursiveSync(
|
||||
`${androidMainSourcePath}/drawable-mdpi`,
|
||||
`${androidMainTargetPath}`
|
||||
);
|
||||
copyFolderRecursiveSync(
|
||||
`${androidMainSourcePath}/drawable-xhdpi`,
|
||||
`${androidMainTargetPath}`
|
||||
);
|
||||
copyFolderRecursiveSync(
|
||||
`${androidMainSourcePath}/drawable-xxhdpi`,
|
||||
`${androidMainTargetPath}`
|
||||
);
|
||||
copyFolderRecursiveSync(
|
||||
`${androidMainSourcePath}/drawable-xxxhdpi`,
|
||||
`${androidMainTargetPath}`
|
||||
);
|
||||
copyFolderRecursiveSync(
|
||||
`${androidSourcePath}/net`,
|
||||
`${androidTargetPath}/log`
|
||||
|
||||
15
react-native-sdk/update_dependencies.js
vendored
15
react-native-sdk/update_dependencies.js
vendored
@@ -25,7 +25,8 @@ function updateDependencies() {
|
||||
updated = true;
|
||||
}
|
||||
|
||||
if (!semver.valid(packageJSON.dependencies[key])) {
|
||||
if (!semver.valid(packageJSON.dependencies[key])
|
||||
&& packageJSON.dependencies[key] !== RNSDKpackageJSON.peerDependencies[key]) {
|
||||
packageJSON.dependencies[key] = RNSDKpackageJSON.peerDependencies[key];
|
||||
updated = true;
|
||||
|
||||
@@ -46,6 +47,18 @@ function updateDependencies() {
|
||||
|
||||
console.log(`${key} is now set to ${RNSDKpackageJSON.peerDependencies[key]}`);
|
||||
}
|
||||
|
||||
if (!semver.valid(RNSDKpackageJSON.peerDependencies[key])
|
||||
&& RNSDKpackageJSON.peerDependencies[key].includes('github')
|
||||
&& packageJSON.dependencies[key] !== RNSDKpackageJSON.peerDependencies[key]) {
|
||||
packageJSON.dependencies[key] = RNSDKpackageJSON.peerDependencies[key];
|
||||
updated = true;
|
||||
|
||||
console.log(
|
||||
`A fix for ${key} is available on ${RNSDKpackageJSON.peerDependencies[key]}.
|
||||
This is now set on your end.`
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
packageJSON.overrides = packageJSON.overrides || {};
|
||||
|
||||
@@ -4,6 +4,7 @@ import React, { Component } from 'react';
|
||||
// in this environment (e.g. JitsiMeetJS or interfaceConfig)
|
||||
import StatelessAvatar from '../base/avatar/components/web/StatelessAvatar';
|
||||
import { getAvatarColor, getInitials } from '../base/avatar/functions';
|
||||
import { DEFAULT_ICON } from '../base/icons/svg/constants';
|
||||
|
||||
import Toolbar from './Toolbar';
|
||||
|
||||
@@ -184,6 +185,7 @@ export default class AlwaysOnTop extends Component<any, IState> {
|
||||
<div id = 'avatarContainer'>
|
||||
<StatelessAvatar
|
||||
color = { getAvatarColor(displayName, customAvatarBackgrounds) }
|
||||
iconUser = { DEFAULT_ICON.IconUser }
|
||||
id = 'avatar'
|
||||
initials = { getInitials(displayName) }
|
||||
url = { avatarURL } />)
|
||||
|
||||
@@ -2,7 +2,8 @@ import React, { Component } from 'react';
|
||||
|
||||
// We need to reference these files directly to avoid loading things that are not available
|
||||
// in this environment (e.g. JitsiMeetJS or interfaceConfig)
|
||||
import { IconMic, IconMicSlash } from '../base/icons/svg';
|
||||
|
||||
import { DEFAULT_ICON } from '../base/icons/svg/constants';
|
||||
import { IProps } from '../base/toolbox/components/AbstractButton';
|
||||
|
||||
import ToolbarButton from './ToolbarButton';
|
||||
@@ -31,8 +32,8 @@ type Props = Partial<IProps>;
|
||||
* Stateless "mute/unmute audio" button for the Always-on-Top windows.
|
||||
*/
|
||||
export default class AudioMuteButton extends Component<Props, IState> {
|
||||
icon = IconMic;
|
||||
toggledIcon = IconMicSlash;
|
||||
icon = DEFAULT_ICON.IconMic;
|
||||
toggledIcon = DEFAULT_ICON.IconMicSlash;
|
||||
accessibilityLabel = 'Audio mute';
|
||||
|
||||
/**
|
||||
|
||||
@@ -2,7 +2,7 @@ import React, { Component } from 'react';
|
||||
|
||||
// We need to reference these files directly to avoid loading things that are not available
|
||||
// in this environment (e.g. JitsiMeetJS or interfaceConfig)
|
||||
import { IconHangup } from '../base/icons/svg';
|
||||
import { DEFAULT_ICON } from '../base/icons/svg/constants';
|
||||
import { IProps } from '../base/toolbox/components/AbstractButton';
|
||||
|
||||
import ToolbarButton from './ToolbarButton';
|
||||
@@ -17,7 +17,7 @@ type Props = Partial<IProps>;
|
||||
export default class HangupButton extends Component<Props> {
|
||||
|
||||
accessibilityLabel = 'Hangup';
|
||||
icon = IconHangup;
|
||||
icon = DEFAULT_ICON.IconHangup;
|
||||
|
||||
/**
|
||||
* Initializes a new {@code HangupButton} instance.
|
||||
|
||||
@@ -2,7 +2,7 @@ import React, { Component } from 'react';
|
||||
|
||||
// We need to reference these files directly to avoid loading things that are not available
|
||||
// in this environment (e.g. JitsiMeetJS or interfaceConfig)
|
||||
import { IconVideo, IconVideoOff } from '../base/icons/svg';
|
||||
import { DEFAULT_ICON } from '../base/icons/svg/constants';
|
||||
import { IProps } from '../base/toolbox/components/AbstractButton';
|
||||
|
||||
import ToolbarButton from './ToolbarButton';
|
||||
@@ -32,8 +32,8 @@ type State = {
|
||||
*/
|
||||
export default class VideoMuteButton extends Component<Props, State> {
|
||||
|
||||
icon = IconVideo;
|
||||
toggledIcon = IconVideoOff;
|
||||
icon = DEFAULT_ICON.IconVideo;
|
||||
toggledIcon = DEFAULT_ICON.IconVideoOff;
|
||||
accessibilityLabel = 'Video mute';
|
||||
|
||||
/**
|
||||
|
||||
@@ -934,3 +934,27 @@ export function createGifSentEvent() {
|
||||
action: 'gif.sent'
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an event which indicates the whiteboard was opened.
|
||||
*
|
||||
* @returns {Object} The event in a format suitable for sending via
|
||||
* sendAnalytics.
|
||||
*/
|
||||
export function createOpenWhiteboardEvent() {
|
||||
return {
|
||||
action: 'whiteboard.open'
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an event which indicates the whiteboard limit was enforced.
|
||||
*
|
||||
* @returns {Object} The event in a format suitable for sending via
|
||||
* sendAnalytics.
|
||||
*/
|
||||
export function createRestrictWhiteboardEvent() {
|
||||
return {
|
||||
action: 'whiteboard.restrict'
|
||||
};
|
||||
}
|
||||
|
||||
@@ -16,6 +16,7 @@ import { getJitsiMeetGlobalNS } from '../base/util/helpers';
|
||||
import { inIframe } from '../base/util/iframeUtils';
|
||||
import { loadScript } from '../base/util/loadScript';
|
||||
import { parseURIString } from '../base/util/uri';
|
||||
import { isPrejoinPageVisible } from '../prejoin/functions';
|
||||
|
||||
import AmplitudeHandler from './handlers/AmplitudeHandler';
|
||||
import MatomoHandler from './handlers/MatomoHandler';
|
||||
@@ -158,9 +159,10 @@ export async function createHandlers({ getState }: IStore) {
|
||||
*
|
||||
* @param {Store} store - The redux store in which the specified {@code action} is being dispatched.
|
||||
* @param {Array<Object>} handlers - The analytics handlers.
|
||||
* @param {boolean|undefined} willShowPrejoin -
|
||||
* @returns {void}
|
||||
*/
|
||||
export function initAnalytics(store: IStore, handlers: Array<Object>) {
|
||||
export function initAnalytics(store: IStore, handlers: Array<Object>, willShowPrejoin?: boolean) {
|
||||
const { getState, dispatch } = store;
|
||||
|
||||
if (!isAnalyticsEnabled(getState) || handlers.length === 0) {
|
||||
@@ -180,8 +182,12 @@ export function initAnalytics(store: IStore, handlers: Array<Object>) {
|
||||
externalApi?: boolean;
|
||||
group?: string;
|
||||
inIframe?: boolean;
|
||||
isPromotedFromVisitor?: boolean;
|
||||
isVisitor?: boolean;
|
||||
server?: string;
|
||||
tenant?: string;
|
||||
wasLobbyVisible?: boolean;
|
||||
wasPrejoinDisplayed?: boolean;
|
||||
websocket?: boolean;
|
||||
} & typeof deploymentInfo = {};
|
||||
|
||||
@@ -207,6 +213,15 @@ export function initAnalytics(store: IStore, handlers: Array<Object>) {
|
||||
// Report the tenant from the URL.
|
||||
permanentProperties.tenant = tenant || '/';
|
||||
|
||||
permanentProperties.wasPrejoinDisplayed = willShowPrejoin ?? isPrejoinPageVisible(state);
|
||||
|
||||
// Currently we don't know if there will be lobby. We will update it to true if we go through lobby.
|
||||
permanentProperties.wasLobbyVisible = false;
|
||||
|
||||
// Setting visitor properties to false by default. We will update them later if it turns out we are visitor.
|
||||
permanentProperties.isVisitor = false;
|
||||
permanentProperties.isPromotedFromVisitor = false;
|
||||
|
||||
// Optionally, include local deployment information based on the
|
||||
// contents of window.config.deploymentInfo.
|
||||
if (deploymentInfo) {
|
||||
@@ -224,7 +239,7 @@ export function initAnalytics(store: IStore, handlers: Array<Object>) {
|
||||
// Set the handlers last, since this triggers emptying of the cache
|
||||
analytics.setAnalyticsHandlers(handlers);
|
||||
|
||||
if (!isMobileBrowser() && browser.isChrome()) {
|
||||
if (!isMobileBrowser() && browser.isChromiumBased()) {
|
||||
const bannerCfg = state['features/base/config'].chromeExtensionBanner;
|
||||
|
||||
checkChromeExtensionsInstalled(bannerCfg).then(extensionsInstalled => {
|
||||
|
||||
@@ -5,6 +5,7 @@ import {
|
||||
SET_ROOM
|
||||
} from '../base/conference/actionTypes';
|
||||
import { SET_CONFIG } from '../base/config/actionTypes';
|
||||
import { analytics } from '../base/lib-jitsi-meet';
|
||||
import { SET_NETWORK_INFO } from '../base/net-info/actionTypes';
|
||||
import MiddlewareRegistry from '../base/redux/MiddlewareRegistry';
|
||||
import {
|
||||
@@ -16,6 +17,10 @@ import {
|
||||
getLocalAudioTrack,
|
||||
getLocalVideoTrack
|
||||
} from '../base/tracks/functions';
|
||||
import { SET_LOBBY_VISIBILITY } from '../lobby/actionTypes';
|
||||
import { getIsLobbyVisible } from '../lobby/functions';
|
||||
import { I_AM_VISITOR_MODE } from '../visitors/actionTypes';
|
||||
import { iAmVisitor } from '../visitors/functions';
|
||||
|
||||
import { createLocalTracksDurationEvent, createNetworkInfoEvent } from './AnalyticsEvents';
|
||||
import { UPDATE_LOCAL_TRACKS_DURATION } from './actionTypes';
|
||||
@@ -81,6 +86,18 @@ function calculateLocalTrackDuration(state: IReduxState) {
|
||||
*/
|
||||
MiddlewareRegistry.register(store => next => action => {
|
||||
switch (action.type) {
|
||||
case I_AM_VISITOR_MODE: {
|
||||
const oldIAmVisitor = iAmVisitor(store.getState());
|
||||
const result = next(action);
|
||||
const newIAmVisitor = iAmVisitor(store.getState());
|
||||
|
||||
analytics.addPermanentProperties({
|
||||
isVisitor: newIAmVisitor,
|
||||
isPromotedFromVisitor: oldIAmVisitor && !newIAmVisitor
|
||||
});
|
||||
|
||||
return result;
|
||||
}
|
||||
case SET_CONFIG:
|
||||
if (navigator.product === 'ReactNative') {
|
||||
// Resetting the analytics is currently not needed for web because
|
||||
@@ -97,7 +114,7 @@ MiddlewareRegistry.register(store => next => action => {
|
||||
const result = next(action);
|
||||
|
||||
createHandlersPromise.then(handlers => {
|
||||
initAnalytics(store, handlers);
|
||||
initAnalytics(store, handlers, action.willShowPrejoin);
|
||||
});
|
||||
|
||||
return result;
|
||||
@@ -144,6 +161,14 @@ MiddlewareRegistry.register(store => next => action => {
|
||||
});
|
||||
break;
|
||||
}
|
||||
case SET_LOBBY_VISIBILITY:
|
||||
if (getIsLobbyVisible(store.getState())) {
|
||||
analytics.addPermanentProperties({
|
||||
wasLobbyVisible: true
|
||||
});
|
||||
}
|
||||
|
||||
break;
|
||||
case SET_NETWORK_INFO:
|
||||
sendAnalytics(
|
||||
createNetworkInfoEvent({
|
||||
|
||||
@@ -1,8 +1,19 @@
|
||||
import { getLocationContextRoot } from '../base/util/uri';
|
||||
// @ts-ignore
|
||||
// eslint-disable-next-line
|
||||
import { openTokenAuthUrl } from '../authentication/actions';
|
||||
|
||||
// @ts-ignore
|
||||
import { getTokenAuthUrl, isTokenAuthEnabled } from '../authentication/functions';
|
||||
import { getJwtExpirationDate } from '../base/jwt/functions';
|
||||
import { MEDIA_TYPE } from '../base/media/constants';
|
||||
import { isLocalTrackMuted } from '../base/tracks/functions.any';
|
||||
import { getLocationContextRoot, parseURIString } from '../base/util/uri';
|
||||
|
||||
import { addTrackStateToURL } from './functions.any';
|
||||
import logger from './logger';
|
||||
import { IStore } from './types';
|
||||
|
||||
|
||||
/**
|
||||
* Redirects to another page generated by replacing the path in the original URL
|
||||
* with the given path.
|
||||
@@ -83,4 +94,68 @@ export function reloadWithStoredParams() {
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether tokenAuthUrl is set, we have a jwt token that will expire soon
|
||||
* and redirect to the auth url to obtain new token if this is the case.
|
||||
*
|
||||
* @param {Dispatch} dispatch - The Redux dispatch function.
|
||||
* @param {Function} getState - The Redux state.
|
||||
* @param {Function} failureCallback - The callback on failure to obtain auth url.
|
||||
* @returns {boolean} Whether we will redirect or not.
|
||||
*/
|
||||
export function maybeRedirectToTokenAuthUrl(
|
||||
dispatch: IStore['dispatch'], getState: IStore['getState'], failureCallback: Function) {
|
||||
const state = getState();
|
||||
const config = state['features/base/config'];
|
||||
const { enabled: audioOnlyEnabled } = state['features/base/audio-only'];
|
||||
const { startAudioOnly } = config;
|
||||
const { locationURL = { href: '' } as URL } = state['features/base/connection'];
|
||||
const audioMuted = isLocalTrackMuted(state['features/base/tracks'], MEDIA_TYPE.AUDIO);
|
||||
const videoMuted = isLocalTrackMuted(state['features/base/tracks'], MEDIA_TYPE.VIDEO);
|
||||
|
||||
if (!isTokenAuthEnabled(config)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// if tokenAuthUrl check jwt if is about to expire go through the url to get new token
|
||||
const jwt = state['features/base/jwt'].jwt;
|
||||
const expirationDate = getJwtExpirationDate(jwt);
|
||||
|
||||
// if there is jwt and its expiration time is less than 3 minutes away
|
||||
// let's obtain new token
|
||||
if (expirationDate && expirationDate.getTime() - Date.now() < 3 * 60 * 1000) {
|
||||
const room = state['features/base/conference'].room;
|
||||
const { tenant } = parseURIString(locationURL.href) || {};
|
||||
|
||||
getTokenAuthUrl(
|
||||
config,
|
||||
locationURL,
|
||||
{
|
||||
audioMuted,
|
||||
audioOnlyEnabled: audioOnlyEnabled || startAudioOnly,
|
||||
skipPrejoin: true,
|
||||
videoMuted
|
||||
},
|
||||
room,
|
||||
tenant
|
||||
)
|
||||
.then((tokenAuthServiceUrl: string | undefined) => {
|
||||
if (!tokenAuthServiceUrl) {
|
||||
logger.warn('Cannot handle login, token service URL is not set');
|
||||
|
||||
return Promise.reject();
|
||||
}
|
||||
|
||||
return dispatch(openTokenAuthUrl(tokenAuthServiceUrl));
|
||||
})
|
||||
.catch(() => {
|
||||
failureCallback();
|
||||
});
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -31,11 +31,11 @@ import { screen } from '../mobile/navigation/routes';
|
||||
import { clearNotifications } from '../notifications/actions';
|
||||
import { isUnsafeRoomWarningEnabled } from '../prejoin/functions';
|
||||
|
||||
import { maybeRedirectToTokenAuthUrl } from './actions.any';
|
||||
import { addTrackStateToURL, getDefaultURL } from './functions.native';
|
||||
import logger from './logger';
|
||||
import { IReloadNowOptions, IStore } from './types';
|
||||
|
||||
|
||||
export * from './actions.any';
|
||||
|
||||
/**
|
||||
@@ -150,9 +150,20 @@ export function appNavigate(uri?: string, options: IReloadNowOptions = {}) {
|
||||
return;
|
||||
}
|
||||
|
||||
let willShowPrejoin = false;
|
||||
let willShowUnsafeRoomWarning = false;
|
||||
|
||||
if (!options.hidePrejoin && isPrejoinPageEnabled(getState()) && room) {
|
||||
if (isUnsafeRoomWarningEnabled(getState()) && isInsecureRoomName(room)) {
|
||||
willShowUnsafeRoomWarning = true;
|
||||
} else {
|
||||
willShowPrejoin = true;
|
||||
}
|
||||
}
|
||||
|
||||
dispatch(setLocationURL(locationURL));
|
||||
dispatch(setConfig(config));
|
||||
dispatch(setRoom(room));
|
||||
dispatch(setRoom(room, willShowPrejoin));
|
||||
|
||||
if (!room) {
|
||||
goBackToRoot(getState(), dispatch);
|
||||
@@ -163,12 +174,10 @@ export function appNavigate(uri?: string, options: IReloadNowOptions = {}) {
|
||||
dispatch(createDesiredLocalTracks());
|
||||
dispatch(clearNotifications());
|
||||
|
||||
if (!options.hidePrejoin && isPrejoinPageEnabled(getState())) {
|
||||
if (isUnsafeRoomWarningEnabled(getState()) && isInsecureRoomName(room)) {
|
||||
navigateRoot(screen.unsafeRoomWarning);
|
||||
} else {
|
||||
navigateRoot(screen.preJoin);
|
||||
}
|
||||
if (willShowUnsafeRoomWarning) {
|
||||
navigateRoot(screen.unsafeRoomWarning);
|
||||
} else if (willShowPrejoin) {
|
||||
navigateRoot(screen.preJoin);
|
||||
} else {
|
||||
dispatch(connect());
|
||||
navigateRoot(screen.conference.root);
|
||||
@@ -205,10 +214,18 @@ export function reloadNow() {
|
||||
// @ts-ignore
|
||||
const newURL = addTrackStateToURL(locationURL, state);
|
||||
|
||||
logger.info(`Reloading the conference using URL: ${locationURL}`);
|
||||
const reloadAction = () => {
|
||||
logger.info(`Reloading the conference using URL: ${locationURL}`);
|
||||
|
||||
dispatch(appNavigate(toURLString(newURL), {
|
||||
hidePrejoin: true
|
||||
}));
|
||||
dispatch(appNavigate(toURLString(newURL), {
|
||||
hidePrejoin: true
|
||||
}));
|
||||
};
|
||||
|
||||
if (maybeRedirectToTokenAuthUrl(dispatch, getState, reloadAction)) {
|
||||
return;
|
||||
}
|
||||
|
||||
reloadAction();
|
||||
};
|
||||
}
|
||||
|
||||
@@ -15,6 +15,7 @@ import { NOTIFICATION_TIMEOUT_TYPE } from '../notifications/constants';
|
||||
import { isWelcomePageEnabled } from '../welcome/functions';
|
||||
|
||||
import {
|
||||
maybeRedirectToTokenAuthUrl,
|
||||
redirectToStaticPage,
|
||||
redirectWithStoredParams,
|
||||
reloadWithStoredParams
|
||||
@@ -170,8 +171,16 @@ export function reloadNow() {
|
||||
const state = getState();
|
||||
const { locationURL } = state['features/base/connection'];
|
||||
|
||||
logger.info(`Reloading the conference using URL: ${locationURL}`);
|
||||
const reloadAction = () => {
|
||||
logger.info(`Reloading the conference using URL: ${locationURL}`);
|
||||
|
||||
dispatch(reloadWithStoredParams());
|
||||
dispatch(reloadWithStoredParams());
|
||||
};
|
||||
|
||||
if (maybeRedirectToTokenAuthUrl(dispatch, getState, reloadAction)) {
|
||||
return;
|
||||
}
|
||||
|
||||
reloadAction();
|
||||
};
|
||||
}
|
||||
|
||||
@@ -7,8 +7,7 @@ import SplashScreen from 'react-native-splash-screen';
|
||||
import BottomSheetContainer from '../../base/dialog/components/native/BottomSheetContainer';
|
||||
import DialogContainer from '../../base/dialog/components/native/DialogContainer';
|
||||
import { updateFlags } from '../../base/flags/actions';
|
||||
import { CALL_INTEGRATION_ENABLED, SERVER_URL_CHANGE_ENABLED } from '../../base/flags/constants';
|
||||
import { getFeatureFlag } from '../../base/flags/functions';
|
||||
import { CALL_INTEGRATION_ENABLED } from '../../base/flags/constants';
|
||||
import { clientResized, setSafeAreaInsets } from '../../base/responsive-ui/actions';
|
||||
import DimensionsDetector from '../../base/responsive-ui/components/DimensionsDetector.native';
|
||||
import { updateSettings } from '../../base/settings/actions';
|
||||
@@ -22,6 +21,7 @@ import { AbstractApp, IProps as AbstractAppProps } from './AbstractApp';
|
||||
import '../middlewares.native';
|
||||
import '../reducers.native';
|
||||
|
||||
|
||||
declare let __DEV__: any;
|
||||
|
||||
const { AppInfo } = NativeModules;
|
||||
@@ -111,7 +111,7 @@ export class App extends AbstractApp<IProps> {
|
||||
*/
|
||||
async _extraInit() {
|
||||
const { dispatch, getState } = this.state.store ?? {};
|
||||
const { flags = {} } = this.props;
|
||||
const { flags = {}, url, userInfo } = this.props;
|
||||
let callIntegrationEnabled = flags[CALL_INTEGRATION_ENABLED as keyof typeof flags];
|
||||
|
||||
// CallKit does not work on the simulator, make sure we disable it.
|
||||
@@ -153,22 +153,19 @@ export class App extends AbstractApp<IProps> {
|
||||
|
||||
await rootNavigationReady;
|
||||
|
||||
// Check if serverURL is configured externally and not allowed to change.
|
||||
const serverURLChangeEnabled = getState && getFeatureFlag(getState(), SERVER_URL_CHANGE_ENABLED, true);
|
||||
// Update specified server URL.
|
||||
if (typeof url !== 'undefined') {
|
||||
|
||||
if (!serverURLChangeEnabled) {
|
||||
// As serverURL is provided externally, so we push it to settings.
|
||||
if (typeof this.props.url !== 'undefined') {
|
||||
// @ts-ignore
|
||||
const { serverURL } = this.props.url;
|
||||
// @ts-ignore
|
||||
const { serverURL } = url;
|
||||
|
||||
if (typeof serverURL !== 'undefined') {
|
||||
dispatch?.(updateSettings({ serverURL }));
|
||||
}
|
||||
if (typeof serverURL !== 'undefined') {
|
||||
dispatch?.(updateSettings({ serverURL }));
|
||||
}
|
||||
}
|
||||
|
||||
dispatch?.(updateSettings(this.props.userInfo || {}));
|
||||
// @ts-ignore
|
||||
dispatch?.(updateSettings(userInfo || {}));
|
||||
|
||||
// Update settings with feature-flag.
|
||||
if (typeof callIntegrationEnabled !== 'undefined') {
|
||||
|
||||
@@ -53,10 +53,22 @@ function _getWebConferenceRoute(state: IReduxState) {
|
||||
if (!browser.isElectron() && config.tokenAuthUrl && config.tokenAuthUrlAutoRedirect
|
||||
&& state['features/authentication'].tokenAuthUrlSuccessful
|
||||
&& !state['features/base/jwt'].jwt && room) {
|
||||
const { locationURL = { href: '' } } = state['features/base/connection'];
|
||||
const { locationURL = { href: '' } as URL } = state['features/base/connection'];
|
||||
const { tenant } = parseURIString(locationURL.href) || {};
|
||||
const { startAudioOnly } = config;
|
||||
|
||||
return getTokenAuthUrl(config, room, tenant)
|
||||
return getTokenAuthUrl(
|
||||
config,
|
||||
locationURL,
|
||||
{
|
||||
audioMuted: false,
|
||||
audioOnlyEnabled: startAudioOnly,
|
||||
skipPrejoin: false,
|
||||
videoMuted: false
|
||||
},
|
||||
room,
|
||||
tenant
|
||||
)
|
||||
.then((url: string | undefined) => {
|
||||
route.href = url;
|
||||
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import '../analytics/middleware';
|
||||
import '../authentication/middleware';
|
||||
import '../av-moderation/middleware';
|
||||
import '../base/app/middleware';
|
||||
import '../base/conference/middleware';
|
||||
import '../base/config/middleware';
|
||||
import '../base/jwt/middleware';
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import '../base/app/middleware';
|
||||
import '../base/connection/middleware';
|
||||
import '../base/i18n/middleware';
|
||||
import '../base/devices/middleware';
|
||||
|
||||
@@ -68,7 +68,7 @@ export function openTokenAuthUrl(tokenAuthServiceUrl: string): any {
|
||||
dispatch(openDialog(LoginQuestionDialog, {
|
||||
handler: () => {
|
||||
// Give time for the dialog to close.
|
||||
setTimeout(() => redirect, 500);
|
||||
setTimeout(() => redirect(), 500);
|
||||
}
|
||||
}));
|
||||
} else {
|
||||
|
||||
@@ -17,6 +17,11 @@ interface IProps {
|
||||
*/
|
||||
_alternativeCancelText?: boolean;
|
||||
|
||||
/**
|
||||
* Is confirm button hidden?
|
||||
*/
|
||||
_isConfirmHidden?: boolean;
|
||||
|
||||
/**
|
||||
* Redux store dispatch function.
|
||||
*/
|
||||
@@ -56,11 +61,14 @@ class WaitForOwnerDialog extends Component<IProps> {
|
||||
* @returns {ReactElement}
|
||||
*/
|
||||
render() {
|
||||
const { _isConfirmHidden } = this.props;
|
||||
|
||||
return (
|
||||
<ConfirmDialog
|
||||
cancelLabel = { this.props._alternativeCancelText ? 'dialog.WaitingForHostButton' : 'dialog.Cancel' }
|
||||
confirmLabel = 'dialog.IamHost'
|
||||
descriptionKey = 'dialog.WaitForHostMsg'
|
||||
isConfirmHidden = { _isConfirmHidden }
|
||||
onCancel = { this._onCancel }
|
||||
onSubmit = { this._onLogin } />
|
||||
);
|
||||
@@ -97,9 +105,11 @@ class WaitForOwnerDialog extends Component<IProps> {
|
||||
*/
|
||||
function mapStateToProps(state: IReduxState) {
|
||||
const { membersOnly, lobbyWaitingForHost } = state['features/base/conference'];
|
||||
const { locationURL } = state['features/base/connection'];
|
||||
|
||||
return {
|
||||
_alternativeCancelText: membersOnly && lobbyWaitingForHost
|
||||
_alternativeCancelText: membersOnly && lobbyWaitingForHost,
|
||||
_isConfirmHidden: locationURL?.hostname?.includes('8x8.vc')
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -13,28 +13,66 @@ export const isTokenAuthEnabled = (config: IConfig): boolean =>
|
||||
/**
|
||||
* Returns the state that we can add as a parameter to the tokenAuthUrl.
|
||||
*
|
||||
* @param {URL} locationURL - The location URL.
|
||||
* @param {Object} options: - Config options {
|
||||
* audioMuted: boolean | undefined
|
||||
* audioOnlyEnabled: boolean | undefined,
|
||||
* skipPrejoin: boolean | undefined,
|
||||
* videoMuted: boolean | undefined
|
||||
* }.
|
||||
* @param {string?} roomName - The room name.
|
||||
* @param {string?} tenant - The tenant name if any.
|
||||
* @param {boolean} skipPrejoin - Whether to skip pre-join page.
|
||||
*
|
||||
* @returns {Object} The state object.
|
||||
*/
|
||||
export const _getTokenAuthState = (
|
||||
locationURL: URL,
|
||||
options: {
|
||||
audioMuted: boolean | undefined;
|
||||
audioOnlyEnabled: boolean | undefined;
|
||||
skipPrejoin: boolean | undefined;
|
||||
videoMuted: boolean | undefined;
|
||||
},
|
||||
roomName: string | undefined,
|
||||
tenant: string | undefined,
|
||||
skipPrejoin: boolean | undefined = false): object => {
|
||||
tenant: string | undefined): object => {
|
||||
const state = {
|
||||
room: roomName,
|
||||
roomSafe: getBackendSafeRoomName(roomName),
|
||||
tenant
|
||||
};
|
||||
|
||||
const {
|
||||
audioMuted = false,
|
||||
audioOnlyEnabled = false,
|
||||
skipPrejoin = false,
|
||||
videoMuted = false
|
||||
} = options;
|
||||
|
||||
if (audioMuted) {
|
||||
|
||||
// @ts-ignore
|
||||
state['config.startWithAudioMuted'] = true;
|
||||
}
|
||||
|
||||
if (audioOnlyEnabled) {
|
||||
|
||||
// @ts-ignore
|
||||
state['config.startAudioOnly'] = true;
|
||||
}
|
||||
|
||||
if (skipPrejoin) {
|
||||
// We have already shown the prejoin screen, no need to show it again after obtaining the token.
|
||||
// @ts-ignore
|
||||
state['config.prejoinConfig.enabled'] = false;
|
||||
}
|
||||
|
||||
const params = new URLSearchParams(window.location.search);
|
||||
if (videoMuted) {
|
||||
|
||||
// @ts-ignore
|
||||
state['config.startWithVideoMuted'] = true;
|
||||
}
|
||||
|
||||
const params = new URLSearchParams(locationURL.hash);
|
||||
|
||||
for (const [ key, value ] of params) {
|
||||
// we allow only config and interfaceConfig overrides in the state
|
||||
|
||||
@@ -14,9 +14,15 @@ export * from './functions.any';
|
||||
* argument to this method.
|
||||
*
|
||||
* @param {Object} config - Configuration state object from store. A URL pattern pointing to the login service.
|
||||
* @param {string} roomName - The name of the conference room for which the user will be authenticated.
|
||||
* @param {string} tenant - The name of the conference tenant.
|
||||
* @param {string} skipPrejoin - The name of the conference room for which the user will be authenticated.
|
||||
* @param {URL} locationURL - The location URL.
|
||||
* @param {Object} options: - Config options {
|
||||
* audioMuted: boolean | undefined
|
||||
* audioOnlyEnabled: boolean | undefined,
|
||||
* skipPrejoin: boolean | undefined,
|
||||
* videoMuted: boolean | undefined
|
||||
* }.
|
||||
* @param {string?} roomName - The room name.
|
||||
* @param {string?} tenant - The tenant name if any.
|
||||
*
|
||||
* @returns {Promise<string|undefined>} - The URL pointing to JWT login service or
|
||||
* <tt>undefined</tt> if the pattern stored in config is not a string and the URL can not be
|
||||
@@ -24,9 +30,23 @@ export * from './functions.any';
|
||||
*/
|
||||
export const getTokenAuthUrl = (
|
||||
config: IConfig,
|
||||
locationURL: URL,
|
||||
options: {
|
||||
audioMuted: boolean | undefined;
|
||||
audioOnlyEnabled: boolean | undefined;
|
||||
skipPrejoin: boolean | undefined;
|
||||
videoMuted: boolean | undefined;
|
||||
},
|
||||
roomName: string | undefined,
|
||||
tenant: string | undefined,
|
||||
skipPrejoin: boolean | undefined = false): Promise<string | undefined> => {
|
||||
// eslint-disable-next-line max-params
|
||||
tenant: string | undefined): Promise<string | undefined> => {
|
||||
|
||||
const {
|
||||
audioMuted = false,
|
||||
audioOnlyEnabled = false,
|
||||
skipPrejoin = false,
|
||||
videoMuted = false
|
||||
} = options;
|
||||
|
||||
let url = config.tokenAuthUrl;
|
||||
|
||||
@@ -35,7 +55,17 @@ export const getTokenAuthUrl = (
|
||||
}
|
||||
|
||||
if (url.indexOf('{state}')) {
|
||||
const state = _getTokenAuthState(roomName, tenant, skipPrejoin);
|
||||
const state = _getTokenAuthState(
|
||||
locationURL,
|
||||
{
|
||||
audioMuted,
|
||||
audioOnlyEnabled,
|
||||
skipPrejoin,
|
||||
videoMuted
|
||||
},
|
||||
roomName,
|
||||
tenant
|
||||
);
|
||||
|
||||
// Append ios=true or android=true to the token URL.
|
||||
// @ts-ignore
|
||||
|
||||
@@ -32,9 +32,15 @@ function _cryptoRandom() {
|
||||
* argument to this method.
|
||||
*
|
||||
* @param {Object} config - Configuration state object from store. A URL pattern pointing to the login service.
|
||||
* @param {string} roomName - The name of the conference room for which the user will be authenticated.
|
||||
* @param {string} tenant - The name of the conference tenant.
|
||||
* @param {string} skipPrejoin - The name of the conference room for which the user will be authenticated.
|
||||
* @param {URL} locationURL - The location URL.
|
||||
* @param {Object} options: - Config options {
|
||||
* audioMuted: boolean | undefined
|
||||
* audioOnlyEnabled: boolean | undefined,
|
||||
* skipPrejoin: boolean | undefined,
|
||||
* videoMuted: boolean | undefined
|
||||
* }.
|
||||
* @param {string?} roomName - The room name.
|
||||
* @param {string?} tenant - The tenant name if any.
|
||||
*
|
||||
* @returns {Promise<string|undefined>} - The URL pointing to JWT login service or
|
||||
* <tt>undefined</tt> if the pattern stored in config is not a string and the URL can not be
|
||||
@@ -42,9 +48,23 @@ function _cryptoRandom() {
|
||||
*/
|
||||
export const getTokenAuthUrl = (
|
||||
config: IConfig,
|
||||
locationURL: URL,
|
||||
options: {
|
||||
audioMuted: boolean | undefined;
|
||||
audioOnlyEnabled: boolean | undefined;
|
||||
skipPrejoin: boolean | undefined;
|
||||
videoMuted: boolean | undefined;
|
||||
},
|
||||
roomName: string | undefined,
|
||||
tenant: string | undefined,
|
||||
skipPrejoin: boolean | undefined = false): Promise<string | undefined> => {
|
||||
// eslint-disable-next-line max-params
|
||||
tenant: string | undefined): Promise<string | undefined> => {
|
||||
|
||||
const {
|
||||
audioMuted = false,
|
||||
audioOnlyEnabled = false,
|
||||
skipPrejoin = false,
|
||||
videoMuted = false
|
||||
} = options;
|
||||
|
||||
let url = config.tokenAuthUrl;
|
||||
|
||||
@@ -53,7 +73,17 @@ export const getTokenAuthUrl = (
|
||||
}
|
||||
|
||||
if (url.indexOf('{state}')) {
|
||||
const state = _getTokenAuthState(roomName, tenant, skipPrejoin);
|
||||
const state = _getTokenAuthState(
|
||||
locationURL,
|
||||
{
|
||||
audioMuted,
|
||||
audioOnlyEnabled,
|
||||
skipPrejoin,
|
||||
videoMuted
|
||||
},
|
||||
roomName,
|
||||
tenant
|
||||
);
|
||||
|
||||
if (browser.isElectron()) {
|
||||
// @ts-ignore
|
||||
|
||||
@@ -13,7 +13,9 @@ import {
|
||||
JitsiConferenceErrors,
|
||||
JitsiConnectionErrors
|
||||
} from '../base/lib-jitsi-meet';
|
||||
import { MEDIA_TYPE } from '../base/media/constants';
|
||||
import MiddlewareRegistry from '../base/redux/MiddlewareRegistry';
|
||||
import { isLocalTrackMuted } from '../base/tracks/functions.any';
|
||||
import { parseURIString } from '../base/util/uri';
|
||||
import { openLogoutDialog } from '../settings/actions';
|
||||
|
||||
@@ -255,8 +257,11 @@ function _handleLogin({ dispatch, getState }: IStore) {
|
||||
const state = getState();
|
||||
const config = state['features/base/config'];
|
||||
const room = state['features/base/conference'].room;
|
||||
const { locationURL = { href: '' } } = state['features/base/connection'];
|
||||
const { locationURL = { href: '' } as URL } = state['features/base/connection'];
|
||||
const { tenant } = parseURIString(locationURL.href) || {};
|
||||
const { enabled: audioOnlyEnabled } = state['features/base/audio-only'];
|
||||
const audioMuted = isLocalTrackMuted(state['features/base/tracks'], MEDIA_TYPE.AUDIO);
|
||||
const videoMuted = isLocalTrackMuted(state['features/base/tracks'], MEDIA_TYPE.VIDEO);
|
||||
|
||||
if (!room) {
|
||||
logger.warn('Cannot handle login, room is undefined!');
|
||||
@@ -270,7 +275,18 @@ function _handleLogin({ dispatch, getState }: IStore) {
|
||||
return;
|
||||
}
|
||||
|
||||
getTokenAuthUrl(config, room, tenant, true)
|
||||
getTokenAuthUrl(
|
||||
config,
|
||||
locationURL,
|
||||
{
|
||||
audioMuted,
|
||||
audioOnlyEnabled,
|
||||
skipPrejoin: true,
|
||||
videoMuted
|
||||
},
|
||||
room,
|
||||
tenant
|
||||
)
|
||||
.then((tokenAuthServiceUrl: string | undefined) => {
|
||||
if (!tokenAuthServiceUrl) {
|
||||
logger.warn('Cannot handle login, token service URL is not set');
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { AnyAction } from 'redux';
|
||||
|
||||
import MiddlewareRegistry from '../../base/redux/MiddlewareRegistry';
|
||||
import MiddlewareRegistry from '../redux/MiddlewareRegistry';
|
||||
import { inIframe } from '../util/iframeUtils';
|
||||
|
||||
import { APP_WILL_MOUNT, APP_WILL_UNMOUNT } from './actionTypes';
|
||||
import logger from './logger';
|
||||
@@ -21,7 +22,9 @@ MiddlewareRegistry.register(() => (next: Function) => async (action: AnyAction)
|
||||
|
||||
switch (action.type) {
|
||||
case APP_WILL_MOUNT: {
|
||||
if ('PressureObserver' in globalThis) {
|
||||
// Disable it inside an iframe until Google fixes the origin trial for 3rd party sources:
|
||||
// https://bugs.chromium.org/p/chromium/issues/detail?id=1504167
|
||||
if (!inIframe() && 'PressureObserver' in globalThis) {
|
||||
pressureObserver = new window.PressureObserver(
|
||||
(records: typeof window.PressureRecord) => {
|
||||
logger.info('Compute pressure state changed:', JSON.stringify(records));
|
||||
@@ -2,6 +2,7 @@ import React, { PureComponent } from 'react';
|
||||
import { connect } from 'react-redux';
|
||||
|
||||
import { IReduxState } from '../../../app/types';
|
||||
import { IconUser } from '../../icons/svg';
|
||||
import { getParticipantById } from '../../participants/functions';
|
||||
import { IParticipant } from '../../participants/types';
|
||||
import { getAvatarColor, getInitials, isCORSAvatarURL } from '../functions';
|
||||
@@ -182,6 +183,7 @@ class Avatar<P extends IProps> extends PureComponent<P, IState> {
|
||||
|
||||
const avatarProps: AbstractProps & {
|
||||
className?: string;
|
||||
iconUser?: any;
|
||||
id?: string;
|
||||
status?: string;
|
||||
testId?: string;
|
||||
@@ -226,6 +228,10 @@ class Avatar<P extends IProps> extends PureComponent<P, IState> {
|
||||
avatarProps.initials = initials;
|
||||
}
|
||||
|
||||
if (navigator.product !== 'ReactNative') {
|
||||
avatarProps.iconUser = IconUser;
|
||||
}
|
||||
|
||||
return (
|
||||
<StatelessAvatar
|
||||
{ ...avatarProps } />
|
||||
|
||||
@@ -2,7 +2,6 @@ import React, { useCallback } from 'react';
|
||||
import { makeStyles } from 'tss-react/mui';
|
||||
|
||||
import Icon from '../../../icons/components/Icon';
|
||||
import { IconUser } from '../../../icons/svg';
|
||||
import { withPixelLineHeight } from '../../../styles/functions.web';
|
||||
import { isIcon } from '../../functions';
|
||||
import { IAvatarProps } from '../../types';
|
||||
@@ -122,6 +121,7 @@ const useStyles = makeStyles()(theme => {
|
||||
const StatelessAvatar = ({
|
||||
className,
|
||||
color,
|
||||
iconUser,
|
||||
id,
|
||||
initials,
|
||||
onAvatarLoadError,
|
||||
@@ -212,7 +212,7 @@ const StatelessAvatar = ({
|
||||
style = { _getAvatarStyle() }>
|
||||
<Icon
|
||||
size = { '50%' }
|
||||
src = { IconUser } />
|
||||
src = { iconUser } />
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -9,7 +9,7 @@ const AVATAR_COLORS = [
|
||||
'#B23683',
|
||||
'#F96E57',
|
||||
'#4380E2',
|
||||
'#2AA076',
|
||||
'#238561',
|
||||
'#00A8B3'
|
||||
];
|
||||
const wordSplitRegex = (/\s+|\.+|_+|;+|-+|,+|\|+|\/+|\\+|"+|'+|\(+|\)+|#+|&+/);
|
||||
|
||||
@@ -5,6 +5,11 @@ export interface IAvatarProps {
|
||||
*/
|
||||
color?: string;
|
||||
|
||||
/**
|
||||
* The user icon(browser only).
|
||||
*/
|
||||
iconUser?: any;
|
||||
|
||||
/**
|
||||
* Initials to be used to render the initials based avatars.
|
||||
*/
|
||||
|
||||
@@ -510,15 +510,18 @@ export function conferenceWillJoin(conference?: IJitsiConference) {
|
||||
*
|
||||
* @param {JitsiConference} conference - The JitsiConference instance which will
|
||||
* be left by the local participant.
|
||||
* @param {boolean} isRedirect - Indicates if the action has been dispatched as part of visitor promotion.
|
||||
* @returns {{
|
||||
* type: CONFERENCE_LEFT,
|
||||
* conference: JitsiConference
|
||||
* conference: JitsiConference,
|
||||
* isRedirect: boolean
|
||||
* }}
|
||||
*/
|
||||
export function conferenceWillLeave(conference?: IJitsiConference) {
|
||||
export function conferenceWillLeave(conference?: IJitsiConference, isRedirect?: boolean) {
|
||||
return {
|
||||
type: CONFERENCE_WILL_LEAVE,
|
||||
conference
|
||||
conference,
|
||||
isRedirect
|
||||
};
|
||||
}
|
||||
|
||||
@@ -897,15 +900,20 @@ export function setObfuscatedRoom(obfuscatedRoom: string, obfuscatedRoomSource:
|
||||
*
|
||||
* @param {(string|undefined)} room - The name of the room of the conference to
|
||||
* be joined.
|
||||
* @param {boolean|undefined} willShowPrejoin - Whether the prejoin should be hidden or not.
|
||||
* NOTE: This argument is used only for mobile currently!
|
||||
*
|
||||
* @returns {{
|
||||
* type: SET_ROOM,
|
||||
* room: string
|
||||
* room: string,
|
||||
* willShowPrejoin: boolean
|
||||
* }}
|
||||
*/
|
||||
export function setRoom(room?: string) {
|
||||
export function setRoom(room?: string, willShowPrejoin?: boolean) {
|
||||
return {
|
||||
type: SET_ROOM,
|
||||
room
|
||||
room,
|
||||
willShowPrejoin
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1008,7 +1016,7 @@ export function redirect(vnode: string, focusJid: string, username: string) {
|
||||
}
|
||||
|
||||
dispatch(overwriteConfig(newConfig)) // @ts-ignore
|
||||
.then(() => dispatch(conferenceWillLeave(conference || joining)))
|
||||
.then(() => dispatch(conferenceWillLeave(conference || joining, true)))
|
||||
.then(() => dispatch(disconnect()))
|
||||
.then(() => dispatch(setIAmVisitor(Boolean(vnode))))
|
||||
|
||||
|
||||
@@ -246,8 +246,6 @@ export function getConferenceOptions(stateful: IStateful) {
|
||||
delete config.analytics?.scriptURLs;
|
||||
delete config.analytics?.amplitudeAPPKey;
|
||||
delete config.analytics?.googleAnalyticsTrackingId;
|
||||
delete options.callStatsID;
|
||||
delete options.callStatsSecret;
|
||||
}
|
||||
|
||||
return options;
|
||||
|
||||
@@ -14,8 +14,10 @@ import { reloadNow } from '../../app/actions';
|
||||
import { IStore } from '../../app/types';
|
||||
import { removeLobbyChatParticipant } from '../../chat/actions.any';
|
||||
import { openDisplayNamePrompt } from '../../display-name/actions';
|
||||
import { isVpaasMeeting } from '../../jaas/functions';
|
||||
import { showErrorNotification } from '../../notifications/actions';
|
||||
import { NOTIFICATION_TIMEOUT_TYPE } from '../../notifications/constants';
|
||||
import { hasDisplayName } from '../../prejoin/utils';
|
||||
import { stopLocalVideoRecording } from '../../recording/actions.any';
|
||||
import LocalRecordingManager from '../../recording/components/Recording/LocalRecordingManager';
|
||||
import { iAmVisitor } from '../../visitors/functions';
|
||||
@@ -276,7 +278,9 @@ function _conferenceJoined({ dispatch, getState }: IStore, next: Function, actio
|
||||
if (requireDisplayName
|
||||
&& !getLocalParticipant(getState)?.name
|
||||
&& !conference.isHidden()) {
|
||||
dispatch(openDisplayNamePrompt(undefined));
|
||||
dispatch(openDisplayNamePrompt({
|
||||
validateInput: hasDisplayName
|
||||
}));
|
||||
}
|
||||
|
||||
return result;
|
||||
@@ -303,7 +307,7 @@ async function _connectionEstablished({ dispatch, getState }: IStore, next: Func
|
||||
|
||||
// if there is token auth URL defined and local participant is using jwt
|
||||
// this means it is logged in when connection is established, so we can change the state
|
||||
if (tokenAuthUrl) {
|
||||
if (tokenAuthUrl && !isVpaasMeeting(getState())) {
|
||||
let email;
|
||||
|
||||
if (getState()['features/base/jwt'].jwt) {
|
||||
|
||||
@@ -73,7 +73,6 @@ export interface IJitsiConference {
|
||||
getSsrcByTrack: Function;
|
||||
grantOwner: Function;
|
||||
isAVModerationSupported: Function;
|
||||
isCallstatsEnabled: Function;
|
||||
isE2EEEnabled: Function;
|
||||
isE2EESupported: Function;
|
||||
isEndConferenceSupported: Function;
|
||||
|
||||
@@ -157,6 +157,13 @@ export interface INoiseSuppressionConfig {
|
||||
};
|
||||
}
|
||||
|
||||
export interface IWhiteboardConfig {
|
||||
collabServerBaseUrl?: string;
|
||||
enabled?: boolean;
|
||||
limitUrl?: string;
|
||||
userLimit?: number;
|
||||
}
|
||||
|
||||
export interface IWatchRTCConfiguration {
|
||||
allowBrowserLogCollection?: boolean;
|
||||
collectionInterval?: number;
|
||||
@@ -224,28 +231,8 @@ export interface IConfig {
|
||||
callDisplayName?: string;
|
||||
callFlowsEnabled?: boolean;
|
||||
callHandle?: string;
|
||||
callStatsConfigParams?: {
|
||||
additionalIDs?: {
|
||||
customerID?: string;
|
||||
fqExtensionID?: string;
|
||||
meetingsName?: string;
|
||||
pbxExtensionID?: string;
|
||||
pbxID?: string;
|
||||
productName?: string;
|
||||
serverName?: string;
|
||||
sessionID?: string;
|
||||
tenantID?: string;
|
||||
};
|
||||
applicationVersion?: string;
|
||||
collectIP?: boolean;
|
||||
collectLegacyStats?: boolean;
|
||||
disableBeforeUnloadHandler?: boolean;
|
||||
disablePrecalltest?: boolean;
|
||||
siteID?: string;
|
||||
};
|
||||
callStatsID?: string;
|
||||
callStatsSecret?: string;
|
||||
callUUID?: string;
|
||||
cameraFacingMode?: string;
|
||||
channelLastN?: number;
|
||||
chromeExtensionBanner?: {
|
||||
chromeExtensionsInfo?: Array<{ id: string; path: string; }>;
|
||||
@@ -452,6 +439,7 @@ export interface IConfig {
|
||||
inviteServiceCallFlowsUrl?: string;
|
||||
inviteServiceUrl?: string;
|
||||
jaasActuatorUrl?: string;
|
||||
jaasConferenceCreatorUrl?: string;
|
||||
jaasFeedbackMetadataURL?: string;
|
||||
jaasTokenUrl?: string;
|
||||
legalUrls?: {
|
||||
@@ -513,6 +501,7 @@ export interface IConfig {
|
||||
pcStatsInterval?: number;
|
||||
peopleSearchQueryTypes?: string[];
|
||||
peopleSearchUrl?: string;
|
||||
preferBosh?: boolean;
|
||||
preferredTranscribeLanguage?: string;
|
||||
prejoinConfig?: {
|
||||
enabled?: boolean;
|
||||
@@ -571,7 +560,6 @@ export interface IConfig {
|
||||
subject?: string;
|
||||
testing?: {
|
||||
assumeBandwidth?: boolean;
|
||||
callStatsThreshold?: number;
|
||||
disableE2EE?: boolean;
|
||||
mobileXmppWsThreshold?: number;
|
||||
noAutoPlayVideo?: boolean;
|
||||
@@ -630,8 +618,5 @@ export interface IConfig {
|
||||
customUrl?: string;
|
||||
disabled?: boolean;
|
||||
};
|
||||
whiteboard?: {
|
||||
collabServerBaseUrl?: string;
|
||||
enabled?: boolean;
|
||||
};
|
||||
whiteboard?: IWhiteboardConfig;
|
||||
}
|
||||
|
||||
@@ -23,6 +23,7 @@ export default [
|
||||
'avgRtpStatsN',
|
||||
'backgroundAlpha',
|
||||
'breakoutRooms',
|
||||
'bridgeChannel',
|
||||
'buttonsWithNotifyClick',
|
||||
|
||||
/**
|
||||
@@ -54,10 +55,6 @@ export default [
|
||||
* @type string
|
||||
*/
|
||||
'callHandle',
|
||||
'callStatsConfIDNamespace',
|
||||
'callStatsConfigParams',
|
||||
'callStatsID',
|
||||
'callStatsSecret',
|
||||
|
||||
/**
|
||||
* The UUID of the CallKit call representing the conference/meeting
|
||||
@@ -74,6 +71,7 @@ export default [
|
||||
*/
|
||||
'callUUID',
|
||||
|
||||
'cameraFacingMode',
|
||||
'conferenceInfo',
|
||||
'channelLastN',
|
||||
'connectionIndicators',
|
||||
@@ -158,7 +156,6 @@ export default [
|
||||
'filmstrip',
|
||||
'firefox_fake_device',
|
||||
'flags',
|
||||
'forceJVB121Ratio',
|
||||
'forceTurnRelay',
|
||||
'gatherStats',
|
||||
'giphy',
|
||||
@@ -197,6 +194,7 @@ export default [
|
||||
'participantMenuButtonsWithNotifyClick',
|
||||
'participantsPane',
|
||||
'pcStatsInterval',
|
||||
'preferBosh',
|
||||
'prejoinConfig',
|
||||
'prejoinPageEnabled',
|
||||
'recordingService',
|
||||
|
||||
@@ -28,8 +28,6 @@ export function _cleanupConfig(config: IConfig) {
|
||||
delete config.analytics?.rtcstatsUseLegacy;
|
||||
delete config.analytics?.obfuscateRoomName;
|
||||
delete config.analytics?.watchRTCEnabled;
|
||||
delete config.callStatsID;
|
||||
delete config.callStatsSecret;
|
||||
delete config.watchRTCConfigParams;
|
||||
config.giphy = { enabled: false };
|
||||
}
|
||||
|
||||
@@ -27,6 +27,7 @@ import { ConnectionFailedError, IIceServers } from './types';
|
||||
*/
|
||||
interface IOptions extends IConfigState {
|
||||
iceServersOverride?: IIceServers;
|
||||
preferVisitor?: boolean;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -112,7 +113,7 @@ export function constructOptions(state: IReduxState) {
|
||||
// redux store.
|
||||
const options: IOptions = _.cloneDeep(state['features/base/config']);
|
||||
|
||||
const { locationURL } = state['features/base/connection'];
|
||||
const { locationURL, preferVisitor } = state['features/base/connection'];
|
||||
const params = parseURLParams(locationURL || '');
|
||||
const iceServersOverride = params['iceServers.replace'];
|
||||
|
||||
@@ -120,7 +121,7 @@ export function constructOptions(state: IReduxState) {
|
||||
options.iceServersOverride = iceServersOverride;
|
||||
}
|
||||
|
||||
const { bosh } = options;
|
||||
const { bosh, preferBosh } = options;
|
||||
let { websocket } = options;
|
||||
|
||||
// TESTING: Only enable WebSocket for some percentage of users.
|
||||
@@ -130,6 +131,10 @@ export function constructOptions(state: IReduxState) {
|
||||
}
|
||||
}
|
||||
|
||||
if (preferBosh) {
|
||||
websocket = undefined;
|
||||
}
|
||||
|
||||
// WebSocket is preferred over BOSH.
|
||||
const serviceUrl = websocket || bosh;
|
||||
|
||||
@@ -151,6 +156,10 @@ export function constructOptions(state: IReduxState) {
|
||||
}
|
||||
}
|
||||
|
||||
if (preferVisitor) {
|
||||
options.preferVisitor = true;
|
||||
}
|
||||
|
||||
return options;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { SET_ROOM } from '../conference/actionTypes';
|
||||
import { SET_JWT } from '../jwt/actionTypes';
|
||||
import { JitsiConnectionErrors } from '../lib-jitsi-meet';
|
||||
import ReducerRegistry from '../redux/ReducerRegistry';
|
||||
import { assign, set } from '../redux/functions';
|
||||
@@ -26,6 +27,7 @@ export interface IConnectionState {
|
||||
error?: ConnectionFailedError;
|
||||
locationURL?: URL;
|
||||
passwordRequired?: Object;
|
||||
preferVisitor?: boolean;
|
||||
showConnectionInfo?: boolean;
|
||||
timeEstablished?: number;
|
||||
}
|
||||
@@ -49,6 +51,9 @@ ReducerRegistry.register<IConnectionState>(
|
||||
case CONNECTION_WILL_CONNECT:
|
||||
return _connectionWillConnect(state, action);
|
||||
|
||||
case SET_JWT:
|
||||
return _setJWT(state, action);
|
||||
|
||||
case SET_LOCATION_URL:
|
||||
return _setLocationURL(state, action);
|
||||
|
||||
@@ -84,6 +89,7 @@ function _connectionDisconnected(
|
||||
return assign(state, {
|
||||
connecting: undefined,
|
||||
connection: undefined,
|
||||
preferVisitor: undefined,
|
||||
timeEstablished: undefined
|
||||
});
|
||||
}
|
||||
@@ -141,7 +147,8 @@ function _connectionFailed(
|
||||
error,
|
||||
passwordRequired:
|
||||
error.name === JitsiConnectionErrors.PASSWORD_REQUIRED
|
||||
? connection : undefined
|
||||
? connection : undefined,
|
||||
preferVisitor: undefined
|
||||
});
|
||||
}
|
||||
|
||||
@@ -184,6 +191,22 @@ function _getCurrentConnection(baseConnectionState: IConnectionState): IConnecti
|
||||
return baseConnectionState.connection || baseConnectionState.connecting;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reduces a specific redux action {@link SET_JWT} of the feature
|
||||
* base/connection.
|
||||
*
|
||||
* @param {IConnectionState} state - The redux state of the feature base/connection.
|
||||
* @param {Action} action - The Redux action SET_JWT to reduce.
|
||||
* @private
|
||||
* @returns {Object} The new state of the feature base/connection after the
|
||||
* reduction of the specified action.
|
||||
*/
|
||||
function _setJWT(state: IConnectionState, { preferVisitor }: { preferVisitor: boolean; }) {
|
||||
return assign(state, {
|
||||
preferVisitor
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reduces a specific redux action {@link SET_LOCATION_URL} of the feature
|
||||
* base/connection.
|
||||
|
||||
@@ -16,9 +16,13 @@ import {
|
||||
} from './actionTypes';
|
||||
import {
|
||||
areDeviceLabelsInitialized,
|
||||
areDevicesDifferent,
|
||||
filterIgnoredDevices,
|
||||
flattenAvailableDevices,
|
||||
getDeviceIdByLabel,
|
||||
getDeviceLabelById,
|
||||
getDevicesFromURL,
|
||||
logDevices,
|
||||
setAudioOutputDeviceId
|
||||
} from './functions';
|
||||
import logger from './logger';
|
||||
@@ -39,7 +43,7 @@ const DEVICE_TYPE_TO_SETTINGS_KEYS = {
|
||||
userSelectedDeviceLabel: 'userSelectedAudioOutputDeviceLabel'
|
||||
},
|
||||
videoInput: {
|
||||
currentDeviceId: 'audioOutputDeviceId',
|
||||
currentDeviceId: 'cameraDeviceId',
|
||||
userSelectedDeviceId: 'userSelectedCameraDeviceId',
|
||||
userSelectedDeviceLabel: 'userSelectedCameraDeviceLabel'
|
||||
}
|
||||
@@ -137,15 +141,21 @@ export function configureInitialDevices() {
|
||||
* @returns {Function}
|
||||
*/
|
||||
export function getAvailableDevices() {
|
||||
return (dispatch: IStore['dispatch']) => new Promise(resolve => {
|
||||
return (dispatch: IStore['dispatch'], getState: IStore['getState']) => new Promise(resolve => {
|
||||
const { mediaDevices } = JitsiMeetJS;
|
||||
|
||||
if (mediaDevices.isDeviceListAvailable()
|
||||
&& mediaDevices.isDeviceChangeAvailable()) {
|
||||
mediaDevices.enumerateDevices((devices: MediaDeviceInfo[]) => {
|
||||
dispatch(updateDeviceList(devices));
|
||||
const { filteredDevices, ignoredDevices } = filterIgnoredDevices(devices);
|
||||
const oldDevices = flattenAvailableDevices(getState()['features/base/devices'].availableDevices);
|
||||
|
||||
resolve(devices);
|
||||
if (areDevicesDifferent(oldDevices, filteredDevices)) {
|
||||
logDevices(ignoredDevices, 'Ignored devices on device list changed:');
|
||||
dispatch(updateDeviceList(filteredDevices));
|
||||
}
|
||||
|
||||
resolve(filteredDevices);
|
||||
});
|
||||
} else {
|
||||
resolve([]);
|
||||
|
||||
8
react/features/base/devices/constants.ts
Normal file
8
react/features/base/devices/constants.ts
Normal file
@@ -0,0 +1,8 @@
|
||||
/**
|
||||
* Prefixes of devices that will be filtered from the device list.
|
||||
*
|
||||
* NOTE: Currently we filter only 'Microsoft Teams Audio Device' virtual device. It seems that it can't be set
|
||||
* as default device on the OS level and this use case is not handled in the code. If we add more device prefixes that
|
||||
* can be default devices we should make sure to handle the default device use case.
|
||||
*/
|
||||
export const DEVICE_LABEL_PREFIXES_TO_IGNORE = [ 'Microsoft Teams Audio Device' ];
|
||||
@@ -5,6 +5,7 @@ import { ISettingsState } from '../settings/reducer';
|
||||
import { setNewAudioOutputDevice } from '../sounds/functions.web';
|
||||
import { parseURLParams } from '../util/parseURLParams';
|
||||
|
||||
import { DEVICE_LABEL_PREFIXES_TO_IGNORE } from './constants';
|
||||
import logger from './logger';
|
||||
import { IDevicesState } from './types';
|
||||
|
||||
@@ -176,6 +177,74 @@ export function filterAudioDevices(devices: MediaDeviceInfo[]) {
|
||||
return devices.filter(device => device.kind === 'audioinput');
|
||||
}
|
||||
|
||||
/**
|
||||
* Filters the devices that start with one of the prefixes from DEVICE_LABEL_PREFIXES_TO_IGNORE.
|
||||
*
|
||||
* @param {MediaDeviceInfo[]} devices - The devices to be filtered.
|
||||
* @returns {MediaDeviceInfo[]} - The filtered devices.
|
||||
*/
|
||||
export function filterIgnoredDevices(devices: MediaDeviceInfo[] = []) {
|
||||
const ignoredDevices: MediaDeviceInfo[] = [];
|
||||
const filteredDevices = devices.filter(device => {
|
||||
if (!device.label) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (DEVICE_LABEL_PREFIXES_TO_IGNORE.find(prefix => device.label?.startsWith(prefix))) {
|
||||
ignoredDevices.push(device);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
});
|
||||
|
||||
return {
|
||||
filteredDevices,
|
||||
ignoredDevices
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the passed device arrays are different.
|
||||
*
|
||||
* @param {MediaDeviceInfo[]} devices1 - Array with devices to be compared.
|
||||
* @param {MediaDeviceInfo[]} devices2 - Array with devices to be compared.
|
||||
* @returns {boolean} - True if the device arrays are different and false otherwise.
|
||||
*/
|
||||
export function areDevicesDifferent(devices1: MediaDeviceInfo[] = [], devices2: MediaDeviceInfo[] = []) {
|
||||
if (devices1.length !== devices2.length) {
|
||||
return true;
|
||||
}
|
||||
|
||||
for (let i = 0; i < devices1.length; i++) {
|
||||
const device1 = devices1[i];
|
||||
const found = devices2.find(({ deviceId, groupId, kind, label }) =>
|
||||
device1.deviceId === deviceId
|
||||
&& device1.groupId === groupId
|
||||
&& device1.kind === kind
|
||||
&& device1.label === label
|
||||
);
|
||||
|
||||
if (!found) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Flattens the availableDevices from redux.
|
||||
*
|
||||
* @param {IDevicesState.availableDevices} devices - The available devices from redux.
|
||||
* @returns {MediaDeviceInfo[]} - The flattened array of devices.
|
||||
*/
|
||||
export function flattenAvailableDevices(
|
||||
{ audioInput = [], audioOutput = [], videoInput = [] }: IDevicesState['availableDevices']) {
|
||||
return audioInput.concat(audioOutput).concat(videoInput);
|
||||
}
|
||||
|
||||
/**
|
||||
* We want to strip any device details that are not very user friendly, like usb ids put in brackets at the end.
|
||||
*
|
||||
@@ -240,6 +309,35 @@ export function getVideoDeviceIds(state: IReduxState) {
|
||||
return state['features/base/devices'].availableDevices.videoInput?.map(({ deviceId }) => deviceId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts an array of device info objects into string.
|
||||
*
|
||||
* @param {MediaDeviceInfo[]} devices - The devices.
|
||||
* @returns {string}
|
||||
*/
|
||||
function devicesToStr(devices?: MediaDeviceInfo[]) {
|
||||
return devices?.map(device => `\t\t${device.label}[${device.deviceId}]`).join('\n');
|
||||
}
|
||||
|
||||
/**
|
||||
* Logs an array of devices.
|
||||
*
|
||||
* @param {MediaDeviceInfo[]} devices - The array of devices.
|
||||
* @param {string} title - The title that will be printed in the log.
|
||||
* @returns {void}
|
||||
*/
|
||||
export function logDevices(devices: MediaDeviceInfo[], title = '') {
|
||||
const deviceList = groupDevicesByKind(devices);
|
||||
const audioInputs = devicesToStr(deviceList.audioInput);
|
||||
const audioOutputs = devicesToStr(deviceList.audioOutput);
|
||||
const videoInputs = devicesToStr(deviceList.videoInput);
|
||||
|
||||
logger.debug(`${title}:\n`
|
||||
+ `audioInput:\n${audioInputs}\n`
|
||||
+ `audioOutput:\n${audioOutputs}\n`
|
||||
+ `videoInput:\n${videoInputs}`);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set device id of the audio output device which is currently in use.
|
||||
* Empty string stands for default device.
|
||||
|
||||
@@ -33,11 +33,10 @@ import {
|
||||
import {
|
||||
areDeviceLabelsInitialized,
|
||||
formatDeviceLabel,
|
||||
groupDevicesByKind,
|
||||
logDevices,
|
||||
setAudioOutputDeviceId
|
||||
} from './functions';
|
||||
import logger from './logger';
|
||||
import { IDevicesState } from './types';
|
||||
|
||||
const JITSI_TRACK_ERROR_TO_MESSAGE_KEY_MAP = {
|
||||
microphone: {
|
||||
@@ -62,25 +61,6 @@ const JITSI_TRACK_ERROR_TO_MESSAGE_KEY_MAP = {
|
||||
*/
|
||||
let permissionsListener: Function | undefined;
|
||||
|
||||
/**
|
||||
* Logs the current device list.
|
||||
*
|
||||
* @param {Object} deviceList - Whatever is returned by {@link groupDevicesByKind}.
|
||||
* @returns {string}
|
||||
*/
|
||||
function logDeviceList(deviceList: IDevicesState['availableDevices']) {
|
||||
const devicesToStr = (list?: MediaDeviceInfo[]) =>
|
||||
list?.map(device => `\t\t${device.label}[${device.deviceId}]`).join('\n');
|
||||
const audioInputs = devicesToStr(deviceList.audioInput);
|
||||
const audioOutputs = devicesToStr(deviceList.audioOutput);
|
||||
const videoInputs = devicesToStr(deviceList.videoInput);
|
||||
|
||||
logger.debug('Device list updated:\n'
|
||||
+ `audioInput:\n${audioInputs}\n`
|
||||
+ `audioOutput:\n${audioOutputs}\n`
|
||||
+ `videoInput:\n${videoInputs}`);
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements the middleware of the feature base/devices.
|
||||
*
|
||||
@@ -199,7 +179,7 @@ MiddlewareRegistry.register(store => next => action => {
|
||||
break;
|
||||
}
|
||||
case UPDATE_DEVICE_LIST:
|
||||
logDeviceList(groupDevicesByKind(action.devices));
|
||||
logDevices(action.devices, 'Device list updated');
|
||||
if (areDeviceLabelsInitialized(store.getState())) {
|
||||
return _processPendingRequests(store, next, action);
|
||||
}
|
||||
|
||||
@@ -41,6 +41,11 @@ interface IProps extends AbstractProps, WithTranslation {
|
||||
*/
|
||||
isConfirmDestructive?: Boolean;
|
||||
|
||||
/**
|
||||
* Whether or not the confirm button is hidden.
|
||||
*/
|
||||
isConfirmHidden?: Boolean;
|
||||
|
||||
/**
|
||||
* Dialog title.
|
||||
*/
|
||||
@@ -60,7 +65,8 @@ class ConfirmDialog extends AbstractDialog<IProps> {
|
||||
* @static
|
||||
*/
|
||||
static defaultProps = {
|
||||
isConfirmDestructive: false
|
||||
isConfirmDestructive: false,
|
||||
isConfirmHidden: false
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -95,6 +101,7 @@ class ConfirmDialog extends AbstractDialog<IProps> {
|
||||
children,
|
||||
confirmLabel,
|
||||
isConfirmDestructive,
|
||||
isConfirmHidden,
|
||||
t,
|
||||
title
|
||||
} = this.props;
|
||||
@@ -118,10 +125,12 @@ class ConfirmDialog extends AbstractDialog<IProps> {
|
||||
label = { t(cancelLabel || 'dialog.confirmNo') }
|
||||
onPress = { this._onCancel }
|
||||
style = { styles.dialogButton } />
|
||||
<Dialog.Button
|
||||
label = { t(confirmLabel || 'dialog.confirmYes') }
|
||||
onPress = { this._onSubmit }
|
||||
style = { dialogButtonStyle } />
|
||||
{
|
||||
!isConfirmHidden && <Dialog.Button
|
||||
label = { t(confirmLabel || 'dialog.confirmYes') }
|
||||
onPress = { this._onSubmit }
|
||||
style = { dialogButtonStyle } />
|
||||
}
|
||||
</Dialog.Container>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -20,6 +20,11 @@ interface IProps extends AbstractProps, WithTranslation {
|
||||
*/
|
||||
descriptionKey?: string;
|
||||
|
||||
/**
|
||||
* Whether to display the cancel button.
|
||||
*/
|
||||
disableCancel?: boolean;
|
||||
|
||||
/**
|
||||
* An optional initial value to initiate the field with.
|
||||
*/
|
||||
@@ -52,6 +57,11 @@ interface IState extends AbstractState {
|
||||
* The current value of the field.
|
||||
*/
|
||||
fieldValue?: string;
|
||||
|
||||
/**
|
||||
* The result of the input validation.
|
||||
*/
|
||||
isValid: boolean;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -68,6 +78,7 @@ class InputDialog extends AbstractDialog<IProps, IState> {
|
||||
|
||||
this.state = {
|
||||
fieldValue: props.initialValue,
|
||||
isValid: props.validateInput ? props.validateInput(props.initialValue) : true,
|
||||
submitting: false
|
||||
};
|
||||
|
||||
@@ -115,10 +126,11 @@ class InputDialog extends AbstractDialog<IProps, IState> {
|
||||
</Dialog.Description>
|
||||
)
|
||||
}
|
||||
<Dialog.Button
|
||||
{!this.props.disableCancel && <Dialog.Button
|
||||
label = { t('dialog.Cancel') }
|
||||
onPress = { this._onCancel } />
|
||||
onPress = { this._onCancel } />}
|
||||
<Dialog.Button
|
||||
disabled = { !this.state.isValid }
|
||||
label = { t('dialog.Ok') }
|
||||
onPress = { this._onSubmitValue } />
|
||||
</Dialog.Container>
|
||||
@@ -132,10 +144,14 @@ class InputDialog extends AbstractDialog<IProps, IState> {
|
||||
* @returns {void}
|
||||
*/
|
||||
_onChangeText(fieldValue: string) {
|
||||
if (this.props.validateInput && !this.props.validateInput(fieldValue)) {
|
||||
if (this.props.validateInput) {
|
||||
this.setState({
|
||||
isValid: this.props.validateInput(fieldValue),
|
||||
fieldValue
|
||||
});
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
this.setState({
|
||||
fieldValue
|
||||
});
|
||||
|
||||
@@ -7,10 +7,11 @@ const { browser } = JitsiMeetJS.util;
|
||||
|
||||
const DEFAULT_OPTIMAL_BROWSERS = [
|
||||
'chrome',
|
||||
'chromium',
|
||||
'electron',
|
||||
'firefox',
|
||||
'nwjs',
|
||||
'safari'
|
||||
'safari',
|
||||
'webkit'
|
||||
];
|
||||
|
||||
const DEFAULT_UNSUPPORTED_BROWSERS: string[] = [];
|
||||
@@ -20,9 +21,8 @@ const browserNameToCheck = {
|
||||
chromium: browser.isChromiumBased.bind(browser),
|
||||
electron: browser.isElectron.bind(browser),
|
||||
firefox: browser.isFirefox.bind(browser),
|
||||
nwjs: browser.isNWJS.bind(browser),
|
||||
opera: browser.isOpera.bind(browser),
|
||||
safari: browser.isSafari.bind(browser)
|
||||
safari: browser.isSafari.bind(browser),
|
||||
webkit: browser.isWebKitBased.bind(browser)
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
@@ -23,6 +23,12 @@ export const AUDIO_MUTE_BUTTON_ENABLED = 'audio-mute.enabled';
|
||||
*/
|
||||
export const AUDIO_ONLY_BUTTON_ENABLED = 'audio-only.enabled';
|
||||
|
||||
/**
|
||||
* Flag indicating that the Breakout Rooms button in the overflow menu is enabled.
|
||||
* Default: enabled (true).
|
||||
*/
|
||||
export const BREAKOUT_ROOMS_BUTTON_ENABLED = 'breakout-rooms.enabled';
|
||||
|
||||
/**
|
||||
* Flag indicating if calendar integration should be enabled.
|
||||
* Default: enabled (true) on Android, auto-detected on iOS.
|
||||
|
||||
@@ -65,9 +65,15 @@ export const DEFAULT_LANGUAGE = 'en';
|
||||
*/
|
||||
const options: i18next.InitOptions = {
|
||||
backend: <HttpBackendOptions>{
|
||||
loadPath: (lng: string[], ns: string[]) =>
|
||||
// eslint-disable-next-line no-extra-parens
|
||||
(ns[0] === 'main' ? 'lang/{{ns}}-{{lng}}.json' : 'lang/{{ns}}.json')
|
||||
loadPath: (lng: string[], ns: string[]) => {
|
||||
switch (ns[0]) {
|
||||
case 'countries':
|
||||
case 'main':
|
||||
return 'lang/{{ns}}-{{lng}}.json';
|
||||
default:
|
||||
return 'lang/{{ns}}.json';
|
||||
}
|
||||
}
|
||||
},
|
||||
defaultNS: 'main',
|
||||
fallbackLng: DEFAULT_LANGUAGE,
|
||||
|
||||
@@ -85,7 +85,6 @@ import { default as IconSip } from './sip.svg';
|
||||
import { default as IconSites } from './sites.svg';
|
||||
import { default as IconRemoteControlStart } from './start-remote-control.svg';
|
||||
import { default as IconRemoteControlStop } from './stop-remote-control.svg';
|
||||
import { default as IconStopScreenshare } from './stop-screenshare.svg';
|
||||
import { default as IconStop } from './stop.svg';
|
||||
import { default as IconSubtitles } from './subtitles.svg';
|
||||
import { default as IconTileView } from './tile-view.svg';
|
||||
@@ -202,7 +201,6 @@ export const DEFAULT_ICON: Record<string, any> = {
|
||||
IconSip,
|
||||
IconSites,
|
||||
IconStop,
|
||||
IconStopScreenshare,
|
||||
IconSubtitles,
|
||||
IconTileView,
|
||||
IconTrash,
|
||||
|
||||
@@ -93,7 +93,6 @@ const {
|
||||
IconSip,
|
||||
IconSites,
|
||||
IconStop,
|
||||
IconStopScreenshare,
|
||||
IconSubtitles,
|
||||
IconTileView,
|
||||
IconTrash,
|
||||
@@ -213,7 +212,6 @@ export {
|
||||
IconSip,
|
||||
IconSites,
|
||||
IconStop,
|
||||
IconStopScreenshare,
|
||||
IconSubtitles,
|
||||
IconTileView,
|
||||
IconTrash,
|
||||
|
||||
@@ -1,5 +0,0 @@
|
||||
<svg width="24" height="24" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M22.2803 2.78033C22.5732 2.48744 22.5732 2.01256 22.2803 1.71967C21.9874 1.42678 21.5126 1.42678 21.2197 1.71967L19.9114 3.02797C19.7769 3.00953 19.6396 3 19.5 3H4.5C2.84315 3 1.5 4.34315 1.5 6V17.25C1.5 18.3842 2.12941 19.3714 3.05799 19.8813L1.71967 21.2197C1.42678 21.5126 1.42678 21.9874 1.71967 22.2803C2.01256 22.5732 2.48744 22.5732 2.78033 22.2803L22.2803 2.78033ZM4.21616 18.7232L5.54187 17.3975C5.40631 17.4169 5.2687 17.4055 5.14194 17.3656C4.78878 17.2544 4.48676 16.9074 4.52225 16.4471C4.8467 12.239 8.62852 8.92199 13.327 8.60046V6.87396C13.327 6.08352 14.2729 5.67701 14.8464 6.22103L15.807 7.13235L18.4393 4.5H4.5C3.67157 4.5 3 5.17157 3 6V17.25C3 17.9814 3.52345 18.5905 4.21616 18.7232ZM12.7759 10.1634C10.0327 10.5417 7.82609 12.097 6.73783 14.1317C8.14978 12.9079 9.68868 12.2376 11.0531 11.8862L12.7759 10.1634Z" fill="white" />
|
||||
<path d="M21 6.1607L22.283 4.87768C22.423 5.22437 22.5 5.60319 22.5 6V17.25C22.5 18.9069 21.1569 20.25 19.5 20.25H18.75C19.1642 20.25 19.5 20.5858 19.5 21C19.5 21.4142 19.1642 21.75 18.75 21.75H5.4107L8.4107 18.75H19.5C20.3284 18.75 21 18.0784 21 17.25V6.1607Z" fill="white" />
|
||||
<path d="M13.327 13.8337V15.2002C13.327 15.9986 14.2893 16.4017 14.8583 15.8416L19.1656 11.6016C19.5284 11.2444 19.523 10.6577 19.1536 10.3073L17.9732 9.18747L16.9122 10.2485L17.6708 10.9682L14.827 13.7676V12.3337L13.327 13.8337Z" fill="white" />
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 1.5 KiB |
@@ -4,7 +4,6 @@
|
||||
export const MEET_FEATURES = {
|
||||
BRANDING: 'branding',
|
||||
CALENDAR: 'calendar',
|
||||
CALLSTATS: 'callstats',
|
||||
FLIP: 'flip',
|
||||
INBOUND_CALL: 'inbound-call',
|
||||
LIVESTREAMING: 'livestreaming',
|
||||
|
||||
@@ -186,3 +186,23 @@ export function validateJwt(jwt: string) {
|
||||
|
||||
return errors;
|
||||
}
|
||||
|
||||
/**
|
||||
* Extracts and returns the expiration date of jwt.
|
||||
*
|
||||
* @param {string|undefined} jwt - The jwt to check.
|
||||
* @returns {Date} The expiration date of the jwt.
|
||||
*/
|
||||
export function getJwtExpirationDate(jwt: string | undefined) {
|
||||
if (!jwt) {
|
||||
return;
|
||||
}
|
||||
|
||||
const payload = jwtDecode(jwt);
|
||||
|
||||
if (payload) {
|
||||
const { exp } = payload;
|
||||
|
||||
return new Date(exp * 1000);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -153,6 +153,11 @@ function _setJWT(store: IStore, next: Function, action: AnyAction) {
|
||||
_overwriteLocalParticipant(
|
||||
store, { ...newUser,
|
||||
features: context.features });
|
||||
|
||||
// eslint-disable-next-line max-depth
|
||||
if (context.user && context.user.role === 'visitor') {
|
||||
action.preferVisitor = true;
|
||||
}
|
||||
} else if (jwtPayload.name || jwtPayload.picture || jwtPayload.email) {
|
||||
// there are some tokens (firebase) having picture and name on the main level.
|
||||
_overwriteLocalParticipant(store, {
|
||||
|
||||
@@ -1,11 +1,9 @@
|
||||
import { IStore } from '../../app/types';
|
||||
import RTCStats from '../../rtcstats/RTCStats';
|
||||
import { isRTCStatsEnabled } from '../../rtcstats/functions';
|
||||
import { getCurrentConference } from '../conference/functions';
|
||||
|
||||
/**
|
||||
* Implements log storage interface from the @jitsi/logger lib. Captured
|
||||
* logs are sent to CallStats.
|
||||
* Implements log storage interface from the @jitsi/logger lib.
|
||||
*/
|
||||
export default class JitsiMeetLogStorage {
|
||||
counter: number;
|
||||
@@ -33,8 +31,7 @@ export default class JitsiMeetLogStorage {
|
||||
}
|
||||
|
||||
/**
|
||||
* The JitsiMeetLogStorage is ready when the CallStats are started and
|
||||
* before refactoring the code it was after the conference has been joined.
|
||||
* The JitsiMeetLogStorage is ready when the conference has been joined.
|
||||
* A conference is considered joined when the 'conference' field is defined
|
||||
* in the base/conference state.
|
||||
*
|
||||
@@ -73,54 +70,8 @@ export default class JitsiMeetLogStorage {
|
||||
*/
|
||||
storeLogs(logEntries: Array<string | any>) {
|
||||
|
||||
// XXX the config.callStatsApplicationLogsDisabled controls whether or not the logs will be sent to callstats.
|
||||
// this is done in LJM
|
||||
this.storeLogsCallstats(logEntries);
|
||||
|
||||
if (this.canStoreLogsRtcstats()) {
|
||||
RTCStats.sendLogs(logEntries);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Store the console logs in callstats (if callstats is enabled).
|
||||
*
|
||||
* @param {Array<string|any>} logEntries - The log entries to send to the rtcstats server.
|
||||
* @returns {void}
|
||||
*/
|
||||
storeLogsCallstats(logEntries: Array<string | any>) {
|
||||
const conference = getCurrentConference(this.getState());
|
||||
|
||||
if (!conference?.isCallstatsEnabled()) {
|
||||
// Discard the logs if CallStats is not enabled.
|
||||
return;
|
||||
}
|
||||
|
||||
let logMessage = `{"log${this.counter}":"\n`;
|
||||
|
||||
for (let i = 0, len = logEntries.length; i < len; i++) {
|
||||
const logEntry = logEntries[i];
|
||||
|
||||
if (logEntry.timestamp) {
|
||||
logMessage += `${logEntry.timestamp} `;
|
||||
}
|
||||
if (logEntry.count > 1) {
|
||||
logMessage += `(${logEntry.count}) `;
|
||||
}
|
||||
logMessage += `${logEntry.text}\n`;
|
||||
}
|
||||
logMessage += '"}';
|
||||
|
||||
this.counter += 1;
|
||||
|
||||
// Try catch was used, because there are many variables
|
||||
// on the way that could be uninitialized if the storeLogs
|
||||
// attempt would be made very early (which is unlikely)
|
||||
try {
|
||||
conference.sendApplicationLog(logMessage);
|
||||
} catch (error) {
|
||||
// NOTE console is intentional here
|
||||
console.error(`Failed to store the logs, msg length: ${logMessage.length} error:`, error);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/**
|
||||
* The type of redux action which stores the log collector that will be
|
||||
* submitting the logs to CallStats.
|
||||
* submitting the logs to a service
|
||||
*
|
||||
* {
|
||||
* type: SET_LOG_COLLECTOR,
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
import { SET_LOGGING_CONFIG, SET_LOG_COLLECTOR } from './actionTypes';
|
||||
|
||||
/**
|
||||
* Stores a {@code Logger.LogCollector} instance which will be uploading logs
|
||||
* to CallStats.
|
||||
* Stores a {@code Logger.LogCollector} instance which will be uploading logs.
|
||||
*
|
||||
* @param {Logger.LogCollector} logCollector - The log collector instance to be
|
||||
* stored in the Redux state of base/logging feature.
|
||||
|
||||
@@ -106,7 +106,7 @@ function _conferenceJoined({ getState }: IStore, next: Function, action: AnyActi
|
||||
logCollector.flush();
|
||||
|
||||
// This event listener will flush the logs, before the statistics module
|
||||
// (CallStats) is stopped.
|
||||
// is stopped.
|
||||
//
|
||||
// NOTE The LogCollector is not stopped, because this event can be
|
||||
// triggered multiple times during single conference (whenever
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user