Compare commits

..

1 Commits

Author SHA1 Message Date
Saúl Ibarra Corretgé
9f4c036174 fix(blur) fix model paths 2021-02-18 15:36:37 +01:00
46 changed files with 299 additions and 731 deletions

View File

@@ -115,7 +115,7 @@ import {
submitFeedback
} from './react/features/feedback';
import { showNotification } from './react/features/notifications';
import { mediaPermissionPromptVisibilityChanged, toggleSlowGUMOverlay } from './react/features/overlay';
import { mediaPermissionPromptVisibilityChanged } from './react/features/overlay';
import { suspendDetected } from './react/features/power-monitor';
import {
initPrejoin,
@@ -502,11 +502,6 @@ export default {
);
}
JitsiMeetJS.mediaDevices.addEventListener(
JitsiMediaDevicesEvents.SLOW_GET_USER_MEDIA,
() => APP.store.dispatch(toggleSlowGUMOverlay(true))
);
let tryCreateLocalTracks;
// On Electron there is no permission prompt for granting permissions. That's why we don't need to
@@ -524,10 +519,8 @@ export default {
return createLocalTracksF({
devices: [ 'audio' ],
timeout,
firePermissionPromptIsShownEvent: true,
fireSlowPromiseEvent: true
})
timeout
}, true)
.then(([ audioStream ]) =>
[ desktopStream, audioStream ])
.catch(error => {
@@ -543,10 +536,8 @@ export default {
return requestedAudio
? createLocalTracksF({
devices: [ 'audio' ],
timeout,
firePermissionPromptIsShownEvent: true,
fireSlowPromiseEvent: true
})
timeout
}, true)
: [];
})
.catch(error => {
@@ -560,10 +551,8 @@ export default {
} else {
tryCreateLocalTracks = createLocalTracksF({
devices: initialDevices,
timeout,
firePermissionPromptIsShownEvent: true,
fireSlowPromiseEvent: true
})
timeout
}, true)
.catch(err => {
if (requestedAudio && requestedVideo) {
@@ -585,10 +574,8 @@ export default {
return (
createLocalTracksF({
devices: [ 'audio' ],
timeout,
firePermissionPromptIsShownEvent: true,
fireSlowPromiseEvent: true
}));
timeout
}, true));
} else if (requestedAudio && !requestedVideo) {
errors.audioOnlyError = err;
@@ -611,9 +598,8 @@ export default {
return requestedVideo
? createLocalTracksF({
devices: [ 'video' ],
firePermissionPromptIsShownEvent: true,
fireSlowPromiseEvent: true
})
timeout
}, true)
: [];
})
.catch(err => {
@@ -633,7 +619,6 @@ export default {
// the user inputs their credentials, but the dialog would be
// overshadowed by the overlay.
tryCreateLocalTracks.then(tracks => {
APP.store.dispatch(toggleSlowGUMOverlay(false));
APP.store.dispatch(mediaPermissionPromptVisibilityChanged(false));
return tracks;
@@ -897,7 +882,7 @@ export default {
showUI && APP.store.dispatch(notifyMicError(error));
};
createLocalTracksF({ devices: [ 'audio' ] })
createLocalTracksF({ devices: [ 'audio' ] }, false)
.then(([ audioTrack ]) => audioTrack)
.catch(error => {
maybeShowErrorDialog(error);
@@ -1011,7 +996,7 @@ export default {
//
// FIXME when local track creation is moved to react/redux
// it should take care of the use case described above
createLocalTracksF({ devices: [ 'video' ] })
createLocalTracksF({ devices: [ 'video' ] }, false)
.then(([ videoTrack ]) => videoTrack)
.catch(error => {
// FIXME should send some feedback to the API on error ?

View File

@@ -240,12 +240,6 @@ var config = {
// 90: 2
// },
// Provides a way to translate the legacy bridge signaling messages, 'LastNChangedEvent',
// 'SelectedEndpointsChangedEvent' and 'ReceiverVideoConstraint' into the new 'ReceiverVideoConstraints' message
// that invokes the new bandwidth allocation algorithm in the bridge which is described here
// - https://github.com/jitsi/jitsi-videobridge/blob/master/doc/allocation.md.
// useNewBandwidthAllocationStrategy: false,
// Specify the settings for video quality optimizations on the client.
// videoQuality: {
// // Provides a way to prevent a video codec from being negotiated on the JVB connection. The codec specified

View File

@@ -1,21 +1,3 @@
/**
* Mixins that mimic the way Atlaskit fills the screen with modals at low screen widths.
*/
@mixin full-size-modal-positioner() {
height: 100%;
left: 0;
position: fixed;
top: 0;
max-width: 100%;
width: 100%;
}
@mixin full-size-modal-dialog() {
height: 100%;
max-height: 100%;
border-radius: 0;
}
/**
* Move the @atlaskit/flag container up a little bit so it does not cover the
* toolbar with the first notification.
@@ -74,43 +56,4 @@
.toolbox-button-wth-dialog > div:nth-child(2) {
max-height: calc(100vh - #{$newToolbarSizeWithPadding} - 46px);
overflow-y: auto;
}
/**
* The following selectors keep the chat modal full-size anywhere between 100px
* and 580px for desktop or 680px for mobile.
*/
@media (min-width: 100px) and (max-width: 320px) {
.smiley-input {
display: none;
}
.shift-right .focus-lock > div > div {
@include full-size-modal-positioner();
}
.shift-right .focus-lock [role="dialog"] {
@include full-size-modal-dialog();
}
}
@media (min-width: 480px) and (max-width: 580px) {
.shift-right .focus-lock > div > div {
@include full-size-modal-positioner();
}
.shift-right .focus-lock [role="dialog"] {
@include full-size-modal-dialog();
}
}
@media (min-width: 580px) and (max-width: 680px) {
.mobile-browser {
&.shift-right .focus-lock > div > div {
@include full-size-modal-positioner();
}
&.shift-right .focus-lock [role="dialog"] {
@include full-size-modal-dialog();
}
}
}
}

View File

@@ -32,13 +32,6 @@
width: $sidebarWidth;
word-wrap: break-word;
display: flex;
flex-direction: column;
& > :first-child {
margin-top: auto;
}
a {
display: block;
}
@@ -129,61 +122,16 @@
}
}
.chat-input-container {
padding: 0 16px 24px;
&.populated {
#chat-input {
border: 1px solid #619CF4;
.send-button {
background: #1B67EC;
cursor: pointer;
path {
fill: #fff;
}
}
}
}
}
#chat-input {
border: 1px solid $chatInputSeparatorColor;
border-top: 1px solid $chatInputSeparatorColor;
display: flex;
padding: 5px 10px;
border-radius: 3px;
* {
background-color: transparent;
}
}
.send-button-container {
display: flex;
align-items: center;
}
.send-button {
display: flex;
align-items: center;
justify-content: center;
height: 40px;
width: 40px;
border-radius: 3px;
path {
fill: $chatInputSeparatorColor;
}
}
.mobile-browser {
.send-button {
height: 48px;
width: 48px;
}
}
.remoteuser {
color: #B8C7E0;
}
@@ -213,47 +161,10 @@
#nickname {
text-align: center;
color: #9d9d9d;
font-size: 16px;
margin: auto 0;
padding: 0 16px;
input {
height: 40px;
}
label {
line-height: 24px;
}
.enter-chat {
display: flex;
align-items: center;
justify-content: center;
margin-top: 16px;
height: 40px;
background: #1B67EC;
border-radius: 3px;
color: #fff;
cursor: pointer;
&.disabled {
color: #757575;
background: #11336E;
pointer-events: none;
}
}
}
.mobile-browser {
#nickname {
input {
height: 48px;
}
.enter-chat {
height: 48px;
}
}
font-size: 18px;
margin-top: 30px;
left: 5px;
right: 5px;
}
.sideToolbarContainer {
@@ -500,16 +411,6 @@
#chatconversation {
width: 100%;
}
.chat-input-container {
padding: 0 0 24px;
}
}
.touchmove-hack {
display: flex;
flex: 1;
overflow: auto;
}
/**

View File

@@ -53,6 +53,21 @@
}
}
@mixin full-size-modal-positioner() {
height: 100%;
left: 0;
position: fixed;
top: 0;
max-width: 100%;
width: 100%;
}
@mixin full-size-modal-dialog() {
height: 100%;
max-height: 100%;
border-radius: 0;
}
@media only screen and (max-width: $verySmallScreen) {
.welcome {
display: block;
@@ -150,3 +165,25 @@
}
}
}
@media (min-width: 480px) and (max-width: 580px) {
.shift-right .focus-lock > div > div {
@include full-size-modal-positioner();
}
.shift-right .focus-lock [role="dialog"] {
@include full-size-modal-dialog();
}
}
@media (min-width: 580px) and (max-width: 680px) {
.mobile-browser {
&.shift-right .focus-lock > div > div {
@include full-size-modal-positioner();
}
&.shift-right .focus-lock [role="dialog"] {
@include full-size-modal-dialog();
}
}
}

View File

@@ -33,12 +33,4 @@
bottom: 24px;
width: 100%;
}
&__spinner-container {
display: flex;
width: 100%;
height: 100%;
justify-content: center;
align-items: center;
}
}

View File

@@ -20,11 +20,11 @@
- (void)sendHangUp;
- (void)sendSetAudioMuted:(BOOL)muted;
- (void)sendEndpointTextMessage:(NSString*)message :(NSString*)to;
- (void)sendEndpointTextMessage:(NSString*)to :(NSString*)message;
- (void)toggleScreenShare;
- (void)retrieveParticipantsInfo:(void (^)(NSArray*))completion;
- (void)openChat:(NSString*)to;
- (void)closeChat;
- (void)sendChatMessage:(NSString*)message :(NSString*)to ;
- (void)sendChatMessage:(NSString*)to :(NSString*)message;
@end

View File

@@ -153,7 +153,7 @@ RCT_EXPORT_METHOD(sendEvent:(NSString *)name
[self sendEventWithName:setAudioMutedAction body:data];
}
- (void)sendEndpointTextMessage:(NSString*)message :(NSString*)to {
- (void)sendEndpointTextMessage:(NSString*)to :(NSString*)message {
NSMutableDictionary *data = [[NSMutableDictionary alloc] init];
data[@"to"] = to;
data[@"message"] = message;
@@ -185,7 +185,7 @@ RCT_EXPORT_METHOD(sendEvent:(NSString *)name
[self sendEventWithName:closeChatAction body:nil];
}
- (void)sendChatMessage:(NSString*)message :(NSString*)to {
- (void)sendChatMessage:(NSString*)to :(NSString*)message {
NSMutableDictionary *data = [[NSMutableDictionary alloc] init];
data[@"to"] = to;
data[@"message"] = message;

View File

@@ -38,11 +38,11 @@
- (void)leave;
- (void)hangUp;
- (void)setAudioMuted:(BOOL)muted;
- (void)sendEndpointTextMessage:(NSString * _Nonnull)message :(NSString * _Nullable)to;
- (void)sendEndpointTextMessage:(NSString*)to :(NSString*)message;
- (void)toggleScreenShare;
- (void)retrieveParticipantsInfo:(void (^ _Nonnull)(NSArray * _Nullable))completionHandler;
- (void)openChat:(NSString * _Nullable)to;
- (void)retrieveParticipantsInfo:(void (^)(NSArray*))completionHandler;
- (void)openChat:(NSString*)to;
- (void)closeChat;
- (void)sendChatMessage:(NSString * _Nonnull)message :(NSString * _Nullable)to;
- (void)sendChatMessage:(NSString*)to :(NSString*)message;
@end

View File

@@ -125,9 +125,9 @@ static void initializeViewsMap() {
[externalAPI sendSetAudioMuted:muted];
}
- (void)sendEndpointTextMessage:(NSString * _Nonnull)message :(NSString * _Nullable)to {
- (void)sendEndpointTextMessage:(NSString*)to :(NSString*)message {
ExternalAPI *externalAPI = [[JitsiMeet sharedInstance] getExternalAPI];
[externalAPI sendEndpointTextMessage:message :to];
[externalAPI sendEndpointTextMessage:to :message];
}
- (void)toggleScreenShare {
@@ -135,7 +135,7 @@ static void initializeViewsMap() {
[externalAPI toggleScreenShare];
}
- (void)retrieveParticipantsInfo:(void (^ _Nonnull)(NSArray * _Nullable))completionHandler {
- (void)retrieveParticipantsInfo:(void (^)(NSArray*))completionHandler {
ExternalAPI *externalAPI = [[JitsiMeet sharedInstance] getExternalAPI];
[externalAPI retrieveParticipantsInfo:completionHandler];
}
@@ -150,9 +150,9 @@ static void initializeViewsMap() {
[externalAPI closeChat];
}
- (void)sendChatMessage:(NSString * _Nonnull)message :(NSString * _Nullable)to {
- (void)sendChatMessage:(NSString*)to :(NSString*)message {
ExternalAPI *externalAPI = [[JitsiMeet sharedInstance] getExternalAPI];
[externalAPI sendChatMessage:message :to];
[externalAPI sendChatMessage:to :message];
}
#pragma mark Private methods

View File

@@ -61,7 +61,6 @@
"today": "Today"
},
"chat": {
"enter": "Enter chat room",
"error": "Error: your message was not sent. Reason: {{error}}",
"fieldPlaceHolder": "Type your message here",
"messagebox": "Type a message",

4
package-lock.json generated
View File

@@ -10343,8 +10343,8 @@
}
},
"lib-jitsi-meet": {
"version": "github:jitsi/lib-jitsi-meet#6a7b16c33e27481b03e5a37636e72426c0848265",
"from": "github:jitsi/lib-jitsi-meet#6a7b16c33e27481b03e5a37636e72426c0848265",
"version": "github:jitsi/lib-jitsi-meet#c534f748849a308d08b06e306f5a66709ccae056",
"from": "github:jitsi/lib-jitsi-meet#c534f748849a308d08b06e306f5a66709ccae056",
"requires": {
"@jitsi/js-utils": "1.0.2",
"@jitsi/sdp-interop": "1.0.3",

View File

@@ -56,7 +56,7 @@
"jquery-i18next": "1.2.1",
"js-md5": "0.6.1",
"jwt-decode": "2.2.0",
"lib-jitsi-meet": "github:jitsi/lib-jitsi-meet#6a7b16c33e27481b03e5a37636e72426c0848265",
"lib-jitsi-meet": "github:jitsi/lib-jitsi-meet#c534f748849a308d08b06e306f5a66709ccae056",
"libflacjs": "github:mmig/libflac.js#93d37e7f811f01cf7d8b6a603e38bd3c3810907d",
"lodash": "4.17.19",
"moment": "2.19.4",

View File

@@ -2,9 +2,9 @@
import React, { useState } from 'react';
import { translate } from '../../base/i18n';
import { Icon, IconCheck, IconCopy } from '../../base/icons';
import { translate } from '../i18n';
import { copyText } from '../util';
import { copyText } from '../../base/util';
type Props = {

View File

@@ -53,11 +53,6 @@ type Props = {
*/
hideCancelButton: boolean,
/**
* If true, no footer will be displayed.
*/
disableFooter?: boolean,
i18n: Object,
/**
@@ -179,10 +174,6 @@ class StatelessDialog extends Component<Props> {
this._renderCancelButton()
].filter(Boolean);
if (this.props.disableFooter) {
return null;
}
return (
<ModalFooter showKeyline = { propsFromModalFooter.showKeyline } >
{

View File

@@ -11,16 +11,6 @@ export function isMobileBrowser() {
return Platform.OS === 'android' || Platform.OS === 'ios';
}
/**
* Returns whether or not the current environment is an ios mobile device.
*
* @returns {boolean}
*/
export function isIosMobileBrowser() {
return Platform.OS === 'ios';
}
/**
* Checks whether the chrome extensions defined in the config file are installed or not.
*

View File

@@ -73,7 +73,6 @@ export { default as IconOpenInNew } from './open_in_new.svg';
export { default as IconOutlook } from './office365.svg';
export { default as IconPhone } from './phone.svg';
export { default as IconPin } from './enlarge.svg';
export { default as IconPlane } from './paper-plane.svg';
export { default as IconPresentation } from './presentation.svg';
export { default as IconRaisedHand } from './raised-hand.svg';
export { default as IconRec } from './rec.svg';

View File

@@ -1,3 +0,0 @@
<svg width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M16.6667 1.66663L1.66669 10.8333L7.6326 11.8276L8.33335 17.0833L10.644 13.2323L16.6667 17.9166V1.66663ZM8.73722 10.3221L6.35041 9.92426L15 4.63839V14.5089L11.3161 11.6436L12.5 7.49996L8.73722 10.3221Z" fill="white"/>
</svg>

Before

Width:  |  Height:  |  Size: 369 B

View File

@@ -127,6 +127,7 @@ export function createLocalTracksA(options = {}) {
options.facingMode || CAMERA_FACING_MODE.USER,
micDeviceId: options.micDeviceId
},
/* firePermissionPromptIsShownEvent */ false,
store)
.then(
localTracks => {

View File

@@ -63,25 +63,16 @@ export async function createLocalPresenterTrack(options, desktopHeight) {
* @param {string|null} [options.micDeviceId] - Microphone device id or
* {@code undefined} to use app's settings.
* @param {number|undefined} [oprions.timeout] - A timeout for JitsiMeetJS.createLocalTracks used to create the tracks.
* @param {boolean} [options.firePermissionPromptIsShownEvent] - Whether lib-jitsi-meet
* @param {boolean} [firePermissionPromptIsShownEvent] - Whether lib-jitsi-meet
* should check for a {@code getUserMedia} permission prompt and fire a
* corresponding event.
* @param {boolean} [options.fireSlowPromiseEvent] - Whether lib-jitsi-meet
* should check for a slow {@code getUserMedia} request and fire a
* corresponding event.
* @param {Object} store - The redux store in the context of which the function
* is to execute and from which state such as {@code config} is to be retrieved.
* @returns {Promise<JitsiLocalTrack[]>}
*/
export function createLocalTracksF(options = {}, store) {
export function createLocalTracksF(options = {}, firePermissionPromptIsShownEvent, store) {
let { cameraDeviceId, micDeviceId } = options;
const {
desktopSharingSourceDevice,
desktopSharingSources,
firePermissionPromptIsShownEvent,
fireSlowPromiseEvent,
timeout
} = options;
const { desktopSharingSourceDevice, desktopSharingSources, timeout } = options;
if (typeof APP !== 'undefined') {
// TODO The app's settings should go in the redux store and then the
@@ -123,12 +114,11 @@ export function createLocalTracksF(options = {}, store) {
devices: options.devices.slice(0),
effects,
firefox_fake_device, // eslint-disable-line camelcase
firePermissionPromptIsShownEvent,
fireSlowPromiseEvent,
micDeviceId,
resolution,
timeout
})
},
firePermissionPromptIsShownEvent)
.catch(err => {
logger.error('Failed to create local tracks', options.devices, err);
@@ -171,10 +161,7 @@ export function createPrejoinTracks() {
// Resolve with no tracks
tryCreateLocalTracks = Promise.resolve([]);
} else {
tryCreateLocalTracks = createLocalTracksF({
devices: initialDevices,
firePermissionPromptIsShownEvent: true
})
tryCreateLocalTracks = createLocalTracksF({ devices: initialDevices }, true)
.catch(err => {
if (requestedAudio && requestedVideo) {
@@ -182,10 +169,7 @@ export function createPrejoinTracks() {
errors.audioAndVideoError = err;
return (
createLocalTracksF({
devices: [ 'audio' ],
firePermissionPromptIsShownEvent: true
}));
createLocalTracksF({ devices: [ 'audio' ] }, true));
} else if (requestedAudio && !requestedVideo) {
errors.audioOnlyError = err;
@@ -206,10 +190,7 @@ export function createPrejoinTracks() {
// Try video only...
return requestedVideo
? createLocalTracksF({
devices: [ 'video' ],
firePermissionPromptIsShownEvent: true
})
? createLocalTracksF({ devices: [ 'video' ] }, true)
: [];
})
.catch(err => {

View File

@@ -31,15 +31,24 @@ export function assignIfDefined(target: Object, source: Object) {
* @param {string} textToCopy - Text to be copied.
* @returns {boolean}
*/
export async function copyText(textToCopy: string) {
export function copyText(textToCopy: string) {
const fakeTextArea = document.createElement('textarea');
let result;
// $FlowFixMe
document.body.appendChild(fakeTextArea);
fakeTextArea.value = textToCopy;
fakeTextArea.select();
try {
result = await navigator.clipboard.writeText(textToCopy);
result = document.execCommand('copy');
} catch (err) {
result = false;
}
// $FlowFixMe
document.body.removeChild(fakeTextArea);
return result;
}

View File

@@ -20,10 +20,9 @@ export * from './actions.any';
*/
export function openChat(participant: Object) {
return function(dispatch: (Object) => Object) {
dispatch({
participant,
type: OPEN_CHAT
});
dispatch({ participant,
type: OPEN_CHAT });
VideoLayout.onResize();
};
}
@@ -41,8 +40,5 @@ export function toggleChat() {
} else {
dispatch(openChat());
}
// Recompute the large video size whenever we toggle the chat, as it takes chat state into account.
VideoLayout.onResize();
};
}

View File

@@ -4,6 +4,7 @@ import React from 'react';
import { translate } from '../../../base/i18n';
import { connect } from '../../../base/redux';
import { toggleChat } from '../../actions.web';
import AbstractChat, {
_mapStateToProps,
type Props
@@ -13,10 +14,8 @@ import ChatDialog from './ChatDialog';
import Header from './ChatDialogHeader';
import ChatInput from './ChatInput';
import DisplayNameForm from './DisplayNameForm';
import KeyboardAvoider from './KeyboardAvoider';
import MessageContainer from './MessageContainer';
import MessageRecipient from './MessageRecipient';
import TouchmoveHack from './TouchmoveHack';
/**
* React Component for holding the chat feature in a side panel that slides in
@@ -51,6 +50,7 @@ class Chat extends AbstractChat<Props> {
// Bind event handlers so they are only bound once for every instance.
this._renderPanelContent = this._renderPanelContent.bind(this);
this._onChatInputResize = this._onChatInputResize.bind(this);
this._onToggleChat = this._onToggleChat.bind(this);
}
/**
@@ -112,16 +112,13 @@ class Chat extends AbstractChat<Props> {
_renderChat() {
return (
<>
<TouchmoveHack isModal = { this.props._isModal }>
<MessageContainer
messages = { this.props._messages }
ref = { this._messageContainerRef } />
</TouchmoveHack>
<MessageContainer
messages = { this.props._messages }
ref = { this._messageContainerRef } />
<MessageRecipient />
<ChatInput
onResize = { this._onChatInputResize }
onSend = { this._onSendMessage } />
<KeyboardAvoider />
</>
);
}
@@ -135,7 +132,9 @@ class Chat extends AbstractChat<Props> {
*/
_renderChatHeader() {
return (
<Header className = 'chat-header' />
<Header
className = 'chat-header'
onCancel = { this._onToggleChat } />
);
}
@@ -199,6 +198,18 @@ class Chat extends AbstractChat<Props> {
}
_onSendMessage: (string) => void;
_onToggleChat: () => void;
/**
* Toggles the chat window.
*
* @returns {Function}
*/
_onToggleChat() {
this.props.dispatch(toggleChat());
}
}
export default translate(connect(_mapStateToProps)(Chat));

View File

@@ -24,7 +24,6 @@ function ChatDialog({ children }: Props) {
<Dialog
customHeader = { Header }
disableEnter = { true }
disableFooter = { true }
hideCancelButton = { true }
submitDisabled = { true }
titleKey = 'chat.title'>

View File

@@ -5,7 +5,7 @@ import React from 'react';
import { translate } from '../../../base/i18n';
import { Icon, IconClose } from '../../../base/icons';
import { connect } from '../../../base/redux';
import { toggleChat } from '../../actions.web';
import { closeChat } from '../../actions.any';
type Props = {
@@ -42,6 +42,6 @@ function Header({ onCancel, className, t }: Props) {
);
}
const mapDispatchToProps = { onCancel: toggleChat };
const mapDispatchToProps = { onCancel: closeChat };
export default translate(connect(null, mapDispatchToProps)(Header));

View File

@@ -6,7 +6,6 @@ import TextareaAutosize from 'react-textarea-autosize';
import type { Dispatch } from 'redux';
import { translate } from '../../../base/i18n';
import { Icon, IconPlane } from '../../../base/icons';
import { connect } from '../../../base/redux';
import SmileysPanel from './SmileysPanel';
@@ -82,7 +81,6 @@ class ChatInput extends Component<Props, State> {
this._onDetectSubmit = this._onDetectSubmit.bind(this);
this._onMessageChange = this._onMessageChange.bind(this);
this._onSmileySelect = this._onSmileySelect.bind(this);
this._onSubmitMessage = this._onSubmitMessage.bind(this);
this._onToggleSmileysPanel = this._onToggleSmileysPanel.bind(this);
this._setTextAreaRef = this._setTextAreaRef.bind(this);
}
@@ -111,40 +109,31 @@ class ChatInput extends Component<Props, State> {
? 'show-smileys' : 'hide-smileys'} smileys-panel`;
return (
<div className = { `chat-input-container${this.state.message.trim().length ? ' populated' : ''}` }>
<div id = 'chat-input' >
<div className = 'smiley-input'>
<div id = 'smileysarea'>
<div id = 'smileys'>
<Emoji
onClick = { this._onToggleSmileysPanel }
text = ':)' />
</div>
</div>
<div className = { smileysPanelClassName }>
<SmileysPanel
onSmileySelect = { this._onSmileySelect } />
<div id = 'chat-input' >
<div className = 'smiley-input'>
<div id = 'smileysarea'>
<div id = 'smileys'>
<Emoji
onClick = { this._onToggleSmileysPanel }
text = ':)' />
</div>
</div>
<div className = 'usrmsg-form'>
<TextareaAutosize
id = 'usermsg'
inputRef = { this._setTextAreaRef }
maxRows = { 5 }
onChange = { this._onMessageChange }
onHeightChange = { this.props.onResize }
onKeyDown = { this._onDetectSubmit }
placeholder = { this.props.t('chat.messagebox') }
value = { this.state.message } />
</div>
<div className = 'send-button-container'>
<div
className = 'send-button'
onClick = { this._onSubmitMessage }>
<Icon src = { IconPlane } />
</div>
<div className = { smileysPanelClassName }>
<SmileysPanel
onSmileySelect = { this._onSmileySelect } />
</div>
</div>
<div className = 'usrmsg-form'>
<TextareaAutosize
id = 'usermsg'
inputRef = { this._setTextAreaRef }
maxRows = { 5 }
onChange = { this._onMessageChange }
onHeightChange = { this.props.onResize }
onKeyDown = { this._onDetectSubmit }
placeholder = { this.props.t('chat.messagebox') }
value = { this.state.message } />
</div>
</div>
);
}
@@ -159,24 +148,6 @@ class ChatInput extends Component<Props, State> {
this._textArea && this._textArea.focus();
}
_onSubmitMessage: () => void;
/**
* Submits the message to the chat window.
*
* @returns {void}
*/
_onSubmitMessage() {
const trimmed = this.state.message.trim();
if (trimmed) {
this.props.onSend(trimmed);
this.setState({ message: '' });
}
}
_onDetectSubmit: (Object) => void;
/**
@@ -192,7 +163,13 @@ class ChatInput extends Component<Props, State> {
&& event.shiftKey === false) {
event.preventDefault();
this._onSubmitMessage();
const trimmed = this.state.message.trim();
if (trimmed) {
this.props.onSend(trimmed);
this.setState({ message: '' });
}
}
}

View File

@@ -8,8 +8,6 @@ import { translate } from '../../../base/i18n';
import { connect } from '../../../base/redux';
import { updateSettings } from '../../../base/settings';
import KeyboardAvoider from './KeyboardAvoider';
/**
* The type of the React {@code Component} props of {@DisplayNameForm}.
*/
@@ -72,24 +70,16 @@ class DisplayNameForm extends Component<Props, State> {
return (
<div id = 'nickname'>
<span>{ this.props.t('chat.nickname.title') }</span>
<form onSubmit = { this._onSubmit }>
<FieldTextStateless
autoFocus = { true }
compact = { true }
id = 'nickinput'
label = { t('chat.nickname.title') }
onChange = { this._onDisplayNameChange }
placeholder = { t('chat.nickname.popover') }
shouldFitContainer = { true }
type = 'text'
value = { this.state.displayName } />
</form>
<div
className = { `enter-chat${this.state.displayName.trim() ? '' : ' disabled'}` }
onClick = { this._onSubmit }>
{ t('chat.enter') }
</div>
<KeyboardAvoider />
</div>
);
}

View File

@@ -1,60 +0,0 @@
// @flow
import React, { useEffect, useState } from 'react';
import styled from 'styled-components';
import { isIosMobileBrowser } from '../../../base/environment/utils';
const Avoider = styled.div`
height: ${props => props.elementHeight}px;
`;
/**
* Component that renders an element to lift the chat input above the Safari keyboard,
* computing the appropriate height comparisons based on the {@code visualViewport}.
*
* @returns {ReactElement}
*/
function KeyboardAvoider() {
if (!isIosMobileBrowser()) {
return null;
}
const [ elementHeight, setElementHeight ] = useState(0);
const [ storedHeight, setStoredHeight ] = useState(window.innerHeight);
/**
* Handles the resizing of the visual viewport in order to compute
* the {@code KeyboardAvoider}'s height.
*
* @returns {void}
*/
function handleViewportResize() {
const { innerWidth, visualViewport: { width, height } } = window;
// Compare the widths to make sure the {@code visualViewport} didn't resize due to zooming.
if (width === innerWidth) {
if (height < storedHeight) {
setElementHeight(storedHeight - height);
} else {
setElementHeight(0);
}
setStoredHeight(height);
}
}
useEffect(() => {
// Call the handler in case the keyboard is open when the {@code KeyboardAvoider} is mounted.
handleViewportResize();
window.visualViewport.addEventListener('resize', handleViewportResize);
return () => {
window.visualViewport.removeEventListener('resize', handleViewportResize);
};
}, []);
return <Avoider elementHeight = { elementHeight } />;
}
export default KeyboardAvoider;

View File

@@ -1,67 +0,0 @@
// @flow
import React, { useEffect, useRef } from 'react';
import { isMobileBrowser } from '../../../base/environment/utils';
type Props = {
/**
* The component(s) that need to be scrollable on mobile.
*/
children: React$Node,
/**
* Whether the component is rendered within a modal.
*/
isModal: boolean
};
/**
* Component that disables {@code touchmove} propagation below it.
*
* @returns {ReactElement}
*/
function TouchmoveHack({ children, isModal }: Props) {
if (!isModal || !isMobileBrowser()) {
return children;
}
const touchMoveElementRef = useRef(null);
/**
* Atlaskit's {@code Modal} uses a third party library to disable touchmove events
* which makes scrolling inside dialogs impossible. We therefore employ this hack
* to intercept and stop the propagation of touchmove events from this wrapper that
* is placed around the chat conversation from the {@code ChatDialog}.
*
* @param {Event} event - The touchmove event fired within the component.
* @returns {void}
*/
function handleTouchMove(event: TouchEvent) {
event.stopImmediatePropagation();
}
useEffect(() => {
if (touchMoveElementRef && touchMoveElementRef.current) {
touchMoveElementRef.current.addEventListener('touchmove', handleTouchMove, true);
}
return () => {
if (touchMoveElementRef && touchMoveElementRef.current) {
touchMoveElementRef.current.removeEventListener('touchmove', handleTouchMove, true);
}
};
}, []);
return (
<div
className = 'touchmove-hack'
ref = { touchMoveElementRef }>
{children}
</div>
);
}
export default TouchmoveHack;

View File

@@ -58,14 +58,6 @@ const DEFAULT_STATE = {
*/
defaultBranding: true,
/**
* Url for a custom page for DID numbers list.
*
* @public
* @type {string}
*/
didPageUrl: '',
/**
* The custom invite domain.
*
@@ -109,7 +101,6 @@ ReducerRegistry.register(STORE_NAME, (state = DEFAULT_STATE, action) => {
backgroundColor,
backgroundImageUrl,
defaultBranding,
didPageUrl,
inviteDomain,
logoClickUrl,
logoImageUrl
@@ -119,7 +110,6 @@ ReducerRegistry.register(STORE_NAME, (state = DEFAULT_STATE, action) => {
backgroundColor,
backgroundImageUrl,
defaultBranding,
didPageUrl,
inviteDomain,
logoClickUrl,
logoImageUrl,

View File

@@ -1,12 +1,14 @@
// @flow
import React, { useEffect } from 'react';
import React, { useState, useEffect } from 'react';
import { createInviteDialogEvent, sendAnalytics } from '../../../../analytics';
import { getRoomName } from '../../../../base/conference';
import { getInviteURL } from '../../../../base/connection';
import { Dialog } from '../../../../base/dialog';
import { translate } from '../../../../base/i18n';
import { JitsiRecordingConstants } from '../../../../base/lib-jitsi-meet';
import { getLocalParticipant } from '../../../../base/participants';
import { connect } from '../../../../base/redux';
import { isVpaasMeeting } from '../../../../billing-counter/functions';
import EmbedMeetingTrigger from '../../../../embed-meeting/components/EmbedMeetingTrigger';
@@ -24,6 +26,11 @@ declare var interfaceConfig: Object;
type Props = {
/**
* The name of the current conference. Used as part of inviting users.
*/
_conferenceName: string,
/**
* The object representing the dialIn feature.
*/
@@ -34,11 +41,6 @@ type Props = {
*/
_embedMeetingVisible: boolean,
/**
* The meeting invitation text.
*/
_invitationText: string,
/**
* Whether or not invite contacts should be visible.
*/
@@ -55,9 +57,14 @@ type Props = {
_liveStreamViewURL: string,
/**
* The default phone number.
* The redux representation of the local participant.
*/
_phoneNumber: ?string,
_localParticipantName: ?string,
/**
* The current location url of the conference.
*/
_locationUrl: Object,
/**
* Invoked to obtain translated strings.
@@ -76,15 +83,17 @@ type Props = {
* @returns {React$Element<any>}
*/
function AddPeopleDialog({
_conferenceName,
_dialIn,
_embedMeetingVisible,
_invitationText,
_inviteContactsVisible,
_inviteUrl,
_liveStreamViewURL,
_phoneNumber,
_localParticipantName,
_locationUrl,
t,
updateNumbers }: Props) {
const [ phoneNumber, setPhoneNumber ] = useState(undefined);
/**
* Updates the dial-in numbers.
@@ -110,6 +119,27 @@ function AddPeopleDialog({
};
}, []);
/**
* Updates the phone number in the state once the dial-in numbers are fetched.
*
* @returns {void}
*/
useEffect(() => {
if (!phoneNumber && _dialIn && _dialIn.numbers) {
setPhoneNumber(_getDefaultPhoneNumber(_dialIn.numbers));
}
}, [ _dialIn ]);
const invite = getInviteText({
_conferenceName,
_localParticipantName,
_inviteUrl,
_locationUrl,
_dialIn,
_liveStreamViewURL,
phoneNumber,
t
});
const inviteSubject = t('addPeople.inviteMoreMailSubject', {
appName: interfaceConfig.APP_NAME
});
@@ -126,7 +156,7 @@ function AddPeopleDialog({
<CopyMeetingLinkSection url = { _inviteUrl } />
<InviteByEmailSection
inviteSubject = { inviteSubject }
inviteText = { _invitationText } />
inviteText = { invite } />
{ _embedMeetingVisible && <EmbedMeetingTrigger /> }
<div className = 'invite-more-dialog separator' />
{
@@ -135,7 +165,11 @@ function AddPeopleDialog({
}
{
_dialIn.numbers
&& <DialInSection phoneNumber = { _phoneNumber } />
&& <DialInSection
conferenceName = { _conferenceName }
dialIn = { _dialIn }
locationUrl = { _locationUrl }
phoneNumber = { phoneNumber } />
}
</div>
</Dialog>
@@ -147,32 +181,29 @@ function AddPeopleDialog({
* {@code AddPeopleDialog} component.
*
* @param {Object} state - The Redux state.
* @param {Object} ownProps - The properties explicitly passed to the component.
* @private
* @returns {Props}
*/
function mapStateToProps(state, ownProps) {
function mapStateToProps(state) {
const localParticipant = getLocalParticipant(state);
const currentLiveStreamingSession
= getActiveSession(state, JitsiRecordingConstants.mode.STREAM);
const { iAmRecorder } = state['features/base/config'];
const addPeopleEnabled = isAddPeopleEnabled(state);
const dialOutEnabled = isDialOutEnabled(state);
const hideInviteContacts = iAmRecorder || (!addPeopleEnabled && !dialOutEnabled);
const dialIn = state['features/invite'];
const phoneNumber = dialIn && dialIn.numbers ? _getDefaultPhoneNumber(dialIn.numbers) : undefined;
return {
_dialIn: dialIn,
_conferenceName: getRoomName(state),
_dialIn: state['features/invite'],
_embedMeetingVisible: !isVpaasMeeting(state),
_invitationText: getInviteText({ state,
phoneNumber,
t: ownProps.t }),
_inviteContactsVisible: interfaceConfig.ENABLE_DIAL_OUT && !hideInviteContacts,
_inviteUrl: getInviteURL(state),
_liveStreamViewURL:
currentLiveStreamingSession
&& currentLiveStreamingSession.liveStreamViewURL,
_phoneNumber: phoneNumber
_localParticipantName: localParticipant?.name,
_locationUrl: state['features/base/connection'].locationURL
};
}

View File

@@ -3,7 +3,6 @@
import React from 'react';
import { translate } from '../../../../base/i18n';
import { connect } from '../../../../base/redux';
import { getDialInfoPageURL } from '../../../functions';
import DialInNumber from './DialInNumber';
@@ -11,14 +10,19 @@ import DialInNumber from './DialInNumber';
type Props = {
/**
* The object representing the dialIn feature.
* The name of the current conference. Used as part of inviting users.
*/
_dialIn: Object,
conferenceName: string,
/**
* The url of the page containing the dial-in numbers list.
* The object representing the dialIn feature.
*/
_dialInfoPageUrl: string,
dialIn: Object,
/**
* The current location url of the conference.
*/
locationUrl: Object,
/**
* The phone number to dial to begin the process of dialing into a
@@ -41,19 +45,25 @@ type Props = {
* @returns {null|ReactElement}
*/
function DialInSection({
_dialIn,
_dialInfoPageUrl,
conferenceName,
dialIn,
locationUrl,
phoneNumber,
t
}: Props) {
return (
<div className = 'invite-more-dialog dial-in-display'>
<DialInNumber
conferenceID = { _dialIn.conferenceID }
conferenceID = { dialIn.conferenceID }
phoneNumber = { phoneNumber } />
<a
className = 'more-numbers'
href = { _dialInfoPageUrl }
href = {
getDialInfoPageURL(
conferenceName,
locationUrl
)
}
rel = 'noopener noreferrer'
target = '_blank'>
{ t('info.moreNumbers') }
@@ -62,20 +72,4 @@ function DialInSection({
);
}
/**
* Maps (parts of) the Redux state to the associated props for the
* {@code DialInLink} component.
*
* @param {Object} state - The Redux state.
* @private
* @returns {Props}
*/
function _mapStateToProps(state) {
return {
_dialIn: state['features/invite'],
_dialInfoPageUrl: getDialInfoPageURL(state)
};
}
export default translate(connect(_mapStateToProps)(DialInSection));
export default translate(DialInSection);

View File

@@ -1,11 +1,7 @@
// @flow
import { getActiveSession } from '../../features/recording/functions';
import { getRoomName } from '../base/conference';
import { getInviteURL } from '../base/connection';
import { i18next } from '../base/i18n';
import { JitsiRecordingConstants } from '../base/lib-jitsi-meet';
import { getLocalParticipant, isLocalParticipantModerator } from '../base/participants';
import { isLocalParticipantModerator } from '../base/participants';
import { toState } from '../base/redux';
import { doGetJSON, parseURIString } from '../base/util';
import { isVpaasMeeting } from '../billing-counter/functions';
@@ -243,44 +239,43 @@ export function getInviteResultsForQuery(
* @returns {string}
*/
export function getInviteText({
state,
_conferenceName,
_localParticipantName,
_inviteUrl,
_locationUrl,
_dialIn,
_liveStreamViewURL,
phoneNumber,
t
}: Object) {
const dialIn = state['features/invite'];
const inviteUrl = getInviteURL(state);
const currentLiveStreamingSession = getActiveSession(state, JitsiRecordingConstants.mode.STREAM);
const liveStreamViewURL
= currentLiveStreamingSession
&& currentLiveStreamingSession.liveStreamViewURL;
const localParticipant = getLocalParticipant(state);
const localParticipantName = localParticipant?.name;
const inviteURL = _decodeRoomURI(_inviteUrl);
const inviteURL = _decodeRoomURI(inviteUrl);
let invite = localParticipantName
? t('info.inviteURLFirstPartPersonal', { name: localParticipantName })
let invite = _localParticipantName
? t('info.inviteURLFirstPartPersonal', { name: _localParticipantName })
: t('info.inviteURLFirstPartGeneral');
invite += t('info.inviteURLSecondPart', {
url: inviteURL
});
if (liveStreamViewURL) {
if (_liveStreamViewURL) {
const liveStream = t('info.inviteLiveStream', {
url: liveStreamViewURL
url: _liveStreamViewURL
});
invite = `${invite}\n${liveStream}`;
}
if (shouldDisplayDialIn(dialIn)) {
if (shouldDisplayDialIn(_dialIn)) {
const dial = t('info.invitePhone', {
number: phoneNumber,
conferenceID: dialIn.conferenceID
conferenceID: _dialIn.conferenceID
});
const moreNumbers = t('info.invitePhoneAlternatives', {
url: getDialInfoPageURL(state),
url: getDialInfoPageURL(
_conferenceName,
_locationUrl
),
silentUrl: `${inviteURL}#config.startSilent=true`
});
@@ -519,7 +514,9 @@ export function getShareInfoText(
.catch(error =>
logger.error('Error fetching numbers or conferenceID', error))
.then(defaultDialInNumber => {
let dialInfoPageUrl = getDialInfoPageURL(state);
let dialInfoPageUrl = getDialInfoPageURL(
room,
state['features/base/connection'].locationURL);
if (useHtml) {
dialInfoPageUrl
@@ -540,19 +537,28 @@ export function getShareInfoText(
/**
* Generates the URL for the static dial in info page.
*
* @param {Object} state - The state from the Redux store.
* @param {string} conferenceName - The conference name.
* @param {Object} locationURL - The current location URL, the object coming
* from state ['features/base/connection'].locationURL.
* @returns {string}
*/
export function getDialInfoPageURL(state: Object) {
const { didPageUrl } = state['features/dynamic-branding'];
const conferenceName = getRoomName(state);
const { locationURL } = state['features/base/connection'];
const { href } = locationURL;
const room = _decodeRoomURI(conferenceName);
export function getDialInfoPageURL(
conferenceName: string,
locationURL: Object) {
const origin = locationURL.origin;
const pathParts = locationURL.pathname.split('/');
const url = didPageUrl || `${href.substring(0, href.lastIndexOf('/'))}/static/dialInInfo.html`;
pathParts.length = pathParts.length - 1;
return `${url}?room=${room}`;
const newPath = pathParts.reduce((accumulator, currentValue) => {
if (currentValue) {
return `${accumulator}/${currentValue}`;
}
return accumulator;
}, '');
return `${origin}${newPath}/static/dialInInfo.html?room=${_decodeRoomURI(conferenceName)}`;
}
/**

View File

@@ -6,7 +6,7 @@ import { getFirstLoadableAvatarUrl, getParticipantDisplayName } from '../base/pa
import { MiddlewareRegistry, StateListenerRegistry } from '../base/redux';
import { isTestModeEnabled } from '../base/testing';
import { NOTIFICATION_TYPE, showNotification } from '../notifications';
import { shouldAutoKnock } from '../prejoin/functions';
import { isPrejoinPageEnabled } from '../prejoin/functions';
import { KNOCKING_PARTICIPANT_ARRIVED_OR_UPDATED } from './actionTypes';
import {
@@ -100,7 +100,8 @@ function _conferenceFailed({ dispatch, getState }, next, action) {
dispatch(openLobbyScreen());
if (shouldAutoKnock(state)) {
if (isPrejoinPageEnabled(state) && !state['features/lobby'].knocking) {
// prejoin is enabled, so we knock automatically
dispatch(startKnocking());
}

View File

@@ -11,16 +11,22 @@ import { getDialInfoPageURL, shouldDisplayDialIn } from '../../invite';
*/
type Props = {
/**
* The name of the current conference.
*/
_room: string,
/**
* The current location url of the conference.
*/
_locationURL: string,
/**
* The redux state representing the dial-in numbers feature.
*/
_dialIn: Object,
/**
* The url of the page containing the dial-in numbers list.
*/
_dialInfoPageUrl: string,
/**
* Invoked to obtain translated strings.
*/
@@ -41,7 +47,7 @@ class DialInLink extends Component<Props> {
* @returns {ReactElement}
*/
render() {
const { _dialIn, _dialInfoPageUrl, t } = this.props;
const { _room, _locationURL, _dialIn, t } = this.props;
if (!shouldDisplayDialIn(_dialIn)) {
return null;
@@ -50,7 +56,12 @@ class DialInLink extends Component<Props> {
return (
<div>{t('toolbar.noAudioSignalDialInDesc')}&nbsp;
<a
href = { _dialInfoPageUrl }
href = {
getDialInfoPageURL(
_room,
_locationURL
)
}
rel = 'noopener noreferrer'
target = '_blank'>
{t('toolbar.noAudioSignalDialInLinkDesc')}
@@ -66,12 +77,18 @@ class DialInLink extends Component<Props> {
*
* @param {Object} state - The Redux state.
* @private
* @returns {Props}
*/
* @returns {{
* _room: string,
* _locationURL: string,
* _dialIn: Object,
* }}
*/
function _mapStateToProps(state) {
return {
_dialIn: state['features/invite'],
_dialInfoPageUrl: getDialInfoPageURL(state)
_room: state['features/base/conference'].room,
_locationURL: state['features/base/connection'].locationURL,
_dialIn: state['features/invite']
};
}

View File

@@ -14,17 +14,6 @@
export const MEDIA_PERMISSION_PROMPT_VISIBILITY_CHANGED
= 'MEDIA_PERMISSION_PROMPT_VISIBILITY_CHANGED';
/**
* The type of the Redux action which signals that the overlay for slow gUM is visible or not.
*
* {
* type: TOGGLE_SLOW_GUM_OVERLAY,
* isVisible: {boolean},
* }
* @public
*/
export const TOGGLE_SLOW_GUM_OVERLAY = 'TOGGLE_SLOW_GUM_OVERLAY';
/**
* Adjust the state of the fatal error which shows/hides the reload screen. See
* action methods's description for more info about each of the fields.

View File

@@ -2,8 +2,7 @@
import {
MEDIA_PERMISSION_PROMPT_VISIBILITY_CHANGED,
SET_FATAL_ERROR,
TOGGLE_SLOW_GUM_OVERLAY
SET_FATAL_ERROR
} from './actionTypes';
/**
@@ -27,24 +26,6 @@ export function mediaPermissionPromptVisibilityChanged(isVisible: boolean, brows
};
}
/**
* Signals that the prompt for media permission is visible or not.
*
* @param {boolean} isVisible - If the value is true - the prompt for media
* permission is visible otherwise the value is false/undefined.
* @public
* @returns {{
* type: SLOW_GET_USER_MEDIA_OVERLAY,
* isVisible: {boolean}
* }}
*/
export function toggleSlowGUMOverlay(isVisible: boolean) {
return {
type: TOGGLE_SLOW_GUM_OVERLAY,
isVisible
};
}
/**
* The action indicates that an unrecoverable error has occurred and the reload
* screen will be displayed or hidden.

View File

@@ -1,33 +0,0 @@
// @flow
import { Component } from 'react';
/**
* The type of the React {@code Component} props of
* {@link AbstractSlowGUMOverlay}.
*/
type Props = {
/**
* The function to translate human-readable text.
*/
t: Function
};
/**
* Implements a React {@link Component} for slow gUM overlay. Shown when
* a slow gUM promise resolution is detected
*/
export default class AbstractSlowGUMOverlay extends Component<Props> {
/**
* Determines whether this overlay needs to be rendered (according to a
* specific redux state). Called by {@link OverlayContainer}.
*
* @param {Object} state - The redux state.
* @returns {boolean} - If this overlay needs to be rendered, {@code true};
* {@code false}, otherwise.
*/
static needsRender(state: Object) {
return state['features/overlay'].isSlowGUMOverlayVisible;
}
}

View File

@@ -1,36 +0,0 @@
// @flow
import Spinner from '@atlaskit/spinner';
import React from 'react';
import { translate } from '../../../base/i18n';
import AbstractSlowGUMOverlay from './AbstractSlowGUMOverlay';
import OverlayFrame from './OverlayFrame';
/**
* Implements a React {@link Component} for slow gUM overlay. Shown when
* a slow gUM promise resolution is detected
*/
class SlowGUMOverlay extends AbstractSlowGUMOverlay {
/**
* Implements React's {@link Component#render()}.
*
* @inheritdoc
* @returns {ReactElement}
*/
render() {
// const { t } = this.props;
return (
<OverlayFrame>
<div className = { 'overlay__spinner-container' }>
<Spinner
invertColor = { true }
size = { 'large' } />
</div>
</OverlayFrame>
);
}
}
export default translate(SlowGUMOverlay);

View File

@@ -5,4 +5,3 @@ export { default as OverlayFrame } from './OverlayFrame';
export { default as PageReloadOverlay } from './PageReloadOverlay';
export { default as SuspendedOverlay } from './SuspendedOverlay';
export { default as UserMediaPermissionsOverlay } from './UserMediaPermissionsOverlay';
export { default as SlowGUMOverlay } from './SlowGUMOverlay';

View File

@@ -2,7 +2,6 @@
import {
PageReloadOverlay,
SlowGUMOverlay,
SuspendedOverlay,
UserMediaPermissionsOverlay
} from './components/web';
@@ -18,7 +17,6 @@ export function getOverlays(): Array<Object> {
return [
PageReloadOverlay,
SuspendedOverlay,
UserMediaPermissionsOverlay,
SlowGUMOverlay
UserMediaPermissionsOverlay
];
}

View File

@@ -5,8 +5,7 @@ import { assign, ReducerRegistry, set } from '../base/redux';
import {
MEDIA_PERMISSION_PROMPT_VISIBILITY_CHANGED,
SET_FATAL_ERROR,
TOGGLE_SLOW_GUM_OVERLAY
SET_FATAL_ERROR
} from './actionTypes';
/**
@@ -29,8 +28,6 @@ ReducerRegistry.register('features/overlay', (state = { }, action) => {
case SET_FATAL_ERROR:
return _setFatalError(state, action);
case TOGGLE_SLOW_GUM_OVERLAY:
return _toggleSlowGUMOverlay(state, action);
}
return state;
@@ -55,24 +52,6 @@ function _mediaPermissionPromptVisibilityChanged(
});
}
/**
* Reduces a specific redux action TOGGLE_SLOW_GUM_OVERLAY of
* the feature overlay.
*
* @param {Object} state - The redux state of the feature overlay.
* @param {Action} action - The redux action to reduce.
* @private
* @returns {Object} The new state of the feature overlay after the reduction of
* the specified action.
*/
function _toggleSlowGUMOverlay(
state,
{ isVisible }) {
return assign(state, {
isSlowGUMOverlayVisible: isVisible
});
}
/**
* Sets the {@code LoadConfigOverlay} overlay visible or not.
*

View File

@@ -4,6 +4,7 @@ declare var JitsiMeetJS: Object;
import uuid from 'uuid';
import { getRoomName } from '../base/conference';
import { getDialOutStatusUrl, getDialOutUrl } from '../base/config/functions';
import { createLocalTrack } from '../base/lib-jitsi-meet';
import {
@@ -261,7 +262,10 @@ export function makePrecallTest(conferenceOptions: Object) {
*/
export function openDialInPage() {
return function(dispatch: Function, getState: Function) {
const dialInPage = getDialInfoPageURL(getState());
const state = getState();
const locationURL = state['features/base/connection'].locationURL;
const roomName = getRoomName(state);
const dialInPage = getDialInfoPageURL(roomName, locationURL);
openURLInBrowser(dialInPage, true);
};

View File

@@ -162,16 +162,3 @@ export function isPrejoinPageEnabled(state: Object): boolean {
export function isPrejoinPageVisible(state: Object): boolean {
return isPrejoinPageEnabled(state) && state['features/prejoin']?.showPrejoin;
}
/**
* Returns true if we should auto-knock in case lobby is enabled for the room.
*
* @param {Object} state - The state of the app.
* @returns {boolean}
*/
export function shouldAutoKnock(state: Object): boolean {
const { iAmRecorder, iAmSipGateway } = state['features/base/config'];
return (isPrejoinPageEnabled(state) || (iAmRecorder && iAmSipGateway))
&& !state['features/lobby'].knocking;
}

View File

@@ -34,10 +34,6 @@ export async function createBlurEffect() {
models['144']
);
if (!modelResponse.ok) {
throw new Error('Failed to download tflite model!');
}
const model = await modelResponse.arrayBuffer();
tflite.HEAPU8.set(new Uint8Array(model), modelBufferOffset);

View File

@@ -216,7 +216,7 @@ function onConnectionSuccess() {
devices.push('video');
}
if (localAudio || autoCreateLocalAudio) {
if (autoCreateLocalAudio) {
devices.push('audio');
}