fix(moderation) display green mic icon only for active speaker (#9744)
This commit is contained in:
parent
595df524b0
commit
6d3a4b920b
|
@ -51,8 +51,10 @@ body {
|
|||
}
|
||||
}
|
||||
|
||||
.jitsi-icon svg {
|
||||
fill: white;
|
||||
.jitsi-icon {
|
||||
&-default svg {
|
||||
fill: white;
|
||||
}
|
||||
}
|
||||
|
||||
.disabled .jitsi-icon svg {
|
||||
|
|
|
@ -153,6 +153,8 @@ export default function Icon(props: Props) {
|
|||
}
|
||||
}, [ onClick, onKeyPress ]);
|
||||
|
||||
const jitsiIconClassName = calculatedColor ? 'jitsi-icon' : 'jitsi-icon jitsi-icon-default';
|
||||
|
||||
return (
|
||||
<Container
|
||||
{ ...rest }
|
||||
|
@ -163,7 +165,7 @@ export default function Icon(props: Props) {
|
|||
aria-haspopup = { ariaHasPopup }
|
||||
aria-label = { ariaLabel }
|
||||
aria-pressed = { ariaPressed }
|
||||
className = { `jitsi-icon ${className || ''}` }
|
||||
className = { `${jitsiIconClassName} ${className || ''}` }
|
||||
id = { containerId }
|
||||
onClick = { onClick }
|
||||
onKeyDown = { onKeyDown }
|
||||
|
|
|
@ -4,17 +4,16 @@ import React, { type Node } from 'react';
|
|||
|
||||
import { Avatar } from '../../../base/avatar';
|
||||
import {
|
||||
Icon,
|
||||
IconCameraEmpty,
|
||||
IconCameraEmptyDisabled,
|
||||
IconMicrophoneEmpty,
|
||||
IconMicrophoneEmptySlash
|
||||
} from '../../../base/icons';
|
||||
import { ACTION_TRIGGER, MEDIA_STATE, type ActionTrigger, type MediaState } from '../../constants';
|
||||
ACTION_TRIGGER,
|
||||
AudioStateIcons,
|
||||
MEDIA_STATE,
|
||||
type ActionTrigger,
|
||||
type MediaState,
|
||||
VideoStateIcons
|
||||
} from '../../constants';
|
||||
|
||||
import { RaisedHandIndicator } from './RaisedHandIndicator';
|
||||
import {
|
||||
ColoredIcon,
|
||||
ParticipantActionsHover,
|
||||
ParticipantActionsPermanent,
|
||||
ParticipantContainer,
|
||||
|
@ -32,54 +31,6 @@ const Actions = {
|
|||
[ACTION_TRIGGER.PERMANENT]: ParticipantActionsPermanent
|
||||
};
|
||||
|
||||
/**
|
||||
* Icon mapping for possible participant audio states.
|
||||
*/
|
||||
const AudioStateIcons: {[MediaState]: React$Element<any> | null} = {
|
||||
[MEDIA_STATE.FORCE_MUTED]: (
|
||||
<ColoredIcon color = '#E04757'>
|
||||
<Icon
|
||||
size = { 16 }
|
||||
src = { IconMicrophoneEmptySlash } />
|
||||
</ColoredIcon>
|
||||
),
|
||||
[MEDIA_STATE.MUTED]: (
|
||||
<Icon
|
||||
size = { 16 }
|
||||
src = { IconMicrophoneEmptySlash } />
|
||||
),
|
||||
[MEDIA_STATE.UNMUTED]: (
|
||||
<ColoredIcon color = '#1EC26A'>
|
||||
<Icon
|
||||
size = { 16 }
|
||||
src = { IconMicrophoneEmpty } />
|
||||
</ColoredIcon>
|
||||
),
|
||||
[MEDIA_STATE.NONE]: null
|
||||
};
|
||||
|
||||
/**
|
||||
* Icon mapping for possible participant video states.
|
||||
*/
|
||||
const VideoStateIcons = {
|
||||
[MEDIA_STATE.FORCE_MUTED]: (
|
||||
<Icon
|
||||
size = { 16 }
|
||||
src = { IconCameraEmptyDisabled } />
|
||||
),
|
||||
[MEDIA_STATE.MUTED]: (
|
||||
<Icon
|
||||
size = { 16 }
|
||||
src = { IconCameraEmptyDisabled } />
|
||||
),
|
||||
[MEDIA_STATE.UNMUTED]: (
|
||||
<Icon
|
||||
size = { 16 }
|
||||
src = { IconCameraEmpty } />
|
||||
),
|
||||
[MEDIA_STATE.NONE]: null
|
||||
};
|
||||
|
||||
type Props = {
|
||||
|
||||
/**
|
||||
|
|
|
@ -190,12 +190,6 @@ export const Heading = styled.div`
|
|||
margin: 8px 0 ${props => props.theme.panePadding}px;
|
||||
`;
|
||||
|
||||
export const ColoredIcon = styled.div`
|
||||
& > div > svg {
|
||||
fill: ${props => props.color || '#fff'};
|
||||
}
|
||||
`;
|
||||
|
||||
export const ParticipantActionButton = styled(Button)`
|
||||
height: ${props => props.theme.participantActionButtonHeight}px;
|
||||
padding: 6px 10px;
|
||||
|
|
|
@ -25,17 +25,19 @@ export const ACTION_TRIGGER: {HOVER: ActionTrigger, PERMANENT: ActionTrigger} =
|
|||
PERMANENT: 'Permanent'
|
||||
};
|
||||
|
||||
export type MediaState = 'Muted' | 'ForceMuted' | 'Unmuted' | 'None';
|
||||
export type MediaState = 'DominantSpeaker' | 'Muted' | 'ForceMuted' | 'Unmuted' | 'None';
|
||||
|
||||
/**
|
||||
* Enum of possible participant media states.
|
||||
*/
|
||||
export const MEDIA_STATE: {
|
||||
DOMINANT_SPEAKER: MediaState,
|
||||
MUTED: MediaState,
|
||||
FORCE_MUTED: MediaState,
|
||||
UNMUTED: MediaState,
|
||||
NONE: MediaState,
|
||||
} = {
|
||||
DOMINANT_SPEAKER: 'DominantSpeaker',
|
||||
MUTED: 'Muted',
|
||||
FORCE_MUTED: 'ForceMuted',
|
||||
UNMUTED: 'Unmuted',
|
||||
|
@ -61,6 +63,12 @@ export const QUICK_ACTION_BUTTON: {
|
|||
* Icon mapping for possible participant audio states.
|
||||
*/
|
||||
export const AudioStateIcons: {[MediaState]: React$Element<any> | null} = {
|
||||
[MEDIA_STATE.DOMINANT_SPEAKER]: (
|
||||
<Icon
|
||||
color = '#1EC26A'
|
||||
size = { 16 }
|
||||
src = { IconMicrophoneEmpty } />
|
||||
),
|
||||
[MEDIA_STATE.FORCE_MUTED]: (
|
||||
<Icon
|
||||
color = '#E04757'
|
||||
|
@ -74,7 +82,6 @@ export const AudioStateIcons: {[MediaState]: React$Element<any> | null} = {
|
|||
),
|
||||
[MEDIA_STATE.UNMUTED]: (
|
||||
<Icon
|
||||
color = '#1EC26A'
|
||||
size = { 16 }
|
||||
src = { IconMicrophoneEmpty } />
|
||||
),
|
||||
|
|
|
@ -8,6 +8,7 @@ import {
|
|||
import { getFeatureFlag, INVITE_ENABLED } from '../base/flags';
|
||||
import { MEDIA_TYPE, type MediaType } from '../base/media/constants';
|
||||
import {
|
||||
getDominantSpeakerParticipant,
|
||||
getParticipantCount,
|
||||
isLocalParticipantModerator,
|
||||
isParticipantModerator
|
||||
|
@ -74,6 +75,12 @@ export function isForceMuted(participant: Object, mediaType: MediaType, state: O
|
|||
* @returns {MediaState}
|
||||
*/
|
||||
export function getParticipantAudioMediaState(participant: Object, muted: Boolean, state: Object) {
|
||||
const dominantSpeaker = getDominantSpeakerParticipant(state);
|
||||
|
||||
if (participant === dominantSpeaker) {
|
||||
return MEDIA_STATE.DOMINANT_SPEAKER;
|
||||
}
|
||||
|
||||
if (muted) {
|
||||
if (isForceMuted(participant, MEDIA_TYPE.AUDIO, state)) {
|
||||
return MEDIA_STATE.FORCE_MUTED;
|
||||
|
|
Loading…
Reference in New Issue