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

[HOLD for payment 2023-04-27] [$1000] App crashes on editing and deleting the emoji messages on #admins on Android in an Offline mode #17164

Closed
1 of 6 tasks
kavimuru opened this issue Apr 7, 2023 · 42 comments
Assignees
Labels
Awaiting Payment Auto-added when associated PR is deployed to production Bug Something is broken. Auto assigns a BugZero manager. Daily KSv2 Engineering External Added to denote the issue can be worked on by a contributor

Comments

@kavimuru
Copy link

kavimuru commented Apr 7, 2023

If you haven’t already, check out our contributing guidelines for onboarding and email contributors@expensify.com to request to join our Slack channel!


Action Performed:

  1. Go to android app and turn off your wifi
  2. Go to any admins room of any workspace
  3. Send a message with only emojis -> 3-4 emojis (do not include text)
  4. Long press the message and immediately click on edit message and add one emoji
  5. Click on save
  6. Now immediately delete the message and notice that the app crashes

Expected Result:

App should not crash on deleting the edited messages only with emojis on Android

Actual Result:

App crashes on deleting the edited messages with only emojis on Android offline

Workaround:

unknown

Platforms:

Which of our officially supported platforms is this issue occurring on?

  • Android / native
  • Android / Chrome
  • iOS / native
  • iOS / Safari
  • MacOS / Chrome / Safari
  • MacOS / Desktop

Version Number:
Reproducible in staging?: needs reproduction
Reproducible in production?: needs reproduction
If this was caught during regression testing, add the test name, ID and link from TestRail:
Email or phone of affected tester (no customers):
Logs: https://stackoverflow.com/c/expensify/questions/4856
Notes/Photos/Videos: Any additional supporting documentation

crash.mp4

Expensify/Expensify Issue URL:
Issue reported by: @priya-zha
Slack conversation: https://expensify.slack.com/archives/C049HHMV9SM/p1680859522702889

View all open jobs on GitHub

Upwork Automation - Do Not Edit
  • Upwork Job URL: https://www.upwork.com/jobs/~01aafa0e43a1c87311
  • Upwork Job ID: 1646091515798622208
  • Last Price Increase: 2023-04-12
@kavimuru kavimuru added Daily KSv2 Needs Reproduction Reproducible steps needed Bug Something is broken. Auto assigns a BugZero manager. labels Apr 7, 2023
@MelvinBot
Copy link

Triggered auto assignment to @alexpensify (Bug), see https://stackoverflow.com/c/expensify/questions/14418 for more details.

@MelvinBot
Copy link

MelvinBot commented Apr 7, 2023

