Skip to content

Commit

Permalink
Merge pull request #12068 from nextcloud/bugfix/app-not-switching-to-…
Browse files Browse the repository at this point in the history
…next-fields-after-entering-pin-number

Bugfix Disable focus change via tap
  • Loading branch information
tobiasKaminsky authored Nov 6, 2023
2 parents 4b5a488 + 6a9f51b commit 28f54f3
Show file tree
Hide file tree
Showing 4 changed files with 94 additions and 66 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,6 @@
import android.text.TextWatcher;
import android.view.KeyEvent;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.Window;
import android.view.inputmethod.InputMethodManager;
import android.widget.EditText;
Expand All @@ -42,6 +41,7 @@
import com.owncloud.android.authentication.PassCodeManager;
import com.owncloud.android.databinding.PasscodelockBinding;
import com.owncloud.android.lib.common.utils.Log_OC;
import com.owncloud.android.ui.components.PassCodeEditText;
import com.owncloud.android.utils.theme.ViewThemeUtils;

import java.util.Arrays;
Expand Down Expand Up @@ -74,7 +74,7 @@ public class PassCodeActivity extends AppCompatActivity implements Injectable {
@Inject PassCodeManager passCodeManager;
@Inject ViewThemeUtils viewThemeUtils;
private PasscodelockBinding binding;
private final EditText[] passCodeEditTexts = new EditText[4];
private final PassCodeEditText[] passCodeEditTexts = new PassCodeEditText[4];
private String[] passCodeDigits = {"", "", "", ""};
private boolean confirmingPassCode;
private boolean changed = true; // to control that only one blocks jump
Expand All @@ -91,7 +91,6 @@ protected void onCreate(Bundle savedInstanceState) {
binding = PasscodelockBinding.inflate(getLayoutInflater());
setContentView(binding.getRoot());


viewThemeUtils.platform.colorTextButtons(binding.cancel);

passCodeEditTexts[0] = binding.txt0;
Expand All @@ -105,7 +104,6 @@ protected void onCreate(Bundle savedInstanceState) {

passCodeEditTexts[0].requestFocus();


Window window = getWindow();
if (window != null) {
window.setSoftInputMode(android.view.WindowManager.LayoutParams.SOFT_INPUT_STATE_VISIBLE);
Expand All @@ -125,7 +123,7 @@ protected void onCreate(Bundle savedInstanceState) {
passCodeDigits = savedInstanceState.getStringArray(PassCodeActivity.KEY_PASSCODE_DIGITS);
}
if (confirmingPassCode) {
// the app was in the passcodeconfirmation
// the app was in the passcode confirmation
requestPassCodeConfirmation();
} else {
// pass code preference has just been activated in SettingsActivity;
Expand Down Expand Up @@ -158,12 +156,7 @@ protected void onCreate(Bundle savedInstanceState) {
protected void setCancelButtonEnabled(boolean enabled) {
if (enabled) {
binding.cancel.setVisibility(View.VISIBLE);
binding.cancel.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
finish();
}
});
binding.cancel.setOnClickListener(v -> finish());
} else {
binding.cancel.setVisibility(View.INVISIBLE);
binding.cancel.setOnClickListener(null);
Expand All @@ -179,20 +172,18 @@ public PasscodelockBinding getBinding() {
* Binds the appropriate listeners to the input boxes receiving each digit of the pass code.
*/
protected void setTextListeners() {
passCodeEditTexts[0].addTextChangedListener(new PassCodeDigitTextWatcher(0, false));
passCodeEditTexts[1].addTextChangedListener(new PassCodeDigitTextWatcher(1, false));
passCodeEditTexts[2].addTextChangedListener(new PassCodeDigitTextWatcher(2, false));
passCodeEditTexts[3].addTextChangedListener(new PassCodeDigitTextWatcher(3, true));

setOnKeyListener(1);
setOnKeyListener(2);
setOnKeyListener(3);
for (int i = 0; i < passCodeEditTexts.length; i++) {
final PassCodeEditText editText = passCodeEditTexts[i];
boolean isLast = (i == 3);

passCodeEditTexts[1].setOnFocusChangeListener((v, hasFocus) -> onPassCodeEditTextFocusChange(1));

passCodeEditTexts[2].setOnFocusChangeListener((v, hasFocus) -> onPassCodeEditTextFocusChange(2));
editText.addTextChangedListener(new PassCodeDigitTextWatcher(i, isLast));
if (i > 0) {
setOnKeyListener(i);
}

passCodeEditTexts[3].setOnFocusChangeListener((v, hasFocus) -> onPassCodeEditTextFocusChange(3));
int finalIndex = i;
editText.setOnFocusChangeListener((v, hasFocus) -> onPassCodeEditTextFocusChange(finalIndex));
}
}

private void onPassCodeEditTextFocusChange(final int passCodeIndex) {
Expand Down Expand Up @@ -265,9 +256,7 @@ private void processFullPassCode() {
savePassCodeAndExit();

} else {
showErrorAndRestart(
R.string.pass_code_mismatch, R.string.pass_code_configure_your_pass_code, View.VISIBLE
);
showErrorAndRestart(R.string.pass_code_mismatch, R.string.pass_code_configure_your_pass_code, View.VISIBLE);
}
}
}
Expand All @@ -279,13 +268,11 @@ private void hideSoftKeyboard() {
(InputMethodManager) getSystemService(INPUT_METHOD_SERVICE);
inputMethodManager.hideSoftInputFromWindow(
focusedView.getWindowToken(),
0
);
0);
}
}

private void showErrorAndRestart(int errorMessage, int headerMessage,
int explanationVisibility) {
private void showErrorAndRestart(int errorMessage, int headerMessage, int explanationVisibility) {
Arrays.fill(passCodeDigits, null);
Snackbar.make(findViewById(android.R.id.content), getString(errorMessage), Snackbar.LENGTH_LONG).show();
binding.header.setText(headerMessage); // TODO check if really needed
Expand All @@ -312,8 +299,6 @@ protected void requestPassCodeConfirmation() {
* @return 'True' if entered pass code equals to the saved one.
*/
protected boolean checkPassCode() {


String[] savedPassCodeDigits = preferences.getPassCode();

boolean result = true;
Expand All @@ -331,11 +316,13 @@ protected boolean checkPassCode() {
protected boolean confirmPassCode() {
confirmingPassCode = false;

boolean result = true;
for (int i = 0; i < passCodeEditTexts.length && result; i++) {
result = passCodeEditTexts[i].getText().toString().equals(passCodeDigits[i]);
for (int i = 0; i < passCodeEditTexts.length; i++) {
Editable passCodeText = passCodeEditTexts[i].getText();
if (passCodeText == null || !passCodeText.toString().equals(passCodeDigits[i])) {
return false;
}
}
return result;
return true;
}

/**
Expand Down Expand Up @@ -401,7 +388,7 @@ private void showDelay() {
@Override
public void run() {
try {
Thread.sleep(delay * 1000);
Thread.sleep(delay * 1000L);

runOnUiThread(() -> {
binding.explanation.setVisibility(View.INVISIBLE);
Expand All @@ -418,7 +405,6 @@ public void run() {
}
}


@Override
public void onSaveInstanceState(@NonNull Bundle outState) {
super.onSaveInstanceState(outState);
Expand All @@ -440,6 +426,7 @@ private class PassCodeDigitTextWatcher implements TextWatcher {
PassCodeDigitTextWatcher(int index, boolean lastOne) {
mIndex = index;
mLastOne = lastOne;

if (mIndex < 0) {
throw new IllegalArgumentException(
"Invalid index in " + PassCodeDigitTextWatcher.class.getSimpleName() +
Expand All @@ -463,12 +450,17 @@ private int next() {
public void afterTextChanged(Editable s) {
if (s.length() > 0) {
if (!confirmingPassCode) {
passCodeDigits[mIndex] = passCodeEditTexts[mIndex].getText().toString();
Editable passCodeText = passCodeEditTexts[mIndex].getText();

if (passCodeText != null) {
passCodeDigits[mIndex] = passCodeText.toString();
}
}
passCodeEditTexts[next()].requestFocus();

if (mLastOne) {
processFullPassCode();
} else {
passCodeEditTexts[next()].requestFocus();
}

} else {
Expand All @@ -477,13 +469,10 @@ public void afterTextChanged(Editable s) {
}

@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
// nothing to do
}
public void beforeTextChanged(CharSequence s, int start, int count, int after) {}

@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
// nothing to do
}
public void onTextChanged(CharSequence s, int start, int before, int count) {}
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
/*
* Nextcloud Android client application
*
* @author Alper Ozturk
* Copyright (C) 2023 Alper Ozturk
* Copyright (C) 2023 Nextcloud GmbH
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero 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 Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package com.owncloud.android.ui.components

import android.annotation.SuppressLint
import android.content.Context
import android.util.AttributeSet
import android.view.KeyEvent
import android.view.MotionEvent
import android.view.View
import androidx.appcompat.widget.AppCompatEditText

@SuppressLint("ClickableViewAccessibility")
class PassCodeEditText(context: Context, attrs: AttributeSet?) : AppCompatEditText(context, attrs) {

init {
disableFocusChangeViaTap()
}

private fun disableFocusChangeViaTap() {
setSelectAllOnFocus(false)
setTextIsSelectable(false)
setOnTouchListener { _: View?, _: MotionEvent? -> true }
}

override fun onKeyPreIme(keyCode: Int, event: KeyEvent): Boolean {
val isBackButtonPressed = (event.keyCode == KeyEvent.KEYCODE_BACK && event.action == KeyEvent.ACTION_UP)
if (isBackButtonPressed) {
// Override default behaviour and prevent dismissing the keyboard
return true
}
return super.dispatchKeyEvent(event)
}
}
25 changes: 5 additions & 20 deletions app/src/main/res/layout/passcodelock.xml
Original file line number Diff line number Diff line change
Expand Up @@ -69,41 +69,26 @@
android:layout_height="wrap_content"
android:gravity="center_horizontal">

<com.google.android.material.textfield.TextInputEditText
<com.owncloud.android.ui.components.PassCodeEditText
android:id="@+id/txt0"
style="@style/PassCodeStyle"
android:cursorVisible="false"
android:focusable="true"
android:hint="@string/hidden_character"
android:imeOptions="flagNoExtractUi"
android:importantForAutofill="no"
tools:text="123">
</com.owncloud.android.ui.components.PassCodeEditText>

<requestFocus />
</com.google.android.material.textfield.TextInputEditText>

<com.google.android.material.textfield.TextInputEditText
<com.owncloud.android.ui.components.PassCodeEditText
android:id="@+id/txt1"
style="@style/PassCodeStyle"
android:cursorVisible="false"
android:hint="@string/hidden_character"
android:imeOptions="flagNoExtractUi"
android:importantForAutofill="no" />

<com.google.android.material.textfield.TextInputEditText
<com.owncloud.android.ui.components.PassCodeEditText
android:id="@+id/txt2"
style="@style/PassCodeStyle"
android:cursorVisible="false"
android:hint="@string/hidden_character"
android:imeOptions="flagNoExtractUi"
android:importantForAutofill="no" />

<com.google.android.material.textfield.TextInputEditText
<com.owncloud.android.ui.components.PassCodeEditText
android:id="@+id/txt3"
style="@style/PassCodeStyle"
android:cursorVisible="false"
android:hint="@string/hidden_character"
android:imeOptions="flagNoExtractUi"
android:importantForAutofill="no" />
</LinearLayout>

Expand Down
2 changes: 2 additions & 0 deletions app/src/main/res/values/styles.xml
Original file line number Diff line number Diff line change
Expand Up @@ -324,9 +324,11 @@
</style>

<style name="PassCodeStyle">
<item name="android:hint">@string/hidden_character</item>
<item name="android:layout_width">50dp</item>
<item name="android:layout_height">50dp</item>
<item name="android:gravity">center</item>
<item name="android:cursorVisible">false</item>
<item name="android:layout_margin">10dp</item>
<item name="android:inputType">numberDecimal</item>
<item name="android:numeric">decimal</item>
Expand Down

0 comments on commit 28f54f3

Please sign in to comment.