Handled case of no common team

This commit is contained in:
harshil Sharma 2023-10-27 17:14:24 +05:30
parent 6752d84b21
commit 723f88cdcf
4 changed files with 347 additions and 0 deletions

View file

@ -0,0 +1,118 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
import React, {useCallback, useEffect, useRef} from 'react';
import {useIntl} from 'react-intl';
import {View} from 'react-native';
import {useTheme} from '@app/context/theme';
import {logDebug} from '@app/utils/log';
import {makeStyleSheetFromTheme} from '@app/utils/theme';
import {displayUsername} from '@app/utils/user';
import Button from '@components/button';
import {ChannelNameInput} from '../channel_name_input';
import MessageBox from '../message_box/message_box';
import {TeamSelector} from '../team_selector';
import {NoCommonTeamForm} from './no_common_teams_form';
const getStyleFromTheme = makeStyleSheetFromTheme((theme: Theme) => {
return {
container: {
paddingVertical: 24,
paddingHorizontal: 20,
display: 'flex',
flexDirection: 'column',
gap: 24,
},
};
});
type Props = {
commonTeams: Team[];
profiles: UserProfile[];
locale?: string;
teammateNameDisplay: string;
}
export const ConvertGMToChannelForm = ({
commonTeams,
profiles,
locale,
teammateNameDisplay,
}: Props) => {
const theme = useTheme();
const styles = getStyleFromTheme(theme);
const team = useRef<Team>();
const {formatMessage} = useIntl();
const confirmButtonText = formatMessage({
id: 'channel_info.convert_gm_to_channel.button_text',
defaultMessage: 'Convert to Private Channel',
});
useEffect(() => {
if (commonTeams.length > 0) {
team.current = commonTeams[0];
}
}, [commonTeams]);
const handleOnSelectTeam = useCallback((selectedTeam: Team) => {
team.current = selectedTeam;
}, []);
const handleOnPress = useCallback(() => {
logDebug(1);
}, []);
const intl = useIntl();
const messageBoxHeader = intl.formatMessage({
id: 'channel_info.convert_gm_to_channel.warning.header',
defaultMessage: 'Conversation history will be visible to any channel members',
});
const userDisplayNames = profiles.map((profile) => displayUsername(profile, locale, teammateNameDisplay));
const defaultUserDisplayNames = intl.formatMessage({id: 'channel_info.convert_gm_to_channel.warning.body.yourself', defaultMessage: 'yourself'});
const memberNames = profiles.length > 0 ? intl.formatList(userDisplayNames) : defaultUserDisplayNames;
const messageBoxBody = intl.formatMessage({
id: 'channel_info.convert_gm_to_channel.warning.bodyXXXX',
defaultMessage: 'You are about to convert the Group Message with {memberNames} to a Channel. This cannot be undone.',
}, {
memberNames,
});
if (commonTeams.length === 0) {
return (
<NoCommonTeamForm containerStyles={styles.container}/>
);
}
return (
<View style={styles.container}>
<MessageBox
header={messageBoxHeader}
body={messageBoxBody}
/>
{
commonTeams.length > 1 &&
<TeamSelector
commonTeams={commonTeams}
onSelectTeam={handleOnSelectTeam}
selectedTeamId={team.current?.id}
/>
}
<ChannelNameInput/>
<Button
onPress={handleOnPress}
text={confirmButtonText}
theme={theme}
buttonType='destructive'
size='lg'
/>
</View>
);
};

View file

@ -0,0 +1,29 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
import {withDatabase} from '@nozbe/watermelondb/DatabaseProvider';
import {switchMap, distinctUntilChanged} from '@nozbe/watermelondb/utils/rx';
import withObservables from '@nozbe/with-observables';
import {of as of$} from 'rxjs';
import {observeCurrentUser, observeTeammateNameDisplay} from '@app/queries/servers/user';
import {ConvertGMToChannelForm} from './convert_gm_to_channel_form';
import type {WithDatabaseArgs} from '@typings/database/database';
const enhanced = withObservables([], ({database}: WithDatabaseArgs) => {
const locale = observeCurrentUser(database).pipe(
switchMap((user) => of$(user?.locale)),
distinctUntilChanged(),
);
const teammateNameDisplay = observeTeammateNameDisplay(database);
return {
locale,
teammateNameDisplay,
};
});
export default withDatabase(enhanced(ConvertGMToChannelForm));

View file

