review fixes

This commit is contained in:
harshil Sharma 2023-11-15 14:13:55 +05:30
parent 9c6ae712a9
commit 4af2ad2f69
9 changed files with 109 additions and 75 deletions

View file

@ -1309,7 +1309,7 @@ export const convertGroupMessageToPrivateChannel = async (serverUrl: string, cha
return {updatedChannel};
} catch (error) {
logDebug('error on convertGroupMessageToPrivateChannel', getFullErrorMessage(error));
logError('error on convertGroupMessageToPrivateChannel', getFullErrorMessage(error));
forceLogoutIfNecessary(serverUrl, error);
return {error};
} finally {

View file

@ -1,7 +1,7 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
import React, {useMemo} from 'react';
import React, {useMemo, type ReactNode} from 'react';
import {type StyleProp, StyleSheet, Text, type TextStyle, View, type ViewStyle} from 'react-native';
import RNButton from 'react-native-button';
@ -21,6 +21,7 @@ type Props = ConditionalProps & {
testID?: string;
onPress: () => void;
text: string;
iconComponent?: ReactNode;
}
const styles = StyleSheet.create({
@ -41,6 +42,7 @@ const Button = ({
testID,
iconName,
iconSize,
iconComponent,
}: Props) => {
const bgStyle = useMemo(() => [
buttonBackgroundStyle(theme, size, emphasis, buttonType, buttonState),
@ -61,6 +63,21 @@ const Button = ({
[iconSize],
);
let icon: ReactNode;
if (iconComponent) {
icon = iconComponent;
} else if (iconName) {
icon = (
<CompassIcon
name={iconName!}
size={iconSize}
color={StyleSheet.flatten(txtStyle).color}
style={styles.icon}
/>
);
}
return (
<RNButton
containerStyle={bgStyle}
@ -68,14 +85,7 @@ const Button = ({
testID={testID}
>
<View style={containerStyle}>
{Boolean(iconName) &&
<CompassIcon
name={iconName!}
size={iconSize}
color={StyleSheet.flatten(txtStyle).color}
style={styles.icon}
/>
}
{icon}
<Text
style={txtStyle}
numberOfLines={1}

View file

@ -1,7 +1,7 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
import React from 'react';
import React, {useCallback} from 'react';
import {useIntl} from 'react-intl';
import OptionItem from '@components/option_item';
@ -16,11 +16,11 @@ type Props = {
const ConvertToChannelLabel = ({channelId}: Props) => {
const {formatMessage} = useIntl();
const goToConvertToPrivateChannel = preventDoubleTap(async () => {
const goToConvertToPrivateChannel = useCallback(preventDoubleTap(async () => {
await dismissBottomSheet();
const title = formatMessage({id: 'channel_info.convert_gm_to_channel.screen_title', defaultMessage: 'Convert to Private Channel'});
goToScreen(Screens.CONVERT_GM_TO_CHANNEL, title, {channelId});
});
}), [channelId]);
return (
<OptionItem

View file

@ -21,6 +21,27 @@ type Props = {
const loadingIndicatorTimeout = 1200;
const matchUserProfiles = (users: UserProfile[], members: ChannelMembership[], currentUserId: string) => {
// Gotta make sure we use profiles that are in members.
// See comment in fetchChannelMemberships for more details.
const usersById: {[id: string]: UserProfile} = {};
users.forEach((profile) => {
if (profile.id !== currentUserId) {
usersById[profile.id] = profile;
}
});
const filteredUsers: UserProfile[] = [];
members.forEach((member) => {
if (usersById[member.user_id]) {
filteredUsers.push(usersById[member.user_id]);
}
});
return filteredUsers;
};
const getStyleFromTheme = makeStyleSheetFromTheme((theme: Theme) => {
return {
loadingContainer: {
@ -74,48 +95,29 @@ const ConvertGMToChannel = ({
};
}, []);
const matchUserProfiles = (users: UserProfile[], members: ChannelMembership[]) => {
// Gotta make sure we use profiles that are in members.
// See comment in fetchChannelMemberships for more details.
const usersById: {[id: string]: UserProfile} = {};
users.forEach((profile) => {
if (profile.id !== currentUserId) {
usersById[profile.id] = profile;
}
});
const filteredUsers: UserProfile[] = [];
members.forEach((member) => {
if (usersById[member.user_id]) {
filteredUsers.push(usersById[member.user_id]);
}
});
return filteredUsers;
};
useEffect(() => {
mounted.current = true;
const options: GetUsersOptions = {sort: 'admin', active: true, per_page: PER_PAGE_DEFAULT};
fetchChannelMemberships(serverUrl, channelId, options, true).then(({users, members}) => {
if (!mounted.current) {
return;
}
if (users.length) {
setProfiles(matchUserProfiles(users, members));
}
setChannelMembersFetched(true);
});
return () => {
mounted.current = false;
};
}, []);
useEffect(() => {
const options: GetUsersOptions = {sort: 'admin', active: true, per_page: PER_PAGE_DEFAULT};
fetchChannelMemberships(serverUrl, channelId, options, true).then(({users, members}) => {
if (!mounted.current || !currentUserId) {
return;
}
if (users.length) {
setProfiles(matchUserProfiles(users, members, currentUserId));
}
setChannelMembersFetched(true);
});
}, [serverUrl, channelId, currentUserId]);
const showLoader = !loadingAnimationTimeout || !commonTeamsFetched || !channelMembersFetched;
if (showLoader) {

View file

@ -6,12 +6,14 @@ import {useIntl} from 'react-intl';
import {Text, View} from 'react-native';
import {convertGroupMessageToPrivateChannel, switchToChannelById} from '@actions/remote/channel';
import {isErrorWithMessage} from '@app/utils/errors';
import Loading from '@app/components/loading';
import {logError} from '@app/utils/log';
import Button from '@components/button';
import {useServerUrl} from '@context/server';
import {useTheme} from '@context/theme';
import {isErrorWithMessage} from '@utils/errors';
import {preventDoubleTap} from '@utils/tap';
import {makeStyleSheetFromTheme} from '@utils/theme';
import {changeOpacity, makeStyleSheetFromTheme} from '@utils/theme';
import {displayUsername} from '@utils/user';
import {ChannelNameInput} from '../channel_name_input';
@ -32,6 +34,11 @@ const getStyleFromTheme = makeStyleSheetFromTheme((theme: Theme) => {
errorMessage: {
color: theme.dndIndicator,
},
loadingContainerStyle: {
marginRight: 10,
padding: 0,
top: -2,
},
};
});
@ -58,10 +65,11 @@ export const ConvertGMToChannelForm = ({
const [selectedTeam, setSelectedTeam] = useState<Team>();
const [newChannelName, setNewChannelName] = useState<string>('');
const [errorMessage, setErrorMessage] = useState<string>('');
const [conversionInProgress, setConversionInProgress] = useState(false); // LOL revert this default value back to false
const {formatMessage} = useIntl();
const userDisplayNames = useMemo(() => profiles.map((profile) => displayUsername(profile, locale, teammateNameDisplay)), [profiles]);
const submitButtonEnabled = selectedTeam && newChannelName.trim();
const submitButtonEnabled = !conversionInProgress && selectedTeam && newChannelName.trim();
useEffect(() => {
if (commonTeams.length > 0) {
@ -74,6 +82,8 @@ export const ConvertGMToChannelForm = ({
return;
}
setConversionInProgress(true);
const {updatedChannel, error} = await convertGroupMessageToPrivateChannel(serverUrl, channelId, selectedTeam.id, newChannelName);
if (error) {
if (isErrorWithMessage(error)) {
@ -82,16 +92,20 @@ export const ConvertGMToChannelForm = ({
setErrorMessage(formatMessage({id: 'channel_info.convert_gm_to_channel.conversion_error', defaultMessage: 'Something went wrong. Failed to convert Group Message to Private Channel.'}));
}
setConversionInProgress(false);
return;
}
if (!updatedChannel) {
logError('No updated channel received from server when converting GM to private channel');
setErrorMessage(formatMessage({id: 'channel_info.convert_gm_to_channel.conversion_error', defaultMessage: 'Something went wrong. Failed to convert Group Message to Private Channel.'}));
setConversionInProgress(false);
return;
}
setErrorMessage('');
switchToChannelById(serverUrl, updatedChannel.id, selectedTeam.id);
setConversionInProgress(false);
}), [selectedTeam, newChannelName, submitButtonEnabled]);
if (commonTeams.length === 0) {
@ -105,11 +119,17 @@ export const ConvertGMToChannelForm = ({
defaultMessage: 'Conversation history will be visible to any channel members',
});
const confirmButtonText = formatMessage({
const textConvert = formatMessage({
id: 'channel_info.convert_gm_to_channel.button_text',
defaultMessage: 'Convert to Private Channel',
});
const textConverting = formatMessage({
id: 'channel_info.convert_gm_to_channel.button_text_converting',
defaultMessage: 'Converting...',
});
const confirmButtonText = conversionInProgress ? textConverting : textConvert;
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({
@ -119,6 +139,13 @@ export const ConvertGMToChannelForm = ({
memberNames,
});
const buttonIcon = conversionInProgress ? (
<Loading
containerStyle={styles.loadingContainerStyle}
color={changeOpacity(theme.centerChannelColor, 0.32)}
/>
) : null;
return (
<View style={styles.container}>
<MessageBox
@ -140,6 +167,7 @@ export const ConvertGMToChannelForm = ({
theme={theme}
buttonType={submitButtonEnabled ? 'destructive' : 'disabled'}
size='lg'
iconComponent={buttonIcon}
/>
{
errorMessage &&

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, useState} from 'react';
import React, {useCallback, useMemo} from 'react';
import {useIntl} from 'react-intl';
import {Platform} from 'react-native';
@ -19,6 +19,9 @@ const getStyleFromTheme = makeStyleSheetFromTheme((theme: Theme) => {
borderBottomWidth: 1,
borderColor: changeOpacity(theme.centerChannelColor, 0.08),
},
labelContainerStyle: {
flexShrink: 0,
},
};
});
@ -33,15 +36,14 @@ export const TeamSelector = ({commonTeams, onSelectTeam, selectedTeamId}: Props)
const theme = useTheme();
const styles = getStyleFromTheme(theme);
const [selectedTeam, setSelectedTeam] = useState<Team>();
const label = formatMessage({id: 'channel_into.convert_gm_to_channel.team_selector.label', defaultMessage: 'Team'});
const placeholder = formatMessage({id: 'channel_into.convert_gm_to_channel.team_selector.placeholder', defaultMessage: 'Select a Team'});
const selectedTeam = useMemo(() => commonTeams.find((t) => t.id === selectedTeamId), [commonTeams, selectedTeamId]);
const selectTeam = useCallback((teamId: string) => {
const team = commonTeams.find((t) => t.id === teamId);
if (team) {
setSelectedTeam(team);
onSelectTeam(team);
}
}, []);
@ -52,13 +54,6 @@ export const TeamSelector = ({commonTeams, onSelectTeam, selectedTeamId}: Props)
goToScreen(Screens.TEAM_SELECTOR_LIST, title, {teams: commonTeams, selectTeam, selectedTeamId});
}), [commonTeams, selectTeam, selectedTeamId]);
useEffect(() => {
if (selectedTeamId && !selectedTeam) {
const team = commonTeams.find((t) => t.id === selectedTeamId);
setSelectedTeam(team);
}
}, [selectedTeamId]);
return (
<OptionItem
action={goToTeamSelectorList}
@ -66,7 +61,7 @@ export const TeamSelector = ({commonTeams, onSelectTeam, selectedTeamId}: Props)
label={label}
type={Platform.select({ios: 'arrow', default: 'default'})}
info={selectedTeam ? selectedTeam.display_name : placeholder}
labelContainerStyle={{flexShrink: 0}}
labelContainerStyle={styles.labelContainerStyle}
/>
);
};

View file

@ -1,6 +1,7 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
import {debounce} from 'lodash';
import React, {useCallback, useMemo, useState} from 'react';
import {StyleSheet, View} from 'react-native';
@ -27,18 +28,16 @@ type Props = {
const TeamSelectorList = ({teams, selectTeam}: Props) => {
const theme = useTheme();
const [filteredTeams, setFilteredTeam] = useState(teams);
const color = useMemo(() => changeOpacity(theme.centerChannelColor, 0.72), [theme]);
const [filteredTeams, setFilteredTeam] = useState(teams);
const handleOnChangeSearchText = useCallback((searchTerm: string) => {
const handleOnChangeSearchText = useCallback(debounce((searchTerm: string) => {
if (searchTerm === '') {
setFilteredTeam(teams);
} else {
setFilteredTeam(teams.filter((team) => team.display_name.includes(searchTerm) || team.name.includes(searchTerm)));
}
}, [teams]);
}, 200), [teams]);
const handleOnPress = useCallback(preventDoubleTap((teamId: string) => {
selectTeam(teamId);

View file

@ -90,6 +90,9 @@ Navigation.setLazyComponentRegistrator((screenName) => {
case Screens.CODE:
screen = withServerDatabase(require('@screens/code').default);
break;
case Screens.CONVERT_GM_TO_CHANNEL:
screen = withServerDatabase(require('@screens/convert_gm_to_channel').default);
break;
case Screens.CREATE_OR_EDIT_CHANNEL:
screen = withServerDatabase(require('@screens/create_or_edit_channel').default);
break;
@ -242,6 +245,9 @@ Navigation.setLazyComponentRegistrator((screenName) => {
case Screens.TABLE:
screen = withServerDatabase(require('@screens/table').default);
break;
case Screens.TEAM_SELECTOR_LIST:
screen = withServerDatabase(require('@screens/convert_gm_to_channel/team_selector_list').default);
break;
case Screens.TERMS_OF_SERVICE:
screen = withServerDatabase(require('@screens/terms_of_service').default);
break;
@ -262,12 +268,6 @@ Navigation.setLazyComponentRegistrator((screenName) => {
case Screens.CALL:
screen = withServerDatabase(require('@calls/screens/call_screen').default);
break;
case Screens.CONVERT_GM_TO_CHANNEL:
screen = withServerDatabase(require('@screens/convert_gm_to_channel').default);
break;
case Screens.TEAM_SELECTOR_LIST:
screen = withServerDatabase(require('@screens/convert_gm_to_channel/team_selector_list').default);
break;
}
if (screen) {

View file

@ -1,5 +1,4 @@
{
"\"channel_modal.name\": \"Name\",": "",
"about.date": "Build Date:",
"about.enterpriseEditione1": "Enterprise Edition",
"about.enterpriseEditionLearn": "Learn more about Enterprise Edition at ",
@ -122,6 +121,7 @@
"channel_info.convert_failed": "We were unable to convert {displayName} to a private channel.",
"channel_info.convert_gm_to_channel": "Convert to a Private Channel",
"channel_info.convert_gm_to_channel.button_text": "Convert to Private Channel",
"channel_info.convert_gm_to_channel.button_text_converting": "Converting...",
"channel_info.convert_gm_to_channel.conversion_error": "Something went wrong. Failed to convert Group Message to Private Channel.",
"channel_info.convert_gm_to_channel.loading.footer": "Fetching details...",
"channel_info.convert_gm_to_channel.screen_title": "Convert to Private Channel",