Compare commits

...

33 Commits

Author SHA1 Message Date
Robert Pintilii
a22db037c7 ref(TS) Improve TS (#13282)
Remove unnecessary @ts-ignores
Use @ts-expect-error instead of @ts-ignore for external dependencies
2023-05-09 11:05:11 +03:00
Horatiu Muresan
44cc0f7e9a fix(toolbar-buttons) Hide rec and livestream buttons for non-moderators (#13328) 2023-05-08 19:17:01 +03:00
Calinteodor
eafb337cd1 feat(video-menu): native track volume control updates (#13305)
* feat(video-menu/native): added volume slider control for remote participants
2023-05-08 16:33:45 +03:00
damencho
9b3be66287 feat: Updates unsupported desktop to tsx.
Easier to apply branding.
2023-05-05 12:44:33 -05:00
Jaya Allamsetty
1a10a00f74 chore(deps) lib-jitsi-meet@latest
https://github.com/jitsi/lib-jitsi-meet/compare/v1629.0.0+1714bf07...v1631.0.0+f0dd4039
2023-05-05 11:05:50 -04:00
George Politis
a196bc27b8 Update RTCStats.ts
Addresses an issue where the client is sending malformed stats messages to the server.

Introduced in 78ce68160a .
2023-05-05 11:30:04 +02:00
damencho
ac8e4d9828 fix: Fixes notifying vnodes to destroy rooms.
It may happen we receive the disconnect iq after the main room is already destroyed. We now send disconnect on destroy to all vnodes or when receiving disconnect iq per vnode.
2023-05-04 15:10:02 -05:00
damencho
a6ade336b7 fix: Fix measure messages.
This just counts messages and should not block processing messages. Breaks visitor messages coming from s2s and no session params are available.
2023-05-04 15:09:52 -05:00
Hristo Terezov
350443ad34 fix(large-video): Attempt to fix jumping.
When the toolbox is hidden and due to a ReactFocusLock instance the
focus is returned to the toolbox the whole page scrolls to the toolbox
which is positioned outside of the viewport in the bottom.
Then when the animation for displaying the toolbox is started the
scenario looks like the large video is jumping.
Now we don't return the focus from ReactFocusLock to elements which are
not part of the viewport.
2023-05-03 17:31:54 -05:00
Jaya Allamsetty
4c37ef7a2c ref(conference) Simplify track creation. (#13209)
* ref(conference) Simplify track creation.
If gUM fails, we do not have to retry gUM with mic only and camera only constraints. gUM has come a long way and this is not needed anymore.

* ref(conference) Filter tracks that are added to conference.

* squash: Address review comments

* fix(prejoin): Display the exact gUM error in prejoin.

* squash: Address review comments
2023-05-03 18:16:48 -04:00
damencho
3eedc2a49d fix: Restore old config for promoted visitors.
In case a visitor is promoted to main room and want to join an empty breakout room we want to send conference iq to jicofo.
2023-05-03 11:04:40 -05:00
FIKRAT HUSEYNKHANOV
aaeb1a90e5 feat: add toggleWhiteboard to Jitsi API (#13292)
* add toggleWhiteboard to Jitsi API

* eslint recommendations applied

* Prevent to send whiteboard status change notifications for mobile

* Fix code style errors (eslint)

* Requested changes (by mihhu) have been made.

---------

Co-authored-by: Fikret Huseynkhanov <fikret.huseynkhanov@simbrella.com>
2023-05-03 09:52:44 -05:00
Saúl Ibarra Corretgé
ed89f9af20 feat(android) add support for Hearing Aid devices 2023-05-03 09:09:10 +02:00
Saúl Ibarra Corretgé
863ad0b0e6 fix(ios) bump WebRTC version to fix crash
Fix a crash in Metal rendering: 0c9cc42025
2023-05-02 23:12:56 +02:00
Дамян Минков
e2d701a8cc feat: Audio output settings in visitor mode. (#13315)
* feat: Audio output settings in visitor mode.

* squash: Fix lint errors.
2023-05-02 16:06:19 -05:00
damencho
2710273069 feat: Sets meeting id using the connect method. 2023-05-02 12:40:08 -05:00
damencho
07af18e284 fix: Handles disconnect coming from jicofo to destroy visitor rooms.
Drops destroy room for no main participants from vnode. In case of breakout rooms we can end up with nobody in the main room for some time, till they are back from the breakout rooms.
2023-05-02 12:40:08 -05:00
damencho
519e37f567 fix: Drops console warn for logger. 2023-05-02 12:40:08 -05:00
damencho
7cf61eb776 fix: Disables p2p for visitors as it doesn't make sense.
The usecase is breakout rooms when main room is empty, but then one of the participants come back.
2023-05-02 12:40:08 -05:00
Jaya Allamsetty
f81446909c chore(deps) lib-jitsi-meet@latest
https://github.com/jitsi/lib-jitsi-meet/compare/v1626.0.0+a41aa571...v1629.0.0+1714bf07
2023-05-02 10:01:10 -04:00
damencho
b4115593c0 fix: Fix xmldom version to be used. 2023-05-02 08:29:10 -05:00
Hristo Terezov
f8bd8b616e feat(reactions): New button for web. 2023-05-02 08:20:35 -05:00
Hristo Terezov
be55ccd6f4 fix(main-Toolbox): Display the correct buttons.
If some of the buttons from the main toolbar are disabled we were
displaying buttons from the overflow menu in their place.
2023-05-02 08:20:35 -05:00
Horatiu Muresan
e7db18bd80 fix(dial-in) Place PIN on a new line (#13309) 2023-05-02 16:02:51 +03:00
Robert Pintilii
dff41e0fcb fix(chat) Fix horizontal scroll (#13308) 2023-05-02 15:53:30 +03:00
damencho
43be4324af fix: Fix room locking without visitors. 2023-05-02 06:25:37 -05:00
Saúl Ibarra Corretgé
c33baf4c96 fix(ios) avoid rejecting builds in progress in TestFlight 2023-05-02 10:21:30 +02:00
Saúl Ibarra Corretgé
f95a356025 feat(android) bump minimum API level to 24
Some of our dependencies (most notably WebRTC) have dropped it and we
can no longer claim to support API level 23).
2023-05-02 10:19:19 +02:00
Robert Pintilii
1ba7765898 ref(TS) Convert some native components to TS (#13281)
Remove some @ts-ignores
2023-05-02 11:09:38 +03:00
Robert Pintilii
0346fca434 fix(checkbox) Fix misalign when label has multiple lines (#13304) 2023-05-02 10:23:04 +03:00
Robert Pintilii
d267b2499d fix(chat) Fix name overflows chat bubble (#13303)
Revert color change of scroll corner
2023-05-02 10:22:49 +03:00
Дамян Минков
e3e5f1fbfa feat(visitors): Handles locked rooms for visitors. (#13296)
* feat(visitors): Handles locked rooms for visitors.

* squash: Handle locked room password on promotion.

* squash: quotes.

* squash: Renames main_domain to local_domain.

* squash: Renames fmuc_main_domain to main_domain.

Adds required config to point to the main virtual host of the main prosody. There are cases when the first visitor tries to join and there are not main participants as they are in the queue waiting for the vnode connect message and we cannot get dynamically the main domain.

* squash: Fix check for main_domain config.
2023-05-01 17:16:16 -05:00
robertpin
4697192b43 fix(keyboard-a11y) Remove space from click trigger 2023-05-01 16:50:23 +02:00
235 changed files with 1893 additions and 1537 deletions

View File

@@ -19,7 +19,7 @@ buildscript {
ext {
buildToolsVersion = "31.0.0"
compileSdkVersion = 32
minSdkVersion = 23
minSdkVersion = 24
targetSdkVersion = 32
supportLibVersion = "28.0.0"

View File

@@ -45,6 +45,12 @@ class AudioDeviceHandlerGeneric implements
*/
private AudioModeModule module;
/**
* Constant defining a Hearing Aid. Only available on API level >= 28.
* The value of: AudioDeviceInfo.TYPE_HEARING_AID
*/
private static final int TYPE_HEARING_AID = 23;
/**
* Constant defining a USB headset. Only available on API level >= 26.
* The value of: AudioDeviceInfo.TYPE_USB_HEADSET
@@ -85,6 +91,7 @@ class AudioDeviceHandlerGeneric implements
break;
case AudioDeviceInfo.TYPE_WIRED_HEADPHONES:
case AudioDeviceInfo.TYPE_WIRED_HEADSET:
case TYPE_HEARING_AID:
case TYPE_USB_HEADSET:
devices.add(AudioModeModule.DEVICE_HEADPHONES);
break;

View File

@@ -559,7 +559,7 @@ export default {
);
}
let tryCreateLocalTracks;
let tryCreateLocalTracks = Promise.resolve([]);
// On Electron there is no permission prompt for granting permissions. That's why we don't need to
// spend much time displaying the overlay screen. If GUM is not resolved within 15 seconds it will
@@ -600,76 +600,65 @@ export default {
return [];
});
} else if (!requestedAudio && !requestedVideo) {
// Resolve with no tracks
tryCreateLocalTracks = Promise.resolve([]);
} else {
} else if (requestedAudio || requestedVideo) {
tryCreateLocalTracks = createLocalTracksF({
devices: initialDevices,
timeout,
firePermissionPromptIsShownEvent: true
})
.catch(err => {
if (requestedAudio && requestedVideo) {
// Try audio only...
errors.audioAndVideoError = err;
if (err.name === JitsiTrackErrors.TIMEOUT && !browser.isElectron()) {
// In this case we expect that the permission prompt is still visible. There is no point of
// executing GUM with different source. Also at the time of writing the following
// inconsistency have been noticed in some browsers - if the permissions prompt is visible
// and another GUM is executed the prompt does not change its content but if the user
// clicks allow the user action isassociated with the latest GUM call.
errors.audioOnlyError = err;
errors.videoOnlyError = err;
return [];
}
return createLocalTracksF(audioOptions);
} else if (requestedAudio && !requestedVideo) {
errors.audioOnlyError = err;
return [];
} else if (requestedVideo && !requestedAudio) {
errors.videoOnlyError = err;
return [];
}
logger.error('Should never happen');
})
.catch(err => {
// Log this just in case...
if (!requestedAudio) {
logger.error('The impossible just happened', err);
}
errors.audioOnlyError = err;
// Try video only...
return requestedVideo
? createLocalTracksF({
devices: [ MEDIA_TYPE.VIDEO ],
firePermissionPromptIsShownEvent: true
})
: [];
})
.catch(err => {
// Log this just in case...
if (!requestedVideo) {
logger.error('The impossible just happened', err);
}
errors.videoOnlyError = err;
.catch(async error => {
if (error.name === JitsiTrackErrors.TIMEOUT && !browser.isElectron()) {
errors.audioAndVideoError = error;
return [];
}
// Retry with separate gUM calls.
const gUMPromises = [];
const tracks = [];
if (requestedAudio) {
gUMPromises.push(createLocalTracksF(audioOptions));
}
if (requestedVideo) {
gUMPromises.push(createLocalTracksF({
devices: [ MEDIA_TYPE.VIDEO ],
timeout,
firePermissionPromptIsShownEvent: true
}));
}
const results = await Promise.allSettled(gUMPromises);
let errorMsg;
results.forEach((result, idx) => {
if (result.status === 'fulfilled') {
tracks.push(result.value[0]);
} else {
errorMsg = result.reason;
const isAudio = idx === 0;
logger.error(`${isAudio ? 'Audio' : 'Video'} track creation failed with error ${errorMsg}`);
if (isAudio) {
errors.audioOnlyError = errorMsg;
} else {
errors.videoOnlyError = errorMsg;
}
}
});
if (errors.audioOnlyError && errors.videoOnlyError) {
errors.audioAndVideoError = errorMsg;
}
return tracks;
});
}
// Hide the permissions prompt/overlay as soon as the tracks are
// created. Don't wait for the connection to be made, since in some
// cases, when auth is required, for instance, that won't happen until
// the user inputs their credentials, but the dialog would be
// overshadowed by the overlay.
// Hide the permissions prompt/overlay as soon as the tracks are created. Don't wait for the connection to
// be established, as in some cases like when auth is required, connection won't be established until the user
// inputs their credentials, but the dialog would be overshadowed by the overlay.
tryCreateLocalTracks.then(tracks => {
APP.store.dispatch(mediaPermissionPromptVisibilityChanged(false));
@@ -810,43 +799,51 @@ export default {
const initialOptions = {
startAudioOnly: config.startAudioOnly,
startScreenSharing: config.startScreenSharing,
startWithAudioMuted: getStartWithAudioMuted(state)
|| isUserInteractionRequiredForUnmute(state),
startWithVideoMuted: getStartWithVideoMuted(state)
|| isUserInteractionRequiredForUnmute(state)
startWithAudioMuted: getStartWithAudioMuted(state) || isUserInteractionRequiredForUnmute(state),
startWithVideoMuted: getStartWithVideoMuted(state) || isUserInteractionRequiredForUnmute(state)
};
this.roomName = roomName;
try {
// Initialize the device list first. This way, when creating tracks
// based on preferred devices, loose label matching can be done in
// cases where the exact ID match is no longer available, such as
// when the camera device has switched USB ports.
// when in startSilent mode we want to start with audio muted
// Initialize the device list first. This way, when creating tracks based on preferred devices, loose label
// matching can be done in cases where the exact ID match is no longer available, such as -
// 1. When the camera device has switched USB ports.
// 2. When in startSilent mode we want to start with audio muted
await this._initDeviceList();
} catch (error) {
logger.warn('initial device list initialization failed', error);
}
const handleStartAudioMuted = (options, tracks) => {
if (options.startWithAudioMuted) {
// Filter out the local tracks based on various config options, i.e., when user joins muted or is muted by
// focus. However, audio track will always be created even though it is not added to the conference since we
// want audio related features (noisy mic, talk while muted, etc.) to work even if the mic is muted.
const handleInitialTracks = (options, tracks) => {
let localTracks = tracks;
// No local tracks are added when user joins as a visitor.
if (iAmVisitor(state)) {
return [];
}
if (options.startWithAudioMuted || room?.isStartAudioMuted()) {
// Always add the track on Safari because of a known issue where audio playout doesn't happen
// if the user joins audio and video muted, i.e., if there is no local media capture.
if (browser.isWebKitBased()) {
this.muteAudio(true, true);
} else {
return tracks.filter(track => track.getType() !== MEDIA_TYPE.AUDIO);
localTracks = localTracks.filter(track => track.getType() !== MEDIA_TYPE.AUDIO);
}
}
if (room?.isStartVideoMuted()) {
localTracks = localTracks.filter(track => track.getType() !== MEDIA_TYPE.VIDEO);
}
return tracks;
return localTracks;
};
if (isPrejoinPageVisible(state)) {
_connectionPromise = connect(roomName).then(c => {
// we want to initialize it early, in case of errors to be able
// to gather logs
// We want to initialize it early, in case of errors to be able to gather logs.
APP.connection = c;
return c;
@@ -859,48 +856,28 @@ export default {
APP.store.dispatch(makePrecallTest(this._getConferenceOptions()));
const { tryCreateLocalTracks, errors } = this.createInitialLocalTracks(initialOptions);
const tracks = await tryCreateLocalTracks;
const localTracks = await tryCreateLocalTracks;
// Initialize device list a second time to ensure device labels
// get populated in case of an initial gUM acceptance; otherwise
// they may remain as empty strings.
// Initialize device list a second time to ensure device labels get populated in case of an initial gUM
// acceptance; otherwise they may remain as empty strings.
this._initDeviceList(true);
if (isPrejoinPageVisible(state)) {
return APP.store.dispatch(initPrejoin(tracks, errors));
return APP.store.dispatch(initPrejoin(localTracks, errors));
}
logger.debug('Prejoin screen no longer displayed at the time when tracks were created');
this._displayErrorsForCreateInitialLocalTracks(errors);
let localTracks = handleStartAudioMuted(initialOptions, tracks);
// In case where gUM is slow and resolves after the startAudio/VideoMuted coming from jicofo, we can be
// join unmuted even though jicofo had instruct us to mute, so let's respect that before passing the tracks
if (!browser.isWebKitBased()) {
if (room?.isStartAudioMuted()) {
localTracks = localTracks.filter(track => track.getType() !== MEDIA_TYPE.AUDIO);
}
}
if (room?.isStartVideoMuted()) {
localTracks = localTracks.filter(track => track.getType() !== MEDIA_TYPE.VIDEO);
}
// Do not add the tracks if the user has joined the call as a visitor.
if (iAmVisitor(state)) {
return Promise.resolve();
}
return this._setLocalAudioVideoStreams(localTracks);
return this._setLocalAudioVideoStreams(handleInitialTracks(initialOptions, localTracks));
}
const [ tracks, con ] = await this.createInitialLocalTracksAndConnect(roomName, initialOptions);
this._initDeviceList(true);
return this.startConference(con, handleStartAudioMuted(initialOptions, tracks));
return this.startConference(con, handleInitialTracks(initialOptions, tracks));
},
/**
@@ -1073,7 +1050,7 @@ export default {
*/
muteVideo(mute, showUI = true) {
if (this.videoSwitchInProgress) {
console.warn('muteVideo - unable to perform operations while video switch is in progress');
logger.warn('muteVideo - unable to perform operations while video switch is in progress');
return;
}

View File

@@ -74,10 +74,6 @@
a:active {
color: black;
}
&::-webkit-scrollbar-corner {
background: #3a3a3a;
}
}

View File

@@ -134,7 +134,7 @@ PODS:
- AppAuth/Core (~> 1.6)
- GTMSessionFetcher/Core (< 3.0, >= 1.5)
- GTMSessionFetcher/Core (2.3.0)
- JitsiWebRTC (111.0.1)
- JitsiWebRTC (111.0.2)
- libwebp (1.2.4):
- libwebp/demux (= 1.2.4)
- libwebp/mux (= 1.2.4)
@@ -725,7 +725,7 @@ SPEC CHECKSUMS:
GoogleUtilities: 9aa0ad5a7bc171f8bae016300bfcfa3fb8425749
GTMAppAuth: 0ff230db599948a9ad7470ca667337803b3fc4dd
GTMSessionFetcher: 3a63d75eecd6aa32c2fc79f578064e1214dfdec2
JitsiWebRTC: 9619c1f71cc16eeca76df68aa2d213c6d63274a8
JitsiWebRTC: 80f62908fcf2a1160e0d14b584323fb6e6be630b
libwebp: f62cb61d0a484ba548448a4bd52aabf150ff6eef
nanopb: a0ba3315591a9ae0a16a309ee504766e90db0c96
ObjectiveDropboxOfficial: fe206ce8c0bc49976c249d472db7fdbc53ebbd53

View File

@@ -98,7 +98,6 @@ platform :ios do
demo_account_required: false,
distribute_external: true,
groups: ENV["JITSI_BETA_TESTING_GROUPS"],
reject_build_waiting_for_review: true,
uses_non_exempt_encryption: false
)

View File

@@ -1150,6 +1150,7 @@
"privateMessage": "Send private message",
"profile": "Edit your profile",
"raiseHand": "Raise your hand",
"reactions": "Reactions",
"reactionsMenu": "Reactions menu",
"recording": "Toggle recording",
"remoteMute": "Mute participant",
@@ -1247,6 +1248,7 @@
"reactionLike": "Send thumbs up reaction",
"reactionSilence": "Send silence reaction",
"reactionSurprised": "Send surprised reaction",
"reactions": "Reactions",
"security": "Security options",
"selectBackground": "Select background",
"shareRoom": "Invite someone",

View File

@@ -113,6 +113,8 @@ import { isAudioMuteButtonDisabled } from '../../react/features/toolbox/function
import { setTileView, toggleTileView } from '../../react/features/video-layout/actions.any';
import { muteAllParticipants } from '../../react/features/video-menu/actions';
import { setVideoQuality } from '../../react/features/video-quality/actions';
import { toggleWhiteboard } from '../../react/features/whiteboard/actions.any';
import { WhiteboardStatus } from '../../react/features/whiteboard/types';
import { getJitsiMeetTransport } from '../transport';
import {
@@ -833,6 +835,9 @@ function initCommands() {
} else {
logger.error(' End Conference not supported');
}
},
'toggle-whiteboard': () => {
APP.store.dispatch(toggleWhiteboard());
}
};
transport.on('event', ({ data, name }) => {
@@ -2014,6 +2019,20 @@ class API {
});
}
/**
* Notify external application (if API is enabled) if whiteboard state is
* changed.
*
* @param {WhiteboardStatus} status - The new whiteboard status.
* @returns {void}
*/
notifyWhiteboardStatusChanged(status: WhiteboardStatus) {
this._sendEvent({
name: 'whiteboard-status-changed',
status
});
}
/**
* Disposes the allocated resources.
*

View File

@@ -90,7 +90,8 @@ const commands = {
toggleSubtitles: 'toggle-subtitles',
toggleTileView: 'toggle-tile-view',
toggleVirtualBackgroundDialog: 'toggle-virtual-background',
toggleVideo: 'toggle-video'
toggleVideo: 'toggle-video',
toggleWhiteboard: 'toggle-whiteboard'
};
/**
@@ -154,7 +155,8 @@ const events = {
'subject-change': 'subjectChange',
'suspend-detected': 'suspendDetected',
'tile-view-changed': 'tileViewChanged',
'toolbar-button-clicked': 'toolbarButtonClicked'
'toolbar-button-clicked': 'toolbarButtonClicked',
'whiteboard-status-changed': 'whiteboardStatusChanged'
};
/**

153
package-lock.json generated
View File

@@ -60,7 +60,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/v1626.0.0+a41aa571/lib-jitsi-meet.tgz",
"lib-jitsi-meet": "https://github.com/jitsi/lib-jitsi-meet/releases/download/v1631.0.0+f0dd4039/lib-jitsi-meet.tgz",
"lodash": "4.17.21",
"moment": "2.29.4",
"moment-duration-format": "2.2.2",
@@ -71,7 +71,7 @@
"react": "17.0.2",
"react-dom": "17.0.2",
"react-emoji-render": "1.2.4",
"react-focus-lock": "2.5.1",
"react-focus-lock": "2.9.4",
"react-i18next": "10.11.4",
"react-linkify": "1.0.0-alpha",
"react-native": "0.68.6",
@@ -10508,9 +10508,9 @@
}
},
"node_modules/focus-lock": {
"version": "0.9.2",
"resolved": "https://registry.npmjs.org/focus-lock/-/focus-lock-0.9.2.tgz",
"integrity": "sha512-YtHxjX7a0IC0ZACL5wsX8QdncXofWpGPNoVMuI/nZUrPGp6LmNI6+D5j0pPj+v8Kw5EpweA+T5yImK0rnWf7oQ==",
"version": "0.11.6",
"resolved": "https://registry.npmjs.org/focus-lock/-/focus-lock-0.11.6.tgz",
"integrity": "sha512-KSuV3ur4gf2KqMNoZx3nXNVhqCkn42GuTYCX4tXPEwf0MjpFQmNMiN6m7dXaUXgIoivL6/65agoUMg4RLS0Vbg==",
"dependencies": {
"tslib": "^2.0.3"
},
@@ -12739,8 +12739,8 @@
},
"node_modules/lib-jitsi-meet": {
"version": "0.0.0",
"resolved": "https://github.com/jitsi/lib-jitsi-meet/releases/download/v1626.0.0+a41aa571/lib-jitsi-meet.tgz",
"integrity": "sha512-0LK5EMCvtsAEQkjkrWzyniTl8BKtshAZxI3e9hGnA/RVDuULLXre7GEWd2zCP3tCfdxclkhqt7skQpfNhCTdqg==",
"resolved": "https://github.com/jitsi/lib-jitsi-meet/releases/download/v1631.0.0+f0dd4039/lib-jitsi-meet.tgz",
"integrity": "sha512-as7vkc9NvpXhNC2vkvrRnxZiPs9Uc4PXbphBXlh5h8LTNtvnMEPWH9FSsBzKukU/2ITIPOhCEJqhCIurkZfPKg==",
"hasInstallScript": true,
"license": "Apache-2.0",
"dependencies": {
@@ -15415,14 +15415,14 @@
}
},
"node_modules/react-clientside-effect": {
"version": "1.2.5",
"resolved": "https://registry.npmjs.org/react-clientside-effect/-/react-clientside-effect-1.2.5.tgz",
"integrity": "sha512-2bL8qFW1TGBHozGGbVeyvnggRpMjibeZM2536AKNENLECutp2yfs44IL8Hmpn8qjFQ2K7A9PnYf3vc7aQq/cPA==",
"version": "1.2.6",
"resolved": "https://registry.npmjs.org/react-clientside-effect/-/react-clientside-effect-1.2.6.tgz",
"integrity": "sha512-XGGGRQAKY+q25Lz9a/4EPqom7WRjz3z9R2k4jhVKA/puQFH/5Nt27vFZYql4m4NVNdUvX8PS3O7r/Zzm7cjUlg==",
"dependencies": {
"@babel/runtime": "^7.12.13"
},
"peerDependencies": {
"react": "^15.3.0 || ^16.0.0 || ^17.0.0"
"react": "^15.3.0 || ^16.0.0 || ^17.0.0 || ^18.0.0"
}
},
"node_modules/react-devtools-core": {
@@ -15484,19 +15484,25 @@
}
},
"node_modules/react-focus-lock": {
"version": "2.5.1",
"resolved": "https://registry.npmjs.org/react-focus-lock/-/react-focus-lock-2.5.1.tgz",
"integrity": "sha512-gOToRZKVEymGEjFaTRUKgJsdYQrNosoiK7yZnXnnd8bYew4vMzk3Rxb0Q4nyrGwsFuUmgQiSAulQirA0J+v4hA==",
"version": "2.9.4",
"resolved": "https://registry.npmjs.org/react-focus-lock/-/react-focus-lock-2.9.4.tgz",
"integrity": "sha512-7pEdXyMseqm3kVjhdVH18sovparAzLg5h6WvIx7/Ck3ekjhrrDMEegHSa3swwC8wgfdd7DIdUVRGeiHT9/7Sgg==",
"dependencies": {
"@babel/runtime": "^7.0.0",
"focus-lock": "^0.9.1",
"focus-lock": "^0.11.6",
"prop-types": "^15.6.2",
"react-clientside-effect": "^1.2.2",
"use-callback-ref": "^1.2.1",
"use-sidecar": "^1.0.1"
"react-clientside-effect": "^1.2.6",
"use-callback-ref": "^1.3.0",
"use-sidecar": "^1.1.2"
},
"peerDependencies": {
"react": "^16.8.0 || ^17.0.0"
"@types/react": "^16.8.0 || ^17.0.0 || ^18.0.0",
"react": "^16.8.0 || ^17.0.0 || ^18.0.0"
},
"peerDependenciesMeta": {
"@types/react": {
"optional": true
}
}
},
"node_modules/react-freeze": {
@@ -17627,15 +17633,6 @@
"ws": "^8.5.0"
}
},
"node_modules/strophe.js/node_modules/@xmldom/xmldom": {
"version": "0.8.2",
"resolved": "https://registry.npmjs.org/@xmldom/xmldom/-/xmldom-0.8.2.tgz",
"integrity": "sha512-+R0juSseERyoPvnBQ/cZih6bpF7IpCXlWbHRoCRzYzqpz6gWHOgf8o4MOEf6KBVuOyqU+gCNLkCWVIJAro8XyQ==",
"optional": true,
"engines": {
"node": ">=10.0.0"
}
},
"node_modules/strophe.js/node_modules/ws": {
"version": "8.13.0",
"resolved": "https://registry.npmjs.org/ws/-/ws-8.13.0.tgz",
@@ -18572,15 +18569,18 @@
}
},
"node_modules/use-callback-ref": {
"version": "1.2.5",
"resolved": "https://registry.npmjs.org/use-callback-ref/-/use-callback-ref-1.2.5.tgz",
"integrity": "sha512-gN3vgMISAgacF7sqsLPByqoePooY3n2emTH59Ur5d/M8eg4WTWu1xp8i8DHjohftIyEx0S08RiYxbffr4j8Peg==",
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/use-callback-ref/-/use-callback-ref-1.3.0.tgz",
"integrity": "sha512-3FT9PRuRdbB9HfXhEq35u4oZkvpJ5kuYbpqhCfmiZyReuRgpnhDlbr2ZEnnuS0RrJAPn6l23xjFg9kpDM+Ms7w==",
"dependencies": {
"tslib": "^2.0.0"
},
"engines": {
"node": ">=8.5.0"
"node": ">=10"
},
"peerDependencies": {
"@types/react": "^16.8.0 || ^17.0.0",
"react": "^16.8.0 || ^17.0.0"
"@types/react": "^16.8.0 || ^17.0.0 || ^18.0.0",
"react": "^16.8.0 || ^17.0.0 || ^18.0.0"
},
"peerDependenciesMeta": {
"@types/react": {
@@ -18639,25 +18639,26 @@
"integrity": "sha512-HtHatS2U4/h32NlkhupDsPlrbiD27gSH5swBdtXbCAlc6pfOFzaj0FehW/FO12rx8j2Vy4/lJScCiJyM01E+bQ=="
},
"node_modules/use-sidecar": {
"version": "1.0.5",
"resolved": "https://registry.npmjs.org/use-sidecar/-/use-sidecar-1.0.5.tgz",
"integrity": "sha512-k9jnrjYNwN6xYLj1iaGhonDghfvmeTmYjAiGvOr7clwKfPjMXJf4/HOr7oT5tJwYafgp2tG2l3eZEOfoELiMcA==",
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/use-sidecar/-/use-sidecar-1.1.2.tgz",
"integrity": "sha512-epTbsLuzZ7lPClpz2TyryBfztm7m+28DlEv2ZCQ3MDr5ssiwyOwGH/e5F9CkfWjJ1t4clvI58yF822/GUkjjhw==",
"dependencies": {
"detect-node-es": "^1.1.0",
"tslib": "^1.9.3"
"tslib": "^2.0.0"
},
"engines": {
"node": ">=8.5.0"
"node": ">=10"
},
"peerDependencies": {
"react": "^16.8.0 || ^17.0.0"
"@types/react": "^16.9.0 || ^17.0.0 || ^18.0.0",
"react": "^16.8.0 || ^17.0.0 || ^18.0.0"
},
"peerDependenciesMeta": {
"@types/react": {
"optional": true
}
}
},
"node_modules/use-sidecar/node_modules/tslib": {
"version": "1.14.1",
"resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz",
"integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg=="
},
"node_modules/use-subscription": {
"version": "1.5.1",
"resolved": "https://registry.npmjs.org/use-subscription/-/use-subscription-1.5.1.tgz",
@@ -27450,9 +27451,9 @@
"integrity": "sha512-1gIBiWJNR0tKUNv8gZuk7l9rVX06OuLzY9AoGio7y/JT4V1IZErEMEq2TJS+PFcw/y0RshZ1J/27VfK1UQzYVg=="
},
"focus-lock": {
"version": "0.9.2",
"resolved": "https://registry.npmjs.org/focus-lock/-/focus-lock-0.9.2.tgz",
"integrity": "sha512-YtHxjX7a0IC0ZACL5wsX8QdncXofWpGPNoVMuI/nZUrPGp6LmNI6+D5j0pPj+v8Kw5EpweA+T5yImK0rnWf7oQ==",
"version": "0.11.6",
"resolved": "https://registry.npmjs.org/focus-lock/-/focus-lock-0.11.6.tgz",
"integrity": "sha512-KSuV3ur4gf2KqMNoZx3nXNVhqCkn42GuTYCX4tXPEwf0MjpFQmNMiN6m7dXaUXgIoivL6/65agoUMg4RLS0Vbg==",
"requires": {
"tslib": "^2.0.3"
}
@@ -29117,8 +29118,8 @@
}
},
"lib-jitsi-meet": {
"version": "https://github.com/jitsi/lib-jitsi-meet/releases/download/v1626.0.0+a41aa571/lib-jitsi-meet.tgz",
"integrity": "sha512-0LK5EMCvtsAEQkjkrWzyniTl8BKtshAZxI3e9hGnA/RVDuULLXre7GEWd2zCP3tCfdxclkhqt7skQpfNhCTdqg==",
"version": "https://github.com/jitsi/lib-jitsi-meet/releases/download/v1631.0.0+f0dd4039/lib-jitsi-meet.tgz",
"integrity": "sha512-as7vkc9NvpXhNC2vkvrRnxZiPs9Uc4PXbphBXlh5h8LTNtvnMEPWH9FSsBzKukU/2ITIPOhCEJqhCIurkZfPKg==",
"requires": {
"@jitsi/js-utils": "2.0.0",
"@jitsi/logger": "2.0.0",
@@ -31170,9 +31171,9 @@
}
},
"react-clientside-effect": {
"version": "1.2.5",
"resolved": "https://registry.npmjs.org/react-clientside-effect/-/react-clientside-effect-1.2.5.tgz",
"integrity": "sha512-2bL8qFW1TGBHozGGbVeyvnggRpMjibeZM2536AKNENLECutp2yfs44IL8Hmpn8qjFQ2K7A9PnYf3vc7aQq/cPA==",
"version": "1.2.6",
"resolved": "https://registry.npmjs.org/react-clientside-effect/-/react-clientside-effect-1.2.6.tgz",
"integrity": "sha512-XGGGRQAKY+q25Lz9a/4EPqom7WRjz3z9R2k4jhVKA/puQFH/5Nt27vFZYql4m4NVNdUvX8PS3O7r/Zzm7cjUlg==",
"requires": {
"@babel/runtime": "^7.12.13"
}
@@ -31216,16 +31217,16 @@
}
},
"react-focus-lock": {
"version": "2.5.1",
"resolved": "https://registry.npmjs.org/react-focus-lock/-/react-focus-lock-2.5.1.tgz",
"integrity": "sha512-gOToRZKVEymGEjFaTRUKgJsdYQrNosoiK7yZnXnnd8bYew4vMzk3Rxb0Q4nyrGwsFuUmgQiSAulQirA0J+v4hA==",
"version": "2.9.4",
"resolved": "https://registry.npmjs.org/react-focus-lock/-/react-focus-lock-2.9.4.tgz",
"integrity": "sha512-7pEdXyMseqm3kVjhdVH18sovparAzLg5h6WvIx7/Ck3ekjhrrDMEegHSa3swwC8wgfdd7DIdUVRGeiHT9/7Sgg==",
"requires": {
"@babel/runtime": "^7.0.0",
"focus-lock": "^0.9.1",
"focus-lock": "^0.11.6",
"prop-types": "^15.6.2",
"react-clientside-effect": "^1.2.2",
"use-callback-ref": "^1.2.1",
"use-sidecar": "^1.0.1"
"react-clientside-effect": "^1.2.6",
"use-callback-ref": "^1.3.0",
"use-sidecar": "^1.1.2"
}
},
"react-freeze": {
@@ -32849,18 +32850,12 @@
"resolved": "https://registry.npmjs.org/strophe.js/-/strophe.js-1.5.0.tgz",
"integrity": "sha512-H5tE/tZxPR5xP3jhXyQwsjnMSwQMf7vrn9r1OkufTApyGHYe8WjzhsfxtL3AFhVu7vFjXPPZBrmUOTm1ccYgOA==",
"requires": {
"@xmldom/xmldom": "0.8.2",
"@xmldom/xmldom": "0.8.7",
"abab": "^2.0.3",
"karma-rollup-preprocessor": "^7.0.8",
"ws": "^8.5.0"
},
"dependencies": {
"@xmldom/xmldom": {
"version": "0.8.2",
"resolved": "https://registry.npmjs.org/@xmldom/xmldom/-/xmldom-0.8.2.tgz",
"integrity": "sha512-+R0juSseERyoPvnBQ/cZih6bpF7IpCXlWbHRoCRzYzqpz6gWHOgf8o4MOEf6KBVuOyqU+gCNLkCWVIJAro8XyQ==",
"optional": true
},
"ws": {
"version": "8.13.0",
"resolved": "https://registry.npmjs.org/ws/-/ws-8.13.0.tgz",
@@ -33536,9 +33531,12 @@
"integrity": "sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ=="
},
"use-callback-ref": {
"version": "1.2.5",
"resolved": "https://registry.npmjs.org/use-callback-ref/-/use-callback-ref-1.2.5.tgz",
"integrity": "sha512-gN3vgMISAgacF7sqsLPByqoePooY3n2emTH59Ur5d/M8eg4WTWu1xp8i8DHjohftIyEx0S08RiYxbffr4j8Peg=="
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/use-callback-ref/-/use-callback-ref-1.3.0.tgz",
"integrity": "sha512-3FT9PRuRdbB9HfXhEq35u4oZkvpJ5kuYbpqhCfmiZyReuRgpnhDlbr2ZEnnuS0RrJAPn6l23xjFg9kpDM+Ms7w==",
"requires": {
"tslib": "^2.0.0"
}
},
"use-composed-ref": {
"version": "1.2.1",
@@ -33569,19 +33567,12 @@
"integrity": "sha512-HtHatS2U4/h32NlkhupDsPlrbiD27gSH5swBdtXbCAlc6pfOFzaj0FehW/FO12rx8j2Vy4/lJScCiJyM01E+bQ=="
},
"use-sidecar": {
"version": "1.0.5",
"resolved": "https://registry.npmjs.org/use-sidecar/-/use-sidecar-1.0.5.tgz",
"integrity": "sha512-k9jnrjYNwN6xYLj1iaGhonDghfvmeTmYjAiGvOr7clwKfPjMXJf4/HOr7oT5tJwYafgp2tG2l3eZEOfoELiMcA==",
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/use-sidecar/-/use-sidecar-1.1.2.tgz",
"integrity": "sha512-epTbsLuzZ7lPClpz2TyryBfztm7m+28DlEv2ZCQ3MDr5ssiwyOwGH/e5F9CkfWjJ1t4clvI58yF822/GUkjjhw==",
"requires": {
"detect-node-es": "^1.1.0",
"tslib": "^1.9.3"
},
"dependencies": {
"tslib": {
"version": "1.14.1",
"resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz",
"integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg=="
}
"tslib": "^2.0.0"
}
},
"use-subscription": {

View File

@@ -65,7 +65,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/v1626.0.0+a41aa571/lib-jitsi-meet.tgz",
"lib-jitsi-meet": "https://github.com/jitsi/lib-jitsi-meet/releases/download/v1631.0.0+f0dd4039/lib-jitsi-meet.tgz",
"lodash": "4.17.21",
"moment": "2.29.4",
"moment-duration-format": "2.2.2",
@@ -76,7 +76,7 @@
"react": "17.0.2",
"react-dom": "17.0.2",
"react-emoji-render": "1.2.4",
"react-focus-lock": "2.5.1",
"react-focus-lock": "2.9.4",
"react-i18next": "10.11.4",
"react-linkify": "1.0.0-alpha",
"react-native": "0.68.6",
@@ -179,7 +179,7 @@
"webpack-dev-server": "4.7.3"
},
"overrides": {
"strophe.js@1.6.0": {
"strophe.js@1.5.0": {
"@xmldom/xmldom": "0.8.7"
}
},

View File

@@ -1,4 +1,3 @@
/* eslint-disable lines-around-comment */
import { setRoom } from '../base/conference/actions';
import {
configWillLoad,
@@ -20,14 +19,11 @@ import {
parseURIString,
toURLString
} from '../base/util/uri';
// @ts-ignore
import { isPrejoinPageEnabled } from '../mobile/navigation/functions';
import {
goBackToRoot,
navigateRoot
// @ts-ignore
} from '../mobile/navigation/rootNavigationContainerRef';
// @ts-ignore
import { screen } from '../mobile/navigation/routes';
import { clearNotifications } from '../notifications/actions';
@@ -143,7 +139,6 @@ export function appNavigate(uri?: string, options: IReloadNowOptions = {}) {
dispatch(createDesiredLocalTracks());
dispatch(clearNotifications());
// @ts-ignore
const { hidePrejoin } = options;
if (!hidePrejoin && isPrejoinPageEnabled(getState())) {

View File

@@ -5,8 +5,6 @@ import { IStateful } from '../base/app/types';
import { isRoomValid } from '../base/conference/functions';
import { isSupportedBrowser } from '../base/environment/environment';
import { toState } from '../base/redux/functions';
// eslint-disable-next-line lines-around-comment
// @ts-ignore
import Conference from '../conference/components/web/Conference';
import { getDeepLinkingPage } from '../deep-linking/functions';
import UnsupportedDesktopBrowser from '../unsupported-browser/components/UnsupportedDesktopBrowser';

View File

@@ -27,13 +27,13 @@ export function cancelLogin() {
// a reaction to CONNECTION_FAILED). Since the
// app/user is going to navigate to WelcomePage, the SDK
// clients/consumers need an event.
const { error, passwordRequired }
const { error = { recoverable: undefined }, passwordRequired }
= getState()['features/base/connection'];
passwordRequired
&& dispatch(
connectionFailed(
passwordRequired, // @ts-ignore
passwordRequired,
set(error, 'recoverable', false) as any));
};
}

View File

@@ -1,4 +1,2 @@
export { default as LoginDialog } from './native/LoginDialog';
// eslint-disable-next-line lines-around-comment
// @ts-ignore
export { default as WaitForOwnerDialog } from './native/WaitForOwnerDialog';

View File

@@ -24,7 +24,7 @@ import {
openLoginDialog,
openWaitForOwnerDialog,
stopWaitForOwner,
waitForOwner } from './actions.native'; // @ts-ignore
waitForOwner } from './actions.native';
import { LoginDialog, WaitForOwnerDialog } from './components';
/**

View File

@@ -300,7 +300,8 @@ export function getVisitorOptions(stateful: IStateful, params: Array<string>) {
if (!vnode) {
// this is redirecting back to main, lets restore config
// no point of updating disableFocus, we can skip the initial iq to jicofo
// not updating disableFocus, as if the room capacity is full the promotion to the main room will fail
// and the visitor will be redirected back to a vnode from jicofo
if (config.oldConfig && username) {
return {
hosts: {
@@ -310,6 +311,7 @@ export function getVisitorOptions(stateful: IStateful, params: Array<string>) {
focusUserJid: focusJid,
disableLocalStats: false,
bosh: config.oldConfig.bosh && appendURLParam(config.oldConfig.bosh, 'customusername', username),
p2p: config.oldConfig.p2p,
websocket: config.oldConfig.websocket
&& appendURLParam(config.oldConfig.websocket, 'customusername', username),
oldConfig: undefined // clears it up
@@ -326,6 +328,7 @@ export function getVisitorOptions(stateful: IStateful, params: Array<string>) {
},
focusUserJid: config.focusUserJid,
bosh: config.bosh,
p2p: config.p2p,
websocket: config.websocket
};
@@ -341,6 +344,10 @@ export function getVisitorOptions(stateful: IStateful, params: Array<string>) {
disableFocus: true, // This flag disables sending the initial conference request
disableLocalStats: true,
bosh: config.bosh && appendURLParam(config.bosh, 'vnode', vnode),
p2p: {
...config.p2p,
enabled: false
},
websocket: config.websocket && appendURLParam(config.websocket, 'vnode', vnode)
};
}

View File

@@ -289,6 +289,12 @@ function _conferenceJoined({ dispatch, getState }: IStore, next: Function, actio
dispatch(conferenceWillLeave(conference));
};
if (!iAmVisitor(getState())) {
// if a visitor is promoted back to main room and want to join an empty breakout room
// we need to send iq to jicofo, so it can join/create the breakout room
dispatch(overwriteConfig({ disableFocus: false }));
}
// @ts-ignore
window.addEventListener(disableBeforeUnloadHandlers ? 'unload' : 'beforeunload', beforeUnloadHandler);

View File

@@ -1,4 +1,4 @@
// @ts-ignore
// @ts-expect-error
import { jitsiLocalStorage } from '@jitsi/js-utils';
import { IStore } from '../../app/types';

View File

@@ -18,6 +18,7 @@ type ToolbarButtons = 'camera' |
'participants-pane' |
'profile' |
'raisehand' |
'reactions' |
'recording' |
'security' |
'select-background' |

View File

@@ -64,7 +64,7 @@ export const THIRD_PARTY_PREJOIN_BUTTONS = [ 'microphone', 'camera', 'select-bac
/**
* The toolbar buttons to show when in visitors mode.
*/
export const VISITORS_MODE_BUTTONS = [ 'chat', 'hangup', 'raisehand', 'tileview' ];
export const VISITORS_MODE_BUTTONS = [ 'chat', 'hangup', 'raisehand', 'settings', 'tileview' ];
/**
* The set of feature flags.

View File

@@ -1,7 +1,7 @@
// @ts-ignore
// @ts-expect-error
import Bourne from '@hapi/bourne';
// eslint-disable-next-line lines-around-comment
// @ts-ignore
// @ts-expect-error
import { jitsiLocalStorage } from '@jitsi/js-utils';
import _ from 'lodash';

View File

@@ -84,6 +84,7 @@ export interface IConfigState extends IConfig {
domain: string;
muc: string;
};
p2p?: object;
websocket?: string;
};
}

View File

@@ -36,7 +36,7 @@ type Props = {
/**
* Function to render a bottom sheet footer element, if necessary.
*/
renderFooter?: Function;
renderFooter?: () => React.ReactNode;
/**
* Function to render a bottom sheet header element, if necessary.
@@ -109,9 +109,7 @@ class BottomSheet extends PureComponent<Props> {
} = this.props;
return (
<SlidingView // @ts-ignore
accessibilityRole = 'menu'
accessibilityViewIsModal = { true }
<SlidingView
onHide = { this._onCancel }
position = 'bottom'
show = { Boolean(showSlidingView) }>

View File

@@ -18,7 +18,7 @@ interface IProps extends AbstractProps, WithTranslation {
/**
* The dialog descriptionKey.
*/
descriptionKey: string;
descriptionKey?: string;
/**
* An optional initial value to initiate the field with.

View File

@@ -1,4 +1,4 @@
// @ts-ignore
// @ts-expect-error
import { randomInt } from '@jitsi/js-utils/random';
import React, { Component } from 'react';
import { WithTranslation } from 'react-i18next';
@@ -11,7 +11,6 @@ import { isFatalJitsiConnectionError } from '../../../lib-jitsi-meet/functions.n
import { hideDialog } from '../../actions';
import logger from '../../logger';
// @ts-ignore
import ConfirmDialog from './ConfirmDialog';
@@ -39,9 +38,7 @@ interface IPageReloadDialogState {
* Shows a warning message and counts down towards the re-load.
*/
class PageReloadDialog extends Component<IPageReloadDialogProps, IPageReloadDialogState> {
// @ts-ignore
_interval: IntervalID;
_interval?: number;
_timeoutSeconds: number;
/**
@@ -105,7 +102,7 @@ class PageReloadDialog extends Component<IPageReloadDialogProps, IPageReloadDial
_onCancel() {
const { dispatch } = this.props;
clearInterval(this._interval);
clearInterval(this._interval ?? 0);
dispatch(appNavigate(undefined));
return true;
@@ -145,7 +142,7 @@ class PageReloadDialog extends Component<IPageReloadDialogProps, IPageReloadDial
_onReloadNow() {
const { dispatch } = this.props;
clearInterval(this._interval);
clearInterval(this._interval ?? 0);
dispatch(reloadNow());
return true;
@@ -200,8 +197,6 @@ function mapStateToProps(state: IReduxState) {
const { fatalError } = state['features/overlay'];
const fatalConnectionError
// @ts-ignore
= connectionError && isFatalJitsiConnectionError(connectionError);
const fatalConfigError = fatalError === configError;

View File

@@ -1,7 +1,7 @@
// @ts-ignore
// @ts-expect-error
import Bourne from '@hapi/bourne';
// eslint-disable-next-line lines-around-comment
// @ts-ignore
// @ts-expect-error
import { jitsiLocalStorage } from '@jitsi/js-utils/jitsi-local-storage';
import { browser } from '../lib-jitsi-meet';

View File

@@ -1,4 +1,4 @@
// @ts-ignore
// @ts-expect-error
import jwtDecode from 'jwt-decode';
import { IReduxState } from '../../app/types';

View File

@@ -1,4 +1,4 @@
// @ts-ignore
// @ts-expect-error
import jwtDecode from 'jwt-decode';
import { AnyAction } from 'redux';

View File

@@ -1,10 +1,9 @@
// @ts-ignore
// @ts-expect-error
import { jitsiLocalStorage } from '@jitsi/js-utils';
import { IStore } from '../../app/types';
import { isOnline } from '../net-info/selectors';
// @ts-ignore
import JitsiMeetJS from './_';
import {
LIB_DID_DISPOSE,

View File

@@ -1,4 +1,5 @@
import { IStateful } from '../app/types';
import { ConnectionFailedError } from '../connection/actions.any';
import { toState } from '../redux/functions';
// @ts-ignore
@@ -91,7 +92,7 @@ export function isFatalJitsiConferenceError(error: Error | string) {
* indicates a fatal {@code JitsiConnection} error, {@code true}; otherwise,
* {@code false}.
*/
export function isFatalJitsiConnectionError(error: Error | string) {
export function isFatalJitsiConnectionError(error: Error | string | ConnectionFailedError) {
if (typeof error !== 'string') {
error = error.name; // eslint-disable-line no-param-reassign
}

View File

@@ -1,4 +1,4 @@
// @ts-ignore
// @ts-expect-error
import Bourne from '@hapi/bourne';
import { NativeModules } from 'react-native';

View File

@@ -1,6 +1,5 @@
// Re-export JitsiMeetJS from the library lib-jitsi-meet to (the other features
// of) the project jitsi-meet.
// @ts-ignore
import JitsiMeetJS from './_';
export { JitsiMeetJS as default };

View File

@@ -6,7 +6,6 @@ import { SET_NETWORK_INFO } from '../net-info/actionTypes';
import { PARTICIPANT_LEFT } from '../participants/actionTypes';
import MiddlewareRegistry from '../redux/MiddlewareRegistry';
// @ts-ignore
import JitsiMeetJS from './_';
import { LIB_WILL_INIT } from './actionTypes';
import { disposeLib, initLib } from './actions';

View File

@@ -1,6 +1,6 @@
import { NativeModules } from 'react-native';
// eslint-disable-next-line lines-around-comment
// @ts-ignore
// @ts-expect-error
import { format } from 'util';
// Some code adapted from https://github.com/houserater/react-native-lumberjack

View File

@@ -1,4 +1,4 @@
// @ts-ignore
// @ts-expect-error
import Logger, { getLogger as _getLogger } from '@jitsi/logger';
import _ from 'lodash';

View File

@@ -1,4 +1,4 @@
// @ts-ignore
// @ts-expect-error
import Logger from '@jitsi/logger';
import { IStore } from '../../app/types';

View File

@@ -1,5 +1,2 @@
// @ts-ignore
export { default as Audio } from './native/Audio';
// @ts-ignore
export { default as Video } from './native/Video';

View File

@@ -7,7 +7,6 @@ import { IReduxState, IStore } from '../../../../app/types';
import { ASPECT_RATIO_WIDE } from '../../../responsive-ui/constants';
import { storeVideoTransform } from '../../actions';
// @ts-ignore
import styles from './styles';
@@ -125,12 +124,12 @@ class VideoTransform extends Component<IProps, IState> {
/**
* The gesture handler object.
*/
gestureHandlers: Object;
gestureHandlers: any;
/**
* The initial distance of the fingers on pinch start.
*/
initialDistance: number;
initialDistance?: number;
/**
* The initial position of the finger on touch start.
@@ -234,8 +233,6 @@ class VideoTransform extends Component<IProps, IState> {
videoTransformedViewContainerStyles,
style
] }
// @ts-ignore
{ ...this.gestureHandlers.panHandlers }>
<SafeAreaView
edges = { [ 'bottom', 'left' ] }
@@ -489,7 +486,7 @@ class VideoTransform extends Component<IProps, IState> {
* @param {?Object | number} value - The value of the gesture, if any.
* @returns {void}
*/
_onGesture(type: string, value: any) {
_onGesture(type: string, value?: any) {
let transform;
switch (type) {
@@ -600,7 +597,7 @@ class VideoTransform extends Component<IProps, IState> {
this._onGesture('scale', scale);
}
} else if (gestureState.numberActiveTouches === 1
&& isNaN(this.initialDistance)
&& isNaN(this.initialDistance ?? 0)
&& this._didMove(gestureState)) {
// this is a move event
const position = this._getTouchPosition(evt);
@@ -623,11 +620,9 @@ class VideoTransform extends Component<IProps, IState> {
*/
_onPanResponderRelease() {
if (this.lastTap && Date.now() - this.lastTap < TAP_TIMEOUT_MS) {
// @ts-ignore
this._onGesture('press');
}
// @ts-ignore
delete this.initialDistance;
this.initialPosition = {
x: 0,

View File

@@ -1,7 +1,7 @@
import NetInfo from '@react-native-community/netinfo';
import type { NetInfoState, NetInfoSubscription } from '@react-native-community/netinfo';
// eslint-disable-next-line lines-around-comment
// @ts-ignore
// @ts-expect-error
import EventEmitter from 'events';
import { ONLINE_STATE_CHANGED_EVENT } from './events';
@@ -15,7 +15,7 @@ export default class NetworkInfoService extends EventEmitter {
/**
* Stores the native subscription for future cleanup.
*/
_subscription: NetInfoSubscription;
_subscription?: NetInfoSubscription;
/**
* Converts library's structure to {@link NetworkInfo} used by jitsi-meet.
@@ -26,10 +26,8 @@ export default class NetworkInfoService extends EventEmitter {
*/
static _convertNetInfoState(netInfoState: NetInfoState): NetworkInfo {
return {
// @ts-ignore
isOnline: netInfoState.isInternetReachable,
isOnline: Boolean(netInfoState.isInternetReachable),
// @ts-ignore
details: netInfoState.details,
networkType: netInfoState.type
};
@@ -51,8 +49,7 @@ export default class NetworkInfoService extends EventEmitter {
*/
start() {
this._subscription = NetInfo.addEventListener(netInfoState => {
// @ts-ignore
this.emit(ONLINE_STATE_CHANGED_EVENT, NetworkInfoService._convertNetInfoState(netInfoState));
super.emit(ONLINE_STATE_CHANGED_EVENT, NetworkInfoService._convertNetInfoState(netInfoState));
});
}
@@ -64,8 +61,6 @@ export default class NetworkInfoService extends EventEmitter {
stop() {
if (this._subscription) {
this._subscription();
// @ts-ignore
this._subscription = undefined;
}
}

View File

@@ -16,13 +16,13 @@ export type NetworkInfo = {
* If {@link networkType} is {@link NetInfoStateType.cellular} then it may provide the info about the type of
* cellular network.
*/
cellularGeneration?: NetInfoCellularGeneration;
cellularGeneration?: NetInfoCellularGeneration | null;
/**
* Indicates whether or not the connection is expensive.
*/
isConnectionExpensive?: boolean;
};
} | null;
/**
* Tells whether or not the internet is reachable.

View File

@@ -1,4 +1,4 @@
// @ts-ignore
// @ts-expect-error
import { getGravatarURL } from '@jitsi/js-utils/avatar';
import { IReduxState, IStore } from '../../app/types';

View File

@@ -6,6 +6,7 @@ import { IReduxState } from '../../../app/types';
import DialogPortal from '../../../toolbox/components/web/DialogPortal';
import Drawer from '../../../toolbox/components/web/Drawer';
import JitsiPortal from '../../../toolbox/components/web/JitsiPortal';
import { isElementInTheViewport } from '../../ui/functions.web';
import { getContextMenuStyle } from '../functions.web';
/**
@@ -258,7 +259,16 @@ class Popover extends Component<IProps, IState> {
'aria-labelledby': headingId,
'aria-label': !headingId && headingLabel ? headingLabel : undefined
}}
returnFocus = { true }>
returnFocus = {
// If we return the focus to an element outside the viewport the page will scroll to
// this element which in our case is undesirable and the element is outside of the
// viewport on purpose (to be hidden). For example if we return the focus to the toolbox
// when it is hidden the whole page will move up in order to show the toolbox. This is
// usually followed up with displaying the toolbox (because now it is on focus) but
// because of the animation the whole scenario looks like jumping large video.
isElementInTheViewport
}>
{this._renderContent()}
</ReactFocusLock>
</DialogPortal>
@@ -304,7 +314,8 @@ class Popover extends Component<IProps, IState> {
&& !this.props.overflowDrawer
&& this._contextMenuRef
&& this._contextMenuRef.contains
&& !this._contextMenuRef.contains(event.target as Node)) {
&& !this._contextMenuRef.contains(event.target as Node)
&& !this._containerRef?.current?.contains(event.target as Node)) {
this._onHideDialog();
}
}

View File

@@ -12,8 +12,6 @@ import { getToolbarButtons, isToolbarButtonEnabled } from '../../../config/funct
import { withPixelLineHeight } from '../../../styles/functions.web';
import ConnectionStatus from './ConnectionStatus';
// eslint-disable-next-line lines-around-comment
// @ts-ignore
import Preview from './Preview';
interface IProps {

View File

@@ -1,5 +1,2 @@
/* eslint-disable lines-around-comment */
// @ts-ignore
export { default as Container } from './native/Container';
// @ts-ignore
export { default as Text } from './native/Text';

View File

@@ -42,7 +42,7 @@ interface IProps {
/**
* Style of the animated view.
*/
style: StyleType;
style?: StyleType;
}
/**

View File

@@ -1,7 +1,7 @@
// @ts-ignore
// @ts-expect-error
import Bourne from '@hapi/bourne';
// eslint-disable-next-line lines-around-comment
// @ts-ignore
// @ts-expect-error
import { jitsiLocalStorage } from '@jitsi/js-utils';
import md5 from 'js-md5';

View File

@@ -1,5 +1,3 @@
/* eslint-disable lines-around-comment */
import { connect } from 'react-redux';
import { IReduxState } from '../../../../app/types';
@@ -7,9 +5,7 @@ import { translate } from '../../../../base/i18n/functions';
import { IconGear } from '../../../../base/icons/svg';
import AbstractButton, { IProps as AbstractButtonProps } from '../../../../base/toolbox/components/AbstractButton';
import { navigate }
// @ts-ignore
from '../../../../mobile/navigation/components/conference/ConferenceNavigationContainerRef';
// @ts-ignore
import { screen } from '../../../../mobile/navigation/routes';
import { SETTINGS_ENABLED } from '../../../flags/constants';
import { getFeatureFlag } from '../../../flags/functions';

View File

@@ -1,4 +1,4 @@
// @ts-ignore
// @ts-expect-error
import { jitsiLocalStorage } from '@jitsi/js-utils';
import _ from 'lodash';

View File

@@ -43,7 +43,7 @@ export default class ToolboxItem extends AbstractToolboxItem<IProps> {
* @returns {void}
*/
_onKeyPress(event?: React.KeyboardEvent) {
if (event?.key === 'Enter' || event?.key === ' ') {
if (event?.key === 'Enter') {
event.preventDefault();
this.props.onClick();
}

View File

@@ -33,17 +33,17 @@ interface IProps {
/**
* Icon of the button.
*/
icon: Function;
icon?: Function;
/**
* Flag used for disabling the small icon.
*/
iconDisabled: boolean;
iconDisabled?: boolean;
/**
* The ID of the icon button.
*/
iconId: string;
iconId?: string;
/**
* Popover close callback.
@@ -65,6 +65,11 @@ interface IProps {
*/
styles?: Object;
/**
* Whether the trigger for open/ close should be click or hover.
*/
trigger?: 'hover' | 'click';
/**
* Whether or not the popover is visible.
*/
@@ -77,7 +82,7 @@ interface IProps {
* @param {Object} props - Component's props.
* @returns {ReactElement}
*/
export default function ToolboxButtonWithIconPopup(props: IProps) {
export default function ToolboxButtonWithPopup(props: IProps) {
const {
ariaControls,
ariaExpanded,
@@ -91,9 +96,29 @@ export default function ToolboxButtonWithIconPopup(props: IProps) {
onPopoverOpen,
popoverContent,
styles,
trigger,
visible
} = props;
if (!icon) {
return (
<div
className = 'settings-button-container'
style = { styles }>
<Popover
content = { popoverContent }
headingLabel = { ariaLabel }
onPopoverClose = { onPopoverClose }
onPopoverOpen = { onPopoverOpen }
position = 'top'
trigger = { trigger }
visible = { visible }>
{children}
</Popover>
</div>
);
}
const iconProps: any = {};
if (iconDisabled) {

View File

@@ -1,6 +1,4 @@
import { IReduxState, IStore } from '../../app/types';
// eslint-disable-next-line lines-around-comment
// @ts-ignore
import { setPictureInPictureEnabled } from '../../mobile/picture-in-picture/functions';
import { showNotification } from '../../notifications/actions';
import { NOTIFICATION_TIMEOUT_TYPE } from '../../notifications/constants';

View File

@@ -10,8 +10,6 @@ import { setScreenAudioShareState, setScreenshareAudioTrack } from '../../screen
import { isAudioOnlySharing, isScreenVideoShared } from '../../screen-share/functions';
import { toggleScreenshotCaptureSummary } from '../../screenshot-capture/actions';
import { isScreenshotCaptureEnabled } from '../../screenshot-capture/functions';
// eslint-disable-next-line lines-around-comment
// @ts-ignore
import { AudioMixerEffect } from '../../stream-effects/audio-mixer/AudioMixerEffect';
import { getCurrentConference } from '../conference/functions';
import { JitsiTrackErrors, JitsiTrackEvents } from '../lib-jitsi-meet';

View File

@@ -1,8 +1,10 @@
import { IStore } from '../../app/types';
import { IStateful } from '../app/types';
import { isMobileBrowser } from '../environment/utils';
import JitsiMeetJS from '../lib-jitsi-meet';
import JitsiMeetJS, { JitsiTrackErrors, browser } from '../lib-jitsi-meet';
import { setAudioMuted } from '../media/actions';
import { MEDIA_TYPE } from '../media/constants';
import { getStartWithAudioMuted } from '../media/functions';
import { toState } from '../redux/functions';
import {
getUserSelectedCameraDeviceId,
@@ -94,10 +96,10 @@ export function createLocalTracksF(options: ITrackOptions = {}, store?: IStore)
}
/**
* Returns an object containing a promise which resolves with the created tracks &
* the errors resulting from that process.
* Returns an object containing a promise which resolves with the created tracks and the errors resulting from that
* process.
*
* @returns {Promise<JitsiLocalTrack>}
* @returns {Promise<JitsiLocalTrack[]>}
*
* @todo Refactor to not use APP.
*/
@@ -106,7 +108,13 @@ export function createPrejoinTracks() {
const initialDevices = [ 'audio' ];
const requestedAudio = true;
let requestedVideo = false;
const { startAudioOnly, startWithAudioMuted, startWithVideoMuted } = APP.store.getState()['features/base/settings'];
const { startAudioOnly, startWithVideoMuted } = APP.store.getState()['features/base/settings'];
const startWithAudioMuted = getStartWithAudioMuted(APP.store.getState());
// On Electron there is no permission prompt for granting permissions. That's why we don't need to
// spend much time displaying the overlay screen. If GUM is not resolved within 15 seconds it will
// probably never resolve.
const timeout = browser.isElectron() ? 15000 : 60000;
// Always get a handle on the audio input device so that we have statistics even if the user joins the
// conference muted. Previous implementation would only acquire the handle when the user first unmuted,
@@ -121,62 +129,66 @@ export function createPrejoinTracks() {
requestedVideo = true;
}
let tryCreateLocalTracks;
let tryCreateLocalTracks: any = Promise.resolve([]);
if (!requestedAudio && !requestedVideo) {
// Resolve with no tracks
tryCreateLocalTracks = Promise.resolve([]);
} else {
if (requestedAudio || requestedVideo) {
tryCreateLocalTracks = createLocalTracksF({
devices: initialDevices,
firePermissionPromptIsShownEvent: true
firePermissionPromptIsShownEvent: true,
timeout
}, APP.store)
.catch((err: Error) => {
if (requestedAudio && requestedVideo) {
.catch(async (err: Error) => {
if (err.name === JitsiTrackErrors.TIMEOUT && !browser.isElectron()) {
errors.audioAndVideoError = err;
// Try audio only...
errors.audioAndVideoError = err;
return [];
}
return (
createLocalTracksF({
devices: [ 'audio' ],
firePermissionPromptIsShownEvent: true
}));
} else if (requestedAudio && !requestedVideo) {
errors.audioOnlyError = err;
// Retry with separate gUM calls.
const gUMPromises: any = [];
const tracks: any = [];
return [];
} else if (requestedVideo && !requestedAudio) {
errors.videoOnlyError = err;
if (requestedAudio) {
gUMPromises.push(createLocalTracksF({
devices: [ MEDIA_TYPE.AUDIO ],
firePermissionPromptIsShownEvent: true,
timeout
}));
}
return [];
if (requestedVideo) {
gUMPromises.push(createLocalTracksF({
devices: [ MEDIA_TYPE.VIDEO ],
firePermissionPromptIsShownEvent: true,
timeout
}));
}
const results = await Promise.allSettled(gUMPromises);
let errorMsg;
results.forEach((result, idx) => {
if (result.status === 'fulfilled') {
tracks.push(result.value[0]);
} else {
errorMsg = result.reason;
const isAudio = idx === 0;
logger.error(`${isAudio ? 'Audio' : 'Video'} track creation failed with error ${errorMsg}`);
if (isAudio) {
errors.audioOnlyError = errorMsg;
} else {
errors.videoOnlyError = errorMsg;
}
logger.error('Should never happen');
})
.catch((err: Error) => {
// Log this just in case...
if (!requestedAudio) {
logger.error('The impossible just happened', err);
}
errors.audioOnlyError = err;
}
});
// Try video only...
return requestedVideo
? createLocalTracksF({
devices: [ 'video' ],
firePermissionPromptIsShownEvent: true
})
: [];
})
.catch((err: Error) => {
// Log this just in case...
if (!requestedVideo) {
logger.error('The impossible just happened', err);
}
errors.videoOnlyError = err;
if (errors.audioOnlyError && errors.videoOnlyError) {
errors.audioAndVideoError = errorMsg;
}
return [];
});
return tracks;
});
}
return {

View File

@@ -2,8 +2,6 @@ import React from 'react';
import { TouchableRipple } from 'react-native-paper';
import Icon from '../../../icons/components/Icon';
// eslint-disable-next-line lines-around-comment
// @ts-ignore
import styles from '../../../react/components/native/styles';
import { IIconButtonProps } from '../../../react/types';
import { BUTTON_TYPES } from '../../constants.native';

View File

@@ -5,6 +5,7 @@ import { keyframes } from 'tss-react';
import { makeStyles } from 'tss-react/mui';
import { withPixelLineHeight } from '../../../styles/functions.web';
import { isElementInTheViewport } from '../../functions.web';
import { DialogTransitionContext } from './DialogTransition';
@@ -184,7 +185,16 @@ const BaseDialog = ({
onClick = { onBackdropClick } />
<FocusLock
className = { classes.focusLock }
returnFocus = { true }>
returnFocus = {
// If we return the focus to an element outside the viewport the page will scroll to
// this element which in our case is undesirable and the element is outside of the
// viewport on purpose (to be hidden). For example if we return the focus to the toolbox
// when it is hidden the whole page will move up in order to show the toolbox. This is
// usually followed up with displaying the toolbox (because now it is on focus) but
// because of the animation the whole scenario looks like jumping large video.
isElementInTheViewport
}>
<div
aria-describedby = { description }
aria-labelledby = { title ?? t(titleKey ?? '') }

View File

@@ -70,7 +70,7 @@ const useStyles = makeStyles()(theme => {
'& input[type="checkbox"]': {
appearance: 'none',
backgroundColor: 'transparent',
margin: 0,
margin: '3px',
font: 'inherit',
color: theme.palette.icon03,
width: '18px',

View File

@@ -57,3 +57,28 @@ export const findAncestorByClass = (target: HTMLElement | null, cssClass: string
return findAncestorByClass(target.parentElement, cssClass);
};
/**
* Checks if the passed element is visible in the viewport.
*
* @param {Element} element - The element.
* @returns {boolean}
*/
export function isElementInTheViewport(element?: Element): boolean {
if (!element) {
return false;
}
if (!document.body.contains(element)) {
return false;
}
const { innerHeight, innerWidth } = window;
const { bottom, left, right, top } = element.getBoundingClientRect();
if (bottom <= innerHeight && top >= 0 && left >= 0 && right <= innerWidth) {
return true;
}
return false;
}

View File

@@ -1,4 +1,4 @@
// @ts-ignore
// @ts-expect-error
import Bourne from '@hapi/bourne';
import { reportError } from './helpers';

View File

@@ -6,8 +6,6 @@ import { IStore } from '../app/types';
import { openDialog } from '../base/dialog/actions';
import { refreshCalendar } from './actions';
// eslint-disable-next-line lines-around-comment
// @ts-ignore
import UpdateCalendarEventDialog from './components/UpdateCalendarEventDialog.native';
import { addLinkToCalendarEntry } from './functions.native';
@@ -40,8 +38,6 @@ export function updateCalendarEvent(eventId: string) {
const roomName = generateRoomWithoutSeparator();
addLinkToCalendarEntry(getState(), eventId, `${defaultUrl}/${roomName}`)
// @ts-ignore
.finally(() => {
dispatch(refreshCalendar(false, false));
});

View File

@@ -1,4 +1,3 @@
/* eslint-disable lines-around-comment */
import { IStore } from '../app/types';
import { IStateful } from '../base/app/types';
import { toState } from '../base/redux/functions';
@@ -17,11 +16,8 @@ import {
} from './constants';
import { _updateCalendarEntries } from './functions.web';
import logger from './logger';
// @ts-ignore
import { googleCalendarApi } from './web/googleCalendar';
// @ts-ignore
import { microsoftCalendarApi } from './web/microsoftCalendar';
/* eslint-enable lines-around-comment */
/**
* Determines whether the calendar feature is enabled by the web.

View File

@@ -1,6 +1,6 @@
import { Client } from '@microsoft/microsoft-graph-client';
// eslint-disable-next-line lines-around-comment
// @ts-ignore
// @ts-expect-error
import base64js from 'base64-js';
import { v4 as uuidV4 } from 'uuid';
import { findWindows } from 'windows-iana';

View File

@@ -1,10 +1,6 @@
/* eslint-disable lines-around-comment, max-len */
import { IParticipant } from '../base/participants/types';
import { navigate }
// @ts-ignore
from '../mobile/navigation/components/conference/ConferenceNavigationContainerRef';
// @ts-ignore
import { screen } from '../mobile/navigation/routes';
import { OPEN_CHAT } from './actionTypes';

View File

@@ -1,6 +1,5 @@
/* eslint-disable react/no-multi-comp */
import { useIsFocused } from '@react-navigation/native';
import { Route, useIsFocused } from '@react-navigation/native';
import React, { useEffect } from 'react';
import { connect } from 'react-redux';
@@ -9,7 +8,7 @@ import JitsiScreen from '../../../base/modal/components/JitsiScreen';
import { TabBarLabelCounter } from '../../../mobile/navigation/components/TabBarLabelCounter';
import { closeChat } from '../../actions.native';
import AbstractChat, {
type Props as AbstractProps,
IProps as AbstractProps,
_mapStateToProps
} from '../AbstractChat';
@@ -18,24 +17,24 @@ import MessageContainer from './MessageContainer';
import MessageRecipient from './MessageRecipient';
import styles from './styles';
type Props = AbstractProps & {
interface IProps extends AbstractProps {
/**
* Default prop for navigating between screen components(React Navigation).
*/
navigation: Object,
navigation: any;
/**
* Default prop for navigating between screen components(React Navigation).
*/
route: Object
};
route: Route<'', { privateMessageRecipient: { name: string; }; }>;
}
/**
* Implements a React native component that renders the chat window (modal) of
* the mobile client.
*/
class Chat extends AbstractChat<Props> {
class Chat extends AbstractChat<IProps> {
/**
* Implements React's {@link Component#render()}.
*
@@ -51,17 +50,16 @@ class Chat extends AbstractChat<Props> {
hasBottomTextInput = { true }
hasTabNavigator = { true }
style = { styles.chatContainer }>
{/* @ts-ignore */}
<MessageContainer messages = { _messages } />
<MessageRecipient privateMessageRecipient = { privateMessageRecipient } />
<ChatInputBar onSend = { this._onSendMessage } />
</JitsiScreen>
);
}
_onSendMessage: (string) => void;
}
export default translate(connect(_mapStateToProps)(props => {
export default translate(connect(_mapStateToProps)((props: IProps) => {
const { _nbUnreadMessages, dispatch, navigation, t } = props;
const unreadMessagesNr = _nbUnreadMessages > 0;
@@ -78,7 +76,9 @@ export default translate(connect(_mapStateToProps)(props => {
)
});
return () => isFocused && dispatch(closeChat());
return () => {
isFocused && dispatch(closeChat());
};
}, [ isFocused, _nbUnreadMessages ]);
return (

View File

@@ -1,5 +1,6 @@
import { connect } from 'react-redux';
import { IReduxState } from '../../../app/types';
import { CHAT_ENABLED } from '../../../base/flags/constants';
import { getFeatureFlag } from '../../../base/flags/functions';
import { translate } from '../../../base/i18n/functions';
@@ -10,23 +11,23 @@ import { screen } from '../../../mobile/navigation/routes';
import { getUnreadPollCount } from '../../../polls/functions';
import { getUnreadCount } from '../../functions';
type Props = AbstractButtonProps & {
interface IProps extends AbstractButtonProps {
/**
* True if the polls feature is disabled.
*/
_isPollsDisabled: boolean,
_isPollsDisabled?: boolean;
/**
* The unread message count.
*/
_unreadMessageCount: number
};
_unreadMessageCount: number;
}
/**
* Implements an {@link AbstractButton} to open the chat screen on mobile.
*/
class ChatButton extends AbstractButton<Props, *> {
class ChatButton extends AbstractButton<IProps> {
accessibilityLabel = 'toolbar.accessibilityLabel.chat';
icon = IconMessage;
label = 'toolbar.chat';
@@ -60,9 +61,9 @@ class ChatButton extends AbstractButton<Props, *> {
*
* @param {Object} state - The Redux state.
* @param {Object} ownProps - The properties explicitly passed to the component instance.
* @returns {Props}
* @returns {IProps}
*/
function _mapStateToProps(state, ownProps) {
function _mapStateToProps(state: IReduxState, ownProps: any) {
const enabled = getFeatureFlag(state, CHAT_ENABLED, true);
const { disablePolls } = state['features/base/config'];
const { visible = enabled } = ownProps;

View File

@@ -25,10 +25,6 @@ class ChatPrivacyDialog extends AbstractChatPrivacyDialog {
onSubmit = { this._onSendPrivateMessage } />
);
}
_onSendGroupMessage: () => boolean;
_onSendPrivateMessage: () => boolean;
}
export default translate(connect(_mapStateToProps, _mapDispatchToProps)(ChatPrivacyDialog));

View File

@@ -1,63 +1,65 @@
import React from 'react';
import { Text, TouchableHighlight, View } from 'react-native';
import { Text, TouchableHighlight, View, ViewStyle } from 'react-native';
import { connect } from 'react-redux';
import { IReduxState, IStore } from '../../../app/types';
import { translate } from '../../../base/i18n/functions';
import Icon from '../../../base/icons/components/Icon';
import { IconCloseLarge } from '../../../base/icons/svg';
import { ILocalParticipant } from '../../../base/participants/types';
import {
setParams
} from '../../../mobile/navigation/components/conference/ConferenceNavigationContainerRef';
import { setLobbyChatActiveState, setPrivateMessageRecipient } from '../../actions.any';
import AbstractMessageRecipient, {
type Props as AbstractProps
IProps as AbstractProps
} from '../AbstractMessageRecipient';
import styles from './styles';
type Props = AbstractProps & {
interface IProps extends AbstractProps {
/**
* The Redux dispatch function.
*/
dispatch: Function,
dispatch: IStore['dispatch'];
/**
* Is lobby messaging active.
*/
isLobbyChatActive: boolean,
isLobbyChatActive: boolean;
/**
* The participant string for lobby chat messaging.
*/
lobbyMessageRecipient: Object,
lobbyMessageRecipient?: {
id: string;
name: string;
} | ILocalParticipant;
/**
* The participant object set for private messaging.
*/
privateMessageRecipient: Object,
};
privateMessageRecipient: { name: string; };
}
/**
* Class to implement the displaying of the recipient of the next message.
*/
class MessageRecipient extends AbstractMessageRecipient<Props> {
class MessageRecipient extends AbstractMessageRecipient<IProps> {
/**
* Constructor of the component.
*
* @param {Props} props - The props of the component.
* @param {IProps} props - The props of the component.
*/
constructor(props: Props) {
constructor(props: IProps) {
super(props);
this._onResetPrivateMessageRecipient = this._onResetPrivateMessageRecipient.bind(this);
this._onResetLobbyMessageRecipient = this._onResetLobbyMessageRecipient.bind(this);
}
_onResetLobbyMessageRecipient: () => void;
/**
* Resets lobby message recipient from state.
*
@@ -69,8 +71,6 @@ class MessageRecipient extends AbstractMessageRecipient<Props> {
dispatch(setLobbyChatActiveState(false));
}
_onResetPrivateMessageRecipient: () => void;
/**
* Resets private message recipient from state.
*
@@ -102,10 +102,10 @@ class MessageRecipient extends AbstractMessageRecipient<Props> {
if (isLobbyChatActive) {
return (
<View style = { styles.lobbyMessageRecipientContainer }>
<View style = { styles.lobbyMessageRecipientContainer as ViewStyle }>
<Text style = { styles.messageRecipientText }>
{ t('chat.lobbyChatMessageTo', {
recipient: lobbyMessageRecipient.name
recipient: lobbyMessageRecipient?.name
}) }
</Text>
<TouchableHighlight
@@ -123,7 +123,7 @@ class MessageRecipient extends AbstractMessageRecipient<Props> {
}
return (
<View style = { styles.messageRecipientContainer }>
<View style = { styles.messageRecipientContainer as ViewStyle }>
<Text style = { styles.messageRecipientText }>
{ t('chat.messageTo', {
recipient: privateMessageRecipient.name
@@ -145,9 +145,10 @@ class MessageRecipient extends AbstractMessageRecipient<Props> {
* Maps part of the redux state to the props of this component.
*
* @param {Object} state - The Redux state.
* @returns {Props}
* @param {any} _ownProps - Component's own props.
* @returns {IProps}
*/
function _mapStateToProps(state) {
function _mapStateToProps(state: IReduxState, _ownProps: any) {
const { lobbyMessageRecipient, isLobbyChatActive } = state['features/chat'];
return {

View File

@@ -29,11 +29,11 @@ const styles = (theme: Theme) => {
chatMessage: {
display: 'inline-flex',
padding: '12px',
marginRight: '12px',
backgroundColor: theme.palette.ui02,
borderRadius: '4px 12px 12px 12px',
maxWidth: '100%',
marginTop: '4px',
boxSizing: 'border-box' as const,
'&.privatemessage': {
backgroundColor: theme.palette.support05
@@ -62,7 +62,8 @@ const styles = (theme: Theme) => {
replyWrapper: {
display: 'flex',
flexDirection: 'row' as const,
alignItems: 'center'
alignItems: 'center',
maxWidth: '100%'
},
messageContent: {
@@ -126,7 +127,7 @@ class ChatMessage extends AbstractChatMessage<IProps> {
return (
<div
className = { classes.chatMessageWrapper }
className = { clsx(classes.chatMessageWrapper, type) }
id = { this.props.message.messageId }
tabIndex = { -1 }>
<div

View File

@@ -25,7 +25,11 @@ const useStyles = makeStyles()(theme => {
messageGroup: {
display: 'flex',
flexDirection: 'column',
maxWidth: '100%'
maxWidth: '100%',
'&.remote': {
maxWidth: 'calc(100% - 40px)' // 100% - avatar and margin
}
},
groupContainer: {

View File

@@ -28,6 +28,13 @@ const useStyles = makeStyles()(theme => {
color: theme.palette.text01
},
text: {
maxWidth: 'calc(100% - 30px)',
overflow: 'hidden',
whiteSpace: 'break-spaces',
wordBreak: 'break-all'
},
iconButton: {
padding: '2px',
@@ -72,7 +79,7 @@ const MessageRecipient = ({
className = { classes.container }
id = 'chat-recipient'
role = 'alert'>
<span>
<span className = { classes.text }>
{t(_isLobbyChatActive ? 'chat.lobbyChatMessageTo' : 'chat.messageTo', {
recipient: _isLobbyChatActive ? _lobbyMessageRecipient : _privateMessageRecipient
})}

View File

@@ -1,7 +1,7 @@
// @ts-ignore
// @ts-expect-error
import aliases from 'react-emoji-render/data/aliases';
// eslint-disable-next-line lines-around-comment
// @ts-ignore
// @ts-expect-error
import emojiAsciiAliases from 'react-emoji-render/data/asciiAliases';
import { IReduxState } from '../app/types';

View File

@@ -1,7 +1,5 @@
import { IStore } from '../app/types';
import { openDialog } from '../base/dialog/actions';
// eslint-disable-next-line lines-around-comment
// @ts-ignore
import AlertDialog from '../base/dialog/components/native/AlertDialog';
import { getParticipantDisplayName } from '../base/participants/functions';

View File

@@ -20,7 +20,6 @@ import { isInBreakoutRoom } from '../../../breakout-rooms/functions';
import { doInvitePeople } from '../../../invite/actions.native';
import { getInviteOthersControl } from '../../../share-room/functions';
// @ts-ignore
import styles from './styles';

View File

@@ -1,30 +1,22 @@
/* eslint-disable lines-around-comment */
import React, { useEffect } from 'react';
import { View } from 'react-native';
import { View, ViewStyle } from 'react-native';
import Orientation from 'react-native-orientation-locker';
import { withSafeAreaInsets } from 'react-native-safe-area-context';
import { useDispatch, useSelector } from 'react-redux';
// @ts-ignore
import JitsiScreen from '../../../../base/modal/components/JitsiScreen';
// @ts-ignore
import LoadingIndicator from '../../../../base/react/components/native/LoadingIndicator';
// @ts-ignore
import TintedView from '../../../../base/react/components/native/TintedView';
import { isLocalVideoTrackDesktop } from '../../../../base/tracks/functions.native';
// @ts-ignore
import { setPictureInPictureEnabled } from '../../../../mobile/picture-in-picture/functions';
// @ts-ignore
import { setIsCarmode } from '../../../../video-layout/actions';
// @ts-ignore
import ConferenceTimer from '../../ConferenceTimer';
// @ts-ignore
import { isConnecting } from '../../functions';
import CarModeFooter from './CarModeFooter';
import MicrophoneButton from './MicrophoneButton';
import TitleBar from './TitleBar';
// @ts-ignore
import styles from './styles';
/**
@@ -66,17 +58,16 @@ const CarMode = (): JSX.Element => {
}
<View
pointerEvents = 'box-none'
style = { styles.titleBarSafeViewColor }>
style = { styles.titleBarSafeViewColor as ViewStyle }>
<View
style = { styles.titleBar }>
{/* @ts-ignore */}
style = { styles.titleBar as ViewStyle }>
<TitleBar />
</View>
<ConferenceTimer textStyle = { styles.roomTimer } />
</View>
<View
pointerEvents = 'box-none'
style = { styles.microphoneContainer }>
style = { styles.microphoneContainer as ViewStyle }>
<MicrophoneButton />
</View>
</JitsiScreen>

View File

@@ -1,11 +1,9 @@
import React from 'react';
import { useTranslation } from 'react-i18next';
import { Text, View } from 'react-native';
import { Text, View, ViewStyle } from 'react-native';
import EndMeetingButton from './EndMeetingButton';
import SoundDeviceButton from './SoundDeviceButton';
// eslint-disable-next-line lines-around-comment
// @ts-ignore
import styles from './styles';
/**
@@ -19,7 +17,7 @@ const CarModeFooter = (): JSX.Element => {
return (
<View
pointerEvents = 'box-none'
style = { styles.bottomContainer }>
style = { styles.bottomContainer as ViewStyle }>
<Text style = { styles.videoStoppedLabel }>
{ t('carmode.labels.videoStopped') }
</Text>

View File

@@ -8,8 +8,6 @@ import Button from '../../../../base/ui/components/native/Button';
import { BUTTON_TYPES } from '../../../../base/ui/constants.native';
import EndMeetingIcon from './EndMeetingIcon';
// eslint-disable-next-line lines-around-comment
// @ts-ignore
import styles from './styles';
/**

View File

@@ -1,5 +1,5 @@
import React, { useCallback, useState } from 'react';
import { TouchableOpacity, View } from 'react-native';
import { TouchableOpacity, View, ViewStyle } from 'react-native';
import { useDispatch, useSelector } from 'react-redux';
import {
@@ -18,7 +18,6 @@ import { isLocalTrackMuted } from '../../../../base/tracks/functions';
import { isAudioMuteButtonDisabled } from '../../../../toolbox/functions.any';
import { muteLocal } from '../../../../video-menu/actions';
// @ts-ignore
import styles from './styles';
const LONG_PRESS = 'long.press';
@@ -77,9 +76,9 @@ const MicrophoneButton = (): JSX.Element | null => {
style = { [
styles.microphoneStyles.container,
!audioMuted && styles.microphoneStyles.unmuted
] }>
] as ViewStyle[] }>
<View
style = { styles.microphoneStyles.iconContainer }>
style = { styles.microphoneStyles.iconContainer as ViewStyle }>
<Icon
src = { audioMuted ? IconMicSlash : IconMic }
style = { styles.microphoneStyles.icon } />

View File

@@ -1,15 +1,14 @@
/* eslint-disable lines-around-comment */
import React, { useCallback } from 'react';
import { useDispatch } from 'react-redux';
import { openSheet } from '../../../../base/dialog/actions';
import Button from '../../../../base/ui/components/native/Button';
import { BUTTON_TYPES } from '../../../../base/ui/constants.native';
// eslint-disable-next-line lines-around-comment
// @ts-ignore
import AudioRoutePickerDialog from '../../../../mobile/audio-mode/components/AudioRoutePickerDialog';
import AudioIcon from './AudioIcon';
// @ts-ignore
import styles from './styles';
/**

View File

@@ -1,5 +1,3 @@
/* eslint-disable lines-around-comment */
import React from 'react';
import { StyleProp, Text, View, ViewStyle } from 'react-native';
import { connect, useSelector } from 'react-redux';
@@ -10,14 +8,12 @@ import { MEETING_NAME_ENABLED } from '../../../../base/flags/constants';
import { getFeatureFlag } from '../../../../base/flags/functions';
import { JitsiRecordingConstants } from '../../../../base/lib-jitsi-meet';
import { getLocalParticipant } from '../../../../base/participants/functions';
// @ts-ignore
import ConnectionIndicator from '../../../../connection-indicator/components/native/ConnectionIndicator';
// @ts-ignore
import RecordingLabel from '../../../../recording/components/native/RecordingLabel';
// eslint-disable-next-line lines-around-comment
// @ts-ignore
import VideoQualityLabel from '../../../../video-quality/components/VideoQualityLabel.native';
// @ts-ignore
import styles from './styles';
@@ -56,9 +52,7 @@ const TitleBar = (props: IProps): JSX.Element => {
<VideoQualityLabel />
</View>
<ConnectionIndicator
// @ts-ignore
iconStyle = { styles.connectionIndicatorIcon }
// @ts-ignore
participantId = { localParticipantId } />
<View style = { styles.headerLabels as StyleProp<ViewStyle> }>
<RecordingLabel mode = { JitsiRecordingConstants.mode.FILE } />

View File

@@ -28,8 +28,6 @@ import { SET_REDUCED_UI } from '../base/responsive-ui/actionTypes';
import { BUTTON_TYPES } from '../base/ui/constants.any';
import { inIframe } from '../base/util/iframeUtils';
import { isCalendarEnabled } from '../calendar-sync/functions';
// eslint-disable-next-line lines-around-comment
// @ts-ignore
import FeedbackDialog from '../feedback/components/FeedbackDialog';
import { setFilmstripEnabled } from '../filmstrip/actions.any';
import { isVpaasMeeting } from '../jaas/functions';

View File

@@ -87,7 +87,6 @@ class ConnectionIndicator extends AbstractConnectionIndicator<IProps, IState> {
constructor(props: IProps) {
super(props);
// @ts-ignore
this.state = {
autoHideTimeout: undefined,
showIndicator: false,

View File

@@ -1,6 +1,4 @@
import BaseTheme from '../../../base/ui/components/BaseTheme.native';
// eslint-disable-next-line lines-around-comment
// @ts-ignore
import { INDICATOR_DISPLAY_THRESHOLD } from '../AbstractConnectionIndicator';
export const CONNECTOR_INDICATOR_LOST = BaseTheme.palette.ui05;

View File

@@ -0,0 +1 @@
export default {};

View File

@@ -0,0 +1 @@
export default {};

View File

@@ -0,0 +1 @@
export default {};

View File

@@ -1,18 +1,13 @@
/* eslint-disable lines-around-comment */
import { IReduxState } from '../app/types';
import { isMobileBrowser } from '../base/environment/utils';
import Platform from '../base/react/Platform';
import { URI_PROTOCOL_PATTERN } from '../base/util/uri';
import { isVpaasMeeting } from '../jaas/functions';
// @ts-ignore
import DeepLinkingDesktopPage from './components/DeepLinkingDesktopPage';
// @ts-ignore
import DeepLinkingMobilePage from './components/DeepLinkingMobilePage';
// @ts-ignore
import NoMobileApp from './components/NoMobileApp';
import { _openDesktopApp } from './openDesktopApp';
/* eslint-enable lines-around-comment */
/**
* Generates a deep linking URL based on the current window URL.

View File

@@ -12,6 +12,7 @@ import AbstractDialogTab, {
import { translate } from '../../base/i18n/functions';
import { createLocalTrack } from '../../base/lib-jitsi-meet/functions.web';
import Checkbox from '../../base/ui/components/web/Checkbox';
import { iAmVisitor as iAmVisitorCheck } from '../../visitors/functions';
import logger from '../logger';
import AudioInputPreview from './AudioInputPreview';
@@ -92,6 +93,11 @@ interface IProps extends AbstractDialogTabProps, WithTranslation {
*/
hideNoiseSuppression: boolean;
/**
* Whether we are in visitors mode.
*/
iAmVisitor: boolean;
/**
* Wether noise suppression is on or not.
*/
@@ -234,6 +240,7 @@ class AudioDevicesSelection extends AbstractDialogTab<IProps, IState> {
hideAudioOutputPreview,
hideDeviceHIDContainer,
hideNoiseSuppression,
iAmVisitor,
noiseSuppressionEnabled,
selectedAudioOutputId,
t
@@ -242,12 +249,12 @@ class AudioDevicesSelection extends AbstractDialogTab<IProps, IState> {
return (
<div className = { classes.container }>
<div
{!iAmVisitor && <div
aria-live = 'polite'
className = { classes.inputContainer }>
{this._renderSelector(audioInput)}
</div>
{!hideAudioInputPreview && hasAudioPermission
</div>}
{!hideAudioInputPreview && hasAudioPermission && !iAmVisitor
&& <AudioInputPreview
track = { this.state.previewAudioTrack } />}
<div
@@ -259,7 +266,7 @@ class AudioDevicesSelection extends AbstractDialogTab<IProps, IState> {
className = { classes.outputButton }
deviceId = { selectedAudioOutputId } />}
</div>
{!hideNoiseSuppression && (
{!hideNoiseSuppression && !iAmVisitor && (
<div className = { classes.noiseSuppressionContainer }>
<Checkbox
checked = { noiseSuppressionEnabled }
@@ -270,7 +277,7 @@ class AudioDevicesSelection extends AbstractDialogTab<IProps, IState> {
}) } />
</div>
)}
{!hideDeviceHIDContainer
{!hideDeviceHIDContainer && !iAmVisitor
&& <DeviceHidContainer />}
</div>
);
@@ -380,7 +387,8 @@ class AudioDevicesSelection extends AbstractDialogTab<IProps, IState> {
const mapStateToProps = (state: IReduxState) => {
return {
availableDevices: state['features/base/devices'].availableDevices ?? {}
availableDevices: state['features/base/devices'].availableDevices ?? {},
iAmVisitor: iAmVisitorCheck(state)
};
};

View File

@@ -1,7 +1,6 @@
import React, { useEffect, useState } from 'react';
import { makeStyles } from 'tss-react/mui';
// @ts-ignore
import JitsiMeetJS from '../../base/lib-jitsi-meet/_.web';
const JitsiTrackEvents = JitsiMeetJS.events.track;

View File

@@ -1,6 +1,5 @@
import { openDialog } from '../base/dialog/actions';
// @ts-ignore
import { DisplayNamePrompt } from './components';
/**

View File

@@ -1,2 +1 @@
// @ts-ignore
export { default as DisplayNamePrompt } from './native/DisplayNamePrompt';

View File

@@ -3,7 +3,6 @@ import { isDialogOpen } from '../base/dialog/functions';
import MiddlewareRegistry from '../base/redux/MiddlewareRegistry';
import { SETTINGS_UPDATED } from '../base/settings/actionTypes';
// @ts-ignore
import { DisplayNamePrompt } from './components';
/**

View File

@@ -1,8 +1,6 @@
import { NativeModules } from 'react-native';
import { IReduxState } from '../app/types';
// eslint-disable-next-line lines-around-comment
// @ts-ignore
import { setPictureInPictureEnabled } from '../mobile/picture-in-picture/functions';
const { Dropbox } = NativeModules;
@@ -70,8 +68,7 @@ export function getSpaceUsage(token: string, _appKey?: any) {
* @returns {boolean}
*/
export function isEnabled(state: IReduxState) {
const { dropbox = {} } = state['features/base/config'];
const { dropbox = { appKey: undefined } } = state['features/base/config'];
// @ts-ignore
return Boolean(Dropbox?.ENABLED && typeof dropbox.appKey === 'string');
}

View File

@@ -0,0 +1,3 @@
import { Component } from 'react';
export default Component;

View File

@@ -1,9 +1,6 @@
// @ts-ignore
import conferenceStyles from '../conference/components/native/styles';
import { SET_TILE_VIEW_DIMENSIONS } from './actionTypes';
// eslint-disable-next-line lines-around-comment
// @ts-ignore
import styles from './components/native/styles';
import { SQUARE_TILE_ASPECT_RATIO, TILE_MARGIN } from './constants';
import { getColumnCount, getTileViewParticipantCount } from './functions.native';
@@ -24,7 +21,7 @@ export function setTileViewDimensions() {
const { clientHeight: height, clientWidth: width, safeAreaInsets = {} } = state['features/base/responsive-ui'];
const { left = 0, right = 0, top = 0, bottom = 0 } = safeAreaInsets;
const columns = getColumnCount(state);
const rows = Math.ceil(participantCount / columns);
const rows = Math.ceil(participantCount / columns); // @ts-ignore
const conferenceBorder = conferenceStyles.conference.borderWidth || 0;
const heightToUse = height - top - bottom - (2 * conferenceBorder);
const widthToUse = width - (TILE_MARGIN * 2) - left - right - (2 * conferenceBorder);

View File

@@ -1,8 +1,6 @@
import React from 'react';
import { IconModerator } from '../../../base/icons/svg';
// eslint-disable-next-line lines-around-comment
// @ts-ignore
import BaseIndicator from '../../../base/react/components/native/BaseIndicator';
/**

View File

@@ -1306,9 +1306,17 @@ function _mapStateToProps(state: IReduxState, ownProps: any): Object {
const { thumbnailSize } = state['features/filmstrip'].tileViewDimensions ?? { thumbnailSize: undefined };
const {
stageFilmstripDimensions = {
thumbnailSize: {}
thumbnailSize: {
height: undefined,
width: undefined
}
},
screenshareFilmstripDimensions
screenshareFilmstripDimensions = {
thumbnailSize: {
height: undefined,
width: undefined
}
}
} = state['features/filmstrip'];
size = {
@@ -1317,16 +1325,19 @@ function _mapStateToProps(state: IReduxState, ownProps: any): Object {
};
if (filmstripType === FILMSTRIP_TYPE.STAGE) {
// @ts-ignore
const { width: _width, height: _height } = stageFilmstripDimensions.thumbnailSize;
const { width: _width, height: _height } = stageFilmstripDimensions.thumbnailSize ?? {
width: undefined,
height: undefined };
size = {
_width,
_height
};
} else if (filmstripType === FILMSTRIP_TYPE.SCREENSHARE) {
// @ts-ignore
const { width: _width, height: _height } = screenshareFilmstripDimensions.thumbnailSize;
const { width: _width, height: _height } = screenshareFilmstripDimensions.thumbnailSize ?? {
width: undefined,
height: undefined
};
size = {
_width,

View File

@@ -1,8 +1,6 @@
import React, { useEffect, useState } from 'react';
import AudioLevelIndicator from '../../../audio-level-indicator/components/AudioLevelIndicator';
// eslint-disable-next-line lines-around-comment
// @ts-ignore
import JitsiMeetJS from '../../../base/lib-jitsi-meet/_';
import { ITrack } from '../../../base/tracks/types';

View File

@@ -11,12 +11,9 @@ import Platform from '../base/react/Platform.native';
import { toState } from '../base/redux/functions';
import { ASPECT_RATIO_NARROW } from '../base/responsive-ui/constants';
import { getHideSelfView } from '../base/settings/functions.any';
// eslint-disable-next-line lines-around-comment
// @ts-ignore
import conferenceStyles from '../conference/components/native/styles';
import { shouldDisplayTileView } from '../video-layout/functions.native';
// @ts-ignore
import styles from './components/native/styles';
export * from './functions.any';
@@ -230,7 +227,7 @@ export function getFilmstripDimensions({
};
localParticipantVisible?: boolean;
}) {
const { height, width, margin } = styles.thumbnail;
const { height, width, margin } = styles.thumbnail; // @ts-ignore
const conferenceBorder = conferenceStyles.conference.borderWidth || 0;
const { left = 0, right = 0, top = 0, bottom = 0 } = insets;

Some files were not shown because too many files have changed in this diff Show More