Skip to content

Commit

Permalink
feat(silent): hide unmute if participant joined without audio (#14803)
Browse files Browse the repository at this point in the history
* feat(silent): hide unmute if participant joined without audio

* Add additional listener for SILENT_STATUS_CHANGED

* squash: Rename local variable.

* chore(deps) lib-jitsi-meet@latest

jitsi/lib-jitsi-meet@v1839.0.0+ea523fc6...v1840.0.0+fc115be5

---------

Co-authored-by: damencho <[email protected]>
  • Loading branch information
nbeckindy and damencho authored Jul 2, 2024
1 parent 3ae50b6 commit b4a5e63
Show file tree
Hide file tree
Showing 11 changed files with 75 additions and 15 deletions.
12 changes: 12 additions & 0 deletions conference.js
Original file line number Diff line number Diff line change
Expand Up @@ -1676,6 +1676,18 @@ export default {
});
}
);

room.on(
JitsiConferenceEvents.SILENT_STATUS_CHANGED,
(id, isSilent) => {
APP.store.dispatch(participantUpdated({
conference: room,
id,
isSilent
}));
}
);

room.on(
JitsiConferenceEvents.BOT_TYPE_CHANGED,
(id, botType) => {
Expand Down
10 changes: 5 additions & 5 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,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/v1839.0.0+ea523fc6/lib-jitsi-meet.tgz",
"lib-jitsi-meet": "https://github.com/jitsi/lib-jitsi-meet/releases/download/v1840.0.0+fc115be5/lib-jitsi-meet.tgz",
"lodash": "4.17.21",
"moment": "2.29.4",
"moment-duration-format": "2.2.2",
Expand Down
8 changes: 8 additions & 0 deletions react/features/base/conference/actions.any.ts
Original file line number Diff line number Diff line change
Expand Up @@ -228,6 +228,14 @@ function _addConferenceListeners(conference: IJitsiConference, dispatch: IStore[
name: getNormalizedDisplayName(displayName)
})));

conference.on(
JitsiConferenceEvents.SILENT_STATUS_CHANGED,
(id: string, isSilent: boolean) => dispatch(participantUpdated({
conference,
id,
isSilent
})));

