Skip to content

Skin tone fix#16604

Merged
mountiny merged 12 commits into
Expensify:mainfrom
margelo:perunt/skin-tone-fix
Apr 3, 2023
Merged

Skin tone fix#16604
mountiny merged 12 commits into
Expensify:mainfrom
margelo:perunt/skin-tone-fix

Conversation

@perunt

@perunt perunt commented Mar 28, 2023

Copy link
Copy Markdown
Contributor

Details

Fixed Issues

$ #15805
PROPOSAL: GH_LINK_ISSUE(COMMENT)

Tests

  1. Click on the text input field for chat to give it focus.
  2. Type :+1: in the text input field.
  3. Verify if the displayed emoji has the correct skin tone.
  4. Change the emoji's skin tone setting.
  5. Type :+1: in the text input field again.
  6. Verify if the displayed emoji now has the updated skin tone.

Repeat the same steps for the message edit input field.

  • Verify that no errors appear in the JS console

Offline tests

QA Steps

  • Verify that no errors appear in the JS console

PR Author Checklist

  • I have verified the author checklist is complete (all boxes are checked off).
  • I verified the correct issue is linked in the ### Fixed Issues section above
  • I verified testing steps are clear and they cover the changes made in this PR
    • I verified the steps for local testing are in the Tests section
    • I verified the steps for Staging and/or Production testing are in the QA steps section
    • I verified the steps cover any possible failure scenarios (i.e. verify an input displays the correct error message if the entered data is not correct)
    • I turned off my network connection and tested it while offline to ensure it matches the expected behavior (i.e. verify the default avatar icon is displayed if app is offline)
  • I checked that screenshots or videos are included for tests on all platforms
  • I included screenshots or videos for tests on all platforms
  • I verified tests pass on all platforms & I tested again on:
    • Android / native
    • Android / Chrome
    • iOS / native
    • iOS / Safari
    • MacOS / Chrome / Safari
    • MacOS / Desktop
  • If there are any errors in the console that are unrelated to this PR, I either fixed them (preferred) or linked to where I reported them in Slack
  • I verified proper code patterns were followed (see Reviewing the code)
    • I verified that any callback methods that were added or modified are named for what the method does and never what callback they handle (i.e. toggleReport and not onIconClick).
    • I verified that comments were added to code that is not self explanatory
    • I verified that any new or modified comments were clear, correct English, and explained "why" the code was doing something instead of only explaining "what" the code was doing.
    • I verified any copy / text shown in the product is localized by adding it to src/languages/* files and using the translation method
    • I verified all numbers, amounts, dates and phone numbers shown in the product are using the localization methods
    • I verified any copy / text that was added to the app is correct English and approved by marketing by adding the Waiting for Copy label for a copy review on the original GH to get the correct copy.
    • I verified proper file naming conventions were followed for any new files or renamed files. All non-platform specific files are named after what they export and are not named "index.js". All platform-specific files are named for the platform the code supports as outlined in the README.
    • I verified the JSDocs style guidelines (in STYLE.md) were followed
  • If a new code pattern is added I verified it was agreed to be used by multiple Expensify engineers
  • I verified that this PR follows the guidelines as stated in the Review Guidelines
  • I verified other components that can be impacted by these changes have been tested, and I retested again (i.e. if the PR modifies a shared library or component like Avatar, I verified the components using Avatar have been tested & I retested again)
  • I verified all code is DRY (the PR doesn't include any logic written more than once, with the exception of tests)
  • I verified any variables that can be defined as constants (ie. in CONST.js or at the top of the file that uses the constant) are defined as such
  • If a new component is created I verified that:
    • A similar component doesn't exist in the codebase
    • All props are defined accurately and each prop has a /** comment above it */
    • The file is named correctly
    • The component has a clear name that is non-ambiguous and the purpose of the component can be inferred from the name alone
    • The only data being stored in the state is data necessary for rendering and nothing else
    • For Class Components, any internal methods passed to components event handlers are bound to this properly so there are no scoping issues (i.e. for onClick={this.submit} the method this.submit should be bound to this in the constructor)
    • Any internal methods bound to this are necessary to be bound (i.e. avoid this.submit = this.submit.bind(this); if this.submit is never passed to a component event handler like onClick)
    • All JSX used for rendering exists in the render method
    • The component has the minimum amount of code necessary for its purpose, and it is broken down into smaller components in order to separate concerns and functions
  • If any new file was added I verified that:
    • The file has a description of what it does and/or why is needed at the top of the file if the code is not self explanatory
  • If a new CSS style is added I verified that:
    • A similar style doesn't already exist
    • The style can't be created with an existing StyleUtils function (i.e. StyleUtils.getBackgroundAndBorderStyle(themeColors.componentBG)
  • If the PR modifies a generic component, I tested and verified that those changes do not break usages of that component in the rest of the App (i.e. if a shared library or component like Avatar is modified, I verified that Avatar is working as expected in all cases)
  • If the PR modifies a component related to any of the existing Storybook stories, I tested and verified all stories for that component are still working as expected.
  • If a new page is added, I verified it's using the ScrollView component to make it scrollable when more elements are added to the page.
  • If the main branch was merged into this PR after a review, I tested again and verified the outcome was still expected according to the Test steps.
  • I have checked off every checkbox in the PR reviewer checklist, including those that don't apply to this PR.

