diff --git a/src/ONYXKEYS.ts b/src/ONYXKEYS.ts index 11c2318672d8..b7c1962e1b41 100755 --- a/src/ONYXKEYS.ts +++ b/src/ONYXKEYS.ts @@ -268,6 +268,8 @@ const ONYXKEYS = { // Manual request tab selector SELECTED_TAB: 'selectedTab_', + PERSONAL_DETAILS: 'personalDetails_', + /** This is deprecated, but needed for a migration, so we still need to include it here so that it will be initialized in Onyx.init */ DEPRECATED_POLICY_MEMBER_LIST: 'policyMemberList_', }, diff --git a/src/components/UserDetailsTooltip/BaseUserDetailsTooltip.web.js b/src/components/UserDetailsTooltip/BaseUserDetailsTooltip.web.js index 871173d01b56..d6d8fbd7e20d 100644 --- a/src/components/UserDetailsTooltip/BaseUserDetailsTooltip.web.js +++ b/src/components/UserDetailsTooltip/BaseUserDetailsTooltip.web.js @@ -16,8 +16,7 @@ import {defaultProps, propTypes} from './userDetailsTooltipPropTypes'; function BaseUserDetailsTooltip(props) { const {translate} = useLocalize(); - - const userDetails = lodashGet(props.personalDetailsList, props.accountID, props.fallbackUserDetails); + const userDetails = props.personalDetails ?? props.fallbackUserDetails; let userDisplayName = userDetails.displayName ? userDetails.displayName.trim() : ''; let userLogin = (userDetails.login || '').trim() && !_.isEqual(userDetails.login, userDetails.displayName) ? Str.removeSMSDomain(userDetails.login) : ''; let userAvatar = userDetails.avatar; @@ -26,11 +25,8 @@ function BaseUserDetailsTooltip(props) { // We replace the actor's email, name, and avatar with the Copilot manually for now. This will be improved upon when // the Copilot feature is implemented. if (props.delegateAccountID) { - const delegateUserDetails = lodashGet(props.personalDetailsList, props.delegateAccountID, {}); - const delegateUserDisplayName = delegateUserDetails.displayName ? delegateUserDetails.displayName.trim() : ''; - userDisplayName = `${delegateUserDisplayName} (${translate('reportAction.asCopilot')} ${userDisplayName})`; - userLogin = delegateUserDetails.login; - userAvatar = delegateUserDetails.avatar; + userDisplayName = `${userDisplayName} (${translate('reportAction.asCopilot')} ${userDisplayName})`; + userLogin = userDetails.login; userAccountID = props.delegateAccountID; } @@ -79,7 +75,10 @@ BaseUserDetailsTooltip.defaultProps = defaultProps; BaseUserDetailsTooltip.displayName = 'BaseUserDetailsTooltip'; export default withOnyx({ - personalDetailsList: { - key: ONYXKEYS.PERSONAL_DETAILS_LIST, + personalDetails: { + key: ({delegateAccountID, accountID}) => { + const id = delegateAccountID ?? accountID; + return `${ONYXKEYS.COLLECTION.PERSONAL_DETAILS}${id}`; + }, }, })(BaseUserDetailsTooltip); diff --git a/src/libs/migrateOnyx.js b/src/libs/migrateOnyx.js index b65670819418..2e92811dd8b0 100644 --- a/src/libs/migrateOnyx.js +++ b/src/libs/migrateOnyx.js @@ -3,6 +3,7 @@ import Log from './Log'; import KeyReportActionsDraftByReportActionID from './migrations/KeyReportActionsDraftByReportActionID'; import PersonalDetailsByAccountID from './migrations/PersonalDetailsByAccountID'; import RenameReceiptFilename from './migrations/RenameReceiptFilename'; +import PersonalDetailsToCollection from './migrations/PersonalDetailsToCollection'; export default function () { const startTime = Date.now(); @@ -10,7 +11,7 @@ export default function () { return new Promise((resolve) => { // Add all migrations to an array so they are executed in order - const migrationPromises = [PersonalDetailsByAccountID, RenameReceiptFilename, KeyReportActionsDraftByReportActionID]; + const migrationPromises = [PersonalDetailsByAccountID, RenameReceiptFilename, KeyReportActionsDraftByReportActionID, PersonalDetailsToCollection]; // Reduce all promises down to a single promise. All promises run in a linear fashion, waiting for the // previous promise to finish before moving onto the next one. diff --git a/src/libs/migrations/PersonalDetailsToCollection.js b/src/libs/migrations/PersonalDetailsToCollection.js new file mode 100644 index 000000000000..733f3602ef4b --- /dev/null +++ b/src/libs/migrations/PersonalDetailsToCollection.js @@ -0,0 +1,47 @@ +import Onyx from 'react-native-onyx'; +import _ from 'lodash'; +import ONYXKEYS from '../../ONYXKEYS'; +import Log from '../Log'; + +// This migration changes personalDetailsList to a collection so that we can subscribe to changes on a single personalDetails +export default function PersonalDetailsToCollection() { + return new Promise((resolve) => { + // Check if migration has already been run + const outerConnectionID = Onyx.connect({ + key: ONYXKEYS.COLLECTION.PERSONAL_DETAILS, + waitForCollectionCallback: true, + callback: (personalDetailsCollection) => { + Onyx.disconnect(outerConnectionID); + if (personalDetailsCollection) { + Log.info('[Migrate Onyx] Skipping migration PersonalDetailsToCollection because it is already migrated'); + return resolve(); + } + + const connectionID = Onyx.connect({ + key: ONYXKEYS.PERSONAL_DETAILS_LIST, + waitForCollectionCallback: true, + callback: (personalDetailsList) => { + Onyx.disconnect(connectionID); + const personalDetailsListLength = _.keys(personalDetailsList).length; + if (!personalDetailsList || personalDetailsListLength === 0) { + Log.info('[Migrate Onyx] Skipped migration PersonalDetailsToCollection because there are no personalDetailsList'); + return resolve(); + } + + Log.info('[Migrate Onyx] Running PersonalDetailsToCollection migration'); + const dataToSave = _.mapKeys( + personalDetailsList, + (_value, key) => `${ONYXKEYS.COLLECTION.PERSONAL_DETAILS}${key}` + ); + + // eslint-disable-next-line rulesdir/prefer-actions-set-data + Onyx.mergeCollection(ONYXKEYS.COLLECTION.PERSONAL_DETAILS, dataToSave).then(() => { + Log.info(`[Migrate Onyx] Ran migration PersonalDetailsToCollection - moved object with ${personalDetailsListLength} keys to a collection`); + resolve(); + }); + }, + }); + }, + }); + }); +}