diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index b1c5a0f1..1d358590 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -3,58 +3,57 @@
xmlns:tools="http://schemas.android.com/tools"
package="com.beemdevelopment.aegis">
-
+
-
-
+
+
+ tools:ignore="GoogleAppIndexingWarning"
+ tools:replace="android:theme">
+
-
-
+
+
+
-
+ android:theme="@style/AppTheme.Fullscreen" />
-
+ android:theme="@style/AppTheme.NoActionBar" />
-
-
-
-
-
+ android:name=".ui.IntroActivity"
+ android:theme="@style/Theme.Intro" />
+
+
-
+ android:theme="@style/AppTheme.TransparentActionBar" />
-
+ android:theme="@style/AppTheme.TransparentActionBar" />
-
+
+
\ No newline at end of file
diff --git a/app/src/main/java/com/beemdevelopment/aegis/helpers/FabScrollHelper.java b/app/src/main/java/com/beemdevelopment/aegis/helpers/FabScrollHelper.java
new file mode 100644
index 00000000..b703ba01
--- /dev/null
+++ b/app/src/main/java/com/beemdevelopment/aegis/helpers/FabScrollHelper.java
@@ -0,0 +1,49 @@
+package com.beemdevelopment.aegis.helpers;
+
+import android.animation.Animator;
+import android.animation.AnimatorListenerAdapter;
+import android.view.View;
+import android.view.animation.AccelerateInterpolator;
+import android.view.animation.DecelerateInterpolator;
+import androidx.coordinatorlayout.widget.CoordinatorLayout;
+import com.getbase.floatingactionbutton.FloatingActionsMenu;
+
+public class FabScrollHelper {
+ private View _fabMenu;
+ private boolean _isAnimating;
+
+ public FabScrollHelper(View floatingActionsMenu) {
+ _fabMenu = floatingActionsMenu;
+ }
+
+ public void onScroll(int dx, int dy) {
+ if (dy > 0 && _fabMenu.getVisibility() == View.VISIBLE && !_isAnimating) {
+ _isAnimating = true;
+ CoordinatorLayout.LayoutParams lp = (CoordinatorLayout.LayoutParams) _fabMenu.getLayoutParams();
+ int fabBottomMargin = lp.bottomMargin;
+ _fabMenu.animate()
+ .translationY(_fabMenu.getHeight() + fabBottomMargin)
+ .setInterpolator(new AccelerateInterpolator(2))
+ .setListener(new AnimatorListenerAdapter() {
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ _isAnimating = false;
+ _fabMenu.setVisibility(View.INVISIBLE);
+ super.onAnimationEnd(animation);
+ }
+ }).start();
+ } else if (dy < 0 && _fabMenu.getVisibility() != View.VISIBLE && !_isAnimating) {
+ _fabMenu.setVisibility(View.VISIBLE);
+ _fabMenu.animate()
+ .translationY(0)
+ .setInterpolator(new DecelerateInterpolator(2))
+ .setListener(new AnimatorListenerAdapter() {
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ _isAnimating = false;
+ super.onAnimationEnd(animation);
+ }
+ }).start();
+ }
+ }
+}
diff --git a/app/src/main/java/com/beemdevelopment/aegis/ui/MainActivity.java b/app/src/main/java/com/beemdevelopment/aegis/ui/MainActivity.java
index e6957393..23ed1904 100644
--- a/app/src/main/java/com/beemdevelopment/aegis/ui/MainActivity.java
+++ b/app/src/main/java/com/beemdevelopment/aegis/ui/MainActivity.java
@@ -30,6 +30,7 @@ import com.beemdevelopment.aegis.db.DatabaseEntry;
import com.beemdevelopment.aegis.db.DatabaseFileCredentials;
import com.beemdevelopment.aegis.db.DatabaseManager;
import com.beemdevelopment.aegis.db.DatabaseManagerException;
+import com.beemdevelopment.aegis.helpers.FabScrollHelper;
import com.beemdevelopment.aegis.helpers.PermissionHelper;
import com.beemdevelopment.aegis.otp.GoogleAuthInfo;
import com.beemdevelopment.aegis.otp.GoogleAuthInfoException;
@@ -79,7 +80,7 @@ public class MainActivity extends AegisActivity implements EntryListView.Listene
private FloatingActionsMenu _fabMenu;
private EntryListView _entryListView;
- private boolean _isAnimating;
+ private FabScrollHelper _fabScrollHelper;
@Override
protected void onCreate(Bundle savedInstanceState) {
@@ -118,6 +119,8 @@ public class MainActivity extends AegisActivity implements EntryListView.Listene
_fabMenu.collapse();
startScanActivity();
});
+
+ _fabScrollHelper = new FabScrollHelper(_fabMenu);
}
@Override
@@ -622,33 +625,6 @@ public class MainActivity extends AegisActivity implements EntryListView.Listene
@Override
public void onScroll(int dx, int dy) {
- if (dy > 0 && _fabMenu.getVisibility() == View.VISIBLE && !_isAnimating) {
- _isAnimating = true;
- CoordinatorLayout.LayoutParams lp = (CoordinatorLayout.LayoutParams) _fabMenu.getLayoutParams();
- int fabBottomMargin = lp.bottomMargin;
- _fabMenu.animate()
- .translationY(_fabMenu.getHeight() + fabBottomMargin)
- .setInterpolator(new AccelerateInterpolator(2))
- .setListener(new AnimatorListenerAdapter() {
- @Override
- public void onAnimationEnd(Animator animation) {
- _isAnimating = false;
- _fabMenu.setVisibility(View.INVISIBLE);
- super.onAnimationEnd(animation);
- }
- }).start();
- } else if (dy < 0 && _fabMenu.getVisibility() != View.VISIBLE && !_isAnimating) {
- _fabMenu.setVisibility(View.VISIBLE);
- _fabMenu.animate()
- .translationY(0)
- .setInterpolator(new DecelerateInterpolator(2))
- .setListener(new AnimatorListenerAdapter() {
- @Override
- public void onAnimationEnd(Animator animation) {
- _isAnimating = false;
- super.onAnimationEnd(animation);
- }
- }).start();
- }
+ _fabScrollHelper.onScroll(dx, dy);
}
}
diff --git a/app/src/main/java/com/beemdevelopment/aegis/ui/PreferencesFragment.java b/app/src/main/java/com/beemdevelopment/aegis/ui/PreferencesFragment.java
index 7eb82b2a..8dba38bb 100644
--- a/app/src/main/java/com/beemdevelopment/aegis/ui/PreferencesFragment.java
+++ b/app/src/main/java/com/beemdevelopment/aegis/ui/PreferencesFragment.java
@@ -2,15 +2,11 @@ package com.beemdevelopment.aegis.ui;
import android.Manifest;
import android.app.Activity;
-import android.content.ClipData;
-import android.content.ClipboardManager;
-import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.media.MediaScannerConnection;
import android.net.Uri;
import android.os.Bundle;
-import android.text.TextUtils;
import android.view.Window;
import android.view.WindowManager;
import android.widget.Toast;
@@ -42,7 +38,6 @@ import com.beemdevelopment.aegis.importers.DatabaseImporterException;
import com.beemdevelopment.aegis.importers.DatabaseImporterResult;
import com.beemdevelopment.aegis.ui.preferences.SwitchPreference;
import com.beemdevelopment.aegis.util.ByteInputStream;
-import com.google.android.material.snackbar.Snackbar;
import com.takisoft.preferencex.PreferenceFragmentCompat;
import com.topjohnwu.superuser.Shell;
@@ -52,7 +47,6 @@ import java.io.InputStream;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
-import java.util.Locale;
import java.util.Map;
import java.util.concurrent.atomic.AtomicReference;
@@ -67,6 +61,7 @@ public class PreferencesFragment extends PreferenceFragmentCompat {
private static final int CODE_IMPORT_DECRYPT = 1;
private static final int CODE_SLOTS = 2;
private static final int CODE_GROUPS = 3;
+ private static final int CODE_SELECT_ENTRIES = 4;
// permission request codes
private static final int CODE_PERM_IMPORT = 0;
@@ -382,6 +377,8 @@ public class PreferencesFragment extends PreferenceFragmentCompat {
break;
case CODE_GROUPS:
onGroupManagerResult(resultCode, data);
+ case CODE_SELECT_ENTRIES:
+ onSelectEntriesResult(resultCode, data);
break;
}
}
@@ -524,44 +521,10 @@ public class PreferencesFragment extends PreferenceFragmentCompat {
List entries = result.getEntries();
List errors = result.getErrors();
- for (DatabaseEntry entry : entries) {
- // temporary: randomize the UUID of duplicate entries and add them anyway
- if (_db.getEntryByUUID(entry.getUUID()) != null) {
- entry.resetUUID();
- }
-
- _db.addEntry(entry);
- }
-
- if (!saveDatabase()) {
- return;
- }
-
- _result.putExtra("needsRecreate", true);
-
- Snackbar bar = Snackbar.make(getView(), String.format(Locale.getDefault(), getString(R.string.imported_entries_count), entries.size(), errors.size()), Snackbar.LENGTH_LONG);
- if (errors.size() > 0) {
- bar.setAction(R.string.details, v -> {
- List messages = new ArrayList<>();
- for (DatabaseImporterEntryException e : errors) {
- messages.add(e.getMessage());
- }
-
- String message = TextUtils.join("\n\n", messages);
- Dialogs.showSecureDialog(new AlertDialog.Builder(getActivity())
- .setTitle(R.string.import_error_title)
- .setMessage(message)
- .setPositiveButton(android.R.string.ok, null)
- .setNeutralButton(android.R.string.copy, (dialog, which) -> {
- ClipboardManager clipboard = (ClipboardManager) getActivity().getSystemService(Context.CLIPBOARD_SERVICE);
- ClipData clip = ClipData.newPlainText("text/plain", message);
- clipboard.setPrimaryClip(clip);
- Toast.makeText(getActivity(), getString(R.string.errors_copied), Toast.LENGTH_SHORT).show();
- })
- .create());
- });
- }
- bar.show();
+ Intent intent = new Intent(getActivity(), SelectEntriesActivity.class);
+ intent.putExtra("entries", (ArrayList) entries);
+ intent.putExtra("errors", (ArrayList) errors);
+ startActivityForResult(intent, CODE_SELECT_ENTRIES);
}
private void onExport() {
@@ -628,6 +591,31 @@ public class PreferencesFragment extends PreferenceFragmentCompat {
}
}
+ private void onSelectEntriesResult(int resultCode, Intent data) {
+ if (resultCode != Activity.RESULT_OK) {
+ return;
+ }
+
+ List entries = (ArrayList) data.getSerializableExtra("entries");
+ for (DatabaseEntry entry : entries) {
+ // temporary: randomize the UUID of duplicate entries and add them anyway
+ if (_db.getEntryByUUID(entry.getUUID()) != null) {
+ entry.resetUUID();
+ }
+
+ _db.addEntry(entry);
+ }
+
+ if (!saveDatabase()) {
+ return;
+ }
+
+ String toastMessage = getResources().getString(R.string.imported_entries_count, entries.size());
+ Toast.makeText(getContext(), toastMessage, Toast.LENGTH_SHORT).show();
+
+ _result.putExtra("needsRecreate", true);
+ }
+
private boolean saveDatabase() {
try {
_db.save();
diff --git a/app/src/main/java/com/beemdevelopment/aegis/ui/SelectEntriesActivity.java b/app/src/main/java/com/beemdevelopment/aegis/ui/SelectEntriesActivity.java
new file mode 100644
index 00000000..ab285cf2
--- /dev/null
+++ b/app/src/main/java/com/beemdevelopment/aegis/ui/SelectEntriesActivity.java
@@ -0,0 +1,138 @@
+package com.beemdevelopment.aegis.ui;
+
+import androidx.annotation.NonNull;
+import androidx.appcompat.app.ActionBar;
+import androidx.appcompat.app.AlertDialog;
+import androidx.recyclerview.widget.LinearLayoutManager;
+import androidx.recyclerview.widget.RecyclerView;
+
+import android.content.ClipData;
+import android.content.ClipboardManager;
+import android.content.Context;
+import android.content.Intent;
+import android.os.Bundle;
+import android.text.TextUtils;
+import android.view.Menu;
+import android.view.MenuItem;
+import android.widget.Toast;
+
+import com.beemdevelopment.aegis.R;
+import com.beemdevelopment.aegis.db.DatabaseEntry;
+import com.beemdevelopment.aegis.helpers.FabScrollHelper;
+import com.beemdevelopment.aegis.importers.DatabaseImporterEntryException;
+import com.beemdevelopment.aegis.ui.models.ImportEntry;
+import com.beemdevelopment.aegis.ui.views.ImportEntriesAdapter;
+import com.getbase.floatingactionbutton.FloatingActionButton;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class SelectEntriesActivity extends AegisActivity {
+ private ImportEntriesAdapter _adapter;
+ private FabScrollHelper _fabScrollHelper;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_select_entries);
+
+ ActionBar bar = getSupportActionBar();
+ bar.setHomeAsUpIndicator(R.drawable.ic_close);
+ bar.setDisplayHomeAsUpEnabled(true);
+
+ _adapter = new ImportEntriesAdapter();
+ RecyclerView entriesView = findViewById(R.id.list_entries);
+ entriesView.addOnScrollListener(new RecyclerView.OnScrollListener() {
+ @Override
+ public void onScrolled(@NonNull RecyclerView recyclerView, int dx, int dy) {
+ super.onScrolled(recyclerView, dx, dy);
+ onScroll(dx, dy);
+ }
+ });
+
+ LinearLayoutManager layoutManager = new LinearLayoutManager(this);
+ entriesView.setLayoutManager(layoutManager);
+ entriesView.setAdapter(_adapter);
+ entriesView.setNestedScrollingEnabled(false);
+
+ Intent intent = getIntent();
+ List entries = (ArrayList) intent.getSerializableExtra("entries");
+ List errors = (ArrayList) intent.getSerializableExtra("errors");
+
+ for (DatabaseEntry entry : entries) {
+ ImportEntry importEntry = new ImportEntry(entry);
+ _adapter.addEntry(importEntry);
+ }
+
+ if (errors.size() > 0) {
+ showErrorDialog(errors);
+ }
+
+ FloatingActionButton fabMenu = findViewById(R.id.fab);
+ fabMenu.setOnClickListener(v -> returnSelectedEntries());
+ _fabScrollHelper = new FabScrollHelper(fabMenu);
+ }
+
+ private void showErrorDialog(List errors) {
+ Dialogs.showSecureDialog(new AlertDialog.Builder(this)
+ .setTitle(R.string.import_error_title)
+ .setMessage(getString(R.string.import_error_dialog, errors.size()))
+ .setPositiveButton(android.R.string.ok, null)
+ .setNeutralButton(getString(R.string.details), (dialog, which) -> showDetailedErrorDialog(errors))
+ .create());
+ }
+
+ private void showDetailedErrorDialog(List errors) {
+ List messages = new ArrayList<>();
+ for (DatabaseImporterEntryException e : errors) {
+ messages.add(e.getMessage());
+ }
+
+ String message = TextUtils.join("\n\n", messages);
+ Dialogs.showSecureDialog(new AlertDialog.Builder(this)
+ .setTitle(R.string.import_error_title)
+ .setMessage(message)
+ .setPositiveButton(android.R.string.ok, null)
+ .setNeutralButton(android.R.string.copy, (dialog2, which2) -> {
+ ClipboardManager clipboard = (ClipboardManager) this.getSystemService(Context.CLIPBOARD_SERVICE);
+ ClipData clip = ClipData.newPlainText("text/plain", message);
+ clipboard.setPrimaryClip(clip);
+ Toast.makeText(this, getString(R.string.errors_copied), Toast.LENGTH_SHORT).show();
+ })
+ .create());
+ }
+
+ private void returnSelectedEntries() {
+ List entries = _adapter.getSelectedEntries();
+ Intent intent = new Intent();
+ intent.putExtra("entries", (ArrayList) entries);
+ setResult(RESULT_OK, intent);
+ finish();
+ }
+
+ public void onScroll(int dx, int dy) {
+ _fabScrollHelper.onScroll(dx, dy);
+ }
+
+ @Override
+ public boolean onCreateOptionsMenu(Menu menu) {
+ getMenuInflater().inflate(R.menu.menu_select_entries, menu);
+ return true;
+ }
+
+ @Override
+ public boolean onOptionsItemSelected(MenuItem item) {
+ switch (item.getItemId()) {
+ case android.R.id.home:
+ onBackPressed();
+ break;
+ case R.id.toggle_checkboxes:
+ _adapter.toggleCheckboxes();
+ break;
+ default:
+ return super.onOptionsItemSelected(item);
+ }
+
+ return true;
+ }
+}
diff --git a/app/src/main/java/com/beemdevelopment/aegis/ui/models/ImportEntry.java b/app/src/main/java/com/beemdevelopment/aegis/ui/models/ImportEntry.java
new file mode 100644
index 00000000..eaa75248
--- /dev/null
+++ b/app/src/main/java/com/beemdevelopment/aegis/ui/models/ImportEntry.java
@@ -0,0 +1,37 @@
+package com.beemdevelopment.aegis.ui.models;
+
+import com.beemdevelopment.aegis.db.DatabaseEntry;
+
+public class ImportEntry {
+ private DatabaseEntry _entry;
+ private boolean _isChecked = true;
+ private Listener _listener;
+
+ public ImportEntry(DatabaseEntry entry) {
+ _entry = entry;
+ }
+
+ public void setOnCheckedChangedListener(Listener listener) {
+ _listener = listener;
+ }
+
+ public DatabaseEntry getDatabaseEntry() {
+ return _entry;
+ }
+
+ public boolean isChecked() {
+ return _isChecked;
+ }
+
+ public void setIsChecked(boolean isChecked) {
+ _isChecked = isChecked;
+
+ if (_listener != null) {
+ _listener.onCheckedChanged(_isChecked);
+ }
+ }
+
+ public interface Listener {
+ void onCheckedChanged(boolean value);
+ }
+}
diff --git a/app/src/main/java/com/beemdevelopment/aegis/ui/views/ImportEntriesAdapter.java b/app/src/main/java/com/beemdevelopment/aegis/ui/views/ImportEntriesAdapter.java
new file mode 100644
index 00000000..f7acff60
--- /dev/null
+++ b/app/src/main/java/com/beemdevelopment/aegis/ui/views/ImportEntriesAdapter.java
@@ -0,0 +1,97 @@
+package com.beemdevelopment.aegis.ui.views;
+
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+
+import com.beemdevelopment.aegis.R;
+import com.beemdevelopment.aegis.db.DatabaseEntry;
+import com.beemdevelopment.aegis.ui.models.ImportEntry;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import androidx.annotation.NonNull;
+import androidx.recyclerview.widget.RecyclerView;
+
+public class ImportEntriesAdapter extends RecyclerView.Adapter {
+ private List _entries;
+
+ public ImportEntriesAdapter() {
+ _entries = new ArrayList<>();
+ }
+
+ public void addEntry(ImportEntry entry) {
+ _entries.add(entry);
+
+ int position = getItemCount() - 1;
+ if (position == 0) {
+ notifyDataSetChanged();
+ } else {
+ notifyItemInserted(position);
+ }
+ }
+
+ @NonNull
+ @Override
+ public ImportEntryHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
+ View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.card_import_entry, parent, false);
+ return new ImportEntryHolder(view);
+ }
+
+ @Override
+ public void onBindViewHolder(@NonNull ImportEntryHolder holder, int position) {
+ ImportEntry entry = _entries.get(position);
+ entry.setOnCheckedChangedListener(holder);
+ holder.setData(entry);
+ }
+
+ @Override
+ public void onViewRecycled(@NonNull ImportEntryHolder holder) {
+ holder.getEntry().setOnCheckedChangedListener(null);
+ }
+
+ @Override
+ public int getItemCount() {
+ return _entries.size();
+ }
+
+ public List getSelectedEntries() {
+ List entries = new ArrayList<>();
+
+ for (ImportEntry entry : getCheckedEntries()) {
+ entries.add(entry.getDatabaseEntry());
+ }
+
+ return entries;
+ }
+
+ private List getCheckedEntries() {
+ List entries = new ArrayList<>();
+
+ for (ImportEntry entry : _entries) {
+ if (entry.isChecked()) {
+ entries.add(entry);
+ }
+ }
+
+ return entries;
+ }
+
+ public void toggleCheckboxes() {
+ int checkedEntries = getCheckedEntries().size();
+ if (checkedEntries == 0 || checkedEntries != _entries.size()) {
+ setCheckboxStates(true);
+ } else {
+ setCheckboxStates(false);
+ }
+ }
+
+ private void setCheckboxStates(boolean checked) {
+ for (ImportEntry entry: _entries) {
+ if (entry.isChecked() != checked) {
+ entry.setIsChecked(checked);
+ }
+ }
+ }
+}
diff --git a/app/src/main/java/com/beemdevelopment/aegis/ui/views/ImportEntryHolder.java b/app/src/main/java/com/beemdevelopment/aegis/ui/views/ImportEntryHolder.java
new file mode 100644
index 00000000..4e8f85cc
--- /dev/null
+++ b/app/src/main/java/com/beemdevelopment/aegis/ui/views/ImportEntryHolder.java
@@ -0,0 +1,48 @@
+package com.beemdevelopment.aegis.ui.views;
+
+import android.content.Context;
+import android.view.View;
+import android.widget.CheckBox;
+import android.widget.TextView;
+
+import com.beemdevelopment.aegis.R;
+import com.beemdevelopment.aegis.db.DatabaseEntry;
+import com.beemdevelopment.aegis.ui.models.ImportEntry;
+
+import androidx.recyclerview.widget.RecyclerView;
+
+public class ImportEntryHolder extends RecyclerView.ViewHolder implements ImportEntry.Listener {
+ private TextView _issuer;
+ private TextView _accountName;
+ private CheckBox _checkbox;
+
+ private ImportEntry _entry;
+
+ public ImportEntryHolder(final View view) {
+ super(view);
+
+ _issuer = view.findViewById(R.id.profile_issuer);
+ _accountName = view.findViewById(R.id.profile_account_name);
+ _checkbox = view.findViewById(R.id.checkbox_import_entry);
+ view.setOnClickListener(v -> _entry.setIsChecked(!_entry.isChecked()));
+ }
+
+ public void setData(ImportEntry entry) {
+ _entry = entry;
+
+ Context context = itemView.getContext();
+ DatabaseEntry dbEntry = entry.getDatabaseEntry();
+ _issuer.setText(!dbEntry.getIssuer().isEmpty() ? dbEntry.getIssuer() : context.getString(R.string.unknown_issuer));
+ _accountName.setText(!dbEntry.getName().isEmpty() ? dbEntry.getName() : context.getString(R.string.unknown_account_name));
+ _checkbox.setChecked(entry.isChecked());
+ }
+
+ public ImportEntry getEntry() {
+ return _entry;
+ }
+
+ @Override
+ public void onCheckedChanged(boolean value) {
+ _checkbox.setChecked(value);
+ }
+}
diff --git a/app/src/main/res/drawable/ic_check_black_24dp.xml b/app/src/main/res/drawable/ic_check_black_24dp.xml
index 3c728c59..d986bb97 100644
--- a/app/src/main/res/drawable/ic_check_black_24dp.xml
+++ b/app/src/main/res/drawable/ic_check_black_24dp.xml
@@ -1,9 +1,5 @@
-
-
+
+
diff --git a/app/src/main/res/drawable/ic_done_all_black_24dp.xml b/app/src/main/res/drawable/ic_done_all_black_24dp.xml
new file mode 100644
index 00000000..dfe4814d
--- /dev/null
+++ b/app/src/main/res/drawable/ic_done_all_black_24dp.xml
@@ -0,0 +1,5 @@
+
+
+
diff --git a/app/src/main/res/layout/activity_select_entries.xml b/app/src/main/res/layout/activity_select_entries.xml
new file mode 100644
index 00000000..16fa06b9
--- /dev/null
+++ b/app/src/main/res/layout/activity_select_entries.xml
@@ -0,0 +1,33 @@
+
+
+
+
+
+
+
+
diff --git a/app/src/main/res/layout/card_import_entry.xml b/app/src/main/res/layout/card_import_entry.xml
new file mode 100644
index 00000000..9418380e
--- /dev/null
+++ b/app/src/main/res/layout/card_import_entry.xml
@@ -0,0 +1,76 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/src/main/res/menu/menu_select_entries.xml b/app/src/main/res/menu/menu_select_entries.xml
new file mode 100644
index 00000000..fc644310
--- /dev/null
+++ b/app/src/main/res/menu/menu_select_entries.xml
@@ -0,0 +1,8 @@
+
+
\ No newline at end of file
diff --git a/app/src/main/res/values-nl/strings.xml b/app/src/main/res/values-nl/strings.xml
index b6e51389..10af584e 100644
--- a/app/src/main/res/values-nl/strings.xml
+++ b/app/src/main/res/values-nl/strings.xml
@@ -109,7 +109,7 @@
Fout: Bestand niet gevonden
Er is een fout opgetreden tijdens het lezen van het bestand
Fout: Er kon geen root-access verkregen worden
- %d items geïmporteerd. %d fouten.
+ %d items geïmporteerd
Er zijn fouten opgetreden tijdens het importeren
Er is een fout opgetreden tijdens het exporteren van de database
De database is geëxporteerd naar:
diff --git a/app/src/main/res/values-ru/strings.xml b/app/src/main/res/values-ru/strings.xml
index 02c25d90..242cce7e 100644
--- a/app/src/main/res/values-ru/strings.xml
+++ b/app/src/main/res/values-ru/strings.xml
@@ -108,7 +108,7 @@
Ошибка: файл не найден
Произошла ошибка при попытке прочитать файл
Ошибка: невозможно получить root-доступ
- Импортироаано %d записей. %d ошибки.
+ Импортироаано %d записей
Произошла ошибка при попытке экспорта базы данных
База данных была экспортирована в:
Это действие экспортирует базу данных из личного хранилища Aegis.
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index 2e836c7a..5c4b946e 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -114,7 +114,8 @@
Error: File not found
An error occurred while trying to read the file
Error: unable to obtain root access
- Imported %d entries. %d errors.
+ Imported %d entries
+ Read %d entries. %d errors.
One or more errors occurred during the import
An error occurred while trying to export the database
The database has been exported to:
@@ -156,6 +157,10 @@
Normal
Compact
Small
+ Unknown issuer
+ Unknown account name
+ Aegis could not import %d tokens. These tokens will be skipped. Press \'details\' to see more information about the errors.
Unable to read and process QR code
Select picture
+ Toggle checkboxes