Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

Fix "user is typing..." indicator - key by accountID #21029

Merged
merged 10 commits into from
Jun 19, 2023
30 changes: 24 additions & 6 deletions src/libs/actions/PersonalDetails.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,10 @@ Onyx.connect({
},
});

let personalDetails;
let allPersonalDetails;
Onyx.connect({
key: ONYXKEYS.PERSONAL_DETAILS_LIST,
callback: (val) => (personalDetails = val),
callback: (val) => (allPersonalDetails = val),
});

/**
Expand All @@ -37,7 +37,7 @@ function getDisplayName(login, personalDetail) {
// If we have a number like [email protected] then let's remove @expensify.sms and format it
marcaaron marked this conversation as resolved.
Show resolved Hide resolved
// so that the option looks cleaner in our UI.
const userLogin = LocalePhoneNumber.formatPhoneNumber(login);
const userDetails = personalDetail || lodashGet(personalDetails, login);
const userDetails = personalDetail || lodashGet(allPersonalDetails, login);

if (!userDetails) {
return userLogin;
Expand All @@ -50,6 +50,23 @@ function getDisplayName(login, personalDetail) {
return fullName || userLogin;
}

/**
*
Beamanator marked this conversation as resolved.
Show resolved Hide resolved
* @param {Number} accountID
* @param {String} [defaultDisplayName] display name to use if user details don't exist in Onyx or if
* found details don't include the user's displayName or login
* @returns {String}
*/
function getDisplayNameByAccountID(accountID, defaultDisplayName = '') {
Beamanator marked this conversation as resolved.
Show resolved Hide resolved
const userDetails = allPersonalDetails && lodashGet(allPersonalDetails, accountID, {});
Beamanator marked this conversation as resolved.
Show resolved Hide resolved

if (_.isEmpty(userDetails)) {
return defaultDisplayName;
}

return userDetails.displayName || getDisplayName(userDetails.login || '', userDetails) || defaultDisplayName;
}

/**
* Gets the first and last name from the user's personal details.
* If the login is the same as the displayName, then they don't exist,
Expand Down Expand Up @@ -402,8 +419,8 @@ function updateAvatar(file) {
key: ONYXKEYS.PERSONAL_DETAILS_LIST,
value: {
[currentUserAccountID]: {
avatar: personalDetails[currentUserAccountID].avatar,
avatarThumbnail: personalDetails[currentUserAccountID].avatarThumbnail || personalDetails[currentUserAccountID].avatar,
avatar: allPersonalDetails[currentUserAccountID].avatar,
avatarThumbnail: allPersonalDetails[currentUserAccountID].avatarThumbnail || allPersonalDetails[currentUserAccountID].avatar,
pendingFields: {
avatar: null,
},
Expand Down Expand Up @@ -439,7 +456,7 @@ function deleteAvatar() {
key: ONYXKEYS.PERSONAL_DETAILS_LIST,
value: {
[currentUserAccountID]: {
avatar: personalDetails[currentUserAccountID].avatar,
avatar: allPersonalDetails[currentUserAccountID].avatar,
},
},
},
Expand All @@ -466,6 +483,7 @@ function clearAvatarErrors() {

export {
getDisplayName,
getDisplayNameByAccountID,
updateAvatar,
deleteAvatar,
openMoneyRequestModalPage,
Expand Down
18 changes: 10 additions & 8 deletions src/libs/actions/Report.js
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,8 @@ function getReportChannelName(reportID) {
function getNormalizedTypingStatus(typingStatus) {
let normalizedTypingStatus = typingStatus;

// TODO: figure out what to do from here
// probably look up login in personalDetails and convert to accountID if it exists
if (_.first(_.keys(typingStatus)) === 'userLogin') {
normalizedTypingStatus = {[typingStatus.userLogin]: true};
}
Expand All @@ -118,26 +120,26 @@ function subscribeToReportTypingEvents(reportID) {
const pusherChannelName = getReportChannelName(reportID);
Pusher.subscribe(pusherChannelName, Pusher.TYPE.USER_IS_TYPING, (typingStatus) => {
const normalizedTypingStatus = getNormalizedTypingStatus(typingStatus);
const login = _.first(_.keys(normalizedTypingStatus));
const accountID = _.first(_.keys(normalizedTypingStatus));

if (!login) {
if (!accountID) {
return;
}

// Don't show the typing indicator if a user is typing on another platform
if (login === currentUserEmail) {
// Don't show the typing indicator if the user is typing on another platform
if (accountID === currentUserAccountID) {
return;
}

// Use a combo of the reportID and the login as a key for holding our timers.
const reportUserIdentifier = `${reportID}-${login}`;
// Use a combo of the reportID and the accountID as a key for holding our timers.
Beamanator marked this conversation as resolved.
Show resolved Hide resolved
const reportUserIdentifier = `${reportID}-${accountID}`;
clearTimeout(typingWatchTimers[reportUserIdentifier]);
Onyx.merge(`${ONYXKEYS.COLLECTION.REPORT_USER_IS_TYPING}${reportID}`, normalizedTypingStatus);

// Wait for 1.5s of no additional typing events before setting the status back to false.
typingWatchTimers[reportUserIdentifier] = setTimeout(() => {
const typingStoppedStatus = {};
typingStoppedStatus[login] = false;
typingStoppedStatus[accountID] = false;
Onyx.merge(`${ONYXKEYS.COLLECTION.REPORT_USER_IS_TYPING}${reportID}`, typingStoppedStatus);
delete typingWatchTimers[reportUserIdentifier];
}, 1500);
Expand Down Expand Up @@ -747,7 +749,7 @@ function setReportWithDraft(reportID, hasDraft) {
function broadcastUserIsTyping(reportID) {
const privateReportChannelName = getReportChannelName(reportID);
const typingStatus = {};
typingStatus[currentUserEmail] = true;
typingStatus[currentUserAccountID] = true;
Pusher.sendEvent(privateReportChannelName, Pusher.TYPE.USER_IS_TYPING, typingStatus);
}

Expand Down
4 changes: 2 additions & 2 deletions src/pages/home/report/ReportTypingIndicator.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ const defaultProps = {
};

function ReportTypingIndicator(props) {
const usersTyping = useMemo(() => _.filter(_.keys(props.userTypingStatuses), (login) => props.userTypingStatuses[login]), [props.userTypingStatuses]);
const usersTyping = useMemo(() => _.filter(_.keys(props.userTypingStatuses), (accountID) => props.userTypingStatuses[accountID]), [props.userTypingStatuses]);
Beamanator marked this conversation as resolved.
Show resolved Hide resolved
Beamanator marked this conversation as resolved.
Show resolved Hide resolved
// If we are offline, the user typing statuses are not up-to-date so do not show them
if (props.network.isOffline) {
return null;
Expand All @@ -43,7 +43,7 @@ function ReportTypingIndicator(props) {
case 1:
return (
<TextWithEllipsis
leadingText={PersonalDetails.getDisplayName(usersTyping[0])}
leadingText={PersonalDetails.getDisplayNameByAccountID(usersTyping[0], 'Someone')}
Beamanator marked this conversation as resolved.
Show resolved Hide resolved
trailingText={` ${props.translate('reportTypingIndicator.isTyping')}`}
textStyle={[styles.chatItemComposeSecondaryRowSubText]}
wrapperStyle={[styles.chatItemComposeSecondaryRow, styles.flex1]}
Expand Down