MM-45754 - Calls: Add current call bar to thread screen (#6628)

* remove isCallsPluginEnabled; add current call bar to thread screen

* popTo thread/call screen; updateProps in dismissAllModalsAndPopToScreen

* remove unneeded withServerUrl; only updateProps if needed
This commit is contained in:
Christopher Poile
2022-10-25 21:34:51 -04:00
committed by GitHub
parent bb051b83b9
commit 67342246eb
8 changed files with 55 additions and 27 deletions

View File

@@ -13,7 +13,7 @@ import CompassIcon from '@components/compass_icon';
import {Events, Screens, WebsocketEvents} from '@constants';
import {CURRENT_CALL_BAR_HEIGHT} from '@constants/view';
import {useTheme} from '@context/theme';
import {goToScreen} from '@screens/navigation';
import {dismissAllModalsAndPopToScreen} from '@screens/navigation';
import {makeStyleSheetFromTheme} from '@utils/theme';
import {displayUsername} from '@utils/user';
@@ -24,6 +24,7 @@ type Props = {
currentCall: CurrentCall | null;
userModelsDict: Dictionary<UserModel>;
teammateNameDisplay: string;
threadScreen?: boolean;
}
const getStyleSheet = makeStyleSheetFromTheme((theme: Theme) => {
@@ -85,6 +86,7 @@ const CurrentCallBar = ({
currentCall,
userModelsDict,
teammateNameDisplay,
threadScreen,
}: Props) => {
const theme = useTheme();
const {formatMessage} = useIntl();
@@ -128,7 +130,7 @@ const CurrentCallBar = ({
}
}, [speaker, setTalkingMessage]);
const goToCallScreen = useCallback(() => {
const goToCallScreen = useCallback(async () => {
const options: Options = {
layout: {
backgroundColor: '#000',
@@ -143,8 +145,8 @@ const CurrentCallBar = ({
},
};
const title = formatMessage({id: 'mobile.calls_call_screen', defaultMessage: 'Call'});
goToScreen(Screens.CALL, title, {}, options);
}, []);
await dismissAllModalsAndPopToScreen(Screens.CALL, title, {fromThreadScreen: threadScreen}, options);
}, [formatMessage, threadScreen]);
const myParticipant = currentCall?.participants[currentCall.myUserId];

View File

@@ -29,12 +29,13 @@ const style = StyleSheet.create({
type Props = {
children: React.ReactNode;
threadScreen?: boolean;
}
const FloatingCallContainer = (props: Props) => {
const FloatingCallContainer = ({threadScreen, ...props}: Props) => {
const insets = useSafeAreaInsets();
const wrapperTop = {
top: topBarHeight + insets.top,
top: insets.top + (threadScreen ? 0 : topBarHeight),
};
return (

View File

@@ -38,7 +38,13 @@ import SlideUpPanelItem, {ITEM_HEIGHT} from '@components/slide_up_panel_item';
import {WebsocketEvents, Screens} from '@constants';
import {useTheme} from '@context/theme';
import DatabaseManager from '@database/manager';
import {bottomSheet, dismissBottomSheet, goToScreen, popTopScreen} from '@screens/navigation';
import {
bottomSheet,
dismissAllModalsAndPopToScreen,
dismissBottomSheet,
goToScreen,
popTopScreen,
} from '@screens/navigation';
import NavigationStore from '@store/navigation_store';
import {bottomSheetSnapPoint} from '@utils/helpers';
import {mergeNavigationOptions} from '@utils/navigation';
@@ -50,6 +56,7 @@ export type Props = {
currentCall: CurrentCall | null;
participantsDict: Dictionary<CallParticipant>;
teammateNameDisplay: string;
fromThreadScreen?: boolean;
}
const getStyleSheet = makeStyleSheetFromTheme((theme: Theme) => ({
@@ -247,18 +254,20 @@ const getStyleSheet = makeStyleSheetFromTheme((theme: Theme) => ({
},
}));
const CallScreen = ({componentId, currentCall, participantsDict, teammateNameDisplay}: Props) => {
const CallScreen = ({componentId, currentCall, participantsDict, teammateNameDisplay, fromThreadScreen}: Props) => {
const intl = useIntl();
const theme = useTheme();
const insets = useSafeAreaInsets();
const {width, height} = useWindowDimensions();
const isLandscape = width > height;
const [showControlsInLandscape, setShowControlsInLandscape] = useState(false);
const myParticipant = currentCall?.participants[currentCall.myUserId];
const style = getStyleSheet(theme);
const showControls = !isLandscape || showControlsInLandscape;
const [speakers, setSpeakers] = useState<Dictionary<boolean>>({});
const style = getStyleSheet(theme);
const isLandscape = width > height;
const showControls = !isLandscape || showControlsInLandscape;
const myParticipant = currentCall?.participants[currentCall.myUserId];
const chatThreadTitle = intl.formatMessage({id: 'mobile.calls_chat_thread', defaultMessage: 'Chat thread'});
useEffect(() => {
mergeNavigationOptions('Call', {
layout: {
@@ -329,17 +338,20 @@ const CallScreen = ({componentId, currentCall, participantsDict, teammateNameDis
const activeUrl = await DatabaseManager.getActiveServerUrl();
if (activeUrl === currentCall.serverUrl) {
goToScreen(Screens.THREAD, '', {rootId: currentCall.threadId});
await dismissAllModalsAndPopToScreen(Screens.THREAD, chatThreadTitle, {rootId: currentCall.threadId});
return;
}
// TODO: this is a temporary solution until we have a proper cross-team thread view.
// https://mattermost.atlassian.net/browse/MM-45752
popTopScreen(componentId);
await popTopScreen(componentId);
if (fromThreadScreen) {
await popTopScreen(Screens.THREAD);
}
await DatabaseManager.setActiveServerDatabase(currentCall.serverUrl);
await appEntry(currentCall.serverUrl, Date.now());
goToScreen(Screens.THREAD, '', {rootId: currentCall.threadId});
}, [currentCall?.serverUrl, currentCall?.threadId]);
await goToScreen(Screens.THREAD, chatThreadTitle, {rootId: currentCall.threadId});
}, [currentCall?.serverUrl, currentCall?.threadId, fromThreadScreen, componentId, chatThreadTitle]);
const showOtherActions = useCallback(() => {
const renderContent = () => {
@@ -348,7 +360,7 @@ const CallScreen = ({componentId, currentCall, participantsDict, teammateNameDis
<SlideUpPanelItem
icon='message-text-outline'
onPress={switchToThread}
text={intl.formatMessage({id: 'mobile.calls_chat_thread', defaultMessage: 'Chat thread'})}
text={chatThreadTitle}
/>
</View>
);

View File

@@ -28,7 +28,6 @@ type ChannelProps = {
serverUrl: string;
channelId: string;
componentId?: string;
isCallsPluginEnabled: boolean;
isCallInCurrentChannel: boolean;
isInACall: boolean;
isInCurrentChannelCall: boolean;
@@ -47,7 +46,6 @@ const Channel = ({
serverUrl,
channelId,
componentId,
isCallsPluginEnabled,
isCallInCurrentChannel,
isInACall,
isInCurrentChannelCall,
@@ -120,7 +118,7 @@ const Channel = ({
let callsComponents: JSX.Element | null = null;
const showJoinCallBanner = isCallInCurrentChannel && !isInCurrentChannelCall;
if (isCallsPluginEnabled && (showJoinCallBanner || isInACall)) {
if (showJoinCallBanner || isInACall) {
callsComponents = (
<FloatingCallContainer>
{showJoinCallBanner &&

View File

@@ -20,10 +20,6 @@ type EnhanceProps = WithDatabaseArgs & {
const enhanced = withObservables([], ({database, serverUrl}: EnhanceProps) => {
const channelId = observeCurrentChannelId(database);
const isCallsPluginEnabled = observeCallsConfig(serverUrl).pipe(
switchMap((config) => of$(config.pluginEnabled)),
distinctUntilChanged(),
);
const isCallInCurrentChannel = combineLatest([channelId, observeChannelsWithCalls(serverUrl)]).pipe(
switchMap(([id, calls]) => of$(Boolean(calls[id]))),
distinctUntilChanged(),
@@ -60,7 +56,6 @@ const enhanced = withObservables([], ({database, serverUrl}: EnhanceProps) => {
return {
channelId,
isCallsPluginEnabled,
isCallInCurrentChannel,
isInACall,
isInCurrentChannelCall,

View File

@@ -403,7 +403,7 @@ export async function dismissAllModalsAndPopToRoot() {
* (if the screen is not in the stack, it will push a new one)
* @param screenId Screen to pop or display
* @param title Title to be shown in the top bar
* @param passProps Props to pass to the screen (Only if the screen does not exist in the stack)
* @param passProps Props to pass to the screen
* @param options Navigation options
*/
export async function dismissAllModalsAndPopToScreen(screenId: string, title: string, passProps = {}, options = {}) {
@@ -421,6 +421,9 @@ export async function dismissAllModalsAndPopToScreen(screenId: string, title: st
}
try {
await Navigation.popTo(screenId, mergeOptions);
if (Object.keys(passProps).length > 0) {
await Navigation.updateProps(screenId, passProps);
}
} catch {
// catch in case there is nothing to pop
}

View File

@@ -3,7 +3,10 @@
import {withDatabase} from '@nozbe/watermelondb/DatabaseProvider';
import withObservables from '@nozbe/with-observables';
import {of as of$} from 'rxjs';
import {distinctUntilChanged, switchMap} from 'rxjs/operators';
import {observeCurrentCall} from '@calls/state';
import {observePost} from '@queries/servers/post';
import Thread from './thread';
@@ -11,8 +14,14 @@ import Thread from './thread';
import type {WithDatabaseArgs} from '@typings/database/database';
const enhanced = withObservables(['rootId'], ({database, rootId}: WithDatabaseArgs & {rootId: string}) => {
const isInACall = observeCurrentCall().pipe(
switchMap((call) => of$(Boolean(call))),
distinctUntilChanged(),
);
return {
rootPost: observePost(database, rootId),
isInACall,
};
});

View File

@@ -6,6 +6,8 @@ import {DeviceEventEmitter, LayoutChangeEvent, StyleSheet, View} from 'react-nat
import {KeyboardTrackingViewRef} from 'react-native-keyboard-tracking-view';
import {Edge, SafeAreaView} from 'react-native-safe-area-context';
import CurrentCallBar from '@calls/components/current_call_bar';
import FloatingCallContainer from '@calls/components/floating_call_container';
import FreezeScreen from '@components/freeze_screen';
import PostDraft from '@components/post_draft';
import RoundedHeaderContext from '@components/rounded_header_context';
@@ -23,6 +25,7 @@ import type PostModel from '@typings/database/models/servers/post';
type ThreadProps = {
componentId: string;
rootPost?: PostModel;
isInACall: boolean;
};
const edges: Edge[] = ['left', 'right'];
@@ -31,7 +34,7 @@ const styles = StyleSheet.create({
flex: {flex: 1},
});
const Thread = ({componentId, rootPost}: ThreadProps) => {
const Thread = ({componentId, rootPost, isInACall}: ThreadProps) => {
const appState = useAppState();
const postDraftRef = useRef<KeyboardTrackingViewRef>(null);
const [containerHeight, setContainerHeight] = useState(0);
@@ -96,6 +99,11 @@ const Thread = ({componentId, rootPost}: ThreadProps) => {
/>
</>
}
{isInACall &&
<FloatingCallContainer threadScreen={true}>
<CurrentCallBar threadScreen={true}/>
</FloatingCallContainer>
}
</SafeAreaView>
</FreezeScreen>
);