mirror of
https://github.com/beemdevelopment/Aegis.git
synced 2025-04-26 08:46:07 +00:00
Finish work on the single progressbar for db's with uniform periods
This commit is contained in:
parent
8a8cb94c16
commit
3f3863a187
9 changed files with 175 additions and 155 deletions
|
@ -42,7 +42,11 @@ public class KeyInfo implements Serializable {
|
|||
}
|
||||
|
||||
public long getMillisTillNextRotation() {
|
||||
long p = _period * 1000;
|
||||
return KeyInfo.getMillisTillNextRotation(_period);
|
||||
}
|
||||
|
||||
public static long getMillisTillNextRotation(int period) {
|
||||
long p = period * 1000;
|
||||
return p - (System.currentTimeMillis() % p);
|
||||
}
|
||||
|
||||
|
|
|
@ -1,22 +1,17 @@
|
|||
package me.impy.aegis.ui;
|
||||
|
||||
import android.Manifest;
|
||||
import android.animation.ObjectAnimator;
|
||||
import android.content.ClipData;
|
||||
import android.content.ClipboardManager;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.graphics.PorterDuff;
|
||||
import android.graphics.Rect;
|
||||
import android.os.Handler;
|
||||
import android.support.design.widget.BottomSheetDialog;
|
||||
import android.os.Bundle;
|
||||
import android.view.Menu;
|
||||
import android.view.MenuItem;
|
||||
import android.view.MotionEvent;
|
||||
import android.view.animation.LinearInterpolator;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.ProgressBar;
|
||||
import android.widget.Toast;
|
||||
|
||||
import com.getbase.floatingactionbutton.FloatingActionsMenu;
|
||||
|
@ -50,12 +45,9 @@ public class MainActivity extends AegisActivity implements KeyProfileView.Listen
|
|||
private AegisApplication _app;
|
||||
private DatabaseManager _db;
|
||||
private KeyProfileView _keyProfileView;
|
||||
private ProgressBar _progressBar;
|
||||
|
||||
private Menu _menu;
|
||||
private FloatingActionsMenu _fabMenu;
|
||||
private Handler _uiHandler;
|
||||
private boolean _running = false;
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
|
@ -63,8 +55,6 @@ public class MainActivity extends AegisActivity implements KeyProfileView.Listen
|
|||
_app = (AegisApplication) getApplication();
|
||||
_db = _app.getDatabaseManager();
|
||||
|
||||
_uiHandler = new Handler();
|
||||
|
||||
// set up the main view
|
||||
setContentView(R.layout.activity_main);
|
||||
|
||||
|
@ -73,10 +63,6 @@ public class MainActivity extends AegisActivity implements KeyProfileView.Listen
|
|||
_keyProfileView.setListener(this);
|
||||
_keyProfileView.setShowIssuer(getPreferences().isIssuerVisible());
|
||||
|
||||
_progressBar = findViewById(R.id.progressBar);
|
||||
int primaryColorId = getResources().getColor(R.color.colorPrimary);
|
||||
_progressBar.getProgressDrawable().setColorFilter(primaryColorId, PorterDuff.Mode.SRC_IN);
|
||||
|
||||
// set up the floating action button
|
||||
_fabMenu = findViewById(R.id.fab);
|
||||
findViewById(R.id.fab_enter).setOnClickListener(view -> {
|
||||
|
@ -431,52 +417,6 @@ public class MainActivity extends AegisActivity implements KeyProfileView.Listen
|
|||
for (DatabaseEntry entry : _db.getKeys()) {
|
||||
_keyProfileView.addKey(new KeyProfile(entry));
|
||||
}
|
||||
|
||||
if(_keyProfileView.allSamePeriod())
|
||||
{
|
||||
startRefreshLoop();
|
||||
}
|
||||
}
|
||||
|
||||
public void refreshCode()
|
||||
{
|
||||
_keyProfileView.refresh();
|
||||
KeyProfile keyProfile = _keyProfileView.getKeyProfile(0);
|
||||
|
||||
// reset the progress bar
|
||||
int maxProgress = _progressBar.getMax();
|
||||
_progressBar.setProgress(maxProgress);
|
||||
|
||||
// calculate the progress the bar should start at
|
||||
long millisTillRotation = keyProfile.getEntry().getInfo().getMillisTillNextRotation();
|
||||
long period = keyProfile.getEntry().getInfo().getPeriod() * maxProgress;
|
||||
int currentProgress = maxProgress - (int) ((((double) period - millisTillRotation) / period) * maxProgress);
|
||||
|
||||
// start progress animation
|
||||
ObjectAnimator animation = ObjectAnimator.ofInt(_progressBar, "progress", currentProgress, 0);
|
||||
animation.setDuration(millisTillRotation);
|
||||
animation.setInterpolator(new LinearInterpolator());
|
||||
animation.start();
|
||||
}
|
||||
|
||||
public void startRefreshLoop() {
|
||||
if (_running) {
|
||||
return;
|
||||
}
|
||||
_running = true;
|
||||
|
||||
KeyProfile keyProfile = _keyProfileView.getKeyProfile(0);
|
||||
|
||||
refreshCode();
|
||||
_uiHandler.postDelayed(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (_running) {
|
||||
refreshCode();
|
||||
_uiHandler.postDelayed(this, keyProfile.getEntry().getInfo().getMillisTillNextRotation());
|
||||
}
|
||||
}
|
||||
}, keyProfile.getEntry().getInfo().getMillisTillNextRotation());
|
||||
}
|
||||
|
||||
private void updateLockIcon() {
|
||||
|
|
|
@ -49,10 +49,6 @@ public class KeyProfileAdapter extends RecyclerView.Adapter<KeyProfileHolder> im
|
|||
notifyDataSetChanged();
|
||||
}
|
||||
|
||||
public ArrayList<KeyProfile> getKeys() {
|
||||
return _keyProfiles;
|
||||
}
|
||||
|
||||
public void replaceKey(KeyProfile newProfile) {
|
||||
KeyProfile oldProfile = getKeyByUUID(newProfile.getEntry().getUUID());
|
||||
int position = _keyProfiles.indexOf(oldProfile);
|
||||
|
@ -60,13 +56,6 @@ public class KeyProfileAdapter extends RecyclerView.Adapter<KeyProfileHolder> im
|
|||
notifyItemChanged(position);
|
||||
}
|
||||
|
||||
public void refresh() {
|
||||
for (KeyProfile profile : _keyProfiles) {
|
||||
profile.refreshCode();
|
||||
}
|
||||
notifyDataSetChanged();
|
||||
}
|
||||
|
||||
private KeyProfile getKeyByUUID(UUID uuid) {
|
||||
for (KeyProfile profile : _keyProfiles) {
|
||||
if (profile.getEntry().getUUID().equals(uuid)) {
|
||||
|
@ -104,17 +93,16 @@ public class KeyProfileAdapter extends RecyclerView.Adapter<KeyProfileHolder> im
|
|||
|
||||
@Override
|
||||
public void onViewRecycled(KeyProfileHolder holder) {
|
||||
holder.setData(null, _showIssuer);
|
||||
holder.stopRefreshLoop();
|
||||
super.onViewRecycled(holder);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBindViewHolder(final KeyProfileHolder holder, int position) {
|
||||
boolean uniform = isPeriodUniform();
|
||||
final KeyProfile profile = _keyProfiles.get(position);
|
||||
holder.setData(profile, _showIssuer);
|
||||
|
||||
if(!allSamePeriod())
|
||||
{
|
||||
holder.setData(profile, _showIssuer, !uniform);
|
||||
if (!uniform) {
|
||||
holder.startRefreshLoop();
|
||||
}
|
||||
|
||||
|
@ -134,19 +122,23 @@ public class KeyProfileAdapter extends RecyclerView.Adapter<KeyProfileHolder> im
|
|||
});
|
||||
}
|
||||
|
||||
public boolean allSamePeriod()
|
||||
{
|
||||
ArrayList<KeyProfile> profiles = getKeys();
|
||||
int period = profiles.get(0).getEntry().getInfo().getPeriod();
|
||||
public int getUniformPeriod() {
|
||||
if (_keyProfiles.isEmpty()) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
for (KeyProfile profile : profiles) {
|
||||
if(period != profile.getEntry().getInfo().getPeriod())
|
||||
{
|
||||
return false;
|
||||
int period = _keyProfiles.get(0).getEntry().getInfo().getPeriod();
|
||||
for (KeyProfile profile : _keyProfiles) {
|
||||
if (period != profile.getEntry().getInfo().getPeriod()) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
return period;
|
||||
}
|
||||
|
||||
public boolean isPeriodUniform() {
|
||||
return getUniformPeriod() != -1;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -1,14 +1,10 @@
|
|||
package me.impy.aegis.ui.views;
|
||||
|
||||
import android.animation.ObjectAnimator;
|
||||
import android.graphics.Color;
|
||||
import android.graphics.PorterDuff;
|
||||
import android.os.Handler;
|
||||
import android.support.v7.widget.RecyclerView;
|
||||
import android.view.View;
|
||||
import android.view.animation.LinearInterpolator;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.ProgressBar;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.amulyakhare.textdrawable.TextDrawable;
|
||||
|
@ -21,7 +17,8 @@ public class KeyProfileHolder extends RecyclerView.ViewHolder {
|
|||
private TextView _profileIssuer;
|
||||
private ImageView _profileDrawable;
|
||||
private KeyProfile _profile;
|
||||
private ProgressBar _progressBar;
|
||||
|
||||
private PeriodProgressBar _progressBar;
|
||||
|
||||
private Handler _uiHandler;
|
||||
private boolean _running = false;
|
||||
|
@ -39,16 +36,15 @@ public class KeyProfileHolder extends RecyclerView.ViewHolder {
|
|||
_progressBar.getProgressDrawable().setColorFilter(primaryColorId, PorterDuff.Mode.SRC_IN);
|
||||
}
|
||||
|
||||
public void setData(KeyProfile profile, boolean showIssuer) {
|
||||
if (profile == null) {
|
||||
_profile = null;
|
||||
_running = false;
|
||||
return;
|
||||
}
|
||||
public void setData(KeyProfile profile, boolean showIssuer, boolean showProgress) {
|
||||
_profile = profile;
|
||||
|
||||
_progressBar.setVisibility(showProgress ? View.VISIBLE : View.INVISIBLE);
|
||||
if (showProgress) {
|
||||
_progressBar.setPeriod(profile.getEntry().getInfo().getPeriod());
|
||||
}
|
||||
|
||||
_profileName.setText(profile.getEntry().getName());
|
||||
_profileCode.setText(profile.getCode());
|
||||
_profileIssuer.setText("");
|
||||
if (showIssuer) {
|
||||
_profileIssuer.setText(" - " + profile.getEntry().getInfo().getIssuer());
|
||||
|
@ -56,6 +52,8 @@ public class KeyProfileHolder extends RecyclerView.ViewHolder {
|
|||
|
||||
TextDrawable drawable = profile.getDrawable();
|
||||
_profileDrawable.setImageDrawable(drawable);
|
||||
|
||||
refreshCode();
|
||||
}
|
||||
|
||||
public void startRefreshLoop() {
|
||||
|
@ -64,35 +62,29 @@ public class KeyProfileHolder extends RecyclerView.ViewHolder {
|
|||
}
|
||||
_running = true;
|
||||
|
||||
refreshCode();
|
||||
refresh();
|
||||
_uiHandler.postDelayed(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (_running) {
|
||||
refreshCode();
|
||||
refresh();
|
||||
_uiHandler.postDelayed(this, _profile.getEntry().getInfo().getMillisTillNextRotation());
|
||||
}
|
||||
}
|
||||
}, _profile.getEntry().getInfo().getMillisTillNextRotation());
|
||||
}
|
||||
|
||||
public void refreshCode() {
|
||||
public void stopRefreshLoop() {
|
||||
_running = false;
|
||||
}
|
||||
|
||||
private void refresh() {
|
||||
refreshCode();
|
||||
_progressBar.refresh();
|
||||
}
|
||||
|
||||
private void refreshCode() {
|
||||
String otp = _profile.refreshCode();
|
||||
|
||||
// reset the progress bar
|
||||
int maxProgress = _progressBar.getMax();
|
||||
_progressBar.setProgress(maxProgress);
|
||||
_profileCode.setText(otp.substring(0, otp.length() / 2) + " " + otp.substring(otp.length() / 2));
|
||||
|
||||
// calculate the progress the bar should start at
|
||||
long millisTillRotation = _profile.getEntry().getInfo().getMillisTillNextRotation();
|
||||
long period = _profile.getEntry().getInfo().getPeriod() * maxProgress;
|
||||
int currentProgress = maxProgress - (int) ((((double) period - millisTillRotation) / period) * maxProgress);
|
||||
|
||||
// start progress animation
|
||||
ObjectAnimator animation = ObjectAnimator.ofInt(_progressBar, "progress", currentProgress, 0);
|
||||
animation.setDuration(millisTillRotation);
|
||||
animation.setInterpolator(new LinearInterpolator());
|
||||
animation.start();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
package me.impy.aegis.ui.views;
|
||||
|
||||
import android.graphics.PorterDuff;
|
||||
import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
import android.support.v4.app.Fragment;
|
||||
import android.support.v7.widget.LinearLayoutManager;
|
||||
import android.support.v7.widget.RecyclerView;
|
||||
|
@ -9,10 +11,8 @@ import android.view.LayoutInflater;
|
|||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
|
||||
import java.lang.reflect.Array;
|
||||
import java.util.ArrayList;
|
||||
|
||||
import me.impy.aegis.R;
|
||||
import me.impy.aegis.crypto.KeyInfo;
|
||||
import me.impy.aegis.db.DatabaseEntry;
|
||||
import me.impy.aegis.helpers.SimpleItemTouchHelperCallback;
|
||||
|
||||
|
@ -20,6 +20,11 @@ public class KeyProfileView extends Fragment implements KeyProfileAdapter.Listen
|
|||
private KeyProfileAdapter _adapter;
|
||||
private Listener _listener;
|
||||
|
||||
private PeriodProgressBar _progressBar;
|
||||
private Handler _uiHandler;
|
||||
private boolean _running = false;
|
||||
private boolean _showProgress = false;
|
||||
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
|
@ -30,6 +35,11 @@ public class KeyProfileView extends Fragment implements KeyProfileAdapter.Listen
|
|||
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
|
||||
View view = inflater.inflate(R.layout.fragment_keyprofile_view, container, false);
|
||||
|
||||
_uiHandler = new Handler();
|
||||
_progressBar = view.findViewById(R.id.progressBar);
|
||||
int primaryColorId = getResources().getColor(R.color.colorPrimary);
|
||||
_progressBar.getProgressDrawable().setColorFilter(primaryColorId, PorterDuff.Mode.SRC_IN);
|
||||
|
||||
// set up the recycler view
|
||||
RecyclerView rvKeyProfiles = view.findViewById(R.id.rvKeyProfiles);
|
||||
LinearLayoutManager mLayoutManager = new LinearLayoutManager(view.getContext());
|
||||
|
@ -42,6 +52,53 @@ public class KeyProfileView extends Fragment implements KeyProfileAdapter.Listen
|
|||
return view;
|
||||
}
|
||||
|
||||
public void refresh() {
|
||||
if (_showProgress) {
|
||||
_progressBar.refresh();
|
||||
}
|
||||
_adapter.notifyDataSetChanged();
|
||||
}
|
||||
|
||||
private void checkPeriodUniformity() {
|
||||
boolean uniform = _adapter.isPeriodUniform();
|
||||
if (uniform == _showProgress) {
|
||||
return;
|
||||
}
|
||||
_showProgress = uniform;
|
||||
|
||||
if (_showProgress) {
|
||||
_progressBar.setVisibility(View.VISIBLE);
|
||||
_progressBar.setPeriod(_adapter.getUniformPeriod());
|
||||
startRefreshLoop();
|
||||
} else {
|
||||
_progressBar.setVisibility(View.INVISIBLE);
|
||||
stopRefreshLoop();
|
||||
}
|
||||
}
|
||||
|
||||
public void startRefreshLoop() {
|
||||
if (_running) {
|
||||
return;
|
||||
}
|
||||
_running = true;
|
||||
|
||||
refresh();
|
||||
_uiHandler.postDelayed(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (_running) {
|
||||
refresh();
|
||||
_uiHandler.postDelayed(this, KeyInfo.getMillisTillNextRotation(_adapter.getUniformPeriod()));
|
||||
}
|
||||
}
|
||||
}, KeyInfo.getMillisTillNextRotation(_adapter.getUniformPeriod()));
|
||||
}
|
||||
|
||||
private void stopRefreshLoop() {
|
||||
refresh();
|
||||
_running = false;
|
||||
}
|
||||
|
||||
public void setListener(Listener listener) {
|
||||
_listener = listener;
|
||||
}
|
||||
|
@ -71,34 +128,24 @@ public class KeyProfileView extends Fragment implements KeyProfileAdapter.Listen
|
|||
_adapter.notifyDataSetChanged();
|
||||
}
|
||||
|
||||
public boolean allSamePeriod()
|
||||
{
|
||||
return _adapter.allSamePeriod();
|
||||
}
|
||||
|
||||
public KeyProfile getKeyProfile(int index)
|
||||
{
|
||||
return _adapter.getKeys().get(index);
|
||||
}
|
||||
|
||||
public void addKey(KeyProfile profile) {
|
||||
_adapter.addKey(profile);
|
||||
checkPeriodUniformity();
|
||||
}
|
||||
|
||||
public void removeKey(KeyProfile profile) {
|
||||
_adapter.removeKey(profile);
|
||||
checkPeriodUniformity();
|
||||
}
|
||||
|
||||
public void clearKeys() {
|
||||
_adapter.clearKeys();
|
||||
checkPeriodUniformity();
|
||||
}
|
||||
|
||||
public void replaceKey(KeyProfile profile) {
|
||||
_adapter.replaceKey(profile);
|
||||
}
|
||||
|
||||
public void refresh() {
|
||||
_adapter.refresh();
|
||||
checkPeriodUniformity();
|
||||
}
|
||||
|
||||
public interface Listener {
|
||||
|
|
|
@ -0,0 +1,53 @@
|
|||
package me.impy.aegis.ui.views;
|
||||
|
||||
import android.animation.ObjectAnimator;
|
||||
import android.content.Context;
|
||||
import android.os.Build;
|
||||
import android.support.annotation.RequiresApi;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.animation.LinearInterpolator;
|
||||
import android.widget.ProgressBar;
|
||||
|
||||
import me.impy.aegis.crypto.KeyInfo;
|
||||
|
||||
public class PeriodProgressBar extends ProgressBar {
|
||||
private int _period;
|
||||
|
||||
public PeriodProgressBar(Context context) {
|
||||
super(context);
|
||||
}
|
||||
|
||||
public PeriodProgressBar(Context context, AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
}
|
||||
|
||||
public PeriodProgressBar(Context context, AttributeSet attrs, int defStyleAttr) {
|
||||
super(context, attrs, defStyleAttr);
|
||||
}
|
||||
|
||||
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
|
||||
public PeriodProgressBar(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
|
||||
super(context, attrs, defStyleAttr, defStyleRes);
|
||||
}
|
||||
|
||||
public void setPeriod(int period) {
|
||||
_period = period;
|
||||
}
|
||||
|
||||
public void refresh() {
|
||||
// reset the progress bar
|
||||
int maxProgress = getMax();
|
||||
setProgress(maxProgress);
|
||||
|
||||
// calculate the progress the bar should start at
|
||||
long millisTillRotation = KeyInfo.getMillisTillNextRotation(_period);
|
||||
long period = _period * maxProgress;
|
||||
int currentProgress = maxProgress - (int) ((((double) period - millisTillRotation) / period) * maxProgress);
|
||||
|
||||
// start progress animation
|
||||
ObjectAnimator animation = ObjectAnimator.ofInt(this, "progress", currentProgress, 0);
|
||||
animation.setDuration(millisTillRotation);
|
||||
animation.setInterpolator(new LinearInterpolator());
|
||||
animation.start();
|
||||
}
|
||||
}
|
|
@ -15,23 +15,6 @@
|
|||
android:layout_width="match_parent"
|
||||
app:layout_behavior="@string/appbar_scrolling_view_behavior"/>
|
||||
|
||||
<LinearLayout
|
||||
android:orientation="horizontal"
|
||||
android:padding="0dp"
|
||||
android:layout_margin="0dp"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<ProgressBar
|
||||
style="?android:attr/progressBarStyleHorizontal"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="4dp"
|
||||
android:id="@+id/progressBar"
|
||||
android:max="1000"
|
||||
android:layout_weight="1"/>
|
||||
</LinearLayout>
|
||||
|
||||
|
||||
<!-- note: the fab should always be the last element to be sure it's displayed on top -->
|
||||
<com.getbase.floatingactionbutton.FloatingActionsMenu
|
||||
android:id="@+id/fab"
|
||||
|
|
|
@ -104,12 +104,11 @@
|
|||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<ProgressBar
|
||||
<me.impy.aegis.ui.views.PeriodProgressBar
|
||||
style="?android:attr/progressBarStyleHorizontal"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="4dp"
|
||||
android:id="@+id/progressBar"
|
||||
android:visibility="invisible"
|
||||
android:max="1000"
|
||||
android:layout_weight="1"/>
|
||||
</LinearLayout>
|
||||
|
|
|
@ -3,10 +3,20 @@
|
|||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:background="?attr/background">
|
||||
android:background="?attr/background"
|
||||
android:orientation="vertical">
|
||||
|
||||
<me.impy.aegis.ui.views.PeriodProgressBar
|
||||
style="?android:attr/progressBarStyleHorizontal"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="4dp"
|
||||
android:id="@+id/progressBar"
|
||||
android:max="1000"/>
|
||||
|
||||
<android.support.v7.widget.RecyclerView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_height="0dp"
|
||||
android:scrollbars="vertical"
|
||||
android:id="@+id/rvKeyProfiles"/>
|
||||
android:id="@+id/rvKeyProfiles"
|
||||
android:layout_weight="1"/>
|
||||
</LinearLayout>
|
||||
|
|
Loading…
Add table
Reference in a new issue