Add group rename, OTP delete
This commit is contained in:
parent
7a82b98169
commit
aa03844f3c
@ -48,7 +48,7 @@ dependencies {
|
|||||||
implementation 'com.google.code.gson:gson:2.8.9'
|
implementation 'com.google.code.gson:gson:2.8.9'
|
||||||
|
|
||||||
|
|
||||||
def camerax_version = "1.2.2"
|
def camerax_version = "1.2.3"
|
||||||
implementation "androidx.camera:camera-core:${camerax_version}"
|
implementation "androidx.camera:camera-core:${camerax_version}"
|
||||||
implementation "androidx.camera:camera-camera2:${camerax_version}"
|
implementation "androidx.camera:camera-camera2:${camerax_version}"
|
||||||
implementation "androidx.camera:camera-lifecycle:${camerax_version}"
|
implementation "androidx.camera:camera-lifecycle:${camerax_version}"
|
||||||
|
@ -10,7 +10,6 @@ import android.view.MenuItem;
|
|||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.widget.AdapterView;
|
import android.widget.AdapterView;
|
||||||
import android.widget.ArrayAdapter;
|
import android.widget.ArrayAdapter;
|
||||||
import android.widget.EditText;
|
|
||||||
import android.widget.Toast;
|
import android.widget.Toast;
|
||||||
|
|
||||||
import androidx.activity.result.ActivityResultLauncher;
|
import androidx.activity.result.ActivityResultLauncher;
|
||||||
@ -237,23 +236,12 @@ public class MainActivity extends AppCompatActivity {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void addGroup(MenuItem item) {
|
public void addGroup(MenuItem item) {
|
||||||
EditText t = new EditText(this);
|
DialogUtil.showCreateGroupDialog(getLayoutInflater(), null, group -> {
|
||||||
new StyledDialogBuilder(this)
|
Fragment frag = NavigationUtil.getCurrentFragment(this);
|
||||||
.setTitle(R.string.action_new_group)
|
if(frag instanceof MenuFragment) {
|
||||||
.setView(t)
|
((MenuFragment) frag).addGroup(group);
|
||||||
.setPositiveButton(R.string.add, (view, which) -> {
|
}
|
||||||
if(t.getText().length() == 0) {
|
});
|
||||||
DialogUtil.showErrorDialog(this, getString(R.string.new_group_missing_title));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
Fragment frag = NavigationUtil.getCurrentFragment(this);
|
|
||||||
if(frag instanceof MenuFragment) {
|
|
||||||
((MenuFragment) frag).addGroup(t.getText().toString());
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.setNegativeButton(R.string.cancel, (view, which) -> {})
|
|
||||||
.show();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -10,9 +10,9 @@ import android.view.ViewGroup;
|
|||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
import androidx.annotation.Nullable;
|
import androidx.annotation.Nullable;
|
||||||
|
|
||||||
import com.cringe_studios.cringe_authenticator.OTPData;
|
|
||||||
import com.cringe_studios.cringe_authenticator.R;
|
import com.cringe_studios.cringe_authenticator.R;
|
||||||
import com.cringe_studios.cringe_authenticator.databinding.FragmentGroupBinding;
|
import com.cringe_studios.cringe_authenticator.databinding.FragmentGroupBinding;
|
||||||
|
import com.cringe_studios.cringe_authenticator.model.OTPData;
|
||||||
import com.cringe_studios.cringe_authenticator.otplist.OTPListAdapter;
|
import com.cringe_studios.cringe_authenticator.otplist.OTPListAdapter;
|
||||||
import com.cringe_studios.cringe_authenticator.otplist.OTPListItem;
|
import com.cringe_studios.cringe_authenticator.otplist.OTPListItem;
|
||||||
import com.cringe_studios.cringe_authenticator.util.DialogUtil;
|
import com.cringe_studios.cringe_authenticator.util.DialogUtil;
|
||||||
@ -28,7 +28,7 @@ public class GroupFragment extends NamedFragment {
|
|||||||
|
|
||||||
public static final String BUNDLE_GROUP = "group";
|
public static final String BUNDLE_GROUP = "group";
|
||||||
|
|
||||||
private String groupName;
|
private String groupID;
|
||||||
|
|
||||||
private FragmentGroupBinding binding;
|
private FragmentGroupBinding binding;
|
||||||
|
|
||||||
@ -40,7 +40,7 @@ public class GroupFragment extends NamedFragment {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getName() {
|
public String getName() {
|
||||||
return groupName;
|
return SettingsUtil.getGroupName(requireContext(), groupID);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -53,7 +53,7 @@ public class GroupFragment extends NamedFragment {
|
|||||||
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
|
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
|
||||||
binding = FragmentGroupBinding.inflate(inflater, container, false);
|
binding = FragmentGroupBinding.inflate(inflater, container, false);
|
||||||
|
|
||||||
groupName = requireArguments().getString(GroupFragment.BUNDLE_GROUP);
|
groupID = requireArguments().getString(GroupFragment.BUNDLE_GROUP);
|
||||||
|
|
||||||
FabUtil.showFabs(requireActivity());
|
FabUtil.showFabs(requireActivity());
|
||||||
|
|
||||||
@ -90,8 +90,8 @@ public class GroupFragment extends NamedFragment {
|
|||||||
break;
|
break;
|
||||||
case 2:
|
case 2:
|
||||||
new StyledDialogBuilder(requireContext())
|
new StyledDialogBuilder(requireContext())
|
||||||
.setTitle("Delete?")
|
.setTitle(R.string.otp_delete_title)
|
||||||
.setMessage("Delete this?")
|
.setMessage(R.string.otp_delete_message)
|
||||||
.setPositiveButton(R.string.yes, (d, w) -> {
|
.setPositiveButton(R.string.yes, (d, w) -> {
|
||||||
otpListAdapter.remove(data);
|
otpListAdapter.remove(data);
|
||||||
saveOTPs();
|
saveOTPs();
|
||||||
@ -103,30 +103,15 @@ public class GroupFragment extends NamedFragment {
|
|||||||
})
|
})
|
||||||
.setNegativeButton(R.string.cancel, (dialog, which) -> {})
|
.setNegativeButton(R.string.cancel, (dialog, which) -> {})
|
||||||
.show();
|
.show();
|
||||||
|
|
||||||
/*switch(data.getType()) {
|
|
||||||
case HOTP:
|
|
||||||
DialogUtil.showHOTPDialog(getLayoutInflater(), data, newData -> {
|
|
||||||
otpListAdapter.replace(data, newData);
|
|
||||||
saveOTPs();
|
|
||||||
});
|
|
||||||
break;
|
|
||||||
case TOTP:
|
|
||||||
DialogUtil.showTOTPDialog(getLayoutInflater(), data, newData -> {
|
|
||||||
otpListAdapter.replace(data, newData);
|
|
||||||
saveOTPs();
|
|
||||||
});
|
|
||||||
break;
|
|
||||||
}*/
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void saveOTPs() {
|
private void saveOTPs() {
|
||||||
SettingsUtil.updateOTPs(requireContext(), groupName, otpListAdapter.getItems());
|
SettingsUtil.updateOTPs(requireContext(), groupID, otpListAdapter.getItems());
|
||||||
refreshCodes();
|
refreshCodes();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void loadOTPs() {
|
private void loadOTPs() {
|
||||||
List<OTPData> data = SettingsUtil.getOTPs(requireContext(), groupName);
|
List<OTPData> data = SettingsUtil.getOTPs(requireContext(), groupID);
|
||||||
|
|
||||||
for(OTPData otp : data) {
|
for(OTPData otp : data) {
|
||||||
otpListAdapter.add(otp);
|
otpListAdapter.add(otp);
|
||||||
@ -134,7 +119,7 @@ public class GroupFragment extends NamedFragment {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void addOTP(OTPData data) {
|
public void addOTP(OTPData data) {
|
||||||
SettingsUtil.addOTP(requireContext(), groupName, data);
|
SettingsUtil.addOTP(requireContext(), groupID, data);
|
||||||
otpListAdapter.add(data);
|
otpListAdapter.add(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -8,13 +8,17 @@ import android.view.ViewGroup;
|
|||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
import androidx.annotation.Nullable;
|
import androidx.annotation.Nullable;
|
||||||
|
|
||||||
|
import com.cringe_studios.cringe_authenticator.R;
|
||||||
import com.cringe_studios.cringe_authenticator.databinding.FragmentMenuBinding;
|
import com.cringe_studios.cringe_authenticator.databinding.FragmentMenuBinding;
|
||||||
import com.cringe_studios.cringe_authenticator.grouplist.GroupListAdapter;
|
import com.cringe_studios.cringe_authenticator.grouplist.GroupListAdapter;
|
||||||
|
import com.cringe_studios.cringe_authenticator.util.DialogUtil;
|
||||||
import com.cringe_studios.cringe_authenticator.util.FabUtil;
|
import com.cringe_studios.cringe_authenticator.util.FabUtil;
|
||||||
import com.cringe_studios.cringe_authenticator.util.NavigationUtil;
|
import com.cringe_studios.cringe_authenticator.util.NavigationUtil;
|
||||||
import com.cringe_studios.cringe_authenticator.util.SettingsUtil;
|
import com.cringe_studios.cringe_authenticator.util.SettingsUtil;
|
||||||
|
import com.cringe_studios.cringe_authenticator.util.StyledDialogBuilder;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
public class MenuFragment extends NamedFragment {
|
public class MenuFragment extends NamedFragment {
|
||||||
|
|
||||||
@ -36,21 +40,42 @@ public class MenuFragment extends NamedFragment {
|
|||||||
Bundle bundle = new Bundle();
|
Bundle bundle = new Bundle();
|
||||||
bundle.putString(GroupFragment.BUNDLE_GROUP, group);
|
bundle.putString(GroupFragment.BUNDLE_GROUP, group);
|
||||||
NavigationUtil.navigate(this, GroupFragment.class, bundle);
|
NavigationUtil.navigate(this, GroupFragment.class, bundle);
|
||||||
}, this::removeGroup);
|
}, this::showGroupDialog);
|
||||||
|
|
||||||
binding.menuItems.setAdapter(groupListAdapter);
|
binding.menuItems.setAdapter(groupListAdapter);
|
||||||
|
|
||||||
loadGroups();
|
loadGroups();
|
||||||
|
|
||||||
/*binding.editSwitch.setOnCheckedChangeListener((view, checked) -> {
|
|
||||||
// TODO: edit mode
|
|
||||||
});*/
|
|
||||||
|
|
||||||
FabUtil.hideFabs(requireActivity());
|
FabUtil.hideFabs(requireActivity());
|
||||||
|
|
||||||
return binding.getRoot();
|
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);
|
||||||
|
});
|
||||||
|
|
||||||
|
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() {
|
private void loadGroups() {
|
||||||
List<String> items = SettingsUtil.getGroups(requireContext());
|
List<String> items = SettingsUtil.getGroups(requireContext());
|
||||||
|
|
||||||
@ -59,9 +84,10 @@ public class MenuFragment extends NamedFragment {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void addGroup(String group) {
|
public void addGroup(String groupName) {
|
||||||
SettingsUtil.addGroup(requireContext(), group);
|
String id = UUID.randomUUID().toString();
|
||||||
groupListAdapter.add(group);
|
SettingsUtil.addGroup(requireContext(), id, groupName);
|
||||||
|
groupListAdapter.add(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void removeGroup(String group) {
|
public void removeGroup(String group) {
|
||||||
@ -69,6 +95,11 @@ public class MenuFragment extends NamedFragment {
|
|||||||
groupListAdapter.remove(group);
|
groupListAdapter.remove(group);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void renameGroup(String group, String newName) {
|
||||||
|
SettingsUtil.setGroupName(requireContext(), group, newName);
|
||||||
|
groupListAdapter.update(group);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onDestroyView() {
|
public void onDestroyView() {
|
||||||
super.onDestroyView();
|
super.onDestroyView();
|
||||||
|
@ -10,9 +10,8 @@ import androidx.annotation.NonNull;
|
|||||||
import androidx.core.util.Consumer;
|
import androidx.core.util.Consumer;
|
||||||
import androidx.recyclerview.widget.RecyclerView;
|
import androidx.recyclerview.widget.RecyclerView;
|
||||||
|
|
||||||
import com.cringe_studios.cringe_authenticator.R;
|
|
||||||
import com.cringe_studios.cringe_authenticator.databinding.MenuItemBinding;
|
import com.cringe_studios.cringe_authenticator.databinding.MenuItemBinding;
|
||||||
import com.cringe_studios.cringe_authenticator.util.StyledDialogBuilder;
|
import com.cringe_studios.cringe_authenticator.util.SettingsUtil;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@ -29,12 +28,12 @@ public class GroupListAdapter extends RecyclerView.Adapter<GroupListItem> {
|
|||||||
|
|
||||||
private Consumer<String> navigateToGroup;
|
private Consumer<String> navigateToGroup;
|
||||||
|
|
||||||
private Consumer<String> removeGroup;
|
private Consumer<String> showMenuCallback;
|
||||||
|
|
||||||
public GroupListAdapter(Context context, Consumer<String> navigateToGroup, Consumer<String> removeGroup) {
|
public GroupListAdapter(Context context, Consumer<String> navigateToGroup, Consumer<String> showMenuCallback) {
|
||||||
this.context = context;
|
this.context = context;
|
||||||
this.navigateToGroup = navigateToGroup;
|
this.navigateToGroup = navigateToGroup;
|
||||||
this.removeGroup = removeGroup;
|
this.showMenuCallback = showMenuCallback;
|
||||||
this.inflater = LayoutInflater.from(context);
|
this.inflater = LayoutInflater.from(context);
|
||||||
this.items = new ArrayList<>();
|
this.items = new ArrayList<>();
|
||||||
this.handler = new Handler(Looper.getMainLooper());
|
this.handler = new Handler(Looper.getMainLooper());
|
||||||
@ -51,17 +50,11 @@ public class GroupListAdapter extends RecyclerView.Adapter<GroupListItem> {
|
|||||||
public void onBindViewHolder(@NonNull GroupListItem holder, int position) {
|
public void onBindViewHolder(@NonNull GroupListItem holder, int position) {
|
||||||
String group = items.get(position);
|
String group = items.get(position);
|
||||||
|
|
||||||
holder.getBinding().button.setText(group);
|
holder.getBinding().button.setText(SettingsUtil.getGroupName(context, group));
|
||||||
|
|
||||||
holder.getBinding().button.setOnClickListener(view -> navigateToGroup.accept(group));
|
holder.getBinding().button.setOnClickListener(view -> navigateToGroup.accept(group));
|
||||||
holder.getBinding().button.setOnLongClickListener(view -> {
|
holder.getBinding().button.setOnLongClickListener(view -> {
|
||||||
new StyledDialogBuilder(context)
|
showMenuCallback.accept(group);
|
||||||
.setTitle(R.string.group_delete_title)
|
|
||||||
.setMessage(R.string.group_delete_message)
|
|
||||||
.setPositiveButton(R.string.yes, (dialog, which) -> removeGroup.accept(group))
|
|
||||||
.setNegativeButton(R.string.no, (dialog, which) -> {})
|
|
||||||
.show();
|
|
||||||
// TODO: better method?
|
|
||||||
return true;
|
return true;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -83,4 +76,10 @@ public class GroupListAdapter extends RecyclerView.Adapter<GroupListItem> {
|
|||||||
notifyItemRemoved(index);
|
notifyItemRemoved(index);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void update(String group) {
|
||||||
|
int index = items.indexOf(group);
|
||||||
|
if(index == -1) return;
|
||||||
|
notifyItemChanged(index);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
package com.cringe_studios.cringe_authenticator;
|
package com.cringe_studios.cringe_authenticator.model;
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
|
|
@ -12,9 +12,9 @@ import androidx.annotation.NonNull;
|
|||||||
import androidx.core.util.Consumer;
|
import androidx.core.util.Consumer;
|
||||||
import androidx.recyclerview.widget.RecyclerView;
|
import androidx.recyclerview.widget.RecyclerView;
|
||||||
|
|
||||||
import com.cringe_studios.cringe_authenticator.OTPData;
|
|
||||||
import com.cringe_studios.cringe_authenticator.R;
|
import com.cringe_studios.cringe_authenticator.R;
|
||||||
import com.cringe_studios.cringe_authenticator.databinding.OtpCodeBinding;
|
import com.cringe_studios.cringe_authenticator.databinding.OtpCodeBinding;
|
||||||
|
import com.cringe_studios.cringe_authenticator.model.OTPData;
|
||||||
import com.cringe_studios.cringe_authenticator_library.OTPException;
|
import com.cringe_studios.cringe_authenticator_library.OTPException;
|
||||||
import com.cringe_studios.cringe_authenticator_library.OTPType;
|
import com.cringe_studios.cringe_authenticator_library.OTPType;
|
||||||
|
|
||||||
|
@ -3,8 +3,8 @@ package com.cringe_studios.cringe_authenticator.otplist;
|
|||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
import androidx.recyclerview.widget.RecyclerView;
|
import androidx.recyclerview.widget.RecyclerView;
|
||||||
|
|
||||||
import com.cringe_studios.cringe_authenticator.OTPData;
|
|
||||||
import com.cringe_studios.cringe_authenticator.databinding.OtpCodeBinding;
|
import com.cringe_studios.cringe_authenticator.databinding.OtpCodeBinding;
|
||||||
|
import com.cringe_studios.cringe_authenticator.model.OTPData;
|
||||||
|
|
||||||
public class OTPListItem extends RecyclerView.ViewHolder {
|
public class OTPListItem extends RecyclerView.ViewHolder {
|
||||||
|
|
||||||
|
@ -27,8 +27,8 @@ import androidx.camera.core.SurfaceOrientedMeteringPointFactory;
|
|||||||
import androidx.camera.lifecycle.ProcessCameraProvider;
|
import androidx.camera.lifecycle.ProcessCameraProvider;
|
||||||
import androidx.core.content.ContextCompat;
|
import androidx.core.content.ContextCompat;
|
||||||
|
|
||||||
import com.cringe_studios.cringe_authenticator.OTPData;
|
|
||||||
import com.cringe_studios.cringe_authenticator.databinding.ActivityQrScannerBinding;
|
import com.cringe_studios.cringe_authenticator.databinding.ActivityQrScannerBinding;
|
||||||
|
import com.cringe_studios.cringe_authenticator.model.OTPData;
|
||||||
import com.cringe_studios.cringe_authenticator.util.OTPParser;
|
import com.cringe_studios.cringe_authenticator.util.OTPParser;
|
||||||
import com.google.common.util.concurrent.ListenableFuture;
|
import com.google.common.util.concurrent.ListenableFuture;
|
||||||
import com.google.mlkit.vision.barcode.BarcodeScanner;
|
import com.google.mlkit.vision.barcode.BarcodeScanner;
|
||||||
|
@ -8,7 +8,7 @@ import androidx.activity.result.contract.ActivityResultContract;
|
|||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
import androidx.annotation.Nullable;
|
import androidx.annotation.Nullable;
|
||||||
|
|
||||||
import com.cringe_studios.cringe_authenticator.OTPData;
|
import com.cringe_studios.cringe_authenticator.model.OTPData;
|
||||||
|
|
||||||
public class QRScannerContract extends ActivityResultContract<Void, ScannerResult> {
|
public class QRScannerContract extends ActivityResultContract<Void, ScannerResult> {
|
||||||
|
|
||||||
|
@ -3,7 +3,7 @@ package com.cringe_studios.cringe_authenticator.scanner;
|
|||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
import androidx.annotation.Nullable;
|
import androidx.annotation.Nullable;
|
||||||
|
|
||||||
import com.cringe_studios.cringe_authenticator.OTPData;
|
import com.cringe_studios.cringe_authenticator.model.OTPData;
|
||||||
|
|
||||||
public class ScannerResult {
|
public class ScannerResult {
|
||||||
|
|
||||||
|
@ -8,8 +8,8 @@ import androidx.annotation.Nullable;
|
|||||||
import androidx.appcompat.app.AlertDialog;
|
import androidx.appcompat.app.AlertDialog;
|
||||||
import androidx.appcompat.app.AppCompatActivity;
|
import androidx.appcompat.app.AppCompatActivity;
|
||||||
|
|
||||||
import com.cringe_studios.cringe_authenticator.OTPData;
|
|
||||||
import com.cringe_studios.cringe_authenticator.R;
|
import com.cringe_studios.cringe_authenticator.R;
|
||||||
|
import com.cringe_studios.cringe_authenticator.model.OTPData;
|
||||||
import com.cringe_studios.cringe_authenticator.util.OTPParser;
|
import com.cringe_studios.cringe_authenticator.util.OTPParser;
|
||||||
import com.cringe_studios.cringe_authenticator.util.StyledDialogBuilder;
|
import com.cringe_studios.cringe_authenticator.util.StyledDialogBuilder;
|
||||||
|
|
||||||
|
@ -0,0 +1,7 @@
|
|||||||
|
package com.cringe_studios.cringe_authenticator.util;
|
||||||
|
|
||||||
|
public interface BiConsumer<T, U> {
|
||||||
|
|
||||||
|
public void accept(T t, U u);
|
||||||
|
|
||||||
|
}
|
@ -10,10 +10,11 @@ import androidx.annotation.NonNull;
|
|||||||
import androidx.appcompat.app.AlertDialog;
|
import androidx.appcompat.app.AlertDialog;
|
||||||
import androidx.core.util.Consumer;
|
import androidx.core.util.Consumer;
|
||||||
|
|
||||||
import com.cringe_studios.cringe_authenticator.OTPData;
|
|
||||||
import com.cringe_studios.cringe_authenticator.R;
|
import com.cringe_studios.cringe_authenticator.R;
|
||||||
|
import com.cringe_studios.cringe_authenticator.databinding.DialogCreateGroupBinding;
|
||||||
import com.cringe_studios.cringe_authenticator.databinding.DialogInputCodeHotpBinding;
|
import com.cringe_studios.cringe_authenticator.databinding.DialogInputCodeHotpBinding;
|
||||||
import com.cringe_studios.cringe_authenticator.databinding.DialogInputCodeTotpBinding;
|
import com.cringe_studios.cringe_authenticator.databinding.DialogInputCodeTotpBinding;
|
||||||
|
import com.cringe_studios.cringe_authenticator.model.OTPData;
|
||||||
import com.cringe_studios.cringe_authenticator_library.OTPAlgorithm;
|
import com.cringe_studios.cringe_authenticator_library.OTPAlgorithm;
|
||||||
import com.cringe_studios.cringe_authenticator_library.OTPType;
|
import com.cringe_studios.cringe_authenticator_library.OTPType;
|
||||||
|
|
||||||
@ -169,4 +170,34 @@ public class DialogUtil {
|
|||||||
case TOTP: showTOTPDialog(inflater, initialData, callback, back, false); break;
|
case TOTP: showTOTPDialog(inflater, initialData, callback, back, false); break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void showCreateGroupDialog(LayoutInflater inflater, String initialName, Consumer<String> callback) {
|
||||||
|
Context context = inflater.getContext();
|
||||||
|
|
||||||
|
DialogCreateGroupBinding binding = DialogCreateGroupBinding.inflate(inflater);
|
||||||
|
binding.createGroupName.setText(initialName);
|
||||||
|
|
||||||
|
AlertDialog dialog = new StyledDialogBuilder(context)
|
||||||
|
.setTitle(R.string.action_new_group)
|
||||||
|
.setView(binding.getRoot())
|
||||||
|
.setPositiveButton(R.string.add, (view, which) -> {})
|
||||||
|
.setNegativeButton(R.string.cancel, (view, which) -> {})
|
||||||
|
.create();
|
||||||
|
|
||||||
|
dialog.setOnShowListener(d -> {
|
||||||
|
Button okButton = dialog.getButton(AlertDialog.BUTTON_POSITIVE);
|
||||||
|
okButton.setOnClickListener(v -> {
|
||||||
|
if(binding.createGroupName.getText().length() == 0) {
|
||||||
|
DialogUtil.showErrorDialog(context, context.getString(R.string.new_group_missing_title));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
dialog.dismiss();
|
||||||
|
callback.accept(binding.createGroupName.getText().toString());
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
dialog.show();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -2,7 +2,7 @@ package com.cringe_studios.cringe_authenticator.util;
|
|||||||
|
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
|
|
||||||
import com.cringe_studios.cringe_authenticator.OTPData;
|
import com.cringe_studios.cringe_authenticator.model.OTPData;
|
||||||
import com.cringe_studios.cringe_authenticator_library.OTPAlgorithm;
|
import com.cringe_studios.cringe_authenticator_library.OTPAlgorithm;
|
||||||
import com.cringe_studios.cringe_authenticator_library.OTPType;
|
import com.cringe_studios.cringe_authenticator_library.OTPType;
|
||||||
|
|
||||||
|
@ -5,8 +5,8 @@ import android.content.SharedPreferences;
|
|||||||
|
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
|
|
||||||
import com.cringe_studios.cringe_authenticator.OTPData;
|
|
||||||
import com.cringe_studios.cringe_authenticator.R;
|
import com.cringe_studios.cringe_authenticator.R;
|
||||||
|
import com.cringe_studios.cringe_authenticator.model.OTPData;
|
||||||
import com.google.gson.Gson;
|
import com.google.gson.Gson;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
@ -44,12 +44,14 @@ public class SettingsUtil {
|
|||||||
return Arrays.asList(GSON.fromJson(prefs.getString("groups", "[]"), String[].class));
|
return Arrays.asList(GSON.fromJson(prefs.getString("groups", "[]"), String[].class));
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void addGroup(Context ctx, String group) {
|
public static void addGroup(Context ctx, String group, String groupName) {
|
||||||
List<String> groups = new ArrayList<>(getGroups(ctx));
|
List<String> groups = new ArrayList<>(getGroups(ctx));
|
||||||
groups.add(group);
|
groups.add(group);
|
||||||
|
|
||||||
SharedPreferences prefs = ctx.getSharedPreferences(GROUPS_PREFS_NAME, Context.MODE_PRIVATE);
|
SharedPreferences prefs = ctx.getSharedPreferences(GROUPS_PREFS_NAME, Context.MODE_PRIVATE);
|
||||||
prefs.edit().putString("groups", GSON.toJson(groups)).apply();
|
prefs.edit().putString("groups", GSON.toJson(groups)).apply();
|
||||||
|
|
||||||
|
setGroupName(ctx, group, groupName);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void removeGroup(Context ctx, String group) {
|
public static void removeGroup(Context ctx, String group) {
|
||||||
@ -59,32 +61,45 @@ public class SettingsUtil {
|
|||||||
SharedPreferences prefs = ctx.getSharedPreferences(GROUPS_PREFS_NAME, Context.MODE_PRIVATE);
|
SharedPreferences prefs = ctx.getSharedPreferences(GROUPS_PREFS_NAME, Context.MODE_PRIVATE);
|
||||||
prefs.edit().putString("groups", GSON.toJson(groups)).apply();
|
prefs.edit().putString("groups", GSON.toJson(groups)).apply();
|
||||||
|
|
||||||
deleteOTPs(ctx, group);
|
deleteGroupData(ctx, group);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static List<OTPData> getOTPs(Context ctx, String group) {
|
public static List<OTPData> getOTPs(Context ctx, String group) {
|
||||||
String currentOTPs = ctx.getSharedPreferences(GROUPS_PREFS_NAME, Context.MODE_PRIVATE).getString("group." + group, "[]");
|
String currentOTPs = ctx.getSharedPreferences(GROUPS_PREFS_NAME, Context.MODE_PRIVATE).getString("group." + group + ".otps", "[]");
|
||||||
return Arrays.asList(GSON.fromJson(currentOTPs, OTPData[].class));
|
return Arrays.asList(GSON.fromJson(currentOTPs, OTPData[].class));
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void addOTP(Context ctx, String group, @NonNull OTPData data) {
|
public static void addOTP(Context ctx, String group, @NonNull OTPData data) {
|
||||||
|
// TODO: check for code with same name
|
||||||
|
|
||||||
List<OTPData> otps = new ArrayList<>(getOTPs(ctx, group));
|
List<OTPData> otps = new ArrayList<>(getOTPs(ctx, group));
|
||||||
otps.add(data);
|
otps.add(data);
|
||||||
|
|
||||||
ctx.getSharedPreferences(GROUPS_PREFS_NAME, Context.MODE_PRIVATE).edit()
|
ctx.getSharedPreferences(GROUPS_PREFS_NAME, Context.MODE_PRIVATE).edit()
|
||||||
.putString("group." + group, GSON.toJson(otps.toArray(new OTPData[0])))
|
.putString("group." + group + ".otps", GSON.toJson(otps.toArray(new OTPData[0])))
|
||||||
.apply();
|
.apply();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void updateOTPs(Context ctx, String group, List<OTPData> otps) {
|
public static void updateOTPs(Context ctx, String group, List<OTPData> otps) {
|
||||||
ctx.getSharedPreferences(GROUPS_PREFS_NAME, Context.MODE_PRIVATE).edit()
|
ctx.getSharedPreferences(GROUPS_PREFS_NAME, Context.MODE_PRIVATE).edit()
|
||||||
.putString("group." + group, GSON.toJson(otps.toArray(new OTPData[0])))
|
.putString("group." + group + ".otps", GSON.toJson(otps.toArray(new OTPData[0])))
|
||||||
.apply();
|
.apply();
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void deleteOTPs(Context ctx, String group) {
|
public static String getGroupName(Context ctx, String group) {
|
||||||
|
return ctx.getSharedPreferences(GROUPS_PREFS_NAME, Context.MODE_PRIVATE).getString("group." + group + ".name", group);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void setGroupName(Context ctx, String group, String name) {
|
||||||
ctx.getSharedPreferences(GROUPS_PREFS_NAME, Context.MODE_PRIVATE).edit()
|
ctx.getSharedPreferences(GROUPS_PREFS_NAME, Context.MODE_PRIVATE).edit()
|
||||||
.remove("group." + group)
|
.putString("group." + group + ".name", name)
|
||||||
|
.apply();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void deleteGroupData(Context ctx, String group) {
|
||||||
|
ctx.getSharedPreferences(GROUPS_PREFS_NAME, Context.MODE_PRIVATE).edit()
|
||||||
|
.remove("group." + group + ".otps")
|
||||||
|
.remove("group." + group + ".name")
|
||||||
.apply();
|
.apply();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
20
app/src/main/res/layout/dialog_create_group.xml
Normal file
20
app/src/main/res/layout/dialog_create_group.xml
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent">
|
||||||
|
|
||||||
|
<EditText
|
||||||
|
android:id="@+id/create_group_name"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginStart="10dp"
|
||||||
|
android:layout_marginTop="10dp"
|
||||||
|
android:layout_marginEnd="10dp"
|
||||||
|
android:ems="10"
|
||||||
|
android:inputType="text"
|
||||||
|
android:text="Name"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintTop_toTopOf="parent" />
|
||||||
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
@ -31,6 +31,9 @@
|
|||||||
<string name="failed_title">Aktion fehlgeschlagen</string>
|
<string name="failed_title">Aktion fehlgeschlagen</string>
|
||||||
<string name="input_code_invalid_number">Ungültige Zahl</string>
|
<string name="input_code_invalid_number">Ungültige Zahl</string>
|
||||||
<string name="back">Zurück</string>
|
<string name="back">Zurück</string>
|
||||||
|
<string name="otp_delete_title">Löschen?</string>
|
||||||
|
<string name="otp_delete_message">OTP löschen?</string>
|
||||||
|
<string name="edit_group_title">Gruppe bearbeiten</string>
|
||||||
<string-array name="view_edit_delete">
|
<string-array name="view_edit_delete">
|
||||||
<item>Anzeigen</item>
|
<item>Anzeigen</item>
|
||||||
<item>Bearbeiten</item>
|
<item>Bearbeiten</item>
|
||||||
|
@ -71,6 +71,9 @@
|
|||||||
<string name="failed_title">Action failed</string>
|
<string name="failed_title">Action failed</string>
|
||||||
<string name="input_code_invalid_number">Invalid number entered</string>
|
<string name="input_code_invalid_number">Invalid number entered</string>
|
||||||
<string name="back">Back</string>
|
<string name="back">Back</string>
|
||||||
|
<string name="otp_delete_title">Delete?</string>
|
||||||
|
<string name="otp_delete_message">Delete this?</string>
|
||||||
|
<string name="edit_group_title">Edit Group</string>
|
||||||
<string-array name="view_edit_delete">
|
<string-array name="view_edit_delete">
|
||||||
<item>View</item>
|
<item>View</item>
|
||||||
<item>Edit</item>
|
<item>Edit</item>
|
||||||
|
Loading…
Reference in New Issue
Block a user