MM-42835_Invite People - add email+user invites

This commit is contained in:
Julian Mondragon
2023-01-20 12:44:31 -05:00
parent 29a66bbc19
commit 3e4851e6fa
4 changed files with 22 additions and 47 deletions

View File

@@ -119,47 +119,31 @@ export async function addUsersToTeam(serverUrl: string, teamId: string, userIds:
try {
client = NetworkManager.getClient(serverUrl);
const {operator} = DatabaseManager.getServerDatabaseAndOperator(serverUrl);
EphemeralStore.startAddingToTeam(teamId);
const members = await client.addUsersToTeamGracefully(teamId, userIds);
if (!fetchOnly) {
setTeamLoading(serverUrl, true);
const teamMemberships: TeamMembership[] = [];
const roles: Record<string, boolean> = {};
const roles = [];
for (const {member} of members) {
teamMemberships.push(member);
member.roles.split(' ').forEach((role) => {
if (!roles[role]) {
roles[role] = true;
}
});
roles.push(...member.roles.split(' '));
}
fetchRolesIfNeeded(serverUrl, Object.getOwnPropertyNames(roles));
const operator = DatabaseManager.serverDatabases[serverUrl]?.operator;
fetchRolesIfNeeded(serverUrl, Array.from(new Set(roles)));
if (operator) {
const team = await client.getTeam(teamId);
const models: Model[] = (await Promise.all([
operator.handleTeam({teams: [team], prepareRecordsOnly: true}),
operator.handleTeamMemberships({teamMemberships, prepareRecordsOnly: true}),
])).flat();
await operator.batchRecords(models);
await operator.handleTeamMemberships({teamMemberships, prepareRecordsOnly: true});
}
setTeamLoading(serverUrl, false);
}
EphemeralStore.finishAddingToTeam(teamId);
return {members};
} catch (error) {
if (client) {
if (EphemeralStore.isAddingToTeam(teamId)) {
EphemeralStore.finishAddingToTeam(teamId);
}
@@ -503,11 +487,10 @@ export async function getTeamMembersByIds(serverUrl: string, teamId: string, use
try {
client = NetworkManager.getClient(serverUrl);
const {operator} = DatabaseManager.getServerDatabaseAndOperator(serverUrl);
const members = await client.getTeamMembersByIds(teamId, userIds);
if (!fetchOnly) {
setTeamLoading(serverUrl, true);
const roles = [];
for (const {roles: memberRoles} of members) {
@@ -516,20 +499,9 @@ export async function getTeamMembersByIds(serverUrl: string, teamId: string, use
fetchRolesIfNeeded(serverUrl, Array.from(new Set(roles)));
const operator = DatabaseManager.serverDatabases[serverUrl]?.operator;
if (operator) {
const team = await client.getTeam(teamId);
const models: Model[] = (await Promise.all([
operator.handleTeam({teams: [team], prepareRecordsOnly: true}),
operator.handleTeamMemberships({teamMemberships: members, prepareRecordsOnly: true}),
])).flat();
await operator.batchRecords(models);
await operator.handleTeamMemberships({teamMemberships: members, prepareRecordsOnly: true});
}
setTeamLoading(serverUrl, false);
}
return {members};

View File

@@ -31,7 +31,6 @@ type Props = {
canJoinChannels: boolean;
canInvitePeople: boolean;
displayName?: string;
inviteId?: string;
iconPad?: boolean;
onHeaderPress?: () => void;
pushProxyStatus: string;

View File

@@ -223,7 +223,7 @@ export default function Invite({
}
}
const currentMemberIds: Record<string, boolean> = {};
const currentMemberIds = new Set();
if (userIds.length) {
const {members: currentTeamMembers = [], error: getTeamMembersByIdsError} = await getTeamMembersByIds(serverUrl, teamId, userIds);
@@ -234,7 +234,7 @@ export default function Invite({
}
for (const {user_id: currentMemberId} of currentTeamMembers) {
currentMemberIds[currentMemberId] = true;
currentMemberIds.add(currentMemberId);
}
}
@@ -245,7 +245,7 @@ export default function Invite({
for (const userId of userIds) {
if (isGuest((selectedIds[userId] as UserProfile).roles)) {
notSent.push({userId, reason: formatMessage({id: 'invite.members.user_is_guest', defaultMessage: 'Contact your admin to make this guest a full member'})});
} else if (currentMemberIds[userId]) {
} else if (currentMemberIds.has(userId)) {
notSent.push({userId, reason: formatMessage({id: 'invite.members.already_member', defaultMessage: 'This person is already a team member'})});
} else {
usersToAdd.push(userId);
@@ -322,7 +322,7 @@ export default function Invite({
};
setButtons(componentId, buttons);
}, [theme, locale, componentId, selectedCount, stage, sendError]);
}, [theme, locale, componentId, selectedCount > 0, stage === Stage.SELECTION, sendError]);
useEffect(() => {
mergeNavigationOptions(componentId, {

View File

@@ -12,7 +12,7 @@ import {
ListRenderItemInfo,
ScrollView,
} from 'react-native';
import Animated, {useDerivedValue} from 'react-native-reanimated';
import Animated, {useAnimatedStyle, useDerivedValue} from 'react-native-reanimated';
import {useSafeAreaInsets} from 'react-native-safe-area-context';
import SelectedUser from '@components/selected_users/selected_user';
@@ -60,6 +60,8 @@ const getStyleSheet = makeStyleSheetFromTheme((theme: Theme) => {
right: 20,
position: 'absolute',
bottom: Platform.select({ios: 'auto', default: undefined}),
borderRadius: 4,
backgroundColor: theme.centerChannelBg,
},
searchListBorder: {
borderWidth: 1,
@@ -194,15 +196,17 @@ export default function Selection({
return Math.min(animatedAutocompleteAvailableSpace.value, defaultMaxHeight);
}, [animatedAutocompleteAvailableSpace, defaultMaxHeight]);
const searchListContainerAnimatedStyle = useAnimatedStyle(() => ({
top: animatedAutocompletePosition.value,
maxHeight: maxHeight.value,
}), [animatedAutocompletePosition, maxHeight]);
const searchListContainerStyle = useMemo(() => {
const style = [];
style.push(
styles.searchList,
{
top: animatedAutocompletePosition.value,
maxHeight: maxHeight.value,
},
searchListContainerAnimatedStyle,
);
if (Platform.OS === 'ios') {
@@ -210,7 +214,7 @@ export default function Selection({
}
return style;
}, [searchResults, styles, animatedAutocompletePosition, maxHeight]);
}, [searchResults, styles, searchListContainerAnimatedStyle]);
const searchListFlatListStyle = useMemo(() => {
const style = [];