Эх сурвалжийг харах

Convert java to kotlin

Signed-off-by: alperozturk <alper_ozturk@proton.me>
alperozturk 1 жил өмнө
parent
commit
4a9b49c1fc

+ 272 - 314
app/src/main/java/com/owncloud/android/ui/activity/PassCodeActivity.kt

@@ -21,319 +21,281 @@
  *   along with this program.  If not, see <http://www.gnu.org/licenses/>.
  *
  */
-package com.owncloud.android.ui.activity;
-
-import android.annotation.SuppressLint;
-import android.content.Intent;
-import android.os.Bundle;
-import android.text.Editable;
-import android.text.TextUtils;
-import android.text.TextWatcher;
-import android.view.KeyEvent;
-import android.view.View;
-import android.view.Window;
-import android.view.inputmethod.InputMethodManager;
-import android.widget.EditText;
-
-import com.google.android.material.snackbar.Snackbar;
-import com.nextcloud.client.di.Injectable;
-import com.nextcloud.client.preferences.AppPreferences;
-import com.owncloud.android.R;
-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;
-
-import javax.inject.Inject;
-
-import androidx.annotation.NonNull;
-import androidx.annotation.VisibleForTesting;
-import androidx.appcompat.app.AppCompatActivity;
-
-public class PassCodeActivity extends AppCompatActivity implements Injectable {
-
-    private static final String TAG = PassCodeActivity.class.getSimpleName();
-    private static final String KEY_PASSCODE_DIGITS = "PASSCODE_DIGITS";
-    private static final String KEY_CONFIRMING_PASSCODE = "CONFIRMING_PASSCODE";
-
-    public final static String ACTION_REQUEST_WITH_RESULT = "ACTION_REQUEST_WITH_RESULT";
-    public final static String ACTION_CHECK_WITH_RESULT = "ACTION_CHECK_WITH_RESULT";
-    public final static String ACTION_CHECK = "ACTION_CHECK";
-    public final static String KEY_PASSCODE = "KEY_PASSCODE";
-    public final static String KEY_CHECK_RESULT = "KEY_CHECK_RESULT";
-
-    public final static String PREFERENCE_PASSCODE_D = "PrefPinCode";
-    public final static String PREFERENCE_PASSCODE_D1 = "PrefPinCode1";
-    public final static String PREFERENCE_PASSCODE_D2 = "PrefPinCode2";
-    public final static String PREFERENCE_PASSCODE_D3 = "PrefPinCode3";
-    public final static String PREFERENCE_PASSCODE_D4 = "PrefPinCode4";
-
-    @Inject AppPreferences preferences;
-    @Inject PassCodeManager passCodeManager;
-    @Inject ViewThemeUtils viewThemeUtils;
-    private PasscodelockBinding binding;
-    private final PassCodeEditText[] passCodeEditTexts = new PassCodeEditText[4];
-    private String[] passCodeDigits = {"", "", "", ""};
-    private boolean confirmingPassCode;
-    private boolean changed = true; // to control that only one blocks jump
+package com.owncloud.android.ui.activity
+
+import android.content.Intent
+import android.os.Bundle
+import android.text.Editable
+import android.text.TextUtils
+import android.text.TextWatcher
+import android.view.KeyEvent
+import android.view.View
+import android.view.WindowManager
+import android.view.inputmethod.InputMethodManager
+import androidx.annotation.VisibleForTesting
+import androidx.appcompat.app.AppCompatActivity
+import com.google.android.material.snackbar.Snackbar
+import com.nextcloud.client.di.Injectable
+import com.nextcloud.client.preferences.AppPreferences
+import com.owncloud.android.R
+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
+import javax.inject.Inject
+
+class PassCodeActivity : AppCompatActivity(), Injectable {
+    @JvmField
+    @Inject
+    var preferences: AppPreferences? = null
+
+    @JvmField
+    @Inject
+    var passCodeManager: PassCodeManager? = null
+
+    @JvmField
+    @Inject
+    var viewThemeUtils: ViewThemeUtils? = null
+
+    @get:VisibleForTesting
+    lateinit var binding: PasscodelockBinding
+        private set
+
+    private val passCodeEditTexts = arrayOfNulls<PassCodeEditText>(4)
+    private var passCodeDigits: Array<String?>? = arrayOf("", "", "", "")
+    private var confirmingPassCode = false
+    private var changed = true // to control that only one blocks jump
 
     /**
      * Initializes the activity.
-     * <p>
-     * An intent with a valid ACTION is expected; if none is found, an {@link IllegalArgumentException} will be thrown.
+     *
+     *
+     * An intent with a valid ACTION is expected; if none is found, an [IllegalArgumentException] will be thrown.
      *
      * @param savedInstanceState Previously saved state - irrelevant in this case
      */
-    protected void onCreate(Bundle savedInstanceState) {
-        super.onCreate(savedInstanceState);
-        binding = PasscodelockBinding.inflate(getLayoutInflater());
-        setContentView(binding.getRoot());
-
-        viewThemeUtils.platform.colorTextButtons(binding.cancel);
-
-        passCodeEditTexts[0] = binding.txt0;
-        passCodeEditTexts[1] = binding.txt1;
-        passCodeEditTexts[2] = binding.txt2;
-        passCodeEditTexts[3] = binding.txt3;
+    override fun onCreate(savedInstanceState: Bundle?) {
+        super.onCreate(savedInstanceState)
+        binding = PasscodelockBinding.inflate(layoutInflater)
+        setContentView(binding.root)
 
-        for (EditText passCodeEditText : passCodeEditTexts) {
-            viewThemeUtils.platform.colorEditText(passCodeEditText);
-        }
+        viewThemeUtils?.platform?.colorTextButtons(binding.cancel)
 
-        passCodeEditTexts[0].requestFocus();
+        setupPasscodeEditTexts()
+        setSoftInputMode()
+        setupUI(savedInstanceState)
+        setTextListeners()
+    }
 
-        Window window = getWindow();
-        if (window != null) {
-            window.setSoftInputMode(android.view.WindowManager.LayoutParams.SOFT_INPUT_STATE_VISIBLE);
-        }
+    private fun setSoftInputMode() {
+        window?.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_VISIBLE)
+    }
 
-        if (ACTION_CHECK.equals(getIntent().getAction())) {
+    private fun setupUI(savedInstanceState: Bundle?) {
+        if (ACTION_CHECK == intent.action) {
             /// this is a pass code request; the user has to input the right value
-            binding.header.setText(R.string.pass_code_enter_pass_code);
-            binding.explanation.setVisibility(View.INVISIBLE);
-            setCancelButtonEnabled(false);      // no option to cancel
-
-            showDelay();
-
-        } else if (ACTION_REQUEST_WITH_RESULT.equals(getIntent().getAction())) {
+            binding.header.setText(R.string.pass_code_enter_pass_code)
+            binding.explanation.visibility = View.INVISIBLE
+            setCancelButtonEnabled(false) // no option to cancel
+            showDelay()
+        } else if (ACTION_REQUEST_WITH_RESULT == intent.action) {
             if (savedInstanceState != null) {
-                confirmingPassCode = savedInstanceState.getBoolean(PassCodeActivity.KEY_CONFIRMING_PASSCODE);
-                passCodeDigits = savedInstanceState.getStringArray(PassCodeActivity.KEY_PASSCODE_DIGITS);
+                confirmingPassCode = savedInstanceState.getBoolean(KEY_CONFIRMING_PASSCODE)
+                passCodeDigits = savedInstanceState.getStringArray(KEY_PASSCODE_DIGITS)
             }
             if (confirmingPassCode) {
                 // the app was in the passcode confirmation
-                requestPassCodeConfirmation();
+                requestPassCodeConfirmation()
             } else {
                 // pass code preference has just been activated in SettingsActivity;
                 // will receive and confirm pass code value
-                binding.header.setText(R.string.pass_code_configure_your_pass_code);
-
-                binding.explanation.setVisibility(View.VISIBLE);
+                binding.header.setText(R.string.pass_code_configure_your_pass_code)
+                binding.explanation.visibility = View.VISIBLE
             }
-            setCancelButtonEnabled(true);
-
-        } else if (ACTION_CHECK_WITH_RESULT.equals(getIntent().getAction())) {
+            setCancelButtonEnabled(true)
+        } else if (ACTION_CHECK_WITH_RESULT == intent.action) {
             // pass code preference has just been disabled in SettingsActivity;
             // will confirm user knows pass code, then remove it
-            binding.header.setText(R.string.pass_code_remove_your_pass_code);
-            binding.explanation.setVisibility(View.INVISIBLE);
-            setCancelButtonEnabled(true);
-
+            binding.header.setText(R.string.pass_code_remove_your_pass_code)
+            binding.explanation.visibility = View.INVISIBLE
+            setCancelButtonEnabled(true)
         } else {
-            throw new IllegalArgumentException("A valid ACTION is needed in the Intent passed to " + TAG);
+            throw IllegalArgumentException("A valid ACTION is needed in the Intent passed to $TAG")
         }
-
-        setTextListeners();
     }
 
-    /**
-     * Enables or disables the cancel button to allow the user interrupt the ACTION requested to the activity.
-     *
-     * @param enabled 'True' makes the cancel button available, 'false' hides it.
-     */
-    protected void setCancelButtonEnabled(boolean enabled) {
-        if (enabled) {
-            binding.cancel.setVisibility(View.VISIBLE);
-            binding.cancel.setOnClickListener(v -> finish());
-        } else {
-            binding.cancel.setVisibility(View.INVISIBLE);
-            binding.cancel.setOnClickListener(null);
+    private fun setupPasscodeEditTexts() {
+        passCodeEditTexts[0] = binding.txt0
+        passCodeEditTexts[1] = binding.txt1
+        passCodeEditTexts[2] = binding.txt2
+        passCodeEditTexts[3] = binding.txt3
+
+        for (passCodeEditText in passCodeEditTexts) {
+            viewThemeUtils?.platform?.colorEditText(passCodeEditText!!)
         }
+
+        passCodeEditTexts[0]?.requestFocus()
     }
 
-    @VisibleForTesting
-    public PasscodelockBinding getBinding() {
-        return binding;
+    private fun setCancelButtonEnabled(enabled: Boolean) {
+        binding.cancel.visibility = if (enabled) { View.VISIBLE } else { View.INVISIBLE }
+        binding.cancel.setOnClickListener {
+            if (enabled) {
+                finish()
+            }
+        }
     }
 
-    /**
-     * Binds the appropriate listeners to the input boxes receiving each digit of the pass code.
-     */
-    protected void setTextListeners() {
-        for (int i = 0; i < passCodeEditTexts.length; i++) {
-            final PassCodeEditText editText = passCodeEditTexts[i];
-            boolean isLast = (i == 3);
+    private fun setTextListeners() {
+        for (i in passCodeEditTexts.indices) {
+            val editText = passCodeEditTexts[i]
+            val isLast = (i == 3)
+
+            editText?.addTextChangedListener(PassCodeDigitTextWatcher(i, isLast))
 
-            editText.addTextChangedListener(new PassCodeDigitTextWatcher(i, isLast));
             if (i > 0) {
-                setOnKeyListener(i);
+                setOnKeyListener(i)
             }
 
-            int finalIndex = i;
-            editText.setOnFocusChangeListener((v, hasFocus) -> onPassCodeEditTextFocusChange(finalIndex));
+            editText?.onFocusChangeListener = View.OnFocusChangeListener { _: View?, _: Boolean ->
+                onPassCodeEditTextFocusChange(i)
+            }
         }
     }
 
-    private void onPassCodeEditTextFocusChange(final int passCodeIndex) {
-        for (int i = 0; i < passCodeIndex; i++) {
-            if (TextUtils.isEmpty(passCodeEditTexts[i].getText())) {
-                passCodeEditTexts[i].requestFocus();
-                break;
+    private fun onPassCodeEditTextFocusChange(passCodeIndex: Int) {
+        for (i in 0 until passCodeIndex) {
+            if (TextUtils.isEmpty(passCodeEditTexts[i]?.text)) {
+                passCodeEditTexts[i]?.requestFocus()
+                break
             }
         }
     }
 
-    private void setOnKeyListener(final int passCodeIndex) {
-        passCodeEditTexts[passCodeIndex].setOnKeyListener((v, keyCode, event) -> {
+    private fun setOnKeyListener(passCodeIndex: Int) {
+        passCodeEditTexts[passCodeIndex]?.setOnKeyListener { _: View?, keyCode: Int, _: KeyEvent? ->
             if (keyCode == KeyEvent.KEYCODE_DEL && changed) {
-                passCodeEditTexts[passCodeIndex - 1].requestFocus();
+                passCodeEditTexts[passCodeIndex - 1]?.requestFocus()
+
                 if (!confirmingPassCode) {
-                    passCodeDigits[passCodeIndex - 1] = "";
+                    passCodeDigits?.set(passCodeIndex - 1, "")
                 }
-                passCodeEditTexts[passCodeIndex - 1].setText("");
-                changed = false;
 
+                passCodeEditTexts[passCodeIndex - 1]?.setText("")
+
+                changed = false
             } else if (!changed) {
-                changed = true;
+                changed = true
             }
-            return false;
-        });
+            false
+        }
     }
 
     /**
      * Processes the pass code entered by the user just after the last digit was in.
-     * <p>
+     *
+     *
      * Takes into account the action requested to the activity, the currently saved pass code and the previously typed
      * pass code, if any.
      */
-    private void processFullPassCode() {
-        if (ACTION_CHECK.equals(getIntent().getAction())) {
+    private fun processFullPassCode() {
+        if (ACTION_CHECK == intent.action) {
             if (checkPassCode()) {
-                preferences.resetPinWrongAttempts();
+                preferences?.resetPinWrongAttempts()
 
                 /// pass code accepted in request, user is allowed to access the app
-                passCodeManager.updateLockTimestamp();
-                hideSoftKeyboard();
-                finish();
-
+                passCodeManager?.updateLockTimestamp()
+                hideSoftKeyboard()
+                finish()
             } else {
-                preferences.increasePinWrongAttempts();
-
-                showErrorAndRestart(R.string.pass_code_wrong, R.string.pass_code_enter_pass_code, View.INVISIBLE);
+                preferences?.increasePinWrongAttempts()
+                showErrorAndRestart(R.string.pass_code_wrong, R.string.pass_code_enter_pass_code, View.INVISIBLE)
             }
-
-        } else if (ACTION_CHECK_WITH_RESULT.equals(getIntent().getAction())) {
+        } else if (ACTION_CHECK_WITH_RESULT == intent.action) {
             if (checkPassCode()) {
-                passCodeManager.updateLockTimestamp();
-                Intent resultIntent = new Intent();
-                resultIntent.putExtra(KEY_CHECK_RESULT, true);
-                setResult(RESULT_OK, resultIntent);
-                hideSoftKeyboard();
-                finish();
+                passCodeManager?.updateLockTimestamp()
+
+                val resultIntent = Intent()
+                resultIntent.putExtra(KEY_CHECK_RESULT, true)
+                setResult(RESULT_OK, resultIntent)
+                hideSoftKeyboard()
+                finish()
             } else {
-                showErrorAndRestart(R.string.pass_code_wrong, R.string.pass_code_enter_pass_code, View.INVISIBLE);
+                showErrorAndRestart(R.string.pass_code_wrong, R.string.pass_code_enter_pass_code, View.INVISIBLE)
             }
-
-        } else if (ACTION_REQUEST_WITH_RESULT.equals(getIntent().getAction())) {
+        } else if (ACTION_REQUEST_WITH_RESULT == intent.action) {
             /// enabling pass code
             if (!confirmingPassCode) {
-                requestPassCodeConfirmation();
-
+                requestPassCodeConfirmation()
             } else if (confirmPassCode()) {
                 /// confirmed: user typed the same pass code twice
-                savePassCodeAndExit();
-
+                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)
             }
         }
     }
 
-    private void hideSoftKeyboard() {
-        View focusedView = getCurrentFocus();
+    private fun hideSoftKeyboard() {
+        val focusedView = currentFocus
         if (focusedView != null) {
-            InputMethodManager inputMethodManager =
-                (InputMethodManager) getSystemService(INPUT_METHOD_SERVICE);
+            val inputMethodManager = getSystemService(INPUT_METHOD_SERVICE) as InputMethodManager
             inputMethodManager.hideSoftInputFromWindow(
-                focusedView.getWindowToken(),
-                0);
+                focusedView.windowToken,
+                0
+            )
         }
     }
 
-    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
-        binding.explanation.setVisibility(explanationVisibility); // TODO check if really needed
-        clearBoxes();
+    private fun showErrorAndRestart(errorMessage: Int, headerMessage: Int, explanationVisibility: Int) {
+        passCodeDigits?.let { Arrays.fill(it, null) }
 
-        showDelay();
+        Snackbar.make(findViewById(android.R.id.content), getString(errorMessage), Snackbar.LENGTH_LONG).show()
+        binding.header.setText(headerMessage) // TODO check if really needed
+        binding.explanation.visibility = explanationVisibility // TODO check if really needed
+        clearBoxes()
+        showDelay()
     }
 
-
     /**
      * Ask to the user for retyping the pass code just entered before saving it as the current pass code.
      */
-    protected void requestPassCodeConfirmation() {
-        clearBoxes();
-        binding.header.setText(R.string.pass_code_reenter_your_pass_code);
-        binding.explanation.setVisibility(View.INVISIBLE);
-        confirmingPassCode = true;
+    private fun requestPassCodeConfirmation() {
+        clearBoxes()
+        binding.header.setText(R.string.pass_code_reenter_your_pass_code)
+        binding.explanation.visibility = View.INVISIBLE
+        confirmingPassCode = true
     }
 
-    /**
-     * Compares pass code entered by the user with the value currently saved in the app.
-     *
-     * @return 'True' if entered pass code equals to the saved one.
-     */
-    protected boolean checkPassCode() {
-        String[] savedPassCodeDigits = preferences.getPassCode();
-
-        boolean result = true;
-        for (int i = 0; i < passCodeDigits.length && result; i++) {
-            result = passCodeDigits[i] != null && passCodeDigits[i].equals(savedPassCodeDigits[i]);
+    private fun checkPassCode(): Boolean {
+        val savedPassCodeDigits = preferences!!.passCode
+        var result = true
+        var i = 0
+        while (i < passCodeDigits!!.size && result) {
+            result = passCodeDigits!![i] != null && passCodeDigits!![i] == savedPassCodeDigits[i]
+            i++
         }
-        return result;
+        return result
     }
 
-    /**
-     * Compares pass code retyped by the user in the input fields with the value entered just before.
-     *
-     * @return 'True' if retyped pass code equals to the entered before.
-     */
-    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]);
+    private fun confirmPassCode(): Boolean {
+        confirmingPassCode = false
+        var result = true
+        var i = 0
+        while (i < passCodeEditTexts.size && result) {
+            result = passCodeEditTexts[i]?.text.toString() == passCodeDigits!![i]
+            i++
         }
-        return result;
+        return result
     }
 
-    /**
-     * Sets the input fields to empty strings and puts the focus on the first one.
-     */
-    protected void clearBoxes() {
-        for (EditText mPassCodeEditText : passCodeEditTexts) {
-            mPassCodeEditText.setText("");
+    private fun clearBoxes() {
+        for (mPassCodeEditText in passCodeEditTexts) {
+            mPassCodeEditText?.setText("")
         }
-        passCodeEditTexts[0].requestFocus();
+        passCodeEditTexts[0]?.requestFocus()
     }
 
     /**
@@ -344,100 +306,86 @@ public class PassCodeActivity extends AppCompatActivity implements Injectable {
      * @param event   Event triggered.
      * @return 'True' when the key event was processed by this method.
      */
-    @Override
-    public boolean onKeyDown(int keyCode, KeyEvent event) {
-        if (keyCode == KeyEvent.KEYCODE_BACK && event.getRepeatCount() == 0) {
-            if (ACTION_CHECK.equals(getIntent().getAction())) {
-                moveTaskToBack(true);
-                finishAndRemoveTask();
-            } else if (ACTION_REQUEST_WITH_RESULT.equals(getIntent().getAction()) ||
-                ACTION_CHECK_WITH_RESULT.equals(getIntent().getAction())) {
-                finish();
-            }// else, do nothing, but report that the key was consumed to stay alive
-            return true;
+    override fun onKeyDown(keyCode: Int, event: KeyEvent): Boolean {
+        if (keyCode == KeyEvent.KEYCODE_BACK && event.repeatCount == 0) {
+            if (ACTION_CHECK == intent.action) {
+                moveTaskToBack(true)
+                finishAndRemoveTask()
+            } else if (ACTION_REQUEST_WITH_RESULT == intent.action || ACTION_CHECK_WITH_RESULT == intent.action) {
+                finish()
+            } // else, do nothing, but report that the key was consumed to stay alive
+            return true
         }
-        return super.onKeyDown(keyCode, event);
+        return super.onKeyDown(keyCode, event)
     }
 
-    /**
-     * Saves the pass code input by the user as the current pass code.
-     */
-    protected void savePassCodeAndExit() {
-        Intent resultIntent = new Intent();
-        resultIntent.putExtra(KEY_PASSCODE,
-                              passCodeDigits[0] + passCodeDigits[1] + passCodeDigits[2] + passCodeDigits[3]);
-
-        setResult(RESULT_OK, resultIntent);
+    private fun savePassCodeAndExit() {
+        val resultIntent = Intent()
+        resultIntent.putExtra(
+            KEY_PASSCODE,
+            passCodeDigits!![0] + passCodeDigits!![1] + passCodeDigits!![2] + passCodeDigits!![3]
+        )
+        setResult(RESULT_OK, resultIntent)
+        passCodeManager?.updateLockTimestamp()
+        finish()
+    }
 
-        passCodeManager.updateLockTimestamp();
+    private fun showDelay() {
+        val delay = preferences?.pinBruteForceDelay() ?: 0
 
-        finish();
-    }
+        if (delay <= 0) {
+            return
+        }
 
-    private void showDelay() {
-        int delay = preferences.pinBruteForceDelay();
-
-        if (delay > 0) {
-            binding.explanation.setText(R.string.brute_force_delay);
-            binding.explanation.setVisibility(View.VISIBLE);
-            binding.txt0.setEnabled(false);
-            binding.txt1.setEnabled(false);
-            binding.txt2.setEnabled(false);
-            binding.txt3.setEnabled(false);
-
-            new Thread(new Runnable() {
-                @Override
-                public void run() {
-                    try {
-                        Thread.sleep(delay * 1000L);
-
-                        runOnUiThread(() -> {
-                            binding.explanation.setVisibility(View.INVISIBLE);
-                            binding.txt0.setEnabled(true);
-                            binding.txt1.setEnabled(true);
-                            binding.txt2.setEnabled(true);
-                            binding.txt3.setEnabled(true);
-                        });
-                    } catch (InterruptedException e) {
-                        Log_OC.e(this, "Could not delay password input prompt");
+        binding.explanation.setText(R.string.brute_force_delay)
+        binding.explanation.visibility = View.VISIBLE
+        binding.txt0.isEnabled = false
+        binding.txt1.isEnabled = false
+        binding.txt2.isEnabled = false
+        binding.txt3.isEnabled = false
+
+        Thread(object : Runnable {
+            override fun run() {
+                try {
+                    Thread.sleep(delay * 1000L)
+
+                    runOnUiThread {
+                        binding.explanation.visibility = View.INVISIBLE
+                        binding.txt0.isEnabled = true
+                        binding.txt1.isEnabled = true
+                        binding.txt2.isEnabled = true
+                        binding.txt3.isEnabled = true
                     }
+                } catch (e: InterruptedException) {
+                    Log_OC.e(this, "Could not delay password input prompt")
                 }
-            }).start();
-        }
+            }
+
+        }).start()
     }
 
-    @Override
-    public void onSaveInstanceState(@NonNull Bundle outState) {
-        super.onSaveInstanceState(outState);
-        outState.putBoolean(PassCodeActivity.KEY_CONFIRMING_PASSCODE, confirmingPassCode);
-        outState.putStringArray(PassCodeActivity.KEY_PASSCODE_DIGITS, passCodeDigits);
+    public override fun onSaveInstanceState(outState: Bundle) {
+        super.onSaveInstanceState(outState)
+        outState.putBoolean(KEY_CONFIRMING_PASSCODE, confirmingPassCode)
+        outState.putStringArray(KEY_PASSCODE_DIGITS, passCodeDigits)
     }
 
-    private class PassCodeDigitTextWatcher implements TextWatcher {
+    private inner class PassCodeDigitTextWatcher(index: Int, lastOne: Boolean) : TextWatcher {
+        private var mIndex = -1
+        private val mLastOne: Boolean
 
-        private int mIndex = -1;
-        private boolean mLastOne;
+        init {
+            mIndex = index
+            mLastOne = lastOne
 
-        /**
-         * Constructor
-         *
-         * @param index   Position in the pass code of the input field that will be bound to this watcher.
-         * @param lastOne 'True' means that watcher corresponds to the last position of the pass code.
-         */
-        PassCodeDigitTextWatcher(int index, boolean lastOne) {
-            mIndex = index;
-            mLastOne = lastOne;
-
-            if (mIndex < 0) {
-                throw new IllegalArgumentException(
-                    "Invalid index in " + PassCodeDigitTextWatcher.class.getSimpleName() +
-                        " constructor"
-                );
+            require(mIndex >= 0) {
+                "Invalid index in " + PassCodeDigitTextWatcher::class.java.simpleName +
+                    " constructor"
             }
         }
 
-        private int next() {
-            return mLastOne ? 0 : mIndex + 1;
+        private operator fun next(): Int {
+            return if (mLastOne) 0 else mIndex + 1
         }
 
         /**
@@ -447,33 +395,43 @@ public class PassCodeActivity extends AppCompatActivity implements Injectable {
          *
          * @param s Changed text
          */
-        @Override
-        public void afterTextChanged(Editable s) {
-            if (s.length() > 0) {
+        override fun afterTextChanged(s: Editable) {
+            if (s.isNotEmpty()) {
                 if (!confirmingPassCode) {
-                    Editable passCodeText = passCodeEditTexts[mIndex].getText();
+                    val passCodeText = passCodeEditTexts[mIndex]?.text
 
                     if (passCodeText != null) {
-                        passCodeDigits[mIndex] = passCodeText.toString();
+                        passCodeDigits!![mIndex] = passCodeText.toString()
                     }
                 }
 
                 if (mLastOne) {
-                    processFullPassCode();
+                    processFullPassCode()
                 } else {
-                    passCodeEditTexts[next()].requestFocus();
+                    passCodeEditTexts[next()]?.requestFocus()
                 }
-
             } else {
-                Log_OC.d(TAG, "Text box " + mIndex + " was cleaned");
+                Log_OC.d(TAG, "Text box $mIndex was cleaned")
             }
         }
 
-        @Override
-        public void beforeTextChanged(CharSequence s, int start, int count, int after) {}
-
-        @Override
-        public void onTextChanged(CharSequence s, int start, int before, int count) {}
+        override fun beforeTextChanged(s: CharSequence, start: Int, count: Int, after: Int) {}
+        override fun onTextChanged(s: CharSequence, start: Int, before: Int, count: Int) {}
     }
 
-}
+    companion object {
+        private val TAG = PassCodeActivity::class.java.simpleName
+        private const val KEY_PASSCODE_DIGITS = "PASSCODE_DIGITS"
+        private const val KEY_CONFIRMING_PASSCODE = "CONFIRMING_PASSCODE"
+        const val ACTION_REQUEST_WITH_RESULT = "ACTION_REQUEST_WITH_RESULT"
+        const val ACTION_CHECK_WITH_RESULT = "ACTION_CHECK_WITH_RESULT"
+        const val ACTION_CHECK = "ACTION_CHECK"
+        const val KEY_PASSCODE = "KEY_PASSCODE"
+        const val KEY_CHECK_RESULT = "KEY_CHECK_RESULT"
+        const val PREFERENCE_PASSCODE_D = "PrefPinCode"
+        const val PREFERENCE_PASSCODE_D1 = "PrefPinCode1"
+        const val PREFERENCE_PASSCODE_D2 = "PrefPinCode2"
+        const val PREFERENCE_PASSCODE_D3 = "PrefPinCode3"
+        const val PREFERENCE_PASSCODE_D4 = "PrefPinCode4"
+    }
+}