[MM-57460] - Calls: Host controls, add mute all to participant list (#7945)
* add mute all to participant list * i18n * hostControlsAvailable * mute-all -> mute-others
This commit is contained in:
parent
7fbd2e52e2
commit
59db1839ec
5 changed files with 88 additions and 3 deletions
|
|
@ -642,6 +642,17 @@ export const hostMuteSession = async (serverUrl: string, callId: string, session
|
|||
}
|
||||
};
|
||||
|
||||
export const hostMuteOthers = async (serverUrl: string, callId: string) => {
|
||||
try {
|
||||
const client = NetworkManager.getClient(serverUrl);
|
||||
return client.hostMuteOthers(callId);
|
||||
} catch (error) {
|
||||
logDebug('error on hostMuteOthers', getFullErrorMessage(error));
|
||||
await forceLogoutIfNecessary(serverUrl, error);
|
||||
return error;
|
||||
}
|
||||
};
|
||||
|
||||
export const hostStopScreenshare = async (serverUrl: string, callId: string, sessionId: string) => {
|
||||
try {
|
||||
const client = NetworkManager.getClient(serverUrl);
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@ export interface ClientCallsMix {
|
|||
dismissCall: (channelId: string) => Promise<ApiResp>;
|
||||
hostMake: (callId: string, newHostId: string) => Promise<ApiResp>;
|
||||
hostMute: (callId: string, sessionId: string) => Promise<ApiResp>;
|
||||
hostMuteOthers: (callId: string) => Promise<ApiResp>;
|
||||
hostScreenOff: (callId: string, sessionId: string) => Promise<ApiResp>;
|
||||
hostLowerHand: (callId: string, sessionId: string) => Promise<ApiResp>;
|
||||
hostRemove: (callId: string, sessionId: string) => Promise<ApiResp>;
|
||||
|
|
@ -131,6 +132,13 @@ const ClientCalls = (superclass: any) => class extends superclass {
|
|||
);
|
||||
};
|
||||
|
||||
hostMuteOthers = async (callId: string) => {
|
||||
return this.doFetch(
|
||||
`${this.getCallsRoute()}/calls/${callId}/host/mute-others`,
|
||||
{method: 'post'},
|
||||
);
|
||||
};
|
||||
|
||||
hostScreenOff = async (callId: string, sessionId: string) => {
|
||||
return this.doFetch(
|
||||
`${this.getCallsRoute()}/calls/${callId}/host/screen-off`,
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@ import {distinctUntilChanged, switchMap} from 'rxjs/operators';
|
|||
|
||||
import {observeCallDatabase, observeCurrentSessionsDict} from '@calls/observers';
|
||||
import {ParticipantsList} from '@calls/screens/participants_list/participants_list';
|
||||
import {observeCurrentCall} from '@calls/state';
|
||||
import {observeTeammateNameDisplay} from '@queries/servers/user';
|
||||
|
||||
const enhanced = withObservables([], () => {
|
||||
|
|
@ -14,10 +15,22 @@ const enhanced = withObservables([], () => {
|
|||
switchMap((db) => (db ? observeTeammateNameDisplay(db) : of$(''))),
|
||||
distinctUntilChanged(),
|
||||
);
|
||||
const callServerUrl = observeCurrentCall().pipe(
|
||||
switchMap((call) => of$(call?.serverUrl)),
|
||||
);
|
||||
const callChannelId = observeCurrentCall().pipe(
|
||||
switchMap((call) => of$(call?.channelId)),
|
||||
);
|
||||
const callUserId = observeCurrentCall().pipe(
|
||||
switchMap((call) => of$(call?.myUserId)),
|
||||
);
|
||||
|
||||
return {
|
||||
sessionsDict: observeCurrentSessionsDict(),
|
||||
teammateNameDisplay,
|
||||
callServerUrl,
|
||||
callChannelId,
|
||||
callUserId,
|
||||
};
|
||||
});
|
||||
|
||||
|
|
|
|||
|
|
@ -4,14 +4,16 @@
|
|||
import {BottomSheetFlatList} from '@gorhom/bottom-sheet';
|
||||
import React, {useCallback, useMemo} from 'react';
|
||||
import {useIntl} from 'react-intl';
|
||||
import {type ListRenderItemInfo, useWindowDimensions, View} from 'react-native';
|
||||
import {type ListRenderItemInfo, Text, TouchableOpacity, useWindowDimensions, View} from 'react-native';
|
||||
import {FlatList} from 'react-native-gesture-handler';
|
||||
import {useSafeAreaInsets} from 'react-native-safe-area-context';
|
||||
|
||||
import {useHostMenus} from '@calls/hooks';
|
||||
import {hostMuteOthers} from '@calls/actions/calls';
|
||||
import {useHostControlsAvailable, useHostMenus} from '@calls/hooks';
|
||||
import {Participant} from '@calls/screens/participants_list/participant';
|
||||
import Pill from '@calls/screens/participants_list/pill';
|
||||
import {sortSessions} from '@calls/utils';
|
||||
import CompassIcon from '@components/compass_icon';
|
||||
import FormattedText from '@components/formatted_text';
|
||||
import {Screens} from '@constants';
|
||||
import {useTheme} from '@context/theme';
|
||||
|
|
@ -31,11 +33,15 @@ type Props = {
|
|||
closeButtonId: string;
|
||||
sessionsDict: Dictionary<CallSession>;
|
||||
teammateNameDisplay: string;
|
||||
callServerUrl?: string;
|
||||
callChannelId?: string;
|
||||
callUserId?: string;
|
||||
}
|
||||
|
||||
const getStyleSheet = makeStyleSheetFromTheme((theme: Theme) => ({
|
||||
header: {
|
||||
paddingBottom: 12,
|
||||
paddingRight: 2,
|
||||
flexDirection: 'row',
|
||||
gap: 8,
|
||||
alignItems: 'center',
|
||||
|
|
@ -44,12 +50,35 @@ const getStyleSheet = makeStyleSheetFromTheme((theme: Theme) => ({
|
|||
color: theme.centerChannelColor,
|
||||
...typography('Heading', 600, 'SemiBold'),
|
||||
},
|
||||
muteButton: {
|
||||
flexDirection: 'row',
|
||||
padding: 6,
|
||||
gap: 6,
|
||||
alignItems: 'center',
|
||||
marginLeft: 'auto',
|
||||
},
|
||||
muteIcon: {
|
||||
color: theme.buttonBg,
|
||||
},
|
||||
muteText: {
|
||||
color: theme.buttonBg,
|
||||
...typography('Body', 100, 'SemiBold'),
|
||||
marginTop: -2,
|
||||
},
|
||||
}));
|
||||
|
||||
export const ParticipantsList = ({closeButtonId, sessionsDict, teammateNameDisplay}: Props) => {
|
||||
export const ParticipantsList = ({
|
||||
closeButtonId,
|
||||
sessionsDict,
|
||||
teammateNameDisplay,
|
||||
callServerUrl,
|
||||
callChannelId,
|
||||
callUserId,
|
||||
}: Props) => {
|
||||
const intl = useIntl();
|
||||
const theme = useTheme();
|
||||
const {onPress} = useHostMenus();
|
||||
const hostControlsAvailable = useHostControlsAvailable();
|
||||
const {bottom} = useSafeAreaInsets();
|
||||
const {height} = useWindowDimensions();
|
||||
const isTablet = useIsTablet();
|
||||
|
|
@ -63,6 +92,14 @@ export const ParticipantsList = ({closeButtonId, sessionsDict, teammateNameDispl
|
|||
if (sessions.length > MIN_ROWS && snapPoint1 < snapPoint2) {
|
||||
snapPoints.push(snapPoint2);
|
||||
}
|
||||
const otherUnMuted = useMemo(() => sessions.some((s) => !s.muted && s.userId !== callUserId), [sessions, callUserId]);
|
||||
|
||||
const muteOthersPress = useCallback(async () => {
|
||||
if (!callServerUrl || !callChannelId) {
|
||||
return;
|
||||
}
|
||||
hostMuteOthers(callServerUrl, callChannelId);
|
||||
}, [callServerUrl, callChannelId]);
|
||||
|
||||
const renderItem = useCallback(({item}: ListRenderItemInfo<CallSession>) => (
|
||||
<Participant
|
||||
|
|
@ -83,6 +120,21 @@ export const ParticipantsList = ({closeButtonId, sessionsDict, teammateNameDispl
|
|||
defaultMessage={'Participants'}
|
||||
/>
|
||||
<Pill text={sessions.length}/>
|
||||
{hostControlsAvailable && otherUnMuted &&
|
||||
<TouchableOpacity
|
||||
style={styles.muteButton}
|
||||
onPress={muteOthersPress}
|
||||
>
|
||||
<CompassIcon
|
||||
size={16}
|
||||
name={'microphone-off'}
|
||||
style={styles.muteIcon}
|
||||
/>
|
||||
<Text style={styles.muteText}>
|
||||
{intl.formatMessage({id: 'mobile.calls_mute_others', defaultMessage: 'Mute others'})}
|
||||
</Text>
|
||||
</TouchableOpacity>
|
||||
}
|
||||
</View>
|
||||
<List
|
||||
data={sessions}
|
||||
|
|
|
|||
|
|
@ -486,6 +486,7 @@
|
|||
"mobile.calls_mic_error": "To participate, open Settings to grant Mattermost access to your microphone.",
|
||||
"mobile.calls_more": "More",
|
||||
"mobile.calls_mute": "Mute",
|
||||
"mobile.calls_mute_others": "Mute others",
|
||||
"mobile.calls_mute_participant": "Mute participant",
|
||||
"mobile.calls_name_is_talking_postfix": "is talking...",
|
||||
"mobile.calls_name_started_call": "{name} started a call",
|
||||
|
|
|
|||
Loading…
Reference in a new issue