Review fixes

This commit is contained in:
harshil Sharma 2023-11-13 15:31:29 +05:30
parent 8fe529a4f5
commit eebd48466f
8 changed files with 139 additions and 118 deletions

View file

@ -10,6 +10,8 @@ import {useServerUrl} from '@context/server';
import ConvertGMToChannelForm from './convert_gm_to_channel_form';
import {Loader} from './loader';
import type UserProfile from '../user_profile/user_profile';
type Props = {
channelId: string;
currentUserId?: string;
@ -30,21 +32,49 @@ const ConvertGMToChannel = ({
const serverUrl = useServerUrl();
const mounted = useRef(false);
const loadingAnimationTimeoutRef = useRef<NodeJS.Timeout>();
useEffect(() => {
setTimeout(() => setLoadingAnimationTimeout(true), loadingIndicatorTimeout);
loadingAnimationTimeoutRef.current = setTimeout(() => setLoadingAnimationTimeout(true), loadingIndicatorTimeout);
async function work() {
const {teams} = await getGroupMessageMembersCommonTeams(serverUrl, channelId);
if (!teams) {
if (!teams || !mounted.current) {
return;
}
setCommonTeams(teams);
setCommonTeamsFetched(true);
}
work();
return () => {
if (loadingAnimationTimeoutRef.current) {
clearTimeout(loadingAnimationTimeoutRef.current);
}
};
}, []);
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;
@ -55,26 +85,7 @@ const ConvertGMToChannel = ({
}
if (users.length) {
// Gotta make sure we use profiles that are in members.
// See comment in fetchChannelMemberships for more details.
const usersById: {[id: string]: UserProfile} = {};
// eslint-disable-next-line max-nested-callbacks
users.forEach((profile) => {
if (profile.id !== currentUserId) {
usersById[profile.id] = profile;
}
});
// eslint-disable-next-line max-nested-callbacks
const filteredUsers: UserProfile[] = [];
// eslint-disable-next-line max-nested-callbacks
members.forEach((member) => {
if (usersById[member.user_id]) {
filteredUsers.push(usersById[member.user_id]);
}
});
setProfiles(filteredUsers);
setProfiles(matchUserProfiles(users, members));
}
setChannelMembersFetched(true);

View file

@ -3,15 +3,16 @@
import React, {useCallback, useEffect, useState} from 'react';
import {useIntl} from 'react-intl';
import {View} from 'react-native';
import {Text, View} from 'react-native';
import {convertGroupMessageToPrivateChannel, switchToChannelById} from '@actions/remote/channel';
import {isErrorWithMessage} from '@app/utils/errors';
import {preventDoubleTap} from '@app/utils/tap';
import Button from '@components/button';
import {useServerUrl} from '@context/server';
import {useTheme} from '@context/theme';
import {logError} from '@utils/log';
import {makeStyleSheetFromTheme} from '@utils/theme';
import {displayUsername} from '@utils/user';
import Button from '@components/button';
import {ChannelNameInput} from '../channel_name_input';
import MessageBox from '../message_box/message_box';
@ -19,7 +20,7 @@ import {TeamSelector} from '../team_selector';
import {NoCommonTeamForm} from './no_common_teams_form';
const getStyleFromTheme = makeStyleSheetFromTheme(() => {
const getStyleFromTheme = makeStyleSheetFromTheme((theme: Theme) => {
return {
container: {
paddingVertical: 24,
@ -28,6 +29,9 @@ const getStyleFromTheme = makeStyleSheetFromTheme(() => {
flexDirection: 'column',
gap: 24,
},
errorMessage: {
color: theme.dndIndicator,
},
};
});
@ -53,6 +57,7 @@ export const ConvertGMToChannelForm = ({
const [selectedTeam, setSelectedTeam] = useState<Team>();
const [newChannelName, setNewChannelName] = useState<string>('');
const [errorMessage, setErrorMessage] = useState<string>('Something went wrong. Failed to convert Group Message to Private Channel');
const submitButtonEnabled = selectedTeam && newChannelName.trim();
@ -66,26 +71,32 @@ export const ConvertGMToChannelForm = ({
if (commonTeams.length > 0) {
setSelectedTeam(commonTeams[0]);
}
}, [commonTeams]);
}, []);
const handleOnPress = useCallback(async () => {
const handleOnPress = useCallback(preventDoubleTap(async () => {
if (!submitButtonEnabled) {
return;
}
const {updatedChannel, error} = await convertGroupMessageToPrivateChannel(serverUrl, channelId, selectedTeam.id, newChannelName);
if (error) {
logError(error);
if (isErrorWithMessage(error)) {
setErrorMessage(error.message);
} else {
setErrorMessage(formatMessage({id: 'channel_info.convert_gm_to_channel.conversion_error', defaultMessage: 'Something went wrong. Failed to convert Group Message to Private Channel.'}));
}
return;
}
if (!updatedChannel) {
setErrorMessage(formatMessage({id: 'channel_info.convert_gm_to_channel.conversion_error', defaultMessage: 'Something went wrong. Failed to convert Group Message to Private Channel.'}));
return;
}
await switchToChannelById(serverUrl, updatedChannel.id, selectedTeam.id);
}, [selectedTeam, newChannelName, submitButtonEnabled]);
setErrorMessage('');
switchToChannelById(serverUrl, updatedChannel.id, selectedTeam.id);
}), [selectedTeam, newChannelName, submitButtonEnabled]);
const messageBoxHeader = intl.formatMessage({
id: 'channel_info.convert_gm_to_channel.warning.header',
@ -130,6 +141,12 @@ export const ConvertGMToChannelForm = ({
buttonType={submitButtonEnabled ? 'destructive' : 'disabled'}
size='lg'
/>
{
errorMessage &&
<Text style={styles.errorMessage}>
{errorMessage}
</Text>
}
</View>
);
};

View file

@ -5,11 +5,12 @@ import React, {useCallback} from 'react';
import {useIntl} from 'react-intl';
import {View, type ViewStyle} from 'react-native';
import {preventDoubleTap} from '@app/utils/tap';
import Button from '@components/button';
import {useTheme} from '@context/theme';
import {popTopScreen} from '@screens/navigation';
import MessageBox from '../message_box';
import MessageBox from '../message_box/message_box';
type Props = {
containerStyles: ViewStyle;
@ -31,9 +32,9 @@ export const NoCommonTeamForm = ({
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(() => {
const handleOnPress = useCallback(preventDoubleTap(() => {
popTopScreen();
}, []);
}), []);
const buttonText = formatMessage({
id: 'generic.back',

View file

@ -85,8 +85,6 @@ const getDangerStylesFromTheme = makeStyleSheetFromTheme((theme: Theme) => {
});
const getStyleFromTheme = (theme: Theme, kind: MessageBoxTypes | undefined) => {
const baseStyles = getBaseStyles(theme);
let kindStyles;
switch (kind) {
case 'danger': {
@ -100,7 +98,6 @@ const getStyleFromTheme = (theme: Theme, kind: MessageBoxTypes | undefined) => {
}
return {
...baseStyles,
...kindStyles,
};
};
@ -111,25 +108,25 @@ const MessageBox = ({
type,
}: Props) => {
const theme = useTheme();
const styles = getBaseStyles(theme);
const foo = getStyleFromTheme(theme, type);
const baseStyle = getBaseStyles(theme);
const kindStyle = getStyleFromTheme(theme, type);
return (
<View style={[styles.container, foo.container]}>
<View style={styles.iconContainer}>
<View style={[baseStyle.container, kindStyle.container]}>
<View style={baseStyle.iconContainer}>
<CompassIcon
name='exclamation-thick'
style={[styles.icon, foo.icon]}
style={[baseStyle.icon, kindStyle.icon]}
/>
</View>
<View style={styles.textContainer}>
<View style={baseStyle.textContainer}>
<View>
<Text style={[styles.heading, foo.heading]}>
<Text style={baseStyle.heading}>
{header}
</Text>
</View>
<View>
<Text style={[styles.body, foo.body]}>
<Text style={baseStyle.body}>
{body}
</Text>
</View>

View file

@ -39,7 +39,7 @@ export const TeamSelector = ({commonTeams, onSelectTeam, selectedTeamId}: Props)
const placeholder = formatMessage({id: 'channel_into.convert_gm_to_channel.team_selector.placeholder', defaultMessage: 'Select a Team'});
useEffect(() => {
if (selectedTeamId) {
if (selectedTeamId && !selectedTeam) {
const team = commonTeams.find((t) => t.id === selectedTeamId);
setSelectedTeam(team);
}

View file

@ -1,6 +1,69 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
import TeamSelectorList from './team_selector_list';
import React, {useCallback, useMemo, useState} from 'react';
import {StyleSheet, View} from 'react-native';
import {preventDoubleTap} from '@app/utils/tap';
import SearchBar from '@components/search';
import TeamList from '@components/team_list';
import {useTheme} from '@context/theme';
import {popTopScreen} from '@screens/navigation';
import {changeOpacity, getKeyboardAppearanceFromTheme} from '@utils/theme';
const styles = StyleSheet.create({
container: {
padding: 12,
},
listContainer: {
marginTop: 12,
},
});
type Props = {
teams: Team[];
selectTeam: (teamId: string) => void;
}
const TeamSelectorList = ({teams, selectTeam}: Props) => {
const theme = useTheme();
const color = useMemo(() => changeOpacity(theme.centerChannelColor, 0.72), [theme]);
const [filteredTeams, setFilteredTeam] = useState(teams);
const handleOnChangeSearchText = useCallback((searchTerm: string) => {
if (searchTerm === '') {
setFilteredTeam(teams);
} else {
setFilteredTeam(teams.filter((team) => team.display_name.includes(searchTerm) || team.name.includes(searchTerm)));
}
}, [teams]);
const handleOnPress = useCallback(preventDoubleTap((teamId: string) => {
selectTeam(teamId);
popTopScreen();
}), []);
return (
<View style={styles.container}>
<SearchBar
autoCapitalize='none'
autoFocus={true}
keyboardAppearance={getKeyboardAppearanceFromTheme(theme)}
placeholderTextColor={color}
searchIconColor={color}
testID='convert_gm_to_channel_team_search_bar'
onChangeText={handleOnChangeSearchText}
/>
<View style={styles.listContainer}>
<TeamList
teams={filteredTeams}
onPress={handleOnPress}
/>
</View>
</View>
);
};
export default TeamSelectorList;

View file

@ -1,69 +0,0 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
import React, {useCallback, useMemo, useState} from 'react';
import {View} from 'react-native';
import SearchBar from '@components/search';
import TeamList from '@components/team_list';
import {useTheme} from '@context/theme';
import {popTopScreen} from '@screens/navigation';
import {changeOpacity, getKeyboardAppearanceFromTheme, makeStyleSheetFromTheme} from '@utils/theme';
const style = StyleSheet.create({
container: {
padding: 12,
},
listContainer: {
marginTop: 12,
},
});
type Props = {
teams: Team[];
selectTeam: (teamId: string) => void;
}
const TeamSelectorList = ({teams, selectTeam}: Props) => {
const theme = useTheme();
const styles = getStyleSheet(theme);
const color = useMemo(() => changeOpacity(theme.centerChannelColor, 0.72), [theme]);
const [filteredTeams, setFilteredTeam] = useState(teams);
const handleOnChangeSearchText = useCallback((searchTerm: string) => {
if (searchTerm === '') {
setFilteredTeam(teams);
} else {
setFilteredTeam(teams.filter((team) => team.display_name.includes(searchTerm) || team.name.includes(searchTerm)));
}
}, [teams]);
const handleOnPress = useCallback((teamId: string) => {
selectTeam(teamId);
popTopScreen();
}, []);
return (
<View style={styles.container}>
<SearchBar
autoCapitalize='none'
autoFocus={true}
keyboardAppearance={getKeyboardAppearanceFromTheme(theme)}
placeholderTextColor={color}
searchIconColor={color}
testID='convert_gm_to_channel_team_search_bar'
onChangeText={handleOnChangeSearchText}
/>
<View style={styles.listContainer}>
<TeamList
teams={filteredTeams}
onPress={handleOnPress}
/>
</View>
</View>
);
};
export default TeamSelectorList;

View file

@ -1099,6 +1099,7 @@
"channel_into.convert_gm_to_channel.team_selector.label": "Team",
"channel_into.convert_gm_to_channel.team_selector.placeholder": "Select a Team",
"channel_info.convert_gm_to_channel.button_text": "Convert to Private Channel",
"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.team_selector_list.title": "Select Team",
"generic.back": "Back"
}