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

Multiple tabs are opening on clicking the concept cards link thrice #4532

Closed
KolliAnitha opened this issue Aug 25, 2022 · 26 comments · Fixed by #4939
Closed

Multiple tabs are opening on clicking the concept cards link thrice #4532

KolliAnitha opened this issue Aug 25, 2022 · 26 comments · Fixed by #4939
Assignees
Labels
bug End user-perceivable behaviors which are not desirable. Impact: Low Low perceived user impact (e.g. edge cases). Work: Medium The means to find the solution is clear, but it isn't at good-first-issue level yet. Z-ibt Temporary label for Ben to keep track of issues he's triaged.

Comments

@KolliAnitha
Copy link

KolliAnitha commented Aug 25, 2022

Describe the bug
Multiple tabs are opening on clicking the concept cards link thrice

To Reproduce
Steps to reproduce the behavior:

  1. Go to 'Percentages' - Revision
  2. Click on 'Converting Percentages to Decimals'
  3. Scroll down to click on equicalent fraction link multiple times
  4. See the no.of tabs opened

Expected behavior
Since the same link is clicked multiple times, single tab must be opened instead of multiple tabs

Demonstration
https://user-images.githubusercontent.com/101634267/186579350-9d2f05b5-d408-40f0-aaa2-2afeb82b0d4b.mp4

Environment
Device name: One plus Nord2 5G
Android version : Android 11
App version : 0.8-alpha-091b45a188

@seanlip
Copy link
Member

seanlip commented Aug 25, 2022

@BenHenning Just noting this since you might want to take a look if you're looking at concept cards currently.

Feel free to deassign if you don't think it's a quick fix.

@BenHenning
Copy link
Member

This is a known problem, though I don't think there's an issue filed for it yet.

The work I'm doing with concept cards is mostly unrelated to this. I think the fix is to not open the concept card dialog if it's already open, but that's a bit tricky in the new world where multiple concept cards can be opened at once (i.e. for cases when a concept card links to another). We will have to look into introducing dynamic keys to make that work properly, based on the skill ID being shown.

This is probably not a very long fix, but it's certainly not a quick one.

@BenHenning BenHenning removed their assignment Aug 25, 2022
@BenHenning BenHenning added Impact: Low Low perceived user impact (e.g. edge cases). Z-ibt Temporary label for Ben to keep track of issues he's triaged. issue_user_learner labels Sep 15, 2022
@rishujam
Copy link

rishujam commented Nov 8, 2022

Hey, I am new to this project. I can't find the percentage revision

@BenHenning
Copy link
Member

Hi @rishujam, welcome!

The Percentages lessons are production-only, so they aren't available in the local developer build of the app. That being said, you could try to repro this issue by using concept cards that are available in the local app. Concept cards can be accessed via the revision cards in the "first test topic" topic that you can open from the local developer build of the app.

You could also download and install the beta version of the app from Play Store to get access to the Percentages lessons (at least to try and build familiarity with how to repro the issue as that understanding may be transferable over to the developer version that you can iterate on).

@rishujam
Copy link

?

@seanlip
Copy link
Member

seanlip commented Nov 10, 2022 via email

@rishujam
Copy link

This is the result after multiple clicks it only opens once.

20221110_221345_Trim.mp4

Approach:
I made a state class for the card (open, close, or default) and after the first click, I set that state to opened and checks the state on the click listener before opening the dialog.

@seanlip
Copy link
Member

seanlip commented Nov 10, 2022

Thanks! One question -- will your fix work in the case where a concept card contains an interior link to a different concept card?

@rishujam
Copy link

rishujam commented Nov 10, 2022

Yes, but I have to write this state code there also (everywhere this issue is occurring). If you could list where are these occurring I can fix those all.

@seanlip
Copy link
Member

seanlip commented Nov 10, 2022

Actually, any concept card can have a link to a different concept card. So you'd need to write a fix to handle this case such that it would automatically work anywhere concept cards are used (including new additions to the codebase later). I think this is why Ben said it's a bit tricky to fix this.

If you have an idea how to do this, that's great, but if not, you might want to tackle a different issue instead since the proposed solution might not be maintainable.

@seanlip
Copy link
Member

seanlip commented Nov 10, 2022

Yes, I think so -- @BenHenning may be able to provide more colour here, but I think that that is the basic idea.

Though, thinking about it, this gets a bit complex -- what if concept card A references B, which in turn references A again? So some product design might be needed here. To start with, I think we can just stack them: open each card "in front" of the previous one, and the user has to close it to reveal the previous card. It's fine to impose a "max depth" of 3 or 5 cards too, but that is optional. Will your approach account for this case?

@rishujam
Copy link

Not for now but will try.

@seanlip
Copy link
Member

seanlip commented Nov 10, 2022

OK, thanks! Feel free to ping this thread with a video and description of your approach when you have an update.

