Add ability to change copy behavior

This commit is contained in:
Michael Schättgen 2023-08-16 01:05:26 +02:00
parent 51897a4ab7
commit 3ff242e6b6
45 changed files with 118 additions and 107 deletions

View file

@ -0,0 +1,17 @@
package com.beemdevelopment.aegis;
public enum CopyBehavior {
NEVER,
SINGLETAP,
DOUBLETAP;
private static CopyBehavior[] _values;
static {
_values = values();
}
public static CopyBehavior fromInteger(int x) {
return _values[x];
}
}

View file

@ -45,6 +45,22 @@ public class Preferences {
if (getPasswordReminderTimestamp().getTime() == 0) {
resetPasswordReminderTimestamp();
}
migratePreferences();
}
public void migratePreferences() {
// Change copy on tap to copy behavior to new preference and delete the old key
String prefCopyOnTapKey = "pref_copy_on_tap";
if (_prefs.contains(prefCopyOnTapKey)) {
boolean isCopyOnTapEnabled = _prefs.getBoolean(prefCopyOnTapKey, false);
if (isCopyOnTapEnabled) {
setCopyBehavior(CopyBehavior.SINGLETAP);
}
_prefs.edit().remove(prefCopyOnTapKey).apply();
}
}
public boolean isTapToRevealEnabled() {
@ -448,8 +464,12 @@ public class Preferences {
_prefs.edit().putBoolean("pref_warn_time_sync", enabled).apply();
}
public boolean isCopyOnTapEnabled() {
return _prefs.getBoolean("pref_copy_on_tap", false);
public CopyBehavior getCopyBehavior() {
return CopyBehavior.fromInteger(_prefs.getInt("pref_current_copy_behavior", 0));
}
public void setCopyBehavior(CopyBehavior copyBehavior) {
_prefs.edit().putInt("pref_current_copy_behavior", copyBehavior.ordinal()).apply();
}
public boolean isMinimizeOnCopyEnabled() {

View file

@ -35,6 +35,7 @@ import androidx.appcompat.app.AlertDialog;
import androidx.appcompat.view.ActionMode;
import androidx.appcompat.widget.SearchView;
import com.beemdevelopment.aegis.CopyBehavior;
import com.beemdevelopment.aegis.AccountNamePosition;
import com.beemdevelopment.aegis.Preferences;
import com.beemdevelopment.aegis.R;
@ -140,7 +141,7 @@ public class MainActivity extends AegisActivity implements EntryListView.Listene
_entryListView.setTapToRevealTime(_prefs.getTapToRevealTime());
_entryListView.setSortCategory(_prefs.getCurrentSortCategory(), false);
_entryListView.setViewMode(_prefs.getCurrentViewMode());
_entryListView.setIsCopyOnTapEnabled(_prefs.isCopyOnTapEnabled());
_entryListView.setCopyBehavior(_prefs.getCopyBehavior());
_entryListView.setPrefGroupFilter(_prefs.getGroupFilter());
FloatingActionButton fab = findViewById(R.id.fab);
@ -278,7 +279,7 @@ public class MainActivity extends AegisActivity implements EntryListView.Listene
boolean tapToReveal = _prefs.isTapToRevealEnabled();
int tapToRevealTime = _prefs.getTapToRevealTime();
ViewMode viewMode = _prefs.getCurrentViewMode();
boolean copyOnTap = _prefs.isCopyOnTapEnabled();
CopyBehavior copyBehavior = _prefs.getCopyBehavior();
_entryListView.setAccountNamePosition(accountNamePosition);
_entryListView.setShowIcon(showIcons);
_entryListView.setCodeGroupSize(codeGroupSize);
@ -287,7 +288,7 @@ public class MainActivity extends AegisActivity implements EntryListView.Listene
_entryListView.setTapToReveal(tapToReveal);
_entryListView.setTapToRevealTime(tapToRevealTime);
_entryListView.setViewMode(viewMode);
_entryListView.setIsCopyOnTapEnabled(copyOnTap);
_entryListView.setCopyBehavior(copyBehavior);
_entryListView.refresh(true);
}
}

View file

@ -2,9 +2,12 @@ package com.beemdevelopment.aegis.ui.fragments.preferences;
import android.os.Bundle;
import androidx.appcompat.app.AlertDialog;
import androidx.preference.Preference;
import com.beemdevelopment.aegis.CopyBehavior;
import com.beemdevelopment.aegis.R;
import com.beemdevelopment.aegis.ui.dialogs.Dialogs;
public class BehaviorPreferencesFragment extends PreferencesFragment {
private Preference _entryPausePreference;
@ -14,9 +17,24 @@ public class BehaviorPreferencesFragment extends PreferencesFragment {
super.onCreatePreferences(savedInstanceState, rootKey);
addPreferencesFromResource(R.xml.preferences_behavior);
Preference copyOnTapPreference = requirePreference("pref_copy_on_tap");
copyOnTapPreference.setOnPreferenceChangeListener((preference, newValue) -> {
getResult().putExtra("needsRefresh", true);
int currentCopyBehavior = _prefs.getCopyBehavior().ordinal();
Preference copyBehaviorPreference = requirePreference("pref_copy_behavior");
copyBehaviorPreference.setSummary(String.format("%s: %s", getString(R.string.selected), getResources().getStringArray(R.array.copy_behavior_titles)[currentCopyBehavior]));
copyBehaviorPreference.setOnPreferenceClickListener(preference -> {
int currentCopyBehavior1 = _prefs.getCopyBehavior().ordinal();
Dialogs.showSecureDialog(new AlertDialog.Builder(requireContext())
.setTitle(getString(R.string.choose_copy_behavior))
.setSingleChoiceItems(R.array.copy_behavior_titles, currentCopyBehavior1, (dialog, which) -> {
int i = ((AlertDialog) dialog).getListView().getCheckedItemPosition();
_prefs.setCopyBehavior(CopyBehavior.fromInteger(i));
copyBehaviorPreference.setSummary(String.format("%s: %s", getString(R.string.selected), getResources().getStringArray(R.array.copy_behavior_titles)[i]));
getResult().putExtra("needsRefresh", true);
dialog.dismiss();
})
.setNegativeButton(android.R.string.cancel, null)
.create());
return true;
});

View file

@ -10,12 +10,14 @@ import android.text.style.StyleSpan;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewConfiguration;
import android.view.ViewGroup;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
import com.beemdevelopment.aegis.CopyBehavior;
import com.beemdevelopment.aegis.AccountNamePosition;
import com.beemdevelopment.aegis.R;
import com.beemdevelopment.aegis.Preferences;
@ -46,7 +48,7 @@ public class EntryAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder>
private List<VaultEntry> _selectedEntries;
private Map<UUID, Integer> _usageCounts;
private VaultEntry _focusedEntry;
private VaultEntry _copiedEntry;
private VaultEntry _clickedEntry;
private Preferences.CodeGrouping _codeGroupSize;
private AccountNamePosition _accountNamePosition;
private boolean _showIcon;
@ -54,7 +56,7 @@ public class EntryAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder>
private boolean _tempHighlightEntry;
private boolean _tapToReveal;
private int _tapToRevealTime;
private boolean _copyOnTap;
private CopyBehavior _copyBehavior;
private List<String> _groupFilter;
private SortCategory _sortCategory;
private ViewMode _viewMode;
@ -62,6 +64,7 @@ public class EntryAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder>
private boolean _isPeriodUniform = true;
private int _uniformPeriod = -1;
private Handler _dimHandler;
private Handler _doubleTapHandler;
private boolean _pauseFocused;
// keeps track of the EntryHolders that are currently bound
@ -74,6 +77,7 @@ public class EntryAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder>
_groupFilter = new ArrayList<>();
_holders = new ArrayList<>();
_dimHandler = new Handler();
_doubleTapHandler = new Handler();
_view = view;
}
@ -112,9 +116,7 @@ public class EntryAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder>
_tempHighlightEntry = highlightEntry;
}
public void setIsCopyOnTapEnabled(boolean enabled) {
_copyOnTap = enabled;
}
public void setCopyBehavior(CopyBehavior copyBehavior) { _copyBehavior = copyBehavior; }
public void setPauseFocused(boolean pauseFocused) {
_pauseFocused = pauseFocused;
@ -436,26 +438,36 @@ public class EntryAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder>
boolean handled = false;
if (_selectedEntries.isEmpty()) {
boolean copiedThisClick = false;
if (_copyOnTap && !entryHolder.isHidden() && !(entry == _copiedEntry)) {
_view.onEntryCopy(entry);
entryHolder.animateCopyText();
_copiedEntry = entry;
copiedThisClick = true;
handled = true;
}
if (_highlightEntry || _tempHighlightEntry || _tapToReveal) {
if (_focusedEntry == entry && !copiedThisClick) {
if (_focusedEntry == entry) {
resetFocus();
_copiedEntry = null;
handled = true;
// Prevent copying when singletap is set and focus is reset
handled = _copyBehavior == CopyBehavior.SINGLETAP;
} else {
focusEntry(entry, _tapToRevealTime);
}
} else {
_copiedEntry = null;
}
switch (_copyBehavior) {
case SINGLETAP:
if (!handled) {
_view.onEntryCopy(entry);
entryHolder.animateCopyText();
_clickedEntry = null;
}
break;
case DOUBLETAP:
_doubleTapHandler.postDelayed(() -> _clickedEntry = null, ViewConfiguration.getDoubleTapTimeout());
if(entry == _clickedEntry) {
_view.onEntryCopy(entry);
entryHolder.animateCopyText();
_clickedEntry = null;
} else {
_clickedEntry = entry;
}
break;
}
incrementUsageCount(entry);

View file

@ -23,6 +23,7 @@ import androidx.recyclerview.widget.ItemTouchHelper;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import com.beemdevelopment.aegis.CopyBehavior;
import com.beemdevelopment.aegis.AccountNamePosition;
import com.beemdevelopment.aegis.Preferences;
import com.beemdevelopment.aegis.R;
@ -174,8 +175,8 @@ public class EntryListView extends Fragment implements EntryAdapter.Listener {
_touchCallback.setIsLongPressDragEnabled(enabled && _adapter.isDragAndDropAllowed());
}
public void setIsCopyOnTapEnabled(boolean enabled) {
_adapter.setIsCopyOnTapEnabled(enabled);
public void setCopyBehavior(CopyBehavior copyBehavior) {
_adapter.setCopyBehavior(copyBehavior);
}
public void setActionModeState(boolean enabled, VaultEntry entry) {