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

Long lines in code blocks should not wrap issue (#7497) is fixed #8790

Merged
merged 21 commits into from
May 9, 2022

Conversation

orkunkarakus
Copy link
Contributor

@orkunkarakus orkunkarakus commented Apr 26, 2022

Details

Issue is code blocks no scrolling in touchable platforms and long lines in code blocks wraping.
The problem in the mentioned issue link has been resolved with this pr and it works smoothly on all platforms.

Fixed Issues

$ https://github.com/Expensify/App/issues/7497

Tests

  1. Open app
  2. Send few long lines of code in chat like this
- name: Decrypt Botify GPG key
        run: cd .github/workflows && gpg --quiet --batch --yes --decrypt --passphrase="$LARGE_SECRET_PASSPHRASE" --output OSBotify-private-key.asc OSBotify-private-key.asc.gpg
        env:
          LARGE_SECRET_PASSPHRASE: ${{ secrets.LARGE_SECRET_PASSPHRASE }}
  1. Verify that Long lines in code blocks should not wrap and scrolling smoothly.
  • Verify that no errors appear in the JS console

PR Review Checklist

Contributor (PR Author) Checklist

  • I linked the correct issue in the ### Fixed Issues section above
  • I wrote clear testing steps that cover the changes made in this PR
    • I added steps for local testing in the Tests section
    • I added steps for Staging and/or Production testing in the QA steps section
    • I added steps to cover 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 included screenshots or videos for tests on all platforms
  • I ran the tests on all platforms & verified they passed on:
    • iOS / native
    • Android / native
    • iOS / Safari
    • Android / Chrome
    • MacOS / Chrome
    • MacOS / Desktop
  • I verified there are no console errors (if there’s a console error not related to the PR, report it or open an issue for it to be fixed)
  • I followed proper code patterns (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 was added in all src/languages/* files
    • I verified any copy / text that was added to the app is correct English and approved by marketing by tagging the marketing team 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 followed the guidelines as stated in the Review Guidelines
  • I tested other components that can be impacted by my changes (i.e. if the PR modifies a shared library or component like Avatar, I verified the components using Avatar are working as expected)
  • 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 */
    • Any functional components have the displayName property
    • 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
  • 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.

PR Reviewer Checklist

  • 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 verified tests pass on all platforms & I tested again on:
    • iOS / native
    • Android / native
    • iOS / Safari
    • Android / Chrome
    • MacOS / Chrome
    • MacOS / Desktop
  • I verified there are no console errors (if there’s a console error not related to the PR, report it or open an issue for it to be fixed)
  • 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 was added in all src/languages/* files
    • I verified any copy / text that was added to the app is correct English and approved by marketing by tagging the marketing team 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 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 */
    • Any functional components have the displayName property
    • 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 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.

QA Steps

  1. Open app
  2. Send few long lines of code in chat like this
- name: Decrypt Botify GPG key
        run: cd .github/workflows && gpg --quiet --batch --yes --decrypt --passphrase="$LARGE_SECRET_PASSPHRASE" --output OSBotify-private-key.asc OSBotify-private-key.asc.gpg
        env:
          LARGE_SECRET_PASSPHRASE: ${{ secrets.LARGE_SECRET_PASSPHRASE }}
  1. Verify that Long lines in code blocks should not wrap and scrolling smoothly.
  • Verify that no errors appear in the JS console

Screenshots

Web

web-expensify.mov

Mobile Web

Simulator Screen Shot - iPhone 13 - 2022-04-26 at 23 43 06

Desktop

desktop-expensify.mov

iOS

ios-expensify.mp4

Android

android-expensify.mov

@orkunkarakus orkunkarakus requested a review from a team as a code owner April 26, 2022 21:44
@melvin-bot melvin-bot bot requested review from NikkiWines and parasharrajat and removed request for a team April 26, 2022 21:44
@github-actions
Copy link
Contributor

github-actions bot commented Apr 26, 2022

CLA Assistant Lite bot All contributors have signed the CLA ✍️ ✅

@orkunkarakus
Copy link
Contributor Author

I have read the CLA Document and I hereby sign the CLA

@parasharrajat
Copy link
Member

Although, the checkboxes are checked on the Contributor (PR Author) Checklist code is not following that. This checklist must be followed. Please update the PR and let me know when ready.

@orkunkarakus
Copy link
Contributor Author

orkunkarakus commented Apr 27, 2022

Although, the checkboxes are checked on the Contributor (PR Author) Checklist code is not following that. This checklist must be followed. Please update the PR and let me know when ready.

@parasharrajat thanks for response. I refactored the pr but I read all of them one by one and I couldn't find the item that I didn't fit. Can you tell me which items I do not comply with? Because items often contain probability. For example "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)" even if there is no generic component intervention in this item, shouldn't this item be ticked?

Comment on lines 34 to 35
const isHoverableDevice = ((Platform.OS === 'web') || (Platform.OS === 'windows') || (Platform.OS === 'macos'));
if ((e.nativeEvent.state !== State.ACTIVE) || isHoverableDevice) {
Copy link
Member

Choose a reason for hiding this comment

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

Doing platform-specific code this way is not allowed. If you want to run some code on a platform use files like index.web.js or index.android.js or index.native.js etc. there are a few libs in src/libs folder which you can take as an example.

Copy link
Member

Choose a reason for hiding this comment

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

Also, Could you please explain to me what are you trying to do here? I can offer alternatives.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Thanks for the detailed response. My purpose here is not to create platform-based code, but to check whether the device is a hoverable device or not. On Hoverable device the Long press handler perceives it as holding it while scrolling and puts us in the action function. I disable the long press handler on hoverable devices with this control.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

At the same time, if I write this file separately for each platform like index.web.js or index.android.js or index.native.js the same file will be repeated for some platforms. Therefore there will be more than one of the same file.

Copy link
Member

Choose a reason for hiding this comment

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

Ok, so you mean that you want to do something for Web and Desktop. So create like this

isHoverable
 index.native.js returns false;
 index.js  returns true

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yes it seems like a good idea, thanks. Then I convert it to like this and test it. After the tests, I will update the pr and let you know.

Copy link
Member

Choose a reason for hiding this comment

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

A better name would be hasHoverSupport

Copy link
Contributor Author

@orkunkarakus orkunkarakus Apr 27, 2022

Choose a reason for hiding this comment

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

Changed the name and made 1 more commit 👍🏼
Retested after this update and found no issues.

Copy link
Member

@parasharrajat parasharrajat left a comment

Choose a reason for hiding this comment

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

Context Menu is not working on mWeb.

Steps:

  1. Open the app on MWeb.
  2. Press and Hold on to any message.
  3. No Action Menu.

@orkunkarakus
Copy link
Contributor Author

orkunkarakus commented Apr 27, 2022

Context Menu is not working on mWeb.

Steps:

  1. Open the app on MWeb.
  2. Press and Hold on to any message.
  3. No Action Menu.

@parasharrajat Thanks for the response. I fixed this issue.
Simulator Screen Shot - iPhone 13 - 2022-04-27 at 23 54 57

@orkunkarakus
Copy link
Contributor Author

@parasharrajat I guess you didn't receive a notification because I tagged you later. Pr is ready for testing.

@parasharrajat
Copy link
Member

Web (firefox)
image

@shawnborton Does this look fine? When we hover over the scrollbar it covers the content.

Copy link
Member

@parasharrajat parasharrajat left a comment

Choose a reason for hiding this comment

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

The code looks good.

@shawnborton
Copy link
Contributor

It looks like the scroll bar cuts off the content a little bit though. Is that expected? Perhaps that only happens on hover?

@parasharrajat
Copy link
Member

Yeah, it only happens on hover. Not sure if this is expected. @orkunkarakus Do you have a solution for this?

@shawnborton
Copy link
Contributor

FWIW I think that's probably fine if it's only cutting off the text like that on hover.

@orkunkarakus
Copy link
Contributor Author

orkunkarakus commented May 2, 2022

Yeah, it only happens on hover. Not sure if this is expected. @orkunkarakus Do you have a solution for this?

@parasharrajat Increasing the padding will be enough. Sended new commit for this bug.

cc: @shawnborton

image

@shawnborton
Copy link
Contributor

My concern with increasing the padding is that this might look strange without the scrollbar now? Can you show me what it looks like without the scrollbar and with the various paddings so we can compare? Thanks!

@orkunkarakus
Copy link
Contributor Author

orkunkarakus commented May 2, 2022

My concern with increasing the padding is that this might look strange without the scrollbar now? Can you show me what it looks like without the scrollbar and with the various paddings so we can compare? Thanks!

@shawnborton sure.

With old padding
image
image

Padding increased
image
image

@shawnborton
Copy link
Contributor

Can you show me those same screenshots but without content that needs to horizontally scroll?

@orkunkarakus
Copy link
Contributor Author

Can you show me those same screenshots but without content that needs to horizontally scroll?

@shawnborton sure. I updated my previous post

Comment on lines 7 to 22
class BasePreRenderer extends React.Component {
render() {
const TDefaultRenderer = this.props.TDefaultRenderer;
const defaultRendererProps = _.omit(this.props, ['TDefaultRenderer']);
return (
<ScrollView ref={this.props.innerRef} horizontal>
<View onStartShouldSetResponder={() => true}>
<TDefaultRenderer
// eslint-disable-next-line react/jsx-props-no-spreading
{...defaultRendererProps}
/>
</View>
</ScrollView>
);
}
}
Copy link
Member

Choose a reason for hiding this comment

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

Looks like a perfect candidate for the functional components. Please read the style guide and correct all style issues.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Looks like a perfect candidate for the functional components. Please read the style guide and correct all style issues.

@parasharrajat i refactored. Please re-check

.removeEventListener('wheel', this.wheelEvent);
}

wheelEvent(event) {
Copy link
Member

@parasharrajat parasharrajat May 3, 2022

Choose a reason for hiding this comment

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

Rename this function. The function name should define what it does instead of where it used.
scrollNode.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@parasharrajat I changed the function name to scrollNode


wheelEvent(event) {
const node = this.ref.current.getScrollableNode();
const checkOverflow = (node.scrollHeight / node.scrollWidth) !== (node.offsetHeight / node.offsetWidth);
Copy link
Member

Choose a reason for hiding this comment

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

Does not seem correct. scrollWidth is used for horizontal scrolling and scrollHeight for vertical scrolling. Shouldn't this be like
HorizontalOverflow = node.scrollWidth > node.offsetWidth

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@parasharrajat i changed it like this

import _ from 'underscore';
import htmlRendererPropTypes from '../htmlRendererPropTypes';

class BasePreRenderer extends React.Component {
Copy link
Member

Choose a reason for hiding this comment

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

this is still class component. 😕

Copy link
Contributor Author

@orkunkarakus orkunkarakus May 3, 2022

Choose a reason for hiding this comment

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

Looks like a perfect candidate for the functional components. Please read the style guide and correct all style issues.

@parasharrajat I interpreted your sentence as this style is very good for functional components but not good for classes.
And it was functional before and we converted it to class, so I never looked in that direction and looked at the styling guide again and again to see where is a mistake 😃
i converted and committed Pr is ready.

parasharrajat
parasharrajat previously approved these changes May 4, 2022
Copy link
Member

@parasharrajat parasharrajat left a comment

Choose a reason for hiding this comment

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

Looking good.

cc: @NikkiWines

🎀 👀 🎀 C+ reviewed

Copy link
Contributor

@NikkiWines NikkiWines left a comment

Choose a reason for hiding this comment

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

Couple of stylistic comments, works well otherwise 👍

return;
}
this.ref
.getScrollableNode()
Copy link
Contributor

Choose a reason for hiding this comment

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

this.ref.getScrollableNode() for stylistic consistency

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Refactored

const PreRenderer = props => (
<BasePreRenderer
// eslint-disable-next-line react/jsx-props-no-spreading
{...props}
Copy link
Contributor

Choose a reason for hiding this comment

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

Props can be inline:

    // eslint-disable-next-line react/jsx-props-no-spreading
    <BasePreRenderer {...props} />

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Refactored.

<View
onStartShouldSetResponder={() => true}
>
<TDefaultRenderer
Copy link
Contributor

Choose a reason for hiding this comment

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

Same as below, props can be inline

Copy link
Contributor Author

Choose a reason for hiding this comment

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

refactored

Copy link
Contributor

Choose a reason for hiding this comment

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

Ah, @orkunkarakus sorry if I was unclear. I meant that you could do the following:

             <View onStartShouldSetResponder={() => true}>
-                <TDefaultRenderer
-                    // eslint-disable-next-line react/jsx-props-no-spreading
-                    {...defaultRendererProps}
-                />
+                {/* eslint-disable-next-line react/jsx-props-no-spreading */}
+                <TDefaultRenderer {...defaultRendererProps} />
             </View>

Copy link
Contributor

@NikkiWines NikkiWines May 9, 2022

Choose a reason for hiding this comment

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

But moving <View onStartShouldSetResponder={() => true}> to a single line is also a good change 👍

<View
onStartShouldSetResponder={() => true}
>
<TDefaultRenderer
Copy link
Contributor

Choose a reason for hiding this comment

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

Ah, @orkunkarakus sorry if I was unclear. I meant that you could do the following:

             <View onStartShouldSetResponder={() => true}>
-                <TDefaultRenderer
-                    // eslint-disable-next-line react/jsx-props-no-spreading
-                    {...defaultRendererProps}
-                />
+                {/* eslint-disable-next-line react/jsx-props-no-spreading */}
+                <TDefaultRenderer {...defaultRendererProps} />
             </View>

<View
onStartShouldSetResponder={() => true}
>
<TDefaultRenderer
Copy link
Contributor

@NikkiWines NikkiWines May 9, 2022

Choose a reason for hiding this comment

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

But moving <View onStartShouldSetResponder={() => true}> to a single line is also a good change 👍

@orkunkarakus
Copy link
Contributor Author

Ah, @orkunkarakus sorry if I was unclear. I meant that you could do the following:

@NikkiWines Sorry, I thought it was View line.
I refactored and committed 👍

Copy link
Contributor

@NikkiWines NikkiWines left a comment

Choose a reason for hiding this comment

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

👍

@NikkiWines
Copy link
Contributor

Going to merge (once tests pass) as @parasharrajat had previously approved and my suggestions were all stylistic changes.

@NikkiWines NikkiWines merged commit cc6ed5f into Expensify:main May 9, 2022
@OSBotify
Copy link
Contributor

OSBotify commented May 9, 2022

✋ 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
Copy link
Contributor

🚀 Deployed to staging by @NikkiWines in version: 1.1.58-0 🚀

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

@OSBotify
Copy link
Contributor

🚀 Deployed to production by @AndrewGable in version: 1.1.60-3 🚀

platform result
🤖 android 🤖 success ✅
🖥 desktop 🖥 success ✅
🍎 iOS 🍎 failure ❌
🕸 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.

5 participants