Merge branch 'master' into reauthenticate_after_inactivity

This commit is contained in:
Jakob Nixdorf 2020-02-03 07:07:59 +01:00 committed by GitHub
commit 5795d07f9c
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
165 changed files with 4473 additions and 2790 deletions

24
.gitignore vendored
View file

@ -1,11 +1,17 @@
*.iml # Local config files
.gradle
crowdin.properties crowdin.properties
/local.properties local.properties
/.idea/workspace.xml
/.idea/libraries # IntelliJ
/.idea/markdown-navigator* *.iml
/.idea/caches .idea
# Gradle
.gradle
build
# Android Studio
captures
# OS files
.DS_Store .DS_Store
/build
/captures

View file

@ -1,35 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="WizardSettings">
<option name="children">
<map>
<entry key="vectorWizard">
<value>
<PersistentState>
<option name="children">
<map>
<entry key="vectorAssetStep">
<value>
<PersistentState>
<option name="values">
<map>
<entry key="assetSourceType" value="FILE" />
<entry key="height" value="128" />
<entry key="outputName" value="thumb_instagram" />
<entry key="overrideSize" value="true" />
<entry key="sourceFile" value="$PROJECT_DIR$/../../../downloads/instagram.svg" />
<entry key="width" value="128" />
</map>
</option>
</PersistentState>
</value>
</entry>
</map>
</option>
</PersistentState>
</value>
</entry>
</map>
</option>
</component>
</project>

View file

@ -1,29 +0,0 @@
<component name="ProjectCodeStyleConfiguration">
<code_scheme name="Project" version="173">
<Objective-C-extensions>
<file>
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Import" />
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Macro" />
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Typedef" />
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Enum" />
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Constant" />
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Global" />
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Struct" />
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="FunctionPredecl" />
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Function" />
</file>
<class>
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Property" />
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Synthesize" />
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="InitMethod" />
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="StaticMethod" />
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="InstanceMethod" />
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="DeallocMethod" />
</class>
<extensions>
<pair source="cpp" header="h" fileNamingConvention="NONE" />
<pair source="c" header="h" fileNamingConvention="NONE" />
</extensions>
</Objective-C-extensions>
</code_scheme>
</component>

View file

@ -1,18 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="GradleSettings">
<option name="linkedExternalProjectsSettings">
<GradleProjectSettings>
<option name="distributionType" value="DEFAULT_WRAPPED" />
<option name="externalProjectPath" value="$PROJECT_DIR$" />
<option name="modules">
<set>
<option value="$PROJECT_DIR$" />
<option value="$PROJECT_DIR$/app" />
</set>
</option>
<option name="resolveModulePerSourceSet" value="false" />
</GradleProjectSettings>
</option>
</component>
</project>

View file

@ -1,14 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="CMakeSettings">
<configurations>
<configuration PROFILE_NAME="Debug" CONFIG_NAME="Debug" />
</configurations>
</component>
<component name="ProjectRootManager" version="2" languageLevel="JDK_1_8" project-jdk-name="1.8" project-jdk-type="JavaSDK">
<output url="file://$PROJECT_DIR$/build/classes" />
</component>
<component name="ProjectType">
<option name="id" value="Android" />
</component>
</project>

View file

@ -1,9 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectModuleManager">
<modules>
<module fileurl="file://$PROJECT_DIR$/andOTP.iml" filepath="$PROJECT_DIR$/andOTP.iml" />
<module fileurl="file://$PROJECT_DIR$/app/app.iml" filepath="$PROJECT_DIR$/app/app.iml" />
</modules>
</component>
</project>

View file

@ -1,12 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="RunConfigurationProducerService">
<option name="ignoredProducers">
<set>
<option value="org.jetbrains.plugins.gradle.execution.test.runner.AllInPackageGradleConfigurationProducer" />
<option value="org.jetbrains.plugins.gradle.execution.test.runner.TestClassGradleConfigurationProducer" />
<option value="org.jetbrains.plugins.gradle.execution.test.runner.TestMethodGradleConfigurationProducer" />
</set>
</option>
</component>
</project>

View file

@ -1,6 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="" vcs="Git" />
</component>
</project>

View file

