1
0
Fork 0
fenix/app/src/main/java/org/mozilla/fenix/settings/search/SearchEngineListPreference.kt

136 lines
5.2 KiB
Kotlin

/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
package org.mozilla.fenix.settings.search
import android.content.Context
import android.content.res.Resources
import android.graphics.drawable.BitmapDrawable
import android.util.AttributeSet
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.CompoundButton
import android.widget.RadioGroup
import androidx.constraintlayout.widget.ConstraintLayout
import androidx.preference.Preference
import androidx.preference.PreferenceViewHolder
import kotlinx.android.synthetic.main.search_engine_radio_button.view.*
import mozilla.components.browser.search.SearchEngine
import org.mozilla.fenix.R
import org.mozilla.fenix.ext.components
import org.mozilla.fenix.ext.settings
abstract class SearchEngineListPreference @JvmOverloads constructor(
context: Context,
attrs: AttributeSet? = null,
defStyleAttr: Int = android.R.attr.preferenceStyle
) : Preference(context, attrs, defStyleAttr), CompoundButton.OnCheckedChangeListener {
protected var searchEngines: List<SearchEngine> = emptyList()
protected var searchEngineGroup: RadioGroup? = null
protected abstract val itemResId: Int
init {
layoutResource = R.layout.preference_search_engine_chooser
}
override fun onBindViewHolder(holder: PreferenceViewHolder?) {
super.onBindViewHolder(holder)
searchEngineGroup = holder!!.itemView.findViewById(R.id.search_engine_group)
val context = searchEngineGroup!!.context
searchEngines = context.components.search.searchEngineManager.getSearchEngines(context)
.sortedBy { it.name }
refreshSearchEngineViews(context)
}
protected abstract fun onSearchEngineSelected(searchEngine: SearchEngine)
protected abstract fun updateDefaultItem(defaultButton: CompoundButton)
private fun refreshSearchEngineViews(context: Context) {
if (searchEngineGroup == null) {
// We want to refresh the search engine list of this preference in onResume,
// but the first time this preference is created onResume is called before onCreateView
// so searchEngineGroup is not set yet.
return
}
// To get the default search engine we have to pass in a name that doesn't exist
// https://github.com/mozilla-mobile/android-components/issues/3344
val defaultSearchEngine = context.components.search.searchEngineManager.getDefaultSearchEngine(
context,
THIS_IS_A_HACK_FIX_ME
)
val selectedSearchEngine =
context.components.search.searchEngineManager.getDefaultSearchEngine(
context,
context.settings().defaultSearchEngineName
).identifier
searchEngineGroup!!.removeAllViews()
val layoutInflater = LayoutInflater.from(context)
val layoutParams = ViewGroup.LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.WRAP_CONTENT
)
val setupSearchEngineItem: (Int, SearchEngine) -> Unit = { index, engine ->
val engineId = engine.identifier
val engineItem = makeButtonFromSearchEngine(engine, layoutInflater, context.resources)
engineItem.id = index
engineItem.tag = engineId
if (engineId == selectedSearchEngine) {
updateDefaultItem(engineItem.radio_button)
}
searchEngineGroup!!.addView(engineItem, layoutParams)
}
setupSearchEngineItem(0, defaultSearchEngine)
searchEngines
.filter { it.identifier != defaultSearchEngine.identifier }
.forEachIndexed(setupSearchEngineItem)
}
private fun makeButtonFromSearchEngine(
engine: SearchEngine,
layoutInflater: LayoutInflater,
res: Resources
): View {
val wrapper = layoutInflater.inflate(itemResId, null) as ConstraintLayout
wrapper.setOnClickListener { wrapper.radio_button.isChecked = true }
wrapper.radio_button.setOnCheckedChangeListener(this)
wrapper.engine_text.text = engine.name
val iconSize = res.getDimension(R.dimen.preference_icon_drawable_size).toInt()
val engineIcon = BitmapDrawable(res, engine.icon)
engineIcon.setBounds(0, 0, iconSize, iconSize)
wrapper.engine_icon.setImageDrawable(engineIcon)
return wrapper
}
override fun onCheckedChanged(buttonView: CompoundButton, isChecked: Boolean) {
searchEngines.forEach { engine ->
val wrapper: ConstraintLayout = searchEngineGroup?.findViewWithTag(engine.identifier) ?: return
when (wrapper.radio_button == buttonView) {
true -> onSearchEngineSelected(engine)
false -> {
wrapper.radio_button.setOnCheckedChangeListener(null)
wrapper.radio_button.isChecked = false
wrapper.radio_button.setOnCheckedChangeListener(this)
}
}
}
}
companion object {
private const val THIS_IS_A_HACK_FIX_ME = "."
}
}