Fix locale on older Android, Clean up code
This commit is contained in:
parent
494f9d66fc
commit
2e88d021bb
@ -2,7 +2,6 @@ package com.cringe_studios.cringe_authenticator;
|
||||
|
||||
import android.content.res.Configuration;
|
||||
import android.os.Bundle;
|
||||
import android.util.Log;
|
||||
import android.view.WindowManager;
|
||||
|
||||
import androidx.activity.result.ActivityResultLauncher;
|
||||
@ -50,7 +49,7 @@ public class BaseActivity extends AppCompatActivity {
|
||||
public void setLocale(Locale locale) {
|
||||
Locale.setDefault(locale);
|
||||
Configuration config = new Configuration();
|
||||
config.locale = locale;
|
||||
config.setLocale(locale);
|
||||
getResources().updateConfiguration(config, getResources().getDisplayMetrics());
|
||||
}
|
||||
|
||||
|
@ -7,8 +7,6 @@ import android.os.Bundle;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.Toast;
|
||||
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
|
||||
import com.cringe_studios.cringe_authenticator.databinding.ActivityIntroBinding;
|
||||
import com.cringe_studios.cringe_authenticator.unlock.UnlockActivity;
|
||||
import com.cringe_studios.cringe_authenticator.util.SettingsUtil;
|
||||
|
@ -1,8 +1,8 @@
|
||||
package com.cringe_studios.cringe_authenticator;
|
||||
|
||||
import android.content.res.Configuration;
|
||||
import android.net.Uri;
|
||||
import android.os.Bundle;
|
||||
import android.util.Log;
|
||||
import android.view.Menu;
|
||||
import android.view.MenuItem;
|
||||
import android.view.View;
|
||||
@ -32,14 +32,12 @@ import com.cringe_studios.cringe_authenticator.scanner.QRScannerContract;
|
||||
import com.cringe_studios.cringe_authenticator.util.DialogUtil;
|
||||
import com.cringe_studios.cringe_authenticator.util.NavigationUtil;
|
||||
import com.cringe_studios.cringe_authenticator.util.OTPDatabase;
|
||||
import com.cringe_studios.cringe_authenticator.util.SettingsUtil;
|
||||
import com.cringe_studios.cringe_authenticator.util.StyledDialogBuilder;
|
||||
import com.cringe_studios.cringe_authenticator.util.ThemeUtil;
|
||||
import com.cringe_studios.cringe_authenticator_library.OTPType;
|
||||
import com.google.mlkit.vision.common.InputImage;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Locale;
|
||||
|
||||
public class MainActivity extends BaseActivity {
|
||||
|
||||
@ -61,7 +59,7 @@ public class MainActivity extends BaseActivity {
|
||||
|
||||
private boolean fullyLaunched;
|
||||
|
||||
private boolean lockOnPause = true;
|
||||
private boolean lockOnStop = true;
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
@ -70,7 +68,7 @@ public class MainActivity extends BaseActivity {
|
||||
qrScanner = new QRScanner();
|
||||
|
||||
startQRCodeScan = registerForActivityResult(new QRScannerContract(), obj -> {
|
||||
lockOnPause = true;
|
||||
lockOnStop = true;
|
||||
|
||||
if(obj == null) return; // Cancelled
|
||||
|
||||
@ -98,19 +96,13 @@ public class MainActivity extends BaseActivity {
|
||||
}
|
||||
|
||||
if(code.isMigrationPart()) {
|
||||
new StyledDialogBuilder(this) // TODO: duplicated from QRScannerActivity
|
||||
.setTitle(R.string.qr_scanner_migration_title)
|
||||
.setMessage(R.string.qr_scanner_migration_message)
|
||||
.setPositiveButton(R.string.yes, (d, which) -> {
|
||||
DialogUtil.showYesNo(this, R.string.qr_scanner_migration_title, R.string.qr_scanner_migration_message, () -> {
|
||||
Fragment fragment = NavigationUtil.getCurrentFragment(this);
|
||||
if (fragment instanceof GroupFragment) {
|
||||
GroupFragment frag = (GroupFragment) fragment;
|
||||
for (OTPData dt : code.getOTPs()) frag.addOTP(dt);
|
||||
}
|
||||
})
|
||||
.setNegativeButton(R.string.no, (d, which) -> {})
|
||||
.show()
|
||||
.setCanceledOnTouchOutside(false);
|
||||
}, null);
|
||||
}else {
|
||||
Fragment fragment = NavigationUtil.getCurrentFragment(this);
|
||||
if (fragment instanceof GroupFragment) {
|
||||
@ -149,7 +141,7 @@ public class MainActivity extends BaseActivity {
|
||||
|
||||
private void launchApp() {
|
||||
fullyLaunched = true;
|
||||
lockOnPause = true;
|
||||
lockOnStop = true;
|
||||
|
||||
binding = ActivityMainBinding.inflate(getLayoutInflater());
|
||||
setContentView(binding.getRoot());
|
||||
@ -225,7 +217,7 @@ public class MainActivity extends BaseActivity {
|
||||
}
|
||||
|
||||
public void scanCode(MenuItem item) {
|
||||
lockOnPause = false;
|
||||
lockOnStop = false;
|
||||
startQRCodeScan.launch(null);
|
||||
}
|
||||
|
||||
@ -324,18 +316,18 @@ public class MainActivity extends BaseActivity {
|
||||
}
|
||||
|
||||
public void promptPickBackupFileSave(String name, Consumer<Uri> callback) {
|
||||
this.lockOnPause = false;
|
||||
this.lockOnStop = false;
|
||||
this.pickBackupFileSaveCallback = uri -> {
|
||||
lockOnPause = true;
|
||||
lockOnStop = true;
|
||||
callback.accept(uri);
|
||||
};
|
||||
pickBackupFileSave.launch(name);
|
||||
}
|
||||
|
||||
public void promptPickBackupFileLoad(Consumer<Uri> callback) {
|
||||
this.lockOnPause = false;
|
||||
this.lockOnStop = false;
|
||||
this.pickBackupFileLoadCallback = uri -> {
|
||||
lockOnPause = true;
|
||||
lockOnStop = true;
|
||||
callback.accept(uri);
|
||||
};
|
||||
pickBackupFileLoad.launch(new String[]{"application/json"});
|
||||
@ -343,14 +335,15 @@ public class MainActivity extends BaseActivity {
|
||||
|
||||
@Override
|
||||
public void recreate() {
|
||||
lockOnPause = false;
|
||||
lockOnStop = false;
|
||||
super.recreate();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onStop() {
|
||||
super.onStop();
|
||||
if(lockOnPause) OTPDatabase.unloadDatabase();
|
||||
Log.d("STOP", lockOnStop+"");
|
||||
if(lockOnStop) OTPDatabase.unloadDatabase();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -1,16 +1,12 @@
|
||||
package com.cringe_studios.cringe_authenticator.backup;
|
||||
|
||||
import android.util.Base64;
|
||||
import android.util.Log;
|
||||
|
||||
import com.cringe_studios.cringe_authenticator.crypto.CryptoException;
|
||||
import com.cringe_studios.cringe_authenticator.crypto.CryptoParameters;
|
||||
import com.cringe_studios.cringe_authenticator.model.OTPData;
|
||||
import com.cringe_studios.cringe_authenticator.proto.OTPMigration;
|
||||
import com.cringe_studios.cringe_authenticator.util.BackupException;
|
||||
import com.cringe_studios.cringe_authenticator.util.OTPDatabase;
|
||||
import com.cringe_studios.cringe_authenticator.util.OTPDatabaseException;
|
||||
import com.cringe_studios.cringe_authenticator.util.SettingsUtil;
|
||||
|
||||
import javax.crypto.SecretKey;
|
||||
|
||||
|
@ -1,7 +1,5 @@
|
||||
package com.cringe_studios.cringe_authenticator.backup;
|
||||
|
||||
import org.jetbrains.annotations.Contract;
|
||||
|
||||
public class BackupGroup {
|
||||
|
||||
public String id;
|
||||
|
@ -9,21 +9,14 @@ import com.cringe_studios.cringe_authenticator.crypto.CryptoParameters;
|
||||
import com.cringe_studios.cringe_authenticator.util.BackupException;
|
||||
import com.cringe_studios.cringe_authenticator.util.IOUtil;
|
||||
import com.cringe_studios.cringe_authenticator.util.OTPDatabase;
|
||||
import com.cringe_studios.cringe_authenticator.util.OTPDatabaseException;
|
||||
import com.cringe_studios.cringe_authenticator.util.SettingsUtil;
|
||||
import com.google.gson.JsonArray;
|
||||
import com.google.gson.JsonElement;
|
||||
import com.google.gson.JsonObject;
|
||||
import com.google.gson.JsonSyntaxException;
|
||||
|
||||
import org.json.JSONObject;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Calendar;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
|
@ -1,15 +1,12 @@
|
||||
package com.cringe_studios.cringe_authenticator.crypto;
|
||||
|
||||
import android.content.Context;
|
||||
import android.os.Build;
|
||||
import android.security.keystore.KeyGenParameterSpec;
|
||||
import android.security.keystore.KeyProperties;
|
||||
import android.util.Log;
|
||||
|
||||
import androidx.annotation.RequiresApi;
|
||||
|
||||
import com.cringe_studios.cringe_authenticator.util.OTPDatabase;
|
||||
import com.cringe_studios.cringe_authenticator.util.SettingsUtil;
|
||||
|
||||
import org.bouncycastle.crypto.generators.Argon2BytesGenerator;
|
||||
import org.bouncycastle.crypto.params.Argon2Parameters;
|
||||
@ -25,7 +22,6 @@ import java.security.NoSuchProviderException;
|
||||
import java.security.SecureRandom;
|
||||
import java.security.UnrecoverableKeyException;
|
||||
import java.security.cert.CertificateException;
|
||||
import java.util.Arrays;
|
||||
import java.util.UUID;
|
||||
|
||||
import javax.crypto.BadPaddingException;
|
||||
|
@ -20,8 +20,6 @@ import com.cringe_studios.cringe_authenticator.util.DialogUtil;
|
||||
import com.cringe_studios.cringe_authenticator.util.OTPDatabase;
|
||||
import com.cringe_studios.cringe_authenticator.util.OTPDatabaseException;
|
||||
import com.cringe_studios.cringe_authenticator.util.SettingsUtil;
|
||||
import com.cringe_studios.cringe_authenticator.util.StyledDialogBuilder;
|
||||
import com.cringe_studios.cringe_authenticator_library.OTPType;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@ -153,11 +151,12 @@ public class GroupFragment extends NamedFragment {
|
||||
for(OTPListItem item : items) {
|
||||
OTPData data = item.getOTPData();
|
||||
OTPDatabase.getLoadedDatabase().addOTP(group, data);
|
||||
OTPDatabase.saveDatabase(requireContext(), SettingsUtil.getCryptoParameters(requireContext()));
|
||||
otpListAdapter.remove(data);
|
||||
}
|
||||
|
||||
OTPDatabase.saveDatabase(requireContext(), SettingsUtil.getCryptoParameters(requireContext()));
|
||||
saveOTPs();
|
||||
otpListAdapter.finishEditing();
|
||||
} catch (OTPDatabaseException | CryptoException e) {
|
||||
DialogUtil.showErrorDialog(requireContext(), e.toString());
|
||||
}
|
||||
@ -171,19 +170,14 @@ public class GroupFragment extends NamedFragment {
|
||||
|
||||
List<OTPListItem> items = otpListAdapter.getSelectedCodes();
|
||||
|
||||
new StyledDialogBuilder(requireContext())
|
||||
.setTitle(R.string.otp_delete_title)
|
||||
.setMessage(R.string.otp_delete_message)
|
||||
.setPositiveButton(R.string.yes, (d, w) -> {
|
||||
DialogUtil.showYesNoCancel(requireContext(), R.string.otp_delete_title, R.string.otp_delete_message, () -> {
|
||||
for(OTPListItem item : items) {
|
||||
otpListAdapter.remove(item.getOTPData());
|
||||
}
|
||||
|
||||
saveOTPs();
|
||||
finishEditing();
|
||||
})
|
||||
.setNegativeButton(R.string.no, (d, w) -> {})
|
||||
.show();
|
||||
}, null, null);
|
||||
}
|
||||
|
||||
public boolean isEditing() {
|
||||
|
@ -18,7 +18,6 @@ import com.cringe_studios.cringe_authenticator.util.NavigationUtil;
|
||||
import com.cringe_studios.cringe_authenticator.util.OTPDatabase;
|
||||
import com.cringe_studios.cringe_authenticator.util.OTPDatabaseException;
|
||||
import com.cringe_studios.cringe_authenticator.util.SettingsUtil;
|
||||
import com.cringe_studios.cringe_authenticator.util.StyledDialogBuilder;
|
||||
import com.google.android.material.bottomsheet.BottomSheetDialogFragment;
|
||||
|
||||
import java.util.List;
|
||||
@ -91,18 +90,13 @@ public class MenuDrawerFragment extends BottomSheetDialogFragment {
|
||||
public void removeSelectedGroups() {
|
||||
if(!groupListAdapter.isEditing()) return;
|
||||
|
||||
new StyledDialogBuilder(requireContext())
|
||||
.setTitle(R.string.group_delete_title)
|
||||
.setMessage(R.string.group_delete_message)
|
||||
.setPositiveButton(R.string.yes, (d, w) -> {
|
||||
DialogUtil.showYesNo(requireContext(), R.string.group_delete_title, R.string.group_delete_message, () -> {
|
||||
for(GroupListItem item : groupListAdapter.getSelectedGroups()) {
|
||||
removeGroup(item.getGroupId());
|
||||
}
|
||||
|
||||
groupListAdapter.finishEditing();
|
||||
})
|
||||
.setNegativeButton(R.string.no, (d, w) -> {})
|
||||
.show();
|
||||
}, null);
|
||||
}
|
||||
|
||||
public void removeGroup(String group) {
|
||||
|
@ -15,6 +15,7 @@ import androidx.annotation.Nullable;
|
||||
import com.cringe_studios.cringe_authenticator.MainActivity;
|
||||
import com.cringe_studios.cringe_authenticator.R;
|
||||
import com.cringe_studios.cringe_authenticator.backup.BackupData;
|
||||
import com.cringe_studios.cringe_authenticator.backup.BackupUtil;
|
||||
import com.cringe_studios.cringe_authenticator.crypto.BiometricKey;
|
||||
import com.cringe_studios.cringe_authenticator.crypto.Crypto;
|
||||
import com.cringe_studios.cringe_authenticator.crypto.CryptoException;
|
||||
@ -22,7 +23,6 @@ import com.cringe_studios.cringe_authenticator.crypto.CryptoParameters;
|
||||
import com.cringe_studios.cringe_authenticator.databinding.FragmentSettingsBinding;
|
||||
import com.cringe_studios.cringe_authenticator.util.Appearance;
|
||||
import com.cringe_studios.cringe_authenticator.util.BackupException;
|
||||
import com.cringe_studios.cringe_authenticator.backup.BackupUtil;
|
||||
import com.cringe_studios.cringe_authenticator.util.BiometricUtil;
|
||||
import com.cringe_studios.cringe_authenticator.util.DialogUtil;
|
||||
import com.cringe_studios.cringe_authenticator.util.OTPDatabase;
|
||||
@ -66,7 +66,6 @@ public class SettingsFragment extends NamedFragment {
|
||||
if(locale.equals(SettingsUtil.getLocale(requireContext()))) return;
|
||||
|
||||
SettingsUtil.setLocale(requireContext(), locale);
|
||||
//((MainActivity) requireActivity()).setLocale(locale);
|
||||
requireActivity().recreate();
|
||||
}
|
||||
|
||||
@ -79,6 +78,8 @@ public class SettingsFragment extends NamedFragment {
|
||||
binding.settingsEnableEncryption.setChecked(SettingsUtil.isDatabaseEncrypted(requireContext()));
|
||||
binding.settingsEnableEncryption.setOnCheckedChangeListener((view, checked) -> {
|
||||
if(checked) {
|
||||
if(SettingsUtil.isDatabaseEncrypted(requireContext())) return;
|
||||
|
||||
DialogUtil.showSetPasswordDialog(requireContext(), password -> {
|
||||
CryptoParameters params = CryptoParameters.createNew();
|
||||
Log.d("Crypto", "Created new crypto params");
|
||||
@ -94,10 +95,13 @@ public class SettingsFragment extends NamedFragment {
|
||||
binding.settingsBiometricLock.setEnabled(true);
|
||||
}
|
||||
} catch (CryptoException | OTPDatabaseException e) {
|
||||
throw new RuntimeException(e); // TODO
|
||||
DialogUtil.showErrorDialog(requireContext(), "Failed to enable encryption", e);
|
||||
}
|
||||
}, null);
|
||||
}, () -> view.setChecked(false));
|
||||
}else {
|
||||
if(!SettingsUtil.isDatabaseEncrypted(requireContext())) return;
|
||||
|
||||
DialogUtil.showYesNo(requireContext(), R.string.disable_encryption_title, R.string.disable_encryption_message, () -> {
|
||||
try {
|
||||
OTPDatabase.decrypt(requireContext());
|
||||
SettingsUtil.disableEncryption(requireContext());
|
||||
@ -106,12 +110,14 @@ public class SettingsFragment extends NamedFragment {
|
||||
binding.settingsBiometricLock.setChecked(false);
|
||||
binding.settingsBiometricLock.setEnabled(false);
|
||||
} catch (OTPDatabaseException | CryptoException e) {
|
||||
throw new RuntimeException(e); // TODO
|
||||
DialogUtil.showErrorDialog(requireContext(), "Failed to disable encryption", e);
|
||||
}
|
||||
}, () -> view.setChecked(true));
|
||||
}
|
||||
});
|
||||
|
||||
if(SettingsUtil.isDatabaseEncrypted(requireContext()) && BiometricUtil.isSupported(requireContext())) {
|
||||
boolean biometricSupported = BiometricUtil.isSupported(requireContext());
|
||||
if(SettingsUtil.isDatabaseEncrypted(requireContext()) && biometricSupported) {
|
||||
binding.settingsBiometricLock.setChecked(SettingsUtil.isBiometricEncryption(requireContext()));
|
||||
binding.settingsBiometricLock.setOnCheckedChangeListener((view, checked) -> {
|
||||
if(checked) {
|
||||
@ -289,7 +295,6 @@ public class SettingsFragment extends NamedFragment {
|
||||
private void loadBackup(Uri uri, SecretKey key, CryptoParameters parameters) throws BackupException, OTPDatabaseException, CryptoException {
|
||||
BackupData data = BackupUtil.loadBackup(requireContext(), uri);
|
||||
OTPDatabase db = data.loadDatabase(key, parameters);
|
||||
//DialogUtil.showErrorDialog(requireContext(), "Success: " + db);
|
||||
// TODO: prompt user that all current data will be deleted
|
||||
OTPDatabase.promptLoadDatabase(requireActivity(), () -> {
|
||||
OTPDatabase oldDatabase = OTPDatabase.getLoadedDatabase();
|
||||
|
@ -1,7 +1,5 @@
|
||||
package com.cringe_studios.cringe_authenticator.grouplist;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.app.Application;
|
||||
import android.content.Context;
|
||||
import android.os.Handler;
|
||||
import android.os.Looper;
|
||||
@ -9,19 +7,13 @@ import android.view.LayoutInflater;
|
||||
import android.view.ViewGroup;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
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.MainActivity;
|
||||
import com.cringe_studios.cringe_authenticator.databinding.MenuItemBinding;
|
||||
import com.cringe_studios.cringe_authenticator.otplist.OTPListItem;
|
||||
import com.cringe_studios.cringe_authenticator.util.SettingsUtil;
|
||||
|
||||
import org.bouncycastle.jcajce.provider.symmetric.ARC4;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
@ -1,10 +1,8 @@
|
||||
package com.cringe_studios.cringe_authenticator.grouplist;
|
||||
|
||||
import android.content.res.ColorStateList;
|
||||
import android.content.res.TypedArray;
|
||||
import android.graphics.Color;
|
||||
import android.graphics.drawable.ColorDrawable;
|
||||
import android.os.Build;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
@ -6,7 +6,6 @@ import com.cringe_studios.cringe_authenticator_library.OTPException;
|
||||
import com.cringe_studios.cringe_authenticator_library.OTPType;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Objects;
|
||||
|
||||
public class OTPData implements Serializable {
|
||||
|
||||
@ -102,17 +101,4 @@ public class OTPData implements Serializable {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
OTPData otpData = (OTPData) o;
|
||||
return digits == otpData.digits && period == otpData.period && counter == otpData.counter && checksum == otpData.checksum && Objects.equals(name, otpData.name) && Objects.equals(issuer, otpData.issuer) && type == otpData.type && Objects.equals(secret, otpData.secret) && algorithm == otpData.algorithm;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(name, issuer, type, secret, algorithm, digits, period, counter, checksum);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -3,14 +3,12 @@ package com.cringe_studios.cringe_authenticator.otplist;
|
||||
import android.content.Context;
|
||||
import android.os.Handler;
|
||||
import android.os.Looper;
|
||||
import android.util.Log;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.Toast;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.core.util.Consumer;
|
||||
import androidx.recyclerview.widget.ItemTouchHelper;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
|
@ -2,7 +2,6 @@ package com.cringe_studios.cringe_authenticator.scanner;
|
||||
|
||||
import com.cringe_studios.cringe_authenticator.model.OTPData;
|
||||
import com.cringe_studios.cringe_authenticator.model.OTPMigrationPart;
|
||||
import com.cringe_studios.cringe_authenticator.proto.OTPMigration;
|
||||
|
||||
public class DetectedCode {
|
||||
|
||||
|
@ -3,7 +3,6 @@ package com.cringe_studios.cringe_authenticator.scanner;
|
||||
import android.net.Uri;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.core.util.Consumer;
|
||||
|
||||
import com.cringe_studios.cringe_authenticator.model.OTPMigrationPart;
|
||||
|
@ -8,13 +8,11 @@ import android.media.Image;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.view.MotionEvent;
|
||||
import android.view.WindowManager;
|
||||
import android.widget.Toast;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.annotation.OptIn;
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
import androidx.camera.core.Camera;
|
||||
import androidx.camera.core.CameraSelector;
|
||||
import androidx.camera.core.ExperimentalGetImage;
|
||||
@ -32,9 +30,7 @@ import com.cringe_studios.cringe_authenticator.R;
|
||||
import com.cringe_studios.cringe_authenticator.databinding.ActivityQrScannerBinding;
|
||||
import com.cringe_studios.cringe_authenticator.model.OTPData;
|
||||
import com.cringe_studios.cringe_authenticator.model.OTPMigrationPart;
|
||||
import com.cringe_studios.cringe_authenticator.util.SettingsUtil;
|
||||
import com.cringe_studios.cringe_authenticator.util.StyledDialogBuilder;
|
||||
import com.cringe_studios.cringe_authenticator.util.ThemeUtil;
|
||||
import com.cringe_studios.cringe_authenticator.util.DialogUtil;
|
||||
import com.google.common.util.concurrent.ListenableFuture;
|
||||
import com.google.mlkit.vision.common.InputImage;
|
||||
|
||||
@ -157,10 +153,7 @@ public class QRScannerActivity extends BaseActivity {
|
||||
}
|
||||
|
||||
if(part.getBatchIndex() == 0) {
|
||||
new StyledDialogBuilder(this)
|
||||
.setTitle(R.string.qr_scanner_migration_title)
|
||||
.setMessage(R.string.qr_scanner_migration_message)
|
||||
.setPositiveButton(R.string.yes, (d, which) -> {
|
||||
DialogUtil.showYesNo(this, R.string.qr_scanner_migration_title, R.string.qr_scanner_migration_message, () -> {
|
||||
if(part.getBatchSize() == 1) {
|
||||
success(part.getOTPs());
|
||||
}else {
|
||||
@ -169,10 +162,7 @@ public class QRScannerActivity extends BaseActivity {
|
||||
Toast.makeText(this, getString(R.string.qr_scanner_migration_part, part.getBatchIndex()+ 1, part.getBatchSize()), Toast.LENGTH_LONG).show();
|
||||
process = true;
|
||||
}
|
||||
})
|
||||
.setNegativeButton(R.string.no, (d, which) -> cancel())
|
||||
.show()
|
||||
.setCanceledOnTouchOutside(false);
|
||||
}, null);
|
||||
}else {
|
||||
currentCodes.addAll(Arrays.asList(part.getOTPs()));
|
||||
Toast.makeText(this, getString(R.string.qr_scanner_migration_part, part.getBatchIndex()+ 1, part.getBatchSize()), Toast.LENGTH_LONG).show();
|
||||
|
@ -1,26 +1,13 @@
|
||||
package com.cringe_studios.cringe_authenticator.unlock;
|
||||
|
||||
import static androidx.biometric.BiometricManager.Authenticators.BIOMETRIC_STRONG;
|
||||
import static androidx.biometric.BiometricManager.Authenticators.DEVICE_CREDENTIAL;
|
||||
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
import android.security.KeyStoreParameter;
|
||||
import android.security.keystore.KeyGenParameterSpec;
|
||||
import android.security.keystore.KeyProtection;
|
||||
import android.view.View;
|
||||
import android.view.WindowManager;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
import androidx.biometric.BiometricManager;
|
||||
import androidx.biometric.BiometricPrompt;
|
||||
import androidx.core.content.ContextCompat;
|
||||
|
||||
import com.cringe_studios.cringe_authenticator.BaseActivity;
|
||||
import com.cringe_studios.cringe_authenticator.MainActivity;
|
||||
import com.cringe_studios.cringe_authenticator.R;
|
||||
import com.cringe_studios.cringe_authenticator.crypto.BiometricKey;
|
||||
import com.cringe_studios.cringe_authenticator.crypto.Crypto;
|
||||
import com.cringe_studios.cringe_authenticator.crypto.CryptoException;
|
||||
@ -32,21 +19,11 @@ import com.cringe_studios.cringe_authenticator.util.OTPDatabaseException;
|
||||
import com.cringe_studios.cringe_authenticator.util.SettingsUtil;
|
||||
import com.cringe_studios.cringe_authenticator.util.ThemeUtil;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.security.KeyStore;
|
||||
import java.security.KeyStoreException;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.security.cert.CertificateException;
|
||||
import java.util.concurrent.Executor;
|
||||
|
||||
import javax.crypto.KeyGenerator;
|
||||
import javax.crypto.SecretKey;
|
||||
import javax.crypto.spec.SecretKeySpec;
|
||||
|
||||
public class UnlockActivity extends BaseActivity {
|
||||
|
||||
private static final long LOCK_TIMEOUT = 10000;
|
||||
|
||||
private ActivityUnlockBinding binding;
|
||||
|
||||
@Override
|
||||
|
@ -8,9 +8,6 @@ import androidx.activity.result.contract.ActivityResultContract;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import com.cringe_studios.cringe_authenticator.scanner.QRScannerActivity;
|
||||
import com.cringe_studios.cringe_authenticator.scanner.ScannerResult;
|
||||
|
||||
public class UnlockContract extends ActivityResultContract<Void, Boolean> {
|
||||
@NonNull
|
||||
@Override
|
||||
|
@ -3,26 +3,21 @@ package com.cringe_studios.cringe_authenticator.urihandler;
|
||||
import android.content.Intent;
|
||||
import android.net.Uri;
|
||||
import android.os.Bundle;
|
||||
import android.util.Log;
|
||||
import android.view.WindowManager;
|
||||
import android.widget.Toast;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.appcompat.app.AlertDialog;
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
|
||||
import com.cringe_studios.cringe_authenticator.BaseActivity;
|
||||
import com.cringe_studios.cringe_authenticator.R;
|
||||
import com.cringe_studios.cringe_authenticator.crypto.CryptoException;
|
||||
import com.cringe_studios.cringe_authenticator.model.OTPData;
|
||||
import com.cringe_studios.cringe_authenticator.unlock.UnlockContract;
|
||||
import com.cringe_studios.cringe_authenticator.util.DialogUtil;
|
||||
import com.cringe_studios.cringe_authenticator.util.OTPDatabase;
|
||||
import com.cringe_studios.cringe_authenticator.util.OTPDatabaseException;
|
||||
import com.cringe_studios.cringe_authenticator.util.OTPParser;
|
||||
import com.cringe_studios.cringe_authenticator.util.SettingsUtil;
|
||||
import com.cringe_studios.cringe_authenticator.util.StyledDialogBuilder;
|
||||
import com.cringe_studios.cringe_authenticator.util.ThemeUtil;
|
||||
|
||||
public class URIHandlerActivity extends BaseActivity {
|
||||
|
||||
|
@ -1,14 +1,13 @@
|
||||
package com.cringe_studios.cringe_authenticator.util;
|
||||
|
||||
import android.content.Context;
|
||||
import android.text.InputType;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.widget.ArrayAdapter;
|
||||
import android.widget.Button;
|
||||
import android.widget.EditText;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.StringRes;
|
||||
import androidx.appcompat.app.AlertDialog;
|
||||
import androidx.core.util.Consumer;
|
||||
|
||||
@ -16,6 +15,7 @@ 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.DialogInputCodeTotpBinding;
|
||||
import com.cringe_studios.cringe_authenticator.databinding.DialogInputPasswordBinding;
|
||||
import com.cringe_studios.cringe_authenticator.databinding.DialogSetPasswordBinding;
|
||||
import com.cringe_studios.cringe_authenticator.model.OTPData;
|
||||
import com.cringe_studios.cringe_authenticator_library.OTPAlgorithm;
|
||||
@ -306,11 +306,11 @@ public class DialogUtil {
|
||||
}
|
||||
|
||||
public static void showInputPasswordDialog(Context context, Consumer<String> callback, Runnable onCancel) {
|
||||
EditText passwordField = new EditText(context);
|
||||
passwordField.setInputType(InputType.TYPE_TEXT_VARIATION_PASSWORD);
|
||||
DialogInputPasswordBinding binding = DialogInputPasswordBinding.inflate(LayoutInflater.from(context));
|
||||
|
||||
AlertDialog dialog = new StyledDialogBuilder(context)
|
||||
.setTitle("Input Password")
|
||||
.setView(passwordField) // TODO: better layout
|
||||
.setView(binding.inputPassword)
|
||||
.setPositiveButton("Ok", (d, which) -> {})
|
||||
.setNegativeButton(R.string.cancel, (d, which) -> { if(onCancel != null) onCancel.run(); })
|
||||
.setOnCancelListener(d -> { if(onCancel != null) onCancel.run(); })
|
||||
@ -319,17 +319,56 @@ public class DialogUtil {
|
||||
dialog.setOnShowListener(d -> {
|
||||
Button okButton = dialog.getButton(AlertDialog.BUTTON_POSITIVE);
|
||||
okButton.setOnClickListener(v -> {
|
||||
if(passwordField.getText().length() == 0) {
|
||||
if(binding.inputPassword.getText().length() == 0) {
|
||||
DialogUtil.showErrorDialog(context, "You need to enter a password");
|
||||
return;
|
||||
}
|
||||
|
||||
dialog.dismiss();
|
||||
callback.accept(passwordField.getText().toString());
|
||||
callback.accept(binding.inputPassword.getText().toString());
|
||||
});
|
||||
});
|
||||
|
||||
dialog.show();
|
||||
}
|
||||
|
||||
public static void showYesNo(Context context, @StringRes int title, @StringRes int message, @StringRes int yesText, @StringRes int noText, Runnable yes, Runnable no) {
|
||||
new StyledDialogBuilder(context)
|
||||
.setTitle(title)
|
||||
.setMessage(message)
|
||||
.setPositiveButton(yesText, (d, w) -> {
|
||||
if(yes != null) yes.run();
|
||||
})
|
||||
.setNegativeButton(noText, (d, w) -> {
|
||||
if(no != null) no.run();
|
||||
})
|
||||
.show()
|
||||
.setCanceledOnTouchOutside(false);
|
||||
}
|
||||
|
||||
public static void showYesNo(Context context, @StringRes int title, @StringRes int message, Runnable yes, Runnable no) {
|
||||
showYesNo(context, title, message, R.string.yes, R.string.no, yes, no);
|
||||
}
|
||||
|
||||
public static void showYesNoCancel(Context context, @StringRes int title, @StringRes int message, @StringRes int yesText, @StringRes int noText, @StringRes int cancelText, Runnable yes, Runnable no, Runnable cancel) {
|
||||
new StyledDialogBuilder(context)
|
||||
.setTitle(title)
|
||||
.setMessage(message)
|
||||
.setPositiveButton(yesText, (d, w) -> {
|
||||
if(yes != null) yes.run();
|
||||
})
|
||||
.setNegativeButton(noText, (d, w) -> {
|
||||
if(no != null) no.run();
|
||||
})
|
||||
.setNeutralButton(cancelText, (d, w) -> d.cancel())
|
||||
.setOnCancelListener(d -> {
|
||||
if(cancel != null) cancel.run();
|
||||
})
|
||||
.show();
|
||||
}
|
||||
|
||||
public static void showYesNoCancel(Context context, @StringRes int title, @StringRes int message, Runnable yes, Runnable no, Runnable cancel) {
|
||||
showYesNoCancel(context, title, message, R.string.yes, R.string.no, R.string.cancel, yes, no, cancel);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -6,7 +6,6 @@ import androidx.appcompat.app.ActionBar;
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
import androidx.fragment.app.Fragment;
|
||||
import androidx.fragment.app.FragmentManager;
|
||||
import androidx.fragment.app.FragmentTransaction;
|
||||
|
||||
import com.cringe_studios.cringe_authenticator.R;
|
||||
import com.cringe_studios.cringe_authenticator.fragment.MenuDrawerFragment;
|
||||
|
@ -2,25 +2,18 @@ package com.cringe_studios.cringe_authenticator.util;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.Context;
|
||||
import android.util.Log;
|
||||
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
import androidx.core.util.Consumer;
|
||||
|
||||
import com.cringe_studios.cringe_authenticator.BaseActivity;
|
||||
import com.cringe_studios.cringe_authenticator.crypto.Crypto;
|
||||
import com.cringe_studios.cringe_authenticator.crypto.CryptoException;
|
||||
import com.cringe_studios.cringe_authenticator.crypto.CryptoParameters;
|
||||
import com.cringe_studios.cringe_authenticator.model.OTPData;
|
||||
import com.cringe_studios.cringe_authenticator.unlock.UnlockContract;
|
||||
import com.google.gson.JsonObject;
|
||||
import com.google.gson.JsonSyntaxException;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
|
@ -2,24 +2,16 @@ package com.cringe_studios.cringe_authenticator.util;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.SharedPreferences;
|
||||
import android.util.Base64;
|
||||
|
||||
import com.cringe_studios.cringe_authenticator.R;
|
||||
import com.cringe_studios.cringe_authenticator.backup.BackupGroup;
|
||||
import com.cringe_studios.cringe_authenticator.crypto.BiometricKey;
|
||||
import com.cringe_studios.cringe_authenticator.crypto.CryptoException;
|
||||
import com.cringe_studios.cringe_authenticator.crypto.CryptoParameters;
|
||||
import com.google.gson.Gson;
|
||||
|
||||
import org.bouncycastle.jcajce.provider.symmetric.ARC4;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
|
||||
public class SettingsUtil {
|
||||
|
||||
|
@ -1,8 +1,6 @@
|
||||
package com.cringe_studios.cringe_authenticator.util;
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
import android.content.res.Configuration;
|
||||
import android.util.Log;
|
||||
import android.view.View;
|
||||
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
|
29
app/src/main/res/layout/dialog_input_password.xml
Normal file
29
app/src/main/res/layout/dialog_input_password.xml
Normal file
@ -0,0 +1,29 @@
|
||||
<?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"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:padding="16dp">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/input_password_text"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/enter_password"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
<EditText
|
||||
android:id="@+id/input_password"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:ems="10"
|
||||
android:hint="@string/password"
|
||||
android:inputType="textPassword"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/input_password_text" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
@ -93,4 +93,7 @@
|
||||
<string name="backups">Backups</string>
|
||||
<string name="create_backup">Backup erstellen</string>
|
||||
<string name="load_backup">Backup laden</string>
|
||||
<string name="enter_password">Passwort eingeben</string>
|
||||
<string name="disable_encryption_title">Verschlüsselung deaktivieren</string>
|
||||
<string name="disable_encryption_message">Willst du wirklich die Verschlüsselung deaktivieren?</string>
|
||||
</resources>
|
@ -94,4 +94,7 @@
|
||||
<string name="backups">Backups</string>
|
||||
<string name="create_backup">Create backup</string>
|
||||
<string name="load_backup">Load backup</string>
|
||||
<string name="enter_password">Enter Password</string>
|
||||
<string name="disable_encryption_title">Disable encryption</string>
|
||||
<string name="disable_encryption_message">Do you really want to disable encryption?</string>
|
||||
</resources>
|
Loading…
Reference in New Issue
Block a user