@ -1,5 +1,29 @@
# Changelog # Changelog
#### v0.6.4 (WIP)
* New feature: Generate a new HOTP token when revealing (Issue #334, PR #366 by @moritzgloeckl)
* New feature: Split issuer and label (Issue #258, PR #372 by @lucavallerini)
* New feature: Automatic thumbnail selection based on the issuer (Issue #388, PR #389 by @schwedenmut)
* New feature: Allow searching the tags and issuers in addition to the label (Issue #327)
* New feature: Turn tokens red if they are about to expire (Issue #311, PR #410 by @Ullas-Aithal)
* New feature: Handle otpauth:// intents from other apps (Issue #324, PR #393 by @schwedenmut)
* New feature: Create an encrypted backup every time the entries are changed (PR #397 by @RichyHBM)
* New feature: Different layouts for the entry cards
* New feature: New thumbnail size "Tiny"
* Improvement: Hide the token list on screen off (Issue #264, PR #391 by @LizardWithHat)
* Improvement: Scale the font of the default thumbnail with its size
* Bug fix: Fix black navigation bar on OxygenOS devices (PR #417 by @Ullas-Aithal)
* Internal: Migrate to AndroidX
* Internal: Update Gradle and a lot of dependencies
* Thumbnails: Lots of new ones (thanks to all contributors)
#### v0.6.3.1
* Introduce build flavors:
- fdroid: Shows donation links in the About section
- play: Doesn't show donation links in the About section
#### v0.6.3 #### v0.6.3
* Security: Improved password derivation for the password protected backups * Security: Improved password derivation for the password protected backups
@ -11,8 +35,10 @@
* Bug fix: Always use arabic numerals for the tokens (Issue #359) * Bug fix: Always use arabic numerals for the tokens (Issue #359)
* Bug fix: Refactor storage access code to allow importing and exporting from cloud storage directly * Bug fix: Refactor storage access code to allow importing and exporting from cloud storage directly
* Bug fix: Hardcode the black background color to avoid strange behaviour on some custom ROMs * Bug fix: Hardcode the black background color to avoid strange behaviour on some custom ROMs
* Bug fix: Force English locales for saving AuthMethod
* Misc: Update donation links (PR #351) * Misc: Update donation links (PR #351)
* Thumbnails: Lots of new thumbnails * Thumbnails: Lots of new thumbnails
* Translations: Hungarian
#### v0.6.2 #### v0.6.2

View file

@ -1,7 +1,7 @@
# andOTP - Android OTP Authenticator # andOTP - Android OTP Authenticator
[![Build Status](https://travis-ci.org/andOTP/andOTP.svg?branch=master)](https://travis-ci.org/andOTP/andOTP) [![Build Status](https://travis-ci.org/andOTP/andOTP.svg?branch=master)](https://travis-ci.org/andOTP/andOTP)
[![Current release](https://img.shields.io/github/release/andOTP/andOTP/all.svg)](https://github.com/andOTP/andOTP/releases/download/v0.6.3-beta1/andOTP_v0.6.3-beta1.apk) [![Current release](https://img.shields.io/github/release/andOTP/andOTP/all.svg)](https://github.com/andOTP/andOTP/releases/download/v0.6.3.1/andOTP_v0.6.3.1.apk)
[![Crowdin](https://d322cqt584bo4o.cloudfront.net/andotp/localized.svg)](https://crowdin.com/project/andotp) [![Crowdin](https://d322cqt584bo4o.cloudfront.net/andotp/localized.svg)](https://crowdin.com/project/andotp)
[![Chat - Telegram](https://img.shields.io/badge/chat-Telegram-blue.svg)](https://t.me/andOTP) [![Chat - Telegram](https://img.shields.io/badge/chat-Telegram-blue.svg)](https://t.me/andOTP)
[![Chat - Matrix](https://img.shields.io/badge/chat-Matrix-blue.svg)](https://matrix.to/#/#andOTP:privacytools.io) [![Chat - Matrix](https://img.shields.io/badge/chat-Matrix-blue.svg)](https://matrix.to/#/#andOTP:privacytools.io)
@ -61,9 +61,9 @@ key, which renders them useless.
### Opening the backups on your PC: ### Opening the backups on your PC:
* [OpenPGP](http://openpgp.org/): OpenPGP can be used to easily decrypt the **OpenPGP-encrypted backups** on your PC. * [OpenPGP](https://openpgp.org/): OpenPGP can be used to easily decrypt the **OpenPGP-encrypted backups** on your PC.
* [WebDecrypt](https://flocke.shadowice.org/andOTP/decrypt/): JavaScript-based decryption of the **new password-protected backup format** in the browser ([source code](https://github.com/andOTP/WebDecrypt)). * [WebDecrypt](https://flocke.shadowice.org/andOTP/decrypt/): JavaScript-based decryption of the **new password-protected backup format** in the browser ([source code](https://github.com/andOTP/WebDecrypt)).
* [andOTP-decrypt](https://github.com/asmw/andOTP-decrypt): Python script written by @asmw to decrypt the **old password-protected backup format** on your PC. * [andOTP-decrypt](https://github.com/asmw/andOTP-decrypt): Python script written by @asmw to decrypt the **old and new password-protected backup format** on your PC.
### Automatic backups: ### Automatic backups:
@ -89,16 +89,18 @@ So make sure you have a **current backup** before switching!
* **Translation**: If you want to help translate andOTP into your language head over to the [Crowdin project](https://crowdin.com/project/andotp). * **Translation**: If you want to help translate andOTP into your language head over to the [Crowdin project](https://crowdin.com/project/andotp).
* **Bug reports and feature requests**: You can report bugs and request features in the [Issue tracker](https://github.com/andOTP/andOTP/issues) on GitHub. * **Bug reports and feature requests**: You can report bugs and request features in the [Issue tracker](https://github.com/andOTP/andOTP/issues) on GitHub.
* **Requesting thumbnails**: If you are missing a thumbnail you can request it by editing the [wiki](https://github.com/andOTP/andOTP/wiki/Thumbnails#thumbnail-requests) * **Requesting thumbnails**: If you are missing a thumbnail you can request it by [opening an issue](https://github.com/andOTP/andOTP/issues/new).
* **Discussion and support**: * **Discussion and support**:
- [XDA thread](https://forum.xda-developers.com/android/apps-games/app-andotp-android-otp-authenticator-t3636993) (please keep off-topic to a minimum) - [XDA thread](https://forum.xda-developers.com/android/apps-games/app-andotp-android-otp-authenticator-t3636993) (please keep off-topic to a minimum)
- Telegram group [@andOTP](https://t.me/andOTP) (if you just want important updates you can mute the group so you only get notified about pinned messages) - Telegram group [@andOTP](https://t.me/andOTP) (if you just want important updates you can mute the group so you only get notified about pinned messages)
- Matrix channel [#andOTP:privacytools.io](https://matrix.to/#/#andOTP:privacytools.io) - Matrix channel [#andOTP:privacytools.io](https://matrix.to/#/#andOTP:privacytools.io)
#### Developers: #### Donations:
* [Jakob Nixdorf](https://github.com/flocke) (Telegram: [@flocke000](https://t.me/flocke000), Reddit: [/u/flocke000](https://www.reddit.com/user/flocke000)) If you want to show your appreciation for our work with a small donation you can do so using the following links:
* [Richy HBM](https://github.com/RichyHBM)
* [Donate to Jakob Nixdorf](https://flocke.shadowice.org/donate.html) (Main developer, maintainer)
* [Donate to Richy HBM](https://richyhbm.co.uk/donate) (Developer)
## Screenshots: ## Screenshots:
#### Light theme: #### Light theme:
@ -136,7 +138,7 @@ So make sure you have a **current backup** before switching!
* [Android-ItemTouchHelper-Demo](https://github.com/iPaulPro/Android-ItemTouchHelper-Demo/tree/master/app/src/main/java/co/paulburke/android/itemtouchhelperdemo/helper) * [Android-ItemTouchHelper-Demo](https://github.com/iPaulPro/Android-ItemTouchHelper-Demo/tree/master/app/src/main/java/co/paulburke/android/itemtouchhelperdemo/helper)
* [Code Parts from Google's Android Samples](https://android.googlesource.com/platform/development/+/master/samples/Vault/src/com/example/android/vault) * [Code Parts from Google's Android Samples](https://android.googlesource.com/platform/development/+/master/samples/Vault/src/com/example/android/vault)
* [LetterBitmap](http://stackoverflow.com/questions/23122088/colored-boxed-with-letters-a-la-gmail) * [LetterBitmap](https://stackoverflow.com/questions/23122088/colored-boxed-with-letters-a-la-gmail)
* [DimensionConverter](https://stackoverflow.com/questions/8343971/how-to-parse-a-dimension-string-and-convert-it-to-a-dimension-value) * [DimensionConverter](https://stackoverflow.com/questions/8343971/how-to-parse-a-dimension-string-and-convert-it-to-a-dimension-value)
#### Previously used open-source components: #### Previously used open-source components:

View file

@ -1,15 +1,15 @@
apply plugin: 'com.android.application' apply plugin: 'com.android.application'
android { android {
compileSdkVersion 28 compileSdkVersion 29
buildToolsVersion '28.0.3' buildToolsVersion '29.0.2'
defaultConfig { defaultConfig {
applicationId "org.shadowice.flocke.andotp" applicationId "org.shadowice.flocke.andotp"
minSdkVersion 19 minSdkVersion 19
targetSdkVersion 28 targetSdkVersion 29
versionCode 24 versionCode 26
versionName "0.6.3-beta1" versionName "0.6.3.1"
vectorDrawables.useSupportLibrary = true vectorDrawables.useSupportLibrary = true
} }
buildTypes { buildTypes {
@ -29,25 +29,38 @@ android {
dataBinding { dataBinding {
enabled = true enabled = true
} }
flavorDimensions 'market'
productFlavors {
fdroid {
dimension = 'market'
}
play {
dimension = 'market'
versionNameSuffix = "-play"
}
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
} }
dependencies { dependencies {
ext.supportLibVersion = "28.0.0" implementation 'androidx.media:media:1.1.0'
implementation 'androidx.legacy:legacy-support-v4:1.0.0'
implementation 'androidx.appcompat:appcompat:1.1.0'
implementation 'androidx.cardview:cardview:1.0.0'
implementation 'androidx.recyclerview:recyclerview:1.1.0'
implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
implementation 'com.google.android.material:material:1.0.0'
implementation "commons-codec:commons-codec:1.12" implementation "commons-codec:commons-codec:1.14"
implementation "com.android.support:support-media-compat:$supportLibVersion"
implementation "com.android.support:support-v4:$supportLibVersion"
implementation "com.android.support:appcompat-v7:$supportLibVersion"
implementation "com.android.support:cardview-v7:$supportLibVersion"
implementation "com.android.support:design:$supportLibVersion"
implementation "com.android.support:recyclerview-v7:$supportLibVersion"
implementation "com.android.support.constraint:constraint-layout:1.1.3"
implementation "com.github.aakira:expandable-layout:1.6.0" implementation "com.github.aakira:expandable-layout:1.6.0"
implementation "com.heinrichreimersoftware:material-intro:1.6.2" implementation "com.heinrichreimersoftware:material-intro:2.0.0"
implementation "com.journeyapps:zxing-android-embedded:3.6.0" implementation "com.journeyapps:zxing-android-embedded:3.6.0"
implementation "com.vanniktech:vntnumberpickerpreference:1.0.0" implementation "com.vanniktech:vntnumberpickerpreference:1.0.0"
implementation "me.zhanghai.android.materialprogressbar:library:1.4.2" implementation "me.zhanghai.android.materialprogressbar:library:1.6.1"
implementation "org.sufficientlysecure:openpgp-api:12.0" implementation "org.sufficientlysecure:openpgp-api:12.0"
implementation "com.leinardi.android:speed-dial:2.0.1" implementation "com.leinardi.android:speed-dial:3.1.1"
implementation "com.mikepenz:aboutlibraries:6.1.1" implementation "com.mikepenz:aboutlibraries:6.2.3"
} }

View file

@ -0,0 +1,54 @@
package org.shadowice.flocke.andotp.Fragments;
import android.os.Bundle;
import androidx.annotation.NonNull;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.LinearLayout;
import org.shadowice.flocke.andotp.R;
public class AboutFragment extends BaseAboutFragment {
private static final String ABOUT_AUTHOR1_EXTRA_LINK = "https://flocke.shadowice.org/donate.html";
private static final String ABOUT_AUTHOR2_EXTRA_LINK = "https://richyhbm.co.uk/donate";
@Override
public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View v = super.onCreateView(inflater, container, savedInstanceState);
LinearLayout author1Content = v.findViewById(R.id.aboutLayoutAuthor1Content);
LinearLayout author2Content = v.findViewById(R.id.aboutLayoutAuthor2Content);
View extra1 = inflater.inflate(R.layout.part_author_extra, null);
View extra2 = inflater.inflate(R.layout.part_author_extra, null);
extra1.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
try {
openURI(ABOUT_AUTHOR1_EXTRA_LINK);
} catch (Exception ignored) {
copyToClipboard(ABOUT_AUTHOR1_EXTRA_LINK);
}
}
});
extra2.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
try {
openURI(ABOUT_AUTHOR2_EXTRA_LINK);
} catch (Exception ignored) {
copyToClipboard(ABOUT_AUTHOR2_EXTRA_LINK);
}
}
});
author1Content.addView(extra1);
author2Content.addView(extra2);
return v;
}
}

View file

@ -0,0 +1,10 @@
<?xml version="1.0" encoding="utf-8"?>
<TextView
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingTop="@dimen/activity_margin_small"
android:background="?android:attr/selectableItemBackground"
android:textAppearance="?android:attr/textAppearanceMedium"
android:textStyle="bold"
android:text="@string/about_label_donate" />

View file

@ -27,8 +27,16 @@
<action android:name="android.intent.action.MAIN" /> <action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" /> <category android:name="android.intent.category.LAUNCHER" />
</intent-filter> </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" android:host="totp" />
<data android:scheme="otpauth" android:host="hotp" />
</intent-filter>
<intent-filter> <intent-filter>
<action android:name="org.shadowice.flocke.andotp.intent.SCAN_QR" /> <action android:name="org.shadowice.flocke.andotp.intent.SCAN_QR" />
<action android:name="org.shadowice.flocke.andotp.intent.IMPORT_QR" />
<action android:name="org.shadowice.flocke.andotp.intent.ENTER_DETAILS" /> <action android:name="org.shadowice.flocke.andotp.intent.ENTER_DETAILS" />
<category android:name="android.intent.category.DEFAULT" /> <category android:name="android.intent.category.DEFAULT" />
</intent-filter> </intent-filter>

View file

@ -23,12 +23,12 @@
package org.shadowice.flocke.andotp.Activities; package org.shadowice.flocke.andotp.Activities;
import android.os.Bundle; import android.os.Bundle;
import android.support.design.widget.TabLayout; import com.google.android.material.tabs.TabLayout;
import android.support.v4.app.Fragment; import androidx.fragment.app.Fragment;
import android.support.v4.app.FragmentManager; import androidx.fragment.app.FragmentManager;
import android.support.v4.app.FragmentPagerAdapter; import androidx.fragment.app.FragmentPagerAdapter;
import android.support.v4.view.ViewPager; import androidx.viewpager.widget.ViewPager;
import android.support.v7.widget.Toolbar; import androidx.appcompat.widget.Toolbar;
import android.view.View; import android.view.View;
import android.view.ViewStub; import android.view.ViewStub;

View file

@ -24,9 +24,9 @@ package org.shadowice.flocke.andotp.Activities;
import android.content.Intent; import android.content.Intent;
import android.os.Bundle; import android.os.Bundle;
import android.support.design.widget.TextInputEditText; import com.google.android.material.textfield.TextInputEditText;
import android.support.design.widget.TextInputLayout; import com.google.android.material.textfield.TextInputLayout;
import android.support.v7.widget.Toolbar; import androidx.appcompat.widget.Toolbar;
import android.text.InputType; import android.text.InputType;
import android.text.method.PasswordTransformationMethod; import android.text.method.PasswordTransformationMethod;
import android.util.Base64; import android.util.Base64;
@ -89,6 +89,9 @@ public class AuthenticateActivity extends ThemedActivity
TextInputLayout passwordLayout = v.findViewById(R.id.passwordLayout); TextInputLayout passwordLayout = v.findViewById(R.id.passwordLayout);
passwordInput = v.findViewById(R.id.passwordEdit); passwordInput = v.findViewById(R.id.passwordEdit);
if (settings.getBlockAccessibility())
passwordLayout.setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS);
passwordLabel.setText(labelMsg); passwordLabel.setText(labelMsg);
authMethod = settings.getAuthMethod(); authMethod = settings.getAuthMethod();

View file

@ -31,10 +31,10 @@ import android.content.IntentSender;
import android.content.pm.PackageManager; import android.content.pm.PackageManager;
import android.net.Uri; import android.net.Uri;
import android.os.Bundle; import android.os.Bundle;
import android.support.annotation.NonNull; import androidx.annotation.NonNull;
import android.support.v4.app.ActivityCompat; import androidx.core.app.ActivityCompat;
import android.support.v4.content.ContextCompat; import androidx.core.content.ContextCompat;
import android.support.v7.widget.Toolbar; import androidx.appcompat.widget.Toolbar;
import android.text.TextUtils; import android.text.TextUtils;
import android.view.View; import android.view.View;
import android.view.ViewStub; import android.view.ViewStub;
@ -458,7 +458,7 @@ public class BackupActivity extends BaseActivity {
String password = settings.getBackupPasswordEnc(); String password = settings.getBackupPasswordEnc();
if (password.isEmpty()) { if (password.isEmpty()) {
PasswordEntryDialog pwDialog = new PasswordEntryDialog(this, PasswordEntryDialog.Mode.ENTER, new PasswordEntryDialog.PasswordEnteredCallback() { PasswordEntryDialog pwDialog = new PasswordEntryDialog(this, PasswordEntryDialog.Mode.ENTER, settings.getBlockAccessibility(), new PasswordEntryDialog.PasswordEnteredCallback() {
@Override @Override
public void onPasswordEntered(String newPassword) { public void onPasswordEntered(String newPassword) {
doRestoreCryptWithPassword(uri, newPassword, old_format); doRestoreCryptWithPassword(uri, newPassword, old_format);
@ -514,7 +514,7 @@ public class BackupActivity extends BaseActivity {
String password = settings.getBackupPasswordEnc(); String password = settings.getBackupPasswordEnc();
if (password.isEmpty()) { if (password.isEmpty()) {
PasswordEntryDialog pwDialog = new PasswordEntryDialog(this, PasswordEntryDialog.Mode.UPDATE, new PasswordEntryDialog.PasswordEnteredCallback() { PasswordEntryDialog pwDialog = new PasswordEntryDialog(this, PasswordEntryDialog.Mode.UPDATE, settings.getBlockAccessibility(), new PasswordEntryDialog.PasswordEnteredCallback() {
@Override @Override
public void onPasswordEntered(String newPassword) { public void onPasswordEntered(String newPassword) {
doBackupCryptWithPassword(uri, newPassword); doBackupCryptWithPassword(uri, newPassword);
@ -528,30 +528,8 @@ public class BackupActivity extends BaseActivity {
private void doBackupCryptWithPassword(Uri uri, String password) { private void doBackupCryptWithPassword(Uri uri, String password) {
if (Tools.isExternalStorageWritable()) { if (Tools.isExternalStorageWritable()) {
ArrayList<Entry> entries = DatabaseHelper.loadDatabase(this, encryptionKey);
String plain = DatabaseHelper.entriesToString(entries);
boolean success = true; boolean success = BackupHelper.backupToFile(this, uri, password, encryptionKey);
try {
int iter = EncryptionHelper.generateRandomIterations();
byte[] salt = EncryptionHelper.generateRandom(Constants.ENCRYPTION_IV_LENGTH);
SecretKey key = EncryptionHelper.generateSymmetricKeyPBKDF2(password, iter, salt);
byte[] encrypted = EncryptionHelper.encrypt(key, plain.getBytes(StandardCharsets.UTF_8));
byte[] iterBytes = ByteBuffer.allocate(Constants.INT_LENGTH).putInt(iter).array();
byte[] data = new byte[Constants.INT_LENGTH + Constants.ENCRYPTION_IV_LENGTH + encrypted.length];
System.arraycopy(iterBytes, 0, data, 0, Constants.INT_LENGTH);
System.arraycopy(salt, 0, data, Constants.INT_LENGTH, Constants.ENCRYPTION_IV_LENGTH);
System.arraycopy(encrypted, 0, data, Constants.INT_LENGTH + Constants.ENCRYPTION_IV_LENGTH, encrypted.length);
StorageAccessHelper.saveFile(this, uri, data);
} catch (Exception e) {
e.printStackTrace();
success = false;
}
if (success) { if (success) {
Toast.makeText(this, R.string.backup_toast_export_success, Toast.LENGTH_LONG).show(); Toast.makeText(this, R.string.backup_toast_export_success, Toast.LENGTH_LONG).show();

View file

@ -27,10 +27,10 @@ import android.animation.ObjectAnimator;
import android.app.KeyguardManager; import android.app.KeyguardManager;
import android.graphics.Color; import android.graphics.Color;
import android.os.Bundle; import android.os.Bundle;
import android.support.annotation.NonNull; import androidx.annotation.NonNull;
import android.support.design.widget.TextInputEditText; import com.google.android.material.textfield.TextInputEditText;
import android.support.design.widget.TextInputLayout; import com.google.android.material.textfield.TextInputLayout;
import android.support.v4.view.ViewPager; import androidx.viewpager.widget.ViewPager;
import android.text.Editable; import android.text.Editable;
import android.text.InputType; import android.text.InputType;
import android.text.TextWatcher; import android.text.TextWatcher;

View file

@ -23,24 +23,30 @@
package org.shadowice.flocke.andotp.Activities; package org.shadowice.flocke.andotp.Activities;
import android.Manifest;
import android.animation.ObjectAnimator; import android.animation.ObjectAnimator;
import android.app.AlertDialog; import android.app.AlertDialog;
import android.app.KeyguardManager; import android.app.KeyguardManager;
import android.content.DialogInterface; import android.content.DialogInterface;
import android.content.Intent; import android.content.Intent;
import android.content.SharedPreferences; import android.content.SharedPreferences;
import android.content.pm.PackageManager;
import android.content.res.Configuration; import android.content.res.Configuration;
import android.os.Bundle; import android.os.Bundle;
import android.os.CountDownTimer; import android.os.CountDownTimer;
import android.os.Handler; import android.os.Handler;
import android.preference.PreferenceManager; import android.preference.PreferenceManager;
import android.support.v4.widget.DrawerLayout; import androidx.annotation.NonNull;
import android.support.v7.app.ActionBarDrawerToggle; import androidx.core.app.ActivityCompat;
import android.support.v7.widget.LinearLayoutManager; import androidx.core.content.ContextCompat;
import android.support.v7.widget.RecyclerView; import androidx.drawerlayout.widget.DrawerLayout;
import android.support.v7.widget.SearchView; import androidx.appcompat.app.ActionBarDrawerToggle;
import android.support.v7.widget.Toolbar; import androidx.recyclerview.widget.LinearLayoutManager;
import android.support.v7.widget.helper.ItemTouchHelper; import androidx.recyclerview.widget.RecyclerView;
import androidx.appcompat.widget.SearchView;
import androidx.appcompat.widget.Toolbar;
import androidx.recyclerview.widget.ItemTouchHelper;
import android.text.TextUtils;
import android.view.Menu; import android.view.Menu;
import android.view.MenuItem; import android.view.MenuItem;
import android.view.View; import android.view.View;
@ -63,10 +69,11 @@ import org.shadowice.flocke.andotp.Utilities.Constants;
import org.shadowice.flocke.andotp.Utilities.EncryptionHelper; import org.shadowice.flocke.andotp.Utilities.EncryptionHelper;
import org.shadowice.flocke.andotp.Utilities.KeyStoreHelper; import org.shadowice.flocke.andotp.Utilities.KeyStoreHelper;
import org.shadowice.flocke.andotp.Utilities.NotificationHelper; import org.shadowice.flocke.andotp.Utilities.NotificationHelper;
import org.shadowice.flocke.andotp.Utilities.ScanQRCodeFromFile;
import org.shadowice.flocke.andotp.Utilities.TokenCalculator; import org.shadowice.flocke.andotp.Utilities.TokenCalculator;
import org.shadowice.flocke.andotp.View.EntriesCardAdapter; import org.shadowice.flocke.andotp.View.EntriesCardAdapter;
import org.shadowice.flocke.andotp.View.ItemTouchHelper.SimpleItemTouchHelperCallback; import org.shadowice.flocke.andotp.View.ItemTouchHelper.SimpleItemTouchHelperCallback;
import org.shadowice.flocke.andotp.View.ManualEntryDialog; import org.shadowice.flocke.andotp.Dialogs.ManualEntryDialog;
import org.shadowice.flocke.andotp.View.TagsAdapter; import org.shadowice.flocke.andotp.View.TagsAdapter;
import java.util.ArrayList; import java.util.ArrayList;
@ -83,6 +90,7 @@ public class MainActivity extends BaseActivity
public static long animatorDuration = 1000; public static long animatorDuration = 1000;
private static final String INTENT_SCAN_QR = "org.shadowice.flocke.andotp.intent.SCAN_QR"; private static final String INTENT_SCAN_QR = "org.shadowice.flocke.andotp.intent.SCAN_QR";
private static final String INTENT_IMPORT_QR = "org.shadowice.flocke.andotp.intent.IMPORT_QR";
private static final String INTENT_ENTER_DETAILS = "org.shadowice.flocke.andotp.intent.ENTER_DETAILS"; private static final String INTENT_ENTER_DETAILS = "org.shadowice.flocke.andotp.intent.ENTER_DETAILS";
private EntriesCardAdapter adapter; private EntriesCardAdapter adapter;
@ -215,6 +223,9 @@ public class MainActivity extends BaseActivity
case R.id.fabEnterDetails: case R.id.fabEnterDetails:
ManualEntryDialog.show(MainActivity.this, settings, adapter); ManualEntryDialog.show(MainActivity.this, settings, adapter);
return false; return false;
case R.id.fabScanQRFromImage:
openFileWithPermissions(Constants.INTENT_MAIN_QR_OPEN_IMAGE);
return false;
default: default:
return false; return false;
} }
@ -280,17 +291,35 @@ public class MainActivity extends BaseActivity
setupDrawer(); setupDrawer();
Intent callingIntent = getIntent(); if (savedInstanceState != null){
if (callingIntent != null && callingIntent.getAction() != null) { setFilterString(savedInstanceState.getString("filterString", ""));
if (callingIntent.getAction().equals(INTENT_SCAN_QR)) {
scanQRCode();
} else if (callingIntent.getAction().equals(INTENT_ENTER_DETAILS)) {
ManualEntryDialog.show(MainActivity.this, settings, adapter);
} }
} }
if (savedInstanceState != null){ private void checkIntent() {
setFilterString(savedInstanceState.getString("filterString", "")); Intent callingIntent = getIntent();
if (callingIntent != null && callingIntent.getAction() != null) {
// Cache and reset the action to prevent the same intent from being evaluated multiple times
String intentAction = callingIntent.getAction();
callingIntent.setAction(null);
if (intentAction.equals(INTENT_SCAN_QR)) {
scanQRCode();
} else if (intentAction.equals(INTENT_IMPORT_QR)) {
openFileWithPermissions(Constants.INTENT_MAIN_QR_OPEN_IMAGE);
} else if (intentAction.equals(INTENT_ENTER_DETAILS)) {
ManualEntryDialog.show(MainActivity.this, settings, adapter);
} else if (intentAction.equals(Intent.ACTION_VIEW)) {
try {
Entry entry = new Entry(callingIntent.getDataString());
entry.updateOTP();
entry.setLastUsed(System.currentTimeMillis());
adapter.addEntry(entry);
Toast.makeText(this, R.string.toast_intent_creation_succeeded, Toast.LENGTH_LONG).show();
} catch (Exception e) {
Toast.makeText(this, R.string.toast_intent_creation_failed, Toast.LENGTH_LONG).show();
}
}
} }
} }
@ -325,6 +354,7 @@ public class MainActivity extends BaseActivity
} else { } else {
populateAdapter(); populateAdapter();
} }
checkIntent();
} }
if(setCountDownTimerNow()) countDownTimer.start(); if(setCountDownTimerNow()) countDownTimer.start();
@ -335,11 +365,22 @@ public class MainActivity extends BaseActivity
setFilterString(this.filterString); setFilterString(this.filterString);
} }
View cardList = findViewById(R.id.cardList);
if(cardList.getVisibility() == View.INVISIBLE)
cardList.setVisibility(View.VISIBLE);
startUpdater(); startUpdater();
} }
@Override @Override
public void onPause() { public void onPause() {
if(settings.getAuthMethod() == AuthMethod.DEVICE)
runOnUiThread(new Runnable() {
@Override
public void run() {
findViewById(R.id.cardList).setVisibility(View.INVISIBLE);
}
});
super.onPause(); super.onPause();
stopUpdater(); stopUpdater();
countDownTimer.cancel(); countDownTimer.cancel();
@ -357,11 +398,15 @@ public class MainActivity extends BaseActivity
key.equals(getString(R.string.settings_key_split_group_size)) || key.equals(getString(R.string.settings_key_split_group_size)) ||
key.equals(getString(R.string.settings_key_thumbnail_size))) { key.equals(getString(R.string.settings_key_thumbnail_size))) {
adapter.notifyDataSetChanged(); adapter.notifyDataSetChanged();
} else if (key.equals(getString(R.string.settings_key_search_includes))) {
adapter.clearFilter();
} else if (key.equals(getString(R.string.settings_key_tap_to_reveal)) || } else if (key.equals(getString(R.string.settings_key_tap_to_reveal)) ||
key.equals(getString(R.string.settings_key_theme)) || key.equals(getString(R.string.settings_key_theme)) ||
key.equals(getString(R.string.settings_key_locale)) || key.equals(getString(R.string.settings_key_locale)) ||
key.equals(getString(R.string.settings_key_enable_screenshot)) || key.equals(getString(R.string.settings_key_enable_screenshot)) ||
key.equals(getString(R.string.settings_key_tag_functionality)) ) { key.equals(getString(R.string.settings_key_tag_functionality)) ||
key.equals(getString(R.string.settings_key_label_highlight_token)) ||
key.equals(getString(R.string.settings_key_card_layout))) {
recreate(); recreate();
} }
} }
@ -380,16 +425,7 @@ public class MainActivity extends BaseActivity
IntentResult result = IntentIntegrator.parseActivityResult(requestCode, resultCode, intent); IntentResult result = IntentIntegrator.parseActivityResult(requestCode, resultCode, intent);
if(result != null) { if(result != null) {
if(result.getContents() != null) { if(result.getContents() != null) {
try { addQRCode(result.getContents());
Entry e = new Entry(result.getContents());
e.updateOTP();
e.setLastUsed(System.currentTimeMillis());
adapter.addEntry(e);
adapter.saveEntries();
refreshTags();
} catch (Exception e) {
Toast.makeText(this, R.string.toast_invalid_qr_code, Toast.LENGTH_LONG).show();
}
} }
} else if (requestCode == Constants.INTENT_MAIN_BACKUP && resultCode == RESULT_OK) { } else if (requestCode == Constants.INTENT_MAIN_BACKUP && resultCode == RESULT_OK) {
if (intent.getBooleanExtra("reload", false)) { if (intent.getBooleanExtra("reload", false)) {
@ -421,6 +457,10 @@ public class MainActivity extends BaseActivity
updateEncryption(authKey); updateEncryption(authKey);
} }
} else if (requestCode == Constants.INTENT_MAIN_QR_OPEN_IMAGE && resultCode == RESULT_OK) {
if (intent != null) {
addQRCode(ScanQRCodeFromFile.scanQRImage(this, intent.getData()));
}
} }
} }
@ -742,4 +782,46 @@ public class MainActivity extends BaseActivity
}; };
return true; return true;
} }
private void openFileWithPermissions(int intentId){
if (ContextCompat.checkSelfPermission(this, Manifest.permission.READ_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED) {
showOpenFileSelector(intentId);
} else {
ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.READ_EXTERNAL_STORAGE}, Constants.PERMISSIONS_MAIN_QR_READ_IMAGE);
}
}
private void showOpenFileSelector(int intentId){
Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT);
intent.addCategory(Intent.CATEGORY_OPENABLE);
intent.setType("image/*");
startActivityForResult(intent, intentId);
}
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
if (requestCode == Constants.PERMISSIONS_MAIN_QR_READ_IMAGE) {
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
showOpenFileSelector(Constants.INTENT_MAIN_QR_OPEN_IMAGE);
} else {
Toast.makeText(this, R.string.backup_toast_storage_permissions, Toast.LENGTH_LONG).show();
}
} else {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
}
}
private void addQRCode(String result){
if(!TextUtils.isEmpty(result)) {
try {
Entry e = new Entry(result);
e.updateOTP();
e.setLastUsed(System.currentTimeMillis());
adapter.addEntry(e);
refreshTags();
} catch (Exception e) {
Toast.makeText(this, R.string.toast_invalid_qr_code, Toast.LENGTH_LONG).show();
}
}
}
} }

View file

@ -35,7 +35,7 @@ import android.preference.Preference;
import android.preference.PreferenceCategory; import android.preference.PreferenceCategory;
import android.preference.PreferenceFragment; import android.preference.PreferenceFragment;
import android.preference.PreferenceManager; import android.preference.PreferenceManager;
import android.support.v7.widget.Toolbar; import androidx.appcompat.widget.Toolbar;
import android.view.ViewStub; import android.view.ViewStub;
import android.widget.Toast; import android.widget.Toast;
@ -44,6 +44,7 @@ import org.openintents.openpgp.util.OpenPgpKeyPreference;
import org.shadowice.flocke.andotp.Database.Entry; import org.shadowice.flocke.andotp.Database.Entry;
import org.shadowice.flocke.andotp.Preferences.CredentialsPreference; import org.shadowice.flocke.andotp.Preferences.CredentialsPreference;
import org.shadowice.flocke.andotp.R; import org.shadowice.flocke.andotp.R;
import org.shadowice.flocke.andotp.Utilities.BackupHelper;
import org.shadowice.flocke.andotp.Utilities.Constants; import org.shadowice.flocke.andotp.Utilities.Constants;
import org.shadowice.flocke.andotp.Utilities.DatabaseHelper; import org.shadowice.flocke.andotp.Utilities.DatabaseHelper;
import org.shadowice.flocke.andotp.Utilities.EncryptionHelper; import org.shadowice.flocke.andotp.Utilities.EncryptionHelper;
@ -52,6 +53,7 @@ import org.shadowice.flocke.andotp.Utilities.Settings;
import org.shadowice.flocke.andotp.Utilities.UIHelper; import org.shadowice.flocke.andotp.Utilities.UIHelper;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Locale;
import javax.crypto.SecretKey; import javax.crypto.SecretKey;
@ -143,6 +145,12 @@ public class SettingsActivity extends BaseActivity
fragment.useAndroidSync.setEnabled(true); fragment.useAndroidSync.setEnabled(true);
} }
} }
if (fragment.useAutoBackup != null) {
fragment.useAutoBackup.setEnabled(BackupHelper.autoBackupType(this) == Constants.BackupType.ENCRYPTED);
if (!fragment.useAutoBackup.isEnabled())
fragment.useAutoBackup.setValue(Constants.AutoBackup.OFF.toString().toLowerCase(Locale.ENGLISH));
}
} }
private void generateNewEncryptionKey() { private void generateNewEncryptionKey() {
@ -236,6 +244,7 @@ public class SettingsActivity extends BaseActivity
Settings settings; Settings settings;
ListPreference encryption; ListPreference encryption;
ListPreference useAutoBackup;
CheckBoxPreference useAndroidSync; CheckBoxPreference useAndroidSync;
OpenPgpAppPreference pgpProvider; OpenPgpAppPreference pgpProvider;
@ -344,6 +353,11 @@ public class SettingsActivity extends BaseActivity
} }
}); });
useAutoBackup = (ListPreference)findPreference(getString(R.string.settings_key_auto_backup_password_enc));
useAutoBackup.setEnabled(BackupHelper.autoBackupType(getActivity()) == Constants.BackupType.ENCRYPTED);
if(!useAutoBackup.isEnabled())
useAutoBackup.setValue(Constants.AutoBackup.OFF.toString().toLowerCase(Locale.ENGLISH));
useAndroidSync = (CheckBoxPreference) findPreference(getString(R.string.settings_key_enable_android_backup_service)); useAndroidSync = (CheckBoxPreference) findPreference(getString(R.string.settings_key_enable_android_backup_service));
useAndroidSync.setEnabled(settings.getEncryption() == EncryptionType.PASSWORD); useAndroidSync.setEnabled(settings.getEncryption() == EncryptionType.PASSWORD);
if(!useAndroidSync.isEnabled()) if(!useAndroidSync.isEnabled())

View file

@ -24,10 +24,13 @@ package org.shadowice.flocke.andotp.Activities;
import android.content.res.Configuration; import android.content.res.Configuration;
import android.content.res.Resources; import android.content.res.Resources;
import android.os.Build;
import android.os.Bundle; import android.os.Bundle;
import android.support.v7.app.AppCompatActivity; import androidx.appcompat.app.AppCompatActivity;
import org.shadowice.flocke.andotp.R;
import org.shadowice.flocke.andotp.Utilities.Settings; import org.shadowice.flocke.andotp.Utilities.Settings;
import org.shadowice.flocke.andotp.Utilities.Tools;
import java.util.Locale; import java.util.Locale;
@ -41,6 +44,11 @@ public abstract class ThemedActivity extends AppCompatActivity {
setTheme(settings.getTheme()); setTheme(settings.getTheme());
setLocale(); setLocale();
//Set navigation bar color
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
getWindow().setNavigationBarColor(Tools.getThemeColor(this,R.attr.navigationBarColor));
}
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
} }

View file

@ -50,6 +50,7 @@ public class Entry {
private static final int DEFAULT_PERIOD = 30; private static final int DEFAULT_PERIOD = 30;
private static final String JSON_SECRET = "secret"; private static final String JSON_SECRET = "secret";
private static final String JSON_ISSUER = "issuer";
private static final String JSON_LABEL = "label"; private static final String JSON_LABEL = "label";
private static final String JSON_PERIOD = "period"; private static final String JSON_PERIOD = "period";
private static final String JSON_COUNTER = "counter"; private static final String JSON_COUNTER = "counter";
@ -66,6 +67,7 @@ public class Entry {
private TokenCalculator.HashAlgorithm algorithm = TokenCalculator.DEFAULT_ALGORITHM; private TokenCalculator.HashAlgorithm algorithm = TokenCalculator.DEFAULT_ALGORITHM;
private byte[] secret; private byte[] secret;
private long counter; private long counter;
private String issuer;
private String label; private String label;
private String currentOTP; private String currentOTP;
private boolean visible = false; private boolean visible = false;
@ -74,27 +76,35 @@ public class Entry {
private long last_used = 0; private long last_used = 0;
public List<String> tags = new ArrayList<>(); public List<String> tags = new ArrayList<>();
private EntryThumbnail.EntryThumbnails thumbnail = EntryThumbnail.EntryThumbnails.Default; private EntryThumbnail.EntryThumbnails thumbnail = EntryThumbnail.EntryThumbnails.Default;
private static final int COLOR_DEFAULT = 0;
public static final int COLOR_RED = 1;
private static final int EXPIRY_TIME = 8;
private int color = COLOR_DEFAULT;
public Entry(){} public Entry(){}
public Entry(OTPType type, String secret, int period, int digits, String label, TokenCalculator.HashAlgorithm algorithm, List<String> tags) { public Entry(OTPType type, String secret, int period, int digits, String issuer, String label, TokenCalculator.HashAlgorithm algorithm, List<String> tags) {
this.type = type; this.type = type;
this.secret = new Base32().decode(secret.toUpperCase()); this.secret = new Base32().decode(secret.toUpperCase());
this.period = period; this.period = period;
this.digits = digits; this.digits = digits;
this.issuer = issuer;
this.label = label; this.label = label;
this.algorithm = algorithm; this.algorithm = algorithm;
this.tags = tags; this.tags = tags;
setThumbnailFromIssuer(issuer);
} }
public Entry(OTPType type, String secret, long counter, int digits, String label, TokenCalculator.HashAlgorithm algorithm, List<String> tags) { public Entry(OTPType type, String secret, long counter, int digits, String issuer, String label, TokenCalculator.HashAlgorithm algorithm, List<String> tags) {
this.type = type; this.type = type;
this.secret = new Base32().decode(secret.toUpperCase()); this.secret = new Base32().decode(secret.toUpperCase());
this.counter = counter; this.counter = counter;
this.digits = digits; this.digits = digits;
this.issuer = issuer;
this.label = label; this.label = label;
this.algorithm = algorithm; this.algorithm = algorithm;
this.tags = tags; this.tags = tags;
setThumbnailFromIssuer(issuer);
} }
public Entry(String contents) throws Exception { public Entry(String contents) throws Exception {
@ -124,10 +134,6 @@ public class Entry {
String algorithm = uri.getQueryParameter("algorithm"); String algorithm = uri.getQueryParameter("algorithm");
List<String> tags = uri.getQueryParameters("tags"); List<String> tags = uri.getQueryParameters("tags");
if (issuer != null){
label = issuer +" - "+label;
}
if (type == OTPType.HOTP) { if (type == OTPType.HOTP) {
if (counter != null) { if (counter != null) {
this.counter = Long.parseLong(counter); this.counter = Long.parseLong(counter);
@ -142,6 +148,7 @@ public class Entry {
} }
} }
this.issuer = issuer;
this.label = label; this.label = label;
this.secret = new Base32().decode(secret.toUpperCase()); this.secret = new Base32().decode(secret.toUpperCase());
@ -157,11 +164,15 @@ public class Entry {
this.algorithm = TokenCalculator.DEFAULT_ALGORITHM; this.algorithm = TokenCalculator.DEFAULT_ALGORITHM;
} }
if(tags != null) { if (tags != null) {
this.tags = tags; this.tags = tags;
} else { } else {
this.tags = new ArrayList<>(); this.tags = new ArrayList<>();
} }
if (issuer != null) {
setThumbnailFromIssuer(issuer);
}
} }
public Entry (JSONObject jsonObj) public Entry (JSONObject jsonObj)
@ -169,6 +180,13 @@ public class Entry {
this.secret = new Base32().decode(jsonObj.getString(JSON_SECRET).toUpperCase()); this.secret = new Base32().decode(jsonObj.getString(JSON_SECRET).toUpperCase());
this.label = jsonObj.getString(JSON_LABEL); this.label = jsonObj.getString(JSON_LABEL);
try {
this.issuer = jsonObj.getString(JSON_ISSUER);
} catch (JSONException e) {
// Older backup version did not save issuer and label separately
this.issuer = "";
}
try { try {
this.type = OTPType.valueOf(jsonObj.getString(JSON_TYPE)); this.type = OTPType.valueOf(jsonObj.getString(JSON_TYPE));
} catch(Exception e) { } catch(Exception e) {
@ -227,6 +245,7 @@ public class Entry {
public JSONObject toJSON() throws JSONException { public JSONObject toJSON() throws JSONException {
JSONObject jsonObj = new JSONObject(); JSONObject jsonObj = new JSONObject();
jsonObj.put(JSON_SECRET, new String(new Base32().encode(getSecret()))); jsonObj.put(JSON_SECRET, new String(new Base32().encode(getSecret())));
jsonObj.put(JSON_ISSUER, getIssuer());
jsonObj.put(JSON_LABEL, getLabel()); jsonObj.put(JSON_LABEL, getLabel());
jsonObj.put(JSON_DIGITS, getDigits()); jsonObj.put(JSON_DIGITS, getDigits());
jsonObj.put(JSON_TYPE, getType().toString()); jsonObj.put(JSON_TYPE, getType().toString());
@ -252,6 +271,8 @@ public class Entry {
return type == OTPType.TOTP || type == OTPType.STEAM; return type == OTPType.TOTP || type == OTPType.STEAM;
} }
public boolean isCounterBased() { return type == OTPType.HOTP; }
public OTPType getType() { public OTPType getType() {
return type; return type;
} }
@ -268,6 +289,14 @@ public class Entry {
this.secret = secret; this.secret = secret;
} }
public String getIssuer() {
return issuer;
}
public void setIssuer(String issuer) {
this.issuer = issuer;
}
public String getLabel() { public String getLabel() {
return label; return label;
} }
@ -360,7 +389,8 @@ public class Entry {
currentOTP = TokenCalculator.TOTP_Steam(secret, period, digits, algorithm); currentOTP = TokenCalculator.TOTP_Steam(secret, period, digits, algorithm);
last_update = counter; last_update = counter;
//New OTP. Change color to default color
setColor(COLOR_DEFAULT);
return true; return true;
} else { } else {
return false; return false;
@ -373,6 +403,33 @@ public class Entry {
} }
} }
/**
* Checks if the OTP is expiring. The color for the entry will be changed to red if the expiry time is less than or equal to 8 seconds
* COLOR_DEFAULT indicates that the OTP has not expired. In this case check if the OTP is about to expire. Update color to COLOR_RED if it's about to expire
* COLOR_RED indicates that the OTP is already about to expire. Don't check again.
* The color will be reset to COLOR_DEFAULT in {@link #updateOTP()} method
*
* @return Return true only if the color has changed to red to save from unnecessary notifying dataset
* */
public boolean hasColorChanged() {
if(color == COLOR_DEFAULT){
long time = System.currentTimeMillis() / 1000;
if ((time % getPeriod()) > (getPeriod() - EXPIRY_TIME)) {
setColor(COLOR_RED);
return true;
}
}
return false;
}
private void setThumbnailFromIssuer(String issuer) {
try {
this.thumbnail = EntryThumbnail.EntryThumbnails.valueOfIgnoreCase(issuer);
} catch(Exception e) {
this.thumbnail = EntryThumbnail.EntryThumbnails.Default;
}
}
@Override @Override
public boolean equals(Object o) { public boolean equals(Object o) {
if (this == o) return true; if (this == o) return true;
@ -391,4 +448,12 @@ public class Entry {
public int hashCode() { public int hashCode() {
return Objects.hash(type, period, counter, digits, algorithm, secret, label); return Objects.hash(type, period, counter, digits, algorithm, secret, label);
} }
public void setColor(int color) {
this.color = color;
}
public int getColor() {
return color;
}
} }

View file

@ -20,11 +20,11 @@
* SOFTWARE. * SOFTWARE.
*/ */
package org.shadowice.flocke.andotp.View; package org.shadowice.flocke.andotp.Dialogs;
import android.app.AlertDialog; import android.app.AlertDialog;
import android.content.DialogInterface; import android.content.DialogInterface;
import android.support.v7.app.AppCompatDelegate; import androidx.appcompat.app.AppCompatDelegate;
import android.text.Editable; import android.text.Editable;
import android.text.TextUtils; import android.text.TextUtils;
import android.text.TextWatcher; import android.text.TextWatcher;
@ -45,6 +45,8 @@ import org.shadowice.flocke.andotp.Database.Entry;
import org.shadowice.flocke.andotp.R; import org.shadowice.flocke.andotp.R;
import org.shadowice.flocke.andotp.Utilities.Settings; import org.shadowice.flocke.andotp.Utilities.Settings;
import org.shadowice.flocke.andotp.Utilities.TokenCalculator; import org.shadowice.flocke.andotp.Utilities.TokenCalculator;
import org.shadowice.flocke.andotp.View.EntriesCardAdapter;
import org.shadowice.flocke.andotp.View.TagsAdapter;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
@ -58,7 +60,11 @@ public class ManualEntryDialog {
ViewGroup container = callingActivity.findViewById(R.id.main_content); ViewGroup container = callingActivity.findViewById(R.id.main_content);
View inputView = callingActivity.getLayoutInflater().inflate(R.layout.dialog_manual_entry, container, false); View inputView = callingActivity.getLayoutInflater().inflate(R.layout.dialog_manual_entry, container, false);
if (settings.getBlockAccessibility())
inputView.setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS);
final Spinner typeInput = inputView.findViewById(R.id.manual_type); final Spinner typeInput = inputView.findViewById(R.id.manual_type);
final EditText issuerInput = inputView.findViewById(R.id.manual_issuer);
final EditText labelInput = inputView.findViewById(R.id.manual_label); final EditText labelInput = inputView.findViewById(R.id.manual_label);
final EditText secretInput = inputView.findViewById(R.id.manual_secret); final EditText secretInput = inputView.findViewById(R.id.manual_secret);
final EditText counterInput = inputView.findViewById(R.id.manual_counter); final EditText counterInput = inputView.findViewById(R.id.manual_counter);
@ -192,28 +198,28 @@ public class ManualEntryDialog {
Entry.OTPType type = (Entry.OTPType) typeInput.getSelectedItem(); Entry.OTPType type = (Entry.OTPType) typeInput.getSelectedItem();
TokenCalculator.HashAlgorithm algorithm = (TokenCalculator.HashAlgorithm) algorithmInput.getSelectedItem(); TokenCalculator.HashAlgorithm algorithm = (TokenCalculator.HashAlgorithm) algorithmInput.getSelectedItem();
String issuer = issuerInput.getText().toString();
String label = labelInput.getText().toString(); String label = labelInput.getText().toString();
String secret = secretInput.getText().toString(); //Replace spaces with empty characters
String secret = secretInput.getText().toString().replaceAll("\\s+","");
int digits = Integer.parseInt(digitsInput.getText().toString()); int digits = Integer.parseInt(digitsInput.getText().toString());
if (type == Entry.OTPType.TOTP || type == Entry.OTPType.STEAM) { if (type == Entry.OTPType.TOTP || type == Entry.OTPType.STEAM) {
int period = Integer.parseInt(periodInput.getText().toString()); int period = Integer.parseInt(periodInput.getText().toString());
Entry e = new Entry(type, secret, period, digits, label, algorithm, tagsAdapter.getActiveTags()); Entry e = new Entry(type, secret, period, digits, issuer, label, algorithm, tagsAdapter.getActiveTags());
e.updateOTP(); e.updateOTP();
e.setLastUsed(System.currentTimeMillis()); e.setLastUsed(System.currentTimeMillis());
adapter.addEntry(e); adapter.addEntry(e);
adapter.saveEntries();
callingActivity.refreshTags(); callingActivity.refreshTags();
} else if (type == Entry.OTPType.HOTP) { } else if (type == Entry.OTPType.HOTP) {
long counter = Long.parseLong(counterInput.getText().toString()); long counter = Long.parseLong(counterInput.getText().toString());
Entry e = new Entry(type, secret, counter, digits, label, algorithm, tagsAdapter.getActiveTags()); Entry e = new Entry(type, secret, counter, digits, issuer, label, algorithm, tagsAdapter.getActiveTags());
e.updateOTP(); e.updateOTP();
e.setLastUsed(System.currentTimeMillis()); e.setLastUsed(System.currentTimeMillis());
adapter.addEntry(e); adapter.addEntry(e);
adapter.saveEntries();
} }
} }
}) })

View file

@ -1,8 +1,10 @@
package org.shadowice.flocke.andotp.Dialogs; package org.shadowice.flocke.andotp.Dialogs;
import android.content.Context; import android.content.Context;
import android.support.design.widget.TextInputEditText; import com.google.android.material.textfield.TextInputEditText;
import android.support.v7.app.AppCompatDialog; import com.google.android.material.textfield.TextInputLayout;
import androidx.appcompat.app.AppCompatDialog;
import android.text.Editable; import android.text.Editable;
import android.text.TextUtils; import android.text.TextUtils;
import android.text.TextWatcher; import android.text.TextWatcher;
@ -29,15 +31,21 @@ public class PasswordEntryDialog extends AppCompatDialog
private EditText passwordConfirm; private EditText passwordConfirm;
private Button okButton; private Button okButton;
public PasswordEntryDialog(Context context, Mode newMode, PasswordEnteredCallback newCallback) { public PasswordEntryDialog(Context context, Mode newMode, boolean blockAccessibility, PasswordEnteredCallback newCallback) {
super(context, Tools.getThemeResource(context, R.attr.dialogTheme)); super(context, Tools.getThemeResource(context, R.attr.dialogTheme));
setTitle(R.string.dialog_title_enter_password); setTitle(R.string.dialog_title_enter_password);
setContentView(R.layout.dialog_password_entry); setContentView(R.layout.dialog_password_entry);
TextInputLayout passwordLayout = findViewById(R.id.passwordInputLayout);
passwordInput = findViewById(R.id.passwordInput); passwordInput = findViewById(R.id.passwordInput);
passwordConfirm = findViewById(R.id.passwordConfirm); passwordConfirm = findViewById(R.id.passwordConfirm);
if (blockAccessibility) {
passwordLayout.setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS);
passwordConfirm.setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_NO);
}
okButton = findViewById(R.id.buttonOk); okButton = findViewById(R.id.buttonOk);
Button cancelButton = findViewById(R.id.buttonCancel); Button cancelButton = findViewById(R.id.buttonCancel);

View file

@ -21,7 +21,7 @@
* SOFTWARE. * SOFTWARE.
*/ */
package org.shadowice.flocke.andotp.View; package org.shadowice.flocke.andotp.Dialogs;
import android.app.AlertDialog; import android.app.AlertDialog;
import android.content.Context; import android.content.Context;
@ -35,6 +35,7 @@ import android.widget.FrameLayout;
import android.widget.ListView; import android.widget.ListView;
import org.shadowice.flocke.andotp.R; import org.shadowice.flocke.andotp.R;
import org.shadowice.flocke.andotp.View.TagsAdapter;
import java.util.HashMap; import java.util.HashMap;
import java.util.concurrent.Callable; import java.util.concurrent.Callable;

View file

@ -11,8 +11,8 @@ import android.content.pm.PackageManager;
import android.graphics.ColorFilter; import android.graphics.ColorFilter;
import android.net.Uri; import android.net.Uri;
import android.os.Bundle; import android.os.Bundle;
import android.support.annotation.NonNull; import androidx.annotation.NonNull;
import android.support.v4.app.Fragment; import androidx.fragment.app.Fragment;
import android.view.LayoutInflater; import android.view.LayoutInflater;
import android.view.View; import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
@ -25,32 +25,27 @@ import org.shadowice.flocke.andotp.R;
import org.shadowice.flocke.andotp.Utilities.Settings; import org.shadowice.flocke.andotp.Utilities.Settings;
import org.shadowice.flocke.andotp.Utilities.Tools; import org.shadowice.flocke.andotp.Utilities.Tools;
public class AboutFragment extends Fragment { public class BaseAboutFragment extends Fragment {
private static final String GITHUB_URI = "https://github.com/andOTP/andOTP"; private static final String GITHUB_URI = "https://github.com/andOTP/andOTP";
private static final String CHANGELOG_URI = GITHUB_URI + "/blob/master/CHANGELOG.md"; private static final String CHANGELOG_URI = GITHUB_URI + "/blob/master/CHANGELOG.md";
private static final String MIT_URI = GITHUB_URI + "/blob/master/LICENSE.txt"; private static final String MIT_URI = GITHUB_URI + "/blob/master/LICENSE.txt";
private static final String AUTHOR1_GITHUB = "https://github.com/flocke"; private static final String AUTHOR1_GITHUB = "https://github.com/flocke";
private static final String AUTHOR1_EXTRA = "https://flocke.shadowice.org/donate.html";
private static final String AUTHOR2_GITHUB = "https://github.com/richyhbm"; private static final String AUTHOR2_GITHUB = "https://github.com/richyhbm";
private static final String AUTHOR2_EXTRA = "https://richyhbm.co.uk/donate";
private static final String AUTHOR_ORIGINAL_GITHUB = "https://github.com/0xbb"; private static final String AUTHOR_ORIGINAL_GITHUB = "https://github.com/0xbb";
private static final String AUTHOR_ORIGINAL_EXTRA = AUTHOR_ORIGINAL_GITHUB + "/otp-authenticator"; private static final String AUTHOR_ORIGINAL_EXTRA = AUTHOR_ORIGINAL_GITHUB + "/otp-authenticator";
private static final String CONTRIBUTORS_URI = GITHUB_URI + "/blob/master/README.md#contributors"; private static final String CONTRIBUTORS_URI = GITHUB_URI + "/graphs/contributors";
private static final String TRANSLATORS_URI = GITHUB_URI + "/blob/master/README.md#translators";
private static final String BUGREPORT_URI = GITHUB_URI + "/issues"; private static final String SUPPORT_URI = GITHUB_URI + "/blob/master/README.md#contribute";
private static final String TRANSLATE_URI = "https://crowdin.com/project/andotp";
private Settings settings; private Settings settings;
static final int[] imageResources = { static final int[] imageResources = {
R.id.aboutImgVersion, R.id.aboutImgLicense, R.id.aboutImgChangelog, R.id.aboutImgSource, R.id.aboutImgVersion, R.id.aboutImgLicense, R.id.aboutImgChangelog, R.id.aboutImgSource,
R.id.aboutImgAuthor2, R.id.aboutImgAuthorOriginal, R.id.aboutImgContributors, R.id.aboutImgAuthor2, R.id.aboutImgAuthorOriginal, R.id.aboutImgContributors,
R.id.aboutImgTranslators, R.id.aboutImgBugs, R.id.aboutImgTranslate R.id.aboutImgSupport
}; };
static long lastTap = 0; static long lastTap = 0;
@ -138,43 +133,20 @@ public class AboutFragment extends Fragment {
}); });
LinearLayout author1Layout = v.findViewById(R.id.aboutLayoutAuthor1); LinearLayout author1Layout = v.findViewById(R.id.aboutLayoutAuthor1);
TextView author1Donate = v.findViewById(R.id.about_author1_extra);
author1Layout.setOnClickListener(new View.OnClickListener() { author1Layout.setOnClickListener(new View.OnClickListener() {
@Override @Override
public void onClick(View view) { public void onClick(View view) {
openURI(AUTHOR1_GITHUB); openURI(AUTHOR1_GITHUB);
} }
}); });
author1Donate.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
try {
openURI(AUTHOR1_EXTRA);
} catch(Exception ignored) {
copyToClipboard(AUTHOR1_EXTRA);
}
}
});
LinearLayout author2Layout = v.findViewById(R.id.aboutLayoutAuthor2); LinearLayout author2Layout = v.findViewById(R.id.aboutLayoutAuthor2);
TextView author2Donate = v.findViewById(R.id.about_author2_extra);
author2Layout.setOnClickListener(new View.OnClickListener() { author2Layout.setOnClickListener(new View.OnClickListener() {
@Override @Override
public void onClick(View view) { public void onClick(View view) {
openURI(AUTHOR2_GITHUB); openURI(AUTHOR2_GITHUB);
} }
}); });
author2Donate.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
try {
openURI(AUTHOR2_EXTRA);
} catch(Exception ignored) {
copyToClipboard(AUTHOR2_EXTRA);
}
}
});
LinearLayout authorOrigialLayout = v.findViewById(R.id.aboutLayoutOriginalAuthor); LinearLayout authorOrigialLayout = v.findViewById(R.id.aboutLayoutOriginalAuthor);
TextView authorOriginalApp = v.findViewById(R.id.about_author_original_extra); TextView authorOriginalApp = v.findViewById(R.id.about_author_original_extra);
@ -196,32 +168,18 @@ public class AboutFragment extends Fragment {
}); });
LinearLayout contributors = v.findViewById(R.id.about_layout_contributors); LinearLayout contributors = v.findViewById(R.id.about_layout_contributors);
LinearLayout translators = v.findViewById(R.id.about_layout_translators);
contributors.setOnClickListener(new View.OnClickListener() { contributors.setOnClickListener(new View.OnClickListener() {
@Override @Override
public void onClick(View view) { public void onClick(View view) {
openURI(CONTRIBUTORS_URI); openURI(CONTRIBUTORS_URI);
} }
}); });
translators.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
openURI(TRANSLATORS_URI);
}
});
LinearLayout bugReport = v.findViewById(R.id.about_layout_bugs); LinearLayout supportLayout = v.findViewById(R.id.about_layout_support);
LinearLayout translate = v.findViewById(R.id.about_layout_translate); supportLayout.setOnClickListener(new View.OnClickListener() {
bugReport.setOnClickListener(new View.OnClickListener() {
@Override @Override
public void onClick(View view) { public void onClick(View view) {
openURI(BUGREPORT_URI); openURI(SUPPORT_URI);
}
});
translate.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
openURI(TRANSLATE_URI);
} }
}); });
@ -259,5 +217,4 @@ public class AboutFragment extends Fragment {
clipboard.setPrimaryClip(clip); clipboard.setPrimaryClip(clip);
Toast.makeText(getActivity(), getString(R.string.about_toast_copied_to_clipboard), Toast.LENGTH_SHORT).show(); Toast.makeText(getActivity(), getString(R.string.about_toast_copied_to_clipboard), Toast.LENGTH_SHORT).show();
} }
} }

View file

@ -26,8 +26,8 @@ import android.app.AlertDialog;
import android.app.KeyguardManager; import android.app.KeyguardManager;
import android.content.Context; import android.content.Context;
import android.preference.DialogPreference; import android.preference.DialogPreference;
import android.support.design.widget.TextInputEditText; import com.google.android.material.textfield.TextInputEditText;
import android.support.design.widget.TextInputLayout; import com.google.android.material.textfield.TextInputLayout;
import android.text.Editable; import android.text.Editable;
import android.text.InputType; import android.text.InputType;
import android.text.TextWatcher; import android.text.TextWatcher;
@ -50,6 +50,7 @@ import org.shadowice.flocke.andotp.Utilities.UIHelper;
import java.util.Arrays; import java.util.Arrays;
import java.util.List; import java.util.List;
import java.util.Locale;
import static android.content.Context.KEYGUARD_SERVICE; import static android.content.Context.KEYGUARD_SERVICE;
import static org.shadowice.flocke.andotp.Utilities.Constants.AuthMethod; import static org.shadowice.flocke.andotp.Utilities.Constants.AuthMethod;
@ -126,6 +127,11 @@ public class CredentialsPreference extends DialogPreference
passwordInput = view.findViewById(R.id.passwordEdit); passwordInput = view.findViewById(R.id.passwordEdit);
passwordConfirm = view.findViewById(R.id.passwordConfirm); passwordConfirm = view.findViewById(R.id.passwordConfirm);
if (settings.getBlockAccessibility()) {
passwordLayout.setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS);
passwordConfirm.setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_NO);
}
toShortWarning = view.findViewById(R.id.toShortWarning); toShortWarning = view.findViewById(R.id.toShortWarning);
passwordInput.addTextChangedListener(this); passwordInput.addTextChangedListener(this);
@ -145,11 +151,11 @@ public class CredentialsPreference extends DialogPreference
@Override @Override
protected void onSetInitialValue(boolean restorePersistedValue, Object defaultValue) { protected void onSetInitialValue(boolean restorePersistedValue, Object defaultValue) {
if (restorePersistedValue) { if (restorePersistedValue) {
String stringValue = getPersistedString(DEFAULT_VALUE.name().toLowerCase()); String stringValue = getPersistedString(DEFAULT_VALUE.name().toLowerCase(Locale.ENGLISH));
value = AuthMethod.valueOf(stringValue.toUpperCase()); value = AuthMethod.valueOf(stringValue.toUpperCase(Locale.ENGLISH));
} else { } else {
value = DEFAULT_VALUE; value = DEFAULT_VALUE;
persistString(value.name().toLowerCase()); persistString(value.name().toLowerCase(Locale.ENGLISH));
} }
setSummary(entries.get(entryValues.indexOf(value))); setSummary(entries.get(entryValues.indexOf(value)));

View file

@ -26,8 +26,8 @@ import android.app.AlertDialog;
import android.content.Context; import android.content.Context;
import android.content.res.TypedArray; import android.content.res.TypedArray;
import android.preference.DialogPreference; import android.preference.DialogPreference;
import android.support.design.widget.TextInputEditText; import com.google.android.material.textfield.TextInputEditText;
import android.support.design.widget.TextInputLayout; import com.google.android.material.textfield.TextInputLayout;
import android.text.Editable; import android.text.Editable;
import android.text.InputType; import android.text.InputType;
import android.text.TextWatcher; import android.text.TextWatcher;
@ -42,6 +42,7 @@ import org.shadowice.flocke.andotp.R;
import org.shadowice.flocke.andotp.Utilities.Constants; import org.shadowice.flocke.andotp.Utilities.Constants;
import org.shadowice.flocke.andotp.Utilities.EncryptionHelper; import org.shadowice.flocke.andotp.Utilities.EncryptionHelper;
import org.shadowice.flocke.andotp.Utilities.KeyStoreHelper; import org.shadowice.flocke.andotp.Utilities.KeyStoreHelper;
import org.shadowice.flocke.andotp.Utilities.Settings;
import java.nio.charset.StandardCharsets; import java.nio.charset.StandardCharsets;
import java.security.KeyPair; import java.security.KeyPair;
@ -92,10 +93,17 @@ public class PasswordEncryptedPreference extends DialogPreference
@Override @Override
protected void onBindDialogView(View view) { protected void onBindDialogView(View view) {
Settings settings = new Settings(getContext());
TextInputLayout passwordLayout = view.findViewById(R.id.passwordLayout); TextInputLayout passwordLayout = view.findViewById(R.id.passwordLayout);
passwordInput = view.findViewById(R.id.passwordEdit); passwordInput = view.findViewById(R.id.passwordEdit);
passwordConfirm = view.findViewById(R.id.passwordConfirm); passwordConfirm = view.findViewById(R.id.passwordConfirm);
if (settings.getBlockAccessibility()) {
passwordLayout.setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS);
passwordConfirm.setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_NO);
}
Button btnCancel = view.findViewById(R.id.btnCancel); Button btnCancel = view.findViewById(R.id.btnCancel);
btnSave = view.findViewById(R.id.btnSave); btnSave = view.findViewById(R.id.btnSave);
btnSave.setEnabled(false); btnSave.setEnabled(false);

View file

@ -27,7 +27,7 @@ import android.Manifest;
import android.content.BroadcastReceiver; import android.content.BroadcastReceiver;
import android.content.Context; import android.content.Context;
import android.content.pm.PackageManager; import android.content.pm.PackageManager;
import android.support.v4.content.ContextCompat; import androidx.core.content.ContextCompat;
import org.shadowice.flocke.andotp.R; import org.shadowice.flocke.andotp.R;
import org.shadowice.flocke.andotp.Utilities.Constants; import org.shadowice.flocke.andotp.Utilities.Constants;

View file

@ -1,6 +1,18 @@
package org.shadowice.flocke.andotp.Utilities; package org.shadowice.flocke.andotp.Utilities;
import android.Manifest;
import android.content.Context; import android.content.Context;
import android.content.pm.PackageManager;
import android.net.Uri;
import androidx.core.content.ContextCompat;
import org.shadowice.flocke.andotp.Database.Entry;
import java.nio.ByteBuffer;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import javax.crypto.SecretKey;
public class BackupHelper { public class BackupHelper {
public static String backupFilename(Context context, Constants.BackupType type) { public static String backupFilename(Context context, Constants.BackupType type) {
@ -28,4 +40,53 @@ public class BackupHelper {
return Constants.BACKUP_FILENAME_PLAIN; return Constants.BACKUP_FILENAME_PLAIN;
} }
public static Constants.BackupType autoBackupType(Context context) {
Settings settings = new Settings(context);
if(ContextCompat.checkSelfPermission(context, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
return Constants.BackupType.UNAVAILABLE;
}
if(settings.getBackupAsk()) {
return Constants.BackupType.UNAVAILABLE;
}
if(!Tools.mkdir(settings.getBackupDir())) {
return Constants.BackupType.UNAVAILABLE;
}
if (!settings.getBackupPasswordEnc().isEmpty()) {
return Constants.BackupType.ENCRYPTED;
}
return Constants.BackupType.UNAVAILABLE;
}
public static boolean backupToFile(Context context, Uri uri, String password, SecretKey encryptionKey)
{
ArrayList<Entry> entries = DatabaseHelper.loadDatabase(context, encryptionKey);
String plain = DatabaseHelper.entriesToString(entries);
try {
int iter = EncryptionHelper.generateRandomIterations();
byte[] salt = EncryptionHelper.generateRandom(Constants.ENCRYPTION_IV_LENGTH);
SecretKey key = EncryptionHelper.generateSymmetricKeyPBKDF2(password, iter, salt);
byte[] encrypted = EncryptionHelper.encrypt(key, plain.getBytes(StandardCharsets.UTF_8));
byte[] iterBytes = ByteBuffer.allocate(Constants.INT_LENGTH).putInt(iter).array();
byte[] data = new byte[Constants.INT_LENGTH + Constants.ENCRYPTION_IV_LENGTH + encrypted.length];
System.arraycopy(iterBytes, 0, data, 0, Constants.INT_LENGTH);
System.arraycopy(salt, 0, data, Constants.INT_LENGTH, Constants.ENCRYPTION_IV_LENGTH);
System.arraycopy(encrypted, 0, data, Constants.INT_LENGTH + Constants.ENCRYPTION_IV_LENGTH, encrypted.length);
StorageAccessHelper.saveFile(context, uri, data);
} catch (Exception e) {
e.printStackTrace();
return false;
}
return true;
}
} }

View file

@ -41,7 +41,7 @@ public class Constants {
} }
public enum BackupType { public enum BackupType {
PLAIN_TEXT, ENCRYPTED, OPEN_PGP PLAIN_TEXT, ENCRYPTED, OPEN_PGP, UNAVAILABLE
} }
public enum TagFunctionality { public enum TagFunctionality {
@ -52,11 +52,24 @@ public class Constants {
BACKUP_FAILED, BACKUP_SUCCESS BACKUP_FAILED, BACKUP_SUCCESS
} }
public enum SearchIncludes {
LABEL, ISSUER, TAGS
}
public enum CardLayouts {
DEFAULT, FULL
}
public enum AutoBackup {
OFF, NEW_ENTRIES, ALL_EDITS
}
// Intents (Format: A0x with A = parent Activity, x = number of the intent) // Intents (Format: A0x with A = parent Activity, x = number of the intent)
public final static int INTENT_MAIN_AUTHENTICATE = 100; public final static int INTENT_MAIN_AUTHENTICATE = 100;
public final static int INTENT_MAIN_SETTINGS = 101; public final static int INTENT_MAIN_SETTINGS = 101;
public final static int INTENT_MAIN_BACKUP = 102; public final static int INTENT_MAIN_BACKUP = 102;
public final static int INTENT_MAIN_INTRO = 103; public final static int INTENT_MAIN_INTRO = 103;
public final static int INTENT_MAIN_QR_OPEN_IMAGE = 104;
public final static int INTENT_BACKUP_OPEN_DOCUMENT_PLAIN = 200; public final static int INTENT_BACKUP_OPEN_DOCUMENT_PLAIN = 200;
public final static int INTENT_BACKUP_SAVE_DOCUMENT_PLAIN = 201; public final static int INTENT_BACKUP_SAVE_DOCUMENT_PLAIN = 201;
@ -71,6 +84,7 @@ public class Constants {
public static final int INTENT_SETTINGS_AUTHENTICATE = 300; public static final int INTENT_SETTINGS_AUTHENTICATE = 300;
// Permission requests (Format: A1x with A = parent Activity, x = number of the request) // Permission requests (Format: A1x with A = parent Activity, x = number of the request)
public final static int PERMISSIONS_MAIN_QR_READ_IMAGE = 111;
public final static int PERMISSIONS_BACKUP_READ_IMPORT_PLAIN = 210; public final static int PERMISSIONS_BACKUP_READ_IMPORT_PLAIN = 210;
public final static int PERMISSIONS_BACKUP_WRITE_EXPORT_PLAIN = 211; public final static int PERMISSIONS_BACKUP_WRITE_EXPORT_PLAIN = 211;
public final static int PERMISSIONS_BACKUP_READ_IMPORT_CRYPT = 212; public final static int PERMISSIONS_BACKUP_READ_IMPORT_CRYPT = 212;

View file

@ -28,7 +28,7 @@ import android.graphics.Bitmap;
import android.graphics.BitmapFactory; import android.graphics.BitmapFactory;
import android.graphics.Canvas; import android.graphics.Canvas;
import android.graphics.drawable.Drawable; import android.graphics.drawable.Drawable;
import android.support.v7.app.AppCompatDelegate; import androidx.appcompat.app.AppCompatDelegate;
import org.shadowice.flocke.andotp.R; import org.shadowice.flocke.andotp.R;
@ -40,6 +40,7 @@ public class EntryThumbnail {
public enum EntryThumbnails { public enum EntryThumbnails {
Default(R.mipmap.ic_launcher_round), Default(R.mipmap.ic_launcher_round),
OneAndOne(R.drawable.thumb_1and1),
OnePassword(R.drawable.thumb_1password), OnePassword(R.drawable.thumb_1password),
Adobe(R.drawable.thumb_adobe), Adobe(R.drawable.thumb_adobe),
AdGuard(R.drawable.thumb_adguard), AdGuard(R.drawable.thumb_adguard),
@ -61,6 +62,7 @@ public class EntryThumbnail {
BitBucket(R.drawable.thumb_bitbucket), BitBucket(R.drawable.thumb_bitbucket),
Bitcoin(R.drawable.thumb_bitcoin), Bitcoin(R.drawable.thumb_bitcoin),
Bitfinex(R.drawable.thumb_bitfinex), Bitfinex(R.drawable.thumb_bitfinex),
Bitmex(R.drawable.thumb_bitmex),
Bitstamp(R.mipmap.thumb_bitstamp, AssetType.Bitmap), Bitstamp(R.mipmap.thumb_bitstamp, AssetType.Bitmap),
Bitpanda(R.drawable.thumb_bitpanda), Bitpanda(R.drawable.thumb_bitpanda),
Bittrex(R.drawable.thumb_bittrex), Bittrex(R.drawable.thumb_bittrex),
@ -86,6 +88,7 @@ public class EntryThumbnail {
Discord(R.drawable.thumb_discord), Discord(R.drawable.thumb_discord),
Discourse(R.drawable.thumb_discourse), Discourse(R.drawable.thumb_discourse),
Disroot(R.drawable.thumb_disroot), Disroot(R.drawable.thumb_disroot),
Docker(R.drawable.thumb_docker),
DocuSign(R.drawable.thumb_docusign), DocuSign(R.drawable.thumb_docusign),
Dropbox(R.drawable.thumb_dropbox), Dropbox(R.drawable.thumb_dropbox),
ElectronicArts(R.drawable.thumb_electronic_arts), ElectronicArts(R.drawable.thumb_electronic_arts),
@ -95,6 +98,7 @@ public class EntryThumbnail {
Facebook(R.drawable.thumb_facebook), Facebook(R.drawable.thumb_facebook),
FACEIT(R.drawable.thumb_faceit), FACEIT(R.drawable.thumb_faceit),
Fingerprint(R.drawable.thumb_fingerprint), Fingerprint(R.drawable.thumb_fingerprint),
Finnair(R.drawable.thumb_finnair),
Firefox(R.drawable.thumb_firefox), Firefox(R.drawable.thumb_firefox),
Flight(R.drawable.thumb_flight_takeoff), Flight(R.drawable.thumb_flight_takeoff),
Floatplane(R.drawable.thumb_floatplane), Floatplane(R.drawable.thumb_floatplane),
@ -116,6 +120,7 @@ public class EntryThumbnail {
HomeAssistant(R.drawable.thumb_home_assistant), HomeAssistant(R.drawable.thumb_home_assistant),
HumbleBundle(R.drawable.thumb_humblebundle), HumbleBundle(R.drawable.thumb_humblebundle),
HurricaneElectric(R.drawable.thumb_hurricane_electric), HurricaneElectric(R.drawable.thumb_hurricane_electric),
IBM(R.drawable.thumb_ibm),
Iconomi(R.drawable.thumb_iconomi), Iconomi(R.drawable.thumb_iconomi),
IFTTT(R.drawable.thumb_ifttt), IFTTT(R.drawable.thumb_ifttt),
Instagram(R.drawable.thumb_instagram), Instagram(R.drawable.thumb_instagram),
@ -127,6 +132,7 @@ public class EntryThumbnail {
Kraken(R.drawable.thumb_kraken), Kraken(R.drawable.thumb_kraken),
Kucoin(R.drawable.thumb_kucoin), Kucoin(R.drawable.thumb_kucoin),
LastPass(R.drawable.thumb_lastpass), LastPass(R.drawable.thumb_lastpass),
LibreNMS(R.drawable.thumb_librenms),
Lichess(R.drawable.thumb_lichess), Lichess(R.drawable.thumb_lichess),
LinkedIn(R.drawable.thumb_linkedin), LinkedIn(R.drawable.thumb_linkedin),
Linode(R.drawable.thumb_linode), Linode(R.drawable.thumb_linode),
@ -158,6 +164,7 @@ public class EntryThumbnail {
Okta(R.drawable.thumb_okta), Okta(R.drawable.thumb_okta),
OnlineNet(R.drawable.thumb_online), OnlineNet(R.drawable.thumb_online),
OpenVZ(R.drawable.thumb_openvz), OpenVZ(R.drawable.thumb_openvz),
OPNsense(R.drawable.thumb_opnsense),
Origin(R.drawable.thumb_origin), Origin(R.drawable.thumb_origin),
OVH(R.drawable.thumb_ovh), OVH(R.drawable.thumb_ovh),
Packet(R.drawable.thumb_packet), Packet(R.drawable.thumb_packet),
@ -170,6 +177,7 @@ public class EntryThumbnail {
phpMyAdmin(R.drawable.thumb_phpmyadmin), phpMyAdmin(R.drawable.thumb_phpmyadmin),
Plurk(R.drawable.thumb_plurk), Plurk(R.drawable.thumb_plurk),
Posteo(R.drawable.thumb_posteo), Posteo(R.drawable.thumb_posteo),
PrivateInternetAccess(R.drawable.thumb_private_internet_access),
ProtonMail(R.drawable.thumb_protonmail), ProtonMail(R.drawable.thumb_protonmail),
Proxmox(R.drawable.thumb_proxmox), Proxmox(R.drawable.thumb_proxmox),
PyPI(R.drawable.thumb_pypi), PyPI(R.drawable.thumb_pypi),
@ -239,14 +247,21 @@ public class EntryThumbnail {
public AssetType getAssetType() { public AssetType getAssetType() {
return assetType; return assetType;
} }
public static EntryThumbnails valueOfIgnoreCase(String thumbnail) {
for (EntryThumbnails entryThumbnails : values())
if (entryThumbnails.name().equalsIgnoreCase(thumbnail)) return entryThumbnails;
throw new IllegalArgumentException();
}
} }
public static Bitmap getThumbnailGraphic(Context context, String label, int size, EntryThumbnails thumbnail) { public static Bitmap getThumbnailGraphic(Context context, String issuer, String label, int size, EntryThumbnails thumbnail) {
AppCompatDelegate.setCompatVectorFromResourcesEnabled(true); AppCompatDelegate.setCompatVectorFromResourcesEnabled(true);
if (thumbnail == EntryThumbnails.Default && size > 0) { if (thumbnail == EntryThumbnails.Default && size > 0) {
LetterBitmap letterBitmap = new LetterBitmap(context); LetterBitmap letterBitmap = new LetterBitmap(context);
return letterBitmap.getLetterTile(label, label, size, size); String letterSrc = issuer.isEmpty() ? label : issuer;
return letterBitmap.getLetterTile(letterSrc, letterSrc, size, size);
} else if (thumbnail != EntryThumbnails.Default) { } else if (thumbnail != EntryThumbnails.Default) {
try { try {

View file

@ -27,13 +27,13 @@ import android.content.Context;
import android.content.res.Resources; import android.content.res.Resources;
import android.content.res.TypedArray; import android.content.res.TypedArray;
import android.graphics.Bitmap; import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas; import android.graphics.Canvas;
import android.graphics.Color; import android.graphics.Color;
import android.graphics.Paint; import android.graphics.Paint;
import android.graphics.Rect; import android.graphics.Rect;
import android.graphics.Typeface; import android.graphics.Typeface;
import android.text.TextPaint; import android.text.TextPaint;
import android.util.TypedValue;
import org.shadowice.flocke.andotp.R; import org.shadowice.flocke.andotp.R;
@ -76,11 +76,7 @@ class LetterBitmap {
/** /**
* The font size used to display the letter * The font size used to display the letter
*/ */
private final int mTileLetterFontSize; private final float mTileLetterFontSizeScale;
/**
* The default image to display
*/
private final Bitmap mDefaultBitmap;
/** /**
* Constructor for <code>LetterTileProvider</code> * Constructor for <code>LetterTileProvider</code>
@ -96,9 +92,10 @@ class LetterBitmap {
mPaint.setAntiAlias(true); mPaint.setAntiAlias(true);
mColors = res.obtainTypedArray(R.array.letter_tile_colors); mColors = res.obtainTypedArray(R.array.letter_tile_colors);
mTileLetterFontSize = res.getDimensionPixelSize(R.dimen.tile_letter_font_size);
mDefaultBitmap = BitmapFactory.decodeResource(res, android.R.drawable.sym_def_app_icon); TypedValue typedValue = new TypedValue();
res.getValue(R.dimen.tile_letter_font_size_scale, typedValue, true);
mTileLetterFontSizeScale = typedValue.getFloat();
} }
/** /**
@ -123,7 +120,7 @@ class LetterBitmap {
c.drawColor(pickColor(key)); c.drawColor(pickColor(key));
mFirstChar[0] = Character.toUpperCase(firstChar); mFirstChar[0] = Character.toUpperCase(firstChar);
mPaint.setTextSize(mTileLetterFontSize); mPaint.setTextSize(mTileLetterFontSizeScale * height);
mPaint.getTextBounds(mFirstChar, 0, 1, mBounds); mPaint.getTextBounds(mFirstChar, 0, 1, mBounds);
c.drawText(mFirstChar, 0, 1, width / 2, height / 2 c.drawText(mFirstChar, 0, 1, width / 2, height / 2
+ (mBounds.bottom - mBounds.top) / 2, mPaint); + (mBounds.bottom - mBounds.top) / 2, mPaint);

View file

@ -27,7 +27,7 @@ import android.app.NotificationChannel;
import android.app.NotificationManager; import android.app.NotificationManager;
import android.content.Context; import android.content.Context;
import android.os.Build; import android.os.Build;
import android.support.v4.app.NotificationCompat; import androidx.core.app.NotificationCompat;
import org.shadowice.flocke.andotp.R; import org.shadowice.flocke.andotp.R;

View file

@ -0,0 +1,65 @@
package org.shadowice.flocke.andotp.Utilities;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.net.Uri;
import android.widget.Toast;
import com.google.zxing.BinaryBitmap;
import com.google.zxing.ChecksumException;
import com.google.zxing.FormatException;
import com.google.zxing.LuminanceSource;
import com.google.zxing.MultiFormatReader;
import com.google.zxing.NotFoundException;
import com.google.zxing.RGBLuminanceSource;
import com.google.zxing.Reader;
import com.google.zxing.Result;
import com.google.zxing.common.HybridBinarizer;
import org.shadowice.flocke.andotp.R;
import java.io.IOException;
public class ScanQRCodeFromFile {
public static String scanQRImage(Context context, Uri uri) {
//Check if external storage is accessible
if (!Tools.isExternalStorageReadable()) {
Toast.makeText(context, R.string.backup_toast_storage_not_accessible, Toast.LENGTH_LONG).show();
return null;
}
//Get image in bytes
byte[] imageInBytes;
try {
imageInBytes = StorageAccessHelper.loadFile(context,uri);
} catch (IOException e) {
e.printStackTrace();
Toast.makeText(context,R.string.toast_file_load_error,Toast.LENGTH_LONG).show();
return null;
}
Bitmap bMap = BitmapFactory.decodeByteArray(imageInBytes,0,imageInBytes.length);
String contents = null;
int[] intArray = new int[bMap.getWidth()*bMap.getHeight()];
bMap.getPixels(intArray, 0, bMap.getWidth(), 0, 0, bMap.getWidth(), bMap.getHeight());
LuminanceSource source = new RGBLuminanceSource(bMap.getWidth(), bMap.getHeight(), intArray);
BinaryBitmap bitmap = new BinaryBitmap(new HybridBinarizer(source));
Reader reader = new MultiFormatReader();
//Try finding QR code
try {
Result result = reader.decode(bitmap);
contents = result.getText();
} catch (NotFoundException e) {
e.printStackTrace();
Toast.makeText(context,R.string.toast_qr_error,Toast.LENGTH_LONG).show();
} catch (ChecksumException e) {
e.printStackTrace();
Toast.makeText(context,R.string.toast_qr_checksum_exception,Toast.LENGTH_LONG).show();
} catch (FormatException e) {
e.printStackTrace();
Toast.makeText(context,R.string.toast_qr_format_error,Toast.LENGTH_LONG).show();
}
//Return QR code (if found)
return contents;
}
}

View file

@ -34,6 +34,7 @@ import java.nio.charset.StandardCharsets;
import java.security.KeyPair; import java.security.KeyPair;
import java.security.NoSuchAlgorithmException; import java.security.NoSuchAlgorithmException;
import java.security.spec.InvalidKeySpecException; import java.security.spec.InvalidKeySpecException;
import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.Collections; import java.util.Collections;
import java.util.HashSet; import java.util.HashSet;
@ -216,12 +217,12 @@ public class Settings {
} }
public AuthMethod getAuthMethod() { public AuthMethod getAuthMethod() {
String authString = getString(R.string.settings_key_auth, CredentialsPreference.DEFAULT_VALUE.name().toLowerCase()); String authString = getString(R.string.settings_key_auth, CredentialsPreference.DEFAULT_VALUE.name().toLowerCase(Locale.ENGLISH));
return AuthMethod.valueOf(authString.toUpperCase()); return AuthMethod.valueOf(authString.toUpperCase(Locale.ENGLISH));
} }
public void setAuthMethod(AuthMethod authMethod) { public void setAuthMethod(AuthMethod authMethod) {
setString(R.string.settings_key_auth, authMethod.name().toLowerCase()); setString(R.string.settings_key_auth, authMethod.name().toLowerCase(Locale.ENGLISH));
} }
public void removeAuthPasswordHash() { public void removeAuthPasswordHash() {
@ -310,6 +311,10 @@ public class Settings {
return getBoolean(R.string.settings_key_relock_screen_off, true); return getBoolean(R.string.settings_key_relock_screen_off, true);
} }
public boolean getBlockAccessibility() {
return getBoolean(R.string.settings_key_block_accessibility, false);
}
public void setLocale(String locale) { public void setLocale(String locale) {
setString(R.string.settings_key_locale, locale); setString(R.string.settings_key_locale, locale);
} }
@ -379,6 +384,23 @@ public class Settings {
setString(R.string.settings_key_sort_mode, value.toString()); setString(R.string.settings_key_sort_mode, value.toString());
} }
public List<Constants.SearchIncludes> getSearchValues() {
Set<String> stringValues = settings.getStringSet(getResString(R.string.settings_key_search_includes), new HashSet<>(Arrays.asList(context.getResources().getStringArray(R.array.settings_defaults_search_includes))));
List<Constants.SearchIncludes> values = new ArrayList<>();
for (String value : stringValues) {
values.add(Constants.SearchIncludes.valueOf(value.toUpperCase(Locale.ENGLISH)));
}
return values;
}
public Constants.CardLayouts getCardLayout() {
String stringValue = getString(R.string.settings_key_card_layout, R.string.settings_default_card_layout);
return Constants.CardLayouts.valueOf(stringValue.toUpperCase(Locale.ENGLISH));
}
public boolean getBackupAsk() { public boolean getBackupAsk() {
return getBoolean(R.string.settings_key_backup_ask, true); return getBoolean(R.string.settings_key_backup_ask, true);
} }
@ -532,4 +554,25 @@ public class Settings {
public boolean getAuthInactivity() { public boolean getAuthInactivity() {
return getBoolean(R.string.settings_key_auth_inactivity, false); return getBoolean(R.string.settings_key_auth_inactivity, false);
} }
public boolean isMinimizeAppOnCopyEnabled() {
return getBoolean(R.string.settings_key_minimize_on_copy, false);
}
private Constants.AutoBackup getAutoBackupEncryptedSetting() {
String stringValue = getString(R.string.settings_key_auto_backup_password_enc, R.string.settings_default_auto_backup_password_enc);
return Constants.AutoBackup.valueOf(stringValue.toUpperCase(Locale.ENGLISH));
}
public boolean getAutoBackupEncryptedPasswordsEnabled() {
return getAutoBackupEncryptedSetting() != Constants.AutoBackup.OFF;
}
public boolean getAutoBackupEncryptedFullEnabled() {
return getAutoBackupEncryptedSetting() == Constants.AutoBackup.ALL_EDITS;
}
public boolean isHighlightTokenOptionEnabled() {
return getBoolean(R.string.settings_key_label_highlight_token,true);
}
} }

View file

@ -27,10 +27,11 @@ import android.content.ClipData;
import android.content.ClipboardManager; import android.content.ClipboardManager;
import android.content.Context; import android.content.Context;
import android.content.DialogInterface; import android.content.DialogInterface;
import android.net.Uri;
import android.os.Handler; import android.os.Handler;
import android.support.annotation.NonNull; import androidx.annotation.NonNull;
import android.support.v7.widget.PopupMenu; import androidx.appcompat.widget.PopupMenu;
import android.support.v7.widget.RecyclerView; import androidx.recyclerview.widget.RecyclerView;
import android.text.Editable; import android.text.Editable;
import android.text.InputType; import android.text.InputType;
import android.text.TextWatcher; import android.text.TextWatcher;
@ -48,10 +49,14 @@ import android.widget.GridView;
import android.widget.LinearLayout; import android.widget.LinearLayout;
import android.widget.Toast; import android.widget.Toast;
import org.shadowice.flocke.andotp.Activities.MainActivity;
import org.shadowice.flocke.andotp.Database.Entry; import org.shadowice.flocke.andotp.Database.Entry;
import org.shadowice.flocke.andotp.Dialogs.TagsDialog;
import org.shadowice.flocke.andotp.R; import org.shadowice.flocke.andotp.R;
import org.shadowice.flocke.andotp.Utilities.BackupHelper;
import org.shadowice.flocke.andotp.Utilities.Constants; import org.shadowice.flocke.andotp.Utilities.Constants;
import org.shadowice.flocke.andotp.Utilities.DatabaseHelper; import org.shadowice.flocke.andotp.Utilities.DatabaseHelper;
import org.shadowice.flocke.andotp.Utilities.EncryptionHelper;
import org.shadowice.flocke.andotp.Utilities.EntryThumbnail; import org.shadowice.flocke.andotp.Utilities.EntryThumbnail;
import org.shadowice.flocke.andotp.Utilities.Settings; import org.shadowice.flocke.andotp.Utilities.Settings;
import org.shadowice.flocke.andotp.Utilities.Tools; import org.shadowice.flocke.andotp.Utilities.Tools;
@ -116,6 +121,7 @@ public class EntriesCardAdapter extends RecyclerView.Adapter<EntryViewHolder>
if (! entries.contains(e)) { if (! entries.contains(e)) {
entries.add(e); entries.add(e);
entriesChanged(); entriesChanged();
saveEntries(settings.getAutoBackupEncryptedPasswordsEnabled());
} else { } else {
Toast.makeText(context, R.string.toast_entry_exists, Toast.LENGTH_LONG).show(); Toast.makeText(context, R.string.toast_entry_exists, Toast.LENGTH_LONG).show();
} }
@ -131,8 +137,25 @@ public class EntriesCardAdapter extends RecyclerView.Adapter<EntryViewHolder>
notifyDataSetChanged(); notifyDataSetChanged();
} }
public void saveEntries() { public void saveEntries(boolean auto_backup) {
DatabaseHelper.saveDatabase(context, entries, encryptionKey); DatabaseHelper.saveDatabase(context, entries, encryptionKey);
if(auto_backup) {
Constants.BackupType backupType = BackupHelper.autoBackupType(context);
if (backupType == Constants.BackupType.ENCRYPTED) {
Uri backupFilename = Tools.buildUri(settings.getBackupDir(), BackupHelper.backupFilename(context, Constants.BackupType.ENCRYPTED));
byte[] keyMaterial = encryptionKey.getEncoded();
SecretKey encryptionKey = EncryptionHelper.generateSymmetricKey(keyMaterial);
boolean success = BackupHelper.backupToFile(context, backupFilename, settings.getBackupPasswordEnc(), encryptionKey);
if (success) {
Toast.makeText(context, R.string.backup_toast_export_success, Toast.LENGTH_LONG).show();
} else {
Toast.makeText(context, R.string.backup_toast_export_failed, Toast.LENGTH_LONG).show();
}
}
}
} }
public void loadEntries() { public void loadEntries() {
@ -177,7 +200,14 @@ public class EntriesCardAdapter extends RecyclerView.Adapter<EntryViewHolder>
for (Entry e : entries) { for (Entry e : entries) {
if (e.isTimeBased()) { if (e.isTimeBased()) {
boolean item_changed = e.updateOTP(); boolean item_changed = e.updateOTP();
change = change || item_changed || e.hasNonDefaultPeriod(); boolean color_changed = false;
//Check color change only if highlighting token feature is enabled
if(settings.isHighlightTokenOptionEnabled()) {
color_changed = e.hasColorChanged();
}
change = change || item_changed || e.hasNonDefaultPeriod() || color_changed;
} }
} }
@ -192,6 +222,9 @@ public class EntriesCardAdapter extends RecyclerView.Adapter<EntryViewHolder>
if (!entry.isTimeBased()) if (!entry.isTimeBased())
entry.updateOTP(); entry.updateOTP();
if(settings.isHighlightTokenOptionEnabled())
entryViewHolder.updateColor(entry.getColor());
entryViewHolder.updateValues(entry); entryViewHolder.updateValues(entry);
entryViewHolder.setLabelSize(settings.getLabelSize()); entryViewHolder.setLabelSize(settings.getLabelSize());
@ -203,7 +236,17 @@ public class EntriesCardAdapter extends RecyclerView.Adapter<EntryViewHolder>
@Override @NonNull @Override @NonNull
public EntryViewHolder onCreateViewHolder(@NonNull ViewGroup viewGroup, int i) { public EntryViewHolder onCreateViewHolder(@NonNull ViewGroup viewGroup, int i) {
View itemView = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.component_card, viewGroup, false); int cardLayout = R.layout.component_card_default;
Constants.CardLayouts layout = settings.getCardLayout();
if (layout == Constants.CardLayouts.DEFAULT) {
cardLayout = R.layout.component_card_default;
} else if (layout == Constants.CardLayouts.FULL) {
cardLayout = R.layout.component_card_full;
}
View itemView = LayoutInflater.from(viewGroup.getContext()).inflate(cardLayout, viewGroup, false);
EntryViewHolder viewHolder = new EntryViewHolder(context, itemView, settings.getTapToReveal()); EntryViewHolder viewHolder = new EntryViewHolder(context, itemView, settings.getTapToReveal());
viewHolder.setCallback(new EntryViewHolder.Callback() { viewHolder.setCallback(new EntryViewHolder.Callback() {
@ -228,6 +271,9 @@ public class EntriesCardAdapter extends RecyclerView.Adapter<EntryViewHolder>
public void onCopyButtonClicked(String text, int position) { public void onCopyButtonClicked(String text, int position) {
copyToClipboard(text); copyToClipboard(text);
updateLastUsed(position, getRealIndex(position)); updateLastUsed(position, getRealIndex(position));
if(context != null && settings.isMinimizeAppOnCopyEnabled()) {
((MainActivity)context).moveTaskToBack(true);
}
} }
@Override @Override
@ -247,6 +293,9 @@ public class EntriesCardAdapter extends RecyclerView.Adapter<EntryViewHolder>
}); });
taskHandler.postDelayed(entries.get(realIndex).getHideTask(), settings.getTapToRevealTimeout() * 1000); taskHandler.postDelayed(entries.get(realIndex).getHideTask(), settings.getTapToRevealTimeout() * 1000);
if (entry.isCounterBased()) {
updateEntry(entry, entries.get(realIndex), position);
}
entry.setVisible(true); entry.setVisible(true);
notifyItemChanged(position); notifyItemChanged(position);
} }
@ -255,18 +304,7 @@ public class EntriesCardAdapter extends RecyclerView.Adapter<EntryViewHolder>
@Override @Override
public void onCounterClicked(int position) { public void onCounterClicked(int position) {
Entry entry = displayedEntries.get(position); updateEntry(displayedEntries.get(position), entries.get(getRealIndex(position)), position);
Entry realEntry = entries.get(getRealIndex(position));
long counter = entry.getCounter() + 1;
entry.setCounter(counter);
entry.updateOTP();
notifyItemChanged(position);
realEntry.setCounter(counter);
realEntry.updateOTP();
DatabaseHelper.saveDatabase(context, entries, encryptionKey);
} }
@Override @Override
@ -278,6 +316,19 @@ public class EntriesCardAdapter extends RecyclerView.Adapter<EntryViewHolder>
return viewHolder; return viewHolder;
} }
private void updateEntry(Entry entry, Entry realEntry, final int position) {
long counter = entry.getCounter() + 1;
entry.setCounter(counter);
entry.updateOTP();
notifyItemChanged(position);
realEntry.setCounter(counter);
realEntry.updateOTP();
saveEntries(settings.getAutoBackupEncryptedFullEnabled());
}
private void hideEntry(Entry entry) { private void hideEntry(Entry entry) {
int pos = displayedEntries.indexOf(entry); int pos = displayedEntries.indexOf(entry);
int realIndex = entries.indexOf(entry); int realIndex = entries.indexOf(entry);
@ -328,7 +379,7 @@ public class EntriesCardAdapter extends RecyclerView.Adapter<EntryViewHolder>
Entry e = entries.get(realIndex); Entry e = entries.get(realIndex);
e.setCounter(newCounter); e.setCounter(newCounter);
DatabaseHelper.saveDatabase(context, entries, encryptionKey); saveEntries(settings.getAutoBackupEncryptedFullEnabled());
} }
}) })
.setNegativeButton(android.R.string.cancel, new DialogInterface.OnClickListener() { .setNegativeButton(android.R.string.cancel, new DialogInterface.OnClickListener() {
@ -346,7 +397,7 @@ public class EntriesCardAdapter extends RecyclerView.Adapter<EntryViewHolder>
displayedEntries.get(position).setLastUsed(timeStamp); displayedEntries.get(position).setLastUsed(timeStamp);
entries.get(realIndex).setLastUsed(timeStamp); entries.get(realIndex).setLastUsed(timeStamp);
DatabaseHelper.saveDatabase(context, entries, encryptionKey); saveEntries(settings.getAutoBackupEncryptedFullEnabled());
if (sortMode == SortMode.LAST_USED) { if (sortMode == SortMode.LAST_USED) {
displayedEntries = sortEntries(displayedEntries); displayedEntries = sortEntries(displayedEntries);
@ -365,12 +416,57 @@ public class EntriesCardAdapter extends RecyclerView.Adapter<EntryViewHolder>
displayedEntries = new ArrayList<>(entries); displayedEntries = new ArrayList<>(entries);
notifyItemMoved(fromPosition, toPosition); notifyItemMoved(fromPosition, toPosition);
DatabaseHelper.saveDatabase(context, entries, encryptionKey); saveEntries(settings.getAutoBackupEncryptedFullEnabled());
} }
return true; return true;
} }
public void editEntryIssuer(final int pos) {
AlertDialog.Builder builder = new AlertDialog.Builder(context);
int marginSmall = context.getResources().getDimensionPixelSize(R.dimen.activity_margin_small);
int marginMedium = context.getResources().getDimensionPixelSize(R.dimen.activity_margin_medium);
final EditText input = new EditText(context);
input.setLayoutParams(new FrameLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT));
input.setText(displayedEntries.get(pos).getIssuer());
input.setSingleLine();
FrameLayout container = new FrameLayout(context);
container.setPaddingRelative(marginMedium, marginSmall, marginMedium, 0);
container.addView(input);
builder.setTitle(R.string.dialog_title_rename)
.setView(container)
.setPositiveButton(R.string.button_save, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialogInterface, int i) {
int realIndex = getRealIndex(pos);
String newIssuer = input.getEditableText().toString();
displayedEntries.get(pos).setIssuer(newIssuer);
if (sortMode == SortMode.LABEL) {
displayedEntries = sortEntries(displayedEntries);
notifyDataSetChanged();
} else {
notifyItemChanged(pos);
}
Entry e = entries.get(realIndex);
e.setIssuer(newIssuer);
DatabaseHelper.saveDatabase(context, entries, encryptionKey);
}
})
.setNegativeButton(android.R.string.cancel, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialogInterface, int i) {}
})
.create()
.show();
}
public void editEntryLabel(final int pos) { public void editEntryLabel(final int pos) {
AlertDialog.Builder builder = new AlertDialog.Builder(context); AlertDialog.Builder builder = new AlertDialog.Builder(context);
@ -405,7 +501,7 @@ public class EntriesCardAdapter extends RecyclerView.Adapter<EntryViewHolder>
Entry e = entries.get(realIndex); Entry e = entries.get(realIndex);
e.setLabel(newLabel); e.setLabel(newLabel);
DatabaseHelper.saveDatabase(context, entries, encryptionKey); saveEntries(settings.getAutoBackupEncryptedFullEnabled());
} }
}) })
.setNegativeButton(android.R.string.cancel, new DialogInterface.OnClickListener() { .setNegativeButton(android.R.string.cancel, new DialogInterface.OnClickListener() {
@ -423,7 +519,7 @@ public class EntriesCardAdapter extends RecyclerView.Adapter<EntryViewHolder>
int marginMedium = context.getResources().getDimensionPixelSize(R.dimen.activity_margin_medium); int marginMedium = context.getResources().getDimensionPixelSize(R.dimen.activity_margin_medium);
int realIndex = getRealIndex(pos); int realIndex = getRealIndex(pos);
final ThumbnailSelectionAdapter thumbnailAdapter = new ThumbnailSelectionAdapter(context, entries.get(realIndex).getLabel()); final ThumbnailSelectionAdapter thumbnailAdapter = new ThumbnailSelectionAdapter(context, entries.get(realIndex).getIssuer(), entries.get(realIndex).getLabel());
final EditText input = new EditText(context); final EditText input = new EditText(context);
input.setLayoutParams(new FrameLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT)); input.setLayoutParams(new FrameLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT));
@ -491,7 +587,7 @@ public class EntriesCardAdapter extends RecyclerView.Adapter<EntryViewHolder>
Entry e = entries.get(realIndex); Entry e = entries.get(realIndex);
e.setThumbnail(thumbnail); e.setThumbnail(thumbnail);
DatabaseHelper.saveDatabase(context, entries, encryptionKey); saveEntries(settings.getAutoBackupEncryptedFullEnabled());
notifyItemChanged(pos); notifyItemChanged(pos);
alert.cancel(); alert.cancel();
} }
@ -519,7 +615,7 @@ public class EntriesCardAdapter extends RecyclerView.Adapter<EntryViewHolder>
@Override @Override
public Object call() throws Exception { public Object call() throws Exception {
entries.get(realPos).setTags(tagsAdapter.getActiveTags()); entries.get(realPos).setTags(tagsAdapter.getActiveTags());
DatabaseHelper.saveDatabase(context, entries, encryptionKey); saveEntries(settings.getAutoBackupEncryptedFullEnabled());
List<String> inUseTags = getTags(); List<String> inUseTags = getTags();
@ -564,7 +660,7 @@ public class EntriesCardAdapter extends RecyclerView.Adapter<EntryViewHolder>
notifyItemRemoved(pos); notifyItemRemoved(pos);
entries.remove(realIndex); entries.remove(realIndex);
DatabaseHelper.saveDatabase(context, entries, encryptionKey); saveEntries(settings.getAutoBackupEncryptedFullEnabled());
} }
}) })
.setNegativeButton(android.R.string.no, new DialogInterface.OnClickListener() { .setNegativeButton(android.R.string.no, new DialogInterface.OnClickListener() {
@ -585,7 +681,10 @@ public class EntriesCardAdapter extends RecyclerView.Adapter<EntryViewHolder>
public boolean onMenuItemClick(MenuItem item) { public boolean onMenuItemClick(MenuItem item) {
int id = item.getItemId(); int id = item.getItemId();
if (id == R.id.menu_popup_editLabel) { if (id == R.id.menu_popup_editIssuer) {
editEntryIssuer(pos);
return true;
} else if (id == R.id.menu_popup_editLabel) {
editEntryLabel(pos); editEntryLabel(pos);
return true; return true;
} else if(id == R.id.menu_popup_changeImage) { } else if(id == R.id.menu_popup_changeImage) {
@ -645,6 +744,11 @@ public class EntriesCardAdapter extends RecyclerView.Adapter<EntryViewHolder>
return filter; return filter;
} }
public void clearFilter() {
if (filter != null)
filter = null;
}
public List<String> getTags() { public List<String> getTags() {
HashSet<String> tags = new HashSet<String>(); HashSet<String> tags = new HashSet<String>();
@ -656,15 +760,28 @@ public class EntriesCardAdapter extends RecyclerView.Adapter<EntryViewHolder>
} }
public class EntryFilter extends Filter { public class EntryFilter extends Filter {
private List<Constants.SearchIncludes> filterValues = settings.getSearchValues();
@Override @Override
protected FilterResults performFiltering(CharSequence constraint) { protected FilterResults performFiltering(CharSequence constraint) {
final FilterResults filterResults = new FilterResults(); final FilterResults filterResults = new FilterResults();
ArrayList<Entry> filtered = new ArrayList<>(); ArrayList<Entry> filtered = new ArrayList<>();
if (constraint != null && constraint.length() != 0){ if (constraint != null && constraint.length() != 0){
for (int i = 0; i < entries.size(); i++) { for (int i = 0; i < entries.size(); i++) {
if (entries.get(i).getLabel().toLowerCase().contains(constraint.toString().toLowerCase())) { if (filterValues.contains(Constants.SearchIncludes.LABEL) && entries.get(i).getLabel().toLowerCase().contains(constraint.toString().toLowerCase())) {
filtered.add(entries.get(i)); filtered.add(entries.get(i));
} else if (filterValues.contains(Constants.SearchIncludes.ISSUER) && entries.get(i).getIssuer().toLowerCase().contains(constraint.toString().toLowerCase())) {
filtered.add(entries.get(i));
} else if (filterValues.contains(Constants.SearchIncludes.TAGS)) {
List<String> tags = entries.get(i).getTags();
for (int j = 0; j < tags.size(); j++) {
if (tags.get(j).toLowerCase().contains(constraint.toString().toLowerCase())) {
filtered.add(entries.get(i));
break;
}
}
} }
} }
} else { } else {

View file

@ -25,8 +25,8 @@ package org.shadowice.flocke.andotp.View;
import android.animation.ObjectAnimator; import android.animation.ObjectAnimator;
import android.content.Context; import android.content.Context;
import android.graphics.ColorFilter; import android.graphics.ColorFilter;
import android.support.v7.widget.CardView; import androidx.cardview.widget.CardView;
import android.support.v7.widget.RecyclerView; import androidx.recyclerview.widget.RecyclerView;
import android.text.TextUtils; import android.text.TextUtils;
import android.view.View; import android.view.View;
import android.view.animation.LinearInterpolator; import android.view.animation.LinearInterpolator;
@ -64,7 +64,9 @@ public class EntryViewHolder extends RecyclerView.ViewHolder
private ImageView visibleImg; private ImageView visibleImg;
private ImageView thumbnailImg; private ImageView thumbnailImg;
private TextView value; private TextView value;
private TextView issuer;
private TextView label; private TextView label;
private TextView separator;
private TextView counter; private TextView counter;
private TextView tags; private TextView tags;
private MaterialProgressBar progressBar; private MaterialProgressBar progressBar;
@ -81,7 +83,9 @@ public class EntryViewHolder extends RecyclerView.ViewHolder
thumbnailFrame = v.findViewById(R.id.thumbnailFrame); thumbnailFrame = v.findViewById(R.id.thumbnailFrame);
thumbnailImg = v.findViewById(R.id.thumbnailImg); thumbnailImg = v.findViewById(R.id.thumbnailImg);
coverLayout = v.findViewById(R.id.coverLayout); coverLayout = v.findViewById(R.id.coverLayout);
issuer = v.findViewById(R.id.textViewIssuer);
label = v.findViewById(R.id.textViewLabel); label = v.findViewById(R.id.textViewLabel);
separator = v.findViewById(R.id.textViewSeparator);
tags = v.findViewById(R.id.textViewTags); tags = v.findViewById(R.id.textViewTags);
counterLayout = v.findViewById(R.id.counterLayout); counterLayout = v.findViewById(R.id.counterLayout);
counter = v.findViewById(R.id.counter); counter = v.findViewById(R.id.counter);
@ -149,7 +153,28 @@ public class EntryViewHolder extends RecyclerView.ViewHolder
final String tokenFormatted = Tools.formatToken(entry.getCurrentOTP(), settings.getTokenSplitGroupSize()); final String tokenFormatted = Tools.formatToken(entry.getCurrentOTP(), settings.getTokenSplitGroupSize());
String issuerText = entry.getIssuer();
if (!TextUtils.isEmpty(issuerText)) {
issuer.setText(entry.getIssuer());
issuer.setVisibility(View.VISIBLE);
} else {
issuer.setVisibility(View.GONE);
}
String labelText = entry.getLabel();
if (!TextUtils.isEmpty(labelText)) {
label.setText(entry.getLabel()); label.setText(entry.getLabel());
label.setVisibility(View.VISIBLE);
} else {
label.setVisibility(View.GONE);
}
if (! issuerText.isEmpty() && ! labelText.isEmpty()) {
separator.setVisibility(View.VISIBLE);
} else {
separator.setVisibility(View.GONE);
}
value.setText(tokenFormatted); value.setText(tokenFormatted);
// save the unformatted token to the tag of this TextView for copy/paste // save the unformatted token to the tag of this TextView for copy/paste
value.setTag(entry.getCurrentOTP()); value.setTag(entry.getCurrentOTP());
@ -170,7 +195,7 @@ public class EntryViewHolder extends RecyclerView.ViewHolder
int thumbnailSize = settings.getThumbnailSize(); int thumbnailSize = settings.getThumbnailSize();
if(settings.getThumbnailVisible()) { if(settings.getThumbnailVisible()) {
thumbnailImg.setImageBitmap(EntryThumbnail.getThumbnailGraphic(context, entry.getLabel(), thumbnailSize, entry.getThumbnail())); thumbnailImg.setImageBitmap(EntryThumbnail.getThumbnailGraphic(context, entry.getIssuer(), entry.getLabel(), thumbnailSize, entry.getThumbnail()));
} }
if (entry.isTimeBased() && entry.hasNonDefaultPeriod()) { if (entry.isTimeBased() && entry.hasNonDefaultPeriod()) {
@ -279,4 +304,19 @@ public class EntryViewHolder extends RecyclerView.ViewHolder
void onCounterClicked(int position); void onCounterClicked(int position);
void onCounterLongPressed(int position); void onCounterLongPressed(int position);
} }
/**
* Updates the color of OTP to red (if expiring) or default color (if new OTP)
*
* @param color will define if the color needs to be changed to red or default
* */
public void updateColor(int color) {
int textColor;
if(color == Entry.COLOR_RED) {
textColor = Tools.getThemeColor(context, R.attr.colorExpiring);
} else {
textColor = Tools.getThemeColor(context, android.R.attr.textColorSecondary);
}
value.setTextColor(textColor);
}
} }

View file

@ -16,8 +16,8 @@
package org.shadowice.flocke.andotp.View.ItemTouchHelper; package org.shadowice.flocke.andotp.View.ItemTouchHelper;
import android.support.v7.widget.RecyclerView; import androidx.recyclerview.widget.RecyclerView;
import android.support.v7.widget.helper.ItemTouchHelper; import androidx.recyclerview.widget.ItemTouchHelper;
/** /**
* Interface to listen for a move or dismissal event from a {@link ItemTouchHelper.Callback}. * Interface to listen for a move or dismissal event from a {@link ItemTouchHelper.Callback}.

View file

@ -16,11 +16,11 @@
package org.shadowice.flocke.andotp.View.ItemTouchHelper; package org.shadowice.flocke.andotp.View.ItemTouchHelper;
import android.support.v7.widget.helper.ItemTouchHelper; import androidx.recyclerview.widget.ItemTouchHelper;
/** /**
* Interface to notify an item ViewHolder of relevant callbacks from {@link * Interface to notify an item ViewHolder of relevant callbacks from {@link
* android.support.v7.widget.helper.ItemTouchHelper.Callback}. * androidx.recyclerview.widget.ItemTouchHelper.Callback}.
* *
* @author Paul Burke (ipaulpro) * @author Paul Burke (ipaulpro)
*/ */

View file

@ -17,9 +17,9 @@
package org.shadowice.flocke.andotp.View.ItemTouchHelper; package org.shadowice.flocke.andotp.View.ItemTouchHelper;
import android.graphics.Canvas; import android.graphics.Canvas;
import android.support.v7.widget.GridLayoutManager; import androidx.recyclerview.widget.GridLayoutManager;
import android.support.v7.widget.RecyclerView; import androidx.recyclerview.widget.RecyclerView;
import android.support.v7.widget.helper.ItemTouchHelper; import androidx.recyclerview.widget.ItemTouchHelper;
/** /**
* An implementation of {@link ItemTouchHelper.Callback} that enables basic drag & drop and * An implementation of {@link ItemTouchHelper.Callback} that enables basic drag & drop and

View file

@ -24,7 +24,7 @@
package org.shadowice.flocke.andotp.View; package org.shadowice.flocke.andotp.View;
import android.content.Context; import android.content.Context;
import android.support.annotation.NonNull; import androidx.annotation.NonNull;
import android.view.LayoutInflater; import android.view.LayoutInflater;
import android.view.View; import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;

View file

@ -24,7 +24,7 @@
package org.shadowice.flocke.andotp.View; package org.shadowice.flocke.andotp.View;
import android.content.Context; import android.content.Context;
import android.support.annotation.NonNull; import androidx.annotation.NonNull;
import android.view.View; import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
import android.widget.BaseAdapter; import android.widget.BaseAdapter;
@ -41,12 +41,14 @@ import java.util.List;
public class ThumbnailSelectionAdapter extends BaseAdapter { public class ThumbnailSelectionAdapter extends BaseAdapter {
private Context context; private Context context;
private List items; private List items;
private String issuer = "Example";
private String label = "Example"; private String label = "Example";
private Settings settings; private Settings settings;
ThumbnailSelectionAdapter(Context context, String label) { ThumbnailSelectionAdapter(Context context, String issuer, String label) {
items = new ArrayList(EntryThumbnail.EntryThumbnails.values().length); items = new ArrayList(EntryThumbnail.EntryThumbnails.values().length);
Collections.addAll(items, EntryThumbnail.EntryThumbnails.values()); Collections.addAll(items, EntryThumbnail.EntryThumbnails.values());
this.issuer = issuer;
this.label = label; this.label = label;
this.context = context; this.context = context;
settings = new Settings(context); settings = new Settings(context);
@ -98,7 +100,7 @@ public class ThumbnailSelectionAdapter extends BaseAdapter {
EntryThumbnail.EntryThumbnails thumb = (EntryThumbnail.EntryThumbnails)getItem(i); EntryThumbnail.EntryThumbnails thumb = (EntryThumbnail.EntryThumbnails)getItem(i);
imageView.setImageBitmap(EntryThumbnail.getThumbnailGraphic(context, label, thumbnailSize, thumb)); imageView.setImageBitmap(EntryThumbnail.getThumbnailGraphic(context, issuer, label, thumbnailSize, thumb));
return imageView; return imageView;
} }
} }

View file

@ -1,9 +0,0 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24.0"
android:viewportHeight="24.0">
<path
android:fillColor="#FF727272"
android:pathData="M20,8h-2.81c-0.45,-0.78 -1.07,-1.45 -1.82,-1.96L17,4.41 15.59,3l-2.17,2.17C12.96,5.06 12.49,5 12,5c-0.49,0 -0.96,0.06 -1.41,0.17L8.41,3 7,4.41l1.62,1.63C7.88,6.55 7.26,7.22 6.81,8L4,8v2h2.09c-0.05,0.33 -0.09,0.66 -0.09,1v1L4,12v2h2v1c0,0.34 0.04,0.67 0.09,1L4,16v2h2.81c1.04,1.79 2.97,3 5.19,3s4.15,-1.21 5.19,-3L20,18v-2h-2.09c0.05,-0.33 0.09,-0.66 0.09,-1v-1h2v-2h-2v-1c0,-0.34 -0.04,-0.67 -0.09,-1L20,10L20,8zM14,16h-4v-2h4v2zM14,12h-4v-2h4v2z"/>
</vector>

View file

@ -0,0 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24.0"
android:viewportHeight="24.0">
<path
android:fillColor="#FF727272"
android:pathData="M12,21.35l-1.45,-1.32C5.4,15.36 2,12.28 2,8.5 2,5.42 4.42,3 7.5,3c1.74,0 3.41,0.81 4.5,2.09C13.09,3.81 14.76,3 16.5,3 19.58,3 22,5.42 22,8.5c0,3.78 -3.4,6.86 -8.55,11.54L12,21.35z"/>
</vector>

View file

@ -0,0 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24.0"
android:viewportHeight="24.0">
<path
android:fillColor="#388E3C"
android:pathData="M21,19V5c0,-1.1 -0.9,-2 -2,-2H5c-1.1,0 -2,0.9 -2,2v14c0,1.1 0.9,2 2,2h14c1.1,0 2,-0.9 2,-2zM8.5,13.5l2.5,3.01L14.5,12l4.5,6H5l3.5,-4.5z" />
</vector>

View file

@ -0,0 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24.0"
android:viewportHeight="24.0" >
<path
android:fillColor="#FFFFFFFF"
android:pathData="M21,19V5c0,-1.1 -0.9,-2 -2,-2H5c-1.1,0 -2,0.9 -2,2v14c0,1.1 0.9,2 2,2h14c1.1,0 2,-0.9 2,-2zM8.5,13.5l2.5,3.01L14.5,12l4.5,6H5l3.5,-4.5z"/>
</vector>

View file

@ -1,9 +0,0 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24.0"
android:viewportHeight="24.0">
<path
android:fillColor="#FF727272"
android:pathData="M12.87,15.07l-2.54,-2.51 0.03,-0.03c1.74,-1.94 2.98,-4.17 3.71,-6.53L17,6L17,4h-7L10,2L8,2v2L1,4v1.99h11.17C11.5,7.92 10.44,9.75 9,11.35 8.07,10.32 7.3,9.19 6.69,8h-2c0.73,1.63 1.73,3.17 2.98,4.56l-5.09,5.02L4,19l5,-5 3.11,3.11 0.76,-2.04zM18.5,10h-2L12,22h2l1.12,-3h4.75L21,22h2l-4.5,-12zM15.88,17l1.62,-4.33L19.12,17h-3.24z"/>
</vector>

View file

@ -0,0 +1,18 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="113.4dp"
android:height="113.4dp"
android:viewportWidth="113.4"
android:viewportHeight="113.4">
<path
android:pathData="M0,0V113.4H113.4V0ZM111.6,111.6H1.9V1.9h109.7z"
android:fillColor="#ffffff"/>
<path
android:pathData="M1.9,111.6H111.6V1.9H1.9ZM78.4,30.7H97V82.3H86.7V39H78.4ZM47.9,52.9c-4.7,-6 -5.6,-8 -5.6,-11.8 0,-6.4 5.4,-11 13.1,-11 7.1,0 12.2,4.8 12.2,11.3 0,4.8 -2,8.3 -8,13.3l8.9,12.1c0.7,-0.7 1.4,-4.8 1.3,-8.1 0,-0.4 -0.1,-1.6 -0.2,-2.8h8.3c0,1.1 0.1,2.7 0.1,3.1 0,6.5 -1,10.6 -4.2,14.6l6.6,8.7H70.3L68,79.2c-3.8,3 -7.1,4.1 -12.4,4.1C45.2,83.2 38,77.9 37.3,68.5 36.9,62.9 40.7,57 47.9,52.9ZM12.4,30.7H31V82.3H20.7V39h-8.3z"
android:fillColor="#164194"/>
<path
android:pathData="m55.6,75.2c3.2,0 5.4,-1.2 7.2,-2.7L53,59.5c-4.6,3 -6.4,6 -6.3,8.8 0.1,4.2 3.7,6.9 8.9,6.9zM59.6,41.3c0,-2.3 -1.6,-3.8 -4.2,-3.8 -2.5,0 -4.3,1.6 -4.3,3.9 0,2.1 0.6,3.3 3.6,7.1 3.6,-2.6 4.9,-4.9 4.9,-7.2z"
android:fillColor="#164194"/>
<path
android:pathData="M86.7,82.3L97,82.3L97,30.7L78.4,30.7L78.4,39h8.3zM55.6,83.3c5.3,0 8.6,-1.1 12.4,-4.1l2.3,3.1L80.5,82.3L73.9,73.6C77,69.6 78.1,65.5 78.1,59 78.1,58.6 78,57 78,55.9h-8.3c0.1,1.3 0.2,2.4 0.2,2.8 0.1,3.3 -0.5,7.4 -1.3,8.1L59.7,54.7c6,-5 8,-8.6 8,-13.3 0,-6.5 -5.1,-11.3 -12.2,-11.3 -7.7,0 -13.1,4.7 -13.1,11 0,3.7 1,5.8 5.6,11.8 -7.2,4.2 -11,10 -10.6,15.6 0.6,9.4 7.8,14.7 18.2,14.8zM55.4,37.5c2.6,0 4.2,1.5 4.2,3.8 0,2.3 -1.3,4.7 -4.8,7.2 -3,-3.8 -3.6,-5 -3.6,-7.1 -0.1,-2.3 1.7,-3.9 4.2,-3.9zM53,59.5 L62.8,72.5c-1.9,1.5 -4,2.7 -7.2,2.7 -5.2,0 -8.8,-2.7 -8.9,-7 -0.1,-2.7 1.8,-5.7 6.3,-8.7zM20.6,82.3L31,82.3L31,30.7L12.4,30.7L12.4,39h8.2z"
android:fillColor="#ffffff"/>
</vector>

View file

@ -0,0 +1,12 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="128dp"
android:height="80dp"
android:viewportWidth="312.41"
android:viewportHeight="195.69">
<path
android:pathData="m107.52,0h118.16a7.78,7.78 0,0 1,-1.55 4.32c-4,6.86 -7.6,14 -11.53,20.86 -5.6,9.82 -10.76,19.88 -16.41,29.69 -3.58,7.06 -7.62,13.9 -11.44,20.84h-68.88c-1.2,0 -2.39,0.06 -3.59,0.13 -1,2.64 -2.66,5 -4,7.43 -1.75,2.84 -3.17,5.87 -4.9,8.71 -1.83,3.82 -4.36,7.24 -6.2,11 -3.8,6.45 -7.35,13 -11.07,19.52q-5.82,10 -11.38,20.28c-1.57,2.43 -3,4.94 -4.33,7.51 -7.77,13.57 -15.29,27.21 -23.07,40.71a16.39,16.39 0,0 1,-2.58 4c-13.3,-0.09 -26.6,0 -39.9,0a20.34,20.34 0,0 0,-4.85 0.68c0,-3.68 2.46,-6.62 4.12,-9.68 2,-4.15 4.67,-8 6.68,-12.16 15.94,-28.52 31.71,-57.14 47.6,-85.68 3.6,-6.2 6.69,-12.53 10.31,-18.61 4.52,-8 8.73,-16.18 13.44,-24.09 1.5,-3.31 3.52,-6.34 5.17,-9.57 5.86,-10.43 11.61,-20.92 17.45,-31.35a18.11,18.11 0,0 1,2.75 -4.54z"
android:fillColor="#eb4a60"/>
<path
android:pathData="m244.44,42c7.87,-13.75 15.47,-27.65 23.45,-41.34h42.68a8.82,8.82 0,0 1,1.84 0.29c-1.42,2.15 -2.61,4.43 -3.86,6.67q-15.44,27.71 -30.79,55.45c-4.3,7.53 -8.3,15.23 -12.66,22.72l-0.43,0.15 -0.08,0.94q-30.1,54 -60,108.08 -58.77,0.04 -117.59,0.04c2.23,-4.66 4.87,-9.11 7.35,-13.64 11.2,-20.57 22.65,-40.91 33.65,-61.43q36.1,-0.06 72.22,0c14.87,-25.93 29.42,-52 44.18,-77.93z"
android:fillColor="#595fb5"/>
</vector>

View file

@ -0,0 +1,181 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="128dp"
android:height="76dp"
android:viewportWidth="270"
android:viewportHeight="160">
<path
android:pathData="m154.958,53.322h22.866v23.375h11.562c5.339,0 10.831,-0.951 15.887,-2.664 2.484,-0.842 5.273,-2.015 7.724,-3.489 -3.228,-4.214 -4.876,-9.536 -5.361,-14.781 -0.659,-7.134 0.78,-16.42 5.609,-22.004l2.404,-2.78 2.864,2.302c7.211,5.794 13.276,13.889 14.345,23.118 8.683,-2.554 18.878,-1.95 26.531,2.467l3.14,1.812 -1.653,3.226c-6.473,12.633 -20.005,16.547 -33.235,15.854 -19.797,49.308 -62.898,72.653 -115.157,72.653 -26.999,0 -51.77,-10.093 -65.876,-34.047 -0.827,-1.488 -1.535,-3.044 -2.286,-4.572 -4.768,-10.544 -6.352,-22.095 -5.277,-33.637l0.322,-3.457H58.92V53.322h22.866V30.456H127.518V7.59h27.44v45.732"
android:fillColor="#394d54"/>
<group>
<clip-path android:pathData="M83.471,9.59L83.471,55.59L61.471,55.59L61.471,78.59L43.051,78.59c-0.078,0.666 -0.141,1.333 -0.206,2 -1.151,12.531 1.036,24.088 6.063,33.969L50.596,117.59c1.011,1.817 2.191,3.523 3.438,5.188 1.245,1.662 1.686,2.583 2.469,3.688C69.791,141.401 89.6,148.59 112.471,148.59 163.119,148.59 206.104,126.152 225.127,75.746 238.624,77.131 251.57,73.67 257.471,62.152 248.072,56.729 235.992,58.467 229.033,61.965L247.471,9.59 175.471,55.59L152.471,55.59L152.471,9.59Z M 0,0"/>
<path
android:pathData="m131.33,-11.465h19.818L151.147,8.352h-19.818z"
android:fillColor="#00acd3"/>
<path
android:pathData="m131.33,11.4h19.818v19.818h-19.818z"
android:fillColor="#20c2ef"/>
<path
android:fillColor="#FF000000"
android:pathData="M133.763,6.701L133.763,-9.815M136.735,6.701L136.735,-9.815m3.002,16.516L139.737,-9.815m3.003,16.516L142.74,-9.815M145.743,6.701L145.743,-9.815m2.971,16.516L148.714,-9.815"
android:strokeWidth="1.55999994"
android:strokeColor="#394d54"/>
<path
android:fillColor="#FF000000"
android:pathData="M133.763,29.567L133.763,13.051M136.735,29.567L136.735,13.051m3.002,16.516L139.737,13.051m3.003,16.516L142.74,13.051M145.743,29.567L145.743,13.051m2.971,16.516L148.714,13.051"
android:strokeWidth="1.55999994"
android:strokeColor="#394d54"/>
<path
android:pathData="m154.196,31.217l19.818,-0L174.014,11.4l-19.818,-0z"
android:fillColor="#00acd3"/>
<path
android:pathData="m154.196,8.352l19.818,-0l0,-19.818l-19.818,-0z"
android:fillColor="#20c2ef"/>
<path
android:fillColor="#FF000000"
android:pathData="M156.629,13.051L156.629,29.567M159.601,13.051L159.601,29.567m3.002,-16.516L162.603,29.567m3.003,-16.516L165.606,29.567M168.609,13.051L168.609,29.567m2.971,-16.516L171.58,29.567"
android:strokeWidth="1.55999994"
android:strokeColor="#394d54"/>
<path
android:fillColor="#FF000000"
android:pathData="M156.629,-9.815L156.629,6.701M159.601,-9.815L159.601,6.701m3.002,-16.516L162.603,6.701m3.003,-16.516L165.606,6.701M168.609,-9.815L168.609,6.701m2.971,-16.516L171.58,6.701"
android:strokeWidth="1.55999994"
android:strokeColor="#394d54"/>
<path
android:pathData="m39.866,34.267h19.818L59.684,54.084h-19.818z"
android:fillColor="#00acd3"/>
<path
android:pathData="m39.866,57.132h19.818v19.818h-19.818z"
android:fillColor="#20c2ef"/>
<path
android:fillColor="#FF000000"
android:pathData="M42.299,52.433L42.299,35.917M45.271,52.433L45.271,35.917m3.002,16.516L48.273,35.917m3.003,16.516L51.276,35.917M54.279,52.433L54.279,35.917m2.971,16.516L57.25,35.917"
android:strokeWidth="1.55999994"
android:strokeColor="#394d54"/>
<path
android:fillColor="#FF000000"
android:pathData="M42.299,75.299L42.299,58.783M45.271,75.299L45.271,58.783m3.002,16.516L48.273,58.783m3.003,16.516L51.276,58.783M54.279,75.299L54.279,58.783m2.971,16.516L57.25,58.783"
android:strokeWidth="1.55999994"
android:strokeColor="#394d54"/>
<path
android:pathData="m62.732,76.949l19.818,-0L82.55,57.132l-19.818,-0z"
android:fillColor="#00acd3"/>
<path
android:pathData="m62.732,54.084l19.818,-0l0,-19.818l-19.818,-0z"
android:fillColor="#20c2ef"/>
<path
android:fillColor="#FF000000"
android:pathData="M65.165,58.783L65.165,75.299M68.137,58.783L68.137,75.299m3.002,-16.516L71.139,75.299m3.003,-16.516L74.142,75.299M77.145,58.783L77.145,75.299m2.971,-16.516L80.116,75.299"
android:strokeWidth="1.55999994"
android:strokeColor="#394d54"/>
<path
android:fillColor="#FF000000"
android:pathData="M65.165,35.917L65.165,52.433M68.137,35.917L68.137,52.433m3.002,-16.516L71.139,52.433m3.003,-16.516L74.142,52.433M77.145,35.917L77.145,52.433m2.971,-16.516L80.116,52.433"
android:strokeWidth="1.55999994"
android:strokeColor="#394d54"/>
<path
android:pathData="m85.598,34.267h19.818L105.416,54.084h-19.818z"
android:fillColor="#00acd3"/>
<path
android:pathData="m85.598,57.132h19.818v19.818h-19.818z"
android:fillColor="#20c2ef"/>
<path
android:fillColor="#FF000000"
android:pathData="M88.031,52.433L88.031,35.917M91.003,52.433L91.003,35.917m3.002,16.516L94.005,35.917m3.003,16.516L97.008,35.917M100.011,52.433L100.011,35.917m2.971,16.516L102.982,35.917"
android:strokeWidth="1.55999994"
android:strokeColor="#394d54"/>
<path
android:fillColor="#FF000000"
android:pathData="M88.031,75.299L88.031,58.783M91.003,75.299L91.003,58.783m3.002,16.516L94.005,58.783m3.003,16.516L97.008,58.783M100.011,75.299L100.011,58.783m2.971,16.516L102.982,58.783"
android:strokeWidth="1.55999994"
android:strokeColor="#394d54"/>
<path
android:pathData="m108.464,76.949l19.818,-0L128.282,57.132l-19.818,-0z"
android:fillColor="#00acd3"/>
<path
android:pathData="m108.464,54.084l19.818,-0l0,-19.818l-19.818,-0z"
android:fillColor="#20c2ef"/>
<path
android:fillColor="#FF000000"
android:pathData="M110.897,58.783L110.897,75.299M113.869,58.783L113.869,75.299m3.002,-16.516L116.871,75.299m3.003,-16.516L119.874,75.299M122.877,58.783L122.877,75.299m2.971,-16.516L125.848,75.299"
android:strokeWidth="1.55999994"
android:strokeColor="#394d54"/>
<path
android:fillColor="#FF000000"
android:pathData="M110.897,35.917L110.897,52.433M113.869,35.917L113.869,52.433m3.002,-16.516L116.871,52.433m3.003,-16.516L119.874,52.433M122.877,35.917L122.877,52.433m2.971,-16.516L125.848,52.433"
android:strokeWidth="1.55999994"
android:strokeColor="#394d54"/>
<path
android:pathData="m131.33,34.267h19.818L151.148,54.084h-19.818z"
android:fillColor="#00acd3"/>
<path
android:pathData="m131.33,57.132h19.818v19.818h-19.818z"
android:fillColor="#20c2ef"/>
<path
android:fillColor="#FF000000"
android:pathData="M133.763,52.433L133.763,35.917M136.735,52.433L136.735,35.917m3.002,16.516L139.737,35.917m3.003,16.516L142.74,35.917M145.743,52.433L145.743,35.917m2.971,16.516L148.714,35.917"
android:strokeWidth="1.55999994"
android:strokeColor="#394d54"/>
<path
android:fillColor="#FF000000"
android:pathData="M133.763,75.299L133.763,58.783M136.735,75.299L136.735,58.783m3.002,16.516L139.737,58.783m3.003,16.516L142.74,58.783M145.743,75.299L145.743,58.783m2.971,16.516L148.714,58.783"
android:strokeWidth="1.55999994"
android:strokeColor="#394d54"/>
<path
android:pathData="m154.196,76.949l19.818,-0L174.014,57.132l-19.818,-0z"
android:fillColor="#00acd3"/>
<path
android:pathData="m154.196,54.084l19.818,-0l0,-19.818l-19.818,-0z"
android:fillColor="#20c2ef"/>
<path
android:fillColor="#FF000000"
android:pathData="M156.629,58.783L156.629,75.299M159.601,58.783L159.601,75.299m3.002,-16.516L162.603,75.299m3.003,-16.516L165.606,75.299M168.609,58.783L168.609,75.299m2.971,-16.516L171.58,75.299"
android:strokeWidth="1.55999994"
android:strokeColor="#394d54"/>
<path
android:fillColor="#FF000000"
android:pathData="M156.629,35.917L156.629,52.433M159.601,35.917L159.601,52.433m3.002,-16.516L162.603,52.433m3.003,-16.516L165.606,52.433M168.609,35.917L168.609,52.433m2.971,-16.516L171.58,52.433"
android:strokeWidth="1.55999994"
android:strokeColor="#394d54"/>
</group>
<group>
<clip-path android:pathData="M83.471,9.59L83.471,55.59L61.471,55.59L61.471,78.59L43.051,78.59c-0.078,0.666 -0.141,1.333 -0.206,2 -1.151,12.531 1.036,24.088 6.063,33.969L50.596,117.59c1.011,1.817 2.191,3.523 3.438,5.188 1.245,1.662 1.686,2.583 2.469,3.688C69.791,141.401 89.6,148.59 112.471,148.59 163.119,148.59 206.104,126.152 225.127,75.746 238.624,77.131 251.57,73.67 257.471,62.152 248.072,56.729 235.992,58.467 229.033,61.965L247.471,9.59 175.471,55.59L152.471,55.59L152.471,9.59Z M 0,0"/>
<path
android:pathData="m229.041,61.969c1.533,-11.915 -7.384,-21.275 -12.914,-25.718 -6.373,7.368 -7.363,26.678 2.635,34.807 -5.58,4.956 -17.337,9.448 -29.376,9.448L41.471,80.507C40.3,93.074 41.471,153.59 41.471,153.59h217l-0.987,-91.424c-9.399,-5.424 -21.484,-3.694 -28.443,-0.197"
android:fillColor="#17b5eb"/>
</group>
<group>
<clip-path android:pathData="M83.471,9.59L83.471,55.59L61.471,55.59L61.471,78.59L43.051,78.59c-0.078,0.666 -0.141,1.333 -0.206,2 -1.151,12.531 1.036,24.088 6.063,33.969L50.596,117.59c1.011,1.817 2.191,3.523 3.438,5.188 1.245,1.662 1.686,2.583 2.469,3.688C69.791,141.401 89.6,148.59 112.471,148.59 163.119,148.59 206.104,126.152 225.127,75.746 238.624,77.131 251.57,73.67 257.471,62.152 248.072,56.729 235.992,58.467 229.033,61.965L247.471,9.59 175.471,55.59L152.471,55.59L152.471,9.59Z M 0,0"/>
<path
android:fillColor="#FF000000"
android:pathData="m41.471,96.59v57L258.471,153.59L258.471,96.59"
android:fillAlpha="0.17000002"/>
</group>
<group>
<clip-path android:pathData="M83.471,9.59L83.471,55.59L61.471,55.59L61.471,78.59L43.051,78.59c-0.078,0.666 -0.141,1.333 -0.206,2 -1.151,12.531 1.036,24.088 6.063,33.969L50.596,117.59c1.011,1.817 2.191,3.523 3.438,5.188 1.245,1.662 1.686,2.583 2.469,3.688C69.791,141.401 89.6,148.59 112.471,148.59 163.119,148.59 206.104,126.152 225.127,75.746 238.624,77.131 251.57,73.67 257.471,62.152 248.072,56.729 235.992,58.467 229.033,61.965L247.471,9.59 175.471,55.59L152.471,55.59L152.471,9.59Z M 0,0"/>
<path
android:pathData="M118.708,148.48C105.168,142.055 97.736,133.321 93.601,123.785L52.471,125.59l21,28 45.237,-5.11"
android:fillColor="#d4edf1"/>
</group>
<group>
<clip-path android:pathData="M83.471,9.59L83.471,55.59L61.471,55.59L61.471,78.59L43.051,78.59c-0.078,0.666 -0.141,1.333 -0.206,2 -1.151,12.531 1.036,24.088 6.063,33.969L50.596,117.59c1.011,1.817 2.191,3.523 3.438,5.188 1.245,1.662 1.686,2.583 2.469,3.688C69.791,141.401 89.6,148.59 112.471,148.59 163.119,148.59 206.104,126.152 225.127,75.746 238.624,77.131 251.57,73.67 257.471,62.152 248.072,56.729 235.992,58.467 229.033,61.965L247.471,9.59 175.471,55.59L152.471,55.59L152.471,9.59Z M 0,0"/>
<path
android:fillColor="#FF000000"
android:pathData="m229.971,61.527v0.031c-20.861,26.889 -50.783,50.379 -82.906,62.719 -28.655,11.008 -53.638,11.06 -70.875,2.219 -1.856,-1.048 -3.676,-2.212 -5.5,-3.313C58.053,114.352 50.935,99.742 51.533,80.496L41.471,80.496L41.471,153.59L258.471,153.59L258.471,57.59h-25z"
android:fillAlpha="0.08500001"/>
</group>
<path
android:pathData="m53.096,124.621c14.165,0.775 29.282,0.914 42.469,-3.219"
android:strokeWidth="3.4000001"
android:fillColor="#00000000"
android:strokeColor="#394d54"
android:strokeLineCap="round"/>
<path
android:pathData="m109.641,114.549c0,3.019 -2.448,5.467 -5.467,5.467 -3.02,0 -5.468,-2.448 -5.468,-5.467 0,-3.019 2.448,-5.468 5.468,-5.468 3.019,0 5.467,2.449 5.467,5.468z"
android:fillColor="#d4edf1"/>
<path
android:pathData="m105.592,110.898c-0.477,0.276 -0.8,0.793 -0.8,1.384 0,0.883 0.716,1.597 1.598,1.597 0.605,0 1.13,-0.336 1.402,-0.832 0.192,0.462 0.298,0.97 0.298,1.502 0,2.162 -1.753,3.915 -3.916,3.915 -2.162,0 -3.916,-1.753 -3.916,-3.915 0,-2.163 1.754,-3.917 3.916,-3.917 0.5,0 0.977,0.094 1.418,0.265z"
android:fillColor="#394d54"/>
<path
android:pathData="M7.471,97.752H261.798c-5.538,-1.405 -17.521,-3.302 -15.545,-10.56 -10.069,11.652 -34.353,8.174 -40.481,2.429 -6.825,9.898 -46.555,6.136 -49.326,-1.575 -8.556,10.041 -35.067,10.041 -43.623,0 -2.772,7.711 -42.501,11.473 -49.327,1.575 -6.128,5.746 -30.41,9.223 -40.48,-2.429 1.976,7.257 -10.007,9.155 -15.546,10.56"
android:fillColor="#394d54"/>
</vector>

View file

@ -0,0 +1,27 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="128dp"
android:height="14dp"
android:viewportWidth="199.999"
android:viewportHeight="21.883688">
<path
android:pathData="M17.985,0.801C18.989,0.27 20.117,-0.006 21.252,0.02 26.324,0.018 31.396,0.037 36.468,0.014 35.806,1.483 35.103,3.417 33.222,3.586 28.509,3.717 23.784,3.574 19.066,3.652 17.9,3.632 16.738,4.246 16.244,5.33c-1.016,1.991 -1.928,4.035 -2.926,6.038 4.043,-0.003 8.088,0.003 12.132,-0.006 -0.354,0.688 -0.619,1.452 -1.175,2.01 -0.678,0.534 -1.601,0.435 -2.406,0.459 -3.131,-0.041 -6.266,0.034 -9.396,-0.044 -1.129,2.116 -2.082,4.318 -3.173,6.453 -0.497,1.007 -1.584,1.658 -2.709,1.619 -2.196,0 -4.397,0.08 -6.591,-0.072v-0.118c0.038,0.009 0.116,0.031 0.156,0.04 1.9,-4.104 3.881,-8.165 5.844,-12.24C6.965,7.428 8.615,5.742 10.603,4.672 13.049,3.354 15.524,2.092 17.985,0.801z"
android:fillColor="#0b1560"/>
<path
android:pathData="m38.996,1.801c0.509,-1.078 1.675,-1.75 2.853,-1.769 2.156,-0.034 4.312,0.013 6.469,-0.022 -3.174,6.676 -6.424,13.319 -9.621,19.985 -0.447,1.091 -1.543,1.875 -2.734,1.858 -2.215,0.031 -4.431,0.007 -6.645,0.01 3.222,-6.687 6.451,-13.373 9.678,-20.062z"
android:fillColor="#0b1560"/>
<path
android:pathData="m56.965,0.137c0.706,-0.351 1.525,0.047 1.909,0.678 3.159,4.344 6.337,8.675 9.527,12.994 0.351,0.478 0.615,1.006 0.875,1.537 2.021,-3.998 3.9,-8.069 5.856,-12.098 0.503,-0.997 0.872,-2.197 1.929,-2.756 1.461,-0.781 3.185,-0.375 4.769,-0.462 -3.524,7.279 -7.041,14.56 -10.561,21.842 -1.785,-0.025 -3.572,0.037 -5.354,-0.027 -1.109,-0.035 -1.965,-0.856 -2.594,-1.688 -2.465,-3.281 -4.934,-6.56 -7.4,-9.834 -0.531,-0.673 -1.047,-1.356 -1.413,-2.134 -2.006,3.994 -3.853,8.067 -5.834,12.074 -0.456,0.881 -1.372,1.528 -2.372,1.582 -1.166,0.067 -2.332,0.01 -3.496,0.024 2.48,-5.319 5.021,-10.616 7.555,-15.91 0.82,-1.744 2.045,-3.344 3.731,-4.319 0.934,-0.544 1.882,-1.069 2.873,-1.503z"
android:fillColor="#0b1560"/>
<path
android:pathData="m91.36,0.137c0.692,-0.344 1.498,0.028 1.889,0.644 3.166,4.347 6.348,8.688 9.544,13.016 0.358,0.481 0.622,1.022 0.888,1.556 2.248,-4.478 4.351,-9.033 6.553,-13.537 0.461,-0.983 1.47,-1.633 2.537,-1.746 1.145,-0.098 2.295,-0.022 3.441,-0.053 -3.479,7.303 -7.031,14.571 -10.551,21.858 -1.793,-0.03 -3.59,0.037 -5.385,-0.03 -1.188,-0.062 -2.057,-0.994 -2.713,-1.892 -2.797,-3.769 -5.674,-7.478 -8.438,-11.272 -0.09,-0.072 -0.271,-0.222 -0.361,-0.293 -1.801,3.848 -3.676,7.659 -5.492,11.5 -0.412,0.943 -1.236,1.781 -2.293,1.922 -1.246,0.131 -2.502,0.024 -3.75,0.071 2.021,-4.479 4.19,-8.899 6.297,-13.343 0.9,-1.771 1.588,-3.697 2.923,-5.207 1.309,-1.498 3.155,-2.345 4.911,-3.194z"
android:fillColor="#0b1560"/>
<path
android:pathData="m128.938,0.833c0.992,-0.538 2.109,-0.828 3.242,-0.811 2.398,0 4.799,-0.002 7.202,0 1.743,-0.006 3.459,0.639 4.8,1.75 1.534,1.182 3.112,2.307 4.631,3.507 0.683,0.469 0.734,1.384 0.345,2.069 -2.304,4.847 -4.679,9.662 -6.981,14.512 -1.99,0 -3.984,0.027 -5.975,-0.006 -1.072,0.074 -1.956,-1.172 -1.432,-2.142 0.854,-1.997 1.91,-3.905 2.791,-5.891 -4.709,-0.011 -9.416,-0.003 -14.125,-0.003 -1.031,2.087 -2.017,4.199 -3.047,6.287 -0.464,0.972 -1.438,1.722 -2.537,1.74 -2.264,0.06 -4.528,-0.014 -6.791,0.034 1.965,-4.135 3.955,-8.257 5.939,-12.382 0.963,-2.034 2.585,-3.729 4.562,-4.797 2.453,-1.301 4.916,-2.582 7.376,-3.867M127.549,5.336c-1.013,1.988 -1.925,4.028 -2.928,6.025 4.716,0.013 9.428,0.003 14.144,0.003 0.947,-1.988 1.909,-3.969 2.879,-5.947 0.152,-0.419 0.519,-0.872 0.293,-1.328 -0.369,-0.537 -1.062,-0.435 -1.619,-0.459 -3.334,0.025 -6.668,-0.021 -10,0.022 -1.167,-0.031 -2.278,0.622 -2.769,1.684z"
android:fillColor="#0b1560"/>
<path
android:pathData="m157.174,2.51c0.44,-1.222 1.423,-2.306 2.778,-2.439 2.281,-0.125 4.572,0.003 6.855,-0.062 -3.078,6.647 -6.354,13.207 -9.502,19.822 -0.43,1.064 -1.406,1.953 -2.589,2.014 -2.291,0.062 -4.584,0.01 -6.878,0.024 3.114,-6.455 6.233,-12.902 9.336,-19.359z"
android:fillColor="#0b1560"/>
<path
android:pathData="m177.005,2.324c1.875,-0.872 3.638,-2.269 5.794,-2.291 2.51,-0.017 5.022,-0.028 7.531,0.006 2.278,0.078 4.222,1.388 5.916,2.794 1.234,1.059 2.766,1.807 3.753,3.125v0.809c-0.578,1.492 -1.253,2.951 -2,4.363 -0.841,1.506 -2.675,1.984 -4.269,2.145 -2.636,0.209 -5.281,-0.055 -7.916,0.148 0.074,0.102 0.226,0.305 0.3,0.403 1.513,0.56 3.71,0.028 4.625,1.681 1.281,2.129 2.562,4.258 3.862,6.377 -2.574,-0.049 -5.152,0.019 -7.729,-0.031 -0.984,0.039 -1.906,-0.498 -2.4,-1.336 -1.184,-1.85 -2.242,-3.774 -3.394,-5.641 -0.44,-0.725 -1.122,-1.372 -2,-1.462 -1.481,-0.147 -2.972,-0.022 -4.456,-0.069 -1.088,2.166 -2.115,4.359 -3.188,6.531 -0.455,1.062 -1.446,1.956 -2.649,1.967 -2.267,0.074 -4.531,-0.008 -6.797,0.036 2.116,-4.399 4.159,-8.84 6.368,-13.19 1.778,-3.347 5.534,-4.628 8.649,-6.365m1.288,2.858c-0.969,1.881 -1.841,3.812 -2.788,5.703 3.791,-0.006 7.582,0.012 11.372,-0.01 1.272,0.003 2.794,-0.259 3.469,-1.479 0.69,-1.299 1.257,-2.662 1.926,-3.971 0.162,-0.426 0.537,-0.897 0.284,-1.363 -0.391,-0.49 -1.054,-0.428 -1.608,-0.435 -3.332,0.025 -6.663,-0.022 -9.994,0.022 -1.077,0.006 -2.161,0.556 -2.661,1.533z"
android:fillColor="#0b1560"/>
</vector>

View file

@ -0,0 +1,14 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="128dp"
android:height="51dp"
android:viewportWidth="1000"
android:viewportHeight="400">
<group>
<clip-path android:pathData="M0,-1v83h55.94v236L1.52,318v82h194.65v-82h-55.94L140.23,82h54.41L194.65,-1zM554.02,0v82h55.94v236h-54.41v82h138.71L694.25,171.84l82.66,228.08 1.68,0.04 81.17,-228.12L859.76,400h140.23v-82h-55.94L944.05,82h54.42L998.47,0h-156.33l-64.73,182.89L711.87,0z M 0,0M222.23,0v82h55.94v130h215.31v-24.93s18.01,-14.04 23.75,-27.37l11.52,-25.85s5.35,-14.47 5.35,-27.41l-2.31,-25.85s-3.62,-21.06 -9.92,-27.33l-22.27,-25.9S471.28,0 433.75,0zM362.46,82h81.99v76L362.46,158z M 0,0M222.23,400l0,-82l55.94,-0l0,-130l215.31,-0l0,24.93s18.01,14.04 23.75,27.37l11.52,25.85s5.35,14.47 5.35,27.41l-2.31,25.85s-3.62,21.06 -9.92,27.33l-22.27,25.9S471.28,400 433.75,400zM362.46,318l81.99,-0l0,-76L362.46,242z M 0,0"/>
<path
android:pathData="M0,13.68h1030v53.23H0m0,53.23h975v53.24H0v53.22h975v53.22H0m0,53.24h1030v53.24H0"
android:strokeWidth="27.37"
android:fillColor="#00000000"
android:strokeColor="#1f70c1"/>
</group>
</vector>

View file

@ -0,0 +1,14 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="128dp"
android:height="128dp"
android:viewportWidth="128"
android:viewportHeight="128">
<path
android:pathData="m71.517,44.187 l12.296,12.296 -4.839,4.879 -12.296,-12.296zM94.007,21.737 L106.303,34.033 101.424,38.912 89.128,26.615zM93.214,65.924 L105.589,78.22 100.71,83.099 88.018,70.803zM115.704,43.473 L128,55.769 123.161,60.648 110.865,47.955zM67.035,34.35 L79.331,22.054 84.249,26.933 71.953,39.229zM88.732,56.166 L101.028,43.87 105.946,48.63 93.65,60.926zM110.468,77.823 L122.764,65.527 127.643,70.366 115.347,82.662zM44.545,56.88 L56.841,44.584 61.759,49.423 49.463,61.719zM66.241,78.537 L78.617,66.241 83.456,71.12 71.16,83.416zM87.978,100.353 L100.274,87.978 105.193,92.856 92.896,105.549z"
android:strokeWidth="0.26458332"
android:fillColor="#575756"/>
<path
android:pathData="m26.576,89.088 l12.376,12.296 -4.839,4.918 -12.376,-12.376zM49.066,66.638 L61.362,78.934 56.523,83.813 44.227,71.517zM48.391,110.825 L60.688,123.121 55.809,128 43.513,115.704zM70.802,88.374 L83.098,100.671 78.259,105.549 65.963,93.253zM4.879,67.352 L17.175,79.648 12.296,84.487 0,72.191zM27.369,44.901 L39.665,57.197 34.787,62.076 22.49,49.78zM49.78,22.451 L62.076,34.747 57.316,39.665 45.02,27.369zM72.191,-0 L84.566,12.296 79.687,17.175 66.995,4.879zM45.337,12.693 L57.634,0.397 62.512,5.236 50.216,17.532zM22.847,35.183 L35.143,22.887 40.062,27.766 27.766,40.062zM0.397,57.673 L12.693,45.377 17.572,50.137 5.276,62.513zM22.054,79.331 L34.35,67.034 39.269,71.913 26.972,84.21zM43.79,101.067 L56.087,88.771 60.966,93.61 48.669,105.906zM65.448,122.804 L77.823,110.508 82.702,115.267 70.406,127.643z"
android:strokeWidth="0.26458332"
android:fillColor="#db202e"/>
</vector>

View file

@ -0,0 +1,31 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="128dp"
android:height="128dp"
android:viewportWidth="128"
android:viewportHeight="128">
<path
android:pathData="m19.747,45.145c-0.04,0.287 -0.109,2.458 -0.155,4.826l-0.083,4.304 4.612,2.237 4.612,2.238 -14.366,0.007L0.001,58.763l0,5.164 0,5.164l14.113,0.031 14.113,0.031 -4.341,2.214 -4.341,2.214 0.014,2.89c0.008,1.59 0.049,3.78 0.092,4.867l0.077,1.977 2.854,-1.463c1.57,-0.805 4.51,-2.285 6.533,-3.289 2.023,-1.004 7.018,-3.535 11.1,-5.623l7.421,-3.797L47.635,63.936 47.635,58.729l-7.928,-4.049c-4.361,-2.227 -9.669,-4.909 -11.797,-5.96 -2.128,-1.052 -3.926,-1.953 -3.996,-2.002 -0.07,-0.05 -1.019,-0.541 -2.11,-1.092l-1.984,-1.002 -0.072,0.521m85.29,1.03c-1.64,0.843 -3.609,1.842 -4.377,2.221 -0.768,0.379 -5.661,2.853 -10.875,5.498l-9.479,4.808 -0.003,5.182 -0.003,5.183 9.038,4.608c4.971,2.534 9.638,4.898 10.371,5.253 0.732,0.355 2.95,1.474 4.927,2.486 1.978,1.012 3.621,1.816 3.652,1.785 0.031,-0.03 0.092,-2.206 0.134,-4.836l0.077,-4.781 -4.32,-2.214 -4.32,-2.214 14.068,-0.031 14.068,-0.031l0,-5.164 0,-5.164l-14.43,-0.007 -14.43,-0.007 4.662,-2.269 4.662,-2.269 -0.017,-2.244c-0.031,-3.973 -0.166,-7.265 -0.3,-7.296 -0.07,-0.017 -1.468,0.659 -3.108,1.502"
android:fillColor="#d3732c"
android:strokeColor="#00000000"
android:fillType="evenOdd"/>
<path
android:pathData="M12.179,0.244C7.005,1.52 2.266,5.764 0.723,10.503 0.044,12.59 0.001,13.097 0.002,19.024l0.001,5.49 13.904,7.194c7.647,3.957 14.397,7.421 15,7.697 0.603,0.277 4.978,2.511 9.722,4.965 4.744,2.454 8.726,4.512 8.848,4.574 0.21,0.106 0.222,-0.16 0.222,-4.796L47.699,39.24L38.39,34.429C33.27,31.783 29.038,29.617 28.986,29.617 28.858,29.617 20.337,25.208 19.849,24.889 19.636,24.75 17.366,23.558 14.803,22.239l-4.66,-2.398 0.035,-2.829c0.045,-3.618 0.52,-4.796 2.279,-5.645l0.66,-0.319l52.366,0 52.366,0l-0.001,4.396 -0.001,4.397 -4.652,2.398c-2.558,1.319 -4.827,2.511 -5.042,2.65 -0.487,0.315 -9.014,4.729 -9.135,4.729 -0.049,0 -4.28,2.167 -9.404,4.816l-9.315,4.816l0,4.902 0,4.902l0.368,-0.185c0.203,-0.102 4.47,-2.303 9.483,-4.893 5.013,-2.589 9.268,-4.763 9.456,-4.83 0.189,-0.067 6.653,-3.387 14.366,-7.377L127.996,24.514 127.997,12.257 127.998,0 70.501,0.02C17.484,0.039 12.939,0.057 12.179,0.244m27.655,82.54c-4.291,2.222 -9.172,4.722 -10.846,5.557 -1.675,0.834 -8.867,4.53 -15.984,8.213L0.065,103.249 0.032,115.625 0,128l58.333,0c57.968,0 58.34,-0.002 59.337,-0.247 4.434,-1.09 8.166,-4.916 9.942,-10.19l0.388,-1.152 -0.033,-6.586 -0.033,-6.586 -13.637,-7.062c-7.5,-3.884 -14.151,-7.299 -14.778,-7.588 -0.628,-0.29 -5.21,-2.632 -10.181,-5.204l-9.04,-4.677 0.033,4.932 0.033,4.932 9.823,5.079c5.403,2.793 9.868,5.079 9.922,5.079 0.124,0 7.728,3.935 7.905,4.091 0.072,0.063 2.3,1.237 4.951,2.609l4.82,2.494l0,3.123 0,3.123l-0.431,0.848c-0.728,1.433 -1.794,2.248 -3.301,2.525 -0.452,0.083 -17.909,0.125 -52.293,0.125L10.147,117.67l0.033,-4.873 0.033,-4.872 4.82,-2.494c2.651,-1.371 4.878,-2.543 4.947,-2.605 0.166,-0.145 7.803,-4.096 7.918,-4.096 0.116,0 19.568,-10.057 19.701,-10.185 0.056,-0.054 0.087,-2.282 0.068,-4.95l-0.033,-4.852 -7.801,4.04"
android:fillColor="#939393"
android:strokeColor="#00000000"
android:fillType="evenOdd"/>
<path
android:pathData="m20.073,22.631 l0.034,2.36 4.44,2.306 4.44,2.306 35.012,0.002 35.012,0.002 4.44,-2.303 4.44,-2.302 0.034,-2.366 0.035,-2.366L64,20.271 20.039,20.271l0.035,2.36m69.911,21.478 l-9.407,4.877 9.392,0.032 9.392,0.032 5.216,-2.659c9.67,-4.93 13.271,-6.832 13.271,-7.008 0,-0.147 -1.386,-0.171 -9.229,-0.162l-9.229,0.011 -9.407,4.878m-79.933,0.11 l0.029,4.891 0.066,-4.743 0.066,-4.743 3.171,1.648c1.744,0.906 5.871,3.027 9.17,4.713l5.999,3.065 9.442,-0.031 9.442,-0.032 -9.225,-4.796 -9.225,-4.796 -9.483,-0.033 -9.482,-0.033 0.029,4.891m16.145,35.831c-1.465,0.748 -3.72,1.888 -5.011,2.534 -4.706,2.354 -11.163,5.728 -11.163,5.833 0,0.061 4.047,0.108 9.289,0.108l9.289,0l9.422,-4.869c5.182,-2.678 9.422,-4.891 9.422,-4.919 0,-0.028 -4.182,-0.049 -9.292,-0.048l-9.292,0.002 -2.664,1.36m54.427,-1.26c0.067,0.057 4.321,2.271 9.454,4.919l9.333,4.815l9.294,0c7.338,0 9.282,-0.032 9.241,-0.152 -0.051,-0.149 -4.175,-2.331 -8.595,-4.548 -1.221,-0.612 -3.997,-2.019 -6.168,-3.126l-3.949,-2.012l-9.365,0c-5.151,0 -9.31,0.047 -9.244,0.103m-56.678,21.998 l-3.901,2.028l0,2.631 0,2.631L64,108.078 107.955,108.078l0,-2.631 0,-2.631l-3.96,-2.042 -3.96,-2.042 -36.095,0.014 -36.094,0.014 -3.901,2.028"
android:fillColor="#3d3d3d"
android:strokeColor="#00000000"
android:fillType="evenOdd"/>
<path
android:pathData="m113.092,42.05c-2.581,1.345 -4.722,2.46 -4.757,2.478 -0.035,0.017 -0.047,1.042 -0.026,2.276l0.037,2.244l4.752,0 4.751,0l0,-4.734c0,-2.604 -0.014,-4.729 -0.032,-4.722 -0.017,0.007 -2.144,1.113 -4.725,2.458m-102.942,2.373l0,4.748l4.757,0 4.757,0l0.024,-1.968c0.013,-1.082 0.028,-2.109 0.032,-2.282 0.007,-0.268 -7.835,-4.589 -9.411,-5.186 -0.125,-0.047 -0.158,0.94 -0.158,4.688m98.269,35.462c-0.132,1.927 -0.104,3.474 0.062,3.474 0.08,0 2.226,1.079 4.769,2.398 2.543,1.319 4.647,2.398 4.675,2.398 0.028,0 0.051,-2.131 0.051,-4.735l0,-4.734l-4.738,0 -4.738,0l-0.082,1.199M10.023,83.529l0,4.72l4.815,-2.475 4.815,-2.475 0.005,-1.488c0.003,-0.819 -0.031,-1.829 -0.076,-2.244l-0.081,-0.756l-4.739,0 -4.739,0l0,4.72"
android:fillColor="#6b6b6b"
android:strokeColor="#00000000"
android:fillType="evenOdd"/>
<path
android:pathData="m12.41,78.778c1.348,0.02 3.517,0.02 4.821,0 1.304,-0.02 0.201,-0.036 -2.45,-0.036 -2.651,0 -3.718,0.016 -2.37,0.036"
android:fillColor="#545454"
android:strokeColor="#00000000"
android:fillType="evenOdd"/>
</vector>

View file

@ -0,0 +1,155 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:aapt="http://schemas.android.com/aapt"
android:width="128dp"
android:height="128dp"
android:viewportWidth="128"
android:viewportHeight="128">
<path
android:pathData="m111.17,46.365l0,0.004L105.973,46.368L105.973,41.724C105.973,18.68 87.179,0 63.993,0 40.81,0 22.016,18.68 22.016,41.724l0,4.644L16.826,46.368C11.375,46.368 6.96,50.755 6.96,56.174l0,38.306c0.011,2.551 0.164,4.406 1.162,5.757 1.036,1.356 2.776,1.84 5.373,1.832l8.35,0l1.274,20.17c0,0.048 -0.004,0.127 -0.004,0.227 0.004,0.536 0.063,1.761 0.741,2.938 0.667,1.188 2.068,2.249 4.333,2.231l21.219,0l11.018,-11.682l8.234,0L79.314,128l0.298,0c0,0 3.856,0 8.13,0 4.266,0 8.95,0 10.6,0l0.004,0c1.639,-0.007 3.141,0.034 4.441,-0.793 1.297,-0.845 2.075,-2.45 2.452,-5.247 0.548,-4.067 0.674,-15.194 0.924,-19.887l8.342,0c2.567,-0.007 4.244,-0.253 5.332,-1.423 1.051,-1.192 1.189,-2.89 1.203,-5.437L121.04,56.174c-0.007,-5.419 -4.423,-9.805 -9.87,-9.809z"
android:strokeWidth="1"
android:fillColor="#349334"
android:strokeColor="#00000000"
android:fillType="nonZero"/>
<path
android:pathData="m119.826,95.291c0.015,2.511 -0.242,3.915 -0.861,4.563 -0.578,0.674 -1.842,1.002 -4.358,0.995l-9.599,0l-0.034,0.618c-0.231,4.426 -0.388,16.265 -0.943,20.411 -0.362,2.675 -1.059,3.807 -1.868,4.329 -0.813,0.548 -2.062,0.589 -3.724,0.581l-0.004,0c-3.034,0 -16.28,0 -18.442,0L69.336,114.734L59.938,114.734L48.911,126.424L28.247,126.424c-1.883,-0.019 -2.684,-0.741 -3.195,-1.576 -0.492,-0.846 -0.57,-1.881 -0.567,-2.291 0,-0.127 0.004,-0.179 0.004,-0.179l0.004,-0.052 -1.364,-21.48L13.548,100.846c-2.494,-0.004 -3.691,-0.462 -4.324,-1.311 -0.671,-0.857 -0.91,-2.47 -0.902,-4.973L8.322,56.247C8.329,51.549 12.154,47.753 16.881,47.745L23.393,47.745L23.393,41.792C23.431,19.463 41.604,1.399 64.076,1.362 86.544,1.399 104.721,19.463 104.762,41.792l0,5.953l6.516,0c4.723,0.007 8.544,3.804 8.552,8.501l0,39.045z"
android:strokeWidth="1"
android:fillColor="#4bb749"
android:strokeColor="#00000000"
android:fillType="nonZero"/>
<path
android:pathData="M24.511,99.707l78.979,0l0,2.617l-78.979,0z"
android:strokeWidth="1"
android:fillColor="#118011"
android:strokeColor="#00000000"
android:fillType="nonZero"/>
<path
android:pathData="M23.3,100.615l0,-49.475l1.335,0l0,49.475z"
android:strokeWidth="1"
android:fillColor="#118011"
android:strokeColor="#00000000"
android:fillType="nonZero"/>
<path
android:pathData="M103.641,100.615l0,-49.475l1.335,0l0,49.475z"
android:strokeWidth="1"
android:fillColor="#118011"
android:strokeColor="#00000000"
android:fillType="nonZero"/>
<path
android:pathData="M35.102,61.73a5.144,28.293 90,1 0,56.586 0a5.144,28.293 90,1 0,-56.586 0z"
android:strokeWidth="1"
android:strokeColor="#00000000"
android:fillType="nonZero">
<aapt:attr name="android:fillColor">
<gradient
android:startY="66.862495"
android:startX="63.394802"
android:endY="57.485966"
android:endX="63.394802"
android:type="linear">
<item android:offset="0" android:color="#FF4BB749"/>
<item android:offset="1" android:color="#FF79B481"/>
</gradient>
</aapt:attr>
</path>
<path
android:pathData="m89.721,48.567l0,-7.545c0,-14.216 -11.547,-25.741 -25.795,-25.741 -14.248,0 -25.799,11.525 -25.799,25.741l0,7.545z"
android:strokeWidth="1"
android:fillColor="#ffffff"
android:strokeColor="#00000000"
android:fillType="nonZero"/>
<path
android:pathData="M53.106,40.7l22.998,0l0,2.735l-22.998,0z"
android:strokeWidth="1"
android:strokeColor="#00000000"
android:fillType="nonZero">
<aapt:attr name="android:fillColor">
<gradient
android:gradientRadius="10.784006"
android:centerX="64.86781"
android:centerY="42.21012"
android:type="radial">
<item android:offset="0" android:color="#FF000000"/>
<item android:offset="0.1901" android:color="#FF030303"/>
<item android:offset="0.3236" android:color="#FF0C0C0C"/>
<item android:offset="0.4397" android:color="#FF1C1C1C"/>
<item android:offset="0.5461" android:color="#FF323232"/>
<item android:offset="0.64559996" android:color="#FF4E4E4E"/>
<item android:offset="0.7402" android:color="#FF717171"/>
<item android:offset="0.83089995" android:color="#FF9A9A9A"/>
<item android:offset="0.9161" android:color="#FFC9C9C9"/>
<item android:offset="0.9985" android:color="#FFFEFEFE"/>
<item android:offset="1" android:color="#FFFFFFFF"/>
</gradient>
</aapt:attr>
</path>
<path
android:pathData="M55.452,29.277m-4.766,0a4.766,4.766 45,1 1,9.532 0a4.766,4.766 135,1 1,-9.532 0"
android:strokeWidth="1"
android:fillColor="#000000"
android:strokeColor="#00000000"
android:fillType="nonZero"/>
<path
android:pathData="M72.397,29.277m-4.766,0a4.766,4.766 0,1 1,9.532 0a4.766,4.766 135,1 1,-9.532 0"
android:strokeWidth="1"
android:fillColor="#000000"
android:strokeColor="#00000000"
android:fillType="nonZero"/>
<path
android:pathData="M54.771,77.314l17.248,0l0,12.861l-17.248,0z"
android:strokeWidth="1"
android:fillColor="#ffffff"
android:strokeColor="#00000000"
android:fillType="nonZero"/>
<path
android:pathData="m57.433,75.953c0.778,-2.716 3.189,-4.687 6.039,-4.69 2.85,0.004 5.261,1.974 6.043,4.69l2.05,0c-0.826,-3.792 -4.115,-6.657 -8.096,-6.657 -3.981,0.004 -7.267,2.865 -8.093,6.657z"
android:strokeWidth="1"
android:fillColor="#ffffff"
android:strokeColor="#00000000"
android:fillType="nonZero"/>
<path
android:pathData="m115.805,103.307c0.464,-0.004 0.89,-0.015 1.302,-0.034l0,-1.448c-0.752,0.116 -1.616,0.157 -2.622,0.161l-8.374,0c-0.127,2.341 -0.221,6.268 -0.352,10.128l1.365,0c0.112,-3.416 0.198,-6.735 0.31,-8.806z"
android:strokeWidth="1"
android:fillColor="#118011"
android:strokeColor="#00000000"
android:fillType="nonZero"/>
<path
android:pathData="m117.106,104.053l0,-0.715c-0.408,0.019 -0.834,0.033 -1.302,0.033l-8.374,0c-0.112,2.057 -0.198,5.351 -0.31,8.742l1.941,-0c4.447,0.004 8.045,-3.606 8.045,-8.06z"
android:strokeWidth="1"
android:strokeColor="#00000000"
android:fillType="nonZero">
<aapt:attr name="android:fillColor">
<gradient
android:startY="97.49953"
android:startX="102.2623"
android:endY="108.40542"
android:endX="112.76872"
android:type="linear">
<item android:offset="0" android:color="#FF23FF16"/>
<item android:offset="1" android:color="#FF189A33"/>
</gradient>
</aapt:attr>
</path>
<path
android:pathData="M21.91,102.073L13.549,102.073c-1.295,0.004 -2.369,-0.115 -3.261,-0.4l0,1.669c0.526,0.063 1.101,0.089 1.731,0.089l8.364,-0.004 0.552,8.686l1.608,0z"
android:strokeWidth="1"
android:fillColor="#118011"
android:strokeColor="#00000000"
android:fillType="nonZero"/>
<path
android:pathData="m12.01,103.427c-0.627,0 -1.199,-0.026 -1.722,-0.089l0,0.722c0,4.447 3.57,8.053 7.975,8.053l2.616,0l-0.549,-8.69z"
android:strokeWidth="1"
android:strokeColor="#00000000"
android:fillType="nonZero">
<aapt:attr name="android:fillColor">
<gradient
android:startY="93.15896"
android:startX="28.748474"
android:endY="110.74311"
android:endX="12.861952"
android:type="linear">
<item android:offset="0" android:color="#FF23FF16"/>
<item android:offset="1" android:color="#FF189A33"/>
</gradient>
</aapt:attr>
</path>
</vector>

View file

@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout <androidx.coordinatorlayout.widget.CoordinatorLayout
xmlns:android="http://schemas.android.com/apk/res/android" xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent" android:layout_width="match_parent"
@ -7,7 +7,7 @@
android:background="?attr/windowBackground" android:background="?attr/windowBackground"
android:fitsSystemWindows="true" > android:fitsSystemWindows="true" >
<android.support.design.widget.AppBarLayout <com.google.android.material.appbar.AppBarLayout
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:theme="@style/AppTheme.AppBarOverlay"> android:theme="@style/AppTheme.AppBarOverlay">
@ -18,7 +18,7 @@
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content"> android:layout_height="wrap_content">
<android.support.v7.widget.Toolbar <androidx.appcompat.widget.Toolbar
android:id="@+id/container_toolbar" android:id="@+id/container_toolbar"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize" android:layout_height="?attr/actionBarSize"
@ -28,7 +28,7 @@
</RelativeLayout> </RelativeLayout>
</android.support.design.widget.AppBarLayout> </com.google.android.material.appbar.AppBarLayout>
<ViewStub <ViewStub
android:id="@+id/container_stub" android:id="@+id/container_stub"
@ -38,4 +38,4 @@
android:layout_height="match_parent" android:layout_height="match_parent"
app:layout_behavior="@string/appbar_scrolling_view_behavior" /> app:layout_behavior="@string/appbar_scrolling_view_behavior" />
</android.support.design.widget.CoordinatorLayout> </androidx.coordinatorlayout.widget.CoordinatorLayout>

View file

@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout <androidx.coordinatorlayout.widget.CoordinatorLayout
xmlns:android="http://schemas.android.com/apk/res/android" xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools" xmlns:tools="http://schemas.android.com/tools"
@ -9,7 +9,7 @@
android:fitsSystemWindows="true" android:fitsSystemWindows="true"
tools:context="org.shadowice.flocke.andotp.Activities.MainActivity"> tools:context="org.shadowice.flocke.andotp.Activities.MainActivity">
<android.support.design.widget.AppBarLayout <com.google.android.material.appbar.AppBarLayout
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:theme="@style/AppTheme.AppBarOverlay"> android:theme="@style/AppTheme.AppBarOverlay">
@ -21,7 +21,7 @@
android:layout_height="wrap_content"> android:layout_height="wrap_content">
<android.support.v7.widget.Toolbar <androidx.appcompat.widget.Toolbar
android:id="@+id/toolbar" android:id="@+id/toolbar"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize" android:layout_height="?attr/actionBarSize"
@ -43,7 +43,7 @@
</RelativeLayout> </RelativeLayout>
</android.support.design.widget.AppBarLayout> </com.google.android.material.appbar.AppBarLayout>
<RelativeLayout <RelativeLayout
android:id="@+id/main_content" android:id="@+id/main_content"
@ -51,12 +51,12 @@
android:layout_height="match_parent" android:layout_height="match_parent"
app:layout_behavior="@string/appbar_scrolling_view_behavior" > app:layout_behavior="@string/appbar_scrolling_view_behavior" >
<android.support.v4.widget.DrawerLayout <androidx.drawerlayout.widget.DrawerLayout
android:id="@+id/drawer_layout" android:id="@+id/drawer_layout"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent"> android:layout_height="match_parent">
<android.support.v7.widget.RecyclerView <androidx.recyclerview.widget.RecyclerView
android:id="@+id/cardList" android:id="@+id/cardList"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
@ -69,7 +69,7 @@
<include layout="@layout/component_tags" /> <include layout="@layout/component_tags" />
</android.support.v4.widget.DrawerLayout> </androidx.drawerlayout.widget.DrawerLayout>
</RelativeLayout> </RelativeLayout>
@ -86,4 +86,4 @@
app:sdMainFabClosedSrc="@drawable/ic_add_white" app:sdMainFabClosedSrc="@drawable/ic_add_white"
app:sdOverlayLayout="@id/speedDialOverlay" /> app:sdOverlayLayout="@id/speedDialOverlay" />
</android.support.design.widget.CoordinatorLayout> </androidx.coordinatorlayout.widget.CoordinatorLayout>

View file

@ -7,13 +7,13 @@
android:layout_height="match_parent" android:layout_height="match_parent"
android:orientation="vertical" > android:orientation="vertical" >
<android.support.design.widget.TabLayout <com.google.android.material.tabs.TabLayout
android:id="@+id/tabLayout" android:id="@+id/tabLayout"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
app:tabMode="fixed" /> app:tabMode="fixed" />
<android.support.v4.view.ViewPager <androidx.viewpager.widget.ViewPager
android:id="@+id/viewPager" android:id="@+id/viewPager"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" /> android:layout_height="wrap_content" />

View file

@ -24,21 +24,21 @@
android:paddingStart="@dimen/activity_margin" android:paddingStart="@dimen/activity_margin"
android:paddingEnd="@dimen/activity_margin"> android:paddingEnd="@dimen/activity_margin">
<android.support.design.widget.TextInputLayout <com.google.android.material.textfield.TextInputLayout
android:id="@+id/passwordLayout" android:id="@+id/passwordLayout"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:hint="@string/settings_hint_password" android:hint="@string/settings_hint_password"
app:passwordToggleEnabled="true" > app:passwordToggleEnabled="true" >
<android.support.design.widget.TextInputEditText <com.google.android.material.textfield.TextInputEditText
android:id="@+id/passwordEdit" android:id="@+id/passwordEdit"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
android:inputType="textPassword" android:inputType="textPassword"
android:autofillHints="password" /> android:autofillHints="password" />
</android.support.design.widget.TextInputLayout> </com.google.android.material.textfield.TextInputLayout>
<EditText <EditText
android:id="@+id/passwordConfirm" android:id="@+id/passwordConfirm"
@ -60,7 +60,7 @@
</LinearLayout> </LinearLayout>
<android.support.v7.widget.ButtonBarLayout <androidx.appcompat.widget.ButtonBarLayout
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginTop="@dimen/activity_margin" android:layout_marginTop="@dimen/activity_margin"
@ -80,6 +80,6 @@
style="?android:attr/buttonBarButtonStyle" style="?android:attr/buttonBarButtonStyle"
android:text="@string/button_save" /> android:text="@string/button_save" />
</android.support.v7.widget.ButtonBarLayout> </androidx.appcompat.widget.ButtonBarLayout>
</LinearLayout> </LinearLayout>

View file

@ -0,0 +1,240 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.cardview.widget.CardView
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/card_view"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/activity_margin_xsmall"
android:layout_marginBottom="@dimen/activity_margin_xsmall"
app:contentPadding="0dp"
style="?attr/cardStyle">
<LinearLayout
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:baselineAligned="false">
<FrameLayout
android:id="@+id/thumbnailFrame"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:paddingEnd="@dimen/activity_margin"
android:paddingStart="@dimen/card_padding_without_corners"
android:background="?attr/thumbnailBackground">
<ImageView
android:id="@+id/thumbnailImg"
android:layout_width="@dimen/card_thumbnail_size"
android:layout_height="@dimen/card_thumbnail_size"
android:layout_gravity="center"
android:src="@mipmap/ic_launcher" />
</FrameLayout>
<LinearLayout
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingTop="@dimen/activity_margin_small"
android:paddingBottom="@dimen/activity_margin_small"
android:paddingStart="@dimen/activity_margin"
android:paddingEnd="@dimen/activity_margin_small"
android:gravity="center_vertical"
android:baselineAligned="false" >
<LinearLayout
android:orientation="vertical"
android:layout_width="0dip"
android:layout_height="wrap_content"
android:layout_weight="1">
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content" >
<LinearLayout
android:id="@+id/valueLayout"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:visibility="gone">
<ImageView
android:id="@+id/valueImg"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_marginEnd="@dimen/activity_margin_small"
app:srcCompat="@drawable/ic_visibility_visible"/>
<TextView
android:textDirection="ltr"
android:id="@+id/valueText"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="?android:attr/textColorSecondary"
android:textSize="28sp"
android:textStyle="bold" />
</LinearLayout>
<LinearLayout
android:id="@+id/coverLayout"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<ImageView
android:id="@+id/coverImg"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_marginEnd="@dimen/activity_margin_small"
android:alpha="0.4"
app:srcCompat="@drawable/ic_visibility_invisible"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:alpha="0.4"
android:textColor="?android:attr/textColorSecondary"
android:textSize="28sp"
android:textStyle="bold"
android:text="@string/label_hidden" />
</LinearLayout>
</LinearLayout>
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal">
<TextView
android:id="@+id/textViewIssuer"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:maxLines="1"
android:ellipsize="end"
android:textSize="18sp"
android:text="Issuer"
android:textStyle="bold" />
<TextView
android:id="@+id/textViewSeparator"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:maxLines="1"
android:textSize="18sp"
android:text="@string/card_separator" />
<TextView
android:id="@+id/textViewLabel"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:maxLines="1"
android:ellipsize="end"
android:text="Label"
android:textSize="18sp" />
</LinearLayout>
<TextView
android:id="@+id/textViewTags"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:maxLines="1"
android:ellipsize="end"
android:text="Tags"
android:textSize="13.5sp" />
</LinearLayout>
<LinearLayout
android:orientation="horizontal"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<LinearLayout
android:id="@+id/customPeriodLayout"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="@dimen/activity_horizontal_margin"
android:visibility="gone"
android:orientation="horizontal" >
<ImageView
android:layout_width="wrap_content"
android:layout_height="match_parent"
app:srcCompat="@drawable/ic_alarm_gray" />
<TextView
android:id="@+id/customPeriod"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textStyle="bold" />
</LinearLayout>
<LinearLayout
android:id="@+id/counterLayout"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:padding="@dimen/activity_horizontal_margin"
android:gravity="center"
android:visibility="visible"
android:orientation="vertical" >
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textStyle="bold"
android:text="@string/label_counter_symbol" />
<TextView
android:id="@+id/counter"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textStyle="bold" />
</LinearLayout>
<ImageButton
android:id="@+id/copyButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:padding="@dimen/activity_margin_small"
android:background="?android:attr/selectableItemBackground"
app:srcCompat="@drawable/ic_content_copy_gray" />
<ImageButton
android:id="@+id/menuButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:padding="@dimen/activity_margin_small"
android:background="?android:attr/selectableItemBackground"
app:srcCompat="@drawable/ic_more_vert_gray" />
</LinearLayout>
</LinearLayout>
</LinearLayout>
<me.zhanghai.android.materialprogressbar.MaterialProgressBar
android:id="@+id/cardProgressBar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:visibility="gone"
android:max="3000"
android:progress="1500"
app:mpb_progressStyle="horizontal"
app:mpb_useIntrinsicPadding="false"
app:mpb_showProgressBackground="false"
style="@style/Widget.MaterialProgressBar.ProgressBar.Horizontal.NoPadding" />
</LinearLayout>
</androidx.cardview.widget.CardView>

View file

@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<android.support.v7.widget.CardView <androidx.cardview.widget.CardView
xmlns:android="http://schemas.android.com/apk/res/android" xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/card_view" android:id="@+id/card_view"
@ -105,6 +105,22 @@
</LinearLayout> </LinearLayout>
</LinearLayout> </LinearLayout>
<TextView
android:id="@+id/textViewIssuer"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:maxLines="1"
android:ellipsize="end"
android:textSize="18sp"
android:textStyle="bold" />
<TextView
android:id="@+id/textViewSeparator"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:maxLines="0"
android:visibility="gone" />
<TextView <TextView
android:id="@+id/textViewLabel" android:id="@+id/textViewLabel"
android:layout_width="wrap_content" android:layout_width="wrap_content"
@ -207,4 +223,4 @@
</LinearLayout> </LinearLayout>
</android.support.v7.widget.CardView> </androidx.cardview.widget.CardView>

View file

@ -26,7 +26,7 @@
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginTop="@dimen/activity_margin" android:layout_marginTop="@dimen/activity_margin"
android:text="@string/intro_slide3_desc_keystore"/> android:text="@string/intro_slide3_desc_password"/>
<Spinner <Spinner
android:id="@+id/introAuthSelection" android:id="@+id/introAuthSelection"
@ -59,21 +59,21 @@
android:paddingStart="@dimen/activity_margin" android:paddingStart="@dimen/activity_margin"
android:paddingEnd="@dimen/activity_margin"> android:paddingEnd="@dimen/activity_margin">
<android.support.design.widget.TextInputLayout <com.google.android.material.textfield.TextInputLayout
android:id="@+id/introPasswordLayout" android:id="@+id/introPasswordLayout"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:hint="@string/settings_hint_password" android:hint="@string/settings_hint_password"
app:passwordToggleEnabled="true" > app:passwordToggleEnabled="true" >
<android.support.design.widget.TextInputEditText <com.google.android.material.textfield.TextInputEditText
android:id="@+id/introPasswordEdit" android:id="@+id/introPasswordEdit"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
android:inputType="textPassword" android:inputType="textPassword"
android:autofillHints="password" /> android:autofillHints="password" />
</android.support.design.widget.TextInputLayout> </com.google.android.material.textfield.TextInputLayout>
<EditText <EditText
android:id="@+id/introPasswordConfirm" android:id="@+id/introPasswordConfirm"

View file

@ -10,21 +10,21 @@
android:paddingStart="@dimen/activity_margin_medium" android:paddingStart="@dimen/activity_margin_medium"
android:paddingEnd="@dimen/activity_margin_medium" > android:paddingEnd="@dimen/activity_margin_medium" >
<android.support.design.widget.TextInputLayout <com.google.android.material.textfield.TextInputLayout
android:id="@+id/passwordLayout" android:id="@+id/passwordLayout"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:hint="@string/settings_hint_password" android:hint="@string/settings_hint_password"
app:passwordToggleEnabled="true" > app:passwordToggleEnabled="true" >
<android.support.design.widget.TextInputEditText <com.google.android.material.textfield.TextInputEditText
android:id="@+id/passwordEdit" android:id="@+id/passwordEdit"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
android:inputType="textPassword" android:inputType="textPassword"
android:autofillHints="password" /> android:autofillHints="password" />
</android.support.design.widget.TextInputLayout> </com.google.android.material.textfield.TextInputLayout>
<EditText <EditText
android:id="@+id/passwordConfirm" android:id="@+id/passwordConfirm"
@ -34,7 +34,7 @@
android:inputType="textPassword" android:inputType="textPassword"
android:autofillHints="password" /> android:autofillHints="password" />
<android.support.v7.widget.ButtonBarLayout <androidx.appcompat.widget.ButtonBarLayout
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginTop="@dimen/activity_margin" android:layout_marginTop="@dimen/activity_margin"
@ -54,6 +54,6 @@
style="?android:attr/buttonBarButtonStyle" style="?android:attr/buttonBarButtonStyle"
android:text="@string/button_save" /> android:text="@string/button_save" />
</android.support.v7.widget.ButtonBarLayout> </androidx.appcompat.widget.ButtonBarLayout>
</LinearLayout> </LinearLayout>

View file

@ -17,14 +17,14 @@
android:textStyle="bold" android:textStyle="bold"
android:text="@string/auth_msg_authenticate"/> android:text="@string/auth_msg_authenticate"/>
<android.support.design.widget.TextInputLayout <com.google.android.material.textfield.TextInputLayout
android:id="@+id/passwordLayout" android:id="@+id/passwordLayout"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:hint="@string/auth_hint_password" android:hint="@string/auth_hint_password"
app:passwordToggleEnabled="true" > app:passwordToggleEnabled="true" >
<android.support.design.widget.TextInputEditText <com.google.android.material.textfield.TextInputEditText
android:id="@+id/passwordEdit" android:id="@+id/passwordEdit"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
@ -32,7 +32,7 @@
android:inputType="textPassword" android:inputType="textPassword"
android:autofillHints="password" /> android:autofillHints="password" />
<requestFocus/> <requestFocus/>
</android.support.design.widget.TextInputLayout> </com.google.android.material.textfield.TextInputLayout>
<Button <Button
android:id="@+id/buttonUnlock" android:id="@+id/buttonUnlock"

View file

@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<android.support.v4.widget.NestedScrollView <androidx.core.widget.NestedScrollView
xmlns:android="http://schemas.android.com/apk/res/android" xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/scroll_view" android:id="@+id/scroll_view"
@ -253,4 +253,4 @@
</RelativeLayout> </RelativeLayout>
</LinearLayout> </LinearLayout>
</android.support.v4.widget.NestedScrollView> </androidx.core.widget.NestedScrollView>

View file

@ -32,6 +32,27 @@
</LinearLayout> </LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_vertical"
android:orientation="horizontal" >
<TextView
android:layout_weight="3"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:text="@string/label_issuer"/>
<EditText
android:id="@+id/manual_issuer"
android:layout_weight="7"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:hint="@string/label_issuer"/>
</LinearLayout>
<LinearLayout <LinearLayout
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
@ -71,6 +92,7 @@
android:layout_width="0dp" android:layout_width="0dp"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:lines="3" android:lines="3"
android:inputType="textVisiblePassword"
android:hint="@string/hint_secret" /> android:hint="@string/hint_secret" />
</LinearLayout> </LinearLayout>

View file

@ -11,20 +11,20 @@
android:background="@null" android:background="@null"
android:padding="@dimen/activity_margin"> android:padding="@dimen/activity_margin">
<android.support.design.widget.TextInputLayout <com.google.android.material.textfield.TextInputLayout
android:id="@+id/passwordInputLayout" android:id="@+id/passwordInputLayout"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:hint="@string/dialog_label_enter_password" android:hint="@string/dialog_label_enter_password"
app:passwordToggleEnabled="true" > app:passwordToggleEnabled="true" >
<android.support.design.widget.TextInputEditText <com.google.android.material.textfield.TextInputEditText
android:id="@+id/passwordInput" android:id="@+id/passwordInput"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
android:inputType="textPassword" /> android:inputType="textPassword" />
</android.support.design.widget.TextInputLayout> </com.google.android.material.textfield.TextInputLayout>
<EditText <EditText
android:id="@+id/passwordConfirm" android:id="@+id/passwordConfirm"

View file

@ -14,7 +14,7 @@
android:clipToPadding="false" android:clipToPadding="false"
android:orientation="vertical" > android:orientation="vertical" >
<android.support.v7.widget.CardView <androidx.cardview.widget.CardView
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginTop="@dimen/activity_margin_small" android:layout_marginTop="@dimen/activity_margin_small"
@ -57,9 +57,9 @@
</LinearLayout> </LinearLayout>
</android.support.v7.widget.CardView> </androidx.cardview.widget.CardView>
<android.support.v7.widget.CardView <androidx.cardview.widget.CardView
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginTop="@dimen/activity_margin_small" android:layout_marginTop="@dimen/activity_margin_small"
@ -209,9 +209,9 @@
</LinearLayout> </LinearLayout>
</LinearLayout> </LinearLayout>
</android.support.v7.widget.CardView> </androidx.cardview.widget.CardView>
<android.support.v7.widget.CardView <androidx.cardview.widget.CardView
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginTop="@dimen/activity_margin_small" android:layout_marginTop="@dimen/activity_margin_small"
@ -249,6 +249,7 @@
android:src="@mipmap/ic_author_flocke" /> android:src="@mipmap/ic_author_flocke" />
<LinearLayout <LinearLayout
android:id="@+id/aboutLayoutAuthor1Content"
android:orientation="vertical" android:orientation="vertical"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
@ -266,16 +267,6 @@
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceSmall" android:textAppearance="?android:attr/textAppearanceSmall"
android:text="@string/about_label_main_developer"/> android:text="@string/about_label_main_developer"/>
<TextView
android:id="@+id/about_author1_extra"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/activity_margin_small"
android:background="?android:attr/selectableItemBackground"
android:textAppearance="?android:attr/textAppearanceMedium"
android:textStyle="bold"
android:text="@string/about_label_donate" />
</LinearLayout> </LinearLayout>
</LinearLayout> </LinearLayout>
@ -306,6 +297,7 @@
app:srcCompat="@drawable/ic_account_circle_gray" /> app:srcCompat="@drawable/ic_account_circle_gray" />
<LinearLayout <LinearLayout
android:id="@+id/aboutLayoutAuthor2Content"
android:orientation="vertical" android:orientation="vertical"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
@ -323,16 +315,6 @@
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceSmall" android:textAppearance="?android:attr/textAppearanceSmall"
android:text="@string/about_label_developer"/> android:text="@string/about_label_developer"/>
<TextView
android:id="@+id/about_author2_extra"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/activity_margin_small"
android:background="?android:attr/selectableItemBackground"
android:textAppearance="?android:attr/textAppearanceMedium"
android:textStyle="bold"
android:text="@string/about_label_donate" />
</LinearLayout> </LinearLayout>
</LinearLayout> </LinearLayout>
@ -428,38 +410,10 @@
</LinearLayout> </LinearLayout>
<!-- translators -->
<LinearLayout
android:id="@+id/about_layout_translators"
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="?android:attr/listPreferredItemHeight"
android:paddingTop="@dimen/activity_margin_small"
android:paddingBottom="@dimen/activity_margin_small"
android:background="?android:attr/selectableItemBackground"
android:gravity="center_vertical" >
<ImageView
android:id="@+id/aboutImgTranslators"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="@dimen/activity_margin"
android:layout_marginEnd="@dimen/activity_margin_large"
app:srcCompat="@drawable/ic_translate_gray" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/about_label_translators"
android:textStyle="bold"
android:textAppearance="?android:attr/textAppearanceMedium" />
</LinearLayout> </LinearLayout>
</androidx.cardview.widget.CardView>
</LinearLayout> <androidx.cardview.widget.CardView
</android.support.v7.widget.CardView>
<android.support.v7.widget.CardView
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginTop="@dimen/activity_margin_small" android:layout_marginTop="@dimen/activity_margin_small"
@ -467,34 +421,22 @@
style="?attr/cardStyle" > style="?attr/cardStyle" >
<LinearLayout <LinearLayout
android:layout_width="match_parent" android:id="@+id/about_layout_support"
android:layout_height="wrap_content"
android:orientation="vertical" >
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/about_title_support"/>
<!-- bug reports -->
<LinearLayout
android:id="@+id/about_layout_bugs"
android:orientation="horizontal" android:orientation="horizontal"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginTop="@dimen/activity_margin"
android:paddingTop="@dimen/activity_margin_small" android:paddingTop="@dimen/activity_margin_small"
android:paddingBottom="@dimen/activity_margin_small" android:paddingBottom="@dimen/activity_margin_small"
android:background="?android:attr/selectableItemBackground" android:background="?android:attr/selectableItemBackground"
android:gravity="center_vertical" > android:gravity="center_vertical" >
<ImageView <ImageView
android:id="@+id/aboutImgBugs" android:id="@+id/aboutImgSupport"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginStart="@dimen/activity_margin" android:layout_marginStart="@dimen/activity_margin"
android:layout_marginEnd="@dimen/activity_margin_large" android:layout_marginEnd="@dimen/activity_margin_large"
app:srcCompat="@drawable/ic_bug_report_gray" /> app:srcCompat="@drawable/ic_heart_gray" />
<LinearLayout <LinearLayout
android:orientation="vertical" android:orientation="vertical"
@ -505,7 +447,7 @@
<TextView <TextView
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:text="@string/about_label_report_bugs" android:text="@string/about_title_support"
android:textAppearance="?android:attr/textAppearanceMedium" android:textAppearance="?android:attr/textAppearanceMedium"
android:textStyle="bold" /> android:textStyle="bold" />
@ -513,57 +455,15 @@
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceSmall" android:textAppearance="?android:attr/textAppearanceSmall"
android:text="@string/about_desc_report_bugs"/> android:text="@string/about_desc_support"/>
</LinearLayout> </LinearLayout>
</LinearLayout> </LinearLayout>
<!-- translate --> </androidx.cardview.widget.CardView>
<LinearLayout
android:id="@+id/about_layout_translate"
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingTop="@dimen/activity_margin_small"
android:paddingBottom="@dimen/activity_margin_small"
android:background="?android:attr/selectableItemBackground"
android:gravity="center_vertical" >
<ImageView
android:id="@+id/aboutImgTranslate"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="@dimen/activity_margin"
android:layout_marginEnd="@dimen/activity_margin_large"
app:srcCompat="@drawable/ic_translate_gray" />
<LinearLayout
android:orientation="vertical"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center_vertical" >
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/about_label_translate"
android:textAppearance="?android:attr/textAppearanceMedium"
android:textStyle="bold" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceSmall"
android:text="@string/about_desc_translate"/>
</LinearLayout>
</LinearLayout>
</LinearLayout>
</android.support.v7.widget.CardView>
<!-- thumbnails --> <!-- thumbnails -->
<android.support.v7.widget.CardView <androidx.cardview.widget.CardView
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginTop="@dimen/activity_margin_small" android:layout_marginTop="@dimen/activity_margin_small"
@ -618,7 +518,7 @@
android:text="@string/about_thumbnails_disclaimer_no4" /> android:text="@string/about_thumbnails_disclaimer_no4" />
</LinearLayout> </LinearLayout>
</LinearLayout> </LinearLayout>
</android.support.v7.widget.CardView> </androidx.cardview.widget.CardView>
</LinearLayout> </LinearLayout>
</ScrollView> </ScrollView>

View file

@ -4,7 +4,10 @@
android:id="@+id/fabEnterDetails" android:id="@+id/fabEnterDetails"
android:title="@string/button_enter_details" android:title="@string/button_enter_details"
android:icon="@drawable/ic_edit_white" /> android:icon="@drawable/ic_edit_white" />
<item
android:id="@+id/fabScanQRFromImage"
android:title="@string/button_qr_from_image"
android:icon="@drawable/ic_image_white" />
<item <item
android:id="@+id/fabScanQR" android:id="@+id/fabScanQR"
android:title="@string/button_scan_qr" android:title="@string/button_scan_qr"

View file

@ -31,7 +31,7 @@
android:title="@string/menu_main_search" android:title="@string/menu_main_search"
android:icon="@drawable/ic_search_white" android:icon="@drawable/ic_search_white"
app:showAsAction="always|collapseActionView" app:showAsAction="always|collapseActionView"
app:actionViewClass="android.support.v7.widget.SearchView" /> app:actionViewClass="androidx.appcompat.widget.SearchView" />
<item <item
android:id="@+id/action_backup" android:id="@+id/action_backup"

View file

@ -1,6 +1,9 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"> <menu xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:id="@+id/menu_popup_editIssuer"
android:title="@string/menu_popup_edit_issuer" />
<item <item
android:id="@+id/menu_popup_editLabel" android:id="@+id/menu_popup_editLabel"
android:title="@string/menu_popup_edit_label" /> android:title="@string/menu_popup_edit_label" />

View file

@ -18,8 +18,7 @@
<string name="about_label_original_author">مؤلف التطبيق الأصلي</string> <string name="about_label_original_author">مؤلف التطبيق الأصلي</string>
<string name="about_label_original_app">التطبيق الأصلي</string> <string name="about_label_original_app">التطبيق الأصلي</string>
<string name="about_label_website">الموقع الإلكتروني</string> <string name="about_label_website">الموقع الإلكتروني</string>
<string name="about_label_donate_paypal">التبرع (Paypal)</string> <string name="about_label_donate">التبرع</string>
<string name="about_label_donate_bitcoin">التبرع (Bitcoin)</string>
<string name="about_label_contributors">المساهمون</string> <string name="about_label_contributors">المساهمون</string>
<string name="about_label_translators">المترجمون</string> <string name="about_label_translators">المترجمون</string>
<!-- Thumbnail disclaimer --> <!-- Thumbnail disclaimer -->

View file

@ -10,6 +10,7 @@
<string name="backup_title_export_openpgp">النسخ الاحتياطي (أوبن بي جي بي)</string> <string name="backup_title_export_openpgp">النسخ الاحتياطي (أوبن بي جي بي)</string>
<string name="backup_title_import_plain">إسترجاع (نص مجرّد)</string> <string name="backup_title_import_plain">إسترجاع (نص مجرّد)</string>
<string name="backup_title_import_crypt">إسترجاع (مشفّر)</string> <string name="backup_title_import_crypt">إسترجاع (مشفّر)</string>
<string name="backup_title_import_crypt_old">Restore (encrypted, old encryption)</string>
<string name="backup_title_import_openpgp">إسترجاع (أوبن بي جي بي)</string> <string name="backup_title_import_openpgp">إسترجاع (أوبن بي جي بي)</string>
<string name="backup_title_replace">إستبدال البيانات الموجودة</string> <string name="backup_title_replace">إستبدال البيانات الموجودة</string>
<string name="backup_desc_export_plain">أنسخ إحتياطيا لكافة الحسابات في ملف JSON نص مُجرَّد </string> <string name="backup_desc_export_plain">أنسخ إحتياطيا لكافة الحسابات في ملف JSON نص مُجرَّد </string>
@ -17,6 +18,8 @@
<string name="backup_desc_export_openpgp">أنسخ إحتياطيا لكافة الحسابات في ملف JSON مشفّر بواسطة أوبن بي جي بي</string> <string name="backup_desc_export_openpgp">أنسخ إحتياطيا لكافة الحسابات في ملف JSON مشفّر بواسطة أوبن بي جي بي</string>
<string name="backup_desc_import_plain">استعادة حسابات من ملف JSON نص مجرّد</string> <string name="backup_desc_import_plain">استعادة حسابات من ملف JSON نص مجرّد</string>
<string name="backup_desc_import_crypt">استعادة حسابات من ملف JSON محمي بكلمة مرور</string> <string name="backup_desc_import_crypt">استعادة حسابات من ملف JSON محمي بكلمة مرور</string>
<string name="backup_desc_import_crypt_old">Restore accounts from a password-protected JSON file
created with an <b>andOTP version lower than 0.6.3</b></string>
<string name="backup_desc_import_openpgp">استعادة حسابات من ملف JSON (مشفر بتقنية اوبن بي جي بي)</string> <string name="backup_desc_import_openpgp">استعادة حسابات من ملف JSON (مشفر بتقنية اوبن بي جي بي)</string>
<string name="backup_desc_crypt_setup">فشل في تحميل كلمة مرور النسخ الاحتياطي من الإعدادات، هذا أما يعني إنه لم يتم تعيين أية كلمة مرور أو حدث خطأ ما. سيطلب منك إدخال كلمة المرور يدوياً عند إنشاء أو استيراد نسخة احتياطية. <string name="backup_desc_crypt_setup">فشل في تحميل كلمة مرور النسخ الاحتياطي من الإعدادات، هذا أما يعني إنه لم يتم تعيين أية كلمة مرور أو حدث خطأ ما. سيطلب منك إدخال كلمة المرور يدوياً عند إنشاء أو استيراد نسخة احتياطية.
</string> </string>
@ -34,6 +37,11 @@
<string name="backup_receiver_read_permission_failed">الإذن للقراءة لم يمنح. الرجاء تمكينها قبل محاولة النسخ</string> <string name="backup_receiver_read_permission_failed">الإذن للقراءة لم يمنح. الرجاء تمكينها قبل محاولة النسخ</string>
<string name="backup_receiver_write_permission_failed">الإذن للكتابة لم يمنح. الرجاء تمكينها قبل محاولة النسخ</string> <string name="backup_receiver_write_permission_failed">الإذن للكتابة لم يمنح. الرجاء تمكينها قبل محاولة النسخ</string>
<string name="backup_receiver_custom_encryption_failed">التشفير عبر كلمة المرور / PIN غير مدعومة مع البث الإحتياطي</string> <string name="backup_receiver_custom_encryption_failed">التشفير عبر كلمة المرور / PIN غير مدعومة مع البث الإحتياطي</string>
<string name="backup_new_format_dialog_title">New encryption method</string>
<string name="backup_new_format_dialog_msg">Since version 0.6.3 of andOTP, a <b>new and improved
encryption method</b> is used for password-protected backups. The old backups can still be
imported, but it is <b>highly recommended to create new backups with the improved
encryption</b>.\n\nThis message will not be shown again.</string>
<!-- Notification channels --> <!-- Notification channels -->
<string name="notification_channel_name_backup_failed">فشل النسخ التلقائي</string> <string name="notification_channel_name_backup_failed">فشل النسخ التلقائي</string>
<string name="notification_channel_name_backup_success">نجح النسخ التلقائي</string> <string name="notification_channel_name_backup_success">نجح النسخ التلقائي</string>

View file

@ -46,7 +46,7 @@
<string name="settings_desc_backup_directory">دليل النسخ الإحتياطي (أسماء الملف يعتمدون على نوع النسخ الإحتياطي)</string> <string name="settings_desc_backup_directory">دليل النسخ الإحتياطي (أسماء الملف يعتمدون على نوع النسخ الإحتياطي)</string>
<string name="settings_desc_backup_password">إختر كلمة المرور التي سوف تستخدم لتشفير النسخ الإحتياطية</string> <string name="settings_desc_backup_password">إختر كلمة المرور التي سوف تستخدم لتشفير النسخ الإحتياطية</string>
<string name="settings_desc_backup_broadcasts">حدد أنواع النسخ الإحتياطي التي يمكن تشغيلها بواسطة تطبيقات البث</string> <string name="settings_desc_backup_broadcasts">حدد أنواع النسخ الإحتياطي التي يمكن تشغيلها بواسطة تطبيقات البث</string>
<string name="settings_desc_openpgp_key_encrypt">البريد الإلكتلتروني التابع الى مفتاح المستخدم لتشفير النسخ</string> <string name="settings_desc_openpgp_key_encrypt">عنوان البريد الإلكتروني للمفتاح المستخدَم لتشفير النسخ الإحتياطية</string>
<string name="settings_desc_openpgp_verify">النسخ المشفرة تسترد فقط إذا وقعوا بمفتاح صالح</string> <string name="settings_desc_openpgp_verify">النسخ المشفرة تسترد فقط إذا وقعوا بمفتاح صالح</string>
<string name="settings_desc_special_features">قم بإلغاء الخيار لتعطيل الميزات الخاصة مجددا</string> <string name="settings_desc_special_features">قم بإلغاء الخيار لتعطيل الميزات الخاصة مجددا</string>
<string name="settings_desc_enable_screenshot">السماح بالتقاط لقطات للشاشة الرئيسية <string name="settings_desc_enable_screenshot">السماح بالتقاط لقطات للشاشة الرئيسية

View file

@ -18,8 +18,7 @@
<string name="about_label_original_author">Autor de l\'aplicació original</string> <string name="about_label_original_author">Autor de l\'aplicació original</string>
<string name="about_label_original_app">Aplicació original</string> <string name="about_label_original_app">Aplicació original</string>
<string name="about_label_website">Lloc web</string> <string name="about_label_website">Lloc web</string>
<string name="about_label_donate_paypal">Donar (PayPal)</string> <string name="about_label_donate">Donar</string>
<string name="about_label_donate_bitcoin">Donar (Bitcoin)</string>
<string name="about_label_contributors">Col·laboradors</string> <string name="about_label_contributors">Col·laboradors</string>
<string name="about_label_translators">Traductors</string> <string name="about_label_translators">Traductors</string>
<!-- Thumbnail disclaimer --> <!-- Thumbnail disclaimer -->

View file

@ -12,8 +12,8 @@
<!-- Buttons --> <!-- Buttons -->
<string name="auth_button_unlock">Desbloqueja</string> <string name="auth_button_unlock">Desbloqueja</string>
<!-- Toast messages --> <!-- Toast messages -->
<string name="auth_toast_password_missing">Please set a password in the <b>Settings</b>!</string> <string name="auth_toast_password_missing">Per favor, establiu una contrasenya a la <b>configuració</b>!</string>
<string name="auth_toast_pin_missing">Please set a PIN in the <b>Settings</b>!</string> <string name="auth_toast_pin_missing">Per favor, establiu un PIN en la <b>configuració</b>!</string>
<string name="auth_toast_password_again">Contrasenya incorrecta; per favor, torneu-ho a intentar!</string> <string name="auth_toast_password_again">Contrasenya incorrecta; per favor, torneu-ho a intentar!</string>
<string name="auth_toast_pin_again">PIN incorrecte; per favor, torneu-ho a intentar!</string> <string name="auth_toast_pin_again">PIN incorrecte; per favor, torneu-ho a intentar!</string>
</resources> </resources>

View file

@ -10,6 +10,7 @@
<string name="backup_title_export_openpgp">Còpia de seguretat (OpenPGP)</string> <string name="backup_title_export_openpgp">Còpia de seguretat (OpenPGP)</string>
<string name="backup_title_import_plain">Restaura (text net)</string> <string name="backup_title_import_plain">Restaura (text net)</string>
<string name="backup_title_import_crypt">Restaura (xifrada)</string> <string name="backup_title_import_crypt">Restaura (xifrada)</string>
<string name="backup_title_import_crypt_old">Restaura (encriptat, encriptació vella)</string>
<string name="backup_title_import_openpgp">Restaura (OpenPGP)</string> <string name="backup_title_import_openpgp">Restaura (OpenPGP)</string>
<string name="backup_title_replace">Substitueix els comptes existents</string> <string name="backup_title_replace">Substitueix els comptes existents</string>
<string name="backup_desc_export_plain">Fes una còpia de seguretat de tots els comptes en un fitxer de text net JSON</string> <string name="backup_desc_export_plain">Fes una còpia de seguretat de tots els comptes en un fitxer de text net JSON</string>
@ -17,6 +18,8 @@
<string name="backup_desc_export_openpgp">Fes una còpia de seguretat tots els comptes en un fitxer JSON encriptat amb OpenPGP</string> <string name="backup_desc_export_openpgp">Fes una còpia de seguretat tots els comptes en un fitxer JSON encriptat amb OpenPGP</string>
<string name="backup_desc_import_plain">Restaura els comptes d\'un fitxer de text net JSON</string> <string name="backup_desc_import_plain">Restaura els comptes d\'un fitxer de text net JSON</string>
<string name="backup_desc_import_crypt">Restaura els comptes d\'un fitxer JSON protegit amb contrasenya</string> <string name="backup_desc_import_crypt">Restaura els comptes d\'un fitxer JSON protegit amb contrasenya</string>
<string name="backup_desc_import_crypt_old">Restaura el conte desde un ficher JSON protegit amb contrasenya
creat amb <b>una versió de andOTP prévia a 0.6.3</b></string>
<string name="backup_desc_import_openpgp">Restaura els comptes d\'un fitxer JSON xifrat amb OpenPGP</string> <string name="backup_desc_import_openpgp">Restaura els comptes d\'un fitxer JSON xifrat amb OpenPGP</string>
<string name="backup_desc_crypt_setup">Failed to load the backup password from the <b>Settings</b>, <string name="backup_desc_crypt_setup">Failed to load the backup password from the <b>Settings</b>,
this either means no password was set or something went wrong. You will be asked to enter this either means no password was set or something went wrong. You will be asked to enter
@ -48,6 +51,11 @@
this before attempting backup</string> this before attempting backup</string>
<string name="backup_receiver_custom_encryption_failed">Password/PIN based encryption not <string name="backup_receiver_custom_encryption_failed">Password/PIN based encryption not
supported with broadcast backup</string> supported with broadcast backup</string>
<string name="backup_new_format_dialog_title">New encryption method</string>
<string name="backup_new_format_dialog_msg">Since version 0.6.3 of andOTP, a <b>new and improved
encryption method</b> is used for password-protected backups. The old backups can still be
imported, but it is <b>highly recommended to create new backups with the improved
encryption</b>.\n\nThis message will not be shown again.</string>
<!-- Notification channels --> <!-- Notification channels -->
<string name="notification_channel_name_backup_failed">Automatic backup failed</string> <string name="notification_channel_name_backup_failed">Automatic backup failed</string>
<string name="notification_channel_name_backup_success">Automatic backup successful</string> <string name="notification_channel_name_backup_success">Automatic backup successful</string>

View file

@ -21,7 +21,7 @@
<string name="label_secret">Secret</string> <string name="label_secret">Secret</string>
<string name="label_period">Període</string> <string name="label_period">Període</string>
<string name="label_digits">Dígits</string> <string name="label_digits">Dígits</string>
<string name="label_counter">Counter</string> <string name="label_counter">Comptador</string>
<string name="label_label">Etiqueta</string> <string name="label_label">Etiqueta</string>
<string name="label_algorithm">Algorisme</string> <string name="label_algorithm">Algorisme</string>
<string name="label_tags">Etiquetes</string> <string name="label_tags">Etiquetes</string>
@ -54,21 +54,21 @@
<string name="dialog_title_manual_entry">Introduïu-ne els detalls</string> <string name="dialog_title_manual_entry">Introduïu-ne els detalls</string>
<string name="dialog_title_remove">Suprimeix</string> <string name="dialog_title_remove">Suprimeix</string>
<string name="dialog_title_rename">Canvia el nom</string> <string name="dialog_title_rename">Canvia el nom</string>
<string name="dialog_title_counter">Counter</string> <string name="dialog_title_counter">Comptador</string>
<string name="dialog_title_last_used">Últimes utilitzades</string> <string name="dialog_title_last_used">Últimes utilitzades</string>
<string name="dialog_title_keystore_error">Error al magatzem de claus</string> <string name="dialog_title_keystore_error">Error al magatzem de claus</string>
<string name="dialog_title_enter_password">Enter password</string> <string name="dialog_title_enter_password">Introduïu la contrasenya</string>
<string name="dialog_label_enter_password">Enter password</string> <string name="dialog_label_enter_password">Introduïu la contrasenya</string>
<string name="dialog_label_confirm_password">Confirm password</string> <string name="dialog_label_confirm_password">Confirmeu la contrasenya</string>
<string name="dialog_msg_auth">Per favor, introduïu les vostres credencials per a iniciar andOTP.</string> <string name="dialog_msg_auth">Per favor, introduïu les vostres credencials per a iniciar andOTP.</string>
<string name="dialog_msg_confirm_delete">Segur que voleu suprimir el compte \"%1$s\"?</string> <string name="dialog_msg_confirm_delete">Segur que voleu suprimir el compte \"%1$s\"?</string>
<string name="dialog_msg_last_used">Per tal que andOTP reconega quin testimoni va ser l\'últim <string name="dialog_msg_last_used">Per tal que andOTP reconega quin testimoni va ser l\'últim
heu d\'habilitar \"toqueu per a mostrar\" o feu servir el botó de copia.\n\nAquest missatge no tornarà heu d\'habilitar \"toqueu per a mostrar\" o feu servir el botó de copia.\n\nAquest missatge no tornarà
a aparéixer.</string> a aparéixer.</string>
<string name="dialog_msg_keystore_error">Failed to load the encryption key from the KeyStore. <string name="dialog_msg_keystore_error">No s\'ha pogut carregar la clau de xifratge del KeyStore.
<b>Any entries that are added will get lost.</b>\n\nTo still be able to use andOTP you can go <b>Qualsevol entrada que s\'hi hagin afegit es perdrà.</b>\n\nPer a continuar usant andOTP, podeu
to the <b>Settings</b> and switch the <b>Database encryption</b> to <b>Password / PIN</b>.</string> anar a la <b>Configuració</b> i canviar el <b>xifratge de la base de dades</b> a <b>Contrasenyes / PIN</b>.</string>
<!-- Shortcuts --> <!-- Shortcuts -->
<string name="shortcut_name_scan_qr">Escaneja un codi QR</string> <string name="shortcut_name_scan_qr">Escaneja un codi QR</string>
<string name="shortcut_name_enter_details">Enter details</string> <string name="shortcut_name_enter_details">Introduïu-ne els detalls</string>
</resources> </resources>

View file

@ -18,8 +18,7 @@
<string name="about_label_original_author">Autor původní aplikace</string> <string name="about_label_original_author">Autor původní aplikace</string>
<string name="about_label_original_app">Původní aplikace</string> <string name="about_label_original_app">Původní aplikace</string>
<string name="about_label_website">Webová stránka</string> <string name="about_label_website">Webová stránka</string>
<string name="about_label_donate_paypal">Podpořit přes PayPal</string> <string name="about_label_donate">Podpořit</string>
<string name="about_label_donate_bitcoin">Podpořit Bitcoinem</string>
<string name="about_label_contributors">K vývoji přispěli</string> <string name="about_label_contributors">K vývoji přispěli</string>
<string name="about_label_translators">Překladatelé</string> <string name="about_label_translators">Překladatelé</string>
<!-- Thumbnail disclaimer --> <!-- Thumbnail disclaimer -->

View file

@ -10,6 +10,7 @@
<string name="backup_title_export_openpgp">Zálohovat (OpenPGP)</string> <string name="backup_title_export_openpgp">Zálohovat (OpenPGP)</string>
<string name="backup_title_import_plain">Obnovit zálohu (nechráněnou)</string> <string name="backup_title_import_plain">Obnovit zálohu (nechráněnou)</string>
<string name="backup_title_import_crypt">Obnovit zálohu (šifrovanou)</string> <string name="backup_title_import_crypt">Obnovit zálohu (šifrovanou)</string>
<string name="backup_title_import_crypt_old">Obnova (šifrované, staré šifrování)</string>
<string name="backup_title_import_openpgp">Obnovit zálohu (OpenPGP)</string> <string name="backup_title_import_openpgp">Obnovit zálohu (OpenPGP)</string>
<string name="backup_title_replace">Nahrazovat předchozí záznamy</string> <string name="backup_title_replace">Nahrazovat předchozí záznamy</string>
<string name="backup_desc_export_plain">Zálohovat všechny účty do nechráněného souboru JSON</string> <string name="backup_desc_export_plain">Zálohovat všechny účty do nechráněného souboru JSON</string>
@ -17,6 +18,8 @@
<string name="backup_desc_export_openpgp">Zálohovat všechny účty do souboru JSON šifrovaného OpenPGP</string> <string name="backup_desc_export_openpgp">Zálohovat všechny účty do souboru JSON šifrovaného OpenPGP</string>
<string name="backup_desc_import_plain">Obnovit účty z nechráněného souboru JSON</string> <string name="backup_desc_import_plain">Obnovit účty z nechráněného souboru JSON</string>
<string name="backup_desc_import_crypt">Obnovit účty ze souboru JSON chráněného heslem</string> <string name="backup_desc_import_crypt">Obnovit účty ze souboru JSON chráněného heslem</string>
<string name="backup_desc_import_crypt_old">Obnoví účty z JSON souboru chráněného heslem,
který byl vytvořen pomocí <b>verze andOTP nižší než 0.6.3</b></string>
<string name="backup_desc_import_openpgp">Obnovit účty ze souboru JSON šifrovaného OpenPGP</string> <string name="backup_desc_import_openpgp">Obnovit účty ze souboru JSON šifrovaného OpenPGP</string>
<string name="backup_desc_crypt_setup">Nepodařilo se načíst záložní heslo z <b>Nastavení</b>, to buď znamená, že není nastaveno žádné heslo nebo něco se pokazilo. Budete vyzváni k ručnímu zadání hesla při vytváření nebo importu zálohy. <string name="backup_desc_crypt_setup">Nepodařilo se načíst záložní heslo z <b>Nastavení</b>, to buď znamená, že není nastaveno žádné heslo nebo něco se pokazilo. Budete vyzváni k ručnímu zadání hesla při vytváření nebo importu zálohy.
</string> </string>
@ -33,6 +36,10 @@
<string name="backup_receiver_read_permission_failed">Nebylo uděleno oprávnění ke čtení, prosím udělte ho před pokusem o zálohování</string> <string name="backup_receiver_read_permission_failed">Nebylo uděleno oprávnění ke čtení, prosím udělte ho před pokusem o zálohování</string>
<string name="backup_receiver_write_permission_failed">Nebylo uděleno oprávnění k zápisu, prosím udělte ho před pokusem o zálohování</string> <string name="backup_receiver_write_permission_failed">Nebylo uděleno oprávnění k zápisu, prosím udělte ho před pokusem o zálohování</string>
<string name="backup_receiver_custom_encryption_failed">Šifrování heslem/PINem není podporováno v kombinaci s automatizovaným zálohováním</string> <string name="backup_receiver_custom_encryption_failed">Šifrování heslem/PINem není podporováno v kombinaci s automatizovaným zálohováním</string>
<string name="backup_new_format_dialog_title">Nová metoda šifrování</string>
<string name="backup_new_format_dialog_msg">Od veze 0.6.3 se pro ochranu heslem používá <b>nová a vylepšená metoda šifrování</b>
Stále lze importovat staré zálohy, ale <b> velmi se doporučuje vytvořit novou zálohu s vylepšeným šifrováním</b>.
\n\nTato zpráva se již nezobrazí.</string>
<!-- Notification channels --> <!-- Notification channels -->
<string name="notification_channel_name_backup_failed">Automatické zálohování selhalo</string> <string name="notification_channel_name_backup_failed">Automatické zálohování selhalo</string>
<string name="notification_channel_name_backup_success">Automatické zálohování proběhlo úspěšně</string> <string name="notification_channel_name_backup_success">Automatické zálohování proběhlo úspěšně</string>

View file

@ -18,8 +18,7 @@
<string name="about_label_original_author">Autor der ursprünglichen App</string> <string name="about_label_original_author">Autor der ursprünglichen App</string>
<string name="about_label_original_app">Ursprüngliche App</string> <string name="about_label_original_app">Ursprüngliche App</string>
<string name="about_label_website">Webseite</string> <string name="about_label_website">Webseite</string>
<string name="about_label_donate_paypal">Spenden (PayPal)</string> <string name="about_label_donate">Spenden</string>
<string name="about_label_donate_bitcoin">Spenden (Bitcoin)</string>
<string name="about_label_contributors">Mitwirkende</string> <string name="about_label_contributors">Mitwirkende</string>
<string name="about_label_translators">Übersetzer</string> <string name="about_label_translators">Übersetzer</string>
<!-- Thumbnail disclaimer --> <!-- Thumbnail disclaimer -->

View file

@ -10,6 +10,7 @@
<string name="backup_title_export_openpgp">Datensicherung (OpenPGP)</string> <string name="backup_title_export_openpgp">Datensicherung (OpenPGP)</string>
<string name="backup_title_import_plain">Wiederherstellen (Klartext)</string> <string name="backup_title_import_plain">Wiederherstellen (Klartext)</string>
<string name="backup_title_import_crypt">Wiederherstellen (verschlüsselt)</string> <string name="backup_title_import_crypt">Wiederherstellen (verschlüsselt)</string>
<string name="backup_title_import_crypt_old">Datensicherung (verschlüsselt, alte Verschlüsselungsmethode)</string>
<string name="backup_title_import_openpgp">Wiederherstellen (OpenPGP)</string> <string name="backup_title_import_openpgp">Wiederherstellen (OpenPGP)</string>
<string name="backup_title_replace">Vorhandene Einträge ersetzen</string> <string name="backup_title_replace">Vorhandene Einträge ersetzen</string>
<string name="backup_desc_export_plain">Alle Konten in einer Klartext-JSON-Datei sichern</string> <string name="backup_desc_export_plain">Alle Konten in einer Klartext-JSON-Datei sichern</string>
@ -17,6 +18,8 @@
<string name="backup_desc_export_openpgp">Alle Konten in einer OpenPGP-verschlüsselten JSON-Datei sichern</string> <string name="backup_desc_export_openpgp">Alle Konten in einer OpenPGP-verschlüsselten JSON-Datei sichern</string>
<string name="backup_desc_import_plain">Konten aus einer Klartext-JSON-Datei wiederherstellen</string> <string name="backup_desc_import_plain">Konten aus einer Klartext-JSON-Datei wiederherstellen</string>
<string name="backup_desc_import_crypt">Konten aus einer passwortgeschützten JSON-Datei wiederherstellen</string> <string name="backup_desc_import_crypt">Konten aus einer passwortgeschützten JSON-Datei wiederherstellen</string>
<string name="backup_desc_import_crypt_old">Konten aus einer passwortgeschützten JSON-Datei wiederherstellen
erstellt mit einer <b>andOTP-Version unter 0.6.3</b></string>
<string name="backup_desc_import_openpgp">Konten aus einer OpenPGP-verschlüsselten JSON-Datei wiederherstellen</string> <string name="backup_desc_import_openpgp">Konten aus einer OpenPGP-verschlüsselten JSON-Datei wiederherstellen</string>
<string name="backup_desc_crypt_setup">Laden des Backup-Passworts aus den <b>Einstellungen</b> fehlgeschlagen, <string name="backup_desc_crypt_setup">Laden des Backup-Passworts aus den <b>Einstellungen</b> fehlgeschlagen,
was bedeutet, dass entweder kein Passwort gesetzt wurde oder etwas schiefgelaufen ist. was bedeutet, dass entweder kein Passwort gesetzt wurde oder etwas schiefgelaufen ist.
@ -40,6 +43,11 @@
zum Sichern benötigt</string> zum Sichern benötigt</string>
<string name="backup_receiver_custom_encryption_failed">Passwort/PIN Verschlüsselung ist nicht <string name="backup_receiver_custom_encryption_failed">Passwort/PIN Verschlüsselung ist nicht
unterstützt mit Broadcast Datensicherung</string> unterstützt mit Broadcast Datensicherung</string>
<string name="backup_new_format_dialog_title">Neue Verschlüsselungsmethode</string>
<string name="backup_new_format_dialog_msg">Seit Version 0.6.3 von andOTP, wird eine <b>neue und verbesserte
Verschlüsselungsmethode</b> für passwortgeschützte Datensicherungen benutzt. Alte Datensicherungen
können weiterhin importiert werden, aber es wird <b>nachdrücklich empfohlen neue Datensicherungen mit
der verbesserten Verschlüsselung zu erstellen</b>.\n\nDiese Nachricht wird nicht erneut angezeigt.</string>
<!-- Notification channels --> <!-- Notification channels -->
<string name="notification_channel_name_backup_failed">Automatische Sicherung fehlgeschlagen</string> <string name="notification_channel_name_backup_failed">Automatische Sicherung fehlgeschlagen</string>
<string name="notification_channel_name_backup_success">Automatische Sicherung erfolgreich</string> <string name="notification_channel_name_backup_success">Automatische Sicherung erfolgreich</string>

View file

@ -18,8 +18,7 @@
<string name="about_label_original_author">Autor de la aplicación original</string> <string name="about_label_original_author">Autor de la aplicación original</string>
<string name="about_label_original_app">Aplicación original</string> <string name="about_label_original_app">Aplicación original</string>
<string name="about_label_website">Página web</string> <string name="about_label_website">Página web</string>
<string name="about_label_donate_paypal">Donar (PayPal)</string> <string name="about_label_donate">Donar</string>
<string name="about_label_donate_bitcoin">Donar (Bitcoin)</string>
<string name="about_label_contributors">Contribuidores</string> <string name="about_label_contributors">Contribuidores</string>
<string name="about_label_translators">Traductores</string> <string name="about_label_translators">Traductores</string>
<!-- Thumbnail disclaimer --> <!-- Thumbnail disclaimer -->

View file

@ -10,6 +10,7 @@
<string name="backup_title_export_openpgp">Copia de seguridad (OpenPGP)</string> <string name="backup_title_export_openpgp">Copia de seguridad (OpenPGP)</string>
<string name="backup_title_import_plain">Restaurar (texto plano)</string> <string name="backup_title_import_plain">Restaurar (texto plano)</string>
<string name="backup_title_import_crypt">Restaurar (cifradas)</string> <string name="backup_title_import_crypt">Restaurar (cifradas)</string>
<string name="backup_title_import_crypt_old">Restaurar (cifrado, antiguo cifrado)</string>
<string name="backup_title_import_openpgp">Restaurar (OpenPGP)</string> <string name="backup_title_import_openpgp">Restaurar (OpenPGP)</string>
<string name="backup_title_replace">Reemplazar entradas existentes</string> <string name="backup_title_replace">Reemplazar entradas existentes</string>
<string name="backup_desc_export_plain">Hace copia de seguridad de todas las cuentas en un fichero JSON de texto plano</string> <string name="backup_desc_export_plain">Hace copia de seguridad de todas las cuentas en un fichero JSON de texto plano</string>
@ -17,6 +18,8 @@
<string name="backup_desc_export_openpgp">Hace copia de seguridad de todas las cuentas en un fichero JSON cifrado con OpenPGP</string> <string name="backup_desc_export_openpgp">Hace copia de seguridad de todas las cuentas en un fichero JSON cifrado con OpenPGP</string>
<string name="backup_desc_import_plain">Restaurar cuentas desde fichero JSON de texto plano</string> <string name="backup_desc_import_plain">Restaurar cuentas desde fichero JSON de texto plano</string>
<string name="backup_desc_import_crypt">Restaurar cuentas desde fichero JSON con contraseña</string> <string name="backup_desc_import_crypt">Restaurar cuentas desde fichero JSON con contraseña</string>
<string name="backup_desc_import_crypt_old">Restaurar cuentas de un archivo JSON protegido por contraseña
creado con una <b>versión de andOTP inferior a 0.6.3</b></string>
<string name="backup_desc_import_openpgp">Restaurar cuentas desde fichero JSON cifrado con OpenPGP</string> <string name="backup_desc_import_openpgp">Restaurar cuentas desde fichero JSON cifrado con OpenPGP</string>
<string name="backup_desc_crypt_setup">Error al cargar la contraseña del respaldo de los <b>Ajustes</b>, esto puede deberse a que no se ha establecido una contraseña o a que algo ha salido mal. Se te pedirá que ingreses la contraseña manualmente cuando crees o importes un respaldo. </string> <string name="backup_desc_crypt_setup">Error al cargar la contraseña del respaldo de los <b>Ajustes</b>, esto puede deberse a que no se ha establecido una contraseña o a que algo ha salido mal. Se te pedirá que ingreses la contraseña manualmente cuando crees o importes un respaldo. </string>
<string name="backup_desc_openpgp_provider">Necesitas instalar un proveedor de OpenPGP y activarlo <string name="backup_desc_openpgp_provider">Necesitas instalar un proveedor de OpenPGP y activarlo
@ -43,6 +46,11 @@
hazlo antes de intentar hacer una copia de seguridad</string> hazlo antes de intentar hacer una copia de seguridad</string>
<string name="backup_receiver_custom_encryption_failed">Cifrado basado en clave/PIN no <string name="backup_receiver_custom_encryption_failed">Cifrado basado en clave/PIN no
soportado en la copia de seguridad de difusión</string> soportado en la copia de seguridad de difusión</string>
<string name="backup_new_format_dialog_title">Nuevo método de cifrado</string>
<string name="backup_new_format_dialog_msg">A partir de la versión 0.6.3 de andOTP, se utiliza un <b>nuevo y mejorado
método de cifrado</b> para copias de seguridad protegidas por contraseña. Las copias de seguridad antiguas aún pueden ser
importadas, pero es <b>sumamente recomendable crear nuevas copias de seguridad con
el cifrado mejorado</b>.\n\nEste mensaje no se mostrará nuevamente.</string>
<!-- Notification channels --> <!-- Notification channels -->
<string name="notification_channel_name_backup_failed">Falló la copia de seguridad automática</string> <string name="notification_channel_name_backup_failed">Falló la copia de seguridad automática</string>
<string name="notification_channel_name_backup_success">La copia de seguridad automática se realizó con éxito</string> <string name="notification_channel_name_backup_success">La copia de seguridad automática se realizó con éxito</string>

View file

@ -7,7 +7,7 @@
\n\nNo te preocupes, siempre podrás modificar la configuración en los <b>Ajustes</b>.</string> \n\nNo te preocupes, siempre podrás modificar la configuración en los <b>Ajustes</b>.</string>
<string name="intro_slide2_desc">Para asegurar la seguridad de tus cuentas <b>andOTP</b> solo las almacena <string name="intro_slide2_desc">Para asegurar la seguridad de tus cuentas <b>andOTP</b> solo las almacena
en ficheros cifrados. Aquí puedes elegir qué método de cifrado se usará.</string> en ficheros cifrados. Aquí puedes elegir qué método de cifrado se usará.</string>
<string name="intro_slide2_desc_keystore">El almacén de claves es una herramienta de Android que permite almacenar claves criptográficas con seguridad. La ventaja de este método es que las llaves se almacenan apartadas de los archivos y pueden ser respaldadas con criptografía por hardware (si tienes un dispositivo compatible). Sin embargo, ya que las claves no se almacenan en los archivos de la aplicación, <b>este método no es compatible con copias de seguridad externas (como Titanium) </b>. Si eliges este método, te verás limitado a las copias de respaldo de <b>andOTP</b>. \n\n<b>Atención</b>: El almacén de claves suele causar problemas, por favor, evita usarlo a menos que realmente tengas que hacerlo. Si no te importa ingresar una contraseña / PIN cuando inicias <b>andOTP</b>, es <b>altamente recomendable que utilices la encriptación por contraseña</b>.</string> <string name="intro_slide2_desc_keystore">El almacén de claves es una herramienta de Android que permite almacenar claves criptográficas con seguridad. La ventaja de este método es que las llaves se almacenan apartadas de los archivos y pueden ser respaldadas con criptografía por hardware (si tienes un dispositivo compatible). Sin embargo, ya que las claves no se almacenan en los archivos de la aplicación, &lt;b&gt;este método no es compatible con copias de seguridad externas (como Titanium) &lt;/b&gt;. Si eliges este método, te verás limitado a las copias de respaldo de &lt;b&gt;andOTP&lt;/b&gt;. \n\n&lt;b&gt;Atención&lt;/b&gt;: El almacén de claves suele causar problemas, por favor, evita usarlo a menos que realmente tengas que hacerlo. Si no te importa ingresar una contraseña / PIN cuando inicias &lt;b&gt;andOTP&lt;/b&gt;, es &lt;b&gt;altamente recomendable que utilices la encriptación por contraseña&lt;b&gt;.</string>
<string name="intro_slide2_desc_password">Este método cifrará tus datos con una clave <string name="intro_slide2_desc_password">Este método cifrará tus datos con una clave
generada desde una contraseña o PIN. La ventaja principal es que funcionará con generada desde una contraseña o PIN. La ventaja principal es que funcionará con
herramientas de copia de seguridad externas (como Titanium) y da menos problemas que el almacen de claves. herramientas de copia de seguridad externas (como Titanium) y da menos problemas que el almacen de claves.

View file

@ -18,8 +18,7 @@
<string name="about_label_original_author">سازنده برنامه اصلی</string> <string name="about_label_original_author">سازنده برنامه اصلی</string>
<string name="about_label_original_app">برنامه اصلی</string> <string name="about_label_original_app">برنامه اصلی</string>
<string name="about_label_website">وب‌سایت</string> <string name="about_label_website">وب‌سایت</string>
<string name="about_label_donate_paypal">حمایت مالی (PayPal)</string> <string name="about_label_donate">حمایت مالی</string>
<string name="about_label_donate_bitcoin">حمایت مالی (Bitcoin)</string>
<string name="about_label_contributors">مشارکت‌کنندگان</string> <string name="about_label_contributors">مشارکت‌کنندگان</string>
<string name="about_label_translators">مترجمان</string> <string name="about_label_translators">مترجمان</string>
<!-- Thumbnail disclaimer --> <!-- Thumbnail disclaimer -->

View file

@ -10,6 +10,7 @@
<string name="backup_title_export_openpgp">پشتیبان‌گیری (OpenPGP)</string> <string name="backup_title_export_openpgp">پشتیبان‌گیری (OpenPGP)</string>
<string name="backup_title_import_plain">بازنشانی (متن ساده)</string> <string name="backup_title_import_plain">بازنشانی (متن ساده)</string>
<string name="backup_title_import_crypt">بازنشانی (رمزگذاری شده)</string> <string name="backup_title_import_crypt">بازنشانی (رمزگذاری شده)</string>
<string name="backup_title_import_crypt_old">بازگردانی (رمزگذاری شده، رمزگذاری قدیمی)</string>
<string name="backup_title_import_openpgp">بازنشانی (OpenPGP)</string> <string name="backup_title_import_openpgp">بازنشانی (OpenPGP)</string>
<string name="backup_title_replace">موارد موجود را جایگزین کن</string> <string name="backup_title_replace">موارد موجود را جایگزین کن</string>
<string name="backup_desc_export_plain">پشتیبان‌گیری از همه حساب‌ها در پرونده JSON متن ساده</string> <string name="backup_desc_export_plain">پشتیبان‌گیری از همه حساب‌ها در پرونده JSON متن ساده</string>
@ -17,6 +18,7 @@
<string name="backup_desc_export_openpgp">پشتیبان‌گیری از همه حساب‌ها در پرونده JSON رمزگذاری شده با OpenPGP</string> <string name="backup_desc_export_openpgp">پشتیبان‌گیری از همه حساب‌ها در پرونده JSON رمزگذاری شده با OpenPGP</string>
<string name="backup_desc_import_plain">بازنشانی از پرونده JSON متن ساده</string> <string name="backup_desc_import_plain">بازنشانی از پرونده JSON متن ساده</string>
<string name="backup_desc_import_crypt">بازنشانی از پرونده JSON رمز دار</string> <string name="backup_desc_import_crypt">بازنشانی از پرونده JSON رمز دار</string>
<string name="backup_desc_import_crypt_old">بازگردانی حساب‌خا از پرونده JSON محافظت‌شده با رمز ساخته شده با یک <b>andOTP با نسخه پایین‌تر از ۰.۶.۳</b></string>
<string name="backup_desc_import_openpgp">بازنشانی از پرونده JSON رمزگذاری شده با OpenPGP</string> <string name="backup_desc_import_openpgp">بازنشانی از پرونده JSON رمزگذاری شده با OpenPGP</string>
<string name="backup_desc_crypt_setup">شکست در بارگیری رمز عبور پشتیبان از <b>تنظیمات</b>، این به معنای عدم وجود رمز عبور است یا اشکالی پیش آمده. زمانی که شما یک پشتیبان می‌سازید یا یک پشتیبان وارد می‌کنید، از شما خواسته خواهد شد تا رمز عبور را به صورت دستی وارد کنید. </string> <string name="backup_desc_crypt_setup">شکست در بارگیری رمز عبور پشتیبان از <b>تنظیمات</b>، این به معنای عدم وجود رمز عبور است یا اشکالی پیش آمده. زمانی که شما یک پشتیبان می‌سازید یا یک پشتیبان وارد می‌کنید، از شما خواسته خواهد شد تا رمز عبور را به صورت دستی وارد کنید. </string>
<string name="backup_desc_openpgp_provider">شما نیاز دارید که یک مهیاکننده OpenPGP نصب کنید و آن را در <b>تنظیمات</b> فعال کنید تا از این قابلیت استفاده کنید. </string> <string name="backup_desc_openpgp_provider">شما نیاز دارید که یک مهیاکننده OpenPGP نصب کنید و آن را در <b>تنظیمات</b> فعال کنید تا از این قابلیت استفاده کنید. </string>
@ -32,6 +34,8 @@
<string name="backup_receiver_read_permission_failed">اجازه خواندن داده نشده، لطفا قبل از تلاش برای پشتیبان‌گیری این اجازه را بدهید</string> <string name="backup_receiver_read_permission_failed">اجازه خواندن داده نشده، لطفا قبل از تلاش برای پشتیبان‌گیری این اجازه را بدهید</string>
<string name="backup_receiver_write_permission_failed">اجازه نوشتن داده نشده، لطفا قبل از تلاش برای پشتیبان‌گیری این اجازه را بدهید</string> <string name="backup_receiver_write_permission_failed">اجازه نوشتن داده نشده، لطفا قبل از تلاش برای پشتیبان‌گیری این اجازه را بدهید</string>
<string name="backup_receiver_custom_encryption_failed">رمز عبور / پین بر اساس رمزگذاری، توسط Broadcast Backup پشتیبانی نمی‌شود</string> <string name="backup_receiver_custom_encryption_failed">رمز عبور / پین بر اساس رمزگذاری، توسط Broadcast Backup پشتیبانی نمی‌شود</string>
<string name="backup_new_format_dialog_title">روش رمزگذاری جدید</string>
<string name="backup_new_format_dialog_msg">از نسخه‌ی ۰.۶.۳ ی andOTP، <b>یک روش بهبودیافته و جدید رمزگذاری</b> برای پشتیبان‌های محافظت‌شده با رمز استفاده شده است. پشتیبان‌های قدیمی هنوز می‌توانند وارد شوند، اما <b>بسیار پیشنهاد می‌شود که از روش بهبودیافته‌ی رمزگذاری</b> استفاده کنید.\n\nاین پیام دوباره نشان داده نخواهد شد.</string>
<!-- Notification channels --> <!-- Notification channels -->
<string name="notification_channel_name_backup_failed">شکست در پشتیبان‌گیری خودکار</string> <string name="notification_channel_name_backup_failed">شکست در پشتیبان‌گیری خودکار</string>
<string name="notification_channel_name_backup_success">پشتیبان‌گیری خودکار با موفقیت انجام شد</string> <string name="notification_channel_name_backup_success">پشتیبان‌گیری خودکار با موفقیت انجام شد</string>

View file

@ -18,8 +18,7 @@
<string name="about_label_original_author">Auteur de l\'application originale</string> <string name="about_label_original_author">Auteur de l\'application originale</string>
<string name="about_label_original_app">Application originale</string> <string name="about_label_original_app">Application originale</string>
<string name="about_label_website">Site web</string> <string name="about_label_website">Site web</string>
<string name="about_label_donate_paypal">Faire un don (PayPal)</string> <string name="about_label_donate">Faire un don</string>
<string name="about_label_donate_bitcoin">Faire un don (Bitcoin)</string>
<string name="about_label_contributors">Contributeurs</string> <string name="about_label_contributors">Contributeurs</string>
<string name="about_label_translators">Traducteurs</string> <string name="about_label_translators">Traducteurs</string>
<!-- Thumbnail disclaimer --> <!-- Thumbnail disclaimer -->

View file

@ -10,6 +10,7 @@
<string name="backup_title_export_openpgp">Sauvegarde (OpenPGP)</string> <string name="backup_title_export_openpgp">Sauvegarde (OpenPGP)</string>
<string name="backup_title_import_plain">Restauration (en clair)</string> <string name="backup_title_import_plain">Restauration (en clair)</string>
<string name="backup_title_import_crypt">Restauration (chiffrée)</string> <string name="backup_title_import_crypt">Restauration (chiffrée)</string>
<string name="backup_title_import_crypt_old">Restaurer (chiffré, ancien chiffrement)</string>
<string name="backup_title_import_openpgp">Restauration (OpenPGP)</string> <string name="backup_title_import_openpgp">Restauration (OpenPGP)</string>
<string name="backup_title_replace">Remplacer les entrées existantes</string> <string name="backup_title_replace">Remplacer les entrées existantes</string>
<string name="backup_desc_export_plain">Sauvegarder tous les comptes en clair dans un fichier JSON</string> <string name="backup_desc_export_plain">Sauvegarder tous les comptes en clair dans un fichier JSON</string>
@ -17,6 +18,8 @@
<string name="backup_desc_export_openpgp">Sauvegarder tous les comptes dans un fichier JSON chiffré avec OpenPGP</string> <string name="backup_desc_export_openpgp">Sauvegarder tous les comptes dans un fichier JSON chiffré avec OpenPGP</string>
<string name="backup_desc_import_plain">Restaurer tous les comptes à partir d\'un fichier JSON en clair</string> <string name="backup_desc_import_plain">Restaurer tous les comptes à partir d\'un fichier JSON en clair</string>
<string name="backup_desc_import_crypt">Restaurer tous les comptes à partir d\'un fichier JSON protégé par un mot de passe</string> <string name="backup_desc_import_crypt">Restaurer tous les comptes à partir d\'un fichier JSON protégé par un mot de passe</string>
<string name="backup_desc_import_crypt_old">Restaurer les comptes depuis un fichier JSON protégé par un mot de passe
créé avec une version <b>andOTP inférieure à 0.6.3</b></string>
<string name="backup_desc_import_openpgp">Restaurer tous les comptes à partir d\'un fichier JSON chiffré avec OpenPGP</string> <string name="backup_desc_import_openpgp">Restaurer tous les comptes à partir d\'un fichier JSON chiffré avec OpenPGP</string>
<string name="backup_desc_crypt_setup">Le mot de passe de sauvegarde n\'a pas été chargé à partir des <b>Réglages</b>, <string name="backup_desc_crypt_setup">Le mot de passe de sauvegarde n\'a pas été chargé à partir des <b>Réglages</b>,
cela signifie soit qu\'aucun mot de passe n\'a été défini, soit que quelque chose n\'a pas fonctionné. Il vous sera demandé d\'entrer cela signifie soit qu\'aucun mot de passe n\'a été défini, soit que quelque chose n\'a pas fonctionné. Il vous sera demandé d\'entrer
@ -34,6 +37,12 @@
<string name="backup_receiver_read_permission_failed">L\'autorisation de lecture n\'est pas accordée, veuillez le faire avant deffectuer la sauvegarde</string> <string name="backup_receiver_read_permission_failed">L\'autorisation de lecture n\'est pas accordée, veuillez le faire avant deffectuer la sauvegarde</string>
<string name="backup_receiver_write_permission_failed">L\'autorisation d\'écriture n\'est pas accordée, veuillez le faire avant deffectuer la sauvegarde</string> <string name="backup_receiver_write_permission_failed">L\'autorisation d\'écriture n\'est pas accordée, veuillez le faire avant deffectuer la sauvegarde</string>
<string name="backup_receiver_custom_encryption_failed">Le chiffrement à base de mot de passe ou code PIN n\'est pas supporté par la sauvegarde par diffusion</string> <string name="backup_receiver_custom_encryption_failed">Le chiffrement à base de mot de passe ou code PIN n\'est pas supporté par la sauvegarde par diffusion</string>
<string name="backup_new_format_dialog_title">Nouvelle méthode de chiffrement</string>
<string name="backup_new_format_dialog_msg">Depuis la version 0.6.3 de andOTP, une <b>nouvelle méthode
de chiffrement améliorée</b> est utilisée pour les sauvegardres protégées par mot de passe
. Les anciennes sauvegardes peuvent jours être importées mais il est <b>hautement
recommandé de créer de nouvelles sauvegardes avec le chiffrement amélioré</b>.\n\nCe
message ne sera pas affiché une seconde fois.</string>
<!-- Notification channels --> <!-- Notification channels -->
<string name="notification_channel_name_backup_failed">Échec de la sauvegarde automatique</string> <string name="notification_channel_name_backup_failed">Échec de la sauvegarde automatique</string>
<string name="notification_channel_name_backup_success">Succès de la sauvegarde automatique</string> <string name="notification_channel_name_backup_success">Succès de la sauvegarde automatique</string>

View file

@ -4,7 +4,7 @@
<!-- Buttons --> <!-- Buttons -->
<string name="button_cancel">Annuler</string> <string name="button_cancel">Annuler</string>
<string name="button_enter_details">Ajouter les détails</string> <string name="button_enter_details">Ajouter les détails</string>
<string name="button_scan_qr">Scanner un code QR</string> <string name="button_scan_qr">Scanner un QR-Code</string>
<string name="button_save">Enregistrer</string> <string name="button_save">Enregistrer</string>
<string name="button_new_tag">Nouveau tag</string> <string name="button_new_tag">Nouveau tag</string>
<string name="button_settings">Paramètres</string> <string name="button_settings">Paramètres</string>
@ -47,7 +47,7 @@
<string name="toast_auth_failed_fatal">Échec d\'authentification, fermeture d\'andOTP !</string> <string name="toast_auth_failed_fatal">Échec d\'authentification, fermeture d\'andOTP !</string>
<string name="toast_copied_to_clipboard">Copié dans le presse-papier</string> <string name="toast_copied_to_clipboard">Copié dans le presse-papier</string>
<string name="toast_entry_exists">Cette entrée existe déjà</string> <string name="toast_entry_exists">Cette entrée existe déjà</string>
<string name="toast_invalid_qr_code">Code QR invalide</string> <string name="toast_invalid_qr_code">QR-Code invalide</string>
<string name="toast_encryption_key_empty">Clé de chiffrement non chargée</string> <string name="toast_encryption_key_empty">Clé de chiffrement non chargée</string>
<!-- Dialogs --> <!-- Dialogs -->
<string name="dialog_title_auth">Identifiez-vous</string> <string name="dialog_title_auth">Identifiez-vous</string>
@ -66,6 +66,6 @@
<string name="dialog_msg_keystore_error">Échec du chargement de la clé de chiffrement à partir de l\'armoire à clés. <string name="dialog_msg_keystore_error">Échec du chargement de la clé de chiffrement à partir de l\'armoire à clés.
<b>Toute entrée ajoutée sera perdue.</b>\n\nPour continuer à utiliser andOTP, vous pouvez aller dans les <b>paramètres</b> pour passer de <b>Chiffrement de la base de données</b> à <b>Mot de passe / Code PIN</b>.</string> <b>Toute entrée ajoutée sera perdue.</b>\n\nPour continuer à utiliser andOTP, vous pouvez aller dans les <b>paramètres</b> pour passer de <b>Chiffrement de la base de données</b> à <b>Mot de passe / Code PIN</b>.</string>
<!-- Shortcuts --> <!-- Shortcuts -->
<string name="shortcut_name_scan_qr">Scanner le code QR</string> <string name="shortcut_name_scan_qr">Scanner le QR-code</string>
<string name="shortcut_name_enter_details">Ajouter les détails</string> <string name="shortcut_name_enter_details">Ajouter les détails</string>
</resources> </resources>

View file

@ -133,8 +133,7 @@
<!-- PasswordPreference --> <!-- PasswordPreference -->
<string name="settings_hint_password">Saisir le nouveau mot de passe</string> <string name="settings_hint_password">Saisir le nouveau mot de passe</string>
<string name="settings_hint_pin">Saisir le nouveau code PIN</string> <string name="settings_hint_pin">Saisir le nouveau code PIN</string>
<string name="settings_hint_password_confirm"> <string name="settings_hint_password_confirm"> Confirmer le mot de passe
Confirmer le mot de passe
</string> </string>
<string name="settings_hint_pin_confirm">Confirmer le code PIN</string> <string name="settings_hint_pin_confirm">Confirmer le code PIN</string>
<string name="settings_label_short_password">Le mot de passe doit comporter au moins %1$d caractères !</string> <string name="settings_label_short_password">Le mot de passe doit comporter au moins %1$d caractères !</string>

View file

@ -2,7 +2,7 @@
<!--Generated by crowdin.com--> <!--Generated by crowdin.com-->
<resources> <resources>
<string name="about_activity_title">Sobre</string> <string name="about_activity_title">Sobre</string>
<string name="about_description">Autenticación de doble-factor de código aberto para Android</string> <string name="about_description">Autenticación de dobre-factor de código aberto para Android</string>
<string name="about_tab_about">Sobre</string> <string name="about_tab_about">Sobre</string>
<string name="about_tab_libraries">Librerías</string> <string name="about_tab_libraries">Librerías</string>
<!-- Misc --> <!-- Misc -->
@ -18,8 +18,7 @@
<string name="about_label_original_author">Autor do aplicativo orixinal</string> <string name="about_label_original_author">Autor do aplicativo orixinal</string>
<string name="about_label_original_app">Aplicativo orixinal</string> <string name="about_label_original_app">Aplicativo orixinal</string>
<string name="about_label_website">Páxina web</string> <string name="about_label_website">Páxina web</string>
<string name="about_label_donate_paypal">Doar (PayPal)</string> <string name="about_label_donate">Doar</string>
<string name="about_label_donate_bitcoin">Doar (Bitcoin)</string>
<string name="about_label_contributors">Colaboradores</string> <string name="about_label_contributors">Colaboradores</string>
<string name="about_label_translators">Tradutores/as</string> <string name="about_label_translators">Tradutores/as</string>
<!-- Thumbnail disclaimer --> <!-- Thumbnail disclaimer -->

View file

@ -10,6 +10,7 @@
<string name="backup_title_export_openpgp">Copia de seguranza (OpenPGP)</string> <string name="backup_title_export_openpgp">Copia de seguranza (OpenPGP)</string>
<string name="backup_title_import_plain">Restaurar (texto plano)</string> <string name="backup_title_import_plain">Restaurar (texto plano)</string>
<string name="backup_title_import_crypt">Restaurar (cifrada)</string> <string name="backup_title_import_crypt">Restaurar (cifrada)</string>
<string name="backup_title_import_crypt_old">Restaurar (cifrado, cifrado antigo)</string>
<string name="backup_title_import_openpgp">Restaurar (OpenPGP)</string> <string name="backup_title_import_openpgp">Restaurar (OpenPGP)</string>
<string name="backup_title_replace">Substituír as entradas existentes</string> <string name="backup_title_replace">Substituír as entradas existentes</string>
<string name="backup_desc_export_plain">Facer copia de seguranza de todas as contas nun ficheiro de texto plano JSON</string> <string name="backup_desc_export_plain">Facer copia de seguranza de todas as contas nun ficheiro de texto plano JSON</string>
@ -17,6 +18,8 @@
<string name="backup_desc_export_openpgp">Facer copia de seguranza de todas as contas nun ficheiro JSON cifrado con OpenPGP</string> <string name="backup_desc_export_openpgp">Facer copia de seguranza de todas as contas nun ficheiro JSON cifrado con OpenPGP</string>
<string name="backup_desc_import_plain">Restaurar contas desde un ficheiro JSON de texto plano</string> <string name="backup_desc_import_plain">Restaurar contas desde un ficheiro JSON de texto plano</string>
<string name="backup_desc_import_crypt">Restaurar contas desde un ficheiro JSON con contrasinal</string> <string name="backup_desc_import_crypt">Restaurar contas desde un ficheiro JSON con contrasinal</string>
<string name="backup_desc_import_crypt_old">Restuarar contas dun ficheiro JSON protexido por contrasinal
creado cunha <b>versión de andOTP inferior a 0.6.3</b></string>
<string name="backup_desc_import_openpgp">Restaurar contas desde un ficheiro JSON cifrado con OpenPGP</string> <string name="backup_desc_import_openpgp">Restaurar contas desde un ficheiro JSON cifrado con OpenPGP</string>
<string name="backup_desc_crypt_setup">Houbo un erro ao cargar o contrasinal de respaldo desde os <b>Axustes</b>, <string name="backup_desc_crypt_setup">Houbo un erro ao cargar o contrasinal de respaldo desde os <b>Axustes</b>,
ou ben non se estableceu o contrasinal ou algo fallou. Pediráselle introducir ou ben non se estableceu o contrasinal ou algo fallou. Pediráselle introducir
@ -47,6 +50,11 @@
arranxe esto ante de intentas o respaldo</string> arranxe esto ante de intentas o respaldo</string>
<string name="backup_receiver_custom_encryption_failed">O cifrado con Contrasinal/PIN non <string name="backup_receiver_custom_encryption_failed">O cifrado con Contrasinal/PIN non
está soportado con respaldo remoto</string> está soportado con respaldo remoto</string>
<string name="backup_new_format_dialog_title">Novo método de cifrado</string>
<string name="backup_new_format_dialog_msg">Dende a versión 0.6.3 de andOTP, úsase un <b>novo e mellorado
método de cifrado</b> para copias de seguridade protexidas por contrasinal. As copias de seguridade antigas
aínd poden ser importadas, pero é <b>moi recomendable crear novas copias de seguridade co novo cifrado
mellorado</b>.\n\nEsta mensaxe non se mostrará de novo.</string>
<!-- Notification channels --> <!-- Notification channels -->
<string name="notification_channel_name_backup_failed">Fallo no respaldo automático</string> <string name="notification_channel_name_backup_failed">Fallo no respaldo automático</string>
<string name="notification_channel_name_backup_success">Respaldo automático correcto</string> <string name="notification_channel_name_backup_success">Respaldo automático correcto</string>

View file

@ -0,0 +1,45 @@
<?xml version="1.0" encoding="utf-8"?>
<!--Generated by crowdin.com-->
<resources>
<string name="about_activity_title">Rólunk</string>
<string name="about_description">Nyílt forráskódú kétfaktoros hitelesítő Androidra</string>
<string name="about_tab_about">Rólunk</string>
<string name="about_tab_libraries">Könyvtárak</string>
<!-- Misc -->
<string name="about_label_changelog">Újdonságok</string>
<string name="about_label_license">Licensz</string>
<string name="about_label_MIT">MIT Licensz</string>
<string name="about_label_source">Forráskód</string>
<string name="about_label_version">Verzió</string>
<!-- Authors -->
<string name="about_title_authors">Készítő</string>
<string name="about_label_main_developer">Fő fejlesztők</string>
<string name="about_label_developer">Fejlesztő</string>
<string name="about_label_original_author">Az eredeti alkalmazás készítője</string>
<string name="about_label_original_app">Az eredeti alkalmazás</string>
<string name="about_label_website">Honlap</string>
<string name="about_label_donate">Adományozz</string>
<string name="about_label_contributors">Közreműködők</string>
<string name="about_label_translators">Fordítók</string>
<!-- Thumbnail disclaimer -->
<string name="about_title_thumbnail_disclaimer">Bélyegkép vélemény</string>
<string name="about_thumbnails_disclaimer_no1"><b>1.</b> Az összes bélyegkép a tulajdonosuk védjegye.</string>
<string name="about_thumbnails_disclaimer_no2"><b>2.</b> Ezen védjegyek használata nem
jelzi a védjegyjogosultnak az andOTP által történő jóváhagyását, és nem fordítva.</string>
<string name="about_thumbnails_disclaimer_no3"><b>3.</b> A bélyegképek csak arra használódnak, hogy
képviseljék azt a vállalatot vagy terméket, amelyre vonatkoznak.</string>
<string name="about_thumbnails_disclaimer_no4"><b>4. Kérjük, ne használja a bélyegképeket
más célra, kivéve az adott márkát vagy szolgáltatást.</b></string>
<!-- Support -->
<string name="about_title_support">Támogassa a fejlesztést</string>
<string name="about_label_report_bugs">Hibajelentés</string>
<string name="about_label_translate">Fordítás</string>
<string name="about_desc_report_bugs">Hibák bejelentése vagy új funkciók igénylése</string>
<string name="about_desc_translate">Segítsen lefordítani az andOTP-t az Ön nyelvére</string>
<string name="about_title_special_features">Speciális tulajdonságok</string>
<string name="about_dialog_special_features">Biztos benne hogy szeretné engedélyezni a speciális tulajdonságokat? A javuk nem szokványos OTP algoritmus melyek bekerültek különleges kérésre. Ezek <b> nem hivatalosan támogatottak </b> és <b> különböző korlátozásokkal jöhetnek </b> kérem olvassa (és értse meg) az oldalt \"Speciális tulajdonságok\" a Github
wiki-n hogy többet tudhasson meg a használatukról.</string>
<string name="about_toast_special_features">Speciális tulajdonságok engedélyezve</string>
<string name="about_toast_special_features_enabled">A speciális tulajdonságok már engedélyezve</string>
<string name="about_toast_copied_to_clipboard">Az adományozó link a vágólapra lett másolva</string>
</resources>

View file

@ -0,0 +1,18 @@
<?xml version="1.0" encoding="utf-8"?>
<!--Generated by crowdin.com-->
<resources>
<string name="auth_activity_title">Hitelesítés</string>
<!-- Hints -->
<string name="auth_hint_password">Jelszó</string>
<string name="auth_hint_pin">PIN kód</string>
<!-- Messages -->
<string name="auth_msg_authenticate">Kérem azonosítsa magát az andOTP indításához!</string>
<string name="auth_msg_confirm_encryption">Kérem erősítse meg az azonosítóját az új kulcsfájl létrehozásához!</string>
<!-- Buttons -->
<string name="auth_button_unlock">Feloldás</string>
<!-- Toast messages -->
<string name="auth_toast_password_missing">Kérem állítsa be a jelszót a <b>Beállítások</b> -ban!</string>
<string name="auth_toast_pin_missing">Kérem állítsa be a PIN kódot a <b>Beállítások</b> -ban!</string>
<string name="auth_toast_password_again">Rossz jelszó, kérem, próbálja újra!</string>
<string name="auth_toast_pin_again">Hibás PIN kód, kérem próbálja újra!</string>
</resources>

View file

@ -0,0 +1,64 @@
<?xml version="1.0" encoding="utf-8"?>
<!--Generated by crowdin.com-->
<resources>
<string name="backup_activity_title">Biztonsági mentések</string>
<string name="backup_category_plain">Egyszerű szöveges biztonsági mentések</string>
<string name="backup_category_crypt">Titkosított biztonsági mentések</string>
<string name="backup_category_openpgp">OpenPGP biztonsági mentések</string>
<string name="backup_title_export_plain">Biztonsági mentés (egyszerű szöveges)</string>
<string name="backup_title_export_crypt">Biztonsági mentés (titkosított)</string>
<string name="backup_title_export_openpgp">Biztonsági mentés (OpenPGP)</string>
<string name="backup_title_import_plain">Visszaállítás (egyszerű szöveges)</string>
<string name="backup_title_import_crypt">Visszaállítás (titkosított)</string>
<string name="backup_title_import_crypt_old">Visszaállítás (titkosított, régi titkosítás)</string>
<string name="backup_title_import_openpgp">Visszaállítás (OpenPGP)</string>
<string name="backup_title_replace">Létező bejegyzés lecserélése</string>
<string name="backup_desc_export_plain">Minden fiók biztonsági mentése egyszerű szöveges JSON fájlba</string>
<string name="backup_desc_export_crypt">Minden fiók biztonsági mentése jelszóval védett JSON fájlba</string>
<string name="backup_desc_export_openpgp">Minden fiók biztonsági mentése OpenPGP titkosított JSON fájlba</string>
<string name="backup_desc_import_plain">Minden fiók visszaállítása egyszerű szöveges JSON fájlból</string>
<string name="backup_desc_import_crypt">Minden fiók visszaállítása jelszóval titkosított JSON fájlból</string>
<string name="backup_desc_import_crypt_old">Fiókok visszaállítása jelszóval védett JSON fájlból
Létrehozva <b>andOTP 0.6.3 vagy kisebb verzióval</b></string>
<string name="backup_desc_import_openpgp">Minden fiók visszaállítása OpenPGP titkosított JSON fájlból</string>
<string name="backup_desc_crypt_setup">Nem sikerült betölteni a biztonsági mentés jelszavát a <b>Beállítások</b> -ból,
ez azt is jelentheti hogy nem volt jelszó beállítva, vagy valami rosszul sikerült. Ön meg lesz kérve a jelszó újbóli beírására a biztonsági másolat mentésekor vagy visszaállításakor. </string>
<string name="backup_desc_openpgp_provider">Telepítenie kell az OpenPGP szolgáltatót és engedélyeznie a <b>Beállítások</b> alatt a funkció használatához.
</string>
<string name="backup_desc_openpgp_keyid">Ki kell választania az OpenPGP kulcsot a <b>Beállítások</b>
alatt, mielőtt létrehozhatna titkosított biztonsági mentéseket. </string>
<string name="backup_desc_replace">Ha engedélyezve van, akkor az összes régi bejegyzést helyettesíti, ha egy biztonsági másolatot importál, és csak a biztonsági mentés van jelen. Ha le van tiltva, a régi bejegyzések és a biztonsági mentések tartalma összeolvad.</string>
<!-- Dialogs -->
<string name="backup_dialog_title_security_warning">Biztonsági figyelmeztetés</string>
<string name="backup_dialog_msg_export_warning">Biztosan szeretné exportálni az adatbázist egyszerű szöveges JSON fájlként? Ez a fájl tartalmazza az összes kulcsot, kérem tartsa <b>biztonságban</b>! </string>
<string name="backup_receiver_title_backup_failed">Sikertelen mentés</string>
<string name="backup_receiver_title_backup_success">A mentés sikerült</string>
<string name="backup_receiver_plain_disabled">Az egyszerű szöveges biztonsági mentések nem engedélyezettek, kérem menjen a Beállításokba engedélyezni őket</string>
<string name="backup_receiver_encrypted_disabled">A titkosított biztonsági mentések nem engedélyezettek, kérem menjen a Beállításokba engedélyezni őket</string>
<string name="backup_receiver_read_permission_failed">Az olvasási engedély nincs jóváhagyva, kérem engedélyezze mielőtt biztonsági mentést hozna létre</string>
<string name="backup_receiver_write_permission_failed">Az írási engedély nincs jóváhagyva, kérem engedélyezze mielőtt biztonsági mentést hozna létre</string>
<string name="backup_receiver_custom_encryption_failed">A jelszó/PIN kód általi titkosítás nem támogatott közvetítő biztonsági mentéssel</string>
<string name="backup_new_format_dialog_title">Új titkosítási mód</string>
<string name="backup_new_format_dialog_msg">Az andOTP 0.6.3 verziója óta az<b> új és továbbfejlesztett
titkosítási eljárás</b>a jelszók titkosítására használt. A régi mentések továbbra is
importálhatóak de <b>erősen ajánlott új biztonsági mentések létrehozására a továbbfejlesztett
titkosítással</b>.\n\nEz az üzenet nem jelenik meg újra.</string>
<!-- Notification channels -->
<string name="notification_channel_name_backup_failed">Az automatikus biztonsági mentés sikertelen</string>
<string name="notification_channel_name_backup_success">Az automatikus biztonsági mentés sikeres</string>
<string name="notification_channel_desc_backup_failed">Ezek az értesítések látszódnak ha a biztonsági mentés nem sikerül valamilyen okból</string>
<string name="notification_channel_desc_backup_success">Ezek az értesítések látszódnak ha a biztonsági mentés sikerül</string>
<!-- Toast messages -->
<string name="backup_toast_mkdir_failed">Nem sikerült létrehozni a mappát</string>
<string name="backup_toast_export_success">A memória kártyára történő exportálás sikeres volt</string>
<string name="backup_toast_export_failed">A memória kártyára történő exportálás sikertelen volt</string>
<string name="backup_toast_import_success">A memória kártyára történő importálás sikeres volt</string>
<string name="backup_toast_import_save_failed">Nem sikerült elmenteni a bejegyzéseket</string>
<string name="backup_toast_import_decryption_failed">A biztonsági másolat dekódolása sikertelen</string>
<string name="backup_toast_import_no_entries">Nem található bejegyzés az importált adatokban</string>
<string name="backup_toast_storage_not_accessible">A memória kártya jelenleg nem érhető el</string>
<string name="backup_toast_storage_permissions">Nincsenek engedélyezve a tárolók engedélyei</string>
<string name="backup_toast_openpgp_error">OpenPGP hiba: %s</string>
<string name="backup_toast_openpgp_not_verified">Nem hitelesített aláírás észlelve</string>
<string name="backup_toast_crypt_password_not_set">A jelszó nincs beállítva, ellenőrizze a <b>Beállítások</b> alatt</string>
</resources>

View file

@ -0,0 +1,19 @@
<?xml version="1.0" encoding="utf-8"?>
<!--Generated by crowdin.com-->
<resources>
<string name="intro_slide1_title">Lássunk neki</string>
<string name="intro_slide1_desc">Üdvözöl az <b>andOTP</b>, ez a varázsló végig fog vezetni az általános beállításokon. Kérem olvassa el figyelmesen máskülönben adatot veszíthet!
\n\nNe aggódjon, ezeket a beállításokat később megváltoztathatja a <b>Beállítások</b> alatt.</string>
<string name="intro_slide2_desc">Hogy biztosítsa önt a fiókjai biztonságáról az <b>andOTP</b> csakis titkosítva tárolja az adatokat. Itt kiválaszthatja melyik módszert kívánja használni.</string>
<string name="intro_slide2_desc_keystore">A KeyStore az Android rendszerkomponense a kriptográfiai kulcsok biztonságos tárolásához. Ennek a módszernek az az előnye, hogy a kulcsokat az adatfájloktól elkülönítve tároljuk, és hardveres titkosítással (ha a készülék támogatja). Mivel azonban a kulcsok nem tárolódnak az alkalmazásadatokkal, a <b> ez a módszer megakadályozza a külső biztonsági megoldások (például a Titanium) használatát </b>. Ha ezt a módszert választja, az <b> andOTP </b> által biztosított belső biztonsági mentési funkciókra kell támaszkodnia. n\n\ <b> Figyelmeztetés: </b>: A KeyStore-ról ismert, hogy sok problémát okoz, kérjük, csak akkor használja, ha feltétlenül szükség van rá. Ha nem bánja a jelszót / PIN-kódot minden alkalommal, amikor elindítja az <b> andOTP </b> programot, akkor <b> ajánlott a jelszó alapú titkosítás használata </b>.</string>
<string name="intro_slide2_desc_password">Ez a módszer titkosítja az adatokat egy jelszóval vagy PIN-kóddal létrehozott kulccsal. A fő előnye, hogy ez külső biztonsági megoldásokkal (például a Titaniummal) működik, és sokkal kevésbé hajlamos a hibákra mint a KeyStore. Az <b> andOTP </b> elindításakor azonban meg kell adnia hitelesítő adatait.</string>
<string name="intro_slide3_desc_keystore">Itt beállíthat egy hitelesítést az <b> andOTP </b> zárolásához. Mivel titkosítási módként a <b> Android KeyStore </b> lehetőséget választotta, ez nem kötelező.</string>
<string name="intro_slide3_desc_password">Itt beállíthat egy hitelesítést az <b> andOTP </b> zárolásához. Mivel titkosítási módként a <b> Jelszó / PIN kód </b> lehetőséget választotta, a folytatáshoz jelszót vagy PIN-kódot kell beállítania.</string>
<string name="intro_slide3_warn_no_password">Kérem állítsa be a jelszót a folytatáshoz!</string>
<string name="intro_slide3_warn_no_pin">Kérem állítsa be PIN kódot a folytatáshoz!</string>
<string name="intro_slide3_warn_confirm_password">Kérem erősítse meg a jelszavát a folytatáshoz!</string>
<string name="intro_slide3_warn_confirm_pin">Kérem erősítse meg a PIN kódját a folytatáshoz!</string>
<string name="intro_slide4_title">Kész</string>
<string name="intro_slide4_desc">Az ön beállításai mentésre kerültek, minden be van állítva és elkezdheti az
<b>andOTP</b> használatát!</string>
</resources>

View file

@ -0,0 +1,72 @@
<?xml version="1.0" encoding="utf-8"?>
<!--Generated by crowdin.com-->
<resources>
<!-- Buttons -->
<string name="button_cancel">Mégsem</string>
<string name="button_enter_details">Adja meg a részleteket</string>
<string name="button_scan_qr">QR kód beolvasása</string>
<string name="button_save">Mentés</string>
<string name="button_new_tag">Új címke</string>
<string name="button_settings">Beállítások</string>
<string name="button_all_tags">Összes címke</string>
<string name="button_no_tags">Nincs címke</string>
<!-- Custom formatting -->
<string name="format_custom_period">%d másodperc</string>
<!-- Hints -->
<string name="hint_label">Címke</string>
<string name="hint_secret">Titkos</string>
<!-- Labels -->
<string name="label_hidden">Rejtett</string>
<string name="label_type">Típus</string>
<string name="label_secret">Titkos</string>
<string name="label_period">Időtartam</string>
<string name="label_digits">Számok</string>
<string name="label_counter">Számláló</string>
<string name="label_label">Cím</string>
<string name="label_algorithm">Algoritmus</string>
<string name="label_tags">Cimkék</string>
<string name="label_advanced">Haladó beállítások</string>
<!-- Drawer -->
<string name="drawer_open">Cimkék megjelenítése</string>
<string name="drawer_close">Címkék elrejtése</string>
<!-- Menu -->
<string name="menu_main_about">Rólunk</string>
<string name="menu_main_backup">Biztonsági mentés</string>
<string name="menu_main_search">Keresés</string>
<string name="menu_main_settings">Beállítások</string>
<string name="menu_main_sort">Rendezés</string>
<string name="menu_sort_none">Rendezetlen</string>
<string name="menu_sort_label">Cím</string>
<string name="menu_sort_last_used">Utoljára használt</string>
<string name="menu_popup_edit_label">Cím szerkesztése</string>
<string name="menu_popup_change_image">Kép módosítása</string>
<string name="menu_popup_edit_tags">Címkék szerkesztése</string>
<string name="menu_popup_remove">Eltávolítás</string>
<!-- Toast messages -->
<string name="toast_auth_failed">A hitelesítés nem sikerült. Kérem próbáld újra!</string>
<string name="toast_auth_failed_fatal">A hitelesítés sikertelen, az andOTP bezárul!</string>
<string name="toast_copied_to_clipboard">Vágólapra másolva</string>
<string name="toast_entry_exists">Ez a bejegyzés már létezik</string>
<string name="toast_invalid_qr_code">Hibás QR kód</string>
<string name="toast_encryption_key_empty">A titkosítási kulcs nem töltődött be</string>
<!-- Dialogs -->
<string name="dialog_title_auth">Hitelesítés</string>
<string name="dialog_title_manual_entry">Adja meg a részleteket</string>
<string name="dialog_title_remove">Eltávolítás</string>
<string name="dialog_title_rename">Átnevezés</string>
<string name="dialog_title_counter">Számláló</string>
<string name="dialog_title_last_used">Utoljára használt</string>
<string name="dialog_title_keystore_error">KeyStore hiba</string>
<string name="dialog_title_enter_password">Jelszó megadása</string>
<string name="dialog_label_enter_password">Jelszó megadása</string>
<string name="dialog_label_confirm_password">Jelszó megerősítése</string>
<string name="dialog_msg_auth">Kérjük, adja meg a készülék hitelesítő adatait az andOTP indításához.</string>
<string name="dialog_msg_confirm_delete">Biztosan törölni szeretné a %1$s\" fiókot?</string>
<string name="dialog_msg_last_used">Annak érdekében, hogy az andOTP felismerje, hogy melyik tokent használták utoljára, engedélyeznie kell a \"érintés általi felfedést\", vagy használja a másolás gombot. \n\nEz az üzenet nem jelenik meg újra.</string>
<string name="dialog_msg_keystore_error">Nem sikerült betölteni a titkosítási kulcsot a KeyStore-ból.
<b> Az újonnan hozzáadott bejegyzések eltűnnek. </b> \n\nHa továbbra is használni szeretné az andOTP-t,
akkor a <b> Beállítások </b> alatt, leválthatja <b> Adatbázis-titkosítást </b> <b> Jelszó / PIN kódra</b>.</string>
<!-- Shortcuts -->
<string name="shortcut_name_scan_qr">QR kód beolvasása</string>
<string name="shortcut_name_enter_details">Adja meg a részleteket</string>
</resources>

View file

@ -0,0 +1,129 @@
<?xml version="1.0" encoding="utf-8"?>
<!--Generated by crowdin.com-->
<resources>
<string name="settings_activity_title">Beállítások</string>
<!-- Categories -->
<string name="settings_category_title_security">Biztonság</string>
<string name="settings_category_title_ui">Felhasználói felület</string>
<string name="settings_category_title_backup">Biztonsági mentés</string>
<!-- Titles -->
<string name="settings_title_tap_to_reveal">Érintse meg a felfedéshez</string>
<string name="settings_title_tap_to_reveal_timeout">Az Érintse meg a felfedés időtúllépése</string>
<string name="settings_title_auth">Hitelesítés</string>
<string name="settings_title_auth_password">Jelszó</string>
<string name="settings_title_auth_pin">PIN kód</string>
<string name="settings_title_encryption">Adatbázis titkosítás</string>
<string name="settings_title_panic">Pánik kioldás</string>
<string name="settings_title_relock_screen_off">Lezárás a kijelző kikapcsolásakor</string>
<string name="settings_title_lang">Nyelv</string>
<string name="settings_title_theme">Téma</string>
<string name="settings_title_label_size">Cím betűmérete</string>
<string name="settings_title_label_scroll">Cím görgetése</string>
<string name="settings_title_thumbnail_size_ask">Bélyegkép méret</string>
<string name="settings_title_split_group_size">Token elválasztása üres hellyel</string>
<string name="settings_title_tag_functionality">Címke kiválasztás viselkedése</string>
<string name="settings_title_backup_append_date">Dátum hozzáadása a fájlnévhez</string>
<string name="settings_title_backup_ask">Fájlnév kérése</string>
<string name="settings_title_backup_directory">Biztonsági mentés mappája</string>
<string name="settings_title_backup_password">Biztonsági mentés jelszava</string>
<string name="settings_title_backup_broadcasts">Közvetítés biztonsági mentése</string>
<string name="settings_title_openpgp_provider">OpenPGP szolgáltató</string>
<string name="settings_title_openpgp_key_encrypt">OpenPGP titkosítási kulcs</string>
<string name="settings_title_openpgp_key_sign">OpenPGP aláíró kulcs (opcionális)</string>
<string name="settings_title_openpgp_verify">Titkosított biztonsági másolatok hitelesítése</string>
<string name="settings_title_special_features">Speciális funkciók engedélyezése</string>
<string name="settings_title_enable_screenshot">Képernyőmentés engedélyezése</string>
<string name="settings_title_enable_android_backup_service">Az Android sync engedélyezése</string>
<string name="settings_title_clear_keystore">A KeyStore törlése</string>
<!-- Descriptions -->
<string name="settings_desc_tap_to_reveal">Az OTP tokenek elrejtése alapértelmezetten, manuálisan fedhetőek fel</string>
<string name="settings_desc_tap_to_reveal_timeout">Válassza ki az időt (másodpercekben) miután a felfedett bejegyzések újra eltünnek</string>
<string name="settings_desc_panic">Határozza meg hogy mi történik a Pánik kioldáskor</string>
<string name="settings_desc_relock_screen_off">Hitelesítés kérése miután a készülék kijelzője kikapcsol</string>
<string name="settings_desc_label_scroll">Görgesse a hosszabb címkéket, ne pedig letörje a végüket</string>
<string name="settings_desc_backup_append_date">Adja hozzá a jelenlegi időt a javasolt biztonsági mentés nevéhez</string>
<string name="settings_desc_backup_ask">Fájl nevének kérése minden alkalommal amikor biztonsági mentés jön létre vagy állítódik vissza</string>
<string name="settings_desc_backup_directory">A biztonsági mentések mappája ( a fájlnevek a biztonsági mentés típusától fognak függeni)</string>
<string name="settings_desc_backup_password">Állítsa be a jelszót amit a biztonsági mentések titkosításához használ</string>
<string name="settings_desc_backup_broadcasts">Jelölje ki, hogy melyik biztonsági másolat típusokat indíthatja el a harmadik féltől származó alkalmazás a Broadcasts segítségével</string>
<string name="settings_desc_openpgp_key_encrypt">A biztonsági mentések titkosításához használt OpenPGP-kulcs e-mail címe</string>
<string name="settings_desc_openpgp_verify">A titkosított biztonsági másolatokat csak akkor lehet importálni, ha érvényes kulccsal írnak alá</string>
<string name="settings_desc_special_features">Törölje a jelölést, hogy ismét kikapcsolja a speciális funkciókat</string>
<string name="settings_desc_enable_screenshot">Lehetővé teszi a főképernyőképek készítését (alapértelmezés szerint letiltva biztonsági okokból)</string>
<string name="settings_desc_enable_android_backup_service">Lehetővé teszi az andOTP számára az Android beépített biztonsági mentési szolgáltatás használatát a kulcsok és tulajdonságok mentéséhez</string>
<string name="settings_desc_clear_keystore">Törölje a titkosítási kulcsot a KeyStore-ból</string>
<!-- Toasts -->
<string name="settings_toast_auth_device_pre_lollipop">Ehhez a funkcióhoz legalább Android 5.0 (Lollipop) szükséges</string>
<string name="settings_toast_auth_device_not_secure">Ezen funkció használatához biztonságos képernyőzár
szükséges (Beállítások -&gt; Biztonság -&gt; Képernyőzár)</string>
<string name="settings_toast_password_empty">Egy üres jelszó nem engedélyezett, állítsa a Hitelesítést \"Nincs\" értékre, hogy letiltsa!</string>
<string name="settings_toast_encryption_changing">Próbáljuk megváltoztatni az adatbázis titkosítását, kérjük várjon!</string>
<string name="settings_toast_encryption_change_success">Sikeresen megváltoztatta az adatbázis titkosítását!</string>
<string name="settings_toast_encryption_change_failed">Nem sikerült megváltoztatni az adatbázis titkosítását, visszaállt az eredeti állapotba!</string>
<string name="settings_toast_encryption_backup_failed">Nem sikerült belső biztonsági mentést létrehozni, megszakítás!</string>
<string name="settings_toast_encryption_no_key">Sikertelen a titkosítási kulcs elérése, megszakítás!</string>
<string name="settings_toast_encryption_auth_failed">A hitelesítés sikertelen!</string>
<string name="settings_toast_auth_upgrade_failed">Nem sikerült a jelszó / PIN-kód frissítése csendesen az új titkosításra, kérjük, kézzel állítsa vissza a beállításokban!</string>
<string name="settings_dialog_title_warning">Figyelem</string>
<string name="settings_dialog_title_error">Hiba</string>
<string name="settings_dialog_title_clear_keystore">A KeyStore törlése?</string>
<string name="settings_dialog_title_android_sync">Android sync</string>
<string name="settings_dialog_msg_encryption_change">az andOTP most megpróbálja megváltoztatni az adatbázis titkosítását. Meghibásodás esetén a belső biztonsági mentés visszaáll, és a titkosítás változatlan marad \n\n <b> Mindig jó ötlet, ha van egy biztonsági mentés, ha valami váratlan történik! </b></string>
<string name="settings_dialog_msg_auth_invalid_with_encryption">Csak akkor használhatja a jelszót vagy a PIN-kódot, amíg az adatbázis-titkosítás beállítása \"Jelszó / PIN kód\"!</string>
<string name="settings_dialog_msg_encryption_invalid_with_auth">Először be kell állítania a hitelesítést \"Jelszó\" vagy \"PIN kód\" -ra!</string>
<string name="settings_dialog_msg_encryption_invalid_without_credentials">A titkosítás megváltoztatása előtt először be kell állítania egy jelszót vagy a PIN-kódot!</string>
<string name="settings_dialog_msg_clear_keystore_password">Egyes esetekben a KeyStore törlése segít megoldani a problémákat. Csak akkor folytassa, ha tudja, hogy mit csinál!\n\nMert az <b> Adatbázis titkosítás </b> beállítása <b> Jelszó / PIN kód </b>, nem szabad elveszíteni ezt az adatot (de egyébként soha nem fáj ha van egybiztonsági mentés.) \n\n <b> Valóban biztos, hogy törölni szeretné a KeyStore-t? </b></string>
<string name="settings_dialog_msg_clear_keystore_keystore">Egyes esetekben a KeyStore törlése segít megoldani a problémákat. Csak akkor folytassa, ha tudja, mit csinál!\n\n<b>Figyelem</b>:
Mivel az <b> Adatbázis titkosítás</b> <b> Android KeyStore</b> -ra van beállítva, így elveszíti az összes fiókját. Győződjön meg róla, hogy van egy biztonsági mentése!\n\n<b>Biztosan szeretné törölni a KeyStore-t?</b></string>
<string name="settings_dialog_msg_android_sync_disabled_encryption">Az Android szinkronizálás nem használható a KeyStore titkosítással, <b> manuális biztonsági mentést kell készítenie! </b></string>
<!-- List entries -->
<string-array name="settings_entries_auth">
<item>Semmi</item>
<item>Jelszó</item>
<item>PIN kód</item>
<item>Készülék adatai</item>
</string-array>
<string-array name="settings_entries_encryption">
<item>Android KeyStore</item>
<item>Jelszó / PIN kód</item>
</string-array>
<string-array name="settings_entries_panic">
<item>Összes fiók törlése</item>
<item>Beállítások visszaállítása</item>
</string-array>
<string-array name="settings_entries_theme">
<item>Világos téma</item>
<item>Sötét téma</item>
<item>Fekete téma</item>
</string-array>
<string-array name="settings_entries_thumbnail_size">
<item>Rejtett</item>
<item>Kicsi</item>
<item>Alapértelmezett</item>
<item>Közepes</item>
<item>Nagy</item>
</string-array>
<string-array name="settings_entries_split_group_size">
<item>Ne válassza szét</item>
<item>Két karakter után</item>
<item>Három karakter után</item>
</string-array>
<string-array name="settings_entries_tag_functionality">
<item>A kiválasztott címkéknek <b> bármely </b> megfelelő bejegyzésének megjelenítése (vagy)</item>
<item>Csak a kiválasztott címkéknek <b> bármely </b> megfelelő bejegyzésének megjelenítése (vagy)</item>
<item>Váltás a címkék között (egyszerre csak egy címkét lehet kiválasztani)</item>
</string-array>
<string-array name="settings_entries_backup_broadcasts">
<item>Egyszerű szöveges biztonsági mentések</item>
<item>Titkosított biztonsági mentések</item>
</string-array>
<!-- Special -->
<string name="settings_lang_sys_default">Rendszer alapértelmezett</string>
<!-- PasswordPreference -->
<string name="settings_hint_password">Adja meg az új jelszót</string>
<string name="settings_hint_pin">Új PIN kód megadása</string>
<string name="settings_hint_password_confirm">Jelszó megerősítése</string>
<string name="settings_hint_pin_confirm">PIN kód megerősítése</string>
<string name="settings_label_short_password">A jelszó legalább %1$d karakter hosszú legyen!</string>
<string name="settings_label_short_pin">A PIN kód legalább %1$d karakter hosszú legyen!</string>
</resources>

Some files were not shown because too many files have changed in this diff Show more