Compare commits

..

1 Commits

Author SHA1 Message Date
George Politis
c91aef29a3 fix: Makes the code more defensive to prevent an error. 2020-10-05 14:56:34 +02:00
23 changed files with 265 additions and 145 deletions

View File

@@ -1,5 +1,4 @@
import groovy.json.JsonSlurper
import org.gradle.util.VersionNumber
// Top-level build file where you can add configuration options common to all
// sub-projects/modules.

View File

@@ -89,9 +89,7 @@ fi
# Now build and publish the Jitsi Meet SDK and its dependencies
echo "Building and publishing the Jitsi Meet SDK"
pushd ${THIS_DIR}/../
./gradlew clean
./gradlew assembleRelease
./gradlew publish
./gradlew clean assembleRelease publish
popd
if [[ $DO_GIT_TAG == 1 ]]; then

View File

@@ -323,6 +323,10 @@ var config = {
// is set in Jicofo and set to 2).
// minParticipants: 2,
// Use the TURN servers discovered via XEP-0215 for the jitsi-videobridge
// connection
// useStunTurn: true,
// Use TURN/UDP servers for the jitsi-videobridge connection (by default
// we filter out TURN/UDP because it is usually not needed since the
// bridge itself is reachable via UDP)
@@ -438,6 +442,9 @@ var config = {
// connection.
enabled: true,
// Use XEP-0215 to fetch STUN and TURN servers.
// useStunTurn: true,
// The STUN servers that will be used in the peer to peer connections
stunServers: [

View File

@@ -1,30 +1,30 @@
.con-status {
position: absolute;
top: 24px;
top: 40px;
width: 100%;
z-index: $toolbarZ + 3;
&-container {
background: rgba(28, 32, 37, .5);
border-radius: 3px;
color: #fff;
font-size: 13px;
line-height: 13px;
line-height: 20px;
margin: 0 auto;
width: 320px;
width: 304px;
}
&-header {
background: rgba(28, 32, 37, .5);
align-items: center;
display: flex;
justify-content: space-between;
padding: 8px;
}
&-circle {
border-radius: 50%;
display: inline-block;
padding: 4px;
margin: 8px;
}
&--good {
@@ -40,16 +40,6 @@
}
&-arrow {
height: 36px;
width: 36px;
border-radius: 3px;
margin-left: 8px;
margin-right: 2px;
display: flex;
align-items: center;
justify-content: center;
transition: background-color 0.16s ease-out;
&--up {
transform: rotate(180deg);
}
@@ -57,10 +47,6 @@
&>svg {
cursor: pointer;
}
&:hover {
background-color: rgba(1,1,1, 0.1);
}
}
&-text {
@@ -68,17 +54,7 @@
}
&-details {
background: rgba(28, 32, 37, .5);
border-top: 1px solid #5E6D7A;
padding: 16px;
transition: opacity 0.16s ease-out;
&-visible {
opacity: 1;
}
&-hidden {
opacity: 0;
}
}
}

View File

@@ -14,6 +14,19 @@
margin: 10px;
}
}
.form {
align-items: stretch;
display: flex;
flex-direction: column;
min-width: 400px;
}
.participant-info {
align-items: center;
display: flex;
flex-direction: column;
}
}
}
@@ -87,6 +100,19 @@
}
}
input {
align-self: stretch;
background-color: transparent;
border: 1px solid #B8C7E0;
border-radius: 4px;
color: white;
padding: 12px 8px;
&:focus {
border-color: rgb(3, 118, 218);
}
}
button {
align-self: stretch;
margin: 8px 0;

View File

@@ -3,6 +3,7 @@
&-input-area {
margin: 0 auto;
text-align: center;
width: 320px;
}
&-title {
@@ -41,11 +42,9 @@
&-error {
color: white;
background-color: rgba(225, 45, 45, 0.6);
border-radius: 3px;
background-color: rgba(229, 75, 75, 0.5);
width: 100%;
padding: 2px;
box-sizing: border-box;
padding: 3px;
margin-top: 4px;
font-size: 13px;
text-align: center;
@@ -59,6 +58,75 @@
}
.prejoin-preview {
height: 100%;
position: absolute;
width: 100%;
&--no-video {
background: radial-gradient(50% 50% at 50% 50%, #5B6F80 0%, #365067 100%), #FFFFFF;
text-align: center;
}
&-video {
height: 100%;
object-fit: cover;
position: absolute;
width: 100%;
}
&-name {
color: #fff;
font-size: 19px;
line-height: 28px;
&--editable {
background: none;
border: 0;
border-bottom: 1px solid #D1DBE8;
margin: 24px 0 16px 0;
outline: none;
text-align: center;
width: 100%;
&::-webkit-input-placeholder {
@include name-placeholder;
}
&::-moz-placeholder {
@include name-placeholder;
}
&:-ms-input-placeholder {
@include name-placeholder;
}
}
&--text {
margin: 16px 0;
outline: none;
}
}
&-avatar.avatar {
background: #A4B8D1;
margin: 200px auto 0 auto;
}
&-overlay {
height: 100%;
position: absolute;
width: 100%;
z-index: 1;
background: linear-gradient(0deg, rgba(0, 0, 0, 0.3), rgba(0, 0, 0, 0.3));
}
&-bottom-overlay {
background: linear-gradient(180deg, rgba(0, 0, 0, 0) 0%, rgba(0, 0, 0, 0.9) 100%);
bottom: 0;
height: 50%;
position: absolute;
width: 100%;
z-index: 1;
}
&-status {
align-items: center;
align-self: stretch;

View File

@@ -12,23 +12,12 @@
.premeeting-screen {
align-items: stretch;
background: radial-gradient(50% 50% at 50% 50%, #2A3A4B 20.83%, #1E2A36 100%);
background: radial-gradient(50% 50% at 50% 50%, #5D95C7 0%, #376288 100%), #FFFFFF;
display: flex;
flex-direction: column;
font-size: 1.3em;
z-index: $toolbarZ + 1;
&-avatar {
background-color: #A4B8D1;
margin-bottom: 24px;
text {
fill: black;
font-size: 26px;
font-weight: 400;
}
}
.action-btn {
border-radius: 3px;
color: #fff;
@@ -70,26 +59,22 @@
fill: #AFB6BC;
}
}
.options {
border-left: 1px solid #AFB6BC;
}
}
.options {
border-radius: 3px;
align-items: center;
border-left: 1px solid #fff;
display: flex;
height: 100%;
justify-content: center;
position: absolute;
right: 0;
top: 0;
width: 36px;
&:hover {
background-color: #0262B6;
}
svg {
pointer-events: none;
}
width: 40px;
}
}
@@ -126,14 +111,12 @@
margin-bottom: 16px;
.url {
background: rgba(28, 32, 37, 0.5);
border-radius: 4px;
display: flex;
padding: 8px 10px;
transition: background 0.16s ease-out;
&:hover {
background: #1C2025;
border-radius: 4px;
}
&.done {
@@ -166,23 +149,20 @@
}
input.field {
background-color: white;
border: none;
outline: none;
border-radius: 3px;
font-size: 15px;
line-height: 24px;
color: #1C2025;
background-color: transparent;
border: 1px solid transparent;
color: white;
outline-width: 0;
padding: 8px 0;
text-align: center;
width: 320px;
&.error {
box-shadow: 0px 0px 4px 3px rgba(225, 45, 45, 0.4);
}
width: 100%;
&.focused {
box-shadow: 0px 0px 4px 3px #0376DA;
border-bottom: 1px solid white;
}
&.error::placeholder {
color: $defaultWarningColor;
}
}
}
@@ -190,7 +170,7 @@
.media-btn-container {
display: flex;
justify-content: center;
margin: 24px 0 16px 0;
margin: 32px 0;
width: 100%;
&> div {
@@ -253,7 +233,6 @@
font-size: 13px;
height: 40px;
margin: 0 auto;
transition: background 0.16s ease-out;
width: 320px;
@include flex-centered();
@@ -263,7 +242,7 @@
}
&:hover {
background: rgba(255, 255, 255, 0.1);
background: #1C2025;
@include icon-container(#A4B8D1, #1C2025);
}
@@ -282,6 +261,14 @@
}
&--toggled {
@include icon-container(white, #1C2025);
background: #75757A;
&:hover {
background: #75757A;
@include icon-container(#A4B8D1, #75757A);
}
@include icon-container(#A4B8D1, #75757A);
}
}

View File

@@ -150,6 +150,11 @@ denied-peer-ip=240.0.0.0-255.255.255.255" >> $TURN_CONFIG
echo "------------------------------------------------"
fi
# Enable turn server in config.js
if [ -f $JITSI_MEET_CONFIG ] ; then
sed -i "s/\/\/ useStunTurn: true/useStunTurn: true/g" $JITSI_MEET_CONFIG
fi
# and we're done with debconf
db_stop
;;

View File

@@ -536,7 +536,7 @@
"dialInMeeting": "Dial into the meeting",
"dialInPin": "Dial into the meeting and enter PIN code:",
"dialing": "Dialing",
"doNotShow": "Don't show this screen again",
"doNotShow": "Don't show this again",
"errorDialOut": "Could not dial out",
"errorDialOutDisconnected": "Could not dial out. Disconnected",
"errorDialOutFailed": "Could not dial out. Call failed",

4
package-lock.json generated
View File

@@ -10778,8 +10778,8 @@
}
},
"lib-jitsi-meet": {
"version": "github:jitsi/lib-jitsi-meet#f370cccdfba6f9190ecb4afc3d78552d9f3ad57c",
"from": "github:jitsi/lib-jitsi-meet#f370cccdfba6f9190ecb4afc3d78552d9f3ad57c",
"version": "github:jitsi/lib-jitsi-meet#0cffc064e644ad87ff381cc6c4df1c1a9f2c73ff",
"from": "github:jitsi/lib-jitsi-meet#0cffc064e644ad87ff381cc6c4df1c1a9f2c73ff",
"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#f370cccdfba6f9190ecb4afc3d78552d9f3ad57c",
"lib-jitsi-meet": "github:jitsi/lib-jitsi-meet#0cffc064e644ad87ff381cc6c4df1c1a9f2c73ff",
"libflacjs": "github:mmig/libflac.js#93d37e7f811f01cf7d8b6a603e38bd3c3810907d",
"lodash": "4.17.19",
"moment": "2.19.4",

View File

@@ -37,11 +37,6 @@ export type Props = {
*/
displayName?: string,
/**
* Whether or not to update the background color of the avatar
*/
dynamicColor?: Boolean,
/**
* ID of the element, if any.
*/
@@ -83,15 +78,6 @@ export const DEFAULT_SIZE = 65;
* Implements a class to render avatars in the app.
*/
class Avatar<P: Props> extends PureComponent<P, State> {
/**
* Default values for {@code Avatar} component's properties.
*
* @static
*/
static defaultProps = {
dynamicColor: true
};
/**
* Instantiates a new {@code Component}.
*
@@ -137,7 +123,6 @@ class Avatar<P: Props> extends PureComponent<P, State> {
_loadableAvatarUrl,
className,
colorBase,
dynamicColor,
id,
size,
status,
@@ -171,10 +156,7 @@ class Avatar<P: Props> extends PureComponent<P, State> {
const initials = getInitials(_initialsBase);
if (initials) {
if (dynamicColor) {
avatarProps.color = getAvatarColor(colorBase || _initialsBase);
}
avatarProps.color = getAvatarColor(colorBase || _initialsBase);
avatarProps.initials = initials;
}

View File

@@ -3,7 +3,7 @@ import extraConfigWhitelist from './extraConfigWhitelist';
/**
* The config keys to whitelist, the keys that can be overridden.
* Currently we can only whitelist the first part of the properties, like
* 'p2p.enabled' we whitelist all p2p options.
* 'p2p.useStunTurn' and 'p2p.enabled' we whitelist all p2p options.
* The whitelist is used only for config.js.
*
* @type Array
@@ -149,6 +149,7 @@ export default [
'stereo',
'subject',
'testing',
'useStunTurn',
'useTurnUdp',
'videoQuality.persist',
'webrtcIceTcpDisable',

View File

@@ -1,3 +0,0 @@
<svg width="10" height="7" viewBox="0 0 10 7" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M8.41115 6.05746C8.71903 6.39955 9.24594 6.42729 9.58803 6.1194C9.93012 5.81152 9.95786 5.28461 9.64997 4.94252L5.72917 0.562752C5.39813 0.194935 4.82138 0.194935 4.49034 0.562752L0.63061 4.94252C0.322728 5.28461 0.35046 5.81152 0.692552 6.1194C1.03464 6.42729 1.56155 6.39955 1.86943 6.05746L5.10975 2.36593L8.41115 6.05746Z" fill="white"/>
</svg>

Before

Width:  |  Height:  |  Size: 492 B

View File

@@ -5,7 +5,6 @@ export { default as IconAddPeople } from './link.svg';
export { default as IconArrowBack } from './arrow_back.svg';
export { default as IconArrowDown } from './arrow_down.svg';
export { default as IconArrowDownSmall } from './arrow-down-small.svg';
export { default as IconArrowUp } from './arrow_up.svg';
export { default as IconArrowLeft } from './arrow-left.svg';
export { default as IconAudioOnly } from './visibility.svg';
export { default as IconAudioOnlyOff } from './visibility-off.svg';

View File

@@ -26,11 +26,6 @@ type Props = {
*/
hasOptions?: boolean,
/**
* Icon to display in the options section.
*/
OptionsIcon?: React$Node,
/**
* TestId of the button. Can be used to locate element when testing UI.
*/
@@ -62,7 +57,6 @@ function ActionButton({
className = '',
disabled,
hasOptions,
OptionsIcon = IconArrowDown,
testId,
type = 'primary',
onClick,
@@ -81,7 +75,7 @@ function ActionButton({
<Icon
className = 'icon'
size = { 14 }
src = { OptionsIcon } />
src = { IconArrowDown } />
</div>
}
</div>

View File

@@ -0,0 +1,61 @@
// @flow
import React from 'react';
import { Avatar } from '../../../avatar';
import { connect } from '../../../redux';
import { calculateAvatarDimensions } from '../../functions';
type Props = {
/**
* The height of the window.
*/
height: number,
/**
* The name of the participant (if any).
*/
name: string
}
/**
* Component displaying the avatar for the premeeting screen.
*
* @param {Props} props - The props of the component.
* @returns {ReactElement}
*/
function PremeetingAvatar({ height, name }: Props) {
const { marginTop, size } = calculateAvatarDimensions(height);
if (size <= 5) {
return null;
}
return (
<div style = {{ marginTop }}>
<Avatar
className = 'preview-avatar'
displayName = { name }
participantId = 'local'
size = { size } />
</div>
);
}
/**
* Maps (parts of) the redux state to the React {@code Component} props.
*
* @param {Object} state - The redux state.
* @returns {{
* height: number
* }}
*/
function mapStateToProps(state) {
return {
height: state['features/base/responsive-ui'].clientHeight
};
}
export default connect(mapStateToProps)(PremeetingAvatar);

View File

@@ -61,9 +61,6 @@ function ConnectionStatus({ connectionDetails, t, connectionType }: Props) {
? 'con-status-arrow con-status-arrow--up'
: 'con-status-arrow';
const detailsText = connectionDetails.map(t).join(' ');
const detailsClassName = showDetails
? 'con-status-details-visible'
: 'con-status-details-hidden';
return (
<div className = 'con-status'>
@@ -82,7 +79,8 @@ function ConnectionStatus({ connectionDetails, t, connectionType }: Props) {
size = { 24 }
src = { IconArrowDownSmall } />
</div>
<div className = { `con-status-details ${detailsClassName}` }>{detailsText}</div>
{ showDetails
&& <div className = 'con-status-details'>{detailsText}</div> }
</div>
</div>
);

View File

@@ -3,7 +3,6 @@
import React, { PureComponent } from 'react';
import { AudioSettingsButton, VideoSettingsButton } from '../../../../toolbox/components/web';
import { Avatar } from '../../../avatar';
import ConnectionStatus from './ConnectionStatus';
import CopyMeetingUrl from './CopyMeetingUrl';
@@ -86,18 +85,12 @@ export default class PreMeetingScreen extends PureComponent<Props> {
id = 'lobby-screen'>
<ConnectionStatus />
<Preview
name = { name }
showAvatar = { showAvatar }
videoMuted = { videoMuted }
videoTrack = { videoTrack } />
{!videoMuted && <div className = 'preview-overlay' />}
<div className = 'content'>
{showAvatar && videoMuted && (
<Avatar
className = 'premeeting-screen-avatar'
displayName = { name }
dynamicColor = { false }
participantId = 'local'
size = { 80 } />
)}
{showConferenceInfo && (
<>
<div className = 'title'>

View File

@@ -6,8 +6,20 @@ import { Video } from '../../../media';
import { connect } from '../../../redux';
import { getLocalVideoTrack } from '../../../tracks';
import PreviewAvatar from './Avatar';
export type Props = {
/**
* The name of the user that is about to join.
*/
name: string,
/**
* Indicates whether the avatar should be shown when video is off
*/
showAvatar: boolean,
/**
* Flag signaling the visibility of camera preview.
*/
@@ -26,7 +38,7 @@ export type Props = {
* @returns {ReactElement}
*/
function Preview(props: Props) {
const { videoMuted, videoTrack } = props;
const { name, showAvatar, videoMuted, videoTrack } = props;
if (!videoMuted && videoTrack) {
return (
@@ -38,9 +50,23 @@ function Preview(props: Props) {
);
}
if (showAvatar) {
return (
<div
className = 'no-video'
id = 'preview'>
<PreviewAvatar name = { name } />
</div>
);
}
return null;
}
Preview.defaultProps = {
showAvatar: true
};
/**
* Maps part of the Redux state to the props of this component.
*

View File

@@ -92,11 +92,15 @@ class LobbyScreen extends AbstractLobbyScreen {
const { t } = this.props;
return (
<InputField
onChange = { this._onChangeDisplayName }
placeHolder = { t('lobby.nameField') }
testId = 'lobby.nameField'
value = { displayName } />
<div className = 'participant-info'>
<div className = 'form'>
<InputField
onChange = { this._onChangeDisplayName }
placeHolder = { t('lobby.nameField') }
testId = 'lobby.nameField'
value = { displayName } />
</div>
</div>
);
}
@@ -109,13 +113,15 @@ class LobbyScreen extends AbstractLobbyScreen {
const { _passwordJoinFailed, t } = this.props;
return (
<InputField
className = { _passwordJoinFailed ? 'error' : '' }
onChange = { this._onChangePassword }
placeHolder = { _passwordJoinFailed ? t('lobby.invalidPassword') : t('lobby.passwordField') }
testId = 'lobby.password'
type = 'password'
value = { this.state.password } />
<div className = 'form'>
<InputField
className = { _passwordJoinFailed ? 'error' : '' }
onChange = { this._onChangePassword }
placeHolder = { _passwordJoinFailed ? t('lobby.invalidPassword') : t('lobby.passwordField') }
testId = 'lobby.password'
type = 'password'
value = { this.state.password } />
</div>
);
}

View File

@@ -5,7 +5,7 @@ import React, { Component } from 'react';
import { getRoomName } from '../../base/conference';
import { translate } from '../../base/i18n';
import { Icon, IconArrowDown, IconArrowUp, IconPhone, IconVolumeOff } from '../../base/icons';
import { Icon, IconPhone, IconVolumeOff } from '../../base/icons';
import { isVideoMutedByUser } from '../../base/media';
import { ActionButton, InputField, PreMeetingScreen, ToggleButton } from '../../base/premeeting';
import { connect } from '../../base/redux';
@@ -316,8 +316,6 @@ class Prejoin extends Component<Props, State> {
<div className = 'prejoin-input-area'>
<InputField
autoFocus = { true }
className = { showError ? 'error' : '' }
hasError = { showError }
onChange = { _setName }
onSubmit = { joinConference }
placeHolder = { t('dialog.enterDisplayName') }
@@ -354,7 +352,6 @@ class Prejoin extends Component<Props, State> {
isOpen = { showJoinByPhoneButtons }
onClose = { _onDropdownClose }>
<ActionButton
OptionsIcon = { showJoinByPhoneButtons ? IconArrowUp : IconArrowDown }
hasOptions = { true }
onClick = { _onJoinButtonClick }
onOptionsClick = { _onOptionsClick }

View File

@@ -9,7 +9,7 @@ pushd ${THIS_DIR}/..
npm install github:jitsi/lib-jitsi-meet#${LATEST_LJM_COMMIT}
git add package.json package-lock.json
git commit -m "chore(deps) lib-jitsi-meet@latest"
git commit -m "deps: lib-jitsi-meet@latest"
popd