Finish up HOTP support

Close #1
This commit is contained in:
Alexander Bakker 2018-06-06 17:23:40 +02:00
parent 3aba0f3f47
commit da37b5175e
8 changed files with 72 additions and 5 deletions

View file

@ -60,4 +60,8 @@ public class HotpInfo extends OtpInfo {
}
_counter = counter;
}
public void incrementCounter() throws OtpInfoException {
setCounter(getCounter() + 1);
}
}

View file

@ -95,7 +95,6 @@ public abstract class OtpInfo implements Serializable {
String algo = obj.getString("algo");
int digits = obj.getInt("digits");
switch (type) {
case "totp":
int period = obj.getInt("period");

View file

@ -438,4 +438,9 @@ public class MainActivity extends AegisActivity implements EntryListView.Listene
public void onEntryDrop(DatabaseEntry entry) {
saveDatabase();
}
@Override
public void onEntryChange(DatabaseEntry entry) {
saveDatabase();
}
}

View file

@ -13,7 +13,9 @@ import java.util.UUID;
import me.impy.aegis.R;
import me.impy.aegis.db.DatabaseEntry;
import me.impy.aegis.helpers.ItemTouchHelperAdapter;
import me.impy.aegis.otp.HotpInfo;
import me.impy.aegis.otp.OtpInfo;
import me.impy.aegis.otp.OtpInfoException;
import me.impy.aegis.otp.TotpInfo;
public class EntryAdapter extends RecyclerView.Adapter<EntryHolder> implements ItemTouchHelperAdapter {
@ -124,6 +126,24 @@ public class EntryAdapter extends RecyclerView.Adapter<EntryHolder> implements I
return _listener.onLongEntryClick(_entries.get(position));
}
});
holder.setOnRefreshClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// this will only be called if the entry is of type HotpInfo
try {
((HotpInfo)entry.getInfo()).incrementCounter();
} catch (OtpInfoException e) {
throw new RuntimeException(e);
}
// notify the listener that the counter has been incremented
// this gives it a chance to save the database
_listener.onEntryChange(entry);
// finally, refresh the code in the UI
holder.refreshCode();
}
});
}
public int getUniformPeriod() {
@ -163,5 +183,6 @@ public class EntryAdapter extends RecyclerView.Adapter<EntryHolder> implements I
boolean onLongEntryClick(DatabaseEntry entry);
void onEntryMove(DatabaseEntry entry1, DatabaseEntry entry2);
void onEntryDrop(DatabaseEntry entry);
void onEntryChange(DatabaseEntry entry);
}
}

View file

@ -12,6 +12,8 @@ import me.impy.aegis.R;
import me.impy.aegis.db.DatabaseEntry;
import me.impy.aegis.helpers.TextDrawableHelper;
import me.impy.aegis.helpers.UiRefresher;
import me.impy.aegis.otp.HotpInfo;
import me.impy.aegis.otp.OtpInfoException;
import me.impy.aegis.otp.TotpInfo;
public class EntryHolder extends RecyclerView.ViewHolder {
@ -20,6 +22,7 @@ public class EntryHolder extends RecyclerView.ViewHolder {
private TextView _profileIssuer;
private ImageView _profileDrawable;
private DatabaseEntry _entry;
private ImageView _buttonRefresh;
private PeriodProgressBar _progressBar;
@ -31,6 +34,7 @@ public class EntryHolder extends RecyclerView.ViewHolder {
_profileCode = view.findViewById(R.id.profile_code);
_profileIssuer = view.findViewById(R.id.profile_issuer);
_profileDrawable = view.findViewById(R.id.ivTextDrawable);
_buttonRefresh = view.findViewById(R.id.buttonRefresh);
_progressBar = view.findViewById(R.id.progressBar);
int primaryColorId = view.getContext().getResources().getColor(R.color.colorPrimary);
@ -53,11 +57,15 @@ public class EntryHolder extends RecyclerView.ViewHolder {
public void setData(DatabaseEntry entry, boolean showIssuer, boolean showProgress) {
_entry = entry;
// only show the progress bar if there is no uniform period and the entry type is TotpInfo
_progressBar.setVisibility(showProgress ? View.VISIBLE : View.INVISIBLE);
if (showProgress) {
_progressBar.setPeriod(((TotpInfo)entry.getInfo()).getPeriod());
}
// only show the button if this entry is of type HotpInfo
_buttonRefresh.setVisibility(entry.getInfo() instanceof HotpInfo ? View.VISIBLE : View.GONE);
_profileName.setText(entry.getName());
_profileIssuer.setText("");
if (showIssuer) {
@ -70,6 +78,10 @@ public class EntryHolder extends RecyclerView.ViewHolder {
refreshCode();
}
public void setOnRefreshClickListener(View.OnClickListener listener) {
_buttonRefresh.setOnClickListener(listener);
}
public void startRefreshLoop() {
_refresher.start();
}
@ -78,7 +90,7 @@ public class EntryHolder extends RecyclerView.ViewHolder {
_refresher.stop();
}
private void refreshCode() {
public void refreshCode() {
String otp = _entry.getInfo().getOtp();
_profileCode.setText(otp.substring(0, otp.length() / 2) + " " + otp.substring(otp.length() / 2));
}

View file

@ -120,6 +120,11 @@ public class EntryListView extends Fragment implements EntryAdapter.Listener {
_listener.onEntryDrop(entry);
}
@Override
public void onEntryChange(DatabaseEntry entry) {
_listener.onEntryChange(entry);
}
public void setShowIssuer(boolean showIssuer) {
_adapter.setShowIssuer(showIssuer);
_adapter.notifyDataSetChanged();
@ -149,5 +154,6 @@ public class EntryListView extends Fragment implements EntryAdapter.Listener {
void onEntryClick(DatabaseEntry entry);
void onEntryMove(DatabaseEntry entry1, DatabaseEntry entry2);
void onEntryDrop(DatabaseEntry entry);
void onEntryChange(DatabaseEntry entry);
}
}

View file

@ -0,0 +1,7 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:height="24dp"
android:width="24dp"
android:viewportWidth="24"
android:viewportHeight="24">
<path android:fillColor="#000" android:pathData="M17.65,6.35C16.2,4.9 14.21,4 12,4A8,8 0 0,0 4,12A8,8 0 0,0 12,20C15.73,20 18.84,17.45 19.73,14H17.65C16.83,16.33 14.61,18 12,18A6,6 0 0,1 6,12A6,6 0 0,1 12,6C13.66,6 15.14,6.69 16.22,7.78L13,11H20V4L17.65,6.35Z" />
</vector>

View file

@ -1,7 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:card_view="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:foreground="?android:attr/selectableItemBackground"
android:clickable="true"
@ -32,8 +30,9 @@
</RelativeLayout>
<RelativeLayout
android:layout_width="match_parent"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:layout_alignParentBottom="false"
android:layout_alignParentTop="false"
android:layout_alignWithParentIfMissing="false"
@ -95,6 +94,20 @@
android:textStyle="normal|bold"/>
</RelativeLayout>
<ImageView
android:id="@+id/buttonRefresh"
android:visibility="gone"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_marginStart="16dp"
android:layout_marginEnd="16dp"
android:padding="8dp"
android:clickable="true"
android:focusable="true"
android:src="@drawable/ic_refresh_black_24dp"
android:tint="?attr/iconColorPrimary"
android:background="?android:attr/selectableItemBackground" />
</LinearLayout>
<LinearLayout