From d841dfea7f7f73b33f5daecb33d56aa8c1ddcce6 Mon Sep 17 00:00:00 2001 From: Mouaad Aallam Date: Tue, 29 Mar 2022 14:28:34 +0200 Subject: [PATCH 1/4] feat: `MultiSearcher`, `HitsSearcher` and `FacetsSearcher` (#44) --- build.gradle | 10 +- compose/.gitignore | 1 - compose/build.gradle | 67 ------- compose/proguard-rules.pro | 21 --- .../searchapp/ExampleInstrumentedTest.kt | 24 --- compose/src/main/AndroidManifest.xml | 25 --- compose/src/main/res/values-night/themes.xml | 16 -- compose/src/main/res/values/colors.xml | 10 -- compose/src/main/res/values/strings.xml | 3 - compose/src/main/res/values/themes.xml | 25 --- .../com/algolia/searchapp/ExampleUnitTest.kt | 17 -- .../query/categories/hits/MainViewModel.kt | 20 +-- .../com/algolia/exchange/multi/index/Actor.kt | 2 +- .../exchange/multi/index/MainViewModel.kt | 18 +- .../com/algolia/exchange/multi/index/Movie.kt | 2 +- .../suggestions/categories/MainViewModel.kt | 32 ++-- .../suggestions/categories/Suggestion.kt | 2 +- .../query/suggestions/hits/MainViewModel.kt | 19 +- .../query/suggestions/hits/Suggestion.kt | 2 +- .../suggestions/categories/MainViewModel.kt | 17 +- .../suggestions/categories/Suggestion.kt | 2 +- .../query/suggestions/MainViewModel.kt | 18 +- .../exchange/query/suggestions/Suggestion.kt | 2 +- .../exchange/voice/search/MainViewModel.kt | 17 +- .../algolia/exchange/voice/search/Product.kt | 2 +- .../exchange/voice/search/SearchScreen.kt | 2 +- gradle/wrapper/gradle-wrapper.properties | 2 +- guides/build.gradle | 32 +++- guides/src/main/AndroidManifest.xml | 16 +- .../com/algolia/instantsearch/guides}/App.kt | 19 +- .../guides/compose/ComposeActivity.kt | 6 +- .../guides/compose}/MainViewModel.kt | 42 ++--- .../guides/compose}/SearchScreen.kt | 10 +- .../guides/compose}/theme/Color.kt | 2 +- .../guides/compose}/theme/Shape.kt | 2 +- .../guides/compose}/theme/Theme.kt | 11 +- .../guides/compose}/theme/Type.kt | 16 +- .../guides/directory/Directory.kt | 13 +- .../guides/directory/DirectoryActivity.kt | 39 ++-- .../guides/directory/DirectoryAdapter.kt | 20 +-- .../guides/directory/DirectoryHit.kt | 2 +- .../guides/directory/DirectoryViewHolder.kt | 9 +- .../guides/extension/RecyclerView.kt | 21 +++ .../guides}/extension/SearchView.kt | 4 +- .../guides/gettingstarted/FacetFragment.kt | 44 ++--- .../gettingstarted/GettingStartedGuide.kt | 38 ++-- .../gettingstarted/MyFacetListViewHolder.kt | 19 +- .../guides/gettingstarted/MyViewModel.kt | 61 +++---- .../guides/gettingstarted/Product.kt | 18 -- .../guides/gettingstarted/ProductAdapter.kt | 45 ++--- .../guides/gettingstarted/ProductFragment.kt | 59 +++--- .../gettingstarted/ProductViewHolder.kt | 14 -- .../guides/insights/InsightsActivity.kt | 69 +++++++ .../guides/insights/ListItemAdapter.kt | 53 ++++++ .../instantsearch/guides/model}/Product.kt | 12 +- .../instantsearch/guides/model/Suggestion.kt | 20 +++ .../instantsearch/guides/places/Adapter.kt | 48 +++-- .../guides/places/PlacesActivity.kt | 31 ++-- .../instantsearch/guides/places/ViewHolder.kt | 34 ---- .../guides/querysuggestion/Adapter.kt | 58 ------ .../guides/querysuggestion/AdapterItem.kt | 44 ----- .../QuerySuggestionActivity.kt | 62 +++++++ .../querysuggestion/QuerySuggestionGuide.kt | 80 --------- .../QuerySuggestionViewModel.kt | 40 +++++ .../guides/querysuggestion/ViewHolder.kt | 49 ----- .../guides/querysuggestion/product/Product.kt | 30 ++++ .../querysuggestion/product/ProductAdapter.kt | 43 +++++ .../product/ProductFragment.kt | 38 ++++ .../suggestion/SuggestionAdapter.kt | 45 +++++ .../suggestion/SuggestionFragment.kt | 41 +++++ .../guides/voice/VoiceSearchActivity.kt | 81 +++++++++ .../res/drawable/ic_add_shopping_cart.xml | 0 .../res/drawable/ic_microphone_outline.xml | 0 .../src/main/res/drawable/ic_search_hint.xml | 0 .../src/main/res/layout/activity_insights.xml | 12 +- .../res/layout/activity_query_suggestion.xml | 25 ++- .../main/res/layout/activity_voice_search.xml | 59 ++++++ guides/src/main/res/layout/fragment_items.xml | 5 + .../main/res/layout/list_item_large_buy.xml | 0 guides/src/main/res/values/strings.xml | 8 +- insights/.gitignore | 1 - insights/build.gradle | 52 ------ insights/consumer-rules.pro | 0 insights/proguard-rules.pro | 21 --- .../insights/ExampleInstrumentedTest.kt | 24 --- insights/src/main/AndroidManifest.xml | 27 --- .../insights/showcase/DemoActivity.kt | 70 -------- .../insights/showcase/ListItem.kt | 17 -- .../insights/showcase/ListItemAdapter.kt | 24 --- .../insights/showcase/ListItemCallback.kt | 14 -- .../insights/showcase/ListItemViewHolder.kt | 33 ---- .../showcase/extension/RecyclerView.kt | 18 -- .../drawable-v24/ic_launcher_foreground.xml | 34 ---- .../res/drawable/ic_launcher_background.xml | 170 ------------------ .../src/main/res/layout/include_search.xml | 36 ---- .../res/mipmap-anydpi-v26/ic_launcher.xml | 5 - .../mipmap-anydpi-v26/ic_launcher_round.xml | 5 - .../src/main/res/mipmap-hdpi/ic_launcher.png | Bin 2963 -> 0 bytes .../res/mipmap-hdpi/ic_launcher_round.png | Bin 4905 -> 0 bytes .../src/main/res/mipmap-mdpi/ic_launcher.png | Bin 2060 -> 0 bytes .../res/mipmap-mdpi/ic_launcher_round.png | Bin 2783 -> 0 bytes .../src/main/res/mipmap-xhdpi/ic_launcher.png | Bin 4490 -> 0 bytes .../res/mipmap-xhdpi/ic_launcher_round.png | Bin 6895 -> 0 bytes .../main/res/mipmap-xxhdpi/ic_launcher.png | Bin 6387 -> 0 bytes .../res/mipmap-xxhdpi/ic_launcher_round.png | Bin 10413 -> 0 bytes .../main/res/mipmap-xxxhdpi/ic_launcher.png | Bin 9128 -> 0 bytes .../res/mipmap-xxxhdpi/ic_launcher_round.png | Bin 15132 -> 0 bytes insights/src/main/res/values/colors.xml | 23 --- insights/src/main/res/values/strings.xml | 5 - insights/src/main/res/values/styles.xml | 43 ----- .../com/algolia/insights/ExampleUnitTest.kt | 17 -- settings.gradle | 2 +- .../drawable-v24/ic_launcher_foreground.xml | 30 ---- .../res/drawable/ic_launcher_background.xml | 170 ------------------ .../res/mipmap-anydpi-v26/ic_launcher.xml | 5 - .../mipmap-anydpi-v26/ic_launcher_round.xml | 5 - .../src/main/res/mipmap-hdpi/ic_launcher.webp | Bin 1404 -> 0 bytes .../res/mipmap-hdpi/ic_launcher_round.webp | Bin 2898 -> 0 bytes .../src/main/res/mipmap-mdpi/ic_launcher.webp | Bin 982 -> 0 bytes .../res/mipmap-mdpi/ic_launcher_round.webp | Bin 1772 -> 0 bytes .../main/res/mipmap-xhdpi/ic_launcher.webp | Bin 1900 -> 0 bytes .../res/mipmap-xhdpi/ic_launcher_round.webp | Bin 3918 -> 0 bytes .../main/res/mipmap-xxhdpi/ic_launcher.webp | Bin 2884 -> 0 bytes .../res/mipmap-xxhdpi/ic_launcher_round.webp | Bin 5914 -> 0 bytes .../main/res/mipmap-xxxhdpi/ic_launcher.webp | Bin 3844 -> 0 bytes .../res/mipmap-xxxhdpi/ic_launcher_round.webp | Bin 7778 -> 0 bytes showcase/{ => android-view}/.gitignore | 0 showcase/{ => android-view}/README.md | 0 showcase/{ => android-view}/build.gradle | 16 +- .../{ => android-view}/proguard-rules.pro | 0 .../src/main/AndroidManifest.xml | 0 .../algolia/instantsearch/showcase/Demo.kt | 54 +++--- .../showcase/customdata/Banner.kt | 0 .../customdata/QueryRuleCustomDataShowcase.kt | 58 +++--- .../showcase/customdata/TemplateActivity.kt | 12 +- .../showcase/directory/Directory.kt | 0 .../showcase/directory/DirectoryAdapter.kt | 13 +- .../showcase/directory/DirectoryHit.kt | 2 +- .../showcase/directory/DirectoryItem.kt | 0 .../showcase/directory/DirectoryShowcase.kt | 29 +-- .../showcase/directory/DirectoryViewHolder.kt | 21 +-- .../filter/clear/FilterClearShowcase.kt | 75 ++++++++ .../filter/current/ShowcaseFilterCurrent.kt | 47 ++--- .../facet/FacetListPersistentShowcase.kt | 81 +++++++++ .../filter/facet/FacetListSearchShowcase.kt | 81 +++++++++ .../filter/facet/FacetListShowcase.kt | 54 +++--- .../filter/facet/FacetListViewHolderImpl.kt | 33 ++++ .../facet/dynamic/DynamicFacetShowcase.kt | 38 ++-- .../filter/facet/dynamic/ViewHolderFactory.kt | 47 +++++ .../showcase/filter/list/FilterListAdapter.kt | 32 ++-- .../filter/list/FilterListAllShowcase.kt | 40 +++-- .../filter/list/FilterListFacetShowcase.kt | 40 +++-- .../filter/list/FilterListNumericShowcase.kt | 40 +++-- .../filter/list/FilterListTagShowcase.kt | 62 +++++++ .../filter/list/FilterListViewHolder.kt | 15 ++ .../showcase/filter/map/FilterMapShowcase.kt | 57 ++++++ .../comparison/FilterComparisonShowcase.kt | 45 +++-- .../numeric/comparison/FilterPriceView.kt | 20 +-- .../numeric/comparison/FilterYearView.kt | 18 +- .../showcase/filter/range/BoundsTextView.kt | 0 .../filter/range/FilterRangeShowcase.kt | 80 +++++++++ .../showcase/filter/range/RangeSliderView.kt | 0 .../showcase/filter/range/RangeTextView.kt | 0 .../showcase/filter/rating/RatingBarView.kt | 0 .../showcase/filter/rating/RatingShowcase.kt | 79 ++++++++ .../showcase/filter/rating/RatingTextView.kt | 0 .../filter/toggle/FilterToggleShowcase.kt | 41 +++-- .../hierarchical/HierarchicalAdapter.kt | 15 +- .../hierarchical/HierarchicalShowcase.kt | 68 +++++++ .../hierarchical/HierarchicalViewHolder.kt | 31 ++++ .../highlighting/HighlightingAdapter.kt | 12 +- .../highlighting/HighlightingShowcase.kt | 21 +-- .../highlighting/HighlightingViewHolder.kt | 20 +-- .../showcase/list/actor/Actor.kt | 3 +- .../showcase/list/actor/ActorAdapterNested.kt | 15 +- .../showcase/list/actor/ActorViewHolder.kt | 12 ++ .../list/actor/ActorViewHolderSmall.kt | 12 ++ .../showcase/list/header/HeaderViewHolder.kt | 3 +- .../showcase/list/merged/ActorsAdapter.kt | 45 +++++ .../list/merged/MergedListShowcase.kt | 69 +++++++ .../showcase/list/movie/Movie.kt | 2 +- .../showcase/list/movie/MovieAdapter.kt | 11 +- .../showcase/list/movie/MovieAdapterNested.kt | 28 +++ .../showcase/list/movie/MovieAdapterPaged.kt | 21 +++ .../showcase/list/movie/MovieDiffUtil.kt | 3 +- .../showcase/list/movie/MovieViewHolder.kt | 22 +++ .../list/movie/MovieViewHolderNested.kt | 19 ++ .../list/paging/PagingMultiSearchAdapter.kt} | 60 ++++--- .../list/paging/PagingMultipleIndexItem.kt | 0 .../paging/PagingMultipleIndexShowcase.kt | 72 ++++++++ .../paging/PagingMultipleIndexViewHolder.kt | 18 +- .../list/paging/PagingSingleIndexShowcase.kt | 56 ++++++ .../showcase/list/product/Product.kt | 0 .../showcase/list/product/ProductAdapter.kt | 29 ++- .../showcase/loading/LoadingShowcase.kt | 63 +++++++ .../relateditems/RelatedItemsShowcase.kt | 27 ++- .../search/SearchAsYouTypeShowcase.kt | 29 +-- .../search/SearchAutoCompleteTextView.kt | 57 ++++++ .../showcase/search/SearchOnSubmitShowcase.kt | 29 +-- .../showcase/sortby/SortByShowcase.kt | 36 ++-- .../showcase/stats/StatsShowcase.kt | 38 ++-- .../res/drawable-anydpi/ic_filter_list.xml | 0 .../drawable-v24/ic_launcher_foreground.xml | 0 .../src/main/res/drawable/ic_add.xml | 0 .../src/main/res/drawable/ic_arrow_down.xml | 0 .../src/main/res/drawable/ic_arrow_up.xml | 0 .../src/main/res/drawable/ic_check.xml | 0 .../src/main/res/drawable/ic_close_hint.xml | 0 .../src/main/res/drawable/ic_delete.xml | 0 .../src/main/res/drawable/ic_info.xml | 0 .../res/drawable/ic_launcher_background.xml | 0 .../res/drawable/ic_microphone_outline.xml | 0 .../src/main/res/drawable/ic_remove.xml | 0 .../src/main/res/drawable/ic_restore.xml | 0 .../src/main/res/drawable/ic_search_hint.xml | 0 .../main/res/drawable/query_background.xml | 0 .../src/main/res/drawable/rectangle.xml | 0 .../src/main/res/drawable/thumb.xml | 0 .../src/main/res/layout/filter_chip.xml | 0 .../src/main/res/layout/header_filter.xml | 0 .../src/main/res/layout/header_item.xml | 0 .../src/main/res/layout/include_list.xml | 0 .../main/res/layout/include_plus_minus.xml | 0 .../src/main/res/layout/include_search.xml | 0 .../main/res/layout/include_search_info.xml | 0 .../src/main/res/layout/list_item_actor.xml | 0 .../res/layout/list_item_highlighting.xml | 0 .../src/main/res/layout/list_item_large.xml | 0 .../src/main/res/layout/list_item_movie.xml | 0 .../src/main/res/layout/list_item_product.xml | 0 .../main/res/layout/list_item_selectable.xml | 0 .../src/main/res/layout/list_item_small.xml | 0 .../src/main/res/layout/menu_item.xml | 0 .../main/res/layout/showcase_directory.xml | 2 +- .../layout/showcase_dynamic_facet_list.xml | 2 +- .../main/res/layout/showcase_facet_list.xml | 1 + .../layout/showcase_facet_list_persistent.xml | 3 +- .../res/layout/showcase_facet_list_search.xml | 2 +- .../main/res/layout/showcase_filter_clear.xml | 0 .../res/layout/showcase_filter_comparison.xml | 0 .../res/layout/showcase_filter_current.xml | 0 .../main/res/layout/showcase_filter_list.xml | 1 + .../main/res/layout/showcase_filter_map.xml | 0 .../main/res/layout/showcase_filter_range.xml | 0 .../res/layout/showcase_filter_rating.xml | 0 .../res/layout/showcase_filter_toggle.xml | 0 .../layout/showcase_filter_toggle_default.xml | 0 .../main/res/layout/showcase_hierarchical.xml | 0 .../main/res/layout/showcase_highlighting.xml | 2 +- .../src/main/res/layout/showcase_loading.xml | 2 +- .../main/res/layout/showcase_multisearch.xml | 73 ++++++++ .../src/main/res/layout/showcase_paging.xml | 2 +- .../showcase_query_rule_custom_data.xml | 2 +- ...owcase_query_rule_custom_data_template.xml | 0 .../main/res/layout/showcase_relateditems.xml | 0 .../src/main/res/layout/showcase_search.xml | 2 +- .../layout/showcase_search_autocomplete.xml | 0 .../src/main/res/layout/showcase_sort_by.xml | 0 .../src/main/res/layout/showcase_stats.xml | 2 +- .../res/mipmap-anydpi-v26/ic_launcher.xml | 0 .../mipmap-anydpi-v26/ic_launcher_round.xml | 0 .../src/main/res/mipmap-hdpi/ic_launcher.png | Bin .../res/mipmap-hdpi/ic_launcher_round.png | Bin .../src/main/res/mipmap-mdpi/ic_launcher.png | Bin .../res/mipmap-mdpi/ic_launcher_round.png | Bin .../src/main/res/mipmap-xhdpi/ic_launcher.png | Bin .../res/mipmap-xhdpi/ic_launcher_round.png | Bin .../main/res/mipmap-xxhdpi/ic_launcher.png | Bin .../res/mipmap-xxhdpi/ic_launcher_round.png | Bin .../main/res/mipmap-xxxhdpi/ic_launcher.png | Bin .../res/mipmap-xxxhdpi/ic_launcher_round.png | Bin .../src/main/res/values/colors.xml | 0 .../src/main/res/values/strings.xml | 2 + .../src/main/res/values/styles.xml | 0 .../compose}/build.gradle | 14 +- .../compose}/src/main/AndroidManifest.xml | 0 .../instantsearch/showcase/compose/Demo.kt | 17 +- .../customdata/QueryRuleCustomDataShowcase.kt | 18 +- .../compose/customdata/TemplateActivity.kt | 0 .../showcase/compose/directory/Directory.kt | 0 .../compose/directory/DirectoryHit.kt | 2 +- .../compose/directory/DirectoryItem.kt | 0 .../compose/directory/DirectoryScreen.kt | 0 .../compose/directory/DirectoryShowcase.kt | 6 +- .../filter/clear/FilterClearShowcase.kt | 23 ++- .../filter/current/FilterCurrentShowcase.kt | 21 +-- .../filter/facet/DynamicFacetShowcase.kt | 19 +- .../facet/FacetListPersistentShowcase.kt | 17 +- .../filter/facet/FacetListSearchShowcase.kt | 47 +++-- .../compose/filter/facet/FacetListShowcase.kt | 25 ++- .../filter/list/FilterListAllShowcase.kt | 17 +- .../filter/list/FilterListFacetShowcase.kt | 17 +- .../filter/list/FilterListNumericShowcase.kt | 17 +- .../compose/filter/list/FilterListScreen.kt | 0 .../filter/list/FilterListTagShowcase.kt | 17 +- .../compose/filter/map/FilterMapShowcase.kt | 19 +- .../comparison/FilterComparisonShowcase.kt | 20 +-- .../filter/range/FilterRangeShowcase.kt | 16 +- .../showcase/compose/filter/range/RangeUI.kt | 0 .../compose/filter/rating/RatingShowcase.kt | 32 ++-- .../filter/toggle/FilterToggleShowcase.kt | 17 +- .../hierarchical/HierarchicalShowcase.kt | 21 +-- .../highlighting/HighlightingShowcase.kt | 11 +- .../compose/list/merged/MergedListShowcase.kt | 64 ++++--- .../paging/PagingMultipleIndexShowcase.kt | 27 +-- .../list/paging/PagingSingleIndexShowcase.kt | 22 +-- .../compose/loading/LoadingShowcase.kt | 20 ++- .../showcase/compose/model/Actor.kt | 0 .../showcase/compose/model/Banner.kt | 0 .../showcase/compose/model/Movie.kt | 2 +- .../showcase/compose/model/Product.kt | 0 .../relateditems/RelatedItemsShowcase.kt | 13 +- .../compose/search/SearchAsYouTypeShowcase.kt | 13 +- .../search/SearchAutoCompleteShowcase.kt | 13 +- .../compose/search/SearchOnSubmitShowcase.kt | 13 +- .../showcase/compose/sortby/SortByShowcase.kt | 34 ++-- .../showcase/compose/stats/StatsShowcase.kt | 17 +- .../showcase/compose/ui/Color.kt | 0 .../showcase/compose/ui/Shape.kt | 0 .../showcase/compose/ui/Theme.kt | 0 .../instantsearch/showcase/compose/ui/Type.kt | 0 .../compose/ui/component/ActorsList.kt | 0 .../ui/component/AutoCompleteTextField.kt | 0 .../compose/ui/component/DropdownTextField.kt | 0 .../compose/ui/component/FacetList.kt | 10 +- .../compose/ui/component/FilterChips.kt | 0 .../compose/ui/component/FilterList.kt | 4 +- .../compose/ui/component/HeaderFilter.kt | 0 .../ui/component/HeaderFilterConnector.kt | 18 +- .../compose/ui/component/HelpDialog.kt | 0 .../compose/ui/component/MoviesList.kt | 0 .../compose/ui/component/ProductList.kt | 0 .../compose/ui/component/RatingBar.kt | 0 .../compose/ui/component/RestoreFab.kt | 0 .../showcase/compose/ui/component/TopBar.kt | 0 .../drawable-v24/ic_launcher_foreground.xml | 0 .../res/drawable/ic_launcher_background.xml | 0 .../src/main/res/drawable/thumb.xml | 0 .../main/res/layout/autocompletetextfield.xml | 0 .../res/mipmap-anydpi-v26/ic_launcher.xml | 0 .../mipmap-anydpi-v26/ic_launcher_round.xml | 0 .../src/main/res/mipmap-hdpi/ic_launcher.webp | Bin .../res/mipmap-hdpi/ic_launcher_round.webp | Bin .../src/main/res/mipmap-mdpi/ic_launcher.webp | Bin .../res/mipmap-mdpi/ic_launcher_round.webp | Bin .../main/res/mipmap-xhdpi/ic_launcher.webp | Bin .../res/mipmap-xhdpi/ic_launcher_round.webp | Bin .../main/res/mipmap-xxhdpi/ic_launcher.webp | Bin .../res/mipmap-xxhdpi/ic_launcher_round.webp | Bin .../main/res/mipmap-xxxhdpi/ic_launcher.webp | Bin .../res/mipmap-xxxhdpi/ic_launcher_round.webp | Bin .../compose}/src/main/res/values/colors.xml | 0 .../compose}/src/main/res/values/strings.xml | 0 .../compose}/src/main/res/values/themes.xml | 0 .../filter/clear/FilterClearShowcase.kt | 71 -------- .../facet/FacetListPersistentShowcase.kt | 80 --------- .../filter/facet/FacetListSearchShowcase.kt | 80 --------- .../filter/facet/FacetListViewHolderImpl.kt | 32 ---- .../filter/facet/dynamic/FacetItem.kt | 9 - .../filter/facet/dynamic/ViewHolderFactory.kt | 43 ----- .../filter/list/FilterListTagShowcase.kt | 60 ------- .../filter/list/FilterListViewHolder.kt | 15 -- .../showcase/filter/map/FilterMapShowcase.kt | 56 ------ .../filter/range/FilterRangeShowcase.kt | 79 -------- .../showcase/filter/rating/RatingShowcase.kt | 83 --------- .../hierarchical/HierarchicalShowcase.kt | 77 -------- .../hierarchical/HierarchicalViewHolder.kt | 30 ---- .../showcase/list/actor/ActorViewHolder.kt | 13 -- .../list/actor/ActorViewHolderSmall.kt | 13 -- .../showcase/list/merged/MergedListAdapter.kt | 64 ------- .../list/merged/MergedListShowcase.kt | 65 ------- .../showcase/list/movie/MovieAdapterNested.kt | 28 --- .../showcase/list/movie/MovieAdapterPaged.kt | 20 --- .../showcase/list/movie/MovieViewHolder.kt | 24 --- .../list/movie/MovieViewHolderNested.kt | 20 --- .../paging/PagingMultipleIndexShowcase.kt | 72 -------- .../list/paging/PagingSingleIndexShowcase.kt | 53 ------ .../showcase/loading/LoadingShowcase.kt | 61 ------- .../search/SearchAutoCompleteTextView.kt | 51 ------ .../src/main/res/drawable/ic_close_hint.xml | 12 -- .../main/res/drawable/query_background.xml | 12 -- 381 files changed, 3138 insertions(+), 3820 deletions(-) delete mode 100644 compose/.gitignore delete mode 100644 compose/build.gradle delete mode 100644 compose/proguard-rules.pro delete mode 100644 compose/src/androidTest/java/com/algolia/searchapp/ExampleInstrumentedTest.kt delete mode 100644 compose/src/main/AndroidManifest.xml delete mode 100644 compose/src/main/res/values-night/themes.xml delete mode 100644 compose/src/main/res/values/colors.xml delete mode 100644 compose/src/main/res/values/strings.xml delete mode 100644 compose/src/main/res/values/themes.xml delete mode 100644 compose/src/test/java/com/algolia/searchapp/ExampleUnitTest.kt rename {insights/src/main/kotlin/com/algolia/instantsearch/insights/showcase => guides/src/main/kotlin/com/algolia/instantsearch/guides}/App.kt (57%) rename compose/src/main/java/com/algolia/searchapp/MainActivity.kt => guides/src/main/kotlin/com/algolia/instantsearch/guides/compose/ComposeActivity.kt (80%) rename {compose/src/main/java/com/algolia/searchapp => guides/src/main/kotlin/com/algolia/instantsearch/guides/compose}/MainViewModel.kt (63%) rename {compose/src/main/java/com/algolia/searchapp => guides/src/main/kotlin/com/algolia/instantsearch/guides/compose}/SearchScreen.kt (95%) rename {compose/src/main/java/com/algolia/searchapp/ui => guides/src/main/kotlin/com/algolia/instantsearch/guides/compose}/theme/Color.kt (76%) rename {compose/src/main/java/com/algolia/searchapp/ui => guides/src/main/kotlin/com/algolia/instantsearch/guides/compose}/theme/Shape.kt (83%) rename {compose/src/main/java/com/algolia/searchapp/ui => guides/src/main/kotlin/com/algolia/instantsearch/guides/compose}/theme/Theme.kt (76%) rename {compose/src/main/java/com/algolia/searchapp/ui => guides/src/main/kotlin/com/algolia/instantsearch/guides/compose}/theme/Type.kt (54%) create mode 100644 guides/src/main/kotlin/com/algolia/instantsearch/guides/extension/RecyclerView.kt rename {insights/src/main/kotlin/com/algolia/instantsearch/insights/showcase => guides/src/main/kotlin/com/algolia/instantsearch/guides}/extension/SearchView.kt (92%) delete mode 100644 guides/src/main/kotlin/com/algolia/instantsearch/guides/gettingstarted/Product.kt delete mode 100644 guides/src/main/kotlin/com/algolia/instantsearch/guides/gettingstarted/ProductViewHolder.kt create mode 100644 guides/src/main/kotlin/com/algolia/instantsearch/guides/insights/InsightsActivity.kt create mode 100644 guides/src/main/kotlin/com/algolia/instantsearch/guides/insights/ListItemAdapter.kt rename {compose/src/main/java/com/algolia/searchapp => guides/src/main/kotlin/com/algolia/instantsearch/guides/model}/Product.kt (53%) create mode 100644 guides/src/main/kotlin/com/algolia/instantsearch/guides/model/Suggestion.kt delete mode 100644 guides/src/main/kotlin/com/algolia/instantsearch/guides/places/ViewHolder.kt delete mode 100644 guides/src/main/kotlin/com/algolia/instantsearch/guides/querysuggestion/Adapter.kt delete mode 100644 guides/src/main/kotlin/com/algolia/instantsearch/guides/querysuggestion/AdapterItem.kt create mode 100644 guides/src/main/kotlin/com/algolia/instantsearch/guides/querysuggestion/QuerySuggestionActivity.kt delete mode 100644 guides/src/main/kotlin/com/algolia/instantsearch/guides/querysuggestion/QuerySuggestionGuide.kt create mode 100644 guides/src/main/kotlin/com/algolia/instantsearch/guides/querysuggestion/QuerySuggestionViewModel.kt delete mode 100644 guides/src/main/kotlin/com/algolia/instantsearch/guides/querysuggestion/ViewHolder.kt create mode 100644 guides/src/main/kotlin/com/algolia/instantsearch/guides/querysuggestion/product/Product.kt create mode 100644 guides/src/main/kotlin/com/algolia/instantsearch/guides/querysuggestion/product/ProductAdapter.kt create mode 100644 guides/src/main/kotlin/com/algolia/instantsearch/guides/querysuggestion/product/ProductFragment.kt create mode 100644 guides/src/main/kotlin/com/algolia/instantsearch/guides/querysuggestion/suggestion/SuggestionAdapter.kt create mode 100644 guides/src/main/kotlin/com/algolia/instantsearch/guides/querysuggestion/suggestion/SuggestionFragment.kt create mode 100644 guides/src/main/kotlin/com/algolia/instantsearch/guides/voice/VoiceSearchActivity.kt rename {insights => guides}/src/main/res/drawable/ic_add_shopping_cart.xml (100%) rename {insights => guides}/src/main/res/drawable/ic_microphone_outline.xml (100%) rename {insights => guides}/src/main/res/drawable/ic_search_hint.xml (100%) rename insights/src/main/res/layout/demo_activity.xml => guides/src/main/res/layout/activity_insights.xml (68%) create mode 100644 guides/src/main/res/layout/activity_voice_search.xml create mode 100644 guides/src/main/res/layout/fragment_items.xml rename insights/src/main/res/layout/list_item_large.xml => guides/src/main/res/layout/list_item_large_buy.xml (100%) delete mode 100644 insights/.gitignore delete mode 100644 insights/build.gradle delete mode 100644 insights/consumer-rules.pro delete mode 100644 insights/proguard-rules.pro delete mode 100644 insights/src/androidTest/java/com/algolia/insights/ExampleInstrumentedTest.kt delete mode 100644 insights/src/main/AndroidManifest.xml delete mode 100644 insights/src/main/kotlin/com/algolia/instantsearch/insights/showcase/DemoActivity.kt delete mode 100644 insights/src/main/kotlin/com/algolia/instantsearch/insights/showcase/ListItem.kt delete mode 100644 insights/src/main/kotlin/com/algolia/instantsearch/insights/showcase/ListItemAdapter.kt delete mode 100644 insights/src/main/kotlin/com/algolia/instantsearch/insights/showcase/ListItemCallback.kt delete mode 100644 insights/src/main/kotlin/com/algolia/instantsearch/insights/showcase/ListItemViewHolder.kt delete mode 100644 insights/src/main/kotlin/com/algolia/instantsearch/insights/showcase/extension/RecyclerView.kt delete mode 100644 insights/src/main/res/drawable-v24/ic_launcher_foreground.xml delete mode 100644 insights/src/main/res/drawable/ic_launcher_background.xml delete mode 100644 insights/src/main/res/layout/include_search.xml delete mode 100644 insights/src/main/res/mipmap-anydpi-v26/ic_launcher.xml delete mode 100644 insights/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml delete mode 100644 insights/src/main/res/mipmap-hdpi/ic_launcher.png delete mode 100644 insights/src/main/res/mipmap-hdpi/ic_launcher_round.png delete mode 100644 insights/src/main/res/mipmap-mdpi/ic_launcher.png delete mode 100644 insights/src/main/res/mipmap-mdpi/ic_launcher_round.png delete mode 100644 insights/src/main/res/mipmap-xhdpi/ic_launcher.png delete mode 100644 insights/src/main/res/mipmap-xhdpi/ic_launcher_round.png delete mode 100644 insights/src/main/res/mipmap-xxhdpi/ic_launcher.png delete mode 100644 insights/src/main/res/mipmap-xxhdpi/ic_launcher_round.png delete mode 100644 insights/src/main/res/mipmap-xxxhdpi/ic_launcher.png delete mode 100644 insights/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png delete mode 100644 insights/src/main/res/values/colors.xml delete mode 100644 insights/src/main/res/values/strings.xml delete mode 100644 insights/src/main/res/values/styles.xml delete mode 100644 insights/src/test/java/com/algolia/insights/ExampleUnitTest.kt delete mode 100644 showcase-compose/src/main/res/drawable-v24/ic_launcher_foreground.xml delete mode 100644 showcase-compose/src/main/res/drawable/ic_launcher_background.xml delete mode 100644 showcase-compose/src/main/res/mipmap-anydpi-v26/ic_launcher.xml delete mode 100644 showcase-compose/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml delete mode 100644 showcase-compose/src/main/res/mipmap-hdpi/ic_launcher.webp delete mode 100644 showcase-compose/src/main/res/mipmap-hdpi/ic_launcher_round.webp delete mode 100644 showcase-compose/src/main/res/mipmap-mdpi/ic_launcher.webp delete mode 100644 showcase-compose/src/main/res/mipmap-mdpi/ic_launcher_round.webp delete mode 100644 showcase-compose/src/main/res/mipmap-xhdpi/ic_launcher.webp delete mode 100644 showcase-compose/src/main/res/mipmap-xhdpi/ic_launcher_round.webp delete mode 100644 showcase-compose/src/main/res/mipmap-xxhdpi/ic_launcher.webp delete mode 100644 showcase-compose/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp delete mode 100644 showcase-compose/src/main/res/mipmap-xxxhdpi/ic_launcher.webp delete mode 100644 showcase-compose/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp rename showcase/{ => android-view}/.gitignore (100%) rename showcase/{ => android-view}/README.md (100%) rename showcase/{ => android-view}/build.gradle (83%) rename showcase/{ => android-view}/proguard-rules.pro (100%) rename showcase/{ => android-view}/src/main/AndroidManifest.xml (100%) rename showcase/{ => android-view}/src/main/kotlin/com/algolia/instantsearch/showcase/Demo.kt (81%) rename showcase/{ => android-view}/src/main/kotlin/com/algolia/instantsearch/showcase/customdata/Banner.kt (100%) rename showcase/{ => android-view}/src/main/kotlin/com/algolia/instantsearch/showcase/customdata/QueryRuleCustomDataShowcase.kt (66%) rename showcase/{ => android-view}/src/main/kotlin/com/algolia/instantsearch/showcase/customdata/TemplateActivity.kt (67%) rename showcase/{ => android-view}/src/main/kotlin/com/algolia/instantsearch/showcase/directory/Directory.kt (100%) rename showcase/{ => android-view}/src/main/kotlin/com/algolia/instantsearch/showcase/directory/DirectoryAdapter.kt (78%) rename showcase/{ => android-view}/src/main/kotlin/com/algolia/instantsearch/showcase/directory/DirectoryHit.kt (90%) rename showcase/{ => android-view}/src/main/kotlin/com/algolia/instantsearch/showcase/directory/DirectoryItem.kt (100%) rename showcase/{ => android-view}/src/main/kotlin/com/algolia/instantsearch/showcase/directory/DirectoryShowcase.kt (57%) rename showcase/{ => android-view}/src/main/kotlin/com/algolia/instantsearch/showcase/directory/DirectoryViewHolder.kt (53%) create mode 100644 showcase/android-view/src/main/kotlin/com/algolia/instantsearch/showcase/filter/clear/FilterClearShowcase.kt rename showcase/{ => android-view}/src/main/kotlin/com/algolia/instantsearch/showcase/filter/current/ShowcaseFilterCurrent.kt (53%) create mode 100644 showcase/android-view/src/main/kotlin/com/algolia/instantsearch/showcase/filter/facet/FacetListPersistentShowcase.kt create mode 100644 showcase/android-view/src/main/kotlin/com/algolia/instantsearch/showcase/filter/facet/FacetListSearchShowcase.kt rename showcase/{ => android-view}/src/main/kotlin/com/algolia/instantsearch/showcase/filter/facet/FacetListShowcase.kt (63%) create mode 100644 showcase/android-view/src/main/kotlin/com/algolia/instantsearch/showcase/filter/facet/FacetListViewHolderImpl.kt rename showcase/{ => android-view}/src/main/kotlin/com/algolia/instantsearch/showcase/filter/facet/dynamic/DynamicFacetShowcase.kt (64%) create mode 100644 showcase/android-view/src/main/kotlin/com/algolia/instantsearch/showcase/filter/facet/dynamic/ViewHolderFactory.kt rename showcase/{ => android-view}/src/main/kotlin/com/algolia/instantsearch/showcase/filter/list/FilterListAdapter.kt (51%) rename showcase/{ => android-view}/src/main/kotlin/com/algolia/instantsearch/showcase/filter/list/FilterListAllShowcase.kt (52%) rename showcase/{ => android-view}/src/main/kotlin/com/algolia/instantsearch/showcase/filter/list/FilterListFacetShowcase.kt (52%) rename showcase/{ => android-view}/src/main/kotlin/com/algolia/instantsearch/showcase/filter/list/FilterListNumericShowcase.kt (52%) create mode 100644 showcase/android-view/src/main/kotlin/com/algolia/instantsearch/showcase/filter/list/FilterListTagShowcase.kt create mode 100644 showcase/android-view/src/main/kotlin/com/algolia/instantsearch/showcase/filter/list/FilterListViewHolder.kt create mode 100644 showcase/android-view/src/main/kotlin/com/algolia/instantsearch/showcase/filter/map/FilterMapShowcase.kt rename showcase/{ => android-view}/src/main/kotlin/com/algolia/instantsearch/showcase/filter/numeric/comparison/FilterComparisonShowcase.kt (54%) rename showcase/{ => android-view}/src/main/kotlin/com/algolia/instantsearch/showcase/filter/numeric/comparison/FilterPriceView.kt (61%) rename showcase/{ => android-view}/src/main/kotlin/com/algolia/instantsearch/showcase/filter/numeric/comparison/FilterYearView.kt (67%) rename showcase/{ => android-view}/src/main/kotlin/com/algolia/instantsearch/showcase/filter/range/BoundsTextView.kt (100%) create mode 100644 showcase/android-view/src/main/kotlin/com/algolia/instantsearch/showcase/filter/range/FilterRangeShowcase.kt rename showcase/{ => android-view}/src/main/kotlin/com/algolia/instantsearch/showcase/filter/range/RangeSliderView.kt (100%) rename showcase/{ => android-view}/src/main/kotlin/com/algolia/instantsearch/showcase/filter/range/RangeTextView.kt (100%) rename showcase/{ => android-view}/src/main/kotlin/com/algolia/instantsearch/showcase/filter/rating/RatingBarView.kt (100%) create mode 100644 showcase/android-view/src/main/kotlin/com/algolia/instantsearch/showcase/filter/rating/RatingShowcase.kt rename showcase/{ => android-view}/src/main/kotlin/com/algolia/instantsearch/showcase/filter/rating/RatingTextView.kt (100%) rename showcase/{ => android-view}/src/main/kotlin/com/algolia/instantsearch/showcase/filter/toggle/FilterToggleShowcase.kt (53%) rename showcase/{ => android-view}/src/main/kotlin/com/algolia/instantsearch/showcase/hierarchical/HierarchicalAdapter.kt (73%) create mode 100644 showcase/android-view/src/main/kotlin/com/algolia/instantsearch/showcase/hierarchical/HierarchicalShowcase.kt create mode 100644 showcase/android-view/src/main/kotlin/com/algolia/instantsearch/showcase/hierarchical/HierarchicalViewHolder.kt rename showcase/{ => android-view}/src/main/kotlin/com/algolia/instantsearch/showcase/highlighting/HighlightingAdapter.kt (68%) rename showcase/{ => android-view}/src/main/kotlin/com/algolia/instantsearch/showcase/highlighting/HighlightingShowcase.kt (57%) rename showcase/{ => android-view}/src/main/kotlin/com/algolia/instantsearch/showcase/highlighting/HighlightingViewHolder.kt (75%) rename showcase/{ => android-view}/src/main/kotlin/com/algolia/instantsearch/showcase/list/actor/Actor.kt (95%) rename showcase/{ => android-view}/src/main/kotlin/com/algolia/instantsearch/showcase/list/actor/ActorAdapterNested.kt (68%) create mode 100644 showcase/android-view/src/main/kotlin/com/algolia/instantsearch/showcase/list/actor/ActorViewHolder.kt create mode 100644 showcase/android-view/src/main/kotlin/com/algolia/instantsearch/showcase/list/actor/ActorViewHolderSmall.kt rename showcase/{ => android-view}/src/main/kotlin/com/algolia/instantsearch/showcase/list/header/HeaderViewHolder.kt (99%) create mode 100644 showcase/android-view/src/main/kotlin/com/algolia/instantsearch/showcase/list/merged/ActorsAdapter.kt create mode 100644 showcase/android-view/src/main/kotlin/com/algolia/instantsearch/showcase/list/merged/MergedListShowcase.kt rename showcase/{ => android-view}/src/main/kotlin/com/algolia/instantsearch/showcase/list/movie/Movie.kt (92%) rename showcase/{ => android-view}/src/main/kotlin/com/algolia/instantsearch/showcase/list/movie/MovieAdapter.kt (70%) create mode 100644 showcase/android-view/src/main/kotlin/com/algolia/instantsearch/showcase/list/movie/MovieAdapterNested.kt create mode 100644 showcase/android-view/src/main/kotlin/com/algolia/instantsearch/showcase/list/movie/MovieAdapterPaged.kt rename showcase/{ => android-view}/src/main/kotlin/com/algolia/instantsearch/showcase/list/movie/MovieDiffUtil.kt (99%) create mode 100644 showcase/android-view/src/main/kotlin/com/algolia/instantsearch/showcase/list/movie/MovieViewHolder.kt create mode 100644 showcase/android-view/src/main/kotlin/com/algolia/instantsearch/showcase/list/movie/MovieViewHolderNested.kt rename showcase/{src/main/kotlin/com/algolia/instantsearch/showcase/list/paging/PagingMultipleIndexAdapter.kt => android-view/src/main/kotlin/com/algolia/instantsearch/showcase/list/paging/PagingMultiSearchAdapter.kt} (72%) rename showcase/{ => android-view}/src/main/kotlin/com/algolia/instantsearch/showcase/list/paging/PagingMultipleIndexItem.kt (100%) create mode 100644 showcase/android-view/src/main/kotlin/com/algolia/instantsearch/showcase/list/paging/PagingMultipleIndexShowcase.kt rename showcase/{ => android-view}/src/main/kotlin/com/algolia/instantsearch/showcase/list/paging/PagingMultipleIndexViewHolder.kt (77%) create mode 100644 showcase/android-view/src/main/kotlin/com/algolia/instantsearch/showcase/list/paging/PagingSingleIndexShowcase.kt rename showcase/{ => android-view}/src/main/kotlin/com/algolia/instantsearch/showcase/list/product/Product.kt (100%) rename showcase/{ => android-view}/src/main/kotlin/com/algolia/instantsearch/showcase/list/product/ProductAdapter.kt (63%) create mode 100644 showcase/android-view/src/main/kotlin/com/algolia/instantsearch/showcase/loading/LoadingShowcase.kt rename showcase/{ => android-view}/src/main/kotlin/com/algolia/instantsearch/showcase/relateditems/RelatedItemsShowcase.kt (66%) rename showcase/{ => android-view}/src/main/kotlin/com/algolia/instantsearch/showcase/search/SearchAsYouTypeShowcase.kt (55%) create mode 100644 showcase/android-view/src/main/kotlin/com/algolia/instantsearch/showcase/search/SearchAutoCompleteTextView.kt rename showcase/{ => android-view}/src/main/kotlin/com/algolia/instantsearch/showcase/search/SearchOnSubmitShowcase.kt (55%) rename showcase/{ => android-view}/src/main/kotlin/com/algolia/instantsearch/showcase/sortby/SortByShowcase.kt (60%) rename showcase/{ => android-view}/src/main/kotlin/com/algolia/instantsearch/showcase/stats/StatsShowcase.kt (55%) rename showcase/{ => android-view}/src/main/res/drawable-anydpi/ic_filter_list.xml (100%) rename showcase/{ => android-view}/src/main/res/drawable-v24/ic_launcher_foreground.xml (100%) rename showcase/{ => android-view}/src/main/res/drawable/ic_add.xml (100%) rename showcase/{ => android-view}/src/main/res/drawable/ic_arrow_down.xml (100%) rename showcase/{ => android-view}/src/main/res/drawable/ic_arrow_up.xml (100%) rename showcase/{ => android-view}/src/main/res/drawable/ic_check.xml (100%) rename {insights => showcase/android-view}/src/main/res/drawable/ic_close_hint.xml (100%) rename showcase/{ => android-view}/src/main/res/drawable/ic_delete.xml (100%) rename showcase/{ => android-view}/src/main/res/drawable/ic_info.xml (100%) rename showcase/{ => android-view}/src/main/res/drawable/ic_launcher_background.xml (100%) rename showcase/{ => android-view}/src/main/res/drawable/ic_microphone_outline.xml (100%) rename showcase/{ => android-view}/src/main/res/drawable/ic_remove.xml (100%) rename showcase/{ => android-view}/src/main/res/drawable/ic_restore.xml (100%) rename showcase/{ => android-view}/src/main/res/drawable/ic_search_hint.xml (100%) rename {insights => showcase/android-view}/src/main/res/drawable/query_background.xml (100%) rename showcase/{ => android-view}/src/main/res/drawable/rectangle.xml (100%) rename {showcase-compose => showcase/android-view}/src/main/res/drawable/thumb.xml (100%) rename showcase/{ => android-view}/src/main/res/layout/filter_chip.xml (100%) rename showcase/{ => android-view}/src/main/res/layout/header_filter.xml (100%) rename showcase/{ => android-view}/src/main/res/layout/header_item.xml (100%) rename showcase/{ => android-view}/src/main/res/layout/include_list.xml (100%) rename showcase/{ => android-view}/src/main/res/layout/include_plus_minus.xml (100%) rename showcase/{ => android-view}/src/main/res/layout/include_search.xml (100%) rename showcase/{ => android-view}/src/main/res/layout/include_search_info.xml (100%) rename showcase/{ => android-view}/src/main/res/layout/list_item_actor.xml (100%) rename showcase/{ => android-view}/src/main/res/layout/list_item_highlighting.xml (100%) rename showcase/{ => android-view}/src/main/res/layout/list_item_large.xml (100%) rename showcase/{ => android-view}/src/main/res/layout/list_item_movie.xml (100%) rename showcase/{ => android-view}/src/main/res/layout/list_item_product.xml (100%) rename showcase/{ => android-view}/src/main/res/layout/list_item_selectable.xml (100%) rename showcase/{ => android-view}/src/main/res/layout/list_item_small.xml (100%) rename showcase/{ => android-view}/src/main/res/layout/menu_item.xml (100%) rename showcase/{ => android-view}/src/main/res/layout/showcase_directory.xml (93%) rename showcase/{ => android-view}/src/main/res/layout/showcase_dynamic_facet_list.xml (93%) rename showcase/{ => android-view}/src/main/res/layout/showcase_facet_list.xml (97%) rename showcase/{ => android-view}/src/main/res/layout/showcase_facet_list_persistent.xml (90%) rename showcase/{ => android-view}/src/main/res/layout/showcase_facet_list_search.xml (95%) rename showcase/{ => android-view}/src/main/res/layout/showcase_filter_clear.xml (100%) rename showcase/{ => android-view}/src/main/res/layout/showcase_filter_comparison.xml (100%) rename showcase/{ => android-view}/src/main/res/layout/showcase_filter_current.xml (100%) rename showcase/{ => android-view}/src/main/res/layout/showcase_filter_list.xml (97%) rename showcase/{ => android-view}/src/main/res/layout/showcase_filter_map.xml (100%) rename showcase/{ => android-view}/src/main/res/layout/showcase_filter_range.xml (100%) rename showcase/{ => android-view}/src/main/res/layout/showcase_filter_rating.xml (100%) rename showcase/{ => android-view}/src/main/res/layout/showcase_filter_toggle.xml (100%) rename showcase/{ => android-view}/src/main/res/layout/showcase_filter_toggle_default.xml (100%) rename showcase/{ => android-view}/src/main/res/layout/showcase_hierarchical.xml (100%) rename showcase/{ => android-view}/src/main/res/layout/showcase_highlighting.xml (93%) rename showcase/{ => android-view}/src/main/res/layout/showcase_loading.xml (94%) create mode 100644 showcase/android-view/src/main/res/layout/showcase_multisearch.xml rename showcase/{ => android-view}/src/main/res/layout/showcase_paging.xml (96%) rename showcase/{ => android-view}/src/main/res/layout/showcase_query_rule_custom_data.xml (96%) rename showcase/{ => android-view}/src/main/res/layout/showcase_query_rule_custom_data_template.xml (100%) rename showcase/{ => android-view}/src/main/res/layout/showcase_relateditems.xml (100%) rename showcase/{ => android-view}/src/main/res/layout/showcase_search.xml (93%) rename showcase/{ => android-view}/src/main/res/layout/showcase_search_autocomplete.xml (100%) rename showcase/{ => android-view}/src/main/res/layout/showcase_sort_by.xml (100%) rename showcase/{ => android-view}/src/main/res/layout/showcase_stats.xml (95%) rename showcase/{ => android-view}/src/main/res/mipmap-anydpi-v26/ic_launcher.xml (100%) rename showcase/{ => android-view}/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml (100%) rename showcase/{ => android-view}/src/main/res/mipmap-hdpi/ic_launcher.png (100%) rename showcase/{ => android-view}/src/main/res/mipmap-hdpi/ic_launcher_round.png (100%) rename showcase/{ => android-view}/src/main/res/mipmap-mdpi/ic_launcher.png (100%) rename showcase/{ => android-view}/src/main/res/mipmap-mdpi/ic_launcher_round.png (100%) rename showcase/{ => android-view}/src/main/res/mipmap-xhdpi/ic_launcher.png (100%) rename showcase/{ => android-view}/src/main/res/mipmap-xhdpi/ic_launcher_round.png (100%) rename showcase/{ => android-view}/src/main/res/mipmap-xxhdpi/ic_launcher.png (100%) rename showcase/{ => android-view}/src/main/res/mipmap-xxhdpi/ic_launcher_round.png (100%) rename showcase/{ => android-view}/src/main/res/mipmap-xxxhdpi/ic_launcher.png (100%) rename showcase/{ => android-view}/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png (100%) rename showcase/{ => android-view}/src/main/res/values/colors.xml (100%) rename showcase/{ => android-view}/src/main/res/values/strings.xml (96%) rename showcase/{ => android-view}/src/main/res/values/styles.xml (100%) rename {showcase-compose => showcase/compose}/build.gradle (85%) rename {showcase-compose => showcase/compose}/src/main/AndroidManifest.xml (100%) rename {showcase-compose => showcase/compose}/src/main/kotlin/com/algolia/instantsearch/showcase/compose/Demo.kt (83%) rename {showcase-compose => showcase/compose}/src/main/kotlin/com/algolia/instantsearch/showcase/compose/customdata/QueryRuleCustomDataShowcase.kt (91%) rename {showcase-compose => showcase/compose}/src/main/kotlin/com/algolia/instantsearch/showcase/compose/customdata/TemplateActivity.kt (100%) rename {showcase-compose => showcase/compose}/src/main/kotlin/com/algolia/instantsearch/showcase/compose/directory/Directory.kt (100%) rename {showcase-compose => showcase/compose}/src/main/kotlin/com/algolia/instantsearch/showcase/compose/directory/DirectoryHit.kt (90%) rename {showcase-compose => showcase/compose}/src/main/kotlin/com/algolia/instantsearch/showcase/compose/directory/DirectoryItem.kt (100%) rename {showcase-compose => showcase/compose}/src/main/kotlin/com/algolia/instantsearch/showcase/compose/directory/DirectoryScreen.kt (100%) rename {showcase-compose => showcase/compose}/src/main/kotlin/com/algolia/instantsearch/showcase/compose/directory/DirectoryShowcase.kt (91%) rename {showcase-compose => showcase/compose}/src/main/kotlin/com/algolia/instantsearch/showcase/compose/filter/clear/FilterClearShowcase.kt (83%) rename {showcase-compose => showcase/compose}/src/main/kotlin/com/algolia/instantsearch/showcase/compose/filter/current/FilterCurrentShowcase.kt (86%) rename {showcase-compose => showcase/compose}/src/main/kotlin/com/algolia/instantsearch/showcase/compose/filter/facet/DynamicFacetShowcase.kt (89%) rename {showcase-compose => showcase/compose}/src/main/kotlin/com/algolia/instantsearch/showcase/compose/filter/facet/FacetListPersistentShowcase.kt (87%) rename {showcase-compose => showcase/compose}/src/main/kotlin/com/algolia/instantsearch/showcase/compose/filter/facet/FacetListSearchShowcase.kt (67%) rename {showcase-compose => showcase/compose}/src/main/kotlin/com/algolia/instantsearch/showcase/compose/filter/facet/FacetListShowcase.kt (86%) rename {showcase-compose => showcase/compose}/src/main/kotlin/com/algolia/instantsearch/showcase/compose/filter/list/FilterListAllShowcase.kt (81%) rename {showcase-compose => showcase/compose}/src/main/kotlin/com/algolia/instantsearch/showcase/compose/filter/list/FilterListFacetShowcase.kt (80%) rename {showcase-compose => showcase/compose}/src/main/kotlin/com/algolia/instantsearch/showcase/compose/filter/list/FilterListNumericShowcase.kt (79%) rename {showcase-compose => showcase/compose}/src/main/kotlin/com/algolia/instantsearch/showcase/compose/filter/list/FilterListScreen.kt (100%) rename {showcase-compose => showcase/compose}/src/main/kotlin/com/algolia/instantsearch/showcase/compose/filter/list/FilterListTagShowcase.kt (78%) rename {showcase-compose => showcase/compose}/src/main/kotlin/com/algolia/instantsearch/showcase/compose/filter/map/FilterMapShowcase.kt (84%) rename {showcase-compose => showcase/compose}/src/main/kotlin/com/algolia/instantsearch/showcase/compose/filter/numeric/comparison/FilterComparisonShowcase.kt (91%) rename {showcase-compose => showcase/compose}/src/main/kotlin/com/algolia/instantsearch/showcase/compose/filter/range/FilterRangeShowcase.kt (92%) rename {showcase-compose => showcase/compose}/src/main/kotlin/com/algolia/instantsearch/showcase/compose/filter/range/RangeUI.kt (100%) rename {showcase-compose => showcase/compose}/src/main/kotlin/com/algolia/instantsearch/showcase/compose/filter/rating/RatingShowcase.kt (89%) rename {showcase-compose => showcase/compose}/src/main/kotlin/com/algolia/instantsearch/showcase/compose/filter/toggle/FilterToggleShowcase.kt (89%) rename {showcase-compose => showcase/compose}/src/main/kotlin/com/algolia/instantsearch/showcase/compose/hierarchical/HierarchicalShowcase.kt (87%) rename {showcase-compose => showcase/compose}/src/main/kotlin/com/algolia/instantsearch/showcase/compose/highlighting/HighlightingShowcase.kt (87%) rename {showcase-compose => showcase/compose}/src/main/kotlin/com/algolia/instantsearch/showcase/compose/list/merged/MergedListShowcase.kt (64%) rename {showcase-compose => showcase/compose}/src/main/kotlin/com/algolia/instantsearch/showcase/compose/list/paging/PagingMultipleIndexShowcase.kt (82%) rename {showcase-compose => showcase/compose}/src/main/kotlin/com/algolia/instantsearch/showcase/compose/list/paging/PagingSingleIndexShowcase.kt (83%) rename {showcase-compose => showcase/compose}/src/main/kotlin/com/algolia/instantsearch/showcase/compose/loading/LoadingShowcase.kt (83%) rename {showcase-compose => showcase/compose}/src/main/kotlin/com/algolia/instantsearch/showcase/compose/model/Actor.kt (100%) rename {showcase-compose => showcase/compose}/src/main/kotlin/com/algolia/instantsearch/showcase/compose/model/Banner.kt (100%) rename {showcase-compose => showcase/compose}/src/main/kotlin/com/algolia/instantsearch/showcase/compose/model/Movie.kt (91%) rename {showcase-compose => showcase/compose}/src/main/kotlin/com/algolia/instantsearch/showcase/compose/model/Product.kt (100%) rename {showcase-compose => showcase/compose}/src/main/kotlin/com/algolia/instantsearch/showcase/compose/relateditems/RelatedItemsShowcase.kt (90%) rename {showcase-compose => showcase/compose}/src/main/kotlin/com/algolia/instantsearch/showcase/compose/search/SearchAsYouTypeShowcase.kt (87%) rename {showcase-compose => showcase/compose}/src/main/kotlin/com/algolia/instantsearch/showcase/compose/search/SearchAutoCompleteShowcase.kt (86%) rename {showcase-compose => showcase/compose}/src/main/kotlin/com/algolia/instantsearch/showcase/compose/search/SearchOnSubmitShowcase.kt (87%) rename {showcase-compose => showcase/compose}/src/main/kotlin/com/algolia/instantsearch/showcase/compose/sortby/SortByShowcase.kt (76%) rename {showcase-compose => showcase/compose}/src/main/kotlin/com/algolia/instantsearch/showcase/compose/stats/StatsShowcase.kt (87%) rename {showcase-compose => showcase/compose}/src/main/kotlin/com/algolia/instantsearch/showcase/compose/ui/Color.kt (100%) rename {showcase-compose => showcase/compose}/src/main/kotlin/com/algolia/instantsearch/showcase/compose/ui/Shape.kt (100%) rename {showcase-compose => showcase/compose}/src/main/kotlin/com/algolia/instantsearch/showcase/compose/ui/Theme.kt (100%) rename {showcase-compose => showcase/compose}/src/main/kotlin/com/algolia/instantsearch/showcase/compose/ui/Type.kt (100%) rename {showcase-compose => showcase/compose}/src/main/kotlin/com/algolia/instantsearch/showcase/compose/ui/component/ActorsList.kt (100%) rename {showcase-compose => showcase/compose}/src/main/kotlin/com/algolia/instantsearch/showcase/compose/ui/component/AutoCompleteTextField.kt (100%) rename {showcase-compose => showcase/compose}/src/main/kotlin/com/algolia/instantsearch/showcase/compose/ui/component/DropdownTextField.kt (100%) rename {showcase-compose => showcase/compose}/src/main/kotlin/com/algolia/instantsearch/showcase/compose/ui/component/FacetList.kt (93%) rename {showcase-compose => showcase/compose}/src/main/kotlin/com/algolia/instantsearch/showcase/compose/ui/component/FilterChips.kt (100%) rename {showcase-compose => showcase/compose}/src/main/kotlin/com/algolia/instantsearch/showcase/compose/ui/component/FilterList.kt (96%) rename {showcase-compose => showcase/compose}/src/main/kotlin/com/algolia/instantsearch/showcase/compose/ui/component/HeaderFilter.kt (100%) rename {showcase-compose => showcase/compose}/src/main/kotlin/com/algolia/instantsearch/showcase/compose/ui/component/HeaderFilterConnector.kt (73%) rename {showcase-compose => showcase/compose}/src/main/kotlin/com/algolia/instantsearch/showcase/compose/ui/component/HelpDialog.kt (100%) rename {showcase-compose => showcase/compose}/src/main/kotlin/com/algolia/instantsearch/showcase/compose/ui/component/MoviesList.kt (100%) rename {showcase-compose => showcase/compose}/src/main/kotlin/com/algolia/instantsearch/showcase/compose/ui/component/ProductList.kt (100%) rename {showcase-compose => showcase/compose}/src/main/kotlin/com/algolia/instantsearch/showcase/compose/ui/component/RatingBar.kt (100%) rename {showcase-compose => showcase/compose}/src/main/kotlin/com/algolia/instantsearch/showcase/compose/ui/component/RestoreFab.kt (100%) rename {showcase-compose => showcase/compose}/src/main/kotlin/com/algolia/instantsearch/showcase/compose/ui/component/TopBar.kt (100%) rename {compose => showcase/compose}/src/main/res/drawable-v24/ic_launcher_foreground.xml (100%) rename {compose => showcase/compose}/src/main/res/drawable/ic_launcher_background.xml (100%) rename showcase/{ => compose}/src/main/res/drawable/thumb.xml (100%) rename {showcase-compose => showcase/compose}/src/main/res/layout/autocompletetextfield.xml (100%) rename {compose => showcase/compose}/src/main/res/mipmap-anydpi-v26/ic_launcher.xml (100%) rename {compose => showcase/compose}/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml (100%) rename {compose => showcase/compose}/src/main/res/mipmap-hdpi/ic_launcher.webp (100%) rename {compose => showcase/compose}/src/main/res/mipmap-hdpi/ic_launcher_round.webp (100%) rename {compose => showcase/compose}/src/main/res/mipmap-mdpi/ic_launcher.webp (100%) rename {compose => showcase/compose}/src/main/res/mipmap-mdpi/ic_launcher_round.webp (100%) rename {compose => showcase/compose}/src/main/res/mipmap-xhdpi/ic_launcher.webp (100%) rename {compose => showcase/compose}/src/main/res/mipmap-xhdpi/ic_launcher_round.webp (100%) rename {compose => showcase/compose}/src/main/res/mipmap-xxhdpi/ic_launcher.webp (100%) rename {compose => showcase/compose}/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp (100%) rename {compose => showcase/compose}/src/main/res/mipmap-xxxhdpi/ic_launcher.webp (100%) rename {compose => showcase/compose}/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp (100%) rename {showcase-compose => showcase/compose}/src/main/res/values/colors.xml (100%) rename {showcase-compose => showcase/compose}/src/main/res/values/strings.xml (100%) rename {showcase-compose => showcase/compose}/src/main/res/values/themes.xml (100%) delete mode 100644 showcase/src/main/kotlin/com/algolia/instantsearch/showcase/filter/clear/FilterClearShowcase.kt delete mode 100644 showcase/src/main/kotlin/com/algolia/instantsearch/showcase/filter/facet/FacetListPersistentShowcase.kt delete mode 100644 showcase/src/main/kotlin/com/algolia/instantsearch/showcase/filter/facet/FacetListSearchShowcase.kt delete mode 100644 showcase/src/main/kotlin/com/algolia/instantsearch/showcase/filter/facet/FacetListViewHolderImpl.kt delete mode 100644 showcase/src/main/kotlin/com/algolia/instantsearch/showcase/filter/facet/dynamic/FacetItem.kt delete mode 100644 showcase/src/main/kotlin/com/algolia/instantsearch/showcase/filter/facet/dynamic/ViewHolderFactory.kt delete mode 100644 showcase/src/main/kotlin/com/algolia/instantsearch/showcase/filter/list/FilterListTagShowcase.kt delete mode 100644 showcase/src/main/kotlin/com/algolia/instantsearch/showcase/filter/list/FilterListViewHolder.kt delete mode 100644 showcase/src/main/kotlin/com/algolia/instantsearch/showcase/filter/map/FilterMapShowcase.kt delete mode 100644 showcase/src/main/kotlin/com/algolia/instantsearch/showcase/filter/range/FilterRangeShowcase.kt delete mode 100644 showcase/src/main/kotlin/com/algolia/instantsearch/showcase/filter/rating/RatingShowcase.kt delete mode 100644 showcase/src/main/kotlin/com/algolia/instantsearch/showcase/hierarchical/HierarchicalShowcase.kt delete mode 100644 showcase/src/main/kotlin/com/algolia/instantsearch/showcase/hierarchical/HierarchicalViewHolder.kt delete mode 100644 showcase/src/main/kotlin/com/algolia/instantsearch/showcase/list/actor/ActorViewHolder.kt delete mode 100644 showcase/src/main/kotlin/com/algolia/instantsearch/showcase/list/actor/ActorViewHolderSmall.kt delete mode 100644 showcase/src/main/kotlin/com/algolia/instantsearch/showcase/list/merged/MergedListAdapter.kt delete mode 100644 showcase/src/main/kotlin/com/algolia/instantsearch/showcase/list/merged/MergedListShowcase.kt delete mode 100644 showcase/src/main/kotlin/com/algolia/instantsearch/showcase/list/movie/MovieAdapterNested.kt delete mode 100644 showcase/src/main/kotlin/com/algolia/instantsearch/showcase/list/movie/MovieAdapterPaged.kt delete mode 100644 showcase/src/main/kotlin/com/algolia/instantsearch/showcase/list/movie/MovieViewHolder.kt delete mode 100644 showcase/src/main/kotlin/com/algolia/instantsearch/showcase/list/movie/MovieViewHolderNested.kt delete mode 100644 showcase/src/main/kotlin/com/algolia/instantsearch/showcase/list/paging/PagingMultipleIndexShowcase.kt delete mode 100644 showcase/src/main/kotlin/com/algolia/instantsearch/showcase/list/paging/PagingSingleIndexShowcase.kt delete mode 100644 showcase/src/main/kotlin/com/algolia/instantsearch/showcase/loading/LoadingShowcase.kt delete mode 100644 showcase/src/main/kotlin/com/algolia/instantsearch/showcase/search/SearchAutoCompleteTextView.kt delete mode 100644 showcase/src/main/res/drawable/ic_close_hint.xml delete mode 100644 showcase/src/main/res/drawable/query_background.xml diff --git a/build.gradle b/build.gradle index 52564693..417dd437 100644 --- a/build.gradle +++ b/build.gradle @@ -1,10 +1,10 @@ buildscript { - ext.kotlin_version = "1.5.31" + ext.kotlin_version = "1.6.10" ext.lifecycle_version = "2.2.0" - ext.build_tools_version = "31.0.0" - ext.instantsearch = '2.11.4' - ext.canary = '2.7' - ext.compose_version = '1.0.5' + ext.build_tools_version = "32.0.0" + ext.instantsearch = '3.0.0-SNAPSHOT' + ext.canary = '2.8.1' + ext.compose_version = '1.1.1' repositories { mavenCentral() google() diff --git a/compose/.gitignore b/compose/.gitignore deleted file mode 100644 index 42afabfd..00000000 --- a/compose/.gitignore +++ /dev/null @@ -1 +0,0 @@ -/build \ No newline at end of file diff --git a/compose/build.gradle b/compose/build.gradle deleted file mode 100644 index 625418e9..00000000 --- a/compose/build.gradle +++ /dev/null @@ -1,67 +0,0 @@ -plugins { - id 'com.android.application' - id 'kotlin-android' - id 'kotlinx-serialization' -} - -android { - compileSdk 31 - buildToolsVersion build_tools_version - - defaultConfig { - applicationId "com.algolia.searchapp" - minSdk 21 - targetSdk 31 - versionCode 1 - versionName "1.0" - - testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" - vectorDrawables { - useSupportLibrary true - } - } - buildTypes { - release { - minifyEnabled false - proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' - } - } - compileOptions { - sourceCompatibility JavaVersion.VERSION_1_8 - targetCompatibility JavaVersion.VERSION_1_8 - } - buildFeatures { - compose true - } - composeOptions { - kotlinCompilerExtensionVersion compose_version - } -} - -dependencies { - implementation "com.algolia:instantsearch-compose:$instantsearch" - - implementation "androidx.compose.material:material-icons-extended:$compose_version" - implementation "androidx.compose.ui:ui:$compose_version" - implementation "androidx.compose.material:material:$compose_version" - implementation "androidx.compose.ui:ui-tooling:$compose_version" - implementation 'androidx.paging:paging-compose:1.0.0-alpha11' - implementation 'androidx.activity:activity-compose:1.3.0-rc02' - implementation 'androidx.lifecycle:lifecycle-runtime-ktx:2.3.1' - implementation 'androidx.core:core-ktx:1.6.0' - implementation 'androidx.appcompat:appcompat:1.3.0' - implementation 'androidx.lifecycle:lifecycle-runtime-ktx:2.3.1' - testImplementation 'junit:junit:4.13.2' - androidTestImplementation 'androidx.test.ext:junit:1.1.3' - androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0' - androidTestImplementation "androidx.compose.ui:ui-test-junit4:$compose_version" -} - -tasks.withType(org.jetbrains.kotlin.gradle.tasks.KotlinCompile).configureEach { - kotlinOptions { - freeCompilerArgs += [ - '-Xopt-in=kotlin.RequiresOptIn', - '-Xopt-in=com.algolia.instantsearch.ExperimentalInstantSearch', - ] - } -} diff --git a/compose/proguard-rules.pro b/compose/proguard-rules.pro deleted file mode 100644 index 481bb434..00000000 --- a/compose/proguard-rules.pro +++ /dev/null @@ -1,21 +0,0 @@ -# Add project specific ProGuard rules here. -# You can control the set of applied configuration files using the -# proguardFiles setting in build.gradle. -# -# For more details, see -# http://developer.android.com/guide/developing/tools/proguard.html - -# If your project uses WebView with JS, uncomment the following -# and specify the fully qualified class name to the JavaScript interface -# class: -#-keepclassmembers class fqcn.of.javascript.interface.for.webview { -# public *; -#} - -# Uncomment this to preserve the line number information for -# debugging stack traces. -#-keepattributes SourceFile,LineNumberTable - -# If you keep the line number information, uncomment this to -# hide the original source file name. -#-renamesourcefileattribute SourceFile \ No newline at end of file diff --git a/compose/src/androidTest/java/com/algolia/searchapp/ExampleInstrumentedTest.kt b/compose/src/androidTest/java/com/algolia/searchapp/ExampleInstrumentedTest.kt deleted file mode 100644 index 31aaeadb..00000000 --- a/compose/src/androidTest/java/com/algolia/searchapp/ExampleInstrumentedTest.kt +++ /dev/null @@ -1,24 +0,0 @@ -package com.algolia.searchapp - -import androidx.test.platform.app.InstrumentationRegistry -import androidx.test.ext.junit.runners.AndroidJUnit4 - -import org.junit.Test -import org.junit.runner.RunWith - -import org.junit.Assert.* - -/** - * Instrumented test, which will execute on an Android device. - * - * See [testing documentation](http://d.android.com/tools/testing). - */ -@RunWith(AndroidJUnit4::class) -class ExampleInstrumentedTest { - @Test - fun useAppContext() { - // Context of the app under test. - val appContext = InstrumentationRegistry.getInstrumentation().targetContext - assertEquals("com.algolia.searchapp", appContext.packageName) - } -} \ No newline at end of file diff --git a/compose/src/main/AndroidManifest.xml b/compose/src/main/AndroidManifest.xml deleted file mode 100644 index 0a79ae12..00000000 --- a/compose/src/main/AndroidManifest.xml +++ /dev/null @@ -1,25 +0,0 @@ - - - - - - - - - - - - - - \ No newline at end of file diff --git a/compose/src/main/res/values-night/themes.xml b/compose/src/main/res/values-night/themes.xml deleted file mode 100644 index 74518cf0..00000000 --- a/compose/src/main/res/values-night/themes.xml +++ /dev/null @@ -1,16 +0,0 @@ - - - - \ No newline at end of file diff --git a/compose/src/main/res/values/colors.xml b/compose/src/main/res/values/colors.xml deleted file mode 100644 index f8c6127d..00000000 --- a/compose/src/main/res/values/colors.xml +++ /dev/null @@ -1,10 +0,0 @@ - - - #FFBB86FC - #FF6200EE - #FF3700B3 - #FF03DAC5 - #FF018786 - #FF000000 - #FFFFFFFF - \ No newline at end of file diff --git a/compose/src/main/res/values/strings.xml b/compose/src/main/res/values/strings.xml deleted file mode 100644 index 0c06b6c1..00000000 --- a/compose/src/main/res/values/strings.xml +++ /dev/null @@ -1,3 +0,0 @@ - - Search App - \ No newline at end of file diff --git a/compose/src/main/res/values/themes.xml b/compose/src/main/res/values/themes.xml deleted file mode 100644 index 0520a47e..00000000 --- a/compose/src/main/res/values/themes.xml +++ /dev/null @@ -1,25 +0,0 @@ - - - - - - - - - - - - - - - - - diff --git a/insights/src/test/java/com/algolia/insights/ExampleUnitTest.kt b/insights/src/test/java/com/algolia/insights/ExampleUnitTest.kt deleted file mode 100644 index 6cd3f020..00000000 --- a/insights/src/test/java/com/algolia/insights/ExampleUnitTest.kt +++ /dev/null @@ -1,17 +0,0 @@ -package com.algolia.insights - -import org.junit.Test - -import org.junit.Assert.* - -/** - * Example local unit test, which will execute on the development machine (host). - * - * See [testing documentation](http://d.android.com/tools/testing). - */ -class ExampleUnitTest { - @Test - fun addition_isCorrect() { - assertEquals(4, 2 + 2) - } -} \ No newline at end of file diff --git a/settings.gradle b/settings.gradle index f866e655..9ea8da11 100644 --- a/settings.gradle +++ b/settings.gradle @@ -1,4 +1,4 @@ -include ':showcase', ':showcase-compose', ':guides', ':insights', ':compose', +include ':showcase:android-view', ':showcase:compose', ':guides', ':exchange:query-suggestions', ':exchange:query-suggestions-hits', ':exchange:query-suggestions-recent', ':exchange:query-suggestions-categories', ':exchange:categories-hits', ':exchange:multi-index', ':exchange:voice-search' diff --git a/showcase-compose/src/main/res/drawable-v24/ic_launcher_foreground.xml b/showcase-compose/src/main/res/drawable-v24/ic_launcher_foreground.xml deleted file mode 100644 index 2b068d11..00000000 --- a/showcase-compose/src/main/res/drawable-v24/ic_launcher_foreground.xml +++ /dev/null @@ -1,30 +0,0 @@ - - - - - - - - - - - \ No newline at end of file diff --git a/showcase-compose/src/main/res/drawable/ic_launcher_background.xml b/showcase-compose/src/main/res/drawable/ic_launcher_background.xml deleted file mode 100644 index 07d5da9c..00000000 --- a/showcase-compose/src/main/res/drawable/ic_launcher_background.xml +++ /dev/null @@ -1,170 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/showcase-compose/src/main/res/mipmap-anydpi-v26/ic_launcher.xml b/showcase-compose/src/main/res/mipmap-anydpi-v26/ic_launcher.xml deleted file mode 100644 index eca70cfe..00000000 --- a/showcase-compose/src/main/res/mipmap-anydpi-v26/ic_launcher.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - - - \ No newline at end of file diff --git a/showcase-compose/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml b/showcase-compose/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml deleted file mode 100644 index eca70cfe..00000000 --- a/showcase-compose/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - - - \ No newline at end of file diff --git a/showcase-compose/src/main/res/mipmap-hdpi/ic_launcher.webp b/showcase-compose/src/main/res/mipmap-hdpi/ic_launcher.webp deleted file mode 100644 index c209e78ecd372343283f4157dcfd918ec5165bb3..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1404 zcmV-?1%vuhNk&F=1pok7MM6+kP&il$0000G0000-002h-06|PpNX!5L00Dqw+t%{r zzW2vH!KF=w&cMnnN@{whkTw+#mAh0SV?YL=)3MimFYCWp#fpdtz~8$hD5VPuQgtcN zXl<@<#Cme5f5yr2h%@8TWh?)bSK`O z^Z@d={gn7J{iyxL_y_%J|L>ep{dUxUP8a{byupH&!UNR*OutO~0{*T4q5R6@ApLF! z5{w?Z150gC7#>(VHFJZ-^6O@PYp{t!jH(_Z*nzTK4 zkc{fLE4Q3|mA2`CWQ3{8;gxGizgM!zccbdQoOLZc8hThi-IhN90RFT|zlxh3Ty&VG z?Fe{#9RrRnxzsu|Lg2ddugg7k%>0JeD+{XZ7>Z~{=|M+sh1MF7~ zz>To~`~LVQe1nNoR-gEzkpe{Ak^7{{ZBk2i_<+`Bq<^GB!RYG+z)h;Y3+<{zlMUYd zrd*W4w&jZ0%kBuDZ1EW&KLpyR7r2=}fF2%0VwHM4pUs}ZI2egi#DRMYZPek*^H9YK zay4Iy3WXFG(F14xYsoDA|KXgGc5%2DhmQ1gFCkrgHBm!lXG8I5h*uf{rn48Z!_@ z4Bk6TJAB2CKYqPjiX&mWoW>OPFGd$wqroa($ne7EUK;#3VYkXaew%Kh^3OrMhtjYN?XEoY`tRPQsAkH-DSL^QqyN0>^ zmC>{#F14jz4GeW{pJoRpLFa_*GI{?T93^rX7SPQgT@LbLqpNA}<@2wH;q493)G=1Y z#-sCiRNX~qf3KgiFzB3I>4Z%AfS(3$`-aMIBU+6?gbgDb!)L~A)je+;fR0jWLL-Fu z4)P{c7{B4Hp91&%??2$v9iRSFnuckHUm}or9seH6 z>%NbT+5*@L5(I9j@06@(!{ZI?U0=pKn8uwIg&L{JV14+8s2hnvbRrU|hZCd}IJu7*;;ECgO%8_*W Kmw_-CKmY()leWbG diff --git a/showcase-compose/src/main/res/mipmap-hdpi/ic_launcher_round.webp b/showcase-compose/src/main/res/mipmap-hdpi/ic_launcher_round.webp deleted file mode 100644 index b2dfe3d1ba5cf3ee31b3ecc1ced89044a1f3b7a9..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2898 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 diff --git a/showcase-compose/src/main/res/mipmap-mdpi/ic_launcher.webp b/showcase-compose/src/main/res/mipmap-mdpi/ic_launcher.webp deleted file mode 100644 index 4f0f1d64e58ba64d180ce43ee13bf9a17835fbca..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 982 zcmV;{11bDcNk&G_0{{S5MM6+kP&il$0000G0000l001ul06|PpNU8t;00Dqo+t#w^ z^1csucXz7-Qrhzl9HuHB%l>&>1tG2^vb*E&k^T3$FG1eQZ51g$uv4V+kI`0<^1Z@N zk?Jjh$olyC%l>)Xq;7!>{iBj&BjJ`P&$fsCfpve_epJOBkTF?nu-B7D!hO=2ZR}

C%4 zc_9eOXvPbC4kzU8YowIA8cW~Uv|eB&yYwAObSwL2vY~UYI7NXPvf3b+c^?wcs~_t{ ze_m66-0)^{JdOMKPwjpQ@Sna!*?$wTZ~su*tNv7o!gXT!GRgivP}ec?5>l1!7<(rT zds|8x(qGc673zrvYIz;J23FG{9nHMnAuP}NpAED^laz3mAN1sy+NXK)!6v1FxQ;lh zOBLA>$~P3r4b*NcqR;y6pwyhZ3_PiDb|%n1gGjl3ZU}ujInlP{eks-#oA6>rh&g+!f`hv#_%JrgYPu z(U^&XLW^QX7F9Z*SRPpQl{B%x)_AMp^}_v~?j7 zapvHMKxSf*Mtyx8I}-<*UGn3)oHd(nn=)BZ`d$lDBwq_GL($_TPaS{UeevT(AJ`p0 z9%+hQb6z)U9qjbuXjg|dExCLjpS8$VKQ55VsIC%@{N5t{NsW)=hNGI`J=x97_kbz@ E0Of=7!TQj4N+cqN`nQhxvX7dAV-`K|Ub$-q+H-5I?Tx0g9jWxd@A|?POE8`3b8fO$T))xP* z(X?&brZw({`)WU&rdAs1iTa0x6F@PIxJ&&L|dpySV!ID|iUhjCcKz(@mE z!x@~W#3H<)4Ae(4eQJRk`Iz3<1)6^m)0b_4_TRZ+cz#eD3f8V;2r-1fE!F}W zEi0MEkTTx}8i1{`l_6vo0(Vuh0HD$I4SjZ=?^?k82R51bC)2D_{y8mi_?X^=U?2|F{Vr7s!k(AZC$O#ZMyavHhlQ7 zUR~QXuH~#o#>(b$u4?s~HLF*3IcF7023AlwAYudn0FV~|odGH^05AYPEfR)8p`i{n zwg3zPVp{+wOsxKc>)(pMupKF!Y2HoUqQ3|Yu|8lwR=?5zZuhG6J?H`bSNk_wPoM{u zSL{c@pY7+c2kck>`^q1^^gR0QB7Y?KUD{vz-uVX~;V-rW)PDcI)$_UjgVV?S?=oLR zf4}zz{#*R_{LkiJ#0RdQLNC^2Vp%JPEUvG9ra2BVZ92(p9h7Ka@!yf9(lj#}>+|u* z;^_?KWdzkM`6gqPo9;;r6&JEa)}R3X{(CWv?NvgLeOTq$cZXqf7|sPImi-7cS8DCN zGf;DVt3Am`>hH3{4-WzH43Ftx)SofNe^-#|0HdCo<+8Qs!}TZP{HH8~z5n`ExcHuT zDL1m&|DVpIy=xsLO>8k92HcmfSKhflQ0H~9=^-{#!I1g(;+44xw~=* zxvNz35vfsQE)@)Zsp*6_GjYD};Squ83<_?^SbALb{a`j<0Gn%6JY!zhp=Fg}Ga2|8 z52e1WU%^L1}15Ex0fF$e@eCT(()_P zvV?CA%#Sy08_U6VPt4EtmVQraWJX` zh=N|WQ>LgrvF~R&qOfB$!%D3cGv?;Xh_z$z7k&s4N)$WYf*k=|*jCEkO19{h_(%W4 zPuOqbCw`SeAX*R}UUsbVsgtuG?xs(#Ikx9`JZoQFz0n*7ZG@Fv@kZk`gzO$HoA9kN z8U5{-yY zvV{`&WKU2$mZeoBmiJrEdzUZAv1sRxpePdg1)F*X^Y)zp^Y*R;;z~vOv-z&)&G)JQ{m!C9cmziu1^nHA z`#`0c>@PnQ9CJKgC5NjJD8HM3|KC(g5nnCq$n0Gsu_DXk36@ql%npEye|?%RmG)

FJ$wK}0tWNB{uH;AM~i diff --git a/showcase-compose/src/main/res/mipmap-xhdpi/ic_launcher.webp b/showcase-compose/src/main/res/mipmap-xhdpi/ic_launcher.webp deleted file mode 100644 index 948a3070fe34c611c42c0d3ad3013a0dce358be0..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1900 zcmV-y2b1_xNk&Fw2LJ$9MM6+kP&il$0000G0001A003VA06|PpNH75a00DqwTbm-~ zullQTcXxO9ki!OCRx^i?oR|n!<8G0=kI^!JSjFi-LL*`V;ET0H2IXfU0*i>o6o6Gy zRq6Ap5(_{XLdXcL-MzlN`ugSdZY_`jXhcENAu)N_0?GhF))9R;E`!bo9p?g?SRgw_ zEXHhFG$0{qYOqhdX<(wE4N@es3VIo$%il%6xP9gjiBri+2pI6aY4 zJbgh-Ud|V%3O!IcHKQx1FQH(_*TK;1>FQWbt^$K1zNn^cczkBs=QHCYZ8b&l!UV{K z{L0$KCf_&KR^}&2Fe|L&?1I7~pBENnCtCuH3sjcx6$c zwqkNkru);ie``q+_QI;IYLD9OV0ZxkuyBz|5<$1BH|vtey$> z5oto4=l-R-Aaq`Dk0}o9N0VrkqW_#;!u{!bJLDq%0092{Ghe=F;(kn} z+sQ@1=UlX30+2nWjkL$B^b!H2^QYO@iFc0{(-~yXj2TWz?VG{v`Jg zg}WyYnwGgn>{HFaG7E~pt=)sOO}*yd(UU-D(E&x{xKEl6OcU?pl)K%#U$dn1mDF19 zSw@l8G!GNFB3c3VVK0?uyqN&utT-D5%NM4g-3@Sii9tSXKtwce~uF zS&Jn746EW^wV~8zdQ1XC28~kXu8+Yo9p!<8h&(Q({J*4DBglPdpe4M_mD8AguZFn~ ztiuO~{6Bx?SfO~_ZV(GIboeR9~hAym{{fV|VM=77MxDrbW6`ujX z<3HF(>Zr;#*uCvC*bpoSr~C$h?_%nXps@A)=l_;({Fo#6Y1+Zv`!T5HB+)#^-Ud_; zBwftPN=d8Vx)*O1Mj+0oO=mZ+NVH*ptNDC-&zZ7Hwho6UQ#l-yNvc0Cm+2$$6YUk2D2t#vdZX-u3>-Be1u9gtTBiMB^xwWQ_rgvGpZ6(C@e23c!^K=>ai-Rqu zhqT`ZQof;9Bu!AD(i^PCbYV%yha9zuoKMp`U^z;3!+&d@Hud&_iy!O-$b9ZLcSRh? z)R|826w}TU!J#X6P%@Zh=La$I6zXa#h!B;{qfug}O%z@K{EZECu6zl)7CiNi%xti0 zB{OKfAj83~iJvmpTU|&q1^?^cIMn2RQ?jeSB95l}{DrEPTW{_gmU_pqTc)h@4T>~& zluq3)GM=xa(#^VU5}@FNqpc$?#SbVsX!~RH*5p0p@w z;~v{QMX0^bFT1!cXGM8K9FP+=9~-d~#TK#ZE{4umGT=;dfvWi?rYj;^l_Zxywze`W z^Cr{55U@*BalS}K%Czii_80e0#0#Zkhlij4-~I@}`-JFJ7$5{>LnoJSs??J8kWVl6|8A}RCGAu9^rAsfCE=2}tHwl93t0C?#+jMpvr7O3`2=tr{Hg$=HlnjVG^ewm|Js0J*kfPa6*GhtB>`fN!m#9J(sU!?(OSfzY*zS(FJ<-Vb zfAIg+`U)YaXv#sY(c--|X zEB+TVyZ%Ie4L$gi#Fc++`h6%vzsS$pjz9aLt+ZL(g;n$Dzy5=m=_TV(3H8^C{r0xd zp#a%}ht55dOq?yhwYPrtp-m1xXp;4X;)NhxxUpgP%XTLmO zcjaFva^}dP3$&sfFTIR_jC=2pHh9kpI@2(6V*GQo7Ws)`j)hd+tr@P~gR*2gO@+1? zG<`_tB+LJuF|SZ9tIec;h%}}6WClT`L>HSW?E{Hp1h^+mlbf_$9zA>!ug>NALJsO{ mU%z=YwVD?}XMya)Bp;vlyE5&E_6!fzx9pwrdz474!~g(M6R?N? diff --git a/showcase-compose/src/main/res/mipmap-xhdpi/ic_launcher_round.webp b/showcase-compose/src/main/res/mipmap-xhdpi/ic_launcher_round.webp deleted file mode 100644 index 1b9a6956b3acdc11f40ce2bb3f6efbd845cc243f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3918 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�(p-{x$&=IACIfoAR!za)F-^da-t3#0Dycnp zwO~NVXwXCl;jE<}>%@xz|=8fIJAB?>+E{7)|4l${4ngA3G|=r z2Dyv;VVWSgZx9Wj>qUjleGl3Ei9K4>h!(lPS%8VOG>Xu0%6VDz^O=bjJmuP7>DeUv zrbI}MlHB^^d?{zv6d=@_ZD2lg1&G7UjnVN{1}9WkaM3H~btX0GtSzB+tZ^qRgWo4m z!GmimlG$=wgXCnr6j@m<1gAL46#T~5Bnm=2{^@>|t&`9mkEPddj zAvG~@Tv~TAm2i%VW}R-g(Z0)z-Y|szHr@rk>4MAyG*Ma*7Yh#H7(!-5>DZ@8r;_dx z{prSe<>~099F8vsYd2xff7uAS%7{S)f(|@me3t2$iy&NEc7OUEchp@9A|X;;IA>8!oX+y(BKJ$EzV* znR$z;!L$s7uy@{OT~nG#B!NRraT8(X##Ho!0r_o@gg0CA-9H^;-uE&?$2$nHv_00o z%cbuUc-tCx$Uh&EZ4Nf4Zgqv)Y6>usG3>GeQnxx_Z6+PcbX-+ysbt1hQ`K1LDpOE? zrAhIZhSN9yVIAOa22gn577tbc&i3|3V8NWy&!tw##`}9*x}gtI^h1DzZRA>UuaJG) zaZ7j)dq!O}{?#8Y7~7i6fHh4{`pL?>-18|p!S75Y#^DM>-S3)vuZG+Q7l@ek zQP~#cBpWgg#mApc_sPYjpw8odQuRokmTkzcNl`^CcKB7e&;zViV;{Y{o^Y$%7i0m# z62%#1Lq!RC?}lK>%mp}T!3Xv;L*0v*>USLm``N%>w>@fwC+#T&Tx2bN4w(20JB}oU zuSa6v^kXi0xPs?pbaOHnyiqq6By1EZY9OZ^^QA>{q-Hsd&m`pbQ%8121aWG-F5xf zlZ%;B{;C>X19|`^_?dVyCq>n+41w7|!tUS!{9rHlbhX=SZO5CQ^;!Du_E7*`GiR^Q w)2!4MKjfSAeNo!9>IaV6aUZ*?W>} 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

UmY2RIYtNPVDpE$%vda+HD#3m z&VuXJ{BK&Qe+rBa7eq}Q(bq|tn(RrJAk|ztj2(i{d>nmQnM?;HF2k&9sA6up5tmjl z7lySlzMbifH17-m-Lwa_F&e7nOH?ESi3#ckR3tsM+jsck3`oG!uMS}|eAwVXv>}qxwq?QY%QJ0}r@^;fhuUA9W z*BVl>TGo&N004@xSiwDUXUvp51sVmqO3m)=B55aPwf@0=e}cN+$-BdKxY`YrT_4)0 z_d10#i44Q*rFr8MC>*)v$EJvz``(pb{e&*6k+b zsMz%($|1+8hn8c2?P(l@;Rb&CsZeYoCI3?2!LqjbwPXW3z4G$Qfj=cT5Yb%vY0(AX oeb?AaKtwrnc|$|zzw9vfvn^aJJ!zd)XFXqqy0000001=f@-~a#s diff --git a/showcase/.gitignore b/showcase/android-view/.gitignore similarity index 100% rename from showcase/.gitignore rename to showcase/android-view/.gitignore diff --git a/showcase/README.md b/showcase/android-view/README.md similarity index 100% rename from showcase/README.md rename to showcase/android-view/README.md diff --git a/showcase/build.gradle b/showcase/android-view/build.gradle similarity index 83% rename from showcase/build.gradle rename to showcase/android-view/build.gradle index ad939794..ee91d53c 100644 --- a/showcase/build.gradle +++ b/showcase/android-view/build.gradle @@ -1,6 +1,5 @@ apply plugin: 'com.android.application' apply plugin: 'kotlin-android' -apply plugin: 'kotlin-android-extensions' apply plugin: 'kotlinx-serialization' android { @@ -33,18 +32,23 @@ android { packagingOptions { exclude("META-INF/*.kotlin_module") } - sourceSets["main"].java.srcDir("src/main/kotlin") + buildFeatures { + viewBinding true + } } dependencies { + implementation "com.algolia:instantsearch-android:$instantsearch" + implementation "com.algolia:instantsearch-android-paging3:$instantsearch" + implementation "com.algolia:instantsearch-android-loading:$instantsearch" + implementation "androidx.lifecycle:lifecycle-extensions:$lifecycle_version" implementation "androidx.lifecycle:lifecycle-common-java8:$lifecycle_version" - implementation "androidx.constraintlayout:constraintlayout:2.0.4" - implementation "com.google.android.material:material:1.3.0" + implementation "androidx.constraintlayout:constraintlayout:2.1.2" + implementation "com.google.android.material:material:1.4.0" implementation "com.github.bumptech.glide:glide:4.10.0" - implementation "com.algolia:instantsearch-android:$instantsearch" implementation "io.apptik.widget:multislider:1.3" - implementation 'androidx.appcompat:appcompat:1.3.0' + implementation 'androidx.appcompat:appcompat:1.4.0' debugImplementation "com.squareup.leakcanary:leakcanary-android:$canary" testImplementation 'junit:junit:4.12' diff --git a/showcase/proguard-rules.pro b/showcase/android-view/proguard-rules.pro similarity index 100% rename from showcase/proguard-rules.pro rename to showcase/android-view/proguard-rules.pro diff --git a/showcase/src/main/AndroidManifest.xml b/showcase/android-view/src/main/AndroidManifest.xml similarity index 100% rename from showcase/src/main/AndroidManifest.xml rename to showcase/android-view/src/main/AndroidManifest.xml diff --git a/showcase/src/main/kotlin/com/algolia/instantsearch/showcase/Demo.kt b/showcase/android-view/src/main/kotlin/com/algolia/instantsearch/showcase/Demo.kt similarity index 81% rename from showcase/src/main/kotlin/com/algolia/instantsearch/showcase/Demo.kt rename to showcase/android-view/src/main/kotlin/com/algolia/instantsearch/showcase/Demo.kt index 700d2706..a35bd9ce 100644 --- a/showcase/src/main/kotlin/com/algolia/instantsearch/showcase/Demo.kt +++ b/showcase/android-view/src/main/kotlin/com/algolia/instantsearch/showcase/Demo.kt @@ -1,5 +1,6 @@ package com.algolia.instantsearch.showcase +import android.app.Activity import android.content.Context import android.content.Intent import android.graphics.Color @@ -12,7 +13,9 @@ import android.text.SpannedString import android.text.style.ForegroundColorSpan import android.text.style.ImageSpan import android.text.style.StyleSpan +import android.view.LayoutInflater import android.view.View +import android.view.ViewGroup import android.widget.AutoCompleteTextView import android.widget.TextView import androidx.appcompat.app.AppCompatActivity @@ -25,22 +28,21 @@ import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.RecyclerView import com.algolia.instantsearch.core.connection.ConnectionHandler import com.algolia.instantsearch.core.searcher.Searcher -import com.algolia.instantsearch.helper.android.filter.clear.FilterClearViewImpl -import com.algolia.instantsearch.helper.android.list.autoScrollToStart -import com.algolia.instantsearch.helper.android.searchbox.SearchBoxViewAppCompat -import com.algolia.instantsearch.helper.android.stats.StatsTextViewSpanned -import com.algolia.instantsearch.helper.filter.clear.FilterClearConnector -import com.algolia.instantsearch.helper.filter.clear.connectView -import com.algolia.instantsearch.helper.filter.state.FilterGroupID -import com.algolia.instantsearch.helper.filter.state.FilterState -import com.algolia.instantsearch.helper.filter.state.toFilterGroups -import com.algolia.instantsearch.helper.searchbox.SearchBoxConnector -import com.algolia.instantsearch.helper.searchbox.connectView -import com.algolia.instantsearch.helper.searcher.SearcherForFacets -import com.algolia.instantsearch.helper.searcher.SearcherSingleIndex -import com.algolia.instantsearch.helper.stats.StatsConnector -import com.algolia.instantsearch.helper.stats.StatsPresenter -import com.algolia.instantsearch.helper.stats.connectView +import com.algolia.instantsearch.android.filter.clear.FilterClearViewImpl +import com.algolia.instantsearch.android.list.autoScrollToStart +import com.algolia.instantsearch.android.searchbox.SearchBoxViewAppCompat +import com.algolia.instantsearch.android.stats.StatsTextViewSpanned +import com.algolia.instantsearch.filter.clear.FilterClearConnector +import com.algolia.instantsearch.filter.clear.connectView +import com.algolia.instantsearch.filter.state.FilterGroupID +import com.algolia.instantsearch.filter.state.FilterState +import com.algolia.instantsearch.filter.state.toFilterGroups +import com.algolia.instantsearch.searchbox.SearchBoxConnector +import com.algolia.instantsearch.searchbox.connectView +import com.algolia.instantsearch.searcher.IndexNameHolder +import com.algolia.instantsearch.stats.StatsConnector +import com.algolia.instantsearch.stats.StatsPresenter +import com.algolia.instantsearch.stats.connectView import com.algolia.search.client.ClientSearch import com.algolia.search.configuration.ConfigurationSearch import com.algolia.search.model.APIKey @@ -50,9 +52,10 @@ import com.algolia.search.model.IndexName import com.algolia.search.model.filter.Filter import com.algolia.search.model.filter.FilterGroup import com.algolia.search.model.filter.FilterGroupsConverter +import com.algolia.search.model.response.ResponseSearch import com.algolia.search.serialize.KeyIndexName import com.algolia.search.serialize.KeyName -import io.ktor.client.features.logging.LogLevel +import io.ktor.client.features.logging.* val client = ClientSearch( @@ -63,7 +66,8 @@ val client = ClientSearch( ) ) -val stubIndex = client.initIndex(IndexName("stub")) +val stubIndexName = IndexName("stub") +val stubIndex = client.initIndex(stubIndexName) fun AppCompatActivity.configureToolbar(toolbar: Toolbar) { setSupportActionBar(toolbar) @@ -106,7 +110,7 @@ fun AppCompatActivity.onClearAllThenClearFilters( } fun AppCompatActivity.onErrorThenUpdateFiltersText( - searcher: SearcherSingleIndex, + searcher: Searcher<*>, filtersTextView: TextView ) { searcher.error.subscribe { @@ -115,7 +119,7 @@ fun AppCompatActivity.onErrorThenUpdateFiltersText( } fun AppCompatActivity.onResponseChangedThenUpdateNbHits( - searcher: SearcherSingleIndex, + searcher: Searcher, nbHitsView: TextView, connection: ConnectionHandler ) { @@ -154,12 +158,12 @@ fun AppCompatActivity.configureTitle( } } -fun AppCompatActivity.configureSearcher(searcher: SearcherSingleIndex) { - searcher.index = client.initIndex(intent.indexName) +fun AppCompatActivity.configureSearcher(searcher: IndexNameHolder) { + searcher.indexName = intent.indexName } -fun AppCompatActivity.configureSearcher(searcher: SearcherForFacets) { - searcher.index = client.initIndex(intent.indexName) +fun Activity.configureSearcher(searcher: IndexNameHolder) { + searcher.indexName = intent.indexName } fun AppCompatActivity.configureRecyclerView( @@ -225,6 +229,8 @@ fun SearchView.showQueryHintIcon( fun Context.dip(value: Int): Int = (value * resources.displayMetrics.density).toInt() +val ViewGroup.layoutInflater: LayoutInflater get() = LayoutInflater.from(context) + public fun Set>.highlight( converter: FilterGroupsConverter>, String?> = FilterGroupsConverter.SQL.Unquoted, colors: Map = mapOf(), diff --git a/showcase/src/main/kotlin/com/algolia/instantsearch/showcase/customdata/Banner.kt b/showcase/android-view/src/main/kotlin/com/algolia/instantsearch/showcase/customdata/Banner.kt similarity index 100% rename from showcase/src/main/kotlin/com/algolia/instantsearch/showcase/customdata/Banner.kt rename to showcase/android-view/src/main/kotlin/com/algolia/instantsearch/showcase/customdata/Banner.kt diff --git a/showcase/src/main/kotlin/com/algolia/instantsearch/showcase/customdata/QueryRuleCustomDataShowcase.kt b/showcase/android-view/src/main/kotlin/com/algolia/instantsearch/showcase/customdata/QueryRuleCustomDataShowcase.kt similarity index 66% rename from showcase/src/main/kotlin/com/algolia/instantsearch/showcase/customdata/QueryRuleCustomDataShowcase.kt rename to showcase/android-view/src/main/kotlin/com/algolia/instantsearch/showcase/customdata/QueryRuleCustomDataShowcase.kt index ace3a45e..bbee3fbf 100644 --- a/showcase/src/main/kotlin/com/algolia/instantsearch/showcase/customdata/QueryRuleCustomDataShowcase.kt +++ b/showcase/android-view/src/main/kotlin/com/algolia/instantsearch/showcase/customdata/QueryRuleCustomDataShowcase.kt @@ -7,41 +7,39 @@ import android.view.View import androidx.appcompat.app.AppCompatActivity import com.algolia.instantsearch.core.connection.ConnectionHandler import com.algolia.instantsearch.core.hits.connectHitsView -import com.algolia.instantsearch.helper.android.searchbox.SearchBoxViewAppCompat -import com.algolia.instantsearch.helper.customdata.QueryRuleCustomDataConnector -import com.algolia.instantsearch.helper.searchbox.SearchBoxConnector -import com.algolia.instantsearch.helper.searchbox.SearchMode -import com.algolia.instantsearch.helper.searchbox.connectView -import com.algolia.instantsearch.helper.searcher.SearcherSingleIndex -import com.algolia.instantsearch.showcase.R -import com.algolia.instantsearch.showcase.configureRecyclerView -import com.algolia.instantsearch.showcase.configureSearchView -import com.algolia.instantsearch.showcase.configureSearcher -import com.algolia.instantsearch.showcase.configureToolbar +import com.algolia.instantsearch.android.searchbox.SearchBoxViewAppCompat +import com.algolia.instantsearch.customdata.QueryRuleCustomDataConnector +import com.algolia.instantsearch.searchbox.SearchBoxConnector +import com.algolia.instantsearch.searchbox.SearchMode +import com.algolia.instantsearch.searchbox.connectView +import com.algolia.instantsearch.searcher.hits.HitsSearcher +import com.algolia.instantsearch.showcase.* import com.algolia.instantsearch.showcase.customdata.TemplateActivity.Companion.EXTRA_CONTENT +import com.algolia.instantsearch.showcase.databinding.IncludeSearchInfoBinding +import com.algolia.instantsearch.showcase.databinding.ShowcaseQueryRuleCustomDataBinding import com.algolia.instantsearch.showcase.list.product.Product import com.algolia.instantsearch.showcase.list.product.ProductAdapter -import com.algolia.instantsearch.showcase.stubIndex import com.algolia.search.helper.deserialize import com.bumptech.glide.Glide import com.google.android.material.dialog.MaterialAlertDialogBuilder -import kotlinx.android.synthetic.main.include_search.searchView -import kotlinx.android.synthetic.main.include_search_info.* -import kotlinx.android.synthetic.main.showcase_query_rule_custom_data.* class QueryRuleCustomDataShowcase : AppCompatActivity() { - private val searcher = SearcherSingleIndex(stubIndex) + private val searcher = HitsSearcher(client, stubIndexName) private val searchBox = SearchBoxConnector(searcher, searchMode = SearchMode.AsYouType) private val queryRuleCustomData = QueryRuleCustomDataConnector(searcher) private val connection = ConnectionHandler(searchBox, queryRuleCustomData) + private lateinit var binding: ShowcaseQueryRuleCustomDataBinding + override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) - setContentView(R.layout.showcase_query_rule_custom_data) + binding = ShowcaseQueryRuleCustomDataBinding.inflate(layoutInflater) + setContentView(binding.root) + val searchBinding = IncludeSearchInfoBinding.bind(binding.searchBox.root) val adapter = ProductAdapter() - val searchBoxView = SearchBoxViewAppCompat(searchView) + val searchBoxView = SearchBoxViewAppCompat(searchBinding.searchView) connection += searchBox.connectView(searchBoxView) connection += searcher.connectHitsView(adapter) { response -> @@ -63,11 +61,11 @@ class QueryRuleCustomDataShowcase : AppCompatActivity() { } } - configureToolbar(toolbar) + configureToolbar(binding.toolbar) configureSearcher(searcher) - configureRecyclerView(hits, adapter) - configureSearchView(searchView, getString(R.string.search_products)) - configureHelp(info) + configureRecyclerView(binding.hits, adapter) + configureSearchView(searchBinding.searchView, getString(R.string.search_products)) + configureHelp(searchBinding.info) searcher.searchAsync() } @@ -79,21 +77,21 @@ class QueryRuleCustomDataShowcase : AppCompatActivity() { } private fun showBannerImage(model: Banner) { - bannerImage.visibility = View.VISIBLE + binding.bannerImage.visibility = View.VISIBLE Glide.with(this) .load(model.banner) .fitCenter() - .into(bannerImage) + .into(binding.bannerImage) - bannerImage.setOnClickListener { + binding.bannerImage.setOnClickListener { redirect(model.link, resources.getString(R.string.redirect_via_banner_tap)) } } private fun showBannerText(model: Banner) { - bannerText.visibility = View.VISIBLE - bannerText.text = model.title - bannerText.setOnClickListener { + binding.bannerText.visibility = View.VISIBLE + binding.bannerText.text = model.title + binding.bannerText.setOnClickListener { redirect(model.link, resources.getString(R.string.redirect_via_banner_tap)) } } @@ -107,8 +105,8 @@ class QueryRuleCustomDataShowcase : AppCompatActivity() { } private fun noBanner() { - bannerImage.reset() - bannerText.reset() + binding.bannerImage.reset() + binding.bannerText.reset() } private fun View.reset() { diff --git a/showcase/src/main/kotlin/com/algolia/instantsearch/showcase/customdata/TemplateActivity.kt b/showcase/android-view/src/main/kotlin/com/algolia/instantsearch/showcase/customdata/TemplateActivity.kt similarity index 67% rename from showcase/src/main/kotlin/com/algolia/instantsearch/showcase/customdata/TemplateActivity.kt rename to showcase/android-view/src/main/kotlin/com/algolia/instantsearch/showcase/customdata/TemplateActivity.kt index 3780ad96..d2cdb72a 100644 --- a/showcase/src/main/kotlin/com/algolia/instantsearch/showcase/customdata/TemplateActivity.kt +++ b/showcase/android-view/src/main/kotlin/com/algolia/instantsearch/showcase/customdata/TemplateActivity.kt @@ -3,21 +3,23 @@ package com.algolia.instantsearch.showcase.customdata import android.os.Bundle import android.view.MenuItem import androidx.appcompat.app.AppCompatActivity -import com.algolia.instantsearch.showcase.R -import kotlinx.android.synthetic.main.showcase_query_rule_custom_data_template.* +import com.algolia.instantsearch.showcase.databinding.ShowcaseQueryRuleCustomDataTemplateBinding class TemplateActivity : AppCompatActivity() { + private lateinit var binding: ShowcaseQueryRuleCustomDataTemplateBinding + override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) - setContentView(R.layout.showcase_query_rule_custom_data_template) + binding = ShowcaseQueryRuleCustomDataTemplateBinding.inflate(layoutInflater) + setContentView(binding.root) setupToolbar() val text = intent.getStringExtra(EXTRA_CONTENT) - content.text = text + binding.content.text = text } private fun setupToolbar() { - setSupportActionBar(toolbar) + setSupportActionBar(binding.toolbar) supportActionBar?.let { it.title = null it.setDisplayHomeAsUpEnabled(true) diff --git a/showcase/src/main/kotlin/com/algolia/instantsearch/showcase/directory/Directory.kt b/showcase/android-view/src/main/kotlin/com/algolia/instantsearch/showcase/directory/Directory.kt similarity index 100% rename from showcase/src/main/kotlin/com/algolia/instantsearch/showcase/directory/Directory.kt rename to showcase/android-view/src/main/kotlin/com/algolia/instantsearch/showcase/directory/Directory.kt diff --git a/showcase/src/main/kotlin/com/algolia/instantsearch/showcase/directory/DirectoryAdapter.kt b/showcase/android-view/src/main/kotlin/com/algolia/instantsearch/showcase/directory/DirectoryAdapter.kt similarity index 78% rename from showcase/src/main/kotlin/com/algolia/instantsearch/showcase/directory/DirectoryAdapter.kt rename to showcase/android-view/src/main/kotlin/com/algolia/instantsearch/showcase/directory/DirectoryAdapter.kt index f76c8fdd..8f7fc16f 100644 --- a/showcase/src/main/kotlin/com/algolia/instantsearch/showcase/directory/DirectoryAdapter.kt +++ b/showcase/android-view/src/main/kotlin/com/algolia/instantsearch/showcase/directory/DirectoryAdapter.kt @@ -7,7 +7,10 @@ import androidx.recyclerview.widget.DiffUtil import androidx.recyclerview.widget.ListAdapter import com.algolia.instantsearch.core.hits.HitsView import com.algolia.instantsearch.showcase.R -import com.algolia.instantsearch.helper.android.inflate +import com.algolia.instantsearch.android.inflate +import com.algolia.instantsearch.showcase.databinding.HeaderItemBinding +import com.algolia.instantsearch.showcase.databinding.ListItemSmallBinding +import com.algolia.instantsearch.showcase.layoutInflater class DirectoryAdapter : ListAdapter(diffUtil), HitsView { @@ -19,8 +22,12 @@ class DirectoryAdapter : ListAdapter(diffUti override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): DirectoryViewHolder { return when (ViewType.values()[viewType]) { - ViewType.Header -> DirectoryViewHolder.Header(parent.inflate(R.layout.header_item)) - ViewType.Item -> DirectoryViewHolder.Item(parent.inflate(R.layout.list_item_small)) + ViewType.Header -> DirectoryViewHolder.Header( + HeaderItemBinding.inflate(parent.layoutInflater, parent, false) + ) + ViewType.Item -> DirectoryViewHolder.Item( + ListItemSmallBinding.inflate(parent.layoutInflater, parent, false) + ) } } diff --git a/showcase/src/main/kotlin/com/algolia/instantsearch/showcase/directory/DirectoryHit.kt b/showcase/android-view/src/main/kotlin/com/algolia/instantsearch/showcase/directory/DirectoryHit.kt similarity index 90% rename from showcase/src/main/kotlin/com/algolia/instantsearch/showcase/directory/DirectoryHit.kt rename to showcase/android-view/src/main/kotlin/com/algolia/instantsearch/showcase/directory/DirectoryHit.kt index 0a1ab672..09bf96ae 100644 --- a/showcase/src/main/kotlin/com/algolia/instantsearch/showcase/directory/DirectoryHit.kt +++ b/showcase/android-view/src/main/kotlin/com/algolia/instantsearch/showcase/directory/DirectoryHit.kt @@ -1,6 +1,6 @@ package com.algolia.instantsearch.showcase.directory -import com.algolia.instantsearch.helper.highlighting.Highlightable +import com.algolia.instantsearch.highlighting.Highlightable import com.algolia.search.model.Attribute import com.algolia.search.model.ObjectID import com.algolia.search.model.indexing.Indexable diff --git a/showcase/src/main/kotlin/com/algolia/instantsearch/showcase/directory/DirectoryItem.kt b/showcase/android-view/src/main/kotlin/com/algolia/instantsearch/showcase/directory/DirectoryItem.kt similarity index 100% rename from showcase/src/main/kotlin/com/algolia/instantsearch/showcase/directory/DirectoryItem.kt rename to showcase/android-view/src/main/kotlin/com/algolia/instantsearch/showcase/directory/DirectoryItem.kt diff --git a/showcase/src/main/kotlin/com/algolia/instantsearch/showcase/directory/DirectoryShowcase.kt b/showcase/android-view/src/main/kotlin/com/algolia/instantsearch/showcase/directory/DirectoryShowcase.kt similarity index 57% rename from showcase/src/main/kotlin/com/algolia/instantsearch/showcase/directory/DirectoryShowcase.kt rename to showcase/android-view/src/main/kotlin/com/algolia/instantsearch/showcase/directory/DirectoryShowcase.kt index d04bfac1..2cc2afc1 100644 --- a/showcase/src/main/kotlin/com/algolia/instantsearch/showcase/directory/DirectoryShowcase.kt +++ b/showcase/android-view/src/main/kotlin/com/algolia/instantsearch/showcase/directory/DirectoryShowcase.kt @@ -4,25 +4,31 @@ import android.os.Bundle import androidx.appcompat.app.AppCompatActivity import com.algolia.instantsearch.core.connection.ConnectionHandler import com.algolia.instantsearch.core.hits.connectHitsView +import com.algolia.instantsearch.searcher.hits.HitsSearcher import com.algolia.instantsearch.showcase.* -import com.algolia.instantsearch.helper.searcher.SearcherSingleIndex +import com.algolia.instantsearch.showcase.databinding.IncludeSearchBinding +import com.algolia.instantsearch.showcase.databinding.ShowcaseDirectoryBinding import com.algolia.search.helper.deserialize import com.algolia.search.model.IndexName import com.algolia.search.model.search.Query -import kotlinx.android.synthetic.main.showcase_directory.* -import kotlinx.android.synthetic.main.include_search.* - class DirectoryShowcase : AppCompatActivity() { - private val index = client.initIndex(IndexName("mobile_demo_home")) - private val searcher = SearcherSingleIndex(index, Query(hitsPerPage = 100)) + private val searcher = HitsSearcher( + client = client, + indexName = IndexName("mobile_demo_home"), + query = Query(hitsPerPage = 100) + ) private val connection = ConnectionHandler() private val adapter = DirectoryAdapter() + private lateinit var binding: ShowcaseDirectoryBinding + override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) - setContentView(R.layout.showcase_directory) + binding = ShowcaseDirectoryBinding.inflate(layoutInflater) + setContentView(binding.root) + val searchBinding = IncludeSearchBinding.bind(binding.searchBox.root) connection += searcher.connectHitsView(adapter) { response -> @@ -31,13 +37,14 @@ class DirectoryShowcase : AppCompatActivity() { .groupBy { it.type } .toSortedMap() .flatMap { (key, value) -> - listOf(DirectoryItem.Header(key)) + value.map { DirectoryItem.Item(it) }.sortedBy { it.hit.objectID.raw } + listOf(DirectoryItem.Header(key)) + value.map { DirectoryItem.Item(it) } + .sortedBy { it.hit.objectID.raw } } } - configureRecyclerView(hits, adapter) - configureSearchView(searchView, getString(R.string.search_showcases)) - configureSearchBox(searchView, searcher, connection) + configureRecyclerView(binding.hits, adapter) + configureSearchView(searchBinding.searchView, getString(R.string.search_showcases)) + configureSearchBox(searchBinding.searchView, searcher, connection) searcher.searchAsync() } diff --git a/showcase/src/main/kotlin/com/algolia/instantsearch/showcase/directory/DirectoryViewHolder.kt b/showcase/android-view/src/main/kotlin/com/algolia/instantsearch/showcase/directory/DirectoryViewHolder.kt similarity index 53% rename from showcase/src/main/kotlin/com/algolia/instantsearch/showcase/directory/DirectoryViewHolder.kt rename to showcase/android-view/src/main/kotlin/com/algolia/instantsearch/showcase/directory/DirectoryViewHolder.kt index 581141cd..d115a5a6 100644 --- a/showcase/src/main/kotlin/com/algolia/instantsearch/showcase/directory/DirectoryViewHolder.kt +++ b/showcase/android-view/src/main/kotlin/com/algolia/instantsearch/showcase/directory/DirectoryViewHolder.kt @@ -2,31 +2,32 @@ package com.algolia.instantsearch.showcase.directory import android.content.Intent import android.view.View -import android.widget.TextView import androidx.recyclerview.widget.RecyclerView -import com.algolia.instantsearch.helper.android.highlighting.toSpannedString +import com.algolia.instantsearch.android.highlighting.toSpannedString +import com.algolia.instantsearch.showcase.databinding.HeaderItemBinding +import com.algolia.instantsearch.showcase.databinding.ListItemSmallBinding import com.algolia.search.serialize.KeyIndexName import com.algolia.search.serialize.KeyName -import kotlinx.android.synthetic.main.list_item_small.view.* - sealed class DirectoryViewHolder(view: View) : RecyclerView.ViewHolder(view) { - data class Header(val view: TextView) : DirectoryViewHolder(view) { + data class Header(private val binding: HeaderItemBinding) : DirectoryViewHolder(binding.root) { fun bind(item: DirectoryItem.Header) { - view.text = item.name + binding.root.text = item.name } } - data class Item(val view: View) : DirectoryViewHolder(view) { + data class Item(private val binding: ListItemSmallBinding) : DirectoryViewHolder(binding.root) { fun bind(item: DirectoryItem.Item) { val text = item.hit.highlightedName?.toSpannedString() ?: item.hit.name + val view = binding.root - view.itemName.text = text + binding.itemName.text = text view.setOnClickListener { - val intent = Intent(view.context, showcases.getValue(item.hit.objectID).java).apply { + val showcase = showcases.getValue(item.hit.objectID).java + val intent = Intent(view.context, showcase).apply { putExtra(KeyIndexName, item.hit.index) putExtra(KeyName, item.hit.name) } @@ -35,4 +36,4 @@ sealed class DirectoryViewHolder(view: View) : RecyclerView.ViewHolder(view) { } } } -} \ No newline at end of file +} diff --git a/showcase/android-view/src/main/kotlin/com/algolia/instantsearch/showcase/filter/clear/FilterClearShowcase.kt b/showcase/android-view/src/main/kotlin/com/algolia/instantsearch/showcase/filter/clear/FilterClearShowcase.kt new file mode 100644 index 00000000..f1f5a3d0 --- /dev/null +++ b/showcase/android-view/src/main/kotlin/com/algolia/instantsearch/showcase/filter/clear/FilterClearShowcase.kt @@ -0,0 +1,75 @@ +package com.algolia.instantsearch.showcase.filter.clear + +import android.os.Bundle +import androidx.appcompat.app.AppCompatActivity +import com.algolia.instantsearch.core.connection.ConnectionHandler +import com.algolia.instantsearch.android.filter.clear.FilterClearViewImpl +import com.algolia.instantsearch.filter.clear.ClearMode +import com.algolia.instantsearch.filter.clear.FilterClearConnector +import com.algolia.instantsearch.filter.clear.connectView +import com.algolia.instantsearch.filter.state.FilterState +import com.algolia.instantsearch.filter.state.filters +import com.algolia.instantsearch.filter.state.groupOr +import com.algolia.instantsearch.searcher.connectFilterState +import com.algolia.instantsearch.searcher.hits.HitsSearcher +import com.algolia.instantsearch.showcase.* +import com.algolia.instantsearch.showcase.databinding.HeaderFilterBinding +import com.algolia.instantsearch.showcase.databinding.ShowcaseFilterClearBinding +import com.algolia.search.model.Attribute + +class FilterClearShowcase : AppCompatActivity() { + + private val color = Attribute("color") + private val category = Attribute("category") + private val groupColor = groupOr(color) + private val groupCategory = groupOr(category) + private val filters = filters { + group(groupColor) { + facet(color, "red") + facet(color, "green") + } + group(groupCategory) { + facet(category, "shoe") + } + } + private val filterState = FilterState(filters) + private val searcher = HitsSearcher(client, stubIndexName) + private val clearAll = FilterClearConnector(filterState) + private val clearSpecified = + FilterClearConnector(filterState, listOf(groupColor), ClearMode.Specified) + private val clearExcept = + FilterClearConnector(filterState, listOf(groupColor), ClearMode.Except) + private val connection = ConnectionHandler( + clearSpecified, + clearExcept, + searcher.connectFilterState(filterState) + ) + + private lateinit var binding: ShowcaseFilterClearBinding + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + binding = ShowcaseFilterClearBinding.inflate(layoutInflater) + setContentView(binding.root) + val headerBinding = HeaderFilterBinding.bind(binding.headerFilter.root) + + connection += clearAll.connectView(FilterClearViewImpl(headerBinding.filtersClearAll)) + connection += clearSpecified.connectView(FilterClearViewImpl(binding.buttonClearSpecified)) + connection += clearExcept.connectView(FilterClearViewImpl(binding.buttonClearExcept)) + + configureToolbar(binding.toolbar) + configureSearcher(searcher) + onFilterChangedThenUpdateFiltersText(filterState, headerBinding.filtersTextView, color, category) + onErrorThenUpdateFiltersText(searcher, headerBinding.filtersTextView) + onResponseChangedThenUpdateNbHits(searcher, headerBinding.nbHits, connection) + onResetThenRestoreFilters(binding.reset, filterState, filters) + + searcher.searchAsync() + } + + override fun onDestroy() { + super.onDestroy() + searcher.cancel() + connection.clear() + } +} diff --git a/showcase/src/main/kotlin/com/algolia/instantsearch/showcase/filter/current/ShowcaseFilterCurrent.kt b/showcase/android-view/src/main/kotlin/com/algolia/instantsearch/showcase/filter/current/ShowcaseFilterCurrent.kt similarity index 53% rename from showcase/src/main/kotlin/com/algolia/instantsearch/showcase/filter/current/ShowcaseFilterCurrent.kt rename to showcase/android-view/src/main/kotlin/com/algolia/instantsearch/showcase/filter/current/ShowcaseFilterCurrent.kt index 0bbcfd33..ffee4957 100644 --- a/showcase/src/main/kotlin/com/algolia/instantsearch/showcase/filter/current/ShowcaseFilterCurrent.kt +++ b/showcase/android-view/src/main/kotlin/com/algolia/instantsearch/showcase/filter/current/ShowcaseFilterCurrent.kt @@ -4,19 +4,18 @@ import android.os.Bundle import androidx.appcompat.app.AppCompatActivity import com.algolia.instantsearch.core.connection.ConnectionHandler import com.algolia.instantsearch.showcase.* -import com.algolia.instantsearch.helper.android.filter.current.FilterCurrentViewImpl -import com.algolia.instantsearch.helper.filter.current.FilterCurrentConnector -import com.algolia.instantsearch.helper.filter.current.connectView -import com.algolia.instantsearch.helper.filter.state.FilterGroupID -import com.algolia.instantsearch.helper.filter.state.FilterState -import com.algolia.instantsearch.helper.filter.state.filters -import com.algolia.instantsearch.helper.searcher.SearcherSingleIndex -import com.algolia.instantsearch.helper.searcher.connectFilterState +import com.algolia.instantsearch.android.filter.current.FilterCurrentViewImpl +import com.algolia.instantsearch.filter.current.FilterCurrentConnector +import com.algolia.instantsearch.filter.current.connectView +import com.algolia.instantsearch.filter.state.FilterGroupID +import com.algolia.instantsearch.filter.state.FilterState +import com.algolia.instantsearch.filter.state.filters +import com.algolia.instantsearch.searcher.connectFilterState +import com.algolia.instantsearch.searcher.hits.HitsSearcher +import com.algolia.instantsearch.showcase.databinding.HeaderFilterBinding +import com.algolia.instantsearch.showcase.databinding.ShowcaseFilterCurrentBinding import com.algolia.search.model.Attribute import com.algolia.search.model.filter.NumericOperator -import kotlinx.android.synthetic.main.showcase_filter_current.* -import kotlinx.android.synthetic.main.header_filter.* - class ShowcaseFilterCurrent : AppCompatActivity() { @@ -40,7 +39,7 @@ class ShowcaseFilterCurrent : AppCompatActivity() { } } private val filterState = FilterState(filters) - private val searcher = SearcherSingleIndex(stubIndex) + private val searcher = HitsSearcher(client, stubIndexName) private val currentFiltersColor = FilterCurrentConnector(filterState, listOf(groupColor)) private val currentFiltersAll = FilterCurrentConnector(filterState) private val connection = ConnectionHandler( @@ -49,20 +48,24 @@ class ShowcaseFilterCurrent : AppCompatActivity() { searcher.connectFilterState(filterState) ) + private lateinit var binding: ShowcaseFilterCurrentBinding + override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) - setContentView(R.layout.showcase_filter_current) + binding = ShowcaseFilterCurrentBinding.inflate(layoutInflater) + setContentView(binding.root) + val headerBinding = HeaderFilterBinding.bind(binding.headerFilter.root) - connection += currentFiltersAll.connectView(FilterCurrentViewImpl(chipGroupAll, R.layout.filter_chip)) - connection += currentFiltersColor.connectView(FilterCurrentViewImpl(chipGroupColors, R.layout.filter_chip)) + connection += currentFiltersAll.connectView(FilterCurrentViewImpl(binding.chipGroupAll, R.layout.filter_chip)) + connection += currentFiltersColor.connectView(FilterCurrentViewImpl(binding.chipGroupColors, R.layout.filter_chip)) configureSearcher(searcher) - configureToolbar(toolbar) - onFilterChangedThenUpdateFiltersText(filterState, filtersTextView, color, price, tags) - onErrorThenUpdateFiltersText(searcher, filtersTextView) - onResponseChangedThenUpdateNbHits(searcher, nbHits, connection) - onClearAllThenClearFilters(filterState, filtersClearAll, connection) - onResetThenRestoreFilters(reset, filterState, filters) + configureToolbar(binding.toolbar) + onResetThenRestoreFilters(binding.reset, filterState, filters) + onFilterChangedThenUpdateFiltersText(filterState, headerBinding.filtersTextView, color, price, tags) + onErrorThenUpdateFiltersText(searcher, headerBinding.filtersTextView) + onResponseChangedThenUpdateNbHits(searcher, headerBinding.nbHits, connection) + onClearAllThenClearFilters(filterState, headerBinding.filtersClearAll, connection) searcher.searchAsync() } @@ -72,4 +75,4 @@ class ShowcaseFilterCurrent : AppCompatActivity() { searcher.cancel() connection.clear() } -} \ No newline at end of file +} diff --git a/showcase/android-view/src/main/kotlin/com/algolia/instantsearch/showcase/filter/facet/FacetListPersistentShowcase.kt b/showcase/android-view/src/main/kotlin/com/algolia/instantsearch/showcase/filter/facet/FacetListPersistentShowcase.kt new file mode 100644 index 00000000..8555af67 --- /dev/null +++ b/showcase/android-view/src/main/kotlin/com/algolia/instantsearch/showcase/filter/facet/FacetListPersistentShowcase.kt @@ -0,0 +1,81 @@ +package com.algolia.instantsearch.showcase.filter.facet + +import android.os.Bundle +import androidx.appcompat.app.AppCompatActivity +import com.algolia.instantsearch.core.connection.ConnectionHandler +import com.algolia.instantsearch.core.selectable.list.SelectionMode +import com.algolia.instantsearch.android.filter.facet.FacetListAdapter +import com.algolia.instantsearch.filter.facet.FacetListConnector +import com.algolia.instantsearch.filter.facet.connectView +import com.algolia.instantsearch.filter.state.FilterState +import com.algolia.instantsearch.searcher.connectFilterState +import com.algolia.instantsearch.searcher.hits.HitsSearcher +import com.algolia.instantsearch.showcase.* +import com.algolia.instantsearch.showcase.databinding.HeaderFilterBinding +import com.algolia.instantsearch.showcase.databinding.IncludeListBinding +import com.algolia.instantsearch.showcase.databinding.IncludeSearchBinding +import com.algolia.instantsearch.showcase.databinding.ShowcaseFacetListPersistentBinding +import com.algolia.search.model.Attribute + +class FacetListPersistentShowcase : AppCompatActivity() { + + private val color = Attribute("color") + private val category = Attribute("category") + private val filterState = FilterState() + private val searcher = HitsSearcher(client, stubIndexName) + private val facetListColor = FacetListConnector( + searcher = searcher, + filterState = filterState, + attribute = color, + selectionMode = SelectionMode.Multiple, + persistentSelection = true + ) + private val facetListCategory = FacetListConnector( + searcher = searcher, + filterState = filterState, + attribute = category, + selectionMode = SelectionMode.Single, + persistentSelection = true + ) + private val connection = ConnectionHandler( + facetListColor, + facetListCategory, + searcher.connectFilterState(filterState) + ) + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + val binding = ShowcaseFacetListPersistentBinding.inflate(layoutInflater) + val searchBinding = IncludeSearchBinding.bind(binding.searchBox.root) + val listBinding = IncludeListBinding.bind(binding.list.root) + val headerBinding = HeaderFilterBinding.bind(listBinding.headerFilter.root) + setContentView(binding.root) + + val adapterColor = FacetListAdapter(FacetListViewHolderImpl.Factory) + val adapterCategory = FacetListAdapter(FacetListViewHolderImpl.Factory) + + connection += facetListColor.connectView(adapterColor) + connection += facetListCategory.connectView(adapterCategory) + + configureToolbar(binding.toolbar) + configureSearcher(searcher) + configureSearchBox(searchBinding.searchView, searcher, connection) + configureSearchView(searchBinding.searchView, getString(R.string.search_items)) + configureRecyclerView(listBinding.listTopLeft, adapterColor) + configureRecyclerView(listBinding.listTopRight, adapterCategory) + configureTitle(listBinding.titleTopLeft, getString(R.string.multiple_choice)) + configureTitle(listBinding.titleTopRight, getString(R.string.single_choice)) + onFilterChangedThenUpdateFiltersText(filterState, headerBinding.filtersTextView, color, category) + onClearAllThenClearFilters(filterState, headerBinding.filtersClearAll, connection) + onErrorThenUpdateFiltersText(searcher, headerBinding.filtersTextView) + onResponseChangedThenUpdateNbHits(searcher, headerBinding.nbHits, connection) + + searcher.searchAsync() + } + + override fun onDestroy() { + super.onDestroy() + searcher.cancel() + connection.clear() + } +} \ No newline at end of file diff --git a/showcase/android-view/src/main/kotlin/com/algolia/instantsearch/showcase/filter/facet/FacetListSearchShowcase.kt b/showcase/android-view/src/main/kotlin/com/algolia/instantsearch/showcase/filter/facet/FacetListSearchShowcase.kt new file mode 100644 index 00000000..6cfbe582 --- /dev/null +++ b/showcase/android-view/src/main/kotlin/com/algolia/instantsearch/showcase/filter/facet/FacetListSearchShowcase.kt @@ -0,0 +1,81 @@ +package com.algolia.instantsearch.showcase.filter.facet + +import android.os.Bundle +import androidx.appcompat.app.AppCompatActivity +import com.algolia.instantsearch.core.connection.ConnectionHandler +import com.algolia.instantsearch.core.selectable.list.SelectionMode +import com.algolia.instantsearch.showcase.* +import com.algolia.instantsearch.android.filter.facet.FacetListAdapter +import com.algolia.instantsearch.android.searchbox.SearchBoxViewAppCompat +import com.algolia.instantsearch.filter.facet.FacetListConnector +import com.algolia.instantsearch.filter.facet.FacetListPresenterImpl +import com.algolia.instantsearch.filter.facet.FacetSortCriterion +import com.algolia.instantsearch.filter.facet.connectView +import com.algolia.instantsearch.filter.state.FilterState +import com.algolia.instantsearch.searchbox.SearchBoxConnector +import com.algolia.instantsearch.searchbox.connectView +import com.algolia.instantsearch.searcher.connectFilterState +import com.algolia.instantsearch.searcher.facets.FacetsSearcher +import com.algolia.instantsearch.searcher.hits.HitsSearcher +import com.algolia.instantsearch.showcase.databinding.HeaderFilterBinding +import com.algolia.instantsearch.showcase.databinding.IncludeSearchBinding +import com.algolia.instantsearch.showcase.databinding.ShowcaseFacetListSearchBinding +import com.algolia.search.model.Attribute + +class FacetListSearchShowcase : AppCompatActivity() { + + private val brand = Attribute("brand") + private val filterState = FilterState() + private val searcher = HitsSearcher(client, stubIndexName) + private val searcherForFacet = FacetsSearcher(client, stubIndexName, brand) + private val searchBox = SearchBoxConnector(searcherForFacet) + private val facetList = FacetListConnector( + searcher = searcherForFacet, + filterState = filterState, + attribute = brand, + selectionMode = SelectionMode.Multiple + ) + private val connection = ConnectionHandler( + searchBox, + facetList, + searcher.connectFilterState(filterState) + ) + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + val binding = ShowcaseFacetListSearchBinding.inflate(layoutInflater) + val searchBinding = IncludeSearchBinding.bind(binding.searchBox.root) + val headerBinding = HeaderFilterBinding.bind(binding.headerFilter.root) + setContentView(binding.root) + + val searchBoxView = SearchBoxViewAppCompat(searchBinding.searchView) + val facetView = FacetListAdapter(FacetListViewHolderImpl.Factory) + val facetPresenter = FacetListPresenterImpl( + sortBy = listOf(FacetSortCriterion.IsRefined, FacetSortCriterion.CountDescending), + limit = 100 + ) + + configureSearcher(searcher) + configureSearcher(searcherForFacet) + + connection += facetList.connectView(facetView, facetPresenter) + connection += searchBox.connectView(searchBoxView) + + configureToolbar(binding.toolbar) + configureRecyclerView(binding.hits, facetView) + configureSearchView(searchBinding.searchView, getString(R.string.search_brands)) + onFilterChangedThenUpdateFiltersText(filterState, headerBinding.filtersTextView, brand) + onClearAllThenClearFilters(filterState, headerBinding.filtersClearAll, connection) + onResponseChangedThenUpdateNbHits(searcher, headerBinding.nbHits, connection) + + searcher.searchAsync() + searcherForFacet.searchAsync() + } + + override fun onDestroy() { + super.onDestroy() + searcher.cancel() + searcherForFacet.cancel() + connection.clear() + } +} diff --git a/showcase/src/main/kotlin/com/algolia/instantsearch/showcase/filter/facet/FacetListShowcase.kt b/showcase/android-view/src/main/kotlin/com/algolia/instantsearch/showcase/filter/facet/FacetListShowcase.kt similarity index 63% rename from showcase/src/main/kotlin/com/algolia/instantsearch/showcase/filter/facet/FacetListShowcase.kt rename to showcase/android-view/src/main/kotlin/com/algolia/instantsearch/showcase/filter/facet/FacetListShowcase.kt index 246a3847..c949dd81 100644 --- a/showcase/src/main/kotlin/com/algolia/instantsearch/showcase/filter/facet/FacetListShowcase.kt +++ b/showcase/android-view/src/main/kotlin/com/algolia/instantsearch/showcase/filter/facet/FacetListShowcase.kt @@ -5,20 +5,19 @@ import androidx.appcompat.app.AppCompatActivity import com.algolia.instantsearch.core.connection.ConnectionHandler import com.algolia.instantsearch.core.selectable.list.SelectionMode import com.algolia.instantsearch.showcase.* -import com.algolia.instantsearch.helper.android.filter.facet.FacetListAdapter -import com.algolia.instantsearch.helper.filter.facet.FacetListConnector -import com.algolia.instantsearch.helper.filter.facet.FacetListPresenterImpl -import com.algolia.instantsearch.helper.filter.facet.FacetSortCriterion -import com.algolia.instantsearch.helper.filter.facet.FacetSortCriterion.* -import com.algolia.instantsearch.helper.filter.facet.connectView -import com.algolia.instantsearch.helper.filter.state.* -import com.algolia.instantsearch.helper.searcher.SearcherSingleIndex -import com.algolia.instantsearch.helper.searcher.connectFilterState +import com.algolia.instantsearch.android.filter.facet.FacetListAdapter +import com.algolia.instantsearch.filter.facet.FacetListConnector +import com.algolia.instantsearch.filter.facet.FacetListPresenterImpl +import com.algolia.instantsearch.filter.facet.FacetSortCriterion +import com.algolia.instantsearch.filter.facet.FacetSortCriterion.* +import com.algolia.instantsearch.filter.facet.connectView +import com.algolia.instantsearch.filter.state.* +import com.algolia.instantsearch.searcher.connectFilterState +import com.algolia.instantsearch.searcher.hits.HitsSearcher +import com.algolia.instantsearch.showcase.databinding.HeaderFilterBinding +import com.algolia.instantsearch.showcase.databinding.IncludeListBinding +import com.algolia.instantsearch.showcase.databinding.ShowcaseFacetListBinding import com.algolia.search.model.Attribute -import kotlinx.android.synthetic.main.showcase_facet_list.* -import kotlinx.android.synthetic.main.header_filter.* -import kotlinx.android.synthetic.main.include_list.* - class FacetListShowcase : AppCompatActivity() { @@ -29,7 +28,7 @@ class FacetListShowcase : AppCompatActivity() { private val groupPromotions = groupAnd(promotions) private val groupCategory = groupOr(category) private val filterState = filterState { group(groupColor) { facet(color, "green") } } - private val searcher = SearcherSingleIndex(stubIndex) + private val searcher = HitsSearcher(client, stubIndexName) private val facetListColor = FacetListConnector( searcher = searcher, filterState = filterState, @@ -66,24 +65,27 @@ class FacetListShowcase : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) - setContentView(R.layout.showcase_facet_list) + val binding = ShowcaseFacetListBinding.inflate(layoutInflater) + val listBinding = IncludeListBinding.bind(binding.list.root) + val headerBinding = HeaderFilterBinding.bind(listBinding.headerFilter.root) + setContentView(binding.root) connection += facetListColor.connectView(colorAdapter, colorPresenter) connection += facetListPromotions.connectView(promotionAdapter, promotionPresenter) connection += facetListCategory.connectView(categoryAdapter, categoryPresenter) - configureToolbar(toolbar) + configureToolbar(binding.toolbar) configureSearcher(searcher) - configureRecyclerView(listTopLeft, colorAdapter) - configureRecyclerView(listTopRight, categoryAdapter) - configureRecyclerView(listBottomLeft, promotionAdapter) - configureTitle(titleTopLeft, formatTitle(colorPresenter, groupColor)) - configureTitle(titleTopRight, formatTitle(categoryPresenter, groupCategory)) - configureTitle(titleBottomLeft, formatTitle(promotionPresenter, groupPromotions)) - onFilterChangedThenUpdateFiltersText(filterState, filtersTextView, color, promotions, category) - onClearAllThenClearFilters(filterState, filtersClearAll, connection) - onErrorThenUpdateFiltersText(searcher, filtersTextView) - onResponseChangedThenUpdateNbHits(searcher, nbHits, connection) + configureRecyclerView(listBinding.listTopLeft, colorAdapter) + configureRecyclerView(listBinding.listTopRight, categoryAdapter) + configureRecyclerView(listBinding.listBottomLeft, promotionAdapter) + configureTitle(listBinding.titleTopLeft, formatTitle(colorPresenter, groupColor)) + configureTitle(listBinding.titleTopRight, formatTitle(categoryPresenter, groupCategory)) + configureTitle(listBinding.titleBottomLeft, formatTitle(promotionPresenter, groupPromotions)) + onFilterChangedThenUpdateFiltersText(filterState, headerBinding.filtersTextView, color, promotions, category) + onClearAllThenClearFilters(filterState, headerBinding.filtersClearAll, connection) + onErrorThenUpdateFiltersText(searcher, headerBinding.filtersTextView) + onResponseChangedThenUpdateNbHits(searcher, headerBinding.nbHits, connection) searcher.searchAsync() } diff --git a/showcase/android-view/src/main/kotlin/com/algolia/instantsearch/showcase/filter/facet/FacetListViewHolderImpl.kt b/showcase/android-view/src/main/kotlin/com/algolia/instantsearch/showcase/filter/facet/FacetListViewHolderImpl.kt new file mode 100644 index 00000000..9ceb4638 --- /dev/null +++ b/showcase/android-view/src/main/kotlin/com/algolia/instantsearch/showcase/filter/facet/FacetListViewHolderImpl.kt @@ -0,0 +1,33 @@ +package com.algolia.instantsearch.showcase.filter.facet + +import android.view.View +import android.view.ViewGroup +import com.algolia.instantsearch.core.highlighting.HighlightTokenizer +import com.algolia.instantsearch.android.filter.facet.FacetListViewHolder +import com.algolia.instantsearch.android.highlighting.toSpannedString +import com.algolia.instantsearch.showcase.databinding.ListItemSelectableBinding +import com.algolia.instantsearch.showcase.layoutInflater +import com.algolia.search.model.search.Facet + +class FacetListViewHolderImpl(private val binding: ListItemSelectableBinding) : + FacetListViewHolder(binding.root) { + + override fun bind(facet: Facet, selected: Boolean, onClickListener: View.OnClickListener) { + binding.root.setOnClickListener(onClickListener) + binding.selectableItemSubtitle.text = facet.count.toString() + binding.selectableItemSubtitle.visibility = View.VISIBLE + binding.selectableItemIcon.visibility = if (selected) View.VISIBLE else View.INVISIBLE + binding.selectableItemName.text = facet.highlightedOrNull?.let { + HighlightTokenizer(preTag = "", postTag = "")(it).toSpannedString() + } ?: facet.value + } + + object Factory : FacetListViewHolder.Factory { + + override fun createViewHolder(parent: ViewGroup): FacetListViewHolder { + return FacetListViewHolderImpl( + ListItemSelectableBinding.inflate(parent.layoutInflater, parent, false) + ) + } + } +} diff --git a/showcase/src/main/kotlin/com/algolia/instantsearch/showcase/filter/facet/dynamic/DynamicFacetShowcase.kt b/showcase/android-view/src/main/kotlin/com/algolia/instantsearch/showcase/filter/facet/dynamic/DynamicFacetShowcase.kt similarity index 64% rename from showcase/src/main/kotlin/com/algolia/instantsearch/showcase/filter/facet/dynamic/DynamicFacetShowcase.kt rename to showcase/android-view/src/main/kotlin/com/algolia/instantsearch/showcase/filter/facet/dynamic/DynamicFacetShowcase.kt index 0eb1bd3e..329a6321 100644 --- a/showcase/src/main/kotlin/com/algolia/instantsearch/showcase/filter/facet/dynamic/DynamicFacetShowcase.kt +++ b/showcase/android-view/src/main/kotlin/com/algolia/instantsearch/showcase/filter/facet/dynamic/DynamicFacetShowcase.kt @@ -4,28 +4,27 @@ import android.os.Bundle import androidx.appcompat.app.AppCompatActivity import com.algolia.instantsearch.core.connection.ConnectionHandler import com.algolia.instantsearch.core.selectable.list.SelectionMode -import com.algolia.instantsearch.helper.android.filter.facet.dynamic.DynamicFacetListAdapter -import com.algolia.instantsearch.helper.android.searchbox.SearchBoxViewAppCompat -import com.algolia.instantsearch.helper.filter.facet.dynamic.DynamicFacetListConnector -import com.algolia.instantsearch.helper.filter.facet.dynamic.connectView -import com.algolia.instantsearch.helper.filter.state.FilterOperator -import com.algolia.instantsearch.helper.filter.state.FilterState -import com.algolia.instantsearch.helper.searchbox.SearchBoxConnector -import com.algolia.instantsearch.helper.searchbox.connectView -import com.algolia.instantsearch.helper.searcher.SearcherSingleIndex -import com.algolia.instantsearch.helper.searcher.connectFilterState +import com.algolia.instantsearch.android.filter.facet.dynamic.DynamicFacetListAdapter +import com.algolia.instantsearch.android.searchbox.SearchBoxViewAppCompat +import com.algolia.instantsearch.filter.facet.dynamic.DynamicFacetListConnector +import com.algolia.instantsearch.filter.facet.dynamic.connectView +import com.algolia.instantsearch.filter.state.FilterOperator +import com.algolia.instantsearch.filter.state.FilterState +import com.algolia.instantsearch.searchbox.SearchBoxConnector +import com.algolia.instantsearch.searchbox.connectView +import com.algolia.instantsearch.searcher.hits.HitsSearcher import com.algolia.instantsearch.showcase.R import com.algolia.instantsearch.showcase.configureRecyclerView import com.algolia.instantsearch.showcase.configureSearchView import com.algolia.instantsearch.showcase.configureToolbar +import com.algolia.instantsearch.showcase.databinding.IncludeSearchBinding +import com.algolia.instantsearch.showcase.databinding.ShowcaseDynamicFacetListBinding import com.algolia.search.client.ClientSearch import com.algolia.search.model.APIKey import com.algolia.search.model.ApplicationID import com.algolia.search.model.Attribute import com.algolia.search.model.IndexName import io.ktor.client.features.logging.* -import kotlinx.android.synthetic.main.include_search.* -import kotlinx.android.synthetic.main.showcase_facet_list_search.* class DynamicFacetShowcase : AppCompatActivity() { @@ -34,8 +33,7 @@ class DynamicFacetShowcase : AppCompatActivity() { APIKey("937e4e6ec422ff69fe89b569dba30180"), LogLevel.ALL ) - val index = client.initIndex(IndexName("test_facet_ordering")) - val searcher = SearcherSingleIndex(index) + val searcher = HitsSearcher(client, IndexName("test_facet_ordering")) val filterState = FilterState() val searchBox = SearchBoxConnector(searcher) val color = Attribute("color") @@ -60,18 +58,20 @@ class DynamicFacetShowcase : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) - setContentView(R.layout.showcase_dynamic_facet_list) + val binding = ShowcaseDynamicFacetListBinding.inflate(layoutInflater) + val searchBinding = IncludeSearchBinding.bind(binding.searchBox.root) + setContentView(binding.root) - val searchBoxView = SearchBoxViewAppCompat(searchView) + val searchBoxView = SearchBoxViewAppCompat(searchBinding.searchView) connection += searchBox.connectView(searchBoxView) val factory = ViewHolderFactory() val adapter = DynamicFacetListAdapter(factory) connection += dynamicFacets.connectView(adapter) - configureToolbar(toolbar) - configureSearchView(searchView, getString(R.string.search_brands)) - configureRecyclerView(hits, adapter) + configureToolbar(binding.toolbar) + configureSearchView(searchBinding.searchView, getString(R.string.search_brands)) + configureRecyclerView(binding.hits, adapter) searcher.query.facets = setOf(brand, color, size, country) searcher.searchAsync() diff --git a/showcase/android-view/src/main/kotlin/com/algolia/instantsearch/showcase/filter/facet/dynamic/ViewHolderFactory.kt b/showcase/android-view/src/main/kotlin/com/algolia/instantsearch/showcase/filter/facet/dynamic/ViewHolderFactory.kt new file mode 100644 index 00000000..8c5e0301 --- /dev/null +++ b/showcase/android-view/src/main/kotlin/com/algolia/instantsearch/showcase/filter/facet/dynamic/ViewHolderFactory.kt @@ -0,0 +1,47 @@ +package com.algolia.instantsearch.showcase.filter.facet.dynamic + +import android.view.View +import android.view.ViewGroup +import android.widget.TextView +import com.algolia.instantsearch.android.filter.facet.dynamic.DynamicFacetListHeaderViewHolder +import com.algolia.instantsearch.android.filter.facet.dynamic.DynamicFacetListItemViewHolder +import com.algolia.instantsearch.android.filter.facet.dynamic.DynamicFacetListViewHolder +import com.algolia.instantsearch.android.filter.facet.dynamic.DynamicFacetListViewHolder.ViewType +import com.algolia.instantsearch.android.filter.facet.dynamic.DynamicFacetModel +import com.algolia.instantsearch.android.inflate +import com.algolia.instantsearch.showcase.R +import com.algolia.instantsearch.showcase.databinding.ListItemSelectableBinding +import com.algolia.instantsearch.showcase.layoutInflater + +class ViewHolderFactory : DynamicFacetListViewHolder.Factory { + + override fun createViewHolder( + parent: ViewGroup, + viewType: ViewType + ): DynamicFacetListViewHolder { + return when (viewType) { + ViewType.Header -> HeaderViewHolder(parent.inflate(R.layout.header_item)) + ViewType.Item -> ItemViewHolder( + ListItemSelectableBinding.inflate(parent.layoutInflater, parent, false) + ) + } + } + + class HeaderViewHolder(view: TextView) : DynamicFacetListHeaderViewHolder(view) { + override fun bind(item: DynamicFacetModel.Header, onClick: View.OnClickListener?) { + val textView = view as TextView + textView.text = item.attribute.raw + } + } + + class ItemViewHolder(private val binding: ListItemSelectableBinding) : + DynamicFacetListItemViewHolder(binding.root) { + override fun bind(item: DynamicFacetModel.Item, onClick: View.OnClickListener?) { + binding.selectableItemName.text = item.facet.value + binding.selectableItemSubtitle.text = "${item.facet.count}" + binding.selectableItemSubtitle.visibility = View.VISIBLE + binding.selectableItemIcon.visibility = if (item.selected) View.VISIBLE else View.GONE + binding.root.setOnClickListener(onClick) + } + } +} diff --git a/showcase/src/main/kotlin/com/algolia/instantsearch/showcase/filter/list/FilterListAdapter.kt b/showcase/android-view/src/main/kotlin/com/algolia/instantsearch/showcase/filter/list/FilterListAdapter.kt similarity index 51% rename from showcase/src/main/kotlin/com/algolia/instantsearch/showcase/filter/list/FilterListAdapter.kt rename to showcase/android-view/src/main/kotlin/com/algolia/instantsearch/showcase/filter/list/FilterListAdapter.kt index c876ecf1..7ecaabfb 100644 --- a/showcase/src/main/kotlin/com/algolia/instantsearch/showcase/filter/list/FilterListAdapter.kt +++ b/showcase/android-view/src/main/kotlin/com/algolia/instantsearch/showcase/filter/list/FilterListAdapter.kt @@ -1,46 +1,52 @@ package com.algolia.instantsearch.showcase.filter.list -import android.view.View import android.view.ViewGroup import androidx.recyclerview.widget.DiffUtil import androidx.recyclerview.widget.ListAdapter import com.algolia.instantsearch.core.Callback import com.algolia.instantsearch.core.selectable.list.SelectableItem -import com.algolia.instantsearch.showcase.R -import com.algolia.instantsearch.helper.android.inflate -import com.algolia.instantsearch.helper.filter.FilterPresenterImpl -import com.algolia.instantsearch.helper.filter.list.FilterListView +import com.algolia.instantsearch.filter.FilterPresenterImpl +import com.algolia.instantsearch.filter.list.FilterListView +import com.algolia.instantsearch.showcase.databinding.ListItemSelectableBinding +import com.algolia.instantsearch.showcase.layoutInflater import com.algolia.search.model.filter.Filter - -class FilterListAdapter : +class FilterListAdapter : ListAdapter, FilterListViewHolder>(DiffUtilItem()), FilterListView { override var onSelection: Callback? = null override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): FilterListViewHolder { - return FilterListViewHolder(parent.inflate(R.layout.list_item_selectable)) + return FilterListViewHolder( + ListItemSelectableBinding.inflate(parent.layoutInflater, parent, false) + ) } override fun onBindViewHolder(holder: FilterListViewHolder, position: Int) { val (filter, selected) = getItem(position) - holder.bind(FilterPresenterImpl()(filter), selected, View.OnClickListener { onSelection?.invoke(filter) }) + holder.bind(FilterPresenterImpl()(filter), selected) { onSelection?.invoke(filter) } } override fun setItems(items: List>) { submitList(items) } - private class DiffUtilItem: DiffUtil.ItemCallback>() { + private class DiffUtilItem : DiffUtil.ItemCallback>() { - override fun areItemsTheSame(oldItem: SelectableItem, newItem: SelectableItem): Boolean { + override fun areItemsTheSame( + oldItem: SelectableItem, + newItem: SelectableItem + ): Boolean { return oldItem::class == newItem::class } - override fun areContentsTheSame(oldItem: SelectableItem, newItem: SelectableItem): Boolean { + override fun areContentsTheSame( + oldItem: SelectableItem, + newItem: SelectableItem + ): Boolean { return oldItem == newItem } } -} \ No newline at end of file +} diff --git a/showcase/src/main/kotlin/com/algolia/instantsearch/showcase/filter/list/FilterListAllShowcase.kt b/showcase/android-view/src/main/kotlin/com/algolia/instantsearch/showcase/filter/list/FilterListAllShowcase.kt similarity index 52% rename from showcase/src/main/kotlin/com/algolia/instantsearch/showcase/filter/list/FilterListAllShowcase.kt rename to showcase/android-view/src/main/kotlin/com/algolia/instantsearch/showcase/filter/list/FilterListAllShowcase.kt index c64727c9..b4be1cb3 100644 --- a/showcase/src/main/kotlin/com/algolia/instantsearch/showcase/filter/list/FilterListAllShowcase.kt +++ b/showcase/android-view/src/main/kotlin/com/algolia/instantsearch/showcase/filter/list/FilterListAllShowcase.kt @@ -3,20 +3,19 @@ package com.algolia.instantsearch.showcase.filter.list import android.os.Bundle import androidx.appcompat.app.AppCompatActivity import com.algolia.instantsearch.core.connection.ConnectionHandler +import com.algolia.instantsearch.filter.list.FilterListConnector +import com.algolia.instantsearch.filter.list.connectView +import com.algolia.instantsearch.filter.state.FilterState +import com.algolia.instantsearch.filter.state.groupAnd +import com.algolia.instantsearch.searcher.connectFilterState +import com.algolia.instantsearch.searcher.hits.HitsSearcher import com.algolia.instantsearch.showcase.* -import com.algolia.instantsearch.helper.filter.list.FilterListConnector -import com.algolia.instantsearch.helper.filter.list.connectView -import com.algolia.instantsearch.helper.filter.state.FilterState -import com.algolia.instantsearch.helper.filter.state.groupAnd -import com.algolia.instantsearch.helper.searcher.SearcherSingleIndex -import com.algolia.instantsearch.helper.searcher.connectFilterState +import com.algolia.instantsearch.showcase.databinding.HeaderFilterBinding +import com.algolia.instantsearch.showcase.databinding.IncludeListBinding +import com.algolia.instantsearch.showcase.databinding.ShowcaseFilterListBinding import com.algolia.search.model.Attribute import com.algolia.search.model.filter.Filter import com.algolia.search.model.filter.NumericOperator -import kotlinx.android.synthetic.main.showcase_filter_list.* -import kotlinx.android.synthetic.main.header_filter.* -import kotlinx.android.synthetic.main.include_list.* - class FilterListAllShowcase : AppCompatActivity() { @@ -26,7 +25,7 @@ class FilterListAllShowcase : AppCompatActivity() { private val all = Attribute("all") private val groupAll = groupAnd(all) private val filterState = FilterState() - private val searcher = SearcherSingleIndex(stubIndex) + private val searcher = HitsSearcher(client, stubIndexName) private val filters = listOf( Filter.Numeric(price, 5..10), Filter.Tag("coupon"), @@ -39,19 +38,22 @@ class FilterListAllShowcase : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) - setContentView(R.layout.showcase_filter_list) + val binding = ShowcaseFilterListBinding.inflate(layoutInflater) + val listBinding = IncludeListBinding.bind(binding.list.root) + val headerBinding = HeaderFilterBinding.bind(listBinding.headerFilter.root) + setContentView(binding.root) val viewAll = FilterListAdapter() connection += filterList.connectView(viewAll) - configureToolbar(toolbar) + configureToolbar(binding.toolbar) configureSearcher(searcher) - configureRecyclerView(listTopLeft, viewAll) - onFilterChangedThenUpdateFiltersText(filterState, filtersTextView, color, price, tags, all) - onClearAllThenClearFilters(filterState, filtersClearAll, connection) - onErrorThenUpdateFiltersText(searcher, filtersTextView) - onResponseChangedThenUpdateNbHits(searcher, nbHits, connection) + configureRecyclerView(listBinding.listTopLeft, viewAll) + onFilterChangedThenUpdateFiltersText(filterState, headerBinding.filtersTextView, color, price, tags, all) + onClearAllThenClearFilters(filterState, headerBinding.filtersClearAll, connection) + onErrorThenUpdateFiltersText(searcher, headerBinding.filtersTextView) + onResponseChangedThenUpdateNbHits(searcher, headerBinding.nbHits, connection) searcher.searchAsync() } @@ -61,4 +63,4 @@ class FilterListAllShowcase : AppCompatActivity() { searcher.cancel() connection.clear() } -} \ No newline at end of file +} diff --git a/showcase/src/main/kotlin/com/algolia/instantsearch/showcase/filter/list/FilterListFacetShowcase.kt b/showcase/android-view/src/main/kotlin/com/algolia/instantsearch/showcase/filter/list/FilterListFacetShowcase.kt similarity index 52% rename from showcase/src/main/kotlin/com/algolia/instantsearch/showcase/filter/list/FilterListFacetShowcase.kt rename to showcase/android-view/src/main/kotlin/com/algolia/instantsearch/showcase/filter/list/FilterListFacetShowcase.kt index d6a7c3b7..575fec6c 100644 --- a/showcase/src/main/kotlin/com/algolia/instantsearch/showcase/filter/list/FilterListFacetShowcase.kt +++ b/showcase/android-view/src/main/kotlin/com/algolia/instantsearch/showcase/filter/list/FilterListFacetShowcase.kt @@ -4,26 +4,25 @@ import android.os.Bundle import androidx.appcompat.app.AppCompatActivity import com.algolia.instantsearch.core.connection.ConnectionHandler import com.algolia.instantsearch.core.selectable.list.SelectionMode +import com.algolia.instantsearch.filter.list.FilterListConnector +import com.algolia.instantsearch.filter.list.connectView +import com.algolia.instantsearch.filter.state.FilterState +import com.algolia.instantsearch.filter.state.groupAnd +import com.algolia.instantsearch.searcher.connectFilterState +import com.algolia.instantsearch.searcher.hits.HitsSearcher import com.algolia.instantsearch.showcase.* -import com.algolia.instantsearch.helper.filter.list.FilterListConnector -import com.algolia.instantsearch.helper.filter.list.connectView -import com.algolia.instantsearch.helper.filter.state.FilterState -import com.algolia.instantsearch.helper.filter.state.groupAnd -import com.algolia.instantsearch.helper.searcher.SearcherSingleIndex -import com.algolia.instantsearch.helper.searcher.connectFilterState +import com.algolia.instantsearch.showcase.databinding.HeaderFilterBinding +import com.algolia.instantsearch.showcase.databinding.IncludeListBinding +import com.algolia.instantsearch.showcase.databinding.ShowcaseFilterListBinding import com.algolia.search.model.Attribute import com.algolia.search.model.filter.Filter -import kotlinx.android.synthetic.main.showcase_filter_list.* -import kotlinx.android.synthetic.main.header_filter.* -import kotlinx.android.synthetic.main.include_list.* - class FilterListFacetShowcase : AppCompatActivity() { private val color = Attribute("color") private val groupColor = groupAnd(color) private val filterState = FilterState() - private val searcher = SearcherSingleIndex(stubIndex) + private val searcher = HitsSearcher(client, stubIndexName) private val facetFilters = listOf( Filter.Facet(color, "red"), Filter.Facet(color, "green"), @@ -41,19 +40,22 @@ class FilterListFacetShowcase : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) - setContentView(R.layout.showcase_filter_list) + val binding = ShowcaseFilterListBinding.inflate(layoutInflater) + val listBinding = IncludeListBinding.bind(binding.list.root) + val headerBinding = HeaderFilterBinding.bind(listBinding.headerFilter.root) + setContentView(binding.root) val viewFacet = FilterListAdapter() connection += filterList.connectView(viewFacet) - configureToolbar(toolbar) + configureToolbar(binding.toolbar) configureSearcher(searcher) - configureRecyclerView(listTopLeft, viewFacet) - onFilterChangedThenUpdateFiltersText(filterState, filtersTextView, color) - onClearAllThenClearFilters(filterState, filtersClearAll, connection) - onErrorThenUpdateFiltersText(searcher, filtersTextView) - onResponseChangedThenUpdateNbHits(searcher, nbHits, connection) + configureRecyclerView(listBinding.listTopLeft, viewFacet) + onFilterChangedThenUpdateFiltersText(filterState, headerBinding.filtersTextView, color) + onClearAllThenClearFilters(filterState, headerBinding.filtersClearAll, connection) + onErrorThenUpdateFiltersText(searcher, headerBinding.filtersTextView) + onResponseChangedThenUpdateNbHits(searcher, headerBinding.nbHits, connection) searcher.searchAsync() } @@ -63,4 +65,4 @@ class FilterListFacetShowcase : AppCompatActivity() { searcher.cancel() connection.clear() } -} \ No newline at end of file +} diff --git a/showcase/src/main/kotlin/com/algolia/instantsearch/showcase/filter/list/FilterListNumericShowcase.kt b/showcase/android-view/src/main/kotlin/com/algolia/instantsearch/showcase/filter/list/FilterListNumericShowcase.kt similarity index 52% rename from showcase/src/main/kotlin/com/algolia/instantsearch/showcase/filter/list/FilterListNumericShowcase.kt rename to showcase/android-view/src/main/kotlin/com/algolia/instantsearch/showcase/filter/list/FilterListNumericShowcase.kt index c43a7e1e..b754375f 100644 --- a/showcase/src/main/kotlin/com/algolia/instantsearch/showcase/filter/list/FilterListNumericShowcase.kt +++ b/showcase/android-view/src/main/kotlin/com/algolia/instantsearch/showcase/filter/list/FilterListNumericShowcase.kt @@ -3,26 +3,25 @@ package com.algolia.instantsearch.showcase.filter.list import android.os.Bundle import androidx.appcompat.app.AppCompatActivity import com.algolia.instantsearch.core.connection.ConnectionHandler +import com.algolia.instantsearch.filter.list.FilterListConnector +import com.algolia.instantsearch.filter.list.connectView +import com.algolia.instantsearch.filter.state.FilterState +import com.algolia.instantsearch.filter.state.groupAnd +import com.algolia.instantsearch.searcher.connectFilterState +import com.algolia.instantsearch.searcher.hits.HitsSearcher import com.algolia.instantsearch.showcase.* -import com.algolia.instantsearch.helper.filter.list.FilterListConnector -import com.algolia.instantsearch.helper.filter.list.connectView -import com.algolia.instantsearch.helper.filter.state.FilterState -import com.algolia.instantsearch.helper.filter.state.groupAnd -import com.algolia.instantsearch.helper.searcher.SearcherSingleIndex -import com.algolia.instantsearch.helper.searcher.connectFilterState +import com.algolia.instantsearch.showcase.databinding.HeaderFilterBinding +import com.algolia.instantsearch.showcase.databinding.IncludeListBinding +import com.algolia.instantsearch.showcase.databinding.ShowcaseFilterListBinding import com.algolia.search.model.Attribute import com.algolia.search.model.filter.Filter import com.algolia.search.model.filter.NumericOperator -import kotlinx.android.synthetic.main.showcase_filter_list.* -import kotlinx.android.synthetic.main.header_filter.* -import kotlinx.android.synthetic.main.include_list.* - class FilterListNumericShowcase : AppCompatActivity() { private val price = Attribute("price") private val groupPrice = groupAnd(price) - private val searcher = SearcherSingleIndex(stubIndex) + private val searcher = HitsSearcher(client, stubIndexName) private val filterState = FilterState() private val filters = listOf( Filter.Numeric(price, NumericOperator.Less, 5), @@ -36,20 +35,23 @@ class FilterListNumericShowcase : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) - setContentView(R.layout.showcase_filter_list) + val binding = ShowcaseFilterListBinding.inflate(layoutInflater) + val listBinding = IncludeListBinding.bind(binding.list.root) + val headerBinding = HeaderFilterBinding.bind(listBinding.headerFilter.root) + setContentView(binding.root) val viewNumeric = FilterListAdapter() connection += searcher.connectFilterState(filterState) connection += filterList.connectView(viewNumeric) - configureToolbar(toolbar) + configureToolbar(binding.toolbar) configureSearcher(searcher) - configureRecyclerView(listTopLeft, viewNumeric) - onFilterChangedThenUpdateFiltersText(filterState, filtersTextView, price) - onClearAllThenClearFilters(filterState, filtersClearAll, connection) - onErrorThenUpdateFiltersText(searcher, filtersTextView) - onResponseChangedThenUpdateNbHits(searcher, nbHits, connection) + configureRecyclerView(listBinding.listTopLeft, viewNumeric) + onFilterChangedThenUpdateFiltersText(filterState, headerBinding.filtersTextView, price) + onClearAllThenClearFilters(filterState, headerBinding.filtersClearAll, connection) + onErrorThenUpdateFiltersText(searcher, headerBinding.filtersTextView) + onResponseChangedThenUpdateNbHits(searcher, headerBinding.nbHits, connection) searcher.searchAsync() } @@ -59,4 +61,4 @@ class FilterListNumericShowcase : AppCompatActivity() { searcher.cancel() connection.clear() } -} \ No newline at end of file +} diff --git a/showcase/android-view/src/main/kotlin/com/algolia/instantsearch/showcase/filter/list/FilterListTagShowcase.kt b/showcase/android-view/src/main/kotlin/com/algolia/instantsearch/showcase/filter/list/FilterListTagShowcase.kt new file mode 100644 index 00000000..23c35c0b --- /dev/null +++ b/showcase/android-view/src/main/kotlin/com/algolia/instantsearch/showcase/filter/list/FilterListTagShowcase.kt @@ -0,0 +1,62 @@ +package com.algolia.instantsearch.showcase.filter.list + +import android.os.Bundle +import androidx.appcompat.app.AppCompatActivity +import com.algolia.instantsearch.core.connection.ConnectionHandler +import com.algolia.instantsearch.filter.list.FilterListConnector +import com.algolia.instantsearch.filter.list.connectView +import com.algolia.instantsearch.filter.state.FilterState +import com.algolia.instantsearch.filter.state.groupOr +import com.algolia.instantsearch.searcher.connectFilterState +import com.algolia.instantsearch.searcher.hits.HitsSearcher +import com.algolia.instantsearch.showcase.* +import com.algolia.instantsearch.showcase.databinding.HeaderFilterBinding +import com.algolia.instantsearch.showcase.databinding.IncludeListBinding +import com.algolia.instantsearch.showcase.databinding.ShowcaseFilterListBinding +import com.algolia.search.model.Attribute +import com.algolia.search.model.filter.Filter + +class FilterListTagShowcase : AppCompatActivity() { + + private val tags = Attribute("_tags") + private val groupTags = groupOr(tags) + private val filterState = FilterState() + private val searcher = HitsSearcher(client, stubIndexName) + private val filters = listOf( + Filter.Tag("free shipping"), + Filter.Tag("coupon"), + Filter.Tag("free return"), + Filter.Tag("on sale"), + Filter.Tag("no exchange") + ) + private val filterList = FilterListConnector.Tag(filters, filterState, groupID = groupTags) + private val connection = ConnectionHandler(filterList, searcher.connectFilterState(filterState)) + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + val binding = ShowcaseFilterListBinding.inflate(layoutInflater) + val listBinding = IncludeListBinding.bind(binding.list.root) + val headerBinding = HeaderFilterBinding.bind(listBinding.headerFilter.root) + setContentView(binding.root) + + val viewTag = FilterListAdapter() + + connection += filterList.connectView(viewTag) + + configureToolbar(binding.toolbar) + configureSearcher(searcher) + configureRecyclerView(listBinding.listTopLeft, viewTag) + onFilterChangedThenUpdateFiltersText(filterState, headerBinding.filtersTextView, tags) + onClearAllThenClearFilters(filterState, headerBinding.filtersClearAll, connection) + onErrorThenUpdateFiltersText(searcher, headerBinding.filtersTextView) + onResponseChangedThenUpdateNbHits(searcher, headerBinding.nbHits, connection) + + searcher.searchAsync() + } + + override fun onDestroy() { + super.onDestroy() + searcher.cancel() + connection.clear() + } +} diff --git a/showcase/android-view/src/main/kotlin/com/algolia/instantsearch/showcase/filter/list/FilterListViewHolder.kt b/showcase/android-view/src/main/kotlin/com/algolia/instantsearch/showcase/filter/list/FilterListViewHolder.kt new file mode 100644 index 00000000..1611bc2a --- /dev/null +++ b/showcase/android-view/src/main/kotlin/com/algolia/instantsearch/showcase/filter/list/FilterListViewHolder.kt @@ -0,0 +1,15 @@ +package com.algolia.instantsearch.showcase.filter.list + +import android.view.View +import androidx.recyclerview.widget.RecyclerView +import com.algolia.instantsearch.showcase.databinding.ListItemSelectableBinding + +class FilterListViewHolder(val binding: ListItemSelectableBinding) : + RecyclerView.ViewHolder(binding.root) { + + fun bind(text: String, selected: Boolean, onClickListener: View.OnClickListener) { + binding.root.setOnClickListener(onClickListener) + binding.selectableItemName.text = text + binding.selectableItemIcon.visibility = if (selected) View.VISIBLE else View.INVISIBLE + } +} diff --git a/showcase/android-view/src/main/kotlin/com/algolia/instantsearch/showcase/filter/map/FilterMapShowcase.kt b/showcase/android-view/src/main/kotlin/com/algolia/instantsearch/showcase/filter/map/FilterMapShowcase.kt new file mode 100644 index 00000000..d6fe1f18 --- /dev/null +++ b/showcase/android-view/src/main/kotlin/com/algolia/instantsearch/showcase/filter/map/FilterMapShowcase.kt @@ -0,0 +1,57 @@ +package com.algolia.instantsearch.showcase.filter.map + +import android.os.Bundle +import androidx.appcompat.app.AppCompatActivity +import com.algolia.instantsearch.core.connection.ConnectionHandler +import com.algolia.instantsearch.android.filter.map.FilterMapViewRadioGroup +import com.algolia.instantsearch.filter.map.FilterMapConnector +import com.algolia.instantsearch.filter.map.connectView +import com.algolia.instantsearch.filter.state.FilterState +import com.algolia.instantsearch.filter.state.groupAnd +import com.algolia.instantsearch.searcher.connectFilterState +import com.algolia.instantsearch.searcher.hits.HitsSearcher +import com.algolia.instantsearch.showcase.* +import com.algolia.instantsearch.showcase.databinding.HeaderFilterBinding +import com.algolia.instantsearch.showcase.databinding.ShowcaseFilterMapBinding +import com.algolia.search.model.Attribute +import com.algolia.search.model.filter.Filter + +class FilterMapShowcase : AppCompatActivity() { + + private val gender = Attribute("gender") + private val groupGender = groupAnd(gender) + private val filterState = FilterState() + private val searcher = HitsSearcher(client, stubIndexName) + private val filters = mapOf( + R.id.male to Filter.Facet(gender, "male"), + R.id.female to Filter.Facet(gender, "female") + ) + private val filterMap = FilterMapConnector(filters, filterState, groupID = groupGender) + private val connection = ConnectionHandler(filterMap, searcher.connectFilterState(filterState)) + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + val binding = ShowcaseFilterMapBinding.inflate(layoutInflater) + val headerBinding = HeaderFilterBinding.bind(binding.headerFilter.root) + setContentView(binding.root) + + val viewGender = FilterMapViewRadioGroup(binding.radioGroupGender) + + connection += filterMap.connectView(viewGender) + + configureToolbar(binding.toolbar) + configureSearcher(searcher) + onFilterChangedThenUpdateFiltersText(filterState, headerBinding.filtersTextView, gender) + onClearAllThenClearFilters(filterState, headerBinding.filtersClearAll, connection) + onErrorThenUpdateFiltersText(searcher, headerBinding.filtersTextView) + onResponseChangedThenUpdateNbHits(searcher, headerBinding.nbHits, connection) + + searcher.searchAsync() + } + + override fun onDestroy() { + super.onDestroy() + searcher.cancel() + connection.clear() + } +} diff --git a/showcase/src/main/kotlin/com/algolia/instantsearch/showcase/filter/numeric/comparison/FilterComparisonShowcase.kt b/showcase/android-view/src/main/kotlin/com/algolia/instantsearch/showcase/filter/numeric/comparison/FilterComparisonShowcase.kt similarity index 54% rename from showcase/src/main/kotlin/com/algolia/instantsearch/showcase/filter/numeric/comparison/FilterComparisonShowcase.kt rename to showcase/android-view/src/main/kotlin/com/algolia/instantsearch/showcase/filter/numeric/comparison/FilterComparisonShowcase.kt index 9518c8ac..8f9658b6 100644 --- a/showcase/src/main/kotlin/com/algolia/instantsearch/showcase/filter/numeric/comparison/FilterComparisonShowcase.kt +++ b/showcase/android-view/src/main/kotlin/com/algolia/instantsearch/showcase/filter/numeric/comparison/FilterComparisonShowcase.kt @@ -5,31 +5,28 @@ import androidx.appcompat.app.AppCompatActivity import com.algolia.instantsearch.core.connection.ConnectionHandler import com.algolia.instantsearch.core.number.range.Range import com.algolia.instantsearch.showcase.* -import com.algolia.instantsearch.helper.filter.numeric.comparison.FilterComparisonConnector -import com.algolia.instantsearch.helper.filter.numeric.comparison.connectView -import com.algolia.instantsearch.helper.filter.numeric.comparison.setBoundsFromFacetStatsInt -import com.algolia.instantsearch.helper.filter.numeric.comparison.setBoundsFromFacetStatsLong -import com.algolia.instantsearch.helper.filter.state.FilterState -import com.algolia.instantsearch.helper.searcher.SearcherSingleIndex -import com.algolia.instantsearch.helper.searcher.addFacet -import com.algolia.instantsearch.helper.searcher.connectFilterState +import com.algolia.instantsearch.filter.numeric.comparison.FilterComparisonConnector +import com.algolia.instantsearch.filter.numeric.comparison.connectView +import com.algolia.instantsearch.filter.numeric.comparison.setBoundsFromFacetStatsInt +import com.algolia.instantsearch.filter.numeric.comparison.setBoundsFromFacetStatsLong +import com.algolia.instantsearch.filter.state.FilterState +import com.algolia.instantsearch.searcher.addFacet +import com.algolia.instantsearch.searcher.connectFilterState +import com.algolia.instantsearch.searcher.hits.HitsSearcher +import com.algolia.instantsearch.showcase.databinding.HeaderFilterBinding +import com.algolia.instantsearch.showcase.databinding.ShowcaseFilterComparisonBinding import com.algolia.search.model.Attribute -import com.algolia.search.model.IndexName import com.algolia.search.model.filter.NumericOperator -import kotlinx.android.synthetic.main.showcase_filter_comparison.* -import kotlinx.android.synthetic.main.header_filter.* import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch import kotlinx.coroutines.withContext - class FilterComparisonShowcase : AppCompatActivity() { private val price = Attribute("price") private val year = Attribute("year") - private val index = client.initIndex(IndexName("stub")) private val filterState = FilterState() - private val searcher = SearcherSingleIndex(index) + private val searcher = HitsSearcher(client, stubIndexName) private val comparisonPrice = FilterComparisonConnector(filterState, price, NumericOperator.GreaterOrEquals) private val comparisonYear = FilterComparisonConnector(filterState, year, NumericOperator.Equals) private val connection = ConnectionHandler( @@ -40,23 +37,25 @@ class FilterComparisonShowcase : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) - setContentView(R.layout.showcase_filter_comparison) + val binding = ShowcaseFilterComparisonBinding.inflate(layoutInflater) + val headerBinding = HeaderFilterBinding.bind(binding.headerFilter.root) + setContentView(binding.root) searcher.query.addFacet(price) searcher.query.addFacet(year) - val priceView = FilterPriceView(filterComparison, price, comparisonPrice.operator) - val yearView = FilterYearView(filterComparison, year, comparisonYear.operator) + val priceView = FilterPriceView(ShowcaseFilterComparisonBinding.bind(binding.filterComparison), price, comparisonPrice.operator) + val yearView = FilterYearView(ShowcaseFilterComparisonBinding.bind(binding.filterComparison), year, comparisonYear.operator) connection += comparisonPrice.connectView(priceView) connection += comparisonYear.connectView(yearView) { year -> year?.toString() ?: "" } - configureToolbar(toolbar) + configureToolbar(binding.toolbar) configureSearcher(searcher) - onFilterChangedThenUpdateFiltersText(filterState, filtersTextView, price, year) - onClearAllThenClearFilters(filterState, filtersClearAll, connection) - onErrorThenUpdateFiltersText(searcher, filtersTextView) - onResponseChangedThenUpdateNbHits(searcher, nbHits, connection) + onFilterChangedThenUpdateFiltersText(filterState, headerBinding.filtersTextView, price, year) + onClearAllThenClearFilters(filterState, headerBinding.filtersClearAll, connection) + onErrorThenUpdateFiltersText(searcher, headerBinding.filtersTextView) + onResponseChangedThenUpdateNbHits(searcher, headerBinding.nbHits, connection) searcher.coroutineScope.launch { val response = searcher.search() @@ -65,7 +64,7 @@ class FilterComparisonShowcase : AppCompatActivity() { comparisonPrice.viewModel.setBoundsFromFacetStatsLong(price, it) comparisonYear.viewModel.setBoundsFromFacetStatsInt(year, it) withContext(Dispatchers.Main) { - inputHint.text = getInputHint(comparisonYear.viewModel.bounds.value!!) + binding.inputHint.text = getInputHint(comparisonYear.viewModel.bounds.value!!) } } } diff --git a/showcase/src/main/kotlin/com/algolia/instantsearch/showcase/filter/numeric/comparison/FilterPriceView.kt b/showcase/android-view/src/main/kotlin/com/algolia/instantsearch/showcase/filter/numeric/comparison/FilterPriceView.kt similarity index 61% rename from showcase/src/main/kotlin/com/algolia/instantsearch/showcase/filter/numeric/comparison/FilterPriceView.kt rename to showcase/android-view/src/main/kotlin/com/algolia/instantsearch/showcase/filter/numeric/comparison/FilterPriceView.kt index bd271db3..24b326a6 100644 --- a/showcase/src/main/kotlin/com/algolia/instantsearch/showcase/filter/numeric/comparison/FilterPriceView.kt +++ b/showcase/android-view/src/main/kotlin/com/algolia/instantsearch/showcase/filter/numeric/comparison/FilterPriceView.kt @@ -1,35 +1,33 @@ package com.algolia.instantsearch.showcase.filter.numeric.comparison -import android.view.View import com.algolia.instantsearch.core.number.Computation import com.algolia.instantsearch.core.number.NumberView import com.algolia.instantsearch.core.number.decrement import com.algolia.instantsearch.core.number.increment +import com.algolia.instantsearch.showcase.databinding.ShowcaseFilterComparisonBinding import com.algolia.search.model.Attribute import com.algolia.search.model.filter.NumericOperator -import kotlinx.android.synthetic.main.showcase_filter_comparison.view.* - class FilterPriceView( - val view: View, - val price: Attribute, - val operator: NumericOperator -): NumberView { + val binding: ShowcaseFilterComparisonBinding, + price: Attribute, + operator: NumericOperator +) : NumberView { init { - view.stepperText.text = "$price ${operator.raw}" + binding.stepperText.text = "$price ${operator.raw}" } override fun setComputation(computation: Computation) { - view.arrowUp.setOnClickListener { + binding.arrowUp.setOnClickListener { computation.increment() } - view.arrowDown.setOnClickListener { + binding.arrowDown.setOnClickListener { computation.decrement() } } override fun setText(text: String) { - view.stepperNumber.text = text + binding.stepperNumber.text = text } } \ No newline at end of file diff --git a/showcase/src/main/kotlin/com/algolia/instantsearch/showcase/filter/numeric/comparison/FilterYearView.kt b/showcase/android-view/src/main/kotlin/com/algolia/instantsearch/showcase/filter/numeric/comparison/FilterYearView.kt similarity index 67% rename from showcase/src/main/kotlin/com/algolia/instantsearch/showcase/filter/numeric/comparison/FilterYearView.kt rename to showcase/android-view/src/main/kotlin/com/algolia/instantsearch/showcase/filter/numeric/comparison/FilterYearView.kt index e3a6d3b1..310622fe 100644 --- a/showcase/src/main/kotlin/com/algolia/instantsearch/showcase/filter/numeric/comparison/FilterYearView.kt +++ b/showcase/android-view/src/main/kotlin/com/algolia/instantsearch/showcase/filter/numeric/comparison/FilterYearView.kt @@ -1,27 +1,25 @@ package com.algolia.instantsearch.showcase.filter.numeric.comparison -import android.view.View import android.view.inputmethod.EditorInfo import com.algolia.instantsearch.core.number.Computation import com.algolia.instantsearch.core.number.NumberView import com.algolia.instantsearch.core.number.just +import com.algolia.instantsearch.showcase.databinding.ShowcaseFilterComparisonBinding import com.algolia.search.model.Attribute import com.algolia.search.model.filter.NumericOperator -import kotlinx.android.synthetic.main.showcase_filter_comparison.view.* - class FilterYearView( - val view: View, - val year: Attribute, - val operator: NumericOperator + val binding: ShowcaseFilterComparisonBinding, + year: Attribute, + operator: NumericOperator ) : NumberView { init { - view.inputText.text = "$year ${operator.raw}" + binding.inputText.text = "$year ${operator.raw}" } override fun setComputation(computation: Computation) { - view.inputEditText.setOnEditorActionListener { v, actionId, _ -> + binding.inputEditText.setOnEditorActionListener { v, actionId, _ -> if (actionId == EditorInfo.IME_ACTION_DONE) { val year = v.text.toString().toIntOrNull() @@ -32,6 +30,6 @@ class FilterYearView( } override fun setText(text: String) { - view.inputEditText.setText(text) + binding.inputEditText.setText(text) } -} \ No newline at end of file +} diff --git a/showcase/src/main/kotlin/com/algolia/instantsearch/showcase/filter/range/BoundsTextView.kt b/showcase/android-view/src/main/kotlin/com/algolia/instantsearch/showcase/filter/range/BoundsTextView.kt similarity index 100% rename from showcase/src/main/kotlin/com/algolia/instantsearch/showcase/filter/range/BoundsTextView.kt rename to showcase/android-view/src/main/kotlin/com/algolia/instantsearch/showcase/filter/range/BoundsTextView.kt diff --git a/showcase/android-view/src/main/kotlin/com/algolia/instantsearch/showcase/filter/range/FilterRangeShowcase.kt b/showcase/android-view/src/main/kotlin/com/algolia/instantsearch/showcase/filter/range/FilterRangeShowcase.kt new file mode 100644 index 00000000..e9489a77 --- /dev/null +++ b/showcase/android-view/src/main/kotlin/com/algolia/instantsearch/showcase/filter/range/FilterRangeShowcase.kt @@ -0,0 +1,80 @@ +package com.algolia.instantsearch.showcase.filter.range + +import android.os.Bundle +import androidx.appcompat.app.AppCompatActivity +import com.algolia.instantsearch.core.connection.ConnectionHandler +import com.algolia.instantsearch.core.number.range.Range +import com.algolia.instantsearch.core.searcher.Debouncer +import com.algolia.instantsearch.filter.range.FilterRangeConnector +import com.algolia.instantsearch.filter.range.connectView +import com.algolia.instantsearch.filter.state.FilterGroupID +import com.algolia.instantsearch.filter.state.FilterState +import com.algolia.instantsearch.filter.state.filters +import com.algolia.instantsearch.searcher.connectFilterState +import com.algolia.instantsearch.searcher.hits.HitsSearcher +import com.algolia.instantsearch.showcase.* +import com.algolia.instantsearch.showcase.databinding.HeaderFilterBinding +import com.algolia.instantsearch.showcase.databinding.ShowcaseFilterRangeBinding +import com.algolia.search.model.Attribute + +class FilterRangeShowcase : AppCompatActivity() { + + private val searcher = HitsSearcher(client, stubIndexName) + private val price = Attribute("price") + private val groupID = FilterGroupID(price) + private val primaryBounds = 0..15 + private val secondaryBounds = 0..10 + private val initialRange = 0..15 + private val filters = filters { + group(groupID) { + range(price, initialRange) + } + } + private val filterState = FilterState(filters) + private val range = + FilterRangeConnector(filterState, price, range = initialRange, bounds = primaryBounds) + private val connection = ConnectionHandler( + range, + searcher.connectFilterState(filterState, Debouncer(100)) + ) + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + val binding = ShowcaseFilterRangeBinding.inflate(layoutInflater) + val headerBinding = HeaderFilterBinding.bind(binding.headerFilter.root) + setContentView(binding.root) + + connection += range.connectView(RangeSliderView(binding.slider)) + connection += range.connectView(RangeTextView(binding.rangeLabel)) + connection += range.connectView(BoundsTextView(binding.boundsLabel)) + + binding.buttonChangeBounds.setOnClickListener { + range.viewModel.bounds.value = Range(secondaryBounds) + it.isEnabled = false + binding.buttonResetBounds.isEnabled = true + } + binding.buttonResetBounds.setOnClickListener { + range.viewModel.bounds.value = Range(primaryBounds) + it.isEnabled = false + binding.buttonChangeBounds.isEnabled = true + } + + binding.reset.setOnClickListener { + filterState.notify { set(filters) } + } + configureToolbar(binding.toolbar) + configureSearcher(searcher) + onFilterChangedThenUpdateFiltersText(filterState, headerBinding.filtersTextView, price) + onClearAllThenClearFilters(filterState, headerBinding.filtersClearAll, connection) + onErrorThenUpdateFiltersText(searcher, headerBinding.filtersTextView) + onResponseChangedThenUpdateNbHits(searcher, headerBinding.nbHits, connection) + + searcher.searchAsync() + } + + override fun onDestroy() { + super.onDestroy() + searcher.cancel() + connection.clear() + } +} diff --git a/showcase/src/main/kotlin/com/algolia/instantsearch/showcase/filter/range/RangeSliderView.kt b/showcase/android-view/src/main/kotlin/com/algolia/instantsearch/showcase/filter/range/RangeSliderView.kt similarity index 100% rename from showcase/src/main/kotlin/com/algolia/instantsearch/showcase/filter/range/RangeSliderView.kt rename to showcase/android-view/src/main/kotlin/com/algolia/instantsearch/showcase/filter/range/RangeSliderView.kt diff --git a/showcase/src/main/kotlin/com/algolia/instantsearch/showcase/filter/range/RangeTextView.kt b/showcase/android-view/src/main/kotlin/com/algolia/instantsearch/showcase/filter/range/RangeTextView.kt similarity index 100% rename from showcase/src/main/kotlin/com/algolia/instantsearch/showcase/filter/range/RangeTextView.kt rename to showcase/android-view/src/main/kotlin/com/algolia/instantsearch/showcase/filter/range/RangeTextView.kt diff --git a/showcase/src/main/kotlin/com/algolia/instantsearch/showcase/filter/rating/RatingBarView.kt b/showcase/android-view/src/main/kotlin/com/algolia/instantsearch/showcase/filter/rating/RatingBarView.kt similarity index 100% rename from showcase/src/main/kotlin/com/algolia/instantsearch/showcase/filter/rating/RatingBarView.kt rename to showcase/android-view/src/main/kotlin/com/algolia/instantsearch/showcase/filter/rating/RatingBarView.kt diff --git a/showcase/android-view/src/main/kotlin/com/algolia/instantsearch/showcase/filter/rating/RatingShowcase.kt b/showcase/android-view/src/main/kotlin/com/algolia/instantsearch/showcase/filter/rating/RatingShowcase.kt new file mode 100644 index 00000000..924db249 --- /dev/null +++ b/showcase/android-view/src/main/kotlin/com/algolia/instantsearch/showcase/filter/rating/RatingShowcase.kt @@ -0,0 +1,79 @@ +package com.algolia.instantsearch.showcase.filter.rating + +import android.os.Bundle +import androidx.appcompat.app.AppCompatActivity +import com.algolia.instantsearch.core.connection.ConnectionHandler +import com.algolia.instantsearch.core.searcher.Debouncer +import com.algolia.instantsearch.filter.range.FilterRangeConnector +import com.algolia.instantsearch.filter.range.connectView +import com.algolia.instantsearch.filter.state.FilterGroupID +import com.algolia.instantsearch.filter.state.FilterState +import com.algolia.instantsearch.filter.state.filters +import com.algolia.instantsearch.searcher.connectFilterState +import com.algolia.instantsearch.searcher.hits.HitsSearcher +import com.algolia.instantsearch.showcase.* +import com.algolia.instantsearch.showcase.databinding.HeaderFilterBinding +import com.algolia.instantsearch.showcase.databinding.IncludePlusMinusBinding +import com.algolia.instantsearch.showcase.databinding.ShowcaseFilterRatingBinding +import com.algolia.search.model.Attribute +import com.algolia.search.model.IndexName +import com.algolia.search.model.filter.Filter + +class RatingShowcase : AppCompatActivity() { + + private val searcher = HitsSearcher(client, IndexName("instant_search")) + private val rating = Attribute("rating") + private val groupID = FilterGroupID(rating) + private val primaryBounds = 0f..5f + private val initialRange = 3f..5f + private val filters = filters { + group(groupID) { + +Filter.Numeric( + rating, + lowerBound = initialRange.start, + upperBound = initialRange.endInclusive + ) + } + } + private val filterState = FilterState(filters) + private val range = + FilterRangeConnector(filterState, rating, range = initialRange, bounds = primaryBounds) + private val connection = ConnectionHandler( + range, + searcher.connectFilterState(filterState, Debouncer(100)) + ) + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + val binding = ShowcaseFilterRatingBinding.inflate(layoutInflater) + val headerBinding = HeaderFilterBinding.bind(binding.headerFilter.root) + val buttonsBinding = IncludePlusMinusBinding.bind(binding.buttons.root) + setContentView(binding.root) + + val ratingBarView = RatingBarView(binding.ratingBar).apply { + stepSize = STEP + buttonsBinding.plus.setOnClickListener { rating += stepSize } + buttonsBinding.minus.setOnClickListener { rating -= stepSize } + } + connection += range.connectView(ratingBarView) + connection += range.connectView(RatingTextView(binding.ratingLabel)) + + configureToolbar(binding.toolbar) + onFilterChangedThenUpdateFiltersText(filterState, headerBinding.filtersTextView, rating) + onClearAllThenClearFilters(filterState, headerBinding.filtersClearAll, connection) + onErrorThenUpdateFiltersText(searcher, headerBinding.filtersTextView) + onResponseChangedThenUpdateNbHits(searcher, headerBinding.nbHits, connection) + + searcher.searchAsync() + } + + override fun onDestroy() { + super.onDestroy() + searcher.cancel() + connection.clear() + } + + companion object { + private const val STEP = 0.1f + } +} diff --git a/showcase/src/main/kotlin/com/algolia/instantsearch/showcase/filter/rating/RatingTextView.kt b/showcase/android-view/src/main/kotlin/com/algolia/instantsearch/showcase/filter/rating/RatingTextView.kt similarity index 100% rename from showcase/src/main/kotlin/com/algolia/instantsearch/showcase/filter/rating/RatingTextView.kt rename to showcase/android-view/src/main/kotlin/com/algolia/instantsearch/showcase/filter/rating/RatingTextView.kt diff --git a/showcase/src/main/kotlin/com/algolia/instantsearch/showcase/filter/toggle/FilterToggleShowcase.kt b/showcase/android-view/src/main/kotlin/com/algolia/instantsearch/showcase/filter/toggle/FilterToggleShowcase.kt similarity index 53% rename from showcase/src/main/kotlin/com/algolia/instantsearch/showcase/filter/toggle/FilterToggleShowcase.kt rename to showcase/android-view/src/main/kotlin/com/algolia/instantsearch/showcase/filter/toggle/FilterToggleShowcase.kt index 8221a873..bcb7d249 100644 --- a/showcase/src/main/kotlin/com/algolia/instantsearch/showcase/filter/toggle/FilterToggleShowcase.kt +++ b/showcase/android-view/src/main/kotlin/com/algolia/instantsearch/showcase/filter/toggle/FilterToggleShowcase.kt @@ -3,19 +3,18 @@ package com.algolia.instantsearch.showcase.filter.toggle import android.os.Bundle import androidx.appcompat.app.AppCompatActivity import com.algolia.instantsearch.core.connection.ConnectionHandler +import com.algolia.instantsearch.android.filter.toggle.FilterToggleViewCompoundButton +import com.algolia.instantsearch.filter.state.FilterState +import com.algolia.instantsearch.filter.toggle.FilterToggleConnector +import com.algolia.instantsearch.filter.toggle.connectView +import com.algolia.instantsearch.searcher.connectFilterState +import com.algolia.instantsearch.searcher.hits.HitsSearcher import com.algolia.instantsearch.showcase.* -import com.algolia.instantsearch.helper.android.filter.toggle.FilterToggleViewCompoundButton -import com.algolia.instantsearch.helper.filter.state.FilterState -import com.algolia.instantsearch.helper.filter.toggle.FilterToggleConnector -import com.algolia.instantsearch.helper.filter.toggle.connectView -import com.algolia.instantsearch.helper.searcher.SearcherSingleIndex -import com.algolia.instantsearch.helper.searcher.connectFilterState +import com.algolia.instantsearch.showcase.databinding.HeaderFilterBinding +import com.algolia.instantsearch.showcase.databinding.ShowcaseFilterToggleBinding import com.algolia.search.model.Attribute import com.algolia.search.model.filter.Filter import com.algolia.search.model.filter.NumericOperator -import kotlinx.android.synthetic.main.showcase_filter_toggle.* -import kotlinx.android.synthetic.main.header_filter.* - class FilterToggleShowcase : AppCompatActivity() { @@ -23,7 +22,7 @@ class FilterToggleShowcase : AppCompatActivity() { private val size = Attribute("size") private val tags = Attribute("_tags") private val filterState = FilterState() - private val searcher = SearcherSingleIndex(stubIndex) + private val searcher = HitsSearcher(client, stubIndexName) private val filterCoupon = Filter.Facet(promotions, "coupon") private val filterSize = Filter.Numeric(size, NumericOperator.Greater, 40) private val filterVintage = Filter.Tag("vintage") @@ -39,22 +38,24 @@ class FilterToggleShowcase : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) - setContentView(R.layout.showcase_filter_toggle) + val binding = ShowcaseFilterToggleBinding.inflate(layoutInflater) + val headerBinding = HeaderFilterBinding.bind(binding.headerFilter.root) + setContentView(binding.root) - val viewCoupon = FilterToggleViewCompoundButton(switchCoupon) - val viewSize = FilterToggleViewCompoundButton(checkBoxSize) - val viewVintage = FilterToggleViewCompoundButton(checkBoxVintage) + val viewCoupon = FilterToggleViewCompoundButton(binding.switchCoupon) + val viewSize = FilterToggleViewCompoundButton(binding.checkBoxSize) + val viewVintage = FilterToggleViewCompoundButton(binding.checkBoxVintage) connection += toggleCoupon.connectView(viewCoupon) connection += toggleSize.connectView(viewSize) connection += toggleVintage.connectView(viewVintage) - configureToolbar(toolbar) + configureToolbar(binding.toolbar) configureSearcher(searcher) - onFilterChangedThenUpdateFiltersText(filterState, filtersTextView, promotions, size, tags) - onClearAllThenClearFilters(filterState, filtersClearAll, connection) - onErrorThenUpdateFiltersText(searcher, filtersTextView) - onResponseChangedThenUpdateNbHits(searcher, nbHits, connection) + onFilterChangedThenUpdateFiltersText(filterState, headerBinding.filtersTextView, promotions, size, tags) + onClearAllThenClearFilters(filterState, headerBinding.filtersClearAll, connection) + onErrorThenUpdateFiltersText(searcher, headerBinding.filtersTextView) + onResponseChangedThenUpdateNbHits(searcher, headerBinding.nbHits, connection) searcher.searchAsync() } @@ -65,5 +66,3 @@ class FilterToggleShowcase : AppCompatActivity() { connection.clear() } } - - diff --git a/showcase/src/main/kotlin/com/algolia/instantsearch/showcase/hierarchical/HierarchicalAdapter.kt b/showcase/android-view/src/main/kotlin/com/algolia/instantsearch/showcase/hierarchical/HierarchicalAdapter.kt similarity index 73% rename from showcase/src/main/kotlin/com/algolia/instantsearch/showcase/hierarchical/HierarchicalAdapter.kt rename to showcase/android-view/src/main/kotlin/com/algolia/instantsearch/showcase/hierarchical/HierarchicalAdapter.kt index 52b8f778..9c33398d 100644 --- a/showcase/src/main/kotlin/com/algolia/instantsearch/showcase/hierarchical/HierarchicalAdapter.kt +++ b/showcase/android-view/src/main/kotlin/com/algolia/instantsearch/showcase/hierarchical/HierarchicalAdapter.kt @@ -1,14 +1,13 @@ package com.algolia.instantsearch.showcase.hierarchical -import android.view.View import android.view.ViewGroup import androidx.recyclerview.widget.DiffUtil import androidx.recyclerview.widget.ListAdapter import com.algolia.instantsearch.core.Callback -import com.algolia.instantsearch.helper.android.inflate -import com.algolia.instantsearch.helper.hierarchical.HierarchicalItem -import com.algolia.instantsearch.helper.hierarchical.HierarchicalView -import com.algolia.instantsearch.showcase.R +import com.algolia.instantsearch.hierarchical.HierarchicalItem +import com.algolia.instantsearch.hierarchical.HierarchicalView +import com.algolia.instantsearch.showcase.databinding.ListItemSelectableBinding +import com.algolia.instantsearch.showcase.layoutInflater class HierarchicalAdapter : ListAdapter(diffUtil), HierarchicalView { @@ -16,13 +15,15 @@ class HierarchicalAdapter : ListAdapter? = null override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): HierarchicalViewHolder { - return HierarchicalViewHolder(parent.inflate(R.layout.list_item_selectable, false)) + return HierarchicalViewHolder( + ListItemSelectableBinding.inflate(parent.layoutInflater, parent, false) + ) } override fun onBindViewHolder(holder: HierarchicalViewHolder, position: Int) { val item = getItem(position) - holder.bind(item, View.OnClickListener { onSelectionChanged?.invoke(item.facet.value) }) + holder.bind(item) { onSelectionChanged?.invoke(item.facet.value) } } override fun setTree(tree: List) { diff --git a/showcase/android-view/src/main/kotlin/com/algolia/instantsearch/showcase/hierarchical/HierarchicalShowcase.kt b/showcase/android-view/src/main/kotlin/com/algolia/instantsearch/showcase/hierarchical/HierarchicalShowcase.kt new file mode 100644 index 00000000..bd722f9f --- /dev/null +++ b/showcase/android-view/src/main/kotlin/com/algolia/instantsearch/showcase/hierarchical/HierarchicalShowcase.kt @@ -0,0 +1,68 @@ +package com.algolia.instantsearch.showcase.hierarchical + +import android.os.Bundle +import androidx.appcompat.app.AppCompatActivity +import com.algolia.instantsearch.core.connection.ConnectionHandler +import com.algolia.instantsearch.filter.state.FilterState +import com.algolia.instantsearch.hierarchical.HierarchicalConnector +import com.algolia.instantsearch.hierarchical.HierarchicalPresenterImpl +import com.algolia.instantsearch.hierarchical.connectView +import com.algolia.instantsearch.searcher.connectFilterState +import com.algolia.instantsearch.searcher.hits.HitsSearcher +import com.algolia.instantsearch.showcase.* +import com.algolia.instantsearch.showcase.databinding.HeaderFilterBinding +import com.algolia.instantsearch.showcase.databinding.ShowcaseHierarchicalBinding +import com.algolia.search.model.Attribute + +class HierarchicalShowcase : AppCompatActivity() { + + private val hierarchicalCategory = Attribute("hierarchicalCategories") + private val hierarchicalCategoryLvl0 = Attribute("$hierarchicalCategory.lvl0") + private val hierarchicalCategoryLvl1 = Attribute("$hierarchicalCategory.lvl1") + private val hierarchicalCategoryLvl2 = Attribute("$hierarchicalCategory.lvl2") + private val hierarchicalAttributes = listOf( + hierarchicalCategoryLvl0, + hierarchicalCategoryLvl1, + hierarchicalCategoryLvl2 + ) + private val searcher = HitsSearcher(client, stubIndexName) + private val filterState = FilterState() + private val separator = " > " + private val hierarchical = HierarchicalConnector( + searcher = searcher, + attribute = hierarchicalCategory, + filterState = filterState, + hierarchicalAttributes = hierarchicalAttributes, + separator = separator + ) + private val connection = ConnectionHandler( + hierarchical, + searcher.connectFilterState(filterState) + ) + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + val binding = ShowcaseHierarchicalBinding.inflate(layoutInflater) + val headerBinding = HeaderFilterBinding.bind(binding.headerFilter.root) + setContentView(binding.root) + + val view = HierarchicalAdapter() + connection += hierarchical.connectView(view, HierarchicalPresenterImpl(separator)) + + configureRecyclerView(binding.hits, view) + configureToolbar(binding.toolbar) + configureSearcher(searcher) + onFilterChangedThenUpdateFiltersText(filterState, headerBinding.filtersTextView, hierarchicalCategory) + onErrorThenUpdateFiltersText(searcher, headerBinding.filtersTextView) + onResponseChangedThenUpdateNbHits(searcher, headerBinding.nbHits, connection) + onClearAllThenClearFilters(filterState, headerBinding.filtersClearAll, connection) + + searcher.searchAsync() + } + + override fun onDestroy() { + super.onDestroy() + searcher.cancel() + connection.clear() + } +} diff --git a/showcase/android-view/src/main/kotlin/com/algolia/instantsearch/showcase/hierarchical/HierarchicalViewHolder.kt b/showcase/android-view/src/main/kotlin/com/algolia/instantsearch/showcase/hierarchical/HierarchicalViewHolder.kt new file mode 100644 index 00000000..8a07d128 --- /dev/null +++ b/showcase/android-view/src/main/kotlin/com/algolia/instantsearch/showcase/hierarchical/HierarchicalViewHolder.kt @@ -0,0 +1,31 @@ +package com.algolia.instantsearch.showcase.hierarchical + +import android.graphics.Typeface +import android.view.View +import androidx.recyclerview.widget.RecyclerView +import com.algolia.instantsearch.hierarchical.HierarchicalItem +import com.algolia.instantsearch.showcase.databinding.ListItemSelectableBinding +import com.algolia.instantsearch.showcase.dip + +class HierarchicalViewHolder(private val binding: ListItemSelectableBinding) : + RecyclerView.ViewHolder(binding.root) { + + fun bind(item: HierarchicalItem, onClick: View.OnClickListener) { + binding.root.elevation = ((6 - item.level * 2) * binding.root.context.dip(4)).toFloat() + binding.root.setOnClickListener(onClick) + binding.selectableItemName.text = item.displayName + binding.selectableItemSubtitle.text = item.facet.count.toString() + binding.selectableItemSubtitle.visibility = View.VISIBLE + if (item.isSelected) selected() else unselected() + } + + private fun selected() { + binding.selectableItemIcon.visibility = View.VISIBLE + binding.selectableItemName.setTypeface(null, Typeface.BOLD) + } + + private fun unselected() { + binding.selectableItemIcon.visibility = View.INVISIBLE + binding.selectableItemName.setTypeface(null, Typeface.NORMAL) + } +} diff --git a/showcase/src/main/kotlin/com/algolia/instantsearch/showcase/highlighting/HighlightingAdapter.kt b/showcase/android-view/src/main/kotlin/com/algolia/instantsearch/showcase/highlighting/HighlightingAdapter.kt similarity index 68% rename from showcase/src/main/kotlin/com/algolia/instantsearch/showcase/highlighting/HighlightingAdapter.kt rename to showcase/android-view/src/main/kotlin/com/algolia/instantsearch/showcase/highlighting/HighlightingAdapter.kt index 60b94bf3..72c1ebd2 100644 --- a/showcase/src/main/kotlin/com/algolia/instantsearch/showcase/highlighting/HighlightingAdapter.kt +++ b/showcase/android-view/src/main/kotlin/com/algolia/instantsearch/showcase/highlighting/HighlightingAdapter.kt @@ -3,16 +3,18 @@ package com.algolia.instantsearch.showcase.highlighting import android.view.ViewGroup import androidx.recyclerview.widget.ListAdapter import com.algolia.instantsearch.core.hits.HitsView -import com.algolia.instantsearch.showcase.R +import com.algolia.instantsearch.showcase.databinding.ListItemHighlightingBinding +import com.algolia.instantsearch.showcase.layoutInflater import com.algolia.instantsearch.showcase.list.movie.Movie import com.algolia.instantsearch.showcase.list.movie.MovieDiffUtil -import com.algolia.instantsearch.helper.android.inflate - -class HighlightingAdapter : ListAdapter(MovieDiffUtil), HitsView { +class HighlightingAdapter : ListAdapter(MovieDiffUtil), + HitsView { override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): HighlightingViewHolder { - return HighlightingViewHolder(parent.inflate(R.layout.list_item_highlighting)) + return HighlightingViewHolder( + ListItemHighlightingBinding.inflate(parent.layoutInflater, parent, false) + ) } override fun onBindViewHolder(holder: HighlightingViewHolder, position: Int) { diff --git a/showcase/src/main/kotlin/com/algolia/instantsearch/showcase/highlighting/HighlightingShowcase.kt b/showcase/android-view/src/main/kotlin/com/algolia/instantsearch/showcase/highlighting/HighlightingShowcase.kt similarity index 57% rename from showcase/src/main/kotlin/com/algolia/instantsearch/showcase/highlighting/HighlightingShowcase.kt rename to showcase/android-view/src/main/kotlin/com/algolia/instantsearch/showcase/highlighting/HighlightingShowcase.kt index 48600c82..773a020f 100644 --- a/showcase/src/main/kotlin/com/algolia/instantsearch/showcase/highlighting/HighlightingShowcase.kt +++ b/showcase/android-view/src/main/kotlin/com/algolia/instantsearch/showcase/highlighting/HighlightingShowcase.kt @@ -4,22 +4,23 @@ import android.os.Bundle import androidx.appcompat.app.AppCompatActivity import com.algolia.instantsearch.core.connection.ConnectionHandler import com.algolia.instantsearch.core.hits.connectHitsView +import com.algolia.instantsearch.searcher.hits.HitsSearcher import com.algolia.instantsearch.showcase.* +import com.algolia.instantsearch.showcase.databinding.IncludeSearchBinding +import com.algolia.instantsearch.showcase.databinding.ShowcaseHighlightingBinding import com.algolia.instantsearch.showcase.list.movie.Movie -import com.algolia.instantsearch.helper.searcher.SearcherSingleIndex import com.algolia.search.helper.deserialize -import kotlinx.android.synthetic.main.showcase_search.* -import kotlinx.android.synthetic.main.include_search.* - class HighlightingShowcase : AppCompatActivity() { - private val searcher = SearcherSingleIndex(stubIndex) + private val searcher = HitsSearcher(client, stubIndexName) private val connection = ConnectionHandler() override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) - setContentView(R.layout.showcase_highlighting) + val binding = ShowcaseHighlightingBinding.inflate(layoutInflater) + val searchBinding = IncludeSearchBinding.bind(binding.searchBox.root) + setContentView(binding.root) val adapter = HighlightingAdapter() @@ -27,11 +28,11 @@ class HighlightingShowcase : AppCompatActivity() { response.hits.deserialize(Movie.serializer()) } - configureToolbar(toolbar) + configureToolbar(binding.toolbar) configureSearcher(searcher) - configureRecyclerView(hits, adapter) - configureSearchView(searchView, getString(R.string.search_movies)) - configureSearchBox(searchView, searcher, connection) + configureRecyclerView(binding.hits, adapter) + configureSearchView(searchBinding.searchView, getString(R.string.search_movies)) + configureSearchBox(searchBinding.searchView, searcher, connection) searcher.searchAsync() } diff --git a/showcase/src/main/kotlin/com/algolia/instantsearch/showcase/highlighting/HighlightingViewHolder.kt b/showcase/android-view/src/main/kotlin/com/algolia/instantsearch/showcase/highlighting/HighlightingViewHolder.kt similarity index 75% rename from showcase/src/main/kotlin/com/algolia/instantsearch/showcase/highlighting/HighlightingViewHolder.kt rename to showcase/android-view/src/main/kotlin/com/algolia/instantsearch/showcase/highlighting/HighlightingViewHolder.kt index 0196e275..127ad6f6 100644 --- a/showcase/src/main/kotlin/com/algolia/instantsearch/showcase/highlighting/HighlightingViewHolder.kt +++ b/showcase/android-view/src/main/kotlin/com/algolia/instantsearch/showcase/highlighting/HighlightingViewHolder.kt @@ -3,26 +3,24 @@ package com.algolia.instantsearch.showcase.highlighting import android.graphics.Color import android.text.TextUtils import android.text.style.BackgroundColorSpan -import android.view.View import android.widget.ImageView import android.widget.TextView import androidx.core.text.buildSpannedString import androidx.core.text.italic import androidx.recyclerview.widget.RecyclerView +import com.algolia.instantsearch.android.highlighting.toSpannedString +import com.algolia.instantsearch.showcase.databinding.ListItemHighlightingBinding import com.algolia.instantsearch.showcase.list.movie.Movie -import com.algolia.instantsearch.helper.android.highlighting.toSpannedString import com.bumptech.glide.Glide -import kotlinx.android.synthetic.main.list_item_highlighting.view.* -import java.util.* - -class HighlightingViewHolder(private val view: View) : RecyclerView.ViewHolder(view) { +class HighlightingViewHolder(private val binding: ListItemHighlightingBinding) : + RecyclerView.ViewHolder(binding.root) { fun bind(movie: Movie) { - movie.bindTitleTo(view.itemTitle) - movie.bindSubtitleTo(view.itemSubtitle) - movie.bindFooterTo(view.itemFooter) - movie.bindImageTo(view.itemImage) + movie.bindTitleTo(binding.itemTitle) + movie.bindSubtitleTo(binding.itemSubtitle) + movie.bindFooterTo(binding.itemFooter) + movie.bindImageTo(binding.itemImage) } private fun Movie.bindTitleTo(view: TextView) { @@ -50,4 +48,4 @@ class HighlightingViewHolder(private val view: View) : RecyclerView.ViewHolder(v .centerCrop() .into(view) } -} \ No newline at end of file +} diff --git a/showcase/src/main/kotlin/com/algolia/instantsearch/showcase/list/actor/Actor.kt b/showcase/android-view/src/main/kotlin/com/algolia/instantsearch/showcase/list/actor/Actor.kt similarity index 95% rename from showcase/src/main/kotlin/com/algolia/instantsearch/showcase/list/actor/Actor.kt rename to showcase/android-view/src/main/kotlin/com/algolia/instantsearch/showcase/list/actor/Actor.kt index 4aa5415a..a41cc98d 100644 --- a/showcase/src/main/kotlin/com/algolia/instantsearch/showcase/list/actor/Actor.kt +++ b/showcase/android-view/src/main/kotlin/com/algolia/instantsearch/showcase/list/actor/Actor.kt @@ -4,9 +4,8 @@ import com.algolia.search.model.ObjectID import com.algolia.search.model.indexing.Indexable import kotlinx.serialization.Serializable - @Serializable data class Actor( val name: String, override val objectID: ObjectID -) : Indexable \ No newline at end of file +) : Indexable diff --git a/showcase/src/main/kotlin/com/algolia/instantsearch/showcase/list/actor/ActorAdapterNested.kt b/showcase/android-view/src/main/kotlin/com/algolia/instantsearch/showcase/list/actor/ActorAdapterNested.kt similarity index 68% rename from showcase/src/main/kotlin/com/algolia/instantsearch/showcase/list/actor/ActorAdapterNested.kt rename to showcase/android-view/src/main/kotlin/com/algolia/instantsearch/showcase/list/actor/ActorAdapterNested.kt index 4bf5e725..357fa666 100644 --- a/showcase/src/main/kotlin/com/algolia/instantsearch/showcase/list/actor/ActorAdapterNested.kt +++ b/showcase/android-view/src/main/kotlin/com/algolia/instantsearch/showcase/list/actor/ActorAdapterNested.kt @@ -1,16 +1,17 @@ package com.algolia.instantsearch.showcase.list.actor import android.view.ViewGroup -import androidx.paging.PagedListAdapter +import androidx.paging.PagingDataAdapter import androidx.recyclerview.widget.DiffUtil -import com.algolia.instantsearch.showcase.R -import com.algolia.instantsearch.helper.android.inflate +import com.algolia.instantsearch.showcase.databinding.ListItemActorBinding +import com.algolia.instantsearch.showcase.layoutInflater - -class ActorAdapterNested : PagedListAdapter(this) { +class ActorAdapterNested : PagingDataAdapter(this) { override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ActorViewHolder { - return ActorViewHolder(parent.inflate(R.layout.list_item_actor)) + return ActorViewHolder( + ListItemActorBinding.inflate(parent.layoutInflater, parent, false) + ) } override fun onBindViewHolder(holder: ActorViewHolder, position: Int) { @@ -35,4 +36,4 @@ class ActorAdapterNested : PagedListAdapter(this) { return oldItem == newItem } } -} \ No newline at end of file +} diff --git a/showcase/android-view/src/main/kotlin/com/algolia/instantsearch/showcase/list/actor/ActorViewHolder.kt b/showcase/android-view/src/main/kotlin/com/algolia/instantsearch/showcase/list/actor/ActorViewHolder.kt new file mode 100644 index 00000000..9bcb34a8 --- /dev/null +++ b/showcase/android-view/src/main/kotlin/com/algolia/instantsearch/showcase/list/actor/ActorViewHolder.kt @@ -0,0 +1,12 @@ +package com.algolia.instantsearch.showcase.list.actor + +import androidx.recyclerview.widget.RecyclerView +import com.algolia.instantsearch.showcase.databinding.ListItemActorBinding + +class ActorViewHolder(private val binding: ListItemActorBinding) : + RecyclerView.ViewHolder(binding.root) { + + fun bind(actor: Actor) { + binding.actorName.text = actor.name + } +} diff --git a/showcase/android-view/src/main/kotlin/com/algolia/instantsearch/showcase/list/actor/ActorViewHolderSmall.kt b/showcase/android-view/src/main/kotlin/com/algolia/instantsearch/showcase/list/actor/ActorViewHolderSmall.kt new file mode 100644 index 00000000..c58a2804 --- /dev/null +++ b/showcase/android-view/src/main/kotlin/com/algolia/instantsearch/showcase/list/actor/ActorViewHolderSmall.kt @@ -0,0 +1,12 @@ +package com.algolia.instantsearch.showcase.list.actor + +import androidx.recyclerview.widget.RecyclerView +import com.algolia.instantsearch.showcase.databinding.ListItemSmallBinding + +class ActorViewHolderSmall(val binding: ListItemSmallBinding) : + RecyclerView.ViewHolder(binding.root) { + + fun bind(actor: Actor) { + binding.itemName.text = actor.name + } +} diff --git a/showcase/src/main/kotlin/com/algolia/instantsearch/showcase/list/header/HeaderViewHolder.kt b/showcase/android-view/src/main/kotlin/com/algolia/instantsearch/showcase/list/header/HeaderViewHolder.kt similarity index 99% rename from showcase/src/main/kotlin/com/algolia/instantsearch/showcase/list/header/HeaderViewHolder.kt rename to showcase/android-view/src/main/kotlin/com/algolia/instantsearch/showcase/list/header/HeaderViewHolder.kt index 54740499..29d6a566 100644 --- a/showcase/src/main/kotlin/com/algolia/instantsearch/showcase/list/header/HeaderViewHolder.kt +++ b/showcase/android-view/src/main/kotlin/com/algolia/instantsearch/showcase/list/header/HeaderViewHolder.kt @@ -3,10 +3,9 @@ package com.algolia.instantsearch.showcase.list.header import android.widget.TextView import androidx.recyclerview.widget.RecyclerView - class HeaderViewHolder(val view: TextView) : RecyclerView.ViewHolder(view) { fun bind(string: String) { view.text = string } -} \ No newline at end of file +} diff --git a/showcase/android-view/src/main/kotlin/com/algolia/instantsearch/showcase/list/merged/ActorsAdapter.kt b/showcase/android-view/src/main/kotlin/com/algolia/instantsearch/showcase/list/merged/ActorsAdapter.kt new file mode 100644 index 00000000..531722b0 --- /dev/null +++ b/showcase/android-view/src/main/kotlin/com/algolia/instantsearch/showcase/list/merged/ActorsAdapter.kt @@ -0,0 +1,45 @@ +package com.algolia.instantsearch.showcase.list.merged + +import android.view.ViewGroup +import androidx.recyclerview.widget.DiffUtil +import androidx.recyclerview.widget.ListAdapter +import com.algolia.instantsearch.core.hits.HitsView +import com.algolia.instantsearch.showcase.databinding.ListItemSmallBinding +import com.algolia.instantsearch.showcase.layoutInflater +import com.algolia.instantsearch.showcase.list.actor.Actor +import com.algolia.instantsearch.showcase.list.actor.ActorViewHolderSmall + +class ActorsAdapter : ListAdapter(ActorsAdapter), HitsView { + + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ActorViewHolderSmall { + return ActorViewHolderSmall( + ListItemSmallBinding.inflate(parent.layoutInflater, parent, false) + ) + } + + override fun onBindViewHolder(holder: ActorViewHolderSmall, position: Int) { + val product = getItem(position) + if (product != null) holder.bind(product) + } + + companion object : DiffUtil.ItemCallback() { + + override fun areItemsTheSame( + oldItem: Actor, + newItem: Actor + ): Boolean { + return oldItem.objectID == newItem.objectID + } + + override fun areContentsTheSame( + oldItem: Actor, + newItem: Actor + ): Boolean { + return oldItem == newItem + } + } + + override fun setHits(hits: List) { + submitList(hits) + } +} diff --git a/showcase/android-view/src/main/kotlin/com/algolia/instantsearch/showcase/list/merged/MergedListShowcase.kt b/showcase/android-view/src/main/kotlin/com/algolia/instantsearch/showcase/list/merged/MergedListShowcase.kt new file mode 100644 index 00000000..9763e4a2 --- /dev/null +++ b/showcase/android-view/src/main/kotlin/com/algolia/instantsearch/showcase/list/merged/MergedListShowcase.kt @@ -0,0 +1,69 @@ +package com.algolia.instantsearch.showcase.list.merged + +import android.os.Bundle +import androidx.appcompat.app.AppCompatActivity +import com.algolia.instantsearch.core.connection.ConnectionHandler +import com.algolia.instantsearch.core.hits.connectHitsView +import com.algolia.instantsearch.android.searchbox.SearchBoxViewAppCompat +import com.algolia.instantsearch.searchbox.SearchBoxConnector +import com.algolia.instantsearch.searchbox.connectView +import com.algolia.instantsearch.searcher.hits.addHitsSearcher +import com.algolia.instantsearch.searcher.multi.MultiSearcher +import com.algolia.instantsearch.showcase.* +import com.algolia.instantsearch.showcase.databinding.IncludeSearchBinding +import com.algolia.instantsearch.showcase.databinding.ShowcaseMultisearchBinding +import com.algolia.instantsearch.showcase.list.actor.Actor +import com.algolia.instantsearch.showcase.list.movie.Movie +import com.algolia.instantsearch.showcase.list.movie.MovieAdapter +import com.algolia.search.helper.deserialize +import com.algolia.search.model.IndexName +import com.algolia.search.model.search.Query + +class MergedListShowcase : AppCompatActivity() { + + private val multiSearcher = MultiSearcher(client) + private val actorsSearcher = multiSearcher.addHitsSearcher( + indexName = IndexName("mobile_demo_actors"), + query = Query(hitsPerPage = 5) + ) + private val moviesSearcher = multiSearcher.addHitsSearcher( + indexName = IndexName("mobile_demo_movies"), + query = Query(hitsPerPage = 3) + ) + private val searchBox = SearchBoxConnector(multiSearcher) + private val connection = ConnectionHandler(searchBox) + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + val binding = ShowcaseMultisearchBinding.inflate(layoutInflater) + val searchBinding = IncludeSearchBinding.bind(binding.searchBox.root) + setContentView(binding.root) + + val actorsAdapter = ActorsAdapter() + val moviesAdapter = MovieAdapter() + val searchBoxView = SearchBoxViewAppCompat(searchBinding.searchView) + + connection += searchBox.connectView(searchBoxView) + connection += actorsSearcher.connectHitsView(actorsAdapter) { response -> + response.hits.deserialize(Actor.serializer()) + } + connection += moviesSearcher.connectHitsView(moviesAdapter) { response -> + response.hits.deserialize(Movie.serializer()) + } + + configureToolbar(binding.toolbar) + configureSearchView(searchBinding.searchView, getString(R.string.search_movies)) + configureTitle(binding.title1, getString(R.string.actors)) + configureTitle(binding.title2, getString(R.string.movies)) + configureRecyclerView(binding.hits1, actorsAdapter) + configureRecyclerView(binding.hits2, moviesAdapter) + + multiSearcher.searchAsync() + } + + override fun onDestroy() { + super.onDestroy() + multiSearcher.cancel() + connection.clear() + } +} diff --git a/showcase/src/main/kotlin/com/algolia/instantsearch/showcase/list/movie/Movie.kt b/showcase/android-view/src/main/kotlin/com/algolia/instantsearch/showcase/list/movie/Movie.kt similarity index 92% rename from showcase/src/main/kotlin/com/algolia/instantsearch/showcase/list/movie/Movie.kt rename to showcase/android-view/src/main/kotlin/com/algolia/instantsearch/showcase/list/movie/Movie.kt index bac3f6b3..2a846d32 100644 --- a/showcase/src/main/kotlin/com/algolia/instantsearch/showcase/list/movie/Movie.kt +++ b/showcase/android-view/src/main/kotlin/com/algolia/instantsearch/showcase/list/movie/Movie.kt @@ -1,6 +1,6 @@ package com.algolia.instantsearch.showcase.list.movie -import com.algolia.instantsearch.helper.highlighting.Highlightable +import com.algolia.instantsearch.highlighting.Highlightable import com.algolia.search.model.Attribute import com.algolia.search.model.ObjectID import com.algolia.search.model.indexing.Indexable diff --git a/showcase/src/main/kotlin/com/algolia/instantsearch/showcase/list/movie/MovieAdapter.kt b/showcase/android-view/src/main/kotlin/com/algolia/instantsearch/showcase/list/movie/MovieAdapter.kt similarity index 70% rename from showcase/src/main/kotlin/com/algolia/instantsearch/showcase/list/movie/MovieAdapter.kt rename to showcase/android-view/src/main/kotlin/com/algolia/instantsearch/showcase/list/movie/MovieAdapter.kt index 540a5b2e..40848f64 100644 --- a/showcase/src/main/kotlin/com/algolia/instantsearch/showcase/list/movie/MovieAdapter.kt +++ b/showcase/android-view/src/main/kotlin/com/algolia/instantsearch/showcase/list/movie/MovieAdapter.kt @@ -3,14 +3,15 @@ package com.algolia.instantsearch.showcase.list.movie import android.view.ViewGroup import androidx.recyclerview.widget.ListAdapter import com.algolia.instantsearch.core.hits.HitsView -import com.algolia.instantsearch.showcase.R -import com.algolia.instantsearch.helper.android.inflate - +import com.algolia.instantsearch.showcase.databinding.ListItemLargeBinding +import com.algolia.instantsearch.showcase.layoutInflater class MovieAdapter : ListAdapter(MovieDiffUtil), HitsView { override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MovieViewHolder { - return MovieViewHolder(parent.inflate(R.layout.list_item_large)) + return MovieViewHolder( + ListItemLargeBinding.inflate(parent.layoutInflater, parent, false) + ) } override fun onBindViewHolder(holder: MovieViewHolder, position: Int) { @@ -22,4 +23,4 @@ class MovieAdapter : ListAdapter(MovieDiffUtil), HitsVie override fun setHits(hits: List) { submitList(hits) } -} \ No newline at end of file +} diff --git a/showcase/android-view/src/main/kotlin/com/algolia/instantsearch/showcase/list/movie/MovieAdapterNested.kt b/showcase/android-view/src/main/kotlin/com/algolia/instantsearch/showcase/list/movie/MovieAdapterNested.kt new file mode 100644 index 00000000..6a9c5500 --- /dev/null +++ b/showcase/android-view/src/main/kotlin/com/algolia/instantsearch/showcase/list/movie/MovieAdapterNested.kt @@ -0,0 +1,28 @@ +package com.algolia.instantsearch.showcase.list.movie + +import android.view.ViewGroup +import androidx.paging.PagingDataAdapter +import com.algolia.instantsearch.showcase.databinding.ListItemMovieBinding +import com.algolia.instantsearch.showcase.dip +import com.algolia.instantsearch.showcase.layoutInflater + +class MovieAdapterNested : PagingDataAdapter(MovieDiffUtil) { + + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MovieViewHolderNested { + val dip8 = parent.context.dip(8) + val layoutParams = + ViewGroup.MarginLayoutParams(parent.width / 2, ViewGroup.LayoutParams.MATCH_PARENT) + .apply { + setMargins(dip8, dip8, dip8, dip8) + } + val binding = ListItemMovieBinding.inflate(parent.layoutInflater, parent, false).apply { + root.layoutParams = layoutParams + } + return MovieViewHolderNested(binding) + } + + override fun onBindViewHolder(holder: MovieViewHolderNested, position: Int) { + val item = getItem(position) + if (item != null) holder.bind(item) + } +} diff --git a/showcase/android-view/src/main/kotlin/com/algolia/instantsearch/showcase/list/movie/MovieAdapterPaged.kt b/showcase/android-view/src/main/kotlin/com/algolia/instantsearch/showcase/list/movie/MovieAdapterPaged.kt new file mode 100644 index 00000000..695354be --- /dev/null +++ b/showcase/android-view/src/main/kotlin/com/algolia/instantsearch/showcase/list/movie/MovieAdapterPaged.kt @@ -0,0 +1,21 @@ +package com.algolia.instantsearch.showcase.list.movie + +import android.view.ViewGroup +import androidx.paging.PagingDataAdapter +import com.algolia.instantsearch.showcase.databinding.ListItemLargeBinding +import com.algolia.instantsearch.showcase.layoutInflater + +class MovieAdapterPaged : PagingDataAdapter(MovieDiffUtil) { + + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MovieViewHolder { + return MovieViewHolder( + ListItemLargeBinding.inflate(parent.layoutInflater, parent, false) + ) + } + + override fun onBindViewHolder(holder: MovieViewHolder, position: Int) { + val item = getItem(position) + + if (item != null) holder.bind(item) + } +} diff --git a/showcase/src/main/kotlin/com/algolia/instantsearch/showcase/list/movie/MovieDiffUtil.kt b/showcase/android-view/src/main/kotlin/com/algolia/instantsearch/showcase/list/movie/MovieDiffUtil.kt similarity index 99% rename from showcase/src/main/kotlin/com/algolia/instantsearch/showcase/list/movie/MovieDiffUtil.kt rename to showcase/android-view/src/main/kotlin/com/algolia/instantsearch/showcase/list/movie/MovieDiffUtil.kt index 5ae47b69..89159197 100644 --- a/showcase/src/main/kotlin/com/algolia/instantsearch/showcase/list/movie/MovieDiffUtil.kt +++ b/showcase/android-view/src/main/kotlin/com/algolia/instantsearch/showcase/list/movie/MovieDiffUtil.kt @@ -2,7 +2,6 @@ package com.algolia.instantsearch.showcase.list.movie import androidx.recyclerview.widget.DiffUtil - object MovieDiffUtil : DiffUtil.ItemCallback() { override fun areItemsTheSame( @@ -18,4 +17,4 @@ object MovieDiffUtil : DiffUtil.ItemCallback() { ): Boolean { return oldItem == newItem } -} \ No newline at end of file +} diff --git a/showcase/android-view/src/main/kotlin/com/algolia/instantsearch/showcase/list/movie/MovieViewHolder.kt b/showcase/android-view/src/main/kotlin/com/algolia/instantsearch/showcase/list/movie/MovieViewHolder.kt new file mode 100644 index 00000000..cfaf8e28 --- /dev/null +++ b/showcase/android-view/src/main/kotlin/com/algolia/instantsearch/showcase/list/movie/MovieViewHolder.kt @@ -0,0 +1,22 @@ +package com.algolia.instantsearch.showcase.list.movie + +import android.text.TextUtils +import androidx.core.text.buildSpannedString +import androidx.core.text.italic +import androidx.recyclerview.widget.RecyclerView +import com.algolia.instantsearch.android.highlighting.toSpannedString +import com.algolia.instantsearch.showcase.databinding.ListItemLargeBinding +import com.bumptech.glide.Glide + +class MovieViewHolder(private val binding: ListItemLargeBinding) : RecyclerView.ViewHolder(binding.root) { + + fun bind(movie: Movie) { + binding.itemTitle.text = TextUtils.concat(movie.highlightedTitle?.toSpannedString(), " (${movie.year})") + binding.itemSubtitle.text = movie.highlightedGenres?.toSpannedString() + ?: buildSpannedString { italic { append("unknown genre") } } + Glide.with(binding.root) + .load(movie.image).placeholder(android.R.drawable.ic_media_play) + .centerCrop() + .into(binding.itemImage) + } +} diff --git a/showcase/android-view/src/main/kotlin/com/algolia/instantsearch/showcase/list/movie/MovieViewHolderNested.kt b/showcase/android-view/src/main/kotlin/com/algolia/instantsearch/showcase/list/movie/MovieViewHolderNested.kt new file mode 100644 index 00000000..1f1b8b85 --- /dev/null +++ b/showcase/android-view/src/main/kotlin/com/algolia/instantsearch/showcase/list/movie/MovieViewHolderNested.kt @@ -0,0 +1,19 @@ +package com.algolia.instantsearch.showcase.list.movie + +import androidx.recyclerview.widget.RecyclerView +import com.algolia.instantsearch.showcase.databinding.ListItemMovieBinding +import com.bumptech.glide.Glide + +class MovieViewHolderNested(private val binding: ListItemMovieBinding) : + RecyclerView.ViewHolder(binding.root) { + + fun bind(movie: Movie) { + binding.itemTitle.text = movie.title + binding.itemSubtitle.text = movie.genre.sorted().joinToString { it } + binding.itemCaption.text = movie.year + Glide.with(binding.root) + .load(movie.image).placeholder(android.R.drawable.ic_media_play) + .centerCrop() + .into(binding.itemImage) + } +} diff --git a/showcase/src/main/kotlin/com/algolia/instantsearch/showcase/list/paging/PagingMultipleIndexAdapter.kt b/showcase/android-view/src/main/kotlin/com/algolia/instantsearch/showcase/list/paging/PagingMultiSearchAdapter.kt similarity index 72% rename from showcase/src/main/kotlin/com/algolia/instantsearch/showcase/list/paging/PagingMultipleIndexAdapter.kt rename to showcase/android-view/src/main/kotlin/com/algolia/instantsearch/showcase/list/paging/PagingMultiSearchAdapter.kt index a5f5a505..557f8eeb 100644 --- a/showcase/src/main/kotlin/com/algolia/instantsearch/showcase/list/paging/PagingMultipleIndexAdapter.kt +++ b/showcase/android-view/src/main/kotlin/com/algolia/instantsearch/showcase/list/paging/PagingMultiSearchAdapter.kt @@ -1,22 +1,31 @@ package com.algolia.instantsearch.showcase.list.paging -import android.annotation.SuppressLint import android.view.ViewGroup -import android.widget.TextView import androidx.recyclerview.widget.DiffUtil import androidx.recyclerview.widget.ListAdapter import androidx.recyclerview.widget.RecyclerView -import com.algolia.instantsearch.showcase.R +import com.algolia.instantsearch.showcase.databinding.HeaderItemBinding import com.algolia.instantsearch.showcase.dip -import com.algolia.instantsearch.helper.android.inflate +import com.algolia.instantsearch.showcase.layoutInflater +class PagingMultiSearchAdapter : + ListAdapter(this) { -class PagingMultipleIndexAdapter : ListAdapter(this) { - - private enum class ViewType { - Header, - Movies, - Actors + override fun onCreateViewHolder( + parent: ViewGroup, + viewType: Int + ): PagingMultipleIndexViewHolder { + return when (ViewType.values()[viewType]) { + ViewType.Header -> PagingMultipleIndexViewHolder.Header( + HeaderItemBinding.inflate(parent.layoutInflater, parent, false) + ) + ViewType.Movies -> PagingMultipleIndexViewHolder.Movies( + recyclerView(parent) + ) + ViewType.Actors -> PagingMultipleIndexViewHolder.Actors( + recyclerView(parent) + ) + } } private fun recyclerView(parent: ViewGroup): RecyclerView { @@ -31,20 +40,6 @@ class PagingMultipleIndexAdapter : ListAdapter PagingMultipleIndexViewHolder.Header( - parent.inflate(R.layout.header_item) - ) - ViewType.Movies -> PagingMultipleIndexViewHolder.Movies( - recyclerView(parent) - ) - ViewType.Actors -> PagingMultipleIndexViewHolder.Actors( - recyclerView(parent) - ) - } - } - override fun onBindViewHolder(holder: PagingMultipleIndexViewHolder, position: Int) { val item = getItem(position) @@ -63,15 +58,24 @@ class PagingMultipleIndexAdapter : ListAdapter() { - override fun areItemsTheSame(oldItem: PagingMultipleIndexItem, newItem: PagingMultipleIndexItem): Boolean { + override fun areItemsTheSame( + oldItem: PagingMultipleIndexItem, + newItem: PagingMultipleIndexItem + ): Boolean { return oldItem == newItem } - @SuppressLint("DiffUtilEquals") // all subclasses are data classes - override fun areContentsTheSame(oldItem: PagingMultipleIndexItem, newItem: PagingMultipleIndexItem): Boolean { + override fun areContentsTheSame( + oldItem: PagingMultipleIndexItem, + newItem: PagingMultipleIndexItem + ): Boolean { return oldItem == newItem } } -} \ No newline at end of file +} diff --git a/showcase/src/main/kotlin/com/algolia/instantsearch/showcase/list/paging/PagingMultipleIndexItem.kt b/showcase/android-view/src/main/kotlin/com/algolia/instantsearch/showcase/list/paging/PagingMultipleIndexItem.kt similarity index 100% rename from showcase/src/main/kotlin/com/algolia/instantsearch/showcase/list/paging/PagingMultipleIndexItem.kt rename to showcase/android-view/src/main/kotlin/com/algolia/instantsearch/showcase/list/paging/PagingMultipleIndexItem.kt diff --git a/showcase/android-view/src/main/kotlin/com/algolia/instantsearch/showcase/list/paging/PagingMultipleIndexShowcase.kt b/showcase/android-view/src/main/kotlin/com/algolia/instantsearch/showcase/list/paging/PagingMultipleIndexShowcase.kt new file mode 100644 index 00000000..179363d8 --- /dev/null +++ b/showcase/android-view/src/main/kotlin/com/algolia/instantsearch/showcase/list/paging/PagingMultipleIndexShowcase.kt @@ -0,0 +1,72 @@ +package com.algolia.instantsearch.showcase.list.paging + +import android.os.Bundle +import androidx.appcompat.app.AppCompatActivity +import androidx.paging.PagingConfig +import com.algolia.instantsearch.android.paging3.Paginator +import com.algolia.instantsearch.android.paging3.liveData +import com.algolia.instantsearch.android.paging3.searchbox.connectPaginator +import com.algolia.instantsearch.android.searchbox.SearchBoxViewAppCompat +import com.algolia.instantsearch.core.connection.ConnectionHandler +import com.algolia.instantsearch.searchbox.SearchBoxConnector +import com.algolia.instantsearch.searchbox.connectView +import com.algolia.instantsearch.searcher.hits.addHitsSearcher +import com.algolia.instantsearch.searcher.multi.MultiSearcher +import com.algolia.instantsearch.showcase.* +import com.algolia.instantsearch.showcase.databinding.IncludeSearchBinding +import com.algolia.instantsearch.showcase.databinding.ShowcaseSearchBinding +import com.algolia.instantsearch.showcase.list.actor.Actor +import com.algolia.instantsearch.showcase.list.actor.ActorAdapterNested +import com.algolia.instantsearch.showcase.list.movie.Movie +import com.algolia.instantsearch.showcase.list.movie.MovieAdapterNested +import com.algolia.search.model.IndexName + +class PagingMultipleIndexShowcase : AppCompatActivity() { + + private val multiSearcher = MultiSearcher(client) + private val moviesSearcher = multiSearcher.addHitsSearcher(IndexName("mobile_demo_movies")) + private val actorsSearcher = multiSearcher.addHitsSearcher(IndexName("mobile_demo_actors")) + private val pagingConfig = PagingConfig(pageSize = 10, enablePlaceholders = false) + private val moviesPaginator = Paginator(moviesSearcher, pagingConfig) { it.deserialize(Movie.serializer()) } + private val actorsPaginator = Paginator(actorsSearcher, pagingConfig) { it.deserialize(Actor.serializer()) } + private val searchBox = SearchBoxConnector(multiSearcher) + private val connection = ConnectionHandler(searchBox) + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + val binding = ShowcaseSearchBinding.inflate(layoutInflater) + val searchBinding = IncludeSearchBinding.bind(binding.searchBox.root) + setContentView(binding.root) + + val adapterActor = ActorAdapterNested() + val adapterMovie = MovieAdapterNested() + val adapter = PagingMultiSearchAdapter() + + actorsPaginator.liveData.observe(this) { adapterActor.submitData(lifecycle, it) } + moviesPaginator.liveData.observe(this) { adapterMovie.submitData(lifecycle, it) } + + adapter.submitList( + listOf( + PagingMultipleIndexItem.Header("Movies"), + PagingMultipleIndexItem.Movies(adapterMovie), + PagingMultipleIndexItem.Header("Actors"), + PagingMultipleIndexItem.Actors(adapterActor) + ) + ) + + val searchBoxView = SearchBoxViewAppCompat(searchBinding.searchView) + connection += searchBox.connectView(searchBoxView) + connection += searchBox.connectPaginator(moviesPaginator) + connection += searchBox.connectPaginator(actorsPaginator) + + configureToolbar(binding.toolbar) + configureSearchView(searchBinding.searchView, getString(R.string.search_movies)) + configureRecyclerView(binding.hits, adapter) + } + + override fun onDestroy() { + super.onDestroy() + multiSearcher.cancel() + connection.clear() + } +} diff --git a/showcase/src/main/kotlin/com/algolia/instantsearch/showcase/list/paging/PagingMultipleIndexViewHolder.kt b/showcase/android-view/src/main/kotlin/com/algolia/instantsearch/showcase/list/paging/PagingMultipleIndexViewHolder.kt similarity index 77% rename from showcase/src/main/kotlin/com/algolia/instantsearch/showcase/list/paging/PagingMultipleIndexViewHolder.kt rename to showcase/android-view/src/main/kotlin/com/algolia/instantsearch/showcase/list/paging/PagingMultipleIndexViewHolder.kt index 724f3a4e..01ac0e53 100644 --- a/showcase/src/main/kotlin/com/algolia/instantsearch/showcase/list/paging/PagingMultipleIndexViewHolder.kt +++ b/showcase/android-view/src/main/kotlin/com/algolia/instantsearch/showcase/list/paging/PagingMultipleIndexViewHolder.kt @@ -1,26 +1,26 @@ package com.algolia.instantsearch.showcase.list.paging import android.view.View -import android.widget.TextView import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.RecyclerView -import com.algolia.instantsearch.helper.android.list.autoScrollToStart +import com.algolia.instantsearch.android.list.autoScrollToStart +import com.algolia.instantsearch.showcase.databinding.HeaderItemBinding sealed class PagingMultipleIndexViewHolder( view: View ) : RecyclerView.ViewHolder(view) { - data class Header( - val view: TextView - ) : PagingMultipleIndexViewHolder(view) { + class Header( + val binding: HeaderItemBinding + ) : PagingMultipleIndexViewHolder(binding.root) { fun bind(item: PagingMultipleIndexItem.Header) { - view.text = item.name + binding.root.text = item.name } } - data class Movies( + class Movies( val view: RecyclerView ) : PagingMultipleIndexViewHolder(view) { @@ -33,7 +33,7 @@ sealed class PagingMultipleIndexViewHolder( } } - data class Actors( + class Actors( val view: RecyclerView ) : PagingMultipleIndexViewHolder(view) { @@ -45,4 +45,4 @@ sealed class PagingMultipleIndexViewHolder( } } } -} \ No newline at end of file +} diff --git a/showcase/android-view/src/main/kotlin/com/algolia/instantsearch/showcase/list/paging/PagingSingleIndexShowcase.kt b/showcase/android-view/src/main/kotlin/com/algolia/instantsearch/showcase/list/paging/PagingSingleIndexShowcase.kt new file mode 100644 index 00000000..6cfc25c7 --- /dev/null +++ b/showcase/android-view/src/main/kotlin/com/algolia/instantsearch/showcase/list/paging/PagingSingleIndexShowcase.kt @@ -0,0 +1,56 @@ +package com.algolia.instantsearch.showcase.list.paging + +import android.os.Bundle +import androidx.appcompat.app.AppCompatActivity +import androidx.paging.PagingConfig +import com.algolia.instantsearch.android.paging3.Paginator +import com.algolia.instantsearch.android.paging3.liveData +import com.algolia.instantsearch.android.paging3.searchbox.connectPaginator +import com.algolia.instantsearch.android.searchbox.SearchBoxViewAppCompat +import com.algolia.instantsearch.core.connection.ConnectionHandler +import com.algolia.instantsearch.searchbox.SearchBoxConnector +import com.algolia.instantsearch.searchbox.connectView +import com.algolia.instantsearch.searcher.hits.HitsSearcher +import com.algolia.instantsearch.showcase.* +import com.algolia.instantsearch.showcase.databinding.IncludeSearchBinding +import com.algolia.instantsearch.showcase.databinding.ShowcasePagingBinding +import com.algolia.instantsearch.showcase.list.movie.Movie +import com.algolia.instantsearch.showcase.list.movie.MovieAdapterPaged + +class PagingSingleIndexShowcase : AppCompatActivity() { + + private val searcher = HitsSearcher(client, stubIndexName) + private val paginator = Paginator( + searcher = searcher, + pagingConfig = PagingConfig(pageSize = 10, enablePlaceholders = false) + ) { it.deserialize(Movie.serializer()) } + private val searchBox = SearchBoxConnector(searcher) + private val connection = ConnectionHandler(searchBox) + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + val binding = ShowcasePagingBinding.inflate(layoutInflater) + val searchBinding = IncludeSearchBinding.bind(binding.searchBox.root) + setContentView(binding.root) + + val adapter = MovieAdapterPaged() + val searchBoxView = SearchBoxViewAppCompat(searchBinding.searchView) + + connection += searchBox.connectView(searchBoxView) + connection += searchBox.connectPaginator(paginator) + + paginator.liveData.observe(this) { adapter.submitData(lifecycle, it) } + + configureToolbar(binding.toolbar) + configureSearcher(searcher) + configureSearchView(searchBinding.searchView, getString(R.string.search_movies)) + configureRecyclerView(binding.hits, adapter) + onResponseChangedThenUpdateNbHits(searcher, binding.nbHits, connection) + } + + override fun onDestroy() { + super.onDestroy() + searcher.cancel() + connection.clear() + } +} diff --git a/showcase/src/main/kotlin/com/algolia/instantsearch/showcase/list/product/Product.kt b/showcase/android-view/src/main/kotlin/com/algolia/instantsearch/showcase/list/product/Product.kt similarity index 100% rename from showcase/src/main/kotlin/com/algolia/instantsearch/showcase/list/product/Product.kt rename to showcase/android-view/src/main/kotlin/com/algolia/instantsearch/showcase/list/product/Product.kt diff --git a/showcase/src/main/kotlin/com/algolia/instantsearch/showcase/list/product/ProductAdapter.kt b/showcase/android-view/src/main/kotlin/com/algolia/instantsearch/showcase/list/product/ProductAdapter.kt similarity index 63% rename from showcase/src/main/kotlin/com/algolia/instantsearch/showcase/list/product/ProductAdapter.kt rename to showcase/android-view/src/main/kotlin/com/algolia/instantsearch/showcase/list/product/ProductAdapter.kt index 4651826e..532fc9ad 100644 --- a/showcase/src/main/kotlin/com/algolia/instantsearch/showcase/list/product/ProductAdapter.kt +++ b/showcase/android-view/src/main/kotlin/com/algolia/instantsearch/showcase/list/product/ProductAdapter.kt @@ -1,25 +1,23 @@ package com.algolia.instantsearch.showcase.list.product -import android.view.View import android.view.ViewGroup import androidx.recyclerview.widget.DiffUtil import androidx.recyclerview.widget.ListAdapter import androidx.recyclerview.widget.RecyclerView import com.algolia.instantsearch.core.hits.HitsView -import com.algolia.instantsearch.helper.android.inflate -import com.algolia.instantsearch.showcase.R +import com.algolia.instantsearch.showcase.databinding.ListItemProductBinding +import com.algolia.instantsearch.showcase.layoutInflater import com.bumptech.glide.Glide -import kotlinx.android.synthetic.main.list_item_product.view.itemBrand -import kotlinx.android.synthetic.main.list_item_product.view.itemImage -import kotlinx.android.synthetic.main.list_item_product.view.itemName -import kotlinx.android.synthetic.main.list_item_product.view.itemType -class ProductAdapter : ListAdapter(ProductDiffUtil), HitsView { +class ProductAdapter : ListAdapter(ProductDiffUtil), + HitsView { var callback: ((Product) -> Unit)? = null override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ProductViewHolder { - return ProductViewHolder(parent.inflate(R.layout.list_item_product)) + return ProductViewHolder( + ListItemProductBinding.inflate(parent.layoutInflater, parent, false) + ) } override fun onBindViewHolder(holder: ProductViewHolder, position: Int) { @@ -34,16 +32,17 @@ class ProductAdapter : ListAdapter(Pr submitList(hits) } - class ProductViewHolder(private val view: View) : RecyclerView.ViewHolder(view) { + class ProductViewHolder(private val binding: ListItemProductBinding) : + RecyclerView.ViewHolder(binding.root) { fun bind(product: Product) { - view.itemName.text = product.name - view.itemBrand.text = product.brand - view.itemType.text = product.type - Glide.with(view) + binding.itemName.text = product.name + binding.itemBrand.text = product.brand + binding.itemType.text = product.type + Glide.with(binding.root) .load(product.image).placeholder(android.R.drawable.ic_media_play) .centerCrop() - .into(view.itemImage) + .into(binding.itemImage) } } diff --git a/showcase/android-view/src/main/kotlin/com/algolia/instantsearch/showcase/loading/LoadingShowcase.kt b/showcase/android-view/src/main/kotlin/com/algolia/instantsearch/showcase/loading/LoadingShowcase.kt new file mode 100644 index 00000000..6a424b5a --- /dev/null +++ b/showcase/android-view/src/main/kotlin/com/algolia/instantsearch/showcase/loading/LoadingShowcase.kt @@ -0,0 +1,63 @@ +package com.algolia.instantsearch.showcase.loading + +import android.os.Bundle +import androidx.appcompat.app.AppCompatActivity +import androidx.paging.PagingConfig +import com.algolia.instantsearch.android.loading.LoadingViewSwipeRefreshLayout +import com.algolia.instantsearch.android.paging3.Paginator +import com.algolia.instantsearch.android.paging3.liveData +import com.algolia.instantsearch.android.paging3.searchbox.connectPaginator +import com.algolia.instantsearch.android.searchbox.SearchBoxViewAppCompat +import com.algolia.instantsearch.core.connection.ConnectionHandler +import com.algolia.instantsearch.loading.LoadingConnector +import com.algolia.instantsearch.loading.connectView +import com.algolia.instantsearch.searchbox.SearchBoxConnector +import com.algolia.instantsearch.searchbox.connectView +import com.algolia.instantsearch.searcher.hits.HitsSearcher +import com.algolia.instantsearch.showcase.* +import com.algolia.instantsearch.showcase.databinding.IncludeSearchBinding +import com.algolia.instantsearch.showcase.databinding.ShowcaseLoadingBinding +import com.algolia.instantsearch.showcase.list.movie.Movie +import com.algolia.instantsearch.showcase.list.movie.MovieAdapterPaged + +class LoadingShowcase : AppCompatActivity() { + + private val searcher = HitsSearcher(client, stubIndexName) + private val paginator = Paginator( + searcher = searcher, + pagingConfig = PagingConfig(pageSize = 10, enablePlaceholders = false) + ) { hit -> hit.deserialize(Movie.serializer()) } + private val loading = LoadingConnector(searcher) + private val searchBox = SearchBoxConnector(searcher) + private val connection = ConnectionHandler(loading, searchBox) + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + val binding = ShowcaseLoadingBinding.inflate(layoutInflater) + val searchBinding = IncludeSearchBinding.bind(binding.searchBox.root) + setContentView(binding.root) + + val view = LoadingViewSwipeRefreshLayout(binding.swipeRefreshLayout) + val searchBoxView = SearchBoxViewAppCompat(searchBinding.searchView) + val adapter = MovieAdapterPaged() + + connection += loading.connectView(view) + connection += searchBox.connectView(searchBoxView) + connection += searchBox.connectPaginator(paginator) + + paginator.liveData.observe(this) { pagingData -> adapter.submitData(lifecycle, pagingData) } + + configureSearcher(searcher) + configureToolbar(binding.toolbar) + configureSearchView(searchBinding.searchView, getString(R.string.search_movies)) + configureRecyclerView(binding.hits, adapter) + + searcher.searchAsync() + } + + override fun onDestroy() { + super.onDestroy() + searcher.cancel() + connection.clear() + } +} diff --git a/showcase/src/main/kotlin/com/algolia/instantsearch/showcase/relateditems/RelatedItemsShowcase.kt b/showcase/android-view/src/main/kotlin/com/algolia/instantsearch/showcase/relateditems/RelatedItemsShowcase.kt similarity index 66% rename from showcase/src/main/kotlin/com/algolia/instantsearch/showcase/relateditems/RelatedItemsShowcase.kt rename to showcase/android-view/src/main/kotlin/com/algolia/instantsearch/showcase/relateditems/RelatedItemsShowcase.kt index d2c0dc02..00593c12 100644 --- a/showcase/src/main/kotlin/com/algolia/instantsearch/showcase/relateditems/RelatedItemsShowcase.kt +++ b/showcase/android-view/src/main/kotlin/com/algolia/instantsearch/showcase/relateditems/RelatedItemsShowcase.kt @@ -4,43 +4,40 @@ import android.os.Bundle import androidx.appcompat.app.AppCompatActivity import com.algolia.instantsearch.core.connection.ConnectionHandler import com.algolia.instantsearch.core.hits.connectHitsView -import com.algolia.instantsearch.helper.relateditems.MatchingPattern -import com.algolia.instantsearch.helper.relateditems.connectRelatedHitsView -import com.algolia.instantsearch.helper.searcher.SearcherSingleIndex -import com.algolia.instantsearch.showcase.R -import com.algolia.instantsearch.showcase.configureRecyclerView -import com.algolia.instantsearch.showcase.configureSearcher -import com.algolia.instantsearch.showcase.configureToolbar +import com.algolia.instantsearch.relateditems.MatchingPattern +import com.algolia.instantsearch.relateditems.connectRelatedHitsView +import com.algolia.instantsearch.searcher.hits.HitsSearcher +import com.algolia.instantsearch.showcase.* +import com.algolia.instantsearch.showcase.databinding.ShowcaseRelateditemsBinding import com.algolia.instantsearch.showcase.list.product.Product import com.algolia.instantsearch.showcase.list.product.ProductAdapter -import com.algolia.instantsearch.showcase.stubIndex import com.algolia.search.helper.deserialize import com.algolia.search.model.Attribute -import kotlinx.android.synthetic.main.showcase_relateditems.* class RelatedItemsShowcase : AppCompatActivity() { - private val searcher = SearcherSingleIndex(stubIndex) - private val relatedItemsSearcher = SearcherSingleIndex(stubIndex) + private val searcher = HitsSearcher(client, stubIndexName) + private val relatedItemsSearcher = HitsSearcher(client, stubIndexName) private val connection = ConnectionHandler() override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) - setContentView(R.layout.showcase_relateditems) + val binding = ShowcaseRelateditemsBinding.inflate(layoutInflater) + setContentView(binding.root) searcher.query.hitsPerPage = 3 // Limit to 3 results - configureToolbar(toolbar) + configureToolbar(binding.toolbar) configureSearcher(searcher) configureSearcher(relatedItemsSearcher) val hitsAdapter = ProductAdapter() - configureRecyclerView(hits, hitsAdapter) + configureRecyclerView(binding.hits, hitsAdapter) connection += searcher.connectHitsView(hitsAdapter) { response -> response.hits.deserialize(Product.serializer()) } val relatedItemsAdapter = ProductAdapter() - configureRecyclerView(relatedItems, relatedItemsAdapter) + configureRecyclerView(binding.relatedItems, relatedItemsAdapter) val matchingPatterns: List> = listOf( MatchingPattern(Attribute("brand"), 1, Product::brand), MatchingPattern(Attribute("categories"), 2, Product::categories) diff --git a/showcase/src/main/kotlin/com/algolia/instantsearch/showcase/search/SearchAsYouTypeShowcase.kt b/showcase/android-view/src/main/kotlin/com/algolia/instantsearch/showcase/search/SearchAsYouTypeShowcase.kt similarity index 55% rename from showcase/src/main/kotlin/com/algolia/instantsearch/showcase/search/SearchAsYouTypeShowcase.kt rename to showcase/android-view/src/main/kotlin/com/algolia/instantsearch/showcase/search/SearchAsYouTypeShowcase.kt index 51fb21a2..00658be6 100644 --- a/showcase/src/main/kotlin/com/algolia/instantsearch/showcase/search/SearchAsYouTypeShowcase.kt +++ b/showcase/android-view/src/main/kotlin/com/algolia/instantsearch/showcase/search/SearchAsYouTypeShowcase.kt @@ -4,39 +4,40 @@ import android.os.Bundle import androidx.appcompat.app.AppCompatActivity import com.algolia.instantsearch.core.connection.ConnectionHandler import com.algolia.instantsearch.core.hits.connectHitsView +import com.algolia.instantsearch.android.searchbox.SearchBoxViewAppCompat +import com.algolia.instantsearch.searchbox.SearchBoxConnector +import com.algolia.instantsearch.searchbox.SearchMode +import com.algolia.instantsearch.searchbox.connectView +import com.algolia.instantsearch.searcher.hits.HitsSearcher import com.algolia.instantsearch.showcase.* +import com.algolia.instantsearch.showcase.databinding.IncludeSearchBinding +import com.algolia.instantsearch.showcase.databinding.ShowcaseSearchBinding import com.algolia.instantsearch.showcase.list.movie.Movie import com.algolia.instantsearch.showcase.list.movie.MovieAdapter -import com.algolia.instantsearch.helper.android.searchbox.SearchBoxViewAppCompat -import com.algolia.instantsearch.helper.searchbox.SearchBoxConnector -import com.algolia.instantsearch.helper.searchbox.SearchMode -import com.algolia.instantsearch.helper.searchbox.connectView -import com.algolia.instantsearch.helper.searcher.SearcherSingleIndex import com.algolia.search.helper.deserialize -import kotlinx.android.synthetic.main.showcase_search.* -import kotlinx.android.synthetic.main.include_search.* - class SearchAsYouTypeShowcase : AppCompatActivity() { - private val searcher = SearcherSingleIndex(stubIndex) + private val searcher = HitsSearcher(client, stubIndexName) private val searchBox = SearchBoxConnector(searcher, searchMode = SearchMode.AsYouType) private val connection = ConnectionHandler(searchBox) override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) - setContentView(R.layout.showcase_search) + val binding = ShowcaseSearchBinding.inflate(layoutInflater) + val searchBinding = IncludeSearchBinding.bind(binding.searchBox.root) + setContentView(binding.root) val adapter = MovieAdapter() - val searchBoxView = SearchBoxViewAppCompat(searchView) + val searchBoxView = SearchBoxViewAppCompat(searchBinding.searchView) connection += searchBox.connectView(searchBoxView) connection += searcher.connectHitsView(adapter) { response -> response.hits.deserialize(Movie.serializer()) } - configureToolbar(toolbar) + configureToolbar(binding.toolbar) configureSearcher(searcher) - configureRecyclerView(hits, adapter) - configureSearchView(searchView, getString(R.string.search_movies)) + configureRecyclerView(binding.hits, adapter) + configureSearchView(searchBinding.searchView, getString(R.string.search_movies)) searcher.searchAsync() } diff --git a/showcase/android-view/src/main/kotlin/com/algolia/instantsearch/showcase/search/SearchAutoCompleteTextView.kt b/showcase/android-view/src/main/kotlin/com/algolia/instantsearch/showcase/search/SearchAutoCompleteTextView.kt new file mode 100644 index 00000000..94f05120 --- /dev/null +++ b/showcase/android-view/src/main/kotlin/com/algolia/instantsearch/showcase/search/SearchAutoCompleteTextView.kt @@ -0,0 +1,57 @@ +package com.algolia.instantsearch.showcase.search + +import android.os.Build +import android.os.Bundle +import android.widget.ArrayAdapter +import androidx.annotation.RequiresApi +import androidx.appcompat.app.AppCompatActivity +import com.algolia.instantsearch.core.connection.ConnectionHandler +import com.algolia.instantsearch.android.hits.HitsArrayAdapter +import com.algolia.instantsearch.android.hits.connectHitsArrayAdapter +import com.algolia.instantsearch.android.searchbox.SearchBoxAutoCompleteTextView +import com.algolia.instantsearch.searchbox.SearchBoxConnector +import com.algolia.instantsearch.searchbox.SearchMode +import com.algolia.instantsearch.searchbox.connectView +import com.algolia.instantsearch.searcher.hits.HitsSearcher +import com.algolia.instantsearch.showcase.client +import com.algolia.instantsearch.showcase.configureSearcher +import com.algolia.instantsearch.showcase.databinding.ShowcaseSearchAutocompleteBinding +import com.algolia.instantsearch.showcase.list.movie.Movie +import com.algolia.instantsearch.showcase.stubIndexName +import com.algolia.search.helper.deserialize + +class SearchAutoCompleteTextView : AppCompatActivity() { + + private val searcher = HitsSearcher(client, stubIndexName) + private val searchBox = SearchBoxConnector(searcher, searchMode = SearchMode.AsYouType) + private val connection = ConnectionHandler(searchBox) + + @RequiresApi(Build.VERSION_CODES.Q) + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + val binding = ShowcaseSearchAutocompleteBinding.inflate(layoutInflater) + setContentView(binding.root) + + val adapter = ArrayAdapter(this, android.R.layout.simple_list_item_1) + val hitsAdapter = HitsArrayAdapter(adapter) + val searchBoxView = SearchBoxAutoCompleteTextView(binding.autoCompleteTextView) + + binding.autoCompleteTextView.setAdapter(adapter) + connection += searchBox.connectView(searchBoxView) + connection += searcher.connectHitsArrayAdapter( + hitsAdapter, + binding.autoCompleteTextView + ) { response -> + response.hits.deserialize(Movie.serializer()).map { it.title } + } + + configureSearcher(searcher) + searcher.searchAsync() + } + + override fun onDestroy() { + super.onDestroy() + searcher.cancel() + connection.clear() + } +} diff --git a/showcase/src/main/kotlin/com/algolia/instantsearch/showcase/search/SearchOnSubmitShowcase.kt b/showcase/android-view/src/main/kotlin/com/algolia/instantsearch/showcase/search/SearchOnSubmitShowcase.kt similarity index 55% rename from showcase/src/main/kotlin/com/algolia/instantsearch/showcase/search/SearchOnSubmitShowcase.kt rename to showcase/android-view/src/main/kotlin/com/algolia/instantsearch/showcase/search/SearchOnSubmitShowcase.kt index e322913e..096566c7 100644 --- a/showcase/src/main/kotlin/com/algolia/instantsearch/showcase/search/SearchOnSubmitShowcase.kt +++ b/showcase/android-view/src/main/kotlin/com/algolia/instantsearch/showcase/search/SearchOnSubmitShowcase.kt @@ -4,41 +4,42 @@ import android.os.Bundle import androidx.appcompat.app.AppCompatActivity import com.algolia.instantsearch.core.connection.ConnectionHandler import com.algolia.instantsearch.core.hits.connectHitsView +import com.algolia.instantsearch.android.searchbox.SearchBoxViewAppCompat +import com.algolia.instantsearch.searchbox.SearchBoxConnector +import com.algolia.instantsearch.searchbox.SearchMode +import com.algolia.instantsearch.searchbox.connectView +import com.algolia.instantsearch.searcher.hits.HitsSearcher import com.algolia.instantsearch.showcase.* +import com.algolia.instantsearch.showcase.databinding.IncludeSearchBinding +import com.algolia.instantsearch.showcase.databinding.ShowcaseSearchBinding import com.algolia.instantsearch.showcase.list.movie.Movie import com.algolia.instantsearch.showcase.list.movie.MovieAdapter -import com.algolia.instantsearch.helper.android.searchbox.SearchBoxViewAppCompat -import com.algolia.instantsearch.helper.searchbox.SearchBoxConnector -import com.algolia.instantsearch.helper.searchbox.SearchMode -import com.algolia.instantsearch.helper.searchbox.connectView -import com.algolia.instantsearch.helper.searcher.SearcherSingleIndex import com.algolia.search.helper.deserialize -import kotlinx.android.synthetic.main.showcase_search.* -import kotlinx.android.synthetic.main.include_search.* - class SearchOnSubmitShowcase : AppCompatActivity() { - private val searcher = SearcherSingleIndex(stubIndex) + private val searcher = HitsSearcher(client, stubIndexName) private val searchBox = SearchBoxConnector(searcher, searchMode = SearchMode.OnSubmit) private val connection = ConnectionHandler(searchBox) override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) - setContentView(R.layout.showcase_search) + val binding = ShowcaseSearchBinding.inflate(layoutInflater) + val searchBinding = IncludeSearchBinding.bind(binding.searchBox.root) + setContentView(binding.root) val adapter = MovieAdapter() - val searchBoxView = SearchBoxViewAppCompat(searchView) + val searchBoxView = SearchBoxViewAppCompat(searchBinding.searchView) connection += searchBox.connectView(searchBoxView) connection += searcher.connectHitsView(adapter) { response -> response.hits.deserialize(Movie.serializer()) } - configureToolbar(toolbar) + configureToolbar(binding.toolbar) configureSearcher(searcher) - configureRecyclerView(hits, adapter) - configureSearchView(searchView, getString(R.string.search_movies)) + configureRecyclerView(binding.hits, adapter) + configureSearchView(searchBinding.searchView, getString(R.string.search_movies)) searcher.searchAsync() } diff --git a/showcase/src/main/kotlin/com/algolia/instantsearch/showcase/sortby/SortByShowcase.kt b/showcase/android-view/src/main/kotlin/com/algolia/instantsearch/showcase/sortby/SortByShowcase.kt similarity index 60% rename from showcase/src/main/kotlin/com/algolia/instantsearch/showcase/sortby/SortByShowcase.kt rename to showcase/android-view/src/main/kotlin/com/algolia/instantsearch/showcase/sortby/SortByShowcase.kt index a0431c31..fac1f666 100644 --- a/showcase/src/main/kotlin/com/algolia/instantsearch/showcase/sortby/SortByShowcase.kt +++ b/showcase/android-view/src/main/kotlin/com/algolia/instantsearch/showcase/sortby/SortByShowcase.kt @@ -5,57 +5,57 @@ import android.widget.ArrayAdapter import androidx.appcompat.app.AppCompatActivity import com.algolia.instantsearch.core.connection.ConnectionHandler import com.algolia.instantsearch.core.hits.connectHitsView +import com.algolia.instantsearch.android.sortby.SortByViewAutocomplete +import com.algolia.instantsearch.searcher.hits.HitsSearcher +import com.algolia.instantsearch.sortby.SortByConnector +import com.algolia.instantsearch.sortby.connectView import com.algolia.instantsearch.showcase.R import com.algolia.instantsearch.showcase.client import com.algolia.instantsearch.showcase.configureRecyclerView import com.algolia.instantsearch.showcase.configureToolbar +import com.algolia.instantsearch.showcase.databinding.ShowcaseSortByBinding import com.algolia.instantsearch.showcase.list.movie.Movie import com.algolia.instantsearch.showcase.list.movie.MovieAdapter -import com.algolia.instantsearch.helper.android.sortby.SortByViewAutocomplete -import com.algolia.instantsearch.helper.searcher.SearcherSingleIndex -import com.algolia.instantsearch.helper.sortby.SortByConnector -import com.algolia.instantsearch.helper.sortby.connectView import com.algolia.search.helper.deserialize import com.algolia.search.model.IndexName -import kotlinx.android.synthetic.main.showcase_sort_by.* - class SortByShowcase : AppCompatActivity() { - private val indexTitle = client.initIndex(IndexName("mobile_demo_movies")) - private val indexYearAsc = client.initIndex(IndexName("mobile_demo_movies_year_asc")) - private val indexYearDesc = client.initIndex(IndexName("mobile_demo_movies_year_desc")) - private val searcher = SearcherSingleIndex(indexTitle) + private val indexTitle = IndexName("mobile_demo_movies") + private val indexYearAsc = IndexName("mobile_demo_movies_year_asc") + private val indexYearDesc = IndexName("mobile_demo_movies_year_desc") + private val searcher = HitsSearcher(client, indexTitle) private val indexes = mapOf( 0 to indexTitle, 1 to indexYearAsc, 2 to indexYearDesc ) - private val sortBy = SortByConnector(indexes, searcher, selected = 0) + private val sortBy = SortByConnector(searcher, indexes, selected = 0) private val connection = ConnectionHandler(sortBy) override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) - setContentView(R.layout.showcase_sort_by) + val binding = ShowcaseSortByBinding.inflate(layoutInflater) + setContentView(binding.root) val adapter = ArrayAdapter(this, R.layout.menu_item) - val view = SortByViewAutocomplete(autoCompleteTextView, adapter) + val view = SortByViewAutocomplete(binding.autoCompleteTextView, adapter) val adapterMovie = MovieAdapter() - connection += sortBy.connectView(view) { index -> - when (index) { + connection += sortBy.connectView(view) { indexName -> + when (indexName) { indexTitle -> "Default" indexYearAsc -> "Year Asc" indexYearDesc -> "Year Desc" - else -> index.indexName.raw + else -> indexName.raw } } connection += searcher.connectHitsView(adapterMovie) { response -> response.hits.deserialize(Movie.serializer()) } - configureToolbar(toolbar) - configureRecyclerView(hits, adapterMovie) + configureToolbar(binding.toolbar) + configureRecyclerView(binding.hits, adapterMovie) searcher.searchAsync() } diff --git a/showcase/src/main/kotlin/com/algolia/instantsearch/showcase/stats/StatsShowcase.kt b/showcase/android-view/src/main/kotlin/com/algolia/instantsearch/showcase/stats/StatsShowcase.kt similarity index 55% rename from showcase/src/main/kotlin/com/algolia/instantsearch/showcase/stats/StatsShowcase.kt rename to showcase/android-view/src/main/kotlin/com/algolia/instantsearch/showcase/stats/StatsShowcase.kt index 0ad5847a..47fbfafd 100644 --- a/showcase/src/main/kotlin/com/algolia/instantsearch/showcase/stats/StatsShowcase.kt +++ b/showcase/android-view/src/main/kotlin/com/algolia/instantsearch/showcase/stats/StatsShowcase.kt @@ -6,31 +6,31 @@ import androidx.appcompat.app.AppCompatActivity import androidx.core.text.bold import androidx.core.text.buildSpannedString import com.algolia.instantsearch.core.connection.ConnectionHandler +import com.algolia.instantsearch.android.stats.StatsTextView +import com.algolia.instantsearch.android.stats.StatsTextViewSpanned +import com.algolia.instantsearch.searcher.hits.HitsSearcher +import com.algolia.instantsearch.stats.StatsConnector +import com.algolia.instantsearch.stats.StatsPresenter +import com.algolia.instantsearch.stats.StatsPresenterImpl +import com.algolia.instantsearch.stats.connectView import com.algolia.instantsearch.showcase.* -import com.algolia.instantsearch.helper.android.stats.StatsTextView -import com.algolia.instantsearch.helper.android.stats.StatsTextViewSpanned -import com.algolia.instantsearch.helper.searcher.SearcherSingleIndex -import com.algolia.instantsearch.helper.stats.StatsConnector -import com.algolia.instantsearch.helper.stats.StatsPresenter -import com.algolia.instantsearch.helper.stats.StatsPresenterImpl -import com.algolia.instantsearch.helper.stats.connectView -import kotlinx.android.synthetic.main.showcase_paging.toolbar -import kotlinx.android.synthetic.main.showcase_stats.* -import kotlinx.android.synthetic.main.include_search.* - +import com.algolia.instantsearch.showcase.databinding.IncludeSearchBinding +import com.algolia.instantsearch.showcase.databinding.ShowcaseStatsBinding class StatsShowcase : AppCompatActivity() { - private val searcher = SearcherSingleIndex(stubIndex) + private val searcher = HitsSearcher(client, stubIndexName) private val stats = StatsConnector(searcher) private val connection = ConnectionHandler(stats) override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) - setContentView(R.layout.showcase_stats) + val binding = ShowcaseStatsBinding.inflate(layoutInflater) + val searchBinding = IncludeSearchBinding.bind(binding.searchBox.root) + setContentView(binding.root) - val statsViewA = StatsTextView(statsA) - val statsViewB = StatsTextViewSpanned(statsB) + val statsViewA = StatsTextView(binding.statsA) + val statsViewB = StatsTextViewSpanned(binding.statsB) val presenter: StatsPresenter = { response -> buildSpannedString { if (response != null) { @@ -48,10 +48,10 @@ class StatsShowcase : AppCompatActivity() { connection += stats.connectView(statsViewA, StatsPresenterImpl()) connection += stats.connectView(statsViewB, presenter) - configureToolbar(toolbar) + configureToolbar(binding.toolbar) configureSearcher(searcher) - configureSearchView(searchView, getString(R.string.search_movies)) - configureSearchBox(searchView, searcher, connection) + configureSearchView(searchBinding.searchView, getString(R.string.search_movies)) + configureSearchBox(searchBinding.searchView, searcher, connection) searcher.searchAsync() } @@ -61,4 +61,4 @@ class StatsShowcase : AppCompatActivity() { searcher.cancel() connection.clear() } -} \ No newline at end of file +} diff --git a/showcase/src/main/res/drawable-anydpi/ic_filter_list.xml b/showcase/android-view/src/main/res/drawable-anydpi/ic_filter_list.xml similarity index 100% rename from showcase/src/main/res/drawable-anydpi/ic_filter_list.xml rename to showcase/android-view/src/main/res/drawable-anydpi/ic_filter_list.xml diff --git a/showcase/src/main/res/drawable-v24/ic_launcher_foreground.xml b/showcase/android-view/src/main/res/drawable-v24/ic_launcher_foreground.xml similarity index 100% rename from showcase/src/main/res/drawable-v24/ic_launcher_foreground.xml rename to showcase/android-view/src/main/res/drawable-v24/ic_launcher_foreground.xml diff --git a/showcase/src/main/res/drawable/ic_add.xml b/showcase/android-view/src/main/res/drawable/ic_add.xml similarity index 100% rename from showcase/src/main/res/drawable/ic_add.xml rename to showcase/android-view/src/main/res/drawable/ic_add.xml diff --git a/showcase/src/main/res/drawable/ic_arrow_down.xml b/showcase/android-view/src/main/res/drawable/ic_arrow_down.xml similarity index 100% rename from showcase/src/main/res/drawable/ic_arrow_down.xml rename to showcase/android-view/src/main/res/drawable/ic_arrow_down.xml diff --git a/showcase/src/main/res/drawable/ic_arrow_up.xml b/showcase/android-view/src/main/res/drawable/ic_arrow_up.xml similarity index 100% rename from showcase/src/main/res/drawable/ic_arrow_up.xml rename to showcase/android-view/src/main/res/drawable/ic_arrow_up.xml diff --git a/showcase/src/main/res/drawable/ic_check.xml b/showcase/android-view/src/main/res/drawable/ic_check.xml similarity index 100% rename from showcase/src/main/res/drawable/ic_check.xml rename to showcase/android-view/src/main/res/drawable/ic_check.xml diff --git a/insights/src/main/res/drawable/ic_close_hint.xml b/showcase/android-view/src/main/res/drawable/ic_close_hint.xml similarity index 100% rename from insights/src/main/res/drawable/ic_close_hint.xml rename to showcase/android-view/src/main/res/drawable/ic_close_hint.xml diff --git a/showcase/src/main/res/drawable/ic_delete.xml b/showcase/android-view/src/main/res/drawable/ic_delete.xml similarity index 100% rename from showcase/src/main/res/drawable/ic_delete.xml rename to showcase/android-view/src/main/res/drawable/ic_delete.xml diff --git a/showcase/src/main/res/drawable/ic_info.xml b/showcase/android-view/src/main/res/drawable/ic_info.xml similarity index 100% rename from showcase/src/main/res/drawable/ic_info.xml rename to showcase/android-view/src/main/res/drawable/ic_info.xml diff --git a/showcase/src/main/res/drawable/ic_launcher_background.xml b/showcase/android-view/src/main/res/drawable/ic_launcher_background.xml similarity index 100% rename from showcase/src/main/res/drawable/ic_launcher_background.xml rename to showcase/android-view/src/main/res/drawable/ic_launcher_background.xml diff --git a/showcase/src/main/res/drawable/ic_microphone_outline.xml b/showcase/android-view/src/main/res/drawable/ic_microphone_outline.xml similarity index 100% rename from showcase/src/main/res/drawable/ic_microphone_outline.xml rename to showcase/android-view/src/main/res/drawable/ic_microphone_outline.xml diff --git a/showcase/src/main/res/drawable/ic_remove.xml b/showcase/android-view/src/main/res/drawable/ic_remove.xml similarity index 100% rename from showcase/src/main/res/drawable/ic_remove.xml rename to showcase/android-view/src/main/res/drawable/ic_remove.xml diff --git a/showcase/src/main/res/drawable/ic_restore.xml b/showcase/android-view/src/main/res/drawable/ic_restore.xml similarity index 100% rename from showcase/src/main/res/drawable/ic_restore.xml rename to showcase/android-view/src/main/res/drawable/ic_restore.xml diff --git a/showcase/src/main/res/drawable/ic_search_hint.xml b/showcase/android-view/src/main/res/drawable/ic_search_hint.xml similarity index 100% rename from showcase/src/main/res/drawable/ic_search_hint.xml rename to showcase/android-view/src/main/res/drawable/ic_search_hint.xml diff --git a/insights/src/main/res/drawable/query_background.xml b/showcase/android-view/src/main/res/drawable/query_background.xml similarity index 100% rename from insights/src/main/res/drawable/query_background.xml rename to showcase/android-view/src/main/res/drawable/query_background.xml diff --git a/showcase/src/main/res/drawable/rectangle.xml b/showcase/android-view/src/main/res/drawable/rectangle.xml similarity index 100% rename from showcase/src/main/res/drawable/rectangle.xml rename to showcase/android-view/src/main/res/drawable/rectangle.xml diff --git a/showcase-compose/src/main/res/drawable/thumb.xml b/showcase/android-view/src/main/res/drawable/thumb.xml similarity index 100% rename from showcase-compose/src/main/res/drawable/thumb.xml rename to showcase/android-view/src/main/res/drawable/thumb.xml diff --git a/showcase/src/main/res/layout/filter_chip.xml b/showcase/android-view/src/main/res/layout/filter_chip.xml similarity index 100% rename from showcase/src/main/res/layout/filter_chip.xml rename to showcase/android-view/src/main/res/layout/filter_chip.xml diff --git a/showcase/src/main/res/layout/header_filter.xml b/showcase/android-view/src/main/res/layout/header_filter.xml similarity index 100% rename from showcase/src/main/res/layout/header_filter.xml rename to showcase/android-view/src/main/res/layout/header_filter.xml diff --git a/showcase/src/main/res/layout/header_item.xml b/showcase/android-view/src/main/res/layout/header_item.xml similarity index 100% rename from showcase/src/main/res/layout/header_item.xml rename to showcase/android-view/src/main/res/layout/header_item.xml diff --git a/showcase/src/main/res/layout/include_list.xml b/showcase/android-view/src/main/res/layout/include_list.xml similarity index 100% rename from showcase/src/main/res/layout/include_list.xml rename to showcase/android-view/src/main/res/layout/include_list.xml diff --git a/showcase/src/main/res/layout/include_plus_minus.xml b/showcase/android-view/src/main/res/layout/include_plus_minus.xml similarity index 100% rename from showcase/src/main/res/layout/include_plus_minus.xml rename to showcase/android-view/src/main/res/layout/include_plus_minus.xml diff --git a/showcase/src/main/res/layout/include_search.xml b/showcase/android-view/src/main/res/layout/include_search.xml similarity index 100% rename from showcase/src/main/res/layout/include_search.xml rename to showcase/android-view/src/main/res/layout/include_search.xml diff --git a/showcase/src/main/res/layout/include_search_info.xml b/showcase/android-view/src/main/res/layout/include_search_info.xml similarity index 100% rename from showcase/src/main/res/layout/include_search_info.xml rename to showcase/android-view/src/main/res/layout/include_search_info.xml diff --git a/showcase/src/main/res/layout/list_item_actor.xml b/showcase/android-view/src/main/res/layout/list_item_actor.xml similarity index 100% rename from showcase/src/main/res/layout/list_item_actor.xml rename to showcase/android-view/src/main/res/layout/list_item_actor.xml diff --git a/showcase/src/main/res/layout/list_item_highlighting.xml b/showcase/android-view/src/main/res/layout/list_item_highlighting.xml similarity index 100% rename from showcase/src/main/res/layout/list_item_highlighting.xml rename to showcase/android-view/src/main/res/layout/list_item_highlighting.xml diff --git a/showcase/src/main/res/layout/list_item_large.xml b/showcase/android-view/src/main/res/layout/list_item_large.xml similarity index 100% rename from showcase/src/main/res/layout/list_item_large.xml rename to showcase/android-view/src/main/res/layout/list_item_large.xml diff --git a/showcase/src/main/res/layout/list_item_movie.xml b/showcase/android-view/src/main/res/layout/list_item_movie.xml similarity index 100% rename from showcase/src/main/res/layout/list_item_movie.xml rename to showcase/android-view/src/main/res/layout/list_item_movie.xml diff --git a/showcase/src/main/res/layout/list_item_product.xml b/showcase/android-view/src/main/res/layout/list_item_product.xml similarity index 100% rename from showcase/src/main/res/layout/list_item_product.xml rename to showcase/android-view/src/main/res/layout/list_item_product.xml diff --git a/showcase/src/main/res/layout/list_item_selectable.xml b/showcase/android-view/src/main/res/layout/list_item_selectable.xml similarity index 100% rename from showcase/src/main/res/layout/list_item_selectable.xml rename to showcase/android-view/src/main/res/layout/list_item_selectable.xml diff --git a/showcase/src/main/res/layout/list_item_small.xml b/showcase/android-view/src/main/res/layout/list_item_small.xml similarity index 100% rename from showcase/src/main/res/layout/list_item_small.xml rename to showcase/android-view/src/main/res/layout/list_item_small.xml diff --git a/showcase/src/main/res/layout/menu_item.xml b/showcase/android-view/src/main/res/layout/menu_item.xml similarity index 100% rename from showcase/src/main/res/layout/menu_item.xml rename to showcase/android-view/src/main/res/layout/menu_item.xml diff --git a/showcase/src/main/res/layout/showcase_directory.xml b/showcase/android-view/src/main/res/layout/showcase_directory.xml similarity index 93% rename from showcase/src/main/res/layout/showcase_directory.xml rename to showcase/android-view/src/main/res/layout/showcase_directory.xml index 6149b8c8..e0126d2a 100644 --- a/showcase/src/main/res/layout/showcase_directory.xml +++ b/showcase/android-view/src/main/res/layout/showcase_directory.xml @@ -14,7 +14,7 @@ app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent"> - + diff --git a/showcase/src/main/res/layout/showcase_dynamic_facet_list.xml b/showcase/android-view/src/main/res/layout/showcase_dynamic_facet_list.xml similarity index 93% rename from showcase/src/main/res/layout/showcase_dynamic_facet_list.xml rename to showcase/android-view/src/main/res/layout/showcase_dynamic_facet_list.xml index 9f5b7437..7e61421f 100644 --- a/showcase/src/main/res/layout/showcase_dynamic_facet_list.xml +++ b/showcase/android-view/src/main/res/layout/showcase_dynamic_facet_list.xml @@ -13,7 +13,7 @@ app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent"> - + diff --git a/showcase/src/main/res/layout/showcase_facet_list.xml b/showcase/android-view/src/main/res/layout/showcase_facet_list.xml similarity index 97% rename from showcase/src/main/res/layout/showcase_facet_list.xml rename to showcase/android-view/src/main/res/layout/showcase_facet_list.xml index 549a991a..23c927a6 100644 --- a/showcase/src/main/res/layout/showcase_facet_list.xml +++ b/showcase/android-view/src/main/res/layout/showcase_facet_list.xml @@ -16,6 +16,7 @@ tools:title="Title" /> - + - + diff --git a/showcase/src/main/res/layout/showcase_filter_clear.xml b/showcase/android-view/src/main/res/layout/showcase_filter_clear.xml similarity index 100% rename from showcase/src/main/res/layout/showcase_filter_clear.xml rename to showcase/android-view/src/main/res/layout/showcase_filter_clear.xml diff --git a/showcase/src/main/res/layout/showcase_filter_comparison.xml b/showcase/android-view/src/main/res/layout/showcase_filter_comparison.xml similarity index 100% rename from showcase/src/main/res/layout/showcase_filter_comparison.xml rename to showcase/android-view/src/main/res/layout/showcase_filter_comparison.xml diff --git a/showcase/src/main/res/layout/showcase_filter_current.xml b/showcase/android-view/src/main/res/layout/showcase_filter_current.xml similarity index 100% rename from showcase/src/main/res/layout/showcase_filter_current.xml rename to showcase/android-view/src/main/res/layout/showcase_filter_current.xml diff --git a/showcase/src/main/res/layout/showcase_filter_list.xml b/showcase/android-view/src/main/res/layout/showcase_filter_list.xml similarity index 97% rename from showcase/src/main/res/layout/showcase_filter_list.xml rename to showcase/android-view/src/main/res/layout/showcase_filter_list.xml index 4afe7deb..b834993e 100644 --- a/showcase/src/main/res/layout/showcase_filter_list.xml +++ b/showcase/android-view/src/main/res/layout/showcase_filter_list.xml @@ -16,6 +16,7 @@ tools:title="Title" /> - + diff --git a/showcase/src/main/res/layout/showcase_loading.xml b/showcase/android-view/src/main/res/layout/showcase_loading.xml similarity index 94% rename from showcase/src/main/res/layout/showcase_loading.xml rename to showcase/android-view/src/main/res/layout/showcase_loading.xml index 506453b4..0ef26caf 100644 --- a/showcase/src/main/res/layout/showcase_loading.xml +++ b/showcase/android-view/src/main/res/layout/showcase_loading.xml @@ -15,7 +15,7 @@ app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent"> - + diff --git a/showcase/android-view/src/main/res/layout/showcase_multisearch.xml b/showcase/android-view/src/main/res/layout/showcase_multisearch.xml new file mode 100644 index 00000000..59f2b5e6 --- /dev/null +++ b/showcase/android-view/src/main/res/layout/showcase_multisearch.xml @@ -0,0 +1,73 @@ + + + + + + + + + + + + + + + + + + diff --git a/showcase/src/main/res/layout/showcase_paging.xml b/showcase/android-view/src/main/res/layout/showcase_paging.xml similarity index 96% rename from showcase/src/main/res/layout/showcase_paging.xml rename to showcase/android-view/src/main/res/layout/showcase_paging.xml index b965913b..7ac3c4d0 100644 --- a/showcase/src/main/res/layout/showcase_paging.xml +++ b/showcase/android-view/src/main/res/layout/showcase_paging.xml @@ -28,7 +28,7 @@ app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent"> - + diff --git a/showcase/src/main/res/layout/showcase_query_rule_custom_data.xml b/showcase/android-view/src/main/res/layout/showcase_query_rule_custom_data.xml similarity index 96% rename from showcase/src/main/res/layout/showcase_query_rule_custom_data.xml rename to showcase/android-view/src/main/res/layout/showcase_query_rule_custom_data.xml index 3a37ac21..0ffeae70 100644 --- a/showcase/src/main/res/layout/showcase_query_rule_custom_data.xml +++ b/showcase/android-view/src/main/res/layout/showcase_query_rule_custom_data.xml @@ -14,7 +14,7 @@ app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent"> - + diff --git a/showcase/src/main/res/layout/showcase_query_rule_custom_data_template.xml b/showcase/android-view/src/main/res/layout/showcase_query_rule_custom_data_template.xml similarity index 100% rename from showcase/src/main/res/layout/showcase_query_rule_custom_data_template.xml rename to showcase/android-view/src/main/res/layout/showcase_query_rule_custom_data_template.xml diff --git a/showcase/src/main/res/layout/showcase_relateditems.xml b/showcase/android-view/src/main/res/layout/showcase_relateditems.xml similarity index 100% rename from showcase/src/main/res/layout/showcase_relateditems.xml rename to showcase/android-view/src/main/res/layout/showcase_relateditems.xml diff --git a/showcase/src/main/res/layout/showcase_search.xml b/showcase/android-view/src/main/res/layout/showcase_search.xml similarity index 93% rename from showcase/src/main/res/layout/showcase_search.xml rename to showcase/android-view/src/main/res/layout/showcase_search.xml index e7026903..923c7362 100644 --- a/showcase/src/main/res/layout/showcase_search.xml +++ b/showcase/android-view/src/main/res/layout/showcase_search.xml @@ -15,7 +15,7 @@ app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent"> - + diff --git a/showcase/src/main/res/layout/showcase_search_autocomplete.xml b/showcase/android-view/src/main/res/layout/showcase_search_autocomplete.xml similarity index 100% rename from showcase/src/main/res/layout/showcase_search_autocomplete.xml rename to showcase/android-view/src/main/res/layout/showcase_search_autocomplete.xml diff --git a/showcase/src/main/res/layout/showcase_sort_by.xml b/showcase/android-view/src/main/res/layout/showcase_sort_by.xml similarity index 100% rename from showcase/src/main/res/layout/showcase_sort_by.xml rename to showcase/android-view/src/main/res/layout/showcase_sort_by.xml diff --git a/showcase/src/main/res/layout/showcase_stats.xml b/showcase/android-view/src/main/res/layout/showcase_stats.xml similarity index 95% rename from showcase/src/main/res/layout/showcase_stats.xml rename to showcase/android-view/src/main/res/layout/showcase_stats.xml index c3895888..3a643859 100644 --- a/showcase/src/main/res/layout/showcase_stats.xml +++ b/showcase/android-view/src/main/res/layout/showcase_stats.xml @@ -40,7 +40,7 @@ app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent"> - + diff --git a/showcase/src/main/res/mipmap-anydpi-v26/ic_launcher.xml b/showcase/android-view/src/main/res/mipmap-anydpi-v26/ic_launcher.xml similarity index 100% rename from showcase/src/main/res/mipmap-anydpi-v26/ic_launcher.xml rename to showcase/android-view/src/main/res/mipmap-anydpi-v26/ic_launcher.xml diff --git a/showcase/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml b/showcase/android-view/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml similarity index 100% rename from showcase/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml rename to showcase/android-view/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml diff --git a/showcase/src/main/res/mipmap-hdpi/ic_launcher.png b/showcase/android-view/src/main/res/mipmap-hdpi/ic_launcher.png similarity index 100% rename from showcase/src/main/res/mipmap-hdpi/ic_launcher.png rename to showcase/android-view/src/main/res/mipmap-hdpi/ic_launcher.png diff --git a/showcase/src/main/res/mipmap-hdpi/ic_launcher_round.png b/showcase/android-view/src/main/res/mipmap-hdpi/ic_launcher_round.png similarity index 100% rename from showcase/src/main/res/mipmap-hdpi/ic_launcher_round.png rename to showcase/android-view/src/main/res/mipmap-hdpi/ic_launcher_round.png diff --git a/showcase/src/main/res/mipmap-mdpi/ic_launcher.png b/showcase/android-view/src/main/res/mipmap-mdpi/ic_launcher.png similarity index 100% rename from showcase/src/main/res/mipmap-mdpi/ic_launcher.png rename to showcase/android-view/src/main/res/mipmap-mdpi/ic_launcher.png diff --git a/showcase/src/main/res/mipmap-mdpi/ic_launcher_round.png b/showcase/android-view/src/main/res/mipmap-mdpi/ic_launcher_round.png similarity index 100% rename from showcase/src/main/res/mipmap-mdpi/ic_launcher_round.png rename to showcase/android-view/src/main/res/mipmap-mdpi/ic_launcher_round.png diff --git a/showcase/src/main/res/mipmap-xhdpi/ic_launcher.png b/showcase/android-view/src/main/res/mipmap-xhdpi/ic_launcher.png similarity index 100% rename from showcase/src/main/res/mipmap-xhdpi/ic_launcher.png rename to showcase/android-view/src/main/res/mipmap-xhdpi/ic_launcher.png diff --git a/showcase/src/main/res/mipmap-xhdpi/ic_launcher_round.png b/showcase/android-view/src/main/res/mipmap-xhdpi/ic_launcher_round.png similarity index 100% rename from showcase/src/main/res/mipmap-xhdpi/ic_launcher_round.png rename to showcase/android-view/src/main/res/mipmap-xhdpi/ic_launcher_round.png diff --git a/showcase/src/main/res/mipmap-xxhdpi/ic_launcher.png b/showcase/android-view/src/main/res/mipmap-xxhdpi/ic_launcher.png similarity index 100% rename from showcase/src/main/res/mipmap-xxhdpi/ic_launcher.png rename to showcase/android-view/src/main/res/mipmap-xxhdpi/ic_launcher.png diff --git a/showcase/src/main/res/mipmap-xxhdpi/ic_launcher_round.png b/showcase/android-view/src/main/res/mipmap-xxhdpi/ic_launcher_round.png similarity index 100% rename from showcase/src/main/res/mipmap-xxhdpi/ic_launcher_round.png rename to showcase/android-view/src/main/res/mipmap-xxhdpi/ic_launcher_round.png diff --git a/showcase/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/showcase/android-view/src/main/res/mipmap-xxxhdpi/ic_launcher.png similarity index 100% rename from showcase/src/main/res/mipmap-xxxhdpi/ic_launcher.png rename to showcase/android-view/src/main/res/mipmap-xxxhdpi/ic_launcher.png diff --git a/showcase/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png b/showcase/android-view/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png similarity index 100% rename from showcase/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png rename to showcase/android-view/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png diff --git a/showcase/src/main/res/values/colors.xml b/showcase/android-view/src/main/res/values/colors.xml similarity index 100% rename from showcase/src/main/res/values/colors.xml rename to showcase/android-view/src/main/res/values/colors.xml diff --git a/showcase/src/main/res/values/strings.xml b/showcase/android-view/src/main/res/values/strings.xml similarity index 96% rename from showcase/src/main/res/values/strings.xml rename to showcase/android-view/src/main/res/values/strings.xml index 12f30918..1cf10aa8 100644 --- a/showcase/src/main/res/values/strings.xml +++ b/showcase/android-view/src/main/res/values/strings.xml @@ -33,4 +33,6 @@ OK Redirect via banner tap Redirect via submit + Actors + Movies diff --git a/showcase/src/main/res/values/styles.xml b/showcase/android-view/src/main/res/values/styles.xml similarity index 100% rename from showcase/src/main/res/values/styles.xml rename to showcase/android-view/src/main/res/values/styles.xml diff --git a/showcase-compose/build.gradle b/showcase/compose/build.gradle similarity index 85% rename from showcase-compose/build.gradle rename to showcase/compose/build.gradle index 5a0e1933..d88aea0a 100644 --- a/showcase-compose/build.gradle +++ b/showcase/compose/build.gradle @@ -46,17 +46,17 @@ android { dependencies { implementation "com.algolia:instantsearch-compose:$instantsearch" - implementation 'androidx.core:core-ktx:1.6.0' - implementation 'androidx.appcompat:appcompat:1.3.1' + implementation "com.algolia:instantsearch-android-paging3:$instantsearch" + + implementation 'androidx.core:core-ktx:1.7.0' + implementation 'androidx.appcompat:appcompat:1.4.0' implementation "androidx.compose.ui:ui:$compose_version" implementation "androidx.compose.material:material:$compose_version" implementation "androidx.compose.material:material-icons-extended:$compose_version" - implementation "androidx.compose.ui:ui-tooling-preview:$compose_version" - implementation 'androidx.lifecycle:lifecycle-runtime-ktx:2.3.1' - implementation 'androidx.activity:activity-compose:1.3.1' implementation 'androidx.paging:paging-compose:1.0.0-alpha14' - implementation 'io.coil-kt:coil-compose:1.3.2' - implementation 'com.google.accompanist:accompanist-swiperefresh:0.16.1' + implementation 'androidx.activity:activity-compose:1.4.0' + implementation 'io.coil-kt:coil-compose:1.4.0' + implementation 'com.google.accompanist:accompanist-swiperefresh:0.20.3' testImplementation 'junit:junit:4.13.2' androidTestImplementation 'androidx.test.ext:junit:1.1.3' androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0' diff --git a/showcase-compose/src/main/AndroidManifest.xml b/showcase/compose/src/main/AndroidManifest.xml similarity index 100% rename from showcase-compose/src/main/AndroidManifest.xml rename to showcase/compose/src/main/AndroidManifest.xml diff --git a/showcase-compose/src/main/kotlin/com/algolia/instantsearch/showcase/compose/Demo.kt b/showcase/compose/src/main/kotlin/com/algolia/instantsearch/showcase/compose/Demo.kt similarity index 83% rename from showcase-compose/src/main/kotlin/com/algolia/instantsearch/showcase/compose/Demo.kt rename to showcase/compose/src/main/kotlin/com/algolia/instantsearch/showcase/compose/Demo.kt index 42333f27..3766aa57 100644 --- a/showcase-compose/src/main/kotlin/com/algolia/instantsearch/showcase/compose/Demo.kt +++ b/showcase/compose/src/main/kotlin/com/algolia/instantsearch/showcase/compose/Demo.kt @@ -11,10 +11,9 @@ import androidx.compose.ui.text.withStyle import com.algolia.instantsearch.compose.searchbox.SearchBoxState import com.algolia.instantsearch.core.connection.ConnectionHandler import com.algolia.instantsearch.core.searcher.Searcher -import com.algolia.instantsearch.helper.searchbox.SearchBoxConnector -import com.algolia.instantsearch.helper.searchbox.connectView -import com.algolia.instantsearch.helper.searcher.SearcherForFacets -import com.algolia.instantsearch.helper.searcher.SearcherSingleIndex +import com.algolia.instantsearch.searchbox.SearchBoxConnector +import com.algolia.instantsearch.searchbox.connectView +import com.algolia.instantsearch.searcher.IndexNameHolder import com.algolia.instantsearch.showcase.compose.ui.* import com.algolia.search.client.ClientSearch import com.algolia.search.configuration.ConfigurationSearch @@ -36,14 +35,14 @@ val client = ClientSearch( ) ) -val stubIndex = client.initIndex(IndexName("stub")) +val stubIndexName = IndexName("stub") -fun AppCompatActivity.configureSearcher(searcher: SearcherSingleIndex) { - searcher.index = client.initIndex(intent.indexName) +fun AppCompatActivity.configureSearcher(searcher: IndexNameHolder) { + searcher.indexName = intent.indexName } -fun AppCompatActivity.configureSearcher(searcher: SearcherForFacets) { - searcher.index = client.initIndex(intent.indexName) +fun Activity.configureSearcher(searcher: IndexNameHolder) { + searcher.indexName = intent.indexName } val Intent.indexName: IndexName get() = IndexName(extras!!.getString(KeyIndexName)!!) diff --git a/showcase-compose/src/main/kotlin/com/algolia/instantsearch/showcase/compose/customdata/QueryRuleCustomDataShowcase.kt b/showcase/compose/src/main/kotlin/com/algolia/instantsearch/showcase/compose/customdata/QueryRuleCustomDataShowcase.kt similarity index 91% rename from showcase-compose/src/main/kotlin/com/algolia/instantsearch/showcase/compose/customdata/QueryRuleCustomDataShowcase.kt rename to showcase/compose/src/main/kotlin/com/algolia/instantsearch/showcase/compose/customdata/QueryRuleCustomDataShowcase.kt index 81658f8e..0b120e9d 100644 --- a/showcase-compose/src/main/kotlin/com/algolia/instantsearch/showcase/compose/customdata/QueryRuleCustomDataShowcase.kt +++ b/showcase/compose/src/main/kotlin/com/algolia/instantsearch/showcase/compose/customdata/QueryRuleCustomDataShowcase.kt @@ -3,6 +3,7 @@ package com.algolia.instantsearch.showcase.compose.customdata import android.content.Intent import android.net.Uri import android.os.Bundle +import android.util.Log import androidx.activity.compose.setContent import androidx.appcompat.app.AppCompatActivity import androidx.compose.foundation.Image @@ -28,17 +29,16 @@ import com.algolia.instantsearch.compose.hits.HitsState import com.algolia.instantsearch.compose.searchbox.SearchBoxState import com.algolia.instantsearch.core.connection.ConnectionHandler import com.algolia.instantsearch.core.hits.connectHitsView -import com.algolia.instantsearch.helper.customdata.QueryRuleCustomDataConnector -import com.algolia.instantsearch.helper.searchbox.SearchBoxConnector -import com.algolia.instantsearch.helper.searchbox.SearchMode -import com.algolia.instantsearch.helper.searchbox.connectView -import com.algolia.instantsearch.helper.searcher.SearcherSingleIndex +import com.algolia.instantsearch.customdata.QueryRuleCustomDataConnector +import com.algolia.instantsearch.searchbox.SearchBoxConnector +import com.algolia.instantsearch.searchbox.SearchMode +import com.algolia.instantsearch.searchbox.connectView +import com.algolia.instantsearch.searcher.hits.HitsSearcher +import com.algolia.instantsearch.showcase.compose.* import com.algolia.instantsearch.showcase.compose.R -import com.algolia.instantsearch.showcase.compose.configureSearcher import com.algolia.instantsearch.showcase.compose.customdata.TemplateActivity.Companion.EXTRA_CONTENT import com.algolia.instantsearch.showcase.compose.model.Banner import com.algolia.instantsearch.showcase.compose.model.Product -import com.algolia.instantsearch.showcase.compose.stubIndex import com.algolia.instantsearch.showcase.compose.ui.BlueDark import com.algolia.instantsearch.showcase.compose.ui.ShowcaseTheme import com.algolia.instantsearch.showcase.compose.ui.WhiteLight @@ -49,7 +49,7 @@ import com.algolia.search.helper.deserialize class QueryRuleCustomDataShowcase : AppCompatActivity() { - private val searcher = SearcherSingleIndex(stubIndex) + private val searcher = HitsSearcher(client, stubIndexName) private val hitsState = HitsState() private val searchBoxState = SearchBoxState() @@ -69,7 +69,7 @@ class QueryRuleCustomDataShowcase : AppCompatActivity() { searchBox.viewModel.eventSubmit.subscribe { val model = queryRuleCustomData.viewModel.item.value ?: return@subscribe - if (model.banner == null && model.title == null) { + if (model.banner == null && model.title ==null) { redirect(model.link, resources.getString(R.string.redirect_via_submit)) } } diff --git a/showcase-compose/src/main/kotlin/com/algolia/instantsearch/showcase/compose/customdata/TemplateActivity.kt b/showcase/compose/src/main/kotlin/com/algolia/instantsearch/showcase/compose/customdata/TemplateActivity.kt similarity index 100% rename from showcase-compose/src/main/kotlin/com/algolia/instantsearch/showcase/compose/customdata/TemplateActivity.kt rename to showcase/compose/src/main/kotlin/com/algolia/instantsearch/showcase/compose/customdata/TemplateActivity.kt diff --git a/showcase-compose/src/main/kotlin/com/algolia/instantsearch/showcase/compose/directory/Directory.kt b/showcase/compose/src/main/kotlin/com/algolia/instantsearch/showcase/compose/directory/Directory.kt similarity index 100% rename from showcase-compose/src/main/kotlin/com/algolia/instantsearch/showcase/compose/directory/Directory.kt rename to showcase/compose/src/main/kotlin/com/algolia/instantsearch/showcase/compose/directory/Directory.kt diff --git a/showcase-compose/src/main/kotlin/com/algolia/instantsearch/showcase/compose/directory/DirectoryHit.kt b/showcase/compose/src/main/kotlin/com/algolia/instantsearch/showcase/compose/directory/DirectoryHit.kt similarity index 90% rename from showcase-compose/src/main/kotlin/com/algolia/instantsearch/showcase/compose/directory/DirectoryHit.kt rename to showcase/compose/src/main/kotlin/com/algolia/instantsearch/showcase/compose/directory/DirectoryHit.kt index 7e47b335..28333a12 100644 --- a/showcase-compose/src/main/kotlin/com/algolia/instantsearch/showcase/compose/directory/DirectoryHit.kt +++ b/showcase/compose/src/main/kotlin/com/algolia/instantsearch/showcase/compose/directory/DirectoryHit.kt @@ -1,6 +1,6 @@ package com.algolia.instantsearch.showcase.compose.directory -import com.algolia.instantsearch.helper.highlighting.Highlightable +import com.algolia.instantsearch.highlighting.Highlightable import com.algolia.search.model.Attribute import com.algolia.search.model.ObjectID import com.algolia.search.model.indexing.Indexable diff --git a/showcase-compose/src/main/kotlin/com/algolia/instantsearch/showcase/compose/directory/DirectoryItem.kt b/showcase/compose/src/main/kotlin/com/algolia/instantsearch/showcase/compose/directory/DirectoryItem.kt similarity index 100% rename from showcase-compose/src/main/kotlin/com/algolia/instantsearch/showcase/compose/directory/DirectoryItem.kt rename to showcase/compose/src/main/kotlin/com/algolia/instantsearch/showcase/compose/directory/DirectoryItem.kt diff --git a/showcase-compose/src/main/kotlin/com/algolia/instantsearch/showcase/compose/directory/DirectoryScreen.kt b/showcase/compose/src/main/kotlin/com/algolia/instantsearch/showcase/compose/directory/DirectoryScreen.kt similarity index 100% rename from showcase-compose/src/main/kotlin/com/algolia/instantsearch/showcase/compose/directory/DirectoryScreen.kt rename to showcase/compose/src/main/kotlin/com/algolia/instantsearch/showcase/compose/directory/DirectoryScreen.kt diff --git a/showcase-compose/src/main/kotlin/com/algolia/instantsearch/showcase/compose/directory/DirectoryShowcase.kt b/showcase/compose/src/main/kotlin/com/algolia/instantsearch/showcase/compose/directory/DirectoryShowcase.kt similarity index 91% rename from showcase-compose/src/main/kotlin/com/algolia/instantsearch/showcase/compose/directory/DirectoryShowcase.kt rename to showcase/compose/src/main/kotlin/com/algolia/instantsearch/showcase/compose/directory/DirectoryShowcase.kt index 3466cb46..04bbff3e 100644 --- a/showcase-compose/src/main/kotlin/com/algolia/instantsearch/showcase/compose/directory/DirectoryShowcase.kt +++ b/showcase/compose/src/main/kotlin/com/algolia/instantsearch/showcase/compose/directory/DirectoryShowcase.kt @@ -8,7 +8,7 @@ import com.algolia.instantsearch.compose.hits.HitsState import com.algolia.instantsearch.compose.searchbox.SearchBoxState import com.algolia.instantsearch.core.connection.ConnectionHandler import com.algolia.instantsearch.core.hits.connectHitsView -import com.algolia.instantsearch.helper.searcher.SearcherSingleIndex +import com.algolia.instantsearch.searcher.hits.HitsSearcher import com.algolia.instantsearch.showcase.compose.client import com.algolia.instantsearch.showcase.compose.configureSearchBox import com.algolia.instantsearch.showcase.compose.ui.ShowcaseTheme @@ -20,8 +20,8 @@ import com.algolia.search.serialize.KeyName class DirectoryShowcase : ComponentActivity() { - private val index = client.initIndex(IndexName("mobile_demo_home")) - private val searcher = SearcherSingleIndex(index, Query(hitsPerPage = 100)) + private val indexName = IndexName("mobile_demo_home") + private val searcher = HitsSearcher(client, indexName, Query(hitsPerPage = 100)) private val hitsState = HitsState(emptyList()) private val searchBoxState = SearchBoxState() private val connections = ConnectionHandler() diff --git a/showcase-compose/src/main/kotlin/com/algolia/instantsearch/showcase/compose/filter/clear/FilterClearShowcase.kt b/showcase/compose/src/main/kotlin/com/algolia/instantsearch/showcase/compose/filter/clear/FilterClearShowcase.kt similarity index 83% rename from showcase-compose/src/main/kotlin/com/algolia/instantsearch/showcase/compose/filter/clear/FilterClearShowcase.kt rename to showcase/compose/src/main/kotlin/com/algolia/instantsearch/showcase/compose/filter/clear/FilterClearShowcase.kt index 1eee308f..3ce2f789 100644 --- a/showcase-compose/src/main/kotlin/com/algolia/instantsearch/showcase/compose/filter/clear/FilterClearShowcase.kt +++ b/showcase/compose/src/main/kotlin/com/algolia/instantsearch/showcase/compose/filter/clear/FilterClearShowcase.kt @@ -14,18 +14,15 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.unit.dp import com.algolia.instantsearch.compose.filter.clear.FilterClear import com.algolia.instantsearch.core.connection.ConnectionHandler -import com.algolia.instantsearch.helper.filter.clear.ClearMode -import com.algolia.instantsearch.helper.filter.clear.FilterClearConnector -import com.algolia.instantsearch.helper.filter.clear.connectView -import com.algolia.instantsearch.helper.filter.state.FilterState -import com.algolia.instantsearch.helper.filter.state.filters -import com.algolia.instantsearch.helper.filter.state.groupOr -import com.algolia.instantsearch.helper.searcher.SearcherSingleIndex -import com.algolia.instantsearch.helper.searcher.connectFilterState -import com.algolia.instantsearch.showcase.compose.configureSearcher -import com.algolia.instantsearch.showcase.compose.filterColors -import com.algolia.instantsearch.showcase.compose.showcaseTitle -import com.algolia.instantsearch.showcase.compose.stubIndex +import com.algolia.instantsearch.filter.clear.ClearMode +import com.algolia.instantsearch.filter.clear.FilterClearConnector +import com.algolia.instantsearch.filter.clear.connectView +import com.algolia.instantsearch.filter.state.FilterState +import com.algolia.instantsearch.filter.state.filters +import com.algolia.instantsearch.filter.state.groupOr +import com.algolia.instantsearch.searcher.connectFilterState +import com.algolia.instantsearch.searcher.hits.HitsSearcher +import com.algolia.instantsearch.showcase.compose.* import com.algolia.instantsearch.showcase.compose.ui.ShowcaseTheme import com.algolia.instantsearch.showcase.compose.ui.component.HeaderFilter import com.algolia.instantsearch.showcase.compose.ui.component.HeaderFilterConnector @@ -35,7 +32,7 @@ import com.algolia.search.model.Attribute class FilterClearShowcase : AppCompatActivity() { - private val searcher = SearcherSingleIndex(stubIndex) + private val searcher = HitsSearcher(client, stubIndexName) private val color = Attribute("color") private val category = Attribute("category") private val groupColor = groupOr(color) diff --git a/showcase-compose/src/main/kotlin/com/algolia/instantsearch/showcase/compose/filter/current/FilterCurrentShowcase.kt b/showcase/compose/src/main/kotlin/com/algolia/instantsearch/showcase/compose/filter/current/FilterCurrentShowcase.kt similarity index 86% rename from showcase-compose/src/main/kotlin/com/algolia/instantsearch/showcase/compose/filter/current/FilterCurrentShowcase.kt rename to showcase/compose/src/main/kotlin/com/algolia/instantsearch/showcase/compose/filter/current/FilterCurrentShowcase.kt index cedaf712..c9254a29 100644 --- a/showcase-compose/src/main/kotlin/com/algolia/instantsearch/showcase/compose/filter/current/FilterCurrentShowcase.kt +++ b/showcase/compose/src/main/kotlin/com/algolia/instantsearch/showcase/compose/filter/current/FilterCurrentShowcase.kt @@ -14,18 +14,15 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.unit.dp import com.algolia.instantsearch.compose.filter.current.FilterCurrentState import com.algolia.instantsearch.core.connection.ConnectionHandler -import com.algolia.instantsearch.helper.filter.current.FilterCurrentConnector -import com.algolia.instantsearch.helper.filter.current.connectView -import com.algolia.instantsearch.helper.filter.state.FilterGroupID -import com.algolia.instantsearch.helper.filter.state.FilterState -import com.algolia.instantsearch.helper.filter.state.filters -import com.algolia.instantsearch.helper.searcher.SearcherSingleIndex -import com.algolia.instantsearch.helper.searcher.connectFilterState -import com.algolia.instantsearch.showcase.compose.configureSearcher +import com.algolia.instantsearch.filter.current.FilterCurrentConnector +import com.algolia.instantsearch.filter.current.connectView +import com.algolia.instantsearch.filter.state.FilterGroupID +import com.algolia.instantsearch.filter.state.FilterState +import com.algolia.instantsearch.filter.state.filters +import com.algolia.instantsearch.searcher.connectFilterState +import com.algolia.instantsearch.searcher.hits.HitsSearcher +import com.algolia.instantsearch.showcase.compose.* import com.algolia.instantsearch.showcase.compose.filter.current.ui.FilterChips -import com.algolia.instantsearch.showcase.compose.filterColors -import com.algolia.instantsearch.showcase.compose.showcaseTitle -import com.algolia.instantsearch.showcase.compose.stubIndex import com.algolia.instantsearch.showcase.compose.ui.ShowcaseTheme import com.algolia.instantsearch.showcase.compose.ui.component.HeaderFilter import com.algolia.instantsearch.showcase.compose.ui.component.HeaderFilterConnector @@ -56,7 +53,7 @@ class FilterCurrentShowcase : AppCompatActivity() { } } private val filterState = FilterState(filters) - private val searcher = SearcherSingleIndex(stubIndex) + private val searcher = HitsSearcher(client, stubIndexName) private val currentFiltersAll = FilterCurrentConnector(filterState) private val currentFiltersColor = FilterCurrentConnector(filterState, listOf(groupColor)) diff --git a/showcase-compose/src/main/kotlin/com/algolia/instantsearch/showcase/compose/filter/facet/DynamicFacetShowcase.kt b/showcase/compose/src/main/kotlin/com/algolia/instantsearch/showcase/compose/filter/facet/DynamicFacetShowcase.kt similarity index 89% rename from showcase-compose/src/main/kotlin/com/algolia/instantsearch/showcase/compose/filter/facet/DynamicFacetShowcase.kt rename to showcase/compose/src/main/kotlin/com/algolia/instantsearch/showcase/compose/filter/facet/DynamicFacetShowcase.kt index f5983b0d..9972d346 100644 --- a/showcase-compose/src/main/kotlin/com/algolia/instantsearch/showcase/compose/filter/facet/DynamicFacetShowcase.kt +++ b/showcase/compose/src/main/kotlin/com/algolia/instantsearch/showcase/compose/filter/facet/DynamicFacetShowcase.kt @@ -21,14 +21,14 @@ import com.algolia.instantsearch.compose.filter.facet.dynamic.DynamicFacetListSt import com.algolia.instantsearch.compose.searchbox.SearchBoxState import com.algolia.instantsearch.core.connection.ConnectionHandler import com.algolia.instantsearch.core.selectable.list.SelectionMode -import com.algolia.instantsearch.helper.filter.facet.dynamic.AttributedFacets -import com.algolia.instantsearch.helper.filter.facet.dynamic.DynamicFacetListConnector -import com.algolia.instantsearch.helper.filter.facet.dynamic.connectView -import com.algolia.instantsearch.helper.filter.state.FilterOperator -import com.algolia.instantsearch.helper.filter.state.FilterState -import com.algolia.instantsearch.helper.searchbox.SearchBoxConnector -import com.algolia.instantsearch.helper.searchbox.connectView -import com.algolia.instantsearch.helper.searcher.SearcherSingleIndex +import com.algolia.instantsearch.filter.facet.dynamic.AttributedFacets +import com.algolia.instantsearch.filter.facet.dynamic.DynamicFacetListConnector +import com.algolia.instantsearch.filter.facet.dynamic.connectView +import com.algolia.instantsearch.filter.state.FilterOperator +import com.algolia.instantsearch.filter.state.FilterState +import com.algolia.instantsearch.searchbox.SearchBoxConnector +import com.algolia.instantsearch.searchbox.connectView +import com.algolia.instantsearch.searcher.hits.HitsSearcher import com.algolia.instantsearch.showcase.compose.R import com.algolia.instantsearch.showcase.compose.ui.GreyLight import com.algolia.instantsearch.showcase.compose.ui.ShowcaseTheme @@ -51,8 +51,7 @@ class DynamicFacetShowcase : AppCompatActivity() { APIKey("937e4e6ec422ff69fe89b569dba30180"), LogLevel.ALL ) - private val index = client.initIndex(IndexName("test_facet_ordering")) - private val searcher = SearcherSingleIndex(index) + private val searcher = HitsSearcher(client, IndexName("test_facet_ordering")) private val filterState = FilterState() private val color = Attribute("color") private val country = Attribute("country") diff --git a/showcase-compose/src/main/kotlin/com/algolia/instantsearch/showcase/compose/filter/facet/FacetListPersistentShowcase.kt b/showcase/compose/src/main/kotlin/com/algolia/instantsearch/showcase/compose/filter/facet/FacetListPersistentShowcase.kt similarity index 87% rename from showcase-compose/src/main/kotlin/com/algolia/instantsearch/showcase/compose/filter/facet/FacetListPersistentShowcase.kt rename to showcase/compose/src/main/kotlin/com/algolia/instantsearch/showcase/compose/filter/facet/FacetListPersistentShowcase.kt index 2be757dc..6bfd5fd1 100644 --- a/showcase-compose/src/main/kotlin/com/algolia/instantsearch/showcase/compose/filter/facet/FacetListPersistentShowcase.kt +++ b/showcase/compose/src/main/kotlin/com/algolia/instantsearch/showcase/compose/filter/facet/FacetListPersistentShowcase.kt @@ -14,15 +14,12 @@ import androidx.compose.ui.unit.dp import com.algolia.instantsearch.compose.filter.facet.FacetListState import com.algolia.instantsearch.core.connection.ConnectionHandler import com.algolia.instantsearch.core.selectable.list.SelectionMode -import com.algolia.instantsearch.helper.filter.facet.FacetListConnector -import com.algolia.instantsearch.helper.filter.facet.connectView -import com.algolia.instantsearch.helper.filter.state.FilterState -import com.algolia.instantsearch.helper.searcher.SearcherSingleIndex -import com.algolia.instantsearch.helper.searcher.connectFilterState -import com.algolia.instantsearch.showcase.compose.client -import com.algolia.instantsearch.showcase.compose.configureSearcher -import com.algolia.instantsearch.showcase.compose.filterColors -import com.algolia.instantsearch.showcase.compose.showcaseTitle +import com.algolia.instantsearch.filter.facet.FacetListConnector +import com.algolia.instantsearch.filter.facet.connectView +import com.algolia.instantsearch.filter.state.FilterState +import com.algolia.instantsearch.searcher.connectFilterState +import com.algolia.instantsearch.searcher.hits.HitsSearcher +import com.algolia.instantsearch.showcase.compose.* import com.algolia.instantsearch.showcase.compose.ui.HoloGreenDark import com.algolia.instantsearch.showcase.compose.ui.HoloRedDark import com.algolia.instantsearch.showcase.compose.ui.ShowcaseTheme @@ -39,7 +36,7 @@ class FacetListPersistentShowcase : AppCompatActivity() { private val category = Attribute("category") private val index = client.initIndex(IndexName("stub")) private val filterState = FilterState() - private val searcher = SearcherSingleIndex(index) + private val searcher = HitsSearcher(client, stubIndexName) private val facetListStateColor = FacetListState() private val facetListColor = FacetListConnector( diff --git a/showcase-compose/src/main/kotlin/com/algolia/instantsearch/showcase/compose/filter/facet/FacetListSearchShowcase.kt b/showcase/compose/src/main/kotlin/com/algolia/instantsearch/showcase/compose/filter/facet/FacetListSearchShowcase.kt similarity index 67% rename from showcase-compose/src/main/kotlin/com/algolia/instantsearch/showcase/compose/filter/facet/FacetListSearchShowcase.kt rename to showcase/compose/src/main/kotlin/com/algolia/instantsearch/showcase/compose/filter/facet/FacetListSearchShowcase.kt index fea52f0b..c9e66642 100644 --- a/showcase-compose/src/main/kotlin/com/algolia/instantsearch/showcase/compose/filter/facet/FacetListSearchShowcase.kt +++ b/showcase/compose/src/main/kotlin/com/algolia/instantsearch/showcase/compose/filter/facet/FacetListSearchShowcase.kt @@ -6,9 +6,12 @@ import androidx.appcompat.app.AppCompatActivity import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.foundation.rememberScrollState import androidx.compose.foundation.verticalScroll +import androidx.compose.material.Divider import androidx.compose.material.Scaffold +import androidx.compose.material.Text import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier import androidx.compose.ui.unit.dp @@ -16,32 +19,27 @@ import com.algolia.instantsearch.compose.filter.facet.FacetListState import com.algolia.instantsearch.compose.searchbox.SearchBoxState import com.algolia.instantsearch.core.connection.ConnectionHandler import com.algolia.instantsearch.core.selectable.list.SelectionMode -import com.algolia.instantsearch.helper.filter.facet.FacetListConnector -import com.algolia.instantsearch.helper.filter.facet.FacetListPresenterImpl -import com.algolia.instantsearch.helper.filter.facet.FacetSortCriterion -import com.algolia.instantsearch.helper.filter.facet.connectView -import com.algolia.instantsearch.helper.filter.state.FilterState -import com.algolia.instantsearch.helper.searchbox.SearchBoxConnector -import com.algolia.instantsearch.helper.searchbox.connectView -import com.algolia.instantsearch.helper.searcher.SearcherForFacets -import com.algolia.instantsearch.helper.searcher.SearcherSingleIndex -import com.algolia.instantsearch.helper.searcher.connectFilterState -import com.algolia.instantsearch.showcase.compose.client -import com.algolia.instantsearch.showcase.compose.filterColors -import com.algolia.instantsearch.showcase.compose.indexName -import com.algolia.instantsearch.showcase.compose.stubIndex +import com.algolia.instantsearch.filter.facet.FacetListConnector +import com.algolia.instantsearch.filter.facet.FacetListPresenterImpl +import com.algolia.instantsearch.filter.facet.FacetSortCriterion +import com.algolia.instantsearch.filter.facet.connectView +import com.algolia.instantsearch.filter.state.FilterState +import com.algolia.instantsearch.searchbox.SearchBoxConnector +import com.algolia.instantsearch.searchbox.connectView +import com.algolia.instantsearch.searcher.connectFilterState +import com.algolia.instantsearch.searcher.facets.FacetsSearcher +import com.algolia.instantsearch.searcher.hits.HitsSearcher +import com.algolia.instantsearch.showcase.compose.* import com.algolia.instantsearch.showcase.compose.ui.ShowcaseTheme -import com.algolia.instantsearch.showcase.compose.ui.component.FacetList -import com.algolia.instantsearch.showcase.compose.ui.component.HeaderFilter -import com.algolia.instantsearch.showcase.compose.ui.component.HeaderFilterConnector -import com.algolia.instantsearch.showcase.compose.ui.component.SearchTopBar +import com.algolia.instantsearch.showcase.compose.ui.component.* import com.algolia.search.model.Attribute +import com.algolia.search.model.search.Query class FacetListSearchShowcase : AppCompatActivity() { private val brand = Attribute("brand") - private val searcher = SearcherSingleIndex(stubIndex) - private val searcherForFacet = SearcherForFacets(stubIndex, brand) + private val searcher = HitsSearcher(client, stubIndexName) + private val searcherForFacet = FacetsSearcher(client, stubIndexName, brand, Query(maxFacetHits = 15)) private val filterState = FilterState() private val searchBoxState = SearchBoxState() @@ -80,9 +78,9 @@ class FacetListSearchShowcase : AppCompatActivity() { } } - val index = client.initIndex(intent.indexName) - searcher.index = index - searcherForFacet.index = index + configureSearcher(searcher) + configureSearcher(searcherForFacet) + searcher.searchAsync() searcherForFacet.searchAsync() } @@ -102,11 +100,10 @@ class FacetListSearchShowcase : AppCompatActivity() { modifier = Modifier.padding(16.dp), filterHeader = filterHeader ) - val scrollState = rememberScrollState() FacetList( modifier = Modifier .fillMaxWidth() - .verticalScroll(scrollState), + .verticalScroll(rememberScrollState()), facetListState = facetListState ) } diff --git a/showcase-compose/src/main/kotlin/com/algolia/instantsearch/showcase/compose/filter/facet/FacetListShowcase.kt b/showcase/compose/src/main/kotlin/com/algolia/instantsearch/showcase/compose/filter/facet/FacetListShowcase.kt similarity index 86% rename from showcase-compose/src/main/kotlin/com/algolia/instantsearch/showcase/compose/filter/facet/FacetListShowcase.kt rename to showcase/compose/src/main/kotlin/com/algolia/instantsearch/showcase/compose/filter/facet/FacetListShowcase.kt index 9c139c46..bd31a9c6 100644 --- a/showcase-compose/src/main/kotlin/com/algolia/instantsearch/showcase/compose/filter/facet/FacetListShowcase.kt +++ b/showcase/compose/src/main/kotlin/com/algolia/instantsearch/showcase/compose/filter/facet/FacetListShowcase.kt @@ -14,19 +14,16 @@ import androidx.compose.ui.unit.dp import com.algolia.instantsearch.compose.filter.facet.FacetListState import com.algolia.instantsearch.core.connection.ConnectionHandler import com.algolia.instantsearch.core.selectable.list.SelectionMode -import com.algolia.instantsearch.helper.filter.facet.FacetListConnector -import com.algolia.instantsearch.helper.filter.facet.FacetListPresenterImpl -import com.algolia.instantsearch.helper.filter.facet.FacetSortCriterion -import com.algolia.instantsearch.helper.filter.facet.connectView -import com.algolia.instantsearch.helper.filter.state.filterState -import com.algolia.instantsearch.helper.filter.state.groupAnd -import com.algolia.instantsearch.helper.filter.state.groupOr -import com.algolia.instantsearch.helper.searcher.SearcherSingleIndex -import com.algolia.instantsearch.helper.searcher.connectFilterState -import com.algolia.instantsearch.showcase.compose.configureSearcher -import com.algolia.instantsearch.showcase.compose.filterColors -import com.algolia.instantsearch.showcase.compose.showcaseTitle -import com.algolia.instantsearch.showcase.compose.stubIndex +import com.algolia.instantsearch.filter.facet.FacetListConnector +import com.algolia.instantsearch.filter.facet.FacetListPresenterImpl +import com.algolia.instantsearch.filter.facet.FacetSortCriterion +import com.algolia.instantsearch.filter.facet.connectView +import com.algolia.instantsearch.filter.state.filterState +import com.algolia.instantsearch.filter.state.groupAnd +import com.algolia.instantsearch.filter.state.groupOr +import com.algolia.instantsearch.searcher.connectFilterState +import com.algolia.instantsearch.searcher.hits.HitsSearcher +import com.algolia.instantsearch.showcase.compose.* import com.algolia.instantsearch.showcase.compose.ui.HoloBlueDark import com.algolia.instantsearch.showcase.compose.ui.HoloGreenDark import com.algolia.instantsearch.showcase.compose.ui.HoloRedDark @@ -46,7 +43,7 @@ class FacetListShowcase : AppCompatActivity() { private val groupPromotions = groupAnd(promotions) private val groupCategory = groupOr(category) private val filterState = filterState { group(groupColor) { facet(color, "green") } } - private val searcher = SearcherSingleIndex(stubIndex) + private val searcher = HitsSearcher(client, stubIndexName) private val facetListStateColor = FacetListState() private val colorPresenter = FacetListPresenterImpl( diff --git a/showcase-compose/src/main/kotlin/com/algolia/instantsearch/showcase/compose/filter/list/FilterListAllShowcase.kt b/showcase/compose/src/main/kotlin/com/algolia/instantsearch/showcase/compose/filter/list/FilterListAllShowcase.kt similarity index 81% rename from showcase-compose/src/main/kotlin/com/algolia/instantsearch/showcase/compose/filter/list/FilterListAllShowcase.kt rename to showcase/compose/src/main/kotlin/com/algolia/instantsearch/showcase/compose/filter/list/FilterListAllShowcase.kt index b2b02f18..062bff4d 100644 --- a/showcase-compose/src/main/kotlin/com/algolia/instantsearch/showcase/compose/filter/list/FilterListAllShowcase.kt +++ b/showcase/compose/src/main/kotlin/com/algolia/instantsearch/showcase/compose/filter/list/FilterListAllShowcase.kt @@ -5,15 +5,16 @@ import androidx.activity.compose.setContent import androidx.appcompat.app.AppCompatActivity import com.algolia.instantsearch.compose.filter.list.FilterListState import com.algolia.instantsearch.core.connection.ConnectionHandler -import com.algolia.instantsearch.helper.filter.list.FilterListConnector -import com.algolia.instantsearch.helper.filter.list.connectView -import com.algolia.instantsearch.helper.filter.state.FilterState -import com.algolia.instantsearch.helper.filter.state.groupAnd -import com.algolia.instantsearch.helper.searcher.SearcherSingleIndex -import com.algolia.instantsearch.helper.searcher.connectFilterState +import com.algolia.instantsearch.filter.list.FilterListConnector +import com.algolia.instantsearch.filter.list.connectView +import com.algolia.instantsearch.filter.state.FilterState +import com.algolia.instantsearch.filter.state.groupAnd +import com.algolia.instantsearch.searcher.connectFilterState +import com.algolia.instantsearch.searcher.hits.HitsSearcher +import com.algolia.instantsearch.showcase.compose.client import com.algolia.instantsearch.showcase.compose.configureSearcher import com.algolia.instantsearch.showcase.compose.filterColors -import com.algolia.instantsearch.showcase.compose.stubIndex +import com.algolia.instantsearch.showcase.compose.stubIndexName import com.algolia.instantsearch.showcase.compose.ui.ShowcaseTheme import com.algolia.instantsearch.showcase.compose.ui.component.HeaderFilterConnector import com.algolia.search.model.Attribute @@ -29,7 +30,7 @@ class FilterListAllShowcase : AppCompatActivity() { private val all = Attribute("all") private val groupAll = groupAnd(all) private val filterState = FilterState() - private val searcher = SearcherSingleIndex(stubIndex) + private val searcher = HitsSearcher(client, stubIndexName) private val filters = listOf( Filter.Numeric(price, 5..10), Filter.Tag("coupon"), diff --git a/showcase-compose/src/main/kotlin/com/algolia/instantsearch/showcase/compose/filter/list/FilterListFacetShowcase.kt b/showcase/compose/src/main/kotlin/com/algolia/instantsearch/showcase/compose/filter/list/FilterListFacetShowcase.kt similarity index 80% rename from showcase-compose/src/main/kotlin/com/algolia/instantsearch/showcase/compose/filter/list/FilterListFacetShowcase.kt rename to showcase/compose/src/main/kotlin/com/algolia/instantsearch/showcase/compose/filter/list/FilterListFacetShowcase.kt index 8cf20740..5296486d 100644 --- a/showcase-compose/src/main/kotlin/com/algolia/instantsearch/showcase/compose/filter/list/FilterListFacetShowcase.kt +++ b/showcase/compose/src/main/kotlin/com/algolia/instantsearch/showcase/compose/filter/list/FilterListFacetShowcase.kt @@ -6,15 +6,16 @@ import androidx.appcompat.app.AppCompatActivity import com.algolia.instantsearch.compose.filter.list.FilterListState import com.algolia.instantsearch.core.connection.ConnectionHandler import com.algolia.instantsearch.core.selectable.list.SelectionMode -import com.algolia.instantsearch.helper.filter.list.FilterListConnector -import com.algolia.instantsearch.helper.filter.list.connectView -import com.algolia.instantsearch.helper.filter.state.FilterState -import com.algolia.instantsearch.helper.filter.state.groupAnd -import com.algolia.instantsearch.helper.searcher.SearcherSingleIndex -import com.algolia.instantsearch.helper.searcher.connectFilterState +import com.algolia.instantsearch.filter.list.FilterListConnector +import com.algolia.instantsearch.filter.list.connectView +import com.algolia.instantsearch.filter.state.FilterState +import com.algolia.instantsearch.filter.state.groupAnd +import com.algolia.instantsearch.searcher.connectFilterState +import com.algolia.instantsearch.searcher.hits.HitsSearcher +import com.algolia.instantsearch.showcase.compose.client import com.algolia.instantsearch.showcase.compose.configureSearcher import com.algolia.instantsearch.showcase.compose.filterColors -import com.algolia.instantsearch.showcase.compose.stubIndex +import com.algolia.instantsearch.showcase.compose.stubIndexName import com.algolia.instantsearch.showcase.compose.ui.component.HeaderFilterConnector import com.algolia.search.model.Attribute import com.algolia.search.model.filter.Filter @@ -25,7 +26,7 @@ class FilterListFacetShowcase : AppCompatActivity() { private val color = Attribute("color") private val groupColor = groupAnd(color) private val filterState = FilterState() - private val searcher = SearcherSingleIndex(stubIndex) + private val searcher = HitsSearcher(client, stubIndexName) private val facetFilters = listOf( Filter.Facet(color, "red"), Filter.Facet(color, "green"), diff --git a/showcase-compose/src/main/kotlin/com/algolia/instantsearch/showcase/compose/filter/list/FilterListNumericShowcase.kt b/showcase/compose/src/main/kotlin/com/algolia/instantsearch/showcase/compose/filter/list/FilterListNumericShowcase.kt similarity index 79% rename from showcase-compose/src/main/kotlin/com/algolia/instantsearch/showcase/compose/filter/list/FilterListNumericShowcase.kt rename to showcase/compose/src/main/kotlin/com/algolia/instantsearch/showcase/compose/filter/list/FilterListNumericShowcase.kt index cf97716f..f8b00279 100644 --- a/showcase-compose/src/main/kotlin/com/algolia/instantsearch/showcase/compose/filter/list/FilterListNumericShowcase.kt +++ b/showcase/compose/src/main/kotlin/com/algolia/instantsearch/showcase/compose/filter/list/FilterListNumericShowcase.kt @@ -5,15 +5,16 @@ import androidx.activity.compose.setContent import androidx.appcompat.app.AppCompatActivity import com.algolia.instantsearch.compose.filter.list.FilterListState import com.algolia.instantsearch.core.connection.ConnectionHandler -import com.algolia.instantsearch.helper.filter.list.FilterListConnector -import com.algolia.instantsearch.helper.filter.list.connectView -import com.algolia.instantsearch.helper.filter.state.FilterState -import com.algolia.instantsearch.helper.filter.state.groupAnd -import com.algolia.instantsearch.helper.searcher.SearcherSingleIndex -import com.algolia.instantsearch.helper.searcher.connectFilterState +import com.algolia.instantsearch.filter.list.FilterListConnector +import com.algolia.instantsearch.filter.list.connectView +import com.algolia.instantsearch.filter.state.FilterState +import com.algolia.instantsearch.filter.state.groupAnd +import com.algolia.instantsearch.searcher.connectFilterState +import com.algolia.instantsearch.searcher.hits.HitsSearcher +import com.algolia.instantsearch.showcase.compose.client import com.algolia.instantsearch.showcase.compose.configureSearcher import com.algolia.instantsearch.showcase.compose.filterColors -import com.algolia.instantsearch.showcase.compose.stubIndex +import com.algolia.instantsearch.showcase.compose.stubIndexName import com.algolia.instantsearch.showcase.compose.ui.component.HeaderFilterConnector import com.algolia.search.model.Attribute import com.algolia.search.model.filter.Filter @@ -24,7 +25,7 @@ class FilterListNumericShowcase : AppCompatActivity() { private val price = Attribute("price") private val groupPrice = groupAnd(price) - private val searcher = SearcherSingleIndex(stubIndex) + private val searcher = HitsSearcher(client, stubIndexName) private val filterState = FilterState() private val filters = listOf( Filter.Numeric(price, NumericOperator.Less, 5), diff --git a/showcase-compose/src/main/kotlin/com/algolia/instantsearch/showcase/compose/filter/list/FilterListScreen.kt b/showcase/compose/src/main/kotlin/com/algolia/instantsearch/showcase/compose/filter/list/FilterListScreen.kt similarity index 100% rename from showcase-compose/src/main/kotlin/com/algolia/instantsearch/showcase/compose/filter/list/FilterListScreen.kt rename to showcase/compose/src/main/kotlin/com/algolia/instantsearch/showcase/compose/filter/list/FilterListScreen.kt diff --git a/showcase-compose/src/main/kotlin/com/algolia/instantsearch/showcase/compose/filter/list/FilterListTagShowcase.kt b/showcase/compose/src/main/kotlin/com/algolia/instantsearch/showcase/compose/filter/list/FilterListTagShowcase.kt similarity index 78% rename from showcase-compose/src/main/kotlin/com/algolia/instantsearch/showcase/compose/filter/list/FilterListTagShowcase.kt rename to showcase/compose/src/main/kotlin/com/algolia/instantsearch/showcase/compose/filter/list/FilterListTagShowcase.kt index b52ff0f9..80c211e4 100644 --- a/showcase-compose/src/main/kotlin/com/algolia/instantsearch/showcase/compose/filter/list/FilterListTagShowcase.kt +++ b/showcase/compose/src/main/kotlin/com/algolia/instantsearch/showcase/compose/filter/list/FilterListTagShowcase.kt @@ -5,15 +5,16 @@ import androidx.activity.compose.setContent import androidx.appcompat.app.AppCompatActivity import com.algolia.instantsearch.compose.filter.list.FilterListState import com.algolia.instantsearch.core.connection.ConnectionHandler -import com.algolia.instantsearch.helper.filter.list.FilterListConnector -import com.algolia.instantsearch.helper.filter.list.connectView -import com.algolia.instantsearch.helper.filter.state.FilterState -import com.algolia.instantsearch.helper.filter.state.groupOr -import com.algolia.instantsearch.helper.searcher.SearcherSingleIndex -import com.algolia.instantsearch.helper.searcher.connectFilterState +import com.algolia.instantsearch.filter.list.FilterListConnector +import com.algolia.instantsearch.filter.list.connectView +import com.algolia.instantsearch.filter.state.FilterState +import com.algolia.instantsearch.filter.state.groupOr +import com.algolia.instantsearch.searcher.connectFilterState +import com.algolia.instantsearch.searcher.hits.HitsSearcher +import com.algolia.instantsearch.showcase.compose.client import com.algolia.instantsearch.showcase.compose.configureSearcher import com.algolia.instantsearch.showcase.compose.filterColors -import com.algolia.instantsearch.showcase.compose.stubIndex +import com.algolia.instantsearch.showcase.compose.stubIndexName import com.algolia.instantsearch.showcase.compose.ui.component.HeaderFilterConnector import com.algolia.search.model.Attribute import com.algolia.search.model.filter.Filter @@ -24,7 +25,7 @@ class FilterListTagShowcase : AppCompatActivity() { private val tags = Attribute("_tags") private val groupTags = groupOr(tags) private val filterState = FilterState() - private val searcher = SearcherSingleIndex(stubIndex) + private val searcher = HitsSearcher(client, stubIndexName) private val filters = listOf( Filter.Tag("free shipping"), Filter.Tag("coupon"), diff --git a/showcase-compose/src/main/kotlin/com/algolia/instantsearch/showcase/compose/filter/map/FilterMapShowcase.kt b/showcase/compose/src/main/kotlin/com/algolia/instantsearch/showcase/compose/filter/map/FilterMapShowcase.kt similarity index 84% rename from showcase-compose/src/main/kotlin/com/algolia/instantsearch/showcase/compose/filter/map/FilterMapShowcase.kt rename to showcase/compose/src/main/kotlin/com/algolia/instantsearch/showcase/compose/filter/map/FilterMapShowcase.kt index 07e2b34c..3018354b 100644 --- a/showcase-compose/src/main/kotlin/com/algolia/instantsearch/showcase/compose/filter/map/FilterMapShowcase.kt +++ b/showcase/compose/src/main/kotlin/com/algolia/instantsearch/showcase/compose/filter/map/FilterMapShowcase.kt @@ -13,16 +13,13 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.unit.dp import com.algolia.instantsearch.compose.filter.map.FilterMapState import com.algolia.instantsearch.core.connection.ConnectionHandler -import com.algolia.instantsearch.helper.filter.map.FilterMapConnector -import com.algolia.instantsearch.helper.filter.map.connectView -import com.algolia.instantsearch.helper.filter.state.FilterState -import com.algolia.instantsearch.helper.filter.state.groupAnd -import com.algolia.instantsearch.helper.searcher.SearcherSingleIndex -import com.algolia.instantsearch.helper.searcher.connectFilterState -import com.algolia.instantsearch.showcase.compose.configureSearcher -import com.algolia.instantsearch.showcase.compose.filterColors -import com.algolia.instantsearch.showcase.compose.showcaseTitle -import com.algolia.instantsearch.showcase.compose.stubIndex +import com.algolia.instantsearch.filter.map.FilterMapConnector +import com.algolia.instantsearch.filter.map.connectView +import com.algolia.instantsearch.filter.state.FilterState +import com.algolia.instantsearch.filter.state.groupAnd +import com.algolia.instantsearch.searcher.connectFilterState +import com.algolia.instantsearch.searcher.hits.HitsSearcher +import com.algolia.instantsearch.showcase.compose.* import com.algolia.instantsearch.showcase.compose.ui.ShowcaseTheme import com.algolia.instantsearch.showcase.compose.ui.component.HeaderFilter import com.algolia.instantsearch.showcase.compose.ui.component.HeaderFilterConnector @@ -35,7 +32,7 @@ class FilterMapShowcase : AppCompatActivity() { private val gender = Attribute("gender") private val groupGender = groupAnd(gender) private val filterState = FilterState() - private val searcher = SearcherSingleIndex(stubIndex) + private val searcher = HitsSearcher(client, stubIndexName) private val filters = mapOf( 0 to Filter.Facet(gender, "male"), 1 to Filter.Facet(gender, "female") diff --git a/showcase-compose/src/main/kotlin/com/algolia/instantsearch/showcase/compose/filter/numeric/comparison/FilterComparisonShowcase.kt b/showcase/compose/src/main/kotlin/com/algolia/instantsearch/showcase/compose/filter/numeric/comparison/FilterComparisonShowcase.kt similarity index 91% rename from showcase-compose/src/main/kotlin/com/algolia/instantsearch/showcase/compose/filter/numeric/comparison/FilterComparisonShowcase.kt rename to showcase/compose/src/main/kotlin/com/algolia/instantsearch/showcase/compose/filter/numeric/comparison/FilterComparisonShowcase.kt index 6ee9b525..7ce5471d 100644 --- a/showcase-compose/src/main/kotlin/com/algolia/instantsearch/showcase/compose/filter/numeric/comparison/FilterComparisonShowcase.kt +++ b/showcase/compose/src/main/kotlin/com/algolia/instantsearch/showcase/compose/filter/numeric/comparison/FilterComparisonShowcase.kt @@ -25,14 +25,14 @@ import com.algolia.instantsearch.core.connection.ConnectionHandler import com.algolia.instantsearch.core.number.decrement import com.algolia.instantsearch.core.number.increment import com.algolia.instantsearch.core.number.just -import com.algolia.instantsearch.helper.filter.numeric.comparison.FilterComparisonConnector -import com.algolia.instantsearch.helper.filter.numeric.comparison.connectView -import com.algolia.instantsearch.helper.filter.numeric.comparison.setBoundsFromFacetStatsInt -import com.algolia.instantsearch.helper.filter.numeric.comparison.setBoundsFromFacetStatsLong -import com.algolia.instantsearch.helper.filter.state.FilterState -import com.algolia.instantsearch.helper.searcher.SearcherSingleIndex -import com.algolia.instantsearch.helper.searcher.addFacet -import com.algolia.instantsearch.helper.searcher.connectFilterState +import com.algolia.instantsearch.filter.numeric.comparison.FilterComparisonConnector +import com.algolia.instantsearch.filter.numeric.comparison.connectView +import com.algolia.instantsearch.filter.numeric.comparison.setBoundsFromFacetStatsInt +import com.algolia.instantsearch.filter.numeric.comparison.setBoundsFromFacetStatsLong +import com.algolia.instantsearch.filter.state.FilterState +import com.algolia.instantsearch.searcher.addFacet +import com.algolia.instantsearch.searcher.connectFilterState +import com.algolia.instantsearch.searcher.hits.HitsSearcher import com.algolia.instantsearch.showcase.compose.* import com.algolia.instantsearch.showcase.compose.R import com.algolia.instantsearch.showcase.compose.ui.ShowcaseTheme @@ -40,7 +40,6 @@ import com.algolia.instantsearch.showcase.compose.ui.component.HeaderFilter import com.algolia.instantsearch.showcase.compose.ui.component.HeaderFilterConnector import com.algolia.instantsearch.showcase.compose.ui.component.TitleTopBar import com.algolia.search.model.Attribute -import com.algolia.search.model.IndexName import com.algolia.search.model.filter.NumericOperator import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch @@ -50,9 +49,8 @@ class FilterComparisonShowcase : AppCompatActivity() { private val price = Attribute("price") private val year = Attribute("year") - private val index = client.initIndex(IndexName("stub")) private val filterState = FilterState() - private val searcher = SearcherSingleIndex(index) + private val searcher = HitsSearcher(client, stubIndexName) private val comparisonPriceState = NumberState("-") private val comparisonPrice = diff --git a/showcase-compose/src/main/kotlin/com/algolia/instantsearch/showcase/compose/filter/range/FilterRangeShowcase.kt b/showcase/compose/src/main/kotlin/com/algolia/instantsearch/showcase/compose/filter/range/FilterRangeShowcase.kt similarity index 92% rename from showcase-compose/src/main/kotlin/com/algolia/instantsearch/showcase/compose/filter/range/FilterRangeShowcase.kt rename to showcase/compose/src/main/kotlin/com/algolia/instantsearch/showcase/compose/filter/range/FilterRangeShowcase.kt index 3716e207..30a85e1a 100644 --- a/showcase-compose/src/main/kotlin/com/algolia/instantsearch/showcase/compose/filter/range/FilterRangeShowcase.kt +++ b/showcase/compose/src/main/kotlin/com/algolia/instantsearch/showcase/compose/filter/range/FilterRangeShowcase.kt @@ -13,13 +13,13 @@ import com.algolia.instantsearch.compose.number.range.NumberRangeState import com.algolia.instantsearch.core.connection.ConnectionHandler import com.algolia.instantsearch.core.number.range.Range import com.algolia.instantsearch.core.searcher.Debouncer -import com.algolia.instantsearch.helper.filter.range.FilterRangeConnector -import com.algolia.instantsearch.helper.filter.range.connectView -import com.algolia.instantsearch.helper.filter.state.FilterGroupID -import com.algolia.instantsearch.helper.filter.state.FilterState -import com.algolia.instantsearch.helper.filter.state.filters -import com.algolia.instantsearch.helper.searcher.SearcherSingleIndex -import com.algolia.instantsearch.helper.searcher.connectFilterState +import com.algolia.instantsearch.filter.range.FilterRangeConnector +import com.algolia.instantsearch.filter.range.connectView +import com.algolia.instantsearch.filter.state.FilterGroupID +import com.algolia.instantsearch.filter.state.FilterState +import com.algolia.instantsearch.filter.state.filters +import com.algolia.instantsearch.searcher.connectFilterState +import com.algolia.instantsearch.searcher.hits.HitsSearcher import com.algolia.instantsearch.showcase.compose.* import com.algolia.instantsearch.showcase.compose.R import com.algolia.instantsearch.showcase.compose.ui.ShowcaseTheme @@ -32,7 +32,7 @@ import java.util.* class FilterRangeShowcase : AppCompatActivity() { - private val searcher = SearcherSingleIndex(stubIndex) + private val searcher = HitsSearcher(client, stubIndexName) private val price = Attribute("price") private val groupID = FilterGroupID(price) private val primaryBounds = 0..15 diff --git a/showcase-compose/src/main/kotlin/com/algolia/instantsearch/showcase/compose/filter/range/RangeUI.kt b/showcase/compose/src/main/kotlin/com/algolia/instantsearch/showcase/compose/filter/range/RangeUI.kt similarity index 100% rename from showcase-compose/src/main/kotlin/com/algolia/instantsearch/showcase/compose/filter/range/RangeUI.kt rename to showcase/compose/src/main/kotlin/com/algolia/instantsearch/showcase/compose/filter/range/RangeUI.kt diff --git a/showcase-compose/src/main/kotlin/com/algolia/instantsearch/showcase/compose/filter/rating/RatingShowcase.kt b/showcase/compose/src/main/kotlin/com/algolia/instantsearch/showcase/compose/filter/rating/RatingShowcase.kt similarity index 89% rename from showcase-compose/src/main/kotlin/com/algolia/instantsearch/showcase/compose/filter/rating/RatingShowcase.kt rename to showcase/compose/src/main/kotlin/com/algolia/instantsearch/showcase/compose/filter/rating/RatingShowcase.kt index 569ebc16..e8eee5a2 100644 --- a/showcase-compose/src/main/kotlin/com/algolia/instantsearch/showcase/compose/filter/rating/RatingShowcase.kt +++ b/showcase/compose/src/main/kotlin/com/algolia/instantsearch/showcase/compose/filter/rating/RatingShowcase.kt @@ -17,13 +17,13 @@ import com.algolia.instantsearch.compose.number.range.NumberRangeState import com.algolia.instantsearch.core.connection.ConnectionHandler import com.algolia.instantsearch.core.number.range.Range import com.algolia.instantsearch.core.searcher.Debouncer -import com.algolia.instantsearch.helper.filter.range.FilterRangeConnector -import com.algolia.instantsearch.helper.filter.range.connectView -import com.algolia.instantsearch.helper.filter.state.FilterGroupID -import com.algolia.instantsearch.helper.filter.state.FilterState -import com.algolia.instantsearch.helper.filter.state.filters -import com.algolia.instantsearch.helper.searcher.SearcherSingleIndex -import com.algolia.instantsearch.helper.searcher.connectFilterState +import com.algolia.instantsearch.filter.range.FilterRangeConnector +import com.algolia.instantsearch.filter.range.connectView +import com.algolia.instantsearch.filter.state.FilterGroupID +import com.algolia.instantsearch.filter.state.FilterState +import com.algolia.instantsearch.filter.state.filters +import com.algolia.instantsearch.searcher.connectFilterState +import com.algolia.instantsearch.searcher.hits.HitsSearcher import com.algolia.instantsearch.showcase.compose.client import com.algolia.instantsearch.showcase.compose.filterColors import com.algolia.instantsearch.showcase.compose.showcaseTitle @@ -38,8 +38,7 @@ import com.algolia.search.model.filter.Filter class RatingShowcase : AppCompatActivity() { - private val index = client.initIndex(IndexName("instant_search")) - private val searcher = SearcherSingleIndex(index) + private val searcher = HitsSearcher(client, IndexName("instant_search")) private val rating = Attribute("rating") private val groupID = FilterGroupID(rating) private val primaryBounds = 0f..5f @@ -84,6 +83,8 @@ class RatingShowcase : AppCompatActivity() { @Composable fun RatingScreen(title: String = showcaseTitle) { + ResetInitialRangeIfNeeded() + Scaffold( topBar = { TitleTopBar( @@ -103,7 +104,9 @@ class RatingShowcase : AppCompatActivity() { .padding(horizontal = 16.dp), horizontalArrangement = Arrangement.SpaceBetween ) { + val step = 0.5f + RatingBar( ratingState = ratingState, step = step @@ -160,13 +163,16 @@ class RatingShowcase : AppCompatActivity() { } } + @Composable + private fun ResetInitialRangeIfNeeded() { + if (ratingState.range == null) { + ratingState.setRange(Range(initialRange)) + } + } + override fun onDestroy() { super.onDestroy() searcher.cancel() connections.clear() } - - companion object { - private const val STEP = 0.1f - } } \ No newline at end of file diff --git a/showcase-compose/src/main/kotlin/com/algolia/instantsearch/showcase/compose/filter/toggle/FilterToggleShowcase.kt b/showcase/compose/src/main/kotlin/com/algolia/instantsearch/showcase/compose/filter/toggle/FilterToggleShowcase.kt similarity index 89% rename from showcase-compose/src/main/kotlin/com/algolia/instantsearch/showcase/compose/filter/toggle/FilterToggleShowcase.kt rename to showcase/compose/src/main/kotlin/com/algolia/instantsearch/showcase/compose/filter/toggle/FilterToggleShowcase.kt index 2dbf259c..60c23442 100644 --- a/showcase-compose/src/main/kotlin/com/algolia/instantsearch/showcase/compose/filter/toggle/FilterToggleShowcase.kt +++ b/showcase/compose/src/main/kotlin/com/algolia/instantsearch/showcase/compose/filter/toggle/FilterToggleShowcase.kt @@ -13,15 +13,12 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.unit.dp import com.algolia.instantsearch.compose.filter.toggle.FilterToggleState import com.algolia.instantsearch.core.connection.ConnectionHandler -import com.algolia.instantsearch.helper.filter.state.FilterState -import com.algolia.instantsearch.helper.filter.toggle.FilterToggleConnector -import com.algolia.instantsearch.helper.filter.toggle.connectView -import com.algolia.instantsearch.helper.searcher.SearcherSingleIndex -import com.algolia.instantsearch.helper.searcher.connectFilterState -import com.algolia.instantsearch.showcase.compose.configureSearcher -import com.algolia.instantsearch.showcase.compose.filterColors -import com.algolia.instantsearch.showcase.compose.showcaseTitle -import com.algolia.instantsearch.showcase.compose.stubIndex +import com.algolia.instantsearch.filter.state.FilterState +import com.algolia.instantsearch.filter.toggle.FilterToggleConnector +import com.algolia.instantsearch.filter.toggle.connectView +import com.algolia.instantsearch.searcher.connectFilterState +import com.algolia.instantsearch.searcher.hits.HitsSearcher +import com.algolia.instantsearch.showcase.compose.* import com.algolia.instantsearch.showcase.compose.ui.ShowcaseTheme import com.algolia.instantsearch.showcase.compose.ui.component.HeaderFilter import com.algolia.instantsearch.showcase.compose.ui.component.HeaderFilterConnector @@ -36,7 +33,7 @@ class FilterToggleShowcase : AppCompatActivity() { private val size = Attribute("size") private val tags = Attribute("_tags") private val filterState = FilterState() - private val searcher = SearcherSingleIndex(stubIndex) + private val searcher = HitsSearcher(client, stubIndexName) private val couponState = FilterToggleState() private val filterCoupon = Filter.Facet(promotions, "coupon") diff --git a/showcase-compose/src/main/kotlin/com/algolia/instantsearch/showcase/compose/hierarchical/HierarchicalShowcase.kt b/showcase/compose/src/main/kotlin/com/algolia/instantsearch/showcase/compose/hierarchical/HierarchicalShowcase.kt similarity index 87% rename from showcase-compose/src/main/kotlin/com/algolia/instantsearch/showcase/compose/hierarchical/HierarchicalShowcase.kt rename to showcase/compose/src/main/kotlin/com/algolia/instantsearch/showcase/compose/hierarchical/HierarchicalShowcase.kt index 3b86a54c..430dffc3 100644 --- a/showcase-compose/src/main/kotlin/com/algolia/instantsearch/showcase/compose/hierarchical/HierarchicalShowcase.kt +++ b/showcase/compose/src/main/kotlin/com/algolia/instantsearch/showcase/compose/hierarchical/HierarchicalShowcase.kt @@ -18,17 +18,14 @@ import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.unit.dp import com.algolia.instantsearch.compose.hierarchical.HierarchicalState import com.algolia.instantsearch.core.connection.ConnectionHandler -import com.algolia.instantsearch.helper.filter.state.FilterState -import com.algolia.instantsearch.helper.hierarchical.HierarchicalConnector -import com.algolia.instantsearch.helper.hierarchical.HierarchicalItem -import com.algolia.instantsearch.helper.hierarchical.HierarchicalPresenterImpl -import com.algolia.instantsearch.helper.hierarchical.connectView -import com.algolia.instantsearch.helper.searcher.SearcherSingleIndex -import com.algolia.instantsearch.helper.searcher.connectFilterState -import com.algolia.instantsearch.showcase.compose.configureSearcher -import com.algolia.instantsearch.showcase.compose.filterColors -import com.algolia.instantsearch.showcase.compose.showcaseTitle -import com.algolia.instantsearch.showcase.compose.stubIndex +import com.algolia.instantsearch.filter.state.FilterState +import com.algolia.instantsearch.hierarchical.HierarchicalConnector +import com.algolia.instantsearch.hierarchical.HierarchicalItem +import com.algolia.instantsearch.hierarchical.HierarchicalPresenterImpl +import com.algolia.instantsearch.hierarchical.connectView +import com.algolia.instantsearch.searcher.connectFilterState +import com.algolia.instantsearch.searcher.hits.HitsSearcher +import com.algolia.instantsearch.showcase.compose.* import com.algolia.instantsearch.showcase.compose.ui.ShowcaseTheme import com.algolia.instantsearch.showcase.compose.ui.White import com.algolia.instantsearch.showcase.compose.ui.component.HeaderFilter @@ -47,7 +44,7 @@ class HierarchicalShowcase : AppCompatActivity() { hierarchicalCategoryLvl1, hierarchicalCategoryLvl2 ) - private val searcher = SearcherSingleIndex(stubIndex) + private val searcher = HitsSearcher(client, stubIndexName) private val filterState = FilterState() private val separator = " > " private val hierarchicalState = HierarchicalState() diff --git a/showcase-compose/src/main/kotlin/com/algolia/instantsearch/showcase/compose/highlighting/HighlightingShowcase.kt b/showcase/compose/src/main/kotlin/com/algolia/instantsearch/showcase/compose/highlighting/HighlightingShowcase.kt similarity index 87% rename from showcase-compose/src/main/kotlin/com/algolia/instantsearch/showcase/compose/highlighting/HighlightingShowcase.kt rename to showcase/compose/src/main/kotlin/com/algolia/instantsearch/showcase/compose/highlighting/HighlightingShowcase.kt index 364ca3bd..8666ee86 100644 --- a/showcase-compose/src/main/kotlin/com/algolia/instantsearch/showcase/compose/highlighting/HighlightingShowcase.kt +++ b/showcase/compose/src/main/kotlin/com/algolia/instantsearch/showcase/compose/highlighting/HighlightingShowcase.kt @@ -11,12 +11,13 @@ import com.algolia.instantsearch.compose.hits.HitsState import com.algolia.instantsearch.compose.searchbox.SearchBoxState import com.algolia.instantsearch.core.connection.ConnectionHandler import com.algolia.instantsearch.core.hits.connectHitsView -import com.algolia.instantsearch.helper.searchbox.SearchBoxConnector -import com.algolia.instantsearch.helper.searchbox.connectView -import com.algolia.instantsearch.helper.searcher.SearcherSingleIndex +import com.algolia.instantsearch.searchbox.SearchBoxConnector +import com.algolia.instantsearch.searchbox.connectView +import com.algolia.instantsearch.searcher.hits.HitsSearcher +import com.algolia.instantsearch.showcase.compose.client import com.algolia.instantsearch.showcase.compose.configureSearcher import com.algolia.instantsearch.showcase.compose.model.Movie -import com.algolia.instantsearch.showcase.compose.stubIndex +import com.algolia.instantsearch.showcase.compose.stubIndexName import com.algolia.instantsearch.showcase.compose.ui.ShowcaseTheme import com.algolia.instantsearch.showcase.compose.ui.White import com.algolia.instantsearch.showcase.compose.ui.component.MoviesList @@ -25,7 +26,7 @@ import com.algolia.search.helper.deserialize class HighlightingShowcase : AppCompatActivity() { - private val searcher = SearcherSingleIndex(stubIndex) + private val searcher = HitsSearcher(client, stubIndexName) private val hitsState = HitsState() private val searchBoxState = SearchBoxState() diff --git a/showcase-compose/src/main/kotlin/com/algolia/instantsearch/showcase/compose/list/merged/MergedListShowcase.kt b/showcase/compose/src/main/kotlin/com/algolia/instantsearch/showcase/compose/list/merged/MergedListShowcase.kt similarity index 64% rename from showcase-compose/src/main/kotlin/com/algolia/instantsearch/showcase/compose/list/merged/MergedListShowcase.kt rename to showcase/compose/src/main/kotlin/com/algolia/instantsearch/showcase/compose/list/merged/MergedListShowcase.kt index 6ba49966..2c7173de 100644 --- a/showcase-compose/src/main/kotlin/com/algolia/instantsearch/showcase/compose/list/merged/MergedListShowcase.kt +++ b/showcase/compose/src/main/kotlin/com/algolia/instantsearch/showcase/compose/list/merged/MergedListShowcase.kt @@ -10,17 +10,16 @@ import androidx.compose.material.MaterialTheme import androidx.compose.material.Scaffold import androidx.compose.material.Text import androidx.compose.runtime.Composable -import androidx.compose.runtime.getValue -import androidx.compose.runtime.mutableStateOf -import androidx.compose.runtime.setValue import androidx.compose.ui.Modifier import androidx.compose.ui.unit.dp +import com.algolia.instantsearch.compose.hits.HitsState import com.algolia.instantsearch.compose.searchbox.SearchBoxState import com.algolia.instantsearch.core.connection.ConnectionHandler -import com.algolia.instantsearch.core.searcher.connectView -import com.algolia.instantsearch.helper.searchbox.SearchBoxConnector -import com.algolia.instantsearch.helper.searchbox.connectView -import com.algolia.instantsearch.helper.searcher.SearcherMultipleIndex +import com.algolia.instantsearch.core.hits.connectHitsView +import com.algolia.instantsearch.searchbox.SearchBoxConnector +import com.algolia.instantsearch.searchbox.connectView +import com.algolia.instantsearch.searcher.hits.addHitsSearcher +import com.algolia.instantsearch.searcher.multi.MultiSearcher import com.algolia.instantsearch.showcase.compose.client import com.algolia.instantsearch.showcase.compose.model.Actor import com.algolia.instantsearch.showcase.compose.model.Movie @@ -31,48 +30,48 @@ import com.algolia.instantsearch.showcase.compose.ui.component.MoviesList import com.algolia.instantsearch.showcase.compose.ui.component.SearchTopBar import com.algolia.search.helper.deserialize import com.algolia.search.model.IndexName -import com.algolia.search.model.multipleindex.IndexQuery import com.algolia.search.model.search.Query class MergedListShowcase : AppCompatActivity() { - private val searcher = SearcherMultipleIndex( - client, - listOf( - IndexQuery(IndexName("mobile_demo_movies"), Query(hitsPerPage = 3)), - IndexQuery(IndexName("mobile_demo_actors"), Query(hitsPerPage = 5)) - ) + + private val multiSearcher = MultiSearcher(client) + private val moviesSearcher = multiSearcher.addHitsSearcher( + indexName = IndexName("mobile_demo_movies"), + query = Query(hitsPerPage = 3) + ) + private val actorsSearcher = multiSearcher.addHitsSearcher( + indexName = IndexName("mobile_demo_actors"), + query = Query(hitsPerPage = 5) ) + private val searchBox = SearchBoxConnector(multiSearcher) + private val connections = ConnectionHandler(searchBox) private val searchBoxState = SearchBoxState() - private val searchBox = SearchBoxConnector(searcher) - private var mergedList by mutableStateOf(null) - - private val connections = ConnectionHandler(searchBox) + private val actorsState = HitsState() + private val moviesState = HitsState() init { connections += searchBox.connectView(searchBoxState) - connections += searcher.connectView(view = { mergedList = it }) { - it?.let { response -> - val actors = response.results[1].hits.deserialize(Actor.serializer()) - val movies = response.results[0].hits.deserialize(Movie.serializer()) - MergedList(actors, movies) - } - } + connections += actorsSearcher.connectHitsView(actorsState) { it.hits.deserialize(Actor.serializer()) } + connections += moviesSearcher.connectHitsView(moviesState) { it.hits.deserialize(Movie.serializer()) } } override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContent { ShowcaseTheme { - MergedListScreen(mergedList) + MergedListScreen(actorsState, moviesState) } } - searcher.searchAsync() + multiSearcher.searchAsync() } @Composable - fun MergedListScreen(mergedList: MergedList?) { + fun MergedListScreen( + actorsState: HitsState, + moviesState: HitsState, + ) { Scaffold( topBar = { SearchTopBar( @@ -82,7 +81,6 @@ class MergedListShowcase : AppCompatActivity() { ) }, content = { - val (actors, movies) = mergedList ?: return@Scaffold Column(Modifier.fillMaxWidth()) { Text( text = "Actors", @@ -90,13 +88,13 @@ class MergedListShowcase : AppCompatActivity() { color = GreyLight, modifier = Modifier.padding(horizontal = 16.dp, vertical = 8.dp) ) - ActorsList(actors = actors) + ActorsList(actors = actorsState.hits) Text( text = "Movies", style = MaterialTheme.typography.subtitle2, color = GreyLight, modifier = Modifier.padding(horizontal = 16.dp, vertical = 8.dp) ) - MoviesList(movies = movies) + MoviesList(movies = moviesState.hits) } } ) @@ -104,9 +102,7 @@ class MergedListShowcase : AppCompatActivity() { override fun onDestroy() { super.onDestroy() - searcher.cancel() + multiSearcher.cancel() connections.clear() } } - -data class MergedList(val actors: List, val movies: List) diff --git a/showcase-compose/src/main/kotlin/com/algolia/instantsearch/showcase/compose/list/paging/PagingMultipleIndexShowcase.kt b/showcase/compose/src/main/kotlin/com/algolia/instantsearch/showcase/compose/list/paging/PagingMultipleIndexShowcase.kt similarity index 82% rename from showcase-compose/src/main/kotlin/com/algolia/instantsearch/showcase/compose/list/paging/PagingMultipleIndexShowcase.kt rename to showcase/compose/src/main/kotlin/com/algolia/instantsearch/showcase/compose/list/paging/PagingMultipleIndexShowcase.kt index 0758ca3c..1edebac7 100644 --- a/showcase-compose/src/main/kotlin/com/algolia/instantsearch/showcase/compose/list/paging/PagingMultipleIndexShowcase.kt +++ b/showcase/compose/src/main/kotlin/com/algolia/instantsearch/showcase/compose/list/paging/PagingMultipleIndexShowcase.kt @@ -15,13 +15,15 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.unit.dp import androidx.paging.PagingData import androidx.paging.compose.collectAsLazyPagingItems -import com.algolia.instantsearch.compose.list.Paginator +import com.algolia.instantsearch.android.paging3.Paginator +import com.algolia.instantsearch.android.paging3.flow +import com.algolia.instantsearch.android.paging3.searchbox.connectPaginator import com.algolia.instantsearch.compose.searchbox.SearchBoxState -import com.algolia.instantsearch.compose.searchbox.connectPaginator import com.algolia.instantsearch.core.connection.ConnectionHandler -import com.algolia.instantsearch.helper.searchbox.SearchBoxConnector -import com.algolia.instantsearch.helper.searchbox.connectView -import com.algolia.instantsearch.helper.searcher.SearcherMultipleIndex +import com.algolia.instantsearch.searchbox.SearchBoxConnector +import com.algolia.instantsearch.searchbox.connectView +import com.algolia.instantsearch.searcher.hits.addHitsSearcher +import com.algolia.instantsearch.searcher.multi.MultiSearcher import com.algolia.instantsearch.showcase.compose.client import com.algolia.instantsearch.showcase.compose.model.Actor import com.algolia.instantsearch.showcase.compose.model.Movie @@ -31,24 +33,23 @@ import com.algolia.instantsearch.showcase.compose.ui.component.ActorsHorizontalL import com.algolia.instantsearch.showcase.compose.ui.component.MoviesHorizontalList import com.algolia.instantsearch.showcase.compose.ui.component.SearchTopBar import com.algolia.search.model.IndexName -import com.algolia.search.model.multipleindex.IndexQuery import kotlinx.coroutines.flow.Flow class PagingMultipleIndexShowcase : AppCompatActivity() { - private val indexMovies = IndexQuery(IndexName("mobile_demo_movies")) - private val indexActors = IndexQuery(IndexName("mobile_demo_actors")) - private val searcher = SearcherMultipleIndex(client, listOf(indexMovies, indexActors)) - private val moviesPaginator = Paginator(searcher, indexMovies) { + private val multiSearcher = MultiSearcher(client) + private val searcherMovies = multiSearcher.addHitsSearcher(IndexName("mobile_demo_movies")) + private val searcherActors = multiSearcher.addHitsSearcher(IndexName("mobile_demo_actors")) + private val moviesPaginator = Paginator(searcherMovies) { it.deserialize(Movie.serializer()) } - private val actorsPaginator = Paginator(searcher, indexActors) { + private val actorsPaginator = Paginator(searcherActors) { it.deserialize(Actor.serializer()) } private val searchBoxState = SearchBoxState() - private val searchBox = SearchBoxConnector(searcher) + private val searchBox = SearchBoxConnector(multiSearcher) private val connections = ConnectionHandler(searchBox) @@ -116,7 +117,7 @@ class PagingMultipleIndexShowcase : AppCompatActivity() { override fun onDestroy() { super.onDestroy() - searcher.cancel() + multiSearcher.cancel() connections.clear() } } diff --git a/showcase-compose/src/main/kotlin/com/algolia/instantsearch/showcase/compose/list/paging/PagingSingleIndexShowcase.kt b/showcase/compose/src/main/kotlin/com/algolia/instantsearch/showcase/compose/list/paging/PagingSingleIndexShowcase.kt similarity index 83% rename from showcase-compose/src/main/kotlin/com/algolia/instantsearch/showcase/compose/list/paging/PagingSingleIndexShowcase.kt rename to showcase/compose/src/main/kotlin/com/algolia/instantsearch/showcase/compose/list/paging/PagingSingleIndexShowcase.kt index dd296d48..c62961a1 100644 --- a/showcase-compose/src/main/kotlin/com/algolia/instantsearch/showcase/compose/list/paging/PagingSingleIndexShowcase.kt +++ b/showcase/compose/src/main/kotlin/com/algolia/instantsearch/showcase/compose/list/paging/PagingSingleIndexShowcase.kt @@ -16,29 +16,31 @@ import androidx.compose.ui.unit.dp import androidx.paging.PagingConfig import androidx.paging.PagingData import androidx.paging.compose.collectAsLazyPagingItems +import com.algolia.instantsearch.android.paging3.Paginator +import com.algolia.instantsearch.android.paging3.flow +import com.algolia.instantsearch.android.paging3.searchbox.connectPaginator import com.algolia.instantsearch.compose.item.StatsTextState -import com.algolia.instantsearch.compose.list.Paginator import com.algolia.instantsearch.compose.searchbox.SearchBoxState -import com.algolia.instantsearch.compose.searchbox.connectPaginator import com.algolia.instantsearch.core.connection.ConnectionHandler -import com.algolia.instantsearch.helper.searchbox.SearchBoxConnector -import com.algolia.instantsearch.helper.searchbox.connectView -import com.algolia.instantsearch.helper.searcher.SearcherSingleIndex -import com.algolia.instantsearch.helper.stats.StatsConnector -import com.algolia.instantsearch.helper.stats.StatsPresenterImpl -import com.algolia.instantsearch.helper.stats.connectView +import com.algolia.instantsearch.searchbox.SearchBoxConnector +import com.algolia.instantsearch.searchbox.connectView +import com.algolia.instantsearch.searcher.hits.HitsSearcher +import com.algolia.instantsearch.showcase.compose.client import com.algolia.instantsearch.showcase.compose.configureSearcher import com.algolia.instantsearch.showcase.compose.model.Movie -import com.algolia.instantsearch.showcase.compose.stubIndex +import com.algolia.instantsearch.showcase.compose.stubIndexName import com.algolia.instantsearch.showcase.compose.ui.GreyLight import com.algolia.instantsearch.showcase.compose.ui.ShowcaseTheme import com.algolia.instantsearch.showcase.compose.ui.component.MoviesList import com.algolia.instantsearch.showcase.compose.ui.component.SearchTopBar +import com.algolia.instantsearch.stats.StatsConnector +import com.algolia.instantsearch.stats.StatsPresenterImpl +import com.algolia.instantsearch.stats.connectView import kotlinx.coroutines.flow.Flow class PagingSingleIndexShowcase : AppCompatActivity() { - private val searcher = SearcherSingleIndex(stubIndex) + private val searcher = HitsSearcher(client, stubIndexName) private val pagingConfig = PagingConfig(pageSize = 10) private val paginator = Paginator(searcher, pagingConfig) { it.deserialize(Movie.serializer()) } diff --git a/showcase-compose/src/main/kotlin/com/algolia/instantsearch/showcase/compose/loading/LoadingShowcase.kt b/showcase/compose/src/main/kotlin/com/algolia/instantsearch/showcase/compose/loading/LoadingShowcase.kt similarity index 83% rename from showcase-compose/src/main/kotlin/com/algolia/instantsearch/showcase/compose/loading/LoadingShowcase.kt rename to showcase/compose/src/main/kotlin/com/algolia/instantsearch/showcase/compose/loading/LoadingShowcase.kt index 502f91c8..9d2f2a54 100644 --- a/showcase-compose/src/main/kotlin/com/algolia/instantsearch/showcase/compose/loading/LoadingShowcase.kt +++ b/showcase/compose/src/main/kotlin/com/algolia/instantsearch/showcase/compose/loading/LoadingShowcase.kt @@ -8,19 +8,21 @@ import androidx.compose.material.Scaffold import androidx.compose.runtime.Composable import androidx.paging.PagingData import androidx.paging.compose.collectAsLazyPagingItems -import com.algolia.instantsearch.compose.list.Paginator +import com.algolia.instantsearch.android.paging3.Paginator +import com.algolia.instantsearch.android.paging3.flow +import com.algolia.instantsearch.android.paging3.searchbox.connectPaginator import com.algolia.instantsearch.compose.loading.LoadingState import com.algolia.instantsearch.compose.searchbox.SearchBoxState -import com.algolia.instantsearch.compose.searchbox.connectPaginator import com.algolia.instantsearch.core.connection.ConnectionHandler -import com.algolia.instantsearch.helper.loading.LoadingConnector -import com.algolia.instantsearch.helper.loading.connectView -import com.algolia.instantsearch.helper.searchbox.SearchBoxConnector -import com.algolia.instantsearch.helper.searchbox.connectView -import com.algolia.instantsearch.helper.searcher.SearcherSingleIndex +import com.algolia.instantsearch.loading.LoadingConnector +import com.algolia.instantsearch.loading.connectView +import com.algolia.instantsearch.searchbox.SearchBoxConnector +import com.algolia.instantsearch.searchbox.connectView +import com.algolia.instantsearch.searcher.hits.HitsSearcher +import com.algolia.instantsearch.showcase.compose.client import com.algolia.instantsearch.showcase.compose.configureSearcher import com.algolia.instantsearch.showcase.compose.model.Movie -import com.algolia.instantsearch.showcase.compose.stubIndex +import com.algolia.instantsearch.showcase.compose.stubIndexName import com.algolia.instantsearch.showcase.compose.ui.ShowcaseTheme import com.algolia.instantsearch.showcase.compose.ui.component.MoviesList import com.algolia.instantsearch.showcase.compose.ui.component.SearchTopBar @@ -30,7 +32,7 @@ import kotlinx.coroutines.flow.Flow class LoadingShowcase : AppCompatActivity() { - private val searcher = SearcherSingleIndex(stubIndex) + private val searcher = HitsSearcher(client, stubIndexName) private val paginator = Paginator(searcher) { it.deserialize(Movie.serializer()) } private val loadingState = LoadingState() diff --git a/showcase-compose/src/main/kotlin/com/algolia/instantsearch/showcase/compose/model/Actor.kt b/showcase/compose/src/main/kotlin/com/algolia/instantsearch/showcase/compose/model/Actor.kt similarity index 100% rename from showcase-compose/src/main/kotlin/com/algolia/instantsearch/showcase/compose/model/Actor.kt rename to showcase/compose/src/main/kotlin/com/algolia/instantsearch/showcase/compose/model/Actor.kt diff --git a/showcase-compose/src/main/kotlin/com/algolia/instantsearch/showcase/compose/model/Banner.kt b/showcase/compose/src/main/kotlin/com/algolia/instantsearch/showcase/compose/model/Banner.kt similarity index 100% rename from showcase-compose/src/main/kotlin/com/algolia/instantsearch/showcase/compose/model/Banner.kt rename to showcase/compose/src/main/kotlin/com/algolia/instantsearch/showcase/compose/model/Banner.kt diff --git a/showcase-compose/src/main/kotlin/com/algolia/instantsearch/showcase/compose/model/Movie.kt b/showcase/compose/src/main/kotlin/com/algolia/instantsearch/showcase/compose/model/Movie.kt similarity index 91% rename from showcase-compose/src/main/kotlin/com/algolia/instantsearch/showcase/compose/model/Movie.kt rename to showcase/compose/src/main/kotlin/com/algolia/instantsearch/showcase/compose/model/Movie.kt index 2a542675..bf8cd782 100644 --- a/showcase-compose/src/main/kotlin/com/algolia/instantsearch/showcase/compose/model/Movie.kt +++ b/showcase/compose/src/main/kotlin/com/algolia/instantsearch/showcase/compose/model/Movie.kt @@ -1,6 +1,6 @@ package com.algolia.instantsearch.showcase.compose.model -import com.algolia.instantsearch.helper.highlighting.Highlightable +import com.algolia.instantsearch.highlighting.Highlightable import com.algolia.search.model.Attribute import com.algolia.search.model.ObjectID import com.algolia.search.model.indexing.Indexable diff --git a/showcase-compose/src/main/kotlin/com/algolia/instantsearch/showcase/compose/model/Product.kt b/showcase/compose/src/main/kotlin/com/algolia/instantsearch/showcase/compose/model/Product.kt similarity index 100% rename from showcase-compose/src/main/kotlin/com/algolia/instantsearch/showcase/compose/model/Product.kt rename to showcase/compose/src/main/kotlin/com/algolia/instantsearch/showcase/compose/model/Product.kt diff --git a/showcase-compose/src/main/kotlin/com/algolia/instantsearch/showcase/compose/relateditems/RelatedItemsShowcase.kt b/showcase/compose/src/main/kotlin/com/algolia/instantsearch/showcase/compose/relateditems/RelatedItemsShowcase.kt similarity index 90% rename from showcase-compose/src/main/kotlin/com/algolia/instantsearch/showcase/compose/relateditems/RelatedItemsShowcase.kt rename to showcase/compose/src/main/kotlin/com/algolia/instantsearch/showcase/compose/relateditems/RelatedItemsShowcase.kt index 0362b9b5..6774a067 100644 --- a/showcase-compose/src/main/kotlin/com/algolia/instantsearch/showcase/compose/relateditems/RelatedItemsShowcase.kt +++ b/showcase/compose/src/main/kotlin/com/algolia/instantsearch/showcase/compose/relateditems/RelatedItemsShowcase.kt @@ -15,13 +15,14 @@ import androidx.compose.ui.unit.dp import com.algolia.instantsearch.compose.hits.HitsState import com.algolia.instantsearch.core.connection.Connection import com.algolia.instantsearch.core.hits.connectHitsView -import com.algolia.instantsearch.helper.relateditems.MatchingPattern -import com.algolia.instantsearch.helper.relateditems.connectRelatedHitsView -import com.algolia.instantsearch.helper.searcher.SearcherSingleIndex +import com.algolia.instantsearch.relateditems.MatchingPattern +import com.algolia.instantsearch.relateditems.connectRelatedHitsView +import com.algolia.instantsearch.searcher.hits.HitsSearcher +import com.algolia.instantsearch.showcase.compose.client import com.algolia.instantsearch.showcase.compose.configureSearcher import com.algolia.instantsearch.showcase.compose.model.Product import com.algolia.instantsearch.showcase.compose.showcaseTitle -import com.algolia.instantsearch.showcase.compose.stubIndex +import com.algolia.instantsearch.showcase.compose.stubIndexName import com.algolia.instantsearch.showcase.compose.ui.GreyLight import com.algolia.instantsearch.showcase.compose.ui.ShowcaseTheme import com.algolia.instantsearch.showcase.compose.ui.component.ProductList @@ -31,8 +32,8 @@ import com.algolia.search.model.Attribute class RelatedItemsShowcase : AppCompatActivity() { - private val searcher = SearcherSingleIndex(stubIndex) - private val relatedItemsSearcher = SearcherSingleIndex(stubIndex) + private val searcher = HitsSearcher(client, stubIndexName) + private val relatedItemsSearcher = HitsSearcher(client, stubIndexName) private val productsHits = HitsState() private val relatedItems = HitsState() diff --git a/showcase-compose/src/main/kotlin/com/algolia/instantsearch/showcase/compose/search/SearchAsYouTypeShowcase.kt b/showcase/compose/src/main/kotlin/com/algolia/instantsearch/showcase/compose/search/SearchAsYouTypeShowcase.kt similarity index 87% rename from showcase-compose/src/main/kotlin/com/algolia/instantsearch/showcase/compose/search/SearchAsYouTypeShowcase.kt rename to showcase/compose/src/main/kotlin/com/algolia/instantsearch/showcase/compose/search/SearchAsYouTypeShowcase.kt index 8ff5af34..41dab004 100644 --- a/showcase-compose/src/main/kotlin/com/algolia/instantsearch/showcase/compose/search/SearchAsYouTypeShowcase.kt +++ b/showcase/compose/src/main/kotlin/com/algolia/instantsearch/showcase/compose/search/SearchAsYouTypeShowcase.kt @@ -12,13 +12,14 @@ import com.algolia.instantsearch.compose.hits.HitsState import com.algolia.instantsearch.compose.searchbox.SearchBoxState import com.algolia.instantsearch.core.connection.ConnectionHandler import com.algolia.instantsearch.core.hits.connectHitsView -import com.algolia.instantsearch.helper.searchbox.SearchBoxConnector -import com.algolia.instantsearch.helper.searchbox.SearchMode -import com.algolia.instantsearch.helper.searchbox.connectView -import com.algolia.instantsearch.helper.searcher.SearcherSingleIndex +import com.algolia.instantsearch.searchbox.SearchBoxConnector +import com.algolia.instantsearch.searchbox.SearchMode +import com.algolia.instantsearch.searchbox.connectView +import com.algolia.instantsearch.searcher.hits.HitsSearcher +import com.algolia.instantsearch.showcase.compose.client import com.algolia.instantsearch.showcase.compose.configureSearcher import com.algolia.instantsearch.showcase.compose.model.Movie -import com.algolia.instantsearch.showcase.compose.stubIndex +import com.algolia.instantsearch.showcase.compose.stubIndexName import com.algolia.instantsearch.showcase.compose.ui.ShowcaseTheme import com.algolia.instantsearch.showcase.compose.ui.component.MoviesList import com.algolia.instantsearch.showcase.compose.ui.component.SearchTopBar @@ -26,7 +27,7 @@ import com.algolia.search.helper.deserialize class SearchAsYouTypeShowcase : AppCompatActivity() { - private val searcher = SearcherSingleIndex(stubIndex) + private val searcher = HitsSearcher(client, stubIndexName) private val hitsState = HitsState() private val searchBoxState = SearchBoxState() diff --git a/showcase-compose/src/main/kotlin/com/algolia/instantsearch/showcase/compose/search/SearchAutoCompleteShowcase.kt b/showcase/compose/src/main/kotlin/com/algolia/instantsearch/showcase/compose/search/SearchAutoCompleteShowcase.kt similarity index 86% rename from showcase-compose/src/main/kotlin/com/algolia/instantsearch/showcase/compose/search/SearchAutoCompleteShowcase.kt rename to showcase/compose/src/main/kotlin/com/algolia/instantsearch/showcase/compose/search/SearchAutoCompleteShowcase.kt index 75149797..d5800647 100644 --- a/showcase-compose/src/main/kotlin/com/algolia/instantsearch/showcase/compose/search/SearchAutoCompleteShowcase.kt +++ b/showcase/compose/src/main/kotlin/com/algolia/instantsearch/showcase/compose/search/SearchAutoCompleteShowcase.kt @@ -13,20 +13,21 @@ import com.algolia.instantsearch.compose.hits.HitsState import com.algolia.instantsearch.compose.searchbox.SearchBoxState import com.algolia.instantsearch.core.connection.ConnectionHandler import com.algolia.instantsearch.core.hits.connectHitsView -import com.algolia.instantsearch.helper.searchbox.SearchBoxConnector -import com.algolia.instantsearch.helper.searchbox.SearchMode -import com.algolia.instantsearch.helper.searchbox.connectView -import com.algolia.instantsearch.helper.searcher.SearcherSingleIndex +import com.algolia.instantsearch.searchbox.SearchBoxConnector +import com.algolia.instantsearch.searchbox.SearchMode +import com.algolia.instantsearch.searchbox.connectView +import com.algolia.instantsearch.searcher.hits.HitsSearcher +import com.algolia.instantsearch.showcase.compose.client import com.algolia.instantsearch.showcase.compose.configureSearcher import com.algolia.instantsearch.showcase.compose.model.Movie -import com.algolia.instantsearch.showcase.compose.stubIndex +import com.algolia.instantsearch.showcase.compose.stubIndexName import com.algolia.instantsearch.showcase.compose.ui.component.AutoCompleteTextField import com.algolia.instantsearch.showcase.compose.ui.component.TitleTopBar import com.algolia.search.helper.deserialize class SearchAutoCompleteShowcase : AppCompatActivity() { - private val searcher = SearcherSingleIndex(stubIndex) + private val searcher = HitsSearcher(client, stubIndexName) private val searchBoxState = SearchBoxState() private val searchBox = SearchBoxConnector(searcher, searchMode = SearchMode.AsYouType) private val hitsState = HitsState() diff --git a/showcase-compose/src/main/kotlin/com/algolia/instantsearch/showcase/compose/search/SearchOnSubmitShowcase.kt b/showcase/compose/src/main/kotlin/com/algolia/instantsearch/showcase/compose/search/SearchOnSubmitShowcase.kt similarity index 87% rename from showcase-compose/src/main/kotlin/com/algolia/instantsearch/showcase/compose/search/SearchOnSubmitShowcase.kt rename to showcase/compose/src/main/kotlin/com/algolia/instantsearch/showcase/compose/search/SearchOnSubmitShowcase.kt index f0e0f4bc..9a1dab75 100644 --- a/showcase-compose/src/main/kotlin/com/algolia/instantsearch/showcase/compose/search/SearchOnSubmitShowcase.kt +++ b/showcase/compose/src/main/kotlin/com/algolia/instantsearch/showcase/compose/search/SearchOnSubmitShowcase.kt @@ -12,13 +12,14 @@ import com.algolia.instantsearch.compose.hits.HitsState import com.algolia.instantsearch.compose.searchbox.SearchBoxState import com.algolia.instantsearch.core.connection.ConnectionHandler import com.algolia.instantsearch.core.hits.connectHitsView -import com.algolia.instantsearch.helper.searchbox.SearchBoxConnector -import com.algolia.instantsearch.helper.searchbox.SearchMode -import com.algolia.instantsearch.helper.searchbox.connectView -import com.algolia.instantsearch.helper.searcher.SearcherSingleIndex +import com.algolia.instantsearch.searchbox.SearchBoxConnector +import com.algolia.instantsearch.searchbox.SearchMode +import com.algolia.instantsearch.searchbox.connectView +import com.algolia.instantsearch.searcher.hits.HitsSearcher +import com.algolia.instantsearch.showcase.compose.client import com.algolia.instantsearch.showcase.compose.configureSearcher import com.algolia.instantsearch.showcase.compose.model.Movie -import com.algolia.instantsearch.showcase.compose.stubIndex +import com.algolia.instantsearch.showcase.compose.stubIndexName import com.algolia.instantsearch.showcase.compose.ui.ShowcaseTheme import com.algolia.instantsearch.showcase.compose.ui.component.MoviesList import com.algolia.instantsearch.showcase.compose.ui.component.SearchTopBar @@ -26,7 +27,7 @@ import com.algolia.search.helper.deserialize class SearchOnSubmitShowcase : AppCompatActivity() { - private val searcher = SearcherSingleIndex(stubIndex) + private val searcher = HitsSearcher(client, stubIndexName) private val hitsState = HitsState() private val searchBoxState = SearchBoxState() diff --git a/showcase-compose/src/main/kotlin/com/algolia/instantsearch/showcase/compose/sortby/SortByShowcase.kt b/showcase/compose/src/main/kotlin/com/algolia/instantsearch/showcase/compose/sortby/SortByShowcase.kt similarity index 76% rename from showcase-compose/src/main/kotlin/com/algolia/instantsearch/showcase/compose/sortby/SortByShowcase.kt rename to showcase/compose/src/main/kotlin/com/algolia/instantsearch/showcase/compose/sortby/SortByShowcase.kt index 9a2d0e1b..50884b98 100644 --- a/showcase-compose/src/main/kotlin/com/algolia/instantsearch/showcase/compose/sortby/SortByShowcase.kt +++ b/showcase/compose/src/main/kotlin/com/algolia/instantsearch/showcase/compose/sortby/SortByShowcase.kt @@ -15,9 +15,9 @@ import com.algolia.instantsearch.compose.hits.HitsState import com.algolia.instantsearch.compose.sortby.SortByState import com.algolia.instantsearch.core.connection.ConnectionHandler import com.algolia.instantsearch.core.hits.connectHitsView -import com.algolia.instantsearch.helper.searcher.SearcherSingleIndex -import com.algolia.instantsearch.helper.sortby.SortByConnector -import com.algolia.instantsearch.helper.sortby.connectView +import com.algolia.instantsearch.searcher.hits.HitsSearcher +import com.algolia.instantsearch.sortby.SortByConnector +import com.algolia.instantsearch.sortby.connectView import com.algolia.instantsearch.showcase.compose.client import com.algolia.instantsearch.showcase.compose.model.Movie import com.algolia.instantsearch.showcase.compose.showcaseTitle @@ -29,28 +29,28 @@ import com.algolia.search.model.IndexName class SortByShowcase : AppCompatActivity() { - private val indexTitle = client.initIndex(IndexName("mobile_demo_movies")) - private val indexYearAsc = client.initIndex(IndexName("mobile_demo_movies_year_asc")) - private val indexYearDesc = client.initIndex(IndexName("mobile_demo_movies_year_desc")) - private val searcher = SearcherSingleIndex(indexTitle) + private val movies = IndexName("mobile_demo_movies") + private val moviesAsc = IndexName("mobile_demo_movies_year_asc") + private val moviesDesc = IndexName("mobile_demo_movies_year_desc") private val hitsState = HitsState() private val indexes = mapOf( - 0 to indexTitle, - 1 to indexYearAsc, - 2 to indexYearDesc + 0 to movies, + 1 to moviesAsc, + 2 to moviesDesc ) + private val searcher = HitsSearcher(client, movies) private val sortByState = SortByState() - private val sortBy = SortByConnector(indexes, searcher, selected = 0) + private val sortBy = SortByConnector(searcher, indexes, selected = 0) private val connections = ConnectionHandler(sortBy) init { connections += searcher.connectHitsView(hitsState) { it.hits.deserialize(Movie.serializer()) } - connections += sortBy.connectView(sortByState) { index -> - when (index) { - indexTitle -> "Default" - indexYearAsc -> "Year Asc" - indexYearDesc -> "Year Desc" - else -> index.indexName.raw + connections += sortBy.connectView(sortByState) { indexName -> + when (indexName) { + movies -> "Default" + moviesAsc -> "Year Asc" + moviesDesc -> "Year Desc" + else -> indexName.raw } } } diff --git a/showcase-compose/src/main/kotlin/com/algolia/instantsearch/showcase/compose/stats/StatsShowcase.kt b/showcase/compose/src/main/kotlin/com/algolia/instantsearch/showcase/compose/stats/StatsShowcase.kt similarity index 87% rename from showcase-compose/src/main/kotlin/com/algolia/instantsearch/showcase/compose/stats/StatsShowcase.kt rename to showcase/compose/src/main/kotlin/com/algolia/instantsearch/showcase/compose/stats/StatsShowcase.kt index 6223d52d..e407987e 100644 --- a/showcase-compose/src/main/kotlin/com/algolia/instantsearch/showcase/compose/stats/StatsShowcase.kt +++ b/showcase/compose/src/main/kotlin/com/algolia/instantsearch/showcase/compose/stats/StatsShowcase.kt @@ -19,21 +19,22 @@ import com.algolia.instantsearch.compose.item.StatsState import com.algolia.instantsearch.compose.item.StatsTextState import com.algolia.instantsearch.compose.searchbox.SearchBoxState import com.algolia.instantsearch.core.connection.ConnectionHandler -import com.algolia.instantsearch.helper.searchbox.SearchBoxConnector -import com.algolia.instantsearch.helper.searchbox.connectView -import com.algolia.instantsearch.helper.searcher.SearcherSingleIndex -import com.algolia.instantsearch.helper.stats.StatsConnector -import com.algolia.instantsearch.helper.stats.StatsPresenterImpl -import com.algolia.instantsearch.helper.stats.connectView +import com.algolia.instantsearch.searchbox.SearchBoxConnector +import com.algolia.instantsearch.searchbox.connectView +import com.algolia.instantsearch.searcher.hits.HitsSearcher +import com.algolia.instantsearch.stats.StatsConnector +import com.algolia.instantsearch.stats.StatsPresenterImpl +import com.algolia.instantsearch.stats.connectView import com.algolia.instantsearch.showcase.compose.R +import com.algolia.instantsearch.showcase.compose.client import com.algolia.instantsearch.showcase.compose.configureSearcher -import com.algolia.instantsearch.showcase.compose.stubIndex +import com.algolia.instantsearch.showcase.compose.stubIndexName import com.algolia.instantsearch.showcase.compose.ui.ShowcaseTheme import com.algolia.instantsearch.showcase.compose.ui.component.SearchTopBar class StatsShowcase : AppCompatActivity() { - private val searcher = SearcherSingleIndex(stubIndex) + private val searcher = HitsSearcher(client, stubIndexName) private val searchBox = SearchBoxConnector(searcher) private val searchBoxState = SearchBoxState() diff --git a/showcase-compose/src/main/kotlin/com/algolia/instantsearch/showcase/compose/ui/Color.kt b/showcase/compose/src/main/kotlin/com/algolia/instantsearch/showcase/compose/ui/Color.kt similarity index 100% rename from showcase-compose/src/main/kotlin/com/algolia/instantsearch/showcase/compose/ui/Color.kt rename to showcase/compose/src/main/kotlin/com/algolia/instantsearch/showcase/compose/ui/Color.kt diff --git a/showcase-compose/src/main/kotlin/com/algolia/instantsearch/showcase/compose/ui/Shape.kt b/showcase/compose/src/main/kotlin/com/algolia/instantsearch/showcase/compose/ui/Shape.kt similarity index 100% rename from showcase-compose/src/main/kotlin/com/algolia/instantsearch/showcase/compose/ui/Shape.kt rename to showcase/compose/src/main/kotlin/com/algolia/instantsearch/showcase/compose/ui/Shape.kt diff --git a/showcase-compose/src/main/kotlin/com/algolia/instantsearch/showcase/compose/ui/Theme.kt b/showcase/compose/src/main/kotlin/com/algolia/instantsearch/showcase/compose/ui/Theme.kt similarity index 100% rename from showcase-compose/src/main/kotlin/com/algolia/instantsearch/showcase/compose/ui/Theme.kt rename to showcase/compose/src/main/kotlin/com/algolia/instantsearch/showcase/compose/ui/Theme.kt diff --git a/showcase-compose/src/main/kotlin/com/algolia/instantsearch/showcase/compose/ui/Type.kt b/showcase/compose/src/main/kotlin/com/algolia/instantsearch/showcase/compose/ui/Type.kt similarity index 100% rename from showcase-compose/src/main/kotlin/com/algolia/instantsearch/showcase/compose/ui/Type.kt rename to showcase/compose/src/main/kotlin/com/algolia/instantsearch/showcase/compose/ui/Type.kt diff --git a/showcase-compose/src/main/kotlin/com/algolia/instantsearch/showcase/compose/ui/component/ActorsList.kt b/showcase/compose/src/main/kotlin/com/algolia/instantsearch/showcase/compose/ui/component/ActorsList.kt similarity index 100% rename from showcase-compose/src/main/kotlin/com/algolia/instantsearch/showcase/compose/ui/component/ActorsList.kt rename to showcase/compose/src/main/kotlin/com/algolia/instantsearch/showcase/compose/ui/component/ActorsList.kt diff --git a/showcase-compose/src/main/kotlin/com/algolia/instantsearch/showcase/compose/ui/component/AutoCompleteTextField.kt b/showcase/compose/src/main/kotlin/com/algolia/instantsearch/showcase/compose/ui/component/AutoCompleteTextField.kt similarity index 100% rename from showcase-compose/src/main/kotlin/com/algolia/instantsearch/showcase/compose/ui/component/AutoCompleteTextField.kt rename to showcase/compose/src/main/kotlin/com/algolia/instantsearch/showcase/compose/ui/component/AutoCompleteTextField.kt diff --git a/showcase-compose/src/main/kotlin/com/algolia/instantsearch/showcase/compose/ui/component/DropdownTextField.kt b/showcase/compose/src/main/kotlin/com/algolia/instantsearch/showcase/compose/ui/component/DropdownTextField.kt similarity index 100% rename from showcase-compose/src/main/kotlin/com/algolia/instantsearch/showcase/compose/ui/component/DropdownTextField.kt rename to showcase/compose/src/main/kotlin/com/algolia/instantsearch/showcase/compose/ui/component/DropdownTextField.kt diff --git a/showcase-compose/src/main/kotlin/com/algolia/instantsearch/showcase/compose/ui/component/FacetList.kt b/showcase/compose/src/main/kotlin/com/algolia/instantsearch/showcase/compose/ui/component/FacetList.kt similarity index 93% rename from showcase-compose/src/main/kotlin/com/algolia/instantsearch/showcase/compose/ui/component/FacetList.kt rename to showcase/compose/src/main/kotlin/com/algolia/instantsearch/showcase/compose/ui/component/FacetList.kt index 31471552..fbf87ab9 100644 --- a/showcase-compose/src/main/kotlin/com/algolia/instantsearch/showcase/compose/ui/component/FacetList.kt +++ b/showcase/compose/src/main/kotlin/com/algolia/instantsearch/showcase/compose/ui/component/FacetList.kt @@ -13,11 +13,11 @@ import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp import com.algolia.instantsearch.compose.filter.facet.FacetListState import com.algolia.instantsearch.core.selectable.list.SelectableItem -import com.algolia.instantsearch.helper.filter.facet.FacetListPresenterImpl -import com.algolia.instantsearch.helper.filter.facet.FacetSortCriterion -import com.algolia.instantsearch.helper.filter.state.FilterGroupID -import com.algolia.instantsearch.helper.filter.state.FilterOperator -import com.algolia.instantsearch.helper.filter.state.groupAnd +import com.algolia.instantsearch.filter.facet.FacetListPresenterImpl +import com.algolia.instantsearch.filter.facet.FacetSortCriterion +import com.algolia.instantsearch.filter.state.FilterGroupID +import com.algolia.instantsearch.filter.state.FilterOperator +import com.algolia.instantsearch.filter.state.groupAnd import com.algolia.instantsearch.showcase.compose.ui.BlueDark import com.algolia.instantsearch.showcase.compose.ui.HoloRedDark import com.algolia.instantsearch.showcase.compose.ui.ShowcaseTheme diff --git a/showcase-compose/src/main/kotlin/com/algolia/instantsearch/showcase/compose/ui/component/FilterChips.kt b/showcase/compose/src/main/kotlin/com/algolia/instantsearch/showcase/compose/ui/component/FilterChips.kt similarity index 100% rename from showcase-compose/src/main/kotlin/com/algolia/instantsearch/showcase/compose/ui/component/FilterChips.kt rename to showcase/compose/src/main/kotlin/com/algolia/instantsearch/showcase/compose/ui/component/FilterChips.kt diff --git a/showcase-compose/src/main/kotlin/com/algolia/instantsearch/showcase/compose/ui/component/FilterList.kt b/showcase/compose/src/main/kotlin/com/algolia/instantsearch/showcase/compose/ui/component/FilterList.kt similarity index 96% rename from showcase-compose/src/main/kotlin/com/algolia/instantsearch/showcase/compose/ui/component/FilterList.kt rename to showcase/compose/src/main/kotlin/com/algolia/instantsearch/showcase/compose/ui/component/FilterList.kt index 73bcbdb6..4354f5e6 100644 --- a/showcase-compose/src/main/kotlin/com/algolia/instantsearch/showcase/compose/ui/component/FilterList.kt +++ b/showcase/compose/src/main/kotlin/com/algolia/instantsearch/showcase/compose/ui/component/FilterList.kt @@ -12,8 +12,8 @@ import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp import com.algolia.instantsearch.compose.filter.list.FilterListState import com.algolia.instantsearch.core.selectable.list.SelectableItem -import com.algolia.instantsearch.helper.filter.FilterPresenter -import com.algolia.instantsearch.helper.filter.FilterPresenterImpl +import com.algolia.instantsearch.filter.FilterPresenter +import com.algolia.instantsearch.filter.FilterPresenterImpl import com.algolia.instantsearch.showcase.compose.ui.BlueDark import com.algolia.instantsearch.showcase.compose.ui.ShowcaseTheme import com.algolia.instantsearch.showcase.compose.ui.White diff --git a/showcase-compose/src/main/kotlin/com/algolia/instantsearch/showcase/compose/ui/component/HeaderFilter.kt b/showcase/compose/src/main/kotlin/com/algolia/instantsearch/showcase/compose/ui/component/HeaderFilter.kt similarity index 100% rename from showcase-compose/src/main/kotlin/com/algolia/instantsearch/showcase/compose/ui/component/HeaderFilter.kt rename to showcase/compose/src/main/kotlin/com/algolia/instantsearch/showcase/compose/ui/component/HeaderFilter.kt diff --git a/showcase-compose/src/main/kotlin/com/algolia/instantsearch/showcase/compose/ui/component/HeaderFilterConnector.kt b/showcase/compose/src/main/kotlin/com/algolia/instantsearch/showcase/compose/ui/component/HeaderFilterConnector.kt similarity index 73% rename from showcase-compose/src/main/kotlin/com/algolia/instantsearch/showcase/compose/ui/component/HeaderFilterConnector.kt rename to showcase/compose/src/main/kotlin/com/algolia/instantsearch/showcase/compose/ui/component/HeaderFilterConnector.kt index 9d4ebc55..807f8933 100644 --- a/showcase-compose/src/main/kotlin/com/algolia/instantsearch/showcase/compose/ui/component/HeaderFilterConnector.kt +++ b/showcase/compose/src/main/kotlin/com/algolia/instantsearch/showcase/compose/ui/component/HeaderFilterConnector.kt @@ -8,18 +8,18 @@ import com.algolia.instantsearch.compose.filter.clear.FilterClear import com.algolia.instantsearch.compose.item.StatsState import com.algolia.instantsearch.compose.item.StatsTextState import com.algolia.instantsearch.core.connection.ConnectionImpl -import com.algolia.instantsearch.helper.filter.clear.FilterClearConnector -import com.algolia.instantsearch.helper.filter.clear.connectView -import com.algolia.instantsearch.helper.filter.state.FilterState -import com.algolia.instantsearch.helper.filter.state.toFilterGroups -import com.algolia.instantsearch.helper.searcher.SearcherIndex -import com.algolia.instantsearch.helper.stats.StatsConnector -import com.algolia.instantsearch.helper.stats.StatsPresenterImpl -import com.algolia.instantsearch.helper.stats.connectView +import com.algolia.instantsearch.filter.clear.FilterClearConnector +import com.algolia.instantsearch.filter.clear.connectView +import com.algolia.instantsearch.filter.state.FilterState +import com.algolia.instantsearch.filter.state.toFilterGroups +import com.algolia.instantsearch.searcher.SearcherForHits +import com.algolia.instantsearch.stats.StatsConnector +import com.algolia.instantsearch.stats.StatsPresenterImpl +import com.algolia.instantsearch.stats.connectView import com.algolia.search.model.filter.FilterGroup class HeaderFilterConnector( - searcher: SearcherIndex<*>, + searcher: SearcherForHits<*>, filterState: FilterState, val filterColors: Map = emptyMap(), val hitsStats: StatsState = StatsTextState(), diff --git a/showcase-compose/src/main/kotlin/com/algolia/instantsearch/showcase/compose/ui/component/HelpDialog.kt b/showcase/compose/src/main/kotlin/com/algolia/instantsearch/showcase/compose/ui/component/HelpDialog.kt similarity index 100% rename from showcase-compose/src/main/kotlin/com/algolia/instantsearch/showcase/compose/ui/component/HelpDialog.kt rename to showcase/compose/src/main/kotlin/com/algolia/instantsearch/showcase/compose/ui/component/HelpDialog.kt diff --git a/showcase-compose/src/main/kotlin/com/algolia/instantsearch/showcase/compose/ui/component/MoviesList.kt b/showcase/compose/src/main/kotlin/com/algolia/instantsearch/showcase/compose/ui/component/MoviesList.kt similarity index 100% rename from showcase-compose/src/main/kotlin/com/algolia/instantsearch/showcase/compose/ui/component/MoviesList.kt rename to showcase/compose/src/main/kotlin/com/algolia/instantsearch/showcase/compose/ui/component/MoviesList.kt diff --git a/showcase-compose/src/main/kotlin/com/algolia/instantsearch/showcase/compose/ui/component/ProductList.kt b/showcase/compose/src/main/kotlin/com/algolia/instantsearch/showcase/compose/ui/component/ProductList.kt similarity index 100% rename from showcase-compose/src/main/kotlin/com/algolia/instantsearch/showcase/compose/ui/component/ProductList.kt rename to showcase/compose/src/main/kotlin/com/algolia/instantsearch/showcase/compose/ui/component/ProductList.kt diff --git a/showcase-compose/src/main/kotlin/com/algolia/instantsearch/showcase/compose/ui/component/RatingBar.kt b/showcase/compose/src/main/kotlin/com/algolia/instantsearch/showcase/compose/ui/component/RatingBar.kt similarity index 100% rename from showcase-compose/src/main/kotlin/com/algolia/instantsearch/showcase/compose/ui/component/RatingBar.kt rename to showcase/compose/src/main/kotlin/com/algolia/instantsearch/showcase/compose/ui/component/RatingBar.kt diff --git a/showcase-compose/src/main/kotlin/com/algolia/instantsearch/showcase/compose/ui/component/RestoreFab.kt b/showcase/compose/src/main/kotlin/com/algolia/instantsearch/showcase/compose/ui/component/RestoreFab.kt similarity index 100% rename from showcase-compose/src/main/kotlin/com/algolia/instantsearch/showcase/compose/ui/component/RestoreFab.kt rename to showcase/compose/src/main/kotlin/com/algolia/instantsearch/showcase/compose/ui/component/RestoreFab.kt diff --git a/showcase-compose/src/main/kotlin/com/algolia/instantsearch/showcase/compose/ui/component/TopBar.kt b/showcase/compose/src/main/kotlin/com/algolia/instantsearch/showcase/compose/ui/component/TopBar.kt similarity index 100% rename from showcase-compose/src/main/kotlin/com/algolia/instantsearch/showcase/compose/ui/component/TopBar.kt rename to showcase/compose/src/main/kotlin/com/algolia/instantsearch/showcase/compose/ui/component/TopBar.kt diff --git a/compose/src/main/res/drawable-v24/ic_launcher_foreground.xml b/showcase/compose/src/main/res/drawable-v24/ic_launcher_foreground.xml similarity index 100% rename from compose/src/main/res/drawable-v24/ic_launcher_foreground.xml rename to showcase/compose/src/main/res/drawable-v24/ic_launcher_foreground.xml diff --git a/compose/src/main/res/drawable/ic_launcher_background.xml b/showcase/compose/src/main/res/drawable/ic_launcher_background.xml similarity index 100% rename from compose/src/main/res/drawable/ic_launcher_background.xml rename to showcase/compose/src/main/res/drawable/ic_launcher_background.xml diff --git a/showcase/src/main/res/drawable/thumb.xml b/showcase/compose/src/main/res/drawable/thumb.xml similarity index 100% rename from showcase/src/main/res/drawable/thumb.xml rename to showcase/compose/src/main/res/drawable/thumb.xml diff --git a/showcase-compose/src/main/res/layout/autocompletetextfield.xml b/showcase/compose/src/main/res/layout/autocompletetextfield.xml similarity index 100% rename from showcase-compose/src/main/res/layout/autocompletetextfield.xml rename to showcase/compose/src/main/res/layout/autocompletetextfield.xml diff --git a/compose/src/main/res/mipmap-anydpi-v26/ic_launcher.xml b/showcase/compose/src/main/res/mipmap-anydpi-v26/ic_launcher.xml similarity index 100% rename from compose/src/main/res/mipmap-anydpi-v26/ic_launcher.xml rename to showcase/compose/src/main/res/mipmap-anydpi-v26/ic_launcher.xml diff --git a/compose/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml b/showcase/compose/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml similarity index 100% rename from compose/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml rename to showcase/compose/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml diff --git a/compose/src/main/res/mipmap-hdpi/ic_launcher.webp b/showcase/compose/src/main/res/mipmap-hdpi/ic_launcher.webp similarity index 100% rename from compose/src/main/res/mipmap-hdpi/ic_launcher.webp rename to showcase/compose/src/main/res/mipmap-hdpi/ic_launcher.webp diff --git a/compose/src/main/res/mipmap-hdpi/ic_launcher_round.webp b/showcase/compose/src/main/res/mipmap-hdpi/ic_launcher_round.webp similarity index 100% rename from compose/src/main/res/mipmap-hdpi/ic_launcher_round.webp rename to showcase/compose/src/main/res/mipmap-hdpi/ic_launcher_round.webp diff --git a/compose/src/main/res/mipmap-mdpi/ic_launcher.webp b/showcase/compose/src/main/res/mipmap-mdpi/ic_launcher.webp similarity index 100% rename from compose/src/main/res/mipmap-mdpi/ic_launcher.webp rename to showcase/compose/src/main/res/mipmap-mdpi/ic_launcher.webp diff --git a/compose/src/main/res/mipmap-mdpi/ic_launcher_round.webp b/showcase/compose/src/main/res/mipmap-mdpi/ic_launcher_round.webp similarity index 100% rename from compose/src/main/res/mipmap-mdpi/ic_launcher_round.webp rename to showcase/compose/src/main/res/mipmap-mdpi/ic_launcher_round.webp diff --git a/compose/src/main/res/mipmap-xhdpi/ic_launcher.webp b/showcase/compose/src/main/res/mipmap-xhdpi/ic_launcher.webp similarity index 100% rename from compose/src/main/res/mipmap-xhdpi/ic_launcher.webp rename to showcase/compose/src/main/res/mipmap-xhdpi/ic_launcher.webp diff --git a/compose/src/main/res/mipmap-xhdpi/ic_launcher_round.webp b/showcase/compose/src/main/res/mipmap-xhdpi/ic_launcher_round.webp similarity index 100% rename from compose/src/main/res/mipmap-xhdpi/ic_launcher_round.webp rename to showcase/compose/src/main/res/mipmap-xhdpi/ic_launcher_round.webp diff --git a/compose/src/main/res/mipmap-xxhdpi/ic_launcher.webp b/showcase/compose/src/main/res/mipmap-xxhdpi/ic_launcher.webp similarity index 100% rename from compose/src/main/res/mipmap-xxhdpi/ic_launcher.webp rename to showcase/compose/src/main/res/mipmap-xxhdpi/ic_launcher.webp diff --git a/compose/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp b/showcase/compose/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp similarity index 100% rename from compose/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp rename to showcase/compose/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp diff --git a/compose/src/main/res/mipmap-xxxhdpi/ic_launcher.webp b/showcase/compose/src/main/res/mipmap-xxxhdpi/ic_launcher.webp similarity index 100% rename from compose/src/main/res/mipmap-xxxhdpi/ic_launcher.webp rename to showcase/compose/src/main/res/mipmap-xxxhdpi/ic_launcher.webp diff --git a/compose/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp b/showcase/compose/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp similarity index 100% rename from compose/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp rename to showcase/compose/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp diff --git a/showcase-compose/src/main/res/values/colors.xml b/showcase/compose/src/main/res/values/colors.xml similarity index 100% rename from showcase-compose/src/main/res/values/colors.xml rename to showcase/compose/src/main/res/values/colors.xml diff --git a/showcase-compose/src/main/res/values/strings.xml b/showcase/compose/src/main/res/values/strings.xml similarity index 100% rename from showcase-compose/src/main/res/values/strings.xml rename to showcase/compose/src/main/res/values/strings.xml diff --git a/showcase-compose/src/main/res/values/themes.xml b/showcase/compose/src/main/res/values/themes.xml similarity index 100% rename from showcase-compose/src/main/res/values/themes.xml rename to showcase/compose/src/main/res/values/themes.xml diff --git a/showcase/src/main/kotlin/com/algolia/instantsearch/showcase/filter/clear/FilterClearShowcase.kt b/showcase/src/main/kotlin/com/algolia/instantsearch/showcase/filter/clear/FilterClearShowcase.kt deleted file mode 100644 index ab1801ab..00000000 --- a/showcase/src/main/kotlin/com/algolia/instantsearch/showcase/filter/clear/FilterClearShowcase.kt +++ /dev/null @@ -1,71 +0,0 @@ -package com.algolia.instantsearch.showcase.filter.clear - -import android.os.Bundle -import androidx.appcompat.app.AppCompatActivity -import com.algolia.instantsearch.core.connection.ConnectionHandler -import com.algolia.instantsearch.showcase.* -import com.algolia.instantsearch.helper.android.filter.clear.FilterClearViewImpl -import com.algolia.instantsearch.helper.filter.clear.ClearMode -import com.algolia.instantsearch.helper.filter.clear.FilterClearConnector -import com.algolia.instantsearch.helper.filter.clear.connectView -import com.algolia.instantsearch.helper.filter.state.FilterState -import com.algolia.instantsearch.helper.filter.state.filters -import com.algolia.instantsearch.helper.filter.state.groupOr -import com.algolia.instantsearch.helper.searcher.SearcherSingleIndex -import com.algolia.instantsearch.helper.searcher.connectFilterState -import com.algolia.search.model.Attribute -import kotlinx.android.synthetic.main.showcase_filter_clear.* -import kotlinx.android.synthetic.main.showcase_filter_toggle_default.toolbar -import kotlinx.android.synthetic.main.header_filter.* - - -class FilterClearShowcase : AppCompatActivity() { - - private val color = Attribute("color") - private val category = Attribute("category") - private val groupColor = groupOr(color) - private val groupCategory = groupOr(category) - private val filters = filters { - group(groupColor) { - facet(color, "red") - facet(color, "green") - } - group(groupCategory) { - facet(category, "shoe") - } - } - private val filterState = FilterState(filters) - private val searcher = SearcherSingleIndex(stubIndex) - private val clearAll = FilterClearConnector(filterState) - private val clearSpecified = FilterClearConnector(filterState, listOf(groupColor), ClearMode.Specified) - private val clearExcept = FilterClearConnector(filterState, listOf(groupColor), ClearMode.Except) - private val connection = ConnectionHandler( - clearSpecified, - clearExcept, - searcher.connectFilterState(filterState) - ) - - override fun onCreate(savedInstanceState: Bundle?) { - super.onCreate(savedInstanceState) - setContentView(R.layout.showcase_filter_clear) - - connection += clearAll.connectView(FilterClearViewImpl(filtersClearAll)) - connection += clearSpecified.connectView(FilterClearViewImpl(buttonClearSpecified)) - connection += clearExcept.connectView(FilterClearViewImpl(buttonClearExcept)) - - configureToolbar(toolbar) - configureSearcher(searcher) - onFilterChangedThenUpdateFiltersText(filterState, filtersTextView, color, category) - onErrorThenUpdateFiltersText(searcher, filtersTextView) - onResponseChangedThenUpdateNbHits(searcher, nbHits, connection) - onResetThenRestoreFilters(reset, filterState, filters) - - searcher.searchAsync() - } - - override fun onDestroy() { - super.onDestroy() - searcher.cancel() - connection.clear() - } -} \ No newline at end of file diff --git a/showcase/src/main/kotlin/com/algolia/instantsearch/showcase/filter/facet/FacetListPersistentShowcase.kt b/showcase/src/main/kotlin/com/algolia/instantsearch/showcase/filter/facet/FacetListPersistentShowcase.kt deleted file mode 100644 index 4eef504b..00000000 --- a/showcase/src/main/kotlin/com/algolia/instantsearch/showcase/filter/facet/FacetListPersistentShowcase.kt +++ /dev/null @@ -1,80 +0,0 @@ -package com.algolia.instantsearch.showcase.filter.facet - -import android.os.Bundle -import androidx.appcompat.app.AppCompatActivity -import com.algolia.instantsearch.core.connection.ConnectionHandler -import com.algolia.instantsearch.core.selectable.list.SelectionMode -import com.algolia.instantsearch.showcase.* -import com.algolia.instantsearch.helper.android.filter.facet.FacetListAdapter -import com.algolia.instantsearch.helper.filter.facet.FacetListConnector -import com.algolia.instantsearch.helper.filter.facet.connectView -import com.algolia.instantsearch.helper.filter.state.FilterState -import com.algolia.instantsearch.helper.searcher.SearcherSingleIndex -import com.algolia.instantsearch.helper.searcher.connectFilterState -import com.algolia.search.model.Attribute -import com.algolia.search.model.IndexName -import kotlinx.android.synthetic.main.showcase_facet_list_persistent.* -import kotlinx.android.synthetic.main.header_filter.* -import kotlinx.android.synthetic.main.include_list.* -import kotlinx.android.synthetic.main.include_search.* - - -class FacetListPersistentShowcase : AppCompatActivity() { - - private val color = Attribute("color") - private val category = Attribute("category") - private val index = client.initIndex(IndexName("stub")) - private val filterState = FilterState() - private val searcher = SearcherSingleIndex(index) - private val facetListColor = FacetListConnector( - searcher = searcher, - filterState = filterState, - attribute = color, - selectionMode = SelectionMode.Multiple, - persistentSelection = true - ) - private val facetListCategory = FacetListConnector( - searcher = searcher, - filterState = filterState, - attribute = category, - selectionMode = SelectionMode.Single, - persistentSelection = true - ) - private val connection = ConnectionHandler( - facetListColor, - facetListCategory, - searcher.connectFilterState(filterState) - ) - - override fun onCreate(savedInstanceState: Bundle?) { - super.onCreate(savedInstanceState) - setContentView(R.layout.showcase_facet_list_persistent) - - val adapterColor = FacetListAdapter(FacetListViewHolderImpl.Factory) - val adapterCategory = FacetListAdapter(FacetListViewHolderImpl.Factory) - - connection += facetListColor.connectView(adapterColor) - connection += facetListCategory.connectView(adapterCategory) - - configureToolbar(toolbar) - configureSearcher(searcher) - configureSearchBox(searchView, searcher, connection) - configureSearchView(searchView, getString(R.string.search_items)) - configureRecyclerView(listTopLeft, adapterColor) - configureRecyclerView(listTopRight, adapterCategory) - configureTitle(titleTopLeft, getString(R.string.multiple_choice)) - configureTitle(titleTopRight, getString(R.string.single_choice)) - onFilterChangedThenUpdateFiltersText(filterState, filtersTextView, color, category) - onClearAllThenClearFilters(filterState, filtersClearAll, connection) - onErrorThenUpdateFiltersText(searcher, filtersTextView) - onResponseChangedThenUpdateNbHits(searcher, nbHits, connection) - - searcher.searchAsync() - } - - override fun onDestroy() { - super.onDestroy() - searcher.cancel() - connection.clear() - } -} \ No newline at end of file diff --git a/showcase/src/main/kotlin/com/algolia/instantsearch/showcase/filter/facet/FacetListSearchShowcase.kt b/showcase/src/main/kotlin/com/algolia/instantsearch/showcase/filter/facet/FacetListSearchShowcase.kt deleted file mode 100644 index c78ee2e6..00000000 --- a/showcase/src/main/kotlin/com/algolia/instantsearch/showcase/filter/facet/FacetListSearchShowcase.kt +++ /dev/null @@ -1,80 +0,0 @@ -package com.algolia.instantsearch.showcase.filter.facet - -import android.os.Bundle -import androidx.appcompat.app.AppCompatActivity -import com.algolia.instantsearch.core.connection.ConnectionHandler -import com.algolia.instantsearch.core.selectable.list.SelectionMode -import com.algolia.instantsearch.showcase.* -import com.algolia.instantsearch.helper.android.filter.facet.FacetListAdapter -import com.algolia.instantsearch.helper.android.searchbox.SearchBoxViewAppCompat -import com.algolia.instantsearch.helper.filter.facet.FacetListConnector -import com.algolia.instantsearch.helper.filter.facet.FacetListPresenterImpl -import com.algolia.instantsearch.helper.filter.facet.FacetSortCriterion -import com.algolia.instantsearch.helper.filter.facet.connectView -import com.algolia.instantsearch.helper.filter.state.FilterState -import com.algolia.instantsearch.helper.searchbox.SearchBoxConnector -import com.algolia.instantsearch.helper.searchbox.connectView -import com.algolia.instantsearch.helper.searcher.SearcherForFacets -import com.algolia.instantsearch.helper.searcher.SearcherSingleIndex -import com.algolia.instantsearch.helper.searcher.connectFilterState -import com.algolia.search.model.Attribute -import kotlinx.android.synthetic.main.showcase_facet_list_search.* -import kotlinx.android.synthetic.main.header_filter.* -import kotlinx.android.synthetic.main.include_search.* - - -class FacetListSearchShowcase : AppCompatActivity() { - - private val brand = Attribute("brand") - private val filterState = FilterState() - private val searcher = SearcherSingleIndex(stubIndex) - private val searcherForFacet = SearcherForFacets(stubIndex, brand) - private val searchBox = SearchBoxConnector(searcherForFacet) - private val facetList = FacetListConnector( - searcher = searcherForFacet, - filterState = filterState, - attribute = brand, - selectionMode = SelectionMode.Multiple - ) - private val connection = ConnectionHandler( - searchBox, - facetList, - searcher.connectFilterState(filterState) - ) - - override fun onCreate(savedInstanceState: Bundle?) { - super.onCreate(savedInstanceState) - setContentView(R.layout.showcase_facet_list_search) - - val index = client.initIndex(intent.indexName) - val searchBoxView = SearchBoxViewAppCompat(searchView) - val facetView = FacetListAdapter(FacetListViewHolderImpl.Factory) - val facetPresenter = FacetListPresenterImpl( - sortBy = listOf(FacetSortCriterion.IsRefined, FacetSortCriterion.CountDescending), - limit = 100 - ) - - searcher.index = index - searcherForFacet.index = index - - connection += facetList.connectView(facetView, facetPresenter) - connection += searchBox.connectView(searchBoxView) - - configureToolbar(toolbar) - configureRecyclerView(hits, facetView) - configureSearchView(searchView, getString(R.string.search_brands)) - onFilterChangedThenUpdateFiltersText(filterState, filtersTextView, brand) - onClearAllThenClearFilters(filterState, filtersClearAll, connection) - onResponseChangedThenUpdateNbHits(searcher, nbHits, connection) - - searcher.searchAsync() - searcherForFacet.searchAsync() - } - - override fun onDestroy() { - super.onDestroy() - searcher.cancel() - searcherForFacet.cancel() - connection.clear() - } -} diff --git a/showcase/src/main/kotlin/com/algolia/instantsearch/showcase/filter/facet/FacetListViewHolderImpl.kt b/showcase/src/main/kotlin/com/algolia/instantsearch/showcase/filter/facet/FacetListViewHolderImpl.kt deleted file mode 100644 index 466b8867..00000000 --- a/showcase/src/main/kotlin/com/algolia/instantsearch/showcase/filter/facet/FacetListViewHolderImpl.kt +++ /dev/null @@ -1,32 +0,0 @@ -package com.algolia.instantsearch.showcase.filter.facet - -import android.view.View -import android.view.ViewGroup -import com.algolia.instantsearch.core.highlighting.HighlightTokenizer -import com.algolia.instantsearch.showcase.R -import com.algolia.instantsearch.helper.android.filter.facet.FacetListViewHolder -import com.algolia.instantsearch.helper.android.highlighting.toSpannedString -import com.algolia.instantsearch.helper.android.inflate -import com.algolia.search.model.search.Facet -import kotlinx.android.synthetic.main.list_item_selectable.view.* - - -class FacetListViewHolderImpl(view: View) : FacetListViewHolder(view) { - - override fun bind(facet: Facet, selected: Boolean, onClickListener: View.OnClickListener) { - view.setOnClickListener(onClickListener) - view.selectableItemSubtitle.text = facet.count.toString() - view.selectableItemSubtitle.visibility = View.VISIBLE - view.selectableItemIcon.visibility = if (selected) View.VISIBLE else View.INVISIBLE - view.selectableItemName.text = facet.highlightedOrNull?.let { - HighlightTokenizer(preTag = "", postTag = "")(it).toSpannedString() - } ?: facet.value - } - - object Factory : FacetListViewHolder.Factory { - - override fun createViewHolder(parent: ViewGroup): FacetListViewHolder { - return FacetListViewHolderImpl(parent.inflate(R.layout.list_item_selectable)) - } - } -} \ No newline at end of file diff --git a/showcase/src/main/kotlin/com/algolia/instantsearch/showcase/filter/facet/dynamic/FacetItem.kt b/showcase/src/main/kotlin/com/algolia/instantsearch/showcase/filter/facet/dynamic/FacetItem.kt deleted file mode 100644 index db43ea3c..00000000 --- a/showcase/src/main/kotlin/com/algolia/instantsearch/showcase/filter/facet/dynamic/FacetItem.kt +++ /dev/null @@ -1,9 +0,0 @@ -package com.algolia.instantsearch.showcase.filter.facet.dynamic - -import com.algolia.search.model.Attribute -import com.algolia.search.model.search.Facet - -sealed class FacetItem { - data class Header(val attribute: Attribute) : FacetItem() - data class Value(val attribute: Attribute, val facet: Facet, val selected: Boolean) : FacetItem() -} diff --git a/showcase/src/main/kotlin/com/algolia/instantsearch/showcase/filter/facet/dynamic/ViewHolderFactory.kt b/showcase/src/main/kotlin/com/algolia/instantsearch/showcase/filter/facet/dynamic/ViewHolderFactory.kt deleted file mode 100644 index 5fbf8c0d..00000000 --- a/showcase/src/main/kotlin/com/algolia/instantsearch/showcase/filter/facet/dynamic/ViewHolderFactory.kt +++ /dev/null @@ -1,43 +0,0 @@ -package com.algolia.instantsearch.showcase.filter.facet.dynamic - -import android.view.View -import android.view.ViewGroup -import android.widget.TextView -import com.algolia.instantsearch.helper.android.filter.facet.dynamic.DynamicFacetListHeaderViewHolder -import com.algolia.instantsearch.helper.android.filter.facet.dynamic.DynamicFacetListItemViewHolder -import com.algolia.instantsearch.helper.android.filter.facet.dynamic.DynamicFacetListViewHolder -import com.algolia.instantsearch.helper.android.filter.facet.dynamic.DynamicFacetListViewHolder.ViewType -import com.algolia.instantsearch.helper.android.filter.facet.dynamic.DynamicFacetModel -import com.algolia.instantsearch.helper.android.inflate -import com.algolia.instantsearch.showcase.R -import kotlinx.android.synthetic.main.list_item_selectable.view.* - -class ViewHolderFactory : DynamicFacetListViewHolder.Factory { - - override fun createViewHolder( - parent: ViewGroup, - viewType: ViewType - ): DynamicFacetListViewHolder { - return when (viewType) { - ViewType.Header -> HeaderViewHolder(parent.inflate(R.layout.header_item)) - ViewType.Item -> ItemViewHolder(parent.inflate(R.layout.list_item_selectable)) - } - } - - class HeaderViewHolder(view: TextView) : DynamicFacetListHeaderViewHolder(view) { - override fun bind(item: DynamicFacetModel.Header, onClick: View.OnClickListener?) { - val textView = view as TextView - textView.text = item.attribute.raw - } - } - - class ItemViewHolder(view: View) : DynamicFacetListItemViewHolder(view) { - override fun bind(item: DynamicFacetModel.Item, onClick: View.OnClickListener?) { - view.selectableItemName.text = item.facet.value - view.selectableItemSubtitle.text = "${item.facet.count}" - view.selectableItemSubtitle.visibility = View.VISIBLE - view.selectableItemIcon.visibility = if (item.selected) View.VISIBLE else View.GONE - view.setOnClickListener(onClick) - } - } -} diff --git a/showcase/src/main/kotlin/com/algolia/instantsearch/showcase/filter/list/FilterListTagShowcase.kt b/showcase/src/main/kotlin/com/algolia/instantsearch/showcase/filter/list/FilterListTagShowcase.kt deleted file mode 100644 index 0931dd91..00000000 --- a/showcase/src/main/kotlin/com/algolia/instantsearch/showcase/filter/list/FilterListTagShowcase.kt +++ /dev/null @@ -1,60 +0,0 @@ -package com.algolia.instantsearch.showcase.filter.list - -import android.os.Bundle -import androidx.appcompat.app.AppCompatActivity -import com.algolia.instantsearch.core.connection.ConnectionHandler -import com.algolia.instantsearch.showcase.* -import com.algolia.instantsearch.helper.filter.list.FilterListConnector -import com.algolia.instantsearch.helper.filter.list.connectView -import com.algolia.instantsearch.helper.filter.state.FilterState -import com.algolia.instantsearch.helper.filter.state.groupOr -import com.algolia.instantsearch.helper.searcher.SearcherSingleIndex -import com.algolia.instantsearch.helper.searcher.connectFilterState -import com.algolia.search.model.Attribute -import com.algolia.search.model.filter.Filter -import kotlinx.android.synthetic.main.showcase_filter_list.* -import kotlinx.android.synthetic.main.header_filter.* -import kotlinx.android.synthetic.main.include_list.* - - -class FilterListTagShowcase : AppCompatActivity() { - - private val tags = Attribute("_tags") - private val groupTags = groupOr(tags) - private val filterState = FilterState() - private val searcher = SearcherSingleIndex(stubIndex) - private val filters = listOf( - Filter.Tag("free shipping"), - Filter.Tag("coupon"), - Filter.Tag("free return"), - Filter.Tag("on sale"), - Filter.Tag("no exchange") - ) - private val filterList = FilterListConnector.Tag(filters, filterState, groupID = groupTags) - private val connection = ConnectionHandler(filterList, searcher.connectFilterState(filterState)) - - override fun onCreate(savedInstanceState: Bundle?) { - super.onCreate(savedInstanceState) - setContentView(R.layout.showcase_filter_list) - - val viewTag = FilterListAdapter() - - connection += filterList.connectView(viewTag) - - configureToolbar(toolbar) - configureSearcher(searcher) - configureRecyclerView(listTopLeft, viewTag) - onFilterChangedThenUpdateFiltersText(filterState, filtersTextView, tags) - onClearAllThenClearFilters(filterState, filtersClearAll, connection) - onErrorThenUpdateFiltersText(searcher, filtersTextView) - onResponseChangedThenUpdateNbHits(searcher, nbHits, connection) - - searcher.searchAsync() - } - - override fun onDestroy() { - super.onDestroy() - searcher.cancel() - connection.clear() - } -} \ No newline at end of file diff --git a/showcase/src/main/kotlin/com/algolia/instantsearch/showcase/filter/list/FilterListViewHolder.kt b/showcase/src/main/kotlin/com/algolia/instantsearch/showcase/filter/list/FilterListViewHolder.kt deleted file mode 100644 index 80b38829..00000000 --- a/showcase/src/main/kotlin/com/algolia/instantsearch/showcase/filter/list/FilterListViewHolder.kt +++ /dev/null @@ -1,15 +0,0 @@ -package com.algolia.instantsearch.showcase.filter.list - -import android.view.View -import androidx.recyclerview.widget.RecyclerView -import kotlinx.android.synthetic.main.list_item_selectable.view.* - - -class FilterListViewHolder(val view: View) : RecyclerView.ViewHolder(view) { - - fun bind(text: String, selected: Boolean, onClickListener: View.OnClickListener) { - view.setOnClickListener(onClickListener) - view.selectableItemName.text = text - view.selectableItemIcon.visibility = if (selected) View.VISIBLE else View.INVISIBLE - } -} \ No newline at end of file diff --git a/showcase/src/main/kotlin/com/algolia/instantsearch/showcase/filter/map/FilterMapShowcase.kt b/showcase/src/main/kotlin/com/algolia/instantsearch/showcase/filter/map/FilterMapShowcase.kt deleted file mode 100644 index fadc2c39..00000000 --- a/showcase/src/main/kotlin/com/algolia/instantsearch/showcase/filter/map/FilterMapShowcase.kt +++ /dev/null @@ -1,56 +0,0 @@ -package com.algolia.instantsearch.showcase.filter.map - -import android.os.Bundle -import androidx.appcompat.app.AppCompatActivity -import com.algolia.instantsearch.core.connection.ConnectionHandler -import com.algolia.instantsearch.showcase.* -import com.algolia.instantsearch.helper.android.filter.map.FilterMapViewRadioGroup -import com.algolia.instantsearch.helper.filter.map.FilterMapConnector -import com.algolia.instantsearch.helper.filter.map.connectView -import com.algolia.instantsearch.helper.filter.state.FilterState -import com.algolia.instantsearch.helper.filter.state.groupAnd -import com.algolia.instantsearch.helper.searcher.SearcherSingleIndex -import com.algolia.instantsearch.helper.searcher.connectFilterState -import com.algolia.search.model.Attribute -import com.algolia.search.model.filter.Filter -import kotlinx.android.synthetic.main.showcase_filter_map.* -import kotlinx.android.synthetic.main.header_filter.* - - -class FilterMapShowcase : AppCompatActivity() { - - private val gender = Attribute("gender") - private val groupGender = groupAnd(gender) - private val filterState = FilterState() - private val searcher = SearcherSingleIndex(stubIndex) - private val filters = mapOf( - R.id.male to Filter.Facet(gender, "male"), - R.id.female to Filter.Facet(gender, "female") - ) - private val filterMap = FilterMapConnector(filters, filterState, groupID = groupGender) - private val connection = ConnectionHandler(filterMap, searcher.connectFilterState(filterState)) - - override fun onCreate(savedInstanceState: Bundle?) { - super.onCreate(savedInstanceState) - setContentView(R.layout.showcase_filter_map) - - val viewGender = FilterMapViewRadioGroup(radioGroupGender) - - connection += filterMap.connectView(viewGender) - - configureToolbar(toolbar) - configureSearcher(searcher) - onFilterChangedThenUpdateFiltersText(filterState, filtersTextView, gender) - onClearAllThenClearFilters(filterState, filtersClearAll, connection) - onErrorThenUpdateFiltersText(searcher, filtersTextView) - onResponseChangedThenUpdateNbHits(searcher, nbHits, connection) - - searcher.searchAsync() - } - - override fun onDestroy() { - super.onDestroy() - searcher.cancel() - connection.clear() - } -} \ No newline at end of file diff --git a/showcase/src/main/kotlin/com/algolia/instantsearch/showcase/filter/range/FilterRangeShowcase.kt b/showcase/src/main/kotlin/com/algolia/instantsearch/showcase/filter/range/FilterRangeShowcase.kt deleted file mode 100644 index bdebd870..00000000 --- a/showcase/src/main/kotlin/com/algolia/instantsearch/showcase/filter/range/FilterRangeShowcase.kt +++ /dev/null @@ -1,79 +0,0 @@ -package com.algolia.instantsearch.showcase.filter.range - -import android.os.Bundle -import androidx.appcompat.app.AppCompatActivity -import com.algolia.instantsearch.core.connection.ConnectionHandler -import com.algolia.instantsearch.core.number.range.Range -import com.algolia.instantsearch.core.searcher.Debouncer -import com.algolia.instantsearch.showcase.* -import com.algolia.instantsearch.helper.filter.range.FilterRangeConnector -import com.algolia.instantsearch.helper.filter.range.connectView -import com.algolia.instantsearch.helper.filter.state.FilterGroupID -import com.algolia.instantsearch.helper.filter.state.FilterState -import com.algolia.instantsearch.helper.filter.state.filters -import com.algolia.instantsearch.helper.searcher.SearcherSingleIndex -import com.algolia.instantsearch.helper.searcher.connectFilterState -import com.algolia.search.model.Attribute -import kotlinx.android.synthetic.main.showcase_filter_range.* -import kotlinx.android.synthetic.main.header_filter.* - - -class FilterRangeShowcase : AppCompatActivity() { - - private val searcher = SearcherSingleIndex(stubIndex) - private val price = Attribute("price") - private val groupID = FilterGroupID(price) - private val primaryBounds = 0..15 - private val secondaryBounds = 0..10 - private val initialRange = 0..15 - private val filters = filters { - group(groupID) { - range(price, initialRange) - } - } - private val filterState = FilterState(filters) - private val range = FilterRangeConnector(filterState, price, range = initialRange, bounds = primaryBounds) - private val connection = ConnectionHandler( - range, - searcher.connectFilterState(filterState, Debouncer(100)) - ) - - override fun onCreate(savedInstanceState: Bundle?) { - super.onCreate(savedInstanceState) - setContentView(R.layout.showcase_filter_range) - - connection += range.connectView(RangeSliderView(slider)) - connection += range.connectView(RangeTextView(rangeLabel)) - connection += range.connectView(BoundsTextView(boundsLabel)) - - buttonChangeBounds.setOnClickListener { - range.viewModel.bounds.value = Range(secondaryBounds) - it.isEnabled = false - buttonResetBounds.isEnabled = true - } - buttonResetBounds.setOnClickListener { - range.viewModel.bounds.value = Range(primaryBounds) - it.isEnabled = false - buttonChangeBounds.isEnabled = true - } - - reset.setOnClickListener { - filterState.notify { set(filters) } - } - configureToolbar(toolbar) - configureSearcher(searcher) - onFilterChangedThenUpdateFiltersText(filterState, filtersTextView, price) - onClearAllThenClearFilters(filterState, filtersClearAll, connection) - onErrorThenUpdateFiltersText(searcher, filtersTextView) - onResponseChangedThenUpdateNbHits(searcher, nbHits, connection) - - searcher.searchAsync() - } - - override fun onDestroy() { - super.onDestroy() - searcher.cancel() - connection.clear() - } -} - diff --git a/showcase/src/main/kotlin/com/algolia/instantsearch/showcase/filter/rating/RatingShowcase.kt b/showcase/src/main/kotlin/com/algolia/instantsearch/showcase/filter/rating/RatingShowcase.kt deleted file mode 100644 index 815602b1..00000000 --- a/showcase/src/main/kotlin/com/algolia/instantsearch/showcase/filter/rating/RatingShowcase.kt +++ /dev/null @@ -1,83 +0,0 @@ -package com.algolia.instantsearch.showcase.filter.rating - -import android.os.Bundle -import androidx.appcompat.app.AppCompatActivity -import com.algolia.instantsearch.core.connection.ConnectionHandler -import com.algolia.instantsearch.core.searcher.Debouncer -import com.algolia.instantsearch.helper.filter.range.FilterRangeConnector -import com.algolia.instantsearch.helper.filter.range.connectView -import com.algolia.instantsearch.helper.filter.state.FilterGroupID -import com.algolia.instantsearch.helper.filter.state.FilterState -import com.algolia.instantsearch.helper.filter.state.filters -import com.algolia.instantsearch.helper.searcher.SearcherSingleIndex -import com.algolia.instantsearch.helper.searcher.connectFilterState -import com.algolia.instantsearch.showcase.R -import com.algolia.instantsearch.showcase.client -import com.algolia.instantsearch.showcase.configureToolbar -import com.algolia.instantsearch.showcase.onClearAllThenClearFilters -import com.algolia.instantsearch.showcase.onErrorThenUpdateFiltersText -import com.algolia.instantsearch.showcase.onFilterChangedThenUpdateFiltersText -import com.algolia.instantsearch.showcase.onResponseChangedThenUpdateNbHits -import com.algolia.search.model.Attribute -import com.algolia.search.model.IndexName -import com.algolia.search.model.filter.Filter -import kotlinx.android.synthetic.main.header_filter.* -import kotlinx.android.synthetic.main.include_plus_minus.* -import kotlinx.android.synthetic.main.showcase_filter_rating.* - -class RatingShowcase : AppCompatActivity() { - - private val index = client.initIndex(IndexName("instant_search")) - private val searcher = SearcherSingleIndex(index) - private val rating = Attribute("rating") - private val groupID = FilterGroupID(rating) - private val primaryBounds = 0f..5f - private val initialRange = 3f..5f - private val filters = filters { - group(groupID) { - +Filter.Numeric( - rating, - lowerBound = initialRange.start, - upperBound = initialRange.endInclusive - ) - } - } - private val filterState = FilterState(filters) - private val range = - FilterRangeConnector(filterState, rating, range = initialRange, bounds = primaryBounds) - private val connection = ConnectionHandler( - range, - searcher.connectFilterState(filterState, Debouncer(100)) - ) - - override fun onCreate(savedInstanceState: Bundle?) { - super.onCreate(savedInstanceState) - setContentView(R.layout.showcase_filter_rating) - - val ratingBarView = RatingBarView(ratingBar).apply { - stepSize = STEP - plus.setOnClickListener { rating += stepSize } - minus.setOnClickListener { rating -= stepSize } - } - connection += range.connectView(ratingBarView) - connection += range.connectView(RatingTextView(ratingLabel)) - - configureToolbar(toolbar) - onFilterChangedThenUpdateFiltersText(filterState, filtersTextView, rating) - onClearAllThenClearFilters(filterState, filtersClearAll, connection) - onErrorThenUpdateFiltersText(searcher, filtersTextView) - onResponseChangedThenUpdateNbHits(searcher, nbHits, connection) - - searcher.searchAsync() - } - - override fun onDestroy() { - super.onDestroy() - searcher.cancel() - connection.clear() - } - - companion object { - private const val STEP = 0.1f - } -} \ No newline at end of file diff --git a/showcase/src/main/kotlin/com/algolia/instantsearch/showcase/hierarchical/HierarchicalShowcase.kt b/showcase/src/main/kotlin/com/algolia/instantsearch/showcase/hierarchical/HierarchicalShowcase.kt deleted file mode 100644 index 4600cf21..00000000 --- a/showcase/src/main/kotlin/com/algolia/instantsearch/showcase/hierarchical/HierarchicalShowcase.kt +++ /dev/null @@ -1,77 +0,0 @@ -package com.algolia.instantsearch.showcase.hierarchical - -import android.os.Bundle -import androidx.appcompat.app.AppCompatActivity -import com.algolia.instantsearch.core.connection.ConnectionHandler -import com.algolia.instantsearch.helper.filter.state.FilterState -import com.algolia.instantsearch.helper.hierarchical.HierarchicalConnector -import com.algolia.instantsearch.helper.hierarchical.HierarchicalPresenterImpl -import com.algolia.instantsearch.helper.hierarchical.connectView -import com.algolia.instantsearch.helper.searcher.SearcherSingleIndex -import com.algolia.instantsearch.helper.searcher.connectFilterState -import com.algolia.instantsearch.showcase.R -import com.algolia.instantsearch.showcase.configureRecyclerView -import com.algolia.instantsearch.showcase.configureSearcher -import com.algolia.instantsearch.showcase.configureToolbar -import com.algolia.instantsearch.showcase.onClearAllThenClearFilters -import com.algolia.instantsearch.showcase.onErrorThenUpdateFiltersText -import com.algolia.instantsearch.showcase.onFilterChangedThenUpdateFiltersText -import com.algolia.instantsearch.showcase.onResetThenRestoreFilters -import com.algolia.instantsearch.showcase.onResponseChangedThenUpdateNbHits -import com.algolia.instantsearch.showcase.stubIndex -import com.algolia.search.model.Attribute -import kotlinx.android.synthetic.main.header_filter.* -import kotlinx.android.synthetic.main.showcase_filter_clear.* -import kotlinx.android.synthetic.main.showcase_hierarchical.* -import kotlinx.android.synthetic.main.showcase_hierarchical.toolbar - -class HierarchicalShowcase : AppCompatActivity() { - - private val hierarchicalCategory = Attribute("hierarchicalCategories") - private val hierarchicalCategoryLvl0 = Attribute("$hierarchicalCategory.lvl0") - private val hierarchicalCategoryLvl1 = Attribute("$hierarchicalCategory.lvl1") - private val hierarchicalCategoryLvl2 = Attribute("$hierarchicalCategory.lvl2") - private val hierarchicalAttributes = listOf( - hierarchicalCategoryLvl0, - hierarchicalCategoryLvl1, - hierarchicalCategoryLvl2 - ) - private val searcher = SearcherSingleIndex(stubIndex) - private val filterState = FilterState() - private val separator = " > " - private val hierarchical = HierarchicalConnector( - searcher = searcher, - attribute = hierarchicalCategory, - filterState = filterState, - hierarchicalAttributes = hierarchicalAttributes, - separator = separator - ) - private val connection = ConnectionHandler( - hierarchical, - searcher.connectFilterState(filterState) - ) - - override fun onCreate(savedInstanceState: Bundle?) { - super.onCreate(savedInstanceState) - setContentView(R.layout.showcase_hierarchical) - - val view = HierarchicalAdapter() - connection += hierarchical.connectView(view, HierarchicalPresenterImpl(separator)) - - configureRecyclerView(hits, view) - configureToolbar(toolbar) - configureSearcher(searcher) - onFilterChangedThenUpdateFiltersText(filterState, filtersTextView, hierarchicalCategory) - onErrorThenUpdateFiltersText(searcher, filtersTextView) - onResponseChangedThenUpdateNbHits(searcher, nbHits, connection) - onClearAllThenClearFilters(filterState, filtersClearAll, connection) - - searcher.searchAsync() - } - - override fun onDestroy() { - super.onDestroy() - searcher.cancel() - connection.clear() - } -} diff --git a/showcase/src/main/kotlin/com/algolia/instantsearch/showcase/hierarchical/HierarchicalViewHolder.kt b/showcase/src/main/kotlin/com/algolia/instantsearch/showcase/hierarchical/HierarchicalViewHolder.kt deleted file mode 100644 index 63d6bf31..00000000 --- a/showcase/src/main/kotlin/com/algolia/instantsearch/showcase/hierarchical/HierarchicalViewHolder.kt +++ /dev/null @@ -1,30 +0,0 @@ -package com.algolia.instantsearch.showcase.hierarchical - -import android.graphics.Typeface -import android.view.View -import androidx.recyclerview.widget.RecyclerView -import com.algolia.instantsearch.helper.hierarchical.HierarchicalItem -import com.algolia.instantsearch.showcase.dip -import kotlinx.android.synthetic.main.list_item_selectable.view.* - -class HierarchicalViewHolder(val view: View) : RecyclerView.ViewHolder(view) { - - fun bind(item: HierarchicalItem, onClick: View.OnClickListener) { - view.elevation = ((6 - item.level * 2) * view.context.dip(4)).toFloat() - view.selectableItemName.text = item.displayName - view.selectableItemSubtitle.text = item.facet.count.toString() - view.selectableItemSubtitle.visibility = View.VISIBLE - view.setOnClickListener(onClick) - if (item.isSelected) selected() else unselected() - } - - private fun selected() { - view.selectableItemIcon.visibility = View.VISIBLE - view.selectableItemName.setTypeface(null, Typeface.BOLD) - } - - private fun unselected() { - view.selectableItemIcon.visibility = View.INVISIBLE - view.selectableItemName.setTypeface(null, Typeface.NORMAL) - } -} diff --git a/showcase/src/main/kotlin/com/algolia/instantsearch/showcase/list/actor/ActorViewHolder.kt b/showcase/src/main/kotlin/com/algolia/instantsearch/showcase/list/actor/ActorViewHolder.kt deleted file mode 100644 index 46caa818..00000000 --- a/showcase/src/main/kotlin/com/algolia/instantsearch/showcase/list/actor/ActorViewHolder.kt +++ /dev/null @@ -1,13 +0,0 @@ -package com.algolia.instantsearch.showcase.list.actor - -import android.view.View -import androidx.recyclerview.widget.RecyclerView -import kotlinx.android.synthetic.main.list_item_actor.view.* - - -class ActorViewHolder(val view: View) : RecyclerView.ViewHolder(view) { - - fun bind(actor: Actor) { - view.actorName.text = actor.name - } -} \ No newline at end of file diff --git a/showcase/src/main/kotlin/com/algolia/instantsearch/showcase/list/actor/ActorViewHolderSmall.kt b/showcase/src/main/kotlin/com/algolia/instantsearch/showcase/list/actor/ActorViewHolderSmall.kt deleted file mode 100644 index 31e5c552..00000000 --- a/showcase/src/main/kotlin/com/algolia/instantsearch/showcase/list/actor/ActorViewHolderSmall.kt +++ /dev/null @@ -1,13 +0,0 @@ -package com.algolia.instantsearch.showcase.list.actor - -import android.view.View -import androidx.recyclerview.widget.RecyclerView -import kotlinx.android.synthetic.main.list_item_small.view.* - - -class ActorViewHolderSmall(val view: View) : RecyclerView.ViewHolder(view) { - - fun bind(actor: Actor) { - view.itemName.text = actor.name - } -} \ No newline at end of file diff --git a/showcase/src/main/kotlin/com/algolia/instantsearch/showcase/list/merged/MergedListAdapter.kt b/showcase/src/main/kotlin/com/algolia/instantsearch/showcase/list/merged/MergedListAdapter.kt deleted file mode 100644 index 37406b30..00000000 --- a/showcase/src/main/kotlin/com/algolia/instantsearch/showcase/list/merged/MergedListAdapter.kt +++ /dev/null @@ -1,64 +0,0 @@ -package com.algolia.instantsearch.showcase.list.merged - -import android.annotation.SuppressLint -import android.view.ViewGroup -import android.widget.TextView -import androidx.recyclerview.widget.DiffUtil -import androidx.recyclerview.widget.ListAdapter -import androidx.recyclerview.widget.RecyclerView -import com.algolia.instantsearch.showcase.R -import com.algolia.instantsearch.showcase.list.actor.Actor -import com.algolia.instantsearch.showcase.list.actor.ActorViewHolderSmall -import com.algolia.instantsearch.showcase.list.header.HeaderViewHolder -import com.algolia.instantsearch.showcase.list.movie.Movie -import com.algolia.instantsearch.showcase.list.movie.MovieViewHolder -import com.algolia.instantsearch.helper.android.inflate - - -class MergedListAdapter : ListAdapter(this) { - - private enum class ViewType { - Header, - Movies, - Actors - } - - override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder { - return when (ViewType.values()[viewType]) { - ViewType.Header -> HeaderViewHolder(parent.inflate(R.layout.header_item)) - ViewType.Movies -> MovieViewHolder(parent.inflate(R.layout.list_item_large)) - ViewType.Actors -> ActorViewHolderSmall(parent.inflate(R.layout.list_item_small)) - } - } - - override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) { - val item = getItem(position) - - when (holder) { - is HeaderViewHolder -> holder.bind(item as String) - is MovieViewHolder -> holder.bind(item as Movie) - is ActorViewHolderSmall -> holder.bind(item as Actor) - } - } - - override fun getItemViewType(position: Int): Int { - return when (getItem(position)) { - is String -> ViewType.Header - is Movie -> ViewType.Movies - is Actor -> ViewType.Actors - else -> throw Exception("Not implemented") - }.ordinal - } - - private companion object : DiffUtil.ItemCallback() { - - override fun areItemsTheSame(oldItem: Any, newItem: Any): Boolean { - return oldItem == newItem - } - - @SuppressLint("DiffUtilEquals") // items are either String/Actor/Movie, with equals() - override fun areContentsTheSame(oldItem: Any, newItem: Any): Boolean { - return oldItem == newItem - } - } -} \ No newline at end of file diff --git a/showcase/src/main/kotlin/com/algolia/instantsearch/showcase/list/merged/MergedListShowcase.kt b/showcase/src/main/kotlin/com/algolia/instantsearch/showcase/list/merged/MergedListShowcase.kt deleted file mode 100644 index 4f1f136a..00000000 --- a/showcase/src/main/kotlin/com/algolia/instantsearch/showcase/list/merged/MergedListShowcase.kt +++ /dev/null @@ -1,65 +0,0 @@ -package com.algolia.instantsearch.showcase.list.merged - -import android.os.Bundle -import androidx.appcompat.app.AppCompatActivity -import com.algolia.instantsearch.core.connection.ConnectionHandler -import com.algolia.instantsearch.core.searcher.connectView -import com.algolia.instantsearch.showcase.* -import com.algolia.instantsearch.showcase.list.actor.Actor -import com.algolia.instantsearch.showcase.list.movie.Movie -import com.algolia.instantsearch.helper.android.searchbox.SearchBoxViewAppCompat -import com.algolia.instantsearch.helper.searchbox.SearchBoxConnector -import com.algolia.instantsearch.helper.searchbox.connectView -import com.algolia.instantsearch.helper.searcher.SearcherMultipleIndex -import com.algolia.search.helper.deserialize -import com.algolia.search.model.IndexName -import com.algolia.search.model.multipleindex.IndexQuery -import com.algolia.search.model.search.Query -import kotlinx.android.synthetic.main.showcase_search.* -import kotlinx.android.synthetic.main.include_search.* - - -class MergedListShowcase : AppCompatActivity() { - - private val searcher = SearcherMultipleIndex( - client, - listOf( - IndexQuery(IndexName("mobile_demo_movies"), Query(hitsPerPage = 3)), - IndexQuery(IndexName("mobile_demo_actors"), Query(hitsPerPage = 5)) - ) - ) - private val searchBox = SearchBoxConnector(searcher) - private val connection = ConnectionHandler(searchBox) - private val adapter = MergedListAdapter() - - override fun onCreate(savedInstanceState: Bundle?) { - super.onCreate(savedInstanceState) - setContentView(R.layout.showcase_search) - - val searchBoxView = SearchBoxViewAppCompat(searchView) - - connection += searcher.connectView(adapter::submitList) { response -> - if (response != null) { - mutableListOf().apply { - add("Actors") - addAll(response.results[1].hits.deserialize(Actor.serializer())) - add("Movies") - addAll(response.results[0].hits.deserialize(Movie.serializer())) - } - } else emptyList() - } - connection += searchBox.connectView(searchBoxView) - - configureToolbar(toolbar) - configureSearchView(searchView, getString(R.string.search_movies)) - configureRecyclerView(hits, adapter) - - searcher.searchAsync() - } - - override fun onDestroy() { - super.onDestroy() - searcher.cancel() - connection.clear() - } -} diff --git a/showcase/src/main/kotlin/com/algolia/instantsearch/showcase/list/movie/MovieAdapterNested.kt b/showcase/src/main/kotlin/com/algolia/instantsearch/showcase/list/movie/MovieAdapterNested.kt deleted file mode 100644 index 57476b28..00000000 --- a/showcase/src/main/kotlin/com/algolia/instantsearch/showcase/list/movie/MovieAdapterNested.kt +++ /dev/null @@ -1,28 +0,0 @@ -package com.algolia.instantsearch.showcase.list.movie - -import android.view.ViewGroup -import androidx.paging.PagedListAdapter -import com.algolia.instantsearch.showcase.R -import com.algolia.instantsearch.showcase.dip -import com.algolia.instantsearch.helper.android.inflate - - -class MovieAdapterNested : PagedListAdapter(MovieDiffUtil) { - - override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MovieViewHolderNested { - val dip8 = parent.context.dip(8) - val layoutParams = ViewGroup.MarginLayoutParams(parent.width / 2, ViewGroup.LayoutParams.MATCH_PARENT).apply { - setMargins(dip8, dip8, dip8, dip8) - } - val view = parent.inflate(R.layout.list_item_movie).also { - it.layoutParams = layoutParams - } - return MovieViewHolderNested(view) - } - - override fun onBindViewHolder(holder: MovieViewHolderNested, position: Int) { - val item = getItem(position) - - if (item != null) holder.bind(item) - } -} \ No newline at end of file diff --git a/showcase/src/main/kotlin/com/algolia/instantsearch/showcase/list/movie/MovieAdapterPaged.kt b/showcase/src/main/kotlin/com/algolia/instantsearch/showcase/list/movie/MovieAdapterPaged.kt deleted file mode 100644 index 0f813679..00000000 --- a/showcase/src/main/kotlin/com/algolia/instantsearch/showcase/list/movie/MovieAdapterPaged.kt +++ /dev/null @@ -1,20 +0,0 @@ -package com.algolia.instantsearch.showcase.list.movie - -import android.view.ViewGroup -import androidx.paging.PagedListAdapter -import com.algolia.instantsearch.showcase.R -import com.algolia.instantsearch.helper.android.inflate - - -class MovieAdapterPaged : PagedListAdapter(MovieDiffUtil) { - - override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MovieViewHolder { - return MovieViewHolder(parent.inflate(R.layout.list_item_large)) - } - - override fun onBindViewHolder(holder: MovieViewHolder, position: Int) { - val item = getItem(position) - - if (item != null) holder.bind(item) - } -} \ No newline at end of file diff --git a/showcase/src/main/kotlin/com/algolia/instantsearch/showcase/list/movie/MovieViewHolder.kt b/showcase/src/main/kotlin/com/algolia/instantsearch/showcase/list/movie/MovieViewHolder.kt deleted file mode 100644 index 864f7963..00000000 --- a/showcase/src/main/kotlin/com/algolia/instantsearch/showcase/list/movie/MovieViewHolder.kt +++ /dev/null @@ -1,24 +0,0 @@ -package com.algolia.instantsearch.showcase.list.movie - -import android.text.TextUtils -import android.view.View -import androidx.core.text.buildSpannedString -import androidx.core.text.italic -import androidx.recyclerview.widget.RecyclerView -import com.algolia.instantsearch.helper.android.highlighting.toSpannedString -import com.bumptech.glide.Glide -import kotlinx.android.synthetic.main.list_item_large.view.* - - -class MovieViewHolder(private val view: View) : RecyclerView.ViewHolder(view) { - - fun bind(movie: Movie) { - view.itemTitle.text = TextUtils.concat(movie.highlightedTitle?.toSpannedString(), " (${movie.year})") - view.itemSubtitle.text = movie.highlightedGenres?.toSpannedString() - ?: buildSpannedString { italic { append("unknown genre") } } - Glide.with(view) - .load(movie.image).placeholder(android.R.drawable.ic_media_play) - .centerCrop() - .into(view.itemImage) - } -} \ No newline at end of file diff --git a/showcase/src/main/kotlin/com/algolia/instantsearch/showcase/list/movie/MovieViewHolderNested.kt b/showcase/src/main/kotlin/com/algolia/instantsearch/showcase/list/movie/MovieViewHolderNested.kt deleted file mode 100644 index df21311b..00000000 --- a/showcase/src/main/kotlin/com/algolia/instantsearch/showcase/list/movie/MovieViewHolderNested.kt +++ /dev/null @@ -1,20 +0,0 @@ -package com.algolia.instantsearch.showcase.list.movie - -import android.view.View -import androidx.recyclerview.widget.RecyclerView -import com.bumptech.glide.Glide -import kotlinx.android.synthetic.main.list_item_movie.view.* - - -class MovieViewHolderNested(private val view: View) : RecyclerView.ViewHolder(view) { - - fun bind(movie: Movie) { - view.itemTitle.text = movie.title - view.itemSubtitle.text = movie.genre.sorted().joinToString { it } - view.itemCaption.text = movie.year - Glide.with(view) - .load(movie.image).placeholder(android.R.drawable.ic_media_play) - .centerCrop() - .into(view.itemImage) - } -} \ No newline at end of file diff --git a/showcase/src/main/kotlin/com/algolia/instantsearch/showcase/list/paging/PagingMultipleIndexShowcase.kt b/showcase/src/main/kotlin/com/algolia/instantsearch/showcase/list/paging/PagingMultipleIndexShowcase.kt deleted file mode 100644 index 9dd1ecb4..00000000 --- a/showcase/src/main/kotlin/com/algolia/instantsearch/showcase/list/paging/PagingMultipleIndexShowcase.kt +++ /dev/null @@ -1,72 +0,0 @@ -package com.algolia.instantsearch.showcase.list.paging - -import android.os.Bundle -import androidx.appcompat.app.AppCompatActivity -import androidx.lifecycle.Observer -import androidx.paging.LivePagedListBuilder -import androidx.paging.PagedList -import com.algolia.instantsearch.core.connection.ConnectionHandler -import com.algolia.instantsearch.showcase.* -import com.algolia.instantsearch.showcase.list.actor.Actor -import com.algolia.instantsearch.showcase.list.actor.ActorAdapterNested -import com.algolia.instantsearch.showcase.list.movie.Movie -import com.algolia.instantsearch.showcase.list.movie.MovieAdapterNested -import com.algolia.instantsearch.helper.android.list.SearcherMultipleIndexDataSource -import com.algolia.instantsearch.helper.android.searchbox.SearchBoxConnectorPagedList -import com.algolia.instantsearch.helper.android.searchbox.SearchBoxViewAppCompat -import com.algolia.instantsearch.helper.android.searchbox.connectView -import com.algolia.instantsearch.helper.searcher.SearcherMultipleIndex -import com.algolia.search.model.IndexName -import com.algolia.search.model.multipleindex.IndexQuery -import kotlinx.android.synthetic.main.showcase_search.* -import kotlinx.android.synthetic.main.include_search.* - - -class PagingMultipleIndexShowcase : AppCompatActivity() { - - private val indexMovies = IndexQuery(IndexName("mobile_demo_movies")) - private val indexActors = IndexQuery(IndexName("mobile_demo_actors")) - private val searcher = SearcherMultipleIndex(client, listOf(indexMovies, indexActors)) - private val pagedListConfig = PagedList.Config.Builder().setPageSize(10).setEnablePlaceholders(false).build() - private val moviesFactory = SearcherMultipleIndexDataSource.Factory(searcher, indexMovies) { it.deserialize(Movie.serializer()) } - private val actorsFactory = SearcherMultipleIndexDataSource.Factory(searcher, indexActors) { it.deserialize(Actor.serializer()) } - private val movies = LivePagedListBuilder(moviesFactory, pagedListConfig).build() - private val actors = LivePagedListBuilder(actorsFactory, pagedListConfig).build() - private val searchBox = SearchBoxConnectorPagedList(searcher, listOf(movies, actors)) - private val connection = ConnectionHandler(searchBox) - - override fun onCreate(savedInstanceState: Bundle?) { - super.onCreate(savedInstanceState) - setContentView(R.layout.showcase_search) - - val adapterActor = ActorAdapterNested() - val adapterMovie = MovieAdapterNested() - val adapter = PagingMultipleIndexAdapter() - - actors.observe(this, Observer { hits -> adapterActor.submitList(hits) }) - movies.observe(this, Observer { hits -> adapterMovie.submitList(hits) }) - - adapter.submitList( - listOf( - PagingMultipleIndexItem.Header("Movies"), - PagingMultipleIndexItem.Movies(adapterMovie), - PagingMultipleIndexItem.Header("Actors"), - PagingMultipleIndexItem.Actors(adapterActor) - ) - ) - - val searchBoxView = SearchBoxViewAppCompat(searchView) - - connection += searchBox.connectView(searchBoxView) - - configureToolbar(toolbar) - configureSearchView(searchView, getString(R.string.search_movies)) - configureRecyclerView(hits, adapter) - } - - override fun onDestroy() { - super.onDestroy() - searcher.cancel() - connection.clear() - } -} diff --git a/showcase/src/main/kotlin/com/algolia/instantsearch/showcase/list/paging/PagingSingleIndexShowcase.kt b/showcase/src/main/kotlin/com/algolia/instantsearch/showcase/list/paging/PagingSingleIndexShowcase.kt deleted file mode 100644 index b8e40b75..00000000 --- a/showcase/src/main/kotlin/com/algolia/instantsearch/showcase/list/paging/PagingSingleIndexShowcase.kt +++ /dev/null @@ -1,53 +0,0 @@ -package com.algolia.instantsearch.showcase.list.paging - -import android.os.Bundle -import androidx.appcompat.app.AppCompatActivity -import androidx.lifecycle.Observer -import androidx.paging.LivePagedListBuilder -import androidx.paging.PagedList -import com.algolia.instantsearch.core.connection.ConnectionHandler -import com.algolia.instantsearch.showcase.* -import com.algolia.instantsearch.showcase.list.movie.Movie -import com.algolia.instantsearch.showcase.list.movie.MovieAdapterPaged -import com.algolia.instantsearch.helper.android.list.SearcherSingleIndexDataSource -import com.algolia.instantsearch.helper.android.searchbox.SearchBoxConnectorPagedList -import com.algolia.instantsearch.helper.android.searchbox.SearchBoxViewAppCompat -import com.algolia.instantsearch.helper.android.searchbox.connectView -import com.algolia.instantsearch.helper.searcher.SearcherSingleIndex -import kotlinx.android.synthetic.main.showcase_paging.* -import kotlinx.android.synthetic.main.include_search.* - - -class PagingSingleIndexShowcase : AppCompatActivity() { - - private val searcher = SearcherSingleIndex(stubIndex) - private val dataSourceFactory = SearcherSingleIndexDataSource.Factory(searcher) { it.deserialize(Movie.serializer()) } - private val pagedListConfig = PagedList.Config.Builder().setPageSize(10).setEnablePlaceholders(false).build() - private val movies = LivePagedListBuilder(dataSourceFactory, pagedListConfig).build() - private val searchBox = SearchBoxConnectorPagedList(searcher, listOf(movies)) - private val connection = ConnectionHandler(searchBox) - - override fun onCreate(savedInstanceState: Bundle?) { - super.onCreate(savedInstanceState) - setContentView(R.layout.showcase_paging) - - val adapter = MovieAdapterPaged() - val searchBoxView = SearchBoxViewAppCompat(searchView) - - connection += searchBox.connectView(searchBoxView) - - movies.observe(this, Observer { hits -> adapter.submitList(hits) }) - - configureToolbar(toolbar) - configureSearcher(searcher) - configureSearchView(searchView, getString(R.string.search_movies)) - configureRecyclerView(hits, adapter) - onResponseChangedThenUpdateNbHits(searcher, nbHits, connection) - } - - override fun onDestroy() { - super.onDestroy() - searcher.cancel() - connection.clear() - } -} diff --git a/showcase/src/main/kotlin/com/algolia/instantsearch/showcase/loading/LoadingShowcase.kt b/showcase/src/main/kotlin/com/algolia/instantsearch/showcase/loading/LoadingShowcase.kt deleted file mode 100644 index 5b570da7..00000000 --- a/showcase/src/main/kotlin/com/algolia/instantsearch/showcase/loading/LoadingShowcase.kt +++ /dev/null @@ -1,61 +0,0 @@ -package com.algolia.instantsearch.showcase.loading - -import android.os.Bundle -import androidx.appcompat.app.AppCompatActivity -import androidx.lifecycle.Observer -import androidx.paging.LivePagedListBuilder -import androidx.paging.PagedList -import com.algolia.instantsearch.core.connection.ConnectionHandler -import com.algolia.instantsearch.showcase.* -import com.algolia.instantsearch.showcase.list.movie.Movie -import com.algolia.instantsearch.showcase.list.movie.MovieAdapterPaged -import com.algolia.instantsearch.helper.android.list.SearcherSingleIndexDataSource -import com.algolia.instantsearch.helper.android.loading.LoadingViewSwipeRefreshLayout -import com.algolia.instantsearch.helper.android.searchbox.SearchBoxConnectorPagedList -import com.algolia.instantsearch.helper.android.searchbox.SearchBoxViewAppCompat -import com.algolia.instantsearch.helper.android.searchbox.connectView -import com.algolia.instantsearch.helper.loading.LoadingConnector -import com.algolia.instantsearch.helper.loading.connectView -import com.algolia.instantsearch.helper.searcher.SearcherSingleIndex -import kotlinx.android.synthetic.main.showcase_loading.* -import kotlinx.android.synthetic.main.showcase_search.hits -import kotlinx.android.synthetic.main.showcase_search.toolbar -import kotlinx.android.synthetic.main.include_search.* - - -class LoadingShowcase : AppCompatActivity() { - - private val searcher = SearcherSingleIndex(stubIndex) - private val dataSourceFactory = SearcherSingleIndexDataSource.Factory(searcher) { it.deserialize(Movie.serializer()) } - private val pagedListConfig = PagedList.Config.Builder().setPageSize(10).setEnablePlaceholders(false).build() - private val movies = LivePagedListBuilder(dataSourceFactory, pagedListConfig).build() - private val loading = LoadingConnector(searcher) - private val searchBox = SearchBoxConnectorPagedList(searcher, listOf(movies)) - private val connection = ConnectionHandler(loading, searchBox) - - override fun onCreate(savedInstanceState: Bundle?) { - super.onCreate(savedInstanceState) - setContentView(R.layout.showcase_loading) - - val view = LoadingViewSwipeRefreshLayout(swipeRefreshLayout) - val searchBoxView = SearchBoxViewAppCompat(searchView) - val adapter = MovieAdapterPaged() - - connection += loading.connectView(view) - connection += searchBox.connectView(searchBoxView) - movies.observe(this, Observer { hits -> adapter.submitList(hits) }) - - configureSearcher(searcher) - configureToolbar(toolbar) - configureSearchView(searchView, getString(R.string.search_movies)) - configureRecyclerView(hits, adapter) - - searcher.searchAsync() - } - - override fun onDestroy() { - super.onDestroy() - searcher.cancel() - connection.clear() - } -} diff --git a/showcase/src/main/kotlin/com/algolia/instantsearch/showcase/search/SearchAutoCompleteTextView.kt b/showcase/src/main/kotlin/com/algolia/instantsearch/showcase/search/SearchAutoCompleteTextView.kt deleted file mode 100644 index 057c0bad..00000000 --- a/showcase/src/main/kotlin/com/algolia/instantsearch/showcase/search/SearchAutoCompleteTextView.kt +++ /dev/null @@ -1,51 +0,0 @@ -package com.algolia.instantsearch.showcase.search - -import android.os.Bundle -import android.widget.ArrayAdapter -import androidx.appcompat.app.AppCompatActivity -import com.algolia.instantsearch.core.connection.ConnectionHandler -import com.algolia.instantsearch.helper.android.hits.HitsArrayAdapter -import com.algolia.instantsearch.helper.android.hits.connectHitsArrayAdapter -import com.algolia.instantsearch.helper.android.searchbox.SearchBoxAutoCompleteTextView -import com.algolia.instantsearch.helper.searchbox.SearchBoxConnector -import com.algolia.instantsearch.helper.searchbox.SearchMode -import com.algolia.instantsearch.helper.searchbox.connectView -import com.algolia.instantsearch.helper.searcher.SearcherSingleIndex -import com.algolia.instantsearch.showcase.R -import com.algolia.instantsearch.showcase.configureSearcher -import com.algolia.instantsearch.showcase.list.movie.Movie -import com.algolia.instantsearch.showcase.stubIndex -import com.algolia.search.helper.deserialize -import kotlinx.android.synthetic.main.showcase_search_autocomplete.* - - -class SearchAutoCompleteTextView : AppCompatActivity() { - - private val searcher = SearcherSingleIndex(stubIndex) - private val searchBox = SearchBoxConnector(searcher, searchMode = SearchMode.AsYouType) - private val connection = ConnectionHandler(searchBox) - - override fun onCreate(savedInstanceState: Bundle?) { - super.onCreate(savedInstanceState) - setContentView(R.layout.showcase_search_autocomplete) - - val adapter = ArrayAdapter(this, android.R.layout.simple_list_item_1) - val hitsAdapter = HitsArrayAdapter(adapter) - val searchBoxView = SearchBoxAutoCompleteTextView(autoCompleteTextView) - - autoCompleteTextView.setAdapter(adapter) - connection += searchBox.connectView(searchBoxView) - connection += searcher.connectHitsArrayAdapter(hitsAdapter, autoCompleteTextView) { response -> - response.hits.deserialize(Movie.serializer()).map { it.title } - } - - configureSearcher(searcher) - searcher.searchAsync() - } - - override fun onDestroy() { - super.onDestroy() - searcher.cancel() - connection.clear() - } -} diff --git a/showcase/src/main/res/drawable/ic_close_hint.xml b/showcase/src/main/res/drawable/ic_close_hint.xml deleted file mode 100644 index bf369069..00000000 --- a/showcase/src/main/res/drawable/ic_close_hint.xml +++ /dev/null @@ -1,12 +0,0 @@ - - - - diff --git a/showcase/src/main/res/drawable/query_background.xml b/showcase/src/main/res/drawable/query_background.xml deleted file mode 100644 index 08a84972..00000000 --- a/showcase/src/main/res/drawable/query_background.xml +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - - - \ No newline at end of file From 888abd80975c62d81ed00ea832d225cd18dec964 Mon Sep 17 00:00:00 2001 From: Mouaad Aallam Date: Tue, 29 Mar 2022 14:49:36 +0200 Subject: [PATCH 2/4] add query suggestion to android-view showcase --- .../QuerySuggestionViewModel.kt | 2 +- showcase/android-view/build.gradle | 10 +-- .../android-view/src/main/AndroidManifest.xml | 4 ++ .../algolia/instantsearch/showcase/Demo.kt | 28 +++++++-- .../showcase/directory/Directory.kt | 2 + .../showcase/list/suggestion/Suggestion.kt | 20 ++++++ .../suggestion/QuerySuggestionShowcase.kt | 62 +++++++++++++++++++ .../suggestion/QuerySuggestionViewModel.kt | 40 ++++++++++++ .../showcase/suggestion/product/Product.kt | 30 +++++++++ .../suggestion/product/ProductAdapter.kt | 45 ++++++++++++++ .../suggestion/product/ProductFragment.kt | 38 ++++++++++++ .../suggestion/SuggestionAdapter.kt | 46 ++++++++++++++ .../suggestion/SuggestionFragment.kt | 41 ++++++++++++ .../main/res/drawable/ic_arrow_up_right.xml | 9 +++ .../main/res/layout/list_item_suggestion.xml | 46 ++++++++++++++ .../src/main/res/layout/list_items.xml | 7 +++ .../res/layout/showcase_query_suggestion.xml | 38 ++++++++++++ 17 files changed, 458 insertions(+), 10 deletions(-) create mode 100644 showcase/android-view/src/main/kotlin/com/algolia/instantsearch/showcase/list/suggestion/Suggestion.kt create mode 100644 showcase/android-view/src/main/kotlin/com/algolia/instantsearch/showcase/suggestion/QuerySuggestionShowcase.kt create mode 100644 showcase/android-view/src/main/kotlin/com/algolia/instantsearch/showcase/suggestion/QuerySuggestionViewModel.kt create mode 100644 showcase/android-view/src/main/kotlin/com/algolia/instantsearch/showcase/suggestion/product/Product.kt create mode 100644 showcase/android-view/src/main/kotlin/com/algolia/instantsearch/showcase/suggestion/product/ProductAdapter.kt create mode 100644 showcase/android-view/src/main/kotlin/com/algolia/instantsearch/showcase/suggestion/product/ProductFragment.kt create mode 100644 showcase/android-view/src/main/kotlin/com/algolia/instantsearch/showcase/suggestion/suggestion/SuggestionAdapter.kt create mode 100644 showcase/android-view/src/main/kotlin/com/algolia/instantsearch/showcase/suggestion/suggestion/SuggestionFragment.kt create mode 100644 showcase/android-view/src/main/res/drawable/ic_arrow_up_right.xml create mode 100644 showcase/android-view/src/main/res/layout/list_item_suggestion.xml create mode 100644 showcase/android-view/src/main/res/layout/list_items.xml create mode 100644 showcase/android-view/src/main/res/layout/showcase_query_suggestion.xml diff --git a/guides/src/main/kotlin/com/algolia/instantsearch/guides/querysuggestion/QuerySuggestionViewModel.kt b/guides/src/main/kotlin/com/algolia/instantsearch/guides/querysuggestion/QuerySuggestionViewModel.kt index c19f8007..ebcb38ba 100644 --- a/guides/src/main/kotlin/com/algolia/instantsearch/guides/querysuggestion/QuerySuggestionViewModel.kt +++ b/guides/src/main/kotlin/com/algolia/instantsearch/guides/querysuggestion/QuerySuggestionViewModel.kt @@ -23,7 +23,7 @@ class QuerySuggestionViewModel : ViewModel() { val multiSearcher = MultiSearcher(client) val productSearcher = multiSearcher.addHitsSearcher( indexName = IndexName("STAGING_native_ecom_demo_products") - ) // TODO: native guide + guide screenshots + ) val suggestionSearcher = multiSearcher.addHitsSearcher( indexName = IndexName("STAGING_native_ecom_demo_products_query_suggestions") ) diff --git a/showcase/android-view/build.gradle b/showcase/android-view/build.gradle index ee91d53c..19b78e9b 100644 --- a/showcase/android-view/build.gradle +++ b/showcase/android-view/build.gradle @@ -42,13 +42,13 @@ dependencies { implementation "com.algolia:instantsearch-android-paging3:$instantsearch" implementation "com.algolia:instantsearch-android-loading:$instantsearch" - implementation "androidx.lifecycle:lifecycle-extensions:$lifecycle_version" - implementation "androidx.lifecycle:lifecycle-common-java8:$lifecycle_version" - implementation "androidx.constraintlayout:constraintlayout:2.1.2" - implementation "com.google.android.material:material:1.4.0" + implementation "androidx.fragment:fragment-ktx:1.4.1" + implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:2.4.1" + implementation "androidx.lifecycle:lifecycle-livedata-ktx:2.4.1" + implementation "androidx.constraintlayout:constraintlayout:2.1.3" + implementation "com.google.android.material:material:1.5.0" implementation "com.github.bumptech.glide:glide:4.10.0" implementation "io.apptik.widget:multislider:1.3" - implementation 'androidx.appcompat:appcompat:1.4.0' debugImplementation "com.squareup.leakcanary:leakcanary-android:$canary" testImplementation 'junit:junit:4.12' diff --git a/showcase/android-view/src/main/AndroidManifest.xml b/showcase/android-view/src/main/AndroidManifest.xml index a74a271a..aed518f5 100644 --- a/showcase/android-view/src/main/AndroidManifest.xml +++ b/showcase/android-view/src/main/AndroidManifest.xml @@ -120,6 +120,10 @@ android:name="com.algolia.instantsearch.showcase.filter.facet.dynamic.DynamicFacetShowcase" android:parentActivityName=".directory.DirectoryShowcase" /> + + diff --git a/showcase/android-view/src/main/kotlin/com/algolia/instantsearch/showcase/Demo.kt b/showcase/android-view/src/main/kotlin/com/algolia/instantsearch/showcase/Demo.kt index a35bd9ce..0927168b 100644 --- a/showcase/android-view/src/main/kotlin/com/algolia/instantsearch/showcase/Demo.kt +++ b/showcase/android-view/src/main/kotlin/com/algolia/instantsearch/showcase/Demo.kt @@ -26,12 +26,12 @@ import androidx.core.text.bold import androidx.core.text.buildSpannedString import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.RecyclerView -import com.algolia.instantsearch.core.connection.ConnectionHandler -import com.algolia.instantsearch.core.searcher.Searcher import com.algolia.instantsearch.android.filter.clear.FilterClearViewImpl import com.algolia.instantsearch.android.list.autoScrollToStart import com.algolia.instantsearch.android.searchbox.SearchBoxViewAppCompat import com.algolia.instantsearch.android.stats.StatsTextViewSpanned +import com.algolia.instantsearch.core.connection.ConnectionHandler +import com.algolia.instantsearch.core.searcher.Searcher import com.algolia.instantsearch.filter.clear.FilterClearConnector import com.algolia.instantsearch.filter.clear.connectView import com.algolia.instantsearch.filter.state.FilterGroupID @@ -179,6 +179,16 @@ fun AppCompatActivity.configureRecyclerView( } } +fun RecyclerView.configure( + recyclerViewAdapter: RecyclerView.Adapter<*> +) { + visibility = View.VISIBLE + layoutManager = LinearLayoutManager(context) + adapter = recyclerViewAdapter + itemAnimator = null + autoScrollToStart(recyclerViewAdapter) +} + val Intent.indexName: IndexName get() = IndexName(extras!!.getString(KeyIndexName)!!) fun AppCompatActivity.configureSearchBox( @@ -244,11 +254,21 @@ public fun Set>.highlight( val string = converter(setOf(group)) it.append(string) - it.setSpan(ForegroundColorSpan(color), begin, it.length, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE) + it.setSpan( + ForegroundColorSpan(color), + begin, + it.length, + Spanned.SPAN_EXCLUSIVE_EXCLUSIVE + ) if (index < size - 1) { begin = it.length it.append(" AND ") - it.setSpan(StyleSpan(Typeface.BOLD), begin, it.length, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE) + it.setSpan( + StyleSpan(Typeface.BOLD), + begin, + it.length, + Spanned.SPAN_EXCLUSIVE_EXCLUSIVE + ) } begin = it.length } diff --git a/showcase/android-view/src/main/kotlin/com/algolia/instantsearch/showcase/directory/Directory.kt b/showcase/android-view/src/main/kotlin/com/algolia/instantsearch/showcase/directory/Directory.kt index d78a54c4..1f772257 100644 --- a/showcase/android-view/src/main/kotlin/com/algolia/instantsearch/showcase/directory/Directory.kt +++ b/showcase/android-view/src/main/kotlin/com/algolia/instantsearch/showcase/directory/Directory.kt @@ -28,6 +28,7 @@ import com.algolia.instantsearch.showcase.search.SearchAutoCompleteTextView import com.algolia.instantsearch.showcase.search.SearchOnSubmitShowcase import com.algolia.instantsearch.showcase.sortby.SortByShowcase import com.algolia.instantsearch.showcase.stats.StatsShowcase +import com.algolia.instantsearch.showcase.suggestion.QuerySuggestionShowcase import com.algolia.search.model.ObjectID val showcases = mapOf( @@ -60,4 +61,5 @@ val showcases = mapOf( ObjectID("query_rule_custom_data") to QueryRuleCustomDataShowcase::class, ObjectID("filter_rating") to RatingShowcase::class, ObjectID("dynamic_facets") to DynamicFacetShowcase::class, + ObjectID("query_suggestions") to QuerySuggestionShowcase::class, ) diff --git a/showcase/android-view/src/main/kotlin/com/algolia/instantsearch/showcase/list/suggestion/Suggestion.kt b/showcase/android-view/src/main/kotlin/com/algolia/instantsearch/showcase/list/suggestion/Suggestion.kt new file mode 100644 index 00000000..dddc65be --- /dev/null +++ b/showcase/android-view/src/main/kotlin/com/algolia/instantsearch/showcase/list/suggestion/Suggestion.kt @@ -0,0 +1,20 @@ +package com.algolia.instantsearch.showcase.list.suggestion + +import com.algolia.instantsearch.core.highlighting.HighlightedString +import com.algolia.instantsearch.highlighting.Highlightable +import com.algolia.search.model.Attribute +import com.algolia.search.model.ObjectID +import com.algolia.search.model.indexing.Indexable +import kotlinx.serialization.Serializable +import kotlinx.serialization.json.JsonObject + +@Serializable +data class Suggestion( + val query: String, + override val objectID: ObjectID, + override val _highlightResult: JsonObject? +) : Indexable, Highlightable { + + val highlightedQuery: HighlightedString? + get() = getHighlight(Attribute("query")) +} diff --git a/showcase/android-view/src/main/kotlin/com/algolia/instantsearch/showcase/suggestion/QuerySuggestionShowcase.kt b/showcase/android-view/src/main/kotlin/com/algolia/instantsearch/showcase/suggestion/QuerySuggestionShowcase.kt new file mode 100644 index 00000000..9846bf6f --- /dev/null +++ b/showcase/android-view/src/main/kotlin/com/algolia/instantsearch/showcase/suggestion/QuerySuggestionShowcase.kt @@ -0,0 +1,62 @@ +package com.algolia.instantsearch.showcase.suggestion + +import android.os.Bundle +import androidx.activity.viewModels +import androidx.appcompat.app.AppCompatActivity +import androidx.appcompat.widget.SearchView +import androidx.fragment.app.commit +import androidx.fragment.app.replace +import com.algolia.instantsearch.android.searchbox.SearchBoxViewAppCompat +import com.algolia.instantsearch.core.connection.ConnectionHandler +import com.algolia.instantsearch.searchbox.connectView +import com.algolia.instantsearch.showcase.R +import com.algolia.instantsearch.showcase.suggestion.product.ProductFragment +import com.algolia.instantsearch.showcase.suggestion.suggestion.SuggestionFragment + +class QuerySuggestionShowcase : AppCompatActivity() { + + private val viewModel by viewModels() + private val connection = ConnectionHandler() + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + setContentView(R.layout.showcase_query_suggestion) + + // Setup search box + val searchView = findViewById(R.id.searchView) + val searchBoxView = SearchBoxViewAppCompat(searchView) + connection += viewModel.searchBox.connectView(searchBoxView) + + // Switch fragments on search box focus + searchView.setOnQueryTextFocusChangeListener { _, hasFocus -> + if (hasFocus) showSuggestions() else showProducts() + } + + // Observe suggestions + viewModel.suggestions.observe(this) { searchBoxView.setText(it.query, true) } + + // Initially show products view + showProducts() + } + + /** display suggestions fragment */ + private fun showSuggestions() { + supportFragmentManager.commit { + replace(R.id.container) + setReorderingAllowed(true) + } + } + + /** display products fragment */ + private fun showProducts() { + supportFragmentManager.commit { + replace(R.id.container) + setReorderingAllowed(true) + } + } + + override fun onDestroy() { + super.onDestroy() + connection.clear() + } +} diff --git a/showcase/android-view/src/main/kotlin/com/algolia/instantsearch/showcase/suggestion/QuerySuggestionViewModel.kt b/showcase/android-view/src/main/kotlin/com/algolia/instantsearch/showcase/suggestion/QuerySuggestionViewModel.kt new file mode 100644 index 00000000..d1c5d30b --- /dev/null +++ b/showcase/android-view/src/main/kotlin/com/algolia/instantsearch/showcase/suggestion/QuerySuggestionViewModel.kt @@ -0,0 +1,40 @@ +package com.algolia.instantsearch.showcase.suggestion + +import androidx.lifecycle.MutableLiveData +import androidx.lifecycle.ViewModel +import com.algolia.instantsearch.core.connection.ConnectionHandler +import com.algolia.instantsearch.searchbox.SearchBoxConnector +import com.algolia.instantsearch.searcher.hits.addHitsSearcher +import com.algolia.instantsearch.searcher.multi.MultiSearcher +import com.algolia.instantsearch.showcase.list.suggestion.Suggestion +import com.algolia.search.client.ClientSearch +import com.algolia.search.model.APIKey +import com.algolia.search.model.ApplicationID +import com.algolia.search.model.IndexName +import io.ktor.client.features.logging.* + +class QuerySuggestionViewModel : ViewModel() { + + private val client = ClientSearch( + applicationID = ApplicationID("latency"), + apiKey = APIKey("927c3fe76d4b52c5a2912973f35a3077"), + logLevel = LogLevel.ALL + ) + val multiSearcher = MultiSearcher(client) + val productSearcher = multiSearcher.addHitsSearcher( + indexName = IndexName("STAGING_native_ecom_demo_products") + ) + val suggestionSearcher = multiSearcher.addHitsSearcher( + indexName = IndexName("STAGING_native_ecom_demo_products_query_suggestions") + ) + val searchBox = SearchBoxConnector(multiSearcher) + private val connection = ConnectionHandler(searchBox) + + val suggestions = MutableLiveData() + + override fun onCleared() { + multiSearcher.cancel() + connection.clear() + client.close() + } +} diff --git a/showcase/android-view/src/main/kotlin/com/algolia/instantsearch/showcase/suggestion/product/Product.kt b/showcase/android-view/src/main/kotlin/com/algolia/instantsearch/showcase/suggestion/product/Product.kt new file mode 100644 index 00000000..0ac1ccef --- /dev/null +++ b/showcase/android-view/src/main/kotlin/com/algolia/instantsearch/showcase/suggestion/product/Product.kt @@ -0,0 +1,30 @@ +package com.algolia.instantsearch.showcase.suggestion.product + +import com.algolia.instantsearch.core.highlighting.HighlightedString +import com.algolia.instantsearch.highlighting.Highlightable +import com.algolia.search.model.Attribute +import com.algolia.search.model.ObjectID +import com.algolia.search.model.indexing.Indexable +import kotlinx.serialization.SerialName +import kotlinx.serialization.Serializable +import kotlinx.serialization.json.JsonObject + +@Serializable +data class Product( + val name: String, + @SerialName("image_urls") val images: List, + val price: Price, + val description: String, + override val objectID: ObjectID, + override val _highlightResult: JsonObject? +) : Indexable, Highlightable { + + val highlightedName: HighlightedString? + get() = getHighlight(Attribute("name")) +} + +@Serializable +data class Price( + val currency: String, + val value: String, +) diff --git a/showcase/android-view/src/main/kotlin/com/algolia/instantsearch/showcase/suggestion/product/ProductAdapter.kt b/showcase/android-view/src/main/kotlin/com/algolia/instantsearch/showcase/suggestion/product/ProductAdapter.kt new file mode 100644 index 00000000..82d64a80 --- /dev/null +++ b/showcase/android-view/src/main/kotlin/com/algolia/instantsearch/showcase/suggestion/product/ProductAdapter.kt @@ -0,0 +1,45 @@ +package com.algolia.instantsearch.showcase.suggestion.product + +import android.view.View +import android.view.ViewGroup +import android.widget.TextView +import androidx.recyclerview.widget.DiffUtil +import androidx.recyclerview.widget.ListAdapter +import androidx.recyclerview.widget.RecyclerView +import com.algolia.instantsearch.android.highlighting.toSpannedString +import com.algolia.instantsearch.android.inflate +import com.algolia.instantsearch.core.hits.HitsView +import com.algolia.instantsearch.showcase.R +import com.algolia.instantsearch.showcase.suggestion.product.ProductAdapter.ProductViewHolder +import com.bumptech.glide.Glide + +class ProductAdapter : ListAdapter(ProductDiffUtil), HitsView { + + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int) = + ProductViewHolder(parent.inflate(R.layout.list_item_large)) + + override fun onBindViewHolder(holder: ProductViewHolder, position: Int) = + holder.bind(getItem(position)) + + override fun setHits(hits: List) = submitList(hits) + + class ProductViewHolder(private val view: View) : RecyclerView.ViewHolder(view) { + + fun bind(item: Product) { + view.findViewById(R.id.itemTitle).text = + item.highlightedName?.toSpannedString() ?: item.name + view.findViewById(R.id.itemSubtitle).text = item.price.value + Glide + .with(view.context) + .load(item.images.first()) + .into(view.findViewById(R.id.itemImage)) + } + } + + private object ProductDiffUtil : DiffUtil.ItemCallback() { + override fun areItemsTheSame(oldItem: Product, newItem: Product) = + oldItem.objectID == newItem.objectID + + override fun areContentsTheSame(oldItem: Product, newItem: Product) = oldItem == newItem + } +} diff --git a/showcase/android-view/src/main/kotlin/com/algolia/instantsearch/showcase/suggestion/product/ProductFragment.kt b/showcase/android-view/src/main/kotlin/com/algolia/instantsearch/showcase/suggestion/product/ProductFragment.kt new file mode 100644 index 00000000..46077287 --- /dev/null +++ b/showcase/android-view/src/main/kotlin/com/algolia/instantsearch/showcase/suggestion/product/ProductFragment.kt @@ -0,0 +1,38 @@ +package com.algolia.instantsearch.showcase.suggestion.product + +import android.os.Bundle +import android.view.View +import androidx.fragment.app.Fragment +import androidx.fragment.app.activityViewModels +import androidx.recyclerview.widget.RecyclerView +import com.algolia.instantsearch.core.connection.ConnectionHandler +import com.algolia.instantsearch.core.hits.connectHitsView +import com.algolia.instantsearch.showcase.R +import com.algolia.instantsearch.showcase.configure +import com.algolia.instantsearch.showcase.suggestion.QuerySuggestionViewModel +import com.algolia.search.helper.deserialize + +class ProductFragment : Fragment(R.layout.list_items) { + + private val viewModel: QuerySuggestionViewModel by activityViewModels() + private val connection = ConnectionHandler() + + override fun onViewCreated(view: View, savedInstanceState: Bundle?) { + super.onViewCreated(view, savedInstanceState) + + // Configure products view + val productAdapter = ProductAdapter() + view.findViewById(R.id.items).configure(productAdapter) + connection += viewModel.productSearcher.connectHitsView(productAdapter) { + it.hits.deserialize(Product.serializer()) + } + + // Run initial search + viewModel.multiSearcher.searchAsync() + } + + override fun onDestroyView() { + super.onDestroyView() + connection.clear() + } +} diff --git a/showcase/android-view/src/main/kotlin/com/algolia/instantsearch/showcase/suggestion/suggestion/SuggestionAdapter.kt b/showcase/android-view/src/main/kotlin/com/algolia/instantsearch/showcase/suggestion/suggestion/SuggestionAdapter.kt new file mode 100644 index 00000000..25044b84 --- /dev/null +++ b/showcase/android-view/src/main/kotlin/com/algolia/instantsearch/showcase/suggestion/suggestion/SuggestionAdapter.kt @@ -0,0 +1,46 @@ +package com.algolia.instantsearch.showcase.suggestion.suggestion + +import android.view.View +import android.view.ViewGroup +import android.widget.TextView +import androidx.recyclerview.widget.DiffUtil +import androidx.recyclerview.widget.ListAdapter +import androidx.recyclerview.widget.RecyclerView +import com.algolia.instantsearch.android.highlighting.toSpannedString +import com.algolia.instantsearch.android.inflate +import com.algolia.instantsearch.core.hits.HitsView +import com.algolia.instantsearch.showcase.R +import com.algolia.instantsearch.showcase.list.suggestion.Suggestion +import com.algolia.instantsearch.showcase.suggestion.suggestion.SuggestionAdapter.SuggestionViewHolder + +class SuggestionAdapter(private val onSuggestionClick: ((Suggestion) -> Unit)) : + ListAdapter(SuggestionAdapter), + HitsView { + + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int) = + SuggestionViewHolder(parent.inflate(R.layout.list_item_suggestion)) + + override fun onBindViewHolder(holder: SuggestionViewHolder, position: Int) { + val item = getItem(position) + holder.bind(item, onSuggestionClick) + } + + override fun setHits(hits: List) = submitList(hits) + + class SuggestionViewHolder(private val view: View) : RecyclerView.ViewHolder(view) { + + fun bind(item: Suggestion, onClick: ((Suggestion) -> Unit)) { + view.setOnClickListener { onClick(item) } + view.findViewById(R.id.itemName).text = + item.highlightedQuery?.toSpannedString() ?: item.query + } + } + + companion object : DiffUtil.ItemCallback() { + override fun areItemsTheSame(oldItem: Suggestion, newItem: Suggestion) = + oldItem.objectID == newItem.objectID + + override fun areContentsTheSame(oldItem: Suggestion, newItem: Suggestion): Boolean = + oldItem == newItem + } +} diff --git a/showcase/android-view/src/main/kotlin/com/algolia/instantsearch/showcase/suggestion/suggestion/SuggestionFragment.kt b/showcase/android-view/src/main/kotlin/com/algolia/instantsearch/showcase/suggestion/suggestion/SuggestionFragment.kt new file mode 100644 index 00000000..d4306535 --- /dev/null +++ b/showcase/android-view/src/main/kotlin/com/algolia/instantsearch/showcase/suggestion/suggestion/SuggestionFragment.kt @@ -0,0 +1,41 @@ +package com.algolia.instantsearch.showcase.suggestion.suggestion + +import android.os.Bundle +import android.view.View +import androidx.fragment.app.Fragment +import androidx.fragment.app.activityViewModels +import androidx.recyclerview.widget.RecyclerView +import com.algolia.instantsearch.core.connection.ConnectionHandler +import com.algolia.instantsearch.core.hits.connectHitsView +import com.algolia.instantsearch.showcase.R +import com.algolia.instantsearch.showcase.configure +import com.algolia.instantsearch.showcase.list.suggestion.Suggestion +import com.algolia.instantsearch.showcase.suggestion.QuerySuggestionViewModel +import com.algolia.search.helper.deserialize + +class SuggestionFragment : Fragment(R.layout.list_items) { + + private val viewModel: QuerySuggestionViewModel by activityViewModels() + private val connection = ConnectionHandler() + + override fun onViewCreated(view: View, savedInstanceState: Bundle?) { + super.onViewCreated(view, savedInstanceState) + // Configure suggestions view + val suggestionAdapter = SuggestionAdapter { + // On suggestion click, update the + viewModel.suggestions.value = it + } + view.findViewById(R.id.items).configure(suggestionAdapter) + connection += viewModel.suggestionSearcher.connectHitsView(suggestionAdapter) { + it.hits.deserialize(Suggestion.serializer()) + } + + // Run initial search + viewModel.multiSearcher.searchAsync() + } + + override fun onDestroyView() { + super.onDestroyView() + connection.clear() + } +} diff --git a/showcase/android-view/src/main/res/drawable/ic_arrow_up_right.xml b/showcase/android-view/src/main/res/drawable/ic_arrow_up_right.xml new file mode 100644 index 00000000..c5b108d4 --- /dev/null +++ b/showcase/android-view/src/main/res/drawable/ic_arrow_up_right.xml @@ -0,0 +1,9 @@ + + + diff --git a/showcase/android-view/src/main/res/layout/list_item_suggestion.xml b/showcase/android-view/src/main/res/layout/list_item_suggestion.xml new file mode 100644 index 00000000..0fd4362c --- /dev/null +++ b/showcase/android-view/src/main/res/layout/list_item_suggestion.xml @@ -0,0 +1,46 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/showcase/android-view/src/main/res/layout/list_items.xml b/showcase/android-view/src/main/res/layout/list_items.xml new file mode 100644 index 00000000..e433223f --- /dev/null +++ b/showcase/android-view/src/main/res/layout/list_items.xml @@ -0,0 +1,7 @@ + + diff --git a/showcase/android-view/src/main/res/layout/showcase_query_suggestion.xml b/showcase/android-view/src/main/res/layout/showcase_query_suggestion.xml new file mode 100644 index 00000000..d54247e4 --- /dev/null +++ b/showcase/android-view/src/main/res/layout/showcase_query_suggestion.xml @@ -0,0 +1,38 @@ + + + + + + + + + + + + From f91320f73d88b35100ce618d4a65270990edbe06 Mon Sep 17 00:00:00 2001 From: Mouaad Aallam Date: Tue, 29 Mar 2022 16:11:27 +0200 Subject: [PATCH 3/4] initial query for query suggestion --- .../guides/querysuggestion/product/ProductFragment.kt | 2 +- .../guides/querysuggestion/suggestion/SuggestionFragment.kt | 2 +- .../showcase/suggestion/product/ProductFragment.kt | 2 +- .../showcase/suggestion/suggestion/SuggestionFragment.kt | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/guides/src/main/kotlin/com/algolia/instantsearch/guides/querysuggestion/product/ProductFragment.kt b/guides/src/main/kotlin/com/algolia/instantsearch/guides/querysuggestion/product/ProductFragment.kt index 589bed94..e3bf3286 100644 --- a/guides/src/main/kotlin/com/algolia/instantsearch/guides/querysuggestion/product/ProductFragment.kt +++ b/guides/src/main/kotlin/com/algolia/instantsearch/guides/querysuggestion/product/ProductFragment.kt @@ -28,7 +28,7 @@ class ProductFragment : Fragment(R.layout.fragment_items) { } // Run initial search - viewModel.multiSearcher.searchAsync() + viewModel.productSearcher.searchAsync() } override fun onDestroyView() { diff --git a/guides/src/main/kotlin/com/algolia/instantsearch/guides/querysuggestion/suggestion/SuggestionFragment.kt b/guides/src/main/kotlin/com/algolia/instantsearch/guides/querysuggestion/suggestion/SuggestionFragment.kt index d6e517da..1ffaa7e4 100644 --- a/guides/src/main/kotlin/com/algolia/instantsearch/guides/querysuggestion/suggestion/SuggestionFragment.kt +++ b/guides/src/main/kotlin/com/algolia/instantsearch/guides/querysuggestion/suggestion/SuggestionFragment.kt @@ -31,7 +31,7 @@ class SuggestionFragment : Fragment(R.layout.fragment_items) { } // Run initial search - viewModel.multiSearcher.searchAsync() + viewModel.suggestionSearcher.searchAsync() } override fun onDestroyView() { diff --git a/showcase/android-view/src/main/kotlin/com/algolia/instantsearch/showcase/suggestion/product/ProductFragment.kt b/showcase/android-view/src/main/kotlin/com/algolia/instantsearch/showcase/suggestion/product/ProductFragment.kt index 46077287..0765436a 100644 --- a/showcase/android-view/src/main/kotlin/com/algolia/instantsearch/showcase/suggestion/product/ProductFragment.kt +++ b/showcase/android-view/src/main/kotlin/com/algolia/instantsearch/showcase/suggestion/product/ProductFragment.kt @@ -28,7 +28,7 @@ class ProductFragment : Fragment(R.layout.list_items) { } // Run initial search - viewModel.multiSearcher.searchAsync() + viewModel.productSearcher.searchAsync() } override fun onDestroyView() { diff --git a/showcase/android-view/src/main/kotlin/com/algolia/instantsearch/showcase/suggestion/suggestion/SuggestionFragment.kt b/showcase/android-view/src/main/kotlin/com/algolia/instantsearch/showcase/suggestion/suggestion/SuggestionFragment.kt index d4306535..e348ed46 100644 --- a/showcase/android-view/src/main/kotlin/com/algolia/instantsearch/showcase/suggestion/suggestion/SuggestionFragment.kt +++ b/showcase/android-view/src/main/kotlin/com/algolia/instantsearch/showcase/suggestion/suggestion/SuggestionFragment.kt @@ -31,7 +31,7 @@ class SuggestionFragment : Fragment(R.layout.list_items) { } // Run initial search - viewModel.multiSearcher.searchAsync() + viewModel.suggestionSearcher.searchAsync() } override fun onDestroyView() { From 1200476c92245b14f1aa7d5a1c03db2135eecfb8 Mon Sep 17 00:00:00 2001 From: Mouaad Aallam Date: Tue, 29 Mar 2022 17:12:32 +0200 Subject: [PATCH 4/4] add loading view --- .../suggestion/QuerySuggestionShowcase.kt | 3 ++ .../suggestion/QuerySuggestionViewModel.kt | 6 +++- .../suggestion/product/ProductFragment.kt | 16 ++++++++-- .../suggestion/SuggestionFragment.kt | 5 +--- .../src/main/res/layout/list_items.xml | 29 ++++++++++++++++--- 5 files changed, 48 insertions(+), 11 deletions(-) diff --git a/showcase/android-view/src/main/kotlin/com/algolia/instantsearch/showcase/suggestion/QuerySuggestionShowcase.kt b/showcase/android-view/src/main/kotlin/com/algolia/instantsearch/showcase/suggestion/QuerySuggestionShowcase.kt index 9846bf6f..3dc31498 100644 --- a/showcase/android-view/src/main/kotlin/com/algolia/instantsearch/showcase/suggestion/QuerySuggestionShowcase.kt +++ b/showcase/android-view/src/main/kotlin/com/algolia/instantsearch/showcase/suggestion/QuerySuggestionShowcase.kt @@ -37,6 +37,9 @@ class QuerySuggestionShowcase : AppCompatActivity() { // Initially show products view showProducts() + + // Initial request + viewModel.multiSearcher.searchAsync() } /** display suggestions fragment */ diff --git a/showcase/android-view/src/main/kotlin/com/algolia/instantsearch/showcase/suggestion/QuerySuggestionViewModel.kt b/showcase/android-view/src/main/kotlin/com/algolia/instantsearch/showcase/suggestion/QuerySuggestionViewModel.kt index d1c5d30b..47ec8b1a 100644 --- a/showcase/android-view/src/main/kotlin/com/algolia/instantsearch/showcase/suggestion/QuerySuggestionViewModel.kt +++ b/showcase/android-view/src/main/kotlin/com/algolia/instantsearch/showcase/suggestion/QuerySuggestionViewModel.kt @@ -3,6 +3,7 @@ package com.algolia.instantsearch.showcase.suggestion import androidx.lifecycle.MutableLiveData import androidx.lifecycle.ViewModel import com.algolia.instantsearch.core.connection.ConnectionHandler +import com.algolia.instantsearch.loading.LoadingConnector import com.algolia.instantsearch.searchbox.SearchBoxConnector import com.algolia.instantsearch.searcher.hits.addHitsSearcher import com.algolia.instantsearch.searcher.multi.MultiSearcher @@ -27,8 +28,11 @@ class QuerySuggestionViewModel : ViewModel() { val suggestionSearcher = multiSearcher.addHitsSearcher( indexName = IndexName("STAGING_native_ecom_demo_products_query_suggestions") ) + val searchBox = SearchBoxConnector(multiSearcher) - private val connection = ConnectionHandler(searchBox) + val loading = LoadingConnector(multiSearcher) + + private val connection = ConnectionHandler(searchBox, loading) val suggestions = MutableLiveData() diff --git a/showcase/android-view/src/main/kotlin/com/algolia/instantsearch/showcase/suggestion/product/ProductFragment.kt b/showcase/android-view/src/main/kotlin/com/algolia/instantsearch/showcase/suggestion/product/ProductFragment.kt index 0765436a..5792e360 100644 --- a/showcase/android-view/src/main/kotlin/com/algolia/instantsearch/showcase/suggestion/product/ProductFragment.kt +++ b/showcase/android-view/src/main/kotlin/com/algolia/instantsearch/showcase/suggestion/product/ProductFragment.kt @@ -2,11 +2,15 @@ package com.algolia.instantsearch.showcase.suggestion.product import android.os.Bundle import android.view.View +import android.widget.ProgressBar import androidx.fragment.app.Fragment import androidx.fragment.app.activityViewModels import androidx.recyclerview.widget.RecyclerView +import com.algolia.instantsearch.core.Callback import com.algolia.instantsearch.core.connection.ConnectionHandler import com.algolia.instantsearch.core.hits.connectHitsView +import com.algolia.instantsearch.core.loading.LoadingView +import com.algolia.instantsearch.loading.connectView import com.algolia.instantsearch.showcase.R import com.algolia.instantsearch.showcase.configure import com.algolia.instantsearch.showcase.suggestion.QuerySuggestionViewModel @@ -27,8 +31,16 @@ class ProductFragment : Fragment(R.layout.list_items) { it.hits.deserialize(Product.serializer()) } - // Run initial search - viewModel.productSearcher.searchAsync() + // Configure loading indicator + val loadingView = loadingView(view.findViewById(R.id.progress)) + connection += viewModel.loading.connectView(loadingView) + } + + private fun loadingView(progressBar: ProgressBar) = object : LoadingView { + override var onReload: Callback? = null + override fun setIsLoading(isLoading: Boolean) { + progressBar.visibility = if (isLoading) View.VISIBLE else View.INVISIBLE + } } override fun onDestroyView() { diff --git a/showcase/android-view/src/main/kotlin/com/algolia/instantsearch/showcase/suggestion/suggestion/SuggestionFragment.kt b/showcase/android-view/src/main/kotlin/com/algolia/instantsearch/showcase/suggestion/suggestion/SuggestionFragment.kt index e348ed46..2acc7a28 100644 --- a/showcase/android-view/src/main/kotlin/com/algolia/instantsearch/showcase/suggestion/suggestion/SuggestionFragment.kt +++ b/showcase/android-view/src/main/kotlin/com/algolia/instantsearch/showcase/suggestion/suggestion/SuggestionFragment.kt @@ -26,12 +26,9 @@ class SuggestionFragment : Fragment(R.layout.list_items) { viewModel.suggestions.value = it } view.findViewById(R.id.items).configure(suggestionAdapter) - connection += viewModel.suggestionSearcher.connectHitsView(suggestionAdapter) { + connection += viewModel.suggestionSearcher.connectHitsView(suggestionAdapter, past = true) { it.hits.deserialize(Suggestion.serializer()) } - - // Run initial search - viewModel.suggestionSearcher.searchAsync() } override fun onDestroyView() { diff --git a/showcase/android-view/src/main/res/layout/list_items.xml b/showcase/android-view/src/main/res/layout/list_items.xml index e433223f..a37393f2 100644 --- a/showcase/android-view/src/main/res/layout/list_items.xml +++ b/showcase/android-view/src/main/res/layout/list_items.xml @@ -1,7 +1,28 @@ - + android:layout_height="match_parent"> + + + + + +