@rishujam
Copy link

Hey, how about this?
We can maintain a stack. See if the top of the stack is the same as the Card we are going to add then we do not open it. If it's different then only we open it.

@seanlip
Copy link
Member

seanlip commented Nov 11, 2022 via email

@rishujam
Copy link

rishujam commented Nov 12, 2022

The only case we do not open the card is those extra clicks done by mistake. Which is our goal to neglect right?

Example:
A -> B are 2 Cards that need to be opened on top of each other. First card A opens (add card A to stack) and now to open card B user clicked 3 times. Now for the first click, B will be added to the stack and the card will open. The rest 2 clicks will be neglected as we will check the stack before opening another card. This way there will not be multiple cards B.

@seanlip
Copy link
Member

seanlip commented Nov 12, 2022

Oh, I see. Yup that sounds fine! Thanks!

I'll assign you, feel free to make a PR.

@rishujam
Copy link

Need help
What I thought: We need something that lives as long as all the cards in order to maintain the stack.

  1. Parent fragment from where the first card was opened- Thought this way is not good for testing as we will need to write that code in every parent fragment from where cards are being created.
  2. Can't add in ConceptCardFrag too as the different cards will have a different instance of ConceptCardFrag and different ViewModel inside them.

Where should I attach the stack?

rishujam added a commit to rishujam/oppia-android that referenced this issue Nov 14, 2022
@rishujam
Copy link

Implemented a solution. Will create PR once I go through PR guidance and code style.

rishujam added a commit to rishujam/oppia-android that referenced this issue Nov 14, 2022
rishujam added a commit to rishujam/oppia-android that referenced this issue Nov 14, 2022
@BenHenning
Copy link
Member

Need help What I thought: We need something that lives as long as all the cards in order to maintain the stack.

  1. Parent fragment from where the first card was opened- Thought this way is not good for testing as we will need to write that code in every parent fragment from where cards are being created.
  2. Can't add in ConceptCardFrag too as the different cards will have a different instance of ConceptCardFrag and different ViewModel inside them.

Where should I attach the stack?

Hmm, concept card already stacks by default since it's a dialog fragment. We usually manage cross-activity state using domain-level controllers (that can live for the lifetime of the application), but that's tricky here since we don't have an easy way to associate backend state with showing/hiding dialog fragments.

