Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 39 additions & 1 deletion app/src/main/java/es/wolfi/app/passman/CopyTextItem.java
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,13 @@
import android.content.ClipData;
import android.content.ClipboardManager;
import android.content.Context;
import android.content.SharedPreferences;
import android.graphics.Canvas;
import android.preference.PreferenceManager;
import android.text.InputType;
import android.text.Spannable;
import android.text.SpannableString;
import android.text.style.ForegroundColorSpan;
import android.util.AttributeSet;
import android.view.LayoutInflater;
import android.view.View;
Expand All @@ -50,6 +55,9 @@ public class CopyTextItem extends LinearLayout {
ImageButton toggle;
ImageButton open_url_toggle;

private String rawText = "";
private boolean passwordMode = false;

public CopyTextItem(Context context) {
super(context);
initView();
Expand Down Expand Up @@ -113,26 +121,31 @@ protected void onDraw(Canvas canvas) {
}

public void setText(String text) {
this.text.setText(text);
this.rawText = text != null ? text : "";
refreshDisplayedText();
}

public TextView getTextView() {
return this.text;
}

public void setModePassword() {
passwordMode = true;
text.setInputType(InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_PASSWORD);
toggle.setVisibility(View.VISIBLE);
open_url_toggle.setVisibility(View.GONE);
refreshDisplayedText();
}

public void setModeText() {
passwordMode = false;
text.setInputType(InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_NORMAL);
toggle.setVisibility(View.GONE);
open_url_toggle.setVisibility(View.GONE);
}

public void setModeEmail() {
passwordMode = false;
text.setInputType(InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_EMAIL_ADDRESS);
toggle.setVisibility(View.GONE);
open_url_toggle.setVisibility(View.GONE);
Expand All @@ -158,6 +171,31 @@ public void toggleVisibility() {
toggle.setImageDrawable(getResources().getDrawable(R.drawable.ic_eye_grey));
break;
}
refreshDisplayedText();
}

private void refreshDisplayedText() {
if (passwordMode && isPasswordRevealed() && isColorDigitsEnabled()) {
SpannableString spannable = new SpannableString(rawText);
int color = getResources().getColor(R.color.password_digit);
for (int i = 0; i < rawText.length(); i++) {
if (Character.isDigit(rawText.charAt(i))) {
spannable.setSpan(new ForegroundColorSpan(color), i, i + 1, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
}
}
text.setText(spannable);
} else {
text.setText(rawText);
}
}

private boolean isPasswordRevealed() {
return text.getInputType() == (InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_VISIBLE_PASSWORD);
}

private boolean isColorDigitsEnabled() {
SharedPreferences settings = PreferenceManager.getDefaultSharedPreferences(getContext());
return settings.getBoolean(SettingValues.COLOR_PASSWORD_DIGITS.toString(), true);
}

public void copyTextToClipboard() {
Expand Down
3 changes: 2 additions & 1 deletion app/src/main/java/es/wolfi/app/passman/SettingValues.java
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,8 @@ public enum SettingValues {
KEY_STORE_ENCRYPTION_KEY("key_store_encryption_key"),
CREDENTIAL_LABEL_SORT("credential_label_sort"),
CASE_INSENSITIVE_CREDENTIAL_LABEL_SORT("case_insensitive_credential_label_sort"),
RESTORE_CUSTOM_CREDENTIAL_SORT_ORDER("restore_custom_credential_sort_order");
RESTORE_CUSTOM_CREDENTIAL_SORT_ORDER("restore_custom_credential_sort_order"),
COLOR_PASSWORD_DIGITS("color_password_digits");

private final String name;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,7 @@ public class SettingsFragment extends Fragment {
EditText settings_password_generator_length_value;

MaterialCheckBox enable_credential_list_icons_switch;
MaterialCheckBox settings_color_password_digits_switch;
MaterialCheckBox enable_offline_cache_switch;

TextView default_autofill_vault_title;
Expand Down Expand Up @@ -163,6 +164,7 @@ public View onCreateView(LayoutInflater inflater, ViewGroup container,
settings_password_generator_length_value = view.findViewById(R.id.settings_password_generator_length_value);

enable_credential_list_icons_switch = view.findViewById(R.id.enable_credential_list_icons_switch);
settings_color_password_digits_switch = view.findViewById(R.id.settings_color_password_digits_switch);
enable_offline_cache_switch = view.findViewById(R.id.enable_offline_cache_switch);

default_autofill_vault_title = view.findViewById(R.id.default_autofill_vault_title);
Expand Down Expand Up @@ -236,6 +238,7 @@ public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
}

enable_credential_list_icons_switch.setChecked(settings.getBoolean(SettingValues.ENABLE_CREDENTIAL_LIST_ICONS.toString(), true));
settings_color_password_digits_switch.setChecked(settings.getBoolean(SettingValues.COLOR_PASSWORD_DIGITS.toString(), true));
enable_offline_cache_switch.setChecked(settings.getBoolean(SettingValues.ENABLE_OFFLINE_CACHE.toString(), true));

Set<Map.Entry<String, Vault>> vaults = getVaultsEntrySet();
Expand Down Expand Up @@ -359,6 +362,7 @@ public void onClick(View view) {
passwordGenerator.applyChanges();

settings.edit().putBoolean(SettingValues.ENABLE_CREDENTIAL_LIST_ICONS.toString(), enable_credential_list_icons_switch.isChecked()).commit();
settings.edit().putBoolean(SettingValues.COLOR_PASSWORD_DIGITS.toString(), settings_color_password_digits_switch.isChecked()).commit();
settings.edit().putBoolean(SettingValues.ENABLE_OFFLINE_CACHE.toString(), enable_offline_cache_switch.isChecked()).commit();

settings.edit().putInt(SettingValues.CLEAR_CLIPBOARD_DELAY.toString(), Integer.parseInt(clear_clipboard_delay_value.getText().toString())).commit();
Expand Down
14 changes: 14 additions & 0 deletions app/src/main/res/layout/fragment_settings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -169,6 +169,20 @@
android:checked="false"
android:text="@string/enable_credential_list_icons" />

<TextView
style="@style/Label"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/color_password_digits" />

<com.google.android.material.checkbox.MaterialCheckBox
android:id="@+id/settings_color_password_digits_switch"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:checked="false"
android:text="@string/color_password_digits_description" />

<TextView
style="@style/Label"
android:layout_width="match_parent"
Expand Down
1 change: 1 addition & 0 deletions app/src/main/res/values/colors.xml
Original file line number Diff line number Diff line change
Expand Up @@ -20,4 +20,5 @@
<color name="danger">#FF0000</color>
<color name="compromised">#36FF0000</color>
<color name="disabled">#7E4C819F</color>
<color name="password_digit">#1565C0</color>
</resources>
2 changes: 2 additions & 0 deletions app/src/main/res/values/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,8 @@
<string name="cancel">Cancel</string>
<string name="enable_credential_list_icons">Enable credential list icons</string>
<string name="credential_icon">Credential icon</string>
<string name="color_password_digits">Highlight password digits</string>
<string name="color_password_digits_description">Show digits in a revealed password in a different color to tell apart characters like 0 and O</string>
<string name="clear_clipboard_delay">Clear clipboard (after seconds)</string>
<string name="generate_password">Generate password</string>
<string name="generate_password_to_clipboard">Generate a random password and copy to clipboard</string>
Expand Down