Bug0 Triage Checklist (Main S/O)

  • This "bug" occurs on a supported platform (ensure Platforms in OP are ✅)
  • This bug is not a duplicate report (check E/App issues and #expensify-bugs)
    • If it is, comment with a link to the original report, close the issue and add any novel details to the original issue instead
  • This bug is reproducible using the reproduction steps in the OP. S/O
    • If the reproduction steps are clear and you're unable to reproduce the bug, check with the reporter and QA first, then close the issue.
    • If the reproduction steps aren't clear and you determine the correct steps, please update the OP.
  • This issue is filled out as thoroughly and clearly as possible
    • Pay special attention to the title, results, platforms where the bug occurs, and if the bug happens on staging/production.
  • I have reviewed and subscribed to the linked Slack conversation to ensure Slack/Github stay in sync

@alexpensify

This comment was marked as resolved.

@alexpensify

This comment was marked as resolved.

@alexpensify
Copy link
Contributor

This one is wild because after I enable cell/wifi service, then the edited emoji list from the offline is there.

@MelvinBot
Copy link

Triggered auto assignment to @techievivek (Engineering), see https://stackoverflow.com/c/expensify/questions/4319 for more details.

@alexpensify
Copy link
Contributor

@techievivek - Assigning to engineering to get feedback on how we want this to function before assigning External.

@techievivek techievivek added External Added to denote the issue can be worked on by a contributor and removed Needs Reproduction Reproducible steps needed labels Apr 12, 2023
@melvin-bot melvin-bot bot changed the title App crashes on editing and deleting the emoji messages on #admins on Android in an Offline mode [$1000] App crashes on editing and deleting the emoji messages on #admins on Android in an Offline mode Apr 12, 2023
@MelvinBot
Copy link

Job added to Upwork: https://www.upwork.com/jobs/~01aafa0e43a1c87311

@MelvinBot
Copy link

Current assignee @alexpensify is eligible for the External assigner, not assigning anyone new.

@MelvinBot
Copy link

Triggered auto assignment to Contributor-plus team member for initial proposal review - @s77rt (External)

@melvin-bot melvin-bot bot added the Help Wanted Apply this label when an issue is open to proposals by contributors label Apr 12, 2023
@tienifr
Copy link
Contributor

tienifr commented Apr 12, 2023

Proposal

Please re-state the problem that we are trying to solve in this issue.

When we send a message in offline mode, then immediately delete it, the app crashes.
I think we should update the bug description, since it's happening everywhere (not just #admin channel, but also any chat which was not preloaded in Onyx), and with any text being sent (not only emojis)

What is the root cause of that problem?

First, let's look at the message deletion logic in Report.js

It contains a logic to check if the item being deleted is the last visible message, then it would search for previous message to update the latest message in LHN. This logic calls the getLastVisibleMessageText() function.

Now let's look at the getLastVisibleMessageText() function

function getLastVisibleMessageText(reportID, actionsToMerge = {}) {
const lastVisibleAction = getLastVisibleAction(reportID, actionsToMerge);
const message = lodashGet(lastVisibleAction, ['message', 0]);
if (isReportMessageAttachment(message)) {
return CONST.ATTACHMENT_MESSAGE_TEXT;
}
const htmlText = lodashGet(lastVisibleAction, 'message[0].html', '');
const parser = new ExpensiMark();
const messageText = parser.htmlToText(htmlText);
return String(messageText)
.replace(CONST.REGEX.AFTER_FIRST_LINE_BREAK, '')
.substring(0, CONST.REPORT.LAST_MESSAGE_TEXT_MAX_LENGTH);
}

Notice the getLastVisibleAction() function call. In a normal scenario with network connection, this function would return a list of previous message, where the new latest message could be obtained. The list contains previous chat messages, which also includes a dummy welcome message at the beginning of the chat. For example, in a case where we are online, and we try to send a text to a new chat, then immediately delete it, the result of the getLastVisibleAction() function would be

[{"style": "strong", "text": "__fake__", "type": "TEXT"}]

That's why in online mode, the app always works when we try to delete messages.

Now let's look at the scenario when we try to delete a message in offline mode. When we access a chat which was not preloaded in Onyx, no previous messages were loaded in Onyx, which causes the getLastVisibleAction() function to return [], since it's using allReportActions from Onyx. Because the getLastVisibleMessageText() function use the first item in the array as the latest message, this value would be undefined, which trigger the app crash because the app is expecting the latest message value to have a text field in order to be rendered correctly in LHN. This is the reason that it will work in cases where the messages are already in Onyx, like this

Screenshot 2023-04-11 at 15 15 55

and will crash in cases where the messages are not loaded yet, like this (notice the chat is still loading)

Screenshot 2023-04-11 at 15 03 19

What changes do you think we should make in order to solve the problem?

To solve this problem, we could add a guard logic in getLastVisibleMessageText() to return '' if the message is undefined, something like

function getLastVisibleMessageText(reportID, actionsToMerge = {}) {
    const lastVisibleAction = getLastVisibleAction(reportID, actionsToMerge);
    const message = lodashGet(lastVisibleAction, ['message', 0]);
+   if (!message)
+      return ''

Furthermore (and optionally), shall we decide for the LHN to not update the previous message if the deleted message is null, we could add another logic inside deleteReportComment() function to only update the last message if it is a valid text

        optimisticReport = {
-           lastMessageText,
            lastVisibleActionCreated,
        };
+      if (lastMessageText !== '') 
+         optimisticReport.lastMessageText = lastMessageText

This will make the LHN to keep the message, instead of deleting it and replace with the default message (i.e the first dummy welcome message). The text will be kept until it's back online again, the user access the report and it will be updated as the actual latest message. Since we are in offline mode, I think there is no proper solution to get the last message which were replaced with our new sent-and-deleted message.

Alternative solutions

Alternatively, in the getLastVisibleMessageText() function, we could add a simple logic to check if message is null or undefined, then we will reassign it to a dummy message, which could be the first dummy welcome message like described above, or something like [Deleted message].

Another way to do it is to add a check logic in the getLastVisibleAction() function to prevent it to return an empty array. If the status is offline and the history is empty, we will append a dummy message

Result

Working well after the fix

https://drive.google.com/file/d/1GGFZKVP3QjHKOSbgwYJUd_UKvXt-uOKb/view?usp=sharing

@MelvinBot
Copy link

Current assignee @techievivek is eligible for the External assigner, not assigning anyone new.

@melvin-bot melvin-bot bot added the Overdue label Apr 13, 2023
@techievivek
Copy link
Contributor

techievivek commented Apr 13, 2023

Not overdue, waiting for @s77rt to take a look at the proposal(s). 😄

@melvin-bot melvin-bot bot removed the Overdue label Apr 13, 2023
@s77rt
Copy link
Contributor

s77rt commented Apr 13, 2023

Sorry for the delay, will review asap.

@s77rt

This comment was marked as resolved.

@s77rt
Copy link
Contributor

s77rt commented Apr 13, 2023

@tienifr Thanks for the proposal. Your RCA is correct. The suggested fix looks good to me. I just have two minor optimisations to consider while raising the PR:

  1. getLastVisibleAction will return -Infinity if visibleActions is empty but this function is supposed to return an object. Let's make an early return with an empty object for such case.
  2. Instead of checking for falsy message, let's just default to an empty object on lodashGet.

🎀 👀 🎀 C+ reviewed

cc @techievivek

@tienifr
Copy link
Contributor

tienifr commented Apr 13, 2023

@s77rt Thanks for the review!

For your 1st optimization, I agree we should make an early return with empty object to prevent returning undefined when there is no visible actions.

For your 2nd optimization, we should keep the check for falsy message. Returning an empty object will not be enough since the isReportMessageAttachment() function, which use the falsy message, is assuming the message would have text and html field. I don't want to modify this function, so the falsy message check should be kept.

For final confirmation, the changes in the PR would be

  1. (Your suggestion) Change default to empty object in lodashGet to prevent falsy message object
  2. (Your suggestion + my proposal) Default to an empty object on lodashGet and add a check to return empty string when the aforementioned object is empty
  3. (My proposal) Add a logic inside deleteReportComment() function to only update the last message only if it is a valid text (not an empty string). This will prevent the LHN preview text to update when there is no message history.

Thoughts?

@tienifr
Copy link
Contributor

tienifr commented Apr 17, 2023

The PR is ready for review: #17450.

@alexpensify
Copy link
Contributor

alexpensify commented Apr 19, 2023

The PR is still under review but moving along.

@tienifr
Copy link
Contributor

tienifr commented Apr 20, 2023

Regression Test Proposal

Bug: App crashes on message deletion in empty chat in Offline mode

Proposed Test Steps:

  1. Login with any account
  2. Reload the page to make sure all chat data in Onyx is cleared
  3. Turn off your internet connection
  4. Go to any chat
  5. Verify that no message has been loaded in the chat (i.e. skeleton view)
  6. Send any message
  7. Delete the message
  8. Verify that the app does not crash and the message should show strike-through
Screencast.from.14-04-2023.15.49.46.webm

Do we 👍 or 👎

@s77rt
Copy link
Contributor

s77rt commented Apr 20, 2023

@tienifr You no longer need to provide regression test proposals. It's a part of C+ process now.

@melvin-bot melvin-bot bot added Weekly KSv2 Awaiting Payment Auto-added when associated PR is deployed to production and removed Daily KSv2 labels Apr 20, 2023
@melvin-bot melvin-bot bot changed the title [$1000] App crashes on editing and deleting the emoji messages on #admins on Android in an Offline mode [HOLD for payment 2023-04-27] [$1000] App crashes on editing and deleting the emoji messages on #admins on Android in an Offline mode Apr 20, 2023
@melvin-bot melvin-bot bot removed the Reviewing Has a PR in review label Apr 20, 2023
@MelvinBot
Copy link

Reviewing label has been removed, please complete the "BugZero Checklist".

@MelvinBot
Copy link

The solution for this issue has been 🚀 deployed to production 🚀 in version 1.3.2-5 and is now subject to a 7-day regression period 📆. Here is the list of pull requests that resolve this issue:

If no regressions arise, payment will be issued on 2023-04-27. 🎊

After the hold period is over and BZ checklist items are completed, please complete any of the applicable payments for this issue, and check them off once done.

  • External issue reporter
  • Contributor that fixed the issue
  • Contributor+ that helped on the issue and/or PR

As a reminder, here are the bonuses/penalties that should be applied for any External issue:

  • Merged PR within 3 business days of assignment - 50% bonus
  • Merged PR more than 9 business days after assignment - 50% penalty

@MelvinBot
Copy link

MelvinBot commented Apr 20, 2023

BugZero Checklist: The PR fixing this issue has been merged! The following checklist (instructions) will need to be completed before the issue can be closed:

  • [@s77rt] The PR that introduced the bug has been identified. Link to the PR:
  • [@s77rt] The offending PR has been commented on, pointing out the bug it caused and why, so the author and reviewers can learn from the mistake. Link to comment:
  • [@s77rt] A discussion in #expensify-bugs has been started about whether any other steps should be taken (e.g. updating the PR review checklist) in order to catch this type of bug sooner. Link to discussion:
  • [@alexpensify] Determine if we should create a regression test for this bug.
  • [@s77rt] If we decide to create a regression test for the bug, please propose the regression test steps to ensure the same bug will not reach production again.
  • [@alexpensify] Link the GH issue for creating/updating the regression test once above steps have been agreed upon: https://github.com/Expensify/Expensify/issues/277726

@s77rt
Copy link
Contributor

s77rt commented Apr 21, 2023


Regression Test Proposal

  1. Open App
  2. Login with an old account (had previous chats with other users)
  3. Turn off your internet connection
  4. Go to any old chat
  5. Verify no message is loaded
  6. Verify a skeleton loader is shown
  7. Send a message
  8. Delete that message
  9. Verify the message is strike-through
  10. Verify the App didn't crash

@techievivek
Copy link
Contributor

The regression test looks good to me. @alexpensify can we add this to testRail. Thanks

@alexpensify
Copy link
Contributor

Done! Following this SO process (https://stackoverflowteams.com/c/expensify/questions/363/364#364), I created the GH to add to testrails.

@alexpensify
Copy link
Contributor

BugZero Checklist is complete-- now waiting for the payment date to start that process.

@melvin-bot melvin-bot bot added Daily KSv2 and removed Weekly KSv2 labels Apr 27, 2023
@alexpensify
Copy link
Contributor

Looks like we are all clear here, I'll work on the payment process tomorrow.

@alexpensify
Copy link
Contributor

alexpensify commented Apr 28, 2023

I saw this in another GH and want to give it a try here to ensure that the payment is correct.

We have the following payouts. I see there is a 50% bonus because it was assigned here on April 17 and was merged into production on April 20:

Issue reporter: $250 - @priya-zha
Contributor: $1,500 - @tienifr
Contributor+: $1,500- @s77rt

@techievivek or @s77rt - Can you please 👍🏼 if you agree and I'll complete the next steps in Upwork. Thank you!

@s77rt
Copy link
Contributor

s77rt commented Apr 28, 2023

@alexpensify It's actually $1,500 not $2,000.

BTW, The bonus timeline is from contributor being assigned to PR getting merged (and not necessary deployed to production). So it's from April 17th to April 19th.

@alexpensify
Copy link
Contributor

@s77rt - Thank you for checking my numbers. I've updated the amounts in my comment. Also, thank you for clarifying it's not production but merging. I was looking at the merge action but said production. 🤕 I'll work on these payments in Upwork.

@alexpensify
Copy link
Contributor

Alright, all payments have been prepared in Upwork and are pending approval from the contributors. I'll finish the process as soon as everyone signs off in Upwork. Thanks!

@alexpensify
Copy link
Contributor

@tienifr - please accept the job in Upwork so I can complete the payment process, thank you.

@tienifr
Copy link
Contributor

tienifr commented May 2, 2023

@alexpensify hi, I tried to accept the offer but it says the offer has been withdrawn, can you help double check?

Thanks!

@alexpensify
Copy link
Contributor

alexpensify commented May 2, 2023

@tienifr - Not sure what happened in Upwork, but I sent over a new offer. Please accept and I can complete the payment. Thanks!

@tienifr
Copy link
Contributor

tienifr commented May 2, 2023

@alexpensify accepted, thanks!

@alexpensify
Copy link
Contributor

Closing because the project is done and everyone has been paid! Great work here!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Awaiting Payment Auto-added when associated PR is deployed to production Bug Something is broken. Auto assigns a BugZero manager. Daily KSv2 Engineering External Added to denote the issue can be worked on by a contributor
Projects
None yet
Development

No branches or pull requests

6 participants