review fixes
This commit is contained in:
parent
9c6ae712a9
commit
4af2ad2f69
9 changed files with 109 additions and 75 deletions
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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 &&
|
||||
|
|
|
|||
|
|
@ -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}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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",
|
||||
|
|
|
|||
Loading…
Reference in a new issue