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 c209e78e..00000000 Binary files a/showcase-compose/src/main/res/mipmap-hdpi/ic_launcher.webp and /dev/null differ 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 b2dfe3d1..00000000 Binary files a/showcase-compose/src/main/res/mipmap-hdpi/ic_launcher_round.webp and /dev/null differ 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 4f0f1d64..00000000 Binary files a/showcase-compose/src/main/res/mipmap-mdpi/ic_launcher.webp and /dev/null differ diff --git a/showcase-compose/src/main/res/mipmap-mdpi/ic_launcher_round.webp b/showcase-compose/src/main/res/mipmap-mdpi/ic_launcher_round.webp deleted file mode 100644 index 62b611da..00000000 Binary files a/showcase-compose/src/main/res/mipmap-mdpi/ic_launcher_round.webp and /dev/null differ 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 948a3070..00000000 Binary files a/showcase-compose/src/main/res/mipmap-xhdpi/ic_launcher.webp and /dev/null differ 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 1b9a6956..00000000 Binary files a/showcase-compose/src/main/res/mipmap-xhdpi/ic_launcher_round.webp and /dev/null differ diff --git a/showcase-compose/src/main/res/mipmap-xxhdpi/ic_launcher.webp b/showcase-compose/src/main/res/mipmap-xxhdpi/ic_launcher.webp deleted file mode 100644 index 28d4b77f..00000000 Binary files a/showcase-compose/src/main/res/mipmap-xxhdpi/ic_launcher.webp and /dev/null differ diff --git a/showcase-compose/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp b/showcase-compose/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp deleted file mode 100644 index 9287f508..00000000 Binary files a/showcase-compose/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp and /dev/null differ diff --git a/showcase-compose/src/main/res/mipmap-xxxhdpi/ic_launcher.webp b/showcase-compose/src/main/res/mipmap-xxxhdpi/ic_launcher.webp deleted file mode 100644 index aa7d6427..00000000 Binary files a/showcase-compose/src/main/res/mipmap-xxxhdpi/ic_launcher.webp and /dev/null differ diff --git a/showcase-compose/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp b/showcase-compose/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp deleted file mode 100644 index 9126ae37..00000000 Binary files a/showcase-compose/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp and /dev/null differ 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 76% rename from showcase/build.gradle rename to showcase/android-view/build.gradle index ad939794..19b78e9b 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 "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 "com.github.bumptech.glide:glide:4.10.0" implementation "com.algolia:instantsearch-android:$instantsearch" + implementation "com.algolia:instantsearch-android-paging3:$instantsearch" + implementation "com.algolia:instantsearch-android-loading:$instantsearch" + + 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.3.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 97% rename from showcase/src/main/AndroidManifest.xml rename to showcase/android-view/src/main/AndroidManifest.xml index a74a271a..aed518f5 100644 --- a/showcase/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/src/main/kotlin/com/algolia/instantsearch/showcase/Demo.kt b/showcase/android-view/src/main/kotlin/com/algolia/instantsearch/showcase/Demo.kt similarity index 75% 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..0927168b 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 @@ -23,24 +26,23 @@ import androidx.core.text.bold import androidx.core.text.buildSpannedString import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.RecyclerView +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.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.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( @@ -175,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( @@ -225,6 +239,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(), @@ -238,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/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 96% 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 index d78a54c4..1f772257 100644 --- 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 @@ -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/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/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/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/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..3dc31498 --- /dev/null +++ b/showcase/android-view/src/main/kotlin/com/algolia/instantsearch/showcase/suggestion/QuerySuggestionShowcase.kt @@ -0,0 +1,65 @@ +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() + + // Initial request + viewModel.multiSearcher.searchAsync() + } + + /** 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..47ec8b1a --- /dev/null +++ b/showcase/android-view/src/main/kotlin/com/algolia/instantsearch/showcase/suggestion/QuerySuggestionViewModel.kt @@ -0,0 +1,44 @@ +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 +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) + val loading = LoadingConnector(multiSearcher) + + private val connection = ConnectionHandler(searchBox, loading) + + 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..5792e360 --- /dev/null +++ b/showcase/android-view/src/main/kotlin/com/algolia/instantsearch/showcase/suggestion/product/ProductFragment.kt @@ -0,0 +1,50 @@ +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 +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()) + } + + // 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() { + 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..2acc7a28 --- /dev/null +++ b/showcase/android-view/src/main/kotlin/com/algolia/instantsearch/showcase/suggestion/suggestion/SuggestionFragment.kt @@ -0,0 +1,38 @@ +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, past = true) { + it.hits.deserialize(Suggestion.serializer()) + } + } + + override fun onDestroyView() { + super.onDestroyView() + connection.clear() + } +} 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/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/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/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..a37393f2 --- /dev/null +++ b/showcase/android-view/src/main/res/layout/list_items.xml @@ -0,0 +1,28 @@ + + + + + + + + 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/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 @@ + + + + + + + + + + + + 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