From 92aaa3edfd2cc5dba8e3d1202d2bd1595e0286dc Mon Sep 17 00:00:00 2001 From: Marten Rebane <54431068+martenrebane@users.noreply.github.com> Date: Tue, 10 Sep 2024 04:26:06 +0300 Subject: [PATCH] Add NFC design icon --- .../update/SignatureUpdateErrorDialog.java | 57 ++++++++++++++--- .../signature/update/nfc/NFCDialog.java | 29 +++++++-- .../signature/update/nfc/NFCOnSubscribe.java | 3 +- .../signature/update/nfc/NFCResponse.java | 5 ++ .../android/signature/update/nfc/NFCView.java | 16 ++++- app/src/main/res/drawable/ic_icon_nfc.xml | 21 +++++++ app/src/main/res/layout/nfc_dialog.xml | 35 +++++++---- .../layout/signature_update_error_dialog.xml | 63 +++++++++++++++++++ .../main/res/layout/signature_update_nfc.xml | 13 +++- app/src/main/res/values-et/strings.xml | 1 + app/src/main/res/values-ru/strings.xml | 1 + app/src/main/res/values/ids.xml | 2 + app/src/main/res/values/strings.xml | 1 + .../main/java/ee/ria/DigiDoc/idcard/NFC.java | 12 +++- 14 files changed, 229 insertions(+), 30 deletions(-) create mode 100644 app/src/main/res/drawable/ic_icon_nfc.xml create mode 100644 app/src/main/res/layout/signature_update_error_dialog.xml diff --git a/app/src/main/java/ee/ria/DigiDoc/android/signature/update/SignatureUpdateErrorDialog.java b/app/src/main/java/ee/ria/DigiDoc/android/signature/update/SignatureUpdateErrorDialog.java index 98089b733..a78a5af15 100644 --- a/app/src/main/java/ee/ria/DigiDoc/android/signature/update/SignatureUpdateErrorDialog.java +++ b/app/src/main/java/ee/ria/DigiDoc/android/signature/update/SignatureUpdateErrorDialog.java @@ -1,5 +1,6 @@ package ee.ria.DigiDoc.android.signature.update; +import static android.view.View.VISIBLE; import static android.view.ViewGroup.LayoutParams.WRAP_CONTENT; import static ee.ria.DigiDoc.android.signature.update.SignatureUpdateErrorDialog.Type.DOCUMENTS_ADD; import static ee.ria.DigiDoc.android.signature.update.SignatureUpdateErrorDialog.Type.DOCUMENT_REMOVE; @@ -12,8 +13,11 @@ import android.text.Html; import android.text.Spanned; import android.text.TextUtils; +import android.view.LayoutInflater; import android.view.View; import android.view.Window; +import android.widget.ImageView; +import android.widget.TextView; import androidx.annotation.NonNull; import androidx.annotation.Nullable; @@ -39,6 +43,7 @@ import ee.ria.DigiDoc.common.exception.SignatureUpdateDetailError; import ee.ria.DigiDoc.common.exception.SignatureUpdateError; import ee.ria.DigiDoc.idcard.CodeVerificationException; +import ee.ria.DigiDoc.idcard.NFC; import ee.ria.DigiDoc.sign.CertificateRevokedException; import ee.ria.DigiDoc.sign.OcspInvalidTimeSlotException; import ee.ria.DigiDoc.sign.TooManyRequestsException; @@ -65,6 +70,11 @@ public final class SignatureUpdateErrorDialog extends ErrorDialog implements Dia private String type; + private View dialogLayout; + private TextView errorDialogHeader; + private ImageView nfcDialogIcon; + private TextView nfcDialogText; + private TextView dialogText; private View view; private View.OnLayoutChangeListener layoutChangeListener; @@ -77,6 +87,14 @@ public final class SignatureUpdateErrorDialog extends ErrorDialog implements Dia SignatureUpdateSignatureAddDialog signatureAddDialog, View view) { super(context, R.style.UniformDialog); + LayoutInflater inflater = LayoutInflater.from(context); + dialogLayout = inflater.inflate(R.layout.signature_update_error_dialog, this.getListView()); + + errorDialogHeader = dialogLayout.findViewById(R.id.errorDialogHeader); + nfcDialogText = dialogLayout.findViewById(R.id.nfcDialogText); + nfcDialogIcon = dialogLayout.findViewById(R.id.nfcDialogIcon); + dialogText = dialogLayout.findViewById(R.id.dialogText); + this.documentsAddIntentSubject = documentsAddIntentSubject; this.documentRemoveIntentSubject = documentRemoveIntentSubject; this.signatureAddIntentSubject = signatureAddIntentSubject; @@ -85,6 +103,7 @@ public final class SignatureUpdateErrorDialog extends ErrorDialog implements Dia this.signatureAddDialog = signatureAddDialog; this.view = view; setButton(BUTTON_POSITIVE, context.getString(android.R.string.ok), (dialog, which) -> {}); + setView(dialogLayout); setOnDismissListener(this); } @@ -99,6 +118,11 @@ void show(@Nullable Throwable documentsAddError, @Nullable Throwable documentRem SignatureUpdateError updateError = null; SignatureUpdateDetailError detailError = null; + errorDialogHeader.setVisibility(VISIBLE); + nfcDialogIcon.setVisibility(VISIBLE); + nfcDialogText.setVisibility(VISIBLE); + dialogText.setVisibility(VISIBLE); + if (documentsAddError != null) { type = DOCUMENTS_ADD; if (documentsAddError instanceof EmptyFileException) { @@ -142,7 +166,8 @@ void show(@Nullable Throwable documentsAddError, @Nullable Throwable documentRem getTextFromTranslation(R.string.signature_update_signature_error_message_additional_information) + "", Html.FROM_HTML_MODE_LEGACY)); } else { - setTitle(R.string.signature_update_signature_add_error_title); + errorDialogHeader.setVisibility(VISIBLE); + errorDialogHeader.setText(R.string.signature_update_signature_add_error_title); if (((DetailMessageSource) signatureAddError).getDetailMessage() != null && !((DetailMessageSource) signatureAddError).getDetailMessage().isEmpty()) { String errorMessage = getContext().getString(R.string.signature_update_signature_error_message_details) + @@ -153,6 +178,8 @@ void show(@Nullable Throwable documentsAddError, @Nullable Throwable documentRem detailError = new DetailMessageException(signatureAddError.getMessage()); } } + } else if (signatureAddError instanceof NFC.NFCException) { + updateError = new NFC.NFCException(signatureAddError.getMessage()); } else if (signatureAddError instanceof TooManyRequestsException) { detailError = new TooManyRequestsException( Html.fromHtml(UrlMessage.withURL( @@ -175,7 +202,8 @@ void show(@Nullable Throwable documentsAddError, @Nullable Throwable documentRem } else if (signatureAddError.getMessage() != null && signatureAddError.getMessage().startsWith("Failed to create ssl connection with host")) { updateError = new SSLHandshakeException(); } else { - setTitle(R.string.signature_update_signature_add_error); + errorDialogHeader.setVisibility(VISIBLE); + errorDialogHeader.setText(R.string.signature_update_signature_add_error); updateError = new GeneralSignatureUpdateException(signatureAddError.getMessage()); } } else if (signatureRemoveError != null) { @@ -185,14 +213,27 @@ void show(@Nullable Throwable documentsAddError, @Nullable Throwable documentRem } if (updateError != null) { - String message = updateError.getMessage(getContext()); - setMessage(message); + if (updateError instanceof NFC.NFCException) { + nfcDialogText.setVisibility(View.VISIBLE); + nfcDialogText.setText(updateError.getMessage(getContext())); + dialogText.setVisibility(View.GONE); + errorDialogHeader.setVisibility(View.GONE); + } else { + nfcDialogText.setVisibility(View.GONE); + nfcDialogIcon.setVisibility(View.GONE); + dialogText.setVisibility(View.VISIBLE); + dialogText.setText(updateError.getMessage(getContext())); + } } else if (detailError != null) { + nfcDialogText.setVisibility(View.GONE); + nfcDialogIcon.setVisibility(View.GONE); + dialogText.setVisibility(View.VISIBLE); + Spanned detailMessage = detailError.getDetailMessage(getContext()); - if (detailMessage == null) { - setMessage(detailError.getMessage(getContext())); + if (detailMessage != null) { + dialogText.setText(detailMessage); } else { - setMessage(detailMessage); + dialogText.setText(detailError.getMessage(getContext())); } } else { dismiss(); @@ -209,7 +250,7 @@ private String getTextFromTranslation(int textId) { @Override public void onDismiss(DialogInterface dialog) { - setTitle(null); + errorDialogHeader.setText(null); removeListeners(); if (TextUtils.equals(type, DOCUMENTS_ADD)) { documentsAddIntentSubject.onNext(DocumentsAddIntent.clear()); diff --git a/app/src/main/java/ee/ria/DigiDoc/android/signature/update/nfc/NFCDialog.java b/app/src/main/java/ee/ria/DigiDoc/android/signature/update/nfc/NFCDialog.java index 6446e2f02..cc94ff369 100644 --- a/app/src/main/java/ee/ria/DigiDoc/android/signature/update/nfc/NFCDialog.java +++ b/app/src/main/java/ee/ria/DigiDoc/android/signature/update/nfc/NFCDialog.java @@ -2,13 +2,19 @@ import android.content.Context; import android.content.DialogInterface; +import android.graphics.PorterDuff; import android.os.Bundle; +import android.view.LayoutInflater; +import android.view.View; import android.view.accessibility.AccessibilityEvent; import android.widget.Button; +import android.widget.ImageView; +import android.widget.TextView; import androidx.annotation.NonNull; import androidx.annotation.StringRes; import androidx.appcompat.app.AlertDialog; +import androidx.core.content.ContextCompat; import ee.ria.DigiDoc.R; import ee.ria.DigiDoc.android.accessibility.AccessibilityUtils; @@ -19,15 +25,28 @@ public final class NFCDialog extends AlertDialog implements DialogInterface.OnClickListener { + private TextView messageView; + private ImageView iconView; + private final Subject buttonClicksSubject = PublishSubject.create(); private final int action; + private final Context context; public NFCDialog(@NonNull Context context, @StringRes int message, int action) { super(context); + this.context = context; SecureUtil.markAsSecure(context, getWindow()); - setMessage(context.getString(message)); + LayoutInflater inflater = LayoutInflater.from(context); + View dialogLayout = inflater.inflate(R.layout.nfc_dialog, this.getListView()); + + messageView = dialogLayout.findViewById(R.id.nfcDialogText); + iconView = dialogLayout.findViewById(R.id.nfcDialogIcon); + + messageView.setText(context.getString(message)); + setView(dialogLayout); + setButton(BUTTON_NEGATIVE, context.getString(android.R.string.cancel), this); this.action = action; @@ -43,15 +62,17 @@ public void showStatus(NFCResponse response) { } if (response.message() != null) { if (response.status() == SessionStatusResponse.ProcessStatus.TECHNICAL_ERROR) { - setMessage(getContext().getString(R.string.signature_update_nfc_technical_error) + ":\n" + response.message()); + messageView.setText(getContext().getString(R.string.signature_update_nfc_technical_error) + ":\n" + response.message()); + iconView.setColorFilter(ContextCompat.getColor(context, R.color.error), PorterDuff.Mode.SRC_IN); } else { - setMessage(response.message()); + messageView.setText(response.message()); + iconView.setColorFilter(ContextCompat.getColor(context, R.color.accent), PorterDuff.Mode.SRC_IN); } } else { if (AccessibilityUtils.isTalkBackEnabled()) { AccessibilityUtils.interrupt(getContext()); } - setMessage(getContext().getString(R.string.signature_update_nfc_hold)); + messageView.setText(getContext().getString(R.string.signature_update_nfc_hold)); } } diff --git a/app/src/main/java/ee/ria/DigiDoc/android/signature/update/nfc/NFCOnSubscribe.java b/app/src/main/java/ee/ria/DigiDoc/android/signature/update/nfc/NFCOnSubscribe.java index 56887da58..8aa172db1 100644 --- a/app/src/main/java/ee/ria/DigiDoc/android/signature/update/nfc/NFCOnSubscribe.java +++ b/app/src/main/java/ee/ria/DigiDoc/android/signature/update/nfc/NFCOnSubscribe.java @@ -67,7 +67,8 @@ public void subscribe(ObservableEmitter emitter) { if (response != null) { if (response.status() != SessionStatusResponse.ProcessStatus.OK) { Timber.log(Log.ERROR, String.format("NFC status: %s", response.status())); - emitter.onError(new NFC.NFCException(response.message())); + emitter.onError(NFCResponse.createException(response.message())); + emitter.onComplete(); } else { emitter.onNext(response); emitter.onComplete(); diff --git a/app/src/main/java/ee/ria/DigiDoc/android/signature/update/nfc/NFCResponse.java b/app/src/main/java/ee/ria/DigiDoc/android/signature/update/nfc/NFCResponse.java index 8eafe4e70..ef4985941 100644 --- a/app/src/main/java/ee/ria/DigiDoc/android/signature/update/nfc/NFCResponse.java +++ b/app/src/main/java/ee/ria/DigiDoc/android/signature/update/nfc/NFCResponse.java @@ -5,6 +5,7 @@ import com.google.auto.value.AutoValue; import ee.ria.DigiDoc.android.signature.update.SignatureAddResponse; +import ee.ria.DigiDoc.idcard.NFC; import ee.ria.DigiDoc.sign.SignedContainer; import ee.ria.DigiDoc.smartid.dto.response.SessionStatusResponse; @@ -46,4 +47,8 @@ private static NFCResponse create(@Nullable SignedContainer container, public static NFCResponse createWithStatus(SessionStatusResponse.ProcessStatus status, String message) { return create(null, status, message); } + + public static NFC.NFCException createException(String message) { + return new NFC.NFCException(message); + } } diff --git a/app/src/main/java/ee/ria/DigiDoc/android/signature/update/nfc/NFCView.java b/app/src/main/java/ee/ria/DigiDoc/android/signature/update/nfc/NFCView.java index 2ef1ddca6..34fa1c09c 100644 --- a/app/src/main/java/ee/ria/DigiDoc/android/signature/update/nfc/NFCView.java +++ b/app/src/main/java/ee/ria/DigiDoc/android/signature/update/nfc/NFCView.java @@ -24,6 +24,7 @@ import androidx.annotation.NonNull; import androidx.annotation.Nullable; +import androidx.core.content.ContextCompat; import com.google.android.material.textfield.TextInputLayout; import com.google.android.material.textview.MaterialTextView; @@ -80,8 +81,8 @@ public NFCView(Context context, @Nullable AttributeSet attrs, int defStyleAttr, handleNFCSupportLayout(); if (AccessibilityUtils.isTalkBackEnabled()) { - AccessibilityUtils.setSingleCharactersContentDescription(canView, "Card number"); - AccessibilityUtils.setSingleCharactersContentDescription(pinView, "PIN code"); + AccessibilityUtils.setSingleCharactersContentDescription(canView, getResources().getString(R.string.signature_update_nfc_can)); + AccessibilityUtils.setSingleCharactersContentDescription(pinView, getResources().getString(R.string.signature_update_nfc_pin2)); AccessibilityUtils.setEditTextCursorToEnd(canView); AccessibilityUtils.setEditTextCursorToEnd(pinView); AccessibilityUtils.setTextViewContentDescription(context, true, null, canLabel.getText().toString(), canView); @@ -149,7 +150,8 @@ private void checkInputsValidity() { } private void checkCANCodeValidity() { - canLayout.setError(null); + setDefaultCANNumberDescription(); + Editable canCodeView = canView.getText(); if (canCodeView != null && !canCodeView.toString().isEmpty() && !isCANLengthValid(canCodeView.toString()) @@ -157,6 +159,7 @@ private void checkCANCodeValidity() { canLayout.setError(getResources().getString( R.string.nfc_sign_can_invalid_length, Integer.toString(CAN_LENGTH))); + canLayout.setErrorTextColor(ContextCompat.getColorStateList(getContext(), R.color.error)); } } @@ -191,10 +194,17 @@ private void setAccessibilityDescription() { AccessibilityUtils.setEditTextCursorToEnd(canView); } + private void setDefaultCANNumberDescription() { + canLayout.setError(getResources().getString(R.string.nfc_sign_can_location)); + canLayout.setErrorTextColor(ContextCompat.getColorStateList(getContext(), R.color.material_color_black)); + } + @Override protected void onAttachedToWindow() { super.onAttachedToWindow(); + setDefaultCANNumberDescription(); + // Better support for Voice Assist to not delete wrong characters accessibilityTouchExplorationStateChangeListener = AccessibilityUtils.addAccessibilityStateChanged(enabled -> { boolean isTalkBackEnabled = AccessibilityUtils.isTalkBackEnabled(); diff --git a/app/src/main/res/drawable/ic_icon_nfc.xml b/app/src/main/res/drawable/ic_icon_nfc.xml new file mode 100644 index 000000000..49b8b4704 --- /dev/null +++ b/app/src/main/res/drawable/ic_icon_nfc.xml @@ -0,0 +1,21 @@ + + + + + + + + diff --git a/app/src/main/res/layout/nfc_dialog.xml b/app/src/main/res/layout/nfc_dialog.xml index b9dba375f..db176df88 100644 --- a/app/src/main/res/layout/nfc_dialog.xml +++ b/app/src/main/res/layout/nfc_dialog.xml @@ -1,27 +1,38 @@ + android:layout_height="match_parent" + xmlns:app="http://schemas.android.com/apk/res-auto"> - + android:layout_marginStart="@dimen/material_list_icon_first_position_margin_start" + android:layout_marginEnd="@dimen/material_list_icon_first_position_margin_start" + android:paddingVertical="@dimen/material_card_media_area_framed_padding_vertical" + android:layout_gravity="center_horizontal" + android:src="@drawable/ic_icon_nfc" + app:tint="@color/accent" + android:importantForAccessibility="no" + android:contentDescription="@string/signature_update_signature_add_method_nfc" /> -