Skip to content
This repository was archived by the owner on Feb 17, 2020. It is now read-only.

Commit eded253

Browse files
committed
Merge branch 'develop' into conf/droidcon-turin-2018
2 parents 9e68a57 + b93ce66 commit eded253

6 files changed

Lines changed: 36 additions & 27 deletions

File tree

app/src/main/java/net/squanchy/search/SearchActivity.kt

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -46,13 +46,16 @@ class SearchActivity : AppCompatActivity(), SearchRecyclerView.OnSearchResultCli
4646
private lateinit var searchTextWatcher: SearchTextWatcher
4747

4848
private var hasQuery: Boolean = false
49+
private lateinit var initialQuery: String
4950

5051
override fun onCreate(savedInstanceState: Bundle?) {
5152
super.onCreate(savedInstanceState)
5253
setContentView(R.layout.activity_search)
5354
enableLightNavigationBar(this)
5455
setupToolbar()
5556

57+
initialQuery = savedInstanceState?.getString(QUERY_KEY) ?: ""
58+
5659
with(searchComponent(this)) {
5760
searchService = service()
5861
navigator = navigator()
@@ -74,7 +77,7 @@ class SearchActivity : AppCompatActivity(), SearchRecyclerView.OnSearchResultCli
7477

7578
val searchSubscription = querySubject.throttleLast(QUERY_DEBOUNCE_TIMEOUT, TimeUnit.MILLISECONDS)
7679
.doOnNext(::updateSearchActionIcon)
77-
.startWith(getInitialQuery())
80+
.startWith(initialQuery)
7881
.flatMap(searchService::find)
7982
.distinctUntilChanged()
8083
.subscribeOn(Schedulers.io())
@@ -93,11 +96,6 @@ class SearchActivity : AppCompatActivity(), SearchRecyclerView.OnSearchResultCli
9396
searchField.requestFocus()
9497
}
9598

96-
private fun getInitialQuery(): String {
97-
val text = searchField.text
98-
return text?.toString() ?: EMPTY_QUERY
99-
}
100-
10199
private fun updateSearchActionIcon(query: String) {
102100
hasQuery = query.isNotEmpty()
103101
invalidateOptionsMenu()
@@ -122,9 +120,8 @@ class SearchActivity : AppCompatActivity(), SearchRecyclerView.OnSearchResultCli
122120
} else {
123121
emptyView.isInvisible = true
124122
searchRecyclerView.isVisible = true
125-
126-
searchRecyclerView.updateWith(searchResult, this)
127123
}
124+
searchRecyclerView.updateWith(searchResult, this)
128125
}
129126

130127
private fun onSearchError() {
@@ -192,6 +189,11 @@ class SearchActivity : AppCompatActivity(), SearchRecyclerView.OnSearchResultCli
192189
}
193190
}
194191

192+
override fun onSaveInstanceState(outState: Bundle?) {
193+
outState?.putString(QUERY_KEY, searchField.text?.toString())
194+
super.onSaveInstanceState(outState)
195+
}
196+
195197
private fun onVoiceSearchClicked() {
196198
Intent(RecognizerIntent.ACTION_RECOGNIZE_SPEECH).apply {
197199
putExtra(RecognizerIntent.EXTRA_MAX_RESULTS, 1)
@@ -245,6 +247,6 @@ class SearchActivity : AppCompatActivity(), SearchRecyclerView.OnSearchResultCli
245247
private const val SPEECH_REQUEST_CODE = 100
246248
private const val QUERY_DEBOUNCE_TIMEOUT = 250L
247249
private const val MIN_QUERY_LENGTH = 2
248-
private const val EMPTY_QUERY = ""
250+
private const val QUERY_KEY = "SearchActivity.query_key"
249251
}
250252
}

app/src/main/java/net/squanchy/search/SearchService.kt

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,16 +3,16 @@ package net.squanchy.search
33
import io.reactivex.Observable
44
import io.reactivex.functions.Function3
55
import net.squanchy.schedule.domain.view.Event
6+
import net.squanchy.search.SearchListElement.AlgoliaLogo
7+
import net.squanchy.search.SearchListElement.EventElement
8+
import net.squanchy.search.SearchListElement.EventHeader
9+
import net.squanchy.search.SearchListElement.SpeakerElement
10+
import net.squanchy.search.SearchListElement.SpeakerHeader
611
import net.squanchy.search.algolia.AlgoliaSearchEngine
712
import net.squanchy.search.algolia.model.AlgoliaSearchResult
8-
import net.squanchy.search.algolia.model.AlgoliaSearchResult.QueryNotLongEnough
913
import net.squanchy.search.algolia.model.AlgoliaSearchResult.ErrorSearching
1014
import net.squanchy.search.algolia.model.AlgoliaSearchResult.Matches
11-
import net.squanchy.search.SearchListElement.SpeakerHeader
12-
import net.squanchy.search.SearchListElement.EventHeader
13-
import net.squanchy.search.SearchListElement.SpeakerElement
14-
import net.squanchy.search.SearchListElement.AlgoliaLogo
15-
import net.squanchy.search.SearchListElement.EventElement
15+
import net.squanchy.search.algolia.model.AlgoliaSearchResult.QueryNotLongEnough
1616
import net.squanchy.service.repository.AuthService
1717
import net.squanchy.service.repository.EventRepository
1818
import net.squanchy.service.repository.SpeakerRepository
@@ -51,7 +51,7 @@ class SearchService(
5151
}
5252

