Handled case of no common team
This commit is contained in:
parent
6752d84b21
commit
723f88cdcf
4 changed files with 347 additions and 0 deletions
|
|
@ -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>
|
||||
);
|
||||
};
|
||||
|
|
@ -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));
|
||||
|
|
@ -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>
|
||||
);
|
||||
};
|
||||
142
app/screens/convert_gm_to_channel/message_box/message_box.tsx
Normal file
142
app/screens/convert_gm_to_channel/message_box/message_box.tsx
Normal 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;
|
||||
Loading…
Reference in a new issue