chromium/components/messages/android/internal/java/src/org/chromium/components/messages/MessageDispatcherImpl.java

// Copyright 2020 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.components.messages;

import android.animation.Animator;

import androidx.annotation.VisibleForTesting;

import org.chromium.base.Callback;
import org.chromium.base.supplier.Supplier;
import org.chromium.content_public.browser.WebContents;
import org.chromium.ui.base.WindowAndroid;
import org.chromium.ui.modelutil.PropertyModel;

/**
 * This class implements public MessageDispatcher interface, delegating the actual work to
 * MessageQueueManager.
 */
public class MessageDispatcherImpl implements ManagedMessageDispatcher {
    private final MessageQueueManager mMessageQueueManager;
    private final MessageContainer mMessageContainer;
    private final Supplier<Integer> mMessageTopOffset;
    private final Supplier<Integer> mMessageMaxTranslationSupplier;
    private final MessageAutodismissDurationProvider mAutodismissDurationProvider;
    private final SwipeAnimationHandler mSwipeAnimationHandler;
    private final WindowAndroid mWindowAndroid;

    /**
     * Build a new message dispatcher
     *
     * @param messageContainer A container view for displaying message banners.
     * @param messageTopOffset A {@link Supplier} that supplies the top offset between message's top
     * side and app's top edge.
     * @param messageMaxTranslation A {@link Supplier} that supplies the maximum translation Y value
     * the message banner can have as a result of the animations or the gestures.
     * @param autodismissDurationProvider A {@link MessageAutodismissDurationProvider} providing
     * autodismiss duration for message banner.
     * @param animatorStartCallback The {@link Callback} that will be used by the message to
     * delegate starting the animations to the {@link WindowAndroid}.
     * @param windowAndroid The current window Android.
     */
    public MessageDispatcherImpl(
            MessageContainer messageContainer,
            Supplier<Integer> messageTopOffset,
            Supplier<Integer> messageMaxTranslation,
            MessageAutodismissDurationProvider autodismissDurationProvider,
            Callback<Animator> animatorStartCallback,
            WindowAndroid windowAndroid) {
        this(
                messageContainer,
                messageTopOffset,
                messageMaxTranslation,
                autodismissDurationProvider,
                windowAndroid,
                new MessageQueueManager(
                        new MessageAnimationCoordinator(messageContainer, animatorStartCallback)));
    }

    @VisibleForTesting
    MessageDispatcherImpl(
            MessageContainer messageContainer,
            Supplier<Integer> messageTopOffset,
            Supplier<Integer> messageMaxTranslation,
            MessageAutodismissDurationProvider autodismissDurationProvider,
            WindowAndroid windowAndroid,
            MessageQueueManager messageQueueManager) {
        mMessageContainer = messageContainer;
        mMessageTopOffset = messageTopOffset;
        mMessageMaxTranslationSupplier = messageMaxTranslation;
        mAutodismissDurationProvider = autodismissDurationProvider;
        mWindowAndroid = windowAndroid;
        mMessageQueueManager = messageQueueManager;
        mSwipeAnimationHandler = messageQueueManager.getAnimationCoordinator();
    }

    /**
     * Enqueue navigation or webContents scoped message.
     * @param messageProperties The PropertyModel with message's visual properties.
     * @param webContents The webContents the message is associated with.
     * @param scopeType The {@link MessageScopeType} of the message.
     * @param highPriority True if the message should be displayed ASAP.
     */
    @Override
    public void enqueueMessage(
            PropertyModel messageProperties,
            WebContents webContents,
            @MessageScopeType int scopeType,
            boolean highPriority) {
        MessageStateHandler messageStateHandler =
                new SingleActionMessage(
                        mMessageContainer,
                        messageProperties,
                        this::dismissMessage,
                        mMessageMaxTranslationSupplier,
                        mMessageTopOffset,
                        mAutodismissDurationProvider,
                        mSwipeAnimationHandler);
        ScopeKey scopeKey;
        assert scopeType != MessageScopeType.WINDOW
                : "Use #enqueueWindowScopedMessage to enqueue a window-scoped message.";
        scopeKey = new ScopeKey(scopeType, webContents);
        mMessageQueueManager.enqueueMessage(
                messageStateHandler, messageProperties, scopeKey, highPriority);
    }

    @Override
    public void enqueueWindowScopedMessage(PropertyModel messageProperties, boolean highPriority) {
        MessageStateHandler messageStateHandler =
                new SingleActionMessage(
                        mMessageContainer,
                        messageProperties,
                        this::dismissMessage,
                        mMessageMaxTranslationSupplier,
                        mMessageTopOffset,
                        mAutodismissDurationProvider,
                        mSwipeAnimationHandler);
        ScopeKey scopeKey = new ScopeKey(mWindowAndroid);
        mMessageQueueManager.enqueueMessage(
                messageStateHandler, messageProperties, scopeKey, highPriority);
    }

    @Override
    public void dismissMessage(PropertyModel messageProperties, @DismissReason int dismissReason) {
        mMessageQueueManager.dismissMessage(messageProperties, dismissReason);
    }

    @Override
    public void dismissAllMessages(@DismissReason int dismissReason) {
        mMessageQueueManager.dismissAllMessages(dismissReason);
    }

    @Override
    public int suspend() {
        return mMessageQueueManager.suspend();
    }

    @Override
    public void resume(int token) {
        mMessageQueueManager.resume(token);
    }

    @Override
    public void setDelegate(MessageQueueDelegate delegate) {
        mMessageQueueManager.setDelegate(delegate);
    }

    MessageQueueManager getMessageQueueManagerForTesting() {
        return mMessageQueueManager;
    }
}