Files
mattermost-mobile/app/screens/channel/header/header.tsx

243 lines
8.6 KiB
TypeScript

// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
import React, {useCallback, useMemo} from 'react';
import {useIntl} from 'react-intl';
import {Keyboard, Platform, Text, View} from 'react-native';
import {useSafeAreaInsets} from 'react-native-safe-area-context';
import CompassIcon from '@components/compass_icon';
import CustomStatusEmoji from '@components/custom_status/custom_status_emoji';
import NavigationHeader from '@components/navigation_header';
import {ITEM_HEIGHT} from '@components/option_item';
import RoundedHeaderContext from '@components/rounded_header_context';
import {General, Screens} from '@constants';
import {QUICK_OPTIONS_HEIGHT} from '@constants/view';
import {useTheme} from '@context/theme';
import {useIsTablet} from '@hooks/device';
import {useDefaultHeaderHeight} from '@hooks/header';
import {bottomSheet, popTopScreen, showModal} from '@screens/navigation';
import {isTypeDMorGM} from '@utils/channel';
import {preventDoubleTap} from '@utils/tap';
import {changeOpacity, makeStyleSheetFromTheme} from '@utils/theme';
import {typography} from '@utils/typography';
import OtherMentionsBadge from './other_mentions_badge';
import QuickActions from './quick_actions';
import type {HeaderRightButton} from '@components/navigation_header/header';
type ChannelProps = {
channelId: string;
channelType: ChannelType;
customStatus?: UserCustomStatus;
isCustomStatusExpired: boolean;
componentId?: string;
displayName: string;
isOwnDirectMessage: boolean;
memberCount?: number;
searchTerm: string;
teamId: string;
callsEnabledInChannel: boolean;
callsFeatureRestricted: boolean;
};
const getStyleSheet = makeStyleSheetFromTheme((theme: Theme) => ({
customStatusContainer: {
flexDirection: 'row',
height: 13,
left: Platform.select({ios: undefined, default: -2}),
marginTop: Platform.select({ios: undefined, default: 1}),
},
customStatusEmoji: {marginRight: 5},
customStatusText: {
alignItems: 'center',
height: 13,
},
subtitle: {
color: changeOpacity(theme.sidebarHeaderTextColor, 0.72),
...typography('Body', 75),
lineHeight: 12,
marginBottom: 8,
marginTop: 2,
height: 13,
},
}));
const ChannelHeader = ({
channelId, channelType, componentId, customStatus, displayName,
isCustomStatusExpired, isOwnDirectMessage, memberCount,
searchTerm, teamId, callsEnabledInChannel, callsFeatureRestricted,
}: ChannelProps) => {
const intl = useIntl();
const isTablet = useIsTablet();
const theme = useTheme();
const styles = getStyleSheet(theme);
const defaultHeight = useDefaultHeaderHeight();
const insets = useSafeAreaInsets();
const callsAvailable = callsEnabledInChannel && !callsFeatureRestricted;
const isDMorGM = isTypeDMorGM(channelType);
const contextStyle = useMemo(() => ({
top: defaultHeight + insets.top,
}), [defaultHeight, insets.top]);
const leftComponent = useMemo(() => {
if (isTablet || !channelId || !teamId) {
return undefined;
}
return (<OtherMentionsBadge channelId={channelId}/>);
}, [isTablet, channelId, teamId]);
const onBackPress = useCallback(() => {
Keyboard.dismiss();
popTopScreen(componentId);
}, []);
const onTitlePress = useCallback(preventDoubleTap(() => {
let title;
switch (channelType) {
case General.DM_CHANNEL:
title = intl.formatMessage({id: 'screens.channel_info.dm', defaultMessage: 'Direct message info'});
break;
case General.GM_CHANNEL:
title = intl.formatMessage({id: 'screens.channel_info.gm', defaultMessage: 'Group message info'});
break;
default:
title = intl.formatMessage({id: 'screens.channel_info', defaultMessage: 'Channel info'});
break;
}
const closeButton = CompassIcon.getImageSourceSync('close', 24, theme.sidebarHeaderTextColor);
const closeButtonId = 'close-channel-info';
const options = {
topBar: {
leftButtons: [{
id: closeButtonId,
icon: closeButton,
testID: 'close.channel_info.button',
}],
},
};
showModal(Screens.CHANNEL_INFO, title, {channelId, closeButtonId}, options);
}), [channelId, channelType, intl, theme]);
const onChannelQuickAction = useCallback(() => {
if (isTablet) {
onTitlePress();
return;
}
// When calls is enabled, we need space to move the "Copy Link" from a button to an option
const height = QUICK_OPTIONS_HEIGHT + (callsAvailable && !isDMorGM ? ITEM_HEIGHT : 0);
const renderContent = () => {
return (
<QuickActions
channelId={channelId}
callsEnabled={callsAvailable}
isDMorGM={isDMorGM}
/>
);
};
bottomSheet({
title: '',
renderContent,
snapPoints: [height, 10],
theme,
closeButtonId: 'close-channel-quick-actions',
});
}, [channelId, isDMorGM, isTablet, onTitlePress, theme, callsAvailable]);
const rightButtons: HeaderRightButton[] = useMemo(() => ([
// {
// iconName: 'magnify',
// onPress: () => {
// DeviceEventEmitter.emit(Navigation.NAVIGATE_TO_TAB, {screen: 'Search', params: {searchTerm: `in: ${searchTerm}`}});
// if (!isTablet) {
// popTopScreen(componentId);
// }
// },
// },
{
iconName: Platform.select({android: 'dots-vertical', default: 'dots-horizontal'}),
onPress: onChannelQuickAction,
buttonType: 'opacity',
testID: 'channel_header.channel_quick_actions.button',
}]), [isTablet, searchTerm, onChannelQuickAction]);
let title = displayName;
if (isOwnDirectMessage) {
title = intl.formatMessage({id: 'channel_header.directchannel.you', defaultMessage: '{displayName} (you)'}, {displayName});
}
let subtitle;
if (memberCount) {
subtitle = intl.formatMessage({id: 'channel_header.member_count', defaultMessage: '{count, plural, one {# member} other {# members}}'}, {count: memberCount});
} else if (!customStatus || !customStatus.text || isCustomStatusExpired) {
subtitle = intl.formatMessage({id: 'channel_header.info', defaultMessage: 'View info'});
}
const subtitleCompanion = useMemo(() => {
if (memberCount || !customStatus || !customStatus.text || isCustomStatusExpired) {
return (
<CompassIcon
color={changeOpacity(theme.sidebarHeaderTextColor, 0.72)}
name='chevron-right'
size={14}
/>
);
} else if (customStatus && customStatus.text) {
return (
<View style={styles.customStatusContainer}>
{Boolean(customStatus.emoji) &&
<CustomStatusEmoji
customStatus={customStatus}
emojiSize={13}
style={styles.customStatusEmoji}
testID='channel_header'
/>
}
<View style={styles.customStatusText}>
<Text
numberOfLines={1}
ellipsizeMode='tail'
style={styles.subtitle}
testID='channel_header.custom_status.custom_status_text'
>
{customStatus.text}
</Text>
</View>
</View>
);
}
return undefined;
}, [memberCount, customStatus, isCustomStatusExpired]);
return (
<>
<NavigationHeader
isLargeTitle={false}
leftComponent={leftComponent}
onBackPress={onBackPress}
onTitlePress={onTitlePress}
rightButtons={rightButtons}
showBackButton={!isTablet}
subtitle={subtitle}
subtitleCompanion={subtitleCompanion}
title={title}
/>
<View style={contextStyle}>
<RoundedHeaderContext/>
</View>
</>
);
};
export default ChannelHeader;