Commit 67c02b26 authored by Daniel Wolf's avatar Daniel Wolf
Browse files

Merge branch '93-replace-all-materialedittext-s-with-textinputlayout' into 'master'

Resolve "Replace all MaterialEditText's with TextInputLayout"

Closes #93

See merge request !26
parents 6b592ce9 160451d4
Pipeline #4863 passed with stage
in 6 minutes and 33 seconds
......@@ -94,7 +94,6 @@ dependencies {
implementation 'com.frostnerd.utilskt:navigationdraweractivity:1.3.17'
implementation 'com.frostnerd.utilskt:encrypteddnstunnelproxy:1.5.112'
implementation 'com.frostnerd.utilskt:general:1.0.15'
implementation 'com.frostnerd.utils:materialedittext:1.0.20'
implementation 'com.frostnerd.utils:design:1.0.17'
implementation 'com.frostnerd.utilskt:networking:1.0.3'
implementation 'com.frostnerd.utilskt:adapters:1.1.0'
......
......@@ -5,7 +5,6 @@ import android.content.DialogInterface
import android.content.Intent
import android.content.res.ColorStateList
import android.graphics.Color
import android.hardware.biometrics.BiometricPrompt
import android.hardware.fingerprint.FingerprintManager
import android.os.*
import android.text.Editable
......@@ -15,16 +14,14 @@ import android.view.Window
import android.widget.EditText
import android.widget.ImageView
import androidx.appcompat.app.AlertDialog
import androidx.appcompat.app.AppCompatDelegate
import androidx.appcompat.widget.AppCompatImageView
import androidx.core.widget.ImageViewCompat
import com.frostnerd.lifecyclemanagement.BaseActivity
import com.frostnerd.materialedittext.MaterialEditText
import com.frostnerd.smokescreen.R
import com.frostnerd.smokescreen.canUseFingerprintAuthentication
import com.frostnerd.smokescreen.getPreferences
import com.frostnerd.smokescreen.service.Command
import com.frostnerd.smokescreen.service.DnsVpnService
import kotlinx.android.synthetic.main.dialog_pin.view.*
import java.math.BigInteger
import java.security.MessageDigest
import java.security.NoSuchAlgorithmException
......@@ -114,23 +111,22 @@ class PinActivity: BaseActivity() {
view.findViewById<ImageView>(R.id.fingerprintImage).visibility = View.GONE
}
val pinInput = view.findViewById<EditText>(R.id.pinInput)
val pinInputMet = view.findViewById<MaterialEditText>(R.id.pinInputMet)
dialog?.getButton(DialogInterface.BUTTON_POSITIVE)?.setOnClickListener {
if(pinInput.text.toString() == getPreferences().pin.toString() || hashMD5(pinInput.text.toString()) == masterPassword) {
pinInputMet.indicatorState = MaterialEditText.IndicatorState.CORRECT
view.pinInputTil.error = null
onPinPassed()
} else {
(getSystemService(Context.VIBRATOR_SERVICE) as Vibrator).vibrate(200)
pinInputMet.indicatorState = MaterialEditText.IndicatorState.INCORRECT
view.pinInputTil.error = getString(R.string.error_invalid_pin)
handler.postDelayed( {
pinInputMet.indicatorState = MaterialEditText.IndicatorState.UNDEFINED
view.pinInputTil.error = null
},2000)
}
}
pinInput.addTextChangedListener(object:TextWatcher {
override fun afterTextChanged(s: Editable?) {
pinInputMet.indicatorState = MaterialEditText.IndicatorState.UNDEFINED
view.pinInputTil.error = null
}
override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {}
......
......@@ -64,7 +64,7 @@ class NewHostSourceDialog (context: Context,
nameTil.error = null
}
if(url.text.isNullOrBlank() || !URLUtil.isValidUrl(url.text.toString())) {
urlTil.error = context.getString(R.string.dialog_newhostsource_url_invalid)
urlTil.error = context.getString(R.string.error_invalid_url)
valid = false
} else {
urlTil.error = null
......
......@@ -17,10 +17,11 @@ import com.frostnerd.encrypteddnstunnelproxy.tls.AbstractTLSDnsHandle
import com.frostnerd.encrypteddnstunnelproxy.tls.TLS
import com.frostnerd.encrypteddnstunnelproxy.tls.TLSUpstreamAddress
import com.frostnerd.lifecyclemanagement.BaseDialog
import com.frostnerd.materialedittext.MaterialEditText
import com.frostnerd.smokescreen.R
import com.frostnerd.smokescreen.getPreferences
import com.frostnerd.smokescreen.log
import com.google.android.material.textfield.TextInputEditText
import com.google.android.material.textfield.TextInputLayout
import kotlinx.android.synthetic.main.dialog_new_server.*
import kotlinx.android.synthetic.main.dialog_new_server.view.*
......@@ -75,7 +76,19 @@ class NewServerDialog(
setOnShowListener {
addUrlTextWatcher(primaryServerWrap, primaryServer, false)
addUrlTextWatcher(secondaryServerWrap, secondaryServer, true)
serverName.addTextChangedListener(object : TextWatcher {
override fun afterTextChanged(s: Editable?) {
serverNameWrap.error = if (s.isNullOrBlank()) context.getString(R.string.error_invalid_servername)
else null
}
override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {
}
override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {
}
})
serverNameWrap.error = context.getString(R.string.error_invalid_servername)
getButton(DialogInterface.BUTTON_POSITIVE).setOnClickListener {
if (inputsValid()) {
val name = serverName.text.toString()
......@@ -120,11 +133,15 @@ class NewServerDialog(
if (dnsOverHttps) {
if(titleOverride == null) setTitle(R.string.dialog_newserver_title_https)
view.primaryServer.setHint(R.string.dialog_newserver_primaryserver_hint)
view.secondaryServer.setHint(R.string.dialog_newserver_secondaryserver_hint)
view.secondaryServer.apply {
if(isFocused || error != null) setHint(R.string.dialog_newserver_secondaryserver_hint)
}
}else {
if(titleOverride == null) setTitle(R.string.dialog_newserver_title_tls)
view.primaryServer.setHint(R.string.dialog_newserver_primaryserver_hint_dot)
view.secondaryServer.setHint(R.string.dialog_newserver_secondaryserver_hint_dot)
view.secondaryServer.apply {
if(isFocused || error != null) setHint(R.string.dialog_newserver_secondaryserver_hint_dot)
}
}
if(titleOverride != null) setTitle(titleOverride)
}
......@@ -250,7 +267,7 @@ class NewServerDialog(
else TLSUpstreamAddress(parsedHost)
}
fun addUrlTextWatcher(materialEditText: MaterialEditText, editText: EditText, emptyAllowed: Boolean) {
fun addUrlTextWatcher(input: TextInputLayout, editText: TextInputEditText, emptyAllowed: Boolean) {
editText.addTextChangedListener(object : TextWatcher {
override fun afterTextChanged(s: Editable) {
val valid =
......@@ -258,10 +275,9 @@ class NewServerDialog(
s.toString()
))
materialEditText.indicatorState = if (valid) {
if (s.isBlank()) MaterialEditText.IndicatorState.UNDEFINED
else MaterialEditText.IndicatorState.CORRECT
} else MaterialEditText.IndicatorState.INCORRECT
input.error = if (valid) {
null
} else context.getString(R.string.error_invalid_url)
}
override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {
......@@ -273,10 +289,9 @@ class NewServerDialog(
})
}
fun inputsValid(): Boolean = serverNameWrap.indicatorState != MaterialEditText.IndicatorState.INCORRECT &&
primaryServerWrap.indicatorState != MaterialEditText.IndicatorState.INCORRECT &&
secondaryServerWrap.indicatorState != MaterialEditText.IndicatorState.INCORRECT
fun inputsValid(): Boolean = serverNameWrap.error == null &&
primaryServerWrap.error == null &&
secondaryServerWrap.error == null
override fun destroy() {}
}
\ No newline at end of file
......@@ -13,15 +13,15 @@ import android.widget.EditText
import com.frostnerd.dnstunnelproxy.DnsServerInformation
import com.frostnerd.encrypteddnstunnelproxy.HttpsDnsServerInformation
import com.frostnerd.lifecyclemanagement.BaseActivity
import com.frostnerd.materialedittext.MaterialEditText
import com.frostnerd.smokescreen.R
import com.frostnerd.smokescreen.activity.BackgroundVpnConfigureActivity
import com.frostnerd.smokescreen.dialog.NewServerDialog
import com.frostnerd.smokescreen.fromServerUrls
import com.frostnerd.smokescreen.hasHttpsServer
import com.frostnerd.smokescreen.tlsServerFromHosts
import com.google.android.material.textfield.TextInputEditText
import com.google.android.material.textfield.TextInputLayout
import kotlinx.android.synthetic.main.activity_tasker_configure.*
import kotlinx.android.synthetic.main.dialog_new_server.view.*
/*
* Copyright (C) 2019 Daniel Wolf (Ch4t4r)
......@@ -104,6 +104,7 @@ class ConfigureActivity : BaseActivity() {
}
}
}
setHints()
}
}
}
......@@ -155,28 +156,35 @@ class ConfigureActivity : BaseActivity() {
validationRegex = if (position == 0) NewServerDialog.SERVER_URL_REGEX else NewServerDialog.TLS_REGEX
primaryServer.text = primaryServer.text
secondaryServer.text = secondaryServer.text
if(position == 1) {
primaryServer.setHint(R.string.dialog_newserver_primaryserver_hint)
secondaryServer.setHint(R.string.dialog_newserver_secondaryserver_hint)
} else {
primaryServer.setHint(R.string.dialog_newserver_primaryserver_hint_dot)
secondaryServer.setHint(R.string.dialog_newserver_secondaryserver_hint_dot)
}
setHints()
}
}
addUrlTextWatcher(primaryServerWrap, primaryServer, false)
addUrlTextWatcher(secondaryServerWrap, secondaryServer, true)
setHints()
}
private fun addUrlTextWatcher(materialEditText: MaterialEditText, editText: EditText, emptyAllowed: Boolean) {
private fun setHints() {
val doh = serverType.selectedItemPosition == 0
println("DOH: $doh")
primaryServer.hint = if(primaryServer.hasFocus() || primaryServerWrap.error != null) {
if(doh) getString(R.string.dialog_newserver_primaryserver_hint)
else getString(R.string.dialog_newserver_primaryserver_hint_dot)
} else null
secondaryServer.hint = if(secondaryServer.hasFocus()) {
if(doh) getString(R.string.dialog_newserver_secondaryserver_hint)
else getString(R.string.dialog_newserver_secondaryserver_hint_dot)
} else null
}
private fun addUrlTextWatcher(input: TextInputLayout, editText: TextInputEditText, emptyAllowed: Boolean) {
editText.addTextChangedListener(object : TextWatcher {
override fun afterTextChanged(s: Editable) {
val valid = (emptyAllowed && s.isBlank()) || validationRegex.matches(s.toString())
materialEditText.indicatorState = if (valid) {
if (s.isBlank()) MaterialEditText.IndicatorState.UNDEFINED
else MaterialEditText.IndicatorState.CORRECT
} else MaterialEditText.IndicatorState.INCORRECT
input.error = if (valid) {
null
} else getString(R.string.error_invalid_url)
}
override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {
......@@ -186,6 +194,9 @@ class ConfigureActivity : BaseActivity() {
}
})
editText.setOnFocusChangeListener { _, hasFocus ->
setHints()
}
}
override fun onBackPressed() {
......@@ -206,8 +217,8 @@ class ConfigureActivity : BaseActivity() {
if (action == "start") {
settings.putBoolean(TaskerHelper.DATA_KEY_STARTIFRUNNING, startIfRunning.isChecked)
if (!useServersFromConfig.isChecked) {
if (primaryServerWrap.indicatorState != MaterialEditText.IndicatorState.INCORRECT &&
secondaryServerWrap.indicatorState != MaterialEditText.IndicatorState.INCORRECT
if (primaryServerWrap.error == null &&
secondaryServerWrap.error == null
) {
var primary = primaryServer.text.toString()
var secondary = if (secondaryServer.text.isNullOrBlank()) null else secondaryServer.text.toString()
......
......@@ -70,63 +70,42 @@
android:visibility="gone"
android:layout_height="wrap_content">
<com.frostnerd.materialedittext.MaterialEditText
<com.google.android.material.textfield.TextInputLayout
android:layout_width="match_parent"
app:labelColorPrimary="?attr/foregroundElementColor"
app:labelColorSecondary="?attr/foregroundElementColor"
app:revealDelay="0"
app:revealType="revealInstant"
app:minCharLength="1"
app:labelText="@string/dialog_newserver_primaryserver"
app:hint="@string/dialog_newserver_primaryserver_hint"
app:allowCollapse="false"
app:animationDuration="0"
app:indicatorState="incorrect"
android:id="@+id/primaryServerWrap"
app:errorEnabled="true"
android:textColorHint="?android:attr/textColorSecondary"
android:hint="@string/dialog_newserver_primaryserver"
android:layout_height="wrap_content">
<EditText
android:id="@+id/primaryServer"
<com.google.android.material.textfield.TextInputEditText
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:imeOptions="actionNext"
android:inputType="text"
android:id="@+id/primaryServer"
android:maxLines="1"
android:text=""
android:imeOptions="actionNext"
android:inputType="textUri"
android:nextFocusDown="@id/secondaryServer"
android:importantForAutofill="no"
android:textColor="?attr/foregroundElementColor">
</EditText>
</com.frostnerd.materialedittext.MaterialEditText>
android:layout_height="wrap_content"/>
</com.google.android.material.textfield.TextInputLayout>
<com.frostnerd.materialedittext.MaterialEditText
<com.google.android.material.textfield.TextInputLayout
android:layout_width="match_parent"
app:labelColorPrimary="?attr/foregroundElementColor"
app:labelColorSecondary="?attr/foregroundElementColor"
app:revealDelay="0"
android:layout_marginTop="8dp"
app:revealType="revealInstant"
app:labelText="@string/dialog_newserver_secondaryserver"
app:hint="@string/dialog_newserver_secondaryserver_hint"
android:id="@+id/secondaryServerWrap"
app:allowCollapse="false"
app:animationDuration="0"
app:errorEnabled="true"
android:textColorHint="?android:attr/textColorSecondary"
android:hint="@string/dialog_newserver_secondaryserver"
android:layout_height="wrap_content">
<EditText
<com.google.android.material.textfield.TextInputEditText
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/secondaryServer"
android:maxLines="1"
android:imeOptions="actionNext"
android:inputType="textUri"
android:nextFocusUp="@id/primaryServer"
android:inputType="text"
android:maxLines="1"
android:id="@+id/secondaryServer"
android:text=""
android:importantForAutofill="no"
android:textColor="?attr/foregroundElementColor">
</EditText>
</com.frostnerd.materialedittext.MaterialEditText>
android:layout_height="wrap_content"/>
</com.google.android.material.textfield.TextInputLayout>
</LinearLayout>
</LinearLayout>
</LinearLayout>
......
......@@ -32,30 +32,23 @@
style="@style/Base.Widget.AppCompat.Button.Borderless"
android:layout_height="24dp"/>
<com.frostnerd.materialedittext.MaterialEditText
<com.google.android.material.textfield.TextInputLayout
android:layout_width="match_parent"
app:image="@drawable/ic_search"
app:iconTint="?attr/foregroundElementColor"
app:allowCollapse="false"
app:animationDuration="0"
app:indicatorState="undefined"
app:indicatorVisibilityWhenUnused="hidden"
app:revealType="revealInstant"
android:id="@+id/nameTil"
app:errorEnabled="true"
android:hint="@string/search"
android:textColorHint="?attr/foregroundElementColor"
android:layout_toStartOf="@id/clearSearch"
android:layout_alignParentStart="true"
app:revealDelay="0"
app:labelText="@string/search"
android:layout_height="wrap_content">
<EditText
<com.google.android.material.textfield.TextInputEditText
android:layout_width="match_parent"
android:textColor="?attr/foregroundElementColor"
android:layout_height="wrap_content"
android:importantForAutofill="no"
android:hint="@string/hint_searchterm"
android:id="@+id/search"
android:inputType="text"/>
</com.frostnerd.materialedittext.MaterialEditText>
android:inputType="text"
android:layout_height="wrap_content"/>
</com.google.android.material.textfield.TextInputLayout>
</RelativeLayout>
......
......@@ -9,15 +9,14 @@
android:paddingBottom="@dimen/dialog_vertical_margin"
android:layout_height="match_parent">
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:orientation="vertical"
android:layout_width="match_parent"
android:paddingLeft="@dimen/dialog_horizontal_margin"
android:paddingRight="@dimen/dialog_horizontal_margin"
android:paddingTop="@dimen/dialog_vertical_margin"
android:paddingBottom="@dimen/dialog_vertical_margin"
android:layout_height="wrap_content">
<LinearLayout
android:orientation="vertical"
android:layout_width="match_parent"
android:paddingLeft="@dimen/dialog_horizontal_margin"
android:paddingRight="@dimen/dialog_horizontal_margin"
android:paddingTop="@dimen/dialog_vertical_margin"
android:paddingBottom="@dimen/dialog_vertical_margin"
android:layout_height="wrap_content">
<Spinner
android:layout_width="match_parent"
......@@ -25,98 +24,66 @@
android:layout_marginBottom="12dp"
android:layout_height="wrap_content"/>
<com.frostnerd.materialedittext.MaterialEditText
<com.google.android.material.textfield.TextInputLayout
android:layout_width="match_parent"
app:labelColorPrimary="?attr/foregroundElementColor"
app:labelColorSecondary="?attr/foregroundElementColor"
android:layout_marginTop="8dp"
app:revealDelay="0"
app:revealType="revealInstant"
app:labelText="@string/dialog_newserver_name"
app:hint="@string/dialog_newserver_name_hint"
app:allowCollapse="false"
app:minCharLength="1"
app:maxCharLength="50"
app:indicatorState="incorrect"
app:animationDuration="0"
android:id="@+id/serverNameWrap"
app:errorEnabled="true"
android:hint="@string/dialog_newserver_name"
android:textColorHint="?attr/foregroundElementColor"
android:layout_marginTop="8dp"
app:openKeyboardOnFocus="true"
android:layout_height="wrap_content">
<EditText
android:id="@+id/serverName"
<com.google.android.material.textfield.TextInputEditText
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:imeOptions="actionNext"
android:hint="@string/dialog_newserver_name_hint"
android:id="@+id/serverName"
android:inputType="text"
android:imeOptions="actionNext"
android:maxLines="1"
android:text=""
android:nextFocusDown="@id/secondaryServer"
android:importantForAutofill="no"
android:textColor="?attr/foregroundElementColor">
android:layout_height="wrap_content"/>
</com.google.android.material.textfield.TextInputLayout>
<requestFocus/>
</EditText>
</com.frostnerd.materialedittext.MaterialEditText>
<com.frostnerd.materialedittext.MaterialEditText
<com.google.android.material.textfield.TextInputLayout
android:layout_width="match_parent"
app:labelColorPrimary="?attr/foregroundElementColor"
app:labelColorSecondary="?attr/foregroundElementColor"
android:layout_marginTop="8dp"
app:revealDelay="0"
app:revealType="revealInstant"
app:minCharLength="1"
app:labelText="@string/dialog_newserver_primaryserver"
app:hint="@string/dialog_newserver_primaryserver_hint"
app:allowCollapse="false"
app:animationDuration="0"
app:indicatorState="incorrect"
android:id="@+id/primaryServerWrap"
app:errorEnabled="true"
android:hint="@string/dialog_newserver_primaryserver"
android:textColorHint="?attr/foregroundElementColor"
android:layout_marginTop="8dp"
app:openKeyboardOnFocus="true"
android:layout_height="wrap_content">
<EditText
android:id="@+id/primaryServer"
<com.google.android.material.textfield.TextInputEditText
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:imeOptions="actionNext"
android:hint="@string/dialog_newserver_name_hint"
android:id="@+id/primaryServer"
android:inputType="text"
android:imeOptions="actionNext"
android:maxLines="1"
android:text=""
android:nextFocusDown="@id/secondaryServer"
android:importantForAutofill="no"
android:textColor="?attr/foregroundElementColor">
</EditText>
</com.frostnerd.materialedittext.MaterialEditText>
android:layout_height="wrap_content"/>
</com.google.android.material.textfield.TextInputLayout>
<com.frostnerd.materialedittext.MaterialEditText
<com.google.android.material.textfield.TextInputLayout
android:layout_width="match_parent"
app:labelColorPrimary="?attr/foregroundElementColor"
app:labelColorSecondary="?attr/foregroundElementColor"
app:revealDelay="0"
android:layout_marginTop="8dp"
app:revealType="revealInstant"
app:labelText="@string/dialog_newserver_secondaryserver"
app:hint="@string/dialog_newserver_secondaryserver_hint"
android:id="@+id/secondaryServerWrap"
app:allowCollapse="false"
app:animationDuration="0"
app:errorEnabled="true"
android:hint="@string/dialog_newserver_secondaryserver"
android:textColorHint="?attr/foregroundElementColor"
android:layout_marginTop="8dp"
app:openKeyboardOnFocus="true"
android:layout_height="wrap_content">
<EditText
<com.google.android.material.textfield.TextInputEditText
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:imeOptions="actionNext"
android:nextFocusUp="@id/primaryServer"
android:id="@+id/secondaryServer"
android:inputType="text"
android:imeOptions="actionNext"
android:maxLines="1"
android:id="@+id/secondaryServer"
android:text=""
android:importantForAutofill="no"
android:textColor="?attr/foregroundElementColor">
</EditText>
</com.frostnerd.materialedittext.MaterialEditText>
android:nextFocusDown="@id/primaryServer"
android:layout_height="wrap_content"/>
</com.google.android.material.textfield.TextInputLayout>
</LinearLayout>
</ScrollView>
......@@ -11,34 +11,21 @@
android:paddingBottom="@dimen/dialog_vertical_margin"
android:layout_height="match_parent">
<com.frostnerd.materialedittext.MaterialEditText
android:id="@+id/pinInputMet"
<com.google.android.material.textfield.TextInputLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/pinInputTil"
app:errorEnabled="true"
android:layout_marginTop="10dp"
app:allowCollapse="false"
app:animationDuration="0"
app:hint="@string/dialog_pin_hint"
app:indicatorState="undefined"
app:indicatorVisibilityWhenUnused="hidden"
app:labelColorPrimary="?attr/foregroundElementColor"
app:labelColorSecondary="?attr/foregroundElementColor"
app:iconTint="?attr/foregroundElementColor"
app:labelText="@string/dialog_pin_inputlabel"
app:revealDelay="0"
app:revealType="revealInstant">
android:textColorHint="?attr/foregroundElementColor"
android:hint="@string/dialog_pin_hint"
android:layout_height="wrap_content">
<EditText
android:importantForAutofill="no"
android:id="@+id/pinInput"
<com.google.android.material.textfield.TextInputEditText
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="?attr/inputElementColor"
android:cursorVisible="true"
android:id="@+id/pinInput"
android:inputType="numberPassword"
android:textColor="?attr/foregroundElementColor"/>
</com.frostnerd.materialedittext.MaterialEditText>
android:layout_height="wrap_content"/>
</com.google.android.material.textfield.TextInputLayout>
<androidx.appcompat.widget.AppCompatImageView
android:id="@+id/fingerprintImage"
......
......@@ -124,7 +124,6 @@
<string name="dialog_newhostsource_name">Name</string>
<string name="dialog_newhostsource_url">URL</string>
<string name="dialog_newhostsource_error_name_empty">Bitte gebe einen Namen an.</string>
<string name="dialog_newhostsource_url_invalid">Bitte gebe eine valide URL an.</string>
<string name="dialog_newdnsrule_title">Neue Dns Regel</string>