MM-54323 - Calls: Incoming call from different server (#7646)

* refactor; tried to clarify more_messages; new design

* adjust more_messages text spacing

* small fix for height with incoming call on current channel

* move calls-specific code in the calls product behind a hook

* show servername for notifications from other servers

* if >1 active servers, always show server name, otherwise don't

* add height of notification bar in measurements

---------

Co-authored-by: Mattermost Build <build@mattermost.com>
This commit is contained in:
Christopher Poile 2023-11-14 17:03:55 -05:00 committed by GitHub
parent 94a910303b
commit f0334d8c0e
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 68 additions and 12 deletions

View file

@ -1,7 +1,7 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
import React, {useCallback, useEffect} from 'react';
import React, {useCallback, useEffect, useState} from 'react';
import {useIntl} from 'react-intl';
import {Pressable, Text, View} from 'react-native';
@ -18,11 +18,14 @@ import {useServerUrl} from '@context/server';
import {useTheme} from '@context/theme';
import DatabaseManager from '@database/manager';
import WebsocketManager from '@managers/websocket_manager';
import {getServerDisplayName} from '@queries/app/servers';
import ChannelMembershipModel from '@typings/database/models/servers/channel_membership';
import {changeOpacity, makeStyleSheetFromTheme} from '@utils/theme';
import {typography} from '@utils/typography';
import {displayUsername} from '@utils/user';
import type ServersModel from '@typings/database/models/app/servers';
const getStyleSheet = makeStyleSheetFromTheme((theme: Theme) => ({
outerContainer: {
borderRadius: 8,
@ -39,6 +42,9 @@ const getStyleSheet = makeStyleSheetFromTheme((theme: Theme) => ({
shadowRadius: 4,
elevation: 4,
},
outerContainerServerName: {
height: CALL_NOTIFICATION_BAR_HEIGHT + 8,
},
innerContainer: {
flexDirection: 'row',
width: '100%',
@ -71,6 +77,7 @@ const getStyleSheet = makeStyleSheetFromTheme((theme: Theme) => ({
},
textContainer: {
flex: 1,
flexDirection: 'column',
marginLeft: 8,
},
text: {
@ -81,6 +88,11 @@ const getStyleSheet = makeStyleSheetFromTheme((theme: Theme) => ({
...typography('Body', 100, 'SemiBold'),
lineHeight: 20,
},
textServerName: {
...typography('Heading', 25),
color: changeOpacity(theme.buttonColor, 0.72),
textTransform: 'uppercase',
},
dismissContainer: {
alignItems: 'center',
width: 32,
@ -93,6 +105,7 @@ const getStyleSheet = makeStyleSheetFromTheme((theme: Theme) => ({
}));
type Props = {
servers: ServersModel[];
incomingCall: IncomingCallNotification;
currentUserId: string;
teammateNameDisplay: string;
@ -101,6 +114,7 @@ type Props = {
}
export const CallNotification = ({
servers,
incomingCall,
currentUserId,
teammateNameDisplay,
@ -111,6 +125,8 @@ export const CallNotification = ({
const serverUrl = useServerUrl();
const theme = useTheme();
const style = getStyleSheet(theme);
const [serverName, setServerName] = useState('');
const moreThanOneServer = servers.length > 1;
useEffect(() => {
const channelMembers = members?.filter((m) => m.userId !== currentUserId);
@ -119,13 +135,24 @@ export const CallNotification = ({
}
}, []);
// We only need to getServerDisplayName once
useEffect(() => {
async function getName() {
setServerName(await getServerDisplayName(incomingCall.serverUrl));
}
if (moreThanOneServer) {
getName();
}
}, [moreThanOneServer, incomingCall.serverUrl]);
const onContainerPress = useCallback(async () => {
if (serverUrl !== incomingCall.serverUrl) {
if (incomingCall.serverUrl !== serverUrl) {
await DatabaseManager.setActiveServerDatabase(incomingCall.serverUrl);
await WebsocketManager.initializeClient(incomingCall.serverUrl);
}
switchToChannelById(incomingCall.serverUrl, incomingCall.channelID);
}, [serverUrl, incomingCall]);
}, [incomingCall, serverUrl]);
const onDismissPress = useCallback(() => {
removeIncomingCall(serverUrl, incomingCall.callID, incomingCall.channelID);
@ -143,7 +170,7 @@ export const CallNotification = ({
name: displayUsername(incomingCall.callerModel, intl.locale, teammateNameDisplay),
}}
style={style.text}
numberOfLines={2}
numberOfLines={1}
ellipsizeMode={'tail'}
/>
);
@ -158,14 +185,14 @@ export const CallNotification = ({
num: (members?.length || 2) - 1,
}}
style={style.text}
numberOfLines={2}
numberOfLines={1}
ellipsizeMode={'tail'}
/>
);
}
return (
<View style={[style.outerContainer]}>
<View style={[style.outerContainer, moreThanOneServer && style.outerContainerServerName]}>
<Pressable
style={[style.innerContainer, onCallsScreen && style.innerOnCallsScreen]}
onPress={onContainerPress}
@ -180,6 +207,11 @@ export const CallNotification = ({
</View>
<View style={style.textContainer}>
{message}
{moreThanOneServer &&
<Text style={style.textServerName}>
{serverName}
</Text>
}
</View>
<Pressable onPress={onDismissPress}>
<View style={style.dismissContainer}>

View file

@ -5,6 +5,7 @@ import withObservables from '@nozbe/with-observables';
import {of as of$} from 'rxjs';
import {distinctUntilChanged, switchMap} from 'rxjs/operators';
import {observeAllActiveServers} from '@app/queries/app/servers';
import {CallNotification} from '@calls/components/call_notification/call_notification';
import DatabaseManager from '@database/manager';
import {observeChannelMembers} from '@queries/servers/channel';
@ -33,6 +34,7 @@ const enhanced = withObservables(['incomingCall'], ({incomingCall}: OwnProps) =>
);
return {
servers: observeAllActiveServers(),
currentUserId,
teammateNameDisplay,
members,

View file

@ -8,13 +8,26 @@ import {useIntl} from 'react-intl';
import {Alert, Platform} from 'react-native';
import Permissions from 'react-native-permissions';
import {CALL_ERROR_BAR_HEIGHT, CALL_NOTIFICATION_BAR_HEIGHT, CURRENT_CALL_BAR_HEIGHT, JOIN_CALL_BAR_HEIGHT} from '@app/constants/view';
import {
CALL_ERROR_BAR_HEIGHT,
CALL_NOTIFICATION_BAR_HEIGHT,
CURRENT_CALL_BAR_HEIGHT,
JOIN_CALL_BAR_HEIGHT,
} from '@app/constants/view';
import {initializeVoiceTrack} from '@calls/actions/calls';
import {setMicPermissionsGranted, useCallsState, useChannelsWithCalls, useCurrentCall, useGlobalCallsState, useIncomingCalls} from '@calls/state';
import {
setMicPermissionsGranted,
useCallsState,
useChannelsWithCalls,
useCurrentCall,
useGlobalCallsState,
useIncomingCalls,
} from '@calls/state';
import {errorAlert} from '@calls/utils';
import {useServerUrl} from '@context/server';
import {useAppState} from '@hooks/device';
import NetworkManager from '@managers/network_manager';
import {queryAllActiveServers} from '@queries/app/servers';
import {getFullErrorMessage} from '@utils/errors';
import type {Client} from '@client/rest';
@ -110,26 +123,35 @@ export const usePermissionsChecker = (micPermissionsGranted: boolean) => {
}, [appState]);
};
export const useCallsAdjustment = (serverUrl: string, channelId: string) => {
export const useCallsAdjustment = (serverUrl: string, channelId: string): number => {
const incomingCalls = useIncomingCalls().incomingCalls;
const channelsWithCalls = useChannelsWithCalls(serverUrl);
const callsState = useCallsState(serverUrl);
const globalCallsState = useGlobalCallsState();
const currentCall = useCurrentCall();
const [numServers, setNumServers] = useState(1);
const dismissed = Boolean(callsState.calls[channelId]?.dismissed[callsState.myUserId]);
const inCurrentCall = currentCall?.id === channelId;
const joinCallBannerVisible = Boolean(channelsWithCalls[channelId]) && !dismissed && !inCurrentCall;
useEffect(() => {
const getNumServers = async () => {
const query = await queryAllActiveServers()?.fetch();
setNumServers(query?.length || 0);
};
getNumServers();
}, []);
// Do we have calls banners?
const currentCallBarVisible = Boolean(currentCall);
const micPermissionsError = !globalCallsState.micPermissionsGranted && (currentCall && !currentCall.micPermissionsErrorDismissed);
const callQualityAlert = Boolean(currentCall?.callQualityAlert);
const incomingCallsShowing = incomingCalls.filter((ic) => ic.channelID !== channelId);
const callsIncomingAdjustment = (incomingCallsShowing.length * CALL_NOTIFICATION_BAR_HEIGHT) + (incomingCallsShowing.length * 8);
const callsAdjustment = (currentCallBarVisible ? CURRENT_CALL_BAR_HEIGHT + 8 : 0) +
const notificationBarHeight = CALL_NOTIFICATION_BAR_HEIGHT + (numServers > 1 ? 8 : 0);
const callsIncomingAdjustment = (incomingCallsShowing.length * notificationBarHeight) + (incomingCallsShowing.length * 8);
return (currentCallBarVisible ? CURRENT_CALL_BAR_HEIGHT + 8 : 0) +
(micPermissionsError ? CALL_ERROR_BAR_HEIGHT + 8 : 0) +
(callQualityAlert ? CALL_ERROR_BAR_HEIGHT + 8 : 0) +
(joinCallBannerVisible ? JOIN_CALL_BAR_HEIGHT + 8 : 0) +
callsIncomingAdjustment;
return callsAdjustment;
};