Compare commits

...

8 Commits

Author SHA1 Message Date
Hristo Terezov 9511533b11 fix(dialog): cancel hide timeout on openDialog
Since we unmount the dialog after a timeout because of an animation we
need to cancel the timeout in case we need to render new dialog.
Otherwise the actual hiding can be executed after we render the new
dialog.
2022-11-17 16:30:25 -06:00
Hristo Terezov 30185ef194 feat(dialog): add disableAutoHideOnSubmit prop
Needed for shared video dialog.
2022-11-17 16:30:10 -06:00
Saúl Ibarra Corretgé 358715e7eb fix(participants) don't treat Jigasi like a fake participant
We only really want to know if a participant is Jigasi for displaying a
specific icon, for all other intents and purposes it's a normal
participant.
2022-11-17 15:26:46 +01:00
Robert Pintilii 4c6107f0b1 fix(dial-in) Fix warning (#12571)
Only show warning if the feature is enabled
2022-11-16 12:16:08 +02:00
Robert Pintilii 3b734190b8 fix(ui) Fix new icons issues (#12545) 2022-11-11 09:59:53 +02:00
Robert Pintilii 1276d1842d fix(thumbnail) Fix top indicators sizes (#12539)
Fix sizes after icon update
2022-11-10 10:31:14 +02:00
Robert Pintilii f445d3bc31 fix(recording) Fix local recording (#12531)
Starting chrome 107, the recorder does not record any data if the audio stream has no tracks
To fix this we create a track for the local user (muted track)
2022-11-10 10:31:04 +02:00
Robert Pintilii 45aba178ad fix(thumbnail) Open native video context menu (#12532) 2022-11-10 10:30:20 +02:00
17 changed files with 62 additions and 38 deletions

View File

@ -33,7 +33,7 @@ const AVATAR_CHECKED_URLS = new Map();
/* eslint-disable arrow-body-style, no-unused-vars */
const AVATAR_CHECKER_FUNCTIONS = [
(participant: IParticipant) => {
return isJigasiParticipant(participant) ? JIGASI_PARTICIPANT_ICON : null;
return participant?.isJigasi ? JIGASI_PARTICIPANT_ICON : null;
},
(participant: IParticipant) => {
return isWhiteboardParticipant(participant) ? WHITEBOARD_PARTICIPANT_ICON : null;
@ -300,16 +300,6 @@ export function getFakeParticipants(stateful: IStateful) {
return toState(stateful)['features/base/participants'].fakeParticipants;
}
/**
* Returns whether the fake participant is Jigasi.
*
* @param {IParticipant|undefined} participant - The participant entity.
* @returns {boolean} - True if it's a Jigasi participant.
*/
function isJigasiParticipant(participant?: IParticipant): boolean {
return participant?.fakeParticipant === FakeParticipant.Jigasi;
}
/**
* Returns whether the fake participant is a local screenshare.
*

View File

@ -80,7 +80,7 @@ import {
} from './functions';
import logger from './logger';
import { PARTICIPANT_JOINED_FILE, PARTICIPANT_LEFT_FILE } from './sounds';
import { FakeParticipant, IJitsiParticipant } from './types';
import { IJitsiParticipant } from './types';
import './subscriber';
@ -438,7 +438,7 @@ StateListenerRegistry.register(
store.dispatch(participantUpdated({
conference,
id: participant.getId(),
fakeParticipant: value ? FakeParticipant.Jigasi : undefined
isJigasi: value
})),
// eslint-disable-next-line @typescript-eslint/no-unused-vars
'features_screen-sharing': (participant: IJitsiParticipant, value: string) =>

View File

@ -1,5 +1,4 @@
export enum FakeParticipant {
Jigasi = 'Jigasi',
LocalScreenShare = 'LocalScreenShare',
RemoteScreenShare = 'RemoteScreenShare',
SharedVideo = 'SharedVideo',
@ -22,6 +21,7 @@ export interface IParticipant {
};
getId?: Function;
id: string;
isJigasi?: boolean;
isReplaced?: boolean;
isReplacing?: number;
jwtId?: string;

View File

@ -143,7 +143,7 @@ const useStyles = makeStyles()((theme: Theme) => {
},
iconButton: {
padding: '10px'
padding: theme.spacing(2)
},
textWithIcon: {
@ -166,7 +166,7 @@ const useStyles = makeStyles()((theme: Theme) => {
...withPixelLineHeight(theme.typography.bodyShortBoldLarge),
'&.iconButton': {
padding: '14px'
padding: '12px'
}
},

View File

@ -191,6 +191,7 @@ interface IDialogProps {
children?: React.ReactNode;
className?: string;
description?: string;
disableAutoHideOnSubmit?: boolean;
disableBackdropClose?: boolean;
disableEnter?: boolean;
hideCloseButton?: boolean;
@ -212,6 +213,7 @@ const Dialog = ({
children,
className,
description,
disableAutoHideOnSubmit = false,
disableBackdropClose,
hideCloseButton,
disableEnter,
@ -233,7 +235,7 @@ const Dialog = ({
}, [ onCancel ]);
const submit = useCallback(() => {
dispatch(hideDialog());
!disableAutoHideOnSubmit && dispatch(hideDialog());
onSubmit?.();
}, [ onSubmit ]);

View File

@ -2,18 +2,29 @@ import React, { ReactElement, useEffect, useState } from 'react';
export const DialogTransitionContext = React.createContext({ isUnmounting: false });
type TimeoutType = ReturnType<typeof setTimeout>;
const DialogTransition = ({ children }: { children: ReactElement | null; }) => {
const [ childrenToRender, setChildrenToRender ] = useState(children);
const [ isUnmounting, setIsUnmounting ] = useState(false);
const [ timeoutID, setTimeoutID ] = useState<TimeoutType | undefined>(undefined);
useEffect(() => {
if (children === null) {
setIsUnmounting(true);
setTimeout(() => {
setChildrenToRender(children);
setIsUnmounting(false);
}, 150);
if (typeof timeoutID === 'undefined') {
setTimeoutID(setTimeout(() => {
setChildrenToRender(children);
setIsUnmounting(false);
setTimeoutID(undefined);
}, 150));
}
} else {
if (typeof timeoutID !== 'undefined') {
clearTimeout(timeoutID);
setTimeoutID(undefined);
setIsUnmounting(false);
}
setChildrenToRender(children);
}
}, [ children ]);

View File

@ -4,7 +4,7 @@ import Tooltip from '@atlaskit/tooltip';
import React from 'react';
import { translate } from '../../../base/i18n';
import { IconWarning } from '../../../base/icons';
import { IconExclamationTriangle } from '../../../base/icons/svg';
import { Label } from '../../../base/label';
import { COLORS } from '../../../base/label/constants';
import { connect } from '../../../base/redux';
@ -26,7 +26,7 @@ class InsecureRoomNameLabel extends AbstractInsecureRoomNameLabel {
position = 'bottom'>
<Label
color = { COLORS.red }
icon = { IconWarning } />
icon = { IconExclamationTriangle } />
</Tooltip>
);
}

View File

@ -36,7 +36,7 @@ const useStyles = makeStyles()(() => {
return {
pinnedIndicator: {
backgroundColor: 'rgba(0, 0, 0, .7)',
padding: '2px',
padding: '4px',
zIndex: 3,
display: 'inline-block',
borderRadius: '4px',

View File

@ -35,7 +35,7 @@ const useStyles = makeStyles()((theme: Theme) => {
return {
raisedHandIndicator: {
backgroundColor: theme.palette.warning02,
padding: '2px',
padding: '4px',
zIndex: 3,
display: 'inline-block',
borderRadius: '4px',

View File

@ -334,7 +334,8 @@ const defaultStyles = (theme: Theme) => {
width: '100%',
height: '100%',
zIndex: 9,
borderRadius: '4px'
borderRadius: '4px',
pointerEvents: 'none' as const
},
borderIndicatorOnTop: {

View File

@ -54,10 +54,6 @@ const useStyles = makeStyles()(() => {
'&>div': {
display: 'flex',
overflow: 'hidden'
},
'&:first-child': {
marginLeft: '6px'
}
}
};

View File

@ -183,7 +183,7 @@ function AddPeopleDialog({
&& <DialInSection phoneNumber = { _phoneNumber } />
}
{
!_dialInVisible && _isVpaasMeeting && <DialInLimit />
!_phoneNumber && _dialInVisible && _isVpaasMeeting && <DialInLimit />
}
</div>
</Dialog>

View File

@ -219,6 +219,17 @@ const LocalRecordingManager: ILocalRecordingManager = {
permittedOrigins: [ '*' ]
});
}
const localAudioTrack = getLocalTrack(tracks, MEDIA_TYPE.AUDIO)?.jitsiTrack?.track;
// Starting chrome 107, the recorder does not record any data if the audio stream has no tracks
// To fix this we create a track for the local user(muted track)
if (!localAudioTrack) {
APP.conference.muteAudio(false);
setTimeout(() => APP.conference.muteAudio(true), 100);
await new Promise(resolve => {
setTimeout(resolve, 100);
});
}
const currentTitle = document.title;
@ -244,9 +255,10 @@ const LocalRecordingManager: ILocalRecordingManager = {
}
this.initializeAudioMixer();
this.mixAudioStream(gdmStream);
tracks.forEach((track: any) => {
const allTracks = getTrackState(getState());
allTracks.forEach((track: any) => {
if (track.mediaType === MEDIA_TYPE.AUDIO) {
const audioTrack = track?.jitsiTrack?.track;

View File

@ -2,7 +2,6 @@
import React, { Component } from 'react';
import { hideDialog } from '../../base/dialog/actions';
import { translate } from '../../base/i18n';
import { getParticipantById } from '../../base/participants';
import { connect } from '../../base/redux';
@ -138,7 +137,6 @@ class RemoteControlAuthorizationDialog extends Component<Props> {
_onSubmit() {
const { dispatch, participantId } = this.props;
dispatch(hideDialog());
dispatch(grant(participantId));
return false;

View File

@ -1,5 +1,6 @@
import React from 'react';
import { hideDialog } from '../../../base/dialog/actions';
import { translate } from '../../../base/i18n/functions';
import { connect } from '../../../base/redux/functions';
import Dialog from '../../../base/ui/components/web/Dialog';
@ -52,7 +53,9 @@ class SharedVideoDialog extends AbstractSharedVideoDialog<any> {
_onSubmitValue() {
const result = super._onSetVideoLink(this.state.value);
if (!result) {
if (result) {
this.props.dispatch(hideDialog());
} else {
this.setState({
error: true
});
@ -72,6 +75,7 @@ class SharedVideoDialog extends AbstractSharedVideoDialog<any> {
return (
<Dialog
disableAutoHideOnSubmit = { true }
ok = {{
disabled: this.state.okDisabled,
translationKey: 'dialog.Share'

View File

@ -115,7 +115,12 @@ const styles = () => {
return {
triggerButton: {
padding: '3px !important',
borderRadius: '4px'
borderRadius: '4px',
'& svg': {
width: '18px',
height: '18px'
}
},
contextMenu: {

View File

@ -117,7 +117,12 @@ const styles = () => {
return {
triggerButton: {
padding: '3px !important',
borderRadius: '4px'
borderRadius: '4px',
'& svg': {
width: '18px',
height: '18px'
}
},
contextMenu: {