Screenshots/Videos

Web
Mar-28-2023.10-02-32.mp4
Apr-03-2023.11-35-46.mp4
Mobile Web - Chrome
Mobile Web - Safari
Desktop

Uploading Apr-03-2023 11-45-17.mp4…

iOS

Uploading Apr-03-2023 11-42-58.mp4…

Android
Apr-03-2023.11-40-43.mp4

@perunt perunt marked this pull request as ready for review March 28, 2023 09:06
@perunt perunt requested a review from a team as a code owner March 28, 2023 09:06
@melvin-bot melvin-bot Bot requested review from PauloGasparSv and removed request for a team March 28, 2023 09:07
@MelvinBot

Copy link
Copy Markdown
Contributor

@PauloGasparSv Please copy/paste the Reviewer Checklist from here into a new comment on this PR and complete it. If you have the K2 extension, you can simply click: [this button]

@PauloGasparSv

PauloGasparSv commented Mar 28, 2023

Copy link
Copy Markdown
Contributor

Hey @perunt, I see you linked the GH issue like this$ [GH_LINK](https://github.com/Expensify/App/issues/15805) but please make sure to always link it like this instead $ https://github.com/Expensify/App/issues/15805.

That's important so the original issue's team members are assigned to the P.R. and so the issue is updated correctly when the P.R. is merged

Let me fix that for you and assign @mountiny here!

@PauloGasparSv

Copy link
Copy Markdown
Contributor

I think there is a console error for users that don't have a preferred skintone (e.g. creating a new account in newDot and sending :+1: generates the warning at the first try. Does it also happen for you @perunt @mountiny?

image

@esh-g

esh-g commented Mar 28, 2023

Copy link
Copy Markdown
Contributor

Hey, just a suggestion, You could use the getEmojiCodeWithSkinColour method that is already present in the EmojiUtils.js

let emojiReplacement = getEmojiCodeWithSkinColor(checkEmoji.metaData, preferredSkinTone);

@esh-g

esh-g commented Mar 28, 2023

Copy link
Copy Markdown
Contributor

Also, the current code causes a crash when we try to edit a message.

Screen.Recording.2023-03-28.at.4.55.40.PM-1.mov

Note: The comment above does not fix this crash, that was just an alternative way of dealing with the skinTone

@mountiny mountiny requested a review from s77rt March 28, 2023 12:09

@mountiny mountiny left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you @PauloGasparSv for the headstart and @esh-g for the tips!

Assigned @s77rt for testing and review

@perunt thanks for working on this so quickly, could you also please add videos on all the platforms? Thank you 🙇

Comment thread src/libs/EmojiUtils.js Outdated
Comment thread src/libs/EmojiUtils.js Outdated
@esh-g

esh-g commented Mar 28, 2023

Copy link
Copy Markdown
Contributor

I also found a way to fix the crash!
We should use initWithStoredValues: false with the onyx key so that the reference to this component is always available.

preferredSkinTone: {
    key: ONYXKEYS.PREFERRED_EMOJI_SKIN_TONE,
    initWithStoredValues: false,
},

@s77rt

s77rt commented Mar 28, 2023

Copy link
Copy Markdown
Member

@esh-g What crash is this supposed to fix?

@esh-g

esh-g commented Mar 28, 2023

Copy link
Copy Markdown
Contributor

It is currently crashing because we are focusing on the textInput here:

focusTextInputAfterAnimation(this.textInput, 100);

But this.textInput is undefined as the ref is not yet ready due to onyx. Similar to this issue: #15296 (comment)

@Pujan92

Pujan92 commented Mar 28, 2023

Copy link
Copy Markdown
Contributor

It is currently crashing because we are focusing on the textInput here:

focusTextInputAfterAnimation(this.textInput, 100);

But this.textInput is undefined as the ref is not yet ready due to onyx. Similar to this issue: #15296 (comment)

Yes, as we immediately focusing the textinput for edit message and onyx fetch won't allow to render the child immediately which will throw the undefined ref issue.

@esh-g

esh-g commented Mar 28, 2023

Copy link
Copy Markdown
Contributor

Okay, Just needed to add the condition to update the component on change to preferredSkinTone and the crash is fixed and works as expected

shouldComponentUpdate(nextProps, nextState) {
        return this.props.displayAsGroup !== nextProps.displayAsGroup
            || this.props.draftMessage !== nextProps.draftMessage
            || this.props.isMostRecentIOUReportAction !== nextProps.isMostRecentIOUReportAction
            || this.props.hasOutstandingIOU !== nextProps.hasOutstandingIOU
            || this.props.shouldDisplayNewMarker !== nextProps.shouldDisplayNewMarker
            || !_.isEqual(this.props.action, nextProps.action)
            || this.state.isContextMenuActive !== nextState.isContextMenuActive
+            || this.props.preferredSkinTone !== nextProps.preferredSkinTone;
    }
    ```

@esh-g

esh-g commented Mar 28, 2023

Copy link
Copy Markdown
Contributor

Here is a summary of the changes I am suggesting:

  1. Add initWithStoredValues: false to the preferredSkinTone key in ReportActionItemMessage.js
  2. Add a condition in ReportActionItem.js shouldComponentUpdate, to have it update when the value of preferredSkinTone changes.

These changes will prevent the crash and also preserve the intended functionality.

Screen.Recording.2023-03-28.at.6.59.45.PM-1.mov

@s77rt

s77rt commented Mar 28, 2023

Copy link
Copy Markdown
Member

Setting initWithStoredValues to false is not the correct approach.

@esh-g

esh-g commented Mar 29, 2023

Copy link
Copy Markdown
Contributor

@s77rt Have you also added the condition in shouldComponentUpdate?

@s77rt

s77rt commented Mar 29, 2023

Copy link
Copy Markdown
Member

@esh-g Yes. no effect.


As an alternative solution maybe we should pass preferredSkinTone as prop to ReportActionItemMessageEdit instead of using onyx: <ReportActionItemMessageEdit preferredSkinTone={this.props.preferredSkinTone} />

Although this solution works well it is not the most optimal as we will re-render every report action (even those that are not in edit mode) if the skin tone is changed. Actually this is looking good...

@perunt

perunt commented Mar 30, 2023

Copy link
Copy Markdown
Contributor Author

We can consolidate ReportActionItemMessage and ReportActionItemMessageEdit into a single file, though it may not be the most optimal solution.

@s77rt

s77rt commented Mar 30, 2023

Copy link
Copy Markdown
Member

@perunt I really don't see why would we merge those files into one. Isn't this achieving the same results of the proposed alternative solution above ^

@perunt

perunt commented Mar 31, 2023

Copy link
Copy Markdown
Contributor Author

In this case, only the Message component would be re-rendered upon modifying the skin tone, while the ReportActionItem remains unchanged. This approach is not flawless, as it still involves some re-rendering.

@perunt perunt marked this pull request as ready for review March 31, 2023 09:00
Comment thread src/pages/home/report/ReportActionItemMessageEdit.js
Comment thread src/pages/home/report/ReportActionItemMessageEdit.js Outdated
@s77rt

s77rt commented Apr 3, 2023

Copy link
Copy Markdown
Member

Reviewer Checklist

  • I have verified the author checklist is complete (all boxes are checked off).
  • I verified the correct issue is linked in the ### Fixed Issues section above
  • I verified testing steps are clear and they cover the changes made in this PR
    • I verified the steps for local testing are in the Tests section
    • I verified the steps for Staging and/or Production testing are in the QA steps section
    • I verified the steps cover any possible failure scenarios (i.e. verify an input displays the correct error message if the entered data is not correct)
    • I turned off my network connection and tested it while offline to ensure it matches the expected behavior (i.e. verify the default avatar icon is displayed if app is offline)
  • I checked that screenshots or videos are included for tests on all platforms
  • I included screenshots or videos for tests on all platforms
  • I verified tests pass on all platforms & I tested again on:
    • Android / native
    • Android / Chrome
    • iOS / native
    • iOS / Safari
    • MacOS / Chrome / Safari
    • MacOS / Desktop
  • If there are any errors in the console that are unrelated to this PR, I either fixed them (preferred) or linked to where I reported them in Slack
  • I verified proper code patterns were followed (see Reviewing the code)
    • I verified that any callback methods that were added or modified are named for what the method does and never what callback they handle (i.e. toggleReport and not onIconClick).
    • I verified that comments were added to code that is not self explanatory
    • I verified that any new or modified comments were clear, correct English, and explained "why" the code was doing something instead of only explaining "what" the code was doing.
    • I verified any copy / text shown in the product is localized by adding it to src/languages/* files and using the translation method
    • I verified all numbers, amounts, dates and phone numbers shown in the product are using the localization methods
    • I verified any copy / text that was added to the app is correct English and approved by marketing by adding the Waiting for Copy label for a copy review on the original GH to get the correct copy.
    • I verified proper file naming conventions were followed for any new files or renamed files. All non-platform specific files are named after what they export and are not named "index.js". All platform-specific files are named for the platform the code supports as outlined in the README.
    • I verified the JSDocs style guidelines (in STYLE.md) were followed
  • If a new code pattern is added I verified it was agreed to be used by multiple Expensify engineers
  • I verified that this PR follows the guidelines as stated in the Review Guidelines
  • I verified other components that can be impacted by these changes have been tested, and I retested again (i.e. if the PR modifies a shared library or component like Avatar, I verified the components using Avatar have been tested & I retested again)
  • I verified all code is DRY (the PR doesn't include any logic written more than once, with the exception of tests)
  • I verified any variables that can be defined as constants (ie. in CONST.js or at the top of the file that uses the constant) are defined as such
  • If a new component is created I verified that:
    • A similar component doesn't exist in the codebase
    • All props are defined accurately and each prop has a /** comment above it */
    • The file is named correctly
    • The component has a clear name that is non-ambiguous and the purpose of the component can be inferred from the name alone
    • The only data being stored in the state is data necessary for rendering and nothing else
    • For Class Components, any internal methods passed to components event handlers are bound to this properly so there are no scoping issues (i.e. for onClick={this.submit} the method this.submit should be bound to this in the constructor)
    • Any internal methods bound to this are necessary to be bound (i.e. avoid this.submit = this.submit.bind(this); if this.submit is never passed to a component event handler like onClick)
    • All JSX used for rendering exists in the render method
    • The component has the minimum amount of code necessary for its purpose, and it is broken down into smaller components in order to separate concerns and functions
  • If any new file was added I verified that:
    • The file has a description of what it does and/or why is needed at the top of the file if the code is not self explanatory
  • If a new CSS style is added I verified that:
    • A similar style doesn't already exist
    • The style can't be created with an existing StyleUtils function (i.e. StyleUtils.getBackgroundAndBorderStyle(themeColors.componentBG)
  • If the PR modifies a generic component, I tested and verified that those changes do not break usages of that component in the rest of the App (i.e. if a shared library or component like Avatar is modified, I verified that Avatar is working as expected in all cases)
  • If the PR modifies a component related to any of the existing Storybook stories, I tested and verified all stories for that component are still working as expected.
  • If a new page is added, I verified it's using the ScrollView component to make it scrollable when more elements are added to the page.
  • If the main branch was merged into this PR after a review, I tested again and verified the outcome was still expected according to the Test steps.
  • I have checked off every checkbox in the PR reviewer checklist, including those that don't apply to this PR.

Screenshots/Videos

Web
web.mp4
Mobile Web - Chrome
mweb-chrome.mp4
Mobile Web - Safari
mweb-safari.mp4
Desktop
desktop.mp4
iOS
ios.mp4
Android
android.mp4

@s77rt s77rt left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just a minor suggestion

Comment thread src/libs/EmojiUtils.js Outdated
Comment thread src/pages/home/report/ReportActionItem.js Outdated
Comment thread src/pages/home/report/ReportActionItemMessageEdit.js Outdated

@mountiny mountiny left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@perunt Lets address the comments from @s77rt and then we can have a final look at this. Thanks everyone

@mountiny mountiny requested a review from s77rt April 3, 2023 13:33
@mountiny

mountiny commented Apr 3, 2023

Copy link
Copy Markdown
Contributor

@s77rt can you do a final tests/check and approve the PR if all is good please?

@s77rt s77rt left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM! 🚀

@mountiny mountiny left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Lets do this then, thanks everyone!

@Expensify Expensify deleted a comment from PauloGasparSv Apr 3, 2023
@mountiny mountiny merged commit f68a199 into Expensify:main Apr 3, 2023
@OSBotify

OSBotify commented Apr 3, 2023

Copy link
Copy Markdown
Contributor

✋ This PR was not deployed to staging yet because QA is ongoing. It will be automatically deployed to staging after the next production release.

@OSBotify

OSBotify commented Apr 3, 2023

Copy link
Copy Markdown
Contributor

🚀 Deployed to staging by https://github.com/mountiny in version: 1.2.94-0 🚀

platform result
🤖 android 🤖 success ✅
🖥 desktop 🖥 success ✅
🍎 iOS 🍎 failure ❌
🕸 web 🕸 success ✅

Comment thread src/libs/EmojiUtils.js
const checkEmoji = emojisTrie.search(emojiData[i].slice(1, -1));
if (checkEmoji && checkEmoji.metaData.code) {
let emojiReplacement = checkEmoji.metaData.code;
let emojiReplacement = this.getEmojiCodeWithSkinColor(checkEmoji.metaData, preferredSkinTone);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This line caused this regression #16896 , We should remove the this. keyword and simply call the getEmojiCodeWithSkinColor() function directly.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How come I was not able to reproduce this on localhost? Is this caused by the diff between debug javascript files and the built ones?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this keyword refer to the module EmojiUtils, on dev environment variables and function names are preserved , When code is minified during production, function and variable names are often changed to shorter, more efficient names. This can cause issues if you are using this to access functions or entities, as the new names may not match the original names.

Dev Same module on production
Screenshot 2023-04-04 at 5 34 42 AM Screenshot 2023-04-04 at 5 34 23 AM

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good find, and that's quite interesting about this. working on Dev but not production 🤔 Maybe we need some better eslint rules to catch this in the future?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Beamanator That would be good. Can you please create a tracking issue for this one? The lint rule is good approach to prevent this bug but what about other unknown diff between dev and built js files?

@OSBotify

OSBotify commented Apr 5, 2023

Copy link
Copy Markdown
Contributor

🚀 Deployed to production by https://github.com/thienlnam in version: 1.2.94-3 🚀

platform result
🤖 android 🤖 success ✅
🖥 desktop 🖥 success ✅
🍎 iOS 🍎 success ✅
🕸 web 🕸 success ✅

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

10 participants