From d3d480545fdea6d51ded5866dd407881857bb04a Mon Sep 17 00:00:00 2001 From: Yauheni Date: Wed, 3 Apr 2024 14:53:31 +0200 Subject: [PATCH 01/27] Remove policyMembersDraft and policyMembers part-1 --- src/ONYXKEYS.ts | 2 - src/components/Indicator.tsx | 13 +- src/libs/PolicyUtils.ts | 18 +- src/libs/WorkspacesSettingsUtils.ts | 23 +-- src/libs/actions/Policy.ts | 188 +++++++----------- src/libs/actions/TeachersUnite.ts | 24 +-- src/pages/home/sidebar/AllSettingsScreen.tsx | 12 +- src/pages/settings/InitialSettingsPage.tsx | 12 +- src/pages/workspace/WorkspaceInitialPage.tsx | 4 +- src/pages/workspace/WorkspacesListPage.tsx | 14 +- src/pages/workspace/withPolicy.tsx | 5 - .../withPolicyAndFullscreenLoading.tsx | 2 - 12 files changed, 114 insertions(+), 203 deletions(-) diff --git a/src/ONYXKEYS.ts b/src/ONYXKEYS.ts index c134d2a65db2..3ff71362af35 100755 --- a/src/ONYXKEYS.ts +++ b/src/ONYXKEYS.ts @@ -309,7 +309,6 @@ const ONYXKEYS = { POLICY: 'policy_', POLICY_MEMBERS: 'policyMembers_', POLICY_DRAFTS: 'policyDrafts_', - POLICY_MEMBERS_DRAFTS: 'policyMembersDrafts_', POLICY_JOIN_MEMBER: 'policyJoinMember_', POLICY_CATEGORIES: 'policyCategories_', POLICY_RECENTLY_USED_CATEGORIES: 'policyRecentlyUsedCategories_', @@ -513,7 +512,6 @@ type OnyxCollectionValuesMapping = { [ONYXKEYS.COLLECTION.POLICY_CATEGORIES]: OnyxTypes.PolicyCategories; [ONYXKEYS.COLLECTION.POLICY_TAGS]: OnyxTypes.PolicyTagList; [ONYXKEYS.COLLECTION.POLICY_MEMBERS]: OnyxTypes.PolicyMembers; - [ONYXKEYS.COLLECTION.POLICY_MEMBERS_DRAFTS]: OnyxTypes.PolicyMember; [ONYXKEYS.COLLECTION.POLICY_RECENTLY_USED_CATEGORIES]: OnyxTypes.RecentlyUsedCategories; [ONYXKEYS.COLLECTION.DEPRECATED_POLICY_MEMBER_LIST]: OnyxTypes.PolicyMembers; [ONYXKEYS.COLLECTION.WORKSPACE_INVITE_MEMBERS_DRAFT]: OnyxTypes.InvitedEmailsToAccountIDs; diff --git a/src/components/Indicator.tsx b/src/components/Indicator.tsx index e3d226a17999..8830681bc55f 100644 --- a/src/components/Indicator.tsx +++ b/src/components/Indicator.tsx @@ -8,14 +8,11 @@ import * as PolicyUtils from '@libs/PolicyUtils'; import * as UserUtils from '@libs/UserUtils'; import * as PaymentMethods from '@userActions/PaymentMethods'; import ONYXKEYS from '@src/ONYXKEYS'; -import type {BankAccountList, FundList, LoginList, Policy, PolicyMembers, ReimbursementAccount, UserWallet, WalletTerms} from '@src/types/onyx'; +import type {BankAccountList, FundList, LoginList, Policy, ReimbursementAccount, UserWallet, WalletTerms} from '@src/types/onyx'; type CheckingMethod = () => boolean; type IndicatorOnyxProps = { - /** The employee list of all policies (coming from Onyx) */ - allPolicyMembers: OnyxCollection; - /** All the user's policies (from Onyx via withFullPolicy) */ policies: OnyxCollection; @@ -40,14 +37,13 @@ type IndicatorOnyxProps = { type IndicatorProps = IndicatorOnyxProps; -function Indicator({reimbursementAccount, allPolicyMembers, policies, bankAccountList, fundList, userWallet, walletTerms, loginList}: IndicatorOnyxProps) { +function Indicator({reimbursementAccount, policies, bankAccountList, fundList, userWallet, walletTerms, loginList}: IndicatorOnyxProps) { const theme = useTheme(); const styles = useThemeStyles(); // If a policy was just deleted from Onyx, then Onyx will pass a null value to the props, and // those should be cleaned out before doing any error checking const cleanPolicies = Object.fromEntries(Object.entries(policies ?? {}).filter(([, policy]) => policy?.id)); - const cleanAllPolicyMembers = Object.fromEntries(Object.entries(allPolicyMembers ?? {}).filter(([, policyMembers]) => !!policyMembers)); // All of the error & info-checking methods are put into an array. This is so that using _.some() will return // early as soon as the first error / info condition is returned. This makes the checks very efficient since @@ -57,7 +53,7 @@ function Indicator({reimbursementAccount, allPolicyMembers, policies, bankAccoun () => PaymentMethods.hasPaymentMethodError(bankAccountList, fundList), () => Object.values(cleanPolicies).some(PolicyUtils.hasPolicyError), () => Object.values(cleanPolicies).some(PolicyUtils.hasCustomUnitsError), - () => Object.values(cleanAllPolicyMembers).some(PolicyUtils.hasPolicyMemberError), + () => Object.values(cleanPolicies).some(PolicyUtils.hasEmployeeListError), () => Object.keys(reimbursementAccount?.errors ?? {}).length > 0, () => !!loginList && UserUtils.hasLoginListError(loginList), @@ -77,9 +73,6 @@ function Indicator({reimbursementAccount, allPolicyMembers, policies, bankAccoun Indicator.displayName = 'Indicator'; export default withOnyx({ - allPolicyMembers: { - key: ONYXKEYS.COLLECTION.POLICY_MEMBERS, - }, policies: { key: ONYXKEYS.COLLECTION.POLICY, }, diff --git a/src/libs/PolicyUtils.ts b/src/libs/PolicyUtils.ts index 0a8437a5afaf..7ff74f8af98e 100644 --- a/src/libs/PolicyUtils.ts +++ b/src/libs/PolicyUtils.ts @@ -26,10 +26,9 @@ function getActivePolicies(policies: OnyxCollection): Policy[] | undefin /** * Checks if we have any errors stored within the POLICY_MEMBERS. Determines whether we should show a red brick road error or not. - * Data structure: {accountID: {role:'user', errors: []}, accountID2: {role:'admin', errors: [{1231312313: 'Unable to do X'}]}, ...} */ -function hasPolicyMemberError(policyMembers: OnyxEntry): boolean { - return Object.values(policyMembers ?? {}).some((member) => Object.keys(member?.errors ?? {}).length > 0); +function hasEmployeeListError(policy: OnyxEntry): boolean { + return Object.values(policy?.employeeList ?? {}).some((employee) => Object.keys(employee?.errors ?? {}).length > 0); } /** @@ -90,12 +89,11 @@ function getUnitRateValue(toLocaleDigit: (arg: string) => string, customUnitRate /** * Get the brick road indicator status for a policy. The policy has an error status if there is a policy member error, a custom unit error or a field error. */ -function getPolicyBrickRoadIndicatorStatus(policy: OnyxEntry, policyMembersCollection: OnyxCollection): ValueOf | undefined { - const policyMembers = policyMembersCollection?.[`${ONYXKEYS.COLLECTION.POLICY_MEMBERS}${policy?.id}`] ?? {}; - if (hasPolicyMemberError(policyMembers) || hasCustomUnitsError(policy) || hasPolicyErrorFields(policy)) { - return CONST.BRICK_ROAD_INDICATOR_STATUS.ERROR; - } - return undefined; +function getPolicyBrickRoadIndicatorStatus(policy: OnyxEntry): ValueOf | undefined { + if (hasEmployeeListError(policy) || hasCustomUnitsError(policy) || hasPolicyErrorFields(policy)) { + return CONST.BRICK_ROAD_INDICATOR_STATUS.ERROR; + } + return undefined; } /** @@ -316,7 +314,7 @@ function getPolicyIDFromNavigationState() { export { getActivePolicies, hasAccountingConnections, - hasPolicyMemberError, + hasEmployeeListError, hasPolicyError, hasPolicyErrorFields, hasCustomUnitsError, diff --git a/src/libs/WorkspacesSettingsUtils.ts b/src/libs/WorkspacesSettingsUtils.ts index 30820fc0c48b..ef35421efb90 100644 --- a/src/libs/WorkspacesSettingsUtils.ts +++ b/src/libs/WorkspacesSettingsUtils.ts @@ -4,12 +4,12 @@ import type {ValueOf} from 'type-fest'; import CONST from '@src/CONST'; import type {TranslationPaths} from '@src/languages/types'; import ONYXKEYS from '@src/ONYXKEYS'; -import type {Policy, PolicyMembers, ReimbursementAccount, Report} from '@src/types/onyx'; +import type {Policy, ReimbursementAccount, Report} from '@src/types/onyx'; import type {Unit} from '@src/types/onyx/Policy'; import * as CurrencyUtils from './CurrencyUtils'; import type {Phrase, PhraseParameters} from './Localize'; import * as OptionsListUtils from './OptionsListUtils'; -import {hasCustomUnitsError, hasPolicyError, hasPolicyMemberError, hasTaxRateError} from './PolicyUtils'; +import {hasCustomUnitsError, hasEmployeeListError, hasPolicyError, hasTaxRateError} from './PolicyUtils'; import * as ReportActionsUtils from './ReportActionsUtils'; import * as ReportUtils from './ReportUtils'; @@ -33,16 +33,6 @@ Onyx.connect({ callback: (value) => (allPolicies = value), }); -let allPolicyMembers: OnyxCollection; - -Onyx.connect({ - key: ONYXKEYS.COLLECTION.POLICY_MEMBERS, - waitForCollectionCallback: true, - callback: (val) => { - allPolicyMembers = val; - }, -}); - let reimbursementAccount: OnyxEntry; Onyx.connect({ @@ -75,17 +65,16 @@ const getBrickRoadForPolicy = (report: Report): BrickRoad => { return shouldShowGreenDotIndicator ? CONST.BRICK_ROAD_INDICATOR_STATUS.INFO : undefined; }; -function hasGlobalWorkspaceSettingsRBR(policies: OnyxCollection, policyMembers: OnyxCollection) { +function hasGlobalWorkspaceSettingsRBR(policies: OnyxCollection) { // When attempting to open a policy with an invalid policyID, the policy collection is updated to include policy objects with error information. // Only policies displayed on the policy list page should be verified. Otherwise, the user will encounter an RBR unrelated to any policies on the list. const cleanPolicies = Object.fromEntries(Object.entries(policies ?? {}).filter(([, policy]) => policy?.id)); - const cleanAllPolicyMembers = Object.fromEntries(Object.entries(policyMembers ?? {}).filter(([, policyMemberValues]) => !!policyMemberValues)); const errorCheckingMethods: CheckingMethod[] = [ () => Object.values(cleanPolicies).some(hasPolicyError), () => Object.values(cleanPolicies).some(hasCustomUnitsError), () => Object.values(cleanPolicies).some(hasTaxRateError), - () => Object.values(cleanAllPolicyMembers).some(hasPolicyMemberError), + () => Object.values(cleanPolicies).some(hasEmployeeListError), () => Object.keys(reimbursementAccount?.errors ?? {}).length > 0, ]; @@ -93,7 +82,7 @@ function hasGlobalWorkspaceSettingsRBR(policies: OnyxCollection, policyM } function hasWorkspaceSettingsRBR(policy: Policy) { - const policyMemberError = allPolicyMembers ? hasPolicyMemberError(allPolicyMembers[`${ONYXKEYS.COLLECTION.POLICY_MEMBERS}${policy.id}`]) : false; + const policyMemberError = hasEmployeeListError(policy); const taxRateError = hasTaxRateError(policy); return Object.keys(reimbursementAccount?.errors ?? {}).length > 0 || hasPolicyError(policy) || hasCustomUnitsError(policy) || policyMemberError || taxRateError; @@ -130,7 +119,7 @@ function getChatTabBrickRoad(policyID?: string): BrickRoad | undefined { function checkIfWorkspaceSettingsTabHasRBR(policyID?: string) { if (!policyID) { - return hasGlobalWorkspaceSettingsRBR(allPolicies, allPolicyMembers); + return hasGlobalWorkspaceSettingsRBR(allPolicies); } const policy = allPolicies ? allPolicies[`${ONYXKEYS.COLLECTION.POLICY}${policyID}`] : null; diff --git a/src/libs/actions/Policy.ts b/src/libs/actions/Policy.ts index 3c34e823ac9a..356eb440e3ca 100644 --- a/src/libs/actions/Policy.ts +++ b/src/libs/actions/Policy.ts @@ -180,15 +180,6 @@ Onyx.connect({ callback: (value) => (allReports = value), }); -let allPolicyMembers: OnyxCollection; -Onyx.connect({ - key: ONYXKEYS.COLLECTION.POLICY_MEMBERS, - waitForCollectionCallback: true, - callback: (val) => { - allPolicyMembers = val; - }, -}); - let lastAccessedWorkspacePolicyID: OnyxEntry = null; Onyx.connect({ key: ONYXKEYS.LAST_ACCESSED_WORKSPACE_POLICY_ID, @@ -820,9 +811,10 @@ function removeMembers(accountIDs: number[], policyID: string) { return; } - const membersListKey = `${ONYXKEYS.COLLECTION.POLICY_MEMBERS}${policyID}` as const; + const policyKey = `${ONYXKEYS.COLLECTION.POLICY}${policyID}` as const; const policy = ReportUtils.getPolicy(policyID); const workspaceChats = ReportUtils.getWorkspaceChats(policyID, accountIDs); + const emailList = accountIDs.map((accountID) => allPersonalDetails?.[accountID]?.login).filter((login) => !!login) as string[]; const optimisticClosedReportActions = workspaceChats.map(() => ReportUtils.buildOptimisticClosedReportAction(sessionEmail, policy.name, CONST.REPORT.ARCHIVE_REASON.REMOVED_FROM_POLICY)); const announceRoomMembers = removeOptimisticAnnounceRoomMembers(policyID, accountIDs); @@ -830,17 +822,17 @@ function removeMembers(accountIDs: number[], policyID: string) { const optimisticMembersState: OnyxCollection = {}; const successMembersState: OnyxCollection = {}; const failureMembersState: OnyxCollection = {}; - accountIDs.forEach((accountID) => { - optimisticMembersState[accountID] = {pendingAction: CONST.RED_BRICK_ROAD_PENDING_ACTION.DELETE}; - successMembersState[accountID] = null; - failureMembersState[accountID] = {errors: ErrorUtils.getMicroSecondOnyxError('workspace.people.error.genericRemove')}; + emailList.forEach((email) => { + optimisticMembersState[email] = {pendingAction: CONST.RED_BRICK_ROAD_PENDING_ACTION.DELETE}; + successMembersState[email] = null; + failureMembersState[email] = {errors: ErrorUtils.getMicroSecondOnyxError('workspace.people.error.genericRemove')}; }); const optimisticData: OnyxUpdate[] = [ { onyxMethod: Onyx.METHOD.MERGE, - key: membersListKey, - value: optimisticMembersState, + key: policyKey, + value: {employeeList: optimisticMembersState}, }, ...announceRoomMembers.onyxOptimisticData, ]; @@ -848,8 +840,8 @@ function removeMembers(accountIDs: number[], policyID: string) { const successData: OnyxUpdate[] = [ { onyxMethod: Onyx.METHOD.MERGE, - key: membersListKey, - value: successMembersState, + key: policyKey, + value: {employeeList: successMembersState}, }, ...announceRoomMembers.onyxSuccessData, ]; @@ -857,8 +849,8 @@ function removeMembers(accountIDs: number[], policyID: string) { const failureData: OnyxUpdate[] = [ { onyxMethod: Onyx.METHOD.MERGE, - key: membersListKey, - value: failureMembersState, + key: policyKey, + value: {employeeList: failureMembersState}, }, ...announceRoomMembers.onyxFailureData, ]; @@ -905,9 +897,8 @@ function removeMembers(accountIDs: number[], policyID: string) { // If we delete all these logins then we should clear the informative messages since they are no longer relevant. if (!isEmptyObject(policy?.primaryLoginsInvited ?? {})) { // Take the current policy members and remove them optimistically - const policyMemberAccountIDs = Object.keys(allPolicyMembers?.[`${ONYXKEYS.COLLECTION.POLICY_MEMBERS}${policyID}`] ?? {}).map((accountID) => Number(accountID)); - const remainingMemberAccountIDs = policyMemberAccountIDs.filter((accountID) => !accountIDs.includes(accountID)); - const remainingLogins: string[] = PersonalDetailsUtils.getLoginsByAccountIDs(remainingMemberAccountIDs); + const employeeListEmails = Object.keys(allPolicies?.[`${ONYXKEYS.COLLECTION.POLICY}${policyID}`]?.employeeList ?? {}); + const remainingLogins = employeeListEmails.filter((email) => !emailList.includes(email)); const invitedPrimaryToSecondaryLogins: Record = {}; if (policy.primaryLoginsInvited) { @@ -918,7 +909,7 @@ function removeMembers(accountIDs: number[], policyID: string) { if (!remainingLogins.some((remainingLogin) => !!invitedPrimaryToSecondaryLogins[remainingLogin])) { optimisticData.push({ onyxMethod: Onyx.METHOD.MERGE, - key: membersListKey, + key: policyKey, value: { primaryLoginsInvited: null, }, @@ -949,7 +940,7 @@ function removeMembers(accountIDs: number[], policyID: string) { }); const params: DeleteMembersFromWorkspaceParams = { - emailList: accountIDs.map((accountID) => allPersonalDetails?.[accountID]?.login).join(','), + emailList: emailList.join(','), policyID, }; @@ -957,7 +948,7 @@ function removeMembers(accountIDs: number[], policyID: string) { } function updateWorkspaceMembersRole(policyID: string, accountIDs: number[], newRole: typeof CONST.POLICY.ROLE.ADMIN | typeof CONST.POLICY.ROLE.USER) { - const previousPolicyMembers = {...allPolicyMembers}; + const previousEmployeeList = {...allPolicies?.[policyID]?.employeeList}; const memberRoles: WorkspaceMembersRoleData[] = accountIDs.reduce((result: WorkspaceMembersRoleData[], accountID: number) => { if (!allPersonalDetails?.[accountID]?.login) { return result; @@ -975,13 +966,15 @@ function updateWorkspaceMembersRole(policyID: string, accountIDs: number[], newR const optimisticData: OnyxUpdate[] = [ { onyxMethod: Onyx.METHOD.MERGE, - key: `${ONYXKEYS.COLLECTION.POLICY_MEMBERS}${policyID}`, + key: `${ONYXKEYS.COLLECTION.POLICY}${policyID}`, value: { - ...memberRoles.reduce((member: Record, current) => { - // eslint-disable-next-line no-param-reassign - member[current.accountID] = {role: current?.role, pendingAction: CONST.RED_BRICK_ROAD_PENDING_ACTION.UPDATE}; - return member; - }, {}), + employeeList: { + ...memberRoles.reduce((member: Record, current) => { + // eslint-disable-next-line no-param-reassign + member[current.email] = {role: current?.role, pendingAction: CONST.RED_BRICK_ROAD_PENDING_ACTION.UPDATE}; + return member; + }, {}), + }, errors: null, }, }, @@ -990,13 +983,15 @@ function updateWorkspaceMembersRole(policyID: string, accountIDs: number[], newR const successData: OnyxUpdate[] = [ { onyxMethod: Onyx.METHOD.MERGE, - key: `${ONYXKEYS.COLLECTION.POLICY_MEMBERS}${policyID}`, + key: `${ONYXKEYS.COLLECTION.POLICY}${policyID}`, value: { - ...memberRoles.reduce((member: Record, current) => { - // eslint-disable-next-line no-param-reassign - member[current.accountID] = {role: current?.role, pendingAction: null}; - return member; - }, {}), + employeeList: { + ...memberRoles.reduce((member: Record, current) => { + // eslint-disable-next-line no-param-reassign + member[current.email] = {role: current?.role, pendingAction: null}; + return member; + }, {}), + }, errors: null, }, }, @@ -1005,9 +1000,9 @@ function updateWorkspaceMembersRole(policyID: string, accountIDs: number[], newR const failureData: OnyxUpdate[] = [ { onyxMethod: Onyx.METHOD.MERGE, - key: `${ONYXKEYS.COLLECTION.POLICY_MEMBERS}${policyID}`, + key: `${ONYXKEYS.COLLECTION.POLICY}${policyID}`, value: { - ...(previousPolicyMembers[`${ONYXKEYS.COLLECTION.POLICY_MEMBERS}${policyID}`] as Record), + employeeList: previousEmployeeList, errors: ErrorUtils.getMicroSecondOnyxError('workspace.editor.genericFailureMessage'), }, }, @@ -1277,7 +1272,7 @@ function createPolicyExpenseChats(policyID: string, invitedEmailsToAccountIDs: I * Please see https://github.com/Expensify/App/blob/main/README.md#Security for more details */ function addMembersToWorkspace(invitedEmailsToAccountIDs: InvitedEmailsToAccountIDs, welcomeNote: string, policyID: string) { - const membersListKey = `${ONYXKEYS.COLLECTION.POLICY_MEMBERS}${policyID}` as const; + const onyxKey = `${ONYXKEYS.COLLECTION.POLICY}${policyID}` as const; const logins = Object.keys(invitedEmailsToAccountIDs).map((memberLogin) => PhoneNumber.addSMSDomainIfPhoneNumber(memberLogin)); const accountIDs = Object.values(invitedEmailsToAccountIDs); @@ -1289,10 +1284,12 @@ function addMembersToWorkspace(invitedEmailsToAccountIDs: InvitedEmailsToAccount const membersChats = createPolicyExpenseChats(policyID, invitedEmailsToAccountIDs); const optimisticMembersState: OnyxCollection = {}; + const successMembersState: OnyxCollection = {}; const failureMembersState: OnyxCollection = {}; - accountIDs.forEach((accountID) => { - optimisticMembersState[accountID] = {pendingAction: CONST.RED_BRICK_ROAD_PENDING_ACTION.ADD}; - failureMembersState[accountID] = { + Object.keys(invitedEmailsToAccountIDs).forEach((email) => { + optimisticMembersState[email] = {pendingAction: CONST.RED_BRICK_ROAD_PENDING_ACTION.ADD}; + successMembersState[email] = {pendingAction: null}; + failureMembersState[email] = { errors: ErrorUtils.getMicroSecondOnyxError('workspace.people.error.genericAdd'), }; }); @@ -1300,10 +1297,12 @@ function addMembersToWorkspace(invitedEmailsToAccountIDs: InvitedEmailsToAccount const optimisticData: OnyxUpdate[] = [ { onyxMethod: Onyx.METHOD.MERGE, - key: membersListKey, + key: onyxKey, // Convert to object with each key containing {pendingAction: ‘add’} - value: optimisticMembersState, + value: { + employeeList: optimisticMembersState, + }, }, ...newPersonalDetailsOnyxData.optimisticData, ...membersChats.onyxOptimisticData, @@ -1313,20 +1312,10 @@ function addMembersToWorkspace(invitedEmailsToAccountIDs: InvitedEmailsToAccount const successData: OnyxUpdate[] = [ { onyxMethod: Onyx.METHOD.MERGE, - key: membersListKey, - - // Convert to object with each key clearing pendingAction, when it is an existing account. - // Remove the object, when it is a newly created account. - value: accountIDs.reduce((accountIDsWithClearedPendingAction, accountID) => { - let value = null; - const accountAlreadyExists = !isEmptyObject(allPersonalDetails?.[accountID]); - - if (accountAlreadyExists) { - value = {pendingAction: null, errors: null}; - } - - return {...accountIDsWithClearedPendingAction, [accountID]: value}; - }, {}), + key: onyxKey, + value: { + employeeList: successMembersState, + }, }, ...newPersonalDetailsOnyxData.finallyData, ...membersChats.onyxSuccessData, @@ -1336,7 +1325,7 @@ function addMembersToWorkspace(invitedEmailsToAccountIDs: InvitedEmailsToAccount const failureData: OnyxUpdate[] = [ { onyxMethod: Onyx.METHOD.MERGE, - key: membersListKey, + key: onyxKey, // Convert to object with each key containing the error. We don’t // need to remove the members since that is handled by onClose of OfflineWithFeedback. @@ -1938,15 +1927,11 @@ function createDraftInitialWorkspace(policyOwnerEmail = '', policyName = '', pol pendingAction: CONST.RED_BRICK_ROAD_PENDING_ACTION.ADD, customUnits, makeMeAdmin, - }, - }, - { - onyxMethod: Onyx.METHOD.SET, - key: `${ONYXKEYS.COLLECTION.POLICY_MEMBERS_DRAFTS}${policyID}`, - value: { - [sessionAccountID]: { - role: CONST.POLICY.ROLE.ADMIN, - errors: {}, + employeeList: { + [sessionEmail]: { + role: CONST.POLICY.ROLE.ADMIN, + errors: {}, + }, }, }, }, @@ -2003,15 +1988,11 @@ function createWorkspace(policyOwnerEmail = '', makeMeAdmin = false, policyName areWorkflowsEnabled: false, areReportFieldsEnabled: false, areConnectionsEnabled: false, - }, - }, - { - onyxMethod: Onyx.METHOD.SET, - key: `${ONYXKEYS.COLLECTION.POLICY_MEMBERS}${policyID}`, - value: { - [sessionAccountID]: { - role: CONST.POLICY.ROLE.ADMIN, - errors: {}, + employeeList: { + [sessionEmail]: { + role: CONST.POLICY.ROLE.ADMIN, + errors: {}, + }, }, }, }, @@ -2065,11 +2046,6 @@ function createWorkspace(policyOwnerEmail = '', makeMeAdmin = false, policyName key: `${ONYXKEYS.COLLECTION.POLICY_DRAFTS}${policyID}`, value: null, }, - { - onyxMethod: Onyx.METHOD.SET, - key: `${ONYXKEYS.COLLECTION.POLICY_MEMBERS_DRAFTS}${policyID}`, - value: null, - }, ]; const successData: OnyxUpdate[] = [ @@ -2140,9 +2116,9 @@ function createWorkspace(policyOwnerEmail = '', makeMeAdmin = false, policyName const failureData: OnyxUpdate[] = [ { - onyxMethod: Onyx.METHOD.SET, - key: `${ONYXKEYS.COLLECTION.POLICY_MEMBERS}${policyID}`, - value: null, + onyxMethod: Onyx.METHOD.MERGE, + key: `${ONYXKEYS.COLLECTION.POLICY}${policyID}`, + value: {employeeList: null}, }, { onyxMethod: Onyx.METHOD.SET, @@ -2491,6 +2467,16 @@ function createWorkspaceFromIOUPayment(iouReport: Report | EmptyObject): string areWorkflowsEnabled: false, areReportFieldsEnabled: false, areConnectionsEnabled: false, + employeeList: { + [sessionEmail]: { + role: CONST.POLICY.ROLE.ADMIN, + errors: {}, + }, + [employeeEmail]: { + role: CONST.POLICY.ROLE.USER, + errors: {}, + }, + }, }; const optimisticData: OnyxUpdate[] = [ @@ -2499,20 +2485,6 @@ function createWorkspaceFromIOUPayment(iouReport: Report | EmptyObject): string key: `${ONYXKEYS.COLLECTION.POLICY}${policyID}`, value: newWorkspace, }, - { - onyxMethod: Onyx.METHOD.SET, - key: `${ONYXKEYS.COLLECTION.POLICY_MEMBERS}${policyID}`, - value: { - [sessionAccountID]: { - role: CONST.POLICY.ROLE.ADMIN, - errors: {}, - }, - [employeeAccountID]: { - role: CONST.POLICY.ROLE.USER, - errors: {}, - }, - }, - }, { onyxMethod: Onyx.METHOD.SET, key: `${ONYXKEYS.COLLECTION.REPORT}${announceChatReportID}`, @@ -2568,13 +2540,6 @@ function createWorkspaceFromIOUPayment(iouReport: Report | EmptyObject): string pendingAction: null, }, }, - { - onyxMethod: Onyx.METHOD.MERGE, - key: `${ONYXKEYS.COLLECTION.POLICY_MEMBERS_DRAFTS}${policyID}`, - value: { - pendingAction: null, - }, - }, ...employeeWorkspaceChat.onyxOptimisticData, ]; @@ -2645,13 +2610,6 @@ function createWorkspaceFromIOUPayment(iouReport: Report | EmptyObject): string ]; const failureData: OnyxUpdate[] = [ - { - onyxMethod: Onyx.METHOD.MERGE, - key: `${ONYXKEYS.COLLECTION.POLICY_MEMBERS}${policyID}`, - value: { - pendingAction: null, - }, - }, { onyxMethod: Onyx.METHOD.MERGE, key: `${ONYXKEYS.COLLECTION.REPORT}${announceChatReportID}`, diff --git a/src/libs/actions/TeachersUnite.ts b/src/libs/actions/TeachersUnite.ts index 1f8b32724bd4..36fd9d340aeb 100644 --- a/src/libs/actions/TeachersUnite.ts +++ b/src/libs/actions/TeachersUnite.ts @@ -96,17 +96,13 @@ function addSchoolPrincipal(firstName: string, partnerUserID: string, lastName: role: CONST.POLICY.ROLE.USER, owner: sessionEmail, outputCurrency: allPersonalDetails?.[sessionAccountID]?.localCurrencyCode ?? CONST.CURRENCY.USD, - pendingAction: CONST.RED_BRICK_ROAD_PENDING_ACTION.ADD, - }, - }, - { - onyxMethod: Onyx.METHOD.SET, - key: `${ONYXKEYS.COLLECTION.POLICY_MEMBERS}${policyID}`, - value: { - [sessionAccountID]: { - role: CONST.POLICY.ROLE.USER, - errors: {}, + employeeList: { + [sessionEmail]: { + role: CONST.POLICY.ROLE.USER, + errors: {}, + }, }, + pendingAction: CONST.RED_BRICK_ROAD_PENDING_ACTION.ADD, }, }, { @@ -155,9 +151,11 @@ function addSchoolPrincipal(firstName: string, partnerUserID: string, lastName: const failureData: OnyxUpdate[] = [ { - onyxMethod: Onyx.METHOD.SET, - key: `${ONYXKEYS.COLLECTION.POLICY_MEMBERS}${policyID}`, - value: null, + onyxMethod: Onyx.METHOD.MERGE, + key: `${ONYXKEYS.COLLECTION.POLICY}${policyID}`, + value: { + [sessionEmail]: null, + }, }, { onyxMethod: Onyx.METHOD.SET, diff --git a/src/pages/home/sidebar/AllSettingsScreen.tsx b/src/pages/home/sidebar/AllSettingsScreen.tsx index 7151cc84e735..8056d9bcc413 100644 --- a/src/pages/home/sidebar/AllSettingsScreen.tsx +++ b/src/pages/home/sidebar/AllSettingsScreen.tsx @@ -18,16 +18,15 @@ import CONST from '@src/CONST'; import type {TranslationPaths} from '@src/languages/types'; import ONYXKEYS from '@src/ONYXKEYS'; import ROUTES from '@src/ROUTES'; -import type {Policy, PolicyMembers} from '@src/types/onyx'; +import type {Policy} from '@src/types/onyx'; type AllSettingsScreenOnyxProps = { policies: OnyxCollection; - policyMembers: OnyxCollection; }; type AllSettingsScreenProps = AllSettingsScreenOnyxProps; -function AllSettingsScreen({policies, policyMembers}: AllSettingsScreenProps) { +function AllSettingsScreen({policies}: AllSettingsScreenProps) { const styles = useThemeStyles(); const waitForNavigate = useWaitForNavigation(); const {translate} = useLocalize(); @@ -48,7 +47,7 @@ function AllSettingsScreen({policies, policyMembers}: AllSettingsScreenProps) { })(); }, focused: !isSmallScreenWidth, - brickRoadIndicator: hasGlobalWorkspaceSettingsRBR(policies, policyMembers) ? CONST.BRICK_ROAD_INDICATOR_STATUS.ERROR : undefined, + brickRoadIndicator: hasGlobalWorkspaceSettingsRBR(policies) ? CONST.BRICK_ROAD_INDICATOR_STATUS.ERROR : undefined, }, ...(shouldShowSubscriptionsMenu ? [ @@ -90,7 +89,7 @@ function AllSettingsScreen({policies, policyMembers}: AllSettingsScreenProps) { hoverAndPressStyle: styles.hoveredComponentBG, brickRoadIndicator: item.brickRoadIndicator, })); - }, [isSmallScreenWidth, styles.hoveredComponentBG, styles.sectionMenuItem, translate, waitForNavigate, policies, policyMembers]); + }, [isSmallScreenWidth, styles.hoveredComponentBG, styles.sectionMenuItem, translate, waitForNavigate, policies]); return ( ({ policies: { key: ONYXKEYS.COLLECTION.POLICY, }, - policyMembers: { - key: ONYXKEYS.COLLECTION.POLICY_MEMBERS, - }, })(AllSettingsScreen); diff --git a/src/pages/settings/InitialSettingsPage.tsx b/src/pages/settings/InitialSettingsPage.tsx index 73bd031b5978..b535165e86bc 100755 --- a/src/pages/settings/InitialSettingsPage.tsx +++ b/src/pages/settings/InitialSettingsPage.tsx @@ -71,9 +71,6 @@ type InitialSettingsPageOnyxProps = { /** The policies which the user has access to */ policies: OnyxCollection; - - /** Members of all the workspaces the user is member of */ - policyMembers: OnyxCollection; }; type InitialSettingsPageProps = InitialSettingsPageOnyxProps & WithCurrentUserPersonalDetailsProps; @@ -98,7 +95,7 @@ type MenuData = { type Menu = {sectionStyle: StyleProp; sectionTranslationKey: TranslationPaths; items: MenuData[]}; -function InitialSettingsPage({session, userWallet, bankAccountList, fundList, walletTerms, loginList, currentUserPersonalDetails, policies, policyMembers}: InitialSettingsPageProps) { +function InitialSettingsPage({session, userWallet, bankAccountList, fundList, walletTerms, loginList, currentUserPersonalDetails, policies}: InitialSettingsPageProps) { const network = useNetwork(); const theme = useTheme(); const styles = useThemeStyles(); @@ -189,7 +186,7 @@ function InitialSettingsPage({session, userWallet, bankAccountList, fundList, wa translationKey: 'common.workspaces', icon: Expensicons.Building, routeName: ROUTES.SETTINGS_WORKSPACES, - brickRoadIndicator: hasGlobalWorkspaceSettingsRBR(policies, policyMembers) ? CONST.BRICK_ROAD_INDICATOR_STATUS.ERROR : undefined, + brickRoadIndicator: hasGlobalWorkspaceSettingsRBR(policies) ? CONST.BRICK_ROAD_INDICATOR_STATUS.ERROR : undefined, }, { translationKey: 'allSettingsScreen.cardsAndDomains', @@ -221,7 +218,7 @@ function InitialSettingsPage({session, userWallet, bankAccountList, fundList, wa sectionTranslationKey: 'common.workspaces', items, }; - }, [policies, policyMembers, styles.workspaceSettingsSectionContainer]); + }, [policies, styles.workspaceSettingsSectionContainer]); /** * Retuns a list of menu items data for general section @@ -529,8 +526,5 @@ export default withCurrentUserPersonalDetails( policies: { key: ONYXKEYS.COLLECTION.POLICY, }, - policyMembers: { - key: ONYXKEYS.COLLECTION.POLICY_MEMBERS, - }, })(InitialSettingsPage), ); diff --git a/src/pages/workspace/WorkspaceInitialPage.tsx b/src/pages/workspace/WorkspaceInitialPage.tsx index 0d3bb027b8e6..1eef3ad214c5 100644 --- a/src/pages/workspace/WorkspaceInitialPage.tsx +++ b/src/pages/workspace/WorkspaceInitialPage.tsx @@ -60,7 +60,7 @@ function dismissError(policyID: string) { Policy.removeWorkspace(policyID); } -function WorkspaceInitialPage({policyDraft, policy: policyProp, policyMembers, reimbursementAccount, policyCategories}: WorkspaceInitialPageProps) { +function WorkspaceInitialPage({policyDraft, policy: policyProp, reimbursementAccount, policyCategories}: WorkspaceInitialPageProps) { const styles = useThemeStyles(); const policy = policyDraft?.id ? policyDraft : policyProp; const [isCurrencyModalOpen, setIsCurrencyModalOpen] = useState(false); @@ -99,7 +99,7 @@ function WorkspaceInitialPage({policyDraft, policy: policyProp, policyMembers, r ReimbursementAccount.navigateToBankAccountRoute(policyID); }, [policyID, policyName]); - const hasMembersError = PolicyUtils.hasPolicyMemberError(policyMembers); + const hasMembersError = PolicyUtils.hasEmployeeListError(policy); const hasPolicyCategoryError = PolicyUtils.hasPolicyCategoriesError(policyCategories); const hasGeneralSettingsError = !isEmptyObject(policy?.errorFields?.generalSettings ?? {}) || !isEmptyObject(policy?.errorFields?.avatar ?? {}); const shouldShowProtectedItems = PolicyUtils.isPolicyAdmin(policy); diff --git a/src/pages/workspace/WorkspacesListPage.tsx b/src/pages/workspace/WorkspacesListPage.tsx index 549d307b2a2f..721aa41c7675 100755 --- a/src/pages/workspace/WorkspacesListPage.tsx +++ b/src/pages/workspace/WorkspacesListPage.tsx @@ -36,7 +36,7 @@ import * as Policy from '@userActions/Policy'; import CONST from '@src/CONST'; import ONYXKEYS from '@src/ONYXKEYS'; import ROUTES from '@src/ROUTES'; -import type {PolicyMembers, Policy as PolicyType, ReimbursementAccount, Report} from '@src/types/onyx'; +import type {Policy as PolicyType, ReimbursementAccount, Report} from '@src/types/onyx'; import type * as OnyxCommon from '@src/types/onyx/OnyxCommon'; import {isEmptyObject} from '@src/types/utils/EmptyObject'; import withPolicyAndFullscreenLoading from './withPolicyAndFullscreenLoading'; @@ -74,9 +74,6 @@ type WorkspaceListPageOnyxProps = { /** Bank account attached to free plan */ reimbursementAccount: OnyxEntry; - /** A collection of objects for all policies which key policy member objects by accountIDs */ - allPolicyMembers: OnyxCollection; - /** All reports shared with the user (coming from Onyx) */ reports: OnyxCollection; }; @@ -114,7 +111,7 @@ function dismissWorkspaceError(policyID: string, pendingAction: OnyxCommon.Pendi throw new Error('Not implemented'); } -function WorkspacesListPage({policies, allPolicyMembers, reimbursementAccount, reports}: WorkspaceListPageProps) { +function WorkspacesListPage({policies, reimbursementAccount, reports}: WorkspaceListPageProps) { const theme = useTheme(); const styles = useThemeStyles(); const {translate} = useLocalize(); @@ -322,7 +319,7 @@ function WorkspacesListPage({policies, allPolicyMembers, reimbursementAccount, r title: policy.name, icon: policy.avatar ? policy.avatar : ReportUtils.getDefaultWorkspaceAvatar(policy.name), action: () => Navigation.navigate(ROUTES.WORKSPACE_INITIAL.getRoute(policy.id)), - brickRoadIndicator: reimbursementAccountBrickRoadIndicator ?? PolicyUtils.getPolicyBrickRoadIndicatorStatus(policy, allPolicyMembers), + brickRoadIndicator: reimbursementAccountBrickRoadIndicator ?? PolicyUtils.getPolicyBrickRoadIndicatorStatus(policy), pendingAction: policy.pendingAction, errors: policy.errors, dismissError: () => { @@ -344,7 +341,7 @@ function WorkspacesListPage({policies, allPolicyMembers, reimbursementAccount, r }; }) .sort((a, b) => localeCompare(a.title, b.title)); - }, [reimbursementAccount?.errors, policies, isOffline, theme.textLight, allPolicyMembers, policyRooms]); + }, [reimbursementAccount?.errors, policies, isOffline, theme.textLight, policyRooms]); if (isEmptyObject(workspaces)) { return ( @@ -435,9 +432,6 @@ export default withPolicyAndFullscreenLoading( policies: { key: ONYXKEYS.COLLECTION.POLICY, }, - allPolicyMembers: { - key: ONYXKEYS.COLLECTION.POLICY_MEMBERS, - }, // @ts-expect-error: ONYXKEYS.REIMBURSEMENT_ACCOUNT is conflicting with ONYXKEYS.FORMS.REIMBURSEMENT_ACCOUNT_FORM reimbursementAccount: { key: ONYXKEYS.REIMBURSEMENT_ACCOUNT, diff --git a/src/pages/workspace/withPolicy.tsx b/src/pages/workspace/withPolicy.tsx index 16af069fa0a2..0f276a9c53e3 100644 --- a/src/pages/workspace/withPolicy.tsx +++ b/src/pages/workspace/withPolicy.tsx @@ -94,7 +94,6 @@ type WithPolicyOnyxProps = { policy: OnyxEntry; policyMembers: OnyxEntry; policyDraft: OnyxEntry; - policyMembersDraft: OnyxEntry; }; type WithPolicyProps = WithPolicyOnyxProps & { @@ -105,7 +104,6 @@ const policyDefaultProps: WithPolicyOnyxProps = { policy: {} as OnyxTypes.Policy, policyMembers: {}, policyDraft: {} as OnyxTypes.Policy, - policyMembersDraft: {}, }; /* @@ -142,9 +140,6 @@ export default function (WrappedComponent: policyDraft: { key: (props) => `${ONYXKEYS.COLLECTION.POLICY_DRAFTS}${getPolicyIDFromRoute(props.route)}`, }, - policyMembersDraft: { - key: (props) => `${ONYXKEYS.COLLECTION.POLICY_MEMBERS_DRAFTS}${getPolicyIDFromRoute(props.route)}`, - }, })(forwardRef(WithPolicy)); } diff --git a/src/pages/workspace/withPolicyAndFullscreenLoading.tsx b/src/pages/workspace/withPolicyAndFullscreenLoading.tsx index 93e10cc1760c..959d6f9290e0 100644 --- a/src/pages/workspace/withPolicyAndFullscreenLoading.tsx +++ b/src/pages/workspace/withPolicyAndFullscreenLoading.tsx @@ -29,7 +29,6 @@ export default function withPolicyAndFullscreenLoading, @@ -46,7 +45,6 @@ export default function withPolicyAndFullscreenLoading ); From 5e84a328e13c1d1e00643cfc7990426231fc11e1 Mon Sep 17 00:00:00 2001 From: Yauheni Date: Wed, 3 Apr 2024 17:57:01 +0200 Subject: [PATCH 02/27] Remove policyMembersDraft and policyMembers part-2 --- src/libs/actions/Policy.ts | 18 ++++++++++++------ src/types/onyx/Policy.ts | 2 +- 2 files changed, 13 insertions(+), 7 deletions(-) diff --git a/src/libs/actions/Policy.ts b/src/libs/actions/Policy.ts index 356eb440e3ca..9287d20a7bcc 100644 --- a/src/libs/actions/Policy.ts +++ b/src/libs/actions/Policy.ts @@ -1781,10 +1781,13 @@ function updateWorkspaceCustomUnitAndRate(policyID: string, currentCustomUnit: C * Removes an error after trying to delete a member */ function clearDeleteMemberError(policyID: string, accountID: number) { - Onyx.merge(`${ONYXKEYS.COLLECTION.POLICY_MEMBERS}${policyID}`, { - [accountID]: { - pendingAction: null, - errors: null, + const email = allPersonalDetails?.[accountID]?.login ?? ''; + Onyx.merge(`${ONYXKEYS.COLLECTION.POLICY}${policyID}`, { + employeeList: { + [email]: { + pendingAction: null, + errors: null, + }, }, }); } @@ -1793,8 +1796,11 @@ function clearDeleteMemberError(policyID: string, accountID: number) { * Removes an error after trying to add a member */ function clearAddMemberError(policyID: string, accountID: number) { - Onyx.merge(`${ONYXKEYS.COLLECTION.POLICY_MEMBERS}${policyID}`, { - [accountID]: null, + const email = allPersonalDetails?.[accountID]?.login ?? ''; + Onyx.merge(`${ONYXKEYS.COLLECTION.POLICY}${policyID}`, { + employeeList: { + [email]: null, + }, }); Onyx.merge(`${ONYXKEYS.PERSONAL_DETAILS_LIST}`, { [accountID]: null, diff --git a/src/types/onyx/Policy.ts b/src/types/onyx/Policy.ts index ddb0c33c2f0c..4a814938c6ba 100644 --- a/src/types/onyx/Policy.ts +++ b/src/types/onyx/Policy.ts @@ -329,7 +329,7 @@ type Policy = OnyxCommon.OnyxValueWithOfflineFeedback< submitsTo?: number; /** The employee list of the policy */ - employeeList?: OnyxTypes.PolicyMembers | []; + employeeList?: OnyxTypes.PolicyMembers; /** The reimbursement choice for policy */ reimbursementChoice?: ValueOf; From e154c4a6a634919ab2c0e82f8459040f1bcbc53e Mon Sep 17 00:00:00 2001 From: Yauheni Date: Wed, 3 Apr 2024 21:18:09 +0200 Subject: [PATCH 03/27] Remove policyMembersDraft and policyMembers part-3 --- src/libs/PolicyUtils.ts | 33 ++--- src/libs/actions/Policy.ts | 1 + src/pages/workspace/WorkspaceInvitePage.tsx | 17 +-- src/pages/workspace/WorkspaceMembersPage.tsx | 126 +++++++++--------- .../members/WorkspaceMemberDetailsPage.tsx | 17 +-- ...orkspaceMemberDetailsRoleSelectionPage.tsx | 5 +- .../withPolicyAndFullscreenLoading.tsx | 15 ++- .../WorkspaceWorkflowsApproverPage.tsx | 12 +- .../workflows/WorkspaceWorkflowsPayerPage.tsx | 22 +-- 9 files changed, 109 insertions(+), 139 deletions(-) diff --git a/src/libs/PolicyUtils.ts b/src/libs/PolicyUtils.ts index 7ff74f8af98e..d48fdd11527b 100644 --- a/src/libs/PolicyUtils.ts +++ b/src/libs/PolicyUtils.ts @@ -28,7 +28,7 @@ function getActivePolicies(policies: OnyxCollection): Policy[] | undefin * Checks if we have any errors stored within the POLICY_MEMBERS. Determines whether we should show a red brick road error or not. */ function hasEmployeeListError(policy: OnyxEntry): boolean { - return Object.values(policy?.employeeList ?? {}).some((employee) => Object.keys(employee?.errors ?? {}).length > 0); + return Object.values(policy?.employeeList ?? {}).some((employee) => Object.keys(employee?.errors ?? {}).length > 0); } /** @@ -90,10 +90,10 @@ function getUnitRateValue(toLocaleDigit: (arg: string) => string, customUnitRate * Get the brick road indicator status for a policy. The policy has an error status if there is a policy member error, a custom unit error or a field error. */ function getPolicyBrickRoadIndicatorStatus(policy: OnyxEntry): ValueOf | undefined { - if (hasEmployeeListError(policy) || hasCustomUnitsError(policy) || hasPolicyErrorFields(policy)) { - return CONST.BRICK_ROAD_INDICATOR_STATUS.ERROR; - } - return undefined; + if (hasEmployeeListError(policy) || hasCustomUnitsError(policy) || hasPolicyErrorFields(policy)) { + return CONST.BRICK_ROAD_INDICATOR_STATUS.ERROR; + } + return undefined; } /** @@ -133,18 +133,19 @@ const isPolicyMember = (policyID: string, policies: OnyxCollection): boo * * We only return members without errors. Otherwise, the members with errors would immediately be removed before the user has a chance to read the error. */ -function getMemberAccountIDsForWorkspace(policyMembers: OnyxEntry, personalDetails: OnyxEntry): MemberEmailsToAccountIDs { +function getMemberAccountIDsForWorkspace(policy: OnyxEntry, personalDetails: OnyxEntry): MemberEmailsToAccountIDs { + const members = policy?.employeeList ?? {}; const memberEmailsToAccountIDs: MemberEmailsToAccountIDs = {}; - Object.keys(policyMembers ?? {}).forEach((accountID) => { - const member = policyMembers?.[accountID]; + Object.keys(members).forEach((email) => { + const member = members?.[email]; if (Object.keys(member?.errors ?? {})?.length > 0) { return; } - const personalDetail = personalDetails?.[accountID]; + const personalDetail = Object.values(personalDetails ?? {})?.find((details) => details?.login === email); if (!personalDetail?.login) { return; } - memberEmailsToAccountIDs[personalDetail.login] = Number(accountID); + memberEmailsToAccountIDs[email] = Number(personalDetail.accountID); }); return memberEmailsToAccountIDs; } @@ -152,19 +153,19 @@ function getMemberAccountIDsForWorkspace(policyMembers: OnyxEntry /** * Get login list that we should not show in the workspace invite options */ -function getIneligibleInvitees(policyMembers: OnyxEntry, personalDetails: OnyxEntry): string[] { +function getIneligibleInvitees(policy: OnyxEntry): string[] { + const members = policy?.employeeList ?? {}; const memberEmailsToExclude: string[] = [...CONST.EXPENSIFY_EMAILS]; - Object.keys(policyMembers ?? {}).forEach((accountID) => { - const policyMember = policyMembers?.[accountID]; + Object.keys(members).forEach((email) => { + const policyMember = members?.[email]; // Policy members that are pending delete or have errors are not valid and we should show them in the invite options (don't exclude them). if (policyMember?.pendingAction === CONST.RED_BRICK_ROAD_PENDING_ACTION.DELETE || Object.keys(policyMember?.errors ?? {}).length > 0) { return; } - const memberEmail = personalDetails?.[accountID]?.login; - if (!memberEmail) { + if (!email) { return; } - memberEmailsToExclude.push(memberEmail); + memberEmailsToExclude.push(email); }); return memberEmailsToExclude; diff --git a/src/libs/actions/Policy.ts b/src/libs/actions/Policy.ts index 9287d20a7bcc..a718e526bb07 100644 --- a/src/libs/actions/Policy.ts +++ b/src/libs/actions/Policy.ts @@ -1973,6 +1973,7 @@ function createWorkspace(policyOwnerEmail = '', makeMeAdmin = false, policyName expenseReportActionData, expenseCreatedReportActionID, } = ReportUtils.buildOptimisticWorkspaceChats(policyID, workspaceName); + const optimisticData: OnyxUpdate[] = [ { onyxMethod: Onyx.METHOD.SET, diff --git a/src/pages/workspace/WorkspaceInvitePage.tsx b/src/pages/workspace/WorkspaceInvitePage.tsx index a8354cfd3276..5c53527bf688 100644 --- a/src/pages/workspace/WorkspaceInvitePage.tsx +++ b/src/pages/workspace/WorkspaceInvitePage.tsx @@ -30,7 +30,7 @@ import CONST from '@src/CONST'; import ONYXKEYS from '@src/ONYXKEYS'; import ROUTES from '@src/ROUTES'; import type SCREENS from '@src/SCREENS'; -import type {Beta, InvitedEmailsToAccountIDs, PersonalDetailsList} from '@src/types/onyx'; +import type {Beta, InvitedEmailsToAccountIDs} from '@src/types/onyx'; import type {Errors} from '@src/types/onyx/OnyxCommon'; import {isEmptyObject} from '@src/types/utils/EmptyObject'; import SearchInputManager from './SearchInputManager'; @@ -40,9 +40,6 @@ import type {WithPolicyAndFullscreenLoadingProps} from './withPolicyAndFullscree type MembersSection = SectionListData>; type WorkspaceInvitePageOnyxProps = { - /** All of the personal details for everyone */ - personalDetails: OnyxEntry; - /** Beta features list */ betas: OnyxEntry; @@ -57,7 +54,6 @@ type WorkspaceInvitePageProps = WithPolicyAndFullscreenLoadingProps & function WorkspaceInvitePage({ route, - policyMembers, personalDetails: personalDetailsProp, betas, invitedEmailsToAccountIDsDraft, @@ -72,7 +68,7 @@ function WorkspaceInvitePage({ const [personalDetails, setPersonalDetails] = useState([]); const [usersToInvite, setUsersToInvite] = useState([]); const openWorkspaceInvitePage = () => { - const policyMemberEmailsToAccountIDs = PolicyUtils.getMemberAccountIDsForWorkspace(policyMembers, personalDetailsProp); + const policyMemberEmailsToAccountIDs = PolicyUtils.getMemberAccountIDsForWorkspace(policy, personalDetailsProp); Policy.openWorkspaceInvitePage(route.params.policyID, Object.keys(policyMemberEmailsToAccountIDs)); }; @@ -91,7 +87,7 @@ function WorkspaceInvitePage({ useNetwork({onReconnect: openWorkspaceInvitePage}); - const excludedUsers = useMemo(() => PolicyUtils.getIneligibleInvitees(policyMembers, personalDetailsProp), [policyMembers, personalDetailsProp]); + const excludedUsers = useMemo(() => PolicyUtils.getIneligibleInvitees(policy), [policy]); useEffect(() => { const newUsersToInviteDict: Record = {}; @@ -100,7 +96,7 @@ function WorkspaceInvitePage({ const inviteOptions = OptionsListUtils.getMemberInviteOptions(personalDetailsProp, betas ?? [], searchTerm, excludedUsers, true); - // Update selectedOptions with the latest personalDetails and policyMembers information + // Update selectedOptions with the latest personalDetails and employeeList information const detailsMap: Record = {}; inviteOptions.personalDetails.forEach((detail) => { if (!detail.login) { @@ -150,7 +146,7 @@ function WorkspaceInvitePage({ setSelectedOptions(Object.values(newSelectedOptionsDict)); // eslint-disable-next-line react-hooks/exhaustive-deps -- we don't want to recalculate when selectedOptions change - }, [personalDetailsProp, policyMembers, betas, searchTerm, excludedUsers]); + }, [personalDetailsProp, policy?.employeeList, betas, searchTerm, excludedUsers]); const sections: MembersSection[] = useMemo(() => { const sectionsArr: MembersSection[] = []; @@ -330,9 +326,6 @@ WorkspaceInvitePage.displayName = 'WorkspaceInvitePage'; export default withNavigationTransitionEnd( withPolicyAndFullscreenLoading( withOnyx({ - personalDetails: { - key: ONYXKEYS.PERSONAL_DETAILS_LIST, - }, betas: { key: ONYXKEYS.BETAS, }, diff --git a/src/pages/workspace/WorkspaceMembersPage.tsx b/src/pages/workspace/WorkspaceMembersPage.tsx index 7b77f6b60ede..3fae61616f3f 100644 --- a/src/pages/workspace/WorkspaceMembersPage.tsx +++ b/src/pages/workspace/WorkspaceMembersPage.tsx @@ -49,9 +49,6 @@ import type {WithPolicyAndFullscreenLoadingProps} from './withPolicyAndFullscree import withPolicyAndFullscreenLoading from './withPolicyAndFullscreenLoading'; type WorkspaceMembersPageOnyxProps = { - /** Personal details of all users */ - personalDetails: OnyxEntry; - /** Session info for the currently logged in user. */ session: OnyxEntry; @@ -73,37 +70,28 @@ function invertObject(object: Record): Record { return inverted; } -type MemberOption = Omit & {accountID: number}; - -function WorkspaceMembersPage({ - policyMembers, - personalDetails, - invitedEmailsToAccountIDsDraft, - route, - policy, - session, - currentUserPersonalDetails, - isLoadingReportData = true, -}: WorkspaceMembersPageProps) { +type MemberOption = Omit & {email: string; accountID: number}; + +function WorkspaceMembersPage({personalDetails, invitedEmailsToAccountIDsDraft, route, policy, session, currentUserPersonalDetails, isLoadingReportData = true}: WorkspaceMembersPageProps) { const styles = useThemeStyles(); const StyleUtils = useStyleUtils(); - const [selectedEmployees, setSelectedEmployees] = useState([]); + const [selectedEmployees, setSelectedEmployees] = useState([]); const [removeMembersConfirmModalVisible, setRemoveMembersConfirmModalVisible] = useState(false); const [errors, setErrors] = useState({}); const {isOffline} = useNetwork(); const prevIsOffline = usePrevious(isOffline); - const accountIDs = useMemo(() => Object.keys(policyMembers ?? {}).map((accountID) => Number(accountID)), [policyMembers]); - const prevAccountIDs = usePrevious(accountIDs); + const accountEmails = useMemo(() => Object.keys(policy?.employeeList ?? {}).map((email) => email), [policy?.employeeList]); + const prevAccountEmails = usePrevious(accountEmails); const textInputRef = useRef(null); - const isOfflineAndNoMemberDataAvailable = isEmptyObject(policyMembers) && isOffline; + const isOfflineAndNoMemberDataAvailable = isEmptyObject(policy?.employeeList ?? {}) && isOffline; const prevPersonalDetails = usePrevious(personalDetails); const {translate, formatPhoneNumber, preferredLocale} = useLocalize(); const {isSmallScreenWidth} = useWindowDimensions(); const dropdownButtonRef = useRef(null); const isPolicyAdmin = PolicyUtils.isPolicyAdmin(policy); const isLoading = useMemo( - () => !isOfflineAndNoMemberDataAvailable && (!OptionsListUtils.isPersonalDetailsReady(personalDetails) || isEmptyObject(policyMembers)), - [isOfflineAndNoMemberDataAvailable, personalDetails, policyMembers], + () => !isOfflineAndNoMemberDataAvailable && (!OptionsListUtils.isPersonalDetailsReady(personalDetails) || isEmptyObject(policy?.employeeList ?? {})), + [isOfflineAndNoMemberDataAvailable, personalDetails, policy?.employeeList], ); const selectionListRef = useRef(null); const isFocused = useIsFocused(); @@ -113,12 +101,13 @@ function WorkspaceMembersPage({ /** * Get filtered personalDetails list with current policyMembers */ - const filterPersonalDetails = (members: OnyxEntry, details: OnyxEntry): PersonalDetailsList => + const filterPersonalDetails = (members: OnyxEntry, personalDetailsList: OnyxEntry): PersonalDetailsList => Object.keys(members ?? {}).reduce((result, key) => { - if (details?.[key]) { + const details = Object.values(personalDetailsList ?? {}).find((currentDetails) => currentDetails?.login === key); + if (details) { return { ...result, - [key]: details[key], + [key]: details, }; } return result; @@ -128,8 +117,8 @@ function WorkspaceMembersPage({ * Get members for the current workspace */ const getWorkspaceMembers = useCallback(() => { - Policy.openWorkspaceMembersPage(route.params.policyID, Object.keys(PolicyUtils.getMemberAccountIDsForWorkspace(policyMembers, personalDetails))); - }, [route.params.policyID, policyMembers, personalDetails]); + Policy.openWorkspaceMembersPage(route.params.policyID, Object.keys(PolicyUtils.getMemberAccountIDsForWorkspace(policy, personalDetails))); + }, [route.params.policyID, policy, personalDetails]); /** * Check if the current selection includes members that cannot be removed @@ -137,7 +126,8 @@ function WorkspaceMembersPage({ const validateSelection = useCallback(() => { const newErrors: Errors = {}; selectedEmployees.forEach((member) => { - if (member !== policy?.ownerAccountID && member !== session?.accountID) { + const details = Object.values(personalDetails ?? {}).find((currentDetails) => currentDetails?.login === member); + if (details?.accountID !== policy?.ownerAccountID && details?.accountID !== session?.accountID) { return; } newErrors[member] = translate('workspace.people.error.cannotRemove'); @@ -156,25 +146,25 @@ function WorkspaceMembersPage({ }, [preferredLocale, validateSelection]); useEffect(() => { - if (removeMembersConfirmModalVisible && !lodashIsEqual(accountIDs, prevAccountIDs)) { + if (removeMembersConfirmModalVisible && !lodashIsEqual(accountEmails, prevAccountEmails)) { setRemoveMembersConfirmModalVisible(false); } setSelectedEmployees((prevSelected) => { // Filter all personal details in order to use the elements needed for the current workspace - const currentPersonalDetails = filterPersonalDetails(policyMembers, personalDetails); + const currentPersonalDetails = filterPersonalDetails(policy?.employeeList ?? {}, personalDetails); // We need to filter the previous selected employees by the new personal details, since unknown/new user id's change when transitioning from offline to online - const prevSelectedElements = prevSelected.map((id) => { - const prevItem = prevPersonalDetails?.id; + const prevSelectedElements = prevSelected.map((email) => { + const prevItem = prevPersonalDetails?.find((item) => item?.login === email); const res = Object.values(currentPersonalDetails).find((item) => prevItem?.login === item?.login); - return res?.accountID ?? id; + return res?.login ?? email; }); // This is an equivalent of the lodash intersection function. The reduce method below is used to filter the items that exist in both arrays. - return [prevSelectedElements, Object.values(PolicyUtils.getMemberAccountIDsForWorkspace(policyMembers, personalDetails))].reduce((prev, members) => + return [prevSelectedElements, Object.keys(PolicyUtils.getMemberAccountIDsForWorkspace(policy, personalDetails))].reduce((prev, members) => prev.filter((item) => members.includes(item)), ); }); // eslint-disable-next-line react-hooks/exhaustive-deps - }, [policyMembers]); + }, [policy]); useEffect(() => { const isReconnecting = prevIsOffline && !isOffline; @@ -201,7 +191,12 @@ function WorkspaceMembersPage({ } // Remove the admin from the list - const accountIDsToRemove = session?.accountID ? selectedEmployees.filter((id) => id !== session.accountID) : selectedEmployees; + const accountIDsToRemove = (session?.accountID ? selectedEmployees.filter((email) => email !== session.email) : selectedEmployees) + .map((email) => { + const details = Object.values(personalDetails ?? {}).find((currentDetails) => currentDetails?.login === email); + return details?.accountID; + }) + .filter(Boolean) as number[]; Policy.removeMembers(accountIDsToRemove, route.params.policyID); setSelectedEmployees([]); @@ -223,13 +218,13 @@ function WorkspaceMembersPage({ */ const toggleAllUsers = (memberList: MemberOption[]) => { const enabledAccounts = memberList.filter((member) => !member.isDisabled && !member.isDisabledCheckbox); - const everyoneSelected = enabledAccounts.every((member) => selectedEmployees.includes(member.accountID)); + const everyoneSelected = enabledAccounts.every((member) => selectedEmployees.includes(member.email)); if (everyoneSelected) { setSelectedEmployees([]); } else { - const everyAccountId = enabledAccounts.map((member) => member.accountID); - setSelectedEmployees(everyAccountId); + const everyEmail = enabledAccounts.map((member) => member.email); + setSelectedEmployees(everyEmail); } validateSelection(); @@ -239,8 +234,8 @@ function WorkspaceMembersPage({ * Add user from the selectedEmployees list */ const addUser = useCallback( - (accountID: number) => { - setSelectedEmployees((prevSelected) => [...prevSelected, accountID]); + (selectedEmail: string) => { + setSelectedEmployees((prevSelected) => [...prevSelected, selectedEmail]); validateSelection(); }, [validateSelection], @@ -250,8 +245,8 @@ function WorkspaceMembersPage({ * Remove user from the selectedEmployees list */ const removeUser = useCallback( - (accountID: number) => { - setSelectedEmployees((prevSelected) => prevSelected.filter((id) => id !== accountID)); + (selectedEmail: string) => { + setSelectedEmployees((prevSelected) => prevSelected.filter((email) => email !== selectedEmail)); validateSelection(); }, [validateSelection], @@ -261,16 +256,16 @@ function WorkspaceMembersPage({ * Toggle user from the selectedEmployees list */ const toggleUser = useCallback( - (accountID: number, pendingAction?: PendingAction) => { + (email: string, pendingAction?: PendingAction) => { if (pendingAction === CONST.RED_BRICK_ROAD_PENDING_ACTION.DELETE) { return; } // Add or remove the user if the checkbox is enabled - if (selectedEmployees.includes(accountID)) { - removeUser(accountID); + if (selectedEmployees.includes(email)) { + removeUser(email); } else { - addUser(accountID); + addUser(email); } }, [selectedEmployees, addUser, removeUser], @@ -319,16 +314,15 @@ function WorkspaceMembersPage({ const getUsers = useCallback((): MemberOption[] => { let result: MemberOption[] = []; - Object.entries(policyMembers ?? {}).forEach(([accountIDKey, policyMember]) => { - const accountID = Number(accountIDKey); + Object.entries(policy?.employeeList ?? {}).forEach(([email, policyMember]) => { if (isDeletedPolicyMember(policyMember)) { return; } - const details = personalDetails?.[accountID]; + const details = Object.values(personalDetails ?? {}).find((currentDetails) => currentDetails?.login === email); if (!details) { - Log.hmmm(`[WorkspaceMembersPage] no personal details found for policy member with accountID: ${accountID}`); + Log.hmmm(`[WorkspaceMembersPage] no personal details found for policy member with email: ${email}`); return; } @@ -341,7 +335,7 @@ function WorkspaceMembersPage({ } } - const isSelected = selectedEmployees.includes(accountID); + const isSelected = selectedEmployees.includes(email); const isOwner = policy?.owner === details.login; const isAdmin = policyMember.role === CONST.POLICY.ROLE.ADMIN; @@ -357,9 +351,12 @@ function WorkspaceMembersPage({ ); } + const accountID = details.accountID ?? 0; + result.push({ - keyForList: accountIDKey, + keyForList: email, accountID, + email, isSelected, isDisabledCheckbox: !(isPolicyAdmin && accountID !== policy?.ownerAccountID && accountID !== session?.accountID), isDisabled: isPolicyAdmin && (policyMember.pendingAction === CONST.RED_BRICK_ROAD_PENDING_ACTION.DELETE || !isEmptyObject(policyMember.errors)), @@ -395,7 +392,7 @@ function WorkspaceMembersPage({ personalDetails, policy?.owner, policy?.ownerAccountID, - policyMembers, + policy?.employeeList, policyOwner, selectedEmployees, session?.accountID, @@ -412,20 +409,20 @@ function WorkspaceMembersPage({ if (!isFocused) { return; } - if (isEmptyObject(invitedEmailsToAccountIDsDraft) || accountIDs === prevAccountIDs) { + if (isEmptyObject(invitedEmailsToAccountIDsDraft) || accountEmails === prevAccountEmails) { return; } const invitedEmails = Object.values(invitedEmailsToAccountIDsDraft).map(String); selectionListRef.current?.scrollAndHighlightItem?.(invitedEmails, 1500); Policy.setWorkspaceInviteMembersDraft(route.params.policyID, {}); - }, [invitedEmailsToAccountIDsDraft, route.params.policyID, isFocused, accountIDs, prevAccountIDs]); + }, [invitedEmailsToAccountIDsDraft, route.params.policyID, isFocused, accountEmails, prevAccountEmails]); const getHeaderMessage = () => { if (isOfflineAndNoMemberDataAvailable) { return translate('workspace.common.mustBeOnlineToViewMembers'); } - return !isLoading && isEmptyObject(policyMembers) ? translate('workspace.common.memberNotFound') : ''; + return !isLoading && isEmptyObject(policy?.employeeList ?? {}) ? translate('workspace.common.memberNotFound') : ''; }; const getHeaderContent = () => ( @@ -467,7 +464,13 @@ function WorkspaceMembersPage({ return; } - const accountIDsToUpdate = selectedEmployees.filter((id) => policyMembers?.[id].role !== role); + const accountIDsToUpdate = selectedEmployees + .filter((email) => policy?.employeeList?.[email].role !== role) + .map((email) => { + const details = Object.values(personalDetails ?? {}).find((currentDetails) => currentDetails?.login === email); + return details?.accountID; + }) + .filter(Boolean) as number[]; Policy.updateWorkspaceMembersRole(route.params.policyID, accountIDsToUpdate, role); setSelectedEmployees([]); @@ -484,7 +487,7 @@ function WorkspaceMembersPage({ ]; if (PolicyUtils.isPaidGroupPolicy(policy)) { - if (selectedEmployees.find((employee) => policyMembers?.[employee]?.role === CONST.POLICY.ROLE.ADMIN)) { + if (selectedEmployees.find((employee) => policy?.employeeList?.[employee]?.role === CONST.POLICY.ROLE.ADMIN)) { options.push({ text: translate('workspace.people.makeMember'), value: CONST.POLICY.MEMBERS_BULK_ACTION_TYPES.MAKE_MEMBER, @@ -493,7 +496,7 @@ function WorkspaceMembersPage({ }); } - if (selectedEmployees.find((employee) => policyMembers?.[employee]?.role === CONST.POLICY.ROLE.USER)) { + if (selectedEmployees.find((employee) => policy?.employeeList?.[employee]?.role === CONST.POLICY.ROLE.USER)) { options.push({ text: translate('workspace.people.makeAdmin'), value: CONST.POLICY.MEMBERS_BULK_ACTION_TYPES.MAKE_ADMIN, @@ -592,7 +595,7 @@ function WorkspaceMembersPage({ headerMessage={getHeaderMessage()} headerContent={getHeaderContent()} onSelectRow={openMemberDetails} - onCheckboxPress={(item) => toggleUser(item.accountID)} + onCheckboxPress={(item) => toggleUser(item.email)} onSelectAll={() => toggleAllUsers(data)} onDismissError={dismissError} showLoadingPlaceholder={isLoading} @@ -613,9 +616,6 @@ WorkspaceMembersPage.displayName = 'WorkspaceMembersPage'; export default withCurrentUserPersonalDetails( withPolicyAndFullscreenLoading( withOnyx({ - personalDetails: { - key: ONYXKEYS.PERSONAL_DETAILS_LIST, - }, invitedEmailsToAccountIDsDraft: { key: ({route}) => `${ONYXKEYS.COLLECTION.WORKSPACE_INVITE_MEMBERS_DRAFT}${route.params.policyID.toString()}`, }, diff --git a/src/pages/workspace/members/WorkspaceMemberDetailsPage.tsx b/src/pages/workspace/members/WorkspaceMemberDetailsPage.tsx index 4199bb5f432d..f73a799affba 100644 --- a/src/pages/workspace/members/WorkspaceMemberDetailsPage.tsx +++ b/src/pages/workspace/members/WorkspaceMemberDetailsPage.tsx @@ -2,7 +2,6 @@ import type {StackScreenProps} from '@react-navigation/stack'; import React, {useCallback, useEffect} from 'react'; import {View} from 'react-native'; import type {OnyxEntry} from 'react-native-onyx'; -import {withOnyx} from 'react-native-onyx'; import type {ValueOf} from 'type-fest'; import Avatar from '@components/Avatar'; import Button from '@components/Button'; @@ -28,7 +27,6 @@ import type {WithPolicyAndFullscreenLoadingProps} from '@pages/workspace/withPol import withPolicyAndFullscreenLoading from '@pages/workspace/withPolicyAndFullscreenLoading'; import * as Policy from '@userActions/Policy'; import CONST from '@src/CONST'; -import ONYXKEYS from '@src/ONYXKEYS'; import type {Route} from '@src/ROUTES'; import ROUTES from '@src/ROUTES'; import type SCREENS from '@src/SCREENS'; @@ -41,7 +39,7 @@ type WorkspacePolicyOnyxProps = { type WorkspaceMemberDetailsPageProps = WithPolicyAndFullscreenLoadingProps & WorkspacePolicyOnyxProps & StackScreenProps; -function WorkspaceMemberDetailsPage({personalDetails, policyMembers, policy, route}: WorkspaceMemberDetailsPageProps) { +function WorkspaceMemberDetailsPage({personalDetails, policy, route}: WorkspaceMemberDetailsPageProps) { const styles = useThemeStyles(); const {isOffline} = useNetwork(); const {translate} = useLocalize(); @@ -54,14 +52,15 @@ function WorkspaceMemberDetailsPage({personalDetails, policyMembers, policy, rou const policyID = route.params.policyID; const backTo = route.params.backTo ?? ('' as Route); - const member = policyMembers?.[accountID]; + const memberLogin = personalDetails?.[accountID]?.login ?? ''; + const member = policy?.employeeList?.[memberLogin]; const details = personalDetails?.[accountID] ?? ({} as PersonalDetails); const avatar = details.avatar ?? UserUtils.getDefaultAvatar(); const fallbackIcon = details.fallbackIcon ?? ''; const displayName = details.displayName ?? ''; const isSelectedMemberOwner = policy?.owner === details.login; const isSelectedMemberCurrentUser = accountID === currentUserPersonalDetails?.accountID; - const isCurrentUserAdmin = policyMembers?.[currentUserPersonalDetails?.accountID]?.role === CONST.POLICY.ROLE.ADMIN; + const isCurrentUserAdmin = policy?.employeeList?.[personalDetails?.[currentUserPersonalDetails?.accountID]?.login ?? '']?.role === CONST.POLICY.ROLE.ADMIN; const isCurrentUserOwner = policy?.owner === currentUserPersonalDetails?.login; useEffect(() => { @@ -184,10 +183,4 @@ function WorkspaceMemberDetailsPage({personalDetails, policyMembers, policy, rou WorkspaceMemberDetailsPage.displayName = 'WorkspaceMemberDetailsPage'; -export default withPolicyAndFullscreenLoading( - withOnyx({ - personalDetails: { - key: ONYXKEYS.PERSONAL_DETAILS_LIST, - }, - })(WorkspaceMemberDetailsPage), -); +export default withPolicyAndFullscreenLoading(WorkspaceMemberDetailsPage); diff --git a/src/pages/workspace/members/WorkspaceMemberDetailsRoleSelectionPage.tsx b/src/pages/workspace/members/WorkspaceMemberDetailsRoleSelectionPage.tsx index 7958ae93b922..36f24b8922da 100644 --- a/src/pages/workspace/members/WorkspaceMemberDetailsRoleSelectionPage.tsx +++ b/src/pages/workspace/members/WorkspaceMemberDetailsRoleSelectionPage.tsx @@ -27,14 +27,15 @@ type ListItemType = { keyForList: typeof CONST.POLICY.ROLE.ADMIN | typeof CONST.POLICY.ROLE.USER; }; -function WorkspaceMemberDetailsRoleSelectionPage({policyMembers, route}: WorkspaceMemberDetailsPageProps) { +function WorkspaceMemberDetailsRoleSelectionPage({route, personalDetails, policy}: WorkspaceMemberDetailsPageProps) { const {translate} = useLocalize(); const styles = useThemeStyles(); const accountID = Number(route.params.accountID) ?? 0; const policyID = route.params.policyID; const backTo = route.params.backTo ?? ('' as Route); - const member = policyMembers?.[accountID]; + const memberLogin = personalDetails?.[accountID]?.login ?? ''; + const member = policy?.employeeList?.[memberLogin]; const items: ListItemType[] = [ { diff --git a/src/pages/workspace/withPolicyAndFullscreenLoading.tsx b/src/pages/workspace/withPolicyAndFullscreenLoading.tsx index 959d6f9290e0..e5d93dbe36d5 100644 --- a/src/pages/workspace/withPolicyAndFullscreenLoading.tsx +++ b/src/pages/workspace/withPolicyAndFullscreenLoading.tsx @@ -6,12 +6,16 @@ import {withOnyx} from 'react-native-onyx'; import FullscreenLoadingIndicator from '@components/FullscreenLoadingIndicator'; import compose from '@libs/compose'; import ONYXKEYS from '@src/ONYXKEYS'; +import type {PersonalDetailsList} from '@src/types/onyx'; import type {WithPolicyOnyxProps, WithPolicyProps} from './withPolicy'; import withPolicy, {policyDefaultProps} from './withPolicy'; type WithPolicyAndFullscreenLoadingOnyxProps = { /** Indicated whether the report data is loading */ isLoadingReportData: OnyxEntry; + + /** Personal details of all users */ + personalDetails: OnyxEntry; }; type WithPolicyAndFullscreenLoadingProps = WithPolicyProps & WithPolicyAndFullscreenLoadingOnyxProps; @@ -24,13 +28,7 @@ export default function withPolicyAndFullscreenLoading>, ): ComponentWithPolicyAndFullscreenLoading { function WithPolicyAndFullscreenLoading( - { - isLoadingReportData = true, - policy = policyDefaultProps.policy, - policyDraft = policyDefaultProps.policyDraft, - policyMembers = policyDefaultProps.policyMembers, - ...rest - }: TProps, + {isLoadingReportData = true, policy = policyDefaultProps.policy, policyDraft = policyDefaultProps.policyDraft, policyMembers = policyDefaultProps.policyMembers, ...rest}: TProps, ref: ForwardedRef, ) { if (isLoadingReportData && isEmpty(policy) && isEmpty(policyDraft)) { @@ -57,6 +55,9 @@ export default function withPolicyAndFullscreenLoading({ - personalDetails: { - key: ONYXKEYS.PERSONAL_DETAILS_LIST, - }, - }), - withPolicyAndFullscreenLoading, -)(WorkspaceWorkflowsApproverPage); +export default withPolicyAndFullscreenLoading(WorkspaceWorkflowsApproverPage); diff --git a/src/pages/workspace/workflows/WorkspaceWorkflowsPayerPage.tsx b/src/pages/workspace/workflows/WorkspaceWorkflowsPayerPage.tsx index e96b19ce4442..c9dc4e7e41ca 100644 --- a/src/pages/workspace/workflows/WorkspaceWorkflowsPayerPage.tsx +++ b/src/pages/workspace/workflows/WorkspaceWorkflowsPayerPage.tsx @@ -2,7 +2,6 @@ import type {StackScreenProps} from '@react-navigation/stack'; import React, {useCallback, useMemo, useState} from 'react'; import type {SectionListData} from 'react-native'; import type {OnyxEntry} from 'react-native-onyx'; -import {withOnyx} from 'react-native-onyx'; import Badge from '@components/Badge'; import FullPageNotFoundView from '@components/BlockingViews/FullPageNotFoundView'; import HeaderWithBackButton from '@components/HeaderWithBackButton'; @@ -14,7 +13,6 @@ import useLocalize from '@hooks/useLocalize'; import useNetwork from '@hooks/useNetwork'; import useStyleUtils from '@hooks/useStyleUtils'; import useThemeStyles from '@hooks/useThemeStyles'; -import compose from '@libs/compose'; import {formatPhoneNumber} from '@libs/LocalePhoneNumber'; import Log from '@libs/Log'; import Navigation from '@libs/Navigation/Navigation'; @@ -29,7 +27,6 @@ import withPolicyAndFullscreenLoading from '@pages/workspace/withPolicyAndFullsc import type {WithPolicyAndFullscreenLoadingProps} from '@pages/workspace/withPolicyAndFullscreenLoading'; import * as Policy from '@userActions/Policy'; import CONST from '@src/CONST'; -import ONYXKEYS from '@src/ONYXKEYS'; import type SCREENS from '@src/SCREENS'; import type {PersonalDetailsList, PolicyMember} from '@src/types/onyx'; import {isEmptyObject} from '@src/types/utils/EmptyObject'; @@ -45,7 +42,7 @@ type WorkspaceWorkflowsPayerPageProps = WorkspaceWorkflowsPayerPageOnyxProps & type MemberOption = Omit & {accountID: number}; type MembersSection = SectionListData>; -function WorkspaceWorkflowsPayerPage({route, policy, policyMembers, personalDetails, isLoadingReportData = true}: WorkspaceWorkflowsPayerPageProps) { +function WorkspaceWorkflowsPayerPage({route, policy, personalDetails, isLoadingReportData = true}: WorkspaceWorkflowsPayerPageProps) { const {translate} = useLocalize(); const styles = useThemeStyles(); const StyleUtils = useStyleUtils(); @@ -63,8 +60,8 @@ function WorkspaceWorkflowsPayerPage({route, policy, policyMembers, personalDeta const policyAdminDetails: MemberOption[] = []; const authorizedPayerDetails: MemberOption[] = []; - Object.entries(policyMembers ?? {}).forEach(([accountIDKey, policyMember]) => { - const accountID = Number(accountIDKey); + Object.entries(policy?.employeeList ?? {}).forEach(([email, policyMember]) => { + const accountID = Object.values(personalDetails ?? {}).find((details) => details?.login === email)?.accountID ?? 0; const details = personalDetails?.[accountID]; if (!details) { Log.hmmm(`[WorkspaceMembersPage] no personal details found for policy member with accountID: ${accountID}`); @@ -90,7 +87,7 @@ function WorkspaceWorkflowsPayerPage({route, policy, policyMembers, personalDeta const isAuthorizedPayer = policy?.reimburserEmail === details?.login ?? policy?.reimburserAccountID === accountID; const formattedMember = { - keyForList: accountIDKey, + keyForList: String(accountID), accountID, isSelected: isAuthorizedPayer, isDisabled: policyMember.pendingAction === CONST.RED_BRICK_ROAD_PENDING_ACTION.DELETE || !isEmptyObject(policyMember.errors), @@ -118,7 +115,7 @@ function WorkspaceWorkflowsPayerPage({route, policy, policyMembers, personalDeta return [policyAdminDetails, authorizedPayerDetails]; }, [ personalDetails, - policyMembers, + policy?.employeeList, translate, policy?.reimburserEmail, isDeletedPolicyMember, @@ -225,11 +222,4 @@ function WorkspaceWorkflowsPayerPage({route, policy, policyMembers, personalDeta WorkspaceWorkflowsPayerPage.displayName = 'WorkspaceWorkflowsPayerPage'; -export default compose( - withOnyx({ - personalDetails: { - key: ONYXKEYS.PERSONAL_DETAILS_LIST, - }, - }), - withPolicyAndFullscreenLoading, -)(WorkspaceWorkflowsPayerPage); +export default withPolicyAndFullscreenLoading(WorkspaceWorkflowsPayerPage); From 72a467fe0f0eefd2e2239606c0edadb16c8d1abb Mon Sep 17 00:00:00 2001 From: Yauheni Date: Sat, 6 Apr 2024 20:41:34 +0200 Subject: [PATCH 04/27] Remove policyMembers from WorkspaceWorkflowsApproverPage and revert changes from WorkspaceMembersPage --- src/libs/PolicyUtils.ts | 4 +- src/pages/workspace/WorkspaceInvitePage.tsx | 2 +- src/pages/workspace/WorkspaceMembersPage.tsx | 157 +++++++----------- .../WorkspaceWorkflowsApproverPage.tsx | 13 +- 4 files changed, 68 insertions(+), 108 deletions(-) diff --git a/src/libs/PolicyUtils.ts b/src/libs/PolicyUtils.ts index d48fdd11527b..f54d45987c0c 100644 --- a/src/libs/PolicyUtils.ts +++ b/src/libs/PolicyUtils.ts @@ -133,8 +133,8 @@ const isPolicyMember = (policyID: string, policies: OnyxCollection): boo * * We only return members without errors. Otherwise, the members with errors would immediately be removed before the user has a chance to read the error. */ -function getMemberAccountIDsForWorkspace(policy: OnyxEntry, personalDetails: OnyxEntry): MemberEmailsToAccountIDs { - const members = policy?.employeeList ?? {}; +function getMemberAccountIDsForWorkspace(policyMembers: PolicyMembers | undefined, personalDetails: OnyxEntry): MemberEmailsToAccountIDs { + const members = policyMembers ?? {}; const memberEmailsToAccountIDs: MemberEmailsToAccountIDs = {}; Object.keys(members).forEach((email) => { const member = members?.[email]; diff --git a/src/pages/workspace/WorkspaceInvitePage.tsx b/src/pages/workspace/WorkspaceInvitePage.tsx index 5c53527bf688..90f44d8dd1c1 100644 --- a/src/pages/workspace/WorkspaceInvitePage.tsx +++ b/src/pages/workspace/WorkspaceInvitePage.tsx @@ -68,7 +68,7 @@ function WorkspaceInvitePage({ const [personalDetails, setPersonalDetails] = useState([]); const [usersToInvite, setUsersToInvite] = useState([]); const openWorkspaceInvitePage = () => { - const policyMemberEmailsToAccountIDs = PolicyUtils.getMemberAccountIDsForWorkspace(policy, personalDetailsProp); + const policyMemberEmailsToAccountIDs = PolicyUtils.getMemberAccountIDsForWorkspace(policy?.employeeList, personalDetailsProp); Policy.openWorkspaceInvitePage(route.params.policyID, Object.keys(policyMemberEmailsToAccountIDs)); }; diff --git a/src/pages/workspace/WorkspaceMembersPage.tsx b/src/pages/workspace/WorkspaceMembersPage.tsx index 3fae61616f3f..c4828409545c 100644 --- a/src/pages/workspace/WorkspaceMembersPage.tsx +++ b/src/pages/workspace/WorkspaceMembersPage.tsx @@ -55,12 +55,10 @@ type WorkspaceMembersPageOnyxProps = { /** An object containing the accountID for every invited user email */ invitedEmailsToAccountIDsDraft: OnyxEntry; }; - type WorkspaceMembersPageProps = WithPolicyAndFullscreenLoadingProps & WithCurrentUserPersonalDetailsProps & WorkspaceMembersPageOnyxProps & StackScreenProps; - /** * Inverts an object, equivalent of _.invert */ @@ -70,55 +68,60 @@ function invertObject(object: Record): Record { return inverted; } -type MemberOption = Omit & {email: string; accountID: number}; - -function WorkspaceMembersPage({personalDetails, invitedEmailsToAccountIDsDraft, route, policy, session, currentUserPersonalDetails, isLoadingReportData = true}: WorkspaceMembersPageProps) { +type MemberOption = Omit & {accountID: number}; + +function WorkspaceMembersPage({ + policyMembers, + personalDetails, + invitedEmailsToAccountIDsDraft, + route, + policy, + session, + currentUserPersonalDetails, + isLoadingReportData = true, +}: WorkspaceMembersPageProps) { const styles = useThemeStyles(); const StyleUtils = useStyleUtils(); - const [selectedEmployees, setSelectedEmployees] = useState([]); + const [selectedEmployees, setSelectedEmployees] = useState([]); const [removeMembersConfirmModalVisible, setRemoveMembersConfirmModalVisible] = useState(false); const [errors, setErrors] = useState({}); const {isOffline} = useNetwork(); const prevIsOffline = usePrevious(isOffline); - const accountEmails = useMemo(() => Object.keys(policy?.employeeList ?? {}).map((email) => email), [policy?.employeeList]); - const prevAccountEmails = usePrevious(accountEmails); + const accountIDs = useMemo(() => Object.keys(policyMembers ?? {}).map((accountID) => Number(accountID)), [policyMembers]); + const prevAccountIDs = usePrevious(accountIDs); const textInputRef = useRef(null); - const isOfflineAndNoMemberDataAvailable = isEmptyObject(policy?.employeeList ?? {}) && isOffline; + const isOfflineAndNoMemberDataAvailable = isEmptyObject(policyMembers) && isOffline; const prevPersonalDetails = usePrevious(personalDetails); const {translate, formatPhoneNumber, preferredLocale} = useLocalize(); const {isSmallScreenWidth} = useWindowDimensions(); const dropdownButtonRef = useRef(null); const isPolicyAdmin = PolicyUtils.isPolicyAdmin(policy); const isLoading = useMemo( - () => !isOfflineAndNoMemberDataAvailable && (!OptionsListUtils.isPersonalDetailsReady(personalDetails) || isEmptyObject(policy?.employeeList ?? {})), - [isOfflineAndNoMemberDataAvailable, personalDetails, policy?.employeeList], + () => !isOfflineAndNoMemberDataAvailable && (!OptionsListUtils.isPersonalDetailsReady(personalDetails) || isEmptyObject(policyMembers)), + [isOfflineAndNoMemberDataAvailable, personalDetails, policyMembers], ); const selectionListRef = useRef(null); const isFocused = useIsFocused(); - const policyID = route.params.policyID; - /** * Get filtered personalDetails list with current policyMembers */ - const filterPersonalDetails = (members: OnyxEntry, personalDetailsList: OnyxEntry): PersonalDetailsList => + const filterPersonalDetails = (members: OnyxEntry, details: OnyxEntry): PersonalDetailsList => Object.keys(members ?? {}).reduce((result, key) => { - const details = Object.values(personalDetailsList ?? {}).find((currentDetails) => currentDetails?.login === key); - if (details) { + if (details?.[key]) { return { ...result, - [key]: details, + [key]: details[key], }; } return result; }, {}); - /** * Get members for the current workspace */ const getWorkspaceMembers = useCallback(() => { - Policy.openWorkspaceMembersPage(route.params.policyID, Object.keys(PolicyUtils.getMemberAccountIDsForWorkspace(policy, personalDetails))); - }, [route.params.policyID, policy, personalDetails]); + Policy.openWorkspaceMembersPage(route.params.policyID, Object.keys(PolicyUtils.getMemberAccountIDsForWorkspace(policy?.employeeList, personalDetails))); + }, [route.params.policyID, policy?.employeeList, personalDetails]); /** * Check if the current selection includes members that cannot be removed @@ -126,8 +129,7 @@ function WorkspaceMembersPage({personalDetails, invitedEmailsToAccountIDsDraft, const validateSelection = useCallback(() => { const newErrors: Errors = {}; selectedEmployees.forEach((member) => { - const details = Object.values(personalDetails ?? {}).find((currentDetails) => currentDetails?.login === member); - if (details?.accountID !== policy?.ownerAccountID && details?.accountID !== session?.accountID) { + if (member !== policy?.ownerAccountID && member !== session?.accountID) { return; } newErrors[member] = translate('workspace.people.error.cannotRemove'); @@ -135,36 +137,34 @@ function WorkspaceMembersPage({personalDetails, invitedEmailsToAccountIDsDraft, setErrors(newErrors); // eslint-disable-next-line react-hooks/exhaustive-deps }, [selectedEmployees, policy?.owner, session?.accountID]); - useEffect(() => { getWorkspaceMembers(); // eslint-disable-next-line react-hooks/exhaustive-deps }, []); - useEffect(() => { validateSelection(); }, [preferredLocale, validateSelection]); useEffect(() => { - if (removeMembersConfirmModalVisible && !lodashIsEqual(accountEmails, prevAccountEmails)) { + if (removeMembersConfirmModalVisible && !lodashIsEqual(accountIDs, prevAccountIDs)) { setRemoveMembersConfirmModalVisible(false); } setSelectedEmployees((prevSelected) => { // Filter all personal details in order to use the elements needed for the current workspace - const currentPersonalDetails = filterPersonalDetails(policy?.employeeList ?? {}, personalDetails); + const currentPersonalDetails = filterPersonalDetails(policyMembers, personalDetails); // We need to filter the previous selected employees by the new personal details, since unknown/new user id's change when transitioning from offline to online - const prevSelectedElements = prevSelected.map((email) => { - const prevItem = prevPersonalDetails?.find((item) => item?.login === email); + const prevSelectedElements = prevSelected.map((id) => { + const prevItem = prevPersonalDetails?.id; const res = Object.values(currentPersonalDetails).find((item) => prevItem?.login === item?.login); - return res?.login ?? email; + return res?.accountID ?? id; }); // This is an equivalent of the lodash intersection function. The reduce method below is used to filter the items that exist in both arrays. - return [prevSelectedElements, Object.keys(PolicyUtils.getMemberAccountIDsForWorkspace(policy, personalDetails))].reduce((prev, members) => + return [prevSelectedElements, Object.values(PolicyUtils.getMemberAccountIDsForWorkspace(policy?.employeeList, personalDetails))].reduce((prev, members) => prev.filter((item) => members.includes(item)), ); }); // eslint-disable-next-line react-hooks/exhaustive-deps - }, [policy]); + }, [policyMembers, policy?.employeeList]); useEffect(() => { const isReconnecting = prevIsOffline && !isOffline; @@ -173,14 +173,12 @@ function WorkspaceMembersPage({personalDetails, invitedEmailsToAccountIDsDraft, } getWorkspaceMembers(); }, [isOffline, prevIsOffline, getWorkspaceMembers]); - /** * Open the modal to invite a user */ const inviteUser = () => { Navigation.navigate(ROUTES.WORKSPACE_INVITE.getRoute(route.params.policyID)); }; - /** * Remove selected users from the workspace * Please see https://github.com/Expensify/App/blob/main/README.md#Security for more details @@ -191,18 +189,12 @@ function WorkspaceMembersPage({personalDetails, invitedEmailsToAccountIDsDraft, } // Remove the admin from the list - const accountIDsToRemove = (session?.accountID ? selectedEmployees.filter((email) => email !== session.email) : selectedEmployees) - .map((email) => { - const details = Object.values(personalDetails ?? {}).find((currentDetails) => currentDetails?.login === email); - return details?.accountID; - }) - .filter(Boolean) as number[]; + const accountIDsToRemove = session?.accountID ? selectedEmployees.filter((id) => id !== session.accountID) : selectedEmployees; Policy.removeMembers(accountIDsToRemove, route.params.policyID); setSelectedEmployees([]); setRemoveMembersConfirmModalVisible(false); }; - /** * Show the modal to confirm removal of the selected members */ @@ -212,65 +204,60 @@ function WorkspaceMembersPage({personalDetails, invitedEmailsToAccountIDsDraft, } setRemoveMembersConfirmModalVisible(true); }; - /** * Add or remove all users passed from the selectedEmployees list */ const toggleAllUsers = (memberList: MemberOption[]) => { const enabledAccounts = memberList.filter((member) => !member.isDisabled && !member.isDisabledCheckbox); - const everyoneSelected = enabledAccounts.every((member) => selectedEmployees.includes(member.email)); + const everyoneSelected = enabledAccounts.every((member) => selectedEmployees.includes(member.accountID)); if (everyoneSelected) { setSelectedEmployees([]); } else { - const everyEmail = enabledAccounts.map((member) => member.email); - setSelectedEmployees(everyEmail); + const everyAccountId = enabledAccounts.map((member) => member.accountID); + setSelectedEmployees(everyAccountId); } validateSelection(); }; - /** * Add user from the selectedEmployees list */ const addUser = useCallback( - (selectedEmail: string) => { - setSelectedEmployees((prevSelected) => [...prevSelected, selectedEmail]); + (accountID: number) => { + setSelectedEmployees((prevSelected) => [...prevSelected, accountID]); validateSelection(); }, [validateSelection], ); - /** * Remove user from the selectedEmployees list */ const removeUser = useCallback( - (selectedEmail: string) => { - setSelectedEmployees((prevSelected) => prevSelected.filter((email) => email !== selectedEmail)); + (accountID: number) => { + setSelectedEmployees((prevSelected) => prevSelected.filter((id) => id !== accountID)); validateSelection(); }, [validateSelection], ); - /** * Toggle user from the selectedEmployees list */ const toggleUser = useCallback( - (email: string, pendingAction?: PendingAction) => { + (accountID: number, pendingAction?: PendingAction) => { if (pendingAction === CONST.RED_BRICK_ROAD_PENDING_ACTION.DELETE) { return; } // Add or remove the user if the checkbox is enabled - if (selectedEmployees.includes(email)) { - removeUser(email); + if (selectedEmployees.includes(accountID)) { + removeUser(accountID); } else { - addUser(email); + addUser(accountID); } }, [selectedEmployees, addUser, removeUser], ); - /** Opens the member details page */ const openMemberDetails = useCallback( (item: MemberOption) => { @@ -278,13 +265,11 @@ function WorkspaceMembersPage({personalDetails, invitedEmailsToAccountIDsDraft, Navigation.navigate(ROUTES.PROFILE.getRoute(item.accountID)); return; } - Policy.clearWorkspaceOwnerChangeFlow(policyID); Navigation.navigate(ROUTES.WORKSPACE_MEMBER_DETAILS.getRoute(route.params.policyID, item.accountID, Navigation.getActiveRoute())); }, [isPolicyAdmin, policy, policyID, route.params.policyID], ); - /** * Dismisses the errors on one item */ @@ -298,7 +283,6 @@ function WorkspaceMembersPage({personalDetails, invitedEmailsToAccountIDsDraft, }, [route.params.policyID], ); - /** * Check if the policy member is deleted from the workspace */ @@ -308,21 +292,20 @@ function WorkspaceMembersPage({personalDetails, invitedEmailsToAccountIDsDraft, ); const policyOwner = policy?.owner; const currentUserLogin = currentUserPersonalDetails.login; - const invitedPrimaryToSecondaryLogins = invertObject(policy?.primaryLoginsInvited ?? {}); - const getUsers = useCallback((): MemberOption[] => { let result: MemberOption[] = []; - Object.entries(policy?.employeeList ?? {}).forEach(([email, policyMember]) => { + Object.entries(policyMembers ?? {}).forEach(([accountIDKey, policyMember]) => { + const accountID = Number(accountIDKey); if (isDeletedPolicyMember(policyMember)) { return; } - const details = Object.values(personalDetails ?? {}).find((currentDetails) => currentDetails?.login === email); + const details = personalDetails?.[accountID]; if (!details) { - Log.hmmm(`[WorkspaceMembersPage] no personal details found for policy member with email: ${email}`); + Log.hmmm(`[WorkspaceMembersPage] no personal details found for policy member with accountID: ${accountID}`); return; } @@ -335,11 +318,10 @@ function WorkspaceMembersPage({personalDetails, invitedEmailsToAccountIDsDraft, } } - const isSelected = selectedEmployees.includes(email); + const isSelected = selectedEmployees.includes(accountID); const isOwner = policy?.owner === details.login; const isAdmin = policyMember.role === CONST.POLICY.ROLE.ADMIN; - let roleBadge = null; if (isOwner || isAdmin) { roleBadge = ( @@ -351,12 +333,9 @@ function WorkspaceMembersPage({personalDetails, invitedEmailsToAccountIDsDraft, ); } - const accountID = details.accountID ?? 0; - result.push({ - keyForList: email, + keyForList: accountIDKey, accountID, - email, isSelected, isDisabledCheckbox: !(isPolicyAdmin && accountID !== policy?.ownerAccountID && accountID !== session?.accountID), isDisabled: isPolicyAdmin && (policyMember.pendingAction === CONST.RED_BRICK_ROAD_PENDING_ACTION.DELETE || !isEmptyObject(policyMember.errors)), @@ -373,14 +352,11 @@ function WorkspaceMembersPage({personalDetails, invitedEmailsToAccountIDsDraft, ], errors: policyMember.errors, pendingAction: policyMember.pendingAction, - // Note which secondary login was used to invite this primary login invitedSecondaryLogin: details?.login ? invitedPrimaryToSecondaryLogins[details.login] ?? '' : '', }); }); - result = result.sort((a, b) => (a.text ?? '').toLowerCase().localeCompare((b.text ?? '').toLowerCase())); - return result; }, [ StyleUtils, @@ -392,7 +368,7 @@ function WorkspaceMembersPage({personalDetails, invitedEmailsToAccountIDsDraft, personalDetails, policy?.owner, policy?.ownerAccountID, - policy?.employeeList, + policyMembers, policyOwner, selectedEmployees, session?.accountID, @@ -402,27 +378,25 @@ function WorkspaceMembersPage({personalDetails, invitedEmailsToAccountIDsDraft, styles.textStrong, translate, ]); - const data = useMemo(() => getUsers(), [getUsers]); - useEffect(() => { if (!isFocused) { return; } - if (isEmptyObject(invitedEmailsToAccountIDsDraft) || accountEmails === prevAccountEmails) { + if (isEmptyObject(invitedEmailsToAccountIDsDraft) || accountIDs === prevAccountIDs) { return; } const invitedEmails = Object.values(invitedEmailsToAccountIDsDraft).map(String); selectionListRef.current?.scrollAndHighlightItem?.(invitedEmails, 1500); Policy.setWorkspaceInviteMembersDraft(route.params.policyID, {}); - }, [invitedEmailsToAccountIDsDraft, route.params.policyID, isFocused, accountEmails, prevAccountEmails]); + }, [invitedEmailsToAccountIDsDraft, route.params.policyID, isFocused, accountIDs, prevAccountIDs]); const getHeaderMessage = () => { if (isOfflineAndNoMemberDataAvailable) { return translate('workspace.common.mustBeOnlineToViewMembers'); } - return !isLoading && isEmptyObject(policy?.employeeList ?? {}) ? translate('workspace.common.memberNotFound') : ''; + return !isLoading && isEmptyObject(policyMembers) ? translate('workspace.common.memberNotFound') : ''; }; const getHeaderContent = () => ( @@ -439,7 +413,6 @@ function WorkspaceMembersPage({personalDetails, invitedEmailsToAccountIDsDraft, )} ); - const getCustomListHeader = () => { const header = ( @@ -451,31 +424,21 @@ function WorkspaceMembersPage({personalDetails, invitedEmailsToAccountIDsDraft, ); - if (isPolicyAdmin) { return header; } - return {header}; }; - const changeUserRole = (role: typeof CONST.POLICY.ROLE.ADMIN | typeof CONST.POLICY.ROLE.USER) => { if (!isEmptyObject(errors)) { return; } - const accountIDsToUpdate = selectedEmployees - .filter((email) => policy?.employeeList?.[email].role !== role) - .map((email) => { - const details = Object.values(personalDetails ?? {}).find((currentDetails) => currentDetails?.login === email); - return details?.accountID; - }) - .filter(Boolean) as number[]; + const accountIDsToUpdate = selectedEmployees.filter((id) => policyMembers?.[id].role !== role); Policy.updateWorkspaceMembersRole(route.params.policyID, accountIDsToUpdate, role); setSelectedEmployees([]); }; - const getBulkActionsButtonOptions = () => { const options: Array> = [ { @@ -487,7 +450,7 @@ function WorkspaceMembersPage({personalDetails, invitedEmailsToAccountIDsDraft, ]; if (PolicyUtils.isPaidGroupPolicy(policy)) { - if (selectedEmployees.find((employee) => policy?.employeeList?.[employee]?.role === CONST.POLICY.ROLE.ADMIN)) { + if (selectedEmployees.find((employee) => policyMembers?.[employee]?.role === CONST.POLICY.ROLE.ADMIN)) { options.push({ text: translate('workspace.people.makeMember'), value: CONST.POLICY.MEMBERS_BULK_ACTION_TYPES.MAKE_MEMBER, @@ -496,7 +459,7 @@ function WorkspaceMembersPage({personalDetails, invitedEmailsToAccountIDsDraft, }); } - if (selectedEmployees.find((employee) => policy?.employeeList?.[employee]?.role === CONST.POLICY.ROLE.USER)) { + if (selectedEmployees.find((employee) => policyMembers?.[employee]?.role === CONST.POLICY.ROLE.USER)) { options.push({ text: translate('workspace.people.makeAdmin'), value: CONST.POLICY.MEMBERS_BULK_ACTION_TYPES.MAKE_ADMIN, @@ -505,15 +468,12 @@ function WorkspaceMembersPage({personalDetails, invitedEmailsToAccountIDsDraft, }); } } - return options; }; - const getHeaderButtons = () => { if (!isPolicyAdmin) { return null; } - return ( {selectedEmployees.length > 0 ? ( @@ -541,7 +501,6 @@ function WorkspaceMembersPage({personalDetails, invitedEmailsToAccountIDsDraft, ); }; - return ( toggleUser(item.email)} + onCheckboxPress={(item) => toggleUser(item.accountID)} onSelectAll={() => toggleAllUsers(data)} onDismissError={dismissError} showLoadingPlaceholder={isLoading} @@ -610,9 +569,7 @@ function WorkspaceMembersPage({personalDetails, invitedEmailsToAccountIDsDraft, ); } - WorkspaceMembersPage.displayName = 'WorkspaceMembersPage'; - export default withCurrentUserPersonalDetails( withPolicyAndFullscreenLoading( withOnyx({ diff --git a/src/pages/workspace/workflows/WorkspaceWorkflowsApproverPage.tsx b/src/pages/workspace/workflows/WorkspaceWorkflowsApproverPage.tsx index 51baaca166b5..d642960255c5 100644 --- a/src/pages/workspace/workflows/WorkspaceWorkflowsApproverPage.tsx +++ b/src/pages/workspace/workflows/WorkspaceWorkflowsApproverPage.tsx @@ -41,7 +41,7 @@ type WorkspaceWorkflowsApproverPageProps = WorkspaceWorkflowsApproverPageOnyxPro type MemberOption = Omit & {accountID: number}; type MembersSection = SectionListData>; -function WorkspaceWorkflowsApproverPage({policy, policyMembers, personalDetails, isLoadingReportData = true, route}: WorkspaceWorkflowsApproverPageProps) { +function WorkspaceWorkflowsApproverPage({policy, personalDetails, isLoadingReportData = true, route}: WorkspaceWorkflowsApproverPageProps) { const {translate} = useLocalize(); const policyName = policy?.name ?? ''; const [searchTerm, setSearchTerm] = useState(''); @@ -58,12 +58,15 @@ function WorkspaceWorkflowsApproverPage({policy, policyMembers, personalDetails, const policyMemberDetails: MemberOption[] = []; const approverDetails: MemberOption[] = []; - Object.entries(policyMembers ?? {}).forEach(([accountIDKey, policyMember]) => { - const accountID = Number(accountIDKey); + const policyMemberEmailsToAccountIDs = PolicyUtils.getMemberAccountIDsForWorkspace(policy?.employeeList, personalDetails); + + Object.entries(policy?.employeeList ?? {}).forEach(([email, policyMember]) => { if (isDeletedPolicyMember(policyMember)) { return; } + const accountID = Number(policyMemberEmailsToAccountIDs[email] || ''); + const details = personalDetails?.[accountID]; if (!details) { Log.hmmm(`[WorkspaceMembersPage] no personal details found for policy member with accountID: ${accountID}`); @@ -85,7 +88,7 @@ function WorkspaceWorkflowsApproverPage({policy, policyMembers, personalDetails, } const formattedMember = { - keyForList: accountIDKey, + keyForList: String(accountID), accountID, isSelected: policy?.approver === details.login, isDisabled: policyMember.pendingAction === CONST.RED_BRICK_ROAD_PENDING_ACTION.DELETE || !isEmptyObject(policyMember.errors), @@ -111,7 +114,7 @@ function WorkspaceWorkflowsApproverPage({policy, policyMembers, personalDetails, } }); return [policyMemberDetails, approverDetails]; - }, [personalDetails, policyMembers, translate, policy?.approver, StyleUtils, isDeletedPolicyMember, policy?.owner, styles]); + }, [personalDetails, translate, policy?.approver, StyleUtils, isDeletedPolicyMember, policy?.owner, styles, policy?.employeeList]); const sections: MembersSection[] = useMemo(() => { const sectionsArray: MembersSection[] = []; From 224f2b7c9ed472e8f3c6594f73203c764abe96d4 Mon Sep 17 00:00:00 2001 From: Yauheni Date: Sat, 6 Apr 2024 21:21:42 +0200 Subject: [PATCH 05/27] Remove policyMembers from ReportScreenIDSetter and refactor PolicyMembersUtils --- .../AppNavigator/ReportScreenIDSetter.ts | 19 +++++++++--------- src/libs/PolicyMembersUtils.ts | 20 +++++++++++++------ src/libs/PolicyUtils.ts | 12 +++++------ 3 files changed, 29 insertions(+), 22 deletions(-) diff --git a/src/libs/Navigation/AppNavigator/ReportScreenIDSetter.ts b/src/libs/Navigation/AppNavigator/ReportScreenIDSetter.ts index 529f0f3d31a7..a9fbf19b4477 100644 --- a/src/libs/Navigation/AppNavigator/ReportScreenIDSetter.ts +++ b/src/libs/Navigation/AppNavigator/ReportScreenIDSetter.ts @@ -6,7 +6,7 @@ import usePermissions from '@hooks/usePermissions'; import {getPolicyMembersByIdWithoutCurrentUser} from '@libs/PolicyUtils'; import * as ReportUtils from '@libs/ReportUtils'; import ONYXKEYS from '@src/ONYXKEYS'; -import type {Policy, PolicyMembers, Report, ReportMetadata} from '@src/types/onyx'; +import type {PersonalDetailsList, Policy, Report, ReportMetadata} from '@src/types/onyx'; import type {ReportScreenWrapperProps} from './ReportScreenWrapper'; type ReportScreenIDSetterComponentProps = { @@ -16,8 +16,8 @@ type ReportScreenIDSetterComponentProps = { /** The policies which the user has access to */ policies: OnyxCollection; - /** Members of all the workspaces the user is member of */ - policyMembers: OnyxCollection; + /** The personal details of the person who is logged in */ + personalDetails: OnyxEntry; /** Whether user is a new user */ isFirstTimeNewExpensifyUser: OnyxEntry; @@ -58,7 +58,7 @@ const getLastAccessedReportID = ( }; // This wrapper is reponsible for opening the last accessed report if there is no reportID specified in the route params -function ReportScreenIDSetter({route, reports, policies, policyMembers = {}, navigation, isFirstTimeNewExpensifyUser = false, reportMetadata, accountID}: ReportScreenIDSetterProps) { +function ReportScreenIDSetter({route, reports, policies, navigation, isFirstTimeNewExpensifyUser = false, reportMetadata, accountID, personalDetails}: ReportScreenIDSetterProps) { const {canUseDefaultRooms} = usePermissions(); const {activeWorkspaceID} = useActiveWorkspace(); @@ -73,7 +73,7 @@ function ReportScreenIDSetter({route, reports, policies, policyMembers = {}, nav return; } - const policyMemberAccountIDs = getPolicyMembersByIdWithoutCurrentUser(policyMembers, activeWorkspaceID, accountID); + const policyMemberAccountIDs = getPolicyMembersByIdWithoutCurrentUser(policies, personalDetails, activeWorkspaceID, accountID); // If there is no reportID in route, try to find last accessed and use it for setParams const reportID = getLastAccessedReportID( @@ -92,7 +92,7 @@ function ReportScreenIDSetter({route, reports, policies, policyMembers = {}, nav if (reportID) { navigation.setParams({reportID: String(reportID)}); } - }, [route, navigation, reports, canUseDefaultRooms, policies, isFirstTimeNewExpensifyUser, reportMetadata, activeWorkspaceID, policyMembers, accountID]); + }, [route, navigation, reports, canUseDefaultRooms, policies, isFirstTimeNewExpensifyUser, reportMetadata, activeWorkspaceID, personalDetails, accountID]); // The ReportScreen without the reportID set will display a skeleton // until the reportID is loaded and set in the route param @@ -110,10 +110,6 @@ export default withOnyx session?.accountID, }, + personalDetails: { + key: ONYXKEYS.PERSONAL_DETAILS_LIST, + }, })(ReportScreenIDSetter); diff --git a/src/libs/PolicyMembersUtils.ts b/src/libs/PolicyMembersUtils.ts index 4376de150f17..59d1bff22597 100644 --- a/src/libs/PolicyMembersUtils.ts +++ b/src/libs/PolicyMembersUtils.ts @@ -1,15 +1,23 @@ -import type {OnyxCollection} from 'react-native-onyx'; +import type {OnyxCollection, OnyxEntry} from 'react-native-onyx'; import Onyx from 'react-native-onyx'; import ONYXKEYS from '@src/ONYXKEYS'; -import type {PolicyMembers} from '@src/types/onyx'; +import type {PersonalDetailsList, Policy} from '@src/types/onyx'; import {getCurrentUserAccountID} from './actions/Report'; import {getPolicyMembersByIdWithoutCurrentUser} from './PolicyUtils'; -let policyMembers: OnyxCollection; +let policies: OnyxCollection; Onyx.connect({ - key: ONYXKEYS.COLLECTION.POLICY_MEMBERS, + key: ONYXKEYS.COLLECTION.POLICY, waitForCollectionCallback: true, - callback: (value) => (policyMembers = value), + callback: (value) => (policies = value), +}); + +let allPersonalDetails: OnyxEntry = {}; +Onyx.connect({ + key: ONYXKEYS.PERSONAL_DETAILS_LIST, + callback: (val) => { + allPersonalDetails = val; + }, }); function getPolicyMemberAccountIDs(policyID?: string) { @@ -19,7 +27,7 @@ function getPolicyMemberAccountIDs(policyID?: string) { const currentUserAccountID = getCurrentUserAccountID(); - return getPolicyMembersByIdWithoutCurrentUser(policyMembers, policyID, currentUserAccountID); + return getPolicyMembersByIdWithoutCurrentUser(policies, allPersonalDetails, policyID, currentUserAccountID); } export default getPolicyMemberAccountIDs; diff --git a/src/libs/PolicyUtils.ts b/src/libs/PolicyUtils.ts index f54d45987c0c..43445db90fdf 100644 --- a/src/libs/PolicyUtils.ts +++ b/src/libs/PolicyUtils.ts @@ -273,12 +273,12 @@ function getPathWithoutPolicyID(path: string) { return path.replace(CONST.REGEX.PATH_WITHOUT_POLICY_ID, '/'); } -function getPolicyMembersByIdWithoutCurrentUser(policyMembers: OnyxCollection, currentPolicyID?: string, currentUserAccountID?: number) { - return policyMembers - ? Object.keys(policyMembers[`${ONYXKEYS.COLLECTION.POLICY_MEMBERS}${currentPolicyID}`] ?? {}) - .map((policyMemberAccountID) => Number(policyMemberAccountID)) - .filter((policyMemberAccountID) => policyMemberAccountID !== currentUserAccountID) - : []; +function getPolicyMembersByIdWithoutCurrentUser(policies: OnyxCollection, personalDetails: OnyxEntry, currentPolicyID?: string, currentUserAccountID?: number) { + const policy = policies?.[`${ONYXKEYS.COLLECTION.POLICY}${currentPolicyID}`] ?? null; + const policyMemberEmailsToAccountIDs = getMemberAccountIDsForWorkspace(policy?.employeeList, personalDetails); + return Object.values(policyMemberEmailsToAccountIDs) + .map((policyMemberAccountID) => Number(policyMemberAccountID)) + .filter((policyMemberAccountID) => policyMemberAccountID !== currentUserAccountID); } function goBackFromInvalidPolicy() { From 99c6a2809649f0dfcd340f325a3de3dbca2c15f9 Mon Sep 17 00:00:00 2001 From: Yauheni Date: Sat, 6 Apr 2024 21:27:04 +0200 Subject: [PATCH 06/27] Remove policyMembers from SidebarLinksData --- src/pages/home/sidebar/SidebarLinksData.js | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) diff --git a/src/pages/home/sidebar/SidebarLinksData.js b/src/pages/home/sidebar/SidebarLinksData.js index 0c1f8b8c5972..016435f42fa5 100644 --- a/src/pages/home/sidebar/SidebarLinksData.js +++ b/src/pages/home/sidebar/SidebarLinksData.js @@ -65,9 +65,6 @@ const propTypes = { // eslint-disable-next-line react/forbid-prop-types policies: PropTypes.object, - // eslint-disable-next-line react/forbid-prop-types - policyMembers: PropTypes.object, - /** All of the transaction violations */ transactionViolations: PropTypes.shape({ violations: PropTypes.arrayOf( @@ -102,7 +99,6 @@ const defaultProps = { priorityMode: CONST.PRIORITY_MODE.DEFAULT, betas: [], policies: {}, - policyMembers: {}, transactionViolations: {}, allReportActions: {}, ...withCurrentUserPersonalDetailsDefaultProps, @@ -120,7 +116,6 @@ function SidebarLinksData({ policies, priorityMode, network, - policyMembers, transactionViolations, currentUserPersonalDetails, }) { @@ -129,7 +124,7 @@ function SidebarLinksData({ const {translate} = useLocalize(); const prevPriorityMode = usePrevious(priorityMode); - const policyMemberAccountIDs = getPolicyMembersByIdWithoutCurrentUser(policyMembers, activeWorkspaceID, currentUserPersonalDetails.accountID); + const policyMemberAccountIDs = getPolicyMembersByIdWithoutCurrentUser(policies, activeWorkspaceID, currentUserPersonalDetails.accountID); // eslint-disable-next-line react-hooks/exhaustive-deps useEffect(() => Policy.openWorkspace(activeWorkspaceID, policyMemberAccountIDs), [activeWorkspaceID]); @@ -322,9 +317,6 @@ export default compose( selector: policySelector, initialValue: {}, }, - policyMembers: { - key: ONYXKEYS.COLLECTION.POLICY_MEMBERS, - }, transactionViolations: { key: ONYXKEYS.COLLECTION.TRANSACTION_VIOLATIONS, initialValue: {}, @@ -348,7 +340,6 @@ export default compose( prevProps.network.isOffline === nextProps.network.isOffline && _.isEqual(prevProps.insets, nextProps.insets) && prevProps.onLinkClick === nextProps.onLinkClick && - _.isEqual(prevProps.policyMembers, nextProps.policyMembers) && _.isEqual(prevProps.transactionViolations, nextProps.transactionViolations) && _.isEqual(prevProps.currentUserPersonalDetails, nextProps.currentUserPersonalDetails) && prevProps.currentReportID === nextProps.currentReportID, From 23235b6b57b1d4505900121a25f81297c4b40616 Mon Sep 17 00:00:00 2001 From: Yauheni Date: Sat, 6 Apr 2024 21:55:53 +0200 Subject: [PATCH 07/27] Remove policyMembers from WorkspaceMembersPage --- src/pages/workspace/WorkspaceMembersPage.tsx | 43 ++++++++----------- src/pages/workspace/withPolicy.tsx | 5 --- .../withPolicyAndFullscreenLoading.tsx | 3 +- 3 files changed, 19 insertions(+), 32 deletions(-) diff --git a/src/pages/workspace/WorkspaceMembersPage.tsx b/src/pages/workspace/WorkspaceMembersPage.tsx index c4828409545c..762e68f6befb 100644 --- a/src/pages/workspace/WorkspaceMembersPage.tsx +++ b/src/pages/workspace/WorkspaceMembersPage.tsx @@ -70,16 +70,8 @@ function invertObject(object: Record): Record { type MemberOption = Omit & {accountID: number}; -function WorkspaceMembersPage({ - policyMembers, - personalDetails, - invitedEmailsToAccountIDsDraft, - route, - policy, - session, - currentUserPersonalDetails, - isLoadingReportData = true, -}: WorkspaceMembersPageProps) { +function WorkspaceMembersPage({personalDetails, invitedEmailsToAccountIDsDraft, route, policy, session, currentUserPersonalDetails, isLoadingReportData = true}: WorkspaceMembersPageProps) { + const policyMemberEmailsToAccountIDs = PolicyUtils.getMemberAccountIDsForWorkspace(policy?.employeeList, personalDetails); const styles = useThemeStyles(); const StyleUtils = useStyleUtils(); const [selectedEmployees, setSelectedEmployees] = useState([]); @@ -87,18 +79,18 @@ function WorkspaceMembersPage({ const [errors, setErrors] = useState({}); const {isOffline} = useNetwork(); const prevIsOffline = usePrevious(isOffline); - const accountIDs = useMemo(() => Object.keys(policyMembers ?? {}).map((accountID) => Number(accountID)), [policyMembers]); + const accountIDs = useMemo(() => Object.values(policyMemberEmailsToAccountIDs ?? {}).map((accountID) => Number(accountID)), [policyMemberEmailsToAccountIDs]); const prevAccountIDs = usePrevious(accountIDs); const textInputRef = useRef(null); - const isOfflineAndNoMemberDataAvailable = isEmptyObject(policyMembers) && isOffline; + const isOfflineAndNoMemberDataAvailable = isEmptyObject(policy?.employeeList) && isOffline; const prevPersonalDetails = usePrevious(personalDetails); const {translate, formatPhoneNumber, preferredLocale} = useLocalize(); const {isSmallScreenWidth} = useWindowDimensions(); const dropdownButtonRef = useRef(null); const isPolicyAdmin = PolicyUtils.isPolicyAdmin(policy); const isLoading = useMemo( - () => !isOfflineAndNoMemberDataAvailable && (!OptionsListUtils.isPersonalDetailsReady(personalDetails) || isEmptyObject(policyMembers)), - [isOfflineAndNoMemberDataAvailable, personalDetails, policyMembers], + () => !isOfflineAndNoMemberDataAvailable && (!OptionsListUtils.isPersonalDetailsReady(personalDetails) || isEmptyObject(policy?.employeeList)), + [isOfflineAndNoMemberDataAvailable, personalDetails, policy?.employeeList], ); const selectionListRef = useRef(null); const isFocused = useIsFocused(); @@ -111,7 +103,7 @@ function WorkspaceMembersPage({ if (details?.[key]) { return { ...result, - [key]: details[key], + [key]: details[policyMemberEmailsToAccountIDs[key] ?? ''], }; } return result; @@ -151,7 +143,7 @@ function WorkspaceMembersPage({ } setSelectedEmployees((prevSelected) => { // Filter all personal details in order to use the elements needed for the current workspace - const currentPersonalDetails = filterPersonalDetails(policyMembers, personalDetails); + const currentPersonalDetails = filterPersonalDetails(policy?.employeeList ?? {}, personalDetails); // We need to filter the previous selected employees by the new personal details, since unknown/new user id's change when transitioning from offline to online const prevSelectedElements = prevSelected.map((id) => { const prevItem = prevPersonalDetails?.id; @@ -164,7 +156,7 @@ function WorkspaceMembersPage({ ); }); // eslint-disable-next-line react-hooks/exhaustive-deps - }, [policyMembers, policy?.employeeList]); + }, [policy?.employeeList]); useEffect(() => { const isReconnecting = prevIsOffline && !isOffline; @@ -296,8 +288,8 @@ function WorkspaceMembersPage({ const getUsers = useCallback((): MemberOption[] => { let result: MemberOption[] = []; - Object.entries(policyMembers ?? {}).forEach(([accountIDKey, policyMember]) => { - const accountID = Number(accountIDKey); + Object.entries(policy?.employeeList ?? {}).forEach(([email, policyMember]) => { + const accountID = Number(policyMemberEmailsToAccountIDs[email] ?? ''); if (isDeletedPolicyMember(policyMember)) { return; } @@ -334,7 +326,7 @@ function WorkspaceMembersPage({ } result.push({ - keyForList: accountIDKey, + keyForList: String(accountID), accountID, isSelected, isDisabledCheckbox: !(isPolicyAdmin && accountID !== policy?.ownerAccountID && accountID !== session?.accountID), @@ -368,7 +360,8 @@ function WorkspaceMembersPage({ personalDetails, policy?.owner, policy?.ownerAccountID, - policyMembers, + policy?.employeeList, + policyMemberEmailsToAccountIDs, policyOwner, selectedEmployees, session?.accountID, @@ -396,7 +389,7 @@ function WorkspaceMembersPage({ return translate('workspace.common.mustBeOnlineToViewMembers'); } - return !isLoading && isEmptyObject(policyMembers) ? translate('workspace.common.memberNotFound') : ''; + return !isLoading && isEmptyObject(policy?.employeeList) ? translate('workspace.common.memberNotFound') : ''; }; const getHeaderContent = () => ( @@ -434,7 +427,7 @@ function WorkspaceMembersPage({ return; } - const accountIDsToUpdate = selectedEmployees.filter((id) => policyMembers?.[id].role !== role); + const accountIDsToUpdate = selectedEmployees.filter((id) => policy?.employeeList?.[policyMemberEmailsToAccountIDs[id]]?.role !== role); Policy.updateWorkspaceMembersRole(route.params.policyID, accountIDsToUpdate, role); setSelectedEmployees([]); @@ -450,7 +443,7 @@ function WorkspaceMembersPage({ ]; if (PolicyUtils.isPaidGroupPolicy(policy)) { - if (selectedEmployees.find((employee) => policyMembers?.[employee]?.role === CONST.POLICY.ROLE.ADMIN)) { + if (selectedEmployees.find((employee) => policy?.employeeList?.[policyMemberEmailsToAccountIDs[employee]]?.role === CONST.POLICY.ROLE.ADMIN)) { options.push({ text: translate('workspace.people.makeMember'), value: CONST.POLICY.MEMBERS_BULK_ACTION_TYPES.MAKE_MEMBER, @@ -459,7 +452,7 @@ function WorkspaceMembersPage({ }); } - if (selectedEmployees.find((employee) => policyMembers?.[employee]?.role === CONST.POLICY.ROLE.USER)) { + if (selectedEmployees.find((employee) => policy?.employeeList?.[policyMemberEmailsToAccountIDs[employee]]?.role === CONST.POLICY.ROLE.USER)) { options.push({ text: translate('workspace.people.makeAdmin'), value: CONST.POLICY.MEMBERS_BULK_ACTION_TYPES.MAKE_ADMIN, diff --git a/src/pages/workspace/withPolicy.tsx b/src/pages/workspace/withPolicy.tsx index 0f276a9c53e3..9262a1b0f727 100644 --- a/src/pages/workspace/withPolicy.tsx +++ b/src/pages/workspace/withPolicy.tsx @@ -92,7 +92,6 @@ const policyPropTypes = { type WithPolicyOnyxProps = { policy: OnyxEntry; - policyMembers: OnyxEntry; policyDraft: OnyxEntry; }; @@ -102,7 +101,6 @@ type WithPolicyProps = WithPolicyOnyxProps & { const policyDefaultProps: WithPolicyOnyxProps = { policy: {} as OnyxTypes.Policy, - policyMembers: {}, policyDraft: {} as OnyxTypes.Policy, }; @@ -134,9 +132,6 @@ export default function (WrappedComponent: policy: { key: (props) => `${ONYXKEYS.COLLECTION.POLICY}${getPolicyIDFromRoute(props.route)}`, }, - policyMembers: { - key: (props) => `${ONYXKEYS.COLLECTION.POLICY_MEMBERS}${getPolicyIDFromRoute(props.route)}`, - }, policyDraft: { key: (props) => `${ONYXKEYS.COLLECTION.POLICY_DRAFTS}${getPolicyIDFromRoute(props.route)}`, }, diff --git a/src/pages/workspace/withPolicyAndFullscreenLoading.tsx b/src/pages/workspace/withPolicyAndFullscreenLoading.tsx index e5d93dbe36d5..161320441843 100644 --- a/src/pages/workspace/withPolicyAndFullscreenLoading.tsx +++ b/src/pages/workspace/withPolicyAndFullscreenLoading.tsx @@ -28,7 +28,7 @@ export default function withPolicyAndFullscreenLoading>, ): ComponentWithPolicyAndFullscreenLoading { function WithPolicyAndFullscreenLoading( - {isLoadingReportData = true, policy = policyDefaultProps.policy, policyDraft = policyDefaultProps.policyDraft, policyMembers = policyDefaultProps.policyMembers, ...rest}: TProps, + {isLoadingReportData = true, policy = policyDefaultProps.policy, policyDraft = policyDefaultProps.policyDraft, ...rest}: TProps, ref: ForwardedRef, ) { if (isLoadingReportData && isEmpty(policy) && isEmpty(policyDraft)) { @@ -42,7 +42,6 @@ export default function withPolicyAndFullscreenLoading ); From b3cc1d0882d38437a5fdb133893b0bb89c0b37d2 Mon Sep 17 00:00:00 2001 From: Yauheni Date: Sat, 6 Apr 2024 22:01:37 +0200 Subject: [PATCH 08/27] Remove POLICY_MEMBERS from utils --- src/ONYXKEYS.ts | 2 -- src/libs/PolicyUtils.ts | 2 +- src/pages/workspace/withPolicy.tsx | 4 ---- 3 files changed, 1 insertion(+), 7 deletions(-) diff --git a/src/ONYXKEYS.ts b/src/ONYXKEYS.ts index 3ff71362af35..c4d83acf24c1 100755 --- a/src/ONYXKEYS.ts +++ b/src/ONYXKEYS.ts @@ -307,7 +307,6 @@ const ONYXKEYS = { COLLECTION: { DOWNLOAD: 'download_', POLICY: 'policy_', - POLICY_MEMBERS: 'policyMembers_', POLICY_DRAFTS: 'policyDrafts_', POLICY_JOIN_MEMBER: 'policyJoinMember_', POLICY_CATEGORIES: 'policyCategories_', @@ -511,7 +510,6 @@ type OnyxCollectionValuesMapping = { [ONYXKEYS.COLLECTION.POLICY_DRAFTS]: OnyxTypes.Policy; [ONYXKEYS.COLLECTION.POLICY_CATEGORIES]: OnyxTypes.PolicyCategories; [ONYXKEYS.COLLECTION.POLICY_TAGS]: OnyxTypes.PolicyTagList; - [ONYXKEYS.COLLECTION.POLICY_MEMBERS]: OnyxTypes.PolicyMembers; [ONYXKEYS.COLLECTION.POLICY_RECENTLY_USED_CATEGORIES]: OnyxTypes.RecentlyUsedCategories; [ONYXKEYS.COLLECTION.DEPRECATED_POLICY_MEMBER_LIST]: OnyxTypes.PolicyMembers; [ONYXKEYS.COLLECTION.WORKSPACE_INVITE_MEMBERS_DRAFT]: OnyxTypes.InvitedEmailsToAccountIDs; diff --git a/src/libs/PolicyUtils.ts b/src/libs/PolicyUtils.ts index 43445db90fdf..79bfd723eb76 100644 --- a/src/libs/PolicyUtils.ts +++ b/src/libs/PolicyUtils.ts @@ -25,7 +25,7 @@ function getActivePolicies(policies: OnyxCollection): Policy[] | undefin } /** - * Checks if we have any errors stored within the POLICY_MEMBERS. Determines whether we should show a red brick road error or not. + * Checks if we have any errors stored within the policy?.employeeList. Determines whether we should show a red brick road error or not. */ function hasEmployeeListError(policy: OnyxEntry): boolean { return Object.values(policy?.employeeList ?? {}).some((employee) => Object.keys(employee?.errors ?? {}).length > 0); diff --git a/src/pages/workspace/withPolicy.tsx b/src/pages/workspace/withPolicy.tsx index 9262a1b0f727..3bdff65e2c66 100644 --- a/src/pages/workspace/withPolicy.tsx +++ b/src/pages/workspace/withPolicy.tsx @@ -9,7 +9,6 @@ import type {ValueOf} from 'type-fest'; import taxPropTypes from '@components/taxPropTypes'; import {translatableTextPropTypes} from '@libs/Localize'; import type {CentralPaneNavigatorParamList, FullScreenNavigatorParamList, SettingsNavigatorParamList, WorkspacesCentralPaneNavigatorParamList} from '@navigation/types'; -import policyMemberPropType from '@pages/policyMemberPropType'; import * as Policy from '@userActions/Policy'; import CONST from '@src/CONST'; import ONYXKEYS from '@src/ONYXKEYS'; @@ -85,9 +84,6 @@ const policyPropTypes = { /** Collection of tax rates attached to a policy */ taxRates: taxPropTypes, }), - - /** The employee list of this policy */ - policyMembers: PropTypes.objectOf(policyMemberPropType), }; type WithPolicyOnyxProps = { From fbe42b21d8e4749d3ac7f9d0df337333d728ac6f Mon Sep 17 00:00:00 2001 From: Yauheni Date: Sat, 6 Apr 2024 22:10:24 +0200 Subject: [PATCH 09/27] Make a little code refactoring --- src/libs/PolicyUtils.ts | 4 ++-- src/pages/workspace/WorkspaceMembersPage.tsx | 2 +- tests/actions/PolicyTest.ts | 16 +--------------- 3 files changed, 4 insertions(+), 18 deletions(-) diff --git a/src/libs/PolicyUtils.ts b/src/libs/PolicyUtils.ts index 79bfd723eb76..8dc61755186b 100644 --- a/src/libs/PolicyUtils.ts +++ b/src/libs/PolicyUtils.ts @@ -133,8 +133,8 @@ const isPolicyMember = (policyID: string, policies: OnyxCollection): boo * * We only return members without errors. Otherwise, the members with errors would immediately be removed before the user has a chance to read the error. */ -function getMemberAccountIDsForWorkspace(policyMembers: PolicyMembers | undefined, personalDetails: OnyxEntry): MemberEmailsToAccountIDs { - const members = policyMembers ?? {}; +function getMemberAccountIDsForWorkspace(employeeList: PolicyMembers | undefined, personalDetails: OnyxEntry): MemberEmailsToAccountIDs { + const members = employeeList ?? {}; const memberEmailsToAccountIDs: MemberEmailsToAccountIDs = {}; Object.keys(members).forEach((email) => { const member = members?.[email]; diff --git a/src/pages/workspace/WorkspaceMembersPage.tsx b/src/pages/workspace/WorkspaceMembersPage.tsx index 762e68f6befb..a49267f37b41 100644 --- a/src/pages/workspace/WorkspaceMembersPage.tsx +++ b/src/pages/workspace/WorkspaceMembersPage.tsx @@ -96,7 +96,7 @@ function WorkspaceMembersPage({personalDetails, invitedEmailsToAccountIDsDraft, const isFocused = useIsFocused(); const policyID = route.params.policyID; /** - * Get filtered personalDetails list with current policyMembers + * Get filtered personalDetails list with current employeeList */ const filterPersonalDetails = (members: OnyxEntry, details: OnyxEntry): PersonalDetailsList => Object.keys(members ?? {}).reduce((result, key) => { diff --git a/tests/actions/PolicyTest.ts b/tests/actions/PolicyTest.ts index dfb8ae81d104..1ca2edec0de7 100644 --- a/tests/actions/PolicyTest.ts +++ b/tests/actions/PolicyTest.ts @@ -4,7 +4,7 @@ import CONST from '@src/CONST'; import OnyxUpdateManager from '@src/libs/actions/OnyxUpdateManager'; import * as Policy from '@src/libs/actions/Policy'; import ONYXKEYS from '@src/ONYXKEYS'; -import type {PolicyMembers, Policy as PolicyType, Report, ReportAction, ReportActions} from '@src/types/onyx'; +import type {Policy as PolicyType, Report, ReportAction, ReportActions} from '@src/types/onyx'; import * as TestHelper from '../utils/TestHelper'; import waitForBatchedUpdates from '../utils/waitForBatchedUpdates'; @@ -61,20 +61,6 @@ describe('actions/Policy', () => { expect(policy?.isPolicyExpenseChatEnabled).toBe(true); expect(policy?.pendingAction).toBe(CONST.RED_BRICK_ROAD_PENDING_ACTION.ADD); - const policyMembers: OnyxCollection = await new Promise((resolve) => { - const connectionID = Onyx.connect({ - key: `${ONYXKEYS.COLLECTION.POLICY_MEMBERS}${policyID}`, - waitForCollectionCallback: true, - callback: (members) => { - Onyx.disconnect(connectionID); - resolve(members); - }, - }); - }); - - // check if the user was added as an admin to the policy - expect(policyMembers?.[ESH_ACCOUNT_ID]?.role).toBe(CONST.POLICY.ROLE.ADMIN); - let allReports: OnyxCollection = await new Promise((resolve) => { const connectionID = Onyx.connect({ key: ONYXKEYS.COLLECTION.REPORT, From a9c77e9e1f6b10333683addf134376f88e433f3c Mon Sep 17 00:00:00 2001 From: Yauheni Date: Sat, 6 Apr 2024 22:27:41 +0200 Subject: [PATCH 10/27] Fix ts issue --- tests/utils/LHNTestUtils.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/utils/LHNTestUtils.tsx b/tests/utils/LHNTestUtils.tsx index 50a495f39d51..b7a8aa4f1616 100644 --- a/tests/utils/LHNTestUtils.tsx +++ b/tests/utils/LHNTestUtils.tsx @@ -248,7 +248,7 @@ function getFakePolicy(id = '1', name = 'Workspace-Test-001'): Policy { owner: 'myuser@gmail.com', outputCurrency: 'BRL', avatar: '', - employeeList: [], + employeeList: {}, isPolicyExpenseChatEnabled: true, lastModified: '1697323926777105', autoReporting: true, From 1bc67dca62985794b58c360abef45110c32d5792 Mon Sep 17 00:00:00 2001 From: Yauheni Date: Sat, 6 Apr 2024 23:02:36 +0200 Subject: [PATCH 11/27] Refactor code and fix some issues --- src/libs/PolicyUtils.ts | 4 +-- src/pages/workspace/WorkspaceInvitePage.tsx | 2 +- src/pages/workspace/WorkspaceMembersPage.tsx | 28 ++++++++++++++++--- .../WorkspaceWorkflowsApproverPage.tsx | 2 +- .../workflows/WorkspaceWorkflowsPayerPage.tsx | 4 ++- 5 files changed, 31 insertions(+), 9 deletions(-) diff --git a/src/libs/PolicyUtils.ts b/src/libs/PolicyUtils.ts index 0bd7cd65b176..135a0f96d684 100644 --- a/src/libs/PolicyUtils.ts +++ b/src/libs/PolicyUtils.ts @@ -153,8 +153,8 @@ function getMemberAccountIDsForWorkspace(employeeList: PolicyMembers | undefined /** * Get login list that we should not show in the workspace invite options */ -function getIneligibleInvitees(policy: OnyxEntry): string[] { - const members = policy?.employeeList ?? {}; +function getIneligibleInvitees(employeeList?: PolicyMembers): string[] { + const members = employeeList ?? {}; const memberEmailsToExclude: string[] = [...CONST.EXPENSIFY_EMAILS]; Object.keys(members).forEach((email) => { const policyMember = members?.[email]; diff --git a/src/pages/workspace/WorkspaceInvitePage.tsx b/src/pages/workspace/WorkspaceInvitePage.tsx index a263db558632..108da0c4c3c8 100644 --- a/src/pages/workspace/WorkspaceInvitePage.tsx +++ b/src/pages/workspace/WorkspaceInvitePage.tsx @@ -91,7 +91,7 @@ function WorkspaceInvitePage({ useNetwork({onReconnect: openWorkspaceInvitePage}); - const excludedUsers = useMemo(() => PolicyUtils.getIneligibleInvitees(policy), [policy]); + const excludedUsers = useMemo(() => PolicyUtils.getIneligibleInvitees(policy?.employeeList), [policy?.employeeList]); useEffect(() => { const newUsersToInviteDict: Record = {}; diff --git a/src/pages/workspace/WorkspaceMembersPage.tsx b/src/pages/workspace/WorkspaceMembersPage.tsx index 1ccb838bdf7c..5b7631b69682 100644 --- a/src/pages/workspace/WorkspaceMembersPage.tsx +++ b/src/pages/workspace/WorkspaceMembersPage.tsx @@ -71,7 +71,7 @@ function invertObject(object: Record): Record { type MemberOption = Omit & {accountID: number}; function WorkspaceMembersPage({personalDetails, invitedEmailsToAccountIDsDraft, route, policy, session, currentUserPersonalDetails, isLoadingReportData = true}: WorkspaceMembersPageProps) { - const policyMemberEmailsToAccountIDs = PolicyUtils.getMemberAccountIDsForWorkspace(policy?.employeeList, personalDetails); + const policyMemberEmailsToAccountIDs = useMemo(() => PolicyUtils.getMemberAccountIDsForWorkspace(policy?.employeeList, personalDetails), [policy?.employeeList, personalDetails]); const styles = useThemeStyles(); const StyleUtils = useStyleUtils(); const [selectedEmployees, setSelectedEmployees] = useState([]); @@ -100,10 +100,10 @@ function WorkspaceMembersPage({personalDetails, invitedEmailsToAccountIDsDraft, */ const filterPersonalDetails = (members: OnyxEntry, details: OnyxEntry): PersonalDetailsList => Object.keys(members ?? {}).reduce((result, key) => { - if (details?.[key]) { + if (details?.[policyMemberEmailsToAccountIDs[key] ?? '']) { return { ...result, - [key]: details[policyMemberEmailsToAccountIDs[key] ?? ''], + [policyMemberEmailsToAccountIDs[key] ?? '']: details[policyMemberEmailsToAccountIDs[key] ?? ''], }; } return result; @@ -162,7 +162,7 @@ function WorkspaceMembersPage({personalDetails, invitedEmailsToAccountIDsDraft, ); }); // eslint-disable-next-line react-hooks/exhaustive-deps - }, [policy?.employeeList]); + }, [policy?.employeeList, policyMemberEmailsToAccountIDs]); useEffect(() => { const isReconnecting = prevIsOffline && !isOffline; @@ -171,12 +171,14 @@ function WorkspaceMembersPage({personalDetails, invitedEmailsToAccountIDsDraft, } getWorkspaceMembers(); }, [isOffline, prevIsOffline, getWorkspaceMembers]); + /** * Open the modal to invite a user */ const inviteUser = () => { Navigation.navigate(ROUTES.WORKSPACE_INVITE.getRoute(route.params.policyID)); }; + /** * Remove selected users from the workspace * Please see https://github.com/Expensify/App/blob/main/README.md#Security for more details @@ -193,6 +195,7 @@ function WorkspaceMembersPage({personalDetails, invitedEmailsToAccountIDsDraft, setSelectedEmployees([]); setRemoveMembersConfirmModalVisible(false); }; + /** * Show the modal to confirm removal of the selected members */ @@ -202,6 +205,7 @@ function WorkspaceMembersPage({personalDetails, invitedEmailsToAccountIDsDraft, } setRemoveMembersConfirmModalVisible(true); }; + /** * Add or remove all users passed from the selectedEmployees list */ @@ -218,6 +222,7 @@ function WorkspaceMembersPage({personalDetails, invitedEmailsToAccountIDsDraft, validateSelection(); }; + /** * Add user from the selectedEmployees list */ @@ -228,6 +233,7 @@ function WorkspaceMembersPage({personalDetails, invitedEmailsToAccountIDsDraft, }, [validateSelection], ); + /** * Remove user from the selectedEmployees list */ @@ -238,6 +244,7 @@ function WorkspaceMembersPage({personalDetails, invitedEmailsToAccountIDsDraft, }, [validateSelection], ); + /** * Toggle user from the selectedEmployees list */ @@ -256,6 +263,7 @@ function WorkspaceMembersPage({personalDetails, invitedEmailsToAccountIDsDraft, }, [selectedEmployees, addUser, removeUser], ); + /** Opens the member details page */ const openMemberDetails = useCallback( (item: MemberOption) => { @@ -268,6 +276,7 @@ function WorkspaceMembersPage({personalDetails, invitedEmailsToAccountIDsDraft, }, [isPolicyAdmin, policy, policyID, route.params.policyID], ); + /** * Dismisses the errors on one item */ @@ -281,6 +290,7 @@ function WorkspaceMembersPage({personalDetails, invitedEmailsToAccountIDsDraft, }, [route.params.policyID], ); + /** * Check if the policy member is deleted from the workspace */ @@ -288,6 +298,7 @@ function WorkspaceMembersPage({personalDetails, invitedEmailsToAccountIDsDraft, (policyMember: PolicyMember): boolean => !isOffline && policyMember.pendingAction === CONST.RED_BRICK_ROAD_PENDING_ACTION.DELETE && isEmptyObject(policyMember.errors), [isOffline], ); + const policyOwner = policy?.owner; const currentUserLogin = currentUserPersonalDetails.login; const invitedPrimaryToSecondaryLogins = invertObject(policy?.primaryLoginsInvited ?? {}); @@ -377,7 +388,9 @@ function WorkspaceMembersPage({personalDetails, invitedEmailsToAccountIDsDraft, styles.textStrong, translate, ]); + const data = useMemo(() => getUsers(), [getUsers]); + useEffect(() => { if (!isFocused) { return; @@ -412,6 +425,7 @@ function WorkspaceMembersPage({personalDetails, invitedEmailsToAccountIDsDraft, )} ); + const getCustomListHeader = () => { const header = ( @@ -428,6 +442,7 @@ function WorkspaceMembersPage({personalDetails, invitedEmailsToAccountIDsDraft, } return {header}; }; + const changeUserRole = (role: typeof CONST.POLICY.ROLE.ADMIN | typeof CONST.POLICY.ROLE.USER) => { if (!isEmptyObject(errors)) { return; @@ -438,6 +453,7 @@ function WorkspaceMembersPage({personalDetails, invitedEmailsToAccountIDsDraft, Policy.updateWorkspaceMembersRole(route.params.policyID, accountIDsToUpdate, role); setSelectedEmployees([]); }; + const getBulkActionsButtonOptions = () => { const options: Array> = [ { @@ -469,6 +485,7 @@ function WorkspaceMembersPage({personalDetails, invitedEmailsToAccountIDsDraft, } return options; }; + const getHeaderButtons = () => { if (!isPolicyAdmin) { return null; @@ -500,6 +517,7 @@ function WorkspaceMembersPage({personalDetails, invitedEmailsToAccountIDsDraft, ); }; + return ( ); } + WorkspaceMembersPage.displayName = 'WorkspaceMembersPage'; + export default withCurrentUserPersonalDetails( withPolicyAndFullscreenLoading( withOnyx({ diff --git a/src/pages/workspace/workflows/WorkspaceWorkflowsApproverPage.tsx b/src/pages/workspace/workflows/WorkspaceWorkflowsApproverPage.tsx index d642960255c5..230c3595bf4b 100644 --- a/src/pages/workspace/workflows/WorkspaceWorkflowsApproverPage.tsx +++ b/src/pages/workspace/workflows/WorkspaceWorkflowsApproverPage.tsx @@ -65,7 +65,7 @@ function WorkspaceWorkflowsApproverPage({policy, personalDetails, isLoadingRepor return; } - const accountID = Number(policyMemberEmailsToAccountIDs[email] || ''); + const accountID = Number(policyMemberEmailsToAccountIDs[email] ?? ''); const details = personalDetails?.[accountID]; if (!details) { diff --git a/src/pages/workspace/workflows/WorkspaceWorkflowsPayerPage.tsx b/src/pages/workspace/workflows/WorkspaceWorkflowsPayerPage.tsx index d0d12dad3fdf..51d956a7614d 100644 --- a/src/pages/workspace/workflows/WorkspaceWorkflowsPayerPage.tsx +++ b/src/pages/workspace/workflows/WorkspaceWorkflowsPayerPage.tsx @@ -60,8 +60,10 @@ function WorkspaceWorkflowsPayerPage({route, policy, personalDetails, isLoadingR const policyAdminDetails: MemberOption[] = []; const authorizedPayerDetails: MemberOption[] = []; + const policyMemberEmailsToAccountIDs = PolicyUtils.getMemberAccountIDsForWorkspace(policy?.employeeList, personalDetails); + Object.entries(policy?.employeeList ?? {}).forEach(([email, policyMember]) => { - const accountID = Object.values(personalDetails ?? {}).find((details) => details?.login === email)?.accountID ?? 0; + const accountID = policyMemberEmailsToAccountIDs?.[email] ?? ''; const details = personalDetails?.[accountID]; if (!details) { Log.hmmm(`[WorkspaceMembersPage] no personal details found for policy member with accountID: ${accountID}`); From afa82392be784a00edf3cbbf1683f160de223dfb Mon Sep 17 00:00:00 2001 From: Yauheni Date: Mon, 8 Apr 2024 09:41:23 +0200 Subject: [PATCH 12/27] Update PolicyMembersUtils --- src/libs/PolicyMembersUtils.ts | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/libs/PolicyMembersUtils.ts b/src/libs/PolicyMembersUtils.ts index 59d1bff22597..43464fca1a18 100644 --- a/src/libs/PolicyMembersUtils.ts +++ b/src/libs/PolicyMembersUtils.ts @@ -5,7 +5,7 @@ import type {PersonalDetailsList, Policy} from '@src/types/onyx'; import {getCurrentUserAccountID} from './actions/Report'; import {getPolicyMembersByIdWithoutCurrentUser} from './PolicyUtils'; -let policies: OnyxCollection; +let policies: OnyxCollection = {}; Onyx.connect({ key: ONYXKEYS.COLLECTION.POLICY, waitForCollectionCallback: true, @@ -15,9 +15,7 @@ Onyx.connect({ let allPersonalDetails: OnyxEntry = {}; Onyx.connect({ key: ONYXKEYS.PERSONAL_DETAILS_LIST, - callback: (val) => { - allPersonalDetails = val; - }, + callback: (val) => (allPersonalDetails = val), }); function getPolicyMemberAccountIDs(policyID?: string) { From d682d3278e13430f64554640b188369a679d0191 Mon Sep 17 00:00:00 2001 From: Yauheni Date: Mon, 8 Apr 2024 11:50:12 +0200 Subject: [PATCH 13/27] Fix bug with selected item on WorkspaceMemberDetailsRoleSelectionPage --- .../members/WorkspaceMemberDetailsRoleSelectionPage.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pages/workspace/members/WorkspaceMemberDetailsRoleSelectionPage.tsx b/src/pages/workspace/members/WorkspaceMemberDetailsRoleSelectionPage.tsx index 36f24b8922da..c591d47975b7 100644 --- a/src/pages/workspace/members/WorkspaceMemberDetailsRoleSelectionPage.tsx +++ b/src/pages/workspace/members/WorkspaceMemberDetailsRoleSelectionPage.tsx @@ -47,7 +47,7 @@ function WorkspaceMemberDetailsRoleSelectionPage({route, personalDetails, policy { value: CONST.POLICY.ROLE.USER, text: translate('common.member'), - isSelected: member?.role === CONST.POLICY.ROLE.USER, + isSelected: member?.role !== CONST.POLICY.ROLE.ADMIN, keyForList: CONST.POLICY.ROLE.USER, }, ]; From 657e5ec3264c3083345fab1591696af55273fc7d Mon Sep 17 00:00:00 2001 From: Yauheni Date: Mon, 8 Apr 2024 18:26:40 +0200 Subject: [PATCH 14/27] Fix comments --- .../AppNavigator/ReportScreenIDSetter.ts | 2 +- src/libs/PolicyMembersUtils.ts | 16 +++++----------- src/libs/PolicyUtils.ts | 11 ++++++----- src/libs/actions/Policy.ts | 2 +- src/pages/workspace/WorkspaceInvitePage.tsx | 3 +-- src/pages/workspace/WorkspaceMembersPage.tsx | 12 ++++++------ .../workflows/WorkspaceWorkflowsApproverPage.tsx | 2 +- .../workflows/WorkspaceWorkflowsPayerPage.tsx | 2 +- 8 files changed, 22 insertions(+), 28 deletions(-) diff --git a/src/libs/Navigation/AppNavigator/ReportScreenIDSetter.ts b/src/libs/Navigation/AppNavigator/ReportScreenIDSetter.ts index a9fbf19b4477..56efcdcf75e3 100644 --- a/src/libs/Navigation/AppNavigator/ReportScreenIDSetter.ts +++ b/src/libs/Navigation/AppNavigator/ReportScreenIDSetter.ts @@ -73,7 +73,7 @@ function ReportScreenIDSetter({route, reports, policies, navigation, isFirstTime return; } - const policyMemberAccountIDs = getPolicyMembersByIdWithoutCurrentUser(policies, personalDetails, activeWorkspaceID, accountID); + const policyMemberAccountIDs = getPolicyMembersByIdWithoutCurrentUser(policies, activeWorkspaceID, accountID); // If there is no reportID in route, try to find last accessed and use it for setParams const reportID = getLastAccessedReportID( diff --git a/src/libs/PolicyMembersUtils.ts b/src/libs/PolicyMembersUtils.ts index 43464fca1a18..f826f4fd257a 100644 --- a/src/libs/PolicyMembersUtils.ts +++ b/src/libs/PolicyMembersUtils.ts @@ -1,21 +1,15 @@ -import type {OnyxCollection, OnyxEntry} from 'react-native-onyx'; +import type {OnyxCollection} from 'react-native-onyx'; import Onyx from 'react-native-onyx'; import ONYXKEYS from '@src/ONYXKEYS'; -import type {PersonalDetailsList, Policy} from '@src/types/onyx'; +import type {Policy} from '@src/types/onyx'; import {getCurrentUserAccountID} from './actions/Report'; import {getPolicyMembersByIdWithoutCurrentUser} from './PolicyUtils'; -let policies: OnyxCollection = {}; +let allPolicies: OnyxCollection = {}; Onyx.connect({ key: ONYXKEYS.COLLECTION.POLICY, waitForCollectionCallback: true, - callback: (value) => (policies = value), -}); - -let allPersonalDetails: OnyxEntry = {}; -Onyx.connect({ - key: ONYXKEYS.PERSONAL_DETAILS_LIST, - callback: (val) => (allPersonalDetails = val), + callback: (value) => (allPolicies = value), }); function getPolicyMemberAccountIDs(policyID?: string) { @@ -25,7 +19,7 @@ function getPolicyMemberAccountIDs(policyID?: string) { const currentUserAccountID = getCurrentUserAccountID(); - return getPolicyMembersByIdWithoutCurrentUser(policies, allPersonalDetails, policyID, currentUserAccountID); + return getPolicyMembersByIdWithoutCurrentUser(allPolicies, policyID, currentUserAccountID); } export default getPolicyMemberAccountIDs; diff --git a/src/libs/PolicyUtils.ts b/src/libs/PolicyUtils.ts index 135a0f96d684..643a13f114ff 100644 --- a/src/libs/PolicyUtils.ts +++ b/src/libs/PolicyUtils.ts @@ -4,13 +4,14 @@ import type {ValueOf} from 'type-fest'; import CONST from '@src/CONST'; import ONYXKEYS from '@src/ONYXKEYS'; import ROUTES from '@src/ROUTES'; -import type {PersonalDetailsList, Policy, PolicyCategories, PolicyMembers, PolicyTagList, PolicyTags, TaxRate} from '@src/types/onyx'; +import type { Policy, PolicyCategories, PolicyMembers, PolicyTagList, PolicyTags, TaxRate} from '@src/types/onyx'; import type {PolicyFeatureName, Rate} from '@src/types/onyx/Policy'; import type {EmptyObject} from '@src/types/utils/EmptyObject'; import {isEmptyObject} from '@src/types/utils/EmptyObject'; import getPolicyIDFromState from './Navigation/getPolicyIDFromState'; import Navigation, {navigationRef} from './Navigation/Navigation'; import type {RootStackParamList, State} from './Navigation/types'; +import {getPersonalDetailByEmail} from './PersonalDetailsUtils'; type MemberEmailsToAccountIDs = Record; @@ -133,7 +134,7 @@ const isPolicyMember = (policyID: string, policies: OnyxCollection): boo * * We only return members without errors. Otherwise, the members with errors would immediately be removed before the user has a chance to read the error. */ -function getMemberAccountIDsForWorkspace(employeeList: PolicyMembers | undefined, personalDetails: OnyxEntry): MemberEmailsToAccountIDs { +function getMemberAccountIDsForWorkspace(employeeList: PolicyMembers | undefined): MemberEmailsToAccountIDs { const members = employeeList ?? {}; const memberEmailsToAccountIDs: MemberEmailsToAccountIDs = {}; Object.keys(members).forEach((email) => { @@ -141,7 +142,7 @@ function getMemberAccountIDsForWorkspace(employeeList: PolicyMembers | undefined if (Object.keys(member?.errors ?? {})?.length > 0) { return; } - const personalDetail = Object.values(personalDetails ?? {})?.find((details) => details?.login === email); + const personalDetail = getPersonalDetailByEmail(email); if (!personalDetail?.login) { return; } @@ -277,9 +278,9 @@ function getPathWithoutPolicyID(path: string) { return path.replace(CONST.REGEX.PATH_WITHOUT_POLICY_ID, '/'); } -function getPolicyMembersByIdWithoutCurrentUser(policies: OnyxCollection, personalDetails: OnyxEntry, currentPolicyID?: string, currentUserAccountID?: number) { +function getPolicyMembersByIdWithoutCurrentUser(policies: OnyxCollection, currentPolicyID?: string, currentUserAccountID?: number) { const policy = policies?.[`${ONYXKEYS.COLLECTION.POLICY}${currentPolicyID}`] ?? null; - const policyMemberEmailsToAccountIDs = getMemberAccountIDsForWorkspace(policy?.employeeList, personalDetails); + const policyMemberEmailsToAccountIDs = getMemberAccountIDsForWorkspace(policy?.employeeList); return Object.values(policyMemberEmailsToAccountIDs) .map((policyMemberAccountID) => Number(policyMemberAccountID)) .filter((policyMemberAccountID) => policyMemberAccountID !== currentUserAccountID); diff --git a/src/libs/actions/Policy.ts b/src/libs/actions/Policy.ts index 19a47d9663a7..af685c517a57 100644 --- a/src/libs/actions/Policy.ts +++ b/src/libs/actions/Policy.ts @@ -1275,7 +1275,7 @@ function createPolicyExpenseChats(policyID: string, invitedEmailsToAccountIDs: I * Please see https://github.com/Expensify/App/blob/main/README.md#Security for more details */ function addMembersToWorkspace(invitedEmailsToAccountIDs: InvitedEmailsToAccountIDs, welcomeNote: string, policyID: string) { - const onyxKey = `${ONYXKEYS.COLLECTION.POLICY}${policyID}` as const; + const policyKey = `${ONYXKEYS.COLLECTION.POLICY}${policyID}` as const; const logins = Object.keys(invitedEmailsToAccountIDs).map((memberLogin) => PhoneNumber.addSMSDomainIfPhoneNumber(memberLogin)); const accountIDs = Object.values(invitedEmailsToAccountIDs); diff --git a/src/pages/workspace/WorkspaceInvitePage.tsx b/src/pages/workspace/WorkspaceInvitePage.tsx index 108da0c4c3c8..7ba9cf10bba0 100644 --- a/src/pages/workspace/WorkspaceInvitePage.tsx +++ b/src/pages/workspace/WorkspaceInvitePage.tsx @@ -55,7 +55,6 @@ type WorkspaceInvitePageProps = WithPolicyAndFullscreenLoadingProps & function WorkspaceInvitePage({ route, - personalDetails: personalDetailsProp, betas, invitedEmailsToAccountIDsDraft, policy, @@ -69,7 +68,7 @@ function WorkspaceInvitePage({ const [personalDetails, setPersonalDetails] = useState([]); const [usersToInvite, setUsersToInvite] = useState([]); const openWorkspaceInvitePage = () => { - const policyMemberEmailsToAccountIDs = PolicyUtils.getMemberAccountIDsForWorkspace(policy?.employeeList, personalDetailsProp); + const policyMemberEmailsToAccountIDs = PolicyUtils.getMemberAccountIDsForWorkspace(policy?.employeeList); Policy.openWorkspaceInvitePage(route.params.policyID, Object.keys(policyMemberEmailsToAccountIDs)); }; const {options, areOptionsInitialized} = useOptionsList({ diff --git a/src/pages/workspace/WorkspaceMembersPage.tsx b/src/pages/workspace/WorkspaceMembersPage.tsx index 5b7631b69682..5458079f5d92 100644 --- a/src/pages/workspace/WorkspaceMembersPage.tsx +++ b/src/pages/workspace/WorkspaceMembersPage.tsx @@ -71,7 +71,7 @@ function invertObject(object: Record): Record { type MemberOption = Omit & {accountID: number}; function WorkspaceMembersPage({personalDetails, invitedEmailsToAccountIDsDraft, route, policy, session, currentUserPersonalDetails, isLoadingReportData = true}: WorkspaceMembersPageProps) { - const policyMemberEmailsToAccountIDs = useMemo(() => PolicyUtils.getMemberAccountIDsForWorkspace(policy?.employeeList, personalDetails), [policy?.employeeList, personalDetails]); + const policyMemberEmailsToAccountIDs = useMemo(() => PolicyUtils.getMemberAccountIDsForWorkspace(policy?.employeeList), [policy?.employeeList]); const styles = useThemeStyles(); const StyleUtils = useStyleUtils(); const [selectedEmployees, setSelectedEmployees] = useState([]); @@ -112,8 +112,8 @@ function WorkspaceMembersPage({personalDetails, invitedEmailsToAccountIDsDraft, * Get members for the current workspace */ const getWorkspaceMembers = useCallback(() => { - Policy.openWorkspaceMembersPage(route.params.policyID, Object.keys(PolicyUtils.getMemberAccountIDsForWorkspace(policy?.employeeList, personalDetails))); - }, [route.params.policyID, policy?.employeeList, personalDetails]); + Policy.openWorkspaceMembersPage(route.params.policyID, Object.keys(PolicyUtils.getMemberAccountIDsForWorkspace(policy?.employeeList))); + }, [route.params.policyID, policy?.employeeList]); /** * Check if the current selection includes members that cannot be removed @@ -157,7 +157,7 @@ function WorkspaceMembersPage({personalDetails, invitedEmailsToAccountIDsDraft, return res?.accountID ?? id; }); // This is an equivalent of the lodash intersection function. The reduce method below is used to filter the items that exist in both arrays. - return [prevSelectedElements, Object.values(PolicyUtils.getMemberAccountIDsForWorkspace(policy?.employeeList, personalDetails))].reduce((prev, members) => + return [prevSelectedElements, Object.values(PolicyUtils.getMemberAccountIDsForWorkspace(policy?.employeeList))].reduce((prev, members) => prev.filter((item) => members.includes(item)), ); }); @@ -465,7 +465,7 @@ function WorkspaceMembersPage({personalDetails, invitedEmailsToAccountIDsDraft, ]; if (PolicyUtils.isPaidGroupPolicy(policy)) { - if (selectedEmployees.find((employee) => policy?.employeeList?.[policyMemberEmailsToAccountIDs[employee]]?.role === CONST.POLICY.ROLE.ADMIN)) { + if (selectedEmployees.find((employeeEmail) => policy?.employeeList?.[policyMemberEmailsToAccountIDs[employeeEmail]]?.role === CONST.POLICY.ROLE.ADMIN)) { options.push({ text: translate('workspace.people.makeMember'), value: CONST.POLICY.MEMBERS_BULK_ACTION_TYPES.MAKE_MEMBER, @@ -474,7 +474,7 @@ function WorkspaceMembersPage({personalDetails, invitedEmailsToAccountIDsDraft, }); } - if (selectedEmployees.find((employee) => policy?.employeeList?.[policyMemberEmailsToAccountIDs[employee]]?.role === CONST.POLICY.ROLE.USER)) { + if (selectedEmployees.find((employeeEmail) => policy?.employeeList?.[policyMemberEmailsToAccountIDs[employeeEmail]]?.role === CONST.POLICY.ROLE.USER)) { options.push({ text: translate('workspace.people.makeAdmin'), value: CONST.POLICY.MEMBERS_BULK_ACTION_TYPES.MAKE_ADMIN, diff --git a/src/pages/workspace/workflows/WorkspaceWorkflowsApproverPage.tsx b/src/pages/workspace/workflows/WorkspaceWorkflowsApproverPage.tsx index 230c3595bf4b..ccf446ab077b 100644 --- a/src/pages/workspace/workflows/WorkspaceWorkflowsApproverPage.tsx +++ b/src/pages/workspace/workflows/WorkspaceWorkflowsApproverPage.tsx @@ -58,7 +58,7 @@ function WorkspaceWorkflowsApproverPage({policy, personalDetails, isLoadingRepor const policyMemberDetails: MemberOption[] = []; const approverDetails: MemberOption[] = []; - const policyMemberEmailsToAccountIDs = PolicyUtils.getMemberAccountIDsForWorkspace(policy?.employeeList, personalDetails); + const policyMemberEmailsToAccountIDs = PolicyUtils.getMemberAccountIDsForWorkspace(policy?.employeeList); Object.entries(policy?.employeeList ?? {}).forEach(([email, policyMember]) => { if (isDeletedPolicyMember(policyMember)) { diff --git a/src/pages/workspace/workflows/WorkspaceWorkflowsPayerPage.tsx b/src/pages/workspace/workflows/WorkspaceWorkflowsPayerPage.tsx index 51d956a7614d..6691fc7f002c 100644 --- a/src/pages/workspace/workflows/WorkspaceWorkflowsPayerPage.tsx +++ b/src/pages/workspace/workflows/WorkspaceWorkflowsPayerPage.tsx @@ -60,7 +60,7 @@ function WorkspaceWorkflowsPayerPage({route, policy, personalDetails, isLoadingR const policyAdminDetails: MemberOption[] = []; const authorizedPayerDetails: MemberOption[] = []; - const policyMemberEmailsToAccountIDs = PolicyUtils.getMemberAccountIDsForWorkspace(policy?.employeeList, personalDetails); + const policyMemberEmailsToAccountIDs = PolicyUtils.getMemberAccountIDsForWorkspace(policy?.employeeList); Object.entries(policy?.employeeList ?? {}).forEach(([email, policyMember]) => { const accountID = policyMemberEmailsToAccountIDs?.[email] ?? ''; From 57ae55de808f961e0e4c965f5009a85100cde179 Mon Sep 17 00:00:00 2001 From: Yauheni Date: Mon, 8 Apr 2024 18:34:57 +0200 Subject: [PATCH 15/27] Fix eslint issues --- src/libs/actions/Policy.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/libs/actions/Policy.ts b/src/libs/actions/Policy.ts index af685c517a57..3d7b5e667b4b 100644 --- a/src/libs/actions/Policy.ts +++ b/src/libs/actions/Policy.ts @@ -1300,7 +1300,7 @@ function addMembersToWorkspace(invitedEmailsToAccountIDs: InvitedEmailsToAccount const optimisticData: OnyxUpdate[] = [ { onyxMethod: Onyx.METHOD.MERGE, - key: onyxKey, + key: policyKey, // Convert to object with each key containing {pendingAction: ‘add’} value: { @@ -1315,7 +1315,7 @@ function addMembersToWorkspace(invitedEmailsToAccountIDs: InvitedEmailsToAccount const successData: OnyxUpdate[] = [ { onyxMethod: Onyx.METHOD.MERGE, - key: onyxKey, + key: policyKey, value: { employeeList: successMembersState, }, @@ -1328,7 +1328,7 @@ function addMembersToWorkspace(invitedEmailsToAccountIDs: InvitedEmailsToAccount const failureData: OnyxUpdate[] = [ { onyxMethod: Onyx.METHOD.MERGE, - key: onyxKey, + key: policyKey, // Convert to object with each key containing the error. We don’t // need to remove the members since that is handled by onClose of OfflineWithFeedback. From fd47bb46c2c295d95ba1145b9a586235eeb709f6 Mon Sep 17 00:00:00 2001 From: Yauheni Date: Mon, 8 Apr 2024 18:54:29 +0200 Subject: [PATCH 16/27] Fix ts and eslint issues --- src/libs/PolicyUtils.ts | 2 +- src/pages/workspace/WorkspaceInvitePage.tsx | 9 +-------- tests/perf-test/PolicyUtils.perf-test.ts | 12 ++++-------- 3 files changed, 6 insertions(+), 17 deletions(-) diff --git a/src/libs/PolicyUtils.ts b/src/libs/PolicyUtils.ts index 643a13f114ff..45539796a7bd 100644 --- a/src/libs/PolicyUtils.ts +++ b/src/libs/PolicyUtils.ts @@ -4,7 +4,7 @@ import type {ValueOf} from 'type-fest'; import CONST from '@src/CONST'; import ONYXKEYS from '@src/ONYXKEYS'; import ROUTES from '@src/ROUTES'; -import type { Policy, PolicyCategories, PolicyMembers, PolicyTagList, PolicyTags, TaxRate} from '@src/types/onyx'; +import type {Policy, PolicyCategories, PolicyMembers, PolicyTagList, PolicyTags, TaxRate} from '@src/types/onyx'; import type {PolicyFeatureName, Rate} from '@src/types/onyx/Policy'; import type {EmptyObject} from '@src/types/utils/EmptyObject'; import {isEmptyObject} from '@src/types/utils/EmptyObject'; diff --git a/src/pages/workspace/WorkspaceInvitePage.tsx b/src/pages/workspace/WorkspaceInvitePage.tsx index 7ba9cf10bba0..660f7b2e1ed8 100644 --- a/src/pages/workspace/WorkspaceInvitePage.tsx +++ b/src/pages/workspace/WorkspaceInvitePage.tsx @@ -53,14 +53,7 @@ type WorkspaceInvitePageProps = WithPolicyAndFullscreenLoadingProps & WorkspaceInvitePageOnyxProps & StackScreenProps; -function WorkspaceInvitePage({ - route, - betas, - invitedEmailsToAccountIDsDraft, - policy, - isLoadingReportData = true, - didScreenTransitionEnd, -}: WorkspaceInvitePageProps) { +function WorkspaceInvitePage({route, betas, invitedEmailsToAccountIDsDraft, policy, isLoadingReportData = true, didScreenTransitionEnd}: WorkspaceInvitePageProps) { const styles = useThemeStyles(); const {translate} = useLocalize(); const [searchTerm, setSearchTerm] = useState(''); diff --git a/tests/perf-test/PolicyUtils.perf-test.ts b/tests/perf-test/PolicyUtils.perf-test.ts index 98403b310f25..4f882ae9f057 100644 --- a/tests/perf-test/PolicyUtils.perf-test.ts +++ b/tests/perf-test/PolicyUtils.perf-test.ts @@ -1,33 +1,29 @@ import {measureFunction} from 'reassure'; import {getMemberAccountIDsForWorkspace} from '@libs/PolicyUtils'; -import type {PersonalDetails, PolicyMember} from '@src/types/onyx'; import createCollection from '../utils/collections/createCollection'; -import createPersonalDetails from '../utils/collections/personalDetails'; import createRandomPolicyMember from '../utils/collections/policyMembers'; describe('PolicyUtils', () => { describe('getMemberAccountIDsForWorkspace', () => { test('500 policy members with personal details', async () => { - const policyMembers = createCollection( + const policyMembers = createCollection( (_, index) => index, () => createRandomPolicyMember(), ); - const personalDetails = createCollection((_, index) => index, createPersonalDetails); - await measureFunction(() => getMemberAccountIDsForWorkspace(policyMembers, personalDetails)); + await measureFunction(() => getMemberAccountIDsForWorkspace(policyMembers)); }); test('500 policy members with errors and personal details', async () => { - const policyMembers = createCollection( + const policyMembers = createCollection( (_, index) => index, () => ({ ...createRandomPolicyMember(), errors: {error: 'Error message'}, }), ); - const personalDetails = createCollection((_, index) => index, createPersonalDetails); - await measureFunction(() => getMemberAccountIDsForWorkspace(policyMembers, personalDetails)); + await measureFunction(() => getMemberAccountIDsForWorkspace(policyMembers)); }); }); }); From 9809d4503db916deb65d0e73fb2f076852954b38 Mon Sep 17 00:00:00 2001 From: Yauheni Date: Tue, 9 Apr 2024 20:28:12 +0200 Subject: [PATCH 17/27] Fix bug and rename policyMembers --- src/ONYXKEYS.ts | 2 +- .../AppNavigator/ReportScreenIDSetter.ts | 4 +- src/libs/Navigation/dismissModalWithReport.ts | 4 +- ...bscribeToReportCommentPushNotifications.ts | 6 +-- ...ersUtils.ts => PolicyEmployeeListUtils.ts} | 8 ++-- src/libs/PolicyUtils.ts | 22 +++++------ src/libs/ReportUtils.ts | 4 +- src/libs/actions/Policy.ts | 14 +++---- src/libs/actions/Report.ts | 6 +-- src/pages/ReportDetailsPage.tsx | 12 +++--- src/pages/RoomInvitePage.tsx | 4 +- src/pages/RoomMembersPage.tsx | 6 +-- src/pages/home/HeaderView.tsx | 6 +-- src/pages/home/sidebar/SidebarLinksData.js | 4 +- src/pages/workspace/WorkspaceInvitePage.tsx | 2 +- src/pages/workspace/WorkspaceMembersPage.tsx | 38 ++++++++++--------- .../WorkspaceWorkflowsApproverPage.tsx | 28 +++++++------- .../workflows/WorkspaceWorkflowsPayerPage.tsx | 20 +++++----- src/types/onyx/Policy.ts | 2 +- .../{PolicyMember.ts => PolicyEmployee.ts} | 8 ++-- src/types/onyx/index.ts | 8 ++-- tests/perf-test/PolicyUtils.perf-test.ts | 14 +++---- tests/utils/collections/policyEmployeeList.ts | 9 +++++ tests/utils/collections/policyMembers.ts | 9 ----- 24 files changed, 122 insertions(+), 118 deletions(-) rename src/libs/{PolicyMembersUtils.ts => PolicyEmployeeListUtils.ts} (65%) rename src/types/onyx/{PolicyMember.ts => PolicyEmployee.ts} (73%) create mode 100644 tests/utils/collections/policyEmployeeList.ts delete mode 100644 tests/utils/collections/policyMembers.ts diff --git a/src/ONYXKEYS.ts b/src/ONYXKEYS.ts index bc3b2da49ecd..6df9a534d689 100755 --- a/src/ONYXKEYS.ts +++ b/src/ONYXKEYS.ts @@ -517,7 +517,7 @@ type OnyxCollectionValuesMapping = { [ONYXKEYS.COLLECTION.POLICY_CATEGORIES]: OnyxTypes.PolicyCategories; [ONYXKEYS.COLLECTION.POLICY_TAGS]: OnyxTypes.PolicyTagList; [ONYXKEYS.COLLECTION.POLICY_RECENTLY_USED_CATEGORIES]: OnyxTypes.RecentlyUsedCategories; - [ONYXKEYS.COLLECTION.DEPRECATED_POLICY_MEMBER_LIST]: OnyxTypes.PolicyMembers; + [ONYXKEYS.COLLECTION.DEPRECATED_POLICY_MEMBER_LIST]: OnyxTypes.PolicyEmployeeList; [ONYXKEYS.COLLECTION.WORKSPACE_INVITE_MEMBERS_DRAFT]: OnyxTypes.InvitedEmailsToAccountIDs; [ONYXKEYS.COLLECTION.WORKSPACE_INVITE_MESSAGE_DRAFT]: string; [ONYXKEYS.COLLECTION.REPORT]: OnyxTypes.Report; diff --git a/src/libs/Navigation/AppNavigator/ReportScreenIDSetter.ts b/src/libs/Navigation/AppNavigator/ReportScreenIDSetter.ts index 56efcdcf75e3..5407a451682a 100644 --- a/src/libs/Navigation/AppNavigator/ReportScreenIDSetter.ts +++ b/src/libs/Navigation/AppNavigator/ReportScreenIDSetter.ts @@ -3,7 +3,7 @@ import type {OnyxCollection, OnyxEntry} from 'react-native-onyx'; import {withOnyx} from 'react-native-onyx'; import useActiveWorkspace from '@hooks/useActiveWorkspace'; import usePermissions from '@hooks/usePermissions'; -import {getPolicyMembersByIdWithoutCurrentUser} from '@libs/PolicyUtils'; +import {getPolicyEmployeeListByIdWithoutCurrentUser} from '@libs/PolicyUtils'; import * as ReportUtils from '@libs/ReportUtils'; import ONYXKEYS from '@src/ONYXKEYS'; import type {PersonalDetailsList, Policy, Report, ReportMetadata} from '@src/types/onyx'; @@ -73,7 +73,7 @@ function ReportScreenIDSetter({route, reports, policies, navigation, isFirstTime return; } - const policyMemberAccountIDs = getPolicyMembersByIdWithoutCurrentUser(policies, activeWorkspaceID, accountID); + const policyMemberAccountIDs = getPolicyEmployeeListByIdWithoutCurrentUser(policies, activeWorkspaceID, accountID); // If there is no reportID in route, try to find last accessed and use it for setParams const reportID = getLastAccessedReportID( diff --git a/src/libs/Navigation/dismissModalWithReport.ts b/src/libs/Navigation/dismissModalWithReport.ts index 2622cc2b9855..c0405c2c9da0 100644 --- a/src/libs/Navigation/dismissModalWithReport.ts +++ b/src/libs/Navigation/dismissModalWithReport.ts @@ -3,7 +3,7 @@ import type {NavigationContainerRef} from '@react-navigation/native'; import {StackActions} from '@react-navigation/native'; import {findLastIndex} from 'lodash'; import Log from '@libs/Log'; -import getPolicyMemberAccountIDs from '@libs/PolicyMembersUtils'; +import getPolicyEmployeeAccountIDs from '@libs/PolicyEmployeeListUtils'; import {doesReportBelongToWorkspace} from '@libs/ReportUtils'; import NAVIGATORS from '@src/NAVIGATORS'; import ROUTES from '@src/ROUTES'; @@ -47,7 +47,7 @@ function dismissModalWithReport(targetReport: Report | EmptyObject, navigationRe if (targetReport.reportID !== getTopmostReportId(state)) { const reportState = getStateFromPath(ROUTES.REPORT_WITH_ID.getRoute(targetReport.reportID)); const policyID = getPolicyIDFromState(state as State); - const policyMemberAccountIDs = getPolicyMemberAccountIDs(policyID); + const policyMemberAccountIDs = getPolicyEmployeeAccountIDs(policyID); const shouldOpenAllWorkspace = isEmptyObject(targetReport) ? true : !doesReportBelongToWorkspace(targetReport, policyMemberAccountIDs, policyID); if (shouldOpenAllWorkspace) { diff --git a/src/libs/Notification/PushNotification/subscribeToReportCommentPushNotifications.ts b/src/libs/Notification/PushNotification/subscribeToReportCommentPushNotifications.ts index 71f68d69acc7..7b8340c76c73 100644 --- a/src/libs/Notification/PushNotification/subscribeToReportCommentPushNotifications.ts +++ b/src/libs/Notification/PushNotification/subscribeToReportCommentPushNotifications.ts @@ -2,7 +2,7 @@ import Onyx from 'react-native-onyx'; import * as OnyxUpdates from '@libs/actions/OnyxUpdates'; import Log from '@libs/Log'; import Navigation from '@libs/Navigation/Navigation'; -import getPolicyMemberAccountIDs from '@libs/PolicyMembersUtils'; +import getPolicyEmployeeAccountIDs from '@libs/PolicyEmployeeListUtils'; import {extractPolicyIDFromPath} from '@libs/PolicyUtils'; import {doesReportBelongToWorkspace, getReport} from '@libs/ReportUtils'; import Visibility from '@libs/Visibility'; @@ -60,9 +60,9 @@ export default function subscribeToReportCommentPushNotifications() { const policyID = lastVisitedPath && extractPolicyIDFromPath(lastVisitedPath); const report = getReport(reportID.toString()); - const policyMembersAccountIDs = policyID ? getPolicyMemberAccountIDs(policyID) : []; + const policyEmployeeAccountIDs = policyID ? getPolicyEmployeeAccountIDs(policyID) : []; - const reportBelongsToWorkspace = policyID && !isEmptyObject(report) && doesReportBelongToWorkspace(report, policyMembersAccountIDs, policyID); + const reportBelongsToWorkspace = policyID && !isEmptyObject(report) && doesReportBelongToWorkspace(report, policyEmployeeAccountIDs, policyID); Log.info('[PushNotification] onSelected() - called', false, {reportID, reportActionID}); Navigation.isNavigationReady() diff --git a/src/libs/PolicyMembersUtils.ts b/src/libs/PolicyEmployeeListUtils.ts similarity index 65% rename from src/libs/PolicyMembersUtils.ts rename to src/libs/PolicyEmployeeListUtils.ts index f826f4fd257a..305ffda87e28 100644 --- a/src/libs/PolicyMembersUtils.ts +++ b/src/libs/PolicyEmployeeListUtils.ts @@ -3,7 +3,7 @@ import Onyx from 'react-native-onyx'; import ONYXKEYS from '@src/ONYXKEYS'; import type {Policy} from '@src/types/onyx'; import {getCurrentUserAccountID} from './actions/Report'; -import {getPolicyMembersByIdWithoutCurrentUser} from './PolicyUtils'; +import {getPolicyEmployeeListByIdWithoutCurrentUser} from './PolicyUtils'; let allPolicies: OnyxCollection = {}; Onyx.connect({ @@ -12,14 +12,14 @@ Onyx.connect({ callback: (value) => (allPolicies = value), }); -function getPolicyMemberAccountIDs(policyID?: string) { +function getPolicyEmployeeAccountIDs(policyID?: string) { if (!policyID) { return []; } const currentUserAccountID = getCurrentUserAccountID(); - return getPolicyMembersByIdWithoutCurrentUser(allPolicies, policyID, currentUserAccountID); + return getPolicyEmployeeListByIdWithoutCurrentUser(allPolicies, policyID, currentUserAccountID); } -export default getPolicyMemberAccountIDs; +export default getPolicyEmployeeAccountIDs; diff --git a/src/libs/PolicyUtils.ts b/src/libs/PolicyUtils.ts index 45539796a7bd..f3bc13295530 100644 --- a/src/libs/PolicyUtils.ts +++ b/src/libs/PolicyUtils.ts @@ -4,7 +4,7 @@ import type {ValueOf} from 'type-fest'; import CONST from '@src/CONST'; import ONYXKEYS from '@src/ONYXKEYS'; import ROUTES from '@src/ROUTES'; -import type {Policy, PolicyCategories, PolicyMembers, PolicyTagList, PolicyTags, TaxRate} from '@src/types/onyx'; +import type {Policy, PolicyCategories, PolicyEmployeeList, PolicyTagList, PolicyTags, TaxRate} from '@src/types/onyx'; import type {PolicyFeatureName, Rate} from '@src/types/onyx/Policy'; import type {EmptyObject} from '@src/types/utils/EmptyObject'; import {isEmptyObject} from '@src/types/utils/EmptyObject'; @@ -127,14 +127,14 @@ const isPolicyAdmin = (policy: OnyxEntry | EmptyObject): boolean => poli */ const isFreeGroupPolicy = (policy: OnyxEntry | EmptyObject): boolean => policy?.type === CONST.POLICY.TYPE.FREE; -const isPolicyMember = (policyID: string, policies: OnyxCollection): boolean => Object.values(policies ?? {}).some((policy) => policy?.id === policyID); +const isPolicyEmployee = (policyID: string, policies: OnyxCollection): boolean => Object.values(policies ?? {}).some((policy) => policy?.id === policyID); /** * Create an object mapping member emails to their accountIDs. Filter for members without errors, and get the login email from the personalDetail object using the accountID. * * We only return members without errors. Otherwise, the members with errors would immediately be removed before the user has a chance to read the error. */ -function getMemberAccountIDsForWorkspace(employeeList: PolicyMembers | undefined): MemberEmailsToAccountIDs { +function getMemberAccountIDsForWorkspace(employeeList: PolicyEmployeeList | undefined): MemberEmailsToAccountIDs { const members = employeeList ?? {}; const memberEmailsToAccountIDs: MemberEmailsToAccountIDs = {}; Object.keys(members).forEach((email) => { @@ -154,13 +154,13 @@ function getMemberAccountIDsForWorkspace(employeeList: PolicyMembers | undefined /** * Get login list that we should not show in the workspace invite options */ -function getIneligibleInvitees(employeeList?: PolicyMembers): string[] { - const members = employeeList ?? {}; +function getIneligibleInvitees(employeeList?: PolicyEmployeeList): string[] { + const policyEmployeeList = employeeList ?? {}; const memberEmailsToExclude: string[] = [...CONST.EXPENSIFY_EMAILS]; - Object.keys(members).forEach((email) => { - const policyMember = members?.[email]; + Object.keys(policyEmployeeList).forEach((email) => { + const policyEmployee = policyEmployeeList?.[email]; // Policy members that are pending delete or have errors are not valid and we should show them in the invite options (don't exclude them). - if (policyMember?.pendingAction === CONST.RED_BRICK_ROAD_PENDING_ACTION.DELETE || Object.keys(policyMember?.errors ?? {}).length > 0) { + if (policyEmployee?.pendingAction === CONST.RED_BRICK_ROAD_PENDING_ACTION.DELETE || Object.keys(policyEmployee?.errors ?? {}).length > 0) { return; } if (!email) { @@ -278,7 +278,7 @@ function getPathWithoutPolicyID(path: string) { return path.replace(CONST.REGEX.PATH_WITHOUT_POLICY_ID, '/'); } -function getPolicyMembersByIdWithoutCurrentUser(policies: OnyxCollection, currentPolicyID?: string, currentUserAccountID?: number) { +function getPolicyEmployeeListByIdWithoutCurrentUser(policies: OnyxCollection, currentPolicyID?: string, currentUserAccountID?: number) { const policy = policies?.[`${ONYXKEYS.COLLECTION.POLICY}${currentPolicyID}`] ?? null; const policyMemberEmailsToAccountIDs = getMemberAccountIDsForWorkspace(policy?.employeeList); return Object.values(policyMemberEmailsToAccountIDs) @@ -344,11 +344,11 @@ export { getCleanedTagName, getCountOfEnabledTagsOfList, isPendingDeletePolicy, - isPolicyMember, + isPolicyEmployee, isPaidGroupPolicy, extractPolicyIDFromPath, getPathWithoutPolicyID, - getPolicyMembersByIdWithoutCurrentUser, + getPolicyEmployeeListByIdWithoutCurrentUser, goBackFromInvalidPolicy, isPolicyFeatureEnabled, hasTaxRateError, diff --git a/src/libs/ReportUtils.ts b/src/libs/ReportUtils.ts index c2bb77bd97ce..933198231a88 100644 --- a/src/libs/ReportUtils.ts +++ b/src/libs/ReportUtils.ts @@ -4887,7 +4887,7 @@ function getMoneyRequestOptions(report: OnyxEntry, policy: OnyxEntry, isPolicyMember: boolean): boolean { +function canLeaveRoom(report: OnyxEntry, isPolicyEmployee: boolean): boolean { if (!report?.visibility) { if ( report?.chatType === CONST.REPORT.CHAT_TYPE.POLICY_ADMINS || @@ -4900,7 +4900,7 @@ function canLeaveRoom(report: OnyxEntry, isPolicyMember: boolean): boole // DM chats don't have a chatType return false; } - } else if (isPublicAnnounceRoom(report) && isPolicyMember) { + } else if (isPublicAnnounceRoom(report) && isPolicyEmployee) { return false; } return true; diff --git a/src/libs/actions/Policy.ts b/src/libs/actions/Policy.ts index 1a63be771680..e79d02914935 100644 --- a/src/libs/actions/Policy.ts +++ b/src/libs/actions/Policy.ts @@ -77,7 +77,7 @@ import type { Policy, PolicyCategories, PolicyCategory, - PolicyMember, + PolicyEmployee, PolicyOwnershipChangeChecks, PolicyTag, PolicyTagList, @@ -824,9 +824,9 @@ function removeMembers(accountIDs: number[], policyID: string) { const announceRoomMembers = removeOptimisticAnnounceRoomMembers(policyID, accountIDs); - const optimisticMembersState: OnyxCollection = {}; - const successMembersState: OnyxCollection = {}; - const failureMembersState: OnyxCollection = {}; + const optimisticMembersState: OnyxCollection = {}; + const successMembersState: OnyxCollection = {}; + const failureMembersState: OnyxCollection = {}; emailList.forEach((email) => { optimisticMembersState[email] = {pendingAction: CONST.RED_BRICK_ROAD_PENDING_ACTION.DELETE}; successMembersState[email] = null; @@ -1286,9 +1286,9 @@ function addMembersToWorkspace(invitedEmailsToAccountIDs: InvitedEmailsToAccount // create onyx data for policy expense chats for each new member const membersChats = createPolicyExpenseChats(policyID, invitedEmailsToAccountIDs); - const optimisticMembersState: OnyxCollection = {}; - const successMembersState: OnyxCollection = {}; - const failureMembersState: OnyxCollection = {}; + const optimisticMembersState: OnyxCollection = {}; + const successMembersState: OnyxCollection = {}; + const failureMembersState: OnyxCollection = {}; Object.keys(invitedEmailsToAccountIDs).forEach((email) => { optimisticMembersState[email] = {pendingAction: CONST.RED_BRICK_ROAD_PENDING_ACTION.ADD, role: CONST.POLICY.ROLE.USER}; successMembersState[email] = {pendingAction: null}; diff --git a/src/libs/actions/Report.ts b/src/libs/actions/Report.ts index 91128ac89178..fd44f976055f 100644 --- a/src/libs/actions/Report.ts +++ b/src/libs/actions/Report.ts @@ -53,7 +53,7 @@ import Navigation from '@libs/Navigation/Navigation'; import LocalNotification from '@libs/Notification/LocalNotification'; import * as PersonalDetailsUtils from '@libs/PersonalDetailsUtils'; import * as PhoneNumber from '@libs/PhoneNumber'; -import getPolicyMemberAccountIDs from '@libs/PolicyMembersUtils'; +import getPolicyEmployeeAccountIDs from '@libs/PolicyEmployeeListUtils'; import {extractPolicyIDFromPath} from '@libs/PolicyUtils'; import processReportIDDeeplink from '@libs/processReportIDDeeplink'; import * as Pusher from '@libs/Pusher/pusher'; @@ -2137,8 +2137,8 @@ function showReportActionNotification(reportID: string, reportAction: ReportActi const onClick = () => Modal.close(() => { const policyID = lastVisitedPath && extractPolicyIDFromPath(lastVisitedPath); - const policyMembersAccountIDs = policyID ? getPolicyMemberAccountIDs(policyID) : []; - const reportBelongsToWorkspace = policyID ? doesReportBelongToWorkspace(report, policyMembersAccountIDs, policyID) : false; + const policyEmployeeAccountIDs = policyID ? getPolicyEmployeeAccountIDs(policyID) : []; + const reportBelongsToWorkspace = policyID ? doesReportBelongToWorkspace(report, policyEmployeeAccountIDs, policyID) : false; if (!reportBelongsToWorkspace) { Navigation.navigateWithSwitchPolicyID({route: ROUTES.HOME}); } diff --git a/src/pages/ReportDetailsPage.tsx b/src/pages/ReportDetailsPage.tsx index 9093bf32b9dd..b4e74252fd61 100644 --- a/src/pages/ReportDetailsPage.tsx +++ b/src/pages/ReportDetailsPage.tsx @@ -65,7 +65,7 @@ function ReportDetailsPage({policies, report, session, personalDetails}: ReportD const route = useRoute(); const policy = useMemo(() => policies?.[`${ONYXKEYS.COLLECTION.POLICY}${report?.policyID ?? ''}`], [policies, report?.policyID]); const isPolicyAdmin = useMemo(() => PolicyUtils.isPolicyAdmin(policy ?? null), [policy]); - const isPolicyMember = useMemo(() => PolicyUtils.isPolicyMember(report?.policyID ?? '', policies), [report?.policyID, policies]); + const isPolicyEmployee = useMemo(() => PolicyUtils.isPolicyEmployee(report?.policyID ?? '', policies), [report?.policyID, policies]); const shouldUseFullTitle = useMemo(() => ReportUtils.shouldUseFullTitleToDisplay(report), [report]); const isChatRoom = useMemo(() => ReportUtils.isChatRoom(report), [report]); const isUserCreatedPolicyRoom = useMemo(() => ReportUtils.isUserCreatedPolicyRoom(report), [report]); @@ -122,9 +122,9 @@ function ReportDetailsPage({policies, report, session, personalDetails}: ReportD // - The report is not a user created room with participants to show i.e. DM, Group Chat, etc // - The report is a user created room and the room and the current user is a workspace member i.e. non-workspace members should not see this option. if ( - ((isDefaultRoom && isChatThread && isPolicyMember) || + ((isDefaultRoom && isChatThread && isPolicyEmployee) || (!isUserCreatedPolicyRoom && participants.length) || - (isUserCreatedPolicyRoom && (isPolicyMember || (isChatThread && !ReportUtils.isPublicRoom(report))))) && + (isUserCreatedPolicyRoom && (isPolicyEmployee || (isChatThread && !ReportUtils.isPublicRoom(report))))) && !ReportUtils.isConciergeChatReport(report) ) { items.push({ @@ -142,8 +142,8 @@ function ReportDetailsPage({policies, report, session, personalDetails}: ReportD }, }); } else if ( - (isUserCreatedPolicyRoom && (!participants.length || !isPolicyMember)) || - ((isDefaultRoom || ReportUtils.isPolicyExpenseChat(report)) && isChatThread && !isPolicyMember) + (isUserCreatedPolicyRoom && (!participants.length || !isPolicyEmployee)) || + ((isDefaultRoom || ReportUtils.isPolicyExpenseChat(report)) && isChatThread && !isPolicyEmployee) ) { items.push({ key: CONST.REPORT_DETAILS_MENU_ITEM.INVITE, @@ -179,7 +179,7 @@ function ReportDetailsPage({policies, report, session, personalDetails}: ReportD } return items; - }, [isArchivedRoom, participants.length, isChatThread, isMoneyRequestReport, report, isGroupDMChat, isPolicyMember, isUserCreatedPolicyRoom, session, isSelfDM, isDefaultRoom]); + }, [isArchivedRoom, participants.length, isChatThread, isMoneyRequestReport, report, isGroupDMChat, isPolicyEmployee, isUserCreatedPolicyRoom, session, isSelfDM, isDefaultRoom]); const displayNamesWithTooltips = useMemo(() => { const hasMultipleParticipants = participants.length > 1; diff --git a/src/pages/RoomInvitePage.tsx b/src/pages/RoomInvitePage.tsx index 49e53381e040..45a66d14e944 100644 --- a/src/pages/RoomInvitePage.tsx +++ b/src/pages/RoomInvitePage.tsx @@ -146,8 +146,8 @@ function RoomInvitePage({betas, report, policies}: RoomInvitePageProps) { // Non policy members should not be able to view the participants of a room const reportID = report?.reportID; - const isPolicyMember = useMemo(() => (report?.policyID ? PolicyUtils.isPolicyMember(report.policyID, policies as Record) : false), [report?.policyID, policies]); - const backRoute = useMemo(() => reportID && (isPolicyMember ? ROUTES.ROOM_MEMBERS.getRoute(reportID) : ROUTES.REPORT_WITH_ID_DETAILS.getRoute(reportID)), [isPolicyMember, reportID]); + const isPolicyEmployee = useMemo(() => (report?.policyID ? PolicyUtils.isPolicyEmployee(report.policyID, policies as Record) : false), [report?.policyID, policies]); + const backRoute = useMemo(() => reportID && (isPolicyEmployee ? ROUTES.ROOM_MEMBERS.getRoute(reportID) : ROUTES.REPORT_WITH_ID_DETAILS.getRoute(reportID)), [isPolicyEmployee, reportID]); const reportName = useMemo(() => ReportUtils.getReportName(report), [report]); const inviteUsers = useCallback(() => { if (!validate()) { diff --git a/src/pages/RoomMembersPage.tsx b/src/pages/RoomMembersPage.tsx index d025a3bde265..009eaaf15a3c 100644 --- a/src/pages/RoomMembersPage.tsx +++ b/src/pages/RoomMembersPage.tsx @@ -224,11 +224,11 @@ function RoomMembersPage({report, session, policies}: RoomMembersPageProps) { return result; }; - const isPolicyMember = useMemo(() => { + const isPolicyEmployee = useMemo(() => { if (!report?.policyID || policies === null) { return false; } - return PolicyUtils.isPolicyMember(report.policyID, policies); + return PolicyUtils.isPolicyEmployee(report.policyID, policies); }, [report?.policyID, policies]); const data = getMemberOptions(); const headerMessage = searchValue.trim() && !data.length ? translate('roomMembersPage.memberNotFound') : ''; @@ -240,7 +240,7 @@ function RoomMembersPage({report, session, policies}: RoomMembersPageProps) { > { diff --git a/src/pages/home/HeaderView.tsx b/src/pages/home/HeaderView.tsx index 1b8957b833b0..ae2e78ff4af5 100644 --- a/src/pages/home/HeaderView.tsx +++ b/src/pages/home/HeaderView.tsx @@ -94,8 +94,8 @@ function HeaderView({report, personalDetails, parentReport, parentReportAction, const isCanceledTaskReport = ReportUtils.isCanceledTaskReport(report, parentReportAction); const isWhisperAction = ReportActionsUtils.isWhisperAction(parentReportAction); const isUserCreatedPolicyRoom = ReportUtils.isUserCreatedPolicyRoom(report); - const isPolicyMember = useMemo(() => !isEmptyObject(policy), [policy]); - const canLeaveRoom = ReportUtils.canLeaveRoom(report, isPolicyMember); + const isPolicyEmployee = useMemo(() => !isEmptyObject(policy), [policy]); + const canLeaveRoom = ReportUtils.canLeaveRoom(report, isPolicyEmployee); const reportDescription = ReportUtils.getReportDescriptionText(report); const policyName = ReportUtils.getPolicyName(report, true); const policyDescription = ReportUtils.getPolicyDescriptionText(policy); @@ -152,7 +152,7 @@ function HeaderView({report, personalDetails, parentReport, parentReportAction, onSelected: join, }); } else if (canLeave) { - const isWorkspaceMemberLeavingWorkspaceRoom = !isChatThread && report.visibility === CONST.REPORT.VISIBILITY.RESTRICTED && isPolicyMember; + const isWorkspaceMemberLeavingWorkspaceRoom = !isChatThread && report.visibility === CONST.REPORT.VISIBILITY.RESTRICTED && isPolicyEmployee; threeDotMenuItems.push({ icon: Expensicons.ChatBubbles, text: translate('common.leave'), diff --git a/src/pages/home/sidebar/SidebarLinksData.js b/src/pages/home/sidebar/SidebarLinksData.js index 792e0f9ad7be..d2d02960186f 100644 --- a/src/pages/home/sidebar/SidebarLinksData.js +++ b/src/pages/home/sidebar/SidebarLinksData.js @@ -16,7 +16,7 @@ import useLocalize from '@hooks/useLocalize'; import usePrevious from '@hooks/usePrevious'; import useThemeStyles from '@hooks/useThemeStyles'; import compose from '@libs/compose'; -import {getPolicyMembersByIdWithoutCurrentUser} from '@libs/PolicyUtils'; +import {getPolicyEmployeeListByIdWithoutCurrentUser} from '@libs/PolicyUtils'; import * as ReportUtils from '@libs/ReportUtils'; import SidebarUtils from '@libs/SidebarUtils'; import reportPropTypes from '@pages/reportPropTypes'; @@ -128,7 +128,7 @@ function SidebarLinksData({ const {translate} = useLocalize(); const prevPriorityMode = usePrevious(priorityMode); - const policyMemberAccountIDs = getPolicyMembersByIdWithoutCurrentUser(policies, activeWorkspaceID, currentUserPersonalDetails.accountID); + const policyMemberAccountIDs = getPolicyEmployeeListByIdWithoutCurrentUser(policies, activeWorkspaceID, currentUserPersonalDetails.accountID); // eslint-disable-next-line react-hooks/exhaustive-deps useEffect(() => Policy.openWorkspace(activeWorkspaceID, policyMemberAccountIDs), [activeWorkspaceID]); diff --git a/src/pages/workspace/WorkspaceInvitePage.tsx b/src/pages/workspace/WorkspaceInvitePage.tsx index 660f7b2e1ed8..4ca2ebab80b2 100644 --- a/src/pages/workspace/WorkspaceInvitePage.tsx +++ b/src/pages/workspace/WorkspaceInvitePage.tsx @@ -91,7 +91,7 @@ function WorkspaceInvitePage({route, betas, invitedEmailsToAccountIDsDraft, poli const newSelectedOptionsDict: Record = {}; const inviteOptions = OptionsListUtils.getMemberInviteOptions(options.personalDetails, betas ?? [], searchTerm, excludedUsers, true); - // Update selectedOptions with the latest personalDetails and policyMembers information + // Update selectedOptions with the latest personalDetails and policyEmployeeList information const detailsMap: Record = {}; inviteOptions.personalDetails.forEach((detail) => { if (!detail.login) { diff --git a/src/pages/workspace/WorkspaceMembersPage.tsx b/src/pages/workspace/WorkspaceMembersPage.tsx index c796113208d2..adbd06d6a32e 100644 --- a/src/pages/workspace/WorkspaceMembersPage.tsx +++ b/src/pages/workspace/WorkspaceMembersPage.tsx @@ -42,7 +42,7 @@ import CONST from '@src/CONST'; import ONYXKEYS from '@src/ONYXKEYS'; import ROUTES from '@src/ROUTES'; import type SCREENS from '@src/SCREENS'; -import type {InvitedEmailsToAccountIDs, PersonalDetailsList, PolicyMember, PolicyMembers, Session} from '@src/types/onyx'; +import type {InvitedEmailsToAccountIDs, PersonalDetailsList, PolicyEmployee, PolicyEmployeeList, Session} from '@src/types/onyx'; import type {Errors, PendingAction} from '@src/types/onyx/OnyxCommon'; import {isEmptyObject} from '@src/types/utils/EmptyObject'; import type {WithPolicyAndFullscreenLoadingProps} from './withPolicyAndFullscreenLoading'; @@ -98,12 +98,13 @@ function WorkspaceMembersPage({personalDetails, invitedEmailsToAccountIDsDraft, /** * Get filtered personalDetails list with current employeeList */ - const filterPersonalDetails = (members: OnyxEntry, details: OnyxEntry): PersonalDetailsList => + const filterPersonalDetails = (members: OnyxEntry, details: OnyxEntry): PersonalDetailsList => Object.keys(members ?? {}).reduce((result, key) => { - if (details?.[policyMemberEmailsToAccountIDs[key] ?? '']) { + const memberAccountIdKey = policyMemberEmailsToAccountIDs[key] ?? ''; + if (details?.[memberAccountIdKey]) { return { ...result, - [policyMemberEmailsToAccountIDs[key] ?? '']: details[policyMemberEmailsToAccountIDs[key] ?? ''], + [memberAccountIdKey]: details[memberAccountIdKey], }; } return result; @@ -130,7 +131,7 @@ function WorkspaceMembersPage({personalDetails, invitedEmailsToAccountIDsDraft, // eslint-disable-next-line react-hooks/exhaustive-deps }, [selectedEmployees, policy?.owner, session?.accountID]); - // useFocusEffect would make getWorkspaceMembers get called twice on fresh login because policyMember is a dependency of getWorkspaceMembers. + // useFocus would make getWorkspaceMembers get called twice on fresh login because policyEmployee is a dependency of getWorkspaceMembers. useEffect(() => { if (!isFocused) { return; @@ -156,10 +157,13 @@ function WorkspaceMembersPage({personalDetails, invitedEmailsToAccountIDsDraft, const res = Object.values(currentPersonalDetails).find((item) => prevItem?.login === item?.login); return res?.accountID ?? id; }); + + const currentSelectedElements = Object.entries(PolicyUtils.getMemberAccountIDsForWorkspace(policy?.employeeList)) + .filter((employee) => policy?.employeeList?.[employee[0]]?.pendingAction !== CONST.RED_BRICK_ROAD_PENDING_ACTION.DELETE) + .map((employee) => employee[1]); + // This is an equivalent of the lodash intersection function. The reduce method below is used to filter the items that exist in both arrays. - return [prevSelectedElements, Object.values(PolicyUtils.getMemberAccountIDsForWorkspace(policy?.employeeList))].reduce((prev, members) => - prev.filter((item) => members.includes(item)), - ); + return [prevSelectedElements, currentSelectedElements].reduce((prev, members) => prev.filter((item) => members.includes(item))); }); // eslint-disable-next-line react-hooks/exhaustive-deps }, [policy?.employeeList, policyMemberEmailsToAccountIDs]); @@ -294,8 +298,8 @@ function WorkspaceMembersPage({personalDetails, invitedEmailsToAccountIDsDraft, /** * Check if the policy member is deleted from the workspace */ - const isDeletedPolicyMember = useCallback( - (policyMember: PolicyMember): boolean => !isOffline && policyMember.pendingAction === CONST.RED_BRICK_ROAD_PENDING_ACTION.DELETE && isEmptyObject(policyMember.errors), + const isDeletedPolicyEmployee = useCallback( + (policyEmployee: PolicyEmployee): boolean => !isOffline && policyEmployee.pendingAction === CONST.RED_BRICK_ROAD_PENDING_ACTION.DELETE && isEmptyObject(policyEmployee.errors), [isOffline], ); @@ -305,9 +309,9 @@ function WorkspaceMembersPage({personalDetails, invitedEmailsToAccountIDsDraft, const getUsers = useCallback((): MemberOption[] => { let result: MemberOption[] = []; - Object.entries(policy?.employeeList ?? {}).forEach(([email, policyMember]) => { + Object.entries(policy?.employeeList ?? {}).forEach(([email, policyEmployee]) => { const accountID = Number(policyMemberEmailsToAccountIDs[email] ?? ''); - if (isDeletedPolicyMember(policyMember)) { + if (isDeletedPolicyEmployee(policyEmployee)) { return; } @@ -330,7 +334,7 @@ function WorkspaceMembersPage({personalDetails, invitedEmailsToAccountIDsDraft, const isSelected = selectedEmployees.includes(accountID); const isOwner = policy?.owner === details.login; - const isAdmin = policyMember.role === CONST.POLICY.ROLE.ADMIN; + const isAdmin = policyEmployee.role === CONST.POLICY.ROLE.ADMIN; let roleBadge = null; if (isOwner || isAdmin) { roleBadge = ( @@ -347,7 +351,7 @@ function WorkspaceMembersPage({personalDetails, invitedEmailsToAccountIDsDraft, accountID, isSelected, isDisabledCheckbox: !(isPolicyAdmin && accountID !== policy?.ownerAccountID && accountID !== session?.accountID), - isDisabled: isPolicyAdmin && (policyMember.pendingAction === CONST.RED_BRICK_ROAD_PENDING_ACTION.DELETE || !isEmptyObject(policyMember.errors)), + isDisabled: isPolicyAdmin && (policyEmployee.pendingAction === CONST.RED_BRICK_ROAD_PENDING_ACTION.DELETE || !isEmptyObject(policyEmployee.errors)), text: formatPhoneNumber(PersonalDetailsUtils.getDisplayNameOrDefault(details)), alternateText: formatPhoneNumber(details?.login ?? ''), rightElement: roleBadge, @@ -359,8 +363,8 @@ function WorkspaceMembersPage({personalDetails, invitedEmailsToAccountIDsDraft, id: accountID, }, ], - errors: policyMember.errors, - pendingAction: policyMember.pendingAction, + errors: policyEmployee.errors, + pendingAction: policyEmployee.pendingAction, // Note which secondary login was used to invite this primary login invitedSecondaryLogin: details?.login ? invitedPrimaryToSecondaryLogins[details.login] ?? '' : '', }); @@ -372,7 +376,7 @@ function WorkspaceMembersPage({personalDetails, invitedEmailsToAccountIDsDraft, currentUserLogin, formatPhoneNumber, invitedPrimaryToSecondaryLogins, - isDeletedPolicyMember, + isDeletedPolicyEmployee, isPolicyAdmin, personalDetails, policy?.owner, diff --git a/src/pages/workspace/workflows/WorkspaceWorkflowsApproverPage.tsx b/src/pages/workspace/workflows/WorkspaceWorkflowsApproverPage.tsx index ccf446ab077b..d32218616662 100644 --- a/src/pages/workspace/workflows/WorkspaceWorkflowsApproverPage.tsx +++ b/src/pages/workspace/workflows/WorkspaceWorkflowsApproverPage.tsx @@ -27,7 +27,7 @@ import type {WithPolicyAndFullscreenLoadingProps} from '@pages/workspace/withPol import * as Policy from '@userActions/Policy'; import CONST from '@src/CONST'; import type SCREENS from '@src/SCREENS'; -import type {PersonalDetailsList, PolicyMember} from '@src/types/onyx'; +import type {PersonalDetailsList, PolicyEmployee} from '@src/types/onyx'; import {isEmptyObject} from '@src/types/utils/EmptyObject'; type WorkspaceWorkflowsApproverPageOnyxProps = { @@ -49,19 +49,19 @@ function WorkspaceWorkflowsApproverPage({policy, personalDetails, isLoadingRepor const styles = useThemeStyles(); const StyleUtils = useStyleUtils(); - const isDeletedPolicyMember = useCallback( - (policyMember: PolicyMember) => !isOffline && policyMember.pendingAction === CONST.RED_BRICK_ROAD_PENDING_ACTION.DELETE && isEmptyObject(policyMember.errors), + const isDeletedPolicyEmployee = useCallback( + (policyEmployee: PolicyEmployee) => !isOffline && policyEmployee.pendingAction === CONST.RED_BRICK_ROAD_PENDING_ACTION.DELETE && isEmptyObject(policyEmployee.errors), [isOffline], ); - const [formattedPolicyMembers, formattedApprover] = useMemo(() => { + const [formattedPolicyEmployeeList, formattedApprover] = useMemo(() => { const policyMemberDetails: MemberOption[] = []; const approverDetails: MemberOption[] = []; const policyMemberEmailsToAccountIDs = PolicyUtils.getMemberAccountIDsForWorkspace(policy?.employeeList); - Object.entries(policy?.employeeList ?? {}).forEach(([email, policyMember]) => { - if (isDeletedPolicyMember(policyMember)) { + Object.entries(policy?.employeeList ?? {}).forEach(([email, policyEmployee]) => { + if (isDeletedPolicyEmployee(policyEmployee)) { return; } @@ -74,7 +74,7 @@ function WorkspaceWorkflowsApproverPage({policy, personalDetails, isLoadingRepor } const isOwner = policy?.owner === details.login; - const isAdmin = policyMember.role === CONST.POLICY.ROLE.ADMIN; + const isAdmin = policyEmployee.role === CONST.POLICY.ROLE.ADMIN; let roleBadge = null; if (isOwner || isAdmin) { @@ -91,7 +91,7 @@ function WorkspaceWorkflowsApproverPage({policy, personalDetails, isLoadingRepor keyForList: String(accountID), accountID, isSelected: policy?.approver === details.login, - isDisabled: policyMember.pendingAction === CONST.RED_BRICK_ROAD_PENDING_ACTION.DELETE || !isEmptyObject(policyMember.errors), + isDisabled: policyEmployee.pendingAction === CONST.RED_BRICK_ROAD_PENDING_ACTION.DELETE || !isEmptyObject(policyEmployee.errors), text: formatPhoneNumber(PersonalDetailsUtils.getDisplayNameOrDefault(details)), alternateText: formatPhoneNumber(details?.login ?? ''), rightElement: roleBadge, @@ -103,8 +103,8 @@ function WorkspaceWorkflowsApproverPage({policy, personalDetails, isLoadingRepor id: accountID, }, ], - errors: policyMember.errors, - pendingAction: policyMember.pendingAction, + errors: policyEmployee.errors, + pendingAction: policyEmployee.pendingAction, }; if (policy?.approver === details.login) { @@ -114,13 +114,13 @@ function WorkspaceWorkflowsApproverPage({policy, personalDetails, isLoadingRepor } }); return [policyMemberDetails, approverDetails]; - }, [personalDetails, translate, policy?.approver, StyleUtils, isDeletedPolicyMember, policy?.owner, styles, policy?.employeeList]); + }, [personalDetails, translate, policy?.approver, StyleUtils, isDeletedPolicyEmployee, policy?.owner, styles, policy?.employeeList]); const sections: MembersSection[] = useMemo(() => { const sectionsArray: MembersSection[] = []; if (searchTerm !== '') { - const filteredOptions = [...formattedApprover, ...formattedPolicyMembers].filter((option) => { + const filteredOptions = [...formattedApprover, ...formattedPolicyEmployeeList].filter((option) => { const searchValue = OptionsListUtils.getSearchValueForPhoneOrEmail(searchTerm); return !!option.text?.toLowerCase().includes(searchValue) || !!option.login?.toLowerCase().includes(searchValue); }); @@ -141,12 +141,12 @@ function WorkspaceWorkflowsApproverPage({policy, personalDetails, isLoadingRepor sectionsArray.push({ title: translate('common.all'), - data: formattedPolicyMembers, + data: formattedPolicyEmployeeList, shouldShow: true, }); return sectionsArray; - }, [formattedPolicyMembers, formattedApprover, searchTerm, translate]); + }, [formattedPolicyEmployeeList, formattedApprover, searchTerm, translate]); const headerMessage = useMemo( () => (searchTerm && !sections[0].data.length ? translate('common.noResultsFound') : ''), diff --git a/src/pages/workspace/workflows/WorkspaceWorkflowsPayerPage.tsx b/src/pages/workspace/workflows/WorkspaceWorkflowsPayerPage.tsx index 6691fc7f002c..da51b2c3e8e3 100644 --- a/src/pages/workspace/workflows/WorkspaceWorkflowsPayerPage.tsx +++ b/src/pages/workspace/workflows/WorkspaceWorkflowsPayerPage.tsx @@ -28,7 +28,7 @@ import type {WithPolicyAndFullscreenLoadingProps} from '@pages/workspace/withPol import * as Policy from '@userActions/Policy'; import CONST from '@src/CONST'; import type SCREENS from '@src/SCREENS'; -import type {PersonalDetailsList, PolicyMember} from '@src/types/onyx'; +import type {PersonalDetailsList, PolicyEmployee} from '@src/types/onyx'; import {isEmptyObject} from '@src/types/utils/EmptyObject'; type WorkspaceWorkflowsPayerPageOnyxProps = { @@ -51,8 +51,8 @@ function WorkspaceWorkflowsPayerPage({route, policy, personalDetails, isLoadingR const [searchTerm, setSearchTerm] = useState(''); - const isDeletedPolicyMember = useCallback( - (policyMember: PolicyMember) => !isOffline && policyMember.pendingAction === CONST.RED_BRICK_ROAD_PENDING_ACTION.DELETE && isEmptyObject(policyMember.errors), + const isDeletedPolicyEmployee = useCallback( + (policyEmployee: PolicyEmployee) => !isOffline && policyEmployee.pendingAction === CONST.RED_BRICK_ROAD_PENDING_ACTION.DELETE && isEmptyObject(policyEmployee.errors), [isOffline], ); @@ -62,7 +62,7 @@ function WorkspaceWorkflowsPayerPage({route, policy, personalDetails, isLoadingR const policyMemberEmailsToAccountIDs = PolicyUtils.getMemberAccountIDsForWorkspace(policy?.employeeList); - Object.entries(policy?.employeeList ?? {}).forEach(([email, policyMember]) => { + Object.entries(policy?.employeeList ?? {}).forEach(([email, policyEmployee]) => { const accountID = policyMemberEmailsToAccountIDs?.[email] ?? ''; const details = personalDetails?.[accountID]; if (!details) { @@ -71,8 +71,8 @@ function WorkspaceWorkflowsPayerPage({route, policy, personalDetails, isLoadingR } const isOwner = policy?.owner === details?.login; - const isAdmin = policyMember.role === CONST.POLICY.ROLE.ADMIN; - const shouldSkipMember = isDeletedPolicyMember(policyMember) || PolicyUtils.isExpensifyTeam(details?.login) || (!isOwner && !isAdmin); + const isAdmin = policyEmployee.role === CONST.POLICY.ROLE.ADMIN; + const shouldSkipMember = isDeletedPolicyEmployee(policyEmployee) || PolicyUtils.isExpensifyTeam(details?.login) || (!isOwner && !isAdmin); if (shouldSkipMember) { return; @@ -92,7 +92,7 @@ function WorkspaceWorkflowsPayerPage({route, policy, personalDetails, isLoadingR keyForList: String(accountID), accountID, isSelected: isAuthorizedPayer, - isDisabled: policyMember.pendingAction === CONST.RED_BRICK_ROAD_PENDING_ACTION.DELETE || !isEmptyObject(policyMember.errors), + isDisabled: policyEmployee.pendingAction === CONST.RED_BRICK_ROAD_PENDING_ACTION.DELETE || !isEmptyObject(policyEmployee.errors), text: formatPhoneNumber(PersonalDetailsUtils.getDisplayNameOrDefault(details)), alternateText: formatPhoneNumber(details?.login ?? ''), rightElement: roleBadge, @@ -104,8 +104,8 @@ function WorkspaceWorkflowsPayerPage({route, policy, personalDetails, isLoadingR id: accountID, }, ], - errors: policyMember.errors, - pendingAction: policyMember.pendingAction ?? isAuthorizedPayer ? policy?.pendingFields?.reimburser : null, + errors: policyEmployee.errors, + pendingAction: policyEmployee.pendingAction ?? isAuthorizedPayer ? policy?.pendingFields?.reimburser : null, }; if (isAuthorizedPayer) { @@ -115,7 +115,7 @@ function WorkspaceWorkflowsPayerPage({route, policy, personalDetails, isLoadingR } }); return [policyAdminDetails, authorizedPayerDetails]; - }, [personalDetails, policy?.employeeList, translate, policy?.achAccount?.reimburser, isDeletedPolicyMember, policy?.owner, styles, StyleUtils, policy?.pendingFields?.reimburser]); + }, [personalDetails, policy?.employeeList, translate, policy?.achAccount?.reimburser, isDeletedPolicyEmployee, policy?.owner, styles, StyleUtils, policy?.pendingFields?.reimburser]); const sections: MembersSection[] = useMemo(() => { const sectionsArray: MembersSection[] = []; diff --git a/src/types/onyx/Policy.ts b/src/types/onyx/Policy.ts index cdfe92b3d09d..1e00bc645aee 100644 --- a/src/types/onyx/Policy.ts +++ b/src/types/onyx/Policy.ts @@ -327,7 +327,7 @@ type Policy = OnyxCommon.OnyxValueWithOfflineFeedback< submitsTo?: number; /** The employee list of the policy */ - employeeList?: OnyxTypes.PolicyMembers; + employeeList?: OnyxTypes.PolicyEmployeeList; /** The reimbursement choice for policy */ reimbursementChoice?: ValueOf; diff --git a/src/types/onyx/PolicyMember.ts b/src/types/onyx/PolicyEmployee.ts similarity index 73% rename from src/types/onyx/PolicyMember.ts rename to src/types/onyx/PolicyEmployee.ts index 366a7ef7d530..4a5f374de44a 100644 --- a/src/types/onyx/PolicyMember.ts +++ b/src/types/onyx/PolicyEmployee.ts @@ -1,6 +1,6 @@ import type * as OnyxCommon from './OnyxCommon'; -type PolicyMember = OnyxCommon.OnyxValueWithOfflineFeedback<{ +type PolicyEmployee = OnyxCommon.OnyxValueWithOfflineFeedback<{ /** Role of the user in the policy */ role?: string; @@ -20,7 +20,7 @@ type PolicyMember = OnyxCommon.OnyxValueWithOfflineFeedback<{ errors?: OnyxCommon.Errors; }>; -type PolicyMembers = Record; +type PolicyEmployeeList = Record; -export default PolicyMember; -export type {PolicyMembers}; +export default PolicyEmployee; +export type {PolicyEmployeeList}; diff --git a/src/types/onyx/index.ts b/src/types/onyx/index.ts index e56066440d80..bcac6a541798 100644 --- a/src/types/onyx/index.ts +++ b/src/types/onyx/index.ts @@ -38,8 +38,8 @@ import type Policy from './Policy'; import type {PolicyReportField, TaxRate, TaxRates, TaxRatesWithDefault} from './Policy'; import type {PolicyCategories, PolicyCategory} from './PolicyCategory'; import type PolicyJoinMember from './PolicyJoinMember'; -import type {PolicyMembers} from './PolicyMember'; -import type PolicyMember from './PolicyMember'; +import type {PolicyEmployeeList} from './PolicyEmployee'; +import type PolicyEmployee from './PolicyEmployee'; import type PolicyOwnershipChangeChecks from './PolicyOwnershipChangeChecks'; import type {PolicyTag, PolicyTagList, PolicyTags} from './PolicyTag'; import type PreferredTheme from './PreferredTheme'; @@ -117,8 +117,8 @@ export type { Policy, PolicyCategories, PolicyCategory, - PolicyMember, - PolicyMembers, + PolicyEmployee, + PolicyEmployeeList, PolicyOwnershipChangeChecks, PolicyTag, PolicyTags, diff --git a/tests/perf-test/PolicyUtils.perf-test.ts b/tests/perf-test/PolicyUtils.perf-test.ts index 4f882ae9f057..0fc0a71bef03 100644 --- a/tests/perf-test/PolicyUtils.perf-test.ts +++ b/tests/perf-test/PolicyUtils.perf-test.ts @@ -1,29 +1,29 @@ import {measureFunction} from 'reassure'; import {getMemberAccountIDsForWorkspace} from '@libs/PolicyUtils'; import createCollection from '../utils/collections/createCollection'; -import createRandomPolicyMember from '../utils/collections/policyMembers'; +import createRandomPolicyEmployeeList from '../utils/collections/policyEmployeeList'; describe('PolicyUtils', () => { describe('getMemberAccountIDsForWorkspace', () => { test('500 policy members with personal details', async () => { - const policyMembers = createCollection( + const policyEmployeeList = createCollection( (_, index) => index, - () => createRandomPolicyMember(), + () => createRandomPolicyEmployeeList(), ); - await measureFunction(() => getMemberAccountIDsForWorkspace(policyMembers)); + await measureFunction(() => getMemberAccountIDsForWorkspace(policyEmployeeList)); }); test('500 policy members with errors and personal details', async () => { - const policyMembers = createCollection( + const policyEmployeeList = createCollection( (_, index) => index, () => ({ - ...createRandomPolicyMember(), + ...createRandomPolicyEmployeeList(), errors: {error: 'Error message'}, }), ); - await measureFunction(() => getMemberAccountIDsForWorkspace(policyMembers)); + await measureFunction(() => getMemberAccountIDsForWorkspace(policyEmployeeList)); }); }); }); diff --git a/tests/utils/collections/policyEmployeeList.ts b/tests/utils/collections/policyEmployeeList.ts new file mode 100644 index 000000000000..9e04c71748b7 --- /dev/null +++ b/tests/utils/collections/policyEmployeeList.ts @@ -0,0 +1,9 @@ +import {randWord} from '@ngneat/falso'; +import type {PolicyEmployee} from '@src/types/onyx'; + +export default function createRandomPolicyEmployeeList(): PolicyEmployee { + return { + role: randWord(), + errors: {}, + }; +} diff --git a/tests/utils/collections/policyMembers.ts b/tests/utils/collections/policyMembers.ts deleted file mode 100644 index 076c8ddb2d3d..000000000000 --- a/tests/utils/collections/policyMembers.ts +++ /dev/null @@ -1,9 +0,0 @@ -import {randWord} from '@ngneat/falso'; -import type {PolicyMember} from '@src/types/onyx'; - -export default function createRandomPolicyMember(): PolicyMember { - return { - role: randWord(), - errors: {}, - }; -} From 851ee9b3e85f6540c0835ffaa106394d4087a80a Mon Sep 17 00:00:00 2001 From: Yauheni Date: Tue, 9 Apr 2024 23:46:07 +0200 Subject: [PATCH 18/27] Fix eslint issue --- src/types/onyx/index.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/types/onyx/index.ts b/src/types/onyx/index.ts index 0088b8f2644b..ea0870a7b8c6 100644 --- a/src/types/onyx/index.ts +++ b/src/types/onyx/index.ts @@ -37,9 +37,9 @@ import type PlaidData from './PlaidData'; import type Policy from './Policy'; import type {PolicyConnectionSyncProgress, PolicyReportField, TaxRate, TaxRates, TaxRatesWithDefault} from './Policy'; import type {PolicyCategories, PolicyCategory} from './PolicyCategory'; -import type PolicyJoinMember from './PolicyJoinMember'; import type {PolicyEmployeeList} from './PolicyEmployee'; import type PolicyEmployee from './PolicyEmployee'; +import type PolicyJoinMember from './PolicyJoinMember'; import type PolicyOwnershipChangeChecks from './PolicyOwnershipChangeChecks'; import type {PolicyTag, PolicyTagList, PolicyTags} from './PolicyTag'; import type PreferredTheme from './PreferredTheme'; From a4c72ec77cac52c363c381f3e24c2b9ce06405fd Mon Sep 17 00:00:00 2001 From: Yauheni Date: Wed, 10 Apr 2024 10:00:14 +0200 Subject: [PATCH 19/27] Fix bug with paddingTop on RoleModal --- .../members/WorkspaceMemberDetailsRoleSelectionModal.tsx | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/pages/workspace/members/WorkspaceMemberDetailsRoleSelectionModal.tsx b/src/pages/workspace/members/WorkspaceMemberDetailsRoleSelectionModal.tsx index 9613a697013e..f1d4334f7069 100644 --- a/src/pages/workspace/members/WorkspaceMemberDetailsRoleSelectionModal.tsx +++ b/src/pages/workspace/members/WorkspaceMemberDetailsRoleSelectionModal.tsx @@ -43,7 +43,10 @@ function WorkspaceMemberDetailsRoleSelectionModal({isVisible, items, onRoleChang hideModalContentWhileAnimating useNativeDriver > - + Date: Fri, 12 Apr 2024 22:28:31 +0200 Subject: [PATCH 20/27] feat: change new arch flash list to interop --- ios/Podfile.lock | 19 +- patches/@shopify+flash-list+1.6.3.patch | 1360 ----------------------- react-native.config.js | 7 +- 3 files changed, 6 insertions(+), 1380 deletions(-) delete mode 100644 patches/@shopify+flash-list+1.6.3.patch diff --git a/ios/Podfile.lock b/ios/Podfile.lock index f9244c515a2c..46df966d80d3 100644 --- a/ios/Podfile.lock +++ b/ios/Podfile.lock @@ -1794,24 +1794,7 @@ PODS: - React-Core - RNFBApp - RNFlashList (1.6.3): - - glog - - hermes-engine - - RCT-Folly (= 2022.05.16.00) - - RCTRequired - - RCTTypeSafety - - React-Codegen - React-Core - - React-debug - - React-Fabric - - React-graphics - - React-ImageManager - - React-NativeModulesApple - - React-RCTFabric - - React-rendererdebug - - React-utils - - ReactCommon/turbomodule/bridging - - ReactCommon/turbomodule/core - - Yoga - RNFS (2.20.0): - React-Core - RNGestureHandler (2.14.1): @@ -2561,7 +2544,7 @@ SPEC CHECKSUMS: RNFBApp: 729c0666395b1953198dc4a1ec6deb8fbe1c302e RNFBCrashlytics: 2061ca863e8e2fa1aae9b12477d7dfa8e88ca0f9 RNFBPerf: 389914cda4000fe0d996a752532a591132cbf3f9 - RNFlashList: 5b0e8311e4cf1ad91e410fd7c8526a89fb5826d1 + RNFlashList: 4b4b6b093afc0df60ae08f9cbf6ccd4c836c667a RNFS: 4ac0f0ea233904cb798630b3c077808c06931688 RNGestureHandler: 1190c218cdaaf029ee1437076a3fbbc3297d89fb RNGoogleSignin: ccaa4a81582cf713eea562c5dd9dc1961a715fd0 diff --git a/patches/@shopify+flash-list+1.6.3.patch b/patches/@shopify+flash-list+1.6.3.patch deleted file mode 100644 index 4910bb20b4ec..000000000000 --- a/patches/@shopify+flash-list+1.6.3.patch +++ /dev/null @@ -1,1360 +0,0 @@ -diff --git a/node_modules/@shopify/flash-list/CHANGELOG.md b/node_modules/@shopify/flash-list/CHANGELOG.md -deleted file mode 100644 -index 9c6bc58..0000000 ---- a/node_modules/@shopify/flash-list/CHANGELOG.md -+++ /dev/null -@@ -1,279 +0,0 @@ --# Changelog -- --All notable changes to this project will be documented in this file. -- --The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) --and adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html). -- --## [Unreleased] -- --## [1.6.3] - 2023-11-09 -- --- Changes for RN 0.73 support -- - https://github.com/Shopify/flash-list/pull/930 -- --## [1.6.2] - 2023-10-19 -- --- Move shouldRefreshWithAnchoring configuration so it is possible to disable it from outside FlashList by invalidating layout -- - https://github.com/Shopify/flash-list/pull/935 -- --## [1.6.1] - 2023-09-14 -- --- Prevent an expired layout provider from being used again -- - https://github.com/Shopify/flash-list/pull/915 -- --## [1.6.0] - 2023-09-13 -- --- Update types to match `react-native@0.72` view types. -- - https://github.com/Shopify/flash-list/pull/890 --- Add option to clear cached layouts on update -- - https://github.com/Shopify/flash-list/pull/910 -- --## [1.5.0] - 2023-07-12 -- --- Update kotlin version to 1.8.10 for RN 0.72 compatibility -- - https://github.com/Shopify/flash-list/pull/865 -- --## [1.4.3] - 2023-04-24 -- --- Fix definition conflicts with previous value -- - https://github.com/Shopify/flash-list/pull/795 --- Fix Android unit test -- - https://github.com/Shopify/flash-list/pull/815 --- Fix performance issues with inverted lists on Android -- - https://github.com/Shopify/flash-list/pull/819 -- --## [1.4.2] - 2023-03-20 -- --- Apply layout correction only to consecutive cells -- - https://github.com/Shopify/flash-list/pull/788 -- --## [1.4.1] - 2023-01-24 -- --- Prevent overflow of sticky headers -- - https://github.com/Shopify/flash-list/pull/714 --- Skip footer correction when layout correction is skipped -- - https://github.com/Shopify/flash-list/pull/743 -- --## [1.4.0] - 2022-11-07 -- --- Add content padding support to FlashList -- - https://github.com/Shopify/flash-list/pull/626 --- Upgrade recyclerlistview to v4.2.0 -- - https://github.com/Shopify/flash-list/pull/660 -- --## [1.3.1] - 2022-10-11 -- --- Expose `columnIndex` and `columnSpan` to `MasonryFlashList.renderItem` -- - https://github.com/Shopify/flash-list/pull/625 -- --## [1.3.0] - 2022-09-26 -- --- Added `MasonryFlashList` which adds support for rendering masonry layouts -- - https://github.com/Shopify/flash-list/pull/587 -- --## [1.2.2] - 2022-09-06 -- --- Fixes type checking error in `AutoLayoutView` due to `children` not being an explicit type -- - https://github.com/Shopify/flash-list/pull/567 -- --## [1.2.1] - 2022-08-03 -- --- Fixed crash when `estimatedListSize` is used in an empty list -- - https://github.com/Shopify/flash-list/pull/546 -- --## [1.2.0] - 2022-07-18 -- --- Fixed out of bound read from data -- - https://github.com/Shopify/flash-list/pull/523 --- Added JS only fallbacks for unsupported platforms -- - https://github.com/Shopify/flash-list/pull/518 --- Added footer correction in AutoLayoutView -- - https://github.com/Shopify/flash-list/pull/519 --- Added `viewPosition` and `viewOffset` support scrollTo methods -- - https://github.com/Shopify/flash-list/pull/521 --- Fix inverted mode while being horizontal -- - https://github.com/Shopify/flash-list/pull/520 --- Upgrade recyclerlistview to v4.1.1 -- - https://github.com/Shopify/flash-list/pull/526 -- --## [1.1.0] - 2022-07-06 -- --- Added render target info to `renderItem` callback -- - https://github.com/Shopify/flash-list/pull/454 --- Add Apple TV support -- - https://github.com/Shopify/flash-list/pull/511 --- Clarify installation instructions in Expo projects -- - https://github.com/Shopify/flash-list/pull/497 --- Upgrade recyclerlistview to v4.0.1 -- - https://github.com/Shopify/flash-list/pull/507 --- Add tslib as a dependency -- - https://github.com/Shopify/flash-list/pull/514 -- --## [1.0.4] - 2022-07-02 -- --- Build fix for Android projects having `kotlinVersion` defined in `build.gradle`. --- Allow providing an external scrollview. -- - https://github.com/Shopify/flash-list/pull/502 -- --## [1.0.3] - 2022-07-01 -- --- Add kotlin-gradle-plugin to buildscript in project build.gradle -- - https://github.com/Shopify/flash-list/pull/481 -- --## [1.0.2] - 2022-06-30 -- --- Minor changes -- --## [1.0.1] - 2022-06-30 -- --- `data` prop change will force update items only if `renderItem` is also updated -- - https://github.com/Shopify/flash-list/pull/453 -- --## [1.0.0] - 2022-06-17 -- --- Upgrade recyclerlistview to v3.3.0-beta.2 -- - https://github.com/Shopify/flash-list/pull/445 --- Added web support -- - https://github.com/Shopify/flash-list/pull/444 --- Added `disableAutoLayout` prop to prevent conflicts with custom `CellRendererComponent` -- - https://github.com/Shopify/flash-list/pull/452 -- --## [0.6.1] - 2022-05-26 -- --- Fix amending layout on iOS -- - https://github.com/Shopify/flash-list/pull/412 --- Define `FlashList` props previously inherited from `VirtualizedList` and `FlatList` explicitly -- - https://github.com/Shopify/flash-list/pull/386 --- Make `estimatedItemSize` optional -- - https://github.com/Shopify/flash-list/pull/378 --- Change `overrideItemType` prop name to `getItemType` -- - https://github.com/Shopify/flash-list/pull/369 --- Added `useBlankAreaTracker` hook for tracking blank area in production -- - https://github.com/Shopify/flash-list/pull/411 --- Added `CellRendererComponent` prop -- - https://github.com/Shopify/flash-list/pull/362 --- Added automatic height measurement for horizontal lists even when parent isn't deterministic -- - https://github.com/Shopify/flash-list/pull/409 -- --## [0.5.0] - 2022-04-29 -- --- Fix finding props with testId -- - https://github.com/Shopify/flash-list/pull/357 --- Reuse cached layouts on orientation change -- - https://github.com/Shopify/flash-list/pull/319 -- --## [0.4.6] - 2022-04-13 -- --- Match FlashList's empty list behavior with FlatList -- - https://github.com/Shopify/flash-list/pull/312 -- --## [0.4.5] - 2022-04-13 -- --- Upgrade recyclerlistview to v3.2.0-beta.4 -- -- - https://github.com/Shopify/flash-list/pull/315 -- --- Add viewability callbacks -- -- - https://github.com/Shopify/flash-list/pull/301 -- --- Calculate average item sizes automatically -- - https://github.com/Shopify/flash-list/pull/296 -- --## [0.4.4] - 2022-04-06 -- --- Fix `FlashList` mock when no data is provided -- - https://github.com/Shopify/flash-list/pull/295 -- --## [0.4.3] - 2022-04-04 -- --- Reduce number of render item calls -- -- - https://github.com/Shopify/flash-list/pull/253 -- --- Upgrade recyclerlistview to v3.2.0-beta.2 -- - https://github.com/Shopify/flash-list/pull/284 -- --## [0.4.2] - 2022-04-04 -- --- Minor changes -- --## [0.4.1] - 2022-03-29 -- --- Crash fix for android activity switching (#256) -- -- - https://github.com/Shopify/flash-list/pull/257 -- --- initialScrollIndex, scrollTo methods will now account for size of header -- -- - https://github.com/Shopify/flash-list/pull/194 -- --- Added a new mock for easier testing of components with `FlashList` -- - https://github.com/Shopify/flash-list/pull/236 -- --## [0.4.0] - 2022-03-23 -- --- Add support for layout animations -- -- - https://github.com/Shopify/flash-list/pull/183 -- --- Suppress recyclerlistview's bounded size exception for some missing cases. -- -- - https://github.com/Shopify/flash-list/pull/192 -- --- Expose reference to recyclerlistview and firstItemOffset -- -- - https://github.com/Shopify/flash-list/pull/217 -- --- recyclerlistview upgraded to v3.1.0-alpha.9 -- - https://github.com/Shopify/flash-list/pull/227 -- --## [0.3.3] - 2022-03-16 -- --- Prevent implicit scroll to top on device orientation change --- Change recyclerlistview's bounded size exception to a warning -- - https://github.com/Shopify/flash-list/pull/187 -- --## [0.3.2] - 2022-03-15 -- --- Minor changes -- --## [0.3.1] - 2022-03-15 -- --- Revert react-native-safe-area upgrade and minSdkVersion bump -- - https://github.com/Shopify/flash-list/pull/184 -- --## [0.3.0] - 2022-03-15 -- --- Fixed untranspiled library code by enforcing stricter TS rules. -- - https://github.com/Shopify/flash-list/pull/181 -- --## [0.2.4] - 2022-03-14 -- --- Added `onLoad` event that is called once the list has rendered items. This is required because FlashList doesn't render items in the first cycle. -- - https://github.com/Shopify/flash-list/pull/180 -- --## [0.2.3] - 2022-03-10 -- --- Fixing publish steps for transpiled code -- - https://github.com/Shopify/flash-list/pull/150 -- --## [0.2.2] - 2022-03-10 -- --- Fixing publish steps for transpiled code -- - https://github.com/Shopify/flash-list/pull/149 -- --## [0.2.1] - 2022-03-09 -- --- Bug fix for style and last separator -- - https://github.com/Shopify/flash-list/pull/141 -- --## [0.2.0] - 2022-03-08 -- --- Rename the component from `RecyclerFlatList` to `FlashList` -- - https://github.com/Shopify/flash-list/pull/140 -- --## [0.1.0] - 2022-03-02 -- --- Initial release -diff --git a/node_modules/@shopify/flash-list/RNFlashList.podspec b/node_modules/@shopify/flash-list/RNFlashList.podspec -index 38ff029..a749f6c 100644 ---- a/node_modules/@shopify/flash-list/RNFlashList.podspec -+++ b/node_modules/@shopify/flash-list/RNFlashList.podspec -@@ -9,14 +9,20 @@ Pod::Spec.new do |s| - s.homepage = package['homepage'] - s.license = package['license'] - s.author = package['author'] -- s.platforms = { :ios => '11.0', :tvos => '12.0' } - s.source = { git: 'https://github.com/shopify/flash-list.git', tag: "v#{s.version}" } - s.source_files = 'ios/Sources/**/*' - s.requires_arc = true - s.swift_version = '5.0' -+ s.pod_target_xcconfig = { 'OTHER_SWIFT_FLAGS' => '-D RCT_NEW_ARCH_ENABLED', } - -- # Dependencies -- s.dependency 'React-Core' -+ if defined?(install_modules_dependencies()) != nil -+ install_modules_dependencies(s) -+ s.ios.deployment_target = "12.4" -+ s.platforms = { :ios => '12.4', :tvos => '12.0' } -+ else -+ s.dependency "React-Core" -+ s.platforms = { :ios => '11.0', :tvos => '12.0' } -+ end - - # Tests spec - s.test_spec 'Tests' do |test_spec| -diff --git a/node_modules/@shopify/flash-list/android/build.gradle b/node_modules/@shopify/flash-list/android/build.gradle -index bed08cd..bad4465 100644 ---- a/node_modules/@shopify/flash-list/android/build.gradle -+++ b/node_modules/@shopify/flash-list/android/build.gradle -@@ -1,7 +1,14 @@ --apply plugin: 'com.android.library' -+def isNewArchitectureEnabled() { -+ return project.hasProperty("newArchEnabled") && project.newArchEnabled == "true" -+} - -+apply plugin: 'com.android.library' - apply plugin: 'kotlin-android' - -+if (isNewArchitectureEnabled()) { -+ apply plugin: 'com.facebook.react' -+} -+ - def _ext = rootProject.ext - - def _reactNativeVersion = _ext.has('reactNative') ? _ext.reactNative : '+' -@@ -40,11 +47,19 @@ android { - debug.java.srcDirs += 'src/debug/kotlin' - test.java.srcDirs += 'src/test/kotlin' - androidTest.java.srcDirs += 'src/androidTest/kotlin' -+ -+ if (isNewArchitectureEnabled()) { -+ main.java.srcDirs += ["${project.buildDir}/generated/source/codegen/java"] -+ main.java.srcDirs += ["src/fabric/java"] -+ } else { -+ main.java.srcDirs += ['src/paper/java'] -+ } - } - - defaultConfig { - minSdkVersion _minSdkVersion - targetSdkVersion _targetSdkVersion -+ buildConfigField "boolean", "IS_NEW_ARCHITECTURE_ENABLED", isNewArchitectureEnabled().toString() - versionCode 1 - versionName "1.0" - testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" -@@ -61,7 +76,7 @@ android { - - dependencies { - compileOnly "com.facebook.react:react-native:${_reactNativeVersion}" -- implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:${_kotlinVersion}" -+ implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:${_kotlinVersion}" - testImplementation "junit:junit:${_junitVersion}" - testImplementation "org.mockito.kotlin:mockito-kotlin:${_mockitoVersion}" - testImplementation "org.mockito:mockito-inline:${_mockitoVersion}" -diff --git a/node_modules/@shopify/flash-list/android/src/fabric/java/com/shopify/reactnative/flash_list/ReactContextExtensions.kt b/node_modules/@shopify/flash-list/android/src/fabric/java/com/shopify/reactnative/flash_list/ReactContextExtensions.kt -new file mode 100644 -index 0000000..6e850fe ---- /dev/null -+++ b/node_modules/@shopify/flash-list/android/src/fabric/java/com/shopify/reactnative/flash_list/ReactContextExtensions.kt -@@ -0,0 +1,12 @@ -+package com.shopify.reactnative.flash_list -+ -+import com.facebook.react.bridge.ReactContext -+import com.facebook.react.fabric.FabricUIManager -+import com.facebook.react.uimanager.UIManagerHelper -+import com.facebook.react.uimanager.common.UIManagerType -+import com.facebook.react.bridge.WritableMap -+ -+fun ReactContext.dispatchEvent(nativeTag: Int, eventName: String, event: WritableMap) { -+ val fabricUIManager = UIManagerHelper.getUIManager(this, UIManagerType.FABRIC) as FabricUIManager -+ fabricUIManager.receiveEvent(nativeTag, eventName, event) -+} -diff --git a/node_modules/@shopify/flash-list/android/src/main/kotlin/com/shopify/reactnative/flash_list/AutoLayoutView.kt b/node_modules/@shopify/flash-list/android/src/main/kotlin/com/shopify/reactnative/flash_list/AutoLayoutView.kt -index 4571798..c6c3cce 100644 ---- a/node_modules/@shopify/flash-list/android/src/main/kotlin/com/shopify/reactnative/flash_list/AutoLayoutView.kt -+++ b/node_modules/@shopify/flash-list/android/src/main/kotlin/com/shopify/reactnative/flash_list/AutoLayoutView.kt -@@ -2,8 +2,6 @@ package com.shopify.reactnative.flash_list - - import android.content.Context - import android.graphics.Canvas --import android.util.DisplayMetrics --import android.util.Log - import android.view.View - import android.view.ViewGroup - import android.widget.HorizontalScrollView -@@ -11,7 +9,6 @@ import android.widget.ScrollView - import com.facebook.react.bridge.Arguments - import com.facebook.react.bridge.ReactContext - import com.facebook.react.bridge.WritableMap --import com.facebook.react.uimanager.events.RCTEventEmitter - import com.facebook.react.views.view.ReactViewGroup - - -@@ -142,9 +139,8 @@ class AutoLayoutView(context: Context) : ReactViewGroup(context) { - val event: WritableMap = Arguments.createMap() - event.putDouble("offsetStart", alShadow.blankOffsetAtStart / pixelDensity) - event.putDouble("offsetEnd", alShadow.blankOffsetAtEnd / pixelDensity) -+ - val reactContext = context as ReactContext -- reactContext -- .getJSModule(RCTEventEmitter::class.java) -- .receiveEvent(id, "onBlankAreaEvent", event) -+ reactContext.dispatchEvent(id, "onBlankAreaEvent", event) - } - } -diff --git a/node_modules/@shopify/flash-list/android/src/main/kotlin/com/shopify/reactnative/flash_list/AutoLayoutViewManager.kt b/node_modules/@shopify/flash-list/android/src/main/kotlin/com/shopify/reactnative/flash_list/AutoLayoutViewManager.kt -index b646f09..7bda0ea 100644 ---- a/node_modules/@shopify/flash-list/android/src/main/kotlin/com/shopify/reactnative/flash_list/AutoLayoutViewManager.kt -+++ b/node_modules/@shopify/flash-list/android/src/main/kotlin/com/shopify/reactnative/flash_list/AutoLayoutViewManager.kt -@@ -3,15 +3,22 @@ package com.shopify.reactnative.flash_list - import com.facebook.react.module.annotations.ReactModule - import com.facebook.react.uimanager.ThemedReactContext - import com.facebook.react.uimanager.annotations.ReactProp --import com.facebook.react.views.view.ReactViewGroup --import com.facebook.react.views.view.ReactViewManager -+import com.facebook.react.uimanager.ViewGroupManager -+import com.facebook.react.uimanager.ViewManagerDelegate -+import com.facebook.react.viewmanagers.AutoLayoutViewManagerDelegate -+import com.facebook.react.viewmanagers.AutoLayoutViewManagerInterface - import com.facebook.react.common.MapBuilder - import kotlin.math.roundToInt - - /** ViewManager for AutoLayoutView - Container for all RecyclerListView children. Automatically removes all gaps and overlaps for GridLayouts with flexible spans. - * Note: This cannot work for masonry layouts i.e, pinterest like layout */ - @ReactModule(name = AutoLayoutViewManager.REACT_CLASS) --class AutoLayoutViewManager: ReactViewManager() { -+class AutoLayoutViewManager: ViewGroupManager(), AutoLayoutViewManagerInterface { -+ private val mDelegate: ViewManagerDelegate -+ -+ init { -+ mDelegate = AutoLayoutViewManagerDelegate(this) -+ } - - companion object { - const val REACT_CLASS = "AutoLayoutView" -@@ -21,45 +28,42 @@ class AutoLayoutViewManager: ReactViewManager() { - return REACT_CLASS - } - -- override fun createViewInstance(context: ThemedReactContext): ReactViewGroup { -+ override fun createViewInstance(context: ThemedReactContext): AutoLayoutView { - return AutoLayoutView(context).also { it.pixelDensity = context.resources.displayMetrics.density.toDouble() } - } - -- override fun getExportedCustomDirectEventTypeConstants(): MutableMap { -- return MapBuilder.builder().put( -- "onBlankAreaEvent", -- MapBuilder.of( -- "registrationName", "onBlankAreaEvent") -- ).build(); -- } -+ override fun getExportedCustomDirectEventTypeConstants() = mutableMapOf( -+ "onBlankAreaEvent" to mutableMapOf("registrationName" to "onBlankAreaEvent"), -+ "topOnBlankAreaEvent" to mutableMapOf("registrationName" to "onBlankAreaEvent"), -+ ) - - @ReactProp(name = "horizontal") -- fun setHorizontal(view: AutoLayoutView, isHorizontal: Boolean) { -+ override fun setHorizontal(view: AutoLayoutView, isHorizontal: Boolean) { - view.alShadow.horizontal = isHorizontal - } - - @ReactProp(name = "disableAutoLayout") -- fun setDisableAutoLayout(view: AutoLayoutView, disableAutoLayout: Boolean) { -+ override fun setDisableAutoLayout(view: AutoLayoutView, disableAutoLayout: Boolean) { - view.disableAutoLayout = disableAutoLayout - } - - @ReactProp(name = "scrollOffset") -- fun setScrollOffset(view: AutoLayoutView, scrollOffset: Double) { -+ override fun setScrollOffset(view: AutoLayoutView, scrollOffset: Double) { - view.alShadow.scrollOffset = convertToPixelLayout(scrollOffset, view.pixelDensity) - } - - @ReactProp(name = "windowSize") -- fun setWindowSize(view: AutoLayoutView, windowSize: Double) { -+ override fun setWindowSize(view: AutoLayoutView, windowSize: Double) { - view.alShadow.windowSize = convertToPixelLayout(windowSize, view.pixelDensity) - } - - @ReactProp(name = "renderAheadOffset") -- fun setRenderAheadOffset(view: AutoLayoutView, renderOffset: Double) { -+ override fun setRenderAheadOffset(view: AutoLayoutView, renderOffset: Double) { - view.alShadow.renderOffset = convertToPixelLayout(renderOffset, view.pixelDensity) - } - - @ReactProp(name = "enableInstrumentation") -- fun setEnableInstrumentation(view: AutoLayoutView, enableInstrumentation: Boolean) { -+ override fun setEnableInstrumentation(view: AutoLayoutView, enableInstrumentation: Boolean) { - view.enableInstrumentation = enableInstrumentation - } - -diff --git a/node_modules/@shopify/flash-list/android/src/main/kotlin/com/shopify/reactnative/flash_list/CellContainerManager.kt b/node_modules/@shopify/flash-list/android/src/main/kotlin/com/shopify/reactnative/flash_list/CellContainerManager.kt -index 1434caa..590ba1d 100644 ---- a/node_modules/@shopify/flash-list/android/src/main/kotlin/com/shopify/reactnative/flash_list/CellContainerManager.kt -+++ b/node_modules/@shopify/flash-list/android/src/main/kotlin/com/shopify/reactnative/flash_list/CellContainerManager.kt -@@ -2,12 +2,20 @@ package com.shopify.reactnative.flash_list - - import com.facebook.react.module.annotations.ReactModule - import com.facebook.react.uimanager.ThemedReactContext -+import com.facebook.react.uimanager.ViewGroupManager -+import com.facebook.react.uimanager.ViewManagerDelegate - import com.facebook.react.uimanager.annotations.ReactProp --import com.facebook.react.views.view.ReactViewGroup --import com.facebook.react.views.view.ReactViewManager -+import com.facebook.react.viewmanagers.CellContainerManagerDelegate -+import com.facebook.react.viewmanagers.CellContainerManagerInterface - - @ReactModule(name = AutoLayoutViewManager.REACT_CLASS) --class CellContainerManager: ReactViewManager() { -+class CellContainerManager: ViewGroupManager(), CellContainerManagerInterface { -+ private val mDelegate: ViewManagerDelegate -+ -+ init { -+ mDelegate = CellContainerManagerDelegate(this); -+ } -+ - companion object { - const val REACT_CLASS = "CellContainer" - } -@@ -16,12 +24,12 @@ class CellContainerManager: ReactViewManager() { - return REACT_CLASS - } - -- override fun createViewInstance(context: ThemedReactContext): ReactViewGroup { -+ override fun createViewInstance(context: ThemedReactContext): CellContainerImpl { - return CellContainerImpl(context) - } - - @ReactProp(name = "index") -- fun setIndex(view: CellContainerImpl, index: Int) { -+ override fun setIndex(view: CellContainerImpl, index: Int) { - view.index = index - } - } -diff --git a/node_modules/@shopify/flash-list/android/src/paper/java/com/facebook/react/viewmanagers/AutoLayoutViewManagerDelegate.java b/node_modules/@shopify/flash-list/android/src/paper/java/com/facebook/react/viewmanagers/AutoLayoutViewManagerDelegate.java -new file mode 100644 -index 0000000..4c90807 ---- /dev/null -+++ b/node_modules/@shopify/flash-list/android/src/paper/java/com/facebook/react/viewmanagers/AutoLayoutViewManagerDelegate.java -@@ -0,0 +1,46 @@ -+/** -+* This code was generated by [react-native-codegen](https://www.npmjs.com/package/react-native-codegen). -+* -+* Do not edit this file as changes may cause incorrect behavior and will be lost -+* once the code is regenerated. -+* -+* @generated by codegen project: GeneratePropsJavaDelegate.js -+*/ -+ -+package com.facebook.react.viewmanagers; -+ -+import android.view.View; -+import androidx.annotation.Nullable; -+import com.facebook.react.uimanager.BaseViewManagerDelegate; -+import com.facebook.react.uimanager.BaseViewManagerInterface; -+ -+public class AutoLayoutViewManagerDelegate & AutoLayoutViewManagerInterface> extends BaseViewManagerDelegate { -+ public AutoLayoutViewManagerDelegate(U viewManager) { -+ super(viewManager); -+ } -+ @Override -+ public void setProperty(T view, String propName, @Nullable Object value) { -+ switch (propName) { -+ case "horizontal": -+ mViewManager.setHorizontal(view, value == null ? false : (boolean) value); -+ break; -+ case "scrollOffset": -+ mViewManager.setScrollOffset(view, value == null ? 0f : ((Double) value).doubleValue()); -+ break; -+ case "windowSize": -+ mViewManager.setWindowSize(view, value == null ? 0f : ((Double) value).doubleValue()); -+ break; -+ case "renderAheadOffset": -+ mViewManager.setRenderAheadOffset(view, value == null ? 0f : ((Double) value).doubleValue()); -+ break; -+ case "enableInstrumentation": -+ mViewManager.setEnableInstrumentation(view, value == null ? false : (boolean) value); -+ break; -+ case "disableAutoLayout": -+ mViewManager.setDisableAutoLayout(view, value == null ? false : (boolean) value); -+ break; -+ default: -+ super.setProperty(view, propName, value); -+ } -+ } -+} -diff --git a/node_modules/@shopify/flash-list/android/src/paper/java/com/facebook/react/viewmanagers/AutoLayoutViewManagerInterface.java b/node_modules/@shopify/flash-list/android/src/paper/java/com/facebook/react/viewmanagers/AutoLayoutViewManagerInterface.java -new file mode 100644 -index 0000000..8ad2622 ---- /dev/null -+++ b/node_modules/@shopify/flash-list/android/src/paper/java/com/facebook/react/viewmanagers/AutoLayoutViewManagerInterface.java -@@ -0,0 +1,21 @@ -+/** -+* This code was generated by [react-native-codegen](https://www.npmjs.com/package/react-native-codegen). -+* -+* Do not edit this file as changes may cause incorrect behavior and will be lost -+* once the code is regenerated. -+* -+* @generated by codegen project: GeneratePropsJavaInterface.js -+*/ -+ -+package com.facebook.react.viewmanagers; -+ -+import android.view.View; -+ -+public interface AutoLayoutViewManagerInterface { -+ void setHorizontal(T view, boolean value); -+ void setScrollOffset(T view, double value); -+ void setWindowSize(T view, double value); -+ void setRenderAheadOffset(T view, double value); -+ void setEnableInstrumentation(T view, boolean value); -+ void setDisableAutoLayout(T view, boolean value); -+} -diff --git a/node_modules/@shopify/flash-list/android/src/paper/java/com/facebook/react/viewmanagers/CellContainerManagerDelegate.java b/node_modules/@shopify/flash-list/android/src/paper/java/com/facebook/react/viewmanagers/CellContainerManagerDelegate.java -new file mode 100644 -index 0000000..2b64af7 ---- /dev/null -+++ b/node_modules/@shopify/flash-list/android/src/paper/java/com/facebook/react/viewmanagers/CellContainerManagerDelegate.java -@@ -0,0 +1,31 @@ -+/** -+* This code was generated by [react-native-codegen](https://www.npmjs.com/package/react-native-codegen). -+* -+* Do not edit this file as changes may cause incorrect behavior and will be lost -+* once the code is regenerated. -+* -+* @generated by codegen project: GeneratePropsJavaDelegate.js -+*/ -+ -+package com.facebook.react.viewmanagers; -+ -+import android.view.View; -+import androidx.annotation.Nullable; -+import com.facebook.react.uimanager.BaseViewManagerDelegate; -+import com.facebook.react.uimanager.BaseViewManagerInterface; -+ -+public class CellContainerManagerDelegate & CellContainerManagerInterface> extends BaseViewManagerDelegate { -+ public CellContainerManagerDelegate(U viewManager) { -+ super(viewManager); -+ } -+ @Override -+ public void setProperty(T view, String propName, @Nullable Object value) { -+ switch (propName) { -+ case "index": -+ mViewManager.setIndex(view, value == null ? 0 : ((Double) value).intValue()); -+ break; -+ default: -+ super.setProperty(view, propName, value); -+ } -+ } -+} -diff --git a/node_modules/@shopify/flash-list/android/src/paper/java/com/facebook/react/viewmanagers/CellContainerManagerInterface.java b/node_modules/@shopify/flash-list/android/src/paper/java/com/facebook/react/viewmanagers/CellContainerManagerInterface.java -new file mode 100644 -index 0000000..b37ddbd ---- /dev/null -+++ b/node_modules/@shopify/flash-list/android/src/paper/java/com/facebook/react/viewmanagers/CellContainerManagerInterface.java -@@ -0,0 +1,16 @@ -+/** -+* This code was generated by [react-native-codegen](https://www.npmjs.com/package/react-native-codegen). -+* -+* Do not edit this file as changes may cause incorrect behavior and will be lost -+* once the code is regenerated. -+* -+* @generated by codegen project: GeneratePropsJavaInterface.js -+*/ -+ -+package com.facebook.react.viewmanagers; -+ -+import android.view.View; -+ -+public interface CellContainerManagerInterface { -+ void setIndex(T view, int value); -+} -diff --git a/node_modules/@shopify/flash-list/android/src/paper/java/com/shopify/reactnative/flash_list/ReactContextExtensions.kt b/node_modules/@shopify/flash-list/android/src/paper/java/com/shopify/reactnative/flash_list/ReactContextExtensions.kt -new file mode 100644 -index 0000000..b867c18 ---- /dev/null -+++ b/node_modules/@shopify/flash-list/android/src/paper/java/com/shopify/reactnative/flash_list/ReactContextExtensions.kt -@@ -0,0 +1,10 @@ -+package com.shopify.reactnative.flash_list -+ -+import com.facebook.react.bridge.ReactContext -+import com.facebook.react.uimanager.events.RCTEventEmitter -+import com.facebook.react.bridge.WritableMap -+ -+fun ReactContext.dispatchEvent(nativeTag: Int, eventName: String, event: WritableMap) { -+ this.getJSModule(RCTEventEmitter::class.java) -+ .receiveEvent(nativeTag, eventName, event) -+} -diff --git a/node_modules/@shopify/flash-list/dist/FlashList.d.ts b/node_modules/@shopify/flash-list/dist/FlashList.d.ts -index ed81d7d..1e24103 100644 ---- a/node_modules/@shopify/flash-list/dist/FlashList.d.ts -+++ b/node_modules/@shopify/flash-list/dist/FlashList.d.ts -@@ -103,6 +103,7 @@ declare class FlashList extends React.PureComponent, FlashL - offset: number; - }): void; - getScrollableNode(): number | null; -+ getNativeScrollRef(): number | null; - /** - * Allows access to internal recyclerlistview. This is useful for enabling access to its public APIs. - * Warning: We may swap recyclerlistview for something else in the future. Use with caution. -diff --git a/node_modules/@shopify/flash-list/dist/FlashList.d.ts.map b/node_modules/@shopify/flash-list/dist/FlashList.d.ts.map -index 97c8cc6..a915a05 100644 ---- a/node_modules/@shopify/flash-list/dist/FlashList.d.ts.map -+++ b/node_modules/@shopify/flash-list/dist/FlashList.d.ts.map -@@ -1 +1 @@ --{"version":3,"file":"FlashList.d.ts","sourceRoot":"","sources":["../src/FlashList.tsx"],"names":[],"mappings":"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"} -\ No newline at end of file -+{"version":3,"file":"FlashList.d.ts","sourceRoot":"","sources":["../src/FlashList.tsx"],"names":[],"mappings":"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"} -\ No newline at end of file -diff --git a/node_modules/@shopify/flash-list/dist/FlashList.js b/node_modules/@shopify/flash-list/dist/FlashList.js -index 1a5d026..37852b8 100644 ---- a/node_modules/@shopify/flash-list/dist/FlashList.js -+++ b/node_modules/@shopify/flash-list/dist/FlashList.js -@@ -478,6 +478,12 @@ var FlashList = /** @class */ (function (_super) { - var _a, _b; - return ((_b = (_a = this.rlvRef) === null || _a === void 0 ? void 0 : _a.getScrollableNode) === null || _b === void 0 ? void 0 : _b.call(_a)) || null; - }; -+ FlashList.prototype.getNativeScrollRef = function () { -+ var _a, _b; -+ // eslint-disable-next-line @typescript-eslint/ban-ts-comment -+ // @ts-ignore -+ return ((_b = (_a = this.rlvRef) === null || _a === void 0 ? void 0 : _a.getNativeScrollRef) === null || _b === void 0 ? void 0 : _b.call(_a)) || null; -+ }; - Object.defineProperty(FlashList.prototype, "recyclerlistview_unsafe", { - /** - * Allows access to internal recyclerlistview. This is useful for enabling access to its public APIs. -diff --git a/node_modules/@shopify/flash-list/dist/FlashList.js.map b/node_modules/@shopify/flash-list/dist/FlashList.js.map -index 375f7fc..8fc9c3f 100644 ---- a/node_modules/@shopify/flash-list/dist/FlashList.js.map -+++ b/node_modules/@shopify/flash-list/dist/FlashList.js.map -@@ -1 +1 @@ --{"version":3,"file":"FlashList.js","sourceRoot":"","sources":["../src/FlashList.tsx"],"names":[],"mappings":"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"} -\ No newline at end of file -+{"version":3,"file":"FlashList.js","sourceRoot":"","sources":["../src/FlashList.tsx"],"names":[],"mappings":"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"} -\ No newline at end of file -diff --git a/node_modules/@shopify/flash-list/dist/fabric/AutoLayoutNativeComponent.d.ts b/node_modules/@shopify/flash-list/dist/fabric/AutoLayoutNativeComponent.d.ts -new file mode 100644 -index 0000000..661dc81 ---- /dev/null -+++ b/node_modules/@shopify/flash-list/dist/fabric/AutoLayoutNativeComponent.d.ts -@@ -0,0 +1,18 @@ -+import type { ViewProps } from "react-native"; -+import type { Int32, Double, DirectEventHandler } from "react-native/Libraries/Types/CodegenTypes"; -+declare type BlankAreaEvent = Readonly<{ -+ offsetStart: Int32; -+ offsetEnd: Int32; -+}>; -+interface NativeProps extends ViewProps { -+ horizontal?: boolean; -+ scrollOffset?: Double; -+ windowSize?: Double; -+ renderAheadOffset?: Double; -+ enableInstrumentation?: boolean; -+ disableAutoLayout?: boolean; -+ onBlankAreaEvent?: DirectEventHandler; -+} -+declare const _default: import("react-native/Libraries/Utilities/codegenNativeComponent").NativeComponentType; -+export default _default; -+//# sourceMappingURL=AutoLayoutNativeComponent.d.ts.map -\ No newline at end of file -diff --git a/node_modules/@shopify/flash-list/dist/fabric/AutoLayoutNativeComponent.d.ts.map b/node_modules/@shopify/flash-list/dist/fabric/AutoLayoutNativeComponent.d.ts.map -new file mode 100644 -index 0000000..25297b9 ---- /dev/null -+++ b/node_modules/@shopify/flash-list/dist/fabric/AutoLayoutNativeComponent.d.ts.map -@@ -0,0 +1 @@ -+{"version":3,"file":"AutoLayoutNativeComponent.d.ts","sourceRoot":"","sources":["../../src/fabric/AutoLayoutNativeComponent.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAC9C,OAAO,KAAK,EACV,KAAK,EACL,MAAM,EACN,kBAAkB,EACnB,MAAM,2CAA2C,CAAC;AAEnD,aAAK,cAAc,GAAG,QAAQ,CAAC;IAC7B,WAAW,EAAE,KAAK,CAAC;IACnB,SAAS,EAAE,KAAK,CAAC;CAClB,CAAC,CAAC;AAEH,UAAU,WAAY,SAAQ,SAAS;IACrC,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,qBAAqB,CAAC,EAAE,OAAO,CAAC;IAChC,iBAAiB,CAAC,EAAE,OAAO,CAAC;IAC5B,gBAAgB,CAAC,EAAE,kBAAkB,CAAC,cAAc,CAAC,CAAC;CACvD;;AAED,wBAAqE"} -\ No newline at end of file -diff --git a/node_modules/@shopify/flash-list/dist/fabric/AutoLayoutNativeComponent.js b/node_modules/@shopify/flash-list/dist/fabric/AutoLayoutNativeComponent.js -new file mode 100644 -index 0000000..c69ba24 ---- /dev/null -+++ b/node_modules/@shopify/flash-list/dist/fabric/AutoLayoutNativeComponent.js -@@ -0,0 +1,6 @@ -+"use strict"; -+Object.defineProperty(exports, "__esModule", { value: true }); -+var tslib_1 = require("tslib"); -+var codegenNativeComponent_1 = tslib_1.__importDefault(require("react-native/Libraries/Utilities/codegenNativeComponent")); -+exports.default = (0, codegenNativeComponent_1.default)("AutoLayoutView"); -+//# sourceMappingURL=AutoLayoutNativeComponent.js.map -\ No newline at end of file -diff --git a/node_modules/@shopify/flash-list/dist/fabric/AutoLayoutNativeComponent.js.map b/node_modules/@shopify/flash-list/dist/fabric/AutoLayoutNativeComponent.js.map -new file mode 100644 -index 0000000..890db63 ---- /dev/null -+++ b/node_modules/@shopify/flash-list/dist/fabric/AutoLayoutNativeComponent.js.map -@@ -0,0 +1 @@ -+{"version":3,"file":"AutoLayoutNativeComponent.js","sourceRoot":"","sources":["../../src/fabric/AutoLayoutNativeComponent.ts"],"names":[],"mappings":";;;AAAA,2HAA6F;AAuB7F,kBAAe,IAAA,gCAAsB,EAAc,gBAAgB,CAAC,CAAC"} -\ No newline at end of file -diff --git a/node_modules/@shopify/flash-list/dist/fabric/CellContainerNativeComponent.d.ts b/node_modules/@shopify/flash-list/dist/fabric/CellContainerNativeComponent.d.ts -new file mode 100644 -index 0000000..bb8f63b ---- /dev/null -+++ b/node_modules/@shopify/flash-list/dist/fabric/CellContainerNativeComponent.d.ts -@@ -0,0 +1,8 @@ -+import type { Int32 } from "react-native/Libraries/Types/CodegenTypes"; -+import type { ViewProps } from "react-native"; -+interface NativeProps extends ViewProps { -+ index?: Int32; -+} -+declare const _default: import("react-native/Libraries/Utilities/codegenNativeComponent").NativeComponentType; -+export default _default; -+//# sourceMappingURL=CellContainerNativeComponent.d.ts.map -\ No newline at end of file -diff --git a/node_modules/@shopify/flash-list/dist/fabric/CellContainerNativeComponent.d.ts.map b/node_modules/@shopify/flash-list/dist/fabric/CellContainerNativeComponent.d.ts.map -new file mode 100644 -index 0000000..993a2c3 ---- /dev/null -+++ b/node_modules/@shopify/flash-list/dist/fabric/CellContainerNativeComponent.d.ts.map -@@ -0,0 +1 @@ -+{"version":3,"file":"CellContainerNativeComponent.d.ts","sourceRoot":"","sources":["../../src/fabric/CellContainerNativeComponent.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,2CAA2C,CAAC;AACvE,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAE9C,UAAU,WAAY,SAAQ,SAAS;IACrC,KAAK,CAAC,EAAE,KAAK,CAAC;CACf;;AAED,wBAAoE"} -\ No newline at end of file -diff --git a/node_modules/@shopify/flash-list/dist/fabric/CellContainerNativeComponent.js b/node_modules/@shopify/flash-list/dist/fabric/CellContainerNativeComponent.js -new file mode 100644 -index 0000000..b21acb7 ---- /dev/null -+++ b/node_modules/@shopify/flash-list/dist/fabric/CellContainerNativeComponent.js -@@ -0,0 +1,6 @@ -+"use strict"; -+Object.defineProperty(exports, "__esModule", { value: true }); -+var tslib_1 = require("tslib"); -+var codegenNativeComponent_1 = tslib_1.__importDefault(require("react-native/Libraries/Utilities/codegenNativeComponent")); -+exports.default = (0, codegenNativeComponent_1.default)("CellContainer"); -+//# sourceMappingURL=CellContainerNativeComponent.js.map -\ No newline at end of file -diff --git a/node_modules/@shopify/flash-list/dist/fabric/CellContainerNativeComponent.js.map b/node_modules/@shopify/flash-list/dist/fabric/CellContainerNativeComponent.js.map -new file mode 100644 -index 0000000..d7c2469 ---- /dev/null -+++ b/node_modules/@shopify/flash-list/dist/fabric/CellContainerNativeComponent.js.map -@@ -0,0 +1 @@ -+{"version":3,"file":"CellContainerNativeComponent.js","sourceRoot":"","sources":["../../src/fabric/CellContainerNativeComponent.ts"],"names":[],"mappings":";;;AAAA,2HAA6F;AAQ7F,kBAAe,IAAA,gCAAsB,EAAc,eAAe,CAAC,CAAC"} -\ No newline at end of file -diff --git a/node_modules/@shopify/flash-list/dist/tsconfig.tsbuildinfo b/node_modules/@shopify/flash-list/dist/tsconfig.tsbuildinfo -deleted file mode 100644 -index 023b94a..0000000 ---- a/node_modules/@shopify/flash-list/dist/tsconfig.tsbuildinfo -+++ /dev/null -@@ -1 +0,0 @@ --{"program":{"fileNames":["../node_modules/typescript/lib/lib.es5.d.ts","../node_modules/typescript/lib/lib.es2015.d.ts","../node_modules/typescript/lib/lib.es2016.d.ts","../node_modules/typescript/lib/lib.es2017.d.ts","../node_modules/typescript/lib/lib.es2018.d.ts","../node_modules/typescript/lib/lib.es2019.d.ts","../node_modules/typescript/lib/lib.es2020.d.ts","../node_modules/typescript/lib/lib.dom.d.ts","../node_modules/typescript/lib/lib.dom.iterable.d.ts","../node_modules/typescript/lib/lib.es2015.core.d.ts","../node_modules/typescript/lib/lib.es2015.collection.d.ts","../node_modules/typescript/lib/lib.es2015.generator.d.ts","../node_modules/typescript/lib/lib.es2015.iterable.d.ts","../node_modules/typescript/lib/lib.es2015.promise.d.ts","../node_modules/typescript/lib/lib.es2015.proxy.d.ts","../node_modules/typescript/lib/lib.es2015.reflect.d.ts","../node_modules/typescript/lib/lib.es2015.symbol.d.ts","../node_modules/typescript/lib/lib.es2015.symbol.wellknown.d.ts","../node_modules/typescript/lib/lib.es2016.array.include.d.ts","../node_modules/typescript/lib/lib.es2017.object.d.ts","../node_modules/typescript/lib/lib.es2017.sharedmemory.d.ts","../node_modules/typescript/lib/lib.es2017.string.d.ts","../node_modules/typescript/lib/lib.es2017.intl.d.ts","../node_modules/typescript/lib/lib.es2017.typedarrays.d.ts","../node_modules/typescript/lib/lib.es2018.asyncgenerator.d.ts","../node_modules/typescript/lib/lib.es2018.asynciterable.d.ts","../node_modules/typescript/lib/lib.es2018.intl.d.ts","../node_modules/typescript/lib/lib.es2018.promise.d.ts","../node_modules/typescript/lib/lib.es2018.regexp.d.ts","../node_modules/typescript/lib/lib.es2019.array.d.ts","../node_modules/typescript/lib/lib.es2019.object.d.ts","../node_modules/typescript/lib/lib.es2019.string.d.ts","../node_modules/typescript/lib/lib.es2019.symbol.d.ts","../node_modules/typescript/lib/lib.es2020.bigint.d.ts","../node_modules/typescript/lib/lib.es2020.date.d.ts","../node_modules/typescript/lib/lib.es2020.promise.d.ts","../node_modules/typescript/lib/lib.es2020.sharedmemory.d.ts","../node_modules/typescript/lib/lib.es2020.string.d.ts","../node_modules/typescript/lib/lib.es2020.symbol.wellknown.d.ts","../node_modules/typescript/lib/lib.es2020.intl.d.ts","../node_modules/typescript/lib/lib.es2020.number.d.ts","../node_modules/typescript/lib/lib.esnext.intl.d.ts","../node_modules/tslib/tslib.d.ts","../node_modules/@types/react-native/modules/BatchedBridge.d.ts","../node_modules/@types/react-native/modules/Codegen.d.ts","../node_modules/@types/react-native/modules/Devtools.d.ts","../node_modules/@types/react-native/modules/globals.d.ts","../node_modules/@types/react-native/modules/LaunchScreen.d.ts","../node_modules/@types/react/global.d.ts","../node_modules/csstype/index.d.ts","../node_modules/@types/prop-types/index.d.ts","../node_modules/@types/scheduler/tracing.d.ts","../node_modules/@types/react/index.d.ts","../node_modules/@types/react-native/private/Utilities.d.ts","../node_modules/@types/react-native/public/Insets.d.ts","../node_modules/@types/react-native/Libraries/ReactNative/RendererProxy.d.ts","../node_modules/@types/react-native/public/ReactNativeTypes.d.ts","../node_modules/@types/react-native/Libraries/Types/CoreEventTypes.d.ts","../node_modules/@types/react-native/public/ReactNativeRenderer.d.ts","../node_modules/@types/react-native/Libraries/Components/Touchable/Touchable.d.ts","../node_modules/@types/react-native/Libraries/Components/View/ViewAccessibility.d.ts","../node_modules/@types/react-native/Libraries/Components/View/ViewPropTypes.d.ts","../node_modules/@types/react-native/Libraries/Components/RefreshControl/RefreshControl.d.ts","../node_modules/@types/react-native/Libraries/Components/ScrollView/ScrollView.d.ts","../node_modules/@types/react-native/Libraries/Components/View/View.d.ts","../node_modules/@types/react-native/Libraries/Image/ImageResizeMode.d.ts","../node_modules/@types/react-native/Libraries/Image/ImageSource.d.ts","../node_modules/@types/react-native/Libraries/Image/Image.d.ts","../node_modules/@react-native/virtualized-lists/Lists/VirtualizedList.d.ts","../node_modules/@react-native/virtualized-lists/index.d.ts","../node_modules/@types/react-native/Libraries/Lists/FlatList.d.ts","../node_modules/@types/react-native/Libraries/Lists/SectionList.d.ts","../node_modules/@types/react-native/Libraries/Text/Text.d.ts","../node_modules/@types/react-native/Libraries/Animated/Animated.d.ts","../node_modules/@types/react-native/Libraries/StyleSheet/StyleSheetTypes.d.ts","../node_modules/@types/react-native/Libraries/StyleSheet/StyleSheet.d.ts","../node_modules/@types/react-native/Libraries/StyleSheet/processColor.d.ts","../node_modules/@types/react-native/Libraries/ActionSheetIOS/ActionSheetIOS.d.ts","../node_modules/@types/react-native/Libraries/Alert/Alert.d.ts","../node_modules/@types/react-native/Libraries/Animated/Easing.d.ts","../node_modules/@types/react-native/Libraries/Animated/useAnimatedValue.d.ts","../node_modules/@types/react-native/Libraries/vendor/emitter/EventEmitter.d.ts","../node_modules/@types/react-native/Libraries/EventEmitter/RCTDeviceEventEmitter.d.ts","../node_modules/@types/react-native/Libraries/EventEmitter/RCTNativeAppEventEmitter.d.ts","../node_modules/@types/react-native/Libraries/AppState/AppState.d.ts","../node_modules/@types/react-native/Libraries/BatchedBridge/NativeModules.d.ts","../node_modules/@types/react-native/Libraries/Components/AccessibilityInfo/AccessibilityInfo.d.ts","../node_modules/@types/react-native/Libraries/Components/ActivityIndicator/ActivityIndicator.d.ts","../node_modules/@types/react-native/Libraries/Components/Clipboard/Clipboard.d.ts","../node_modules/@types/react-native/Libraries/Components/DrawerAndroid/DrawerLayoutAndroid.d.ts","../node_modules/@types/react-native/Libraries/EventEmitter/NativeEventEmitter.d.ts","../node_modules/@types/react-native/Libraries/Components/Keyboard/Keyboard.d.ts","../node_modules/@types/react-native/private/TimerMixin.d.ts","../node_modules/@types/react-native/Libraries/Components/Keyboard/KeyboardAvoidingView.d.ts","../node_modules/@types/react-native/Libraries/Components/Pressable/Pressable.d.ts","../node_modules/@types/react-native/Libraries/Components/ProgressBarAndroid/ProgressBarAndroid.d.ts","../node_modules/@types/react-native/Libraries/Components/SafeAreaView/SafeAreaView.d.ts","../node_modules/@types/react-native/Libraries/Components/StatusBar/StatusBar.d.ts","../node_modules/@types/react-native/Libraries/Components/Switch/Switch.d.ts","../node_modules/@types/react-native/Libraries/Components/TextInput/InputAccessoryView.d.ts","../node_modules/@types/react-native/Libraries/Components/TextInput/TextInput.d.ts","../node_modules/@types/react-native/Libraries/Components/ToastAndroid/ToastAndroid.d.ts","../node_modules/@types/react-native/Libraries/Components/Touchable/TouchableWithoutFeedback.d.ts","../node_modules/@types/react-native/Libraries/Components/Touchable/TouchableHighlight.d.ts","../node_modules/@types/react-native/Libraries/Components/Touchable/TouchableOpacity.d.ts","../node_modules/@types/react-native/Libraries/Components/Touchable/TouchableNativeFeedback.d.ts","../node_modules/@types/react-native/Libraries/Components/Button.d.ts","../node_modules/@types/react-native/Libraries/DevToolsSettings/DevToolsSettingsManager.d.ts","../node_modules/@types/react-native/Libraries/Interaction/InteractionManager.d.ts","../node_modules/@types/react-native/Libraries/Interaction/PanResponder.d.ts","../node_modules/@types/react-native/Libraries/LayoutAnimation/LayoutAnimation.d.ts","../node_modules/@types/react-native/Libraries/Linking/Linking.d.ts","../node_modules/@types/react-native/Libraries/LogBox/LogBox.d.ts","../node_modules/@types/react-native/Libraries/Modal/Modal.d.ts","../node_modules/@types/react-native/Libraries/Performance/Systrace.d.ts","../node_modules/@types/react-native/Libraries/PermissionsAndroid/PermissionsAndroid.d.ts","../node_modules/@types/react-native/Libraries/PushNotificationIOS/PushNotificationIOS.d.ts","../node_modules/@types/react-native/Libraries/Utilities/IPerformanceLogger.d.ts","../node_modules/@types/react-native/Libraries/ReactNative/AppRegistry.d.ts","../node_modules/@types/react-native/Libraries/ReactNative/I18nManager.d.ts","../node_modules/@types/react-native/Libraries/ReactNative/RootTag.d.ts","../node_modules/@types/react-native/Libraries/ReactNative/UIManager.d.ts","../node_modules/@types/react-native/Libraries/ReactNative/requireNativeComponent.d.ts","../node_modules/@types/react-native/Libraries/Settings/Settings.d.ts","../node_modules/@types/react-native/Libraries/Share/Share.d.ts","../node_modules/@types/react-native/Libraries/StyleSheet/PlatformColorValueTypesIOS.d.ts","../node_modules/@types/react-native/Libraries/StyleSheet/PlatformColorValueTypes.d.ts","../node_modules/@types/react-native/Libraries/TurboModule/RCTExport.d.ts","../node_modules/@types/react-native/Libraries/TurboModule/TurboModuleRegistry.d.ts","../node_modules/@types/react-native/Libraries/Utilities/Appearance.d.ts","../node_modules/@types/react-native/Libraries/Utilities/BackHandler.d.ts","../node_modules/@types/react-native/Libraries/Utilities/DevSettings.d.ts","../node_modules/@types/react-native/Libraries/Utilities/Dimensions.d.ts","../node_modules/@types/react-native/Libraries/Utilities/PixelRatio.d.ts","../node_modules/@types/react-native/Libraries/Utilities/Platform.d.ts","../node_modules/@types/react-native/Libraries/Vibration/Vibration.d.ts","../node_modules/@types/react-native/Libraries/YellowBox/YellowBoxDeprecated.d.ts","../node_modules/@types/react-native/Libraries/vendor/core/ErrorUtils.d.ts","../node_modules/@types/react-native/public/DeprecatedPropertiesAlias.d.ts","../node_modules/@types/react-native/index.d.ts","../node_modules/recyclerlistview/dist/reactnative/core/dependencies/ContextProvider.d.ts","../node_modules/recyclerlistview/dist/reactnative/core/dependencies/DataProvider.d.ts","../node_modules/recyclerlistview/dist/reactnative/core/layoutmanager/LayoutManager.d.ts","../node_modules/recyclerlistview/dist/reactnative/core/dependencies/LayoutProvider.d.ts","../node_modules/recyclerlistview/dist/reactnative/core/dependencies/GridLayoutProvider.d.ts","../node_modules/recyclerlistview/dist/reactnative/core/scrollcomponent/BaseScrollView.d.ts","../node_modules/recyclerlistview/dist/reactnative/core/ViewabilityTracker.d.ts","../node_modules/recyclerlistview/dist/reactnative/core/VirtualRenderer.d.ts","../node_modules/recyclerlistview/dist/reactnative/core/ItemAnimator.d.ts","../node_modules/recyclerlistview/dist/reactnative/utils/ComponentCompat.d.ts","../node_modules/recyclerlistview/dist/reactnative/core/RecyclerListView.d.ts","../node_modules/recyclerlistview/dist/reactnative/utils/AutoScroll.d.ts","../node_modules/recyclerlistview/dist/reactnative/core/layoutmanager/GridLayoutManager.d.ts","../node_modules/recyclerlistview/dist/reactnative/core/ProgressiveListView.d.ts","../node_modules/recyclerlistview/dist/reactnative/core/devutils/debughandlers/resize/ResizeDebugHandler.d.ts","../node_modules/recyclerlistview/dist/reactnative/core/devutils/debughandlers/DebugHandlers.d.ts","../node_modules/recyclerlistview/dist/reactnative/index.d.ts","../node_modules/recyclerlistview/dist/reactnative/core/StickyContainer.d.ts","../node_modules/recyclerlistview/sticky/index.d.ts","../src/native/auto-layout/AutoLayoutViewNativeComponentProps.ts","../src/native/auto-layout/AutoLayoutViewNativeComponent.ts","../src/native/auto-layout/AutoLayoutView.tsx","../src/native/cell-container/CellContainer.tsx","../src/PureComponentWrapper.tsx","../src/viewability/ViewToken.ts","../src/FlashListProps.ts","../src/utils/AverageWindow.ts","../src/utils/ContentContainerUtils.ts","../src/GridLayoutProviderWithProps.ts","../src/errors/CustomError.ts","../src/errors/ExceptionList.ts","../src/errors/Warnings.ts","../src/viewability/ViewabilityHelper.ts","../src/viewability/ViewabilityManager.ts","../node_modules/recyclerlistview/dist/reactnative/platform/reactnative/itemanimators/defaultjsanimator/DefaultJSItemAnimator.d.ts","../src/native/config/PlatformHelper.ts","../src/FlashList.tsx","../src/AnimatedFlashList.ts","../src/MasonryFlashList.tsx","../src/benchmark/AutoScrollHelper.ts","../src/benchmark/roundToDecimalPlaces.ts","../src/benchmark/JSFPSMonitor.ts","../src/benchmark/useBlankAreaTracker.ts","../src/benchmark/useBenchmark.ts","../src/benchmark/useDataMultiplier.ts","../src/benchmark/useFlatListBenchmark.ts","../src/index.ts","../src/__tests__/AverageWindow.test.ts","../src/__tests__/ContentContainerUtils.test.ts","../node_modules/@quilted/react-testing/build/typescript/types.d.ts","../node_modules/@quilted/react-testing/build/typescript/matchers/index.d.ts","../node_modules/@quilted/react-testing/build/typescript/environment.d.ts","../node_modules/@quilted/react-testing/build/typescript/implementations/test-renderer.d.ts","../node_modules/@quilted/react-testing/build/typescript/index.d.ts","../src/__tests__/helpers/mountFlashList.tsx","../src/__tests__/FlashList.test.tsx","../src/__tests__/GridLayoutProviderWithProps.test.ts","../src/__tests__/helpers/mountMasonryFlashList.tsx","../src/__tests__/MasonryFlashList.test.ts","../src/native/config/PlatformHelper.web.ts","../src/__tests__/PlatformHelper.web.test.ts","../src/__tests__/ViewabilityHelper.test.ts","../src/__tests__/useBlankAreaTracker.test.tsx","../src/native/auto-layout/AutoLayoutViewNativeComponent.android.ts","../src/native/auto-layout/AutoLayoutViewNativeComponent.ios.ts","../src/native/cell-container/CellContainer.android.ts","../src/native/cell-container/CellContainer.ios.ts","../src/native/cell-container/CellContainer.web.tsx","../src/native/config/PlatformHelper.android.ts","../src/native/config/PlatformHelper.ios.ts","../node_modules/@babel/types/lib/index.d.ts","../node_modules/@types/babel__generator/index.d.ts","../node_modules/@babel/parser/typings/babel-parser.d.ts","../node_modules/@types/babel__template/index.d.ts","../node_modules/@types/babel__traverse/index.d.ts","../node_modules/@types/babel__core/index.d.ts","../node_modules/@types/node/assert.d.ts","../node_modules/@types/node/assert/strict.d.ts","../node_modules/@types/node/globals.d.ts","../node_modules/@types/node/async_hooks.d.ts","../node_modules/@types/node/buffer.d.ts","../node_modules/@types/node/child_process.d.ts","../node_modules/@types/node/cluster.d.ts","../node_modules/@types/node/console.d.ts","../node_modules/@types/node/constants.d.ts","../node_modules/@types/node/crypto.d.ts","../node_modules/@types/node/dgram.d.ts","../node_modules/@types/node/diagnostics_channel.d.ts","../node_modules/@types/node/dns.d.ts","../node_modules/@types/node/dns/promises.d.ts","../node_modules/@types/node/domain.d.ts","../node_modules/@types/node/events.d.ts","../node_modules/@types/node/fs.d.ts","../node_modules/@types/node/fs/promises.d.ts","../node_modules/@types/node/http.d.ts","../node_modules/@types/node/http2.d.ts","../node_modules/@types/node/https.d.ts","../node_modules/@types/node/inspector.d.ts","../node_modules/@types/node/module.d.ts","../node_modules/@types/node/net.d.ts","../node_modules/@types/node/os.d.ts","../node_modules/@types/node/path.d.ts","../node_modules/@types/node/perf_hooks.d.ts","../node_modules/@types/node/process.d.ts","../node_modules/@types/node/punycode.d.ts","../node_modules/@types/node/querystring.d.ts","../node_modules/@types/node/readline.d.ts","../node_modules/@types/node/repl.d.ts","../node_modules/@types/node/stream.d.ts","../node_modules/@types/node/stream/promises.d.ts","../node_modules/@types/node/stream/consumers.d.ts","../node_modules/@types/node/stream/web.d.ts","../node_modules/@types/node/string_decoder.d.ts","../node_modules/@types/node/timers.d.ts","../node_modules/@types/node/timers/promises.d.ts","../node_modules/@types/node/tls.d.ts","../node_modules/@types/node/trace_events.d.ts","../node_modules/@types/node/tty.d.ts","../node_modules/@types/node/url.d.ts","../node_modules/@types/node/util.d.ts","../node_modules/@types/node/v8.d.ts","../node_modules/@types/node/vm.d.ts","../node_modules/@types/node/wasi.d.ts","../node_modules/@types/node/worker_threads.d.ts","../node_modules/@types/node/zlib.d.ts","../node_modules/@types/node/globals.global.d.ts","../node_modules/@types/node/index.d.ts","../node_modules/@types/graceful-fs/index.d.ts","../node_modules/@types/istanbul-lib-coverage/index.d.ts","../node_modules/@types/istanbul-lib-report/index.d.ts","../node_modules/@types/istanbul-reports/index.d.ts","../node_modules/chalk/index.d.ts","../node_modules/@sinclair/typebox/typebox.d.ts","../node_modules/@jest/schemas/build/index.d.ts","../node_modules/pretty-format/build/index.d.ts","../node_modules/jest-diff/build/index.d.ts","../node_modules/jest-matcher-utils/build/index.d.ts","../node_modules/@types/jest/index.d.ts","../node_modules/@types/json-schema/index.d.ts","../node_modules/@types/json5/index.d.ts","../node_modules/@types/parse-json/index.d.ts","../node_modules/@types/prettier/index.d.ts","../node_modules/@types/react-test-renderer/index.d.ts","../node_modules/@types/scheduler/index.d.ts","../node_modules/@types/stack-utils/index.d.ts","../node_modules/@types/websocket/index.d.ts","../node_modules/@types/yargs-parser/index.d.ts","../node_modules/@types/yargs/index.d.ts"],"fileInfos":[{"version":"f5c28122bee592cfaf5c72ed7bcc47f453b79778ffa6e301f45d21a0970719d4","affectsGlobalScope":true},"dc47c4fa66b9b9890cf076304de2a9c5201e94b740cffdf09f87296d877d71f6","7a387c58583dfca701b6c85e0adaf43fb17d590fb16d5b2dc0a2fbd89f35c467","8a12173c586e95f4433e0c6dc446bc88346be73ffe9ca6eec7aa63c8f3dca7f9","5f4e733ced4e129482ae2186aae29fde948ab7182844c3a5a51dd346182c7b06","e6b724280c694a9f588847f754198fb96c43d805f065c3a5b28bbc9594541c84","1fc5ab7a764205c68fa10d381b08417795fc73111d6dd16b5b1ed36badb743d9",{"version":"3f149f903dd20dfeb7c80e228b659f0e436532de772469980dbd00702cc05cc1","affectsGlobalScope":true},{"version":"1272277fe7daa738e555eb6cc45ded42cc2d0f76c07294142283145d49e96186","affectsGlobalScope":true},{"version":"adb996790133eb33b33aadb9c09f15c2c575e71fb57a62de8bf74dbf59ec7dfb","affectsGlobalScope":true},{"version":"43fb1d932e4966a39a41b464a12a81899d9ae5f2c829063f5571b6b87e6d2f9c","affectsGlobalScope":true},{"version":"cdccba9a388c2ee3fd6ad4018c640a471a6c060e96f1232062223063b0a5ac6a","affectsGlobalScope":true},{"version":"c5c05907c02476e4bde6b7e76a79ffcd948aedd14b6a8f56e4674221b0417398","affectsGlobalScope":true},{"version":"0d5f52b3174bee6edb81260ebcd792692c32c81fd55499d69531496f3f2b25e7","affectsGlobalScope":true},{"version":"810627a82ac06fb5166da5ada4159c4ec11978dfbb0805fe804c86406dab8357","affectsGlobalScope":true},{"version":"181f1784c6c10b751631b24ce60c7f78b20665db4550b335be179217bacc0d5f","affectsGlobalScope":true},{"version":"3013574108c36fd3aaca79764002b3717da09725a36a6fc02eac386593110f93","affectsGlobalScope":true},{"version":"75ec0bdd727d887f1b79ed6619412ea72ba3c81d92d0787ccb64bab18d261f14","affectsGlobalScope":true},{"version":"3be5a1453daa63e031d266bf342f3943603873d890ab8b9ada95e22389389006","affectsGlobalScope":true},{"version":"17bb1fc99591b00515502d264fa55dc8370c45c5298f4a5c2083557dccba5a2a","affectsGlobalScope":true},{"version":"7ce9f0bde3307ca1f944119f6365f2d776d281a393b576a18a2f2893a2d75c98","affectsGlobalScope":true},{"version":"6a6b173e739a6a99629a8594bfb294cc7329bfb7b227f12e1f7c11bc163b8577","affectsGlobalScope":true},{"version":"12a310447c5d23c7d0d5ca2af606e3bd08afda69100166730ab92c62999ebb9d","affectsGlobalScope":true},{"version":"b0124885ef82641903d232172577f2ceb5d3e60aed4da1153bab4221e1f6dd4e","affectsGlobalScope":true},{"version":"0eb85d6c590b0d577919a79e0084fa1744c1beba6fd0d4e951432fa1ede5510a","affectsGlobalScope":true},{"version":"da233fc1c8a377ba9e0bed690a73c290d843c2c3d23a7bd7ec5cd3d7d73ba1e0","affectsGlobalScope":true},{"version":"d154ea5bb7f7f9001ed9153e876b2d5b8f5c2bb9ec02b3ae0d239ec769f1f2ae","affectsGlobalScope":true},{"version":"bb2d3fb05a1d2ffbca947cc7cbc95d23e1d053d6595391bd325deb265a18d36c","affectsGlobalScope":true},{"version":"c80df75850fea5caa2afe43b9949338ce4e2de086f91713e9af1a06f973872b8","affectsGlobalScope":true},{"version":"9d57b2b5d15838ed094aa9ff1299eecef40b190722eb619bac4616657a05f951","affectsGlobalScope":true},{"version":"6c51b5dd26a2c31dbf37f00cfc32b2aa6a92e19c995aefb5b97a3a64f1ac99de","affectsGlobalScope":true},{"version":"6e7997ef61de3132e4d4b2250e75343f487903ddf5370e7ce33cf1b9db9a63ed","affectsGlobalScope":true},{"version":"2ad234885a4240522efccd77de6c7d99eecf9b4de0914adb9a35c0c22433f993","affectsGlobalScope":true},{"version":"09aa50414b80c023553090e2f53827f007a301bc34b0495bfb2c3c08ab9ad1eb","affectsGlobalScope":true},{"version":"d7f680a43f8cd12a6b6122c07c54ba40952b0c8aa140dcfcf32eb9e6cb028596","affectsGlobalScope":true},{"version":"3787b83e297de7c315d55d4a7c546ae28e5f6c0a361b7a1dcec1f1f50a54ef11","affectsGlobalScope":true},{"version":"e7e8e1d368290e9295ef18ca23f405cf40d5456fa9f20db6373a61ca45f75f40","affectsGlobalScope":true},{"version":"faf0221ae0465363c842ce6aa8a0cbda5d9296940a8e26c86e04cc4081eea21e","affectsGlobalScope":true},{"version":"06393d13ea207a1bfe08ec8d7be562549c5e2da8983f2ee074e00002629d1871","affectsGlobalScope":true},{"version":"cd483c056da900716879771893a3c9772b66c3c88f8943b4205aec738a94b1d0","affectsGlobalScope":true},{"version":"b248e32ca52e8f5571390a4142558ae4f203ae2f94d5bac38a3084d529ef4e58","affectsGlobalScope":true},{"version":"c37f8a49593a0030eecb51bbfa270e709bec9d79a6cc3bb851ef348d4e6b26f8","affectsGlobalScope":true},"14a84fbe4ec531dcbaf5d2594fd95df107258e60ae6c6a076404f13c3f66f28e",{"version":"1c0e04c54479b57b49fec4e93556974b3d071b65d0b750897e07b3b7d2145fc5","affectsGlobalScope":true},"bc1852215dc1488e6747ca43ae0605041de22ab9a6eeef39542d29837919c414","ae6da60c852e7bacc4a49ff14a42dc1a3fdbb44e11bd9b4acb1bf3d58866ee71",{"version":"0dab023e564abb43c817779fff766e125017e606db344f9633fdba330c970532","affectsGlobalScope":true},"4cbd76eafece5844dc0a32807e68047aecbdd8d863edba651f34c050624f18df",{"version":"ecf78e637f710f340ec08d5d92b3f31b134a46a4fcf2e758690d8c46ce62cba6","affectsGlobalScope":true},"ea0aa24a32c073b8639aa1f3130ba0add0f0f2f76b314d9ba988a5cb91d7e3c4","f7b46d22a307739c145e5fddf537818038fdfffd580d79ed717f4d4d37249380","f5a8b384f182b3851cec3596ccc96cb7464f8d3469f48c74bf2befb782a19de5",{"version":"29b8a3a533884705024eab54e56465614ad167f5dd87fdc2567d8e451f747224","affectsGlobalScope":true},"4f2490e3f420ea6345cade9aee5eada76888848e053726956aaf2af8705477ea","b3ac03d0c853c0ac076a10cfef4dc21d810f54dac5899ade2b1c628c35263533","d17a689ac1bd689f37d6f0d3d9a21afac349e60633844044f7a7b7b9d6f7fd83","019650941b03d4978f62d21ae874788a665c02b54e3268ef2029b02d3b4f7561","ae591c8a4d5c7f7fa44b6965016391457d9c1fd763475f68340599a2a2987a24","fbdef0c642b82cc1713b965f07b4da8005bbbb2c026039bfdc15ca2d20769e38","c2c004e7f1a150541d06bc4a408b96e45ac1f08e0b1b35dfd07fc0f678205f95","1f2081eb2cbeb0828f9baa1dd12cf6d207f8104ae0b085ab9975d11adc7f7e6f","cda9069fc4c312ff484c1373455e4297a02d38ae3bd7d0959aad772a2809623c","c028d20108bcaa3b1fdf3514956a8a90ccf680f18672fa3c92ce5acf81d7ab23","1054f6e8774a75aaf17e7cfea4899344f69590b2db1e06da21048ed1e063c693","9533301b8f75664e1b40a8484a4fd9c77efc04aef526409c2447aab7d12ddc63","b78b5b3fdb4e30976c4263c66c0ad38fb81edcc8075a4160a39d99c6dedd35be","032b51d656feaece529823992f5a39fe9e24d44dfa21b3a149982f7787fc7bdf","5bbfdfb694b019cb2a2022fba361a7a857efc1fc2b77a892c92ebc1349b7e984","46bc25e3501d321a70d0878e82a1d47b16ab77bdf017c8fecc76343f50806a0d","42bacb33cddecbcfe3e043ee1117ba848801749e44f947626765b3e0aec74b1c","49dba0d7a37268e6ae2026e84ad4362eac7e776d816756abf649be7fa177dcd5","5f2b5ab209daae571eb9acc1fd2067ccc94e2a13644579a245875bc4f02b562f","f072acf9547f89b814b9fdb3e72f4ebb1649191591cec99db43d35383906f87f","42450dba65ba1307f27c914a8e45e0b602c6f8f78773c052e42b0b87562f081e","f5870d0ca7b0dfb7e2b9ba9abad3a2e2bffe5c711b53dab2e6e76ca2df58302b","aeb20169389e9f508b1a4eb2a30371b64d64bb7c8543120bc39a3c6b78adfcc9","2a3d3acbab8567057a943f9f56113c0144f5fc561623749fbd6bb5c2b33bf738","9cf21fdcd1beb5142a514887133fa59057e06275bb3070713f3b6d51e830ffa0","0ad4f0b67db47064b404df89c50f99552ce12d6c4bb6154255be61eb6beed094","f8a464b9999126fe1095968c266c0d9c6174612cf256379a1ed1993a87bccdc6","49f981ca657ac160b5de5919ee5602d48bc8f8aac0805107c2ce4fd41dc9a2a1","56e4e08d95a3a7886266a2b4f66b67065c340480d9f1beb73ed7578aa83c639a","eb4360d3818dcd879ee965ae2f4b3fdfdc4149db921b6be338cb7dc7c2bd6710","1c1275f325f13af001aa5873418cb497a26b4b8271f9ad20a45e33f61ea3f9d9","b33e8426136c4f9b349b02c940d23310d350179f790899733aa097ed76457061","05aab001669a230a88820be09a54031c45d9af2488b27d53d4a9c8880ce73e8f","d93a066d4b8b33335dfff910fb25abb8979f8814f8ba45ea902a1360907da1f6","41e97e42d182b4d5f0733ebaad69294faaa507d95e595f317168b8f2325da9ca","debc734fc99b6e1684ed565946bad008913c769d4d2e400d8722c0c23d079c06","5a9f7e087aacb01fa0cdbc36b703a60367239f62beed2507a507199e4c417549","c7c23798fbf564983ed69c1ced3371970d986aaed4801a6e0fb41862550dc034","921f5bce372610ae8948ade7d82decbd2cf56d263de578976189585edd0abac0","ac11f8b13beef593e2f097450a7e214b23dca0d428babd570a2f39582f10e9ab","2499beb5d3e2b4c606977bcc2e08b6ef77b2ecda70e78e0622f5af3bed95c9ba","a11057410396907b84051cbdb8b0cd7f7049d72b58d2b6ac1c14ac2608191a52","bb630c26d487cc45ed107f4f2d3c2a95434716f6367f059de734c40d288c31eb","67cbce0ccdfa96b25de478a93cc493266c152e256c3c96b3d16d1f811e3d881f","19905c928bc4c016d05d915625bb08568447266c4661232faf89f7ddc4417ccc","26204eb4c326e8c975f1b789cbf345c6820205bded6d72e57246a83918d3bc84","618f25b2d41a99216e71817a3bc578991eee86c858c3f0f62a9e70707f4d279d","4cd2947878536ec078e4115b7d53cdcd4dcecd3a8288760caa79098db4f8f61f","2129e984399e94c82b77a32b975f3371ca5ee96341ab9f123474f1a5a1a9921f","798120aaa4952d68cd4b43d6625524c62a135c2f5a3eb705caee98de2355230d","6047365397173788c34bd71fea2bf07a9036d981212efd059b33e52d2c405e97","d7e25d7c03ccf8b10972c2a3a57e29a8d9024e6dbc4ac223baf633a6e8c7145c","6c2e2dead2d80007ee44c429b925d0a7b86f8f3d4c237b2197f7db9f39545dc6","38fbc8f9610fbf4bf619854b26e28c4fbbab16dc1944c4317a4af9bf1ac08d8e","1bd0470a72e6869c330e6e978f15ef32ba2c245249aca097b410448152e8a06b","dd05d7970a92b789f7df3b2252574b2e60f1b9a3758e2839e167b498b8f77159","7092be1889127b2f319efd5d9bdcc0b5cf6fe0740e47247ed039446045518898","0a3d5dbf7c2091017e697ebf9af0a727571f5d99cb4c19e6856212a745c6c355","d05f9c767924db6fb89f6075acb64c042cebdb12779bbd1aaca12c850b772d49","d032678e20ff0f4b8ef6f1e4823b6ae37931b776e8381676dc9141999909b3d7","3e4ab0e8e96e968ac84a2484104892c881ded1757acd81b5e969b6229851f54c","d43a36641f5812794a3b4a941e3dfb5fa070f9fff64cfd6daf5291cb962c8b05","32468df81188116040636844517fbe4f67fc37af4fe565c7592353df8e11d2f3","c12b5f9bf412c891cad443ef00a378ad2d3f1301f140943414308665a7d90af8","cf1b65c20036885ed99ce1c18aa0a0ed66f42acd6d415e99b48a8fa4105c23ed","173aec8be1be982c8244df6f94880d77a9b766c8c1ec3eb0af662c8dc6da7f2e","08188020373062e07955835a996fda1aff97a89e57d469edc6b9210bd9c8926f","cad5c2c0085a3e3b74f58aa199944b25ed8d24f93f51c99ebe2463e4f1694785","3e2d93a797c41ab081fbcd80e959b7c30d5d1c358f091c22a6ebe416ef7c5e19","c440df5735a3305e7db118bf821efb597c8318910861f735372846db9f7b506b","d6d8de719a75e5d2ed9dd9d6a99296d1337259e1c96166579db50797edd72ede","32b4c732e183bf5d123f88d526ac21b71a681089c18d2d761be342df31179d94","212d16020e7dce1b5509f3b9813de73612de57c6a3d74536714eb88787b96dc3","1a63d5212341783aa49cf78d667bf2a6cd03208ea09620b2fc3e647ae07f4e0d","84ea58841272970e6e3247cba4dbb326cf22764c2f4bbcb03f1c634315bbbcb5","86f9fbecdd848d02c90f861cc9839d8f3449c518a77e77ea65362f6a4126c63b","ecdaf317a4a1e7e3540e2f1b6aae38acd78dd99d564b52f98eea7358ac74416d","c30430960f1a0552b3cdaf1ef8164fdd4f289c782a8912df5180d57bc9ddfc03","a348081c01502c9f87d39d9e4b5dd58e1111b34c62686d6e569c595a0417bb35","eff69aee13c76502a16b756cde9c451fb4b5c4234052f3b3bee9dbfe92e1b1d5","9943f44400939f4ff008a882ff71162f70ba0c2f735c9743fd4645ef5c925fc4","b7836eba6c5173a1683aee8aa1771ff339e795cb9c21411590edb910274febe4","6fe447aa7e6fabc4f6c536f2997e3b1116b7f73dbe5bf3fc8d958bad434e4a84","15d3908d453d14be4dae760122ed5d74ad789a19f1fec2edd4034e57217436e9","ef00bc701f382da70870ab7721ed8f6552a38e332e60370b93cf340b6470845c","18891a02fa046e57b43a543dddc7212086fcb04ae6c8e8f28f8605dd3ccf57ed",{"version":"5980a888624dce1b0937a0d21c623f97056501bb61a8da29cbe07f1a0be2c9a8","affectsGlobalScope":true},"590a41ccab332c66a6aa62746612b03ceb2e92cc1da58c140e90fb7ff6e8c851","dc1d2996f23fe7f0da0b2c843e05c0ac170a36b51da11e58de089d344de93c3b","78ff01b50e7e9761f239527ec70b96171bccc28a08d909243e193db03b6f6983","ed18472ee2247563a26d754dd4c8bd66383013df13ce7c2927b03cab1a27b7e8","28ac9ac1fa163e5f2321fafa49b9931908c0076216ed3c82646d79abdf79775e","07dd4bed8ddab685f82a2125bf3aa41b42e36f28c16a5aec7357b727649076fb","fc15a2216f29b825747c0c3a54d6989518dd0f4aa0b580520e5526b4a47bec8f","c656d5baf3d4a8f358fc083db04b0fda8cb8503a613a9ba42327ecbd7909773c","397c2c81eaeae1388f7459699d7606feecfc304b212eb9113407c1315746a578","c2d923e9adc26a3efe5186f3a4a72413d24c80f03b306c68c30fa146690fb101","d34782833b7d5f72486a5fb926d3d96198706ed76aeaf1d435c748ebcf9169fc","b093e56054755189dd891ea832dec40d729d110a0a3f432fff5ea5ab1078cdde","98affe620e6230a3888b445c32376e4edbf6b1b376a71f2bf9c07bee11fcdd65","1e05491bef32ff48393d605d557152735899da3d9b111ba3588a1800f2927f4a","1ff7813974b1b9a0524c1e5a99aa52a05e79fc7df7749ada75ded8c53fe1b7e0","cd8c517f54d4ff3475755b290d741c8799df3265ce73d454d8fafe423f8ff749","bf431147b104ae92d61de6b43e9f25d27e8d3eaeaffd612e0c0d3bb8e2423926","f0f21604ae8f880c0ab529f00303806fdeadc943e32a25ca063fc8fea0fa063c","8dc4f45212fba9381e1674e8bd934a588730efbb8a6681b661cad8cd09b081c5",{"version":"52bf774bd30177ebb3e450c808d8d46f67896848a942e6203ae78b65b33d0106","signature":"688c437017a53e69ff66aac2036a0d7f6263082f676a408c9998cbd87ea2ec73"},{"version":"8b6ee36fd764378c62dca37041c5a12fd5a77b9e853c78908b7ed1c90dc149e4","signature":"03846acca031c757d910dbc017d846c87574faf90bde82316fb9b8537896d5ee"},{"version":"0d089d33f31b56697d142aa7395738c0323cf761b4c79fd6bf65a54ab1ddf02f","signature":"027c87e1cb049497d4f185bc9b922ce91cad59832da8faf3411e6b298b9deb78"},{"version":"ec0982b9e7d6c1b6c80e2829c5909eefb9ecee687e60621e0bb937e8ad5d1d43","signature":"8478b617a5be940f1b4b4d19d2fc6149c21ac69c4a7e00c8a7db2c2c21aa2274"},{"version":"84c5fc9d0d22f4566791b88d5fc2c24f56508b50c9ce894ac549ebaa158b1fca","signature":"677ea66c6fa02f1cebf82df19f416a8302c7a7d10e2de265b162760fcd865eef"},{"version":"8455135ea42310a73404fa2513e212d170af1191584061f583ec1e0f6b75dd91","signature":"83e4298f0b6834e955ee6a76569d3e5b3192065d47f1daf4535bb9edb16e88cb"},{"version":"73529962207605bdc5285d5e745919b8d57b776daa0f22a14b75cd8a92d63af9","signature":"422fcd2a7fd87f05efdfaa6eab382ca607d5d54e1f175ba2efccd4aacd5433ef"},{"version":"ebe927d8a9739c9d32ef4df28c1c36cf82daa9abba7cdf3f79e320c5e99e99d8","signature":"2421f9c6b1ecedd50818719090a77e9d2748c2339c33f3d4817beebf7a39d211"},{"version":"165c56632fea46c85e2a62f1b4eae600b846ea0deacd3c137fde9bacb845c30e","signature":"79bf9e3846b43e706d181c00f3c1c50ae8fc60e587c97a16e521adc150317624"},{"version":"866e1d2cf16a41851b056a2cc0cdc5f0f00df0435376cc2c723a8c609f61fbd0","signature":"5f5bbca60f0bfed6ff714163c4e962a5e260e59db754c89ee2063403accd03e3"},{"version":"ecfa1b63e3829b310ac968b2cc1cc7016ba76ffb8532439aebecbcbc57173b99","signature":"2f1dda63ade2bd085704674523b56ede942bc8c2c37fe8ed9b9b0fdfd69b1262"},{"version":"51d2f746d7e599a5549f5a946565934b4556bb9155be1eed2c474e25f1474872","signature":"c15585fe8935ed5cfedec39b7d41ec49990973f40faaba4b3e14278861643d79"},{"version":"b1d1378906c54a2f4d230ad69d212beedd2552afe3f7ad171b7eacb4cecc26d7","signature":"f9e60e8f79a7f606f19e02e2d39a24995719767dbe587f564f970bb24e3ca29d"},{"version":"f5a156e5b3783ea0399ac0326b7ab31a00e8874c5fa9b5e26fac217da8b5adfd","signature":"cfa7179e0306fc04d93f062c96e7ae8bad58d0cc4a7aa0dd4494ff9d262b101c"},{"version":"3c9fefca9303bcfd5712de11a3cbda20b3d6e85f29019bc75cab24690fb0f90d","signature":"306683152ff5a6038cf05b03ddff85a15b1bc8e18ef268aad26b02fd8e0e8b9d"},"a11c3e55d22d6379fe0949793e2638a6b43aa6e9def4f7452c3e352a296ef8da",{"version":"2770956c9437d7d66650084891c559ff6bb94200b7e2820940fd5d5dd0efa489","signature":"2faaf4f254008bf5be0e145be10dba35dccfac7116e9083f9d697a476a8e7076"},{"version":"ceee917fd557b841b93f7e13103dfdad79d38fe9962408f538f27db03dc9368d","signature":"15003ff6ed10d259dca775c7e5f7a64b272a9c370b6085db2d42a2d4a1d81579"},{"version":"a1691ae6d70af82f3e26d9e2e021dc5063021bd9c335bfdb40dc97d3574d1b3f","signature":"cd1c566b611a70ff987a79d0465da67649a8ed7e7668feddfcdf6dceb01c09a8"},{"version":"a105417dd540f1a400f0665c877e5d7e48e2efe08f01c2e5c7272256e644faa5","signature":"b3a6ee392811d6cddb38378ebaa373d4a39aa7dc4ecac73497c6b33627e6430b"},{"version":"581b44cf6122e3ad267d6bda2428c214fef3d38b6d7249df9fa6bc240a880a78","signature":"0ca09d92d6469d906a3d1c7192a6294c7f65b75f4f7eb8072bbd1b68c7f021e1"},{"version":"2e6426c1a1ff8561aa5f01d9398426bf06e55307f688464939de3196f0d4c143","signature":"5357bd09c9816a9765e617f86a9b49f85133d0bc0f9c5e29e834f2f8e6d52acb"},{"version":"508279c48de5627ae6c30a0aee01f4391bf32450335d7f09d5dd82acbc4d13c5","signature":"11d546a505f70f9c5f8092916027d8045c280a817b709fcaf2c4e63fa026c89c"},{"version":"557f2e0a4e5ac8a59b7c3068b2b30162fb963d72d50152482ab8c414e81caf37","signature":"008eaae28119118f1c589a1e29ea7fd17277f2280d2d3bfddeacd71fd1671bb5"},{"version":"f45c172ca54fb28d64b2dd04e495f17038034e20f37bd286a9f3eeb286cf1388","signature":"75a8761564c8fc5581b062dd339ea698921baf60e52eae055c8177dfa89eba90"},{"version":"ea696a0517ad69afea472e47eb1f904aba1667f54d4557eb98b8c766469d56a2","signature":"7e125d9abc19f62d1480f6c04a45d7bb2c89153316245ae8b8e5a0234b078c4e"},{"version":"902937c505f88d8b5b32829b4c14243eb740013fd0e2f58e6485324bbfe197a6","signature":"dc7de7650e5a64fc010387db18e84d48fe8f562dbd9caac01e54f83681ac976b"},{"version":"842accda78bb1b6f494f264aae307b84d933486d607e91f6e1d3a4d2e4851783","signature":"430d9683c8e5aaab71f0e3b271c4240cd5120a91191f953722985499af51d7e6"},{"version":"45b1a895868587c78a2ddff937967669b4e1968ea72c01e1c2b6dd5993f53b36","signature":"8e609bb71c20b858c77f0e9f90bb1319db8477b13f9f965f1a1e18524bf50881"},{"version":"99cab9373415bac71e9d2c84279782c0a361b59551d0ca8dfaee8d4c08ed3247","signature":"8e609bb71c20b858c77f0e9f90bb1319db8477b13f9f965f1a1e18524bf50881"},"ba1fed463e8a21ffddb67a53df3f0d818b351991723736e167d065e2de1c7183",{"version":"22e311fec88bcc49b2b1fb3c9a7c082cd84b3388c9bcc7b9ef08253f6fa74e26","affectsGlobalScope":true},"c186097fd9b86681981cdeba08c0b6bbfcd8b562ab490c25656d85fef8f10c79","0b0c483e991e81c3f26e5f2da53ff26a15994c98c8b89cda1e4156dfc2428111","3340eb7b30bdee5f0349107d4068fd6f2f4712e11a2ba68e203b2f2489350317",{"version":"2000d60bd5195730ffff0d4ce9389003917928502c455ed2a9e296d3bf1a4b42","signature":"56335d3c9b867cc8654c05e633c508dd8de0038157f9958eb8794b7c123bb90e"},{"version":"dfceb5b9355a4a9002a7c291b1c3315511977c73cb23d9c123a72567783a18c0","signature":"b1802850887a3ea11a06df1fc1c65c6579332eefba1e63b3967a73dc937a2574"},{"version":"384fc0e3fa5966f524c96f1782b9d7a005346ba1621c43d0d1d819bf39077fbc","signature":"8e609bb71c20b858c77f0e9f90bb1319db8477b13f9f965f1a1e18524bf50881"},{"version":"7fde517b3f03bb21ec3a46ba5f85c6797f8abf27deacb862183126e2f072788e","signature":"8b310edcfec83da25bc4f3adb20a7583bc5dae56d7d06c5b1431b76d390c1b72"},{"version":"894d93831d2afcd26f7362347e4960dd6d53f4153dad08813f3670e1327e387c","signature":"b1802850887a3ea11a06df1fc1c65c6579332eefba1e63b3967a73dc937a2574"},{"version":"8f9eac2c3ae305c25d4ffeff800b9811c8d3ec6a11b142fe96d08a2bc40f6440","signature":"08d6a2d1b004bbcac4249cd5baf6e9c662adc6139939c266b42e0422ef0c68b3"},{"version":"ac8980bdd810c30c444b59cca584c9b61d5ab274fa9474d778970537f3090240","signature":"8e609bb71c20b858c77f0e9f90bb1319db8477b13f9f965f1a1e18524bf50881"},{"version":"1c024431c672cf9c6dcdb4d30c5b625435d81a5423b9d45e8de0082e969af8a8","signature":"8e609bb71c20b858c77f0e9f90bb1319db8477b13f9f965f1a1e18524bf50881"},{"version":"eee1b57475023853cd09dd79b8d0d6639b6b82c3baee5863c2f2022b710f4102","signature":"8e609bb71c20b858c77f0e9f90bb1319db8477b13f9f965f1a1e18524bf50881"},{"version":"377ba49d29102653a4b0c72b3870f9c599575df7db3a3fae7a21be5327ff84e2","signature":"c47f5db4df0a5031ed84bc6ee192c412b9e2d4d5e94681af77ccdcc25c851839"},{"version":"377ba49d29102653a4b0c72b3870f9c599575df7db3a3fae7a21be5327ff84e2","signature":"c47f5db4df0a5031ed84bc6ee192c412b9e2d4d5e94681af77ccdcc25c851839"},{"version":"39833acf7547216b2f31b2279dcfec3ed1359dec8adc9d1cb87c695ebf9bff94","signature":"7292d4dc9dac6d815dc30245a4a4a4959845d3a2b84ba0166857e4b23f2d033f"},{"version":"39833acf7547216b2f31b2279dcfec3ed1359dec8adc9d1cb87c695ebf9bff94","signature":"7292d4dc9dac6d815dc30245a4a4a4959845d3a2b84ba0166857e4b23f2d033f"},{"version":"529dd364d169ab3dbbb177ccdc4987c4a6f69187f553f3d36460ab65879ad998","signature":"3919e9d5911da2254732c31942e2cdc0057056ebfc2a16d34041c76a9b58d447"},{"version":"ebea587ca6477b9db29baf75d359924c55ab490fecdc38d7c0f16e589f0d27f9","signature":"0688c25f38e78e052338305d23046c7841074b3da5709a8f9e598ed705b9932b"},{"version":"de411013305dbe5c7a1ac13d2ea16dc36e52e6efd255b4e912fe53862058c649","signature":"2faaf4f254008bf5be0e145be10dba35dccfac7116e9083f9d697a476a8e7076"},"e432b56911b58550616fc4d54c1606f65fe98c74875b81d74601f5f965767c60","cc957354aa3c94c9961ebf46282cfde1e81d107fc5785a61f62c67f1dd3ac2eb","a46a2e69d12afe63876ec1e58d70e5dbee6d3e74132f4468f570c3d69f809f1c","93de1c6dab503f053efe8d304cb522bb3a89feab8c98f307a674a4fae04773e9","3b043cf9a81854a72963fdb57d1884fc4da1cf5be69b5e0a4c5b751e58cb6d88","dd5647a9ccccb2b074dca8a02b00948ac293091ebe73fdf2e6e98f718819f669","0cba3a5d7b81356222594442753cf90dd2892e5ccfe1d262aaca6896ba6c1380","a69c09dbea52352f479d3e7ac949fde3d17b195abe90b045d619f747b38d6d1a",{"version":"c2ab70bbc7a24c42a790890739dd8a0ba9d2e15038b40dff8163a97a5d148c00","affectsGlobalScope":true},"422dbb183fdced59425ca072c8bd09efaa77ce4e2ab928ec0d8a1ce062d2a45a",{"version":"712ba0d43b44d144dfd01593f61af6e2e21cfae83e834d297643e7973e55ed61","affectsGlobalScope":true},"1dab5ab6bcf11de47ab9db295df8c4f1d92ffa750e8f095e88c71ce4c3299628","f71f46ccd5a90566f0a37b25b23bc4684381ab2180bdf6733f4e6624474e1894",{"version":"54e65985a3ee3cec182e6a555e20974ea936fc8b8d1738c14e8ed8a42bd921d4","affectsGlobalScope":true},"82408ed3e959ddc60d3e9904481b5a8dc16469928257af22a3f7d1a3bc7fd8c4","98a3ebfa494b46265634a73459050befba5da8fdc6ca0ef9b7269421780f4ff3","34e5de87d983bc6aefef8b17658556e3157003e8d9555d3cb098c6bef0b5fbc8","cc0b61316c4f37393f1f9595e93b673f4184e9d07f4c127165a490ec4a928668","f27371653aded82b2b160f7a7033fb4a5b1534b6f6081ef7be1468f0f15327d3","c762cd6754b13a461c54b59d0ae0ab7aeef3c292c6cf889873f786ee4d8e75c9","f4ea7d5df644785bd9fbf419930cbaec118f0d8b4160037d2339b8e23c059e79",{"version":"bfea28e6162ed21a0aeed181b623dcf250aa79abf49e24a6b7e012655af36d81","affectsGlobalScope":true},"7a5459efa09ea82088234e6533a203d528c594b01787fb90fba148885a36e8b6","ae97e20f2e10dbeec193d6a2f9cd9a367a1e293e7d6b33b68bacea166afd7792","10d4796a130577d57003a77b95d8723530bbec84718e364aa2129fa8ffba0378","ad41bb744149e92adb06eb953da195115620a3f2ad48e7d3ae04d10762dae197","bf73c576885408d4a176f44a9035d798827cc5020d58284cb18d7573430d9022","7ae078ca42a670445ae0c6a97c029cb83d143d62abd1730efb33f68f0b2c0e82",{"version":"e8b18c6385ff784228a6f369694fcf1a6b475355ba89090a88de13587a9391d5","affectsGlobalScope":true},"5d0a9ea09d990b5788f867f1c79d4878f86f7384cb7dab38eecbf22f9efd063d","12eea70b5e11e924bb0543aea5eadc16ced318aa26001b453b0d561c2fd0bd1e","08777cd9318d294646b121838574e1dd7acbb22c21a03df84e1f2c87b1ad47f2","08a90bcdc717df3d50a2ce178d966a8c353fd23e5c392fd3594a6e39d9bb6304",{"version":"4cd4cff679c9b3d9239fd7bf70293ca4594583767526916af8e5d5a47d0219c7","affectsGlobalScope":true},"2a12d2da5ac4c4979401a3f6eaafa874747a37c365e4bc18aa2b171ae134d21b","002b837927b53f3714308ecd96f72ee8a053b8aeb28213d8ec6de23ed1608b66","1dc9c847473bb47279e398b22c740c83ea37a5c88bf66629666e3cf4c5b9f99c","a9e4a5a24bf2c44de4c98274975a1a705a0abbaad04df3557c2d3cd8b1727949","00fa7ce8bc8acc560dc341bbfdf37840a8c59e6a67c9bfa3fa5f36254df35db2","1b952304137851e45bc009785de89ada562d9376177c97e37702e39e60c2f1ff",{"version":"806ef4cac3b3d9fa4a48d849c8e084d7c72fcd7b16d76e06049a9ed742ff79c0","affectsGlobalScope":true},"44b8b584a338b190a59f4f6929d072431950c7bd92ec2694821c11bce180c8a5","5f0ed51db151c2cdc4fa3bb0f44ce6066912ad001b607a34e65a96c52eb76248",{"version":"3345c276cab0e76dda86c0fb79104ff915a4580ba0f3e440870e183b1baec476","affectsGlobalScope":true},"664d8f2d59164f2e08c543981453893bc7e003e4dfd29651ce09db13e9457980","e383ff72aabf294913f8c346f5da1445ae6ad525836d28efd52cbadc01a361a6","f52fbf64c7e480271a9096763c4882d356b05cab05bf56a64e68a95313cd2ce2","59bdb65f28d7ce52ccfc906e9aaf422f8b8534b2d21c32a27d7819be5ad81df7",{"version":"3a2da34079a2567161c1359316a32e712404b56566c45332ac9dcee015ecce9f","affectsGlobalScope":true},"28a2e7383fd898c386ffdcacedf0ec0845e5d1a86b5a43f25b86bc315f556b79","3aff9c8c36192e46a84afe7b926136d520487155154ab9ba982a8b544ea8fc95","a880cf8d85af2e4189c709b0fea613741649c0e40fffb4360ec70762563d5de0","85bbf436a15bbeda4db888be3062d47f99c66fd05d7c50f0f6473a9151b6a070","9f9c49c95ecd25e0cb2587751925976cf64fd184714cb11e213749c80cf0f927","f0c75c08a71f9212c93a719a25fb0320d53f2e50ca89a812640e08f8ad8c408c",{"version":"ab9b9a36e5284fd8d3bf2f7d5fcbc60052f25f27e4d20954782099282c60d23e","affectsGlobalScope":true},"9cafe917bf667f1027b2bb62e2de454ecd2119c80873ad76fc41d941089753b8","3ebae8c00411116a66fca65b08228ea0cf0b72724701f9b854442100aab55aba","8b06ac3faeacb8484d84ddb44571d8f410697f98d7bfa86c0fda60373a9f5215","7eb06594824ada538b1d8b48c3925a83e7db792f47a081a62cf3e5c4e23cf0ee","f5638f7c2f12a9a1a57b5c41b3c1ea7db3876c003bab68e6a57afd6bcc169af0","0d14fa22c41fdc7277e6f71473b20ebc07f40f00e38875142335d5b63cdfc9d2","7980bf9d2972585cdf76b5a72105f7817be0723ccb2256090f6335f45b462abe","301d7466eb591139c7d456958f732153b3400f3243f68d3321956b43a64769e9","22f13de9e2fe5f0f4724797abd3d34a1cdd6e47ef81fc4933fea3b8bf4ad524b","e3ba509d3dce019b3190ceb2f3fc88e2610ab717122dabd91a9efaa37804040d","cda0cb09b995489b7f4c57f168cd31b83dcbaa7aad49612734fb3c9c73f6e4f2",{"version":"2abad7477cf6761b55c18bea4c21b5a5dcf319748c13696df3736b35f8ac149e","affectsGlobalScope":true},"d38e588a10943bbab1d4ce03d94759bf065ff802a9a72fc57aa75a72f1725b71","96d14f21b7652903852eef49379d04dbda28c16ed36468f8c9fa08f7c14c9538","2b8264b2fefd7367e0f20e2c04eed5d3038831fe00f5efbc110ff0131aab899b","6209c901f30cc321f4b86800d11fad3d67e73a3308f19946b1bc642af0280298","60aaac5fb1858fbd4c4eb40e01706eb227eed9eca5c665564bd146971280dbd3","74b0245c42990ed8a849df955db3f4362c81b13f799ebc981b7bec2d5b414a57","b0d10e46cfe3f6c476b69af02eaa38e4ccc7430221ce3109ae84bb9fb8282298","4266ccd2cf1d6a281efd9c7ddf9efd7daecf76575364148bd233e18919cac3ed","70e9a18da08294f75bf23e46c7d69e67634c0765d355887b9b41f0d959e1426e","105b9a2234dcb06ae922f2cd8297201136d416503ff7d16c72bfc8791e9895c1"],"options":{"composite":true,"declaration":true,"declarationMap":true,"downlevelIteration":true,"esModuleInterop":true,"experimentalDecorators":true,"importHelpers":true,"jsx":2,"noEmitOnError":false,"noImplicitAny":true,"noUnusedLocals":true,"outDir":"./","rootDir":"../src","skipLibCheck":true,"sourceMap":true,"strictNullChecks":true,"target":1,"tsBuildInfoFile":"./tsconfig.tsbuildinfo"},"fileIdsList":[[211,260],[260],[260,273],[53,190,260],[192,194,260],[190,192,193,260],[53,260],[53,140,260],[69,260],[211,212,213,214,215,260],[211,213,260],[233,260,267],[260,269],[260,270],[260,275,277],[217,260],[220,260],[221,226,260],[222,232,233,240,249,259,260],[222,223,232,240,260],[224,260],[225,226,233,241,260],[226,249,256,260],[227,229,232,240,260],[228,260],[229,230,260],[231,232,260],[232,260],[232,233,234,249,259,260],[232,233,234,249,260],[235,240,249,259,260],[232,233,235,236,240,249,256,259,260],[235,237,249,256,259,260],[217,218,219,220,221,222,223,224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255,256,257,258,259,260,261,262,263,264,265,266],[232,238,260],[239,259,260],[229,232,240,249,260],[241,260],[242,260],[220,243,260],[244,258,260,264],[245,260],[246,260],[232,247,260],[247,248,260,262],[232,249,250,251,260],[249,251,260],[249,250,260],[252,260],[253,260],[232,254,255,260],[254,255,260],[226,240,249,256,260],[257,260],[240,258,260],[221,235,246,259,260],[226,260],[249,260,261],[260,262],[260,263],[221,226,232,234,243,249,259,260,262,264],[249,260,265],[76,77,260],[53,58,64,65,68,71,72,73,76,260],[74,260],[84,260],[53,57,82,260],[53,54,57,58,62,75,76,260],[53,76,105,106,260],[53,54,57,58,62,76,260],[82,91,260],[53,54,62,75,76,93,260],[53,55,58,61,62,65,75,76,260],[53,54,57,62,76,260],[53,54,57,62,260],[53,54,55,58,60,62,63,75,76,260],[53,76,260],[53,75,76,260],[53,54,57,58,61,62,75,76,82,93,260],[53,55,58,260],[53,54,57,60,75,76,93,103,260],[53,54,60,76,103,105,260],[53,54,57,60,62,93,103,260],[53,54,55,58,60,61,75,76,93,260],[58,260],[53,55,58,59,60,61,75,76,260],[82,260],[83,260],[53,54,55,57,58,61,66,67,75,76,260],[58,59,260],[53,64,65,70,75,76,260],[53,56,64,70,75,76,260],[53,58,62,260],[53,118,260],[53,57,260],[57,260],[76,260],[75,260],[66,74,76,260],[53,54,57,58,61,75,76,260],[128,260],[53,56,57,260],[91,260],[44,45,46,47,48,55,56,57,58,59,60,61,62,63,64,65,66,67,68,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,260],[140,260],[46,260],[49,50,51,52,260],[232,235,237,240,259,260,267],[260,287],[260,275],[260,272,276],[260,274],[151,260],[53,141,142,143,144,146,147,148,149,150,157,260],[53,140,147,150,151,260],[143,144,260],[142,143,144,147,260],[143,260],[155,260],[157,260],[144,260],[53,144,260],[141,142,143,144,145,146,147,149,150,151,152,153,154,156,260],[149,260],[158,260],[43,140,166,177,260],[43,53,140,157,159,162,163,164,166,168,169,170,171,172,174,176,260],[43,53,140,162,165,260],[43,157,166,167,168,260],[43,53,140,165,166,168,170,171,177,260],[43,53,260],[43,167,260],[43,168,260],[43,53,140,157,162,163,166,172,191,195,260],[43,140,157,177,195,260],[43,53,140,157,177,179,191,198,260],[43,200,260],[43,157,170,171,173,260],[43,53,140,166,177,191,194,260],[43,53,140,166,179,191,194,260],[43,53,177,183,194,195,260],[43,260],[43,181,260],[43,53,177,180,181,182,183,260],[43,53,157,162,177,260],[43,53,140,180,182,184,260],[43,162,163,165,166,177,178,179,180,182,183,184,185,186,260],[43,53,140,160,161,260],[43,140,160,260],[43,140,260],[43,53,140,260],[43,157,260],[43,157,175,260],[43,53,140,157,175,260],[43,140,157,166,260],[43,140,157,170,171,260],[43,140,165,173,177,260],[53,140,166],[53,157,166,169],[53,140,162,165],[157,166],[53,140,166,177],[53],[191],[53,166,177,191,194],[53,166,179,191,194],[53,177,182,183,187],[53,162,177],[140,184],[162,163,165,166,177,178,179,180,182,183,184,185,186],[53,140],[140,160],[140],[157],[53,157],[140,157,166],[140,157],[177]],"referencedMap":[[213,1],[211,2],[274,3],[192,4],[193,5],[194,6],[191,4],[190,7],[69,8],[70,9],[273,2],[216,10],[212,1],[214,11],[215,1],[268,12],[269,2],[270,13],[271,14],[278,15],[279,2],[280,2],[217,16],[218,16],[220,17],[221,18],[222,19],[223,20],[224,21],[225,22],[226,23],[227,24],[228,25],[229,26],[230,26],[231,27],[232,28],[233,29],[234,30],[219,2],[266,2],[235,31],[236,32],[237,33],[267,34],[238,35],[239,36],[240,37],[241,38],[242,39],[243,40],[244,41],[245,42],[246,43],[247,44],[248,45],[249,46],[251,47],[250,48],[252,49],[253,50],[254,51],[255,52],[256,53],[257,54],[258,55],[259,56],[260,57],[261,58],[262,59],[263,60],[264,61],[265,62],[281,2],[282,2],[51,2],[78,63],[79,2],[74,64],[80,2],[81,65],[85,66],[86,2],[87,67],[88,68],[107,69],[89,2],[90,70],[92,71],[94,72],[95,73],[96,74],[63,74],[97,75],[64,76],[98,77],[99,68],[100,78],[101,79],[102,2],[60,80],[104,81],[106,82],[105,83],[103,84],[65,75],[61,85],[62,86],[108,2],[91,87],[83,87],[84,88],[68,89],[66,2],[67,2],[109,87],[110,90],[111,2],[112,71],[71,91],[72,92],[113,2],[114,93],[115,2],[116,2],[117,2],[119,94],[120,2],[56,7],[121,7],[122,95],[123,96],[124,2],[125,97],[127,97],[126,97],[76,98],[75,99],[77,97],[73,100],[128,2],[129,101],[58,102],[130,66],[131,66],[132,103],[133,87],[118,2],[134,2],[135,2],[136,2],[137,7],[138,2],[82,2],[140,104],[44,2],[45,105],[46,106],[48,2],[47,2],[93,2],[54,2],[139,105],[55,2],[59,85],[57,7],[283,7],[49,2],[53,107],[284,2],[52,2],[285,2],[286,108],[287,2],[288,109],[272,2],[50,2],[276,110],[277,111],[275,112],[149,2],[154,113],[151,114],[158,115],[147,116],[148,117],[141,2],[142,2],[145,116],[144,118],[156,119],[155,120],[153,116],[143,121],[146,122],[157,123],[175,124],[152,2],[150,7],[159,125],[43,2],[8,2],[9,2],[11,2],[10,2],[2,2],[12,2],[13,2],[14,2],[15,2],[16,2],[17,2],[18,2],[19,2],[3,2],[4,2],[23,2],[20,2],[21,2],[22,2],[24,2],[25,2],[26,2],[5,2],[27,2],[28,2],[29,2],[30,2],[6,2],[31,2],[32,2],[33,2],[34,2],[7,2],[35,2],[40,2],[41,2],[36,2],[37,2],[38,2],[39,2],[1,2],[42,2],[178,126],[177,127],[166,128],[169,129],[179,130],[164,131],[188,132],[189,133],[196,134],[197,135],[199,136],[201,137],[202,138],[195,139],[198,140],[203,141],[180,142],[182,143],[181,142],[184,144],[183,145],[185,142],[186,146],[170,142],[171,142],[172,142],[187,147],[162,148],[204,149],[205,149],[161,149],[160,131],[206,150],[207,150],[163,151],[208,131],[209,152],[210,152],[176,153],[200,154],[167,142],[168,155],[165,142],[173,156],[174,157]],"exportedModulesMap":[[213,1],[211,2],[274,3],[192,4],[193,5],[194,6],[191,4],[190,7],[69,8],[70,9],[273,2],[216,10],[212,1],[214,11],[215,1],[268,12],[269,2],[270,13],[271,14],[278,15],[279,2],[280,2],[217,16],[218,16],[220,17],[221,18],[222,19],[223,20],[224,21],[225,22],[226,23],[227,24],[228,25],[229,26],[230,26],[231,27],[232,28],[233,29],[234,30],[219,2],[266,2],[235,31],[236,32],[237,33],[267,34],[238,35],[239,36],[240,37],[241,38],[242,39],[243,40],[244,41],[245,42],[246,43],[247,44],[248,45],[249,46],[251,47],[250,48],[252,49],[253,50],[254,51],[255,52],[256,53],[257,54],[258,55],[259,56],[260,57],[261,58],[262,59],[263,60],[264,61],[265,62],[281,2],[282,2],[51,2],[78,63],[79,2],[74,64],[80,2],[81,65],[85,66],[86,2],[87,67],[88,68],[107,69],[89,2],[90,70],[92,71],[94,72],[95,73],[96,74],[63,74],[97,75],[64,76],[98,77],[99,68],[100,78],[101,79],[102,2],[60,80],[104,81],[106,82],[105,83],[103,84],[65,75],[61,85],[62,86],[108,2],[91,87],[83,87],[84,88],[68,89],[66,2],[67,2],[109,87],[110,90],[111,2],[112,71],[71,91],[72,92],[113,2],[114,93],[115,2],[116,2],[117,2],[119,94],[120,2],[56,7],[121,7],[122,95],[123,96],[124,2],[125,97],[127,97],[126,97],[76,98],[75,99],[77,97],[73,100],[128,2],[129,101],[58,102],[130,66],[131,66],[132,103],[133,87],[118,2],[134,2],[135,2],[136,2],[137,7],[138,2],[82,2],[140,104],[44,2],[45,105],[46,106],[48,2],[47,2],[93,2],[54,2],[139,105],[55,2],[59,85],[57,7],[283,7],[49,2],[53,107],[284,2],[52,2],[285,2],[286,108],[287,2],[288,109],[272,2],[50,2],[276,110],[277,111],[275,112],[149,2],[154,113],[151,114],[158,115],[147,116],[148,117],[141,2],[142,2],[145,116],[144,118],[156,119],[155,120],[153,116],[143,121],[146,122],[157,123],[175,124],[152,2],[150,7],[159,125],[43,2],[8,2],[9,2],[11,2],[10,2],[2,2],[12,2],[13,2],[14,2],[15,2],[16,2],[17,2],[18,2],[19,2],[3,2],[4,2],[23,2],[20,2],[21,2],[22,2],[24,2],[25,2],[26,2],[5,2],[27,2],[28,2],[29,2],[30,2],[6,2],[31,2],[32,2],[33,2],[34,2],[7,2],[35,2],[40,2],[41,2],[36,2],[37,2],[38,2],[39,2],[1,2],[42,2],[178,158],[177,159],[166,160],[169,161],[179,162],[164,163],[196,164],[199,164],[195,165],[198,166],[184,167],[183,168],[186,169],[187,170],[162,171],[204,172],[205,172],[161,172],[160,163],[206,173],[207,173],[163,171],[208,163],[209,174],[210,174],[176,174],[200,175],[168,176],[173,177],[174,178]],"semanticDiagnosticsPerFile":[213,211,274,192,193,194,191,190,69,70,273,216,212,214,215,268,269,270,271,278,279,280,217,218,220,221,222,223,224,225,226,227,228,229,230,231,232,233,234,219,266,235,236,237,267,238,239,240,241,242,243,244,245,246,247,248,249,251,250,252,253,254,255,256,257,258,259,260,261,262,263,264,265,281,282,51,78,79,74,80,81,85,86,87,88,107,89,90,92,94,95,96,63,97,64,98,99,100,101,102,60,104,106,105,103,65,61,62,108,91,83,84,68,66,67,109,110,111,112,71,72,113,114,115,116,117,119,120,56,121,122,123,124,125,127,126,76,75,77,73,128,129,58,130,131,132,133,118,134,135,136,137,138,82,140,44,45,46,48,47,93,54,139,55,59,57,283,49,53,284,52,285,286,287,288,272,50,276,277,275,149,154,151,158,147,148,141,142,145,144,156,155,153,143,146,157,175,152,150,159,43,8,9,11,10,2,12,13,14,15,16,17,18,19,3,4,23,20,21,22,24,25,26,5,27,28,29,30,6,31,32,33,34,7,35,40,41,36,37,38,39,1,42,178,177,166,169,179,164,188,189,196,197,199,201,202,195,198,203,180,182,181,184,183,185,186,170,171,172,187,162,204,205,161,160,206,207,163,208,209,210,176,200,167,168,165,173,174]},"version":"4.7.4"} -\ No newline at end of file -diff --git a/node_modules/@shopify/flash-list/ios/Sources/AutoLayoutView.swift b/node_modules/@shopify/flash-list/ios/Sources/AutoLayoutView.swift -index f18e92c..af1903c 100644 ---- a/node_modules/@shopify/flash-list/ios/Sources/AutoLayoutView.swift -+++ b/node_modules/@shopify/flash-list/ios/Sources/AutoLayoutView.swift -@@ -4,31 +4,35 @@ import UIKit - - /// Container for all RecyclerListView children. This will automatically remove all gaps and overlaps for GridLayouts with flexible spans. - /// Note: This cannot work for masonry layouts i.e, pinterest like layout --@objc class AutoLayoutView: UIView { -+@objc public class AutoLayoutView: UIView { -+ #if RCT_NEW_ARCH_ENABLED -+ @objc public var onBlankAreaEventHandler: ((CGFloat, CGFloat) -> Void)? -+ #endif -+ - @objc(onBlankAreaEvent) - var onBlankAreaEvent: RCTDirectEventBlock? - -- @objc func setHorizontal(_ horizontal: Bool) { -+ @objc public func setHorizontal(_ horizontal: Bool) { - self.horizontal = horizontal - } - -- @objc func setScrollOffset(_ scrollOffset: Int) { -+ @objc public func setScrollOffset(_ scrollOffset: Int) { - self.scrollOffset = CGFloat(scrollOffset) - } - -- @objc func setWindowSize(_ windowSize: Int) { -+ @objc public func setWindowSize(_ windowSize: Int) { - self.windowSize = CGFloat(windowSize) - } - -- @objc func setRenderAheadOffset(_ renderAheadOffset: Int) { -+ @objc public func setRenderAheadOffset(_ renderAheadOffset: Int) { - self.renderAheadOffset = CGFloat(renderAheadOffset) - } - -- @objc func setEnableInstrumentation(_ enableInstrumentation: Bool) { -+ @objc public func setEnableInstrumentation(_ enableInstrumentation: Bool) { - self.enableInstrumentation = enableInstrumentation - } - -- @objc func setDisableAutoLayout(_ disableAutoLayout: Bool) { -+ @objc public func setDisableAutoLayout(_ disableAutoLayout: Bool) { - self.disableAutoLayout = disableAutoLayout - } - -@@ -46,7 +50,15 @@ import UIKit - /// Tracks where first pixel is drawn in the visible window - private var lastMinBound: CGFloat = 0 - -- override func layoutSubviews() { -+ private var viewsToLayout: [UIView] { -+ #if RCT_NEW_ARCH_ENABLED -+ return superview?.subviews ?? [] -+ #else -+ return subviews -+ #endif -+ } -+ -+ override public func layoutSubviews() { - fixLayout() - super.layoutSubviews() - -@@ -69,12 +81,16 @@ import UIKit - distanceFromWindowEnd: distanceFromWindowEnd - ) - -+ #if RCT_NEW_ARCH_ENABLED -+ onBlankAreaEventHandler?(blankOffsetStart, blankOffsetEnd) -+ #else - onBlankAreaEvent?( - [ - "offsetStart": blankOffsetStart, - "offsetEnd": blankOffsetEnd, - ] - ) -+ #endif - } - - func getScrollView() -> UIScrollView? { -@@ -85,15 +101,21 @@ import UIKit - /// Performance: Sort is needed. Given relatively low number of views in RecyclerListView render tree this should be a non issue. - private func fixLayout() { - guard -- subviews.count > 1, -+ viewsToLayout.count > 1, - // Fixing layout during animation can interfere with it. - layer.animationKeys()?.isEmpty ?? true, - !disableAutoLayout - else { return } -- let cellContainers = subviews -- .compactMap { subview -> CellContainer? in -- if let cellContainer = subview as? CellContainer { -+ let cellContainers = viewsToLayout -+ .compactMap { subview -> CellContainerComponentView? in -+ if let cellContainer = subview as? CellContainerComponentView { - return cellContainer -+ } else if subview is AutoLayoutView { -+ // On Fabric, due to view flattening children of AutoLayoutView are moved one level up, so they appear -+ // as children of AutoLayoutViewComponentView in view hierarchy. viewsToLayout property takes it under -+ // consideration, returning children of AutoLayoutViewComponentView when on Fabric. Because of that -+ // AutoLayoutView may be on the list, in which case we want to ignore it. -+ return nil - } else { - assertionFailure("CellRendererComponent outer view should always be CellContainer. Learn more here: https://shopify.github.io/flash-list/docs/usage#cellrenderercomponent.") - return nil -@@ -106,7 +128,7 @@ import UIKit - - /// Checks for overlaps or gaps between adjacent items and then applies a correction. - /// Performance: RecyclerListView renders very small number of views and this is not going to trigger multiple layouts on the iOS side. -- private func clearGaps(for cellContainers: [CellContainer]) { -+ private func clearGaps(for cellContainers: [CellContainerComponentView]) { - var maxBound: CGFloat = 0 - var minBound: CGFloat = CGFloat(Int.max) - var maxBoundNextCell: CGFloat = 0 -@@ -192,7 +214,7 @@ import UIKit - lastMinBound = minBound - } - -- private func updateLastMaxBoundOverall(currentCell: CellContainer, nextCell: CellContainer) { -+ private func updateLastMaxBoundOverall(currentCell: CellContainerComponentView, nextCell: CellContainerComponentView) { - lastMaxBoundOverall = max(lastMaxBoundOverall, horizontal ? currentCell.frame.maxX : currentCell.frame.maxY, horizontal ? nextCell.frame.maxX : nextCell.frame.maxY) - } - -@@ -217,7 +239,7 @@ import UIKit - - /// It's important to avoid correcting views outside the render window. An item that isn't being recycled might still remain in the view tree. If views outside get considered then gaps between unused items will cause algorithm to fail. - func isWithinBounds( -- _ cellContainer: CellContainer, -+ _ cellContainer: CellContainerComponentView, - scrollOffset: CGFloat, - renderAheadOffset: CGFloat, - windowSize: CGFloat, -@@ -260,10 +282,10 @@ import UIKit - } - - private func footerDiff() -> CGFloat { -- if subviews.count == 0 { -+ if viewsToLayout.count == 0 { - lastMaxBoundOverall = 0 -- } else if subviews.count == 1 { -- let firstChild = subviews[0] -+ } else if viewsToLayout.count == 1 { -+ let firstChild = viewsToLayout[0] - lastMaxBoundOverall = horizontal ? firstChild.frame.maxX : firstChild.frame.maxY - } - let autoLayoutEnd = horizontal ? frame.width : frame.height -@@ -271,6 +293,13 @@ import UIKit - } - - private func footer() -> UIView? { -- return superview?.subviews.first(where:{($0 as? CellContainer)?.index == -1}) -+ // On Fabric, AutoLayoutView is wrapped with AutoLayoutViewComponentView, so we need to go up one more level -+ #if RCT_NEW_ARCH_ENABLED -+ let parentSubviews = superview?.superview?.subviews -+ #else -+ let parentSubviews = superview?.subviews -+ #endif -+ -+ return parentSubviews?.first(where:{($0 as? CellContainerComponentView)?.index == -1}) - } - } -diff --git a/node_modules/@shopify/flash-list/ios/Sources/AutoLayoutViewComponentView.h b/node_modules/@shopify/flash-list/ios/Sources/AutoLayoutViewComponentView.h -new file mode 100644 -index 0000000..1ae0b66 ---- /dev/null -+++ b/node_modules/@shopify/flash-list/ios/Sources/AutoLayoutViewComponentView.h -@@ -0,0 +1,16 @@ -+#ifndef AutoLayoutViewComponentView_h -+#define AutoLayoutViewComponentView_h -+ -+#ifdef RCT_NEW_ARCH_ENABLED -+ -+#import -+#import -+ -+@interface AutoLayoutViewComponentView : RCTViewComponentView -+ -+@end -+ -+ -+#endif /* RCT_NEW_ARCH_ENABLED */ -+ -+#endif /* AutoLayoutViewComponentView_h */ -diff --git a/node_modules/@shopify/flash-list/ios/Sources/AutoLayoutViewComponentView.mm b/node_modules/@shopify/flash-list/ios/Sources/AutoLayoutViewComponentView.mm -new file mode 100644 -index 0000000..2d4295c ---- /dev/null -+++ b/node_modules/@shopify/flash-list/ios/Sources/AutoLayoutViewComponentView.mm -@@ -0,0 +1,80 @@ -+#ifdef RCT_NEW_ARCH_ENABLED -+#import "AutoLayoutViewComponentView.h" -+#import -+#import -+ -+#import -+#import -+#import -+#import -+ -+#import "RCTFabricComponentsPlugins.h" -+#import -+ -+using namespace facebook::react; -+ -+@interface AutoLayoutViewComponentView () -+@end -+ -+@implementation AutoLayoutViewComponentView -+{ -+ AutoLayoutView *_autoLayoutView; -+} -+ -+- (instancetype)initWithFrame:(CGRect)frame -+{ -+ if (self = [super initWithFrame:frame]) { -+ static const auto defaultProps = std::make_shared(); -+ _props = defaultProps; -+ _autoLayoutView = [[AutoLayoutView alloc] initWithFrame:self.bounds]; -+ -+ // Due to view flattening, AutoLayoutView's children get moved to its parent (AutoLayoutViewComponentView) and -+ // AutoLayoutView is positioned above them consuming all events. Turning off userInteraction prevents that. -+ _autoLayoutView.userInteractionEnabled = false; -+ -+ self.contentView = _autoLayoutView; -+ -+ __weak AutoLayoutViewComponentView* weakSelf = self; -+ _autoLayoutView.onBlankAreaEventHandler = ^(CGFloat start, CGFloat end) { -+ AutoLayoutViewComponentView *strongSelf = weakSelf; -+ if (strongSelf != nullptr && strongSelf->_eventEmitter != nullptr) { -+ std::dynamic_pointer_cast(strongSelf->_eventEmitter) -+ ->onBlankAreaEvent(facebook::react::AutoLayoutViewEventEmitter::OnBlankAreaEvent{ -+ .offsetStart = (int) floor(start), -+ .offsetEnd = (int) floor(end), -+ }); -+ } -+ }; -+ } -+ -+ return self; -+} -+ -+#pragma mark - RCTComponentViewProtocol -+ -++ (ComponentDescriptorProvider)componentDescriptorProvider -+{ -+ return concreteComponentDescriptorProvider(); -+} -+ -+- (void)updateProps:(const Props::Shared &)props oldProps:(const Props::Shared &)oldProps -+{ -+ const auto &newProps = *std::static_pointer_cast(props); -+ -+ [_autoLayoutView setHorizontal:newProps.horizontal]; -+ [_autoLayoutView setScrollOffset:newProps.scrollOffset]; -+ [_autoLayoutView setWindowSize:newProps.windowSize]; -+ [_autoLayoutView setRenderAheadOffset:newProps.renderAheadOffset]; -+ [_autoLayoutView setEnableInstrumentation:newProps.enableInstrumentation]; -+ [_autoLayoutView setDisableAutoLayout:newProps.disableAutoLayout]; -+ -+ [super updateProps:props oldProps:oldProps]; -+} -+@end -+ -+Class AutoLayoutViewCls(void) -+{ -+ return AutoLayoutViewComponentView.class; -+} -+ -+#endif /* RCT_NEW_ARCH_ENABLED */ -diff --git a/node_modules/@shopify/flash-list/ios/Sources/AutoLayoutViewManager.m b/node_modules/@shopify/flash-list/ios/Sources/AutoLayoutViewManager.mm -similarity index 100% -rename from node_modules/@shopify/flash-list/ios/Sources/AutoLayoutViewManager.m -rename to node_modules/@shopify/flash-list/ios/Sources/AutoLayoutViewManager.mm -diff --git a/node_modules/@shopify/flash-list/ios/Sources/CellContainer.swift b/node_modules/@shopify/flash-list/ios/Sources/CellContainer.swift -deleted file mode 100644 -index 7f09ce7..0000000 ---- a/node_modules/@shopify/flash-list/ios/Sources/CellContainer.swift -+++ /dev/null -@@ -1,9 +0,0 @@ --import Foundation -- --@objc class CellContainer: UIView { -- var index: Int = -1 -- -- @objc func setIndex(_ index: Int) { -- self.index = index -- } --} -diff --git a/node_modules/@shopify/flash-list/ios/Sources/CellContainerComponentView.h b/node_modules/@shopify/flash-list/ios/Sources/CellContainerComponentView.h -new file mode 100644 -index 0000000..ca1cbfe ---- /dev/null -+++ b/node_modules/@shopify/flash-list/ios/Sources/CellContainerComponentView.h -@@ -0,0 +1,18 @@ -+#ifndef CellContainer_h -+#define CellContainer_h -+ -+#import -+ -+#ifdef RCT_NEW_ARCH_ENABLED -+#import -+ -+@interface CellContainerComponentView : RCTViewComponentView -+#else -+@interface CellContainerComponentView : UIView -+#endif -+ -+@property int64_t index; -+ -+@end -+ -+#endif /* CellContainer_h */ -diff --git a/node_modules/@shopify/flash-list/ios/Sources/CellContainerComponentView.mm b/node_modules/@shopify/flash-list/ios/Sources/CellContainerComponentView.mm -new file mode 100644 -index 0000000..3a1c57e ---- /dev/null -+++ b/node_modules/@shopify/flash-list/ios/Sources/CellContainerComponentView.mm -@@ -0,0 +1,57 @@ -+#import "CellContainerComponentView.h" -+ -+#ifdef RCT_NEW_ARCH_ENABLED -+#import -+ -+#import -+#import -+#import -+#import -+ -+#import "RCTFabricComponentsPlugins.h" -+#import -+ -+using namespace facebook::react; -+ -+@interface CellContainerComponentView () -+@end -+ -+@implementation CellContainerComponentView -+ -+- (instancetype)initWithFrame:(CGRect)frame -+{ -+ if (self = [super initWithFrame:frame]) { -+ static const auto defaultProps = std::make_shared(); -+ _props = defaultProps; -+ -+ self.userInteractionEnabled = true; -+ } -+ -+ return self; -+} -+ -+#pragma mark - RCTComponentViewProtocol -+ -++ (ComponentDescriptorProvider)componentDescriptorProvider -+{ -+ return concreteComponentDescriptorProvider(); -+} -+ -+- (void)updateProps:(const Props::Shared &)props oldProps:(const Props::Shared &)oldProps -+{ -+ const auto &newProps = *std::static_pointer_cast(props); -+ -+ self.index = newProps.index; -+ -+ [super updateProps:props oldProps:oldProps]; -+} -+@end -+ -+Class CellContainerCls(void) -+{ -+ return CellContainerComponentView.class; -+} -+#else -+@implementation CellContainerComponentView -+@end -+#endif /* RCT_NEW_ARCH_ENABLED */ -diff --git a/node_modules/@shopify/flash-list/ios/Sources/CellContainerManager.m b/node_modules/@shopify/flash-list/ios/Sources/CellContainerManager.mm -similarity index 100% -rename from node_modules/@shopify/flash-list/ios/Sources/CellContainerManager.m -rename to node_modules/@shopify/flash-list/ios/Sources/CellContainerManager.mm -diff --git a/node_modules/@shopify/flash-list/ios/Sources/CellContainerManager.swift b/node_modules/@shopify/flash-list/ios/Sources/CellContainerManager.swift -index a36fccd..dbe6c14 100644 ---- a/node_modules/@shopify/flash-list/ios/Sources/CellContainerManager.swift -+++ b/node_modules/@shopify/flash-list/ios/Sources/CellContainerManager.swift -@@ -3,7 +3,7 @@ import Foundation - @objc(CellContainerManager) - class CellContainerManager: RCTViewManager { - override func view() -> UIView! { -- return CellContainer() -+ return CellContainerComponentView() - } - - override static func requiresMainQueueSetup() -> Bool { -diff --git a/node_modules/@shopify/flash-list/ios/Sources/FlatListPro-Bridging-Header.h b/node_modules/@shopify/flash-list/ios/Sources/FlatListPro-Bridging-Header.h -index e3e23d5..7ed83ce 100644 ---- a/node_modules/@shopify/flash-list/ios/Sources/FlatListPro-Bridging-Header.h -+++ b/node_modules/@shopify/flash-list/ios/Sources/FlatListPro-Bridging-Header.h -@@ -4,5 +4,8 @@ - #import - #import - #import -+#import -+ -+#import "CellContainerComponentView.h" - - #endif /* FlatListPro_Bridging_Header_h */ -diff --git a/node_modules/@shopify/flash-list/package.json b/node_modules/@shopify/flash-list/package.json -index b90c287..ccca16d 100644 ---- a/node_modules/@shopify/flash-list/package.json -+++ b/node_modules/@shopify/flash-list/package.json -@@ -25,6 +25,7 @@ - "author": "shopify", - "license": "MIT", - "homepage": "https://shopify.github.io/flash-list/", -+ "react-native": "src/index.ts", - "main": "dist/index.js", - "types": "dist/index.d.ts", - "scripts": { -@@ -64,7 +65,7 @@ - "@react-native-community/eslint-config": "^3.0.3", - "@shopify/eslint-plugin": "^41.3.1", - "@types/jest": "^28.1.3", -- "@types/react-native": "0.72.2", -+ "@types/react-native": "^0.72.2", - "babel-jest": "^28.1.1", - "enhanced-resolve": "^5.9.3", - "eslint": "8.18.0", -@@ -74,7 +75,7 @@ - "prettier": "^2.7.1", - "react": "17.0.2", - "react-native": "0.68.5", -- "typescript": "^4.7.4" -+ "typescript": "4.8.4" - }, - "files": [ - "android", -@@ -87,5 +88,10 @@ - "dependencies": { - "recyclerlistview": "4.2.0", - "tslib": "2.4.0" -+ }, -+ "codegenConfig": { -+ "name": "rnflashlist", -+ "type": "components", -+ "jsSrcsDir": "./src/fabric" - } - } -diff --git a/node_modules/@shopify/flash-list/src/FlashList.tsx b/node_modules/@shopify/flash-list/src/FlashList.tsx -index 64748fe..87dea16 100644 ---- a/node_modules/@shopify/flash-list/src/FlashList.tsx -+++ b/node_modules/@shopify/flash-list/src/FlashList.tsx -@@ -827,6 +827,12 @@ class FlashList extends React.PureComponent< - return this.rlvRef?.getScrollableNode?.() || null; - } - -+ public getNativeScrollRef(): number | null { -+ // eslint-disable-next-line @typescript-eslint/ban-ts-comment -+ // @ts-ignore -+ return this.rlvRef?.getNativeScrollRef?.() || null; -+ } -+ - /** - * Allows access to internal recyclerlistview. This is useful for enabling access to its public APIs. - * Warning: We may swap recyclerlistview for something else in the future. Use with caution. -diff --git a/node_modules/@shopify/flash-list/src/fabric/AutoLayoutNativeComponent.ts b/node_modules/@shopify/flash-list/src/fabric/AutoLayoutNativeComponent.ts -new file mode 100644 -index 0000000..93750de ---- /dev/null -+++ b/node_modules/@shopify/flash-list/src/fabric/AutoLayoutNativeComponent.ts -@@ -0,0 +1,24 @@ -+import codegenNativeComponent from "react-native/Libraries/Utilities/codegenNativeComponent"; -+import type { ViewProps } from "react-native"; -+import type { -+ Int32, -+ Double, -+ DirectEventHandler, -+} from "react-native/Libraries/Types/CodegenTypes"; -+ -+type BlankAreaEvent = Readonly<{ -+ offsetStart: Int32; -+ offsetEnd: Int32; -+}>; -+ -+interface NativeProps extends ViewProps { -+ horizontal?: boolean; -+ scrollOffset?: Double; -+ windowSize?: Double; -+ renderAheadOffset?: Double; -+ enableInstrumentation?: boolean; -+ disableAutoLayout?: boolean; -+ onBlankAreaEvent?: DirectEventHandler; -+} -+ -+export default codegenNativeComponent("AutoLayoutView"); -diff --git a/node_modules/@shopify/flash-list/src/fabric/CellContainerNativeComponent.ts b/node_modules/@shopify/flash-list/src/fabric/CellContainerNativeComponent.ts -new file mode 100644 -index 0000000..dd284ac ---- /dev/null -+++ b/node_modules/@shopify/flash-list/src/fabric/CellContainerNativeComponent.ts -@@ -0,0 +1,9 @@ -+import codegenNativeComponent from "react-native/Libraries/Utilities/codegenNativeComponent"; -+import type { Int32 } from "react-native/Libraries/Types/CodegenTypes"; -+import type { ViewProps } from "react-native"; -+ -+interface NativeProps extends ViewProps { -+ index?: Int32; -+} -+ -+export default codegenNativeComponent("CellContainer"); diff --git a/react-native.config.js b/react-native.config.js index 6d6dd3f5805f..7dc0482f74bb 100644 --- a/react-native.config.js +++ b/react-native.config.js @@ -1,7 +1,10 @@ module.exports = { project: { - ios: {sourceDir: 'ios'}, - android: {}, + ios: {sourceDir: 'ios', + unstable_reactLegacyComponentNames: [ "AutoLayoutView", "CellContainer" ]}, + android: { + unstable_reactLegacyComponentNames: [ "AutoLayoutView", "CellContainer" ] + }, }, assets: ['./assets/fonts/native'], }; From 1bb5258d96d0507cc33d003fc7ad94ab099e4dfb Mon Sep 17 00:00:00 2001 From: Wojciech Lewicki Date: Fri, 12 Apr 2024 22:41:28 +0200 Subject: [PATCH 21/27] fix: prettier --- react-native.config.js | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/react-native.config.js b/react-native.config.js index 7dc0482f74bb..b941493529e7 100644 --- a/react-native.config.js +++ b/react-native.config.js @@ -1,9 +1,8 @@ module.exports = { project: { - ios: {sourceDir: 'ios', - unstable_reactLegacyComponentNames: [ "AutoLayoutView", "CellContainer" ]}, + ios: {sourceDir: 'ios', unstable_reactLegacyComponentNames: ['AutoLayoutView', 'CellContainer']}, android: { - unstable_reactLegacyComponentNames: [ "AutoLayoutView", "CellContainer" ] + unstable_reactLegacyComponentNames: ['AutoLayoutView', 'CellContainer'], }, }, assets: ['./assets/fonts/native'], From 2fc2ddd180344f22e60d0bcfbb916d2be8efb9f1 Mon Sep 17 00:00:00 2001 From: Yauheni Date: Sun, 14 Apr 2024 17:09:02 +0200 Subject: [PATCH 22/27] Fix eslint issue --- src/pages/workspace/WorkspaceInvitePage.tsx | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/src/pages/workspace/WorkspaceInvitePage.tsx b/src/pages/workspace/WorkspaceInvitePage.tsx index 940abd4279fb..0310104590e5 100644 --- a/src/pages/workspace/WorkspaceInvitePage.tsx +++ b/src/pages/workspace/WorkspaceInvitePage.tsx @@ -52,13 +52,7 @@ type WorkspaceInvitePageProps = WithPolicyAndFullscreenLoadingProps & WorkspaceInvitePageOnyxProps & StackScreenProps; -function WorkspaceInvitePage({ - route, - betas, - invitedEmailsToAccountIDsDraft, - policy, - isLoadingReportData = true, -}: WorkspaceInvitePageProps) { +function WorkspaceInvitePage({route, betas, invitedEmailsToAccountIDsDraft, policy, isLoadingReportData = true}: WorkspaceInvitePageProps) { const styles = useThemeStyles(); const {translate} = useLocalize(); const [searchTerm, setSearchTerm] = useState(''); From 91f90025e1803dff889adc3b079231899cdf03dd Mon Sep 17 00:00:00 2001 From: Yauheni Date: Sun, 14 Apr 2024 17:39:17 +0200 Subject: [PATCH 23/27] Add test for employeeList --- tests/actions/PolicyTest.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/actions/PolicyTest.ts b/tests/actions/PolicyTest.ts index 8495f822cdb4..44b69bcb86fe 100644 --- a/tests/actions/PolicyTest.ts +++ b/tests/actions/PolicyTest.ts @@ -59,6 +59,7 @@ describe('actions/Policy', () => { expect(policy?.owner).toBe(ESH_EMAIL); expect(policy?.isPolicyExpenseChatEnabled).toBe(true); expect(policy?.pendingAction).toBe(CONST.RED_BRICK_ROAD_PENDING_ACTION.ADD); + expect(policy?.employeeList).toEqual({[ESH_EMAIL]: {errors: {}, role: CONST.POLICY.ROLE.ADMIN}}); let allReports: OnyxCollection = await new Promise((resolve) => { const connectionID = Onyx.connect({ From 593f41e9ae3461b528144e36305ea59ab95018e2 Mon Sep 17 00:00:00 2001 From: Shridhar Goel <35566748+ShridharGoel@users.noreply.github.com> Date: Mon, 15 Apr 2024 12:19:39 +0530 Subject: [PATCH 24/27] Enable live markdown in IOU request descriptions --- src/pages/iou/request/step/IOURequestStepDescription.tsx | 1 + 1 file changed, 1 insertion(+) diff --git a/src/pages/iou/request/step/IOURequestStepDescription.tsx b/src/pages/iou/request/step/IOURequestStepDescription.tsx index d075ed81c956..70a7bbc7c885 100644 --- a/src/pages/iou/request/step/IOURequestStepDescription.tsx +++ b/src/pages/iou/request/step/IOURequestStepDescription.tsx @@ -176,6 +176,7 @@ function IOURequestStepDescription({ autoGrowHeight containerStyles={[styles.autoGrowHeightMultilineInput]} shouldSubmitForm + isMarkdownEnabled /> From 48545bb0bd4d87e80568a3e1c2c33c20de198e80 Mon Sep 17 00:00:00 2001 From: Yauheni Date: Mon, 15 Apr 2024 14:52:35 +0200 Subject: [PATCH 25/27] Update leaveWorkspace --- src/libs/actions/Policy.ts | 37 ++++++++++++++++--------------------- 1 file changed, 16 insertions(+), 21 deletions(-) diff --git a/src/libs/actions/Policy.ts b/src/libs/actions/Policy.ts index 90f3ac0aeef4..fffc992746d9 100644 --- a/src/libs/actions/Policy.ts +++ b/src/libs/actions/Policy.ts @@ -968,52 +968,47 @@ function removeMembers(accountIDs: number[], policyID: string) { } function leaveWorkspace(policyID: string) { - const membersListKey = `${ONYXKEYS.COLLECTION.POLICY_MEMBERS}${policyID}` as const; const policy = allPolicies?.[`${ONYXKEYS.COLLECTION.POLICY}${policyID}`]; const workspaceChats = ReportUtils.getAllWorkspaceReports(policyID); const optimisticData: OnyxUpdate[] = [ - { - onyxMethod: Onyx.METHOD.MERGE, - key: membersListKey, - value: { - [sessionAccountID]: { - pendingAction: CONST.RED_BRICK_ROAD_PENDING_ACTION.DELETE, - }, - }, - }, { onyxMethod: Onyx.METHOD.MERGE, key: `${ONYXKEYS.COLLECTION.POLICY}${policyID}`, value: { pendingAction: CONST.RED_BRICK_ROAD_PENDING_ACTION.DELETE, + employeeList: { + [sessionEmail]: { + pendingAction: CONST.RED_BRICK_ROAD_PENDING_ACTION.DELETE, + }, + }, }, }, ]; + const successData: OnyxUpdate[] = [ { onyxMethod: Onyx.METHOD.MERGE, - key: membersListKey, + key: `${ONYXKEYS.COLLECTION.POLICY}${policyID}`, value: { - [sessionAccountID]: null, + pendingAction: CONST.RED_BRICK_ROAD_PENDING_ACTION.DELETE, + employeeList: { + [sessionEmail]: null, + }, }, }, ]; const failureData: OnyxUpdate[] = [ - { - onyxMethod: Onyx.METHOD.MERGE, - key: membersListKey, - value: { - [sessionAccountID]: { - errors: ErrorUtils.getMicroSecondOnyxError('workspace.people.error.genericRemove'), - }, - }, - }, { onyxMethod: Onyx.METHOD.MERGE, key: `${ONYXKEYS.COLLECTION.POLICY}${policyID}`, value: { pendingAction: policy?.pendingAction, + employeeList: { + [sessionEmail]: { + errors: ErrorUtils.getMicroSecondOnyxError('workspace.people.error.genericRemove'), + }, + }, }, }, ]; From 6ad3d75dcd428c609ac665affbbe095bac9e94ec Mon Sep 17 00:00:00 2001 From: Jakub Piasecki Date: Tue, 16 Apr 2024 11:09:52 +0200 Subject: [PATCH 26/27] Keep relevant parts of the patch --- patches/@shopify+flash-list+1.6.3.patch | 46 +++++++++++++++++++++++++ 1 file changed, 46 insertions(+) create mode 100644 patches/@shopify+flash-list+1.6.3.patch diff --git a/patches/@shopify+flash-list+1.6.3.patch b/patches/@shopify+flash-list+1.6.3.patch new file mode 100644 index 000000000000..92308913026b --- /dev/null +++ b/patches/@shopify+flash-list+1.6.3.patch @@ -0,0 +1,46 @@ +diff --git a/node_modules/@shopify/flash-list/dist/FlashList.d.ts b/node_modules/@shopify/flash-list/dist/FlashList.d.ts +index ed81d7d..1e24103 100644 +--- a/node_modules/@shopify/flash-list/dist/FlashList.d.ts ++++ b/node_modules/@shopify/flash-list/dist/FlashList.d.ts +@@ -103,6 +103,7 @@ declare class FlashList extends React.PureComponent, FlashL + offset: number; + }): void; + getScrollableNode(): number | null; ++ getNativeScrollRef(): number | null; + /** + * Allows access to internal recyclerlistview. This is useful for enabling access to its public APIs. + * Warning: We may swap recyclerlistview for something else in the future. Use with caution. +diff --git a/node_modules/@shopify/flash-list/dist/FlashList.js b/node_modules/@shopify/flash-list/dist/FlashList.js +index 1a5d026..37852b8 100644 +--- a/node_modules/@shopify/flash-list/dist/FlashList.js ++++ b/node_modules/@shopify/flash-list/dist/FlashList.js +@@ -478,6 +478,12 @@ var FlashList = /** @class */ (function (_super) { + var _a, _b; + return ((_b = (_a = this.rlvRef) === null || _a === void 0 ? void 0 : _a.getScrollableNode) === null || _b === void 0 ? void 0 : _b.call(_a)) || null; + }; ++ FlashList.prototype.getNativeScrollRef = function () { ++ var _a, _b; ++ // eslint-disable-next-line @typescript-eslint/ban-ts-comment ++ // @ts-ignore ++ return ((_b = (_a = this.rlvRef) === null || _a === void 0 ? void 0 : _a.getNativeScrollRef) === null || _b === void 0 ? void 0 : _b.call(_a)) || null; ++ }; + Object.defineProperty(FlashList.prototype, "recyclerlistview_unsafe", { + /** + * Allows access to internal recyclerlistview. This is useful for enabling access to its public APIs. +diff --git a/node_modules/@shopify/flash-list/src/FlashList.tsx b/node_modules/@shopify/flash-list/src/FlashList.tsx +index 64748fe..87dea16 100644 +--- a/node_modules/@shopify/flash-list/src/FlashList.tsx ++++ b/node_modules/@shopify/flash-list/src/FlashList.tsx +@@ -827,6 +827,12 @@ class FlashList extends React.PureComponent< + return this.rlvRef?.getScrollableNode?.() || null; + } + ++ public getNativeScrollRef(): number | null { ++ // eslint-disable-next-line @typescript-eslint/ban-ts-comment ++ // @ts-ignore ++ return this.rlvRef?.getNativeScrollRef?.() || null; ++ } ++ + /** + * Allows access to internal recyclerlistview. This is useful for enabling access to its public APIs. + * Warning: We may swap recyclerlistview for something else in the future. Use with caution. From 1a20e163dad22c89b1242a4c167216ff034923e6 Mon Sep 17 00:00:00 2001 From: OSBotify Date: Tue, 16 Apr 2024 22:31:39 +0000 Subject: [PATCH 27/27] Update version to 1.4.62-13 --- android/app/build.gradle | 4 ++-- ios/NewExpensify/Info.plist | 2 +- ios/NewExpensifyTests/Info.plist | 2 +- ios/NotificationServiceExtension/Info.plist | 2 +- package-lock.json | 4 ++-- package.json | 2 +- 6 files changed, 8 insertions(+), 8 deletions(-) diff --git a/android/app/build.gradle b/android/app/build.gradle index b9a7fa4d6b4b..32dfb496daa8 100644 --- a/android/app/build.gradle +++ b/android/app/build.gradle @@ -98,8 +98,8 @@ android { minSdkVersion rootProject.ext.minSdkVersion targetSdkVersion rootProject.ext.targetSdkVersion multiDexEnabled rootProject.ext.multiDexEnabled - versionCode 1001046212 - versionName "1.4.62-12" + versionCode 1001046213 + versionName "1.4.62-13" // Supported language variants must be declared here to avoid from being removed during the compilation. // This also helps us to not include unnecessary language variants in the APK. resConfigs "en", "es" diff --git a/ios/NewExpensify/Info.plist b/ios/NewExpensify/Info.plist index 9db0bbd40945..0b59d7e8316d 100644 --- a/ios/NewExpensify/Info.plist +++ b/ios/NewExpensify/Info.plist @@ -40,7 +40,7 @@ CFBundleVersion - 1.4.62.12 + 1.4.62.13 ITSAppUsesNonExemptEncryption LSApplicationQueriesSchemes diff --git a/ios/NewExpensifyTests/Info.plist b/ios/NewExpensifyTests/Info.plist index c2fe74d90fcd..2a6db0634f2f 100644 --- a/ios/NewExpensifyTests/Info.plist +++ b/ios/NewExpensifyTests/Info.plist @@ -19,6 +19,6 @@ CFBundleSignature ???? CFBundleVersion - 1.4.62.12 + 1.4.62.13 diff --git a/ios/NotificationServiceExtension/Info.plist b/ios/NotificationServiceExtension/Info.plist index 7503dd04702b..50171f3eb050 100644 --- a/ios/NotificationServiceExtension/Info.plist +++ b/ios/NotificationServiceExtension/Info.plist @@ -13,7 +13,7 @@ CFBundleShortVersionString 1.4.62 CFBundleVersion - 1.4.62.12 + 1.4.62.13 NSExtension NSExtensionPointIdentifier diff --git a/package-lock.json b/package-lock.json index 0817e4bbbd2a..478ae3c12b3c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "new.expensify", - "version": "1.4.62-12", + "version": "1.4.62-13", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "new.expensify", - "version": "1.4.62-12", + "version": "1.4.62-13", "hasInstallScript": true, "license": "MIT", "dependencies": { diff --git a/package.json b/package.json index 60e6a320cfb0..e5092e132eae 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "new.expensify", - "version": "1.4.62-12", + "version": "1.4.62-13", "author": "Expensify, Inc.", "homepage": "https://new.expensify.com", "description": "New Expensify is the next generation of Expensify: a reimagination of payments based atop a foundation of chat.",