Fix locale on older Android, Clean up code

This commit is contained in:
MrLetsplay 2023-09-27 15:40:45 +02:00
parent 494f9d66fc
commit 2e88d021bb
Signed by: mr
SSH Key Fingerprint: SHA256:92jBH80vpXyaZHjaIl47pjRq+Yt7XGTArqQg1V7hSqg
28 changed files with 147 additions and 194 deletions

View File

@ -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());
}

View File

@ -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;

View File

@ -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) -> {
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);
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);
}
}, 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

View File

@ -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;

View File

@ -1,7 +1,5 @@
package com.cringe_studios.cringe_authenticator.backup;
import org.jetbrains.annotations.Contract;
public class BackupGroup {
public String id;

View File

@ -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;

View File

@ -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;

View File

@ -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) -> {
for(OTPListItem item : items) {
otpListAdapter.remove(item.getOTPData());
}
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();
saveOTPs();
finishEditing();
}, null, null);
}
public boolean isEditing() {

View File

@ -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) -> {
for(GroupListItem item : groupListAdapter.getSelectedGroups()) {
removeGroup(item.getGroupId());
}
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();
groupListAdapter.finishEditing();
}, null);
}
public void removeGroup(String group) {

View File

@ -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,24 +95,29 @@ 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 {
try {
OTPDatabase.decrypt(requireContext());
SettingsUtil.disableEncryption(requireContext());
Log.d("Crypto", "DB encryption disabled");
if(!SettingsUtil.isDatabaseEncrypted(requireContext())) return;
binding.settingsBiometricLock.setChecked(false);
binding.settingsBiometricLock.setEnabled(false);
} catch (OTPDatabaseException | CryptoException e) {
throw new RuntimeException(e); // TODO
}
DialogUtil.showYesNo(requireContext(), R.string.disable_encryption_title, R.string.disable_encryption_message, () -> {
try {
OTPDatabase.decrypt(requireContext());
SettingsUtil.disableEncryption(requireContext());
Log.d("Crypto", "DB encryption disabled");
binding.settingsBiometricLock.setChecked(false);
binding.settingsBiometricLock.setEnabled(false);
} catch (OTPDatabaseException | CryptoException e) {
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();

View File

@ -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;

View File

@ -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;

View File

@ -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);
}
}

View File

@ -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;

View File

@ -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 {

View File

@ -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;

View File

@ -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,22 +153,16 @@ 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) -> {
if(part.getBatchSize() == 1) {
success(part.getOTPs());
}else {
currentCodes.addAll(Arrays.asList(part.getOTPs()));
lastPart = part;
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);
DialogUtil.showYesNo(this, R.string.qr_scanner_migration_title, R.string.qr_scanner_migration_message, () -> {
if(part.getBatchSize() == 1) {
success(part.getOTPs());
}else {
currentCodes.addAll(Arrays.asList(part.getOTPs()));
lastPart = part;
Toast.makeText(this, getString(R.string.qr_scanner_migration_part, part.getBatchIndex()+ 1, part.getBatchSize()), Toast.LENGTH_LONG).show();
process = true;
}
}, 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();

View File

@ -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

View File

@ -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

View File

@ -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 {

View File

@ -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);
}
}

View File

@ -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;

View File

@ -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;

View File

@ -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 {

View File

@ -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;

View 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>

View File

@ -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>

View File

@ -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>