Compare commits

...
17 Commits
Author SHA1 Message Date
Alexander Bakker b6a31ed789 Release v1.0 2019-09-08 14:22:33 +02:00
Alexander BakkerandGitHub 9c272a0d4d Merge pull request #190 from michaelschattgen/feature-about
Add AboutActivity
2019-09-07 12:50:11 +02:00
Michael Schättgen 3e626a37db Add AboutActivity
Add DialogStyles for different themes

Add review fixes

Remove unused usings
2019-09-07 12:49:31 +02:00
Alexander BakkerandGitHub e2150e3823 Merge pull request #194 from michaelschattgen/feature-empty-dataset
Add placeholder for empty recyclerview
2019-09-07 11:55:49 +02:00
Michael Schättgen 6480fef315 Add placeholder for empty recyclerview 2019-09-07 11:48:38 +02:00
Alexander BakkerandGitHub 95df2ceb42 Merge pull request #193 from michaelschattgen/fix-icon-onboarding
Fix app icon in IntroActivity
2019-09-07 10:41:02 +02:00
Michael SchättgenandGitHub 189698dddb Merge pull request #189 from alexbakker/entry-defaults
Set a default value for period and digits for new entries
2019-09-07 00:03:55 +02:00
Michael Schättgen 438d5581aa Fix app icon in IntroActivity 2019-09-06 23:58:04 +02:00
Alexander BakkerandGitHub 7af78b11f5 Merge pull request #192 from michaelschattgen/feature-fixbackpress
Add temporary backpress fix
2019-09-06 22:02:10 +02:00
Michael SchättgenandGitHub 5d68211ce9 Merge pull request #191 from alexbakker/travis-test
Add Travis CI configuration
2019-09-06 21:49:44 +02:00
Michael Schättgen a7e1a88dc8 Add temporary backpress fix 2019-09-06 21:48:17 +02:00
Alexander Bakker 3054032a37 Add Travis CI configuration
This doesn't spin up an emulator yet, but we don't have any tests that require
one anyway
2019-09-05 01:12:30 +02:00
Alexander Bakker 79279630ba Fix all linter errors
Well almost all, just ignore missing translation errors
2019-09-05 01:09:16 +02:00
Alexander Bakker e019fb6db2 Set a default value for period and digits for new entries
This is also in preparation for #24, but I haven't fully figured out how to do
that nicely yet, so that'll come later.
2019-09-04 23:48:30 +02:00
Alexander Bakker 85bdecc573 Fix syntax error in the XML file of the German translation 2019-09-04 23:47:25 +02:00
Andrey SaksonovandAlexander Bakker 21f3d93295 Update Russian localization (#170) 2019-09-03 10:14:08 +02:00
xopezandAlexander Bakker 888e9d0e4a Added German Translation (#188)
* Added German Translation

* Update arrays.xml
2019-09-03 10:10:22 +02:00
39 changed files with 1660 additions and 261 deletions
+7
View File
@@ -0,0 +1,7 @@
language: android
android:
components:
- android-28
- build-tools-28.0.3
script:
- ./gradlew build test
+18 -4
View File
@@ -7,13 +7,23 @@ android {
applicationId "com.beemdevelopment.aegis"
minSdkVersion 19
targetSdkVersion 28
versionCode 18
versionName "1.0-beta1"
versionCode 19
versionName "1.0"
}
lintOptions {
abortOnError true
disable "MissingTranslation"
}
testOptions {
unitTests.all {
useJUnitPlatform()
ignoreFailures false
testLogging {
events "passed", "skipped", "failed", "standardOut", "standardError"
}
}
}
@@ -60,11 +70,15 @@ dependencies {
implementation "com.github.topjohnwu.libsu:io:${libsuVersion}"
implementation 'com.github.bumptech.glide:annotations:4.9.0'
implementation 'com.github.bumptech.glide:glide:4.9.0'
implementation ("com.github.bumptech.glide:recyclerview-integration:4.9.0") {
implementation "com.mikepenz:iconics-core:3.2.5"
implementation 'com.mikepenz:material-design-iconic-typeface:2.2.0.5@aar'
implementation 'de.psdev.licensesdialog:licensesdialog:2.1.0'
implementation("com.github.bumptech.glide:recyclerview-integration:4.9.0") {
transitive = false
}
annotationProcessor 'androidx.annotation:annotation:1.1.0'
annotationProcessor 'com.github.bumptech.glide:compiler:4.9.0'
testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.4.2'
testImplementation 'org.junit.jupiter:junit-jupiter-api:5.4.2'
}
}
@@ -1,13 +0,0 @@
package com.beemdevelopment.aegis;
import android.app.Application;
import android.test.ApplicationTestCase;
/**
* <a href="http://d.android.com/tools/testing/testing_android.html">Testing Fundamentals</a>
*/
public class ApplicationTest extends ApplicationTestCase<Application> {
public ApplicationTest() {
super(Application.class);
}
}
+6
View File
@@ -17,6 +17,9 @@
android:theme="@style/AppTheme.NoActionBar"
tools:ignore="GoogleAppIndexingWarning"
tools:replace="android:theme">
<activity
android:name=".ui.AboutActivity"
android:label="@string/title_activity_about"></activity>
<activity
android:name=".ui.SelectEntriesActivity"
android:label="Select entries" />
@@ -26,12 +29,15 @@
android:launchMode="singleTask">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="otpauth" />
</intent-filter>
</activity>
+45
View File
@@ -0,0 +1,45 @@
<html>
<head>
<style type="text/css">
* {
word-wrap: break-word;
}
body {
background-color: #%1$s;
color: #%2$s;
}
ul {
list-style-position: inside;
padding: 0;
padding-left: 5px;
}
li {
padding-bottom: 8px;
list-style-position: outside;
margin-left: 1em;
}
h3 {
padding-bottom: 0;
}
</style>
</head>
<body>
<div></div>
<h3>Version 1.0</h3>
<h4>New</h4>
<ul>
<li>New icon</li>
<li>Overhaul of interaction with the entry list</li>
<li>Persistent notification while the vault is unlocked</li>
<li>Language override option</li>
<li>Support for importing from FreeOTP+</li>
<li>Ability to toggle password visibility during unlock</li>
<li>Support for deeplinking otpauth URIs</li>
</ul>
<h4>Fixes</h4>
<ul>
<li>Bad overall performance and high battery usage</li>
<li>Codes with an uneven number of digits are displayed incorrectly</li>
<li>Crash when entering a large value for OTP period</li>
</ul>
</body>
@@ -0,0 +1,7 @@
package com.beemdevelopment.aegis;
public enum CancelAction {
KILL,
CLOSE
}
@@ -5,6 +5,7 @@ import com.beemdevelopment.aegis.encoding.Base64Exception;
import com.beemdevelopment.aegis.otp.GoogleAuthInfo;
import com.beemdevelopment.aegis.otp.OtpInfo;
import com.beemdevelopment.aegis.otp.OtpInfoException;
import com.beemdevelopment.aegis.otp.TotpInfo;
import com.beemdevelopment.aegis.util.UUIDMap;
import org.json.JSONException;
@@ -133,11 +134,34 @@ public class DatabaseEntry extends UUIDMap.Value {
}
DatabaseEntry entry = (DatabaseEntry) o;
return super.equals(entry)
&& getName().equals(entry.getName())
return super.equals(entry) && equivalates(entry);
}
/**
* Reports whether this entry is equivalent to the given entry. The UUIDs of these
* entries are ignored during the comparison, so they are not necessarily the same
* instance.
*/
public boolean equivalates(DatabaseEntry entry) {
return getName().equals(entry.getName())
&& getIssuer().equals(entry.getIssuer())
&& Objects.equals(getGroup(), entry.getGroup())
&& getInfo().equals(entry.getInfo())
&& Arrays.equals(getIcon(), entry.getIcon());
}
/**
* Reports whether this entry has its values set to the defaults.
*/
public boolean isDefault() {
return equivalates(getDefault());
}
public static DatabaseEntry getDefault() {
try {
return new DatabaseEntry(new TotpInfo(null));
} catch (OtpInfoException e) {
throw new RuntimeException(e);
}
}
}
@@ -5,13 +5,16 @@ import android.content.Context;
import android.hardware.fingerprint.FingerprintManager;
import android.os.Build;
import androidx.annotation.RequiresApi;
public class FingerprintHelper {
private FingerprintHelper() {
}
@RequiresApi(api = Build.VERSION_CODES.M)
public static FingerprintManager getManager(Context context) {
if (isSupported() && PermissionHelper.granted(context, Manifest.permission.USE_FINGERPRINT)) {
if (PermissionHelper.granted(context, Manifest.permission.USE_FINGERPRINT)) {
FingerprintManager manager = (FingerprintManager) context.getSystemService(Context.FINGERPRINT_SERVICE);
if (manager != null && manager.isHardwareDetected() && manager.hasEnrolledFingerprints()) {
return manager;
@@ -20,6 +23,11 @@ public class FingerprintHelper {
return null;
}
@RequiresApi(api = Build.VERSION_CODES.M)
public static boolean isAvailable(Context context) {
return getManager(context) != null;
}
public static boolean isSupported() {
return Build.VERSION.SDK_INT >= Build.VERSION_CODES.M;
}
@@ -0,0 +1,121 @@
package com.beemdevelopment.aegis.ui;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.content.res.Resources;
import android.graphics.Color;
import android.net.Uri;
import android.os.Bundle;
import android.view.View;
import android.widget.TextView;
import com.beemdevelopment.aegis.Preferences;
import com.beemdevelopment.aegis.R;
import com.beemdevelopment.aegis.Theme;
import com.beemdevelopment.aegis.helpers.ThemeHelper;
import com.beemdevelopment.aegis.ui.glide.GlideLicense;
import com.mikepenz.iconics.Iconics;
import com.mikepenz.iconics.context.IconicsLayoutInflater2;
import com.mikepenz.material_design_iconic_typeface_library.MaterialDesignIconic;
import androidx.core.view.LayoutInflaterCompat;
import de.psdev.licensesdialog.LicenseResolver;
import de.psdev.licensesdialog.LicensesDialog;
import de.psdev.licensesdialog.licenses.License;
public class AboutActivity extends AegisActivity {
private static String GITHUB = "https://github.com/beemdevelopment/Aegis";
private static String WEBSITE_ALEXANDER = "https://alexbakker.me";
private static String GITHUB_MICHAEL = "https://github.com/michaelschattgen";
private static String MAIL_BEEMDEVELOPMENT = "beemdevelopment@gmail.com";
private static String WEBSITE_BEEMDEVELOPMENT = "https://beem.dev/";
private static String PLAYSTORE_BEEMDEVELOPMENT = "https://play.google.com/store/apps/details?id=com.beemdevelopment.aegis";
@Override
protected void onCreate(Bundle savedInstanceState) {
LayoutInflaterCompat.setFactory2(getLayoutInflater(), new IconicsLayoutInflater2(getDelegate()));
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_about);
Iconics.init(getApplicationContext());
Iconics.registerFont(new MaterialDesignIconic());
View btnLicenses = findViewById(R.id.btn_licenses);
btnLicenses.setOnClickListener(v -> showLicenseDialog());
TextView appVersion = findViewById(R.id.app_version);
appVersion.setText(getCurrentVersion());
View btnGithub = findViewById(R.id.btn_github);
btnGithub.setOnClickListener(v -> openUrl(GITHUB));
View btnAlexander = findViewById(R.id.btn_alexander);
btnAlexander.setOnClickListener(v -> openUrl(WEBSITE_ALEXANDER));
View btnMichael = findViewById(R.id.btn_michael);
btnMichael.setOnClickListener(v -> openUrl(GITHUB_MICHAEL));
View btnMail = findViewById(R.id.btn_email);
btnMail.setOnClickListener(v -> openMail(MAIL_BEEMDEVELOPMENT));
View btnWebsite = findViewById(R.id.btn_website);
btnWebsite.setOnClickListener(v -> openUrl(WEBSITE_BEEMDEVELOPMENT));
View btnRate = findViewById(R.id.btn_rate);
btnRate.setOnClickListener(v -> openUrl(PLAYSTORE_BEEMDEVELOPMENT ));
View btnChangelog = findViewById(R.id.btn_changelog);
btnChangelog.setOnClickListener(v -> {
ChangelogDialog.create().setTheme(getCurrentTheme()).show(getSupportFragmentManager(), "CHANGELOG_DIALOG");
});
}
private String getCurrentVersion() {
try {
return getPackageManager().getPackageInfo(getPackageName(), 0).versionName;
} catch (PackageManager.NameNotFoundException e) {
e.printStackTrace();
}
return "Unknown version";
}
private void openUrl(String url) {
Intent browserIntent = new Intent(Intent.ACTION_VIEW);
browserIntent.setData(Uri.parse(url));
browserIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(browserIntent);
}
private void openMail(String mailaddress) {
Intent mailIntent = new Intent(Intent.ACTION_SENDTO);
mailIntent.setData(Uri.parse("mailto:" + mailaddress));
mailIntent.putExtra(Intent.EXTRA_EMAIL, mailaddress);
mailIntent.putExtra(Intent.EXTRA_SUBJECT, R.string.app_name_full);
startActivity(Intent.createChooser(mailIntent, this.getString(R.string.email)));
}
private void showLicenseDialog() {
String stylesheet = getString(R.string.custom_notices_format_style);
int backgroundColorResource = getCurrentTheme() == Theme.AMOLED ? R.attr.cardBackgroundFocused : R.attr.cardBackground;
String backgroundColor = String.format("%06X", (0xFFFFFF & ThemeHelper.getThemeColor(backgroundColorResource, getTheme())));
String textColor = String.format("%06X", (0xFFFFFF & ThemeHelper.getThemeColor(R.attr.primaryText, getTheme())));
String licenseColor = String.format("%06X", (0xFFFFFF & ThemeHelper.getThemeColor(R.attr.cardBackgroundFocused, getTheme())));
stylesheet = String.format(stylesheet, backgroundColor, textColor, licenseColor);
LicenseResolver.registerLicense(new GlideLicense());
new LicensesDialog.Builder(this)
.setNotices(R.raw.notices)
.setTitle(R.string.licenses)
.setNoticesCssStyle(stylesheet)
.setIncludeOwnLicense(true)
.build()
.show();
}
}
@@ -22,6 +22,7 @@ import java.util.Locale;
public abstract class AegisActivity extends AppCompatActivity implements AegisApplication.LockListener {
private boolean _resumed;
private AegisApplication _app;
private Theme _currentTheme;
@Override
protected void onCreate(Bundle savedInstanceState) {
@@ -89,6 +90,8 @@ public abstract class AegisActivity extends AppCompatActivity implements AegisAp
}
protected void setPreferredTheme(Theme theme) {
_currentTheme = theme;
switch (theme) {
case LIGHT:
setTheme(R.style.AppTheme);
@@ -136,4 +139,8 @@ public abstract class AegisActivity extends AppCompatActivity implements AegisAp
}
}
}
protected Theme getCurrentTheme() {
return _currentTheme;
}
}
@@ -1,5 +1,6 @@
package com.beemdevelopment.aegis.ui;
import android.annotation.SuppressLint;
import android.content.Context;
import android.content.Intent;
import android.hardware.fingerprint.FingerprintManager;
@@ -17,6 +18,7 @@ import android.widget.LinearLayout;
import android.widget.TextView;
import com.beemdevelopment.aegis.R;
import com.beemdevelopment.aegis.CancelAction;
import com.beemdevelopment.aegis.crypto.KeyStoreHandle;
import com.beemdevelopment.aegis.crypto.KeyStoreHandleException;
import com.beemdevelopment.aegis.db.DatabaseFileCredentials;
@@ -39,11 +41,13 @@ import androidx.appcompat.app.AlertDialog;
public class AuthActivity extends AegisActivity implements FingerprintUiHelper.Callback, SlotListTask.Callback {
private EditText _textPassword;
private CancelAction _cancelAction;
private SlotList _slots;
private FingerprintUiHelper _fingerHelper;
private FingerprintManager.CryptoObject _fingerCryptoObj;
@Override
@SuppressLint("NewApi")
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_auth);
@@ -69,11 +73,13 @@ public class AuthActivity extends AegisActivity implements FingerprintUiHelper.C
Intent intent = getIntent();
_slots = (SlotList) intent.getSerializableExtra("slots");
_cancelAction = (CancelAction) intent.getSerializableExtra("cancelAction");
// only show the fingerprint controls if the api version is new enough, permission is granted, a scanner is found and a fingerprint slot is found
FingerprintManager manager = FingerprintHelper.getManager(this);
if (manager != null && _slots.has(FingerprintSlot.class)) {
if (_slots.has(FingerprintSlot.class) && FingerprintHelper.isSupported() && FingerprintHelper.isAvailable(this)) {
boolean invalidated = false;
FingerprintManager manager = FingerprintHelper.getManager(this);
try {
// find a fingerprint slot with an id that matches an alias in the keystore
for (FingerprintSlot slot : _slots.findAll(FingerprintSlot.class)) {
@@ -144,10 +150,19 @@ public class AuthActivity extends AegisActivity implements FingerprintUiHelper.C
@Override
public void onBackPressed() {
// ignore back button presses
switch (_cancelAction) {
case KILL:
finishAffinity();
case CLOSE:
Intent intent = new Intent();
setResult(RESULT_CANCELED, intent);
finish();
}
}
@Override
@SuppressLint("NewApi")
public void onResume() {
super.onResume();
@@ -157,6 +172,7 @@ public class AuthActivity extends AegisActivity implements FingerprintUiHelper.C
}
@Override
@SuppressLint("NewApi")
public void onPause() {
super.onPause();
@@ -166,6 +182,7 @@ public class AuthActivity extends AegisActivity implements FingerprintUiHelper.C
}
@Override
@SuppressLint("NewApi")
public void onAuthenticated() {
trySlots(FingerprintSlot.class, _fingerCryptoObj.getCipher());
}
@@ -0,0 +1,90 @@
package com.beemdevelopment.aegis.ui;
import android.annotation.SuppressLint;
import android.app.Dialog;
import android.content.Context;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.graphics.Color;
import android.os.Bundle;
import android.view.InflateException;
import android.view.LayoutInflater;
import android.view.View;
import android.webkit.WebView;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AlertDialog;
import androidx.fragment.app.DialogFragment;
import com.beemdevelopment.aegis.R;
import com.beemdevelopment.aegis.Theme;
import com.beemdevelopment.aegis.helpers.ThemeHelper;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
public class ChangelogDialog extends DialogFragment {
private Theme _themeStyle;
public static ChangelogDialog create() {
return new ChangelogDialog();
}
@SuppressLint("InflateParams")
@NonNull
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
final View customView;
try {
customView = LayoutInflater.from(getActivity()).inflate(R.layout.dialog_web_view, null);
} catch (InflateException e) {
e.printStackTrace();
return new AlertDialog.Builder(getActivity())
.setTitle(android.R.string.dialog_alert_title)
.setMessage(getString(R.string.webview_error))
.setPositiveButton(android.R.string.ok, null)
.show();
}
AlertDialog dialog = new AlertDialog.Builder(getActivity())
.setTitle("Changelog")
.setView(customView)
.setPositiveButton(android.R.string.ok, null)
.show();
final WebView webView = customView.findViewById(R.id.web_view);
StringBuilder buf = new StringBuilder();
try (InputStream html = getActivity().getAssets().open("changelog.html")) {
BufferedReader in = new BufferedReader(new InputStreamReader(html, "UTF-8"));
String str;
while ((str = in.readLine()) != null)
buf.append(str);
in.close();
String changelog = buf.toString();
changelog = replaceStylesheet(changelog);
webView.loadData(changelog, "text/html", "UTF-8");
} catch (IOException e) {
webView.loadData("<h1>Unable to load</h1><p>" + e.getLocalizedMessage() + "</p>", "text/html", "UTF-8");
}
return dialog;
}
private String replaceStylesheet(String changelog) {
int backgroundColorResource = _themeStyle == Theme.AMOLED ? R.attr.cardBackgroundFocused : R.attr.cardBackground;
String backgroundColor = String.format("%06X", (0xFFFFFF & ThemeHelper.getThemeColor(backgroundColorResource, getContext().getTheme())));
String textColor = String.format("%06X", (0xFFFFFF & ThemeHelper.getThemeColor(R.attr.primaryText, getContext().getTheme())));
return String.format(changelog, backgroundColor, textColor);
}
public ChangelogDialog setTheme(Theme theme) {
_themeStyle = theme;
return this;
}
}
@@ -5,6 +5,7 @@ import android.app.Dialog;
import android.content.Context;
import android.content.DialogInterface;
import android.hardware.fingerprint.FingerprintManager;
import android.os.Build;
import android.text.Editable;
import android.text.InputType;
import android.text.TextWatcher;
@@ -35,6 +36,7 @@ import java.util.concurrent.atomic.AtomicReference;
import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import androidx.annotation.RequiresApi;
import androidx.annotation.StringRes;
import androidx.appcompat.app.AlertDialog;
@@ -178,6 +180,7 @@ public class Dialogs {
showSecureDialog(dialog);
}
@RequiresApi(api = Build.VERSION_CODES.M)
public static void showFingerprintDialog(Activity activity, Dialogs.SlotListener listener) {
View view = activity.getLayoutInflater().inflate(R.layout.dialog_fingerprint, null);
TextView textFingerprint = view.findViewById(R.id.text_fingerprint);
@@ -133,51 +133,49 @@ public class EditEntryActivity extends AegisActivity {
_advancedSettings = findViewById(R.id.expandableLayout);
// fill the fields with values if possible
if (_origEntry != null) {
if (_origEntry.hasIcon()) {
Glide.with(this)
.asDrawable()
.load(_origEntry)
.diskCacheStrategy(DiskCacheStrategy.NONE)
.skipMemoryCache(false)
.into(_iconView);
_hasCustomIcon = true;
} else {
TextDrawable drawable = TextDrawableHelper.generate(_origEntry.getIssuer(), _origEntry.getName(), _iconView);
_iconView.setImageDrawable(drawable);
}
_textName.setText(_origEntry.getName());
_textIssuer.setText(_origEntry.getIssuer());
OtpInfo info = _origEntry.getInfo();
if (info instanceof TotpInfo) {
_textPeriod.setText(Integer.toString(((TotpInfo) info).getPeriod()));
_rowPeriod.setVisibility(View.VISIBLE);
} else if (info instanceof HotpInfo) {
_textCounter.setText(Long.toString(((HotpInfo) info).getCounter()));
_rowCounter.setVisibility(View.VISIBLE);
} else {
throw new RuntimeException();
}
_textDigits.setText(Integer.toString(info.getDigits()));
byte[] secretBytes = _origEntry.getInfo().getSecret();
if (secretBytes != null) {
char[] secretChars = Base32.encode(secretBytes);
_textSecret.setText(secretChars, 0, secretChars.length);
}
String type = _origEntry.getInfo().getType();
_spinnerType.setSelection(getStringResourceIndex(R.array.otp_types_array, type), false);
String algo = _origEntry.getInfo().getAlgorithm(false);
_spinnerAlgo.setSelection(getStringResourceIndex(R.array.otp_algo_array, algo), false);
String group = _origEntry.getGroup();
setGroup(group);
if (_origEntry.hasIcon()) {
Glide.with(this)
.asDrawable()
.load(_origEntry)
.diskCacheStrategy(DiskCacheStrategy.NONE)
.skipMemoryCache(false)
.into(_iconView);
_hasCustomIcon = true;
} else {
TextDrawable drawable = TextDrawableHelper.generate(_origEntry.getIssuer(), _origEntry.getName(), _iconView);
_iconView.setImageDrawable(drawable);
}
_textName.setText(_origEntry.getName());
_textIssuer.setText(_origEntry.getIssuer());
OtpInfo info = _origEntry.getInfo();
if (info instanceof TotpInfo) {
_textPeriod.setText(Integer.toString(((TotpInfo) info).getPeriod()));
_rowPeriod.setVisibility(View.VISIBLE);
} else if (info instanceof HotpInfo) {
_textCounter.setText(Long.toString(((HotpInfo) info).getCounter()));
_rowCounter.setVisibility(View.VISIBLE);
} else {
throw new RuntimeException();
}
_textDigits.setText(Integer.toString(info.getDigits()));
byte[] secretBytes = _origEntry.getInfo().getSecret();
if (secretBytes != null) {
char[] secretChars = Base32.encode(secretBytes);
_textSecret.setText(secretChars, 0, secretChars.length);
}
String type = _origEntry.getInfo().getType();
_spinnerType.setSelection(getStringResourceIndex(R.array.otp_types_array, type), false);
String algo = _origEntry.getInfo().getAlgorithm(false);
_spinnerAlgo.setSelection(getStringResourceIndex(R.array.otp_algo_array, algo), false);
String group = _origEntry.getGroup();
setGroup(group);
// update the icon if the text changed
_textIssuer.addTextChangedListener(_iconChangeListener);
_textName.addTextChangedListener(_iconChangeListener);
@@ -331,7 +329,7 @@ public class EditEntryActivity extends AegisActivity {
}
// close the activity if the entry has not been changed
if (_origEntry != null && !_hasChangedIcon && _origEntry.equals(entry.get())) {
if (!_hasChangedIcon && _origEntry.equals(entry.get())) {
super.onBackPressed();
return;
}
@@ -465,7 +463,6 @@ public class EditEntryActivity extends AegisActivity {
throw new ParseException("Secret is not valid base32.");
}
// set otp info
OtpInfo info;
try {
switch (type.toLowerCase()) {
@@ -494,14 +491,8 @@ public class EditEntryActivity extends AegisActivity {
throw new ParseException("The entered info is incorrect: " + e.getMessage());
}
// set database entry info
DatabaseEntry entry;
if (_origEntry == null) {
entry = new DatabaseEntry(info);
} else {
entry = Cloner.clone(_origEntry);
entry.setInfo(info);
}
DatabaseEntry entry = Cloner.clone(_origEntry);
entry.setInfo(info);
entry.setIssuer(_textIssuer.getText().toString());
entry.setName(_textName.getText().toString());
@@ -65,7 +65,7 @@ public class IntroActivity extends AppIntro2 implements DerivationTask.Callback
SliderPage homeSliderPage = new SliderPage();
homeSliderPage.setTitle(getString(R.string.welcome));
homeSliderPage.setImageDrawable(R.drawable.icon_foreground_white);
homeSliderPage.setImageDrawable(R.drawable.app_icon);
homeSliderPage.setTitleColor(getResources().getColor(R.color.primary_text_dark));
homeSliderPage.setDescription(getString(R.string.app_description));
homeSliderPage.setDescColor(getResources().getColor(R.color.primary_text_dark));
@@ -83,7 +83,7 @@ public class IntroActivity extends AppIntro2 implements DerivationTask.Callback
SliderPage endSliderPage = new SliderPage();
endSliderPage.setTitle(getString(R.string.setup_completed));
endSliderPage.setDescription(getString(R.string.setup_completed_description));
endSliderPage.setImageDrawable(R.drawable.icon_foreground_white);
endSliderPage.setImageDrawable(R.drawable.app_icon);
endSliderPage.setBgColor(getResources().getColor(R.color.colorSecondary));
_endSlide = AppIntroFragment.newInstance(endSliderPage);
addSlide(_endSlide);
@@ -1,7 +1,6 @@
package com.beemdevelopment.aegis.ui;
import android.Manifest;
import android.app.Activity;
import android.content.ClipData;
import android.content.ClipboardManager;
import android.content.Context;
@@ -16,17 +15,15 @@ import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.MotionEvent;
import android.view.SubMenu;
import android.widget.LinearLayout;
import android.widget.SearchView;
import android.widget.Toast;
import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.view.ActionMode;
import androidx.core.view.MenuItemCompat;
import com.beemdevelopment.aegis.AegisApplication;
import com.beemdevelopment.aegis.R;
import com.beemdevelopment.aegis.SortCategory;
import com.beemdevelopment.aegis.CancelAction;
import com.beemdevelopment.aegis.ViewMode;
import com.beemdevelopment.aegis.db.DatabaseEntry;
import com.beemdevelopment.aegis.db.DatabaseFileCredentials;
@@ -38,7 +35,6 @@ import com.beemdevelopment.aegis.otp.GoogleAuthInfo;
import com.beemdevelopment.aegis.otp.GoogleAuthInfoException;
import com.beemdevelopment.aegis.ui.views.EntryListView;
import com.getbase.floatingactionbutton.FloatingActionsMenu;
import com.google.android.material.bottomsheet.BottomSheetDialog;
import com.google.zxing.BinaryBitmap;
import com.google.zxing.ChecksumException;
import com.google.zxing.FormatException;
@@ -49,6 +45,7 @@ import com.google.zxing.RGBLuminanceSource;
import com.google.zxing.Reader;
import com.google.zxing.Result;
import com.google.zxing.common.HybridBinarizer;
import com.mikepenz.iconics.context.IconicsContextWrapper;
import java.io.IOException;
import java.io.InputStream;
@@ -92,6 +89,7 @@ public class MainActivity extends AegisActivity implements EntryListView.Listene
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
_app = (AegisApplication) getApplication();
_db = _app.getDatabaseManager();
_loaded = false;
@@ -231,9 +229,7 @@ public class MainActivity extends AegisActivity implements EntryListView.Listene
private void startEditProfileActivity(int requestCode, DatabaseEntry entry, boolean isNew) {
Intent intent = new Intent(this, EditEntryActivity.class);
if (entry != null) {
intent.putExtra("entry", entry);
}
intent.putExtra("entry", entry != null ? entry : DatabaseEntry.getDefault());
intent.putExtra("isNew", isNew);
intent.putExtra("selectedGroup", _selectedGroup);
intent.putExtra("groups", new ArrayList<>(_db.getGroups()));
@@ -502,6 +498,11 @@ public class MainActivity extends AegisActivity implements EntryListView.Listene
_entryListView.removeEntry(oldEntry);
}
@Override
protected void attachBaseContext(Context newBase) {
super.attachBaseContext(IconicsContextWrapper.wrap(newBase));
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
_menu = menu;
@@ -548,10 +549,16 @@ public class MainActivity extends AegisActivity implements EntryListView.Listene
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.action_settings:
case R.id.action_settings: {
Intent intent = new Intent(this, PreferencesActivity.class);
startActivityForResult(intent, CODE_PREFERENCES);
return true;
}
case R.id.action_about: {
Intent intent = new Intent(this, AboutActivity.class);
startActivity(intent);
return true;
}
case R.id.action_lock:
_app.lock();
return true;
@@ -636,6 +643,7 @@ public class MainActivity extends AegisActivity implements EntryListView.Listene
Intent intent = new Intent(this, AuthActivity.class);
intent.putExtra("slots", _db.getFileHeader().getSlots());
intent.putExtra("requiresUnlock", false);
intent.putExtra("cancelAction", CancelAction.KILL);
startActivityForResult(intent, CODE_DECRYPT);
}
@@ -14,6 +14,7 @@ import android.widget.Toast;
import com.beemdevelopment.aegis.AegisApplication;
import com.beemdevelopment.aegis.BuildConfig;
import com.beemdevelopment.aegis.CancelAction;
import com.beemdevelopment.aegis.R;
import com.beemdevelopment.aegis.Theme;
import com.beemdevelopment.aegis.ViewMode;
@@ -284,7 +285,9 @@ public class PreferencesFragment extends PreferenceFragmentCompat {
SlotList slots = creds.getSlots();
if (!slots.has(FingerprintSlot.class)) {
Dialogs.showFingerprintDialog(getActivity(), new RegisterFingerprintListener());
if (FingerprintHelper.isSupported() && FingerprintHelper.isAvailable(getContext())) {
Dialogs.showFingerprintDialog(getActivity(), new RegisterFingerprintListener());
}
} else {
// remove the fingerprint slot
FingerprintSlot slot = slots.find(FingerprintSlot.class);
@@ -468,6 +471,7 @@ public class PreferencesFragment extends PreferenceFragmentCompat {
Intent intent = new Intent(getActivity(), AuthActivity.class);
intent.putExtra("slots", ((AegisImporter.EncryptedState) state).getSlots());
intent.putExtra("cancelAction", CancelAction.CLOSE);
startActivityForResult(intent, CODE_IMPORT_DECRYPT);
} else {
state.decrypt(getActivity(), new DatabaseImporter.DecryptListener() {
@@ -669,8 +673,9 @@ public class PreferencesFragment extends PreferenceFragmentCompat {
boolean multiPassword = slots.findAll(PasswordSlot.class).size() > 1;
boolean multiFinger = slots.findAll(FingerprintSlot.class).size() > 1;
boolean showSlots = BuildConfig.DEBUG || multiPassword || multiFinger;
boolean canUseFinger = FingerprintHelper.isSupported() && FingerprintHelper.isAvailable(getContext());
_setPasswordPreference.setEnabled(!multiPassword);
_fingerprintPreference.setEnabled(FingerprintHelper.getManager(getContext()) != null && !multiFinger);
_fingerprintPreference.setEnabled(canUseFinger && !multiFinger);
_fingerprintPreference.setChecked(slots.has(FingerprintSlot.class), true);
_slotsPreference.setVisible(showSlots);
} else {
@@ -43,7 +43,9 @@ public class SlotManagerActivity extends AegisActivity implements SlotAdapter.Li
bar.setDisplayHomeAsUpEnabled(true);
findViewById(R.id.button_add_fingerprint).setOnClickListener(view -> {
Dialogs.showFingerprintDialog(this ,this);
if (FingerprintHelper.isSupported() && FingerprintHelper.isAvailable(this)) {
Dialogs.showFingerprintDialog(this ,this);
}
});
findViewById(R.id.button_add_password).setOnClickListener(view -> {
@@ -71,7 +73,7 @@ public class SlotManagerActivity extends AegisActivity implements SlotAdapter.Li
// only show the fingerprint option if we can get an instance of the fingerprint manager
// and if none of the slots in the collection has a matching alias in the keystore
int visibility = View.VISIBLE;
if (FingerprintHelper.getManager(this) != null) {
if (FingerprintHelper.isSupported() && FingerprintHelper.isAvailable(this)) {
try {
KeyStoreHandle keyStore = new KeyStoreHandle();
for (FingerprintSlot slot : _creds.getSlots().findAll(FingerprintSlot.class)) {
@@ -0,0 +1,34 @@
package com.beemdevelopment.aegis.ui.glide;
import android.content.Context;
import com.beemdevelopment.aegis.R;
import de.psdev.licensesdialog.licenses.License;
public class GlideLicense extends License {
@Override
public String getName() {
return "Glide License";
}
@Override
public String readSummaryTextFromResources(Context context) {
return getContent(context, R.raw.glide_license);
}
@Override
public String readFullTextFromResources(Context context) {
return getContent(context, R.raw.glide_license);
}
@Override
public String getVersion() {
return null;
}
@Override
public String getUrl() {
return "https://github.com/bumptech/glide/blob/master/LICENSE";
}
}
@@ -1,5 +1,6 @@
package com.beemdevelopment.aegis.ui.slides;
import android.annotation.SuppressLint;
import android.content.Context;
import android.content.Intent;
import android.hardware.fingerprint.FingerprintManager;
@@ -70,6 +71,7 @@ public class CustomAuthenticatedSlide extends Fragment implements FingerprintUiH
return EditTextHelper.getEditTextChars(_textPassword);
}
@SuppressLint("NewApi")
public Cipher getFingerCipher() {
return _fingerCryptoObj.getCipher();
}
@@ -83,6 +85,7 @@ public class CustomAuthenticatedSlide extends Fragment implements FingerprintUiH
}
@Override
@SuppressLint("NewApi")
public void onSlideSelected() {
Intent intent = getActivity().getIntent();
_cryptType = intent.getIntExtra("cryptType", CustomAuthenticationSlide.CRYPT_TYPE_INVALID);
@@ -124,6 +127,7 @@ public class CustomAuthenticatedSlide extends Fragment implements FingerprintUiH
}
@Override
@SuppressLint("NewApi")
public void onSlideDeselected() {
if (_fingerHelper != null) {
_fingerAuthenticated = false;
@@ -1,5 +1,6 @@
package com.beemdevelopment.aegis.ui.slides;
import android.annotation.SuppressLint;
import android.content.Intent;
import android.hardware.fingerprint.FingerprintManager;
import android.os.Bundle;
@@ -34,8 +35,7 @@ public class CustomAuthenticationSlide extends Fragment implements ISlidePolicy,
onCheckedChanged(_buttonGroup, _buttonGroup.getCheckedRadioButtonId());
// only enable the fingerprint option if the api version is new enough, permission is granted and a scanner is found
FingerprintManager manager = FingerprintHelper.getManager(getContext());
if (manager != null) {
if (FingerprintHelper.isSupported() && FingerprintHelper.isAvailable(getContext())) {
RadioButton button = view.findViewById(R.id.rb_fingerprint);
TextView text = view.findViewById(R.id.text_rb_fingerprint);
button.setEnabled(true);
@@ -8,7 +8,7 @@ import android.view.View;
import android.view.ViewGroup;
import android.view.animation.AnimationUtils;
import android.view.animation.LayoutAnimationController;
import android.widget.Toast;
import android.widget.LinearLayout;
import com.beemdevelopment.aegis.R;
import com.beemdevelopment.aegis.SortCategory;
@@ -47,6 +47,7 @@ public class EntryListView extends Fragment implements EntryAdapter.Listener {
private PeriodProgressBar _progressBar;
private boolean _showProgress;
private ViewMode _viewMode;
private LinearLayout _emptyStateView;
private UiRefresher _refresher;
@@ -107,6 +108,8 @@ public class EntryListView extends Fragment implements EntryAdapter.Listener {
}
});
_emptyStateView = view.findViewById(R.id.vEmptyList);
return view;
}
@@ -218,14 +221,17 @@ public class EntryListView extends Fragment implements EntryAdapter.Listener {
public void addEntry(DatabaseEntry entry) {
_adapter.addEntry(entry);
updateEmptyState();
}
public void addEntries(List<DatabaseEntry> entries) {
_adapter.addEntries(entries);
updateEmptyState();
}
public void removeEntry(DatabaseEntry entry) {
_adapter.removeEntry(entry);
updateEmptyState();
}
public void clearEntries() {
@@ -267,6 +273,16 @@ public class EntryListView extends Fragment implements EntryAdapter.Listener {
_recyclerView.addItemDecoration(_dividerDecoration);
}
private void updateEmptyState() {
if (_adapter.getItemCount() > 0) {
_recyclerView.setVisibility(View.VISIBLE);
_emptyStateView.setVisibility(View.GONE);
} else {
_recyclerView.setVisibility(View.GONE);
_emptyStateView.setVisibility(View.VISIBLE);
}
}
public interface Listener {
void onEntryClick(DatabaseEntry entry);
void onEntryMove(DatabaseEntry entry1, DatabaseEntry entry2);
Binary file not shown.

After

Width:  |  Height:  |  Size: 144 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 75 KiB

@@ -0,0 +1,20 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.coordinatorlayout.widget.CoordinatorLayout 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:fitsSystemWindows="true"
android:background="?attr/background"
tools:context="com.beemdevelopment.aegis.ui.AboutActivity">
<ScrollView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:clipToPadding="false"
android:isScrollContainer="true">
<include layout="@layout/content_about" />
</ScrollView>
</androidx.coordinatorlayout.widget.CoordinatorLayout>
+484
View File
@@ -0,0 +1,484 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="8dp"
app:cardUseCompatPadding="true">
<androidx.cardview.widget.CardView
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:cardUseCompatPadding="true"
android:background="?attr/cardBackground"
android:layout_marginBottom="8dp"
tools:ignore="MissingPrefix">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingBottom="8dp"
android:background="?attr/cardBackground"
android:orientation="vertical">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="72dp"
android:orientation="horizontal"
android:background="?attr/selectableItemBackground"
android:padding="16dp">
<ImageView
android:layout_width="35dp"
android:layout_height="35dp"
android:layout_gravity="center_vertical"
android:src="@mipmap/ic_launcher"
tools:ignore="ContentDescription" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:paddingLeft="16dp"
android:paddingRight="16dp"
android:text="@string/app_name_full"
android:textAppearance="@style/TextAppearance.AppCompat.Headline" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="?attr/selectableItemBackground"
android:clickable="true"
android:gravity="center_vertical"
android:orientation="horizontal"
android:paddingLeft="16dp"
android:paddingRight="16dp"
android:focusable="true">
<ImageView
android:layout_width="20dp"
android:layout_height="20dp"
app:ico_color="@color/icon_about"
app:ico_icon="gmi-info-outline"
app:ico_size="16dp" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="32dp"
android:layout_marginLeft="32dp"
android:orientation="vertical"
android:paddingTop="8dp"
android:paddingBottom="8dp">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/version"
android:textAppearance="@style/TextAppearance.AppCompat.Subhead" />
<TextView
android:id="@+id/app_version"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="0.0.0 (0)"
android:textAppearance="@style/TextAppearance.AppCompat.Caption"
tools:ignore="HardcodedText" />
</LinearLayout>
</LinearLayout>
<LinearLayout
android:id="@+id/btn_changelog"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:foreground="?attr/selectableItemBackground"
android:clickable="true"
android:gravity="center_vertical"
android:orientation="horizontal"
android:paddingLeft="16dp"
android:paddingRight="16dp"
android:focusable="true">
<ImageView
android:layout_width="20dp"
android:layout_height="20dp"
app:ico_color="@color/icon_about"
app:ico_icon="gmi-time-restore"
app:ico_size="16dp" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="32dp"
android:layout_marginLeft="32dp"
android:orientation="vertical"
android:paddingTop="8dp"
android:paddingBottom="8dp">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/changelog"
android:textAppearance="@style/TextAppearance.AppCompat.Subhead" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/whats_new"
android:textAppearance="@style/TextAppearance.AppCompat.Caption" />
</LinearLayout>
</LinearLayout>
<LinearLayout
android:id="@+id/btn_github"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="?attr/selectableItemBackground"
android:clickable="true"
android:gravity="center_vertical"
android:orientation="horizontal"
android:paddingLeft="16dp"
android:paddingRight="16dp"
android:focusable="true">
<ImageView
android:layout_width="20dp"
android:layout_height="20dp"
app:ico_color="@color/icon_about"
app:ico_icon="gmi-github"
app:ico_size="16dp" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="32dp"
android:layout_marginLeft="32dp"
android:orientation="vertical"
android:paddingTop="8dp"
android:paddingBottom="8dp">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/github"
android:textAppearance="@style/TextAppearance.AppCompat.Subhead" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/github_description"
android:textAppearance="@style/TextAppearance.AppCompat.Caption" />
</LinearLayout>
</LinearLayout>
<LinearLayout
android:id="@+id/btn_licenses"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="?attr/selectableItemBackground"
android:clickable="true"
android:gravity="center_vertical"
android:orientation="horizontal"
android:paddingLeft="16dp"
android:paddingRight="16dp"
android:focusable="true">
<ImageView
android:layout_width="20dp"
android:layout_height="20dp"
app:ico_color="@color/icon_about"
app:ico_icon="gmi-file-text"
app:ico_size="16dp" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="32dp"
android:layout_marginLeft="32dp"
android:orientation="vertical"
android:paddingTop="8dp"
android:paddingBottom="8dp">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/licenses"
android:textAppearance="@style/TextAppearance.AppCompat.Subhead" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/licenses_description"
android:textAppearance="@style/TextAppearance.AppCompat.Caption" />
</LinearLayout>
</LinearLayout>
</LinearLayout>
</androidx.cardview.widget.CardView>
<androidx.cardview.widget.CardView
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:cardUseCompatPadding="true"
android:background="?attr/cardBackground"
android:layout_marginBottom="8dp"
tools:ignore="MissingPrefix">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingBottom="8dp"
android:background="?attr/cardBackground"
android:orientation="vertical">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="start|center_vertical"
android:paddingLeft="16dp"
android:paddingTop="24dp"
android:paddingRight="16dp"
android:paddingBottom="16dp"
android:text="@string/org_name_full"
android:textAppearance="@style/TextAppearance.AppCompat.Body2"
android:textColor="?android:textColorSecondary" />
<LinearLayout
android:id="@+id/btn_alexander"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="?attr/selectableItemBackground"
android:clickable="true"
android:gravity="center_vertical"
android:minHeight="@dimen/list_item_height"
android:orientation="horizontal"
android:paddingLeft="16dp"
android:paddingRight="16dp"
android:focusable="true">
<ImageView
android:layout_width="20dp"
android:layout_height="20dp"
app:ico_color="@color/icon_about"
app:ico_icon="gmi-account"
app:ico_size="16dp" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="32dp"
android:layout_marginLeft="32dp"
android:orientation="vertical"
android:paddingTop="8dp"
android:paddingBottom="8dp">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/author_alex"
android:textAppearance="@style/TextAppearance.AppCompat.Subhead" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/country_netherlands"
android:textAppearance="@style/TextAppearance.AppCompat.Caption" />
</LinearLayout>
</LinearLayout>
<LinearLayout
android:id="@+id/btn_michael"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="?attr/selectableItemBackground"
android:clickable="true"
android:gravity="center_vertical"
android:minHeight="@dimen/list_item_height"
android:orientation="horizontal"
android:paddingLeft="16dp"
android:paddingRight="16dp"
android:focusable="true">
<ImageView
android:layout_width="20dp"
android:layout_height="20dp"
app:ico_color="@color/icon_about"
app:ico_icon="gmi-account"
app:ico_size="16dp" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="32dp"
android:layout_marginLeft="32dp"
android:orientation="vertical"
android:paddingTop="8dp"
android:paddingBottom="8dp">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/author_michael"
android:textAppearance="@style/TextAppearance.AppCompat.Subhead" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/country_netherlands"
android:textAppearance="@style/TextAppearance.AppCompat.Caption" />
</LinearLayout>
</LinearLayout>
<LinearLayout
android:id="@+id/btn_email"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="?attr/selectableItemBackground"
android:clickable="true"
android:gravity="center_vertical"
android:minHeight="@dimen/list_item_height"
android:orientation="horizontal"
android:paddingLeft="16dp"
android:paddingRight="16dp"
android:focusable="true">
<ImageView
android:layout_width="20dp"
android:layout_height="20dp"
app:ico_color="@color/icon_about"
app:ico_icon="gmi-email"
app:ico_size="16dp" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="32dp"
android:layout_marginLeft="32dp"
android:paddingTop="8dp"
android:paddingBottom="8dp"
android:text="@string/email_us"
android:textAppearance="@style/TextAppearance.AppCompat.Subhead" />
</LinearLayout>
<LinearLayout
android:id="@+id/btn_website"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="?attr/selectableItemBackground"
android:clickable="true"
android:gravity="center_vertical"
android:minHeight="@dimen/list_item_height"
android:orientation="horizontal"
android:paddingLeft="16dp"
android:paddingRight="16dp"
android:focusable="true">
<ImageView
android:layout_width="20dp"
android:layout_height="20dp"
app:ico_color="@color/icon_about"
app:ico_icon="gmi-globe"
app:ico_size="16dp" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="32dp"
android:layout_marginLeft="32dp"
android:paddingTop="8dp"
android:paddingBottom="8dp"
android:text="@string/visit_website"
android:textAppearance="@style/TextAppearance.AppCompat.Subhead" />
</LinearLayout>
</LinearLayout>
</androidx.cardview.widget.CardView>
<androidx.cardview.widget.CardView
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:cardUseCompatPadding="true"
android:layout_marginBottom="8dp"
android:background="?attr/cardBackground"
tools:ignore="MissingPrefix">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingBottom="8dp"
android:background="?attr/cardBackground"
android:orientation="vertical">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="start|center_vertical"
android:paddingLeft="16dp"
android:paddingTop="24dp"
android:paddingRight="16dp"
android:paddingBottom="16dp"
android:text="@string/about_support"
android:textAppearance="@style/TextAppearance.AppCompat.Body2"
android:textColor="?android:textColorSecondary" />
<LinearLayout
android:id="@+id/btn_rate"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:foreground="?attr/selectableItemBackground"
android:clickable="true"
android:gravity="center_vertical"
android:minHeight="@dimen/list_item_height"
android:orientation="horizontal"
android:paddingLeft="16dp"
android:paddingRight="16dp"
android:focusable="true">
<ImageView
android:layout_width="20dp"
android:layout_height="20dp"
app:ico_color="@color/icon_about"
app:ico_icon="gmi-star"
app:ico_size="16dp" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="32dp"
android:layout_marginLeft="32dp"
android:orientation="vertical"
android:paddingTop="8dp"
android:paddingBottom="8dp">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/support_rate"
android:textAppearance="@style/TextAppearance.AppCompat.Subhead" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/support_rate_description"
android:textAppearance="@style/TextAppearance.AppCompat.Caption" />
</LinearLayout>
</LinearLayout>
</LinearLayout>
</androidx.cardview.widget.CardView>
</LinearLayout>
@@ -0,0 +1,14 @@
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingLeft="16dp"
android:paddingRight="16dp">
<WebView
android:id="@+id/web_view"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:scrollbars="none" />
</FrameLayout>
@@ -22,4 +22,47 @@
android:id="@+id/rvKeyProfiles"
android:layoutAnimation="@anim/layout_animation_fall_down"
android:layout_weight="1"/>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center|fill_vertical"
android:id="@+id/vEmptyList"
android:orientation="vertical">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1"
android:gravity="center"
android:orientation="vertical"
android:paddingBottom="150dp">
<ImageView
android:id="@+id/imageView"
android:layout_width="50dp"
android:layout_height="50dp"
android:src="@drawable/ic_qrcode_scan"
android:tint="?attr/primaryText" />
<TextView
android:id="@+id/textView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/empty_list_title"
android:paddingTop="17dp"
android:textColor="?attr/primaryText"
android:textSize="18sp" />
<TextView
android:id="@+id/textView5"
android:layout_width="300dp"
android:layout_height="wrap_content"
android:lineSpacingExtra="5dp"
android:paddingTop="7dp"
android:text="@string/empty_list"
android:textAlignment="center" />
</LinearLayout>
</LinearLayout>
</LinearLayout>
+5
View File
@@ -63,4 +63,9 @@
android:orderInCategory="100"
android:title="@string/action_settings"
app:showAsAction="never" />
<item
android:id="@+id/action_about"
android:orderInCategory="110"
android:title="@string/action_about"
app:showAsAction="never" />
</menu>
+94
View File
@@ -0,0 +1,94 @@
License for everything not in third_party and not otherwise marked:
Copyright 2014 Google, Inc. All rights reserved.
Redistribution and use in source and binary forms, with or without modification, are
permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this list of
conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice, this list
of conditions and the following disclaimer in the documentation and/or other materials
provided with the distribution.
THIS SOFTWARE IS PROVIDED BY GOOGLE, INC. ``AS IS'' AND ANY EXPRESS OR IMPLIED
WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GOOGLE, INC. OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
The views and conclusions contained in the software and documentation are those of the
authors and should not be interpreted as representing official policies, either expressed
or implied, of Google, Inc.
---------------------------------------------------------------------------------------------
License for third_party/disklrucache:
Copyright 2012 Jake Wharton
Copyright 2011 The Android Open Source Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
---------------------------------------------------------------------------------------------
License for third_party/gif_decoder:
Copyright (c) 2013 Xcellent Creations, Inc.
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
---------------------------------------------------------------------------------------------
License for third_party/gif_encoder/AnimatedGifEncoder.java and
third_party/gif_encoder/LZWEncoder.java:
No copyright asserted on the source code of this class. May be used for any
purpose, however, refer to the Unisys LZW patent for restrictions on use of
the associated LZWEncoder class. Please forward any corrections to
kweiner@fmsware.com.
-----------------------------------------------------------------------------
License for third_party/gif_encoder/NeuQuant.java
Copyright (c) 1994 Anthony Dekker
NEUQUANT Neural-Net quantization algorithm by Anthony Dekker, 1994. See
"Kohonen neural networks for optimal colour quantization" in "Network:
Computation in Neural Systems" Vol. 5 (1994) pp 351-367. for a discussion of
the algorithm.
Any party obtaining a copy of these files from the author, directly or
indirectly, is granted, free of charge, a full and unrestricted irrevocable,
world-wide, paid up, royalty-free, nonexclusive right and license to deal in
this software and documentation files (the "Software"), including without
limitation the rights to use, copy, modify, merge, publish, distribute,
sublicense, and/or sell copies of the Software, and to permit persons who
receive copies from any such party to do so, with the only requirement being
that this copyright notice remain intact.
+79
View File
@@ -0,0 +1,79 @@
<?xml version="1.0" encoding="utf-8"?>
<notices>
<notice>
<name>TextDrawable</name>
<url>https://github.com/amulyakhare/TextDrawable</url>
<copyright>Copyright (C) 2014 Amulya Khare</copyright>
<license>MIT License</license>
</notice>
<notice>
<name>Preferencex</name>
<url>https://github.com/takisoft/preferencex-android</url>
<copyright />
<license>Apache Software License 2.0</license>
</notice>
<notice>
<name>FloatingActionButton</name>
<url>https://github.com/futuresimple/android-floating-action-button</url>
<copyright>Copyright 2014 Jerzy Chalupski</copyright>
<license>Apache Software License 2.0</license>
</notice>
<notice>
<name>AppIntro</name>
<url>https://github.com/AppIntro/AppIntro</url>
<copyright/>
<license>Apache Software License 2.0</license>
</notice>
<notice>
<name>Krop</name>
<url>https://github.com/avito-tech/krop</url>
<copyright>Copyright (c) 2017 Avito Technology</copyright>
<license>MIT License</license>
</notice>
<notice>
<name>Spongycastle</name>
<url>https://github.com/rtyley/spongycastle/</url>
<copyright>Copyright (c) 2000-2017 The Legion of the Bouncy Castle Inc. (http://www.bouncycastle.org)</copyright>
<license>Apache Software License 2.0</license>
</notice>
<notice>
<name>Swirl</name>
<url>https://github.com/mattprecious/swirl</url>
<copyright>Copyright 2016 Matthew Precious</copyright>
<license>Apache Software License 2.0</license>
</notice>
<notice>
<name>CircleImageView</name>
<url>https://github.com/hdodenhof/CircleImageView</url>
<copyright>Copyright 2014 - 2019 Henning Dodenhof</copyright>
<license>Apache Software License 2.0</license>
</notice>
<notice>
<name>Barcodescanner</name>
<url>https://github.com/dm77/barcodescanner</url>
<copyright>Copyright (c) 2014 Dushyanth Maguluru</copyright>
<license>Apache Software License 2.0</license>
</notice>
<notice>
<name>libsu</name>
<url>https://github.com/topjohnwu/libsu</url>
<license>Apache Software License 2.0</license>
</notice>
<notice>
<name>Glide</name>
<url>https://github.com/bumptech/glide</url>
<license>Glide License</license>
</notice>
<notice>
<name>Iconics</name>
<url>https://github.com/mikepenz/Android-Iconics</url>
<copyright/>
<license>Apache Software License 2.0</license>
</notice>
<notice>
<name>Android Support Libraries</name>
<url>http://developer.android.com/tools/support-library/index.html</url>
<copyright>Copyright (C) 2016 The Android Open Source Project</copyright>
<license>Apache Software License 2.0</license>
</notice>
</notices>
+174
View File
@@ -0,0 +1,174 @@
<resources>
<string name="app_name">Aegis</string>
<string name="app_name_full">Aegis Authenticator</string>
<string name="app_name_dev">AegisDev</string>
<string name="action_settings">Einstellungen</string>
<string name="action_import">Importieren</string>
<string name="action_delete">Löschen</string>
<string name="action_default_icon">Standard-Symbol wiederherstellen</string>
<string name="discard">Verwerfen</string>
<string name="save">Speichern</string>
<string name="issuer">Herausgeber</string>
<string name="settings">Einstellungen</string>
<string name="pref_appearance_group_title">Aussehen</string>
<string name="pref_security_group_title">Sicherheit</string>
<string name="pref_tools_group_title">Hilfsmittel</string>
<string name="pref_select_theme_title">Thema</string>
<string name="pref_view_mode_title">Ansichtsmodus</string>
<string name="pref_lang_title">Sprache</string>
<string name="pref_account_name_title">Anzeigen des Kontonamens</string>
<string name="pref_account_name_summary">Aktiviere dies, um den Kontonamen neben dem Herausgeber anzuzeigen.</string>
<string name="pref_timeout_title">Zeitüberschreitung</string>
<string name="pref_timeout_summary">Sperrt die Datenbank automatisch nach %1$s Sekunden Inaktivität.</string>
<string name="pref_slots_title">Schlüssel Steckplätze</string>
<string name="pref_slots_summary">Verwalte die Liste der Schlüssel, die die Datenbank entschlüsseln können.</string>
<string name="pref_import_file_title">Aus Datei importieren</string>
<string name="pref_import_file_summary">Importieren einer Datenbank aus einer Datei</string>
<string name="pref_import_app_title">Aus App importieren</string>
<string name="pref_import_app_summary">Importieren einer Datenbank aus einer App (erfordert Root-Zugriff)</string>
<string name="pref_export_title">Exportieren</string>
<string name="pref_export_summary">Exportieren der Datenbank</string>
<string name="pref_secure_screen_title">Bildschirmsicherheit</string>
<string name="pref_secure_screen_summary">Blockiere Screenshots und andere Versuche, den Bildschirm innerhalb der App aufzunehmen.</string>
<string name="pref_tap_to_reveal_title">Zum Aufdecken tippen</string>
<string name="pref_tap_to_reveal_summary">Schlüssel werden standardmäßig ausgeblendet. Tippe auf die Schlüssel, um den Code anzuzeigen.</string>
<string name="pref_tap_to_reveal_time_title">Zeitüberschreitung für Tippen zum Anzeigen</string>
<string name="pref_auto_lock_title">Automatische Sperre</string>
<string name="pref_auto_lock_summary">Automatische Sperre, wenn die App geschlossen oder dein Gerät gesperrt wird.</string>
<string name="pref_encryption_title">Verschlüsselung</string>
<string name="pref_encryption_summary">Verschlüssele die Datenbank und entsperre mit einem Passwort oder Fingerabdruck.</string>
<string name="pref_fingerprint_title">Fingerabdruck</string>
<string name="pref_fingerprint_summary">Ermöglicht es, dass auf diesem Gerät registrierte Fingerabdrücke den Tresor freischalten.</string>
<string name="pref_set_password_title">Passwort ändern</string>
<string name="pref_set_password_summary">Legen ein neues Passwort fest, das erforderlich ist, um deinen Tresor freizuschalten.</string>
<string name="fingerprint_hint">Berührungssensor</string>
<string name="fingerprint_not_recognized">Fingerabdruck nicht erkannt. Versuche es noch einmal.</string>
<string name="fingerprint_success">Fingerabdruck erkannt</string>
<string name="choose_authentication_method">Sicherheit</string>
<string name="authentication_method_none">Keine</string>
<string name="authentication_method_none_description">Du brauchst kein Passwort, um den Tresor freizuschalten, und es wird nicht verschlüsselt. Diese Option wird nicht empfohlen.</string>
<string name="authentication_method_password">Passwort</string>
<string name="authentication_method_password_description">Du benötigst ein Passwort, um den Tresor freizuschalten.</string>
<string name="authentication_method_fingerprint">Fingerabdruck</string>
<string name="authentication_method_fingerprint_description">Zusätzlich zu einem Passwort können auf diesem Gerät registrierte Fingerabdrücke verwendet werden, um den Tresor freizuschalten.</string>
<string name="authentication_method_set_password">Passwort</string>
<string name="authentication_enter_password">Gib dein Passwort ein</string>
<string name="authentication">Entsperre den Tresor.</string>
<string name="set_password">Bitte gib ein Passwort ein</string>
<string name="set_group">Bitte gib einen Gruppennamen ein</string>
<string name="set_number">Bitte gib eine Zahl ein</string>
<string name="set_password_confirm">Bitte bestätige das Passwort</string>
<string name="invalidated_fingerprint">Es wurde eine Änderung der Sicherheitseinstellungen deines Geräts festgestellt. Bitte gehe zu \"Aegis -> Einstellungen -> Fingerabdruck\" und füge deinen Fingerabdruck erneut hinzu.</string>
<string name="unlock">Entsperren</string>
<string name="advanced">Fortgeschritten</string>
<string name="seconds">Sekunden</string>
<string name="counter">Zähler</string>
<string name="digits">Ziffern</string>
<string name="secret">Schlüssel</string>
<string name="scan">QR-Code scannen</string>
<string name="scan_image">Bild scannen</string>
<string name="enter_manually">Manuell eingeben</string>
<string name="add_fingerprint">Fingerabdruck hinzufügen</string>
<string name="add_password">Passwort hinzufügen</string>
<string name="slots_warning">Der Tresor ist nur so sicher wie dein schwächster Schlüssel. Wenn ein neuer Fingerabdruck zu deinem Gerät hinzugefügt wird, musst du die Fingerabdruck-Authentifizierung in Aegis reaktivieren.</string>
<string name="copy">Kopieren</string>
<string name="edit">Bearbeiten</string>
<string name="delete">Löschen</string>
<string name="password">Passwort</string>
<string name="confirm_password">Passwort bestätigen</string>
<string name="new_profile">Neues Profil</string>
<string name="add_new_profile">Neues Profil hinzufügen</string>
<string name="unlock_vault_error">Der Tresor konnte nicht entsperrt werden.</string>
<string name="unlock_vault_error_description">Falsches Passwort. Achte darauf, dass du dein Passwort nicht falsch eingibst.</string>
<string name="password_equality_error">Passwörter sollten identisch und nicht leer sein.</string>
<string name="register_fingerprint">Registriere deinen Fingerabdruck</string>
<string name="snackbar_authentication_method">Bitte wähle eine Authentifizierungsmethode aus</string>
<string name="encrypting_vault">Verschlüsseln des Tresors</string>
<string name="delete_entry">Eintrag löschen</string>
<string name="delete_entry_description">Bist du sicher, dass du diesen Eintrag löschen möchtest?</string>
<string name="discard_changes">Änderungen verwerfen?</string>
<string name="discard_changes_description">Deine Änderungen wurden nicht gespeichert.</string>
<string name="folder">Ordner</string>
<string name="tap_to_select">Zum Auswählen tippen</string>
<string name="saving_profile_error">Fehler beim Speichern des Profils</string>
<string name="welcome">Willkommen</string>
<string name="app_description">Aegis ist eine kostenlose, sichere und Open Source 2FA App.</string>
<string name="setup_completed">Einrichten abgeschlossen</string>
<string name="setup_completed_description">Aegis ist eingerichtet und einsatzbereit.</string>
<string name="vault_not_found">Tresor nicht gefunden, Starten der Einrichtung…</string>
<string name="code_copied">Code in die Zwischenablage kopiert</string>
<string name="errors_copied">Fehlermeldungen in die Zwischenablage kopiert</string>
<string name="decryption_error">Beim Versuch, den Tresor zu entsperren, ist ein Fehler aufgetreten.</string>
<string name="saving_error">Beim Versuch, den Tresor zu speichern, ist ein Fehler aufgetreten.</string>
<string name="disable_encryption">Verschlüsselung deaktivieren</string>
<string name="disable_encryption_description">Bist du sicher, dass du die Verschlüsselung deaktivieren willst? Dadurch wird der Tresor im Klartext gespeichert.</string>
<string name="enable_encryption_error">Bei der Aktivierung der Verschlüsselung ist ein Fehler aufgetreten.</string>
<string name="disable_encryption_error">Bei der Deaktivierung der Verschlüsselung ist ein Fehler aufgetreten.</string>
<string name="permission_denied">Zugriff verweigert</string>
<string name="choose_application">Wähle die Anwendung aus, aus der du eine Datenbank importieren möchtest.</string>
<string name="choose_theme">Wähle das gewünschte Thema aus</string>
<string name="choose_view_mode">Wähle den gewünschten Ansichtsmodus aus</string>
<string name="parsing_file_error">Beim Versuch, die Datei zu analysieren, ist ein Fehler aufgetreten.</string>
<string name="file_not_found">Fehler: Datei nicht gefunden</string>
<string name="reading_file_error">Beim Versuch, die Datei zu lesen, ist ein Fehler aufgetreten.</string>
<string name="app_lookup_error">Fehler: App ist nicht installiert</string>
<string name="root_error">Fehler: Es konnte kein Root-Zugriff gewährt werden.</string>
<string name="imported_entries_count">Importierte %d Einträge</string>
<string name="read_entries_count">%d Einträge gelesen. %d Fehler.</string>
<string name="import_error_title">Beim Import sind ein oder mehrere Fehler aufgetreten.</string>
<string name="exporting_database_error">Beim Versuch, die Datenbank zu exportieren, ist ein Fehler aufgetreten.</string>
<string name="export_database_location">Die Datenbank wurde exportiert nach:</string>
<string name="export_warning">Diese Aktion exportiert die Datenbank aus dem privaten Speicher von Aegis.</string>
<string name="encryption_set_password_error">Beim Versuch, das Passwort festzulegen, ist ein Fehler aufgetreten: </string>
<string name="encryption_enable_fingerprint_error">Beim Versuch den Fingerabdruck zu entsperren, ist ein Fehler aufgetreten: </string>
<string name="no_cameras_available">Keine Kameras verfügbar</string>
<string name="read_qr_error">Beim Versuch, den QR-Code zu lesen, ist ein Fehler aufgetreten.</string>
<string name="authentication_method_raw">Raw</string>
<string name="unlocking_vault">Entsperren des Tresors</string>
<string name="unlocking_vault_repair">Entsperren des Tresors (Reparieren)</string>
<string name="password_slot_error">Du musst mindestens einen Passwort-Slot haben.</string>
<string name="remove_slot">Slot entfernen</string>
<string name="remove_slot_description">Bist du sicher, dass du diesen Slot entfernen willst?</string>
<string name="remove_group">Gruppe entfernen</string>
<string name="remove_group_description">Bist du sicher, dass du diese Gruppe entfernen möchtest? Einträge in dieser Gruppe wechseln automatisch zu \'Keine Gruppe\'.</string>
<string name="adding_new_slot_error">Beim Versuch, einen neuen Slot hinzuzufügen, ist ein Fehler aufgetreten:</string>
<string name="progressbar_error">Die Skala der Animationsdauer kann nicht zurückgesetzt werden. Fortschrittsbalken werden unsichtbar sein.</string>
<string name="details">Details</string>
<string name="filter">Filter</string>
<string name="lock">Sperren</string>
<string name="all">Alle</string>
<string name="name">Name</string>
<string name="no_group">Keine Gruppe</string>
<string name="sort_alphabetically">Herausgeber (A bis Z)</string>
<string name="sort_alphabetically_reverse">Herausgeber (Z bis A)</string>
<string name="sort_alphabetically_name">Konto (A bis Z)</string>
<string name="sort_alphabetically_name_reverse">Konto (Z bis A)</string>
<string name="sort_custom">Benutzerdefiniert</string>
<string name="new_group">Neue Gruppe…</string>
<string name="enter_group_name">Gib einen Gruppennamen ein</string>
<string name="group_name_hint">Gruppenname</string>
<string name="preference_manage_groups">Gruppen bearbeiten</string>
<string name="preference_manage_groups_summary">Verwalte und lösche deine Gruppen hier</string>
<string name="tap_to_reveal">Versteckt</string>
<string name="selected">Ausgewählt</string>
<string name="dark_theme_title">Dunkles Thema</string>
<string name="light_theme_title">Helles Thema</string>
<string name="amoled_theme_title">Amoled Thema</string>
<string name="normal_viewmode_title">Normal</string>
<string name="compact_mode_title">Kompakt</string>
<string name="small_mode_title">Klein</string>
<string name="unknown_issuer">Unbekannter Herausgeber</string>
<string name="unknown_account_name">Unbekannter Kontoname</string>
<string name="import_error_dialog">Aegis konnte %d Tokens nicht importieren. Diese Tokens werden übersprungen. Drücke \'details\', um mehr Informationen über die Fehler zu erhalten.</string>
<string name="unable_to_read_qrcode">QR-Code kann nicht gelesen und verarbeitet werden.</string>
<string name="select_picture">Bild auswählen</string>
<string name="toggle_checkboxes">Markierungen umschalten</string>
<string name="search">Suche</string>
<string name="channel_name_lock_status">Sperrstatus</string>
<string name="channel_description_lock_status">Aegis kann eine dauerhafte Benachrichtigung erstellen, um dich zu benachrichtigen, wenn der Tresor gesperrt ist.</string>
<string name="vault_unlocked_state">Der Tresor ist freigeschaltet. Hier tippen, um zu sperren.</string>
</resources>
+166 -162
View File
@@ -1,168 +1,172 @@
<resources>
    <string name="app_name">Aegis</string>
    <string name="app_name_dev">AegisDev</string>
    <string name="action_settings">Настройки</string>
    <string name="action_import">Импорт</string>
    <string name="action_delete">Удалить</string>
    <string name="action_default_icon">Восстановить значок по умолчанию</string>
    <string name="discard">Отмена</string>
    <string name="save">Сохранить</string>
    <string name="issuer">Эмитент</string>
<string name="app_name">Aegis</string>
<string name="app_name_dev">AegisDev</string>
<string name="action_settings">Настройки</string>
<string name="action_import">Импорт</string>
<string name="action_delete">Удалить</string>
<string name="action_default_icon">Восстановить иконку по умолчанию</string>
<string name="discard">Отмена</string>
<string name="save">Сохранить</string>
<string name="issuer">Эмитент</string>
    <string name="settings">Предпочтения</string>
    <string name="pref_appearance_group_title">Appearance</string>
    <string name="pref_security_group_title">Security</string>
    <string name="pref_tools_group_title">Tools</string>
    <string name="pref_select_theme_title">Тема</string>
    <string name="pref_view_mode_title">Select view mode</string>
    <string name="pref_account_name_title">Показать имя аккаунта</string>
    <string name="pref_account_name_summary">Включите это, чтобы показать имя учетной записи рядом с эмитентом</string>
    <string name="pref_timeout_title">Тайм-аут</string>
    <string name="pref_timeout_summary">Автоматическая блокировка базы данных после %1$s секунд бездействия</string>
    <string name="pref_slots_title">Ключевые слоты</string>
    <string name="pref_slots_summary">Управление списком ключей которые могут расшифровать базу данных</string>
    <string name="pref_import_file_title">Импорт из файла</string>
    <string name="pref_import_file_summary">Импортировать базу данных из файла</string>
    <string name="pref_import_app_title">Импорт из приложения</string>
    <string name="pref_import_app_summary">Импорт базы данных из приложения (требуется root-доступ)</string>
    <string name="pref_export_title">Экспорт</string>
    <string name="pref_export_summary">Экспорт базы данных</string>
    <string name="pref_secure_screen_title">Безопасность экрана</string>
    <string name="pref_secure_screen_summary">Блокировка скриншотов и других попыток захвата экрана в приложении</string>
    <string name="pref_tap_to_reveal_title">Нажмите, чтобы показать</string>
    <string name="pref_tap_to_reveal_summary">Токены будут скрыты по умолчанию. Нажмите на токены, чтобы показать код.</string>
    <string name="pref_tap_to_reveal_time_title">Тайм-аут для показа экрана</string>
    <string name="pref_auto_lock_title">Автоматически блокировать</string>
    <string name="pref_auto_lock_summary">Автоматически блокировать, когда приложение закрывается или устройство блокируется</string>
    <string name="pref_encryption_title">Шифрование</string>
    <string name="pref_encryption_summary">Зашифруйте базу данных и разблокируйте ее с помощью пароля или отпечатка пальца</string>
    <string name="pref_fingerprint_title">Отпечаток пальца</string>
    <string name="pref_fingerprint_summary">Разрешить отпечатки пальцев  зарегистрированных на этом устройстве, чтобы разблокировать хранилище</string>
    <string name="pref_set_password_title">Изменить пароль</string>
    <string name="pref_set_password_summary">Установите новый пароль который вам понадобится, чтобы разблокировать ваше хранилище</string>
<string name="settings">Предпочтения</string>
<string name="pref_appearance_group_title">Внешний вид</string>
<string name="pref_security_group_title">Безопасность</string>
<string name="pref_tools_group_title">Инструменты</string>
<string name="pref_select_theme_title">Тема</string>
<string name="pref_view_mode_title">Режим отображения</string>
<string name="pref_account_name_title">Отображать имя аккаунта</string>
<string name="pref_account_name_summary">Включите это, чтобы отображать имя учетной записи рядом с эмитентом</string>
<string name="pref_timeout_title">Тайм-аут</string>
<string name="pref_timeout_summary">Автоматическая блокировка базы данных после %1$s секунд бездействия</string>
<string name="pref_slots_title">Ключевые слоты</string>
<string name="pref_slots_summary">Управление списком ключей которые могут расшифровать базу данных</string>
<string name="pref_import_file_title">Импорт из файла</string>
<string name="pref_import_file_summary">Импортировать базу данных из файла</string>
<string name="pref_import_app_title">Импорт из приложения</string>
<string name="pref_import_app_summary">Импорт базы данных из другого приложения (требуются права суперпользователя)</string>
<string name="pref_export_title">Экспорт в файл</string>
<string name="pref_export_summary">Экспортировать базу данных в файл</string>
<string name="pref_secure_screen_title">Безопасность экрана</string>
<string name="pref_secure_screen_summary">Блокировка скриншотов и других попыток захвата экрана в приложении</string>
<string name="pref_tap_to_reveal_title">Отображение по нажатию</string>
<string name="pref_tap_to_reveal_summary">Коды будут скрыты по умолчанию. Нажмите на токен, чтобы показать код.</string>
<string name="pref_tap_to_reveal_time_title">Тайм-аут для отображения по нажатию</string>
<string name="pref_auto_lock_title">Автоматическая блокировка</string>
<string name="pref_auto_lock_summary">Автоматическая блокировка при закрытии приложения и блокировке устройства.</string>
<string name="pref_encryption_title">Шифрование</string>
<string name="pref_encryption_summary">Зашифруйте базу данных и разблокируйте ее с помощью пароля или отпечатка пальца</string>
<string name="pref_fingerprint_title">Отпечаток пальца</string>
<string name="pref_fingerprint_summary">Разрешить разблокировку хранилища при помощи отпечатков пальцев, зарегистрированных на этом устройстве</string>
<string name="pref_set_password_title">Изменить пароль</string>
<string name="pref_set_password_summary">Установите новый пароль, который вам понадобится, чтобы разблокировать ваше хранилище</string>
    <string name="fingerprint_hint">Сенсорный датчик</string>
    <string name="fingerprint_not_recognized">Отпечаток пальца не распознан. Попробуйте снова.</string>
    <string name="fingerprint_success">Отпечаток пальца распознан</string>
<string name="fingerprint_hint">Прикоснитесь к сенсору</string>
<string name="fingerprint_not_recognized">Отпечаток пальца не распознан. Попробуйте снова.</string>
<string name="fingerprint_success">Отпечаток пальца распознан</string>
    <string name="choose_authentication_method">Безопасность</string>
    <string name="authentication_method_none">Нет</string>
    <string name="authentication_method_none_description">Вам не нужен пароль для разблокировки хранилища, и он не будет зашифрован. Этот вариант не рекомендуется.</string>
    <string name="authentication_method_password">Пароль</string>
    <string name="authentication_method_password_description">Вам нужен пароль чтобы разблокировать хранилище.</string>
    <string name="authentication_method_fingerprint">Отпечаток</string>
    <string name="authentication_method_fingerprint_description">В дополнение к паролю для разблокировки хранилища можно использовать отпечатки пальцев, зарегистрированные на этом устройстве.</string>
    <string name="authentication_method_set_password">Пароль</string>
    <string name="authentication_enter_password">Введите свой пароль</string>
    <string name="authentication">Разблокировать хранилище</string>
    <string name="set_password">Пожалуйста, введите пароль</string>
    <string name="set_group">Пожалуйста, введите название группы</string>
    <string name="set_number">Пожалуйста, введите номер</string>
    <string name="set_password_confirm">Пожалуйста, подтвердите пароль</string>
    <string name="invalidated_fingerprint">Обнаружено изменение настроек безопасности вашего устройства. Перейдите в «Настройки - Отпечаток пальца» и повторно добавьте свой отпечаток пальца.</string>
<string name="choose_authentication_method">Безопасность</string>
<string name="authentication_method_none">Нет</string>
<string name="authentication_method_none_description">Вам не нужен пароль для разблокировки хранилища, и оно не будет зашифровано. Этот вариант не рекомендуется.</string>
<string name="authentication_method_password">Пароль</string>
<string name="authentication_method_password_description">Вам нужен пароль, чтобы разблокировать хранилище.</string>
<string name="authentication_method_fingerprint">Отпечаток пальца</string>
<string name="authentication_method_fingerprint_description">В дополнение к паролю, для разблокировки хранилища можно использовать отпечатки пальцев, зарегистрированные на этом устройстве.</string>
<string name="authentication_method_set_password">Пароль</string>
<string name="authentication_enter_password">Введите свой пароль</string>
<string name="authentication">Разблокировать хранилище</string>
<string name="set_password">Пожалуйста, введите пароль</string>
<string name="set_group">Пожалуйста, введите название группы</string>
<string name="set_number">Пожалуйста, введите номер</string>
<string name="set_password_confirm">Пожалуйста, подтвердите пароль</string>
<string name="invalidated_fingerprint">Обнаружено изменение настроек безопасности вашего устройства. Перейдите в «Настройки - Отпечаток пальца» и повторно добавьте свой отпечаток пальца.</string>
    <string name="unlock">Разблокировать</string>
    <string name="advanced">Расширенные</string>
    <string name="seconds">секунд</string>
    <string name="counter">Счетчик</string>
    <string name="digits">Цифры</string>
    <string name="secret">Секрет</string>
    <string name="scan">Сканировать QR-код</string>
    <string name="scan_image">Сканировать изображение</string>
    <string name="enter_manually">Введите вручную</string>
    <string name="add_fingerprint">Добавить отпечаток</string>
    <string name="add_password">Добавить паспорт</string>
    <string name="slots_warning">Хранилище надежно защищено. При добавлении нового отпечатка пальца на ваше устройство вы активируете аутентификацию по отпечатку пальца в Aegis.</string>
    <string name="copy">Копировать</string>
    <string name="edit">Изменить</string>
    <string name="delete">Удалить</string>
    <string name="password">Пароль</string>
    <string name="confirm_password">Подтвердите пароль</string>
    <string name="new_profile">Новый профиль</string>
    <string name="add_new_profile">Добавить новый профиль</string>
    <string name="unlock_vault_error">Не удалось разблокировать хранилище</string>
    <string name="unlock_vault_error_description">Неверный пароль. Убедитесь, что вы не опечатали свой пароль.</string>
    <string name="password_equality_error">Пароли должны быть одинаковыми и непустыми</string>
    <string name="register_fingerprint">Зарегистрируйте свой отпечаток пальца</string>
    <string name="snackbar_authentication_method">Пожалуйста, выберите метод аутентификации</string>
    <string name="encrypting_vault">Шифрование хранилища</string>
    <string name="delete_entry">Удалить запись</string>
    <string name="delete_entry_description">Вы уверены что хотите удалить эту запись?</string>
    <string name="discard_changes">Отменить изменения?</string>
    <string name="discard_changes_description">Ваши изменения не были сохранены</string>
    <string name="folder">Папка</string>
    <string name="tap_to_select">Нажмите, чтобы выбрать</string>
    <string name="saving_profile_error">Ошибка сохранения профиля</string>
    <string name="welcome">Добро пожаловать</string>
    <string name="app_description">Aegis - бесплатное, безопасное и открытое приложение 2FA.</string>
    <string name="setup_completed">Настройка завершена</string>
    <string name="setup_completed_description">Aegis настроен и готов к работе.</string>
    <string name="vault_not_found">Хранилище не найдено, запуск установки…</string>
    <string name="code_copied">Код скопирован в буфер обмена</string>
    <string name="errors_copied">Ошибка скопирована в буфер обмена</string>
    <string name="decryption_error">Произошла ошибка при попытке разблокировать хранилище</string>
    <string name="saving_error">Произошла ошибка при попытке сохранить хранилище</string>
    <string name="disable_encryption">Отключить шифрование</string>
    <string name="disable_encryption_description">Вы уверены что хотите отключить шифрование? Это приведет к хранению хранилища в виде простого текста.</string>
    <string name="enable_encryption_error">Произошла ошибка при включении шифрования</string>
    <string name="disable_encryption_error">Произошла ошибка при отключении шифрования</string>
    <string name="permission_denied">Доступ запрещен</string>
    <string name="choose_application">Выберите приложение из которого вы хотите импортировать базу данных.</string>
    <string name="choose_theme">Выберите тему</string>
    <string name="choose_view_mode">Выберите нужный режим просмотра</string>
    <string name="parsing_file_error">Произошла ошибка при попытке разобрать файл</string>
    <string name="file_not_found">Ошибка: файл не найден</string>
    <string name="reading_file_error">Произошла ошибка при попытке прочитать файл</string>
    <string name="app_lookup_error">Ошибка: приложение не установлено</string>
    <string name="root_error">Ошибка: невозможно получить root-доступ</string>
    <string name="imported_entries_count">Импортироаано %d записей</string>
    <string name="read_entries_count">Прочитано %d записей. %d ошибок.</string>
    <string name="import_error_title">Одна или более ошибок произошли при импорте</string>
    <string name="exporting_database_error">Произошла ошибка при попытке экспорта базы данных</string>
    <string name="export_database_location">База данных была экспортирована в:</string>
    <string name="export_warning">Это действие экспортирует базу данных из личного хранилища Aegis.</string>
    <string name="encryption_set_password_error">Произошла ошибка при попытке установить пароль:</string>
    <string name="encryption_enable_fingerprint_error">Произошла ошибка при попытке разблокировать отпечаток пальца:</string>
    <string name="no_cameras_available">Нет доступных камер</string>
    <string name="read_qr_error">Произошла ошибка при попытке прочитать QR-код</string>
    <string name="authentication_method_raw">Необработанный</string>
    <string name="unlocking_vault">Разблокировка хранилища</string>
    <string name="password_slot_error">У вас должен быть хотя бы один слот для пароля</string>
    <string name="remove_slot">Удалить слот</string>
    <string name="remove_slot_description">Вы уверены что хотите удалить этот слот?</string>
    <string name="remove_group">Удалить группу</string>
    <string name="remove_group_description">Вы уверены что хотите удалить эту группу? Записи в этой группе автоматически переключатся на «Нет группы».</string>
    <string name="adding_new_slot_error">Произошла ошибка при попытке добавить новый слот:</string>
    <string name="progressbar_error">Невозможно сбросить шкалу длительности аниматора. Индикаторы прогресса будут невидимы.</string>
    <string name="details">Подробнее</string>
    <string name="filter">Фильтр</string>
    <string name="lock">Заблокировать</string>
    <string name="all">Все</string>
    <string name="name">Имя</string>
    <string name="no_group">Нет группы</string>
    <string name="sort_alphabetically">Эмитенты (по алфавиту)</string>
    <string name="sort_alphabetically_reverse">Эмитенты (обратный порядок алфавита)</string>
    <string name="sort_alphabetically_name">Аккаунт (по алфавиту)</string>
    <string name="sort_alphabetically_name_reverse">Аккаунт (алфавит в обратном порядке)</string>
    <string name="sort_custom">По другому</string>
    <string name="new_group">Новая группа...</string>
    <string name="enter_group_name">Введите название группы</string>
    <string name="group_name_hint">Название группы</string>
    <string name="preference_manage_groups">Редактировать группы</string>
    <string name="preference_manage_groups_summary">Управляйте и удаляйте свои группы здесь</string>
    <string name="tap_to_reveal">Скрытый</string>
    <string name="selected">Выбрано</string>
    <string name="dark_theme_title">Темная тема</string>
    <string name="light_theme_title">Светлая тема</string>
    <string name="amoled_theme_title">Черная тема</string>
    <string name="normal_viewmode_title">Обычный</string>
    <string name="compact_mode_title">Компактный</string>
    <string name="small_mode_title">Маленький</string>
    <string name="unknown_issuer">Неизвестный эмитент</string>
    <string name="unknown_account_name">Неизвестное имя аккаунта</string>
    <string name="import_error_dialog">Aegis не может имитировать %d токены. Эти токены пропущены. Нажмите \'подробнее\' чтобы увидеть информацию об ошибках</string>
    <string name="unable_to_read_qrcode">Не удается прочитать и обработать QR-код</string>
    <string name="select_picture">Выбрать картинку</string>
    <string name="toggle_checkboxes">Переключить выбор</string>
    <string name="search">Поиск</string>
<string name="unlock">Разблокировать</string>
<string name="advanced">Расширенные</string>
<string name="seconds">секунд</string>
<string name="counter">Счетчик</string>
<string name="digits">Цифры</string>
<string name="secret">Секрет</string>
<string name="scan">Сканировать QR-код</string>
<string name="scan_image">Сканировать изображение</string>
<string name="enter_manually">Ввести вручную</string>
<string name="add_fingerprint">Добавить отпечаток</string>
<string name="add_password">Добавить пароль</string>
<string name="slots_warning">Хранилище надежно защищено. При добавлении нового отпечатка пальца на ваше устройство необходимо будет заново настроить разблокировку хранилища по отпечатку пальца в Aegis.</string>
<string name="copy">Копировать</string>
<string name="edit">Изменить</string>
<string name="delete">Удалить</string>
<string name="password">Пароль</string>
<string name="confirm_password">Подтвердите пароль</string>
<string name="new_profile">Новый профиль</string>
<string name="add_new_profile">Добавить новый профиль</string>
<string name="unlock_vault_error">Не удалось разблокировать хранилище</string>
<string name="unlock_vault_error_description">Некорректный пароль. Убедитесь, что вы не допустили опечатку в вашем пароле.</string>
<string name="password_equality_error">Пароли должны быть одинаковыми и непустыми</string>
<string name="register_fingerprint">Зарегистрируйте свой отпечаток пальца</string>
<string name="snackbar_authentication_method">Пожалуйста, выберите метод аутентификации</string>
<string name="encrypting_vault">Шифрование хранилища</string>
<string name="delete_entry">Удалить запись</string>
<string name="delete_entry_description">Вы уверены что хотите удалить эту запись?</string>
<string name="discard_changes">Отменить изменения?</string>
<string name="discard_changes_description">Ваши изменения не были сохранены</string>
<string name="folder">Папка</string>
<string name="tap_to_select">Нажмите, чтобы выбрать</string>
<string name="saving_profile_error">Ошибка сохранения профиля</string>
<string name="welcome">Добро пожаловать</string>
<string name="app_description">Aegis - бесплатное, безопасное и открытое приложение 2FA.</string>
<string name="setup_completed">Настройка завершена</string>
<string name="setup_completed_description">Aegis настроен и готов к работе.</string>
<string name="vault_not_found">Хранилище не найдено, запуск первоначальной настройки…</string>
<string name="code_copied">Код скопирован в буфер обмена</string>
<string name="errors_copied">Ошибки скопированы в буфер обмена</string>
<string name="decryption_error">Произошла ошибка при попытке разблокировать хранилище</string>
<string name="saving_error">Произошла ошибка при попытке сохранить хранилище</string>
<string name="disable_encryption">Отключить шифрование</string>
<string name="disable_encryption_description">Вы уверены что хотите отключить шифрование? Это приведет к хранению хранилища в виде открытого текста.</string>
<string name="enable_encryption_error">Произошла ошибка при включении шифрования</string>
<string name="disable_encryption_error">Произошла ошибка при отключении шифрования</string>
<string name="permission_denied">Доступ запрещен</string>
<string name="choose_application">Выберите приложение из которого вы хотите импортировать базу данных</string>
<string name="choose_theme">Выберите тему</string>
<string name="choose_view_mode">Выберите режим отображения</string>
<string name="parsing_file_error">Произошла ошибка при попытке разобрать файл</string>
<string name="file_not_found">Ошибка: файл не найден</string>
<string name="reading_file_error">Произошла ошибка при попытке прочитать файл</string>
<string name="app_lookup_error">Ошибка: приложение не установлено</string>
<string name="root_error">Ошибка: невозможно получить права суперпользователя</string>
<string name="imported_entries_count">Импортировано %d записей</string>
<string name="read_entries_count">Прочитано %d записей. %d ошибок.</string>
<string name="import_error_title">При импорте произошла одна или несколько ошибок</string>
<string name="exporting_database_error">Произошла ошибка при попытке экспорта базы данных</string>
<string name="export_database_location">База данных была экспортирована в:</string>
<string name="export_warning">Это действие экспортирует базу данных из приватного хранилища Aegis.</string>
<string name="encryption_set_password_error">Произошла ошибка при попытке установить пароль:</string>
<string name="encryption_enable_fingerprint_error">Произошла ошибка при попытке разблокировать отпечаток пальца:</string>
<string name="no_cameras_available">Нет доступных камер</string>
<string name="read_qr_error">Произошла ошибка при попытке прочитать QR-код</string>
<string name="authentication_method_raw">Необработанный</string>
<string name="unlocking_vault">Разблокировка хранилища</string>
<string name="unlocking_vault_repair">Разблокировка хранилища (восстановление)</string>
<string name="password_slot_error">У вас должен быть хотя бы один слот для пароля</string>
<string name="remove_slot">Удалить слот</string>
<string name="remove_slot_description">Вы уверены что хотите удалить этот слот?</string>
<string name="remove_group">Удалить группу</string>
<string name="remove_group_description">Вы уверены что хотите удалить эту группу? Записи в этой группе будут автоматически перемещены в «Нет группы».</string>
<string name="adding_new_slot_error">Произошла ошибка при попытке добавить новый слот:</string>
<string name="progressbar_error">Не удалось установить продолжительность анимации. Индикаторы прогресса не будут отображаться.</string>
<string name="details">Подробнее</string>
<string name="filter">Фильтр</string>
<string name="lock">Заблокировать</string>
<string name="all">Все</string>
<string name="name">Имя</string>
<string name="sort_alphabetically">Эмитент (в алфавитном порядке)</string>
<string name="sort_alphabetically_reverse">Эмитент (в обратном порядке)</string>
<string name="sort_alphabetically_name">Учетная запись (в алфавитном порядке)</string>
<string name="sort_alphabetically_name_reverse">Учетная запись (в обратном порядке)</string>
<string name="sort_custom">Произвольно</string>
<string name="no_group">Нет группы</string>
<string name="new_group">Новая группа…</string>
<string name="enter_group_name">Введите название группы</string>
<string name="group_name_hint">Название группы</string>
<string name="preference_manage_groups">Редактировать группы</string>
<string name="preference_manage_groups_summary">Редактирование и удаление ваших групп</string>
<string name="tap_to_reveal">Скрытый</string>
<string name="selected">Выбрано</string>
<string name="dark_theme_title">Темная тема</string>
<string name="light_theme_title">Светлая тема</string>
<string name="amoled_theme_title">AMOLED-тема</string>
<string name="normal_viewmode_title">Обычный</string>
<string name="compact_mode_title">Компактный</string>
<string name="small_mode_title">Уменьшенный</string>
<string name="unknown_issuer">Неизвестный эмитент</string>
<string name="unknown_account_name">Неизвестное название учетной записи</string>
<string name="import_error_dialog">Aegis не удалось импортировать %d pfgbctq. Эти записи будут проигнорированы. Нажмите \'подробнее\' чтобы получить больше информации о возникших ошибках.</string>
<string name="unable_to_read_qrcode">Не удалось прочитать и обработать QR-код</string>
<string name="select_picture">Выберите изображение</string>
<string name="toggle_checkboxes">Установите переключатели</string>
<string name="search">Поиск</string>
<string name="channel_name_lock_status">Статус блокировки</string>
<string name="channel_description_lock_status">Aegis может создать постоянное уведомление для отображения статуса блокировки хранилища</string>
<string name="vault_unlocked_state">Хранилище разблокировано. Нажмите для блокировки.</string>
</resources>
+2
View File
@@ -35,6 +35,7 @@
<item>Dutch</item>
<item>English</item>
<item>French</item>
<item>German</item>
<item>Russian</item>
</string-array>
@@ -43,6 +44,7 @@
<item>nl</item>
<item>en</item>
<item>fr</item>
<item>de</item>
<item>ru</item>
</string-array>
+2 -1
View File
@@ -9,6 +9,7 @@
<color name="colorAccentPressed">#FF5252</color>
<color name="primary_text">#212121</color>
<color name="secondary_text">#757575</color>
<color name="icon_about">#757575</color>
<color name="extra_info_text">#8e8e8e</color>
<color name="primary_text_inverted">#ffffff</color>
<color name="secondary_text_inverted">#efefef</color>b
@@ -31,7 +32,7 @@
<color name="code_primary_text">#0d47a1</color>
<color name="code_primary_text_dark">#ffffff</color>
<color name="card_background_dark">#424242</color>
<color name="card_background_dark">#363636</color>
<color name="card_background_focused_dark">#6B6B6B</color>
<color name="card_background_focused_true_dark">#1B1B1B</color>
<color name="primary_text_dark">#ffffff</color>
+1
View File
@@ -3,4 +3,5 @@
<dimen name="activity_horizontal_margin">16dp</dimen>
<dimen name="activity_vertical_margin">16dp</dimen>
<dimen name="fab_margin">16dp</dimen>
<dimen name="list_item_height">48dp</dimen>
</resources>
+36
View File
@@ -2,7 +2,9 @@
<string name="app_name">Aegis</string>
<string name="app_name_full">Aegis Authenticator</string>
<string name="app_name_dev">AegisDev</string>
<string name="org_name_full">Beem Development</string>
<string name="action_settings">Settings</string>
<string name="action_about">About</string>
<string name="action_import">Import</string>
<string name="action_delete">Delete</string>
<string name="action_default_icon">Restore default icon</string>
@@ -171,4 +173,38 @@
<string name="channel_name_lock_status">Lock status</string>
<string name="channel_description_lock_status">Aegis can create a persistent notification to notify you when the vault is locked</string>
<string name="vault_unlocked_state">Vault is unlocked. Tap here to lock.</string>
<string name="title_activity_about">About</string>
<string name="version">Version</string>
<string name="changelog">Changelog</string>
<string name="whats_new">What\'s new</string>
<string name="github">GitHub</string>
<string name="github_description">Source code, issues and information</string>
<string name="licenses">Licenses</string>
<string name="licenses_description">Licenses of the libraries Aegis uses</string>
<string name="author_alex">Alexander Bakker</string>
<string name="country_netherlands">Netherlands</string>
<string name="author_michael">Michael Schättgen</string>
<string name="email_us">Write an email</string>
<string name="visit_website">Visit our website</string>
<string name="about_support">Support</string>
<string name="support_rate">Rate</string>
<string name="support_rate_description">Support us by leaving a review in the Google Play Store</string>
<string name="webview_error">This device doesn\'t support web view, which is necessary to view the change log. It is missing a system component.</string>
<string name="email">Email</string>
<string name="custom_notices_format_style" translatable="false" >
body {
background-color: #%1$s;
color: #%2$s;
font-family: sans-serif;
overflow-wrap: break-word;
}
pre {
background-color: #%3$s;
padding: 1em;
white-space: pre-wrap;
}
</string>
<string name="empty_list">There are no codes to be shown. Start adding entries by tapping the plus sign in the bottom right corner</string>
<string name="empty_list_title">No entries found</string>
</resources>
+48 -2
View File
@@ -17,8 +17,9 @@
<item name="android:windowIsTranslucent">true</item>
</style>
<style name="AppTheme.AppBarOverlay" parent="ThemeOverlay.AppCompat.Dark.ActionBar"/>
<style name="AppTheme.PopupOverlay" parent="ThemeOverlay.AppCompat.Light"/>
<style name="AppTheme.AppBarOverlay" parent="ThemeOverlay.AppCompat.Dark.ActionBar" />
<style name="AppTheme.PopupOverlay" parent="ThemeOverlay.AppCompat.Light" />
<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
<item name="primaryText">@color/primary_text</item>
@@ -39,34 +40,43 @@
<item name="actionModeStyle">@style/ActionModeStyle</item>
<item name="actionBarTheme">@style/ThemeOverlay.AppCompat.Dark.ActionBar</item>
<item name="alertDialogTheme">@style/DialogStyle</item>
</style>
<style name="ActionModeStyle" parent="@style/Widget.AppCompat.Light.ActionMode.Inverse">
<item name="background">@color/colorPrimary</item>
<item name="titleTextStyle">@style/ActionModeTitleTextStyle</item>
<item name="iconColorPrimary">@color/icon_primary</item>
<item name="iconColorInverted">@color/icon_primary_inverted</item>
</style>
<style name="ActionModeStyle.Dark" parent="@style/Widget.AppCompat.Light.ActionMode.Inverse">
<item name="colorPrimary">@color/colorPrimary</item>
<item name="background">@color/colorPrimary</item>
<item name="titleTextStyle">@style/ActionModeTitleTextStyle</item>
<item name="iconColorPrimary">@color/icon_primary</item>
<item name="iconColorInverted">@color/icon_primary_inverted</item>
<item name="alertDialogStyle">@style/DialogStyle.Dark</item>
</style>
<style name="ActionModeStyle.TrueBlack" parent="@style/Widget.AppCompat.Light.ActionMode.Inverse">
<item name="colorPrimary">@color/background_true_dark</item>
<item name="background">@color/background_true_dark</item>
<item name="titleTextStyle">@style/ActionModeTitleTextStyle</item>
<item name="iconColorPrimary">@color/icon_primary</item>
<item name="iconColorInverted">@color/icon_primary_inverted</item>
<item name="alertDialogStyle">@style/DialogStyle.TrueDark</item>
</style>
<style name="ActionModeTitleTextStyle" parent="@style/TextAppearance.AppCompat.Widget.ActionMode.Title">
<item name="android:textColor">@android:color/white</item>
</style>
<style name="AppTheme.NoActionBar">
<item name="windowActionBar">false</item>
<item name="windowNoTitle">true</item>
</style>
<style name="AppTheme.TransparentActionBar">
<item name="android:actionBarStyle">@style/ThemeActionBar</item>
<item name="android:windowActionBarOverlay">true</item>
@@ -74,6 +84,7 @@
<item name="actionBarStyle">@style/ThemeActionBar</item>
<item name="windowActionBarOverlay">true</item>
</style>
<style name="AppTheme.Fullscreen" parent="AppTheme.TransparentActionBar">
<item name="android:windowNoTitle">true</item>
<item name="android:windowFullscreen">true</item>
@@ -97,6 +108,8 @@
<item name="swirl_errorColor">@color/colorSwirlErrorDark</item>
<item name="actionModeStyle">@style/ActionModeStyle.Dark</item>
<item name="alertDialogTheme">@style/DialogStyle.Dark</item>
</style>
<style name="AppTheme.TrueBlack" parent="AppTheme.Dark">
@@ -107,6 +120,8 @@
<item name="colorPrimaryDark">@color/background_true_dark</item>
<item name="preferenceTheme">@style/PreferenceThemeOverlay.v14.Material</item>
<item name="actionModeStyle">@style/ActionModeStyle.TrueBlack</item>
<item name="alertDialogTheme">@style/DialogStyle.TrueDark</item>
</style>
<style name="AppTheme.TrueBlack.Preferences" parent="AppTheme.TrueBlack">
@@ -117,6 +132,7 @@
<item name="windowActionBar">false</item>
<item name="windowNoTitle">true</item>
</style>
<style name="AppTheme.Dark.TransparentActionBar">
<item name="android:actionBarStyle">@style/ThemeActionBar</item>
<item name="android:windowActionBarOverlay">true</item>
@@ -130,4 +146,34 @@
<item name="android:textColor">#FFFFFF</item>
</style>
<style name="AppTheme.NoActionBar.NoActionBar">
<item name="windowActionBar">false</item>
<item name="windowNoTitle">true</item>
</style>
<style name="DialogStyle" parent="Theme.AppCompat.Light.Dialog.Alert">
<item name="android:background">@color/card_background</item>
<item name="colorAccent">@color/colorAccent</item>
<item name="textColorAlertDialogListItem">@color/primary_text</item>
</style>
<style name="DialogStyle.Dark" parent="Theme.AppCompat.Dialog">
<item name="android:background">@color/card_background_dark</item>
<item name="colorAccent">@color/colorAccent</item>
<item name="textColorAlertDialogListItem">@color/primary_text_dark</item>
<!--The following lines are needed because the non-light version of this parent changes the
min width to 80% or something. Looks weird.-->
<item name="android:windowMinWidthMajor">97%</item>
<item name="android:windowMinWidthMinor">97%</item>
</style>
<style name="DialogStyle.TrueDark" parent="DialogStyle.Dark">
<item name="android:background">@color/card_background_focused_true_dark</item>
</style>
<style name="AppTheme.NoActionBar.AppBarOverlay" parent="ThemeOverlay.AppCompat.Dark.ActionBar" />
<style name="AppTheme.NoActionBar.PopupOverlay" parent="ThemeOverlay.AppCompat.Light" />
</resources>
+2 -2
View File
@@ -1,6 +1,6 @@
#Mon Jun 10 14:39:47 CEST 2019
#Sun Sep 01 21:12:20 CEST 2019
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-5.1.1-all.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-5.4.1-all.zip