From 82cc4760cf94cb9734e36ce745d51ba376423363 Mon Sep 17 00:00:00 2001 From: MrLetsplay Date: Wed, 20 Sep 2023 19:53:34 +0200 Subject: [PATCH] Rework OTP editing (WIP) --- .../cringe_authenticator/MainActivity.java | 54 ++++++- .../fragment/GroupFragment.java | 134 +++++++++++------- .../fragment/MenuFragment.java | 27 +--- .../grouplist/GroupListAdapter.java | 5 +- .../grouplist/GroupListItem.java | 2 +- .../otplist/OTPListAdapter.java | 108 +++++++++++--- .../otplist/OTPListItem.java | 19 +++ .../cringe_authenticator/util/DialogUtil.java | 23 ++- .../main/res/drawable/baseline_compare_24.xml | 2 +- app/src/main/res/layout/fragment_group.xml | 5 +- app/src/main/res/layout/fragment_menu.xml | 7 + app/src/main/res/layout/menu_item.xml | 4 +- app/src/main/res/layout/otp_code.xml | 12 +- app/src/main/res/menu/menu_otps.xml | 23 +++ app/src/main/res/menu/menu_otps_edit.xml | 44 ++++++ app/src/main/res/values-de-rDE/strings.xml | 6 +- app/src/main/res/values/colors.xml | 2 + app/src/main/res/values/strings.xml | 8 +- 18 files changed, 356 insertions(+), 129 deletions(-) create mode 100644 app/src/main/res/menu/menu_otps.xml create mode 100644 app/src/main/res/menu/menu_otps_edit.xml diff --git a/app/src/main/java/com/cringe_studios/cringe_authenticator/MainActivity.java b/app/src/main/java/com/cringe_studios/cringe_authenticator/MainActivity.java index 1f8d951..b14e80b 100644 --- a/app/src/main/java/com/cringe_studios/cringe_authenticator/MainActivity.java +++ b/app/src/main/java/com/cringe_studios/cringe_authenticator/MainActivity.java @@ -167,6 +167,13 @@ public class MainActivity extends BaseActivity { return true; } + if(fragment instanceof GroupFragment) { + GroupFragment frag = (GroupFragment) fragment; + getMenuInflater().inflate(frag.isEditing() ? R.menu.menu_otps_edit : R.menu.menu_otps, menu); + if(frag.isEditing() && frag.hasSelectedMultipleItems()) menu.removeItem(R.id.action_edit_group); + return true; + } + getMenuInflater().inflate(R.menu.menu_main, menu); return true; } @@ -197,6 +204,14 @@ public class MainActivity extends BaseActivity { } } + if(fragment instanceof GroupFragment) { + GroupFragment groupFragment = (GroupFragment) fragment; + if(groupFragment.isEditing()) { + groupFragment.finishEditing(); + return; + } + } + if(!(fragment instanceof HomeFragment)) { NavigationUtil.navigate(this, HomeFragment.class, null); } @@ -256,7 +271,7 @@ public class MainActivity extends BaseActivity { if(!(fragment instanceof GroupFragment)) return; ((GroupFragment) fragment).addOTP(data); - }, () -> inputCode(), false); + }, false); } private void showHOTPDialog() { @@ -265,7 +280,7 @@ public class MainActivity extends BaseActivity { if(!(fragment instanceof GroupFragment)) return; ((GroupFragment) fragment).addOTP(data); - }, () -> inputCode(), false); + }, false); } public void addGroup(MenuItem item) { @@ -289,6 +304,41 @@ public class MainActivity extends BaseActivity { } } + public void addOTP(MenuItem item) { + Fragment frag = NavigationUtil.getCurrentFragment(this); + if(frag instanceof GroupFragment) { + ((GroupFragment) frag).addOTP(); + } + } + + public void viewOTP(MenuItem item) { + Fragment frag = NavigationUtil.getCurrentFragment(this); + if(frag instanceof GroupFragment) { + ((GroupFragment) frag).viewOTP(); + } + } + + public void editOTP(MenuItem item) { + Fragment frag = NavigationUtil.getCurrentFragment(this); + if(frag instanceof GroupFragment) { + ((GroupFragment) frag).editOTP(); + } + } + + public void moveOTP(MenuItem item) { + Fragment frag = NavigationUtil.getCurrentFragment(this); + if(frag instanceof GroupFragment) { + ((GroupFragment) frag).moveOTP(); + } + } + + public void deleteOTP(MenuItem item) { + Fragment frag = NavigationUtil.getCurrentFragment(this); + if(frag instanceof GroupFragment) { + ((GroupFragment) frag).deleteOTP(); + } + } + @Override protected void onPause() { super.onPause(); diff --git a/app/src/main/java/com/cringe_studios/cringe_authenticator/fragment/GroupFragment.java b/app/src/main/java/com/cringe_studios/cringe_authenticator/fragment/GroupFragment.java index 8ead607..50a4800 100644 --- a/app/src/main/java/com/cringe_studios/cringe_authenticator/fragment/GroupFragment.java +++ b/app/src/main/java/com/cringe_studios/cringe_authenticator/fragment/GroupFragment.java @@ -5,6 +5,7 @@ import android.os.Bundle; import android.os.Handler; import android.os.Looper; import android.view.LayoutInflater; +import android.view.MenuItem; import android.view.View; import android.view.ViewGroup; @@ -16,6 +17,7 @@ import androidx.recyclerview.widget.RecyclerView; import com.cringe_studios.cringe_authenticator.R; import com.cringe_studios.cringe_authenticator.crypto.CryptoException; import com.cringe_studios.cringe_authenticator.databinding.FragmentGroupBinding; +import com.cringe_studios.cringe_authenticator.grouplist.GroupListItem; import com.cringe_studios.cringe_authenticator.model.OTPData; import com.cringe_studios.cringe_authenticator.otplist.OTPListAdapter; import com.cringe_studios.cringe_authenticator.otplist.OTPListItem; @@ -63,8 +65,7 @@ public class GroupFragment extends NamedFragment { FabUtil.showFabs(requireActivity()); - otpListAdapter = new OTPListAdapter(requireContext(), data -> showOTPDialog(data)); - + otpListAdapter = new OTPListAdapter(requireContext(), binding.itemList); binding.itemList.setAdapter(otpListAdapter); loadOTPs(); @@ -80,52 +81,6 @@ public class GroupFragment extends NamedFragment { return binding.getRoot(); } - private void showOTPDialog(OTPData data) { - new StyledDialogBuilder(requireContext()) - .setTitle(R.string.edit_otp_title) - .setItems(R.array.view_edit_move_delete, (dialog, which) -> { - switch(which) { - case 0: - DialogUtil.showViewCodeDialog(getLayoutInflater(), data, () -> showOTPDialog(data)); - break; - case 1: - DialogUtil.showEditCodeDialog(getLayoutInflater(), data, newData -> { - otpListAdapter.replace(data, newData); - saveOTPs(); - }, () -> showOTPDialog(data)); - break; - case 2: - DialogUtil.showChooseGroupDialog(requireContext(), group -> { - OTPDatabase.promptLoadDatabase(requireActivity(), () -> { - try { - OTPDatabase.getLoadedDatabase().addOTP(group, data); - OTPDatabase.saveDatabase(requireContext(), SettingsUtil.getCryptoParameters(requireContext())); - otpListAdapter.remove(data); - saveOTPs(); - } catch (OTPDatabaseException | CryptoException e) { - DialogUtil.showErrorDialog(requireContext(), e.toString()); - } - }, null); - saveOTPs(); - }, null); - break; - case 3: - new StyledDialogBuilder(requireContext()) - .setTitle(R.string.otp_delete_title) - .setMessage(R.string.otp_delete_message) - .setPositiveButton(R.string.yes, (d, w) -> { - otpListAdapter.remove(data); - saveOTPs(); - }) - .setNegativeButton(R.string.no, (d, w) -> {}) - .show(); - break; - } - }) - .setNegativeButton(R.string.cancel, (dialog, which) -> {}) - .show(); - } - private void saveOTPs() { OTPDatabase.promptLoadDatabase(requireActivity(), () -> { try { @@ -178,6 +133,89 @@ public class GroupFragment extends NamedFragment { } } + public void addOTP() { + // TODO + } + + public void viewOTP() { + if(!otpListAdapter.isEditing()) return; + + List items = otpListAdapter.getSelectedCodes(); + if(items.size() != 1) return; + + OTPData data = items.get(0).getOTPData(); + DialogUtil.showViewCodeDialog(getLayoutInflater(), data); + } + + public void editOTP() { + if(!otpListAdapter.isEditing()) return; + + List items = otpListAdapter.getSelectedCodes(); + if(items.size() != 1) return; + + OTPData data = items.get(0).getOTPData(); + DialogUtil.showEditCodeDialog(getLayoutInflater(), data, newData -> { + otpListAdapter.replace(data, newData); + saveOTPs(); + otpListAdapter.finishEditing(); + }); + } + + public void moveOTP() { + if(!otpListAdapter.isEditing()) return; + + List items = otpListAdapter.getSelectedCodes(); + + DialogUtil.showChooseGroupDialog(requireContext(), group -> { + OTPDatabase.promptLoadDatabase(requireActivity(), () -> { + try { + for(OTPListItem item : items) { + OTPData data = item.getOTPData(); + OTPDatabase.getLoadedDatabase().addOTP(group, data); + OTPDatabase.saveDatabase(requireContext(), SettingsUtil.getCryptoParameters(requireContext())); + otpListAdapter.remove(data); + } + + saveOTPs(); + } catch (OTPDatabaseException | CryptoException e) { + DialogUtil.showErrorDialog(requireContext(), e.toString()); + } + }, null); + saveOTPs(); + }, null); + } + + public void deleteOTP() { + if(!otpListAdapter.isEditing()) return; + + List items = otpListAdapter.getSelectedCodes(); + + new StyledDialogBuilder(requireContext()) + .setTitle(R.string.otp_delete_title) + .setMessage(R.string.otp_delete_message) + .setPositiveButton(R.string.yes, (d, w) -> { + for(OTPListItem item : items) { + otpListAdapter.remove(item.getOTPData()); + } + + saveOTPs(); + }) + .setNegativeButton(R.string.no, (d, w) -> {}) + .show(); + } + + public boolean isEditing() { + return otpListAdapter.isEditing(); + } + + public void finishEditing() { + otpListAdapter.finishEditing(); + } + + public boolean hasSelectedMultipleItems() { + return otpListAdapter.getSelectedCodes().size() > 1; + } + @Override public void onDestroyView() { super.onDestroyView(); diff --git a/app/src/main/java/com/cringe_studios/cringe_authenticator/fragment/MenuFragment.java b/app/src/main/java/com/cringe_studios/cringe_authenticator/fragment/MenuFragment.java index da897de..cba533f 100644 --- a/app/src/main/java/com/cringe_studios/cringe_authenticator/fragment/MenuFragment.java +++ b/app/src/main/java/com/cringe_studios/cringe_authenticator/fragment/MenuFragment.java @@ -54,31 +54,6 @@ public class MenuFragment extends NamedFragment { return binding.getRoot(); } - private void showGroupDialog(String group) { - new StyledDialogBuilder(requireContext()) - .setTitle(R.string.edit_group_title) - .setItems(R.array.rename_delete, (dialog, which) -> { - switch(which) { - case 0: - DialogUtil.showCreateGroupDialog(getLayoutInflater(), SettingsUtil.getGroupName(requireContext(), group), newName -> { - renameGroup(group, newName); - }, null); - - break; - case 1: - new StyledDialogBuilder(requireContext()) - .setTitle(R.string.group_delete_title) - .setMessage(R.string.group_delete_message) - .setPositiveButton(R.string.yes, (d, w) -> removeGroup(group)) - .setNegativeButton(R.string.no, (d, w) -> {}) - .show(); - break; - } - }) - .setNegativeButton(R.string.cancel, (dialog, which) -> {}) - .show(); - } - private void loadGroups() { List items = SettingsUtil.getGroups(requireContext()); @@ -114,7 +89,7 @@ public class MenuFragment extends NamedFragment { new StyledDialogBuilder(requireContext()) .setTitle(R.string.group_delete_title) - .setMessage("Delete selected groups?") + .setMessage(R.string.group_delete_message) .setPositiveButton(R.string.yes, (d, w) -> { for(GroupListItem item : groupListAdapter.getSelectedGroups()) { removeGroup(item.getGroupId()); diff --git a/app/src/main/java/com/cringe_studios/cringe_authenticator/grouplist/GroupListAdapter.java b/app/src/main/java/com/cringe_studios/cringe_authenticator/grouplist/GroupListAdapter.java index bd66371..c22f84a 100644 --- a/app/src/main/java/com/cringe_studios/cringe_authenticator/grouplist/GroupListAdapter.java +++ b/app/src/main/java/com/cringe_studios/cringe_authenticator/grouplist/GroupListAdapter.java @@ -68,6 +68,7 @@ public class GroupListAdapter extends RecyclerView.Adapter { String group = items.get(position); holder.setGroupId(group); + holder.setSelected(false); holder.getBinding().button.setText(SettingsUtil.getGroupName(context, group)); @@ -80,10 +81,6 @@ public class GroupListAdapter extends RecyclerView.Adapter { ((BaseActivity) context).invalidateMenu(); } }); - /*holder.getBinding().button.setOnLongClickListener(view -> { - showMenuCallback.accept(group); - return true; - });*/ holder.getBinding().button.setOnLongClickListener(view -> { if(editing) return true; diff --git a/app/src/main/java/com/cringe_studios/cringe_authenticator/grouplist/GroupListItem.java b/app/src/main/java/com/cringe_studios/cringe_authenticator/grouplist/GroupListItem.java index 3451867..b0a6231 100644 --- a/app/src/main/java/com/cringe_studios/cringe_authenticator/grouplist/GroupListItem.java +++ b/app/src/main/java/com/cringe_studios/cringe_authenticator/grouplist/GroupListItem.java @@ -40,7 +40,7 @@ public class GroupListItem extends RecyclerView.ViewHolder { this.selected = selected; if(selected) { - binding.menuItemBackground.setBackground(new ColorDrawable(0xFFFF00FF)); + binding.menuItemBackground.setBackground(new ColorDrawable(binding.getRoot().getContext().getResources().getColor(R.color.selected_highlight))); }else { binding.menuItemBackground.setBackground(null); } diff --git a/app/src/main/java/com/cringe_studios/cringe_authenticator/otplist/OTPListAdapter.java b/app/src/main/java/com/cringe_studios/cringe_authenticator/otplist/OTPListAdapter.java index 8ac328d..e3f1f6f 100644 --- a/app/src/main/java/com/cringe_studios/cringe_authenticator/otplist/OTPListAdapter.java +++ b/app/src/main/java/com/cringe_studios/cringe_authenticator/otplist/OTPListAdapter.java @@ -11,8 +11,10 @@ import android.widget.Toast; import androidx.annotation.NonNull; import androidx.core.util.Consumer; +import androidx.recyclerview.widget.ItemTouchHelper; import androidx.recyclerview.widget.RecyclerView; +import com.cringe_studios.cringe_authenticator.BaseActivity; import com.cringe_studios.cringe_authenticator.R; import com.cringe_studios.cringe_authenticator.databinding.OtpCodeBinding; import com.cringe_studios.cringe_authenticator.model.OTPData; @@ -21,26 +23,29 @@ import com.cringe_studios.cringe_authenticator_library.OTPException; import com.cringe_studios.cringe_authenticator_library.OTPType; import java.util.ArrayList; +import java.util.Collections; import java.util.List; public class OTPListAdapter extends RecyclerView.Adapter { private Context context; + private RecyclerView recyclerView; + private LayoutInflater inflater; private List items; private Handler handler; - private Consumer showMenuCallback; + private boolean editing; - public OTPListAdapter(Context context, Consumer showMenuCallback) { + public OTPListAdapter(Context context, RecyclerView recyclerView) { this.context = context; + this.recyclerView = recyclerView; this.inflater = LayoutInflater.from(context); this.items = new ArrayList<>(); this.handler = new Handler(Looper.getMainLooper()); - this.showMenuCallback = showMenuCallback; } @NonNull @@ -55,32 +60,44 @@ public class OTPListAdapter extends RecyclerView.Adapter { OTPData data = items.get(position); holder.setOTPData(data); + holder.setSelected(false); + holder.getBinding().label.setText(String.format("%s%s", data.getIssuer() == null || data.getIssuer().isEmpty() ? "" : data.getIssuer() + ": ", data.getName())); holder.getBinding().progress.setVisibility(data.getType() == OTPType.TOTP ? View.VISIBLE : View.INVISIBLE); holder.getBinding().getRoot().setOnClickListener(view -> { - if(!view.isClickable()) return; + if(!editing) { + if (!view.isClickable()) return; - if(data.getType() != OTPType.HOTP) return; + if (data.getType() != OTPType.HOTP) return; - // Click delay for HOTP - view.setClickable(false); - data.incrementCounter(); + // Click delay for HOTP + view.setClickable(false); + data.incrementCounter(); - try { - holder.getBinding().otpCode.setText(OTPListItem.formatCode(data.getPin())); - }catch(OTPException e) { - DialogUtil.showErrorDialog(context, context.getString(R.string.otp_add_error, e.getMessage() != null ? e.getMessage() : e.toString())); - return; + try { + holder.getBinding().otpCode.setText(OTPListItem.formatCode(data.getPin())); + } catch (OTPException e) { + DialogUtil.showErrorDialog(context, context.getString(R.string.otp_add_error, e.getMessage() != null ? e.getMessage() : e.toString())); + return; + } + + Toast.makeText(view.getContext(), R.string.hotp_generated_new_code, Toast.LENGTH_SHORT).show(); + + handler.postDelayed(() -> view.setClickable(true), 5000); + }else { + holder.setSelected(!holder.isSelected()); + if(getSelectedCodes().isEmpty()) editing = false; + ((BaseActivity) context).invalidateMenu(); } - - Toast.makeText(view.getContext(), R.string.hotp_generated_new_code, Toast.LENGTH_SHORT).show(); - - handler.postDelayed(() -> view.setClickable(true), 5000); }); holder.getBinding().getRoot().setOnLongClickListener(view -> { - showMenuCallback.accept(holder.getOTPData()); + if(editing) return true; + + holder.setSelected(true); + editing = true; + ((BaseActivity) context).invalidateMenu(); return true; }); } @@ -113,4 +130,59 @@ public class OTPListAdapter extends RecyclerView.Adapter { notifyItemRemoved(index); } + public boolean isEditing() { + return editing; + } + + public void finishEditing() { + if(!editing) return; + + editing = false; + for(OTPListItem item : getSelectedCodes()) { + item.setSelected(false); + } + + ((BaseActivity) context).invalidateMenu(); + } + + public List getSelectedCodes() { + if(!editing) return Collections.emptyList(); + + List selected = new ArrayList<>(); + for(int i = 0; i < items.size(); i++) { + OTPListItem vh = (OTPListItem) recyclerView.findViewHolderForAdapterPosition(i); + if(vh == null) continue; + if(vh.isSelected()) selected.add(vh); + } + return selected; + } + + private void attachTouchHelper(RecyclerView view) { + new ItemTouchHelper(new OTPListAdapter.TouchHelperCallback()).attachToRecyclerView(view); + } + + private class TouchHelperCallback extends ItemTouchHelper.Callback { + + @Override + public int getMovementFlags(@NonNull RecyclerView recyclerView, @NonNull RecyclerView.ViewHolder viewHolder) { + return makeMovementFlags(ItemTouchHelper.UP | ItemTouchHelper.DOWN, 0); + } + + @Override + public boolean onMove(@NonNull RecyclerView recyclerView, @NonNull RecyclerView.ViewHolder viewHolder, @NonNull RecyclerView.ViewHolder target) { + Collections.swap(items, viewHolder.getAdapterPosition(), target.getAdapterPosition()); + notifyItemMoved(viewHolder.getAdapterPosition(), target.getAdapterPosition()); + //saveGroups.run(); + return true; + } + + @Override + public void onSwiped(@NonNull RecyclerView.ViewHolder viewHolder, int direction) {} + + @Override + public boolean isLongPressDragEnabled() { + return editing; + } + } + } diff --git a/app/src/main/java/com/cringe_studios/cringe_authenticator/otplist/OTPListItem.java b/app/src/main/java/com/cringe_studios/cringe_authenticator/otplist/OTPListItem.java index 25a7c13..739d7a8 100644 --- a/app/src/main/java/com/cringe_studios/cringe_authenticator/otplist/OTPListItem.java +++ b/app/src/main/java/com/cringe_studios/cringe_authenticator/otplist/OTPListItem.java @@ -1,8 +1,11 @@ package com.cringe_studios.cringe_authenticator.otplist; +import android.graphics.drawable.ColorDrawable; + import androidx.annotation.NonNull; import androidx.recyclerview.widget.RecyclerView; +import com.cringe_studios.cringe_authenticator.R; import com.cringe_studios.cringe_authenticator.databinding.OtpCodeBinding; import com.cringe_studios.cringe_authenticator.model.OTPData; @@ -12,6 +15,8 @@ public class OTPListItem extends RecyclerView.ViewHolder { private OTPData otpData; + private boolean selected; + public OTPListItem(OtpCodeBinding binding) { super(binding.getRoot()); this.binding = binding; @@ -43,4 +48,18 @@ public class OTPListItem extends RecyclerView.ViewHolder { return b.toString(); } + public void setSelected(boolean selected) { + this.selected = selected; + + if(selected) { + binding.otpCodeBackground.setBackground(new ColorDrawable(binding.getRoot().getContext().getResources().getColor(R.color.selected_highlight))); + }else { + binding.otpCodeBackground.setBackground(null); + } + } + + public boolean isSelected() { + return selected; + } + } diff --git a/app/src/main/java/com/cringe_studios/cringe_authenticator/util/DialogUtil.java b/app/src/main/java/com/cringe_studios/cringe_authenticator/util/DialogUtil.java index e450734..4bc238c 100644 --- a/app/src/main/java/com/cringe_studios/cringe_authenticator/util/DialogUtil.java +++ b/app/src/main/java/com/cringe_studios/cringe_authenticator/util/DialogUtil.java @@ -28,12 +28,11 @@ public class DialogUtil { private static final Integer[] DIGITS = new Integer[]{6, 7, 8, 9, 10, 11, 12}; - private static void showCodeDialog(Context context, View view, DialogCallback ok, Runnable back) { + private static void showCodeDialog(Context context, View view, DialogCallback ok) { AlertDialog dialog = new StyledDialogBuilder(context) .setTitle(R.string.code_input_title) .setView(view) .setPositiveButton(R.string.ok, (btnView, which) -> {}) - .setNeutralButton(R.string.back, (btnView, which) -> back.run()) .setNegativeButton(R.string.cancel, (btnView, which) -> {}) .create(); @@ -60,7 +59,7 @@ public class DialogUtil { showErrorDialog(context, errorMessage, null); } - public static void showTOTPDialog(LayoutInflater inflater, OTPData initialData, Consumer callback, Runnable back, boolean view) { + public static void showTOTPDialog(LayoutInflater inflater, OTPData initialData, Consumer callback, boolean view) { Context context = inflater.getContext(); DialogInputCodeTotpBinding binding = DialogInputCodeTotpBinding.inflate(inflater); @@ -122,10 +121,10 @@ public class DialogUtil { showErrorDialog(context, context.getString(R.string.input_code_invalid_number)); return false; } - }, back); + }); } - public static void showHOTPDialog(LayoutInflater inflater, OTPData initialData, Consumer callback, Runnable back, boolean view) { + public static void showHOTPDialog(LayoutInflater inflater, OTPData initialData, Consumer callback, boolean view) { Context context = inflater.getContext(); DialogInputCodeHotpBinding binding = DialogInputCodeHotpBinding.inflate(inflater); @@ -187,21 +186,21 @@ public class DialogUtil { showErrorDialog(context, context.getString(R.string.input_code_invalid_number)); return false; } - }, back); + }); } - public static void showViewCodeDialog(LayoutInflater inflater, @NonNull OTPData initialData, Runnable back) { + public static void showViewCodeDialog(LayoutInflater inflater, @NonNull OTPData initialData) { // TODO: use better dialogs switch(initialData.getType()) { - case HOTP: showHOTPDialog(inflater, initialData, d -> {}, back, true); break; - case TOTP: showTOTPDialog(inflater, initialData, d -> {}, back, true); break; + case HOTP: showHOTPDialog(inflater, initialData, d -> {}, true); break; + case TOTP: showTOTPDialog(inflater, initialData, d -> {}, true); break; } } - public static void showEditCodeDialog(LayoutInflater inflater, @NonNull OTPData initialData, Consumer callback, Runnable back) { + public static void showEditCodeDialog(LayoutInflater inflater, @NonNull OTPData initialData, Consumer callback) { switch(initialData.getType()) { - case HOTP: showHOTPDialog(inflater, initialData, callback, back, false); break; - case TOTP: showTOTPDialog(inflater, initialData, callback, back, false); break; + case HOTP: showHOTPDialog(inflater, initialData, callback, false); break; + case TOTP: showTOTPDialog(inflater, initialData, callback, false); break; } } diff --git a/app/src/main/res/drawable/baseline_compare_24.xml b/app/src/main/res/drawable/baseline_compare_24.xml index 929ab22..125d105 100644 --- a/app/src/main/res/drawable/baseline_compare_24.xml +++ b/app/src/main/res/drawable/baseline_compare_24.xml @@ -1,4 +1,4 @@ - diff --git a/app/src/main/res/layout/fragment_group.xml b/app/src/main/res/layout/fragment_group.xml index 881a257..5a17a0d 100644 --- a/app/src/main/res/layout/fragment_group.xml +++ b/app/src/main/res/layout/fragment_group.xml @@ -8,8 +8,7 @@ + android:layout_height="match_parent"> diff --git a/app/src/main/res/layout/fragment_menu.xml b/app/src/main/res/layout/fragment_menu.xml index 923b88f..8822237 100644 --- a/app/src/main/res/layout/fragment_menu.xml +++ b/app/src/main/res/layout/fragment_menu.xml @@ -35,5 +35,12 @@ android:orientation="vertical" app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager" /> + + \ No newline at end of file diff --git a/app/src/main/res/layout/menu_item.xml b/app/src/main/res/layout/menu_item.xml index 287bdbf..3fc0411 100644 --- a/app/src/main/res/layout/menu_item.xml +++ b/app/src/main/res/layout/menu_item.xml @@ -7,9 +7,7 @@ android:orientation="vertical" android:padding="5dp" android:paddingStart="16dp" - android:paddingEnd="16dp" - android:clickable="true" - android:focusable="true" > + android:paddingEnd="16dp" > + android:padding="5dp" + android:paddingStart="16dp" + android:paddingEnd="16dp"> + android:orientation="horizontal" + android:paddingTop="5dp" + android:paddingBottom="5dp" + android:background="@drawable/button_themed"> + + + + + \ No newline at end of file diff --git a/app/src/main/res/menu/menu_otps_edit.xml b/app/src/main/res/menu/menu_otps_edit.xml new file mode 100644 index 0000000..7513df8 --- /dev/null +++ b/app/src/main/res/menu/menu_otps_edit.xml @@ -0,0 +1,44 @@ + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/values-de-rDE/strings.xml b/app/src/main/res/values-de-rDE/strings.xml index e0308c8..99bb987 100644 --- a/app/src/main/res/values-de-rDE/strings.xml +++ b/app/src/main/res/values-de-rDE/strings.xml @@ -21,8 +21,8 @@ Scannen fehlgeschlagen: %s Abspielen des Videos fehlgeschlagen OTP bearbeiten - Gruppe(n) löschen - Willst du die ausgewählte(n) Gruppe(n) löschen?\n\nHinweis: Dadurch werden alle darin enthaltenen OTPs gelöscht! + Gruppen löschen + Willst du die ausgewählten Gruppen löschen?\n\nHinweis: Dadurch werden alle darin enthaltenen OTPs gelöscht! Neuen Code generiert Hinzufügen des Codes fehlgeschlagen Code eingeben @@ -30,7 +30,7 @@ Ungültige Zahl Zurück OTP löschen - Willst du das OTP löschen? + Willst du die ausgewählten OTPs löschen? Gruppe bearbeiten Intro-Video zeigen Biometrische Authentifizierung aktivieren diff --git a/app/src/main/res/values/colors.xml b/app/src/main/res/values/colors.xml index a6816c1..f007332 100644 --- a/app/src/main/res/values/colors.xml +++ b/app/src/main/res/values/colors.xml @@ -16,4 +16,6 @@ #FFE500 #00FFF7 #00FF0A + + #33008BFF \ No newline at end of file diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index a88d050..ced1e85 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -21,16 +21,16 @@ Scan failed: %s Failed to play video Edit OTP - Delete Group(s) - Do you want to delete the group(s)?\n\nNote: This will delete all of the contained OTPs! + Delete Groups + Do you want to delete the groups?\n\nNote: This will delete all of the contained OTPs! Generated new code Failed to add code Input Code Action failed Invalid number entered Back - Delete OTP - Do you want to delete the OTP? + Delete OTP(s) + Do you want to delete the selected OTP(s)? Edit Group Enable intro video Require biometric unlock