Commit 69096d11 authored by Sinan Sahin's avatar Sinan Sahin Committed by Commit Bot

[Messages] Handle show/hide on Webapps

This CL also includes a bug fix for the show/hide animations so that
the "message dismissed" callback isn't called for animations that don't
actually hide the message.

Bug: 1137941
Change-Id: I8286feacf03196879642870ce5d582910d8df01e
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2538338Reviewed-by: default avatarPavel Yatsuk <pavely@chromium.org>
Reviewed-by: default avatarTheresa  <twellington@chromium.org>
Commit-Queue: Sinan Sahin <sinansahin@google.com>
Cr-Commit-Position: refs/heads/master@{#829898}
parent 5ae79a3b
...@@ -16,10 +16,12 @@ import org.chromium.chrome.browser.layouts.LayoutStateProvider; ...@@ -16,10 +16,12 @@ import org.chromium.chrome.browser.layouts.LayoutStateProvider;
import org.chromium.chrome.browser.layouts.LayoutStateProvider.LayoutStateObserver; import org.chromium.chrome.browser.layouts.LayoutStateProvider.LayoutStateObserver;
import org.chromium.chrome.browser.layouts.LayoutType; import org.chromium.chrome.browser.layouts.LayoutType;
import org.chromium.chrome.browser.tab.Tab; import org.chromium.chrome.browser.tab.Tab;
import org.chromium.chrome.browser.tab.TabBrowserControlsConstraintsHelper;
import org.chromium.chrome.browser.tabmodel.TabModelObserver; import org.chromium.chrome.browser.tabmodel.TabModelObserver;
import org.chromium.chrome.browser.tabmodel.TabModelSelector; import org.chromium.chrome.browser.tabmodel.TabModelSelector;
import org.chromium.components.messages.ManagedMessageDispatcher; import org.chromium.components.messages.ManagedMessageDispatcher;
import org.chromium.components.messages.MessageQueueDelegate; import org.chromium.components.messages.MessageQueueDelegate;
import org.chromium.content_public.common.BrowserControlsState;
import org.chromium.ui.util.TokenHolder; import org.chromium.ui.util.TokenHolder;
/** /**
...@@ -129,7 +131,9 @@ public class ChromeMessageQueueMediator implements MessageQueueDelegate { ...@@ -129,7 +131,9 @@ public class ChromeMessageQueueMediator implements MessageQueueDelegate {
mBrowserControlsToken = mBrowserControlsToken =
mBrowserControlsManager.getBrowserVisibilityDelegate().showControlsPersistent(); mBrowserControlsManager.getBrowserVisibilityDelegate().showControlsPersistent();
mContainerCoordinator.showMessageContainer(); mContainerCoordinator.showMessageContainer();
if (BrowserControlsUtils.areBrowserControlsFullyVisible(mBrowserControlsManager)) { final Tab tab = mTabModelSelector != null ? mTabModelSelector.getCurrentTab() : null;
if (TabBrowserControlsConstraintsHelper.getConstraints(tab) == BrowserControlsState.HIDDEN
|| BrowserControlsUtils.areBrowserControlsFullyVisible(mBrowserControlsManager)) {
runnable.run(); runnable.run();
} else { } else {
mBrowserControlsObserver.setOneTimeRunnableOnControlsFullyVisible(runnable); mBrowserControlsObserver.setOneTimeRunnableOnControlsFullyVisible(runnable);
......
...@@ -54,14 +54,20 @@ public class MessageContainerCoordinator implements BrowserControlsStateProvider ...@@ -54,14 +54,20 @@ public class MessageContainerCoordinator implements BrowserControlsStateProvider
} }
/** /**
* If there are no browser controls visible, the {@link MessageContainer} view should be laid
* out for this method to return a meaningful value.
*
* @return The maximum translation Y value the message banner can have as a result of the * @return The maximum translation Y value the message banner can have as a result of the
* animations or the gestures. Positive values mean the message banner can be translated * animations or the gestures. Positive values mean the message banner can be translated
* upward from the top of the MessagesContainer. * upward from the top of the MessagesContainer.
*/ */
public int getMessageMaxTranslation() { public int getMessageMaxTranslation() {
// TODO(sinansahin): We need to account for other scenarios where there are no browser final int containerTopOffset = getContainerTopOffset();
// controls visible (e.g. PWAs). if (containerTopOffset == 0) {
return getContainerTopOffset(); return mContainer.getHeight();
}
return containerTopOffset;
} }
@Override @Override
...@@ -77,8 +83,9 @@ public class MessageContainerCoordinator implements BrowserControlsStateProvider ...@@ -77,8 +83,9 @@ public class MessageContainerCoordinator implements BrowserControlsStateProvider
/** @return Offset of the message container from the top of the screen. */ /** @return Offset of the message container from the top of the screen. */
private int getContainerTopOffset() { private int getContainerTopOffset() {
if (mControlsManager.getContentOffset() == 0) return 0;
final Resources res = mContainer.getResources(); final Resources res = mContainer.getResources();
return mControlsManager.getTopControlsHeight() return mControlsManager.getContentOffset()
- res.getDimensionPixelOffset(R.dimen.message_bubble_inset) - res.getDimensionPixelOffset(R.dimen.message_bubble_inset)
- res.getDimensionPixelOffset(R.dimen.message_shadow_top_margin); - res.getDimensionPixelOffset(R.dimen.message_shadow_top_margin);
} }
......
...@@ -51,7 +51,6 @@ class MessageBannerMediator implements SwipeHandler { ...@@ -51,7 +51,6 @@ class MessageBannerMediator implements SwipeHandler {
Resources resources, Runnable messageDismissed) { Resources resources, Runnable messageDismissed) {
mModel = model; mModel = model;
mMaxTranslationSupplier = maxTranslationSupplier; mMaxTranslationSupplier = maxTranslationSupplier;
mModel.set(TRANSLATION_Y, -mMaxTranslationSupplier.get());
mHideThresholdPx = resources.getDimensionPixelSize(R.dimen.message_hide_threshold); mHideThresholdPx = resources.getDimensionPixelSize(R.dimen.message_hide_threshold);
mMessageDismissed = messageDismissed; mMessageDismissed = messageDismissed;
} }
...@@ -61,6 +60,9 @@ class MessageBannerMediator implements SwipeHandler { ...@@ -61,6 +60,9 @@ class MessageBannerMediator implements SwipeHandler {
* @param messageShown The {@link Runnable} that will run once the message banner is shown. * @param messageShown The {@link Runnable} that will run once the message banner is shown.
*/ */
void show(Runnable messageShown) { void show(Runnable messageShown) {
if (mAnimatorSet == null) {
mModel.set(TRANSLATION_Y, -mMaxTranslationSupplier.get());
}
cancelAnyAnimations(); cancelAnyAnimations();
mAnimatorSet = createAnimatorSet(true); mAnimatorSet = createAnimatorSet(true);
mAnimatorSet.addListener(new CancelAwareAnimatorListener() { mAnimatorSet.addListener(new CancelAwareAnimatorListener() {
...@@ -119,11 +121,12 @@ class MessageBannerMediator implements SwipeHandler { ...@@ -119,11 +121,12 @@ class MessageBannerMediator implements SwipeHandler {
// No need to animate if the message banner is in resting position. // No need to animate if the message banner is in resting position.
if (mModel.get(TRANSLATION_Y) == 0.f) return; if (mModel.get(TRANSLATION_Y) == 0.f) return;
mAnimatorSet = createAnimatorSet(mModel.get(TRANSLATION_Y) > -mHideThresholdPx); final boolean isShow = mModel.get(TRANSLATION_Y) > -mHideThresholdPx;
mAnimatorSet = createAnimatorSet(isShow);
mAnimatorSet.addListener(new CancelAwareAnimatorListener() { mAnimatorSet.addListener(new CancelAwareAnimatorListener() {
@Override @Override
public void onEnd(Animator animator) { public void onEnd(Animator animator) {
mMessageDismissed.run(); if (!isShow) mMessageDismissed.run();
mAnimatorSet = null; mAnimatorSet = null;
} }
}); });
......
...@@ -48,4 +48,27 @@ public class MessageContainer extends FrameLayout { ...@@ -48,4 +48,27 @@ public class MessageContainer extends FrameLayout {
ViewUtils.setAncestorsShouldClipChildren(this, true); ViewUtils.setAncestorsShouldClipChildren(this, true);
removeAllViews(); removeAllViews();
} }
/**
* Runs a {@link Runnable} after the initial layout. If the view is already laid out, the
* {@link Runnable} will be called immediately.
* @param runnable The {@link Runnable}.
*/
void runAfterInitialLayout(Runnable runnable) {
if (getHeight() > 0) {
runnable.run();
return;
}
addOnLayoutChangeListener(new OnLayoutChangeListener() {
@Override
public void onLayoutChange(View v, int left, int top, int right, int bottom,
int oldLeft, int oldTop, int oldRight, int oldBottom) {
if (v.getHeight() == 0) return;
runnable.run();
v.removeOnLayoutChangeListener(this);
}
});
}
} }
...@@ -57,11 +57,16 @@ public class SingleActionMessage implements MessageStateHandler { ...@@ -57,11 +57,16 @@ public class SingleActionMessage implements MessageStateHandler {
mContainer.getResources(), mDismissHandler.bind(mModel)); mContainer.getResources(), mDismissHandler.bind(mModel));
} }
mContainer.addMessage(mView); mContainer.addMessage(mView);
final Runnable onShown = () -> {
final Runnable showRunnable = () -> mMessageBanner.show(() -> {
mMessageBanner.setOnTouchRunnable(mAutoDismissTimer::resetTimer); mMessageBanner.setOnTouchRunnable(mAutoDismissTimer::resetTimer);
mAutoDismissTimer.startTimer(() -> { mDismissHandler.onResult(mModel); }); mAutoDismissTimer.startTimer(() -> { mDismissHandler.onResult(mModel); });
}; });
mMessageBanner.show(onShown);
// Wait until the message and the container are measured before showing the message. This
// is required in case the animation set-up requires the height of the container, e.g.
// showing messages without the top controls visible.
mContainer.runAfterInitialLayout(showRunnable);
} }
/** /**
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment