Implemented #311. OTP details will turn red if it's about to expire in 8 seconds.
This commit is contained in:
parent
0f54078ddf
commit
9a3b408720
6 changed files with 80 additions and 4 deletions
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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());
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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"/>
|
||||
|
|
Loading…
Reference in a new issue