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

Improve search history by attaching change listener #9794

Merged
merged 20 commits into from
May 4, 2023

Conversation

dkokkotas
Copy link
Contributor

@dkokkotas dkokkotas commented Apr 24, 2023

Fixes #9685

Essentially, we record the search query, only when the user completes the search process and "leaves" the search box. We ensure that, by checking whether the focus is lost or active on search bar and that helps us prevent storing redundant data (e.g prefixes)

What steps are followed?

  1. User wants to search an entry
  2. User types search query into search box --> focus is active on search box
  3. User selects the desired entry from the search results --> user leaves search box --> focus
    changes to inactive / lost
  4. Search query is recorded in search history

About the implementation

Resolving the issue, we attach a change listener to the search box node and call addSearchHistory method, only when:
- the focus property of search box is lost and
- the search query is not empty.
In case, the two aforementioned conditions are met, we record the query successfully.

Before that, the addSearchHistory method was called inside performSearch.
The performSearch was called every time the search box was idle for more than(SEARCH_DELAY = 400) ms, as a proper waiting time to perform the query and show search results, yet not proper for storing the search queries.
Consequently, there were unnecessary data (prefixes) recorded in history, as the user would not type the query that fast (<400ms/character typed). Therefore, we remove the call of addSearchHistory and place it under change listener's registration.

Change listener is NOT attached : Redundant prefixes are recorded

bug.mov

Change listener is attached : Recording query by the completion of search process

bug-fixed.mov

Note: In both cases I slowtype on purpose, so the search box could be idle for more than 400ms for every character typing.

Compulsory checks

Preview Give feedback

@dkokkotas dkokkotas marked this pull request as draft April 24, 2023 20:47
@dkokkotas dkokkotas changed the title Improve search history attaching change listener Improve search history by attaching change listener Apr 25, 2023
@dkokkotas
Copy link
Contributor Author

dkokkotas commented Apr 28, 2023

Commited modifications regarding the listener attachment.

  1. Need to add some GUI tests corresponding to changes
  2. About the implementation of string similarity and close timestamp concepts, could you provide feedback? Is it something I should work on and include. I have already stated my opinion on it's usefulness in the issue's comments.

@koppor
Copy link
Member

koppor commented Apr 28, 2023

You got partial feedback at #9685 (comment).

To judge the question, I need to check the current state. Maybe, you can summarize it? Not sure, when I have time to checkout your PR and check it. Not sure about the others though.

@dkokkotas
Copy link
Contributor Author

dkokkotas commented Apr 28, 2023

Briefly, regarding the current state, the bug is fixed and there are no redundant recordings. I’m just wondering if we need the 2nd solution as an additional mechanism to optimize the search history.
The bug as introduced in issue's description, was the following (at my understanding). The addSearchHistory method call was embedded in performSearch, which was called every time the search box was idle for more than 400ms. That caused issues (e.g. prefixes were stored in case we slowtype). So, Houssem suggested two solutions regarding search history improvement.

First solution

Attach a change listener to focus property of search box node, so only when it gets inactive / lost (i.e. user completes search) then we record the query. Also removed the addSearchHistory method call from performSearch and placed it under listener's lambda expression. See pr's description for more details

Second solution

Each time a query is recorded, we loop the search history observable list and:

  • Check StringSimilarity between the recently added and the previous ones, by calculating the edit distance, that needs to be within the preferred threshold.
  • We also check if the time period between the two recordings is short enough.

In case both of them return the desired results, we merge the two queries

What I implemented?

I followed the first solution.
I will also upload some screenshots soon enough.

@Siedlerchr
Copy link
Member

Totally fine if you don't need the similarity. I'm happy with the solution.
Try to make a test for it, if it's too complicated (gui tests are not easy, a manual test is also fine)

Copy link
Member

@koppor koppor left a comment

Choose a reason for hiding this comment

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

"Code" comments attached.

src/main/java/org/jabref/gui/search/GlobalSearchBar.java Outdated Show resolved Hide resolved
src/main/java/org/jabref/gui/search/GlobalSearchBar.java Outdated Show resolved Hide resolved
src/main/java/org/jabref/gui/search/GlobalSearchBar.java Outdated Show resolved Hide resolved
@koppor
Copy link
Member

koppor commented Apr 28, 2023

I tested it, but could not see any search history. What do I need to do to test this feature?

image

Is there any screenshot?

@dkokkotas
Copy link
Contributor Author

@koppor I have just uploaded screenshots.
@Siedlerchr Will also add GUI tests so please don't merge.

@koppor
Copy link
Member

koppor commented Apr 29, 2023

Thank you for the video! -- I was expecting that there was a dropdown shown. Need to search the PR and check for the decision.

Copy link
Member

@koppor koppor left a comment

Choose a reason for hiding this comment

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

Improves the situation, so I would suggest to add a CHANGELOG entry and then we go for a merge. Tests can be done later.

@dkokkotas dkokkotas marked this pull request as ready for review April 29, 2023 21:38
@dkokkotas dkokkotas requested review from Siedlerchr and koppor April 29, 2023 21:38
CHANGELOG.md Outdated Show resolved Hide resolved
@dkokkotas dkokkotas requested a review from Siedlerchr April 29, 2023 22:23
Siedlerchr
Siedlerchr previously approved these changes Apr 29, 2023
Copy link
Member

@Siedlerchr Siedlerchr left a comment

