mirror of
https://gitcode.com/GitHub_Trending/ji/jitsi-meet.git
synced 2026-05-09 07:32:33 +00:00
Compare commits
94 Commits
android-23
...
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 |
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
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
|
||||
|
||||
@@ -26,5 +26,5 @@ android.useAndroidX=true
|
||||
android.enableJetifier=true
|
||||
android.bundle.enableUncompressedNativeLibs=false
|
||||
|
||||
appVersion=23.6.1
|
||||
sdkVersion=8.6.1
|
||||
appVersion=99.0.0
|
||||
sdkVersion=99.0.0
|
||||
|
||||
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
|
||||
};
|
||||
|
||||
126
conference.js
126
conference.js
@@ -154,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';
|
||||
@@ -718,8 +718,6 @@ export default {
|
||||
};
|
||||
|
||||
if (isPrejoinPageVisible(state)) {
|
||||
APP.store.dispatch(makePrecallTest(this._getConferenceOptions()));
|
||||
|
||||
const { tryCreateLocalTracks, errors } = this.createInitialLocalTracks(initialOptions);
|
||||
const localTracks = await tryCreateLocalTracks;
|
||||
|
||||
@@ -1039,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.
|
||||
*
|
||||
@@ -1061,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();
|
||||
@@ -2049,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}`);
|
||||
|
||||
@@ -2107,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}`);
|
||||
@@ -2193,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);
|
||||
});
|
||||
}
|
||||
@@ -2207,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.
|
||||
@@ -2385,14 +2322,10 @@ 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));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2445,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();
|
||||
@@ -2462,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));
|
||||
},
|
||||
|
||||
/**
|
||||
@@ -2498,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 = () => {
|
||||
|
||||
111
config.js
111
config.js
@@ -97,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.
|
||||
@@ -218,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,
|
||||
|
||||
@@ -291,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
|
||||
|
||||
@@ -434,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
|
||||
@@ -890,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: {
|
||||
@@ -944,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,
|
||||
|
||||
@@ -952,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,
|
||||
|
||||
@@ -1503,8 +1523,6 @@ var config = {
|
||||
_peerConnStatusOutOfLastNTimeout
|
||||
_peerConnStatusRtcMuteTimeout
|
||||
avgRtpStatsN
|
||||
callStatsConfIDNamespace
|
||||
callStatsCustomScriptUrl
|
||||
desktopSharingSources
|
||||
disableAEC
|
||||
disableAGC
|
||||
@@ -1678,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',
|
||||
// },
|
||||
|
||||
|
||||
@@ -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 {
|
||||
|
||||
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/
|
||||
|
||||
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 |
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
|
||||
|
||||
578
ios/Podfile.lock
578
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.12)
|
||||
- FBReactNativeSpec (0.69.12):
|
||||
- RCT-Folly (= 2021.06.28.00-v2)
|
||||
- RCTRequired (= 0.69.12)
|
||||
- RCTTypeSafety (= 0.69.12)
|
||||
- React-Core (= 0.69.12)
|
||||
- React-jsi (= 0.69.12)
|
||||
- ReactCommon/turbomodule/core (= 0.69.12)
|
||||
- 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.12)
|
||||
- RCTTypeSafety (0.69.12):
|
||||
- FBLazyVector (= 0.69.12)
|
||||
- RCTRequired (= 0.69.12)
|
||||
- React-Core (= 0.69.12)
|
||||
- React (0.69.12):
|
||||
- React-Core (= 0.69.12)
|
||||
- React-Core/DevSupport (= 0.69.12)
|
||||
- React-Core/RCTWebSocket (= 0.69.12)
|
||||
- React-RCTActionSheet (= 0.69.12)
|
||||
- React-RCTAnimation (= 0.69.12)
|
||||
- React-RCTBlob (= 0.69.12)
|
||||
- React-RCTImage (= 0.69.12)
|
||||
- React-RCTLinking (= 0.69.12)
|
||||
- React-RCTNetwork (= 0.69.12)
|
||||
- React-RCTSettings (= 0.69.12)
|
||||
- React-RCTText (= 0.69.12)
|
||||
- React-RCTVibration (= 0.69.12)
|
||||
- React-bridging (0.69.12):
|
||||
- RCT-Folly (= 2021.06.28.00-v2)
|
||||
- React-jsi (= 0.69.12)
|
||||
- React-callinvoker (0.69.12)
|
||||
- React-Codegen (0.69.12):
|
||||
- FBReactNativeSpec (= 0.69.12)
|
||||
- RCT-Folly (= 2021.06.28.00-v2)
|
||||
- RCTRequired (= 0.69.12)
|
||||
- RCTTypeSafety (= 0.69.12)
|
||||
- React-Core (= 0.69.12)
|
||||
- React-jsi (= 0.69.12)
|
||||
- React-jsiexecutor (= 0.69.12)
|
||||
- ReactCommon/turbomodule/core (= 0.69.12)
|
||||
- React-Core (0.69.12):
|
||||
- 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.12)
|
||||
- React-cxxreact (= 0.69.12)
|
||||
- React-jsi (= 0.69.12)
|
||||
- React-jsiexecutor (= 0.69.12)
|
||||
- React-perflogger (= 0.69.12)
|
||||
- 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.12):
|
||||
- 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.12)
|
||||
- React-jsi (= 0.69.12)
|
||||
- React-jsiexecutor (= 0.69.12)
|
||||
- React-perflogger (= 0.69.12)
|
||||
- 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.12):
|
||||
- React-Core/Default (0.70.14):
|
||||
- glog
|
||||
- RCT-Folly (= 2021.06.28.00-v2)
|
||||
- React-cxxreact (= 0.69.12)
|
||||
- React-jsi (= 0.69.12)
|
||||
- React-jsiexecutor (= 0.69.12)
|
||||
- React-perflogger (= 0.69.12)
|
||||
- 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.12):
|
||||
- React-Core/DevSupport (0.70.14):
|
||||
- glog
|
||||
- RCT-Folly (= 2021.06.28.00-v2)
|
||||
- React-Core/Default (= 0.69.12)
|
||||
- React-Core/RCTWebSocket (= 0.69.12)
|
||||
- React-cxxreact (= 0.69.12)
|
||||
- React-jsi (= 0.69.12)
|
||||
- React-jsiexecutor (= 0.69.12)
|
||||
- React-jsinspector (= 0.69.12)
|
||||
- React-perflogger (= 0.69.12)
|
||||
- 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.12):
|
||||
- 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.12)
|
||||
- React-jsi (= 0.69.12)
|
||||
- React-jsiexecutor (= 0.69.12)
|
||||
- React-perflogger (= 0.69.12)
|
||||
- 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.12):
|
||||
- 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.12)
|
||||
- React-jsi (= 0.69.12)
|
||||
- React-jsiexecutor (= 0.69.12)
|
||||
- React-perflogger (= 0.69.12)
|
||||
- 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.12):
|
||||
- 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.12)
|
||||
- React-jsi (= 0.69.12)
|
||||
- React-jsiexecutor (= 0.69.12)
|
||||
- React-perflogger (= 0.69.12)
|
||||
- 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.12):
|
||||
- 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.12)
|
||||
- React-jsi (= 0.69.12)
|
||||
- React-jsiexecutor (= 0.69.12)
|
||||
- React-perflogger (= 0.69.12)
|
||||
- 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.12):
|
||||
- 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.12)
|
||||
- React-jsi (= 0.69.12)
|
||||
- React-jsiexecutor (= 0.69.12)
|
||||
- React-perflogger (= 0.69.12)
|
||||
- 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.12):
|
||||
- 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.12)
|
||||
- React-jsi (= 0.69.12)
|
||||
- React-jsiexecutor (= 0.69.12)
|
||||
- React-perflogger (= 0.69.12)
|
||||
- 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.12):
|
||||
- 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.12)
|
||||
- React-jsi (= 0.69.12)
|
||||
- React-jsiexecutor (= 0.69.12)
|
||||
- React-perflogger (= 0.69.12)
|
||||
- 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.12):
|
||||
- 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.12)
|
||||
- React-jsi (= 0.69.12)
|
||||
- React-jsiexecutor (= 0.69.12)
|
||||
- React-perflogger (= 0.69.12)
|
||||
- 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.12):
|
||||
- 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.12)
|
||||
- React-jsi (= 0.69.12)
|
||||
- React-jsiexecutor (= 0.69.12)
|
||||
- React-perflogger (= 0.69.12)
|
||||
- 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.12):
|
||||
- React-Core/RCTWebSocket (0.70.14):
|
||||
- glog
|
||||
- RCT-Folly (= 2021.06.28.00-v2)
|
||||
- React-Core/Default (= 0.69.12)
|
||||
- React-cxxreact (= 0.69.12)
|
||||
- React-jsi (= 0.69.12)
|
||||
- React-jsiexecutor (= 0.69.12)
|
||||
- React-perflogger (= 0.69.12)
|
||||
- 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.12):
|
||||
- RCT-Folly (= 2021.06.28.00-v2)
|
||||
- RCTTypeSafety (= 0.69.12)
|
||||
- React-Codegen (= 0.69.12)
|
||||
- React-Core/CoreModulesHeaders (= 0.69.12)
|
||||
- React-jsi (= 0.69.12)
|
||||
- React-RCTImage (= 0.69.12)
|
||||
- ReactCommon/turbomodule/core (= 0.69.12)
|
||||
- React-cxxreact (0.69.12):
|
||||
- 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.12)
|
||||
- React-jsi (= 0.69.12)
|
||||
- React-jsinspector (= 0.69.12)
|
||||
- React-logger (= 0.69.12)
|
||||
- React-perflogger (= 0.69.12)
|
||||
- React-runtimeexecutor (= 0.69.12)
|
||||
- React-jsi (0.69.12):
|
||||
- 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.12)
|
||||
- React-jsi/Default (0.69.12):
|
||||
- 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.12):
|
||||
- RCT-Folly (= 2021.07.22.00)
|
||||
- React-jsiexecutor (0.70.14):
|
||||
- DoubleConversion
|
||||
- glog
|
||||
- RCT-Folly (= 2021.06.28.00-v2)
|
||||
- React-cxxreact (= 0.69.12)
|
||||
- React-jsi (= 0.69.12)
|
||||
- React-perflogger (= 0.69.12)
|
||||
- React-jsinspector (0.69.12)
|
||||
- React-logger (0.69.12):
|
||||
- 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,7 +371,7 @@ 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.6.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.6):
|
||||
- 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.12)
|
||||
- React-RCTActionSheet (0.69.12):
|
||||
- React-Core/RCTActionSheetHeaders (= 0.69.12)
|
||||
- React-RCTAnimation (0.69.12):
|
||||
- RCT-Folly (= 2021.06.28.00-v2)
|
||||
- RCTTypeSafety (= 0.69.12)
|
||||
- React-Codegen (= 0.69.12)
|
||||
- React-Core/RCTAnimationHeaders (= 0.69.12)
|
||||
- React-jsi (= 0.69.12)
|
||||
- ReactCommon/turbomodule/core (= 0.69.12)
|
||||
- React-RCTBlob (0.69.12):
|
||||
- RCT-Folly (= 2021.06.28.00-v2)
|
||||
- React-Codegen (= 0.69.12)
|
||||
- React-Core/RCTBlobHeaders (= 0.69.12)
|
||||
- React-Core/RCTWebSocket (= 0.69.12)
|
||||
- React-jsi (= 0.69.12)
|
||||
- React-RCTNetwork (= 0.69.12)
|
||||
- ReactCommon/turbomodule/core (= 0.69.12)
|
||||
- React-RCTImage (0.69.12):
|
||||
- RCT-Folly (= 2021.06.28.00-v2)
|
||||
- RCTTypeSafety (= 0.69.12)
|
||||
- React-Codegen (= 0.69.12)
|
||||
- React-Core/RCTImageHeaders (= 0.69.12)
|
||||
- React-jsi (= 0.69.12)
|
||||
- React-RCTNetwork (= 0.69.12)
|
||||
- ReactCommon/turbomodule/core (= 0.69.12)
|
||||
- React-RCTLinking (0.69.12):
|
||||
- React-Codegen (= 0.69.12)
|
||||
- React-Core/RCTLinkingHeaders (= 0.69.12)
|
||||
- React-jsi (= 0.69.12)
|
||||
- ReactCommon/turbomodule/core (= 0.69.12)
|
||||
- React-RCTNetwork (0.69.12):
|
||||
- RCT-Folly (= 2021.06.28.00-v2)
|
||||
- RCTTypeSafety (= 0.69.12)
|
||||
- React-Codegen (= 0.69.12)
|
||||
- React-Core/RCTNetworkHeaders (= 0.69.12)
|
||||
- React-jsi (= 0.69.12)
|
||||
- ReactCommon/turbomodule/core (= 0.69.12)
|
||||
- React-RCTSettings (0.69.12):
|
||||
- RCT-Folly (= 2021.06.28.00-v2)
|
||||
- RCTTypeSafety (= 0.69.12)
|
||||
- React-Codegen (= 0.69.12)
|
||||
- React-Core/RCTSettingsHeaders (= 0.69.12)
|
||||
- React-jsi (= 0.69.12)
|
||||
- ReactCommon/turbomodule/core (= 0.69.12)
|
||||
- React-RCTText (0.69.12):
|
||||
- React-Core/RCTTextHeaders (= 0.69.12)
|
||||
- React-RCTVibration (0.69.12):
|
||||
- RCT-Folly (= 2021.06.28.00-v2)
|
||||
- React-Codegen (= 0.69.12)
|
||||
- React-Core/RCTVibrationHeaders (= 0.69.12)
|
||||
- React-jsi (= 0.69.12)
|
||||
- ReactCommon/turbomodule/core (= 0.69.12)
|
||||
- React-runtimeexecutor (0.69.12):
|
||||
- React-jsi (= 0.69.12)
|
||||
- ReactCommon/turbomodule/core (0.69.12):
|
||||
- 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.12)
|
||||
- React-callinvoker (= 0.69.12)
|
||||
- React-Core (= 0.69.12)
|
||||
- React-cxxreact (= 0.69.12)
|
||||
- React-jsi (= 0.69.12)
|
||||
- React-logger (= 0.69.12)
|
||||
- React-perflogger (= 0.69.12)
|
||||
- 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: 6fab494fa11340bd4206edaebed07279a6bafad4
|
||||
FBReactNativeSpec: 76d7b03876b0ad0b86bc5c84d23af8e64db8e096
|
||||
FBLazyVector: efad4471d02263013cfcb7a2f75de6ac7565692f
|
||||
FBReactNativeSpec: 9cd9542bfdcc64e07bc649f809dd621876f78619
|
||||
Firebase: 5f8193dff4b5b7c5d5ef72ae54bb76c08e2b841d
|
||||
FirebaseAnalytics: 7761cbadb00a717d8d0939363eb46041526474fa
|
||||
FirebaseCore: 5743c5785c074a794d35f2fff7ecc254a91e08b1
|
||||
@@ -721,37 +721,37 @@ 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: b9e53f0512019150020156fa0dacd6583ab838be
|
||||
RCTTypeSafety: 04b72202bef8302802610dee70bb9407a245b64c
|
||||
React: 59288a7ca8104eb8002f01378606fe42eeabf4b5
|
||||
React-bridging: b042b8c217f04e568409786de5f221793be49c31
|
||||
React-callinvoker: c7b83d582112e2d5a049dc46abf4c64d871b5c45
|
||||
React-Codegen: 5747238d0446e3ab1deb967e749a2bfde6a5c866
|
||||
React-Core: d8e1250039d47112513757038d9d9f9b638565c6
|
||||
React-CoreModules: 63cceb0040ec2b43a258113193be91f934b37f1b
|
||||
React-cxxreact: 429404aac55d8bffca77328002452fc7fa8b29e8
|
||||
React-jsi: a8f60feb519ac00085eb9a39d20eaa65c96b51ea
|
||||
React-jsiexecutor: ce0b9aa647bdf94126eb2ee1f235d329eb8c0aec
|
||||
React-jsinspector: f275698149311abc8c32ebb97797d6b97c44adde
|
||||
React-logger: da69d7f1c9501c78cd60776d52a60d7fa5e4d9c2
|
||||
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-netinfo: 3aa5637c18834966e0c932de8ae1ae56fea20a97
|
||||
react-native-orientation-locker: 4409c5b12b65f942e75449872b4f078b6f27af81
|
||||
react-native-pager-view: 0ccb8bf60e2ebd38b1f3669fa3650ecce81db2df
|
||||
react-native-performance: 47ac22ebf2aa24f324a96a5825581f6ce18c09e8
|
||||
@@ -759,33 +759,33 @@ SPEC CHECKSUMS:
|
||||
react-native-slider: 1cdd6ba29675df21f30544253bf7351d3c2d68c4
|
||||
react-native-splash-screen: 4312f786b13a81b5169ef346d76d33bc0c6dc457
|
||||
react-native-video: 967eead48aaa42c25a9e1d65c3b1ab30762a88df
|
||||
react-native-webrtc: 255a1172fd31525b952b36aef7b8e9a41de325e5
|
||||
react-native-webrtc: c8d9ad3c152105b2720ca2851d04b49659551992
|
||||
react-native-webview: 8baa0f5c6d336d6ba488e942bcadea5bf51f050a
|
||||
React-perflogger: 5ade0a1627352f1647d283e78331819bb46cceae
|
||||
React-RCTActionSheet: 8e94f1e46e09c7035b81fe56c0ed8d78f3ccd340
|
||||
React-RCTAnimation: bf2af72f03cf16528db9a830be69fa04b341a1b7
|
||||
React-RCTBlob: 4d076b8bb55e631ad1280280ecba674fb1e46d16
|
||||
React-RCTImage: 073dcc1689466851fe120c7f8a3cfe3db0196c9f
|
||||
React-RCTLinking: 8872818dc894a17bf17cb4b120f76917bf2e9f0a
|
||||
React-RCTNetwork: 1e9c873f4a210784a4fb752194cb595502112464
|
||||
React-RCTSettings: 1475a717c54f4a9ed627dffffad2470c4b15a419
|
||||
React-RCTText: ed34088172126f84130eea859d62fedca0dd7975
|
||||
React-RCTVibration: c9cd9f21bbcb3b9c6deedbb66f13e373f57dd795
|
||||
React-runtimeexecutor: ea78653fbc68bd6f2d3f5e7e311bc5a9dc8bfeca
|
||||
ReactCommon: f4bb9e5209ea5c3c6ab25e100895119e58d6e50a
|
||||
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: 8a90b50af67eaa9fe94fd03e550bfeab06096873
|
||||
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;
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>$(PRODUCT_BUNDLE_PACKAGE_TYPE)</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>23.6.1</string>
|
||||
<string>99.0.0</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>1</string>
|
||||
<key>NSExtension</key>
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>APPL</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>23.6.1</string>
|
||||
<string>99.0.0</string>
|
||||
<key>CFBundleSignature</key>
|
||||
<string>????</string>
|
||||
<key>CFBundleURLTypes</key>
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>APPL</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>23.6.1</string>
|
||||
<string>99.0.0</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>1</string>
|
||||
<key>UISupportedInterfaceOrientations</key>
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>XPC!</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>23.6.1</string>
|
||||
<string>99.0.0</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>1</string>
|
||||
<key>CLKComplicationPrincipalClass</key>
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>FMWK</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>8.6.1</string>
|
||||
<string>99.0.0</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>$(CURRENT_PROJECT_VERSION)</string>
|
||||
<key>NSPrincipalClass</key>
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>FMWK</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>8.6.1</string>
|
||||
<string>99.0.0</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>$(CURRENT_PROJECT_VERSION)</string>
|
||||
<key>NSPrincipalClass</key>
|
||||
|
||||
@@ -419,6 +419,7 @@
|
||||
"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.",
|
||||
|
||||
@@ -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
@@ -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"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -421,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.",
|
||||
|
||||
@@ -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) => {
|
||||
@@ -1107,7 +1097,11 @@ class API {
|
||||
this._enabled = true;
|
||||
|
||||
initCommands();
|
||||
|
||||
this.notifyBrowserSupport(isSupportedBrowser());
|
||||
|
||||
// Let the embedder know we are ready.
|
||||
this._sendEvent({ name: 'ready' });
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1983,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.
|
||||
*
|
||||
|
||||
32
modules/API/external/external_api.js
vendored
32
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,6 +160,7 @@ const events = {
|
||||
'suspend-detected': 'suspendDetected',
|
||||
'tile-view-changed': 'tileViewChanged',
|
||||
'toolbar-button-clicked': 'toolbarButtonClicked',
|
||||
'transcription-chunk-received': 'transcriptionChunkReceived',
|
||||
'whiteboard-status-changed': 'whiteboardStatusChanged'
|
||||
};
|
||||
|
||||
@@ -273,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;
|
||||
@@ -365,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: {
|
||||
@@ -375,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;
|
||||
@@ -396,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');
|
||||
@@ -415,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;
|
||||
@@ -427,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);
|
||||
@@ -580,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') {
|
||||
|
||||
@@ -1425,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) {
|
||||
|
||||
4430
package-lock.json
generated
4430
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
20
package.json
20
package.json
@@ -22,7 +22,7 @@
|
||||
"@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.15/jitsi-excalidraw-0.0.15.tgz",
|
||||
"@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",
|
||||
@@ -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/v1716.0.0+93c167d3/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.12",
|
||||
"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",
|
||||
@@ -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.6",
|
||||
"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,6 +135,8 @@
|
||||
"@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",
|
||||
@@ -145,7 +146,6 @@
|
||||
"@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",
|
||||
|
||||
@@ -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];
|
||||
}
|
||||
|
||||
156
react-native-sdk/package-lock.json
generated
156
react-native-sdk/package-lock.json
generated
@@ -1,16 +1,16 @@
|
||||
{
|
||||
"name": "@jitsi/react-native-sdk",
|
||||
"version": "1.0.3",
|
||||
"version": "0.0.0",
|
||||
"lockfileVersion": 2,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "@jitsi/react-native-sdk",
|
||||
"version": "1.0.3",
|
||||
"version": "0.0.0",
|
||||
"hasInstallScript": true,
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
"@jitsi/js-utils": "2.2.1",
|
||||
"@jitsi/js-utils": "2.1.3",
|
||||
"@jitsi/logger": "2.0.2",
|
||||
"@jitsi/rtcstats": "9.5.1",
|
||||
"@react-navigation/bottom-tabs": "6.5.8",
|
||||
@@ -19,7 +19,7 @@
|
||||
"@react-navigation/native": "6.1.7",
|
||||
"@react-navigation/stack": "6.3.17",
|
||||
"@xmldom/xmldom": "0.8.7",
|
||||
"base64-js": "1.5.1",
|
||||
"base64-js": "1.3.1",
|
||||
"grapheme-splitter": "1.0.4",
|
||||
"i18n-iso-countries": "6.8.0",
|
||||
"i18next": "17.0.6",
|
||||
@@ -27,7 +27,7 @@
|
||||
"js-md5": "0.6.1",
|
||||
"js-sha512": "0.8.0",
|
||||
"jwt-decode": "2.2.0",
|
||||
"lib-jitsi-meet": "https://github.com/jitsi/lib-jitsi-meet/releases/download/v1716.0.0+93c167d3/lib-jitsi-meet.tgz",
|
||||
"lib-jitsi-meet": "https://github.com/jitsi/lib-jitsi-meet/releases/download/v1687.0.0+cafe30d7/lib-jitsi-meet.tgz",
|
||||
"lodash": "4.17.21",
|
||||
"moment": "2.29.4",
|
||||
"moment-duration-format": "2.2.2",
|
||||
@@ -69,7 +69,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.6.0",
|
||||
"react-native-orientation-locker": "1.5.0",
|
||||
"react-native-pager-view": "6.2.0",
|
||||
"react-native-paper": "5.10.3",
|
||||
"react-native-performance": "5.0.0",
|
||||
@@ -80,7 +80,7 @@
|
||||
"react-native-svg": "13.13.0",
|
||||
"react-native-video": "6.0.0-alpha.7",
|
||||
"react-native-watch-connectivity": "1.1.0",
|
||||
"react-native-webrtc": "111.0.6",
|
||||
"react-native-webrtc": "111.0.3",
|
||||
"react-native-webview": "13.5.1"
|
||||
}
|
||||
},
|
||||
@@ -396,13 +396,13 @@
|
||||
"integrity": "sha512-Waj1cwPXJDucOib4a3bAISsKJVb15MKi9IvmTI/7ssVEm6sywXGjVJDhl6/umt1pK1ZS7PacXU3A1PmFKHEZ2w=="
|
||||
},
|
||||
"node_modules/@jitsi/js-utils": {
|
||||
"version": "2.2.1",
|
||||
"resolved": "https://registry.npmjs.org/@jitsi/js-utils/-/js-utils-2.2.1.tgz",
|
||||
"integrity": "sha512-4Ia4hWO7aTMGbYftzeBr+IHIu5YxiWwTlhsSK34z6925oNAUNI863WgYYGTcXkW/1yuM6LBZrnuZBySDqosISA==",
|
||||
"version": "2.1.3",
|
||||
"resolved": "https://registry.npmjs.org/@jitsi/js-utils/-/js-utils-2.1.3.tgz",
|
||||
"integrity": "sha512-fXoNLu2JHQGPgzjCDG5qWPPStiXI+AxSzu1JIVY4dMULIFsw4a+doMgcjTIlSfB393J2xccKQYwZSejZUn9MEw==",
|
||||
"dependencies": {
|
||||
"@hapi/bourne": "^3.0.0",
|
||||
"js-md5": "0.7.3",
|
||||
"ua-parser-js": "1.0.35"
|
||||
"bowser": "2.7.0",
|
||||
"js-md5": "0.7.3"
|
||||
}
|
||||
},
|
||||
"node_modules/@jitsi/js-utils/node_modules/js-md5": {
|
||||
@@ -993,23 +993,9 @@
|
||||
"integrity": "sha512-Y5gU45svrR5tI2Vt/X9GPd3L0HNIKzGu202EjxrXMpuc2V2CiKgemAbUUsqYmZJvPtCXoUKjNZwBJzsNScUbXA=="
|
||||
},
|
||||
"node_modules/base64-js": {
|
||||
"version": "1.5.1",
|
||||
"resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz",
|
||||
"integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==",
|
||||
"funding": [
|
||||
{
|
||||
"type": "github",
|
||||
"url": "https://github.com/sponsors/feross"
|
||||
},
|
||||
{
|
||||
"type": "patreon",
|
||||
"url": "https://www.patreon.com/feross"
|
||||
},
|
||||
{
|
||||
"type": "consulting",
|
||||
"url": "https://feross.org/support"
|
||||
}
|
||||
]
|
||||
"version": "1.3.1",
|
||||
"resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.3.1.tgz",
|
||||
"integrity": "sha512-mLQ4i2QO1ytvGWFWmcngKO//JXAQueZvwEKtjgQFM4jIK0kU+ytMfplL8j+n5mspOfjHwoAg+9yhb7BwAHm36g=="
|
||||
},
|
||||
"node_modules/binary-extensions": {
|
||||
"version": "2.2.0",
|
||||
@@ -1024,6 +1010,11 @@
|
||||
"resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz",
|
||||
"integrity": "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww=="
|
||||
},
|
||||
"node_modules/bowser": {
|
||||
"version": "2.7.0",
|
||||
"resolved": "https://registry.npmjs.org/bowser/-/bowser-2.7.0.tgz",
|
||||
"integrity": "sha512-aIlMvstvu8x+34KEiOHD3AsBgdrzg6sxALYiukOWhFvGMbQI6TRP/iY0LMhUrHs56aD6P1G0Z7h45PUJaa5m9w=="
|
||||
},
|
||||
"node_modules/brace-expansion": {
|
||||
"version": "1.1.11",
|
||||
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
|
||||
@@ -2490,14 +2481,14 @@
|
||||
},
|
||||
"node_modules/lib-jitsi-meet": {
|
||||
"version": "0.0.0",
|
||||
"resolved": "https://github.com/jitsi/lib-jitsi-meet/releases/download/v1716.0.0+93c167d3/lib-jitsi-meet.tgz",
|
||||
"integrity": "sha512-+6nI2ExiTS8aKnq3ZDpYKs1MSDtUHaK4hIhVxyI7Db6ZojrMOpZx6lnrmqz+AHWllSHvIggFz48du7tG6UYANw==",
|
||||
"resolved": "https://github.com/jitsi/lib-jitsi-meet/releases/download/v1687.0.0+cafe30d7/lib-jitsi-meet.tgz",
|
||||
"integrity": "sha512-ky3q5gLeLDHFtenXe7+QlxAh33opz0a3bqEp8svA9urR1AICUi0QthOwmUerTdfSRFU3wfVObF9axlX1fbHZ3A==",
|
||||
"hasInstallScript": true,
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
"@jitsi/js-utils": "2.2.1",
|
||||
"@jitsi/js-utils": "2.1.3",
|
||||
"@jitsi/logger": "2.0.2",
|
||||
"@jitsi/rtcstats": "9.6.0",
|
||||
"@jitsi/rtcstats": "9.5.1",
|
||||
"@jitsi/sdp-interop": "git+https://github.com/jitsi/sdp-interop#3d49eb4aa26863a3f8d32d7581cdb4321244266b",
|
||||
"@jitsi/sdp-simulcast": "0.4.0",
|
||||
"@testrtc/watchrtc-sdk": "1.36.3",
|
||||
@@ -2518,30 +2509,6 @@
|
||||
"webrtc-adapter": "8.1.1"
|
||||
}
|
||||
},
|
||||
"node_modules/lib-jitsi-meet/node_modules/@jitsi/rtcstats": {
|
||||
"version": "9.6.0",
|
||||
"resolved": "https://registry.npmjs.org/@jitsi/rtcstats/-/rtcstats-9.6.0.tgz",
|
||||
"integrity": "sha512-eFFD6vp1dFwvjAR+NRjsxlvclFvqo/nbU2RcSLzXbIjG/WraMHyxMSzllZyT1T3S2iPehS4dnZ/ZYyz5WYHTaA==",
|
||||
"dependencies": {
|
||||
"@jitsi/js-utils": "^2.2.0",
|
||||
"@jitsi/logger": "2.0.2",
|
||||
"sdp": "^3.0.3",
|
||||
"uuid": "^8.3.2"
|
||||
}
|
||||
},
|
||||
"node_modules/lib-jitsi-meet/node_modules/@jitsi/rtcstats/node_modules/uuid": {
|
||||
"version": "8.3.2",
|
||||
"resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz",
|
||||
"integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==",
|
||||
"bin": {
|
||||
"uuid": "dist/bin/uuid"
|
||||
}
|
||||
},
|
||||
"node_modules/lib-jitsi-meet/node_modules/base64-js": {
|
||||
"version": "1.3.1",
|
||||
"resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.3.1.tgz",
|
||||
"integrity": "sha512-mLQ4i2QO1ytvGWFWmcngKO//JXAQueZvwEKtjgQFM4jIK0kU+ytMfplL8j+n5mspOfjHwoAg+9yhb7BwAHm36g=="
|
||||
},
|
||||
"node_modules/lib-jitsi-meet/node_modules/uuid": {
|
||||
"version": "8.1.0",
|
||||
"resolved": "https://registry.npmjs.org/uuid/-/uuid-8.1.0.tgz",
|
||||
@@ -3603,24 +3570,6 @@
|
||||
"url": "https://github.com/sponsors/ljharb"
|
||||
}
|
||||
},
|
||||
"node_modules/ua-parser-js": {
|
||||
"version": "1.0.35",
|
||||
"resolved": "https://registry.npmjs.org/ua-parser-js/-/ua-parser-js-1.0.35.tgz",
|
||||
"integrity": "sha512-fKnGuqmTBnIE+/KXSzCn4db8RTigUzw1AN0DmdU6hJovUTbYJKyqj+8Mt1c4VfRDnOVJnENmfYkIPZ946UrSAA==",
|
||||
"funding": [
|
||||
{
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/ua-parser-js"
|
||||
},
|
||||
{
|
||||
"type": "paypal",
|
||||
"url": "https://paypal.me/faisalman"
|
||||
}
|
||||
],
|
||||
"engines": {
|
||||
"node": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/uc.micro": {
|
||||
"version": "1.0.6",
|
||||
"resolved": "https://registry.npmjs.org/uc.micro/-/uc.micro-1.0.6.tgz",
|
||||
@@ -4095,13 +4044,13 @@
|
||||
"integrity": "sha512-Waj1cwPXJDucOib4a3bAISsKJVb15MKi9IvmTI/7ssVEm6sywXGjVJDhl6/umt1pK1ZS7PacXU3A1PmFKHEZ2w=="
|
||||
},
|
||||
"@jitsi/js-utils": {
|
||||
"version": "2.2.1",
|
||||
"resolved": "https://registry.npmjs.org/@jitsi/js-utils/-/js-utils-2.2.1.tgz",
|
||||
"integrity": "sha512-4Ia4hWO7aTMGbYftzeBr+IHIu5YxiWwTlhsSK34z6925oNAUNI863WgYYGTcXkW/1yuM6LBZrnuZBySDqosISA==",
|
||||
"version": "2.1.3",
|
||||
"resolved": "https://registry.npmjs.org/@jitsi/js-utils/-/js-utils-2.1.3.tgz",
|
||||
"integrity": "sha512-fXoNLu2JHQGPgzjCDG5qWPPStiXI+AxSzu1JIVY4dMULIFsw4a+doMgcjTIlSfB393J2xccKQYwZSejZUn9MEw==",
|
||||
"requires": {
|
||||
"@hapi/bourne": "^3.0.0",
|
||||
"js-md5": "0.7.3",
|
||||
"ua-parser-js": "1.0.35"
|
||||
"bowser": "2.7.0",
|
||||
"js-md5": "0.7.3"
|
||||
},
|
||||
"dependencies": {
|
||||
"js-md5": {
|
||||
@@ -4496,9 +4445,9 @@
|
||||
"integrity": "sha512-Y5gU45svrR5tI2Vt/X9GPd3L0HNIKzGu202EjxrXMpuc2V2CiKgemAbUUsqYmZJvPtCXoUKjNZwBJzsNScUbXA=="
|
||||
},
|
||||
"base64-js": {
|
||||
"version": "1.5.1",
|
||||
"resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz",
|
||||
"integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA=="
|
||||
"version": "1.3.1",
|
||||
"resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.3.1.tgz",
|
||||
"integrity": "sha512-mLQ4i2QO1ytvGWFWmcngKO//JXAQueZvwEKtjgQFM4jIK0kU+ytMfplL8j+n5mspOfjHwoAg+9yhb7BwAHm36g=="
|
||||
},
|
||||
"binary-extensions": {
|
||||
"version": "2.2.0",
|
||||
@@ -4510,6 +4459,11 @@
|
||||
"resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz",
|
||||
"integrity": "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww=="
|
||||
},
|
||||
"bowser": {
|
||||
"version": "2.7.0",
|
||||
"resolved": "https://registry.npmjs.org/bowser/-/bowser-2.7.0.tgz",
|
||||
"integrity": "sha512-aIlMvstvu8x+34KEiOHD3AsBgdrzg6sxALYiukOWhFvGMbQI6TRP/iY0LMhUrHs56aD6P1G0Z7h45PUJaa5m9w=="
|
||||
},
|
||||
"brace-expansion": {
|
||||
"version": "1.1.11",
|
||||
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
|
||||
@@ -5522,12 +5476,12 @@
|
||||
}
|
||||
},
|
||||
"lib-jitsi-meet": {
|
||||
"version": "https://github.com/jitsi/lib-jitsi-meet/releases/download/v1716.0.0+93c167d3/lib-jitsi-meet.tgz",
|
||||
"integrity": "sha512-+6nI2ExiTS8aKnq3ZDpYKs1MSDtUHaK4hIhVxyI7Db6ZojrMOpZx6lnrmqz+AHWllSHvIggFz48du7tG6UYANw==",
|
||||
"version": "https://github.com/jitsi/lib-jitsi-meet/releases/download/v1687.0.0+cafe30d7/lib-jitsi-meet.tgz",
|
||||
"integrity": "sha512-ky3q5gLeLDHFtenXe7+QlxAh33opz0a3bqEp8svA9urR1AICUi0QthOwmUerTdfSRFU3wfVObF9axlX1fbHZ3A==",
|
||||
"requires": {
|
||||
"@jitsi/js-utils": "2.2.1",
|
||||
"@jitsi/js-utils": "2.1.3",
|
||||
"@jitsi/logger": "2.0.2",
|
||||
"@jitsi/rtcstats": "9.6.0",
|
||||
"@jitsi/rtcstats": "9.5.1",
|
||||
"@jitsi/sdp-interop": "git+https://github.com/jitsi/sdp-interop#3d49eb4aa26863a3f8d32d7581cdb4321244266b",
|
||||
"@jitsi/sdp-simulcast": "0.4.0",
|
||||
"@testrtc/watchrtc-sdk": "1.36.3",
|
||||
@@ -5548,29 +5502,6 @@
|
||||
"webrtc-adapter": "8.1.1"
|
||||
},
|
||||
"dependencies": {
|
||||
"@jitsi/rtcstats": {
|
||||
"version": "9.6.0",
|
||||
"resolved": "https://registry.npmjs.org/@jitsi/rtcstats/-/rtcstats-9.6.0.tgz",
|
||||
"integrity": "sha512-eFFD6vp1dFwvjAR+NRjsxlvclFvqo/nbU2RcSLzXbIjG/WraMHyxMSzllZyT1T3S2iPehS4dnZ/ZYyz5WYHTaA==",
|
||||
"requires": {
|
||||
"@jitsi/js-utils": "^2.2.0",
|
||||
"@jitsi/logger": "2.0.2",
|
||||
"sdp": "^3.0.3",
|
||||
"uuid": "^8.3.2"
|
||||
},
|
||||
"dependencies": {
|
||||
"uuid": {
|
||||
"version": "8.3.2",
|
||||
"resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz",
|
||||
"integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg=="
|
||||
}
|
||||
}
|
||||
},
|
||||
"base64-js": {
|
||||
"version": "1.3.1",
|
||||
"resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.3.1.tgz",
|
||||
"integrity": "sha512-mLQ4i2QO1ytvGWFWmcngKO//JXAQueZvwEKtjgQFM4jIK0kU+ytMfplL8j+n5mspOfjHwoAg+9yhb7BwAHm36g=="
|
||||
},
|
||||
"uuid": {
|
||||
"version": "8.1.0",
|
||||
"resolved": "https://registry.npmjs.org/uuid/-/uuid-8.1.0.tgz",
|
||||
@@ -6332,11 +6263,6 @@
|
||||
"is-typed-array": "^1.1.9"
|
||||
}
|
||||
},
|
||||
"ua-parser-js": {
|
||||
"version": "1.0.35",
|
||||
"resolved": "https://registry.npmjs.org/ua-parser-js/-/ua-parser-js-1.0.35.tgz",
|
||||
"integrity": "sha512-fKnGuqmTBnIE+/KXSzCn4db8RTigUzw1AN0DmdU6hJovUTbYJKyqj+8Mt1c4VfRDnOVJnENmfYkIPZ946UrSAA=="
|
||||
},
|
||||
"uc.micro": {
|
||||
"version": "1.0.6",
|
||||
"resolved": "https://registry.npmjs.org/uc.micro/-/uc.micro-1.0.6.tgz",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@jitsi/react-native-sdk",
|
||||
"version": "1.0.3",
|
||||
"version": "0.0.0",
|
||||
"description": "React Native SDK for Jitsi Meet.",
|
||||
"main": "index.tsx",
|
||||
"license": "Apache-2.0",
|
||||
@@ -11,7 +11,7 @@
|
||||
"url": "git+https://github.com/jitsi/jitsi-meet.git"
|
||||
},
|
||||
"dependencies": {
|
||||
"@jitsi/js-utils": "2.2.1",
|
||||
"@jitsi/js-utils": "2.1.3",
|
||||
"@jitsi/logger": "2.0.2",
|
||||
"@jitsi/rtcstats": "9.5.1",
|
||||
"@react-navigation/bottom-tabs": "6.5.8",
|
||||
@@ -20,7 +20,7 @@
|
||||
"@react-navigation/native": "6.1.7",
|
||||
"@react-navigation/stack": "6.3.17",
|
||||
"@xmldom/xmldom": "0.8.7",
|
||||
"base64-js": "1.5.1",
|
||||
"base64-js": "1.3.1",
|
||||
"grapheme-splitter": "1.0.4",
|
||||
"i18n-iso-countries": "6.8.0",
|
||||
"i18next": "17.0.6",
|
||||
@@ -28,7 +28,7 @@
|
||||
"i18next-http-backend": "^2.2.1",
|
||||
"js-sha512": "0.8.0",
|
||||
"jwt-decode": "2.2.0",
|
||||
"lib-jitsi-meet": "https://github.com/jitsi/lib-jitsi-meet/releases/download/v1716.0.0+93c167d3/lib-jitsi-meet.tgz",
|
||||
"lib-jitsi-meet": "https://github.com/jitsi/lib-jitsi-meet/releases/download/v1687.0.0+cafe30d7/lib-jitsi-meet.tgz",
|
||||
"lodash": "4.17.21",
|
||||
"moment": "2.29.4",
|
||||
"moment-duration-format": "2.2.2",
|
||||
@@ -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",
|
||||
@@ -73,7 +72,7 @@
|
||||
"react-native-pager-view": "6.2.0",
|
||||
"react-native-paper": "5.10.3",
|
||||
"react-native-performance": "5.0.0",
|
||||
"react-native-orientation-locker": "1.6.0",
|
||||
"react-native-orientation-locker": "1.5.0",
|
||||
"react-native-safe-area-context": "4.7.1",
|
||||
"react-native-screens": "3.24.0",
|
||||
"react-native-sound": "0.11.2",
|
||||
@@ -81,7 +80,7 @@
|
||||
"react-native-svg": "13.13.0",
|
||||
"react-native-video": "6.0.0-alpha.7",
|
||||
"react-native-watch-connectivity": "1.1.0",
|
||||
"react-native-webrtc": "111.0.6",
|
||||
"react-native-webrtc": "111.0.3",
|
||||
"react-native-webview": "13.5.1"
|
||||
},
|
||||
"overrides": {
|
||||
@@ -97,4 +96,4 @@
|
||||
"keywords": [
|
||||
"react-native"
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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({
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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));
|
||||
@@ -9,7 +9,7 @@ const AVATAR_COLORS = [
|
||||
'#B23683',
|
||||
'#F96E57',
|
||||
'#4380E2',
|
||||
'#2AA076',
|
||||
'#238561',
|
||||
'#00A8B3'
|
||||
];
|
||||
const wordSplitRegex = (/\s+|\.+|_+|;+|-+|,+|\|+|\/+|\\+|"+|'+|\(+|\)+|#+|&+/);
|
||||
|
||||
@@ -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,6 +14,7 @@ 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';
|
||||
@@ -306,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;
|
||||
|
||||
@@ -231,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; }>;
|
||||
@@ -459,6 +439,7 @@ export interface IConfig {
|
||||
inviteServiceCallFlowsUrl?: string;
|
||||
inviteServiceUrl?: string;
|
||||
jaasActuatorUrl?: string;
|
||||
jaasConferenceCreatorUrl?: string;
|
||||
jaasFeedbackMetadataURL?: string;
|
||||
jaasTokenUrl?: string;
|
||||
legalUrls?: {
|
||||
@@ -579,7 +560,6 @@ export interface IConfig {
|
||||
subject?: string;
|
||||
testing?: {
|
||||
assumeBandwidth?: boolean;
|
||||
callStatsThreshold?: number;
|
||||
disableE2EE?: boolean;
|
||||
mobileXmppWsThreshold?: number;
|
||||
noAutoPlayVideo?: boolean;
|
||||
|
||||
@@ -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',
|
||||
|
||||
@@ -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 };
|
||||
}
|
||||
|
||||
@@ -43,7 +43,7 @@ const DEVICE_TYPE_TO_SETTINGS_KEYS = {
|
||||
userSelectedDeviceLabel: 'userSelectedAudioOutputDeviceLabel'
|
||||
},
|
||||
videoInput: {
|
||||
currentDeviceId: 'audioOutputDeviceId',
|
||||
currentDeviceId: 'cameraDeviceId',
|
||||
userSelectedDeviceId: 'userSelectedCameraDeviceId',
|
||||
userSelectedDeviceLabel: 'userSelectedCameraDeviceLabel'
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -4,7 +4,6 @@
|
||||
export const MEET_FEATURES = {
|
||||
BRANDING: 'branding',
|
||||
CALENDAR: 'calendar',
|
||||
CALLSTATS: 'callstats',
|
||||
FLIP: 'flip',
|
||||
INBOUND_CALL: 'inbound-call',
|
||||
LIVESTREAMING: 'livestreaming',
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -10,14 +10,13 @@ const DEFAULT_LOGGING_CONFIG = {
|
||||
// default log level for the app and lib-jitsi-meet
|
||||
defaultLogLevel: 'trace' as LogLevel,
|
||||
|
||||
// Option to disable LogCollector (which stores the logs on CallStats)
|
||||
// Option to disable LogCollector (which stores the logs)
|
||||
// disableLogCollector: true,
|
||||
|
||||
loggers: {
|
||||
// The following are too verbose in their logging with the
|
||||
// {@link #defaultLogLevel}:
|
||||
'modules/RTC/TraceablePeerConnection.js': 'info' as LogLevel,
|
||||
'modules/statistics/CallStats.js': 'info' as LogLevel,
|
||||
'modules/xmpp/strophe.util.js': 'log' as LogLevel
|
||||
}
|
||||
};
|
||||
|
||||
@@ -23,7 +23,12 @@ import MiddlewareRegistry from '../redux/MiddlewareRegistry';
|
||||
import { getPropertyValue } from '../settings/functions.any';
|
||||
import { TRACK_ADDED } from '../tracks/actionTypes';
|
||||
import { destroyLocalTracks } from '../tracks/actions.any';
|
||||
import { isLocalTrackMuted, isLocalVideoTrackDesktop, setTrackMuted } from '../tracks/functions.any';
|
||||
import {
|
||||
getCameraFacingMode,
|
||||
isLocalTrackMuted,
|
||||
isLocalVideoTrackDesktop,
|
||||
setTrackMuted
|
||||
} from '../tracks/functions.any';
|
||||
import { ITrack } from '../tracks/types';
|
||||
|
||||
import {
|
||||
@@ -40,7 +45,6 @@ import {
|
||||
setVideoMuted
|
||||
} from './actions';
|
||||
import {
|
||||
CAMERA_FACING_MODE,
|
||||
MEDIA_TYPE,
|
||||
SCREENSHARE_MUTISM_AUTHORITY,
|
||||
VIDEO_MUTISM_AUTHORITY
|
||||
@@ -233,7 +237,7 @@ function _setRoom({ dispatch, getState }: IStore, next: Function, action: AnyAct
|
||||
// the user i.e. the state of base/media. Eventually, practice/reality i.e.
|
||||
// the state of base/tracks will or will not agree with the desires.
|
||||
dispatch(setAudioMuted(audioMuted));
|
||||
dispatch(setCameraFacingMode(CAMERA_FACING_MODE.USER));
|
||||
dispatch(setCameraFacingMode(getCameraFacingMode(state)));
|
||||
dispatch(setVideoMuted(videoMuted));
|
||||
}
|
||||
|
||||
|
||||
@@ -3,7 +3,6 @@ import { WithTranslation } from 'react-i18next';
|
||||
import { connect } from 'react-redux';
|
||||
import { makeStyles } from 'tss-react/mui';
|
||||
|
||||
import { IReduxState } from '../../../../app/types';
|
||||
import { translate } from '../../../i18n/functions';
|
||||
import Icon from '../../../icons/components/Icon';
|
||||
import { IconArrowDown, IconWifi1Bar, IconWifi2Bars, IconWifi3Bars } from '../../../icons/svg';
|
||||
@@ -217,8 +216,8 @@ function ConnectionStatus({ connectionDetails, t, connectionType }: IProps) {
|
||||
* @param {Object} state - The redux state.
|
||||
* @returns {Object}
|
||||
*/
|
||||
function mapStateToProps(state: IReduxState) {
|
||||
const { connectionDetails, connectionType } = getConnectionData(state);
|
||||
function mapStateToProps() {
|
||||
const { connectionDetails, connectionType } = getConnectionData();
|
||||
|
||||
return {
|
||||
connectionDetails,
|
||||
|
||||
@@ -1,14 +1,5 @@
|
||||
import { findIndex } from 'lodash';
|
||||
|
||||
import { IReduxState } from '../../app/types';
|
||||
|
||||
import { CONNECTION_TYPE } from './constants';
|
||||
|
||||
const LOSS_AUDIO_THRESHOLDS = [ 0.33, 0.05 ];
|
||||
const LOSS_VIDEO_THRESHOLDS = [ 0.33, 0.1, 0.05 ];
|
||||
|
||||
const THROUGHPUT_AUDIO_THRESHOLDS = [ 8, 20 ];
|
||||
const THROUGHPUT_VIDEO_THRESHOLDS = [ 60, 750 ];
|
||||
|
||||
/**
|
||||
* The avatar size to container size ration.
|
||||
@@ -79,132 +70,15 @@ export function calculateAvatarDimensions(height: number) {
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the level based on a list of thresholds.
|
||||
*
|
||||
* @param {number[]} thresholds - The thresholds array.
|
||||
* @param {number} value - The value against which the level is calculated.
|
||||
* @param {boolean} descending - The order based on which the level is calculated.
|
||||
*
|
||||
* @returns {number}
|
||||
*/
|
||||
function _getLevel(thresholds: number[], value: number, descending = true) {
|
||||
let predicate;
|
||||
|
||||
if (descending) {
|
||||
predicate = function(threshold: number) {
|
||||
return value > threshold;
|
||||
};
|
||||
} else {
|
||||
predicate = function(threshold: number) {
|
||||
return value < threshold;
|
||||
};
|
||||
}
|
||||
|
||||
const i = findIndex(thresholds, predicate);
|
||||
|
||||
if (i === -1) {
|
||||
return thresholds.length;
|
||||
}
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the connection details from the test results.
|
||||
*
|
||||
* @param {number} testResults.fractionalLoss - Factional loss.
|
||||
* @param {number} testResults.throughput - Throughput.
|
||||
*
|
||||
* @returns {{
|
||||
* connectionType: string,
|
||||
* connectionDetails: string[]
|
||||
* }}
|
||||
*/
|
||||
function _getConnectionDataFromTestResults({ fractionalLoss: l, throughput: t }:
|
||||
{ fractionalLoss: number; throughput: number; }) {
|
||||
const loss = {
|
||||
audioQuality: _getLevel(LOSS_AUDIO_THRESHOLDS, l),
|
||||
videoQuality: _getLevel(LOSS_VIDEO_THRESHOLDS, l)
|
||||
};
|
||||
const throughput = {
|
||||
audioQuality: _getLevel(THROUGHPUT_AUDIO_THRESHOLDS, t, false),
|
||||
videoQuality: _getLevel(THROUGHPUT_VIDEO_THRESHOLDS, t, false)
|
||||
};
|
||||
let connectionType = CONNECTION_TYPE.NONE;
|
||||
const connectionDetails = [];
|
||||
|
||||
if (throughput.audioQuality === 0 || loss.audioQuality === 0) {
|
||||
// Calls are impossible.
|
||||
connectionType = CONNECTION_TYPE.POOR;
|
||||
connectionDetails.push('prejoin.connectionDetails.veryPoorConnection');
|
||||
} else if (
|
||||
throughput.audioQuality === 2
|
||||
&& throughput.videoQuality === 2
|
||||
&& loss.audioQuality === 2
|
||||
&& loss.videoQuality === 3
|
||||
) {
|
||||
// Ideal conditions for both audio and video. Show only one message.
|
||||
connectionType = CONNECTION_TYPE.GOOD;
|
||||
connectionDetails.push('prejoin.connectionDetails.goodQuality');
|
||||
} else {
|
||||
connectionType = CONNECTION_TYPE.NON_OPTIMAL;
|
||||
|
||||
if (throughput.audioQuality === 1) {
|
||||
// Minimum requirements for a call are met.
|
||||
connectionDetails.push('prejoin.connectionDetails.audioLowNoVideo');
|
||||
} else {
|
||||
// There are two paragraphs: one saying something about audio and the other about video.
|
||||
if (loss.audioQuality === 1) {
|
||||
connectionDetails.push('prejoin.connectionDetails.audioClipping');
|
||||
} else {
|
||||
connectionDetails.push('prejoin.connectionDetails.audioHighQuality');
|
||||
}
|
||||
|
||||
if (throughput.videoQuality === 0 || loss.videoQuality === 0) {
|
||||
connectionDetails.push('prejoin.connectionDetails.noVideo');
|
||||
} else if (throughput.videoQuality === 1) {
|
||||
connectionDetails.push('prejoin.connectionDetails.videoLowQuality');
|
||||
} else if (loss.videoQuality === 1) {
|
||||
connectionDetails.push('prejoin.connectionDetails.videoFreezing');
|
||||
} else if (loss.videoQuality === 2) {
|
||||
connectionDetails.push('prejoin.connectionDetails.videoTearing');
|
||||
} else {
|
||||
connectionDetails.push('prejoin.connectionDetails.videoHighQuality');
|
||||
}
|
||||
}
|
||||
connectionDetails.push('prejoin.connectionDetails.undetectable');
|
||||
}
|
||||
|
||||
return {
|
||||
connectionType,
|
||||
connectionDetails
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Selector for determining the connection type & details.
|
||||
*
|
||||
* @param {Object} state - The state of the app.
|
||||
* @returns {{
|
||||
* connectionType: string,
|
||||
* connectionDetails: string[]
|
||||
* }}
|
||||
*/
|
||||
export function getConnectionData(state: IReduxState) {
|
||||
const { precallTestResults } = state['features/prejoin'];
|
||||
|
||||
if (precallTestResults) {
|
||||
if (precallTestResults.mediaConnectivity) {
|
||||
return _getConnectionDataFromTestResults(precallTestResults);
|
||||
}
|
||||
|
||||
return {
|
||||
connectionType: CONNECTION_TYPE.POOR,
|
||||
connectionDetails: [ 'prejoin.connectionDetails.noMediaConnectivity' ]
|
||||
};
|
||||
}
|
||||
|
||||
export function getConnectionData() {
|
||||
return {
|
||||
connectionType: CONNECTION_TYPE.NONE,
|
||||
connectionDetails: []
|
||||
|
||||
@@ -158,15 +158,13 @@ class Watermarks extends Component<IProps, State> {
|
||||
_showJitsiWatermark
|
||||
} = this.props;
|
||||
const { noMargins, t } = this.props;
|
||||
const className = `watermark ${noMargins ? 'leftwatermarknomargin' : 'leftwatermark'}`;
|
||||
const className = `watermark leftwatermark ${noMargins ? 'no-margin' : ''}`;
|
||||
|
||||
let reactElement = null;
|
||||
|
||||
if (_showJitsiWatermark) {
|
||||
const style = {
|
||||
backgroundImage: `url(${_logoUrl})`,
|
||||
maxWidth: 140,
|
||||
maxHeight: 70,
|
||||
position: _logoLink ? 'static' : 'absolute'
|
||||
} as const;
|
||||
|
||||
|
||||
@@ -3,9 +3,14 @@ import { PREJOIN_INITIALIZED } from '../../prejoin/actionTypes';
|
||||
import { setPrejoinPageVisibility } from '../../prejoin/actions';
|
||||
import { APP_WILL_MOUNT } from '../app/actionTypes';
|
||||
import { getJwtName } from '../jwt/functions';
|
||||
import { MEDIA_TYPE } from '../media/constants';
|
||||
import MiddlewareRegistry from '../redux/MiddlewareRegistry';
|
||||
import { TRACK_ADDED } from '../tracks/actionTypes';
|
||||
import { ITrack } from '../tracks/types';
|
||||
|
||||
import { updateSettings } from './actions';
|
||||
import logger from './logger';
|
||||
|
||||
|
||||
import './middleware.any';
|
||||
|
||||
@@ -27,6 +32,9 @@ MiddlewareRegistry.register(store => next => action => {
|
||||
case PREJOIN_INITIALIZED:
|
||||
_maybeUpdateDisplayName(store);
|
||||
break;
|
||||
case TRACK_ADDED:
|
||||
_maybeUpdateDeviceId(store, action.track);
|
||||
break;
|
||||
}
|
||||
|
||||
return result;
|
||||
@@ -68,3 +76,30 @@ function _maybeUpdateDisplayName({ dispatch, getState }: IStore) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Maybe update the camera or mic device id when local track is added or updated.
|
||||
*
|
||||
* @param {Store} store - The redux store.
|
||||
* @param {ITrack} track - The potential local track.
|
||||
* @private
|
||||
* @returns {void}
|
||||
*/
|
||||
function _maybeUpdateDeviceId({ dispatch, getState }: IStore, track: ITrack) {
|
||||
if (track.local) {
|
||||
const { cameraDeviceId, micDeviceId } = getState()['features/base/settings'];
|
||||
const deviceId = track.jitsiTrack.getDeviceId();
|
||||
|
||||
if (track.mediaType === MEDIA_TYPE.VIDEO && track.videoType === 'camera' && cameraDeviceId !== deviceId) {
|
||||
dispatch(updateSettings({
|
||||
cameraDeviceId: track.jitsiTrack.getDeviceId()
|
||||
}));
|
||||
logger.info(`switched local video device to: ${deviceId}`);
|
||||
} else if (track.mediaType === MEDIA_TYPE.AUDIO && micDeviceId !== deviceId) {
|
||||
dispatch(updateSettings({
|
||||
micDeviceId: track.jitsiTrack.getDeviceId()
|
||||
}));
|
||||
logger.info(`switched local audio input device to: ${deviceId}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -53,6 +53,11 @@ export interface IProps extends WithTranslation {
|
||||
*/
|
||||
handleClick?: Function;
|
||||
|
||||
/**
|
||||
* Whether the button open a menu or not.
|
||||
*/
|
||||
isMenuButton?: boolean;
|
||||
|
||||
/**
|
||||
* Notify mode for `toolbarButtonClicked` event -
|
||||
* whether to only notify or to also prevent button click routine.
|
||||
@@ -102,7 +107,7 @@ export const defaultDisabledButtonStyles = {
|
||||
/**
|
||||
* An abstract implementation of a button.
|
||||
*/
|
||||
export default class AbstractButton<P extends IProps, S=any> extends Component<P, S> {
|
||||
export default class AbstractButton<P extends IProps, S = any> extends Component<P, S> {
|
||||
static defaultProps = {
|
||||
afterClick: undefined,
|
||||
disabledStyles: defaultDisabledButtonStyles,
|
||||
@@ -354,7 +359,7 @@ export default class AbstractButton<P extends IProps, S=any> extends Component<P
|
||||
|
||||
if (typeof APP !== 'undefined' && notifyMode) {
|
||||
APP.API.notifyToolbarButtonClicked(
|
||||
buttonKey, notifyMode === NOTIFY_CLICK_MODE.PREVENT_AND_NOTIFY
|
||||
buttonKey, notifyMode === NOTIFY_CLICK_MODE.PREVENT_AND_NOTIFY
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -19,6 +19,11 @@ interface IProps extends AbstractToolboxItemProps {
|
||||
*/
|
||||
contextMenu?: boolean;
|
||||
|
||||
/**
|
||||
* Whether the button open a menu or not.
|
||||
*/
|
||||
isMenuButton?: boolean;
|
||||
|
||||
/**
|
||||
* On key down handler.
|
||||
*/
|
||||
@@ -67,6 +72,7 @@ export default class ToolboxItem extends AbstractToolboxItem<IProps> {
|
||||
const {
|
||||
backgroundColor,
|
||||
contextMenu,
|
||||
isMenuButton,
|
||||
disabled,
|
||||
elementAfter,
|
||||
icon,
|
||||
@@ -77,8 +83,9 @@ export default class ToolboxItem extends AbstractToolboxItem<IProps> {
|
||||
toggled
|
||||
} = this.props;
|
||||
const className = showLabel ? 'overflow-menu-item' : 'toolbox-button';
|
||||
const buttonAttribute = isMenuButton ? 'aria-expanded' : 'aria-pressed';
|
||||
const props = {
|
||||
'aria-pressed': toggled,
|
||||
[buttonAttribute]: toggled,
|
||||
'aria-disabled': disabled,
|
||||
'aria-label': this.accessibilityLabel,
|
||||
className: className + (disabled ? ' disabled' : ''),
|
||||
|
||||
@@ -35,6 +35,7 @@ import {
|
||||
} from './actionTypes';
|
||||
import {
|
||||
createLocalTracksF,
|
||||
getCameraFacingMode,
|
||||
getLocalTrack,
|
||||
getLocalTracks,
|
||||
getLocalVideoTrack,
|
||||
@@ -140,6 +141,7 @@ export function createLocalTracksA(options: ITrackOptions = {}) {
|
||||
getState
|
||||
};
|
||||
const promises = [];
|
||||
const state = getState();
|
||||
|
||||
// The following executes on React Native only at the time of this
|
||||
// writing. The effort to port Web's createInitialLocalTracks
|
||||
@@ -153,7 +155,7 @@ export function createLocalTracksA(options: ITrackOptions = {}) {
|
||||
// device separately.
|
||||
for (const device of devices) {
|
||||
if (getLocalTrack(
|
||||
getState()['features/base/tracks'],
|
||||
state['features/base/tracks'],
|
||||
device as MediaType,
|
||||
/* includePending */ true)) {
|
||||
throw new Error(`Local track for ${device} already exists`);
|
||||
@@ -165,7 +167,7 @@ export function createLocalTracksA(options: ITrackOptions = {}) {
|
||||
cameraDeviceId: options.cameraDeviceId,
|
||||
devices: [ device ],
|
||||
facingMode:
|
||||
options.facingMode || CAMERA_FACING_MODE.USER,
|
||||
options.facingMode || getCameraFacingMode(state),
|
||||
micDeviceId: options.micDeviceId
|
||||
},
|
||||
store)
|
||||
|
||||
@@ -4,7 +4,7 @@ import {
|
||||
} from '../config/functions.any';
|
||||
import { JitsiTrackErrors, browser } from '../lib-jitsi-meet';
|
||||
import { gumPending } from '../media/actions';
|
||||
import { MEDIA_TYPE, MediaType, VIDEO_TYPE } from '../media/constants';
|
||||
import { CAMERA_FACING_MODE, MEDIA_TYPE, MediaType, VIDEO_TYPE } from '../media/constants';
|
||||
import { IMediaState } from '../media/reducer';
|
||||
import { IGUMPendingState } from '../media/types';
|
||||
import {
|
||||
@@ -447,3 +447,13 @@ export function logTracksForParticipant(tracksState: ITrack[], participantId: st
|
||||
|
||||
logger.debug(`${logStringPrefix}${reason ? `(reason: ${reason})` : ''}:${tracksLogMsg}`);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the default camera facing mode.
|
||||
*
|
||||
* @param {Object} state - The redux state.
|
||||
* @returns {string} - The camera facing mode.
|
||||
*/
|
||||
export function getCameraFacingMode(state: IReduxState) {
|
||||
return state['features/base/config'].cameraFacingMode ?? CAMERA_FACING_MODE.USER;
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { IStore } from '../../app/types';
|
||||
import JitsiMeetJS from '../lib-jitsi-meet';
|
||||
|
||||
import { getCameraFacingMode } from './functions.any';
|
||||
import { ITrackOptions } from './types';
|
||||
|
||||
export * from './functions.any';
|
||||
@@ -39,6 +40,7 @@ export function createLocalTracksF(options: ITrackOptions = {}, store: IStore) {
|
||||
|
||||
// Copy array to avoid mutations inside library.
|
||||
devices: options.devices?.slice(0),
|
||||
facingMode: options.facingMode || getCameraFacingMode(state),
|
||||
micDeviceId,
|
||||
resolution
|
||||
});
|
||||
|
||||
@@ -12,6 +12,7 @@ import {
|
||||
getUserSelectedMicDeviceId
|
||||
} from '../settings/functions.web';
|
||||
|
||||
import { getCameraFacingMode } from './functions.any';
|
||||
import loadEffects from './loadEffects';
|
||||
import logger from './logger';
|
||||
import { ITrackOptions } from './types';
|
||||
@@ -82,6 +83,7 @@ export function createLocalTracksF(options: ITrackOptions = {}, store?: IStore)
|
||||
// Copy array to avoid mutations inside library.
|
||||
devices: options.devices?.slice(0),
|
||||
effects,
|
||||
facingMode: options.facingMode || getCameraFacingMode(state),
|
||||
firefox_fake_device, // eslint-disable-line camelcase
|
||||
firePermissionPromptIsShownEvent,
|
||||
micDeviceId,
|
||||
|
||||
@@ -344,7 +344,6 @@ const ContextMenu = ({
|
||||
|
||||
if (event.key === 'Escape') {
|
||||
// Close the menu
|
||||
event.preventDefault();
|
||||
setIsHidden(true);
|
||||
|
||||
} else if (event.key === 'ArrowUp') {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { IStore } from '../app/types';
|
||||
import { configureInitialDevices } from '../base/devices/actions.web';
|
||||
import { configureInitialDevices, getAvailableDevices } from '../base/devices/actions.web';
|
||||
import { openDialog } from '../base/dialog/actions';
|
||||
import { getBackendSafeRoomName } from '../base/util/uri';
|
||||
|
||||
@@ -34,6 +34,18 @@ export function dismissCalendarNotification() {
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Setups initial devices. Makes sure we populate availableDevices list before configuring.
|
||||
*
|
||||
* @returns {Promise<any>}
|
||||
*/
|
||||
export function setupInitialDevices() {
|
||||
return async (dispatch: IStore['dispatch']) => {
|
||||
await dispatch(getAvailableDevices());
|
||||
await dispatch(configureInitialDevices());
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Init.
|
||||
*
|
||||
@@ -45,7 +57,7 @@ export function init() {
|
||||
|
||||
// XXX For web based version we use conference initialization logic
|
||||
// from the old app (at the moment of writing).
|
||||
return dispatch(configureInitialDevices()).then(
|
||||
return dispatch(setupInitialDevices()).then(
|
||||
() => APP.conference.init({
|
||||
roomName: room
|
||||
}).catch((error: Error) => {
|
||||
|
||||
@@ -127,13 +127,6 @@ class DesktopPicker extends PureComponent<IProps, IState> {
|
||||
types: []
|
||||
};
|
||||
|
||||
/**
|
||||
* Stores the type of the selected tab.
|
||||
*
|
||||
* @type {string}
|
||||
*/
|
||||
_selectedTabType = DEFAULT_TAB_TYPE;
|
||||
|
||||
/**
|
||||
* Initializes a new DesktopPicker instance.
|
||||
*
|
||||
@@ -223,17 +216,20 @@ class DesktopPicker extends PureComponent<IProps, IState> {
|
||||
* Computes the selected source.
|
||||
*
|
||||
* @param {Object} sources - The available sources.
|
||||
* @param {string} selectedTab - The selected tab.
|
||||
* @returns {Object} The selectedSource value.
|
||||
*/
|
||||
_getSelectedSource(sources: any = {}) {
|
||||
_getSelectedSource(sources: any = {}, selectedTab?: string) {
|
||||
const { selectedSource } = this.state;
|
||||
|
||||
const currentSelectedTab = selectedTab ?? this.state.selectedTab;
|
||||
|
||||
/**
|
||||
* If there are no sources for this type (or no sources for any type)
|
||||
* we can't select anything.
|
||||
*/
|
||||
if (!Array.isArray(sources[this._selectedTabType as keyof typeof sources])
|
||||
|| sources[this._selectedTabType as keyof typeof sources].length <= 0) {
|
||||
if (!Array.isArray(sources[currentSelectedTab as keyof typeof sources])
|
||||
|| sources[currentSelectedTab as keyof typeof sources].length <= 0) {
|
||||
return {};
|
||||
}
|
||||
|
||||
@@ -245,12 +241,12 @@ class DesktopPicker extends PureComponent<IProps, IState> {
|
||||
* 3) The selected source is no longer available.
|
||||
*/
|
||||
if (!selectedSource // scenario 1)
|
||||
|| selectedSource.type !== this._selectedTabType // scenario 2)
|
||||
|| !sources[this._selectedTabType].some( // scenario 3)
|
||||
|| selectedSource.type !== currentSelectedTab // scenario 2)
|
||||
|| !sources[currentSelectedTab].some( // scenario 3)
|
||||
(source: any) => source.id === selectedSource.id)) {
|
||||
return {
|
||||
id: sources[this._selectedTabType][0].id,
|
||||
type: this._selectedTabType
|
||||
id: sources[currentSelectedTab][0].id,
|
||||
type: currentSelectedTab
|
||||
};
|
||||
}
|
||||
|
||||
@@ -319,10 +315,10 @@ class DesktopPicker extends PureComponent<IProps, IState> {
|
||||
// use the option from one tab when sharing from another.
|
||||
this.setState({
|
||||
screenShareAudio: false,
|
||||
selectedSource: this._getSelectedSource(sources),
|
||||
selectedSource: this._getSelectedSource(sources, id),
|
||||
|
||||
// select type `window` or `screen` from id
|
||||
selectedTab: id.split('-')[0]
|
||||
selectedTab: id
|
||||
});
|
||||
}
|
||||
|
||||
@@ -410,8 +406,8 @@ class DesktopPicker extends PureComponent<IProps, IState> {
|
||||
const selectedSource = this._getSelectedSource(sources);
|
||||
|
||||
this.setState({
|
||||
sources,
|
||||
selectedSource
|
||||
selectedSource,
|
||||
sources
|
||||
});
|
||||
})
|
||||
.catch((error: any) => logger.log(error));
|
||||
|
||||
@@ -109,7 +109,7 @@ export function getVideoDeviceSelectionDialogProps(stateful: IStateful, isDispla
|
||||
const framerate = state['features/screen-share'].captureFrameRate ?? SS_DEFAULT_FRAME_RATE;
|
||||
|
||||
let disableVideoInputSelect = !inputDeviceChangeSupported;
|
||||
let selectedVideoInputId = settings.cameraDeviceId;
|
||||
let selectedVideoInputId = settings.cameraDeviceId || userSelectedCamera;
|
||||
|
||||
// audio input change will be a problem only when we are in a
|
||||
// conference and this is not supported, when we open device selection on
|
||||
@@ -180,8 +180,8 @@ export function processExternalDeviceRequest( // eslint-disable-line max-params
|
||||
};
|
||||
const currentlyUsedDeviceIds = new Set([
|
||||
getAudioOutputDeviceId(),
|
||||
settings.micDeviceId,
|
||||
settings.cameraDeviceId
|
||||
settings.micDeviceId ?? getUserSelectedMicDeviceId(state),
|
||||
settings.cameraDeviceId ?? getUserSelectedCameraDeviceId(state)
|
||||
]);
|
||||
|
||||
devices.forEach(device => {
|
||||
|
||||
@@ -4,7 +4,6 @@ import { IStore } from '../app/types';
|
||||
import { IJitsiConference } from '../base/conference/reducer';
|
||||
import { openDialog } from '../base/dialog/actions';
|
||||
import { extractFqnFromPath } from '../dynamic-branding/functions.any';
|
||||
import { isVpaasMeeting } from '../jaas/functions';
|
||||
|
||||
import {
|
||||
CANCEL_FEEDBACK,
|
||||
@@ -12,7 +11,7 @@ import {
|
||||
SUBMIT_FEEDBACK_SUCCESS
|
||||
} from './actionTypes';
|
||||
import FeedbackDialog from './components/FeedbackDialog.web';
|
||||
import { sendFeedbackToJaaSRequest } from './functions.web';
|
||||
import { sendFeedbackToJaaSRequest, shouldSendJaaSFeedbackMetadata } from './functions.web';
|
||||
|
||||
/**
|
||||
* Caches the passed in feedback in the redux store.
|
||||
@@ -72,7 +71,8 @@ export function maybeOpenFeedbackDialog(conference: IJitsiConference, title?: st
|
||||
showThankYou: true,
|
||||
wasDialogShown: false
|
||||
});
|
||||
} else if (conference.isCallstatsEnabled() && feedbackPercentage > Math.random() * 100) {
|
||||
} else if (shouldSendJaaSFeedbackMetadata(state)
|
||||
&& feedbackPercentage > Math.random() * 100) {
|
||||
return new Promise(resolve => {
|
||||
dispatch(openFeedbackDialog(conference, title, () => {
|
||||
const { submitted } = getState()['features/feedback'];
|
||||
@@ -125,16 +125,15 @@ export function openFeedbackDialog(conference?: IJitsiConference, title?: string
|
||||
* @returns {Promise}
|
||||
*/
|
||||
export function sendJaasFeedbackMetadata(conference: IJitsiConference, feedback: Object) {
|
||||
return (dispatch: IStore['dispatch'], getState: IStore['getState']): Promise<any> => {
|
||||
return (_dispatch: IStore['dispatch'], getState: IStore['getState']) => {
|
||||
const state = getState();
|
||||
const { jaasFeedbackMetadataURL } = state['features/base/config'];
|
||||
|
||||
const { jwt, user, tenant } = state['features/base/jwt'];
|
||||
|
||||
if (!isVpaasMeeting(state) || !jaasFeedbackMetadataURL) {
|
||||
if (!shouldSendJaaSFeedbackMetadata(state)) {
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
||||
const { jaasFeedbackMetadataURL } = state['features/base/config'];
|
||||
const { jwt, user, tenant } = state['features/base/jwt'];
|
||||
const meetingFqn = extractFqnFromPath();
|
||||
const feedbackData = {
|
||||
...feedback,
|
||||
@@ -164,17 +163,35 @@ export function submitFeedback(
|
||||
score: number,
|
||||
message: string,
|
||||
conference: IJitsiConference) {
|
||||
return (dispatch: IStore['dispatch']) =>
|
||||
conference.sendFeedback(score, message)
|
||||
.then(() => dispatch({ type: SUBMIT_FEEDBACK_SUCCESS }))
|
||||
.then(() => dispatch(sendJaasFeedbackMetadata(conference, { score,
|
||||
message }))
|
||||
.catch(error => {
|
||||
return (dispatch: IStore['dispatch'], getState: IStore['getState']) => {
|
||||
const state = getState();
|
||||
const promises = [];
|
||||
|
||||
if (shouldSendJaaSFeedbackMetadata(state)) {
|
||||
promises.push(dispatch(sendJaasFeedbackMetadata(conference, {
|
||||
score,
|
||||
message
|
||||
})));
|
||||
}
|
||||
|
||||
return Promise.allSettled(promises)
|
||||
.then(results => {
|
||||
const rejected = results.find((result): result is PromiseRejectedResult => result?.status === 'rejected');
|
||||
|
||||
if (typeof rejected === 'undefined') {
|
||||
dispatch({ type: SUBMIT_FEEDBACK_SUCCESS });
|
||||
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
||||
const error = rejected.reason;
|
||||
|
||||
dispatch({
|
||||
type: SUBMIT_FEEDBACK_ERROR,
|
||||
error
|
||||
});
|
||||
|
||||
return Promise.reject(error);
|
||||
}));
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
@@ -9,6 +9,7 @@ import { translate } from '../../base/i18n/functions';
|
||||
import { IconFeedback } from '../../base/icons/svg';
|
||||
import AbstractButton, { IProps as AbstractButtonProps } from '../../base/toolbox/components/AbstractButton';
|
||||
import { openFeedbackDialog } from '../actions';
|
||||
import { shouldSendJaaSFeedbackMetadata } from '../functions.web';
|
||||
|
||||
/**
|
||||
* The type of the React {@code Component} props of {@link FeedbackButton}.
|
||||
@@ -45,11 +46,11 @@ class FeedbackButton extends AbstractButton<IProps> {
|
||||
}
|
||||
|
||||
const mapStateToProps = (state: IReduxState) => {
|
||||
const { callStatsID } = state['features/base/config'];
|
||||
const { conference } = state['features/base/conference'];
|
||||
|
||||
return {
|
||||
_conference: state['features/base/conference'].conference,
|
||||
visible: Boolean(callStatsID)
|
||||
_conference: conference,
|
||||
visible: shouldSendJaaSFeedbackMetadata(state)
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
@@ -1,16 +1,23 @@
|
||||
import { IReduxState } from '../app/types';
|
||||
import { isVpaasMeeting } from '../jaas/functions';
|
||||
|
||||
import logger from './logger';
|
||||
|
||||
/**
|
||||
* Sends feedback metadata to JaaS endpoints.
|
||||
*
|
||||
* @param {string} url - The JaaS metadata endpoint URL.
|
||||
* @param {string|undefined} url - The JaaS metadata endpoint URL.
|
||||
* @param {Object} feedbackData - The feedback data object.
|
||||
* @returns {Promise}
|
||||
*/
|
||||
export async function sendFeedbackToJaaSRequest(url: string, feedbackData: {
|
||||
export async function sendFeedbackToJaaSRequest(url: string | undefined, feedbackData: {
|
||||
jwt?: string; meetingFqn: string; message?: string; score?: number;
|
||||
sessionId: string; tenant?: string; userId?: string;
|
||||
}) {
|
||||
if (!url) {
|
||||
throw new TypeError('Trying to send jaas feedback request to an undefined URL!');
|
||||
}
|
||||
|
||||
const {
|
||||
jwt,
|
||||
sessionId,
|
||||
@@ -49,3 +56,15 @@ export async function sendFeedbackToJaaSRequest(url: string, feedbackData: {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether jaas feedback metadata should be send or not.
|
||||
*
|
||||
* @param {IReduxState} state - The redux state.
|
||||
* @returns {boolean} - True if jaas feedback metadata should be send and false otherwise.
|
||||
*/
|
||||
export function shouldSendJaaSFeedbackMetadata(state: IReduxState) {
|
||||
const { jaasFeedbackMetadataURL } = state['features/base/config'];
|
||||
|
||||
return Boolean(isVpaasMeeting(state) && jaasFeedbackMetadataURL);
|
||||
}
|
||||
|
||||
|
||||
@@ -3,6 +3,7 @@ import { Component } from 'react';
|
||||
import { createInviteDialogEvent } from '../../../analytics/AnalyticsEvents';
|
||||
import { sendAnalytics } from '../../../analytics/functions';
|
||||
import { IReduxState, IStore } from '../../../app/types';
|
||||
import { getMeetingRegion } from '../../../base/config/functions.any';
|
||||
import { showErrorNotification, showNotification } from '../../../notifications/actions';
|
||||
import { NOTIFICATION_TIMEOUT_TYPE } from '../../../notifications/constants';
|
||||
import { INotificationProps } from '../../../notifications/types';
|
||||
@@ -65,6 +66,11 @@ export interface IProps {
|
||||
*/
|
||||
_peopleSearchUrl: string;
|
||||
|
||||
/**
|
||||
* The region where we connected to.
|
||||
*/
|
||||
_region: string;
|
||||
|
||||
/**
|
||||
* Whether or not to allow sip invites.
|
||||
*/
|
||||
@@ -248,6 +254,7 @@ export default class AbstractAddPeopleDialog<P extends IProps, S extends IState>
|
||||
_jwt: jwt,
|
||||
_peopleSearchQueryTypes: peopleSearchQueryTypes,
|
||||
_peopleSearchUrl: peopleSearchUrl,
|
||||
_region: region,
|
||||
_sipInviteEnabled: sipInviteEnabled
|
||||
} = this.props;
|
||||
const options = {
|
||||
@@ -259,6 +266,7 @@ export default class AbstractAddPeopleDialog<P extends IProps, S extends IState>
|
||||
jwt,
|
||||
peopleSearchQueryTypes,
|
||||
peopleSearchUrl,
|
||||
region,
|
||||
sipInviteEnabled
|
||||
};
|
||||
|
||||
@@ -300,6 +308,7 @@ export function _mapStateToProps(state: IReduxState) {
|
||||
_jwt: state['features/base/jwt'].jwt ?? '',
|
||||
_peopleSearchQueryTypes: peopleSearchQueryTypes ?? [],
|
||||
_peopleSearchUrl: peopleSearchUrl ?? '',
|
||||
_region: getMeetingRegion(state),
|
||||
_sipInviteEnabled: isSipInviteEnabled(state)
|
||||
};
|
||||
}
|
||||
|
||||
@@ -41,13 +41,15 @@ export const sharingFeatures = {
|
||||
*
|
||||
* @param {string} dialNumber - The dial number to check for validity.
|
||||
* @param {string} dialOutAuthUrl - The endpoint to use for checking validity.
|
||||
* @param {string} region - The region we are connected to.
|
||||
* @returns {Promise} - The promise created by the request.
|
||||
*/
|
||||
export function checkDialNumber(
|
||||
dialNumber: string,
|
||||
dialOutAuthUrl: string
|
||||
dialOutAuthUrl: string,
|
||||
region: string
|
||||
): Promise<{ allow?: boolean; country?: string; phone?: string; }> {
|
||||
const fullUrl = `${dialOutAuthUrl}?phone=${dialNumber}`;
|
||||
const fullUrl = `${dialOutAuthUrl}?phone=${dialNumber}®ion=${region}`;
|
||||
|
||||
return new Promise((resolve, reject) =>
|
||||
fetch(fullUrl)
|
||||
@@ -146,6 +148,11 @@ export type GetInviteResultsOptions = {
|
||||
*/
|
||||
peopleSearchUrl: string;
|
||||
|
||||
/**
|
||||
* The region we are connected to.
|
||||
*/
|
||||
region: string;
|
||||
|
||||
/**
|
||||
* Whether or not to check sip invites.
|
||||
*/
|
||||
@@ -174,6 +181,7 @@ export function getInviteResultsForQuery(
|
||||
dialOutEnabled,
|
||||
peopleSearchQueryTypes,
|
||||
peopleSearchUrl,
|
||||
region,
|
||||
sipInviteEnabled,
|
||||
jwt
|
||||
} = options;
|
||||
@@ -217,7 +225,7 @@ export function getInviteResultsForQuery(
|
||||
// so ensure only digits get sent.
|
||||
numberToVerify = getDigitsOnly(numberToVerify);
|
||||
|
||||
phoneNumberPromise = checkDialNumber(numberToVerify, dialOutAuthUrl);
|
||||
phoneNumberPromise = checkDialNumber(numberToVerify, dialOutAuthUrl, region);
|
||||
} else if (dialOutEnabled && !dialOutAuthUrl) {
|
||||
// fake having a country code to hide the country code reminder
|
||||
hasCountryCode = true;
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { IReduxState } from '../app/types';
|
||||
import { IJitsiConference } from '../base/conference/reducer';
|
||||
|
||||
import { VPAAS_TENANT_PREFIX } from './constants';
|
||||
import logger from './logger';
|
||||
@@ -47,6 +48,31 @@ export function isVpaasMeeting(state: IReduxState) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends a request for retrieving the conference creator's customer id.
|
||||
*
|
||||
* @param {IJitsiConference} conference - The conference state.
|
||||
* @param {IReduxState} state - The state of the app.
|
||||
* @returns {Object} - Object containing customerId field.
|
||||
*/
|
||||
export async function sendGetCustomerIdRequest(conference: IJitsiConference, state: IReduxState) {
|
||||
const { jaasConferenceCreatorUrl } = state['features/base/config'];
|
||||
|
||||
const roomJid = conference?.room?.roomjid;
|
||||
|
||||
if (jaasConferenceCreatorUrl && roomJid) {
|
||||
const fullUrl = `${jaasConferenceCreatorUrl}?conference=${encodeURIComponent(roomJid)}`;
|
||||
const response = await fetch(fullUrl);
|
||||
const responseBody = await response.json();
|
||||
|
||||
if (response.ok) {
|
||||
return responseBody;
|
||||
}
|
||||
|
||||
logger.error(`Failed to fetch ${fullUrl}. with: ${JSON.stringify(responseBody)}`);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends a request for retrieving jaas customer details.
|
||||
*
|
||||
|
||||
@@ -228,16 +228,17 @@ class LargeVideo extends Component<IProps> {
|
||||
* another container for the background and the
|
||||
* largeVideoWrapper in order to hide/show them.
|
||||
*/}
|
||||
{ _displayScreenSharingPlaceholder ? <ScreenSharePlaceholder /> : <></>}
|
||||
<div
|
||||
id = 'largeVideoWrapper'
|
||||
onTouchEnd = { this._onDoubleTap }
|
||||
ref = { this._wrapperRef }
|
||||
role = 'figure' >
|
||||
{ _displayScreenSharingPlaceholder ? <ScreenSharePlaceholder /> : <video
|
||||
<video
|
||||
autoPlay = { !_noAutoPlayVideo }
|
||||
id = 'largeVideo'
|
||||
muted = { true }
|
||||
playsInline = { true } /* for Safari on iOS to work */ /> }
|
||||
playsInline = { true } /* for Safari on iOS to work */ />
|
||||
</div>
|
||||
</div>
|
||||
{ interfaceConfig.DISABLE_TRANSCRIPTION_SUBTITLES
|
||||
|
||||
@@ -15,7 +15,10 @@ const useStyles = makeStyles()(theme => {
|
||||
display: 'flex',
|
||||
justifyContent: 'center',
|
||||
alignItems: 'center',
|
||||
position: 'absolute'
|
||||
position: 'absolute',
|
||||
top: 0,
|
||||
left: 0,
|
||||
zIndex: 2
|
||||
},
|
||||
content: {
|
||||
display: 'flex',
|
||||
|
||||
@@ -154,11 +154,10 @@ function _conferenceFailed({ getState }: IStore, next: Function, action: AnyActi
|
||||
// prevented the user from joining a specific conference but the app may be
|
||||
// able to eventually join the conference.
|
||||
if (!action.error.recoverable) {
|
||||
const { callUUID } = action.conference;
|
||||
|
||||
if (callUUID) {
|
||||
if (action?.conference?.callUUID) {
|
||||
delete action.conference.callUUID;
|
||||
CallIntegration.reportCallFailed(callUUID);
|
||||
CallIntegration.reportCallFailed(action.conference.callUUIDID);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -185,9 +184,9 @@ function _conferenceJoined({ getState }: IStore, next: Function, action: AnyActi
|
||||
return result;
|
||||
}
|
||||
|
||||
const { callUUID } = action.conference;
|
||||
if (action?.conference?.callUUID) {
|
||||
const { callUUID } = action.conference;
|
||||
|
||||
if (callUUID) {
|
||||
CallIntegration.reportConnectedOutgoingCall(callUUID)
|
||||
.then(() => {
|
||||
// iOS 13 doesn't like the mute state to be false before the call is started
|
||||
@@ -230,11 +229,9 @@ function _conferenceLeft({ getState }: IStore, next: Function, action: AnyAction
|
||||
return result;
|
||||
}
|
||||
|
||||
const { callUUID } = action.conference;
|
||||
|
||||
if (callUUID) {
|
||||
if (action?.conference?.callUUID) {
|
||||
delete action.conference.callUUID;
|
||||
CallIntegration.endCall(callUUID);
|
||||
CallIntegration.endCall(action.conference.callUUID);
|
||||
}
|
||||
|
||||
return result;
|
||||
|
||||
@@ -30,7 +30,7 @@ interface IProps {
|
||||
/**
|
||||
* Is the navigator part of Welcome page?
|
||||
*/
|
||||
isInWelcomePage?: boolean;
|
||||
isInWelcomePage?: boolean | undefined;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -288,13 +288,6 @@ function _visitNode(node, callback) {
|
||||
global.performance.now = performanceNow;
|
||||
global.PerformanceObserver = perf.PerformanceObserver;
|
||||
|
||||
// CallStats
|
||||
//
|
||||
// Required by:
|
||||
// - lib-jitsi-meet
|
||||
require('react-native-callstats/csio-polyfill');
|
||||
global.callstats = require('react-native-callstats/callstats');
|
||||
|
||||
// Timers
|
||||
//
|
||||
// React Native's timers won't run while the app is in the background, this
|
||||
|
||||
@@ -152,9 +152,6 @@ export default class AbstractPageReloadOverlay<P extends IProps>
|
||||
* @returns {void}
|
||||
*/
|
||||
componentDidMount() {
|
||||
// FIXME (CallStats - issue) This event will not make it to CallStats
|
||||
// because the log queue is not flushed before "fabric terminated" is
|
||||
// sent to the backed.
|
||||
// FIXME: We should dispatch action for this.
|
||||
if (typeof APP !== 'undefined' && APP.conference?._room) {
|
||||
APP.conference._room.sendApplicationLog(JSON.stringify({
|
||||
|
||||
@@ -128,6 +128,7 @@ export const RoomParticipantContextMenu = ({
|
||||
size = { AVATAR_SIZE } />,
|
||||
text: entity?.participantName
|
||||
} ] } />}
|
||||
|
||||
<ContextMenuItemGroup>
|
||||
<div className = { styles.text }>
|
||||
{t('breakoutRooms.actions.sendToBreakoutRoom')}
|
||||
|
||||
@@ -6,6 +6,10 @@ import { useDispatch, useSelector } from 'react-redux';
|
||||
|
||||
import { IReduxState } from '../../../app/types';
|
||||
import { openDialog, openSheet } from '../../../base/dialog/actions';
|
||||
import {
|
||||
BREAKOUT_ROOMS_BUTTON_ENABLED
|
||||
} from '../../../base/flags/constants';
|
||||
import { getFeatureFlag } from '../../../base/flags/functions';
|
||||
import Icon from '../../../base/icons/components/Icon';
|
||||
import { IconDotsHorizontal, IconRingGroup } from '../../../base/icons/svg';
|
||||
import BaseTheme from '../../../base/ui/components/BaseTheme.native';
|
||||
@@ -34,6 +38,9 @@ const ParticipantsPaneFooter = (): JSX.Element => {
|
||||
const isBreakoutRoomsSupported = useSelector((state: IReduxState) =>
|
||||
state['features/base/conference'].conference?.getBreakoutRooms()?.isSupported()
|
||||
);
|
||||
const isBreakoutRoomsEnabled = useSelector((state: IReduxState) =>
|
||||
getFeatureFlag(state, BREAKOUT_ROOMS_BUTTON_ENABLED, true)
|
||||
);
|
||||
const openMoreMenu = useCallback(() => dispatch(openSheet(ContextMenuMore)), [ dispatch ]);
|
||||
const muteAll = useCallback(() => dispatch(openDialog(MuteEveryoneDialog)),
|
||||
[ dispatch ]);
|
||||
@@ -44,6 +51,7 @@ const ParticipantsPaneFooter = (): JSX.Element => {
|
||||
<View style = { styles.participantsPaneFooterContainer as ViewStyle }>
|
||||
{
|
||||
isBreakoutRoomsSupported
|
||||
&& isBreakoutRoomsEnabled
|
||||
&& <Button
|
||||
accessibilityLabel = 'participantsPane.actions.breakoutRooms'
|
||||
// eslint-disable-next-line react/jsx-no-bind, no-confusing-arrow
|
||||
|
||||
@@ -39,11 +39,6 @@ export const SET_DIALOUT_STATUS = 'SET_DIALOUT_STATUS';
|
||||
*/
|
||||
export const SET_JOIN_BY_PHONE_DIALOG_VISIBLITY = 'SET_JOIN_BY_PHONE_DIALOG_VISIBLITY';
|
||||
|
||||
/**
|
||||
* Action type to set the precall test data.
|
||||
*/
|
||||
export const SET_PRECALL_TEST_RESULTS = 'SET_PRECALL_TEST_RESULTS';
|
||||
|
||||
/**
|
||||
* Action type to disable the audio while on prejoin page.
|
||||
*/
|
||||
|
||||
@@ -30,7 +30,6 @@ import {
|
||||
SET_DIALOUT_NUMBER,
|
||||
SET_DIALOUT_STATUS,
|
||||
SET_JOIN_BY_PHONE_DIALOG_VISIBLITY,
|
||||
SET_PRECALL_TEST_RESULTS,
|
||||
SET_PREJOIN_DEVICE_ERRORS,
|
||||
SET_PREJOIN_PAGE_VISIBILITY,
|
||||
SET_SKIP_PREJOIN_RELOAD
|
||||
@@ -313,25 +312,6 @@ export function joinConferenceWithoutAudio() {
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes the 'precallTest' and executes one test, storing the results.
|
||||
*
|
||||
* @param {Object} conferenceOptions - The conference options.
|
||||
* @returns {Function}
|
||||
*/
|
||||
export function makePrecallTest(conferenceOptions: Object) {
|
||||
return async function(dispatch: IStore['dispatch']) {
|
||||
try {
|
||||
await JitsiMeetJS.precallTest.init(conferenceOptions);
|
||||
const results = await JitsiMeetJS.precallTest.execute();
|
||||
|
||||
dispatch(setPrecallTestResults(results));
|
||||
} catch (error) {
|
||||
logger.debug('Failed to execute pre call test - ', error);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Opens an external page with all the dial in numbers.
|
||||
*
|
||||
@@ -515,19 +495,6 @@ export function setJoinByPhoneDialogVisiblity(value: boolean) {
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Action used to set data from precall test.
|
||||
*
|
||||
* @param {Object} value - The precall test results.
|
||||
* @returns {Object}
|
||||
*/
|
||||
export function setPrecallTestResults(value: Object) {
|
||||
return {
|
||||
type: SET_PRECALL_TEST_RESULTS,
|
||||
value
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Action used to set the initial errors after creating the tracks.
|
||||
*
|
||||
|
||||
@@ -2,13 +2,13 @@ import React, { ComponentType } from 'react';
|
||||
import { batch } from 'react-redux';
|
||||
|
||||
import BaseApp from '../../../base/app/components/BaseApp';
|
||||
import { getConferenceOptions } from '../../../base/conference/functions';
|
||||
import { setConfig } from '../../../base/config/actions';
|
||||
import { createPrejoinTracks } from '../../../base/tracks/functions.web';
|
||||
import GlobalStyles from '../../../base/ui/components/GlobalStyles.web';
|
||||
import JitsiThemeProvider from '../../../base/ui/components/JitsiThemeProvider.web';
|
||||
import DialogContainer from '../../../base/ui/components/web/DialogContainer';
|
||||
import { initPrejoin, makePrecallTest } from '../../actions.web';
|
||||
import { setupInitialDevices } from '../../../conference/actions.web';
|
||||
import { initPrejoin } from '../../actions.web';
|
||||
|
||||
import PrejoinThirdParty from './PrejoinThirdParty';
|
||||
|
||||
@@ -59,13 +59,13 @@ export default class PrejoinApp extends BaseApp<Props> {
|
||||
startWithVideoMuted
|
||||
}));
|
||||
|
||||
await dispatch?.(setupInitialDevices());
|
||||
const { tryCreateLocalTracks, errors } = createPrejoinTracks();
|
||||
|
||||
const tracks = await tryCreateLocalTracks;
|
||||
|
||||
batch(() => {
|
||||
dispatch?.(initPrejoin(tracks, errors));
|
||||
store && dispatch?.(makePrecallTest(getConferenceOptions(store.getState())));
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -8,7 +8,6 @@ import {
|
||||
SET_DIALOUT_NUMBER,
|
||||
SET_DIALOUT_STATUS,
|
||||
SET_JOIN_BY_PHONE_DIALOG_VISIBLITY,
|
||||
SET_PRECALL_TEST_RESULTS,
|
||||
SET_PREJOIN_DEVICE_ERRORS,
|
||||
SET_PREJOIN_PAGE_VISIBILITY,
|
||||
SET_SKIP_PREJOIN_RELOAD
|
||||
@@ -45,11 +44,6 @@ export interface IPrejoinState {
|
||||
dialOutStatus: string;
|
||||
joiningInProgress?: boolean;
|
||||
name: string;
|
||||
precallTestResults?: {
|
||||
fractionalLoss: number;
|
||||
mediaConnectivity: boolean;
|
||||
throughput: number;
|
||||
};
|
||||
rawError: string;
|
||||
showJoinByPhoneDialog: boolean;
|
||||
showPrejoin: boolean;
|
||||
@@ -81,12 +75,6 @@ ReducerRegistry.register<IPrejoinState>(
|
||||
};
|
||||
}
|
||||
|
||||
case SET_PRECALL_TEST_RESULTS:
|
||||
return {
|
||||
...state,
|
||||
precallTestResults: action.value
|
||||
};
|
||||
|
||||
case SET_PREJOIN_PAGE_VISIBILITY:
|
||||
return {
|
||||
...state,
|
||||
|
||||
@@ -69,6 +69,16 @@ class RTCStats {
|
||||
JitsiMeetJS.rtcstats.sendStatsEntry('e2eRtt', e2eRttData);
|
||||
}
|
||||
|
||||
/**
|
||||
* Send identity data, the data will be processed by rtcstats-server and saved in the dump file.
|
||||
*
|
||||
* @param {Object} identityData - The object that holds the identity data.
|
||||
* @returns {void}
|
||||
*/
|
||||
sendIdentityData(identityData: Object) {
|
||||
JitsiMeetJS.rtcstats.sendIdentityEntry(identityData);
|
||||
}
|
||||
|
||||
/**
|
||||
* Send the timestamp of the start of the conference, the data will be processed by the rtcstats-server
|
||||
* and saved in the dump file.
|
||||
|
||||
@@ -11,12 +11,14 @@ import MiddlewareRegistry from '../base/redux/MiddlewareRegistry';
|
||||
import { TRACK_ADDED, TRACK_UPDATED } from '../base/tracks/actionTypes';
|
||||
import { ADD_FACE_LANDMARKS } from '../face-landmarks/actionTypes';
|
||||
import { FaceLandmarks } from '../face-landmarks/types';
|
||||
import { sendGetCustomerIdRequest } from '../jaas/functions';
|
||||
|
||||
import RTCStats from './RTCStats';
|
||||
import {
|
||||
canSendFaceLandmarksRTCStatsData,
|
||||
isRTCStatsEnabled
|
||||
} from './functions';
|
||||
import logger from './logger';
|
||||
|
||||
/**
|
||||
* Middleware which intercepts lib-jitsi-meet initialization and conference join in order init the
|
||||
@@ -33,6 +35,16 @@ MiddlewareRegistry.register((store: IStore) => (next: Function) => (action: AnyA
|
||||
case CONFERENCE_JOINED: {
|
||||
if (isRTCStatsEnabled(state)) {
|
||||
RTCStats.init();
|
||||
|
||||
sendGetCustomerIdRequest(action?.conference, state)
|
||||
.then(customerData => {
|
||||
const { customerId } = customerData ?? {};
|
||||
|
||||
customerId && RTCStats.sendIdentityData({ customerId });
|
||||
})
|
||||
.catch(error => {
|
||||
logger.error('Error while getting customer id:', error);
|
||||
});
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -31,6 +31,6 @@ export function showSalesforceNotification() {
|
||||
dispatch(openDialog(SalesforceLinkDialog));
|
||||
} ],
|
||||
appearance: NOTIFICATION_TYPE.NORMAL
|
||||
}, NOTIFICATION_TIMEOUT_TYPE.STICKY));
|
||||
}, NOTIFICATION_TIMEOUT_TYPE.LONG));
|
||||
};
|
||||
}
|
||||
|
||||
@@ -83,9 +83,10 @@ class ShareAudioDialog extends Component<IProps> {
|
||||
titleKey = { t('dialog.shareAudioTitle') }>
|
||||
<div className = 'share-audio-dialog'>
|
||||
<img
|
||||
alt = ''
|
||||
alt = { t('dialog.shareAudioAltText') }
|
||||
className = 'share-audio-animation'
|
||||
src = 'images/share-audio.gif' />
|
||||
src = 'images/share-audio.gif'
|
||||
tabIndex = { 0 } />
|
||||
<Checkbox
|
||||
checked = { this.props._shouldHideShareAudioHelper }
|
||||
label = { t('dialog.hideShareAudioHelper') }
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
import resemble from 'resemblejs';
|
||||
import 'image-capture';
|
||||
import './createImageBitmap';
|
||||
|
||||
@@ -7,20 +6,20 @@ import { sendAnalytics } from '../analytics/functions';
|
||||
import { IReduxState } from '../app/types';
|
||||
import { getCurrentConference } from '../base/conference/functions';
|
||||
import { getLocalParticipant, getRemoteParticipants } from '../base/participants/functions';
|
||||
import { ITrack } from '../base/tracks/types';
|
||||
import { getBaseUrl } from '../base/util/helpers';
|
||||
import { extractFqnFromPath } from '../dynamic-branding/functions.any';
|
||||
|
||||
import {
|
||||
CLEAR_INTERVAL,
|
||||
INTERVAL_TIMEOUT,
|
||||
PERCENTAGE_LOWER_BOUND,
|
||||
CLEAR_TIMEOUT,
|
||||
POLL_INTERVAL,
|
||||
SET_INTERVAL
|
||||
SCREENSHOT_QUEUE_LIMIT,
|
||||
SET_TIMEOUT,
|
||||
TIMEOUT_TICK
|
||||
} from './constants';
|
||||
import logger from './logger';
|
||||
// eslint-disable-next-line lines-around-comment
|
||||
// @ts-ignore
|
||||
import { processScreenshot } from './processScreenshot';
|
||||
import { timerWorkerScript } from './worker';
|
||||
|
||||
declare let ImageCapture: any;
|
||||
|
||||
@@ -30,14 +29,10 @@ declare let ImageCapture: any;
|
||||
*/
|
||||
export default class ScreenshotCaptureSummary {
|
||||
_state: IReduxState;
|
||||
_currentCanvas: HTMLCanvasElement;
|
||||
_currentCanvasContext: CanvasRenderingContext2D | null;
|
||||
_initializedRegion: boolean;
|
||||
_imageCapture: any;
|
||||
_imageCapture: ImageCapture;
|
||||
_streamWorker: Worker;
|
||||
_streamHeight: any;
|
||||
_streamWidth: any;
|
||||
_storedImageData?: ImageData;
|
||||
_queue: Blob[];
|
||||
|
||||
/**
|
||||
* Initializes a new {@code ScreenshotCaptureEffect} instance.
|
||||
@@ -46,16 +41,23 @@ export default class ScreenshotCaptureSummary {
|
||||
*/
|
||||
constructor(state: IReduxState) {
|
||||
this._state = state;
|
||||
this._currentCanvas = document.createElement('canvas');
|
||||
this._currentCanvasContext = this._currentCanvas.getContext('2d');
|
||||
|
||||
// Bind handlers such that they access the same instance.
|
||||
this._handleWorkerAction = this._handleWorkerAction.bind(this);
|
||||
this._initScreenshotCapture = this._initScreenshotCapture.bind(this);
|
||||
this._streamWorker = new Worker(timerWorkerScript, { name: 'Screenshot capture worker' });
|
||||
const baseUrl = `${getBaseUrl()}libs/`;
|
||||
|
||||
let workerUrl = `${baseUrl}screenshot-capture-worker.min.js`;
|
||||
|
||||
// @ts-ignore
|
||||
const workerBlob = new Blob([ `importScripts("${workerUrl}");` ], { type: 'application/javascript' });
|
||||
|
||||
// @ts-ignore
|
||||
workerUrl = window.URL.createObjectURL(workerBlob);
|
||||
this._streamWorker = new Worker(workerUrl, { name: 'Screenshot capture worker' });
|
||||
this._streamWorker.onmessage = this._handleWorkerAction;
|
||||
|
||||
this._initializedRegion = false;
|
||||
this._queue = [];
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -77,10 +79,17 @@ export default class ScreenshotCaptureSummary {
|
||||
...jwt && { 'Authorization': `Bearer ${jwt}` }
|
||||
};
|
||||
|
||||
await fetch(`${_screenshotHistoryRegionUrl}/${sessionId}`, {
|
||||
method: 'POST',
|
||||
headers
|
||||
});
|
||||
try {
|
||||
await fetch(`${_screenshotHistoryRegionUrl}/${sessionId}`, {
|
||||
method: 'POST',
|
||||
headers
|
||||
});
|
||||
} catch (err) {
|
||||
logger.warn(`Could not create screenshot region: ${err}`);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
this._initializedRegion = true;
|
||||
}
|
||||
@@ -88,31 +97,27 @@ export default class ScreenshotCaptureSummary {
|
||||
/**
|
||||
* Starts the screenshot capture event on a loop.
|
||||
*
|
||||
* @param {Track} track - The track that contains the stream from which screenshots are to be sent.
|
||||
* @param {JitsiTrack} jitsiTrack - The track that contains the stream from which screenshots are to be sent.
|
||||
* @returns {Promise} - Promise that resolves once effect has started or rejects if the
|
||||
* videoType parameter is not desktop.
|
||||
*/
|
||||
async start(track: ITrack) {
|
||||
const { videoType } = track;
|
||||
const stream = track.getOriginalStream();
|
||||
async start(jitsiTrack: any) {
|
||||
if (!window.OffscreenCanvas) {
|
||||
logger.warn('Can\'t start screenshot capture, OffscreenCanvas is not available');
|
||||
|
||||
return;
|
||||
}
|
||||
const { videoType, track } = jitsiTrack;
|
||||
|
||||
if (videoType !== 'desktop') {
|
||||
return;
|
||||
}
|
||||
const desktopTrack = stream.getVideoTracks()[0];
|
||||
const { height, width }
|
||||
= desktopTrack.getSettings() ?? desktopTrack.getConstraints();
|
||||
|
||||
this._streamHeight = height;
|
||||
this._streamWidth = width;
|
||||
this._currentCanvas.height = parseInt(height, 10);
|
||||
this._currentCanvas.width = parseInt(width, 10);
|
||||
this._imageCapture = new ImageCapture(desktopTrack);
|
||||
this._imageCapture = new ImageCapture(track);
|
||||
|
||||
if (!this._initializedRegion) {
|
||||
await this._initRegionSelection();
|
||||
}
|
||||
this._initScreenshotCapture();
|
||||
this.sendTimeout();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -121,28 +126,34 @@ export default class ScreenshotCaptureSummary {
|
||||
* @returns {void}
|
||||
*/
|
||||
stop() {
|
||||
this._streamWorker.postMessage({ id: CLEAR_INTERVAL });
|
||||
this._streamWorker.postMessage({ id: CLEAR_TIMEOUT });
|
||||
}
|
||||
|
||||
/**
|
||||
* Method that is called as soon as the first frame of the video loads from stream.
|
||||
* The method is used to store the {@code ImageData} object from the first frames
|
||||
* in order to use it for future comparisons based on which we can process only certain
|
||||
* screenshots.
|
||||
* Sends to worker the imageBitmap for the next timeout.
|
||||
*
|
||||
* @private
|
||||
* @returns {void}
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
async _initScreenshotCapture() {
|
||||
const imageBitmap = await this._imageCapture.grabFrame();
|
||||
async sendTimeout() {
|
||||
let imageBitmap: ImageBitmap | undefined;
|
||||
|
||||
this._currentCanvasContext?.drawImage(imageBitmap, 0, 0, this._streamWidth, this._streamHeight);
|
||||
const imageData = this._currentCanvasContext?.getImageData(0, 0, this._streamWidth, this._streamHeight);
|
||||
if (!this._imageCapture.track || this._imageCapture.track.readyState !== 'live') {
|
||||
logger.warn('Track is in invalid state');
|
||||
this.stop();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
imageBitmap = await this._imageCapture.grabFrame();
|
||||
} catch (e) {
|
||||
// ignore error
|
||||
}
|
||||
|
||||
this._storedImageData = imageData;
|
||||
this._streamWorker.postMessage({
|
||||
id: SET_INTERVAL,
|
||||
timeMs: POLL_INTERVAL
|
||||
id: SET_TIMEOUT,
|
||||
timeMs: POLL_INTERVAL,
|
||||
imageBitmap
|
||||
});
|
||||
}
|
||||
|
||||
@@ -153,18 +164,24 @@ export default class ScreenshotCaptureSummary {
|
||||
* @param {EventHandler} message - Message received from the Worker.
|
||||
* @returns {void}
|
||||
*/
|
||||
_handleWorkerAction(message: { data: { id: number; }; }) {
|
||||
return message.data.id === INTERVAL_TIMEOUT && this._handleScreenshot();
|
||||
_handleWorkerAction(message: { data: { id: number; imageBlob?: Blob; }; }) {
|
||||
const { id, imageBlob } = message.data;
|
||||
|
||||
this.sendTimeout();
|
||||
if (id === TIMEOUT_TICK && imageBlob && this._queue.length < SCREENSHOT_QUEUE_LIMIT) {
|
||||
this._doProcessScreenshot(imageBlob);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Method that processes the screenshot.
|
||||
*
|
||||
* @private
|
||||
* @param {ImageData} imageData - The image data of the new screenshot.
|
||||
* @param {Blob} imageBlob - The blob for the current screenshot.
|
||||
* @returns {void}
|
||||
*/
|
||||
_doProcessScreenshot(imageData?: ImageData) {
|
||||
_doProcessScreenshot(imageBlob: Blob) {
|
||||
this._queue.push(imageBlob);
|
||||
sendAnalytics(createScreensharingCaptureTakenEvent());
|
||||
|
||||
const conference = getCurrentConference(this._state);
|
||||
@@ -175,41 +192,24 @@ export default class ScreenshotCaptureSummary {
|
||||
const { jwt } = this._state['features/base/jwt'];
|
||||
const meetingFqn = extractFqnFromPath();
|
||||
const remoteParticipants = getRemoteParticipants(this._state);
|
||||
const participants = [];
|
||||
const participants: Array<string | undefined> = [];
|
||||
|
||||
participants.push(getLocalParticipant(this._state)?.id);
|
||||
remoteParticipants.forEach(p => participants.push(p.id));
|
||||
this._storedImageData = imageData;
|
||||
|
||||
processScreenshot(this._currentCanvas, {
|
||||
processScreenshot(imageBlob, {
|
||||
jid,
|
||||
jwt,
|
||||
sessionId,
|
||||
timestamp,
|
||||
meetingFqn,
|
||||
participants
|
||||
}).then(() => {
|
||||
const index = this._queue.indexOf(imageBlob);
|
||||
|
||||
if (index > -1) {
|
||||
this._queue.splice(index, 1);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Screenshot handler.
|
||||
*
|
||||
* @private
|
||||
* @returns {void}
|
||||
*/
|
||||
async _handleScreenshot() {
|
||||
const imageBitmap = await this._imageCapture.grabFrame();
|
||||
|
||||
this._currentCanvasContext?.drawImage(imageBitmap, 0, 0, this._streamWidth, this._streamHeight);
|
||||
const imageData = this._currentCanvasContext?.getImageData(0, 0, this._streamWidth, this._streamHeight);
|
||||
|
||||
resemble(imageData ?? '')
|
||||
.compareTo(this._storedImageData ?? '')
|
||||
.setReturnEarlyThreshold(PERCENTAGE_LOWER_BOUND)
|
||||
.onComplete(resultData => {
|
||||
if (resultData.rawMisMatchPercentage > PERCENTAGE_LOWER_BOUND) {
|
||||
this._doProcessScreenshot(imageData);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,40 +1,44 @@
|
||||
/**
|
||||
* Percent of pixels that signal if two images should be considered different.
|
||||
*/
|
||||
export const PERCENTAGE_LOWER_BOUND = 5;
|
||||
export const PERCENTAGE_LOWER_BOUND = 4;
|
||||
|
||||
/**
|
||||
* Number of milliseconds that represent how often screenshots should be taken.
|
||||
*/
|
||||
export const POLL_INTERVAL = 4000;
|
||||
export const POLL_INTERVAL = 2000;
|
||||
|
||||
/**
|
||||
* SET_INTERVAL constant is used to set interval and it is set in
|
||||
* SET_TIMEOUT constant is used to set interval and it is set in
|
||||
* the id property of the request.data property. TimeMs property must
|
||||
* also be set. Request.data example:
|
||||
*
|
||||
* {
|
||||
* id: SET_INTERVAL,
|
||||
* id: SET_TIMEOUT,
|
||||
* timeMs: 33
|
||||
* }.
|
||||
*/
|
||||
export const SET_INTERVAL = 1;
|
||||
export const SET_TIMEOUT = 1;
|
||||
|
||||
/**
|
||||
* CLEAR_INTERVAL constant is used to clear the interval and it is set in
|
||||
* CLEAR_TIMEOUT constant is used to clear the interval and it is set in
|
||||
* the id property of the request.data property.
|
||||
*
|
||||
* {
|
||||
* id: CLEAR_INTERVAL
|
||||
* id: CLEAR_TIMEOUT
|
||||
* }.
|
||||
*/
|
||||
export const CLEAR_INTERVAL = 2;
|
||||
export const CLEAR_TIMEOUT = 2;
|
||||
|
||||
/**
|
||||
* INTERVAL_TIMEOUT constant is used as response and it is set in the id property.
|
||||
* TIMEOUT_TICK constant is used as response and it is set in the id property.
|
||||
*
|
||||
* {
|
||||
* id: INTERVAL_TIMEOUT
|
||||
* id: TIMEOUT_TICK
|
||||
* }.
|
||||
*/
|
||||
export const INTERVAL_TIMEOUT = 3;
|
||||
export const TIMEOUT_TICK = 3;
|
||||
|
||||
export const SCREENSHOT_QUEUE_LIMIT = 3;
|
||||
|
||||
export const MAX_FILE_SIZE = 1000000;
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
/**
|
||||
* Helper method used to process screenshots captured by the {@code ScreenshotCaptureEffect}.
|
||||
*
|
||||
* @param {HTMLCanvasElement} canvas - The canvas containing a screenshot to be processed.
|
||||
* @param {Blob} imageBlob - The blob of the screenshot that has to be processed.
|
||||
* @param {Object} options - Custom options required for processing.
|
||||
* @returns {void}
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
export function processScreenshot(canvas, options) { // eslint-disable-line no-unused-vars
|
||||
export async function processScreenshot(imageBlob, options) { // eslint-disable-line no-unused-vars
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1,29 +1,132 @@
|
||||
import pixelmatch from 'pixelmatch';
|
||||
|
||||
import {
|
||||
CLEAR_INTERVAL,
|
||||
INTERVAL_TIMEOUT,
|
||||
SET_INTERVAL
|
||||
CLEAR_TIMEOUT,
|
||||
MAX_FILE_SIZE,
|
||||
PERCENTAGE_LOWER_BOUND,
|
||||
SET_TIMEOUT,
|
||||
TIMEOUT_TICK
|
||||
} from './constants';
|
||||
|
||||
const code = `
|
||||
var timer;
|
||||
|
||||
onmessage = function(request) {
|
||||
switch (request.data.id) {
|
||||
case ${SET_INTERVAL}: {
|
||||
timer = setInterval(() => {
|
||||
postMessage({ id: ${INTERVAL_TIMEOUT} });
|
||||
}, request.data.timeMs);
|
||||
break;
|
||||
}
|
||||
case ${CLEAR_INTERVAL}: {
|
||||
if (timer) {
|
||||
clearInterval(timer);
|
||||
let timer: ReturnType<typeof setTimeout>;
|
||||
const canvas = new OffscreenCanvas(0, 0);
|
||||
const ctx = canvas.getContext('2d');
|
||||
let storedImageData: ImageData | undefined;
|
||||
|
||||
/**
|
||||
* Sends Blob with the screenshot to main thread.
|
||||
*
|
||||
* @param {ImageData} imageData - The image of the screenshot.
|
||||
* @returns {void}
|
||||
*/
|
||||
async function sendBlob(imageData: ImageData) {
|
||||
let imageBlob = await canvas.convertToBlob({ type: 'image/jpeg' });
|
||||
|
||||
if (imageBlob.size > MAX_FILE_SIZE) {
|
||||
const quality = Number((MAX_FILE_SIZE / imageBlob.size).toFixed(2)) * 0.92;
|
||||
|
||||
imageBlob = await canvas.convertToBlob({ type: 'image/jpeg',
|
||||
quality });
|
||||
}
|
||||
|
||||
storedImageData = imageData;
|
||||
|
||||
postMessage({
|
||||
id: TIMEOUT_TICK,
|
||||
imageBlob
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends empty message to main thread.
|
||||
*
|
||||
* @returns {void}
|
||||
*/
|
||||
function sendEmpty() {
|
||||
postMessage({
|
||||
id: TIMEOUT_TICK
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Draws the image bitmap on the canvas and checks the difference percent with the previous image
|
||||
* if there is no previous image the percentage is not calculated.
|
||||
*
|
||||
* @param {ImageBitmap} imageBitmap - The image bitmap that is drawn on canvas.
|
||||
* @returns {void}
|
||||
*/
|
||||
function checkScreenshot(imageBitmap: ImageBitmap) {
|
||||
const { height, width } = imageBitmap;
|
||||
|
||||
if (canvas.width !== width) {
|
||||
canvas.width = width;
|
||||
}
|
||||
|
||||
if (canvas.height !== height) {
|
||||
canvas.height = height;
|
||||
}
|
||||
|
||||
ctx?.drawImage(imageBitmap, 0, 0, width, height);
|
||||
const imageData = ctx?.getImageData(0, 0, width, height);
|
||||
|
||||
imageBitmap.close();
|
||||
|
||||
if (!imageData) {
|
||||
sendEmpty();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (!storedImageData || imageData.data.length !== storedImageData.data.length) {
|
||||
sendBlob(imageData);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
let numOfPixels = 0;
|
||||
|
||||
try {
|
||||
numOfPixels = pixelmatch(
|
||||
imageData.data,
|
||||
storedImageData.data,
|
||||
null,
|
||||
width,
|
||||
height);
|
||||
} catch {
|
||||
sendEmpty();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
const percent = numOfPixels / imageData.data.length * 100;
|
||||
|
||||
if (percent >= PERCENTAGE_LOWER_BOUND) {
|
||||
sendBlob(imageData);
|
||||
} else {
|
||||
sendEmpty();
|
||||
}
|
||||
}
|
||||
|
||||
onmessage = function(request) {
|
||||
switch (request.data.id) {
|
||||
case SET_TIMEOUT: {
|
||||
timer = setTimeout(async () => {
|
||||
const imageBitmap = request.data.imageBitmap;
|
||||
|
||||
if (imageBitmap) {
|
||||
checkScreenshot(imageBitmap);
|
||||
} else {
|
||||
sendEmpty();
|
||||
}
|
||||
break;
|
||||
}, request.data.timeMs);
|
||||
break;
|
||||
}
|
||||
case CLEAR_TIMEOUT: {
|
||||
if (timer) {
|
||||
clearTimeout(timer);
|
||||
}
|
||||
}
|
||||
};
|
||||
`;
|
||||
|
||||
// @ts-ignore
|
||||
export const timerWorkerScript = URL.createObjectURL(new Blob([ code ], { type: 'application/javascript' }));
|
||||
break;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -2,6 +2,7 @@ import { useNavigation } from '@react-navigation/native';
|
||||
import React, { useCallback, useLayoutEffect, useState } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { ScrollView, Text, View, ViewStyle } from 'react-native';
|
||||
import { Edge } from 'react-native-safe-area-context';
|
||||
import { useDispatch, useSelector } from 'react-redux';
|
||||
|
||||
import { IReduxState } from '../../../app/types';
|
||||
@@ -39,6 +40,7 @@ const ProfileView = ({ isInWelcomePage }: {
|
||||
(state: IReduxState) => state['features/base/settings']
|
||||
);
|
||||
const participant = useSelector((state: IReduxState) => getLocalParticipant(state));
|
||||
const { locationURL } = useSelector((state: IReduxState) => state['features/base/connection']);
|
||||
|
||||
const [ displayName, setDisplayName ] = useState(reduxDisplayName);
|
||||
const [ email, setEmail ] = useState(reduxEmail);
|
||||
@@ -103,7 +105,9 @@ const ProfileView = ({ isInWelcomePage }: {
|
||||
useLayoutEffect(() => {
|
||||
navigation.setOptions({
|
||||
headerLeft,
|
||||
headerRight: !isInWelcomePage && headerRight
|
||||
headerRight: !isInWelcomePage
|
||||
&& !locationURL?.hostname?.includes('8x8.vc')
|
||||
&& headerRight
|
||||
});
|
||||
}, [ navigation ]);
|
||||
|
||||
@@ -112,7 +116,7 @@ const ProfileView = ({ isInWelcomePage }: {
|
||||
disableForcedKeyboardDismiss = { true }
|
||||
|
||||
// @ts-ignore
|
||||
safeAreaInsets = { [ !isInWelcomePage && 'bottom', 'left', 'right' ].filter(Boolean) }
|
||||
safeAreaInsets = { [ !isInWelcomePage && 'bottom', 'left', 'right' ].filter(Boolean) as Edge[] }
|
||||
style = { styles.settingsViewContainer }>
|
||||
<ScrollView
|
||||
bounces = { isInWelcomePage }
|
||||
|
||||
@@ -1,18 +1,18 @@
|
||||
import React, { Component } from 'react';
|
||||
import { WithTranslation } from 'react-i18next';
|
||||
import React from 'react';
|
||||
import {
|
||||
ScrollView,
|
||||
Text,
|
||||
TextStyle,
|
||||
TouchableHighlight,
|
||||
View,
|
||||
ViewStyle
|
||||
} from 'react-native';
|
||||
import { Divider } from 'react-native-paper';
|
||||
import { connect } from 'react-redux';
|
||||
import { Edge } from 'react-native-safe-area-context';
|
||||
import { useSelector } from 'react-redux';
|
||||
|
||||
import { IReduxState, IStore } from '../../../app/types';
|
||||
import { IReduxState } from '../../../app/types';
|
||||
import Avatar from '../../../base/avatar/components/Avatar';
|
||||
import { translate } from '../../../base/i18n/functions';
|
||||
import Icon from '../../../base/icons/components/Icon';
|
||||
import { IconArrowRight } from '../../../base/icons/svg';
|
||||
import JitsiScreen from '../../../base/modal/components/JitsiScreen';
|
||||
@@ -30,148 +30,72 @@ import NotificationsSection from './NotificationsSection';
|
||||
import { AVATAR_SIZE } from './constants';
|
||||
import styles from './styles';
|
||||
|
||||
/**
|
||||
* The type of the React {@code Component} props of
|
||||
* {@link SettingsView}.
|
||||
*/
|
||||
interface IProps extends WithTranslation {
|
||||
|
||||
_displayName?: string;
|
||||
interface IProps {
|
||||
|
||||
/**
|
||||
* The ID of the local participant.
|
||||
*/
|
||||
_localParticipantId?: string;
|
||||
|
||||
/**
|
||||
* Flag indicating whether the moderator settings are available.
|
||||
*/
|
||||
_showModeratorSettings: boolean;
|
||||
|
||||
/**
|
||||
* Whether {@link SettingsView} is visible.
|
||||
*
|
||||
* @protected
|
||||
*/
|
||||
_visible?: boolean;
|
||||
|
||||
/**
|
||||
* Redux store dispatch function.
|
||||
*/
|
||||
dispatch: IStore['dispatch'];
|
||||
|
||||
/**
|
||||
* Flag indicating whether the settings is launched inside welcome page.
|
||||
*/
|
||||
isInWelcomePage?: boolean;
|
||||
|
||||
/**
|
||||
* Default prop for navigating between screen components(React Navigation).
|
||||
*/
|
||||
navigation?: Object;
|
||||
isInWelcomePage?: boolean | undefined;
|
||||
}
|
||||
|
||||
/**
|
||||
* The native container rendering the app settings page.
|
||||
*/
|
||||
class SettingsView extends Component<IProps> {
|
||||
const SettingsView = ({ isInWelcomePage }: IProps) => {
|
||||
const { displayName } = useSelector((state: IReduxState) => state['features/base/settings']);
|
||||
const localParticipant = useSelector((state: IReduxState) => getLocalParticipant(state));
|
||||
const showModeratorSettings = useSelector((state: IReduxState) => shouldShowModeratorSettings(state));
|
||||
const { visible } = useSelector((state: IReduxState) => state['features/settings']);
|
||||
|
||||
/**
|
||||
* Opens the profile settings screen.
|
||||
*
|
||||
* @returns {void}
|
||||
*/
|
||||
_onPressProfile() {
|
||||
navigate(screen.settings.profile);
|
||||
const addBottomInset = !isInWelcomePage;
|
||||
const localParticipantId = localParticipant?.id;
|
||||
const scrollBounces = Boolean(isInWelcomePage);
|
||||
|
||||
if (visible !== undefined && !visible) {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements React's {@link Component#render()}, renders the settings page.
|
||||
*
|
||||
* @inheritdoc
|
||||
* @returns {ReactElement}
|
||||
*/
|
||||
render() {
|
||||
const {
|
||||
_displayName
|
||||
} = this.props;
|
||||
return (
|
||||
<JitsiScreen
|
||||
disableForcedKeyboardDismiss = { true }
|
||||
safeAreaInsets = { [ addBottomInset && 'bottom', 'left', 'right' ].filter(Boolean) as Edge[] }
|
||||
style = { styles.settingsViewContainer }>
|
||||
<ScrollView bounces = { scrollBounces }>
|
||||
<View style = { styles.profileContainerWrapper as ViewStyle }>
|
||||
<TouchableHighlight
|
||||
|
||||
const {
|
||||
isInWelcomePage,
|
||||
_showModeratorSettings
|
||||
} = this.props;
|
||||
/* eslint-disable react/jsx-no-bind */
|
||||
onPress = { () => navigate(screen.settings.profile) }>
|
||||
<View
|
||||
style = { styles.profileContainer as ViewStyle }>
|
||||
<Avatar
|
||||
participantId = { localParticipantId }
|
||||
size = { AVATAR_SIZE } />
|
||||
<Text style = { styles.displayName as TextStyle }>
|
||||
{ displayName }
|
||||
</Text>
|
||||
<Icon
|
||||
size = { 24 }
|
||||
src = { IconArrowRight }
|
||||
style = { styles.profileViewArrow } />
|
||||
</View>
|
||||
</TouchableHighlight>
|
||||
</View>
|
||||
<GeneralSection />
|
||||
{ isInWelcomePage && <>
|
||||
<Divider style = { styles.fieldSeparator as ViewStyle } />
|
||||
<ConferenceSection />
|
||||
</> }
|
||||
<Divider style = { styles.fieldSeparator as ViewStyle } />
|
||||
<NotificationsSection />
|
||||
|
||||
const addBottomInset = !isInWelcomePage;
|
||||
const scrollBounces = Boolean(isInWelcomePage);
|
||||
|
||||
return (
|
||||
<JitsiScreen
|
||||
disableForcedKeyboardDismiss = { true }
|
||||
|
||||
// @ts-ignore
|
||||
safeAreaInsets = { [ addBottomInset && 'bottom', 'left', 'right' ].filter(Boolean) }
|
||||
style = { styles.settingsViewContainer }>
|
||||
<ScrollView bounces = { scrollBounces }>
|
||||
<View style = { styles.profileContainerWrapper }>
|
||||
<TouchableHighlight onPress = { this._onPressProfile }>
|
||||
<View
|
||||
style = { styles.profileContainer as ViewStyle }>
|
||||
<Avatar
|
||||
participantId = { this.props._localParticipantId }
|
||||
size = { AVATAR_SIZE } />
|
||||
<Text style = { styles.displayName }>
|
||||
{ _displayName }
|
||||
</Text>
|
||||
<Icon
|
||||
size = { 24 }
|
||||
src = { IconArrowRight }
|
||||
style = { styles.profileViewArrow } />
|
||||
</View>
|
||||
</TouchableHighlight>
|
||||
</View>
|
||||
<GeneralSection />
|
||||
{ isInWelcomePage && <>
|
||||
{/* @ts-ignore */}
|
||||
<Divider style = { styles.fieldSeparator } />
|
||||
<ConferenceSection />
|
||||
{ showModeratorSettings
|
||||
&& <>
|
||||
<Divider style = { styles.fieldSeparator as ViewStyle } />
|
||||
<ModeratorSection />
|
||||
</> }
|
||||
{/* @ts-ignore */}
|
||||
<Divider style = { styles.fieldSeparator } />
|
||||
<NotificationsSection />
|
||||
<Divider style = { styles.fieldSeparator as ViewStyle } />
|
||||
<AdvancedSection />
|
||||
<Divider style = { styles.fieldSeparator as ViewStyle } />
|
||||
<LinksSection />
|
||||
</ScrollView>
|
||||
</JitsiScreen>
|
||||
);
|
||||
};
|
||||
|
||||
{ _showModeratorSettings
|
||||
&& <>
|
||||
{/* @ts-ignore */}
|
||||
<Divider style = { styles.fieldSeparator } />
|
||||
<ModeratorSection />
|
||||
</> }
|
||||
{/* @ts-ignore */}
|
||||
<Divider style = { styles.fieldSeparator } />
|
||||
<AdvancedSection />
|
||||
{/* @ts-ignore */}
|
||||
<Divider style = { styles.fieldSeparator } />
|
||||
<LinksSection />
|
||||
</ScrollView>
|
||||
</JitsiScreen>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Maps part of the Redux state to the props of this component.
|
||||
*
|
||||
* @param {Object} state - The Redux state.
|
||||
* @returns {IProps}
|
||||
*/
|
||||
function _mapStateToProps(state: IReduxState) {
|
||||
const localParticipant = getLocalParticipant(state);
|
||||
|
||||
return {
|
||||
_localParticipantId: localParticipant?.id,
|
||||
_displayName: state['features/base/settings'].displayName,
|
||||
_visible: state['features/settings'].visible,
|
||||
_showModeratorSettings: shouldShowModeratorSettings(state)
|
||||
};
|
||||
}
|
||||
|
||||
export default translate(connect(_mapStateToProps)(SettingsView));
|
||||
export default SettingsView;
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user