Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Room settings-Members added/deleted in a room in offline mode are not grayed out/crossed #35355

Merged
merged 24 commits into from
Mar 20, 2024
Merged
Show file tree
Hide file tree
Changes from 20 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
78 changes: 70 additions & 8 deletions src/libs/actions/Report.ts
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ import ROUTES from '@src/ROUTES';
import INPUT_IDS from '@src/types/form/NewRoomForm';
import type {PersonalDetails, PersonalDetailsList, PolicyReportField, RecentlyUsedReportFields, ReportActionReactions, ReportMetadata, ReportUserIsTyping} from '@src/types/onyx';
import type {Decision, OriginalMessageIOU} from '@src/types/onyx/OriginalMessage';
import type {NotificationPreference, RoomVisibility, WriteCapability} from '@src/types/onyx/Report';
import type {NotificationPreference, PendingAccount, RoomVisibility, WriteCapability} from '@src/types/onyx/Report';
import type Report from '@src/types/onyx/Report';
import type {Message, ReportActionBase, ReportActions} from '@src/types/onyx/ReportAction';
import type ReportAction from '@src/types/onyx/ReportAction';
Expand Down Expand Up @@ -2417,27 +2417,48 @@ function inviteToRoom(reportID: string, inviteeEmailsToAccountIDs: Record<string
const logins = inviteeEmails.map((memberLogin) => PhoneNumber.addSMSDomainIfPhoneNumber(memberLogin));
const newPersonalDetailsOnyxData = PersonalDetailsUtils.getNewPersonalDetailsOnyxData(logins, inviteeAccountIDs);

const optimisticPendingAccounts: Record<string, PendingAccount> = {};
const successPendingAccounts: Record<string, NullishDeep<PendingAccount>> = {};
const failurePendingAccounts: Record<string, PendingAccount> = {};

inviteeAccountIDs.forEach((accountID) => {
optimisticPendingAccounts[accountID] = {pendingAction: CONST.RED_BRICK_ROAD_PENDING_ACTION.ADD};
successPendingAccounts[accountID] = {pendingAction: null};
failurePendingAccounts[accountID] = {
errors: ErrorUtils.getMicroSecondOnyxError('workspace.people.error.genericAdd'),
};
});

const optimisticData: OnyxUpdate[] = [
{
onyxMethod: Onyx.METHOD.MERGE,
key: `${ONYXKEYS.COLLECTION.REPORT}${reportID}`,
value: {
participantAccountIDs: participantAccountIDsAfterInvitation,
visibleChatMemberAccountIDs: visibleMemberAccountIDsAfterInvitation,
pendingAccounts: optimisticPendingAccounts,
},
},
...newPersonalDetailsOnyxData.optimisticData,
];

const successData: OnyxUpdate[] = newPersonalDetailsOnyxData.finallyData;
const successData: OnyxUpdate[] = [
{
onyxMethod: Onyx.METHOD.MERGE,
key: `${ONYXKEYS.COLLECTION.REPORT}${reportID}`,
value: {
pendingAccounts: successPendingAccounts,
},
},
...newPersonalDetailsOnyxData.finallyData,
];

const failureData: OnyxUpdate[] = [
{
onyxMethod: Onyx.METHOD.MERGE,
key: `${ONYXKEYS.COLLECTION.REPORT}${reportID}`,
value: {
participantAccountIDs: report.participantAccountIDs,
visibleChatMemberAccountIDs: report.visibleChatMemberAccountIDs,
pendingAccounts: failurePendingAccounts,
},
},
...newPersonalDetailsOnyxData.finallyData,
Expand All @@ -2460,13 +2481,24 @@ function removeFromRoom(reportID: string, targetAccountIDs: number[]) {
const participantAccountIDsAfterRemoval = report?.participantAccountIDs?.filter((id: number) => !targetAccountIDs.includes(id));
const visibleChatMemberAccountIDsAfterRemoval = report?.visibleChatMemberAccountIDs?.filter((id: number) => !targetAccountIDs.includes(id));

const optimisticPendingAccounts: Record<string, PendingAccount> = {};
const successPendingAccounts: Record<string, NullishDeep<PendingAccount>> = {};
const failurePendingAccounts: Record<string, PendingAccount> = {};

targetAccountIDs.forEach((accountID) => {
optimisticPendingAccounts[accountID] = {pendingAction: CONST.RED_BRICK_ROAD_PENDING_ACTION.DELETE};
successPendingAccounts[accountID] = {pendingAction: null};
failurePendingAccounts[accountID] = {
errors: ErrorUtils.getMicroSecondOnyxError('workspace.people.error.genericRemove'),
};
});

const optimisticData: OnyxUpdate[] = [
{
onyxMethod: Onyx.METHOD.MERGE,
key: `${ONYXKEYS.COLLECTION.REPORT}${reportID}`,
value: {
participantAccountIDs: participantAccountIDsAfterRemoval,
visibleChatMemberAccountIDs: visibleChatMemberAccountIDsAfterRemoval,
pendingAccounts: optimisticPendingAccounts,
},
},
];
Expand All @@ -2476,8 +2508,7 @@ function removeFromRoom(reportID: string, targetAccountIDs: number[]) {
onyxMethod: Onyx.METHOD.MERGE,
key: `${ONYXKEYS.COLLECTION.REPORT}${reportID}`,
value: {
participantAccountIDs: report?.participantAccountIDs,
visibleChatMemberAccountIDs: report?.visibleChatMemberAccountIDs,
pendingAccounts: failurePendingAccounts,
},
},
];
Expand All @@ -2491,6 +2522,7 @@ function removeFromRoom(reportID: string, targetAccountIDs: number[]) {
value: {
participantAccountIDs: participantAccountIDsAfterRemoval,
visibleChatMemberAccountIDs: visibleChatMemberAccountIDsAfterRemoval,
pendingAccounts: successPendingAccounts,
},
},
];
Expand Down Expand Up @@ -2938,6 +2970,34 @@ function resolveActionableMentionWhisper(reportId: string, reportAction: OnyxEnt
API.write(WRITE_COMMANDS.RESOLVE_ACTIONABLE_MENTION_WHISPER, parameters, {optimisticData, failureData});
}

/**
* Removes an error after trying to delete a member
*/
function clearDeleteMemberError(reportID: string, accountID: number) {
Onyx.merge(`${ONYXKEYS.COLLECTION.REPORT}${reportID}`, {
pendingAccounts: {
[accountID]: null,
},
});
}

/**
* Removes an error after trying to add a member
*/
function clearAddMemberError(reportID: string, accountID: number) {
const report = currentReportData?.[reportID];
const participantAccountIDs = report?.participantAccountIDs?.filter((id: number) => id !== accountID);
const visibleChatMemberAccountIDs = report?.visibleChatMemberAccountIDs?.filter((id: number) => id !== accountID);

Onyx.merge(`${ONYXKEYS.COLLECTION.REPORT}${reportID}`, {
pendingAccounts: {
[accountID]: null,
},
participantAccountIDs,
visibleChatMemberAccountIDs,
});
}

export {
searchInServer,
addComment,
Expand Down Expand Up @@ -3007,5 +3067,7 @@ export {
updateReportField,
updateReportName,
resolveActionableMentionWhisper,
clearDeleteMemberError,
clearAddMemberError,
updateRoomVisibility,
};
8 changes: 6 additions & 2 deletions src/libs/mapChildrenFlat.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,12 @@ import React from 'react';
* return modifiedChild;
* });
*/
const mapChildrenFlat = <T, C>(...args: Parameters<typeof React.Children.map<T, C>>) => {
const mappedChildren = React.Children.map(...args);
const mapChildrenFlat = <T, C>(element: C, fn: (child: C, index: number) => T) => {
if (typeof element === 'function') {
return element(false) as C;
}

const mappedChildren = React.Children.map(element, fn);

if (Array.isArray(mappedChildren) && mappedChildren.length === 1) {
return mappedChildren[0];
Expand Down
22 changes: 21 additions & 1 deletion src/pages/RoomMembersPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,7 @@ function RoomMembersPage({report, session, policies}: RoomMembersPageProps) {

const getMemberOptions = (): ListItem[] => {
let result: ListItem[] = [];
const pendingAccounts = report.pendingAccounts;

report?.visibleChatMemberAccountIDs?.forEach((accountID) => {
const details = personalDetails[accountID];
Expand Down Expand Up @@ -183,7 +184,6 @@ function RoomMembersPage({report, session, policies}: RoomMembersPageProps) {
return;
}
}

result.push({
keyForList: String(accountID),
accountID,
Expand All @@ -199,6 +199,8 @@ function RoomMembersPage({report, session, policies}: RoomMembersPageProps) {
id: Number(accountID),
},
],
pendingAction: pendingAccounts?.[accountID]?.pendingAction,
errors: pendingAccounts?.[accountID]?.errors,
});
});

Expand All @@ -207,6 +209,23 @@ function RoomMembersPage({report, session, policies}: RoomMembersPageProps) {
return result;
};

/**
* Dismisses the errors on one item
*/
const dismissError = useCallback(
(item: ListItem) => {
if (!item.accountID) {
return;
}
if (item.pendingAction === CONST.RED_BRICK_ROAD_PENDING_ACTION.DELETE) {
Report.clearDeleteMemberError(report.reportID, item.accountID);
} else {
Report.clearAddMemberError(report.reportID, item.accountID);
}
},
[report.reportID],
);

const isPolicyMember = useMemo(() => {
if (!report?.policyID || policies === null) {
return false;
Expand Down Expand Up @@ -277,6 +296,7 @@ function RoomMembersPage({report, session, policies}: RoomMembersPageProps) {
showLoadingPlaceholder={!OptionsListUtils.isPersonalDetailsReady(personalDetails) || !didLoadRoomMembers}
showScrollIndicator
shouldPreventDefaultFocusOnSelectRow={!DeviceCapabilities.canUseTouchScreen()}
onDismissError={dismissError}
ListItem={UserListItem}
/>
</View>
Expand Down
9 changes: 8 additions & 1 deletion src/types/onyx/Report.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,11 @@ type Participant = {

type Participants = Record<number, Participant>;

type PendingAccount = {
errors?: OnyxCommon.Errors;
pendingAction?: OnyxCommon.PendingAction;
};

type Report = OnyxCommon.OnyxValueWithOfflineFeedback<
{
/** The specific type of chat */
Expand Down Expand Up @@ -172,6 +177,8 @@ type Report = OnyxCommon.OnyxValueWithOfflineFeedback<

/** If the report contains reportFields, save the field id and its value */
reportFields?: Record<string, PolicyReportField>;

pendingAccounts?: Record<string, PendingAccount>;
},
PolicyReportField['fieldID']
>;
Expand All @@ -180,4 +187,4 @@ type ReportCollectionDataSet = CollectionDataSet<typeof ONYXKEYS.COLLECTION.REPO

export default Report;

export type {NotificationPreference, RoomVisibility, WriteCapability, Note, ReportCollectionDataSet};
export type {NotificationPreference, RoomVisibility, WriteCapability, Note, ReportCollectionDataSet, PendingAccount};
Loading