chromium/chrome/browser/ui/android/autofill/internal/java/src/org/chromium/chrome/browser/ui/autofill/OtpVerificationDialogMediator.java

// Copyright 2021 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

package org.chromium.chrome.browser.ui.autofill;

import static org.chromium.chrome.browser.ui.autofill.OtpVerificationDialogProperties.DELAY_BETWEEN_CONFIRMATION_SHOWN_AND_DISMISSAL_MS;
import static org.chromium.chrome.browser.ui.autofill.OtpVerificationDialogProperties.EDIT_TEXT;
import static org.chromium.chrome.browser.ui.autofill.OtpVerificationDialogProperties.OTP_ERROR_MESSAGE;
import static org.chromium.chrome.browser.ui.autofill.OtpVerificationDialogProperties.OTP_LENGTH;
import static org.chromium.chrome.browser.ui.autofill.OtpVerificationDialogProperties.SHOW_CONFIRMATION;
import static org.chromium.chrome.browser.ui.autofill.OtpVerificationDialogProperties.SHOW_PROGRESS_BAR_OVERLAY;
import static org.chromium.chrome.browser.ui.autofill.OtpVerificationDialogProperties.VIEW_DELEGATE;

import android.os.Handler;

import org.chromium.chrome.browser.ui.autofill.OtpVerificationDialogCoordinator.Delegate;
import org.chromium.ui.modaldialog.DialogDismissalCause;
import org.chromium.ui.modaldialog.ModalDialogManager;
import org.chromium.ui.modaldialog.ModalDialogProperties;
import org.chromium.ui.modelutil.PropertyModel;

import java.util.Optional;

class OtpVerificationDialogMediator
        implements ModalDialogProperties.Controller, OtpVerificationDialogProperties.ViewDelegate {
    private final ModalDialogManager mModalDialogManager;
    private PropertyModel mModalDialogModel;
    private Delegate mDelegate;
    private PropertyModel mOtpVerificationDialogModel;

    OtpVerificationDialogMediator(
            ModalDialogManager modalDialogManager,
            PropertyModel.Builder dialogModelBuilder,
            Delegate delegate) {
        mModalDialogManager = modalDialogManager;
        mModalDialogModel = dialogModelBuilder.with(ModalDialogProperties.CONTROLLER, this).build();
        mDelegate = delegate;
    }

    @Override
    public void onDismiss(PropertyModel model, int dismissalCause) {
        mDelegate.onDialogDismissed();
    }

    @Override
    public void onClick(PropertyModel model, int buttonType) {
        switch (buttonType) {
            case ModalDialogProperties.ButtonType.POSITIVE:
                Optional<CharSequence> editTextOptional =
                        mOtpVerificationDialogModel.get(EDIT_TEXT);
                // Safety check, this should always be true.
                if (editTextOptional.isPresent()) {
                    showProgressBarOverlay();
                    mDelegate.onConfirm(editTextOptional.get().toString());
                }
                break;
            case ModalDialogProperties.ButtonType.NEGATIVE:
                mModalDialogManager.dismissDialog(
                        model, DialogDismissalCause.NEGATIVE_BUTTON_CLICKED);
                break;
        }
    }

    @Override
    public void onTextChanged(CharSequence s) {
        mModalDialogModel.set(
                ModalDialogProperties.POSITIVE_BUTTON_DISABLED,
                s.length() != mOtpVerificationDialogModel.get(OTP_LENGTH));
        mOtpVerificationDialogModel.set(OTP_ERROR_MESSAGE, Optional.empty());
        mOtpVerificationDialogModel.set(EDIT_TEXT, Optional.of(s));
    }

    @Override
    public void onResendLinkClicked() {
        clearEditText();
        onNewOtpRequested();
    }

    /**
     * Show the OtpVerification dialog.
     *
     * @param dialogViewModel The model for the dialog view.
     */
    void show(PropertyModel dialogViewModel) {
        setDialogViewModel(dialogViewModel);
        mModalDialogManager.showDialog(mModalDialogModel, ModalDialogManager.ModalDialogType.TAB);
    }

    /** Dismiss the dialog if is already showing. */
    void dismissDialog() {
        mModalDialogManager.dismissDialog(
                mModalDialogModel, DialogDismissalCause.DISMISSED_BY_NATIVE);
    }

    /** Clear the text in the Edit Text field. */
    void clearEditText() {
        mOtpVerificationDialogModel.set(EDIT_TEXT, Optional.empty());
    }

    /**
     * Shows the progress bar overlay for the dialog. This method is called once the users clicks
     * the accept button.
     */
    void showProgressBarOverlay() {
        mOtpVerificationDialogModel.set(SHOW_PROGRESS_BAR_OVERLAY, true);
        mModalDialogModel.set(ModalDialogProperties.POSITIVE_BUTTON_DISABLED, true);
    }

    /** Show an error message for the submitted otp. */
    void showOtpErrorMessage(Optional<String> errorMessage) {
        mOtpVerificationDialogModel.set(SHOW_PROGRESS_BAR_OVERLAY, false);
        mOtpVerificationDialogModel.set(OTP_ERROR_MESSAGE, errorMessage);
        mModalDialogModel.set(ModalDialogProperties.POSITIVE_BUTTON_DISABLED, true);
    }

    /**
     * Shows the confirmation message and dismisses the dialog. This method is called when the
     * server returns a success response after the user clicked the accept button.
     *
     * @param confirmationMessage The confirmation message that gets shown on successful server
     * response.
     */
    void showConfirmationAndDismissDialog(String confirmationMessage) {
        mOtpVerificationDialogModel.set(SHOW_CONFIRMATION, confirmationMessage);
        new Handler()
                .postDelayed(
                        this::dismissDialog, DELAY_BETWEEN_CONFIRMATION_SHOWN_AND_DISMISSAL_MS);
    }

    void onNewOtpRequested() {
        mDelegate.onNewOtpRequested();
    }

    private void setDialogViewModel(PropertyModel dialogViewModel) {
        mOtpVerificationDialogModel = dialogViewModel;
        mOtpVerificationDialogModel.set(VIEW_DELEGATE, this);
    }
}