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

#1962: Refactoring of Search Behavior: Restoring of Previous Search Query After Coming Back from Card Interaction or Screen Rotation on Search #2092

Open
wants to merge 1 commit into
base: main
Choose a base branch
from

Conversation

vp193dt
Copy link

@vp193dt vp193dt commented Sep 30, 2024

Hello,
In this pull request, I implemented functionality to save and restore the user's search query during screen rotations and enhance the user experience when navigating back from a selected card, the way user will have the query entered before saved and retrived, based on Issue #1962.
Unit tests were added and all four possible tests were run successfully without any error.

After hours of debugging I figured out the only way this Issue is solveble, where we need to implement 2 Strings to handle the changing text as input from user, because of the behaviour after coming back from a card regarding onQueryTextChange. (alternativelly we could use one string and one boolean for this very same behaviour) - changes in states were not effective on this Issue.
This approach is a bit extraordinary but It solves both parts of problem of this Issue.

The changes are divided into 2 categories, the first are changes that are connected to screen rotation:

Saving Instance State:

I overridden the onSaveInstanceState method. When a user clicks on a card from the list, the current search query (currentQuery) is saved to a variable called finalQuery.
This finalQuery is then stored in the outState bundle, allowing it to be retained even when the screen is rotated.

Restoring Instance State:

The onRestoreInstanceState method is also overridden to retrieve the saved query when the screen is rotated.
If the savedInstanceState is not null, the stored search query is fetched and assigned to finalQuery.
Finally, if mSearchView is available, the restored query is set in the search view, allowing users to see their previous search term after rotation.

The second part regarding the retrieving the text after coming back from card picking:

New Logic for Search History:

Additional logic was implemented to ensure that the user sees the last search query after returning from a picked card.
If the newText input is empty, the app checks if finalQuery is not empty. If so, it sets the query text to finalQuery for the user.
If both finalQuery and currentQuery are empty, the app clears the current search (currentQuery = "") and resets the search view to show all cards.
When the user changes the text in the search view, the input is stored in currentQuery to be used later for restoring search history.

Handling Navigation from a Picked Card:

Upon returning from a picked card, if finalQuery is not empty, the search view is expanded to show the previous query.
The finalQuery is reset to an empty string to avoid unintended behavior caused by the onQueryTextChange method, which is called automatically after returning to the search view.

Tests are focused on both rotation of screen by user (testing same test case as in previous unit test but with rotation commands) and also on simulating steps of the core of the issue with coming back from a card.

Thank you for feedback.
Have a nice day :)

…ious Search Query After Coming Back from Card Interaction or Screen Rotation on Search
@TheLastProject
Copy link
Member

Thanks for your contribution!

From quick testing I can confirm it does seem to work. However, while reading through your code, I can't help but feel it is very complex for how simple what we're trying to do should be.

While I think the onSaveInstanceState and onRestoreInstanceState are the correct functions to go to deal with the state loss on rotation, I do quite worry how we went from one variable to store the current search filter in (mFilter) to three variables. I also have my doubts your onRestoreInstanceState code does more than set the variable because, from my testing, mSearchView seems to always be null when in onRestoreInstanceState, so the query is never executed.

I've been debugging with the original code (before your change) and I noticed that the value of mFilter does correctly stay set even when returning from a card being viewed, so we do actually know the correct search value in onResume when we return from the card. However, shortly after, for some reason the setQuery gets called on the mSearchView and sets mFilter to an empty string.

So I guess the real issue here is: why is the OnQueryTextListener of the mSearchView called with an empty string when we return from the card view activity? I sadly don't really have an answer to this but I think this is the only issue we have to really fix/work around to restore the search when coming back from the card view.

If we have the workaround for restoring the search state from mFilter when returning, saving and restoring mFilter on rotation (with onSaveInstanceState/onRestoreInstanceState) should be all we need to fix both issues.

One thing I think we may want to consider, given this post I found, is to try to replace the embedded androidx.appcompat.widget.SearchView which Catima currently uses with the new Material SearchView in the hope it does not have this OnQueryTextListener quirk that's causing all our pain here, which would hopefully allow us to restore it straight from mFilter. That would mean leaving this PR alone for a while and focusing on replacing the search view first, which is sadly quite a scope change (created a new issue for that in #2093) :(


So, to summarize: I think your change makes sense to fix the issue requested and the general design is in the right direction. They are however complicated due to bugs in the rest of Android. If we replace the SearchView for a more modern component, we may be able to make this PR a lot simpler and cleaner.

It's a pretty decent first PR :)

@TheLastProject
Copy link
Member

Thinking about this a bit more, and searching the web and finding https://www.reddit.com/r/android_devs/comments/iwwk3x/restoring_the_query_of_a_searchview_after/:

Seeing your change at https://github.com/CatimaLoyalty/Android/pull/2092/files#diff-941e4f5c2de040ee272e9798812bb09cf81bb8a9cd1d03f09ca02a706f7bdf54R608, wouldn't it suffice to start the value of mFilter in a new mFilterToRestore variable on saving the instance state or when opening another activity to the value of mFilter and adding a setQuery to your change like:

if (mFilterToRestore.isNotEmpty()) {
            searchMenuItem.expandActionView();
            mSearchView.setQuery(mFilterToRestore, false);
            mFilterToRestore = "";

If I understood that post correctly, all the other changes would be unneeded.

Just quick brainstorming though, haven't had the time to try this (so, sorry if you tried it already!) But that could bring back the complexity or your PR a lot if it would work. Still annoying to need a second variable so the search view doesn't wipe it due to that one bug but alas.

@vp193dt
Copy link
Author

vp193dt commented Oct 5, 2024

Hello, for me this solution did not work when I tested it but please test it in your enviroment so we can be sure, in my case cards remained filtered but search bar was not expanded with search query.
Thanks :)

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.

2 participants