I think your working approach in #4719 could be made to be a robust solution, but a few changes would be needed:

  • We should avoid showing the concept card if it's already showing (rather than dismissing after the fact--this will avoid potential visual jank).
  • We should make sure that we have a way of strictly observing the lifetime of the concept card (perhaps by binding to the fragment's lifecycle?) to ensure that the tracked list is always kept up-to-date.
  • The utility holding the backstack needs to be injectable and marked as @Singleton scope so that it retained across fragment instances.

We may even be able to generalize this for all dialog fragments, but let's start with concept cards first and see what the solution ends up looking like @rishujam.

rishujam added a commit to rishujam/oppia-android that referenced this issue Nov 15, 2022
rishujam added a commit to rishujam/oppia-android that referenced this issue Nov 15, 2022
@rishujam
Copy link

I have to write a test file for the back stack manager and I just got into unit testing and roboelectric. I have some questions related to this.

  1. As my main manager class has just contains 4 functions of add, remove, peek, destroy so I don't need to write test about that right?
  2. I have to test that the lifecycle of the manager stick to concept cards until all the cards are closed.
  3. If possible can you send any resource about lifecycle testing or any demo inside this project that do somethings similar.

@rishujam
Copy link

Please guide me about testing this back stack manager.

@BenHenning
Copy link
Member

I have to write a test file for the back stack manager and I just got into unit testing and roboelectric. I have some questions related to this.

  1. As my main manager class has just contains 4 functions of add, remove, peek, destroy so I don't need to write test about that right?
  2. I have to test that the lifecycle of the manager stick to concept cards until all the cards are closed.
  3. If possible can you send any resource about lifecycle testing or any demo inside this project that do somethings similar.

@rishujam per (1), each class that can be tested, should be tested. We have a few exceptions today (presenters, view models, and interfaces), but we try to test every other class. The reasons for this are two-fold:
(a) Having narrow, specific tests allow us to catch regressions closer to the source of the failure (this is part of the "fail fast" philosophy.
(b) Tests are part of public contract of a component. They more exactly define exactly what behaviors a component is capable of supporting (vs. just an API and documentation which don't actually strong enforce these behaviors).

Per (2), I'm not sure what the question is here--could you maybe clarify? Generally, we try to test all major "happy path" (i.e. cases where nothing goes wrong) and failure cases.

Per (3), I can't think of a close example at the moment, but to some extent all of our orientation change tests are verifying a lifecycle-related test. We also have LiveData tests in DataProviderTest, but those might be a bit complicated. The main idea behind testing lifecycles is determining the different possible states of an object within its lifecycle, the conditions that could lead to those states, and then creating tests to verify each of these scenarios.

@rishujam
Copy link

Thanks, last point (3) gave me some clarity.

@rishujam
Copy link

rishujam commented Dec 2, 2022

Hey @BenHenning, As you said we can follow the factory method to create the instance of ConceptCardFragment so here's what I have done.

  1. Injected the stack manager in the factory, Factory manages the creation of card objects.
  2. Now we need to inject the factory in every class where we need to create ConceptCard and that's what I did.
    Is this way fine?

@BenHenning
Copy link
Member

Hey @BenHenning, As you said we can follow the factory method to create the instance of ConceptCardFragment so here's what I have done.

  1. Injected the stack manager in the factory, Factory manages the creation of card objects.
  2. Now we need to inject the factory in every class where we need to create ConceptCard and that's what I did.
    Is this way fine?

Your description sounds correct @rishujam but I'd need to see the code to be sure.

rishujam added a commit to rishujam/oppia-android that referenced this issue Dec 4, 2022
rishujam added a commit to rishujam/oppia-android that referenced this issue Dec 4, 2022
rishujam added a commit to rishujam/oppia-android that referenced this issue Dec 4, 2022
rishujam added a commit to rishujam/oppia-android that referenced this issue Dec 17, 2022
@seanlip seanlip added bug End user-perceivable behaviors which are not desirable. and removed issue_user_learner labels Mar 29, 2023
@adhiamboperes adhiamboperes added Work: Medium The means to find the solution is clear, but it isn't at good-first-issue level yet. work label added labels May 3, 2023
BenHenning added a commit that referenced this issue May 9, 2023
<!-- READ ME FIRST: Please fill in the explanation section below and
check off every point from the Essential Checklist! -->
## Explanation
<!--
- Explain what your PR does. If this PR fixes an existing bug, please
include
- "Fixes #bugnum:" in the explanation so that GitHub can auto-close the
issue
  - when this PR is merged.
  -->

Fix #4532: only allow one concept card open at a time. If the new new
concept card has the same skill id as an existing one, do not open and
instead reuse the existing one.

I modified a couple of concept card data for dev so that they link to
each other. This change is not necessary for this PR to work, but it
allows manually testing the scenario where a concept car links to
another.

Current behavior:
[multiple concept cards allowed, even with same skill
id.webm](https://user-images.githubusercontent.com/103062089/232325925-d9ce7ad2-a260-46a8-a23a-075d0152f48e.webm)

New behavior:
[ConceptCard deduplication
demo.webm](https://user-images.githubusercontent.com/103062089/232325566-96c74599-a5b8-4201-9feb-37f71c34649c.webm)

## Essential Checklist
<!-- Please tick the relevant boxes by putting an "x" in them. -->
- [x] The PR title and explanation each start with "Fix #bugnum: " (If
this PR fixes part of an issue, prefix the title with "Fix part of
#bugnum: ...".)
- [x] Any changes to
[scripts/assets](https://github.com/oppia/oppia-android/tree/develop/scripts/assets)
files have their rationale included in the PR explanation.
- [x] The PR follows the [style
guide](https://github.com/oppia/oppia-android/wiki/Coding-style-guide).
- [x] The PR does not contain any unnecessary code changes from Android
Studio
([reference](https://github.com/oppia/oppia-android/wiki/Guidance-on-submitting-a-PR#undo-unnecessary-changes)).
- [x] The PR is made from a branch that's **not** called "develop" and
is up-to-date with "develop".
- [x] The PR is **assigned** to the appropriate reviewers
([reference](https://github.com/oppia/oppia-android/wiki/Guidance-on-submitting-a-PR#clarification-regarding-assignees-and-reviewers-section)).

## For UI-specific PRs only
<!-- Delete these section if this PR does not include UI-related
changes. -->
If your PR includes UI-related changes, then:
- Add screenshots for portrait/landscape for both a tablet & phone of
the before & after UI changes
- For the screenshots above, include both English and pseudo-localized
(RTL) screenshots (see [RTL
guide](https://github.com/oppia/oppia-android/wiki/RTL-Guidelines))
- Add a video showing the full UX flow with a screen reader enabled (see
[accessibility
guide](https://github.com/oppia/oppia-android/wiki/Accessibility-A11y-Guide))
- Add a screenshot demonstrating that you ran affected Espresso tests
locally & that they're passing

---------

Co-authored-by: Ben Henning <ben@oppia.org>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug End user-perceivable behaviors which are not desirable. Impact: Low Low perceived user impact (e.g. edge cases). Work: Medium The means to find the solution is clear, but it isn't at good-first-issue level yet. Z-ibt Temporary label for Ben to keep track of issues he's triaged.
6 participants