Choose a reason for hiding this comment

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

From my side lgtm so far already

@Siedlerchr
Copy link
Member

The last time I executed the code locally it worked in intellij. tests were passing.

@koppor
Copy link
Member

koppor commented May 3, 2023

Good to hear that it works on your macOS systems (you and @demetres12 use macOS). -- It does not work on my Windows and it also does not work on GitHub.

For GitHub, I already showed the links to the failing tests.

It is totally unclear to me why this happens.

@calixtus Can you run GlobalSearchBarTest.java on your Linux (and maybe Windows) machine?

On the one hand, it would be OK for me to disable the tests and to reserve it as "future work" to fix them. On the other hand, working with FXCollections in tests is very fundamental. Thus, we should devote some time to get this working on GitHub (Linux!) and on Windows machines.

@Siedlerchr
Copy link
Member

change the Focus method to DefaultTaskExecutor.runAndWaitInJavaFXThread(() -> hBox.requestFocus());

that seemed to do the trick. Wating for the FX thread to execute

@Siedlerchr
Copy link
Member

Yeah seems like it worked now 👍 💯

@dkokkotas
Copy link
Contributor Author

Is there a reason the public access modifier for test methods is not used in several test classes?

@Siedlerchr
Copy link
Member

Basically, this is a feature of junit5. Back in JUnit 4 they had to be public.

It is generally recommended to omit the public modifier for test classes, test methods, and lifecycle methods unless there is a technical reason for doing so – for example, when a test class is extended by a test class in another package. Another technical reason for making classes and methods public is to simplify testing on the module path when using the Java Module System.

https://junit.org/junit5/docs/snapshot/user-guide/

@dkokkotas dkokkotas requested review from Siedlerchr and koppor May 3, 2023 16:56
Siedlerchr
Siedlerchr previously approved these changes May 3, 2023
@Siedlerchr Siedlerchr added the status: ready-for-review Pull Requests that are ready to be reviewed by the maintainers label May 3, 2023
Copy link
Member

@koppor koppor left a comment

Choose a reason for hiding this comment

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

Thank you for the updates. I have three nitpicks on the testing. I commented - and also updated the code for myself to keep things going. If the tests are green, I will merge.

@koppor koppor merged commit 6269698 into JabRef:main May 4, 2023
@Siedlerchr
Copy link
Member

Siedlerchr commented May 4, 2023

@koppor the assertFalse check was necessary to ensure the focus listener was working correctly. The assertEquals returned this weird collections type differences until this task executor waiting

@dkokkotas
Copy link
Contributor Author

@koppor @Siedlerchr
Your expertise and enthusiasm were both appreciated during a time that can be challenging for my concerns!!!
Heart thanks and gratefulness

Siedlerchr added a commit that referenced this pull request May 4, 2023
* upstream/main:
  Fix modernizer (#9824)
  Improve search history by attaching change listener (#9794)
  Fix split multiline localization (#9814)
  New Crowdin updates (#9834)
  change versin to 0.8.10
  remove  jacoco version config
Siedlerchr added a commit to brunaoo/jabref that referenced this pull request May 5, 2023
* upstream/main: (88 commits)
  Minimal config for openRewrite
  Fix missing #
  Fix modernizer (JabRef#9824)
  CHANGELOG.md
  Removed unused code
  Refined ui
  Dissolved FileTab and moved contents to EntryTab
  Renamed CustomEditorFieldsTab to EntryEditorTabsTab
  Fixed antipattern, fixed radiobutton with checkbox
  Renamed ImportExportPreferences to ExportPreferences
  Improve search history by attaching change listener (JabRef#9794)
  Separated WebSearchPrefs and ExportPrefs
  Separated WebSearchTab and ExportTab
  Renamed ImportExportTab to WebSearchTab
  Fix split multiline localization (JabRef#9814)
  New Crowdin updates (JabRef#9834)
  change versin to 0.8.10
  remove  jacoco version config
  Bump org.junit.platform:junit-platform-launcher from 1.9.2 to 1.9.3
  Bump org.jsoup:jsoup from 1.15.4 to 1.16.1
  ...
Siedlerchr added a commit to GuyPuts/jabref that referenced this pull request May 6, 2023
…biblatex-date-formats

* upstream/main: (132 commits)
  Add four rules not having any effect
  Apply BooleanChecksNotInverted
  Remove unused RadioButtonCell
  Minimal config for openRewrite
  Fix missing #
  Fix modernizer (JabRef#9824)
  CHANGELOG.md
  Removed unused code
  Refined ui
  Dissolved FileTab and moved contents to EntryTab
  Renamed CustomEditorFieldsTab to EntryEditorTabsTab
  Fixed antipattern, fixed radiobutton with checkbox
  Renamed ImportExportPreferences to ExportPreferences
  Improve search history by attaching change listener (JabRef#9794)
  Separated WebSearchPrefs and ExportPrefs
  Separated WebSearchTab and ExportTab
  Renamed ImportExportTab to WebSearchTab
  Fix split multiline localization (JabRef#9814)
  New Crowdin updates (JabRef#9834)
  change versin to 0.8.10
  ...
@dkokkotas dkokkotas deleted the fix-for-9685 branch May 24, 2023 22:41
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
search status: ready-for-review Pull Requests that are ready to be reviewed by the maintainers
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Improve the recording of the search history
4 participants