Use dropdown for country picker

This commit is contained in:
Sylvain Berfini 2023-09-27 16:00:35 +02:00
parent f4566ce812
commit 42dd293aa8
8 changed files with 69 additions and 223 deletions

View file

@ -1,102 +0,0 @@
/*
* Copyright (c) 2010-2020 Belledonne Communications SARL.
*
* This file is part of linphone-android
* (see https://www.linphone.org).
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.linphone.ui.assistant.adapter
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.BaseAdapter
import android.widget.Filter
import android.widget.Filterable
import android.widget.TextView
import kotlin.collections.ArrayList
import org.linphone.R
import org.linphone.core.DialPlan
import org.linphone.core.Factory
class CountryPickerAdapter : BaseAdapter(), Filterable {
private var countries: ArrayList<DialPlan>
init {
val dialPlans = Factory.instance().dialPlans
countries = arrayListOf()
countries.addAll(dialPlans)
}
override fun getView(position: Int, convertView: View?, parent: ViewGroup): View {
val view: View = convertView ?: LayoutInflater.from(parent.context).inflate(
R.layout.assistant_country_picker_cell,
parent,
false
)
val dialPlan: DialPlan = countries[position]
val flag = view.findViewById<TextView>(R.id.country_flag)
flag.text = dialPlan.flag
val name = view.findViewById<TextView>(R.id.country_name)
name.text = dialPlan.country
val dialCode = view.findViewById<TextView>(R.id.country_prefix)
dialCode.text = String.format("(%s)", dialPlan.countryCallingCode)
view.tag = dialPlan
return view
}
override fun getItem(position: Int): DialPlan {
return countries[position]
}
override fun getItemId(position: Int): Long {
return position.toLong()
}
override fun getCount(): Int {
return countries.size
}
override fun getFilter(): Filter {
return object : Filter() {
override fun performFiltering(constraint: CharSequence): FilterResults {
val filteredCountries = arrayListOf<DialPlan>()
for (dialPlan in Factory.instance().dialPlans) {
if (dialPlan.country.contains(constraint, ignoreCase = true) ||
dialPlan.countryCallingCode.contains(constraint)
) {
filteredCountries.add(dialPlan)
}
}
val filterResults = FilterResults()
filterResults.values = filteredCountries
return filterResults
}
@Suppress("UNCHECKED_CAST")
override fun publishResults(
constraint: CharSequence,
results: FilterResults
) {
countries = results.values as ArrayList<DialPlan>
notifyDataSetChanged()
}
}
}
}

View file

@ -1,89 +0,0 @@
/*
* Copyright (c) 2010-2020 Belledonne Communications SARL.
*
* This file is part of linphone-android
* (see https://www.linphone.org).
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.linphone.ui.assistant.fragment
import android.os.Bundle
import android.text.Editable
import android.text.TextWatcher
import android.view.*
import androidx.annotation.UiThread
import androidx.fragment.app.DialogFragment
import org.linphone.R
import org.linphone.core.DialPlan
import org.linphone.databinding.AssistantCountryPickerFragmentBinding
import org.linphone.ui.assistant.adapter.CountryPickerAdapter
@UiThread
class CountryPickerFragment : DialogFragment() {
private var _binding: AssistantCountryPickerFragmentBinding? = null
private val binding get() = _binding!!
private lateinit var adapter: CountryPickerAdapter
var listener: CountryPickedListener? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setStyle(STYLE_NO_TITLE, R.style.Theme_LinphoneDialog)
}
override fun onDestroyView() {
super.onDestroyView()
_binding = null
}
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View {
_binding = AssistantCountryPickerFragmentBinding.inflate(inflater, container, false)
adapter = CountryPickerAdapter()
binding.countryList.adapter = adapter
binding.countryList.setOnItemClickListener { _, _, position, _ ->
if (position >= 0 && position < adapter.count) {
val dialPlan = adapter.getItem(position)
listener?.onCountryClicked(dialPlan)
}
dismiss()
}
binding.searchCountry.addTextChangedListener(object : TextWatcher {
override fun afterTextChanged(s: Editable?) {
adapter.filter.filter(s)
}
override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) { }
override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) { }
})
binding.setCancelClickListener {
dismiss()
}
return binding.root
}
interface CountryPickedListener {
fun onCountryClicked(dialPlan: DialPlan)
}
}

View file

@ -27,6 +27,8 @@ import android.text.TextWatcher
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.AdapterView
import android.widget.ArrayAdapter
import androidx.annotation.UiThread
import androidx.fragment.app.Fragment
import androidx.lifecycle.lifecycleScope
@ -56,6 +58,19 @@ class RegisterFragment : Fragment() {
R.id.assistant_nav_graph
)
private val dropdownListener = object : AdapterView.OnItemSelectedListener {
override fun onItemSelected(parent: AdapterView<*>?, view: View?, position: Int, id: Long) {
val dialPlan = viewModel.dialPlansList[position]
Log.i(
"$TAG Selected dialplan updated [+${dialPlan.countryCallingCode}] / [${dialPlan.country}]"
)
viewModel.selectedDialPlan.value = dialPlan
}
override fun onNothingSelected(parent: AdapterView<*>?) {
}
}
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
@ -79,12 +94,6 @@ class RegisterFragment : Fragment() {
goBack()
}
binding.setShowCountryPickerClickListener {
val countryPickerFragment = CountryPickerFragment()
countryPickerFragment.listener = viewModel
countryPickerFragment.show(childFragmentManager, "CountryPicker")
}
binding.setOpenSubscribeWebPageClickListener {
val url = getString(R.string.web_platform_register_email_url)
try {
@ -148,9 +157,24 @@ class RegisterFragment : Fragment() {
}
coreContext.postOnCoreThread {
val adapter = ArrayAdapter(
requireContext(),
R.layout.drop_down_item,
viewModel.dialPlansLabelList
)
adapter.setDropDownViewResource(R.layout.assistant_country_picker_dropdown_cell)
val dialPlan = PhoneNumberUtils.getDeviceDialPlan(requireContext())
var default = 0
if (dialPlan != null) {
viewModel.setDialPlan(dialPlan)
viewModel.selectedDialPlan.postValue(dialPlan)
default = viewModel.dialPlansList.indexOf(dialPlan)
}
coreContext.postOnMainThread {
binding.prefix.adapter = adapter
binding.prefix.setSelection(default)
binding.prefix.onItemSelectedListener = dropdownListener
}
}
}

View file

@ -84,7 +84,7 @@ class ThirdPartySipAccountLoginFragment : Fragment() {
R.layout.drop_down_item,
viewModel.availableTransports
)
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item)
adapter.setDropDownViewResource(R.layout.assistant_transport_dropdown_cell)
binding.transport.adapter = adapter
binding.transport.onItemSelectedListener = dropdownListener
binding.transport.setSelection(viewModel.availableTransports.size - 1)

View file

@ -42,12 +42,12 @@ import org.linphone.core.AccountCreatorListenerStub
import org.linphone.core.Core
import org.linphone.core.CoreListenerStub
import org.linphone.core.DialPlan
import org.linphone.core.Factory
import org.linphone.core.tools.Log
import org.linphone.ui.assistant.fragment.CountryPickerFragment
import org.linphone.utils.AppUtils
import org.linphone.utils.Event
class AccountCreationViewModel @UiThread constructor() : ViewModel(), CountryPickerFragment.CountryPickedListener {
class AccountCreationViewModel @UiThread constructor() : ViewModel() {
companion object {
private const val TAG = "[Account Creation ViewModel]"
}
@ -64,9 +64,11 @@ class AccountCreationViewModel @UiThread constructor() : ViewModel(), CountryPic
val phoneNumberError = MutableLiveData<String>()
val selectedDialPlan = MutableLiveData<DialPlan>()
val dialPlansLabelList = arrayListOf<String>()
val internationalPrefix = MutableLiveData<String>()
val dialPlansList = arrayListOf<DialPlan>()
val selectedDialPlan = MutableLiveData<DialPlan>()
val showPassword = MutableLiveData<Boolean>()
@ -272,6 +274,12 @@ class AccountCreationViewModel @UiThread constructor() : ViewModel(), CountryPic
operationInProgress.value = false
coreContext.postOnCoreThread { core ->
val dialPlans = Factory.instance().dialPlans.toList()
for (dialPlan in dialPlans) {
dialPlansList.add(dialPlan)
dialPlansLabelList.add("${dialPlan.flag} +${dialPlan.countryCallingCode}")
}
accountCreator = core.createAccountCreator(core.accountCreatorUrl)
accountCreator.addListener(accountCreatorListener)
core.addListener(coreListener)
@ -293,18 +301,6 @@ class AccountCreationViewModel @UiThread constructor() : ViewModel(), CountryPic
}
}
@UiThread
override fun onCountryClicked(dialPlan: DialPlan) {
coreContext.postOnCoreThread {
setDialPlan(dialPlan)
}
}
@WorkerThread
fun setDialPlan(dialPlan: DialPlan) {
internationalPrefix.postValue("${dialPlan.flag} +${dialPlan.countryCallingCode}")
}
@UiThread
override fun onCleared() {
coreContext.postOnCoreThread { core ->

View file

@ -0,0 +1,11 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.appcompat.widget.AppCompatTextView xmlns:android="http://schemas.android.com/apk/res/android"
style="@style/default_text_style"
android:id="@android:id/text1"
android:layout_width="match_parent"
android:layout_height="40dp"
android:text="🇫🇷 +33"
android:background="@color/white"
android:gravity="center_vertical"
android:paddingStart="20dp"
android:paddingEnd="20dp"/>

View file

@ -12,9 +12,6 @@
<variable
name="createAccountClickListener"
type="View.OnClickListener" />
<variable
name="showCountryPickerClickListener"
type="View.OnClickListener" />
<variable
name="openSubscribeWebPageClickListener"
type="View.OnClickListener" />
@ -136,7 +133,7 @@
android:id="@+id/phone_number"
android:layout_width="0dp"
android:layout_height="50dp"
android:paddingStart="115dp"
android:paddingStart="120dp"
android:paddingEnd="20dp"
android:text="@={viewModel.phoneNumber, default=`6 01 02 03 04 05`}"
android:textSize="14sp"
@ -151,14 +148,12 @@
app:layout_constraintStart_toStartOf="@id/username"
app:layout_constraintEnd_toEndOf="@id/username"/>
<androidx.appcompat.widget.AppCompatTextView
android:onClick="@{showCountryPickerClickListener}"
<androidx.appcompat.widget.AppCompatSpinner
style="@style/default_text_style"
android:id="@+id/prefix"
android:layout_width="110dp"
android:layout_width="wrap_content"
android:layout_height="0dp"
android:paddingStart="20dp"
android:text="@{viewModel.internationalPrefix, default=`🇫🇷 +33`}"
android:textSize="14sp"
android:textColor="@color/gray_main2_600"
android:gravity="center_vertical"

View file

@ -0,0 +1,11 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.appcompat.widget.AppCompatTextView xmlns:android="http://schemas.android.com/apk/res/android"
style="@style/default_text_style"
android:id="@android:id/text1"
android:layout_width="match_parent"
android:layout_height="40dp"
android:text="UDP"
android:background="@color/white"
android:gravity="center_vertical"
android:paddingStart="20dp"
android:paddingEnd="20dp"/>