5353
private fun createResultForQueryNotLongEnough(speakers: List<Speaker>): List<SearchListElement> {
54-
return listOf(SpeakerHeader) + speakers.map(::SpeakerElement)
54+
return listOf(SpeakerHeader) + speakers.map(::SpeakerElement).sortedBy { it.speaker.name }
5555
}
5656

5757
private fun createResultForSuccessfulSearch(events: List<Event>, speakers: List<Speaker>): List<SearchListElement> {

app/src/main/java/net/squanchy/search/view/GridSpanSizeLookup.kt

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,14 +3,22 @@ package net.squanchy.search.view
33
import android.support.v7.widget.GridLayoutManager
44
import net.squanchy.search.SearchListElement
55

6-
internal class GridSpanSizeLookup(private val items: List<SearchListElement>, private val columnCount: Int) : GridLayoutManager.SpanSizeLookup() {
6+
internal class GridSpanSizeLookup(
7+
private val itemRetriever: (Int) -> SearchListElement,
8+
private val isAdapterEmpty: () -> Boolean,
9+
private val columnCount: Int
10+
) : GridLayoutManager.SpanSizeLookup() {
711

812
init {
913
super.setSpanIndexCacheEnabled(true)
1014
}
1115

1216
override fun getSpanSize(position: Int): Int {
13-
return if (items.isEmpty()) SINGLE_COLUMN_SPAN_SIZE else getSpanSizeFor(items[position])
17+
if (isAdapterEmpty()) {
18+
return SINGLE_COLUMN_SPAN_SIZE
19+
} else {
20+
return getSpanSizeFor(itemRetriever(position))
21+
}
1422
}
1523

1624
private fun getSpanSizeFor(element: SearchListElement): Int =

app/src/main/java/net/squanchy/search/view/SearchAdapter.kt

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,7 @@ internal class SearchAdapter(activity: AppCompatActivity) : ListAdapter<SearchLi
7979
}
8080

8181
override fun onBindViewHolder(holder: SearchItemViewHolder, position: Int) {
82-
val item = searchResult.elements[position]
82+
val item = getItem(position)
8383
when (item) {
8484
is SearchListElement.EventHeader -> (holder as HeaderViewHolder).updateWith(HeaderType.EVENTS)
8585
is SearchListElement.SpeakerHeader -> (holder as HeaderViewHolder).updateWith(HeaderType.SPEAKERS)
@@ -90,9 +90,11 @@ internal class SearchAdapter(activity: AppCompatActivity) : ListAdapter<SearchLi
9090
}
9191

9292
fun createSpanSizeLookup(columnsCount: Int): GridLayoutManager.SpanSizeLookup {
93-
return GridSpanSizeLookup(searchResult.elements, columnsCount)
93+
return GridSpanSizeLookup(::getItem, ::isEmpty, columnsCount)
9494
}
9595

96+
private fun isEmpty() = itemCount == 0
97+
9698
fun updateWith(searchResult: SearchResult.Success, listener: SearchRecyclerView.OnSearchResultClickListener) {
9799
this.listener = listener
98100
this.searchResult = searchResult

app/src/main/java/net/squanchy/search/view/SearchRecyclerView.kt

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import net.squanchy.schedule.domain.view.Event
1212
import net.squanchy.search.SearchResult
1313
import net.squanchy.speaker.domain.view.Speaker
1414
import net.squanchy.support.unwrapToActivityContext
15+
import net.squanchy.support.view.setAdapterIfNone
1516
import net.squanchy.support.widget.CardLayout
1617

1718
class SearchRecyclerView @JvmOverloads constructor(
@@ -33,20 +34,16 @@ class SearchRecyclerView @JvmOverloads constructor(
3334
addItemDecoration(CardOnlySpacingItemDecorator(horizontalSpacing, verticalSpacing))
3435

3536
adapter = SearchAdapter(context.unwrapToActivityContext())
36-
setAdapter(adapter)
3737
clipToPadding = false
3838
}
3939

4040
fun updateWith(searchResult: SearchResult.Success, listener: OnSearchResultClickListener) {
41-
if (getAdapter() == null) {
42-
super.setAdapter(adapter)
43-
}
41+
setAdapterIfNone(adapter)
4442

4543
adapter.updateWith(searchResult, listener)
4644

47-
val layoutManager = layoutManager as GridLayoutManager
4845
val spanSizeLookup = adapter.createSpanSizeLookup(COLUMNS_COUNT)
49-
layoutManager.spanSizeLookup = spanSizeLookup
46+
(layoutManager as GridLayoutManager).spanSizeLookup = spanSizeLookup
5047
}
5148

5249
interface OnSearchResultClickListener {

dependencies.gradle

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ ext {
6363
]
6464

6565
buildScript = [
66-
android : 'com.android.tools.build:gradle:3.1.0',
66+
android : 'com.android.tools.build:gradle:3.1.1',
6767
firebase : 'com.google.firebase:firebase-plugins:1.1.5',
6868
googleServices : 'com.google.gms:google-services:3.2.0',
6969
gradleStaticAnalysisPlugin: 'com.novoda:gradle-static-analysis-plugin:0.5.2',

0 commit comments

Comments
 (0)