mirror of
https://github.com/beemdevelopment/Aegis.git
synced 2025-05-15 22:42:51 +00:00
Merge pull request #323 from michaelschattgen/feature-copied
Improve method to notify users on copy
This commit is contained in:
commit
d247750e62
20 changed files with 164 additions and 25 deletions
|
@ -757,7 +757,6 @@ public class MainActivity extends AegisActivity implements EntryListView.Listene
|
|||
ClipboardManager clipboard = (ClipboardManager) getSystemService(Context.CLIPBOARD_SERVICE);
|
||||
ClipData clip = ClipData.newPlainText("text/plain", entry.getInfo().getOtp());
|
||||
clipboard.setPrimaryClip(clip);
|
||||
Toast.makeText(this, getString(R.string.code_copied), Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
|
||||
private class ActionModeCallbacks implements ActionMode.Callback {
|
||||
|
|
|
@ -4,6 +4,8 @@ import android.os.Handler;
|
|||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.view.animation.Animation;
|
||||
import android.view.animation.AnimationUtils;
|
||||
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
|
@ -340,6 +342,7 @@ public class EntryAdapter extends RecyclerView.Adapter<EntryHolder> implements I
|
|||
|
||||
if (!handled) {
|
||||
_view.onEntryClick(entry);
|
||||
holder.animateCopyText();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
|
|
@ -1,8 +1,12 @@
|
|||
package com.beemdevelopment.aegis.ui.views;
|
||||
|
||||
import android.graphics.PorterDuff;
|
||||
import android.os.Handler;
|
||||
import android.view.View;
|
||||
import android.view.animation.Animation;
|
||||
import android.view.animation.AnimationUtils;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.RelativeLayout;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.fragment.app.Fragment;
|
||||
|
@ -28,9 +32,11 @@ public class EntryHolder extends RecyclerView.ViewHolder {
|
|||
private TextView _profileName;
|
||||
private TextView _profileCode;
|
||||
private TextView _profileIssuer;
|
||||
private TextView _profileCopied;
|
||||
private ImageView _profileDrawable;
|
||||
private VaultEntry _entry;
|
||||
private ImageView _buttonRefresh;
|
||||
private RelativeLayout _description;
|
||||
|
||||
private boolean _hidden;
|
||||
|
||||
|
@ -38,6 +44,7 @@ public class EntryHolder extends RecyclerView.ViewHolder {
|
|||
private View _view;
|
||||
|
||||
private UiRefresher _refresher;
|
||||
private Handler _animationHandler;
|
||||
|
||||
public EntryHolder(final View view) {
|
||||
super(view);
|
||||
|
@ -47,6 +54,8 @@ public class EntryHolder extends RecyclerView.ViewHolder {
|
|||
_profileName = view.findViewById(R.id.profile_account_name);
|
||||
_profileCode = view.findViewById(R.id.profile_code);
|
||||
_profileIssuer = view.findViewById(R.id.profile_issuer);
|
||||
_profileCopied = view.findViewById(R.id.profile_copied);
|
||||
_description = view.findViewById(R.id.description);
|
||||
_profileDrawable = view.findViewById(R.id.ivTextDrawable);
|
||||
_buttonRefresh = view.findViewById(R.id.buttonRefresh);
|
||||
|
||||
|
@ -200,6 +209,29 @@ public class EntryHolder extends RecyclerView.ViewHolder {
|
|||
animateAlphaTo(DEFAULT_ALPHA);
|
||||
}
|
||||
|
||||
public void animateCopyText() {
|
||||
if (_animationHandler != null) {
|
||||
_animationHandler.removeCallbacksAndMessages(null);
|
||||
}
|
||||
Animation slideDownFadeIn = AnimationUtils.loadAnimation(itemView.getContext(), R.anim.slide_down_fade_in);
|
||||
Animation slideDownFadeOut = AnimationUtils.loadAnimation(itemView.getContext(), R.anim.slide_down_fade_out);
|
||||
Animation fadeOut = AnimationUtils.loadAnimation(itemView.getContext(), R.anim.fade_out);
|
||||
Animation fadeIn = AnimationUtils.loadAnimation(itemView.getContext(), R.anim.fade_in);
|
||||
|
||||
_profileCopied.startAnimation(slideDownFadeIn);
|
||||
_description.startAnimation(slideDownFadeOut);
|
||||
|
||||
|
||||
_animationHandler = new Handler();
|
||||
_animationHandler.postDelayed(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
_profileCopied.startAnimation(fadeOut);
|
||||
_description.startAnimation(fadeIn);
|
||||
}
|
||||
}, 3000);
|
||||
}
|
||||
|
||||
private void animateAlphaTo(float alpha) {
|
||||
itemView.animate().alpha(alpha).setDuration(200).start();
|
||||
}
|
||||
|
|
12
app/src/main/res/anim/fade_in.xml
Normal file
12
app/src/main/res/anim/fade_in.xml
Normal file
|
@ -0,0 +1,12 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<set xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<translate
|
||||
android:duration="0"
|
||||
android:fromYDelta="-100%"
|
||||
android:toYDelta="0" />
|
||||
|
||||
<alpha
|
||||
android:fromAlpha="0.0"
|
||||
android:toAlpha="1.0"
|
||||
android:duration="300"/>
|
||||
</set>
|
8
app/src/main/res/anim/fade_out.xml
Normal file
8
app/src/main/res/anim/fade_out.xml
Normal file
|
@ -0,0 +1,8 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<set xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<alpha
|
||||
android:fromAlpha="1.0"
|
||||
android:toAlpha="0.0"
|
||||
android:duration="300"/>
|
||||
|
||||
</set>
|
16
app/src/main/res/anim/slide_down_fade_in.xml
Normal file
16
app/src/main/res/anim/slide_down_fade_in.xml
Normal file
|
@ -0,0 +1,16 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<set xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:fillAfter="true"
|
||||
android:fillEnabled="true">
|
||||
|
||||
<translate
|
||||
android:duration="300"
|
||||
android:fromYDelta="0"
|
||||
android:toYDelta="100%" />
|
||||
|
||||
<alpha
|
||||
android:fromAlpha="0.0"
|
||||
android:toAlpha="1.0"
|
||||
android:duration="500"/>
|
||||
|
||||
</set>
|
21
app/src/main/res/anim/slide_down_fade_out.xml
Normal file
21
app/src/main/res/anim/slide_down_fade_out.xml
Normal file
|
@ -0,0 +1,21 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<set xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:fillAfter="true"
|
||||
android:fillEnabled="true">
|
||||
|
||||
<translate
|
||||
android:duration="300"
|
||||
android:fromYDelta="0"
|
||||
android:toYDelta="100%" />
|
||||
|
||||
<alpha
|
||||
android:fromAlpha="1.0"
|
||||
android:toAlpha="0.0"
|
||||
android:duration="500"/>
|
||||
|
||||
<alpha
|
||||
android:fromAlpha="1.0"
|
||||
android:toAlpha="0.0"
|
||||
android:duration="500"/>
|
||||
|
||||
</set>
|
|
@ -49,8 +49,30 @@
|
|||
android:paddingRight="16dp"
|
||||
android:paddingStart="16dp">
|
||||
|
||||
|
||||
<TextView
|
||||
android:id="@+id/profile_copied"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:includeFontPadding="false"
|
||||
android:maxLines="1"
|
||||
android:text="@string/copied"
|
||||
android:layout_above="@+id/description"
|
||||
android:layout_alignLeft="@+id/profile_code"
|
||||
android:layout_alignStart="@+id/profile_code"
|
||||
android:textColor="?attr/secondaryText"
|
||||
android:textSize="15sp"
|
||||
android:visibility="invisible" />
|
||||
|
||||
<RelativeLayout
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:id="@+id/description"
|
||||
android:layout_below="@+id/profile_code"
|
||||
android:layout_alignLeft="@+id/profile_code"
|
||||
android:layout_alignStart="@+id/profile_code">
|
||||
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:id="@+id/profile_issuer"
|
||||
|
@ -58,9 +80,6 @@
|
|||
android:textColor="?attr/secondaryText"
|
||||
android:includeFontPadding="false"
|
||||
android:textSize="15sp"
|
||||
android:layout_below="@+id/profile_code"
|
||||
android:layout_alignLeft="@+id/profile_code"
|
||||
android:layout_alignStart="@+id/profile_code"
|
||||
android:ellipsize="end"
|
||||
android:maxLines="1"/>
|
||||
|
||||
|
@ -68,7 +87,6 @@
|
|||
android:id="@+id/profile_account_name"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_below="@id/profile_code"
|
||||
android:layout_toRightOf="@id/profile_issuer"
|
||||
android:ellipsize="end"
|
||||
android:includeFontPadding="false"
|
||||
|
@ -77,6 +95,8 @@
|
|||
android:textSize="15sp"
|
||||
tools:text=" - AccountName" />
|
||||
|
||||
</RelativeLayout>
|
||||
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
|
|
|
@ -49,6 +49,28 @@
|
|||
android:paddingRight="8dp"
|
||||
android:paddingStart="8dp">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/profile_copied"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:includeFontPadding="false"
|
||||
android:maxLines="1"
|
||||
android:text="@string/copied"
|
||||
android:layout_above="@+id/description"
|
||||
android:layout_alignLeft="@+id/profile_code"
|
||||
android:layout_alignStart="@+id/profile_code"
|
||||
android:textColor="?attr/secondaryText"
|
||||
android:textSize="13sp"
|
||||
android:visibility="invisible" />
|
||||
|
||||
<RelativeLayout
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:id="@+id/description"
|
||||
android:layout_below="@+id/profile_code"
|
||||
android:layout_alignLeft="@+id/profile_code"
|
||||
android:layout_alignStart="@+id/profile_code">
|
||||
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
|
@ -58,9 +80,6 @@
|
|||
android:textColor="?attr/secondaryText"
|
||||
android:includeFontPadding="false"
|
||||
android:textSize="13sp"
|
||||
android:layout_below="@+id/profile_code"
|
||||
android:layout_alignLeft="@+id/profile_code"
|
||||
android:layout_alignStart="@+id/profile_code"
|
||||
android:ellipsize="end"
|
||||
android:maxLines="1"/>
|
||||
|
||||
|
@ -68,7 +87,6 @@
|
|||
android:id="@+id/profile_account_name"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_below="@id/profile_code"
|
||||
android:layout_toRightOf="@id/profile_issuer"
|
||||
android:ellipsize="end"
|
||||
android:includeFontPadding="false"
|
||||
|
@ -76,6 +94,7 @@
|
|||
android:textColor="@color/extra_info_text"
|
||||
android:textSize="13sp"
|
||||
tools:text=" - AccountName" />
|
||||
</RelativeLayout>
|
||||
|
||||
|
||||
<TextView
|
||||
|
|
|
@ -49,6 +49,28 @@
|
|||
android:paddingRight="8dp"
|
||||
android:paddingStart="8dp">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/profile_copied"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:includeFontPadding="false"
|
||||
android:maxLines="1"
|
||||
android:text="@string/copied"
|
||||
android:layout_above="@+id/description"
|
||||
android:layout_alignLeft="@+id/profile_code"
|
||||
android:layout_alignStart="@+id/profile_code"
|
||||
android:textColor="?attr/secondaryText"
|
||||
android:textSize="13sp"
|
||||
android:visibility="invisible" />
|
||||
|
||||
<RelativeLayout
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:id="@+id/description"
|
||||
android:layout_below="@+id/profile_code"
|
||||
android:layout_alignLeft="@+id/profile_code"
|
||||
android:layout_alignStart="@+id/profile_code">
|
||||
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
|
@ -58,9 +80,6 @@
|
|||
android:textColor="?attr/secondaryText"
|
||||
android:includeFontPadding="false"
|
||||
android:textSize="13sp"
|
||||
android:layout_below="@+id/profile_code"
|
||||
android:layout_alignLeft="@+id/profile_code"
|
||||
android:layout_alignStart="@+id/profile_code"
|
||||
android:ellipsize="end"
|
||||
android:maxLines="1"/>
|
||||
|
||||
|
@ -68,7 +87,6 @@
|
|||
android:id="@+id/profile_account_name"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_below="@id/profile_code"
|
||||
android:layout_toRightOf="@id/profile_issuer"
|
||||
android:ellipsize="end"
|
||||
android:includeFontPadding="false"
|
||||
|
@ -76,7 +94,7 @@
|
|||
android:textColor="@color/extra_info_text"
|
||||
android:textSize="13sp"
|
||||
tools:text=" - AccountName" />
|
||||
|
||||
</RelativeLayout>
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
|
|
|
@ -92,7 +92,6 @@
|
|||
<string name="setup_completed">Nastavení dokončeno</string>
|
||||
<string name="setup_completed_description">Aegis je nastaven a připraven k používání.</string>
|
||||
<string name="vault_not_found">Trezor nebyl nenalezen, spouštím nastavení…</string>
|
||||
<string name="code_copied">Kód zkopírován do schránky</string>
|
||||
<string name="errors_copied">Chyby zkopírovány do schránky</string>
|
||||
<string name="version_copied">Verze zkopírována do schránky</string>
|
||||
<string name="decryption_error">Při odemykání trezoru došlo k chybě</string>
|
||||
|
|
|
@ -84,7 +84,6 @@
|
|||
<string name="setup_completed">Einrichten abgeschlossen</string>
|
||||
<string name="setup_completed_description">Aegis ist eingerichtet und einsatzbereit.</string>
|
||||
<string name="vault_not_found">Tresor nicht gefunden, Starten der Einrichtung…</string>
|
||||
<string name="code_copied">Code in die Zwischenablage kopiert</string>
|
||||
<string name="errors_copied">Fehlermeldungen in die Zwischenablage kopiert</string>
|
||||
<string name="version_copied">Version in die Zwischenablage kopiert</string>
|
||||
<string name="decryption_error">Beim Versuch, den Tresor zu entsperren, ist ein Fehler aufgetreten.</string>
|
||||
|
|
|
@ -93,7 +93,6 @@
|
|||
<string name="setup_completed">Configuración completada</string>
|
||||
<string name="setup_completed_description">Aegis se ha configurado y está listo para funcionar.</string>
|
||||
<string name="vault_not_found">Caja fuerte no encontrada, iniciando la configuración…</string>
|
||||
<string name="code_copied">Código copiado al portapapeles</string>
|
||||
<string name="errors_copied">Errores copiados al portapapeles</string>
|
||||
<string name="version_copied">Versión copiada al portapapeles</string>
|
||||
<string name="decryption_error">Se ha producido un error tratando de desbloquear la caja fuerte</string>
|
||||
|
|
|
@ -84,7 +84,6 @@
|
|||
<string name="setup_completed">Configuration terminée</string>
|
||||
<string name="setup_completed_description">Aegis a été configuré et est prêt à être utilisé.</string>
|
||||
<string name="vault_not_found">Coffre-fort introuvable, lancement de la configuration…</string>
|
||||
<string name="code_copied">Code copié dans le presse-papier</string>
|
||||
<string name="errors_copied">Erreurs copiées dans le presse-papier</string>
|
||||
<string name="version_copied">Version copiée dans le presse-papier</string>
|
||||
<string name="decryption_error">Une erreur est survenue en essayant de déverrouiller le coffre-fort</string>
|
||||
|
|
|
@ -90,7 +90,6 @@
|
|||
<string name="setup_completed">Configurazione completata</string>
|
||||
<string name="setup_completed_description">Aegis è stata configurata, sei pronto a partire.</string>
|
||||
<string name="vault_not_found">Cassaforte non trovata, avvio configurazione…</string>
|
||||
<string name="code_copied">Codice copiato negli appunti</string>
|
||||
<string name="errors_copied">Codice errore copiato negli appunti</string>
|
||||
<string name="version_copied">Versione copiata negli appunti</string>
|
||||
<string name="decryption_error">Si è verificato un errore nello sblocco della cassaforte</string>
|
||||
|
|
|
@ -84,7 +84,6 @@
|
|||
<string name="setup_completed">ತಯಾರಿ ಪೂರ್ಣಗೊಂಡಿದೆ</string>
|
||||
<string name="setup_completed_description">Aegis ತಯಾರಿಯಾಗಿದೆ ಹಾಗು ಮುಂದುವರೆಯಲು ಸಿದ್ಧವಾಗಿದೆ.</string>
|
||||
<string name="vault_not_found">ವೌಲ್ಟ್ ಸಿಗಲಿಲ್ಲ, ತಯಾರಿಯನ್ನು ಪ್ರಾರಂಭಿಸಲಾಗುತ್ತಿದೆ…</string>
|
||||
<string name="code_copied">ಸಂಕೇತವನ್ನು ಕ್ಲಿಪ್ಬೋರ್ಡಿಗೆ ನಕಲಿಸಲಾಗಿದೆ</string>
|
||||
<string name="errors_copied">ದೋಷಗಳು ಕ್ಲಿಪ್ಬೋರ್ಡಿಗೆ ನಕಲಿಸಲಾಗಿದೆ</string>
|
||||
<string name="version_copied">ಅವೃತ್ತಿ ಕ್ಲಿಪ್ಬೋರ್ಡಿಗೆ ನಕಲಿಸಲಾಗಿದೆ</string>
|
||||
<string name="decryption_error">ವೌಲ್ಟಿನ ಬೀಗವನ್ನು ತೆರೆಯುವಾಗ ಒಂದು ದೋಷ ಸಂಭವಿಸಿದೆ</string>
|
||||
|
|
|
@ -84,7 +84,6 @@
|
|||
<string name="setup_completed">Configuratie voltooid</string>
|
||||
<string name="setup_completed_description">Aegis is geconfigureerd en is klaar voor gebruik.</string>
|
||||
<string name="vault_not_found">Kluis niet gevonden, configuratie wordt gestart…</string>
|
||||
<string name="code_copied">Code gekopieerd naar klembord</string>
|
||||
<string name="errors_copied">Fouten zijn gekopieerd naar klembord</string>
|
||||
<string name="version_copied">Versie is gekopieerd naar het klembord</string>
|
||||
<string name="decryption_error">Er is een fout opgetreden tijdens het ontgrendelen van de kluis</string>
|
||||
|
|
|
@ -81,7 +81,6 @@
|
|||
<string name="setup_completed">Настройка завершена</string>
|
||||
<string name="setup_completed_description">Aegis настроен и готов к работе.</string>
|
||||
<string name="vault_not_found">Хранилище не найдено, запуск первоначальной настройки…</string>
|
||||
<string name="code_copied">Код скопирован в буфер обмена</string>
|
||||
<string name="errors_copied">Ошибки скопированы в буфер обмена</string>
|
||||
<string name="decryption_error">Произошла ошибка при попытке разблокировать хранилище</string>
|
||||
<string name="saving_error">Произошла ошибка при попытке сохранить хранилище</string>
|
||||
|
|
|
@ -104,7 +104,6 @@
|
|||
<string name="setup_completed">设置完成</string>
|
||||
<string name="setup_completed_description">Aegis 设置完成,可以开始使用了。</string>
|
||||
<string name="vault_not_found">数据库未找到,开始设置……</string>
|
||||
<string name="code_copied">验证码已复制到剪贴板</string>
|
||||
<string name="errors_copied">错误已复制到剪贴板</string>
|
||||
<string name="version_copied">版本号已复制到剪贴板</string>
|
||||
<string name="decryption_error">试图解锁数据库时出错</string>
|
||||
|
|
|
@ -112,7 +112,7 @@
|
|||
<string name="setup_completed">Setup completed</string>
|
||||
<string name="setup_completed_description">Aegis has been setup and is ready to go.</string>
|
||||
<string name="vault_not_found">Vault not found, starting setup…</string>
|
||||
<string name="code_copied">Code copied to the clipboard</string>
|
||||
<string name="copied">Copied</string>
|
||||
<string name="errors_copied">Errors copied to the clipboard</string>
|
||||
<string name="version_copied">Version copied to the clipboard</string>
|
||||
<string name="decryption_error">An error occurred while trying to unlock the vault</string>
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue