Implemented #311. OTP details will turn red if it's about to expire in 8 seconds.

This commit is contained in:
Ullas-Aithal 2019-10-26 21:15:54 -05:00
parent 0f54078ddf
commit 9a3b408720
6 changed files with 80 additions and 4 deletions

View file

@ -23,6 +23,7 @@
package org.shadowice.flocke.andotp.Database;
import android.graphics.ColorFilter;
import android.net.Uri;
import org.apache.commons.codec.binary.Base32;
@ -76,6 +77,10 @@ public class Entry {
private long last_used = 0;
public List<String> tags = new ArrayList<>();
private EntryThumbnail.EntryThumbnails thumbnail = EntryThumbnail.EntryThumbnails.Default;
private static final int COLOR_DEFAULT = 0;
public static final int COLOR_RED = 1;
private static final int EXPIRY_TIME = 8;
private int color = COLOR_DEFAULT;
public Entry(){}
@ -385,7 +390,8 @@ public class Entry {
currentOTP = TokenCalculator.TOTP_Steam(secret, period, digits, algorithm);
last_update = counter;
//New OTP. Change color to default color
setColor(COLOR_DEFAULT);
return true;
} else {
return false;
@ -398,6 +404,25 @@ public class Entry {
}
}
/**
* Checks if the OTP is expiring. The color for the entry will be changed to red if the expiry time is less than or equal to 8 seconds
* COLOR_DEFAULT indicates that the OTP has not expired. In this case check if the OTP is about to expire. Update color to COLOR_RED if it's about to expire
* COLOR_RED indicates that the OTP is already about to expire. Don't check again.
* The color will be reset to COLOR_DEFAULT in {@link #updateOTP()} method
*
* @return Return true only if the color has changed to red to save from unnecessary notifying dataset
* */
public boolean hasColorChanged() {
if(color == COLOR_DEFAULT){
long time = System.currentTimeMillis() / 1000;
if ((time % getPeriod()) > (getPeriod() - EXPIRY_TIME)) {
setColor(COLOR_RED);
return true;
}
}
return false;
}
private void setThumbnailFromIssuer(String issuer) {
try {
this.thumbnail = EntryThumbnail.EntryThumbnails.valueOfIgnoreCase(issuer);
@ -424,4 +449,12 @@ public class Entry {
public int hashCode() {
return Objects.hash(type, period, counter, digits, algorithm, secret, label);
}
public void setColor(int color) {
this.color = color;
}
public int getColor() {
return color;
}
}

View file

@ -65,7 +65,6 @@ import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Locale;
import java.util.Set;
import java.util.concurrent.Callable;
import javax.crypto.SecretKey;
@ -178,7 +177,9 @@ public class EntriesCardAdapter extends RecyclerView.Adapter<EntryViewHolder>
for (Entry e : entries) {
if (e.isTimeBased()) {
boolean item_changed = e.updateOTP();
change = change || item_changed || e.hasNonDefaultPeriod();
boolean color_changed = e.hasColorChanged();
change = change || item_changed || e.hasNonDefaultPeriod() || color_changed;
}
}
@ -193,6 +194,7 @@ public class EntriesCardAdapter extends RecyclerView.Adapter<EntryViewHolder>
if (!entry.isTimeBased())
entry.updateOTP();
entryViewHolder.updateColor(entry.getColor());
entryViewHolder.updateValues(entry);
entryViewHolder.setLabelSize(settings.getLabelSize());

View file

@ -62,7 +62,9 @@ public class EntryViewHolder extends RecyclerView.ViewHolder
private LinearLayout counterLayout;
private FrameLayout thumbnailFrame;
private ImageView visibleImg;
private ImageView invisibleImg;
private ImageView thumbnailImg;
private TextView hidden;
private TextView value;
private TextView issuer;
private TextView label;
@ -78,6 +80,7 @@ public class EntryViewHolder extends RecyclerView.ViewHolder
card = v.findViewById(R.id.card_view);
value = v.findViewById(R.id.valueText);
valueLayout = v.findViewById(R.id.valueLayout);
hidden = v.findViewById(R.id.hiddenText);
visibleImg = v.findViewById(R.id.valueImg);
thumbnailFrame = v.findViewById(R.id.thumbnailFrame);
thumbnailImg = v.findViewById(R.id.thumbnailImg);
@ -88,10 +91,10 @@ public class EntryViewHolder extends RecyclerView.ViewHolder
counterLayout = v.findViewById(R.id.counterLayout);
counter = v.findViewById(R.id.counter);
progressBar = v.findViewById(R.id.cardProgressBar);
invisibleImg = v.findViewById(R.id.coverImg);
ImageButton menuButton = v.findViewById(R.id.menuButton);
ImageButton copyButton = v.findViewById(R.id.copyButton);
ImageView invisibleImg = v.findViewById(R.id.coverImg);
// Style the buttons in the current theme colors
ColorFilter colorFilter = Tools.getThemeColorFilter(context, android.R.attr.textColorSecondary);
@ -296,4 +299,30 @@ public class EntryViewHolder extends RecyclerView.ViewHolder
void onCounterClicked(int position);
void onCounterLongPressed(int position);
}
/**
* Updates the color of the following items to red (if expiring) or default color (if new OTP)
* TextViews: OTP, "Hidden" text, issuer, label, tags
* ImageViews: Visible, Invisible
*
* @param color will define if the color needs to be changed to red or default
* */
public void updateColor(int color) {
int textColor;
ColorFilter colorFilter;
if(color == Entry.COLOR_RED) {
textColor = Tools.getThemeColor(context, R.attr.colorExpiring);
colorFilter = Tools.getThemeColorFilter(context, R.attr.colorExpiring);
} else {
textColor = Tools.getThemeColor(context, android.R.attr.textColorSecondary);
colorFilter = Tools.getThemeColorFilter(context, android.R.attr.textColorSecondary);
}
value.setTextColor(textColor);
hidden.setTextColor(textColor);
issuer.setTextColor(textColor);
label.setTextColor(textColor);
tags.setTextColor(textColor);
visibleImg.setColorFilter(colorFilter);
invisibleImg.setColorFilter(colorFilter);
}
}

View file

@ -94,6 +94,7 @@
app:srcCompat="@drawable/ic_visibility_invisible"/>
<TextView
android:id="@+id/hiddenText"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:alpha="0.4"

View file

@ -16,4 +16,7 @@
<color name="dark_thumbnail_background">#ffe0e0e0</color> <!-- material_grey_300 -->
<color name="fab_small_label_background">#212121</color>
<color name="expiring_red_light">#f05545</color> <!--Light color from https://material.io/resources/color/#!/?view.left=0&view.right=0&primary.color=B71C1C-->
<color name="expiring_red_dark">#d50000</color> <!--Dark color from https://material.io/resources/color/#!/?view.left=0&view.right=0&primary.color=D50000-->
</resources>

View file

@ -7,6 +7,8 @@
<attr name="colorGithub" format="reference" />
<attr name="thumbnailBackground" format="reference" />
<attr name="colorExpiring" format="reference"/>
<!-- General styles -->
<style name="AppTheme.AppBarOverlay" parent="ThemeOverlay.AppCompat.Dark.ActionBar" />
@ -33,6 +35,8 @@
<item name="about_libraries_text_openSource">@color/about_libraries_text_openSource</item>
<item name="about_libraries_dividerDark_openSource">@color/about_libraries_dividerDark_openSource</item>
<item name="about_libraries_dividerLight_openSource">@color/about_libraries_dividerLight_openSource</item>
<item name="colorExpiring">@color/expiring_red_dark</item>
</style>
<style name="AppTheme" parent="AppBaseTheme"/>
@ -69,6 +73,8 @@
<item name="about_libraries_text_openSource">@color/about_libraries_text_openSource_dark</item>
<item name="about_libraries_dividerDark_openSource">@color/about_libraries_dividerDark_openSource_dark</item>
<item name="about_libraries_dividerLight_openSource">@color/about_libraries_dividerLight_openSource_dark</item>
<item name="colorExpiring">@color/expiring_red_light</item>
</style>
<style name="AppTheme.Dark" parent = "AppBaseTheme.Dark"/>
@ -101,6 +107,8 @@
<item name="about_libraries_text_openSource">@color/about_libraries_text_openSource_dark</item>
<item name="about_libraries_dividerDark_openSource">@color/about_libraries_dividerDark_openSource_dark</item>
<item name="about_libraries_dividerLight_openSource">@color/about_libraries_dividerLight_openSource_dark</item>
<item name="colorExpiring">@color/expiring_red_light</item>
</style>
<style name="AppTheme.Black" parent="AppBaseTheme.Black"/>