@ -0,0 +1,58 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
import React, {useCallback} from 'react';
import {useIntl} from 'react-intl';
import {View, type ViewStyle} from 'react-native';
import Button from '@app/components/button';
import {useTheme} from '@app/context/theme';
import {popTopScreen} from '@app/screens/navigation';
import MessageBox from '../message_box/message_box';
type Props = {
containerStyles: ViewStyle;
}
export const NoCommonTeamForm = ({
containerStyles,
}: Props) => {
const theme = useTheme();
const {formatMessage} = useIntl();
const header = formatMessage({
id: 'channel_info.convert_gm_to_channel.warning.no_teams.header',
defaultMessage: 'Unable to convert to a channel because group members are part of different teams',
});
const body = formatMessage({
id: 'channel_info.convert_gm_to_channel.warning.no_teams.body',
defaultMessage: 'Group Message cannot be converted to a channel because members are not a part of the same team. Add all members to a single team to convert this group message to a channel.',
});
const handleOnPress = useCallback(() => {
popTopScreen();
}, []);
const buttonText = formatMessage({
id: 'generic.back',
defaultMessage: 'back',
});
return (
<View style={containerStyles}>
<MessageBox
header={header}
body={body}
type='danger'
/>
<Button
onPress={handleOnPress}
text={buttonText}
theme={theme}
size='lg'
/>
</View>
);
};

View file

@ -0,0 +1,142 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
import React from 'react';
import {Text, View} from 'react-native';
import CompassIcon from '@app/components/compass_icon';
import {useTheme} from '@app/context/theme';
import {changeOpacity, makeStyleSheetFromTheme} from '@app/utils/theme';
import {typography} from '@app/utils/typography';
type MessageBoxTypes = 'default' | 'danger'
type Props = {
header: string;
body: string;
type?: MessageBoxTypes;
}
const getBaseStyles = makeStyleSheetFromTheme((theme: Theme) => {
return {
container: {
backgroundColor: changeOpacity(theme.sidebarTextActiveBorder, 0.08),
borderWidth: 1,
borderRadius: 8,
borderColor: changeOpacity(theme.sidebarTextActiveBorder, 0.16),
display: 'flex',
flexDirection: 'row',
padding: 16,
gap: 12,
},
icon: {
marginTop: 5,
fontSize: 20,
width: 28,
height: 28,
borderWidth: 3,
color: theme.sidebarTextActiveBorder,
borderColor: theme.sidebarTextActiveBorder,
borderRadius: 14,
textAlign: 'center',
},
iconContainer: {},
textContainer: {
display: 'flex',
flexDirection: 'column',
gap: 8,
flex: 1,
},
heading: {
color: theme.centerChannelColor,
...typography('Body', 100, 'SemiBold'),
},
body: {
color: theme.centerChannelColor,
...typography('Body', 100),
},
};
});
const getDefaultStylesFromTheme = makeStyleSheetFromTheme((theme: Theme) => {
return {
container: {
backgroundColor: changeOpacity(theme.sidebarTextActiveBorder, 0.08),
borderColor: changeOpacity(theme.sidebarTextActiveBorder, 0.16),
},
icon: {
color: theme.sidebarTextActiveBorder,
borderColor: theme.sidebarTextActiveBorder,
},
};
});
const getDangerStylesFromTheme = makeStyleSheetFromTheme((theme: Theme) => {
return {
container: {
backgroundColor: changeOpacity(theme.dndIndicator, 0.08),
borderColor: changeOpacity(theme.dndIndicator, 0.16),
},
icon: {
color: theme.dndIndicator,
borderColor: theme.dndIndicator,
},
};
});
const getStyleFromTheme = (theme: Theme, kind: MessageBoxTypes | undefined) => {
const baseStyles = getBaseStyles(theme);
let kindStyles;
switch (kind) {
case 'danger': {
kindStyles = getDangerStylesFromTheme(theme);
break;
}
default: {
kindStyles = getDefaultStylesFromTheme(theme);
break;
}
}
return {
...baseStyles,
...kindStyles,
};
};
const MessageBox = ({
header,
body,
type,
}: Props) => {
const theme = useTheme();
const styles = getBaseStyles(theme);
const foo = getStyleFromTheme(theme, type);
return (
<View style={[styles.container, foo.container]}>
<View style={styles.iconContainer}>
<CompassIcon
name='exclamation-thick'
style={[styles.icon, foo.icon]}
/>
</View>
<View style={styles.textContainer}>
<View>
<Text style={[styles.heading, foo.heading]}>
{header}
</Text>
</View>
<View>
<Text style={[styles.body, foo.body]}>
{body}
</Text>
</View>
</View>
</View>
);
};
export default MessageBox;