diff --git a/app/actions/remote/team.ts b/app/actions/remote/team.ts index 90d68c09e2..7db5a09f9d 100644 --- a/app/actions/remote/team.ts +++ b/app/actions/remote/team.ts @@ -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 = {}; + 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}; diff --git a/app/screens/home/channel_list/categories_list/header/header.tsx b/app/screens/home/channel_list/categories_list/header/header.tsx index 5e5d25aa01..262cdc0d30 100644 --- a/app/screens/home/channel_list/categories_list/header/header.tsx +++ b/app/screens/home/channel_list/categories_list/header/header.tsx @@ -31,7 +31,6 @@ type Props = { canJoinChannels: boolean; canInvitePeople: boolean; displayName?: string; - inviteId?: string; iconPad?: boolean; onHeaderPress?: () => void; pushProxyStatus: string; diff --git a/app/screens/invite/invite.tsx b/app/screens/invite/invite.tsx index a1b6f57291..001594aa32 100644 --- a/app/screens/invite/invite.tsx +++ b/app/screens/invite/invite.tsx @@ -223,7 +223,7 @@ export default function Invite({ } } - const currentMemberIds: Record = {}; + 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, { diff --git a/app/screens/invite/selection.tsx b/app/screens/invite/selection.tsx index 5be704b19d..c7e1e3d082 100644 --- a/app/screens/invite/selection.tsx +++ b/app/screens/invite/selection.tsx @@ -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 = [];