blob: a65a5dac046e5ecfbb6bbc431afcd055410c3728 [file] [log] [blame]
/*
* Copyright (C) 2022 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.quicksearchbox.ui
import android.database.DataSetObserver
import android.util.Log
import android.view.View.OnFocusChangeListener
import com.android.quicksearchbox.SuggestionCursor
import com.android.quicksearchbox.SuggestionPosition
import com.android.quicksearchbox.Suggestions
/**
* A [SuggestionsListAdapter] that doesn't expose the new suggestions until there are some results
* to show.
*/
class DelayingSuggestionsAdapter<A>(private val mDelayedAdapter: SuggestionsAdapterBase<A>) :
SuggestionsAdapter<A> {
private var mPendingDataSetObserver: DataSetObserver? = null
private var mPendingSuggestions: Suggestions? = null
fun close() {
setPendingSuggestions(null)
mDelayedAdapter.close()
}
/** Gets whether the given suggestions are non-empty for the selected source. */
private fun shouldPublish(suggestions: Suggestions?): Boolean {
if (suggestions!!.isDone) return true
val cursor: SuggestionCursor? = suggestions.getResult()
return cursor != null && cursor.count > 0
}
private fun setPendingSuggestions(suggestions: Suggestions?) {
if (mPendingSuggestions === suggestions) {
return
}
if (mDelayedAdapter.isClosed) {
suggestions?.release()
return
}
if (mPendingDataSetObserver == null) {
mPendingDataSetObserver = PendingSuggestionsObserver()
}
if (mPendingSuggestions != null) {
mPendingSuggestions!!.unregisterDataSetObserver(mPendingDataSetObserver)
// Close old suggestions, but only if they are not also the current
// suggestions.
if (mPendingSuggestions !== this.suggestions) {
mPendingSuggestions!!.release()
}
}
mPendingSuggestions = suggestions
if (mPendingSuggestions != null) {
mPendingSuggestions!!.registerDataSetObserver(mPendingDataSetObserver)
}
}
protected fun onPendingSuggestionsChanged() {
if (DBG) Log.d(TAG, "onPendingSuggestionsChanged(), mPendingSuggestions=" + mPendingSuggestions)
if (shouldPublish(mPendingSuggestions)) {
if (DBG) Log.d(TAG, "Suggestions now available, publishing: $mPendingSuggestions")
mDelayedAdapter.suggestions = mPendingSuggestions
// The suggestions are no longer pending.
setPendingSuggestions(null)
}
}
private inner class PendingSuggestionsObserver : DataSetObserver() {
@Override
override fun onChanged() {
onPendingSuggestionsChanged()
}
}
@get:Override
override val listAdapter: A
get() = mDelayedAdapter.listAdapter
val currentPromotedSuggestions: SuggestionCursor?
get() = mDelayedAdapter.currentSuggestions
// Clear any old pending suggestions.
@get:Override
@set:Override
override var suggestions: Suggestions?
get() = mDelayedAdapter.suggestions
set(suggestions) {
if (suggestions == null) {
mDelayedAdapter.suggestions = null
setPendingSuggestions(null)
return
}
if (shouldPublish(suggestions)) {
if (DBG) Log.d(TAG, "Publishing suggestions immediately: $suggestions")
mDelayedAdapter.suggestions = suggestions
// Clear any old pending suggestions.
setPendingSuggestions(null)
} else {
if (DBG) Log.d(TAG, "Delaying suggestions publishing: $suggestions")
setPendingSuggestions(suggestions)
}
}
@Override
override fun getSuggestion(suggestionId: Long): SuggestionPosition? {
return mDelayedAdapter.getSuggestion(suggestionId)
}
@Override
override fun onSuggestionClicked(suggestionId: Long) {
mDelayedAdapter.onSuggestionClicked(suggestionId)
}
@Override
override fun onSuggestionQueryRefineClicked(suggestionId: Long) {
mDelayedAdapter.onSuggestionQueryRefineClicked(suggestionId)
}
@Override
override fun setOnFocusChangeListener(l: OnFocusChangeListener?) {
mDelayedAdapter.setOnFocusChangeListener(l)
}
@Override
override fun setSuggestionClickListener(listener: SuggestionClickListener?) {
mDelayedAdapter.setSuggestionClickListener(listener)
}
@get:Override
override val isEmpty: Boolean
get() = mDelayedAdapter.isEmpty
companion object {
private const val DBG = false
private const val TAG = "QSB.DelayingSuggestionsAdapter"
}
}