Skip to content

Commit

Permalink
Add haptic feedback toggle for code refresh
Browse files Browse the repository at this point in the history
  • Loading branch information
michaelschattgen committed Jan 22, 2025
1 parent 9ab949a commit 7197878
Show file tree
Hide file tree
Showing 9 changed files with 97 additions and 3 deletions.
1 change: 1 addition & 0 deletions app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.USE_BIOMETRIC" />
<uses-permission android:name="android.permission.VIBRATE" />

<!-- NOTE: Disabled for now. See issue: #1047
<uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
Expand Down
4 changes: 4 additions & 0 deletions app/src/main/java/com/beemdevelopment/aegis/Preferences.java
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,10 @@ public boolean isEntryHighlightEnabled() {
return _prefs.getBoolean("pref_highlight_entry", false);
}

public boolean isHapticFeedbackEnabled() {
return _prefs.getBoolean("pref_haptic_feedback", true);
}

public boolean isPauseFocusedEnabled() {
boolean dependenciesEnabled = isTapToRevealEnabled() || isEntryHighlightEnabled();
if (!dependenciesEnabled) return false;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package com.beemdevelopment.aegis;

public class VibrationPatterns {
private VibrationPatterns() {}

public static final long[] EXPIRING = {475, 20, 5, 20, 965, 20, 5, 20, 965, 20, 5, 20, 420};
public static final long[] REFRESH_CODE = {0, 100};
}
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@ public void start() {
}
_running = true;

_listener.onRefresh();
_handler.postDelayed(new Runnable() {
@Override
public void run() {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
package com.beemdevelopment.aegis.helpers;

import android.content.Context;
import android.os.Build;
import android.os.VibrationEffect;
import android.os.Vibrator;
import android.os.VibratorManager;

import com.beemdevelopment.aegis.Preferences;

import dagger.hilt.InstallIn;
import dagger.hilt.android.EarlyEntryPoint;
import dagger.hilt.android.EarlyEntryPoints;
import dagger.hilt.components.SingletonComponent;

public class VibrationHelper {
public static void vibratePattern(Context context, long[] pattern) {
if (!isHapticFeedbackEnabled(context)) {
return;
}

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
VibratorManager vibratorManager = (VibratorManager) context.getSystemService(Context.VIBRATOR_MANAGER_SERVICE);
if (vibratorManager != null) {
Vibrator vibrator = vibratorManager.getDefaultVibrator();
VibrationEffect effect = VibrationEffect.createWaveform(pattern, -1);
vibrator.vibrate(effect);
}
} else {
Vibrator vibrator = (Vibrator) context.getSystemService(Context.VIBRATOR_SERVICE);
if (vibrator != null) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
VibrationEffect effect = VibrationEffect.createWaveform(pattern, -1);
vibrator.vibrate(effect);
}
}
}
}

public static boolean isHapticFeedbackEnabled(Context context) {
Preferences _prefs = EarlyEntryPoints.get(context.getApplicationContext(), PrefEntryPoint.class).getPreferences();

return _prefs.isHapticFeedbackEnabled();
}

@EarlyEntryPoint
@InstallIn(SingletonComponent.class)
public interface PrefEntryPoint {
Preferences getPreferences();
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package com.beemdevelopment.aegis.ui.views;

import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.AnimatorSet;
import android.animation.ArgbEvaluator;
import android.animation.ObjectAnimator;
Expand All @@ -25,11 +27,13 @@
import com.beemdevelopment.aegis.AccountNamePosition;
import com.beemdevelopment.aegis.Preferences;
import com.beemdevelopment.aegis.R;
import com.beemdevelopment.aegis.VibrationPatterns;
import com.beemdevelopment.aegis.ViewMode;
import com.beemdevelopment.aegis.helpers.AnimationsHelper;
import com.beemdevelopment.aegis.helpers.CenterVerticalSpan;
import com.beemdevelopment.aegis.helpers.SimpleAnimationEndListener;
import com.beemdevelopment.aegis.helpers.UiRefresher;
import com.beemdevelopment.aegis.helpers.VibrationHelper;
import com.beemdevelopment.aegis.otp.HotpInfo;
import com.beemdevelopment.aegis.otp.OtpInfo;
import com.beemdevelopment.aegis.otp.OtpInfoException;
Expand Down Expand Up @@ -67,6 +71,7 @@ public class EntryHolder extends RecyclerView.ViewHolder {

private boolean _hidden;
private boolean _paused;
private boolean _nonUniform;

private TotpProgressBar _progressBar;
private MaterialCardView _view;
Expand Down Expand Up @@ -118,12 +123,13 @@ public long getMillisTillNextRefresh() {
});
}

public void setData(VaultEntry entry, Preferences.CodeGrouping groupSize, ViewMode viewMode, AccountNamePosition accountNamePosition, boolean showIcon, boolean showProgress, boolean hidden, boolean paused, boolean dimmed, boolean showExpirationState, boolean showNextCode) {
public void setData(VaultEntry entry, Preferences.CodeGrouping groupSize, ViewMode viewMode, AccountNamePosition accountNamePosition, boolean showIcon, boolean nonUniform, boolean hidden, boolean paused, boolean dimmed, boolean showExpirationState, boolean showNextCode) {
_entry = entry;
_hidden = hidden;
_paused = paused;
_codeGrouping = groupSize;
_viewMode = viewMode;
_nonUniform = nonUniform;

_accountNamePosition = accountNamePosition;
if (viewMode.equals(ViewMode.TILES) && _accountNamePosition == AccountNamePosition.END) {
Expand All @@ -140,7 +146,7 @@ public void setData(VaultEntry entry, Preferences.CodeGrouping groupSize, ViewMo
_favoriteIndicator.setVisibility(_entry.isFavorite() ? View.VISIBLE : View.INVISIBLE);

// only show the progress bar if there is no uniform period and the entry type is TotpInfo
setShowProgress(showProgress);
setShowProgress(nonUniform);

// only show the button if this entry is of type HotpInfo
_buttonRefresh.setVisibility(entry.getInfo() instanceof HotpInfo ? View.VISIBLE : View.GONE);
Expand Down Expand Up @@ -457,6 +463,16 @@ public void startExpirationAnimation() {
final int blinkDuration = 3000;
ValueAnimator delayAnim2 = ValueAnimator.ofFloat(0f, 0f);
delayAnim2.setDuration((long) ((totalStateDuration - blinkDuration) / durationScale));
delayAnim2.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
if (!_nonUniform) {
if (itemView.isShown()) {
VibrationHelper.vibratePattern(itemView.getContext(), VibrationPatterns.EXPIRING);
}
}
}
});

ObjectAnimator alphaAnim = ObjectAnimator.ofFloat(_profileCode, "alpha", 1f, .5f);
alphaAnim.setDuration((long) (500 / durationScale));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,11 +33,13 @@
import com.beemdevelopment.aegis.Preferences;
import com.beemdevelopment.aegis.R;
import com.beemdevelopment.aegis.SortCategory;
import com.beemdevelopment.aegis.VibrationPatterns;
import com.beemdevelopment.aegis.ViewMode;
import com.beemdevelopment.aegis.helpers.AnimationsHelper;
import com.beemdevelopment.aegis.helpers.MetricsHelper;
import com.beemdevelopment.aegis.helpers.SimpleItemTouchHelperCallback;
import com.beemdevelopment.aegis.helpers.UiRefresher;
import com.beemdevelopment.aegis.helpers.VibrationHelper;
import com.beemdevelopment.aegis.otp.TotpInfo;
import com.beemdevelopment.aegis.ui.glide.GlideHelper;
import com.beemdevelopment.aegis.ui.models.ErrorCardInfo;
Expand Down Expand Up @@ -144,6 +146,10 @@ public int getSpanSize(int position) {
@Override
public void onRefresh() {
refresh(false);

if (_recyclerView.isShown()) {
VibrationHelper.vibratePattern(getContext(), VibrationPatterns.REFRESH_CODE);
}
}

@Override
Expand Down
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 @@ -373,6 +373,8 @@
<string name="note" comment="Users can add a note to an entry">Note</string>
<string name="clear">Clear</string>

<string name="pref_haptic_feedback_summary">Make your device vibrate when codes are refreshing</string>
<string name="pref_haptic_feedback_title">Haptic feedback</string>
<string name="pref_highlight_entry_title">Highlight tokens when tapped</string>
<string name="pref_highlight_entry_summary">Make tokens easier to distinguish from each other by temporarily highlighting them when tapped</string>
<string name="pref_minimize_on_copy_title">Minimize on copy</string>
Expand Down
7 changes: 7 additions & 0 deletions app/src/main/res/xml/preferences_behavior.xml
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,13 @@
android:title="@string/pref_copy_behavior_title"
app:iconSpaceReserved="false"/>

<androidx.preference.SwitchPreferenceCompat
android:defaultValue="true"
android:key="pref_haptic_feedback"
android:title="@string/pref_haptic_feedback_title"
android:summary="@string/pref_haptic_feedback_summary"
app:iconSpaceReserved="false"/>

<androidx.preference.SwitchPreferenceCompat
android:defaultValue="false"
android:key="pref_highlight_entry"
Expand Down

0 comments on commit 7197878

Please sign in to comment.