Loading app/src/main/assets/known-base-urls.txt 0 → 100644 +22 −0 Original line number Diff line number Diff line carddav.a1.net aol.com dav.edis.at dav.fruux.com caldav.gmx.net carddav.gmx.net icloud.com cloud.liberta.vip office.luckycloud.de calendar.mail.ru mailbox.org mailfence.com posteo.de:8443 live.teambox.eu spica.t-online.de caldav.calendar.yahoo.com yandex.ru webmail.your-server.de/rpc.php/ calendar.zoho.com calendar.zoho.eu contacts.zoho.com contacts.zoho.eu app/src/main/java/at/bitfire/davdroid/ui/setup/DefaultLoginCredentialsModel.kt +58 −3 Original line number Diff line number Diff line Loading @@ -8,14 +8,24 @@ package at.bitfire.davdroid.ui.setup import android.app.Application import android.content.Context import android.content.Intent import android.text.Editable import android.widget.ArrayAdapter import android.widget.Filter import android.widget.RadioGroup import androidx.annotation.MainThread import androidx.lifecycle.AndroidViewModel import androidx.lifecycle.MutableLiveData import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope import at.bitfire.davdroid.R import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch import java.io.InputStreamReader import java.util.regex.Pattern class DefaultLoginCredentialsModel: ViewModel() { class DefaultLoginCredentialsModel(app: Application): AndroidViewModel(app) { private var initialized = false Loading @@ -23,7 +33,7 @@ class DefaultLoginCredentialsModel: ViewModel() { val loginWithUrlAndUsername = MutableLiveData<Boolean>() val loginAdvanced = MutableLiveData<Boolean>() val baseUrlAdapter = MutableLiveData<LoginUrlAdapter>() val baseUrl = MutableLiveData<String>() val baseUrlError = MutableLiveData<String>() Loading Loading @@ -84,6 +94,51 @@ class DefaultLoginCredentialsModel: ViewModel() { loginWithEmailAddress.value = true username.value = givenUsername password.value = givenPassword // load base URL presets viewModelScope.launch(Dispatchers.IO) { baseUrlAdapter.postValue(LoginUrlAdapter(getApplication())) } } class LoginUrlAdapter(context: Context): ArrayAdapter<String>(context, R.layout.text_list_item, android.R.id.text1) { /** * list of known host names/domains (without https://), like "example.com" or "carddav.example.com" */ val knownUrls = mutableListOf<String>() init { InputStreamReader(context.assets.open("known-base-urls.txt")).use { reader -> knownUrls.addAll(reader.readLines()) } } override fun getFilter(): Filter = object: Filter() { override fun performFiltering(constraint: CharSequence): FilterResults { val str = constraint.removePrefix("https://").toString() var results = if (str.isEmpty()) knownUrls else { val regex = Pattern.compile("(\\.|\\b)" + Pattern.quote(str)) knownUrls.filter { url -> regex.matcher(url).find() }.map { url -> "https://" + url } } return FilterResults().apply { values = results count = results.size } } override fun publishResults(constraint: CharSequence?, results: FilterResults) { clear() (results.values as List<String>?)?.let { suggestions -> addAll(suggestions) } } } } } app/src/main/res/layout/login_credentials_fragment.xml +3 −2 Original line number Diff line number Diff line Loading @@ -128,19 +128,20 @@ android:visibility="@{model.loginWithUrlAndUsername ? View.VISIBLE : View.GONE}"> <com.google.android.material.textfield.TextInputLayout style="@style/Widget.MaterialComponents.TextInputLayout.OutlinedBox.Dense" style="@style/Widget.MaterialComponents.TextInputLayout.OutlinedBox.ExposedDropdownMenu" android:layout_width="match_parent" android:layout_height="wrap_content" android:hint="@string/login_base_url" app:error="@{model.baseUrlError}" app:errorEnabled="true"> <!--suppress AndroidUnknownAttribute --> <com.google.android.material.textfield.TextInputEditText <AutoCompleteTextView android:id="@+id/loginUrlBaseUrlEdittext" android:layout_width="match_parent" android:layout_height="wrap_content" android:afterTextChanged="@{model::clearUrlError}" android:inputType="textUri" app:adapter="@{model.baseUrlAdapter}" android:text="@={model.baseUrl}" /> </com.google.android.material.textfield.TextInputLayout> Loading Loading
app/src/main/assets/known-base-urls.txt 0 → 100644 +22 −0 Original line number Diff line number Diff line carddav.a1.net aol.com dav.edis.at dav.fruux.com caldav.gmx.net carddav.gmx.net icloud.com cloud.liberta.vip office.luckycloud.de calendar.mail.ru mailbox.org mailfence.com posteo.de:8443 live.teambox.eu spica.t-online.de caldav.calendar.yahoo.com yandex.ru webmail.your-server.de/rpc.php/ calendar.zoho.com calendar.zoho.eu contacts.zoho.com contacts.zoho.eu
app/src/main/java/at/bitfire/davdroid/ui/setup/DefaultLoginCredentialsModel.kt +58 −3 Original line number Diff line number Diff line Loading @@ -8,14 +8,24 @@ package at.bitfire.davdroid.ui.setup import android.app.Application import android.content.Context import android.content.Intent import android.text.Editable import android.widget.ArrayAdapter import android.widget.Filter import android.widget.RadioGroup import androidx.annotation.MainThread import androidx.lifecycle.AndroidViewModel import androidx.lifecycle.MutableLiveData import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope import at.bitfire.davdroid.R import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch import java.io.InputStreamReader import java.util.regex.Pattern class DefaultLoginCredentialsModel: ViewModel() { class DefaultLoginCredentialsModel(app: Application): AndroidViewModel(app) { private var initialized = false Loading @@ -23,7 +33,7 @@ class DefaultLoginCredentialsModel: ViewModel() { val loginWithUrlAndUsername = MutableLiveData<Boolean>() val loginAdvanced = MutableLiveData<Boolean>() val baseUrlAdapter = MutableLiveData<LoginUrlAdapter>() val baseUrl = MutableLiveData<String>() val baseUrlError = MutableLiveData<String>() Loading Loading @@ -84,6 +94,51 @@ class DefaultLoginCredentialsModel: ViewModel() { loginWithEmailAddress.value = true username.value = givenUsername password.value = givenPassword // load base URL presets viewModelScope.launch(Dispatchers.IO) { baseUrlAdapter.postValue(LoginUrlAdapter(getApplication())) } } class LoginUrlAdapter(context: Context): ArrayAdapter<String>(context, R.layout.text_list_item, android.R.id.text1) { /** * list of known host names/domains (without https://), like "example.com" or "carddav.example.com" */ val knownUrls = mutableListOf<String>() init { InputStreamReader(context.assets.open("known-base-urls.txt")).use { reader -> knownUrls.addAll(reader.readLines()) } } override fun getFilter(): Filter = object: Filter() { override fun performFiltering(constraint: CharSequence): FilterResults { val str = constraint.removePrefix("https://").toString() var results = if (str.isEmpty()) knownUrls else { val regex = Pattern.compile("(\\.|\\b)" + Pattern.quote(str)) knownUrls.filter { url -> regex.matcher(url).find() }.map { url -> "https://" + url } } return FilterResults().apply { values = results count = results.size } } override fun publishResults(constraint: CharSequence?, results: FilterResults) { clear() (results.values as List<String>?)?.let { suggestions -> addAll(suggestions) } } } } }
app/src/main/res/layout/login_credentials_fragment.xml +3 −2 Original line number Diff line number Diff line Loading @@ -128,19 +128,20 @@ android:visibility="@{model.loginWithUrlAndUsername ? View.VISIBLE : View.GONE}"> <com.google.android.material.textfield.TextInputLayout style="@style/Widget.MaterialComponents.TextInputLayout.OutlinedBox.Dense" style="@style/Widget.MaterialComponents.TextInputLayout.OutlinedBox.ExposedDropdownMenu" android:layout_width="match_parent" android:layout_height="wrap_content" android:hint="@string/login_base_url" app:error="@{model.baseUrlError}" app:errorEnabled="true"> <!--suppress AndroidUnknownAttribute --> <com.google.android.material.textfield.TextInputEditText <AutoCompleteTextView android:id="@+id/loginUrlBaseUrlEdittext" android:layout_width="match_parent" android:layout_height="wrap_content" android:afterTextChanged="@{model::clearUrlError}" android:inputType="textUri" app:adapter="@{model.baseUrlAdapter}" android:text="@={model.baseUrl}" /> </com.google.android.material.textfield.TextInputLayout> Loading