conference.on(
JitsiConferenceEvents.DOMINANT_SPEAKER_CHANGED,
(dominant: string, previous: string[], silence: boolean | string) => {
Expand Down
4 changes: 4 additions & 0 deletions react/features/base/conference/middleware.any.ts
Original file line number Diff line number Diff line change
Expand Up @@ -706,6 +706,10 @@ function _updateLocalParticipantInConference({ dispatch, getState }: IStore, nex
conference.setDisplayName(participant.name);
}

if ('isSilent' in participant) {
conference.setIsSilent(participant.isSilent);
}

if ('role' in participant && participant.role === PARTICIPANT_ROLE.MODERATOR) {
const { pendingSubjectChange, subject } = getState()['features/base/conference'];

Expand Down
1 change: 1 addition & 0 deletions react/features/base/conference/reducer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,7 @@ export interface IJitsiConference {
setAssumedBandwidthBps: (value: number) => void;
setDesktopSharingFrameRate: Function;
setDisplayName: Function;
setIsSilent: Function;
setLocalParticipantProperty: Function;
setMediaEncryptionKey: Function;
setReceiverConstraints: Function;
Expand Down
24 changes: 23 additions & 1 deletion react/features/base/participants/middleware.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ import { CALLING, INVITED } from '../../presence-status/constants';
import { RAISE_HAND_SOUND_ID } from '../../reactions/constants';
import { RECORDING_OFF_SOUND_ID, RECORDING_ON_SOUND_ID } from '../../recording/constants';
import { APP_WILL_MOUNT, APP_WILL_UNMOUNT } from '../app/actionTypes';
import { CONFERENCE_WILL_JOIN } from '../conference/actionTypes';
import { CONFERENCE_JOINED, CONFERENCE_WILL_JOIN } from '../conference/actionTypes';
import { forEachConference, getCurrentConference } from '../conference/functions';
import { IJitsiConference } from '../conference/reducer';
import { SET_CONFIG } from '../config/actionTypes';
Expand Down Expand Up @@ -201,6 +201,28 @@ MiddlewareRegistry.register(store => next => action => {
return result;
}

case CONFERENCE_JOINED: {
const result = next(action);

const state = store.getState();
const { startSilent } = state['features/base/config'];

if (startSilent) {
const localId = getLocalParticipant(store.getState())?.id;

if (localId) {
store.dispatch(participantUpdated({
id: localId,
local: true,
isSilent: startSilent
}));
}
}

return result;
}


case SET_LOCAL_PARTICIPANT_RECORDING_STATUS: {
const state = store.getState();
const { recording, onlySelf } = action;
Expand Down
1 change: 1 addition & 0 deletions react/features/base/participants/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ export interface IParticipant {
isJigasi?: boolean;
isReplaced?: boolean;
isReplacing?: number;
isSilent?: boolean;
jwtId?: string;
loadableAvatarUrl?: string;
loadableAvatarUrlUseCORS?: boolean;
Expand Down
9 changes: 7 additions & 2 deletions react/features/participants-pane/functions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,10 @@ export function getParticipantAudioMediaState(participant: IParticipant | undefi
muted: Boolean, state: IReduxState) {
const dominantSpeaker = getDominantSpeakerParticipant(state);

if (participant?.isSilent) {
return MEDIA_STATE.NONE;
}

if (muted) {
if (isForceMuted(participant, MEDIA_TYPE.AUDIO, state)) {
return MEDIA_STATE.FORCE_MUTED;
Expand Down Expand Up @@ -146,9 +150,10 @@ export function getQuickActionButtonType(
state: IReduxState) {
// handled only by moderators
const isVideoForceMuted = isForceMuted(participant, MEDIA_TYPE.VIDEO, state);
const isParticipantSilent = participant?.isSilent || false;

if (isLocalParticipantModerator(state)) {
if (!isAudioMuted) {
if (!isAudioMuted && !isParticipantSilent) {
return QUICK_ACTION_BUTTON.MUTE;
}
if (!isVideoMuted) {
Expand All @@ -157,7 +162,7 @@ export function getQuickActionButtonType(
if (isVideoForceMuted) {
return QUICK_ACTION_BUTTON.ALLOW_VIDEO;
}
if (isSupported()(state)) {
if (isSupported()(state) && !isParticipantSilent) {
return QUICK_ACTION_BUTTON.ASK_TO_UNMUTE;
}
}
Expand Down
15 changes: 11 additions & 4 deletions react/features/video-menu/components/native/RemoteVideoMenu.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,11 @@ interface IProps {
*/
_isParticipantAvailable?: boolean;

/**
* Whether or not the targeted participant joined without audio.
*/
_isParticipantSilent: boolean;

/**
* Whether the local participant is moderator or not.
*/
Expand Down Expand Up @@ -143,6 +148,7 @@ class RemoteVideoMenu extends PureComponent<IProps> {
_disableGrantModerator,
_isBreakoutRoom,
_isParticipantAvailable,
_isParticipantSilent,
_moderator,
_rooms,
_showDemote,
Expand All @@ -166,10 +172,10 @@ class RemoteVideoMenu extends PureComponent<IProps> {
<BottomSheet
renderHeader = { this._renderMenuHeader }
showSlidingView = { _isParticipantAvailable }>
<AskUnmuteButton { ...buttonProps } />
{!_isParticipantSilent && <AskUnmuteButton { ...buttonProps } />}
{ !_disableRemoteMute && <MuteButton { ...buttonProps } /> }
<MuteEveryoneElseButton { ...buttonProps } />
{ !_disableRemoteMute && <MuteVideoButton { ...buttonProps } /> }
{ !_disableRemoteMute && !_isParticipantSilent && <MuteVideoButton { ...buttonProps } /> }
{/* @ts-ignore */}
<Divider style = { styles.divider as ViewStyle } />
{ !_disableKick && <KickButton { ...buttonProps } /> }
Expand Down Expand Up @@ -242,7 +248,7 @@ function _mapStateToProps(state: IReduxState, ownProps: any) {
const kickOutEnabled = getFeatureFlag(state, KICK_OUT_ENABLED, true);
const { participantId } = ownProps;
const { remoteVideoMenu = {}, disableRemoteMute } = state['features/base/config'];
const isParticipantAvailable = getParticipantById(state, participantId);
const participant = getParticipantById(state, participantId);
const { disableKick, disablePrivateChat } = remoteVideoMenu;
const _rooms = Object.values(getBreakoutRooms(state));
const _currentRoomId = getCurrentRoomId(state);
Expand All @@ -257,7 +263,8 @@ function _mapStateToProps(state: IReduxState, ownProps: any) {
_disableRemoteMute: Boolean(disableRemoteMute),
_disablePrivateChat: Boolean(disablePrivateChat) || _iAmVisitor,
_isBreakoutRoom,
_isParticipantAvailable: Boolean(isParticipantAvailable),
_isParticipantAvailable: Boolean(participant),
_isParticipantSilent: Boolean(participant?.isSilent),
_moderator: moderator,
_participantDisplayName: getParticipantDisplayName(state, participantId),
_rooms,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -214,7 +214,7 @@ const ParticipantContextMenu = ({

if (_isModerator) {
if (isModerationSupported) {
if (_isAudioMuted
if (_isAudioMuted && !participant.isSilent
&& !(isClickedFromParticipantPane && quickActionButtonType === QUICK_ACTION_BUTTON.ASK_TO_UNMUTE)) {
buttons.push(<AskToUnmuteButton
{ ...getButtonProps(BUTTONS.ASK_UNMUTE) }
Expand All @@ -230,7 +230,7 @@ const ParticipantContextMenu = ({
}
}

if (!disableRemoteMute) {
if (!disableRemoteMute && !participant.isSilent) {
if (!(isClickedFromParticipantPane && quickActionButtonType === QUICK_ACTION_BUTTON.MUTE)) {
buttons.push(<MuteButton { ...getButtonProps(BUTTONS.MUTE) } />);
}
Expand Down

0 comments on commit b4a5e63

Please sign in to comment.