Migrated SearchFragment -> Search Composable#4703
Migrated SearchFragment -> Search Composable#4703atharvyadav22 wants to merge 14 commits intokiwix:mainfrom
Conversation
|
@MohitMaliFtechiz @gouri-panda |
MohitMaliFtechiz
left a comment
There was a problem hiding this comment.
What is this SEARCH text here? It is making the UI very odd. If you are talking about the voice feature of search. It should not be like this. There should be a mic icon instead of this text. It's confusing the user here.
- The second issue is when we open any item in the reader by clicking the searched item. Then again, open the searchScreen, that item is not showing(in the previous code that shows). But, if I searched for anything and removed the query from searchBox then those items show that we have opened in a previous search.
core/src/main/java/org/kiwix/kiwixmobile/core/main/reader/CoreReaderFragment.kt
Show resolved
Hide resolved
core/src/main/java/org/kiwix/kiwixmobile/core/search/SearchScreen.kt
Outdated
Show resolved
Hide resolved
core/src/main/java/org/kiwix/kiwixmobile/core/search/SearchContainer.kt
Outdated
Show resolved
Hide resolved
core/src/main/java/org/kiwix/kiwixmobile/core/search/SearchContainer.kt
Outdated
Show resolved
Hide resolved
core/src/main/java/org/kiwix/kiwixmobile/core/search/SearchContainer.kt
Outdated
Show resolved
Hide resolved
core/src/main/java/org/kiwix/kiwixmobile/core/search/viewmodel/SearchViewModel.kt
Show resolved
Hide resolved
core/src/main/java/org/kiwix/kiwixmobile/core/search/viewmodel/SearchViewModel.kt
Outdated
Show resolved
Hide resolved
|
@atharvyadav22 Please rebase this PR as well with the review changes. |
I'll also add that test coverage here should i reference this PR? or only work for migration and create new issue for it. |
|
@atharvyadav22 One ticket/PR per thing. First we should atleast achive the existing fucntionality and than we should add testing. Migration is a different thing, and code coverage is different. Doing both together can introduce regressions here. |
|
@atharvyadav22 Mark all your PRs along with this one, as draft, on which work is currently in progress. |
235968a to
08177e5
Compare
|
@MohitMaliFtechiz @kelson42 Could you verify if there are any more functionalities other than these? as we have seen migration have caused us an trouble with many functionality.
|
|
@MohitMaliFtechiz we have Fragment Tests too what do with them now ? |
Codecov Report❌ Patch coverage is ❌ Your patch check has failed because the patch coverage (69.76%) is below the target coverage (70.00%). You can increase the patch coverage or adjust the target coverage. Additional details and impacted files@@ Coverage Diff @@
## main #4703 +/- ##
============================================
+ Coverage 60.62% 60.63% +0.01%
+ Complexity 1667 1635 -32
============================================
Files 333 333
Lines 16037 15987 -50
Branches 2224 2228 +4
============================================
- Hits 9722 9694 -28
+ Misses 4843 4816 -27
- Partials 1472 1477 +5 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
They are not for testing the fragment. They are for testing the functionality of that screen. We should rename the test cases, as now we have composables, not fragments. |
There is one more functionality where we can directly search from browsers as well via the
|
|
Yes i have already covered that too mentioned it in description as it was also an Issue it now works for both within and and outside the app |
Okay now it should be aligned with SearchScreenRoutes right? so should i raise an another PR for it as you said tests are different |
|
@atharvyadav22 Renaming the test cases should happen here. Since we are migrating to composables, related to that should be improved here. |
I thought we should add tests too got confused. |
@atharvyadav22 If you have found something that needs to be improved in testing for the current migration screen. Then you can add test cases for that in your current PR. @harshsomankar123-tech did this in his PRs. You can take reference from his PRs. But no unrelated changes should be made in PRs. |
f4c42ee to
9c8bb31
Compare
|
@atharvyadav22 Thank you for making the changes. I will review this shortly :) |
MohitMaliFtechiz
left a comment
There was a problem hiding this comment.
@atharvyadav22, I don't understand why we are always changing the UI behaviour when this PR is just for removing the fragment and migrating it to pure composables.
Here FIND_IN_PAGE option is not visible when there is no word typed. We already have a ticket for this #1782. But this type of UI change made the review harder(needs more testing/caring, and they have no effect. It only takes a long time to merge any PR).
core/src/main/java/org/kiwix/kiwixmobile/core/search/SearchScreenRoute.kt
Outdated
Show resolved
Hide resolved
core/src/main/java/org/kiwix/kiwixmobile/core/search/SearchScreenRoute.kt
Show resolved
Hide resolved
core/src/main/java/org/kiwix/kiwixmobile/core/search/SearchScreenRoute.kt
Show resolved
Hide resolved
core/src/main/java/org/kiwix/kiwixmobile/core/search/viewmodel/SearchViewModel.kt
Outdated
Show resolved
Hide resolved
core/src/main/java/org/kiwix/kiwixmobile/core/main/reader/CoreReaderFragment.kt
Show resolved
Hide resolved
core/src/main/java/org/kiwix/kiwixmobile/core/search/viewmodel/SearchViewModel.kt
Outdated
Show resolved
Hide resolved
|
@MohitMaliFtechiz Also i found one more issue about that cursor going back to start position on recomposition so i have fixed that too. Hope i could solve all the reviews please have a look about the changes. |
|
Once finalize ill mark this for review |
|
@atharvyadav22 Thank you for the update. I will have a look at this one.
Sure, thank you for debugging and fixing that :). |
|
@MohitMaliFtechiz done with these alongside there was an Coroutine Dispatcher issue done that was affecting test. Ci failing for emulator issue |
MohitMaliFtechiz
left a comment
There was a problem hiding this comment.
@atharvyadav22 There are still some test are failing.
core/src/main/java/org/kiwix/kiwixmobile/core/search/viewmodel/SearchResultGenerator.kt
Outdated
Show resolved
Hide resolved
core/src/main/java/org/kiwix/kiwixmobile/core/search/viewmodel/SearchViewModel.kt
Outdated
Show resolved
Hide resolved
core/src/test/java/org/kiwix/kiwixmobile/core/search/viewmodel/SearchStateTest.kt
Outdated
Show resolved
Hide resolved
core/src/test/java/org/kiwix/kiwixmobile/core/search/viewmodel/SearchStateTest.kt
Show resolved
Hide resolved
core/src/test/java/org/kiwix/kiwixmobile/core/search/viewmodel/SearchStateTest.kt
Outdated
Show resolved
Hide resolved
core/src/test/java/org/kiwix/kiwixmobile/core/search/viewmodel/SearchViewModelTest.kt
Outdated
Show resolved
Hide resolved
core/src/test/java/org/kiwix/kiwixmobile/core/search/viewmodel/SearchViewModelTest.kt
Outdated
Show resolved
Hide resolved
5a00913 to
6285a15
Compare
|
@MohitMaliFtechiz |
There was a problem hiding this comment.
@atharvyadav22 The unit coverage is never completed. It is stuck on the ZimSearchResultGeneratorTest.
Use this version of the test it will pass.
internal class ZimSearchResultGeneratorTest {
@RegisterExtension
private val mainDispatcherRule = MainDispatcherRule()
private val zimFileReader: ZimFileReader = mockk()
private val zimSearchResultGenerator: ZimSearchResultGenerator =
ZimSearchResultGenerator(mainDispatcherRule.dispatcher)
@Test
internal fun `empty search term returns empty list`() = runTest {
assertThat(zimSearchResultGenerator.generateSearchResults("", zimFileReader))
.isEqualTo(null)
}
@Test
internal fun `suggestion results are distinct`() = runTest {
val searchTerm = "a"
val suggestionSearchWrapper: SuggestionSearchWrapper = mockk()
every { zimFileReader.searchSuggestions(searchTerm) } returns suggestionSearchWrapper
assertThat(zimSearchResultGenerator.generateSearchResults(searchTerm, zimFileReader))
.isEqualTo(suggestionSearchWrapper)
verify {
zimFileReader.searchSuggestions(searchTerm)
}
}
}
core/src/main/java/org/kiwix/kiwixmobile/core/search/viewmodel/SearchViewModel.kt
Outdated
Show resolved
Hide resolved
core/src/test/java/org/kiwix/kiwixmobile/core/settings/viewmodel/CoreSettingsViewModelTest.kt
Outdated
Show resolved
Hide resolved
core/src/main/java/org/kiwix/kiwixmobile/core/search/viewmodel/SearchViewModel.kt
Outdated
Show resolved
Hide resolved
core/src/main/java/org/kiwix/kiwixmobile/core/search/viewmodel/SearchViewModel.kt
Outdated
Show resolved
Hide resolved
| import org.kiwix.kiwixmobile.core.base.SideEffect | ||
| import org.kiwix.kiwixmobile.core.extensions.closeKeyboard | ||
|
|
||
| object CloseKeyboard : SideEffect<Unit> { |
There was a problem hiding this comment.
We should add a test case for this as well. Like we have added the test cases for side effects.
There was a problem hiding this comment.
Why do we not test this sideEffect separately? As I have said, we should test this side effect like we are testing other side effects.
An example of what I was asking is SaveSearchToRecents and SaveSearchToRecentsTest. You should take a reference from there.
There was a problem hiding this comment.
I saw your test. But what your test is doing. When the CloseKeyboard action is triggered. It calls the CloseKeyboard side effect, and that's it. What about the CloseKeyboard side-effect functionality? We are not verifying its functionality. Like we are doing for SaveSearchToRecents. That's why i have given you the reference of that side-effect.
There was a problem hiding this comment.
Okay i got your point you are saying i should make New file for This CloseKeyboard right? just like SaveSearchToRecentsTest
Also any more side effects i should add?
There was a problem hiding this comment.
Okay i got your point you are saying i should make New file for This CloseKeyboard right?
Yes. It could be CloseKeyboardTest.
Also any more side effects i should add?
Which side effects are used in this search functionality, check them. I guess most of the tests are already written; if not, add for that. Do not include the test for other side-effects which are not related to this functionality(not used in SearchViewModel).
There was a problem hiding this comment.
Okay i checked that there are two cases for null and one for focus that closeKeyBoard uses View scope so ill mock that
core/src/test/java/org/kiwix/kiwixmobile/core/search/viewmodel/SearchViewModelTest.kt
Show resolved
Hide resolved
| cancelAndIgnoreRemainingEvents() | ||
| } | ||
| } | ||
|
|
There was a problem hiding this comment.
We have not tested the main click functionality, such as onItemClick, onItemLongClick, and onNewTabIconClick. These are the major UI functionalities; please test them.
There was a problem hiding this comment.
They were already covered in inner class ActionMapper
There was a problem hiding this comment.
It is ActionMapping. How do you think testing the OnItemClick sideEffect also test the same when the user clicks in the UI? the sideEffect only tests the action, which triggers after the onItemClick performs its operation, like closing the keyboard and sending the OnItemClick action. We should test both onItemClick and onItemLongClick methods.
There was a problem hiding this comment.
Okie, Actually the function naming function was earlier written code so made no changes i got your point i didn't read that function properly i thought it does the work I'll surely change.
There was a problem hiding this comment.
Okie, Actually the function naming function was earlier written code so made no changes
That was written because at that time, click functionalities were inside the fragment, not inside the viewModel. But now we have moved it to the viewModel, so it should be tested properly.
core/src/test/java/org/kiwix/kiwixmobile/core/search/viewmodel/SearchViewModelTest.kt
Show resolved
Hide resolved
dbf6508 to
55c3d2e
Compare
|
@MohitMaliFtechiz |
MohitMaliFtechiz
left a comment
There was a problem hiding this comment.
@atharvyadav22 The commit message should be clean.
|
|
||
| fun onItemLongClick(it: SearchListItem) { | ||
| closeKeyboard() | ||
| actions.tryEmit(Action.OnItemLongClick(it)) |
There was a problem hiding this comment.
Yes Strange windows didnt showed this
| import org.kiwix.kiwixmobile.core.base.SideEffect | ||
| import org.kiwix.kiwixmobile.core.extensions.closeKeyboard | ||
|
|
||
| object CloseKeyboard : SideEffect<Unit> { |
There was a problem hiding this comment.
Why do we not test this sideEffect separately? As I have said, we should test this side effect like we are testing other side effects.
An example of what I was asking is SaveSearchToRecents and SaveSearchToRecentsTest. You should take a reference from there.
| fun `OnItemClick offers Saves and Opens`() = | ||
| runTest { | ||
| val searchListItem = RecentSearchListItem("", "") | ||
| actionResultsInEffects( |
There was a problem hiding this comment.
It is the ActionMapping class. How do you think testing the effects also tests the UI clicks functionality? There are some logics that are missing to test. Like when onItemClick is performed from UI, it closes the keyboard and emits the OnItemClick click action. The ActionMapping class is testing after that functionality.
| cancelAndIgnoreRemainingEvents() | ||
| } | ||
| } | ||
|
|
There was a problem hiding this comment.
It is ActionMapping. How do you think testing the OnItemClick sideEffect also test the same when the user clicks in the UI? the sideEffect only tests the action, which triggers after the onItemClick performs its operation, like closing the keyboard and sending the OnItemClick action. We should test both onItemClick and onItemLongClick methods.
…` via DI and enhancing the `generateSearchResults` method. * Replaced `Channel` with `MutableSharedFlow` for actions and effects, as it is lifecycle-aware and more Compose-friendly. Refactored related code and test cases accordingly. * Consolidated multiple `StateFlows` into a single UI state to simplify state management and improve maintainability. * Fixed: Loading icon was not showing when searching for results. * Fixed an issue where the loading indicator was not displayed during search. * Fixed a regression where search results were not returned from libkiwix when the search term contained spaces. * Fixed an issue where "load more" was triggered indefinitely even when no additional results were available in the ZIM file for the given search term.
* Fixed an issue where frequent typing/removal triggered multiple unnecessary calls to libkiwix. This now follows the same behavior as the Fragment implementation, using Flow operators that automatically cancel previous running jobs. * Fixed an issue where loadMore was executed on the UI coroutine scope, which could lead to lifecycle and cancellation problems. Introduced a LoadMoreResults action so the ViewModel handles pagination safely. * Improved the loadMore logic for better reliability and consistency. * Added a CloseKeyboard side effect to allow the ViewModel to control keyboard dismissal without additional UI handling. * Removed SearchScreenState. The UI now directly observes uiState from the ViewModel and only sends actions, making the architecture cleaner and more maintainable. * Fixed minor issues and edge cases.
Added Cases for Keyboard and changed requested review comments
55c3d2e to
6069634
Compare
|
@MohitMaliFtechiz |


Fixes: #4616 - Migrated Search Fragment to Pure Composable with basic test functionality.
Fixes: #4662 - Search keyword travel was broke due to Fragment lifecycle error and intent action issue.
It now works Within app and also outside the app
Fixes #4722
WhatsApp.Video.2026-02-18.at.9.09.27.PM.1.mp4
Fixes: #4702 - Voice to Search was broken due to Regression and Fragment changes.
WhatsApp.Video.2026-02-18.at.9.09.27.PM.mp4
Fixes: #4722 - Fixed Keyboard not closing when back button press on search screen.
WhatsApp.Video.2026-02-26.at.9.51.05.PM.mp4