package com.tresorit.zerokit;
import android.content.Context;
import android.os.Parcelable;
import android.support.v4.util.LongSparseArray;
import android.support.v7.widget.AppCompatEditText;
import android.text.Editable;
import android.text.InputType;
import android.text.TextWatcher;
import android.util.AttributeSet;
import java.util.Arrays;
public final class PasswordEditText extends AppCompatEditText {
private final LongSparseArray<Editable> editablePool = new LongSparseArray<>();
OnChangeListener onChangeListener;
public PasswordEditText(Context context) {
super(context);
init();
}
public PasswordEditText(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
public PasswordEditText(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init();
}
private void init() {
super.setInputType(InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_PASSWORD);
super.setText("");
super.addTextChangedListener(new TextWatcher() {
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
if (onChangeListener != null)
onChangeListener.onChanged();
}
@Override
public void afterTextChanged(Editable s) {
}
});
}
public final void setPasswordExporter(PasswordExporter passwordExporter) {
passwordExporter.setEditText(this);
}
public final void setOnChangeListener(OnChangeListener onChangeListener) {
this.onChangeListener = onChangeListener;
}
public final PasswordExporter getPasswordExporter() {
return new PasswordExporter(this);
}
@Override
public final Editable getText() {
if (editablePool == null) return super.getText();
int length = super.getText().length();
@SuppressWarnings("ConstantConditions")
Editable result = editablePool == null ? super.getText() : editablePool.get(length);
if (result == null) {
char[] chars = new char[length];
Arrays.fill(chars, '*');
result = Editable.Factory.getInstance().newEditable(new String(chars));
editablePool.put(length, result);
}
return result;
}
@Override
public final void setText(CharSequence text, BufferType type) {
super.setText("", type);
}
@Override
public final void setInputType(int type) {
}
@Override
public final Parcelable onSaveInstanceState() {
clear();
return super.onSaveInstanceState();
}
@Override
public final void addTextChangedListener(TextWatcher watcher) {
}
//**********************************
public final void clear() {
super.getText().clear();
}
@Override
public final int length() {
return super.getText().length();
}
public final boolean isEmpty() {
return length() <= 0;
}
public final boolean isContentEqual(PasswordEditText passwordEditText) {
char[] charArray1 = getCharArray(false);
char[] charArray2 = passwordEditText.getCharArray(false);
boolean result = Arrays.equals(charArray1, charArray2);
Arrays.fill(charArray1, '\u0000');
Arrays.fill(charArray2, '\u0000');
return result;
}
public final boolean isContentEqual(PasswordExporter exporter) {
return isContentEqual(exporter.editText);
}
final char[] getCharArray(boolean clear) {
Editable editable = super.getText();
char[] chars = new char[editable.length()];
editable.getChars(0, chars.length, chars, 0);
if (clear) editable.clear();
return chars;
}
public static final class PasswordExporter {
PasswordEditText editText;
OnChangeListener onChangeListener;
public PasswordExporter() {
}
PasswordExporter(PasswordEditText editText) {
this.editText = editText;
}
public final int length() {
return editText.length();
}
public final boolean isEmpty() {
return editText.isEmpty();
}
public void clear() {
editText.clear();
}
public final boolean isContentEqual(PasswordExporter passwordExporter) {
return editText.isContentEqual(passwordExporter);
}
public final boolean isContentEqual(PasswordEditText editText) {
return editText.isContentEqual(editText);
}
public final void setOnChangeListener(OnChangeListener changeListener){
this.onChangeListener = changeListener;
if (editText != null) editText.setOnChangeListener(changeListener);
}
final void setEditText(PasswordEditText editText) {
this.editText = editText;
setOnChangeListener(onChangeListener);
}
final char[] getCharArray(boolean clear) {
return editText.getCharArray(clear);
}
}
public interface OnChangeListener{
void onChanged();
}
}