From 52a88e3e161c99b2ebf9d3ca1ba7996580d345ff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Gonz=C3=A1lez?= Date: Fri, 20 Mar 2020 08:48:59 +0100 Subject: [PATCH 001/104] added simple bottom navigation bar --- .../app/browser/BottomNavigationBar.kt | 34 +++++++++ .../res/drawable/ic_bookmarks_black_24dp.xml | 25 +++++++ .../main/res/drawable/ic_fire_black_24dp.xml | 25 +++++++ .../main/res/layout/fragment_browser_tab.xml | 2 + .../layout/layout_bottom_navigation_bar.xml | 69 +++++++++++++++++++ .../layout_bottom_navigation_bar_view.xml | 69 +++++++++++++++++++ 6 files changed, 224 insertions(+) create mode 100644 app/src/main/java/com/duckduckgo/app/browser/BottomNavigationBar.kt create mode 100644 app/src/main/res/drawable/ic_bookmarks_black_24dp.xml create mode 100644 app/src/main/res/drawable/ic_fire_black_24dp.xml create mode 100644 app/src/main/res/layout/layout_bottom_navigation_bar.xml create mode 100644 app/src/main/res/layout/layout_bottom_navigation_bar_view.xml diff --git a/app/src/main/java/com/duckduckgo/app/browser/BottomNavigationBar.kt b/app/src/main/java/com/duckduckgo/app/browser/BottomNavigationBar.kt new file mode 100644 index 000000000000..3ff451a0465a --- /dev/null +++ b/app/src/main/java/com/duckduckgo/app/browser/BottomNavigationBar.kt @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2020 DuckDuckGo + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.duckduckgo.app.browser + +import android.animation.Animator +import android.animation.AnimatorListenerAdapter +import android.content.Context +import android.view.LayoutInflater +import android.widget.FrameLayout +import android.widget.LinearLayout +import com.google.android.material.bottomnavigation.BottomNavigationView +import kotlinx.android.synthetic.main.view_tab_switcher_button.view.* + +class BottomNavigationBar(context: Context) : BottomNavigationView(context) { + + init { + LayoutInflater.from(context).inflate(R.layout.layout_bottom_navigation_bar, this, true) + } + +} \ No newline at end of file diff --git a/app/src/main/res/drawable/ic_bookmarks_black_24dp.xml b/app/src/main/res/drawable/ic_bookmarks_black_24dp.xml new file mode 100644 index 000000000000..917c3f4e6b91 --- /dev/null +++ b/app/src/main/res/drawable/ic_bookmarks_black_24dp.xml @@ -0,0 +1,25 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/ic_fire_black_24dp.xml b/app/src/main/res/drawable/ic_fire_black_24dp.xml new file mode 100644 index 000000000000..f7b42ae701e3 --- /dev/null +++ b/app/src/main/res/drawable/ic_fire_black_24dp.xml @@ -0,0 +1,25 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/fragment_browser_tab.xml b/app/src/main/res/layout/fragment_browser_tab.xml index ee449c483f0a..f1ec6d5c8f8a 100644 --- a/app/src/main/res/layout/fragment_browser_tab.xml +++ b/app/src/main/res/layout/fragment_browser_tab.xml @@ -24,6 +24,8 @@ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/layout_bottom_navigation_bar_view.xml b/app/src/main/res/layout/layout_bottom_navigation_bar_view.xml new file mode 100644 index 000000000000..1ac2c5d9a3dc --- /dev/null +++ b/app/src/main/res/layout/layout_bottom_navigation_bar_view.xml @@ -0,0 +1,69 @@ + + + + + + + + + + + + + \ No newline at end of file From 956adeab0a51c91d83d532a8802ff093d7b3d11e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Gonz=C3=A1lez?= Date: Mon, 23 Mar 2020 14:10:41 +0100 Subject: [PATCH 002/104] adding a new behaviour that hides the bottom bar when scrolling down the content, but shows it when scrolling up --- .../browser/{ => ui}/BottomNavigationBar.kt | 9 +- .../ui/HideBottomViewOnScrollBehavior.java | 165 ++++++++++++++++++ .../layout/layout_bottom_navigation_bar.xml | 6 +- .../layout_bottom_navigation_bar_view.xml | 4 +- 4 files changed, 173 insertions(+), 11 deletions(-) rename app/src/main/java/com/duckduckgo/app/browser/{ => ui}/BottomNavigationBar.kt (74%) create mode 100644 app/src/main/java/com/duckduckgo/app/browser/ui/HideBottomViewOnScrollBehavior.java diff --git a/app/src/main/java/com/duckduckgo/app/browser/BottomNavigationBar.kt b/app/src/main/java/com/duckduckgo/app/browser/ui/BottomNavigationBar.kt similarity index 74% rename from app/src/main/java/com/duckduckgo/app/browser/BottomNavigationBar.kt rename to app/src/main/java/com/duckduckgo/app/browser/ui/BottomNavigationBar.kt index 3ff451a0465a..b0fec5c43c99 100644 --- a/app/src/main/java/com/duckduckgo/app/browser/BottomNavigationBar.kt +++ b/app/src/main/java/com/duckduckgo/app/browser/ui/BottomNavigationBar.kt @@ -14,18 +14,15 @@ * limitations under the License. */ -package com.duckduckgo.app.browser +package com.duckduckgo.app.browser.ui -import android.animation.Animator -import android.animation.AnimatorListenerAdapter import android.content.Context import android.view.LayoutInflater -import android.widget.FrameLayout import android.widget.LinearLayout +import com.duckduckgo.app.browser.R import com.google.android.material.bottomnavigation.BottomNavigationView -import kotlinx.android.synthetic.main.view_tab_switcher_button.view.* -class BottomNavigationBar(context: Context) : BottomNavigationView(context) { +class BottomNavigationBar(context: Context) : LinearLayout(context) { init { LayoutInflater.from(context).inflate(R.layout.layout_bottom_navigation_bar, this, true) diff --git a/app/src/main/java/com/duckduckgo/app/browser/ui/HideBottomViewOnScrollBehavior.java b/app/src/main/java/com/duckduckgo/app/browser/ui/HideBottomViewOnScrollBehavior.java new file mode 100644 index 000000000000..adfb72b02634 --- /dev/null +++ b/app/src/main/java/com/duckduckgo/app/browser/ui/HideBottomViewOnScrollBehavior.java @@ -0,0 +1,165 @@ +/* + * Copyright (c) 2020 DuckDuckGo + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.duckduckgo.app.browser.ui; + +import android.animation.Animator; +import android.animation.AnimatorListenerAdapter; +import android.animation.TimeInterpolator; +import android.content.Context; +import androidx.annotation.Dimension; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.core.view.ViewCompat; +import android.util.AttributeSet; +import android.view.View; +import android.view.ViewGroup; +import android.view.ViewPropertyAnimator; +import androidx.coordinatorlayout.widget.CoordinatorLayout; +import androidx.coordinatorlayout.widget.CoordinatorLayout.Behavior; +import com.google.android.material.animation.AnimationUtils; + +/** + * The {@link Behavior} for a View within a {@link CoordinatorLayout} to hide the view off the + * bottom of the screen when scrolling down, and show it when scrolling up. + */ +public class HideBottomViewOnScrollBehavior extends CoordinatorLayout.Behavior { + + protected static final int ENTER_ANIMATION_DURATION = 225; + protected static final int EXIT_ANIMATION_DURATION = 175; + + private static final int STATE_SCROLLED_DOWN = 1; + private static final int STATE_SCROLLED_UP = 2; + + private int height = 0; + private int currentState = STATE_SCROLLED_UP; + private int additionalHiddenOffsetY = 0; + @Nullable private ViewPropertyAnimator currentAnimator; + + public HideBottomViewOnScrollBehavior() {} + + public HideBottomViewOnScrollBehavior(Context context, AttributeSet attrs) { + super(context, attrs); + } + + @Override + public boolean onLayoutChild( + @NonNull CoordinatorLayout parent, @NonNull V child, int layoutDirection) { + ViewGroup.MarginLayoutParams paramsCompat = + (ViewGroup.MarginLayoutParams) child.getLayoutParams(); + height = child.getMeasuredHeight() + paramsCompat.bottomMargin; + return super.onLayoutChild(parent, child, layoutDirection); + } + + /** + * Sets an additional offset for the y position used to hide the view. + * + * @param child the child view that is hidden by this behavior + * @param offset the additional offset in pixels that should be added when the view slides away + */ + public void setAdditionalHiddenOffsetY(@NonNull V child, @Dimension int offset) { + additionalHiddenOffsetY = offset; + + if (currentState == STATE_SCROLLED_DOWN) { + child.setTranslationY(height + additionalHiddenOffsetY); + } + } + + @Override + public boolean onStartNestedScroll( + @NonNull CoordinatorLayout coordinatorLayout, + @NonNull V child, + @NonNull View directTargetChild, + @NonNull View target, + int nestedScrollAxes, + int type) { + return nestedScrollAxes == ViewCompat.SCROLL_AXIS_VERTICAL; + } + + @Override + public void onNestedScroll( + CoordinatorLayout coordinatorLayout, + @NonNull V child, + @NonNull View target, + int dxConsumed, + int dyConsumed, + int dxUnconsumed, + int dyUnconsumed, + int type, + @NonNull int[] consumed) { + if (dyConsumed > 0) { + slideUp(child); + } else if (dyConsumed < 0) { + slideDown(child); + } + } + + /** + * Perform an animation that will slide the child from it's current position to be totally on the + * screen. + */ + public void slideUp(@NonNull V child) { + if (currentState == STATE_SCROLLED_UP) { + return; + } + + if (currentAnimator != null) { + currentAnimator.cancel(); + child.clearAnimation(); + } + currentState = STATE_SCROLLED_UP; + animateChildTo( + child, 0, ENTER_ANIMATION_DURATION, AnimationUtils.LINEAR_OUT_SLOW_IN_INTERPOLATOR); + } + + /** + * Perform an animation that will slide the child from it's current position to be totally off the + * screen. + */ + public void slideDown(@NonNull V child) { + if (currentState == STATE_SCROLLED_DOWN) { + return; + } + + if (currentAnimator != null) { + currentAnimator.cancel(); + child.clearAnimation(); + } + currentState = STATE_SCROLLED_DOWN; + animateChildTo( + child, + height + additionalHiddenOffsetY, + EXIT_ANIMATION_DURATION, + AnimationUtils.FAST_OUT_LINEAR_IN_INTERPOLATOR); + } + + private void animateChildTo( + @NonNull V child, int targetY, long duration, TimeInterpolator interpolator) { + currentAnimator = + child + .animate() + .translationY(targetY) + .setInterpolator(interpolator) + .setDuration(duration) + .setListener( + new AnimatorListenerAdapter() { + @Override + public void onAnimationEnd(Animator animation) { + currentAnimator = null; + } + }); + } +} \ No newline at end of file diff --git a/app/src/main/res/layout/layout_bottom_navigation_bar.xml b/app/src/main/res/layout/layout_bottom_navigation_bar.xml index 333e5409ef40..f65d5e9f8650 100644 --- a/app/src/main/res/layout/layout_bottom_navigation_bar.xml +++ b/app/src/main/res/layout/layout_bottom_navigation_bar.xml @@ -14,7 +14,7 @@ ~ limitations under the License. --> - + app:layout_behavior="com.duckduckgo.app.browser.ui.HideBottomViewOnScrollBehavior"> - \ No newline at end of file + \ No newline at end of file diff --git a/app/src/main/res/layout/layout_bottom_navigation_bar_view.xml b/app/src/main/res/layout/layout_bottom_navigation_bar_view.xml index 1ac2c5d9a3dc..9d734c630254 100644 --- a/app/src/main/res/layout/layout_bottom_navigation_bar_view.xml +++ b/app/src/main/res/layout/layout_bottom_navigation_bar_view.xml @@ -14,7 +14,7 @@ ~ limitations under the License. --> - - \ No newline at end of file + \ No newline at end of file From afa70064da5066b72a2d4d05cc0734f53e28e323 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Gonz=C3=A1lez?= Date: Mon, 23 Mar 2020 14:39:21 +0100 Subject: [PATCH 003/104] cleaning up the bottombar, proper inheritance --- .../app/browser/ui/BottomNavigationBar.kt | 19 ++++++++++-- .../main/res/layout/fragment_browser_tab.xml | 11 ++++++- .../layout/layout_bottom_navigation_bar.xml | 30 +++++++------------ 3 files changed, 37 insertions(+), 23 deletions(-) diff --git a/app/src/main/java/com/duckduckgo/app/browser/ui/BottomNavigationBar.kt b/app/src/main/java/com/duckduckgo/app/browser/ui/BottomNavigationBar.kt index b0fec5c43c99..7aad74dfb4f4 100644 --- a/app/src/main/java/com/duckduckgo/app/browser/ui/BottomNavigationBar.kt +++ b/app/src/main/java/com/duckduckgo/app/browser/ui/BottomNavigationBar.kt @@ -17,15 +17,28 @@ package com.duckduckgo.app.browser.ui import android.content.Context +import android.util.AttributeSet import android.view.LayoutInflater +import android.view.View import android.widget.LinearLayout import com.duckduckgo.app.browser.R import com.google.android.material.bottomnavigation.BottomNavigationView -class BottomNavigationBar(context: Context) : LinearLayout(context) { +class BottomNavigationBar @JvmOverloads constructor( + context: Context, + attrs: AttributeSet? = null, + defStyleAttr: Int = 0 +) : LinearLayout(context, attrs, defStyleAttr) { - init { - LayoutInflater.from(context).inflate(R.layout.layout_bottom_navigation_bar, this, true) + override fun onFinishInflate() { + super.onFinishInflate() + View.inflate(context, R.layout.layout_bottom_navigation_bar, this) + } + + fun onItemClicked(view: View, onClick: () -> Unit) { + view.setOnClickListener { + onClick() + } } } \ No newline at end of file diff --git a/app/src/main/res/layout/fragment_browser_tab.xml b/app/src/main/res/layout/fragment_browser_tab.xml index f1ec6d5c8f8a..229cfb5eee6a 100644 --- a/app/src/main/res/layout/fragment_browser_tab.xml +++ b/app/src/main/res/layout/fragment_browser_tab.xml @@ -24,7 +24,16 @@ - + - + tools:parentTag="android.widget.LinearLayout"> + android:src="@drawable/ic_arrow_back_24dp" /> + android:src="@drawable/ic_arrow_forward_24dp" /> + android:src="@drawable/ic_fire_black_24dp" /> + android:src="@drawable/ic_bookmarks_black_24dp" /> - \ No newline at end of file + \ No newline at end of file From 9e577a99994110d03b6e1738796df527344cdcdc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Gonz=C3=A1lez?= Date: Mon, 23 Mar 2020 15:40:05 +0100 Subject: [PATCH 004/104] added tabswitcher button to bottomnavigationbar --- .../app/browser/BrowserTabFragment.kt | 51 +++++++++---------- .../app/browser/TabSwitcherButton.kt | 16 ++++-- app/src/main/res/layout/activity_browser.xml | 3 +- .../main/res/layout/fragment_browser_tab.xml | 3 +- .../res/layout/include_new_browser_tab.xml | 1 - .../layout/layout_bottom_navigation_bar.xml | 6 +++ .../res/layout/view_tab_switcher_button.xml | 9 ++-- .../main/res/menu/menu_browser_activity.xml | 34 ------------- 8 files changed, 47 insertions(+), 76 deletions(-) delete mode 100644 app/src/main/res/menu/menu_browser_activity.xml diff --git a/app/src/main/java/com/duckduckgo/app/browser/BrowserTabFragment.kt b/app/src/main/java/com/duckduckgo/app/browser/BrowserTabFragment.kt index 41e05d7f56b8..bcda0cefa782 100644 --- a/app/src/main/java/com/duckduckgo/app/browser/BrowserTabFragment.kt +++ b/app/src/main/java/com/duckduckgo/app/browser/BrowserTabFragment.kt @@ -101,6 +101,11 @@ import kotlinx.android.synthetic.main.include_find_in_page.* import kotlinx.android.synthetic.main.include_new_browser_tab.* import kotlinx.android.synthetic.main.include_omnibar_toolbar.* import kotlinx.android.synthetic.main.include_omnibar_toolbar.view.* +import kotlinx.android.synthetic.main.layout_bottom_navigation_bar.bottomBarBackItem +import kotlinx.android.synthetic.main.layout_bottom_navigation_bar.bottomBarBookmarksItem +import kotlinx.android.synthetic.main.layout_bottom_navigation_bar.bottomBarFireItem +import kotlinx.android.synthetic.main.layout_bottom_navigation_bar.bottomBarForwardItem +import kotlinx.android.synthetic.main.layout_bottom_navigation_bar.bottomBarTabsItem import kotlinx.android.synthetic.main.popup_window_browser_menu.view.* import kotlinx.coroutines.* import org.jetbrains.anko.longToast @@ -209,12 +214,6 @@ class BrowserTabFragment : Fragment(), FindListener, CoroutineScope { private val browserActivity get() = activity as? BrowserActivity - private val tabsButton: MenuItem? - get() = toolbar.menu.findItem(R.id.tabs) - - private val fireMenuButton: MenuItem? - get() = toolbar.menu.findItem(R.id.fire) - private val menuButton: ViewGroup? get() = appBarLayout.browserMenu @@ -268,6 +267,7 @@ class BrowserTabFragment : Fragment(), FindListener, CoroutineScope { createPopupMenu() configureObservers() configureAppBar() + configureBottomBar() configureWebView() viewModel.registerWebViewListener(webViewClient, webChromeClient) configureOmnibarTextInput() @@ -298,8 +298,7 @@ class BrowserTabFragment : Fragment(), FindListener, CoroutineScope { val transport = message.obj as WebView.WebViewTransport transport.webView = webView message.sendToTarget() - val tabsButton = tabsButton?.actionView as TabSwitcherButton - tabsButton.animateCount() + bottomBarTabsItem.animateCount() viewModel.onMessageProcessed() } @@ -314,13 +313,13 @@ class BrowserTabFragment : Fragment(), FindListener, CoroutineScope { } private fun configureShowTabSwitcherListener() { - tabsButton?.actionView?.setOnClickListener { + bottomBarTabsItem.setOnClickListener { launch { viewModel.userLaunchingTabSwitcher() } } } private fun configureLongClickOpensNewTabListener() { - tabsButton?.actionView?.setOnLongClickListener { + bottomBarTabsItem.setOnLongClickListener { launch { viewModel.userRequestedOpeningNewTab() } return@setOnLongClickListener true } @@ -605,8 +604,7 @@ class BrowserTabFragment : Fragment(), FindListener, CoroutineScope { private fun openInNewBackgroundTab() { appBarLayout.setExpanded(true, true) viewModel.tabs.removeObservers(this) - val view = tabsButton?.actionView as TabSwitcherButton - view.increment { + bottomBarTabsItem.increment { addTabsObserver() } } @@ -725,17 +723,6 @@ class BrowserTabFragment : Fragment(), FindListener, CoroutineScope { } private fun configureAppBar() { - toolbar.inflateMenu(R.menu.menu_browser_activity) - - toolbar.setOnMenuItemClickListener { menuItem -> - when (menuItem.itemId) { - R.id.fire -> { - browserActivity?.launchFire() - return@setOnMenuItemClickListener true - } - else -> return@setOnMenuItemClickListener false - } - } toolbar.privacyGradeButton.setOnClickListener { browserActivity?.launchPrivacyDashboard() @@ -756,6 +743,15 @@ class BrowserTabFragment : Fragment(), FindListener, CoroutineScope { }) } + private fun configureBottomBar(){ + bottomNavigationBar.apply { + onItemClicked(bottomBarBackItem) { activity?.onBackPressed() } + onItemClicked(bottomBarForwardItem) { viewModel.onUserPressedForward() } + onItemClicked(bottomBarFireItem) { browserActivity?.launchFire() } + onItemClicked(bottomBarBookmarksItem) { viewModel.onBookmarkAddRequested() } + } + } + private fun configureFindInPage() { findInPageInput.setOnFocusChangeListener { _, hasFocus -> if (hasFocus && findInPageInput.text.toString() != viewModel.findInPageViewState.value?.searchTerm) { @@ -1363,8 +1359,8 @@ class BrowserTabFragment : Fragment(), FindListener, CoroutineScope { private fun renderToolbarMenus(viewState: BrowserViewState) { privacyGradeButton?.isVisible = viewState.showPrivacyGrade clearTextButton?.isVisible = viewState.showClearButton - tabsButton?.isVisible = viewState.showTabsButton - fireMenuButton?.isVisible = viewState.showFireButton + bottomBarTabsItem?.isVisible = viewState.showTabsButton + bottomBarFireItem?.isVisible = viewState.showFireButton menuButton?.isVisible = viewState.showMenuButton } @@ -1386,9 +1382,8 @@ class BrowserTabFragment : Fragment(), FindListener, CoroutineScope { fun renderTabIcon(tabs: List) { context?.let { - val button = tabsButton?.actionView as TabSwitcherButton - button.count = tabs.count() - button.hasUnread = tabs.firstOrNull { !it.viewed } != null + bottomBarTabsItem.count = tabs.count() + bottomBarTabsItem.hasUnread = tabs.firstOrNull { !it.viewed } != null } } diff --git a/app/src/main/java/com/duckduckgo/app/browser/TabSwitcherButton.kt b/app/src/main/java/com/duckduckgo/app/browser/TabSwitcherButton.kt index e698d3a2a367..949fd0287159 100644 --- a/app/src/main/java/com/duckduckgo/app/browser/TabSwitcherButton.kt +++ b/app/src/main/java/com/duckduckgo/app/browser/TabSwitcherButton.kt @@ -19,11 +19,19 @@ package com.duckduckgo.app.browser import android.animation.Animator import android.animation.AnimatorListenerAdapter import android.content.Context +import android.util.AttributeSet import android.view.LayoutInflater +import android.view.View import android.widget.FrameLayout +import android.widget.LinearLayout +import android.widget.RelativeLayout import kotlinx.android.synthetic.main.view_tab_switcher_button.view.* -class TabSwitcherButton(context: Context) : FrameLayout(context) { +class TabSwitcherButton @JvmOverloads constructor( + context: Context, + attrs: AttributeSet? = null, + defStyleAttr: Int = 0 +) : RelativeLayout(context, attrs, defStyleAttr) { var count = 0 set(value) { @@ -38,9 +46,9 @@ class TabSwitcherButton(context: Context) : FrameLayout(context) { anim.progress = if (hasUnread) 1.0f else 0.0f } - init { - LayoutInflater.from(context).inflate(R.layout.view_tab_switcher_button, this, true) - + override fun onFinishInflate() { + super.onFinishInflate() + View.inflate(context, R.layout.view_tab_switcher_button, this) clickZone.setOnClickListener { super.callOnClick() } diff --git a/app/src/main/res/layout/activity_browser.xml b/app/src/main/res/layout/activity_browser.xml index 24bbbdca1c5e..eb2c1d43d6fb 100644 --- a/app/src/main/res/layout/activity_browser.xml +++ b/app/src/main/res/layout/activity_browser.xml @@ -22,8 +22,7 @@ android:layout_width="match_parent" android:layout_height="match_parent" app:layout_scrollFlags="scroll|enterAlways" - tools:context="com.duckduckgo.app.browser.BrowserActivity" - tools:menu="@menu/menu_browser_activity"> + tools:context="com.duckduckgo.app.browser.BrowserActivity"> + tools:context="com.duckduckgo.app.browser.BrowserActivity"> + + \ No newline at end of file diff --git a/app/src/main/res/layout/view_tab_switcher_button.xml b/app/src/main/res/layout/view_tab_switcher_button.xml index eaa521925e51..6166cf3a3fce 100644 --- a/app/src/main/res/layout/view_tab_switcher_button.xml +++ b/app/src/main/res/layout/view_tab_switcher_button.xml @@ -14,11 +14,10 @@ ~ limitations under the License. --> - + tools:parentTag="android.widget.RelativeLayout"> - \ No newline at end of file + \ No newline at end of file diff --git a/app/src/main/res/menu/menu_browser_activity.xml b/app/src/main/res/menu/menu_browser_activity.xml deleted file mode 100644 index b1a9ae5d5b9b..000000000000 --- a/app/src/main/res/menu/menu_browser_activity.xml +++ /dev/null @@ -1,34 +0,0 @@ - - - - - - - - - \ No newline at end of file From d8465a68ba34e8df1de8c04dd17aa713b1eea028 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Gonz=C3=A1lez?= Date: Mon, 23 Mar 2020 15:46:04 +0100 Subject: [PATCH 005/104] enabling buttons in bottom bar based on state --- .../java/com/duckduckgo/app/browser/BrowserTabFragment.kt | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/app/src/main/java/com/duckduckgo/app/browser/BrowserTabFragment.kt b/app/src/main/java/com/duckduckgo/app/browser/BrowserTabFragment.kt index bcda0cefa782..ea4a3e1e3453 100644 --- a/app/src/main/java/com/duckduckgo/app/browser/BrowserTabFragment.kt +++ b/app/src/main/java/com/duckduckgo/app/browser/BrowserTabFragment.kt @@ -748,7 +748,7 @@ class BrowserTabFragment : Fragment(), FindListener, CoroutineScope { onItemClicked(bottomBarBackItem) { activity?.onBackPressed() } onItemClicked(bottomBarForwardItem) { viewModel.onUserPressedForward() } onItemClicked(bottomBarFireItem) { browserActivity?.launchFire() } - onItemClicked(bottomBarBookmarksItem) { viewModel.onBookmarkAddRequested() } + onItemClicked(bottomBarBookmarksItem) { launch { viewModel.onBookmarkAddRequested() } } } } @@ -1323,6 +1323,7 @@ class BrowserTabFragment : Fragment(), FindListener, CoroutineScope { toggleDesktopSiteMode(viewState.isDesktopBrowsingMode) renderToolbarMenus(viewState) + renderBottomBar(viewState) renderPopupMenus(browserShowing, viewState) renderFullscreenMode(viewState) } @@ -1338,6 +1339,11 @@ class BrowserTabFragment : Fragment(), FindListener, CoroutineScope { } } + private fun renderBottomBar(viewState: BrowserViewState){ + bottomBarForwardItem.isEnabled = viewState.canGoForward + bottomBarBackItem.isEnabled = viewState.canGoBack + } + private fun renderPopupMenus(browserShowing: Boolean, viewState: BrowserViewState) { popupMenu.contentView.apply { backPopupMenuItem.isEnabled = viewState.canGoBack From 59525f812e9f6eb3ca5c97fe964c2183906b741c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Gonz=C3=A1lez?= Date: Mon, 23 Mar 2020 17:35:05 +0100 Subject: [PATCH 006/104] removing all scrolling layout flags from the xml, we use the OmnibarScrolling for that --- .../app/browser/omnibar/OmnibarScrolling.kt | 3 +- .../ui/HideBottomViewOnScrollBehavior.java | 225 +++++++++--------- app/src/main/res/layout/activity_browser.xml | 2 - .../main/res/layout/fragment_browser_tab.xml | 3 +- .../res/layout/include_omnibar_toolbar.xml | 21 +- .../layout/layout_bottom_navigation_bar.xml | 8 +- 6 files changed, 130 insertions(+), 132 deletions(-) diff --git a/app/src/main/java/com/duckduckgo/app/browser/omnibar/OmnibarScrolling.kt b/app/src/main/java/com/duckduckgo/app/browser/omnibar/OmnibarScrolling.kt index dc7e17685eb1..f02d11228b1d 100644 --- a/app/src/main/java/com/duckduckgo/app/browser/omnibar/OmnibarScrolling.kt +++ b/app/src/main/java/com/duckduckgo/app/browser/omnibar/OmnibarScrolling.kt @@ -18,8 +18,7 @@ package com.duckduckgo.app.browser.omnibar import android.view.View import com.google.android.material.appbar.AppBarLayout -import com.google.android.material.appbar.AppBarLayout.LayoutParams.SCROLL_FLAG_ENTER_ALWAYS -import com.google.android.material.appbar.AppBarLayout.LayoutParams.SCROLL_FLAG_SCROLL +import com.google.android.material.appbar.AppBarLayout.LayoutParams.* import javax.inject.Inject diff --git a/app/src/main/java/com/duckduckgo/app/browser/ui/HideBottomViewOnScrollBehavior.java b/app/src/main/java/com/duckduckgo/app/browser/ui/HideBottomViewOnScrollBehavior.java index adfb72b02634..acb62eba43da 100644 --- a/app/src/main/java/com/duckduckgo/app/browser/ui/HideBottomViewOnScrollBehavior.java +++ b/app/src/main/java/com/duckduckgo/app/browser/ui/HideBottomViewOnScrollBehavior.java @@ -20,16 +20,18 @@ import android.animation.AnimatorListenerAdapter; import android.animation.TimeInterpolator; import android.content.Context; -import androidx.annotation.Dimension; -import androidx.annotation.NonNull; -import androidx.annotation.Nullable; -import androidx.core.view.ViewCompat; import android.util.AttributeSet; import android.view.View; import android.view.ViewGroup; import android.view.ViewPropertyAnimator; + +import androidx.annotation.Dimension; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; import androidx.coordinatorlayout.widget.CoordinatorLayout; import androidx.coordinatorlayout.widget.CoordinatorLayout.Behavior; +import androidx.core.view.ViewCompat; + import com.google.android.material.animation.AnimationUtils; /** @@ -38,128 +40,133 @@ */ public class HideBottomViewOnScrollBehavior extends CoordinatorLayout.Behavior { - protected static final int ENTER_ANIMATION_DURATION = 225; - protected static final int EXIT_ANIMATION_DURATION = 175; + protected static final int ENTER_ANIMATION_DURATION = 225; + protected static final int EXIT_ANIMATION_DURATION = 175; - private static final int STATE_SCROLLED_DOWN = 1; - private static final int STATE_SCROLLED_UP = 2; + private static final int STATE_SCROLLED_DOWN = 1; + private static final int STATE_SCROLLED_UP = 2; - private int height = 0; - private int currentState = STATE_SCROLLED_UP; - private int additionalHiddenOffsetY = 0; - @Nullable private ViewPropertyAnimator currentAnimator; + private int height = 0; + private int currentState = STATE_SCROLLED_UP; + private int additionalHiddenOffsetY = 0; + @Nullable + private ViewPropertyAnimator currentAnimator; - public HideBottomViewOnScrollBehavior() {} - - public HideBottomViewOnScrollBehavior(Context context, AttributeSet attrs) { - super(context, attrs); - } - - @Override - public boolean onLayoutChild( - @NonNull CoordinatorLayout parent, @NonNull V child, int layoutDirection) { - ViewGroup.MarginLayoutParams paramsCompat = - (ViewGroup.MarginLayoutParams) child.getLayoutParams(); - height = child.getMeasuredHeight() + paramsCompat.bottomMargin; - return super.onLayoutChild(parent, child, layoutDirection); - } + public HideBottomViewOnScrollBehavior() { + } - /** - * Sets an additional offset for the y position used to hide the view. - * - * @param child the child view that is hidden by this behavior - * @param offset the additional offset in pixels that should be added when the view slides away - */ - public void setAdditionalHiddenOffsetY(@NonNull V child, @Dimension int offset) { - additionalHiddenOffsetY = offset; - - if (currentState == STATE_SCROLLED_DOWN) { - child.setTranslationY(height + additionalHiddenOffsetY); + public HideBottomViewOnScrollBehavior(Context context, AttributeSet attrs) { + super(context, attrs); } - } - @Override - public boolean onStartNestedScroll( - @NonNull CoordinatorLayout coordinatorLayout, - @NonNull V child, - @NonNull View directTargetChild, - @NonNull View target, - int nestedScrollAxes, - int type) { - return nestedScrollAxes == ViewCompat.SCROLL_AXIS_VERTICAL; - } + @Override + public boolean onLayoutChild(@NonNull CoordinatorLayout parent, @NonNull V child, int layoutDirection) { + ViewGroup.MarginLayoutParams paramsCompat = (ViewGroup.MarginLayoutParams) child.getLayoutParams(); + height = child.getMeasuredHeight() + paramsCompat.bottomMargin; + return super.onLayoutChild(parent, child, layoutDirection); + } - @Override - public void onNestedScroll( - CoordinatorLayout coordinatorLayout, - @NonNull V child, - @NonNull View target, - int dxConsumed, - int dyConsumed, - int dxUnconsumed, - int dyUnconsumed, - int type, - @NonNull int[] consumed) { - if (dyConsumed > 0) { - slideUp(child); - } else if (dyConsumed < 0) { - slideDown(child); + /** + * Sets an additional offset for the y position used to hide the view. + * + * @param child the child view that is hidden by this behavior + * @param offset the additional offset in pixels that should be added when the view slides away + */ + public void setAdditionalHiddenOffsetY(@NonNull V child, @Dimension int offset) { + additionalHiddenOffsetY = offset; + + if (currentState == STATE_SCROLLED_DOWN) { + child.setTranslationY(height + additionalHiddenOffsetY); + } } - } - /** - * Perform an animation that will slide the child from it's current position to be totally on the - * screen. - */ - public void slideUp(@NonNull V child) { - if (currentState == STATE_SCROLLED_UP) { - return; + @Override + public boolean onStartNestedScroll( + @NonNull CoordinatorLayout coordinatorLayout, + @NonNull V child, + @NonNull View directTargetChild, + @NonNull View target, + int nestedScrollAxes, + int type) { + return nestedScrollAxes == ViewCompat.SCROLL_AXIS_VERTICAL; } - if (currentAnimator != null) { - currentAnimator.cancel(); - child.clearAnimation(); + @Override + public void onNestedScroll( + CoordinatorLayout coordinatorLayout, + @NonNull V child, + @NonNull View target, + int dxConsumed, + int dyConsumed, + int dxUnconsumed, + int dyUnconsumed, + int type, + @NonNull int[] consumed) { + if (dyConsumed > 0) { + slideUp(child); + } else if (dyConsumed < 0) { + slideDown(child); + } } - currentState = STATE_SCROLLED_UP; - animateChildTo( - child, 0, ENTER_ANIMATION_DURATION, AnimationUtils.LINEAR_OUT_SLOW_IN_INTERPOLATOR); + + @Override + public boolean layoutDependsOn(@NonNull CoordinatorLayout parent, @NonNull V child, @NonNull View dependency) { + return super.layoutDependsOn(parent, child, dependency); } /** - * Perform an animation that will slide the child from it's current position to be totally off the - * screen. - */ - public void slideDown(@NonNull V child) { - if (currentState == STATE_SCROLLED_DOWN) { - return; + * Perform an animation that will slide the child from it's current position to be totally on the + * screen. + */ + public void slideUp(@NonNull V child) { + if (currentState == STATE_SCROLLED_UP) { + return; + } + + if (currentAnimator != null) { + currentAnimator.cancel(); + child.clearAnimation(); + } + currentState = STATE_SCROLLED_UP; + animateChildTo( + child, 0, ENTER_ANIMATION_DURATION, AnimationUtils.LINEAR_OUT_SLOW_IN_INTERPOLATOR); } - if (currentAnimator != null) { - currentAnimator.cancel(); - child.clearAnimation(); + /** + * Perform an animation that will slide the child from it's current position to be totally off the + * screen. + */ + public void slideDown(@NonNull V child) { + if (currentState == STATE_SCROLLED_DOWN) { + return; + } + + if (currentAnimator != null) { + currentAnimator.cancel(); + child.clearAnimation(); + } + currentState = STATE_SCROLLED_DOWN; + animateChildTo( + child, + height + additionalHiddenOffsetY, + EXIT_ANIMATION_DURATION, + AnimationUtils.FAST_OUT_LINEAR_IN_INTERPOLATOR); } - currentState = STATE_SCROLLED_DOWN; - animateChildTo( - child, - height + additionalHiddenOffsetY, - EXIT_ANIMATION_DURATION, - AnimationUtils.FAST_OUT_LINEAR_IN_INTERPOLATOR); - } - private void animateChildTo( - @NonNull V child, int targetY, long duration, TimeInterpolator interpolator) { - currentAnimator = - child - .animate() - .translationY(targetY) - .setInterpolator(interpolator) - .setDuration(duration) - .setListener( - new AnimatorListenerAdapter() { - @Override - public void onAnimationEnd(Animator animation) { - currentAnimator = null; - } - }); - } + private void animateChildTo( + @NonNull V child, int targetY, long duration, TimeInterpolator interpolator) { + currentAnimator = + child + .animate() + .translationY(targetY) + .setInterpolator(interpolator) + .setDuration(duration) + .setListener( + new AnimatorListenerAdapter() { + @Override + public void onAnimationEnd(Animator animation) { + currentAnimator = null; + } + }); + } } \ No newline at end of file diff --git a/app/src/main/res/layout/activity_browser.xml b/app/src/main/res/layout/activity_browser.xml index eb2c1d43d6fb..af5c31b1dd5f 100644 --- a/app/src/main/res/layout/activity_browser.xml +++ b/app/src/main/res/layout/activity_browser.xml @@ -21,10 +21,8 @@ xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" - app:layout_scrollFlags="scroll|enterAlways" tools:context="com.duckduckgo.app.browser.BrowserActivity"> - + android:layout_height="match_parent"> diff --git a/app/src/main/res/layout/include_omnibar_toolbar.xml b/app/src/main/res/layout/include_omnibar_toolbar.xml index 291301e25444..1368ad9d2a33 100644 --- a/app/src/main/res/layout/include_omnibar_toolbar.xml +++ b/app/src/main/res/layout/include_omnibar_toolbar.xml @@ -27,16 +27,13 @@ android:id="@+id/appBarLayout" android:layout_width="match_parent" android:layout_height="?attr/actionBarSize" - android:fitsSystemWindows="true" - android:theme="@style/AppTheme.Dark.AppBarOverlay" - app:layout_scrollFlags="scroll|enterAlways"> + android:theme="@style/AppTheme.Dark.AppBarOverlay"> + android:theme="@style/OmnibarToolbarTheme"> - + - diff --git a/app/src/main/res/layout/layout_bottom_navigation_bar.xml b/app/src/main/res/layout/layout_bottom_navigation_bar.xml index cc2c9f3cc941..e7618ad3ec35 100644 --- a/app/src/main/res/layout/layout_bottom_navigation_bar.xml +++ b/app/src/main/res/layout/layout_bottom_navigation_bar.xml @@ -24,7 +24,7 @@ android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_weight="1" - android:background="?selectableItemBackground" + android:background="?selectableItemBackgroundBorderless" android:contentDescription="@string/back" android:src="@drawable/ic_arrow_back_24dp" /> @@ -34,7 +34,7 @@ android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_weight="1" - android:background="?selectableItemBackground" + android:background="?selectableItemBackgroundBorderless" android:contentDescription="@string/back" android:src="@drawable/ic_arrow_forward_24dp" /> @@ -44,7 +44,7 @@ android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_weight="1" - android:background="?selectableItemBackground" + android:background="?selectableItemBackgroundBorderless" android:contentDescription="@string/back" android:src="@drawable/ic_fire_black_24dp" /> @@ -54,7 +54,7 @@ android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_weight="1" - android:background="?selectableItemBackground" + android:background="?selectableItemBackgroundBorderless" android:contentDescription="@string/back" android:src="@drawable/ic_bookmarks_black_24dp" /> From eea2c487e19e4f6265409dc056ed70814ccb011e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Gonz=C3=A1lez?= Date: Tue, 24 Mar 2020 10:34:42 +0100 Subject: [PATCH 007/104] adding snapping behaviour to the bottom bar --- .../app/browser/omnibar/OmnibarScrolling.kt | 2 +- .../browser/ui/BottomNavigationBehavior.kt | 117 ++++++++++++++++++ .../main/res/layout/fragment_browser_tab.xml | 2 +- 3 files changed, 119 insertions(+), 2 deletions(-) create mode 100644 app/src/main/java/com/duckduckgo/app/browser/ui/BottomNavigationBehavior.kt diff --git a/app/src/main/java/com/duckduckgo/app/browser/omnibar/OmnibarScrolling.kt b/app/src/main/java/com/duckduckgo/app/browser/omnibar/OmnibarScrolling.kt index f02d11228b1d..398b4c7eae42 100644 --- a/app/src/main/java/com/duckduckgo/app/browser/omnibar/OmnibarScrolling.kt +++ b/app/src/main/java/com/duckduckgo/app/browser/omnibar/OmnibarScrolling.kt @@ -25,7 +25,7 @@ import javax.inject.Inject class OmnibarScrolling @Inject constructor() { fun enableOmnibarScrolling(toolbarContainer: View) { - updateScrollFlag(SCROLL_FLAG_SCROLL or SCROLL_FLAG_ENTER_ALWAYS, toolbarContainer) + updateScrollFlag(SCROLL_FLAG_SCROLL or SCROLL_FLAG_SNAP or SCROLL_FLAG_ENTER_ALWAYS, toolbarContainer) } fun disableOmnibarScrolling(toolbarContainer: View) { diff --git a/app/src/main/java/com/duckduckgo/app/browser/ui/BottomNavigationBehavior.kt b/app/src/main/java/com/duckduckgo/app/browser/ui/BottomNavigationBehavior.kt new file mode 100644 index 000000000000..5e6e61bf4bf1 --- /dev/null +++ b/app/src/main/java/com/duckduckgo/app/browser/ui/BottomNavigationBehavior.kt @@ -0,0 +1,117 @@ +/* + * Copyright (c) 2020 DuckDuckGo + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.duckduckgo.app.browser.ui + +import android.animation.ValueAnimator +import android.content.Context +import android.util.AttributeSet +import android.view.Gravity +import android.view.View +import android.view.animation.DecelerateInterpolator +import androidx.coordinatorlayout.widget.CoordinatorLayout +import androidx.core.view.ViewCompat +import com.google.android.material.snackbar.Snackbar + +class BottomNavigationBehavior(context: Context, attrs: AttributeSet) : + CoordinatorLayout.Behavior(context, attrs) { + + @ViewCompat.NestedScrollType + private var lastStartedType: Int = 0 + + private var offsetAnimator: ValueAnimator? = null + + var isSnappingEnabled = true + + override fun layoutDependsOn(parent: CoordinatorLayout, child: V, dependency: View): Boolean { + if (dependency is Snackbar.SnackbarLayout) { + updateSnackbar(child, dependency) + } + return super.layoutDependsOn(parent, child, dependency) + } + + override fun onStartNestedScroll( + coordinatorLayout: CoordinatorLayout, child: V, directTargetChild: View, target: View, axes: Int, type: Int + ): Boolean { + if (axes != ViewCompat.SCROLL_AXIS_VERTICAL) + return false + + lastStartedType = type + + offsetAnimator?.cancel() + + return true + } + + override fun onNestedPreScroll( + coordinatorLayout: CoordinatorLayout, child: V, target: View, dx: Int, dy: Int, consumed: IntArray, type: Int + ) { + super.onNestedPreScroll(coordinatorLayout, child, target, dx, dy, consumed, type) + child.translationY = kotlin.math.max(0f, kotlin.math.min(child.height.toFloat(), child.translationY + dy)) + } + + override fun onStopNestedScroll(coordinatorLayout: CoordinatorLayout, child: V, target: View, type: Int) { + if (!isSnappingEnabled) + return + + // add snap behaviour + // Logic here borrowed from AppBarLayout onStopNestedScroll code + if (lastStartedType == ViewCompat.TYPE_TOUCH || type == ViewCompat.TYPE_NON_TOUCH) { + // find nearest seam + val currTranslation = child.translationY + val childHalfHeight = child.height * 0.5f + + // translate down + if (currTranslation >= childHalfHeight) { + animateBarVisibility(child, isVisible = false) + } + // translate up + else { + animateBarVisibility(child, isVisible = true) + } + } + } + + private fun animateBarVisibility(child: View, isVisible: Boolean) { + if (offsetAnimator == null) { + offsetAnimator = ValueAnimator().apply { + interpolator = DecelerateInterpolator() + duration = 150L + } + + offsetAnimator?.addUpdateListener { + child.translationY = it.animatedValue as Float + } + } else { + offsetAnimator?.cancel() + } + + val targetTranslation = if (isVisible) 0f else child.height.toFloat() + offsetAnimator?.setFloatValues(child.translationY, targetTranslation) + offsetAnimator?.start() + } + + private fun updateSnackbar(child: View, snackbarLayout: Snackbar.SnackbarLayout) { + if (snackbarLayout.layoutParams is CoordinatorLayout.LayoutParams) { + val params = snackbarLayout.layoutParams as CoordinatorLayout.LayoutParams + + params.anchorId = child.id + params.anchorGravity = Gravity.TOP + params.gravity = Gravity.TOP + snackbarLayout.layoutParams = params + } + } +} \ No newline at end of file diff --git a/app/src/main/res/layout/fragment_browser_tab.xml b/app/src/main/res/layout/fragment_browser_tab.xml index c15557bedeaa..55dd5c3e00a0 100644 --- a/app/src/main/res/layout/fragment_browser_tab.xml +++ b/app/src/main/res/layout/fragment_browser_tab.xml @@ -32,7 +32,7 @@ android:elevation="8dp" android:gravity="center" android:orientation="horizontal" - app:layout_behavior="com.duckduckgo.app.browser.ui.HideBottomViewOnScrollBehavior" /> + app:layout_behavior="com.duckduckgo.app.browser.ui.BottomNavigationBehavior" /> Date: Wed, 25 Mar 2020 10:19:55 +0100 Subject: [PATCH 008/104] cleaning up the behaviour --- .../app/browser/ui/BottomNavigationBehavior.kt | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/app/src/main/java/com/duckduckgo/app/browser/ui/BottomNavigationBehavior.kt b/app/src/main/java/com/duckduckgo/app/browser/ui/BottomNavigationBehavior.kt index 5e6e61bf4bf1..b448325c70e7 100644 --- a/app/src/main/java/com/duckduckgo/app/browser/ui/BottomNavigationBehavior.kt +++ b/app/src/main/java/com/duckduckgo/app/browser/ui/BottomNavigationBehavior.kt @@ -44,7 +44,12 @@ class BottomNavigationBehavior(context: Context, attrs: AttributeSet) } override fun onStartNestedScroll( - coordinatorLayout: CoordinatorLayout, child: V, directTargetChild: View, target: View, axes: Int, type: Int + coordinatorLayout: CoordinatorLayout, + child: V, + directTargetChild: View, + target: View, + axes: Int, + type: Int ): Boolean { if (axes != ViewCompat.SCROLL_AXIS_VERTICAL) return false @@ -56,9 +61,7 @@ class BottomNavigationBehavior(context: Context, attrs: AttributeSet) return true } - override fun onNestedPreScroll( - coordinatorLayout: CoordinatorLayout, child: V, target: View, dx: Int, dy: Int, consumed: IntArray, type: Int - ) { + override fun onNestedPreScroll(coordinatorLayout: CoordinatorLayout, child: V, target: View, dx: Int, dy: Int, consumed: IntArray, type: Int) { super.onNestedPreScroll(coordinatorLayout, child, target, dx, dy, consumed, type) child.translationY = kotlin.math.max(0f, kotlin.math.min(child.height.toFloat(), child.translationY + dy)) } @@ -67,8 +70,6 @@ class BottomNavigationBehavior(context: Context, attrs: AttributeSet) if (!isSnappingEnabled) return - // add snap behaviour - // Logic here borrowed from AppBarLayout onStopNestedScroll code if (lastStartedType == ViewCompat.TYPE_TOUCH || type == ViewCompat.TYPE_NON_TOUCH) { // find nearest seam val currTranslation = child.translationY From 8f0d084cad39e012575f9ff7d9630ef2ca8f0415 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Gonz=C3=A1lez?= Date: Wed, 25 Mar 2020 14:15:33 +0100 Subject: [PATCH 009/104] added missing menu for browser activity --- .../main/res/menu/menu_browser_activity.xml | 34 +++++++++++++++++++ 1 file changed, 34 insertions(+) create mode 100644 app/src/main/res/menu/menu_browser_activity.xml diff --git a/app/src/main/res/menu/menu_browser_activity.xml b/app/src/main/res/menu/menu_browser_activity.xml new file mode 100644 index 000000000000..d537d514af14 --- /dev/null +++ b/app/src/main/res/menu/menu_browser_activity.xml @@ -0,0 +1,34 @@ + + + + + + + + + \ No newline at end of file From c4627168d21e20f1fa4c1852d1b45edf1d665fec Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Gonz=C3=A1lez?= Date: Wed, 25 Mar 2020 14:33:36 +0100 Subject: [PATCH 010/104] added experiment decorator that will handle UI for different experiments --- .../app/browser/BrowserTabFragment.kt | 191 +++++++++++++++--- 1 file changed, 163 insertions(+), 28 deletions(-) diff --git a/app/src/main/java/com/duckduckgo/app/browser/BrowserTabFragment.kt b/app/src/main/java/com/duckduckgo/app/browser/BrowserTabFragment.kt index ea4a3e1e3453..c404aa308a7c 100644 --- a/app/src/main/java/com/duckduckgo/app/browser/BrowserTabFragment.kt +++ b/app/src/main/java/com/duckduckgo/app/browser/BrowserTabFragment.kt @@ -23,20 +23,37 @@ import android.annotation.SuppressLint import android.app.Activity.RESULT_OK import android.app.ActivityOptions import android.appwidget.AppWidgetManager -import android.content.* +import android.content.ClipData +import android.content.ClipboardManager +import android.content.ComponentName +import android.content.Context +import android.content.Intent import android.content.pm.PackageManager import android.content.res.Configuration import android.media.MediaScannerConnection import android.net.Uri -import android.os.* +import android.os.Build +import android.os.Bundle +import android.os.Environment +import android.os.Handler +import android.os.Message import android.text.Editable -import android.view.* +import android.view.ContextMenu +import android.view.KeyEvent +import android.view.LayoutInflater +import android.view.MenuItem +import android.view.View import android.view.View.* +import android.view.ViewGroup import android.view.inputmethod.EditorInfo -import android.webkit.* +import android.webkit.ValueCallback +import android.webkit.WebChromeClient +import android.webkit.WebSettings +import android.webkit.WebView import android.webkit.WebView.FindListener import android.webkit.WebView.HitTestResult import android.webkit.WebView.HitTestResult.* +import android.webkit.WebViewDatabase import android.widget.EditText import android.widget.TextView import android.widget.Toast @@ -52,7 +69,11 @@ import androidx.core.view.isVisible import androidx.core.view.postDelayed import androidx.fragment.app.DialogFragment import androidx.fragment.app.Fragment -import androidx.lifecycle.* +import androidx.lifecycle.Lifecycle +import androidx.lifecycle.LifecycleObserver +import androidx.lifecycle.Observer +import androidx.lifecycle.OnLifecycleEvent +import androidx.lifecycle.ViewModelProviders import androidx.recyclerview.widget.LinearLayoutManager import com.duckduckgo.app.autocomplete.api.AutoComplete.AutoCompleteSuggestion import com.duckduckgo.app.bookmarks.ui.EditBookmarkDialogFragment @@ -76,10 +97,25 @@ import com.duckduckgo.app.browser.tabpreview.WebViewPreviewGenerator import com.duckduckgo.app.browser.tabpreview.WebViewPreviewPersister import com.duckduckgo.app.browser.ui.HttpAuthenticationDialogFragment import com.duckduckgo.app.browser.useragent.UserAgentProvider -import com.duckduckgo.app.cta.ui.* +import com.duckduckgo.app.cta.ui.Cta +import com.duckduckgo.app.cta.ui.CtaViewModel +import com.duckduckgo.app.cta.ui.DaxBubbleCta +import com.duckduckgo.app.cta.ui.DaxDialogCta +import com.duckduckgo.app.cta.ui.HomePanelCta +import com.duckduckgo.app.cta.ui.SecondaryButtonCta import com.duckduckgo.app.global.ViewModelFactory import com.duckduckgo.app.global.device.DeviceInfo -import com.duckduckgo.app.global.view.* +import com.duckduckgo.app.global.view.NonDismissibleBehavior +import com.duckduckgo.app.global.view.TextChangedWatcher +import com.duckduckgo.app.global.view.gone +import com.duckduckgo.app.global.view.hide +import com.duckduckgo.app.global.view.hideKeyboard +import com.duckduckgo.app.global.view.isDifferent +import com.duckduckgo.app.global.view.isImmersiveModeEnabled +import com.duckduckgo.app.global.view.renderIfChanged +import com.duckduckgo.app.global.view.show +import com.duckduckgo.app.global.view.showKeyboard +import com.duckduckgo.app.global.view.toggleFullScreen import com.duckduckgo.app.onboarding.ui.page.DefaultBrowserPage import com.duckduckgo.app.privacy.model.PrivacyGrade import com.duckduckgo.app.privacy.renderer.icon @@ -94,20 +130,64 @@ import com.duckduckgo.app.widget.ui.AddWidgetInstructionsActivity import com.duckduckgo.widget.SearchWidgetLight import com.google.android.material.snackbar.Snackbar import dagger.android.support.AndroidSupportInjection -import kotlinx.android.synthetic.main.fragment_browser_tab.* -import kotlinx.android.synthetic.main.include_cta_buttons.view.* -import kotlinx.android.synthetic.main.include_dax_dialog_cta.* -import kotlinx.android.synthetic.main.include_find_in_page.* -import kotlinx.android.synthetic.main.include_new_browser_tab.* -import kotlinx.android.synthetic.main.include_omnibar_toolbar.* -import kotlinx.android.synthetic.main.include_omnibar_toolbar.view.* +import kotlinx.android.synthetic.main.fragment_browser_tab.autoCompleteSuggestionsList +import kotlinx.android.synthetic.main.fragment_browser_tab.bottomNavigationBar +import kotlinx.android.synthetic.main.fragment_browser_tab.browserLayout +import kotlinx.android.synthetic.main.fragment_browser_tab.defaultCard +import kotlinx.android.synthetic.main.fragment_browser_tab.focusDummy +import kotlinx.android.synthetic.main.fragment_browser_tab.rootView +import kotlinx.android.synthetic.main.fragment_browser_tab.webViewContainer +import kotlinx.android.synthetic.main.fragment_browser_tab.webViewFullScreenContainer +import kotlinx.android.synthetic.main.include_cta_buttons.view.ctaDismissButton +import kotlinx.android.synthetic.main.include_cta_buttons.view.ctaOkButton +import kotlinx.android.synthetic.main.include_dax_dialog_cta.daxCtaContainer +import kotlinx.android.synthetic.main.include_dax_dialog_cta.dialogTextCta +import kotlinx.android.synthetic.main.include_find_in_page.closeFindInPagePanel +import kotlinx.android.synthetic.main.include_find_in_page.findInPageContainer +import kotlinx.android.synthetic.main.include_find_in_page.findInPageInput +import kotlinx.android.synthetic.main.include_find_in_page.findInPageMatches +import kotlinx.android.synthetic.main.include_find_in_page.nextSearchTermButton +import kotlinx.android.synthetic.main.include_find_in_page.previousSearchTermButton +import kotlinx.android.synthetic.main.include_new_browser_tab.ctaContainer +import kotlinx.android.synthetic.main.include_new_browser_tab.ddgLogo +import kotlinx.android.synthetic.main.include_new_browser_tab.newTabLayout +import kotlinx.android.synthetic.main.include_omnibar_toolbar.appBarLayout +import kotlinx.android.synthetic.main.include_omnibar_toolbar.browserMenu +import kotlinx.android.synthetic.main.include_omnibar_toolbar.clearTextButton +import kotlinx.android.synthetic.main.include_omnibar_toolbar.networksContainer +import kotlinx.android.synthetic.main.include_omnibar_toolbar.omniBarContainer +import kotlinx.android.synthetic.main.include_omnibar_toolbar.omnibarTextInput +import kotlinx.android.synthetic.main.include_omnibar_toolbar.pageLoadingIndicator +import kotlinx.android.synthetic.main.include_omnibar_toolbar.privacyGradeButton +import kotlinx.android.synthetic.main.include_omnibar_toolbar.toolbar +import kotlinx.android.synthetic.main.include_omnibar_toolbar.toolbarContainer +import kotlinx.android.synthetic.main.include_omnibar_toolbar.view.browserMenu +import kotlinx.android.synthetic.main.include_omnibar_toolbar.view.privacyGradeButton import kotlinx.android.synthetic.main.layout_bottom_navigation_bar.bottomBarBackItem import kotlinx.android.synthetic.main.layout_bottom_navigation_bar.bottomBarBookmarksItem import kotlinx.android.synthetic.main.layout_bottom_navigation_bar.bottomBarFireItem import kotlinx.android.synthetic.main.layout_bottom_navigation_bar.bottomBarForwardItem import kotlinx.android.synthetic.main.layout_bottom_navigation_bar.bottomBarTabsItem -import kotlinx.android.synthetic.main.popup_window_browser_menu.view.* -import kotlinx.coroutines.* +import kotlinx.android.synthetic.main.popup_window_browser_menu.view.addBookmarksPopupMenuItem +import kotlinx.android.synthetic.main.popup_window_browser_menu.view.addToHome +import kotlinx.android.synthetic.main.popup_window_browser_menu.view.backPopupMenuItem +import kotlinx.android.synthetic.main.popup_window_browser_menu.view.bookmarksPopupMenuItem +import kotlinx.android.synthetic.main.popup_window_browser_menu.view.brokenSitePopupMenuItem +import kotlinx.android.synthetic.main.popup_window_browser_menu.view.findInPageMenuItem +import kotlinx.android.synthetic.main.popup_window_browser_menu.view.forwardPopupMenuItem +import kotlinx.android.synthetic.main.popup_window_browser_menu.view.newTabPopupMenuItem +import kotlinx.android.synthetic.main.popup_window_browser_menu.view.refreshPopupMenuItem +import kotlinx.android.synthetic.main.popup_window_browser_menu.view.requestDesktopSiteCheckMenuItem +import kotlinx.android.synthetic.main.popup_window_browser_menu.view.settingsPopupMenuItem +import kotlinx.android.synthetic.main.popup_window_browser_menu.view.sharePageMenuItem +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.GlobalScope +import kotlinx.coroutines.Job +import kotlinx.coroutines.SupervisorJob +import kotlinx.coroutines.delay +import kotlinx.coroutines.launch +import kotlinx.coroutines.withContext import org.jetbrains.anko.longToast import org.jetbrains.anko.share import timber.log.Timber @@ -198,6 +278,8 @@ class BrowserTabFragment : Fragment(), FindListener, CoroutineScope { private lateinit var renderer: BrowserTabFragmentRenderer + private lateinit var decorator: BrowserTabFragmentExperimentDecorator + private val viewModel: BrowserTabViewModel by lazy { val viewModel = ViewModelProviders.of(this, viewModelFactory).get(BrowserTabViewModel::class.java) viewModel.loadData(tabId, initialUrl, skipHome) @@ -256,6 +338,7 @@ class BrowserTabFragment : Fragment(), FindListener, CoroutineScope { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) renderer = BrowserTabFragmentRenderer() + decorator = BrowserTabFragmentExperimentDecorator() } override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { @@ -264,18 +347,20 @@ class BrowserTabFragment : Fragment(), FindListener, CoroutineScope { override fun onActivityCreated(savedInstanceState: Bundle?) { super.onActivityCreated(savedInstanceState) - createPopupMenu() + configureObservers() - configureAppBar() - configureBottomBar() configureWebView() viewModel.registerWebViewListener(webViewClient, webChromeClient) configureOmnibarTextInput() configureFindInPage() configureAutoComplete() configureKeyboardAwareLogoAnimation() + + createPopupMenu() + configureAppBar() configureShowTabSwitcherListener() configureLongClickOpensNewTabListener() + decorateWithExperiments() if (savedInstanceState == null) { viewModel.onViewReady() @@ -722,6 +807,22 @@ class BrowserTabFragment : Fragment(), FindListener, CoroutineScope { autoCompleteSuggestionsList.adapter = autoCompleteSuggestionsAdapter } + + private fun decorateWithExperiments(){ + when{ + variantManager.getVariant().hasFeature(VariantManager.VariantFeature.ConceptTest) -> { + decorator.decorateWithToolbarOnlyExperiment() + } + variantManager.getVariant().hasFeature(VariantManager.VariantFeature.ConceptTest) -> { + decorator.decorateWithBottomBarNavigationOnlyExperiment() + } + else -> { + decorator.decorateWithBottomBarAndToolbarExperiment() + } + } + } + + private fun configureAppBar() { toolbar.privacyGradeButton.setOnClickListener { @@ -743,15 +844,6 @@ class BrowserTabFragment : Fragment(), FindListener, CoroutineScope { }) } - private fun configureBottomBar(){ - bottomNavigationBar.apply { - onItemClicked(bottomBarBackItem) { activity?.onBackPressed() } - onItemClicked(bottomBarForwardItem) { viewModel.onUserPressedForward() } - onItemClicked(bottomBarFireItem) { browserActivity?.launchFire() } - onItemClicked(bottomBarBookmarksItem) { launch { viewModel.onBookmarkAddRequested() } } - } - } - private fun configureFindInPage() { findInPageInput.setOnFocusChangeListener { _, hasFocus -> if (hasFocus && findInPageInput.text.toString() != viewModel.findInPageViewState.value?.searchTerm) { @@ -1183,6 +1275,49 @@ class BrowserTabFragment : Fragment(), FindListener, CoroutineScope { } } + inner class BrowserTabFragmentExperimentDecorator { + + fun decorateWithToolbarOnlyExperiment(){ + hideBottomBar() + } + + fun decorateWithBottomBarNavigationOnlyExperiment(){ + decorateAppBarWithToolbarOnlyExperiment() + decorateBottomBar() + } + + fun decorateWithBottomBarAndToolbarExperiment(){ + decorateAppBarWithToolbarOnlyExperiment() + decorateBottomBar() + } + + private fun decorateAppBarWithToolbarOnlyExperiment(){ + toolbar.inflateMenu(R.menu.menu_browser_activity) + toolbar.setOnMenuItemClickListener { menuItem -> + when (menuItem.itemId) { + R.id.fire -> { + browserActivity?.launchFire() + return@setOnMenuItemClickListener true + } + else -> return@setOnMenuItemClickListener false + } + } + } + + private fun decorateBottomBar(){ + bottomNavigationBar.apply { + onItemClicked(bottomBarBackItem) { activity?.onBackPressed() } + onItemClicked(bottomBarForwardItem) { viewModel.onUserPressedForward() } + onItemClicked(bottomBarFireItem) { browserActivity?.launchFire() } + onItemClicked(bottomBarBookmarksItem) { launch { viewModel.onBookmarkAddRequested() } } + } + } + + private fun hideBottomBar(){ + bottomNavigationBar.gone() + } + } + inner class BrowserTabFragmentRenderer { private var lastSeenOmnibarViewState: OmnibarViewState? = null From 6e5306739313731d4418556cffbc097709e77b40 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Gonz=C3=A1lez?= Date: Wed, 25 Mar 2020 14:50:50 +0100 Subject: [PATCH 011/104] implemented decorator variants as per current designs --- .../app/browser/BrowserTabFragment.kt | 106 +++++++++++------- 1 file changed, 68 insertions(+), 38 deletions(-) diff --git a/app/src/main/java/com/duckduckgo/app/browser/BrowserTabFragment.kt b/app/src/main/java/com/duckduckgo/app/browser/BrowserTabFragment.kt index c404aa308a7c..b3c29a263acb 100644 --- a/app/src/main/java/com/duckduckgo/app/browser/BrowserTabFragment.kt +++ b/app/src/main/java/com/duckduckgo/app/browser/BrowserTabFragment.kt @@ -296,6 +296,12 @@ class BrowserTabFragment : Fragment(), FindListener, CoroutineScope { private val browserActivity get() = activity as? BrowserActivity + private val tabsButton: MenuItem? + get() = toolbar.menu.findItem(R.id.tabs) + + private val fireMenuButton: MenuItem? + get() = toolbar.menu.findItem(R.id.fire) + private val menuButton: ViewGroup? get() = appBarLayout.browserMenu @@ -355,11 +361,8 @@ class BrowserTabFragment : Fragment(), FindListener, CoroutineScope { configureFindInPage() configureAutoComplete() configureKeyboardAwareLogoAnimation() - - createPopupMenu() configureAppBar() - configureShowTabSwitcherListener() - configureLongClickOpensNewTabListener() + decorateWithExperiments() if (savedInstanceState == null) { @@ -397,19 +400,6 @@ class BrowserTabFragment : Fragment(), FindListener, CoroutineScope { } } - private fun configureShowTabSwitcherListener() { - bottomBarTabsItem.setOnClickListener { - launch { viewModel.userLaunchingTabSwitcher() } - } - } - - private fun configureLongClickOpensNewTabListener() { - bottomBarTabsItem.setOnLongClickListener { - launch { viewModel.userRequestedOpeningNewTab() } - return@setOnLongClickListener true - } - } - private fun launchTabSwitcher() { val activity = activity ?: return startActivity(TabSwitcherActivity.intent(activity, tabId)) @@ -435,25 +425,6 @@ class BrowserTabFragment : Fragment(), FindListener, CoroutineScope { super.onPause() } - private fun createPopupMenu() { - popupMenu = BrowserPopupMenu(layoutInflater) - val view = popupMenu.contentView - popupMenu.apply { - onMenuItemClicked(view.forwardPopupMenuItem) { viewModel.onUserPressedForward() } - onMenuItemClicked(view.backPopupMenuItem) { activity?.onBackPressed() } - onMenuItemClicked(view.refreshPopupMenuItem) { viewModel.onRefreshRequested() } - onMenuItemClicked(view.newTabPopupMenuItem) { viewModel.userRequestedOpeningNewTab() } - onMenuItemClicked(view.bookmarksPopupMenuItem) { browserActivity?.launchBookmarks() } - onMenuItemClicked(view.addBookmarksPopupMenuItem) { launch { viewModel.onBookmarkAddRequested() } } - onMenuItemClicked(view.findInPageMenuItem) { viewModel.onFindInPageSelected() } - onMenuItemClicked(view.brokenSitePopupMenuItem) { viewModel.onBrokenSiteSelected() } - onMenuItemClicked(view.settingsPopupMenuItem) { browserActivity?.launchSettings() } - onMenuItemClicked(view.requestDesktopSiteCheckMenuItem) { viewModel.onDesktopSiteModeToggled(view.requestDesktopSiteCheckMenuItem.isChecked) } - onMenuItemClicked(view.sharePageMenuItem) { viewModel.onShareSelected() } - onMenuItemClicked(view.addToHome) { viewModel.onPinPageToHomeSelected() } - } - } - private fun addHomeShortcut(homeShortcut: Command.AddHomeShortcut, context: Context) { val shortcutInfo = shortcutBuilder.buildPinnedPageShortcut(context, homeShortcut) ShortcutManagerCompat.requestPinShortcut(context, shortcutInfo, null) @@ -809,6 +780,8 @@ class BrowserTabFragment : Fragment(), FindListener, CoroutineScope { private fun decorateWithExperiments(){ + decorator.decorateWithToolbarOnlyExperiment() + return when{ variantManager.getVariant().hasFeature(VariantManager.VariantFeature.ConceptTest) -> { decorator.decorateWithToolbarOnlyExperiment() @@ -1279,16 +1252,26 @@ class BrowserTabFragment : Fragment(), FindListener, CoroutineScope { fun decorateWithToolbarOnlyExperiment(){ hideBottomBar() + decorateAppBarWithToolbarOnlyExperiment() + createPopupMenuWithToolbarOnlyExperiment() + configureShowTabSwitcherListenerWithToolbarOnlyExperiment() + configureLongClickOpensNewTabListenerWithToolbarOnlyExperiment() } fun decorateWithBottomBarNavigationOnlyExperiment(){ - decorateAppBarWithToolbarOnlyExperiment() decorateBottomBar() + decorateAppBarWithToolbarOnlyExperiment() + createPopupMenuWithToolbarOnlyExperiment() + configureShowTabSwitcherListenerWithBottomBarNavigationOnlyExperiment() + configureLongClickOpensNewTabListenerWithBottomBarNavigationOnlyExperiment() } fun decorateWithBottomBarAndToolbarExperiment(){ - decorateAppBarWithToolbarOnlyExperiment() decorateBottomBar() + decorateAppBarWithToolbarOnlyExperiment() + createPopupMenuWithToolbarOnlyExperiment() + configureShowTabSwitcherListenerWithBottomBarNavigationOnlyExperiment() + configureLongClickOpensNewTabListenerWithBottomBarNavigationOnlyExperiment() } private fun decorateAppBarWithToolbarOnlyExperiment(){ @@ -1304,6 +1287,25 @@ class BrowserTabFragment : Fragment(), FindListener, CoroutineScope { } } + private fun createPopupMenuWithToolbarOnlyExperiment() { + popupMenu = BrowserPopupMenu(layoutInflater) + val view = popupMenu.contentView + popupMenu.apply { + onMenuItemClicked(view.forwardPopupMenuItem) { viewModel.onUserPressedForward() } + onMenuItemClicked(view.backPopupMenuItem) { activity?.onBackPressed() } + onMenuItemClicked(view.refreshPopupMenuItem) { viewModel.onRefreshRequested() } + onMenuItemClicked(view.newTabPopupMenuItem) { viewModel.userRequestedOpeningNewTab() } + onMenuItemClicked(view.bookmarksPopupMenuItem) { browserActivity?.launchBookmarks() } + onMenuItemClicked(view.addBookmarksPopupMenuItem) { launch { viewModel.onBookmarkAddRequested() } } + onMenuItemClicked(view.findInPageMenuItem) { viewModel.onFindInPageSelected() } + onMenuItemClicked(view.brokenSitePopupMenuItem) { viewModel.onBrokenSiteSelected() } + onMenuItemClicked(view.settingsPopupMenuItem) { browserActivity?.launchSettings() } + onMenuItemClicked(view.requestDesktopSiteCheckMenuItem) { viewModel.onDesktopSiteModeToggled(view.requestDesktopSiteCheckMenuItem.isChecked) } + onMenuItemClicked(view.sharePageMenuItem) { viewModel.onShareSelected() } + onMenuItemClicked(view.addToHome) { viewModel.onPinPageToHomeSelected() } + } + } + private fun decorateBottomBar(){ bottomNavigationBar.apply { onItemClicked(bottomBarBackItem) { activity?.onBackPressed() } @@ -1316,8 +1318,36 @@ class BrowserTabFragment : Fragment(), FindListener, CoroutineScope { private fun hideBottomBar(){ bottomNavigationBar.gone() } + + private fun configureShowTabSwitcherListenerWithToolbarOnlyExperiment() { + tabsButton?.actionView?.setOnClickListener { + launch { viewModel.userLaunchingTabSwitcher() } + } + } + + private fun configureShowTabSwitcherListenerWithBottomBarNavigationOnlyExperiment() { + bottomBarTabsItem.setOnClickListener { + launch { viewModel.userLaunchingTabSwitcher() } + } + } + + private fun configureLongClickOpensNewTabListenerWithToolbarOnlyExperiment() { + tabsButton?.actionView?.setOnLongClickListener { + launch { viewModel.userRequestedOpeningNewTab() } + return@setOnLongClickListener true + } + } + + private fun configureLongClickOpensNewTabListenerWithBottomBarNavigationOnlyExperiment() { + bottomBarTabsItem.setOnLongClickListener { + launch { viewModel.userRequestedOpeningNewTab() } + return@setOnLongClickListener true + } + } } + + inner class BrowserTabFragmentRenderer { private var lastSeenOmnibarViewState: OmnibarViewState? = null From b77e47dee38697b86a00130de413bcdf3c4e9be0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Gonz=C3=A1lez?= Date: Wed, 25 Mar 2020 14:57:32 +0100 Subject: [PATCH 012/104] PopupMenu also knows about the experiment we are running --- .../app/browser/BrowserPopupMenu.kt | 25 ++++++++++++++++--- .../app/browser/BrowserTabFragment.kt | 2 +- 2 files changed, 22 insertions(+), 5 deletions(-) diff --git a/app/src/main/java/com/duckduckgo/app/browser/BrowserPopupMenu.kt b/app/src/main/java/com/duckduckgo/app/browser/BrowserPopupMenu.kt index a12f4f0ebf05..f90b741c6cb7 100644 --- a/app/src/main/java/com/duckduckgo/app/browser/BrowserPopupMenu.kt +++ b/app/src/main/java/com/duckduckgo/app/browser/BrowserPopupMenu.kt @@ -24,11 +24,13 @@ import android.view.LayoutInflater import android.view.View import android.view.ViewGroup.LayoutParams.WRAP_CONTENT import android.widget.PopupWindow +import com.duckduckgo.app.statistics.Variant +import com.duckduckgo.app.statistics.VariantManager class BrowserPopupMenu : PopupWindow { - constructor(layoutInflater: LayoutInflater, view: View = BrowserPopupMenu.inflate(layoutInflater)) - : super(view, WRAP_CONTENT, WRAP_CONTENT, true) { + constructor(layoutInflater: LayoutInflater, variant: Variant, view: View = inflate(layoutInflater, variant)) + : super(view, WRAP_CONTENT, WRAP_CONTENT, true) { if (SDK_INT <= 22) { // popupwindow gets stuck on the screen on API 22 (tested on 23) without a background @@ -59,10 +61,25 @@ class BrowserPopupMenu : PopupWindow { private const val margin = 30 - fun inflate(layoutInflater: LayoutInflater): View { - return layoutInflater.inflate(R.layout.popup_window_browser_menu, null) + fun inflate(layoutInflater: LayoutInflater, variant: Variant): View { + return inflateToolbarOnlyExperiment(layoutInflater) + + when { + variant.hasFeature(VariantManager.VariantFeature.ConceptTest) -> { + inflateToolbarOnlyExperiment(layoutInflater) + } + variant.hasFeature(VariantManager.VariantFeature.ConceptTest) -> { + inflateToolbarOnlyExperiment(layoutInflater) + } + else -> { + inflateToolbarOnlyExperiment(layoutInflater) + } + } } + private fun inflateToolbarOnlyExperiment(layoutInflater: LayoutInflater): View { + return layoutInflater.inflate(R.layout.popup_window_browser_menu, null) + } } } diff --git a/app/src/main/java/com/duckduckgo/app/browser/BrowserTabFragment.kt b/app/src/main/java/com/duckduckgo/app/browser/BrowserTabFragment.kt index b3c29a263acb..41b37ae4f1d4 100644 --- a/app/src/main/java/com/duckduckgo/app/browser/BrowserTabFragment.kt +++ b/app/src/main/java/com/duckduckgo/app/browser/BrowserTabFragment.kt @@ -1288,7 +1288,7 @@ class BrowserTabFragment : Fragment(), FindListener, CoroutineScope { } private fun createPopupMenuWithToolbarOnlyExperiment() { - popupMenu = BrowserPopupMenu(layoutInflater) + popupMenu = BrowserPopupMenu(layoutInflater, variantManager.getVariant()) val view = popupMenu.contentView popupMenu.apply { onMenuItemClicked(view.forwardPopupMenuItem) { viewModel.onUserPressedForward() } From 0416259ece579643e137e59989a3d66b6abc9f14 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Gonz=C3=A1lez?= Date: Thu, 26 Mar 2020 14:40:50 +0100 Subject: [PATCH 013/104] added swipe to refresh --- app/build.gradle | 2 + .../app/browser/BrowserTabFragment.kt | 47 +++-- .../ui/HideBottomViewOnScrollBehavior.java | 172 ------------------ .../ui/ScrollAwareSwipeRefreshLayout.kt | 41 +++++ .../main/res/layout/fragment_browser_tab.xml | 22 ++- 5 files changed, 92 insertions(+), 192 deletions(-) delete mode 100644 app/src/main/java/com/duckduckgo/app/browser/ui/HideBottomViewOnScrollBehavior.java create mode 100644 app/src/main/java/com/duckduckgo/app/browser/ui/ScrollAwareSwipeRefreshLayout.kt diff --git a/app/build.gradle b/app/build.gradle index 8b7ab7ec27df..8eade9154d6b 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -99,6 +99,7 @@ ext { materialDesign = "1.1.0-alpha05" architectureComponents = "1.1.1" architectureComponentsExtensions = "1.1.1" + swipeRefresh = "1.0.0" androidKtx = "1.0.2" fragmentKtx = "1.0.0" constraintLayout = "2.0.0-beta1" @@ -150,6 +151,7 @@ dependencies { implementation "androidx.appcompat:appcompat:$androidX" implementation "com.google.android.material:material:$materialDesign" implementation "androidx.constraintlayout:constraintlayout:$constraintLayout" + implementation "androidx.swiperefreshlayout:swiperefreshlayout:$swipeRefresh" implementation "androidx.webkit:webkit:$webkit" implementation "com.squareup.okhttp3:okhttp:$okHttp" implementation "com.squareup.retrofit2:retrofit:$retrofit" diff --git a/app/src/main/java/com/duckduckgo/app/browser/BrowserTabFragment.kt b/app/src/main/java/com/duckduckgo/app/browser/BrowserTabFragment.kt index 41b37ae4f1d4..9556426f03e7 100644 --- a/app/src/main/java/com/duckduckgo/app/browser/BrowserTabFragment.kt +++ b/app/src/main/java/com/duckduckgo/app/browser/BrowserTabFragment.kt @@ -96,6 +96,7 @@ import com.duckduckgo.app.browser.shortcut.ShortcutBuilder import com.duckduckgo.app.browser.tabpreview.WebViewPreviewGenerator import com.duckduckgo.app.browser.tabpreview.WebViewPreviewPersister import com.duckduckgo.app.browser.ui.HttpAuthenticationDialogFragment +import com.duckduckgo.app.browser.ui.ScrollAwareSwipeRefreshLayout import com.duckduckgo.app.browser.useragent.UserAgentProvider import com.duckduckgo.app.cta.ui.Cta import com.duckduckgo.app.cta.ui.CtaViewModel @@ -136,6 +137,7 @@ import kotlinx.android.synthetic.main.fragment_browser_tab.browserLayout import kotlinx.android.synthetic.main.fragment_browser_tab.defaultCard import kotlinx.android.synthetic.main.fragment_browser_tab.focusDummy import kotlinx.android.synthetic.main.fragment_browser_tab.rootView +import kotlinx.android.synthetic.main.fragment_browser_tab.swipeContainer import kotlinx.android.synthetic.main.fragment_browser_tab.webViewContainer import kotlinx.android.synthetic.main.fragment_browser_tab.webViewFullScreenContainer import kotlinx.android.synthetic.main.include_cta_buttons.view.ctaDismissButton @@ -362,6 +364,7 @@ class BrowserTabFragment : Fragment(), FindListener, CoroutineScope { configureAutoComplete() configureKeyboardAwareLogoAnimation() configureAppBar() + configureSwipeToRefresh() decorateWithExperiments() @@ -512,6 +515,7 @@ class BrowserTabFragment : Fragment(), FindListener, CoroutineScope { } fun onRefreshRequested() { + swipeContainer.isRefreshing = true viewModel.onRefreshRequested() } @@ -778,11 +782,10 @@ class BrowserTabFragment : Fragment(), FindListener, CoroutineScope { autoCompleteSuggestionsList.adapter = autoCompleteSuggestionsAdapter } - - private fun decorateWithExperiments(){ + private fun decorateWithExperiments() { decorator.decorateWithToolbarOnlyExperiment() return - when{ + when { variantManager.getVariant().hasFeature(VariantManager.VariantFeature.ConceptTest) -> { decorator.decorateWithToolbarOnlyExperiment() } @@ -795,7 +798,6 @@ class BrowserTabFragment : Fragment(), FindListener, CoroutineScope { } } - private fun configureAppBar() { toolbar.privacyGradeButton.setOnClickListener { @@ -817,6 +819,19 @@ class BrowserTabFragment : Fragment(), FindListener, CoroutineScope { }) } + private fun configureSwipeToRefresh() { + swipeContainer.setCanWebViewScrollUpCallback(object : ScrollAwareSwipeRefreshLayout.CanWebViewScrollUpCallback { + override fun canSwipeRefreshChildScrollUp(): Boolean { + return webView?.canScrollVertically(-1) ?: false + } + }) + + swipeContainer.setColorSchemeColors(ContextCompat.getColor(context!!, R.color.cornflowerBlue)) + swipeContainer.setOnRefreshListener { + viewModel.onRefreshRequested() + } + } + private fun configureFindInPage() { findInPageInput.setOnFocusChangeListener { _, hasFocus -> if (hasFocus && findInPageInput.text.toString() != viewModel.findInPageViewState.value?.searchTerm) { @@ -1250,7 +1265,7 @@ class BrowserTabFragment : Fragment(), FindListener, CoroutineScope { inner class BrowserTabFragmentExperimentDecorator { - fun decorateWithToolbarOnlyExperiment(){ + fun decorateWithToolbarOnlyExperiment() { hideBottomBar() decorateAppBarWithToolbarOnlyExperiment() createPopupMenuWithToolbarOnlyExperiment() @@ -1258,7 +1273,7 @@ class BrowserTabFragment : Fragment(), FindListener, CoroutineScope { configureLongClickOpensNewTabListenerWithToolbarOnlyExperiment() } - fun decorateWithBottomBarNavigationOnlyExperiment(){ + fun decorateWithBottomBarNavigationOnlyExperiment() { decorateBottomBar() decorateAppBarWithToolbarOnlyExperiment() createPopupMenuWithToolbarOnlyExperiment() @@ -1266,7 +1281,7 @@ class BrowserTabFragment : Fragment(), FindListener, CoroutineScope { configureLongClickOpensNewTabListenerWithBottomBarNavigationOnlyExperiment() } - fun decorateWithBottomBarAndToolbarExperiment(){ + fun decorateWithBottomBarAndToolbarExperiment() { decorateBottomBar() decorateAppBarWithToolbarOnlyExperiment() createPopupMenuWithToolbarOnlyExperiment() @@ -1274,7 +1289,7 @@ class BrowserTabFragment : Fragment(), FindListener, CoroutineScope { configureLongClickOpensNewTabListenerWithBottomBarNavigationOnlyExperiment() } - private fun decorateAppBarWithToolbarOnlyExperiment(){ + private fun decorateAppBarWithToolbarOnlyExperiment() { toolbar.inflateMenu(R.menu.menu_browser_activity) toolbar.setOnMenuItemClickListener { menuItem -> when (menuItem.itemId) { @@ -1306,16 +1321,16 @@ class BrowserTabFragment : Fragment(), FindListener, CoroutineScope { } } - private fun decorateBottomBar(){ + private fun decorateBottomBar() { bottomNavigationBar.apply { onItemClicked(bottomBarBackItem) { activity?.onBackPressed() } onItemClicked(bottomBarForwardItem) { viewModel.onUserPressedForward() } - onItemClicked(bottomBarFireItem) { browserActivity?.launchFire() } - onItemClicked(bottomBarBookmarksItem) { launch { viewModel.onBookmarkAddRequested() } } + onItemClicked(bottomBarFireItem) { browserActivity?.launchFire() } + onItemClicked(bottomBarBookmarksItem) { launch { viewModel.onBookmarkAddRequested() } } } } - private fun hideBottomBar(){ + private fun hideBottomBar() { bottomNavigationBar.gone() } @@ -1346,8 +1361,6 @@ class BrowserTabFragment : Fragment(), FindListener, CoroutineScope { } } - - inner class BrowserTabFragmentRenderer { private var lastSeenOmnibarViewState: OmnibarViewState? = null @@ -1412,6 +1425,10 @@ class BrowserTabFragment : Fragment(), FindListener, CoroutineScope { createTrackersAnimation() } } + + if (!viewState.isLoading) { + swipeContainer.isRefreshing = false + } } } @@ -1504,7 +1521,7 @@ class BrowserTabFragment : Fragment(), FindListener, CoroutineScope { } } - private fun renderBottomBar(viewState: BrowserViewState){ + private fun renderBottomBar(viewState: BrowserViewState) { bottomBarForwardItem.isEnabled = viewState.canGoForward bottomBarBackItem.isEnabled = viewState.canGoBack } diff --git a/app/src/main/java/com/duckduckgo/app/browser/ui/HideBottomViewOnScrollBehavior.java b/app/src/main/java/com/duckduckgo/app/browser/ui/HideBottomViewOnScrollBehavior.java deleted file mode 100644 index acb62eba43da..000000000000 --- a/app/src/main/java/com/duckduckgo/app/browser/ui/HideBottomViewOnScrollBehavior.java +++ /dev/null @@ -1,172 +0,0 @@ -/* - * Copyright (c) 2020 DuckDuckGo - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.duckduckgo.app.browser.ui; - -import android.animation.Animator; -import android.animation.AnimatorListenerAdapter; -import android.animation.TimeInterpolator; -import android.content.Context; -import android.util.AttributeSet; -import android.view.View; -import android.view.ViewGroup; -import android.view.ViewPropertyAnimator; - -import androidx.annotation.Dimension; -import androidx.annotation.NonNull; -import androidx.annotation.Nullable; -import androidx.coordinatorlayout.widget.CoordinatorLayout; -import androidx.coordinatorlayout.widget.CoordinatorLayout.Behavior; -import androidx.core.view.ViewCompat; - -import com.google.android.material.animation.AnimationUtils; - -/** - * The {@link Behavior} for a View within a {@link CoordinatorLayout} to hide the view off the - * bottom of the screen when scrolling down, and show it when scrolling up. - */ -public class HideBottomViewOnScrollBehavior extends CoordinatorLayout.Behavior { - - protected static final int ENTER_ANIMATION_DURATION = 225; - protected static final int EXIT_ANIMATION_DURATION = 175; - - private static final int STATE_SCROLLED_DOWN = 1; - private static final int STATE_SCROLLED_UP = 2; - - private int height = 0; - private int currentState = STATE_SCROLLED_UP; - private int additionalHiddenOffsetY = 0; - @Nullable - private ViewPropertyAnimator currentAnimator; - - public HideBottomViewOnScrollBehavior() { - } - - public HideBottomViewOnScrollBehavior(Context context, AttributeSet attrs) { - super(context, attrs); - } - - @Override - public boolean onLayoutChild(@NonNull CoordinatorLayout parent, @NonNull V child, int layoutDirection) { - ViewGroup.MarginLayoutParams paramsCompat = (ViewGroup.MarginLayoutParams) child.getLayoutParams(); - height = child.getMeasuredHeight() + paramsCompat.bottomMargin; - return super.onLayoutChild(parent, child, layoutDirection); - } - - /** - * Sets an additional offset for the y position used to hide the view. - * - * @param child the child view that is hidden by this behavior - * @param offset the additional offset in pixels that should be added when the view slides away - */ - public void setAdditionalHiddenOffsetY(@NonNull V child, @Dimension int offset) { - additionalHiddenOffsetY = offset; - - if (currentState == STATE_SCROLLED_DOWN) { - child.setTranslationY(height + additionalHiddenOffsetY); - } - } - - @Override - public boolean onStartNestedScroll( - @NonNull CoordinatorLayout coordinatorLayout, - @NonNull V child, - @NonNull View directTargetChild, - @NonNull View target, - int nestedScrollAxes, - int type) { - return nestedScrollAxes == ViewCompat.SCROLL_AXIS_VERTICAL; - } - - @Override - public void onNestedScroll( - CoordinatorLayout coordinatorLayout, - @NonNull V child, - @NonNull View target, - int dxConsumed, - int dyConsumed, - int dxUnconsumed, - int dyUnconsumed, - int type, - @NonNull int[] consumed) { - if (dyConsumed > 0) { - slideUp(child); - } else if (dyConsumed < 0) { - slideDown(child); - } - } - - @Override - public boolean layoutDependsOn(@NonNull CoordinatorLayout parent, @NonNull V child, @NonNull View dependency) { - return super.layoutDependsOn(parent, child, dependency); - } - - /** - * Perform an animation that will slide the child from it's current position to be totally on the - * screen. - */ - public void slideUp(@NonNull V child) { - if (currentState == STATE_SCROLLED_UP) { - return; - } - - if (currentAnimator != null) { - currentAnimator.cancel(); - child.clearAnimation(); - } - currentState = STATE_SCROLLED_UP; - animateChildTo( - child, 0, ENTER_ANIMATION_DURATION, AnimationUtils.LINEAR_OUT_SLOW_IN_INTERPOLATOR); - } - - /** - * Perform an animation that will slide the child from it's current position to be totally off the - * screen. - */ - public void slideDown(@NonNull V child) { - if (currentState == STATE_SCROLLED_DOWN) { - return; - } - - if (currentAnimator != null) { - currentAnimator.cancel(); - child.clearAnimation(); - } - currentState = STATE_SCROLLED_DOWN; - animateChildTo( - child, - height + additionalHiddenOffsetY, - EXIT_ANIMATION_DURATION, - AnimationUtils.FAST_OUT_LINEAR_IN_INTERPOLATOR); - } - - private void animateChildTo( - @NonNull V child, int targetY, long duration, TimeInterpolator interpolator) { - currentAnimator = - child - .animate() - .translationY(targetY) - .setInterpolator(interpolator) - .setDuration(duration) - .setListener( - new AnimatorListenerAdapter() { - @Override - public void onAnimationEnd(Animator animation) { - currentAnimator = null; - } - }); - } -} \ No newline at end of file diff --git a/app/src/main/java/com/duckduckgo/app/browser/ui/ScrollAwareSwipeRefreshLayout.kt b/app/src/main/java/com/duckduckgo/app/browser/ui/ScrollAwareSwipeRefreshLayout.kt new file mode 100644 index 000000000000..fbcf8cc3a22d --- /dev/null +++ b/app/src/main/java/com/duckduckgo/app/browser/ui/ScrollAwareSwipeRefreshLayout.kt @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2020 DuckDuckGo + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.duckduckgo.app.browser.ui + +import android.content.Context +import android.util.AttributeSet +import androidx.swiperefreshlayout.widget.SwipeRefreshLayout + +class ScrollAwareSwipeRefreshLayout @JvmOverloads constructor( + context: Context, + attrs: AttributeSet? = null +) : SwipeRefreshLayout(context, attrs) { + private var canWebViewScrollUpCallback: CanWebViewScrollUpCallback? = null + + interface CanWebViewScrollUpCallback { + fun canSwipeRefreshChildScrollUp(): Boolean + } + + fun setCanWebViewScrollUpCallback(canWebViewScrollUpCallback: CanWebViewScrollUpCallback) { + this.canWebViewScrollUpCallback = canWebViewScrollUpCallback + } + + override fun canChildScrollUp(): Boolean { + return if (canWebViewScrollUpCallback != null) { + canWebViewScrollUpCallback!!.canSwipeRefreshChildScrollUp() + } else super.canChildScrollUp() + } +} \ No newline at end of file diff --git a/app/src/main/res/layout/fragment_browser_tab.xml b/app/src/main/res/layout/fragment_browser_tab.xml index 55dd5c3e00a0..bc9b30855c3f 100644 --- a/app/src/main/res/layout/fragment_browser_tab.xml +++ b/app/src/main/res/layout/fragment_browser_tab.xml @@ -82,16 +82,28 @@ app:layout_behavior="@string/appbar_scrolling_view_behavior" tools:context="com.duckduckgo.app.browser.BrowserActivity"> - + app:layout_constraintTop_toTopOf="parent"> + + + + Date: Fri, 27 Mar 2020 14:06:14 +0100 Subject: [PATCH 014/104] using bottom bar for now --- .../main/java/com/duckduckgo/app/browser/BrowserTabFragment.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/main/java/com/duckduckgo/app/browser/BrowserTabFragment.kt b/app/src/main/java/com/duckduckgo/app/browser/BrowserTabFragment.kt index 9556426f03e7..1b22394987f0 100644 --- a/app/src/main/java/com/duckduckgo/app/browser/BrowserTabFragment.kt +++ b/app/src/main/java/com/duckduckgo/app/browser/BrowserTabFragment.kt @@ -783,7 +783,7 @@ class BrowserTabFragment : Fragment(), FindListener, CoroutineScope { } private fun decorateWithExperiments() { - decorator.decorateWithToolbarOnlyExperiment() + decorator.decorateWithBottomBarAndToolbarExperiment() return when { variantManager.getVariant().hasFeature(VariantManager.VariantFeature.ConceptTest) -> { From c2de8ab4a87ae75fd7bf1fa21cf1d9fa3bf5c737 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Gonz=C3=A1lez?= Date: Mon, 30 Mar 2020 14:24:16 +0200 Subject: [PATCH 015/104] cleaning up the code --- .../app/browser/ui/ScrollAwareSwipeRefreshLayout.kt | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/app/src/main/java/com/duckduckgo/app/browser/ui/ScrollAwareSwipeRefreshLayout.kt b/app/src/main/java/com/duckduckgo/app/browser/ui/ScrollAwareSwipeRefreshLayout.kt index fbcf8cc3a22d..e11b9bb1e20b 100644 --- a/app/src/main/java/com/duckduckgo/app/browser/ui/ScrollAwareSwipeRefreshLayout.kt +++ b/app/src/main/java/com/duckduckgo/app/browser/ui/ScrollAwareSwipeRefreshLayout.kt @@ -34,8 +34,6 @@ class ScrollAwareSwipeRefreshLayout @JvmOverloads constructor( } override fun canChildScrollUp(): Boolean { - return if (canWebViewScrollUpCallback != null) { - canWebViewScrollUpCallback!!.canSwipeRefreshChildScrollUp() - } else super.canChildScrollUp() + return canWebViewScrollUpCallback?.canSwipeRefreshChildScrollUp() ?: super.canChildScrollUp() } } \ No newline at end of file From dd2224ba35b55024288eaafd460a86ce0dc8ea33 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Gonz=C3=A1lez?= Date: Mon, 30 Mar 2020 14:42:55 +0200 Subject: [PATCH 016/104] cleaning up --- .../app/browser/BrowserTabFragment.kt | 10 +-- .../app/browser/ui/BottomNavigationBar.kt | 5 +- ..._bottom_navigation_bar_experiment_one.xml} | 0 .../layout_bottom_navigation_bar_view.xml | 69 ------------------- 4 files changed, 7 insertions(+), 77 deletions(-) rename app/src/main/res/layout/{layout_bottom_navigation_bar.xml => layout_bottom_navigation_bar_experiment_one.xml} (100%) delete mode 100644 app/src/main/res/layout/layout_bottom_navigation_bar_view.xml diff --git a/app/src/main/java/com/duckduckgo/app/browser/BrowserTabFragment.kt b/app/src/main/java/com/duckduckgo/app/browser/BrowserTabFragment.kt index 1b22394987f0..0650f7fbc947 100644 --- a/app/src/main/java/com/duckduckgo/app/browser/BrowserTabFragment.kt +++ b/app/src/main/java/com/duckduckgo/app/browser/BrowserTabFragment.kt @@ -165,11 +165,11 @@ import kotlinx.android.synthetic.main.include_omnibar_toolbar.toolbar import kotlinx.android.synthetic.main.include_omnibar_toolbar.toolbarContainer import kotlinx.android.synthetic.main.include_omnibar_toolbar.view.browserMenu import kotlinx.android.synthetic.main.include_omnibar_toolbar.view.privacyGradeButton -import kotlinx.android.synthetic.main.layout_bottom_navigation_bar.bottomBarBackItem -import kotlinx.android.synthetic.main.layout_bottom_navigation_bar.bottomBarBookmarksItem -import kotlinx.android.synthetic.main.layout_bottom_navigation_bar.bottomBarFireItem -import kotlinx.android.synthetic.main.layout_bottom_navigation_bar.bottomBarForwardItem -import kotlinx.android.synthetic.main.layout_bottom_navigation_bar.bottomBarTabsItem +import kotlinx.android.synthetic.main.layout_bottom_navigation_bar_experiment_one.bottomBarBackItem +import kotlinx.android.synthetic.main.layout_bottom_navigation_bar_experiment_one.bottomBarBookmarksItem +import kotlinx.android.synthetic.main.layout_bottom_navigation_bar_experiment_one.bottomBarFireItem +import kotlinx.android.synthetic.main.layout_bottom_navigation_bar_experiment_one.bottomBarForwardItem +import kotlinx.android.synthetic.main.layout_bottom_navigation_bar_experiment_one.bottomBarTabsItem import kotlinx.android.synthetic.main.popup_window_browser_menu.view.addBookmarksPopupMenuItem import kotlinx.android.synthetic.main.popup_window_browser_menu.view.addToHome import kotlinx.android.synthetic.main.popup_window_browser_menu.view.backPopupMenuItem diff --git a/app/src/main/java/com/duckduckgo/app/browser/ui/BottomNavigationBar.kt b/app/src/main/java/com/duckduckgo/app/browser/ui/BottomNavigationBar.kt index 7aad74dfb4f4..56da7c5d3b5e 100644 --- a/app/src/main/java/com/duckduckgo/app/browser/ui/BottomNavigationBar.kt +++ b/app/src/main/java/com/duckduckgo/app/browser/ui/BottomNavigationBar.kt @@ -18,11 +18,9 @@ package com.duckduckgo.app.browser.ui import android.content.Context import android.util.AttributeSet -import android.view.LayoutInflater import android.view.View import android.widget.LinearLayout import com.duckduckgo.app.browser.R -import com.google.android.material.bottomnavigation.BottomNavigationView class BottomNavigationBar @JvmOverloads constructor( context: Context, @@ -32,7 +30,8 @@ class BottomNavigationBar @JvmOverloads constructor( override fun onFinishInflate() { super.onFinishInflate() - View.inflate(context, R.layout.layout_bottom_navigation_bar, this) + + View.inflate(context, R.layout.layout_bottom_navigation_bar_experiment_one, this) } fun onItemClicked(view: View, onClick: () -> Unit) { diff --git a/app/src/main/res/layout/layout_bottom_navigation_bar.xml b/app/src/main/res/layout/layout_bottom_navigation_bar_experiment_one.xml similarity index 100% rename from app/src/main/res/layout/layout_bottom_navigation_bar.xml rename to app/src/main/res/layout/layout_bottom_navigation_bar_experiment_one.xml diff --git a/app/src/main/res/layout/layout_bottom_navigation_bar_view.xml b/app/src/main/res/layout/layout_bottom_navigation_bar_view.xml deleted file mode 100644 index 9d734c630254..000000000000 --- a/app/src/main/res/layout/layout_bottom_navigation_bar_view.xml +++ /dev/null @@ -1,69 +0,0 @@ - - - - - - - - - - - - - \ No newline at end of file From 107959bb617523b08ead52e05aa2aa0d2d34f6f3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Gonz=C3=A1lez?= Date: Mon, 30 Mar 2020 16:57:07 +0200 Subject: [PATCH 017/104] binding all buttons in bottom bar --- .../app/browser/BrowserTabFragment.kt | 39 ++++++----- .../app/browser/ui/BottomNavigationBar.kt | 10 ++- ...e.xml => layout_bottom_navigation_bar.xml} | 32 ++++++++- ...t_bottom_navigation_bar_experiment_two.xml | 67 ------------------- 4 files changed, 62 insertions(+), 86 deletions(-) rename app/src/main/res/layout/{layout_bottom_navigation_bar_experiment_one.xml => layout_bottom_navigation_bar.xml} (67%) delete mode 100644 app/src/main/res/layout/layout_bottom_navigation_bar_experiment_two.xml diff --git a/app/src/main/java/com/duckduckgo/app/browser/BrowserTabFragment.kt b/app/src/main/java/com/duckduckgo/app/browser/BrowserTabFragment.kt index 05cb2c94ec1a..9bd157e97ce4 100644 --- a/app/src/main/java/com/duckduckgo/app/browser/BrowserTabFragment.kt +++ b/app/src/main/java/com/duckduckgo/app/browser/BrowserTabFragment.kt @@ -132,16 +132,8 @@ import com.duckduckgo.app.widget.ui.AddWidgetInstructionsActivity import com.duckduckgo.widget.SearchWidgetLight import com.google.android.material.snackbar.Snackbar import dagger.android.support.AndroidSupportInjection -import kotlinx.android.synthetic.main.fragment_browser_tab.* -import kotlinx.android.synthetic.main.include_cta_buttons.view.* -import kotlinx.android.synthetic.main.include_dax_dialog_cta.* -import kotlinx.android.synthetic.main.include_find_in_page.* import kotlinx.android.synthetic.main.include_new_browser_tab.* -import kotlinx.android.synthetic.main.include_omnibar_toolbar.* -import kotlinx.android.synthetic.main.include_omnibar_toolbar.view.* import kotlinx.android.synthetic.main.include_top_cta.view.* -import kotlinx.android.synthetic.main.popup_window_browser_menu.view.* -import kotlinx.coroutines.* import kotlinx.android.synthetic.main.fragment_browser_tab.autoCompleteSuggestionsList import kotlinx.android.synthetic.main.fragment_browser_tab.bottomNavigationBar import kotlinx.android.synthetic.main.fragment_browser_tab.browserLayout @@ -176,11 +168,13 @@ import kotlinx.android.synthetic.main.include_omnibar_toolbar.toolbar import kotlinx.android.synthetic.main.include_omnibar_toolbar.toolbarContainer import kotlinx.android.synthetic.main.include_omnibar_toolbar.view.browserMenu import kotlinx.android.synthetic.main.include_omnibar_toolbar.view.privacyGradeButton -import kotlinx.android.synthetic.main.layout_bottom_navigation_bar_experiment_one.bottomBarBackItem -import kotlinx.android.synthetic.main.layout_bottom_navigation_bar_experiment_one.bottomBarBookmarksItem -import kotlinx.android.synthetic.main.layout_bottom_navigation_bar_experiment_one.bottomBarFireItem -import kotlinx.android.synthetic.main.layout_bottom_navigation_bar_experiment_one.bottomBarForwardItem -import kotlinx.android.synthetic.main.layout_bottom_navigation_bar_experiment_one.bottomBarTabsItem +import kotlinx.android.synthetic.main.layout_bottom_navigation_bar.bottomBarBackItem +import kotlinx.android.synthetic.main.layout_bottom_navigation_bar.bottomBarBookmarksItem +import kotlinx.android.synthetic.main.layout_bottom_navigation_bar.bottomBarBookmarksItemOne +import kotlinx.android.synthetic.main.layout_bottom_navigation_bar.bottomBarBookmarksItemTwo +import kotlinx.android.synthetic.main.layout_bottom_navigation_bar.bottomBarFireItem +import kotlinx.android.synthetic.main.layout_bottom_navigation_bar.bottomBarForwardItem +import kotlinx.android.synthetic.main.layout_bottom_navigation_bar.bottomBarTabsItem import kotlinx.android.synthetic.main.popup_window_browser_menu.view.addBookmarksPopupMenuItem import kotlinx.android.synthetic.main.popup_window_browser_menu.view.addToHome import kotlinx.android.synthetic.main.popup_window_browser_menu.view.backPopupMenuItem @@ -1285,7 +1279,7 @@ class BrowserTabFragment : Fragment(), FindListener, CoroutineScope { } fun decorateWithBottomBarNavigationOnlyExperiment() { - decorateBottomBar() + decorateBottomBarWithNavigationOnlyExperiment() decorateAppBarWithToolbarOnlyExperiment() createPopupMenuWithToolbarOnlyExperiment() configureShowTabSwitcherListenerWithBottomBarNavigationOnlyExperiment() @@ -1293,7 +1287,7 @@ class BrowserTabFragment : Fragment(), FindListener, CoroutineScope { } fun decorateWithBottomBarAndToolbarExperiment() { - decorateBottomBar() + decorateBottomBarWithBottomBarAndToolbarExperiment() decorateAppBarWithToolbarOnlyExperiment() createPopupMenuWithToolbarOnlyExperiment() configureShowTabSwitcherListenerWithBottomBarNavigationOnlyExperiment() @@ -1332,12 +1326,23 @@ class BrowserTabFragment : Fragment(), FindListener, CoroutineScope { } } - private fun decorateBottomBar() { + private fun decorateBottomBarWithNavigationOnlyExperiment() { + bindBottomBarButtons() + + } + + private fun decorateBottomBarWithBottomBarAndToolbarExperiment() { + bindBottomBarButtons() + + } + + private fun bindBottomBarButtons() { bottomNavigationBar.apply { onItemClicked(bottomBarBackItem) { activity?.onBackPressed() } onItemClicked(bottomBarForwardItem) { viewModel.onUserPressedForward() } onItemClicked(bottomBarFireItem) { browserActivity?.launchFire() } - onItemClicked(bottomBarBookmarksItem) { launch { viewModel.onBookmarkAddRequested() } } + onItemClicked(bottomBarBookmarksItemOne) { launch { viewModel.onBookmarkAddRequested() } } + onItemClicked(bottomBarBookmarksItemTwo) { launch { viewModel.onBookmarkAddRequested() } } } } diff --git a/app/src/main/java/com/duckduckgo/app/browser/ui/BottomNavigationBar.kt b/app/src/main/java/com/duckduckgo/app/browser/ui/BottomNavigationBar.kt index 56da7c5d3b5e..1bd7af4e70ce 100644 --- a/app/src/main/java/com/duckduckgo/app/browser/ui/BottomNavigationBar.kt +++ b/app/src/main/java/com/duckduckgo/app/browser/ui/BottomNavigationBar.kt @@ -31,7 +31,7 @@ class BottomNavigationBar @JvmOverloads constructor( override fun onFinishInflate() { super.onFinishInflate() - View.inflate(context, R.layout.layout_bottom_navigation_bar_experiment_one, this) + View.inflate(context, R.layout.layout_bottom_navigation_bar, this) } fun onItemClicked(view: View, onClick: () -> Unit) { @@ -40,4 +40,12 @@ class BottomNavigationBar @JvmOverloads constructor( } } + fun decorateExperimentOne(){ + + } + + fun decorateExperimentTwo(){ + + } + } \ No newline at end of file diff --git a/app/src/main/res/layout/layout_bottom_navigation_bar_experiment_one.xml b/app/src/main/res/layout/layout_bottom_navigation_bar.xml similarity index 67% rename from app/src/main/res/layout/layout_bottom_navigation_bar_experiment_one.xml rename to app/src/main/res/layout/layout_bottom_navigation_bar.xml index e7618ad3ec35..526ea310052f 100644 --- a/app/src/main/res/layout/layout_bottom_navigation_bar_experiment_one.xml +++ b/app/src/main/res/layout/layout_bottom_navigation_bar.xml @@ -28,6 +28,16 @@ android:contentDescription="@string/back" android:src="@drawable/ic_arrow_back_24dp" /> + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/layout_bottom_navigation_bar_experiment_two.xml b/app/src/main/res/layout/layout_bottom_navigation_bar_experiment_two.xml deleted file mode 100644 index 6cde9a18ded9..000000000000 --- a/app/src/main/res/layout/layout_bottom_navigation_bar_experiment_two.xml +++ /dev/null @@ -1,67 +0,0 @@ - - - - - - - - - - - - - - - \ No newline at end of file From 5e8369a8e2283d479d0c1d0fb21b8b6003a7e53e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Gonz=C3=A1lez?= Date: Mon, 30 Mar 2020 17:14:37 +0200 Subject: [PATCH 018/104] added popupmenu that anchors to the bottombar --- .../app/browser/BrowserPopupMenu.kt | 8 + .../app/browser/BrowserTabFragment.kt | 36 +++-- ..._window_browser_bottom_navigation_menu.xml | 144 +++++++++++++++++ .../popup_window_browser_bottom_tab_menu.xml | 146 ++++++++++++++++++ 4 files changed, 317 insertions(+), 17 deletions(-) create mode 100644 app/src/main/res/layout/popup_window_browser_bottom_navigation_menu.xml create mode 100644 app/src/main/res/layout/popup_window_browser_bottom_tab_menu.xml diff --git a/app/src/main/java/com/duckduckgo/app/browser/BrowserPopupMenu.kt b/app/src/main/java/com/duckduckgo/app/browser/BrowserPopupMenu.kt index f90b741c6cb7..b660e9b59933 100644 --- a/app/src/main/java/com/duckduckgo/app/browser/BrowserPopupMenu.kt +++ b/app/src/main/java/com/duckduckgo/app/browser/BrowserPopupMenu.kt @@ -80,6 +80,14 @@ class BrowserPopupMenu : PopupWindow { private fun inflateToolbarOnlyExperiment(layoutInflater: LayoutInflater): View { return layoutInflater.inflate(R.layout.popup_window_browser_menu, null) } + + private fun inflateBottomBarWithNavigationExperiment(layoutInflater: LayoutInflater): View { + return layoutInflater.inflate(R.layout.popup_window_browser_bottom_navigation_menu, null) + } + + private fun inflateBottomBarWithSearchExperiment(layoutInflater: LayoutInflater): View { + return layoutInflater.inflate(R.layout.popup_window_browser_bottom_tab_menu, null) + } } } diff --git a/app/src/main/java/com/duckduckgo/app/browser/BrowserTabFragment.kt b/app/src/main/java/com/duckduckgo/app/browser/BrowserTabFragment.kt index 9bd157e97ce4..c56597bb7410 100644 --- a/app/src/main/java/com/duckduckgo/app/browser/BrowserTabFragment.kt +++ b/app/src/main/java/com/duckduckgo/app/browser/BrowserTabFragment.kt @@ -169,7 +169,6 @@ import kotlinx.android.synthetic.main.include_omnibar_toolbar.toolbarContainer import kotlinx.android.synthetic.main.include_omnibar_toolbar.view.browserMenu import kotlinx.android.synthetic.main.include_omnibar_toolbar.view.privacyGradeButton import kotlinx.android.synthetic.main.layout_bottom_navigation_bar.bottomBarBackItem -import kotlinx.android.synthetic.main.layout_bottom_navigation_bar.bottomBarBookmarksItem import kotlinx.android.synthetic.main.layout_bottom_navigation_bar.bottomBarBookmarksItemOne import kotlinx.android.synthetic.main.layout_bottom_navigation_bar.bottomBarBookmarksItemTwo import kotlinx.android.synthetic.main.layout_bottom_navigation_bar.bottomBarFireItem @@ -788,17 +787,17 @@ class BrowserTabFragment : Fragment(), FindListener, CoroutineScope { } private fun decorateWithExperiments() { - decorator.decorateWithBottomBarAndToolbarExperiment() + decorator.decorateWithBottomBarNavigationExperiment() return when { variantManager.getVariant().hasFeature(VariantManager.VariantFeature.ConceptTest) -> { decorator.decorateWithToolbarOnlyExperiment() } variantManager.getVariant().hasFeature(VariantManager.VariantFeature.ConceptTest) -> { - decorator.decorateWithBottomBarNavigationOnlyExperiment() + decorator.decorateWithBottomBarSearchExperiment() } else -> { - decorator.decorateWithBottomBarAndToolbarExperiment() + decorator.decorateWithBottomBarNavigationExperiment() } } } @@ -809,11 +808,6 @@ class BrowserTabFragment : Fragment(), FindListener, CoroutineScope { browserActivity?.launchPrivacyDashboard() } - browserMenu.setOnClickListener { - hideKeyboardImmediately() - launchPopupMenu() - } - viewModel.privacyGrade.observe(this, Observer { Timber.d("Observed grade: $it") it?.let { privacyGrade -> @@ -1012,10 +1006,6 @@ class BrowserTabFragment : Fragment(), FindListener, CoroutineScope { return super.onContextItemSelected(item) } - private fun launchPopupMenu() { - popupMenu.show(rootView, toolbar) - } - private fun bookmarkAdded(bookmarkId: Long, title: String?, url: String?) { Snackbar.make(rootView, R.string.bookmarkEdited, Snackbar.LENGTH_LONG) @@ -1278,7 +1268,7 @@ class BrowserTabFragment : Fragment(), FindListener, CoroutineScope { configureLongClickOpensNewTabListenerWithToolbarOnlyExperiment() } - fun decorateWithBottomBarNavigationOnlyExperiment() { + fun decorateWithBottomBarSearchExperiment() { decorateBottomBarWithNavigationOnlyExperiment() decorateAppBarWithToolbarOnlyExperiment() createPopupMenuWithToolbarOnlyExperiment() @@ -1286,7 +1276,7 @@ class BrowserTabFragment : Fragment(), FindListener, CoroutineScope { configureLongClickOpensNewTabListenerWithBottomBarNavigationOnlyExperiment() } - fun decorateWithBottomBarAndToolbarExperiment() { + fun decorateWithBottomBarNavigationExperiment() { decorateBottomBarWithBottomBarAndToolbarExperiment() decorateAppBarWithToolbarOnlyExperiment() createPopupMenuWithToolbarOnlyExperiment() @@ -1324,13 +1314,25 @@ class BrowserTabFragment : Fragment(), FindListener, CoroutineScope { onMenuItemClicked(view.sharePageMenuItem) { viewModel.onShareSelected() } onMenuItemClicked(view.addToHome) { viewModel.onPinPageToHomeSelected() } } + browserMenu.setOnClickListener { + hideKeyboardImmediately() + launchBottomAnchoredPopupMenu() + } } - private fun decorateBottomBarWithNavigationOnlyExperiment() { - bindBottomBarButtons() + private fun launchTopAnchoredPopupMenu() { + popupMenu.show(rootView, toolbar) + } + private fun launchBottomAnchoredPopupMenu() { + popupMenu.show(rootView, bottomNavigationBar) } + private fun decorateBottomBarWithNavigationOnlyExperiment() { + bindBottomBarButtons() + + } + private fun decorateBottomBarWithBottomBarAndToolbarExperiment() { bindBottomBarButtons() diff --git a/app/src/main/res/layout/popup_window_browser_bottom_navigation_menu.xml b/app/src/main/res/layout/popup_window_browser_bottom_navigation_menu.xml new file mode 100644 index 000000000000..b39c149b7c41 --- /dev/null +++ b/app/src/main/res/layout/popup_window_browser_bottom_navigation_menu.xml @@ -0,0 +1,144 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/popup_window_browser_bottom_tab_menu.xml b/app/src/main/res/layout/popup_window_browser_bottom_tab_menu.xml new file mode 100644 index 000000000000..c15c3571a9f3 --- /dev/null +++ b/app/src/main/res/layout/popup_window_browser_bottom_tab_menu.xml @@ -0,0 +1,146 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file From 5f272b51bcb022bc0799f0d5656b23ae319a9f79 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Gonz=C3=A1lez?= Date: Mon, 30 Mar 2020 17:29:58 +0200 Subject: [PATCH 019/104] we can now decorate the toolbar based on the experiment --- .../app/browser/BrowserTabFragment.kt | 39 ++++++++++++++++--- 1 file changed, 34 insertions(+), 5 deletions(-) diff --git a/app/src/main/java/com/duckduckgo/app/browser/BrowserTabFragment.kt b/app/src/main/java/com/duckduckgo/app/browser/BrowserTabFragment.kt index c56597bb7410..6214b3e85420 100644 --- a/app/src/main/java/com/duckduckgo/app/browser/BrowserTabFragment.kt +++ b/app/src/main/java/com/duckduckgo/app/browser/BrowserTabFragment.kt @@ -1260,6 +1260,32 @@ class BrowserTabFragment : Fragment(), FindListener, CoroutineScope { inner class BrowserTabFragmentExperimentDecorator { + fun decorateToolbarMenus(viewState: BrowserViewState){ + decorator.hideToolbarMenu() + return + when { + variantManager.getVariant().hasFeature(VariantManager.VariantFeature.ConceptTest) -> { + decorator.decorateToolbarMenu(viewState) + } + variantManager.getVariant().hasFeature(VariantManager.VariantFeature.ConceptTest) -> { + decorator.hideToolbarMenu() + } + else -> { + decorator.hideToolbarMenu() + } + } + } + + private fun decorateToolbarMenu(viewState: BrowserViewState){ + tabsButton?.isVisible = viewState.showTabsButton + fireMenuButton?.isVisible = viewState.showFireButton + menuButton?.isVisible = viewState.showMenuButton + } + + private fun hideToolbarMenu(){ + menuButton?.gone() + } + fun decorateWithToolbarOnlyExperiment() { hideBottomBar() decorateAppBarWithToolbarOnlyExperiment() @@ -1270,7 +1296,7 @@ class BrowserTabFragment : Fragment(), FindListener, CoroutineScope { fun decorateWithBottomBarSearchExperiment() { decorateBottomBarWithNavigationOnlyExperiment() - decorateAppBarWithToolbarOnlyExperiment() + decorateAppBarWithBottomBarExperiment() createPopupMenuWithToolbarOnlyExperiment() configureShowTabSwitcherListenerWithBottomBarNavigationOnlyExperiment() configureLongClickOpensNewTabListenerWithBottomBarNavigationOnlyExperiment() @@ -1278,7 +1304,7 @@ class BrowserTabFragment : Fragment(), FindListener, CoroutineScope { fun decorateWithBottomBarNavigationExperiment() { decorateBottomBarWithBottomBarAndToolbarExperiment() - decorateAppBarWithToolbarOnlyExperiment() + decorateAppBarWithBottomBarExperiment() createPopupMenuWithToolbarOnlyExperiment() configureShowTabSwitcherListenerWithBottomBarNavigationOnlyExperiment() configureLongClickOpensNewTabListenerWithBottomBarNavigationOnlyExperiment() @@ -1297,6 +1323,10 @@ class BrowserTabFragment : Fragment(), FindListener, CoroutineScope { } } + private fun decorateAppBarWithBottomBarExperiment() { + menuButton?.gone() + } + private fun createPopupMenuWithToolbarOnlyExperiment() { popupMenu = BrowserPopupMenu(layoutInflater, variantManager.getVariant()) val view = popupMenu.contentView @@ -1565,9 +1595,8 @@ class BrowserTabFragment : Fragment(), FindListener, CoroutineScope { private fun renderToolbarMenus(viewState: BrowserViewState) { privacyGradeButton?.isVisible = viewState.showPrivacyGrade clearTextButton?.isVisible = viewState.showClearButton - bottomBarTabsItem?.isVisible = viewState.showTabsButton - bottomBarFireItem?.isVisible = viewState.showFireButton - menuButton?.isVisible = viewState.showMenuButton + + decorator.decorateToolbarMenus(viewState) } fun renderFindInPageState(viewState: FindInPageViewState) { From b5a014d3305ae5339422de4eda109c4252379746 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Gonz=C3=A1lez?= Date: Mon, 30 Mar 2020 18:41:25 +0200 Subject: [PATCH 020/104] added experiment variants for the bottom navigation --- .../app/browser/BrowserTabFragment.kt | 34 ++++++++----------- .../app/statistics/VariantManager.kt | 20 +++++++++-- 2 files changed, 31 insertions(+), 23 deletions(-) diff --git a/app/src/main/java/com/duckduckgo/app/browser/BrowserTabFragment.kt b/app/src/main/java/com/duckduckgo/app/browser/BrowserTabFragment.kt index 6214b3e85420..b59c25e769a2 100644 --- a/app/src/main/java/com/duckduckgo/app/browser/BrowserTabFragment.kt +++ b/app/src/main/java/com/duckduckgo/app/browser/BrowserTabFragment.kt @@ -132,8 +132,6 @@ import com.duckduckgo.app.widget.ui.AddWidgetInstructionsActivity import com.duckduckgo.widget.SearchWidgetLight import com.google.android.material.snackbar.Snackbar import dagger.android.support.AndroidSupportInjection -import kotlinx.android.synthetic.main.include_new_browser_tab.* -import kotlinx.android.synthetic.main.include_top_cta.view.* import kotlinx.android.synthetic.main.fragment_browser_tab.autoCompleteSuggestionsList import kotlinx.android.synthetic.main.fragment_browser_tab.bottomNavigationBar import kotlinx.android.synthetic.main.fragment_browser_tab.browserLayout @@ -154,6 +152,7 @@ import kotlinx.android.synthetic.main.include_find_in_page.findInPageMatches import kotlinx.android.synthetic.main.include_find_in_page.nextSearchTermButton import kotlinx.android.synthetic.main.include_find_in_page.previousSearchTermButton import kotlinx.android.synthetic.main.include_new_browser_tab.ctaContainer +import kotlinx.android.synthetic.main.include_new_browser_tab.ctaTopContainer import kotlinx.android.synthetic.main.include_new_browser_tab.ddgLogo import kotlinx.android.synthetic.main.include_new_browser_tab.newTabLayout import kotlinx.android.synthetic.main.include_omnibar_toolbar.appBarLayout @@ -168,6 +167,7 @@ import kotlinx.android.synthetic.main.include_omnibar_toolbar.toolbar import kotlinx.android.synthetic.main.include_omnibar_toolbar.toolbarContainer import kotlinx.android.synthetic.main.include_omnibar_toolbar.view.browserMenu import kotlinx.android.synthetic.main.include_omnibar_toolbar.view.privacyGradeButton +import kotlinx.android.synthetic.main.include_top_cta.view.closeButton import kotlinx.android.synthetic.main.layout_bottom_navigation_bar.bottomBarBackItem import kotlinx.android.synthetic.main.layout_bottom_navigation_bar.bottomBarBookmarksItemOne import kotlinx.android.synthetic.main.layout_bottom_navigation_bar.bottomBarBookmarksItemTwo @@ -787,17 +787,15 @@ class BrowserTabFragment : Fragment(), FindListener, CoroutineScope { } private fun decorateWithExperiments() { - decorator.decorateWithBottomBarNavigationExperiment() - return when { - variantManager.getVariant().hasFeature(VariantManager.VariantFeature.ConceptTest) -> { - decorator.decorateWithToolbarOnlyExperiment() + variantManager.getVariant().hasFeature(VariantManager.VariantFeature.BottomBarWithNavigationExperiment) -> { + decorator.decorateWithBottomBarNavigationExperiment() } - variantManager.getVariant().hasFeature(VariantManager.VariantFeature.ConceptTest) -> { + variantManager.getVariant().hasFeature(VariantManager.VariantFeature.BottomBarWithSearchExperiment) -> { decorator.decorateWithBottomBarSearchExperiment() } else -> { - decorator.decorateWithBottomBarNavigationExperiment() + decorator.decorateWithToolbarOnlyExperiment() } } } @@ -1260,29 +1258,27 @@ class BrowserTabFragment : Fragment(), FindListener, CoroutineScope { inner class BrowserTabFragmentExperimentDecorator { - fun decorateToolbarMenus(viewState: BrowserViewState){ - decorator.hideToolbarMenu() - return + fun decorateToolbarMenus(viewState: BrowserViewState) { when { - variantManager.getVariant().hasFeature(VariantManager.VariantFeature.ConceptTest) -> { - decorator.decorateToolbarMenu(viewState) + variantManager.getVariant().hasFeature(VariantManager.VariantFeature.BottomBarWithNavigationExperiment) -> { + decorator.hideToolbarMenu() } - variantManager.getVariant().hasFeature(VariantManager.VariantFeature.ConceptTest) -> { + variantManager.getVariant().hasFeature(VariantManager.VariantFeature.BottomBarWithSearchExperiment) -> { decorator.hideToolbarMenu() } else -> { - decorator.hideToolbarMenu() + decorator.decorateToolbarMenu(viewState) } } } - private fun decorateToolbarMenu(viewState: BrowserViewState){ + private fun decorateToolbarMenu(viewState: BrowserViewState) { tabsButton?.isVisible = viewState.showTabsButton fireMenuButton?.isVisible = viewState.showFireButton menuButton?.isVisible = viewState.showMenuButton } - private fun hideToolbarMenu(){ + private fun hideToolbarMenu() { menuButton?.gone() } @@ -1360,12 +1356,10 @@ class BrowserTabFragment : Fragment(), FindListener, CoroutineScope { private fun decorateBottomBarWithNavigationOnlyExperiment() { bindBottomBarButtons() - - } + } private fun decorateBottomBarWithBottomBarAndToolbarExperiment() { bindBottomBarButtons() - } private fun bindBottomBarButtons() { diff --git a/app/src/main/java/com/duckduckgo/app/statistics/VariantManager.kt b/app/src/main/java/com/duckduckgo/app/statistics/VariantManager.kt index fe20cc14aedf..bc640f965eb7 100644 --- a/app/src/main/java/com/duckduckgo/app/statistics/VariantManager.kt +++ b/app/src/main/java/com/duckduckgo/app/statistics/VariantManager.kt @@ -36,6 +36,8 @@ interface VariantManager { object DefaultBrowserDaxCta : VariantFeature() object SearchWidgetDaxCta : VariantFeature() object StickySearchNotification : VariantFeature() + object BottomBarWithSearchExperiment : VariantFeature() + object BottomBarWithNavigationExperiment : VariantFeature() } companion object { @@ -48,8 +50,8 @@ interface VariantManager { val ACTIVE_VARIANTS = listOf( // SERP variants. "sc" may also be used as a shared control for mobile experiments in // the future if we can filter by app version - Variant(key = "sc", weight = 1.0, features = emptyList(), filterBy = { noFilter() }), - Variant(key = "se", weight = 1.0, features = emptyList(), filterBy = { noFilter() }), + Variant(key = "sc", weight = 0.0, features = emptyList(), filterBy = { noFilter() }), + Variant(key = "se", weight = 0.0, features = emptyList(), filterBy = { noFilter() }), // Concept test experiment Variant(key = "mc", weight = 0.0, features = emptyList(), filterBy = { isEnglishLocale() }), @@ -90,8 +92,20 @@ interface VariantManager { filterBy = { isEnglishLocale() }), Variant( key = "mg", - weight = 1.0, + weight = 0.0, features = listOf(StickySearchNotification), + filterBy = { isEnglishLocale() }), + + // Bottom Bar Navigation Experiment + Variant( + key = "mm", + weight = 0.0, + features = listOf(BottomBarWithSearchExperiment), + filterBy = { isEnglishLocale() }), + Variant( + key = "mn", + weight = 0.0, + features = listOf(BottomBarWithNavigationExperiment), filterBy = { isEnglishLocale() }) // All groups in an experiment (control and variants) MUST use the same filters From 297d9de826b61f8c49228c17dd3dc1f68db42ef7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Gonz=C3=A1lez?= Date: Mon, 30 Mar 2020 19:08:29 +0200 Subject: [PATCH 021/104] always showing the omnibar background --- .../app/browser/BrowserTabFragment.kt | 3 ++- .../main/res/layout/include_omnibar_toolbar.xml | 17 ++++++++++++++--- 2 files changed, 16 insertions(+), 4 deletions(-) diff --git a/app/src/main/java/com/duckduckgo/app/browser/BrowserTabFragment.kt b/app/src/main/java/com/duckduckgo/app/browser/BrowserTabFragment.kt index b59c25e769a2..3712965cd434 100644 --- a/app/src/main/java/com/duckduckgo/app/browser/BrowserTabFragment.kt +++ b/app/src/main/java/com/duckduckgo/app/browser/BrowserTabFragment.kt @@ -163,6 +163,7 @@ import kotlinx.android.synthetic.main.include_omnibar_toolbar.omniBarContainer import kotlinx.android.synthetic.main.include_omnibar_toolbar.omnibarTextInput import kotlinx.android.synthetic.main.include_omnibar_toolbar.pageLoadingIndicator import kotlinx.android.synthetic.main.include_omnibar_toolbar.privacyGradeButton +import kotlinx.android.synthetic.main.include_omnibar_toolbar.searchIcon import kotlinx.android.synthetic.main.include_omnibar_toolbar.toolbar import kotlinx.android.synthetic.main.include_omnibar_toolbar.toolbarContainer import kotlinx.android.synthetic.main.include_omnibar_toolbar.view.browserMenu @@ -1589,7 +1590,7 @@ class BrowserTabFragment : Fragment(), FindListener, CoroutineScope { private fun renderToolbarMenus(viewState: BrowserViewState) { privacyGradeButton?.isVisible = viewState.showPrivacyGrade clearTextButton?.isVisible = viewState.showClearButton - + searchIcon?.isVisible = !viewState.showPrivacyGrade decorator.decorateToolbarMenus(viewState) } diff --git a/app/src/main/res/layout/include_omnibar_toolbar.xml b/app/src/main/res/layout/include_omnibar_toolbar.xml index 1368ad9d2a33..a5de54c2242b 100644 --- a/app/src/main/res/layout/include_omnibar_toolbar.xml +++ b/app/src/main/res/layout/include_omnibar_toolbar.xml @@ -79,14 +79,25 @@ app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent" /> + + Date: Tue, 31 Mar 2020 20:34:23 +0200 Subject: [PATCH 022/104] no need for old custom webview, scroll is already properly supported --- .../app/browser/DuckDuckGoWebViewTest.kt | 37 ----- .../app/browser/DuckDuckGoWebView.kt | 143 ------------------ .../main/res/layout/fragment_browser_tab.xml | 1 - .../include_duckduckgo_browser_webview.xml | 4 +- 4 files changed, 2 insertions(+), 183 deletions(-) delete mode 100644 app/src/androidTest/java/com/duckduckgo/app/browser/DuckDuckGoWebViewTest.kt delete mode 100644 app/src/main/java/com/duckduckgo/app/browser/DuckDuckGoWebView.kt diff --git a/app/src/androidTest/java/com/duckduckgo/app/browser/DuckDuckGoWebViewTest.kt b/app/src/androidTest/java/com/duckduckgo/app/browser/DuckDuckGoWebViewTest.kt deleted file mode 100644 index 7963b15c4032..000000000000 --- a/app/src/androidTest/java/com/duckduckgo/app/browser/DuckDuckGoWebViewTest.kt +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright (c) 2018 DuckDuckGo - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.duckduckgo.app.browser - -import android.os.Build -import androidx.test.annotation.UiThreadTest -import androidx.test.platform.app.InstrumentationRegistry -import org.junit.Assert.assertFalse -import org.junit.Test - -class DuckDuckGoWebViewTest { - - private lateinit var testee: DuckDuckGoWebView - - @UiThreadTest - @Test - fun whenWebViewInitialisedThenSafeBrowsingDisabled() { - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { - testee = DuckDuckGoWebView(InstrumentationRegistry.getInstrumentation().targetContext) - assertFalse(testee.settings.safeBrowsingEnabled) - } - } -} \ No newline at end of file diff --git a/app/src/main/java/com/duckduckgo/app/browser/DuckDuckGoWebView.kt b/app/src/main/java/com/duckduckgo/app/browser/DuckDuckGoWebView.kt deleted file mode 100644 index ad31599f4a2a..000000000000 --- a/app/src/main/java/com/duckduckgo/app/browser/DuckDuckGoWebView.kt +++ /dev/null @@ -1,143 +0,0 @@ -/* - * Copyright (c) 2017 DuckDuckGo - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.duckduckgo.app.browser - -import android.annotation.SuppressLint -import android.content.Context -import androidx.core.view.NestedScrollingChild -import androidx.core.view.NestedScrollingChildHelper -import androidx.core.view.ViewCompat -import android.util.AttributeSet -import android.view.MotionEvent -import android.view.inputmethod.EditorInfo -import android.view.inputmethod.InputConnection -import android.webkit.WebView - -/** - * WebView subclass which allows the WebView to - * - hide the toolbar when placed in a CoordinatorLayout - * - add the flag so that users' typing isn't used for personalisation - * - * Originally based on https://github.com/takahirom/webview-in-coordinatorlayout for scrolling behaviour - */ -class DuckDuckGoWebView : WebView, NestedScrollingChild { - private var lastY: Int = 0 - private val scrollOffset = IntArray(2) - private val scrollConsumed = IntArray(2) - private var nestedOffsetY: Int = 0 - private var nestedScrollHelper: NestedScrollingChildHelper = NestedScrollingChildHelper(this) - - constructor(context: Context) : this(context, null) - constructor(context: Context, attrs: AttributeSet?) : super(context, attrs) { - isNestedScrollingEnabled = true - } - - override fun onCreateInputConnection(outAttrs: EditorInfo): InputConnection? { - val inputConnection = super.onCreateInputConnection(outAttrs) ?: return null - - addNoPersonalisedFlag(outAttrs) - - return inputConnection - } - - - private fun addNoPersonalisedFlag(outAttrs: EditorInfo) { - outAttrs.imeOptions = outAttrs.imeOptions or IME_FLAG_NO_PERSONALIZED_LEARNING - } - - @SuppressLint("ClickableViewAccessibility") - override fun onTouchEvent(ev: MotionEvent): Boolean { - var returnValue = false - - val event = MotionEvent.obtain(ev) - val action = event.actionMasked - if (action == MotionEvent.ACTION_DOWN) { - nestedOffsetY = 0 - } - val eventY = event.y.toInt() - event.offsetLocation(0f, nestedOffsetY.toFloat()) - - when (action) { - MotionEvent.ACTION_MOVE -> { - var deltaY = lastY - eventY - - if (dispatchNestedPreScroll(0, deltaY, scrollConsumed, scrollOffset)) { - deltaY -= scrollConsumed[1] - lastY = eventY - scrollOffset[1] - event.offsetLocation(0f, (-scrollOffset[1]).toFloat()) - nestedOffsetY += scrollOffset[1] - } - - returnValue = super.onTouchEvent(event) - - if (dispatchNestedScroll(0, scrollOffset[1], 0, deltaY, scrollOffset)) { - event.offsetLocation(0f, scrollOffset[1].toFloat()) - nestedOffsetY += scrollOffset[1] - lastY -= scrollOffset[1] - } - } - - MotionEvent.ACTION_DOWN -> { - returnValue = super.onTouchEvent(event) - lastY = eventY - startNestedScroll(ViewCompat.SCROLL_AXIS_VERTICAL) - } - - else -> { - returnValue = super.onTouchEvent(event) - stopNestedScroll() - } - } - - return returnValue - } - - override fun setNestedScrollingEnabled(enabled: Boolean) { - nestedScrollHelper.isNestedScrollingEnabled = enabled - } - - override fun stopNestedScroll() { - nestedScrollHelper.stopNestedScroll() - } - - override fun isNestedScrollingEnabled(): Boolean = nestedScrollHelper.isNestedScrollingEnabled - - override fun startNestedScroll(axes: Int): Boolean = nestedScrollHelper.startNestedScroll(axes) - - override fun hasNestedScrollingParent(): Boolean = nestedScrollHelper.hasNestedScrollingParent() - - override fun dispatchNestedScroll(dxConsumed: Int, dyConsumed: Int, dxUnconsumed: Int, dyUnconsumed: Int, offsetInWindow: IntArray?): Boolean = - nestedScrollHelper.dispatchNestedScroll(dxConsumed, dyConsumed, dxUnconsumed, dyUnconsumed, offsetInWindow) - - override fun dispatchNestedPreScroll(dx: Int, dy: Int, consumed: IntArray?, offsetInWindow: IntArray?): Boolean = - nestedScrollHelper.dispatchNestedPreScroll(dx, dy, consumed, offsetInWindow) - - override fun dispatchNestedFling(velocityX: Float, velocityY: Float, consumed: Boolean): Boolean = - nestedScrollHelper.dispatchNestedFling(velocityX, velocityY, consumed) - - override fun dispatchNestedPreFling(velocityX: Float, velocityY: Float): Boolean = - nestedScrollHelper.dispatchNestedPreFling(velocityX, velocityY) - - companion object { - - /* - * Taken from EditorInfo.IME_FLAG_NO_PERSONALIZED_LEARNING - * We can't use that value directly as it was only added on Oreo, but we can apply the value anyway. - */ - private const val IME_FLAG_NO_PERSONALIZED_LEARNING = 0x1000000 - } -} diff --git a/app/src/main/res/layout/fragment_browser_tab.xml b/app/src/main/res/layout/fragment_browser_tab.xml index bc9b30855c3f..58ff77498583 100644 --- a/app/src/main/res/layout/fragment_browser_tab.xml +++ b/app/src/main/res/layout/fragment_browser_tab.xml @@ -82,7 +82,6 @@ app:layout_behavior="@string/appbar_scrolling_view_behavior" tools:context="com.duckduckgo.app.browser.BrowserActivity"> - - - \ No newline at end of file + \ No newline at end of file From 90fd052d9444445dfb66d24063722866371f7fca Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Gonz=C3=A1lez?= Date: Wed, 1 Apr 2020 15:31:16 +0200 Subject: [PATCH 023/104] removing pull to refresh for now --- .../app/browser/BrowserTabFragment.kt | 21 ---------- .../ui/ScrollAwareSwipeRefreshLayout.kt | 39 ------------------- .../main/res/layout/fragment_browser_tab.xml | 21 +++------- 3 files changed, 5 insertions(+), 76 deletions(-) delete mode 100644 app/src/main/java/com/duckduckgo/app/browser/ui/ScrollAwareSwipeRefreshLayout.kt diff --git a/app/src/main/java/com/duckduckgo/app/browser/BrowserTabFragment.kt b/app/src/main/java/com/duckduckgo/app/browser/BrowserTabFragment.kt index 3712965cd434..68e0dfb23bc5 100644 --- a/app/src/main/java/com/duckduckgo/app/browser/BrowserTabFragment.kt +++ b/app/src/main/java/com/duckduckgo/app/browser/BrowserTabFragment.kt @@ -96,7 +96,6 @@ import com.duckduckgo.app.browser.shortcut.ShortcutBuilder import com.duckduckgo.app.browser.tabpreview.WebViewPreviewGenerator import com.duckduckgo.app.browser.tabpreview.WebViewPreviewPersister import com.duckduckgo.app.browser.ui.HttpAuthenticationDialogFragment -import com.duckduckgo.app.browser.ui.ScrollAwareSwipeRefreshLayout import com.duckduckgo.app.browser.useragent.UserAgentProvider import com.duckduckgo.app.cta.ui.Cta import com.duckduckgo.app.cta.ui.CtaViewModel @@ -138,7 +137,6 @@ import kotlinx.android.synthetic.main.fragment_browser_tab.browserLayout import kotlinx.android.synthetic.main.fragment_browser_tab.defaultCard import kotlinx.android.synthetic.main.fragment_browser_tab.focusDummy import kotlinx.android.synthetic.main.fragment_browser_tab.rootView -import kotlinx.android.synthetic.main.fragment_browser_tab.swipeContainer import kotlinx.android.synthetic.main.fragment_browser_tab.webViewContainer import kotlinx.android.synthetic.main.fragment_browser_tab.webViewFullScreenContainer import kotlinx.android.synthetic.main.include_cta_buttons.view.ctaDismissButton @@ -369,7 +367,6 @@ class BrowserTabFragment : Fragment(), FindListener, CoroutineScope { configureAutoComplete() configureKeyboardAwareLogoAnimation() configureAppBar() - configureSwipeToRefresh() decorateWithExperiments() @@ -520,7 +517,6 @@ class BrowserTabFragment : Fragment(), FindListener, CoroutineScope { } fun onRefreshRequested() { - swipeContainer.isRefreshing = true viewModel.onRefreshRequested() } @@ -817,19 +813,6 @@ class BrowserTabFragment : Fragment(), FindListener, CoroutineScope { }) } - private fun configureSwipeToRefresh() { - swipeContainer.setCanWebViewScrollUpCallback(object : ScrollAwareSwipeRefreshLayout.CanWebViewScrollUpCallback { - override fun canSwipeRefreshChildScrollUp(): Boolean { - return webView?.canScrollVertically(-1) ?: false - } - }) - - swipeContainer.setColorSchemeColors(ContextCompat.getColor(context!!, R.color.cornflowerBlue)) - swipeContainer.setOnRefreshListener { - viewModel.onRefreshRequested() - } - } - private fun configureFindInPage() { findInPageInput.setOnFocusChangeListener { _, hasFocus -> if (hasFocus && findInPageInput.text.toString() != viewModel.findInPageViewState.value?.searchTerm) { @@ -1468,10 +1451,6 @@ class BrowserTabFragment : Fragment(), FindListener, CoroutineScope { createTrackersAnimation() } } - - if (!viewState.isLoading) { - swipeContainer.isRefreshing = false - } } } diff --git a/app/src/main/java/com/duckduckgo/app/browser/ui/ScrollAwareSwipeRefreshLayout.kt b/app/src/main/java/com/duckduckgo/app/browser/ui/ScrollAwareSwipeRefreshLayout.kt deleted file mode 100644 index e11b9bb1e20b..000000000000 --- a/app/src/main/java/com/duckduckgo/app/browser/ui/ScrollAwareSwipeRefreshLayout.kt +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Copyright (c) 2020 DuckDuckGo - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.duckduckgo.app.browser.ui - -import android.content.Context -import android.util.AttributeSet -import androidx.swiperefreshlayout.widget.SwipeRefreshLayout - -class ScrollAwareSwipeRefreshLayout @JvmOverloads constructor( - context: Context, - attrs: AttributeSet? = null -) : SwipeRefreshLayout(context, attrs) { - private var canWebViewScrollUpCallback: CanWebViewScrollUpCallback? = null - - interface CanWebViewScrollUpCallback { - fun canSwipeRefreshChildScrollUp(): Boolean - } - - fun setCanWebViewScrollUpCallback(canWebViewScrollUpCallback: CanWebViewScrollUpCallback) { - this.canWebViewScrollUpCallback = canWebViewScrollUpCallback - } - - override fun canChildScrollUp(): Boolean { - return canWebViewScrollUpCallback?.canSwipeRefreshChildScrollUp() ?: super.canChildScrollUp() - } -} \ No newline at end of file diff --git a/app/src/main/res/layout/fragment_browser_tab.xml b/app/src/main/res/layout/fragment_browser_tab.xml index 58ff77498583..55dd5c3e00a0 100644 --- a/app/src/main/res/layout/fragment_browser_tab.xml +++ b/app/src/main/res/layout/fragment_browser_tab.xml @@ -82,27 +82,16 @@ app:layout_behavior="@string/appbar_scrolling_view_behavior" tools:context="com.duckduckgo.app.browser.BrowserActivity"> - - - - - + app:layout_constraintTop_toTopOf="parent" + tools:background="#4F00" /> Date: Wed, 1 Apr 2020 15:50:40 +0200 Subject: [PATCH 024/104] using the search experiment by default --- .../app/browser/DuckDuckGoWebView.kt | 143 ++++++++++++++++++ .../app/statistics/VariantManager.kt | 4 +- .../include_duckduckgo_browser_webview.xml | 4 +- 3 files changed, 147 insertions(+), 4 deletions(-) create mode 100644 app/src/main/java/com/duckduckgo/app/browser/DuckDuckGoWebView.kt diff --git a/app/src/main/java/com/duckduckgo/app/browser/DuckDuckGoWebView.kt b/app/src/main/java/com/duckduckgo/app/browser/DuckDuckGoWebView.kt new file mode 100644 index 000000000000..54e7c2d1ad06 --- /dev/null +++ b/app/src/main/java/com/duckduckgo/app/browser/DuckDuckGoWebView.kt @@ -0,0 +1,143 @@ +/* + * Copyright (c) 2017 DuckDuckGo + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.duckduckgo.app.browser + +import android.annotation.SuppressLint +import android.content.Context +import androidx.core.view.NestedScrollingChild +import androidx.core.view.NestedScrollingChildHelper +import androidx.core.view.ViewCompat +import android.util.AttributeSet +import android.view.MotionEvent +import android.view.inputmethod.EditorInfo +import android.view.inputmethod.InputConnection +import android.webkit.WebView + +/** + * WebView subclass which allows the WebView to + * - hide the toolbar when placed in a CoordinatorLayout + * - add the flag so that users' typing isn't used for personalisation + * + * Originally based on https://github.com/takahirom/webview-in-coordinatorlayout for scrolling behaviour + */ +class DuckDuckGoWebView : WebView, NestedScrollingChild { + private var lastY: Int = 0 + private val scrollOffset = IntArray(2) + private val scrollConsumed = IntArray(2) + private var nestedOffsetY: Int = 0 + private var nestedScrollHelper: NestedScrollingChildHelper = NestedScrollingChildHelper(this) + + constructor(context: Context) : this(context, null) + constructor(context: Context, attrs: AttributeSet?) : super(context, attrs) { + isNestedScrollingEnabled = true + } + + override fun onCreateInputConnection(outAttrs: EditorInfo): InputConnection? { + val inputConnection = super.onCreateInputConnection(outAttrs) ?: return null + + addNoPersonalisedFlag(outAttrs) + + return inputConnection + } + + + private fun addNoPersonalisedFlag(outAttrs: EditorInfo) { + outAttrs.imeOptions = outAttrs.imeOptions or IME_FLAG_NO_PERSONALIZED_LEARNING + } + + @SuppressLint("ClickableViewAccessibility") + override fun onTouchEvent(ev: MotionEvent): Boolean { + var returnValue = false + + val event = MotionEvent.obtain(ev) + val action = event.actionMasked + if (action == MotionEvent.ACTION_DOWN) { + nestedOffsetY = 0 + } + val eventY = event.y.toInt() + event.offsetLocation(0f, nestedOffsetY.toFloat()) + + when (action) { + MotionEvent.ACTION_MOVE -> { + var deltaY = lastY - eventY + + if (dispatchNestedPreScroll(0, deltaY, scrollConsumed, scrollOffset)) { + deltaY -= scrollConsumed[1] + lastY = eventY - scrollOffset[1] + event.offsetLocation(0f, (-scrollOffset[1]).toFloat()) + nestedOffsetY += scrollOffset[1] + } + + returnValue = super.onTouchEvent(event) + + if (dispatchNestedScroll(0, scrollOffset[1], 0, deltaY, scrollOffset)) { + event.offsetLocation(0f, scrollOffset[1].toFloat()) + nestedOffsetY += scrollOffset[1] + lastY -= scrollOffset[1] + } + } + + MotionEvent.ACTION_DOWN -> { + returnValue = super.onTouchEvent(event) + lastY = eventY + startNestedScroll(ViewCompat.SCROLL_AXIS_VERTICAL) + } + + else -> { + returnValue = super.onTouchEvent(event) + stopNestedScroll() + } + } + + return returnValue + } + + override fun setNestedScrollingEnabled(enabled: Boolean) { + nestedScrollHelper.isNestedScrollingEnabled = enabled + } + + override fun stopNestedScroll() { + nestedScrollHelper.stopNestedScroll() + } + + override fun isNestedScrollingEnabled(): Boolean = nestedScrollHelper.isNestedScrollingEnabled + + override fun startNestedScroll(axes: Int): Boolean = nestedScrollHelper.startNestedScroll(axes) + + override fun hasNestedScrollingParent(): Boolean = nestedScrollHelper.hasNestedScrollingParent() + + override fun dispatchNestedScroll(dxConsumed: Int, dyConsumed: Int, dxUnconsumed: Int, dyUnconsumed: Int, offsetInWindow: IntArray?): Boolean = + nestedScrollHelper.dispatchNestedScroll(dxConsumed, dyConsumed, dxUnconsumed, dyUnconsumed, offsetInWindow) + + override fun dispatchNestedPreScroll(dx: Int, dy: Int, consumed: IntArray?, offsetInWindow: IntArray?): Boolean = + nestedScrollHelper.dispatchNestedPreScroll(dx, dy, consumed, offsetInWindow) + + override fun dispatchNestedFling(velocityX: Float, velocityY: Float, consumed: Boolean): Boolean = + nestedScrollHelper.dispatchNestedFling(velocityX, velocityY, consumed) + + override fun dispatchNestedPreFling(velocityX: Float, velocityY: Float): Boolean = + nestedScrollHelper.dispatchNestedPreFling(velocityX, velocityY) + + companion object { + + /* + * Taken from EditorInfo.IME_FLAG_NO_PERSONALIZED_LEARNING + * We can't use that value directly as it was only added on Oreo, but we can apply the value anyway. + */ + private const val IME_FLAG_NO_PERSONALIZED_LEARNING = 0x1000000 + } +} \ No newline at end of file diff --git a/app/src/main/java/com/duckduckgo/app/statistics/VariantManager.kt b/app/src/main/java/com/duckduckgo/app/statistics/VariantManager.kt index cfe5bb65c6a6..2b776f12a1d0 100644 --- a/app/src/main/java/com/duckduckgo/app/statistics/VariantManager.kt +++ b/app/src/main/java/com/duckduckgo/app/statistics/VariantManager.kt @@ -50,7 +50,7 @@ interface VariantManager { // Quick Search Notification Experiment Variant( key = "mf", - weight = 1.0, + weight = 0.0, features = emptyList(), filterBy = { isEnglishLocale() }), Variant( @@ -62,7 +62,7 @@ interface VariantManager { // Bottom Bar Navigation Experiment Variant( key = "mm", - weight = 0.0, + weight = 1.0, features = listOf(BottomBarWithSearchExperiment), filterBy = { isEnglishLocale() }), Variant( diff --git a/app/src/main/res/layout/include_duckduckgo_browser_webview.xml b/app/src/main/res/layout/include_duckduckgo_browser_webview.xml index fdba38bfb0e5..73ad7576d225 100644 --- a/app/src/main/res/layout/include_duckduckgo_browser_webview.xml +++ b/app/src/main/res/layout/include_duckduckgo_browser_webview.xml @@ -14,7 +14,7 @@ ~ limitations under the License. --> - - \ No newline at end of file + \ No newline at end of file From af961dbe8f3151c7118747424f3124d44f4268c7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Gonz=C3=A1lez?= Date: Thu, 2 Apr 2020 16:40:13 +0200 Subject: [PATCH 025/104] removed the second experiment, binding popup and bottom bar click listeners --- .../app/browser/BrowserPopupMenu.kt | 20 +- .../app/browser/BrowserTabFragment.kt | 184 +++++++++++------- .../app/browser/ui/BottomNavigationBar.kt | 8 - .../app/statistics/VariantManager.kt | 6 - .../main/res/drawable/ic_share_black_24dp.xml | 25 +++ .../layout/layout_bottom_navigation_bar.xml | 32 +-- .../popup_window_browser_bottom_tab_menu.xml | 29 ++- app/src/main/res/values/styles.xml | 2 +- 8 files changed, 163 insertions(+), 143 deletions(-) create mode 100644 app/src/main/res/drawable/ic_share_black_24dp.xml diff --git a/app/src/main/java/com/duckduckgo/app/browser/BrowserPopupMenu.kt b/app/src/main/java/com/duckduckgo/app/browser/BrowserPopupMenu.kt index cc97baa90a19..df2e397455b7 100644 --- a/app/src/main/java/com/duckduckgo/app/browser/BrowserPopupMenu.kt +++ b/app/src/main/java/com/duckduckgo/app/browser/BrowserPopupMenu.kt @@ -62,18 +62,12 @@ class BrowserPopupMenu : PopupWindow { private const val margin = 30 fun inflate(layoutInflater: LayoutInflater, variant: Variant): View { - return inflateToolbarOnlyExperiment(layoutInflater) + return inflateBottomBarWithSearchExperiment(layoutInflater) - when { - variant.hasFeature(VariantManager.VariantFeature.BottomBarWithSearchExperiment) -> { - inflateBottomBarWithSearchExperiment(layoutInflater) - } - variant.hasFeature(VariantManager.VariantFeature.BottomBarWithNavigationExperiment) -> { - inflateBottomBarWithNavigationExperiment(layoutInflater) - } - else -> { - inflateToolbarOnlyExperiment(layoutInflater) - } + if (variant.hasFeature(VariantManager.VariantFeature.BottomBarWithSearchExperiment)){ + inflateBottomBarWithSearchExperiment(layoutInflater) + } else { + inflateToolbarOnlyExperiment(layoutInflater) } } @@ -81,10 +75,6 @@ class BrowserPopupMenu : PopupWindow { return layoutInflater.inflate(R.layout.popup_window_browser_menu, null) } - private fun inflateBottomBarWithNavigationExperiment(layoutInflater: LayoutInflater): View { - return layoutInflater.inflate(R.layout.popup_window_browser_bottom_navigation_menu, null) - } - private fun inflateBottomBarWithSearchExperiment(layoutInflater: LayoutInflater): View { return layoutInflater.inflate(R.layout.popup_window_browser_bottom_tab_menu, null) } diff --git a/app/src/main/java/com/duckduckgo/app/browser/BrowserTabFragment.kt b/app/src/main/java/com/duckduckgo/app/browser/BrowserTabFragment.kt index 3abef15c553f..9ca6e8662c37 100644 --- a/app/src/main/java/com/duckduckgo/app/browser/BrowserTabFragment.kt +++ b/app/src/main/java/com/duckduckgo/app/browser/BrowserTabFragment.kt @@ -23,20 +23,42 @@ import android.annotation.SuppressLint import android.app.Activity.RESULT_OK import android.app.ActivityOptions import android.appwidget.AppWidgetManager -import android.content.* +import android.content.ClipData +import android.content.ClipboardManager +import android.content.ComponentName +import android.content.Context +import android.content.Intent import android.content.pm.PackageManager import android.content.res.Configuration import android.media.MediaScannerConnection import android.net.Uri -import android.os.* +import android.os.Build +import android.os.Bundle +import android.os.Environment +import android.os.Handler +import android.os.Message import android.text.Editable -import android.view.* -import android.view.View.* +import android.view.ContextMenu +import android.view.KeyEvent +import android.view.LayoutInflater +import android.view.MenuItem +import android.view.View +import android.view.View.GONE +import android.view.View.OnFocusChangeListener +import android.view.View.VISIBLE +import android.view.View.inflate +import android.view.ViewGroup import android.view.inputmethod.EditorInfo -import android.webkit.* +import android.webkit.ValueCallback +import android.webkit.WebChromeClient +import android.webkit.WebSettings +import android.webkit.WebView import android.webkit.WebView.FindListener import android.webkit.WebView.HitTestResult -import android.webkit.WebView.HitTestResult.* +import android.webkit.WebView.HitTestResult.IMAGE_TYPE +import android.webkit.WebView.HitTestResult.SRC_IMAGE_ANCHOR_TYPE +import android.webkit.WebView.HitTestResult.UNKNOWN_TYPE +import android.webkit.WebViewDatabase import android.widget.EditText import android.widget.TextView import androidx.annotation.AnyThread @@ -51,12 +73,23 @@ import androidx.core.view.isVisible import androidx.core.view.postDelayed import androidx.fragment.app.DialogFragment import androidx.fragment.app.Fragment -import androidx.lifecycle.* +import androidx.lifecycle.Lifecycle +import androidx.lifecycle.LifecycleObserver +import androidx.lifecycle.Observer +import androidx.lifecycle.OnLifecycleEvent +import androidx.lifecycle.ViewModelProviders import androidx.recyclerview.widget.LinearLayoutManager import com.duckduckgo.app.autocomplete.api.AutoComplete.AutoCompleteSuggestion import com.duckduckgo.app.bookmarks.ui.EditBookmarkDialogFragment import com.duckduckgo.app.brokensite.BrokenSiteActivity -import com.duckduckgo.app.browser.BrowserTabViewModel.* +import com.duckduckgo.app.browser.BrowserTabViewModel.AutoCompleteViewState +import com.duckduckgo.app.browser.BrowserTabViewModel.BrowserViewState +import com.duckduckgo.app.browser.BrowserTabViewModel.Command +import com.duckduckgo.app.browser.BrowserTabViewModel.CtaViewState +import com.duckduckgo.app.browser.BrowserTabViewModel.FindInPageViewState +import com.duckduckgo.app.browser.BrowserTabViewModel.GlobalLayoutViewState +import com.duckduckgo.app.browser.BrowserTabViewModel.LoadingViewState +import com.duckduckgo.app.browser.BrowserTabViewModel.OmnibarViewState import com.duckduckgo.app.browser.autocomplete.BrowserAutoCompleteSuggestionsAdapter import com.duckduckgo.app.browser.downloader.FileDownloadNotificationManager import com.duckduckgo.app.browser.downloader.FileDownloader @@ -73,7 +106,13 @@ import com.duckduckgo.app.browser.tabpreview.WebViewPreviewGenerator import com.duckduckgo.app.browser.tabpreview.WebViewPreviewPersister import com.duckduckgo.app.browser.ui.HttpAuthenticationDialogFragment import com.duckduckgo.app.browser.useragent.UserAgentProvider -import com.duckduckgo.app.cta.ui.* +import com.duckduckgo.app.cta.ui.Cta +import com.duckduckgo.app.cta.ui.CtaViewModel +import com.duckduckgo.app.cta.ui.DaxBubbleCta +import com.duckduckgo.app.cta.ui.DaxDialogCta +import com.duckduckgo.app.cta.ui.HomePanelCta +import com.duckduckgo.app.cta.ui.HomeTopPanelCta +import com.duckduckgo.app.cta.ui.SecondaryButtonCta import com.duckduckgo.app.global.ViewModelFactory import com.duckduckgo.app.global.device.DeviceInfo import com.duckduckgo.app.global.view.* @@ -90,22 +129,46 @@ import com.duckduckgo.app.widget.ui.AddWidgetInstructionsActivity import com.duckduckgo.widget.SearchWidgetLight import com.google.android.material.snackbar.Snackbar import dagger.android.support.AndroidSupportInjection -import kotlinx.android.synthetic.main.fragment_browser_tab.* -import kotlinx.android.synthetic.main.include_cta_buttons.view.* -import kotlinx.android.synthetic.main.include_dax_dialog_cta.* -import kotlinx.android.synthetic.main.include_find_in_page.* -import kotlinx.android.synthetic.main.include_new_browser_tab.* +import kotlinx.android.synthetic.main.fragment_browser_tab.autoCompleteSuggestionsList +import kotlinx.android.synthetic.main.fragment_browser_tab.bottomNavigationBar +import kotlinx.android.synthetic.main.fragment_browser_tab.browserLayout +import kotlinx.android.synthetic.main.fragment_browser_tab.focusDummy +import kotlinx.android.synthetic.main.fragment_browser_tab.rootView +import kotlinx.android.synthetic.main.fragment_browser_tab.webViewContainer +import kotlinx.android.synthetic.main.fragment_browser_tab.webViewFullScreenContainer +import kotlinx.android.synthetic.main.include_cta_buttons.view.ctaDismissButton +import kotlinx.android.synthetic.main.include_cta_buttons.view.ctaOkButton +import kotlinx.android.synthetic.main.include_dax_dialog_cta.daxCtaContainer +import kotlinx.android.synthetic.main.include_dax_dialog_cta.dialogTextCta +import kotlinx.android.synthetic.main.include_find_in_page.closeFindInPagePanel +import kotlinx.android.synthetic.main.include_find_in_page.findInPageContainer +import kotlinx.android.synthetic.main.include_find_in_page.findInPageInput +import kotlinx.android.synthetic.main.include_find_in_page.findInPageMatches +import kotlinx.android.synthetic.main.include_find_in_page.nextSearchTermButton +import kotlinx.android.synthetic.main.include_find_in_page.previousSearchTermButton +import kotlinx.android.synthetic.main.include_new_browser_tab.ctaContainer +import kotlinx.android.synthetic.main.include_new_browser_tab.ctaTopContainer +import kotlinx.android.synthetic.main.include_new_browser_tab.ddgLogo +import kotlinx.android.synthetic.main.include_new_browser_tab.newTabLayout import kotlinx.android.synthetic.main.include_omnibar_toolbar.* -import kotlinx.android.synthetic.main.include_omnibar_toolbar.view.* -import kotlinx.android.synthetic.main.include_top_cta.view.* -import kotlinx.android.synthetic.main.layout_bottom_navigation_bar.bottomBarBackItem +import kotlinx.android.synthetic.main.include_omnibar_toolbar.view.browserMenu +import kotlinx.android.synthetic.main.include_omnibar_toolbar.view.privacyGradeButton +import kotlinx.android.synthetic.main.include_top_cta.view.closeButton import kotlinx.android.synthetic.main.layout_bottom_navigation_bar.bottomBarBookmarksItemOne -import kotlinx.android.synthetic.main.layout_bottom_navigation_bar.bottomBarBookmarksItemTwo import kotlinx.android.synthetic.main.layout_bottom_navigation_bar.bottomBarFireItem -import kotlinx.android.synthetic.main.layout_bottom_navigation_bar.bottomBarForwardItem +import kotlinx.android.synthetic.main.layout_bottom_navigation_bar.bottomBarOverflowItem +import kotlinx.android.synthetic.main.layout_bottom_navigation_bar.bottomBarSearchItem import kotlinx.android.synthetic.main.layout_bottom_navigation_bar.bottomBarTabsItem +import kotlinx.android.synthetic.main.popup_window_browser_bottom_tab_menu.view.sharePopupMenuItem import kotlinx.android.synthetic.main.popup_window_browser_menu.view.* -import kotlinx.coroutines.* +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.GlobalScope +import kotlinx.coroutines.Job +import kotlinx.coroutines.SupervisorJob +import kotlinx.coroutines.delay +import kotlinx.coroutines.launch +import kotlinx.coroutines.withContext import org.jetbrains.anko.longToast import org.jetbrains.anko.share import timber.log.Timber @@ -661,21 +724,14 @@ class BrowserTabFragment : Fragment(), FindListener, CoroutineScope { } private fun decorateWithExperiments() { - when { - variantManager.getVariant().hasFeature(VariantManager.VariantFeature.BottomBarWithNavigationExperiment) -> { - decorator.decorateWithBottomBarNavigationExperiment() - } - variantManager.getVariant().hasFeature(VariantManager.VariantFeature.BottomBarWithSearchExperiment) -> { - decorator.decorateWithBottomBarSearchExperiment() - } - else -> { - decorator.decorateWithToolbarOnlyExperiment() - } + if (variantManager.getVariant().hasFeature(VariantManager.VariantFeature.BottomBarWithSearchExperiment)) { + decorator.decorateWithBottomBarSearchExperiment() + } else { + decorator.decorateWithToolbarOnlyExperiment() } } private fun configureAppBar() { - toolbar.privacyGradeButton.setOnClickListener { browserActivity?.launchPrivacyDashboard() } @@ -1115,18 +1171,11 @@ class BrowserTabFragment : Fragment(), FindListener, CoroutineScope { } inner class BrowserTabFragmentExperimentDecorator { - fun decorateToolbarMenus(viewState: BrowserViewState) { - when { - variantManager.getVariant().hasFeature(VariantManager.VariantFeature.BottomBarWithNavigationExperiment) -> { - decorator.hideToolbarMenu() - } - variantManager.getVariant().hasFeature(VariantManager.VariantFeature.BottomBarWithSearchExperiment) -> { - decorator.hideToolbarMenu() - } - else -> { - decorator.decorateToolbarMenu(viewState) - } + if (variantManager.getVariant().hasFeature(VariantManager.VariantFeature.BottomBarWithSearchExperiment)) { + decorator.hideToolbarMenu() + } else { + decorator.decorateToolbarMenu(viewState) } } @@ -1151,15 +1200,7 @@ class BrowserTabFragment : Fragment(), FindListener, CoroutineScope { fun decorateWithBottomBarSearchExperiment() { decorateBottomBarWithNavigationOnlyExperiment() decorateAppBarWithBottomBarExperiment() - createPopupMenuWithToolbarOnlyExperiment() - configureShowTabSwitcherListenerWithBottomBarNavigationOnlyExperiment() - configureLongClickOpensNewTabListenerWithBottomBarNavigationOnlyExperiment() - } - - fun decorateWithBottomBarNavigationExperiment() { - decorateBottomBarWithBottomBarAndToolbarExperiment() - decorateAppBarWithBottomBarExperiment() - createPopupMenuWithToolbarOnlyExperiment() + createPopupMenuWithBottomBarExperiment() configureShowTabSwitcherListenerWithBottomBarNavigationOnlyExperiment() configureLongClickOpensNewTabListenerWithBottomBarNavigationOnlyExperiment() } @@ -1200,7 +1241,7 @@ class BrowserTabFragment : Fragment(), FindListener, CoroutineScope { } browserMenu.setOnClickListener { hideKeyboardImmediately() - launchBottomAnchoredPopupMenu() + launchTopAnchoredPopupMenu() } } @@ -1208,6 +1249,24 @@ class BrowserTabFragment : Fragment(), FindListener, CoroutineScope { popupMenu.show(rootView, toolbar) } + private fun createPopupMenuWithBottomBarExperiment() { + popupMenu = BrowserPopupMenu(layoutInflater, variantManager.getVariant()) + val view = popupMenu.contentView + popupMenu.apply { + onMenuItemClicked(view.forwardPopupMenuItem) { viewModel.onUserPressedForward() } + onMenuItemClicked(view.backPopupMenuItem) { activity?.onBackPressed() } + onMenuItemClicked(view.refreshPopupMenuItem) { viewModel.onRefreshRequested() } + onMenuItemClicked(view.sharePopupMenuItem) { viewModel.onShareSelected() } + onMenuItemClicked(view.newTabPopupMenuItem) { viewModel.userRequestedOpeningNewTab() } + onMenuItemClicked(view.addBookmarksPopupMenuItem) { launch { viewModel.onBookmarkAddRequested() } } + onMenuItemClicked(view.findInPageMenuItem) { viewModel.onFindInPageSelected() } + onMenuItemClicked(view.brokenSitePopupMenuItem) { viewModel.onBrokenSiteSelected() } + onMenuItemClicked(view.settingsPopupMenuItem) { browserActivity?.launchSettings() } + onMenuItemClicked(view.requestDesktopSiteCheckMenuItem) { viewModel.onDesktopSiteModeToggled(view.requestDesktopSiteCheckMenuItem.isChecked) } + onMenuItemClicked(view.addToHome) { viewModel.onPinPageToHomeSelected() } + } + } + private fun launchBottomAnchoredPopupMenu() { popupMenu.show(rootView, bottomNavigationBar) } @@ -1216,17 +1275,16 @@ class BrowserTabFragment : Fragment(), FindListener, CoroutineScope { bindBottomBarButtons() } - private fun decorateBottomBarWithBottomBarAndToolbarExperiment() { - bindBottomBarButtons() - } - private fun bindBottomBarButtons() { bottomNavigationBar.apply { - onItemClicked(bottomBarBackItem) { activity?.onBackPressed() } - onItemClicked(bottomBarForwardItem) { viewModel.onUserPressedForward() } onItemClicked(bottomBarFireItem) { browserActivity?.launchFire() } - onItemClicked(bottomBarBookmarksItemOne) { launch { viewModel.onBookmarkAddRequested() } } - onItemClicked(bottomBarBookmarksItemTwo) { launch { viewModel.onBookmarkAddRequested() } } + onItemClicked(bottomBarBookmarksItemOne) { browserActivity?.launchBookmarks() } + onItemClicked(bottomBarSearchItem) { browserActivity?.launchBookmarks() } + onItemClicked(bottomBarTabsItem) { viewModel.userLaunchingTabSwitcher() } + onItemClicked(bottomBarOverflowItem) { + hideKeyboardImmediately() + launchBottomAnchoredPopupMenu() + } } } @@ -1399,7 +1457,6 @@ class BrowserTabFragment : Fragment(), FindListener, CoroutineScope { toggleDesktopSiteMode(viewState.isDesktopBrowsingMode) renderToolbarMenus(viewState) - renderBottomBar(viewState) renderPopupMenus(browserShowing, viewState) renderFullscreenMode(viewState) } @@ -1415,11 +1472,6 @@ class BrowserTabFragment : Fragment(), FindListener, CoroutineScope { } } - private fun renderBottomBar(viewState: BrowserViewState) { - bottomBarForwardItem.isEnabled = viewState.canGoForward - bottomBarBackItem.isEnabled = viewState.canGoBack - } - private fun renderPopupMenus(browserShowing: Boolean, viewState: BrowserViewState) { popupMenu.contentView.apply { backPopupMenuItem.isEnabled = viewState.canGoBack diff --git a/app/src/main/java/com/duckduckgo/app/browser/ui/BottomNavigationBar.kt b/app/src/main/java/com/duckduckgo/app/browser/ui/BottomNavigationBar.kt index 1bd7af4e70ce..84124c1b22e3 100644 --- a/app/src/main/java/com/duckduckgo/app/browser/ui/BottomNavigationBar.kt +++ b/app/src/main/java/com/duckduckgo/app/browser/ui/BottomNavigationBar.kt @@ -40,12 +40,4 @@ class BottomNavigationBar @JvmOverloads constructor( } } - fun decorateExperimentOne(){ - - } - - fun decorateExperimentTwo(){ - - } - } \ No newline at end of file diff --git a/app/src/main/java/com/duckduckgo/app/statistics/VariantManager.kt b/app/src/main/java/com/duckduckgo/app/statistics/VariantManager.kt index 2b776f12a1d0..244112ec640f 100644 --- a/app/src/main/java/com/duckduckgo/app/statistics/VariantManager.kt +++ b/app/src/main/java/com/duckduckgo/app/statistics/VariantManager.kt @@ -31,7 +31,6 @@ interface VariantManager { sealed class VariantFeature { object StickySearchNotification : VariantFeature() object BottomBarWithSearchExperiment : VariantFeature() - object BottomBarWithNavigationExperiment : VariantFeature() } companion object { @@ -64,11 +63,6 @@ interface VariantManager { key = "mm", weight = 1.0, features = listOf(BottomBarWithSearchExperiment), - filterBy = { isEnglishLocale() }), - Variant( - key = "mn", - weight = 0.0, - features = listOf(BottomBarWithNavigationExperiment), filterBy = { isEnglishLocale() }) // All groups in an experiment (control and variants) MUST use the same filters diff --git a/app/src/main/res/drawable/ic_share_black_24dp.xml b/app/src/main/res/drawable/ic_share_black_24dp.xml new file mode 100644 index 000000000000..09aeef1c3893 --- /dev/null +++ b/app/src/main/res/drawable/ic_share_black_24dp.xml @@ -0,0 +1,25 @@ + + + + + diff --git a/app/src/main/res/layout/layout_bottom_navigation_bar.xml b/app/src/main/res/layout/layout_bottom_navigation_bar.xml index 526ea310052f..d60f4a0fbade 100644 --- a/app/src/main/res/layout/layout_bottom_navigation_bar.xml +++ b/app/src/main/res/layout/layout_bottom_navigation_bar.xml @@ -19,17 +19,7 @@ tools:parentTag="android.widget.LinearLayout"> - - - - - - - - - - + android:src="@drawable/ic_arrow_back_24dp" /> + + + - - + android:src="@drawable/ic_share_black_24dp" /> - \ No newline at end of file diff --git a/app/src/main/res/values/styles.xml b/app/src/main/res/values/styles.xml index 1cfbe02bfc78..279007f55ce8 100644 --- a/app/src/main/res/values/styles.xml +++ b/app/src/main/res/values/styles.xml @@ -149,7 +149,7 @@ From ea3022a0c5836857db48404540c2563f1c8d6b49 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Gonz=C3=A1lez?= Date: Fri, 3 Apr 2020 14:49:31 +0200 Subject: [PATCH 026/104] added new icons for bottom bar and popup menu --- .../app/browser/BrowserTabFragment.kt | 2 +- .../app/global/DuckDuckGoActivity.kt | 2 ++ .../app/tabs/ui/TabSwitcherActivity.kt | 1 + app/src/main/res/drawable/ic_back.xml | 25 ++++++++++++++++++ .../res/drawable/ic_bottom_bar_bookmarks.xml | 26 +++++++++++++++++++ .../res/drawable/ic_bottom_bar_refresh.xml | 25 ++++++++++++++++++ app/src/main/res/drawable/ic_close.xml | 25 ++++++++++++++++++ app/src/main/res/drawable/ic_forward.xml | 25 ++++++++++++++++++ app/src/main/res/drawable/ic_newtab.xml | 25 ++++++++++++++++++ app/src/main/res/drawable/ic_share.xml | 26 +++++++++++++++++++ app/src/main/res/drawable/ic_tabs.xml | 26 +++++++++++++++++++ .../res/layout/include_omnibar_toolbar.xml | 4 +-- .../layout/layout_bottom_navigation_bar.xml | 2 +- .../popup_window_browser_bottom_tab_menu.xml | 9 +++---- .../res/layout/popup_window_browser_menu.xml | 6 ++--- 15 files changed, 217 insertions(+), 12 deletions(-) create mode 100644 app/src/main/res/drawable/ic_back.xml create mode 100644 app/src/main/res/drawable/ic_bottom_bar_bookmarks.xml create mode 100644 app/src/main/res/drawable/ic_bottom_bar_refresh.xml create mode 100644 app/src/main/res/drawable/ic_close.xml create mode 100644 app/src/main/res/drawable/ic_forward.xml create mode 100644 app/src/main/res/drawable/ic_newtab.xml create mode 100644 app/src/main/res/drawable/ic_share.xml create mode 100644 app/src/main/res/drawable/ic_tabs.xml diff --git a/app/src/main/java/com/duckduckgo/app/browser/BrowserTabFragment.kt b/app/src/main/java/com/duckduckgo/app/browser/BrowserTabFragment.kt index 9ca6e8662c37..d527e1fcb937 100644 --- a/app/src/main/java/com/duckduckgo/app/browser/BrowserTabFragment.kt +++ b/app/src/main/java/com/duckduckgo/app/browser/BrowserTabFragment.kt @@ -1279,7 +1279,7 @@ class BrowserTabFragment : Fragment(), FindListener, CoroutineScope { bottomNavigationBar.apply { onItemClicked(bottomBarFireItem) { browserActivity?.launchFire() } onItemClicked(bottomBarBookmarksItemOne) { browserActivity?.launchBookmarks() } - onItemClicked(bottomBarSearchItem) { browserActivity?.launchBookmarks() } + onItemClicked(bottomBarSearchItem) { omnibarTextInput.requestFocus() } onItemClicked(bottomBarTabsItem) { viewModel.userLaunchingTabSwitcher() } onItemClicked(bottomBarOverflowItem) { hideKeyboardImmediately() diff --git a/app/src/main/java/com/duckduckgo/app/global/DuckDuckGoActivity.kt b/app/src/main/java/com/duckduckgo/app/global/DuckDuckGoActivity.kt index 91f28d1b3a42..b3ae859b6c6d 100644 --- a/app/src/main/java/com/duckduckgo/app/global/DuckDuckGoActivity.kt +++ b/app/src/main/java/com/duckduckgo/app/global/DuckDuckGoActivity.kt @@ -24,8 +24,10 @@ import androidx.appcompat.app.AppCompatActivity import androidx.lifecycle.ViewModel import androidx.lifecycle.ViewModelProviders import androidx.localbroadcastmanager.content.LocalBroadcastManager +import com.duckduckgo.app.browser.R import com.duckduckgo.app.settings.db.SettingsDataStore import dagger.android.AndroidInjection +import kotlinx.android.synthetic.main.include_toolbar.toolbar import javax.inject.Inject diff --git a/app/src/main/java/com/duckduckgo/app/tabs/ui/TabSwitcherActivity.kt b/app/src/main/java/com/duckduckgo/app/tabs/ui/TabSwitcherActivity.kt index c99b83f17211..cab5445a242f 100644 --- a/app/src/main/java/com/duckduckgo/app/tabs/ui/TabSwitcherActivity.kt +++ b/app/src/main/java/com/duckduckgo/app/tabs/ui/TabSwitcherActivity.kt @@ -38,6 +38,7 @@ import com.duckduckgo.app.tabs.model.TabEntity import com.duckduckgo.app.tabs.ui.TabSwitcherViewModel.Command import com.duckduckgo.app.tabs.ui.TabSwitcherViewModel.Command.Close import com.duckduckgo.app.tabs.ui.TabSwitcherViewModel.Command.DisplayMessage +import kotlinx.android.synthetic.main.include_omnibar_toolbar.toolbar import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.SupervisorJob diff --git a/app/src/main/res/drawable/ic_back.xml b/app/src/main/res/drawable/ic_back.xml new file mode 100644 index 000000000000..1d48d2bedc38 --- /dev/null +++ b/app/src/main/res/drawable/ic_back.xml @@ -0,0 +1,25 @@ + + + + + diff --git a/app/src/main/res/drawable/ic_bottom_bar_bookmarks.xml b/app/src/main/res/drawable/ic_bottom_bar_bookmarks.xml new file mode 100644 index 000000000000..b21ad2f25f1b --- /dev/null +++ b/app/src/main/res/drawable/ic_bottom_bar_bookmarks.xml @@ -0,0 +1,26 @@ + + + + + diff --git a/app/src/main/res/drawable/ic_bottom_bar_refresh.xml b/app/src/main/res/drawable/ic_bottom_bar_refresh.xml new file mode 100644 index 000000000000..98a71f5f56eb --- /dev/null +++ b/app/src/main/res/drawable/ic_bottom_bar_refresh.xml @@ -0,0 +1,25 @@ + + + + + diff --git a/app/src/main/res/drawable/ic_close.xml b/app/src/main/res/drawable/ic_close.xml new file mode 100644 index 000000000000..1ef78847614f --- /dev/null +++ b/app/src/main/res/drawable/ic_close.xml @@ -0,0 +1,25 @@ + + + + + diff --git a/app/src/main/res/drawable/ic_forward.xml b/app/src/main/res/drawable/ic_forward.xml new file mode 100644 index 000000000000..5a10bc088f03 --- /dev/null +++ b/app/src/main/res/drawable/ic_forward.xml @@ -0,0 +1,25 @@ + + + + + diff --git a/app/src/main/res/drawable/ic_newtab.xml b/app/src/main/res/drawable/ic_newtab.xml new file mode 100644 index 000000000000..57f9b295b6b3 --- /dev/null +++ b/app/src/main/res/drawable/ic_newtab.xml @@ -0,0 +1,25 @@ + + + + + diff --git a/app/src/main/res/drawable/ic_share.xml b/app/src/main/res/drawable/ic_share.xml new file mode 100644 index 000000000000..85d63158e24f --- /dev/null +++ b/app/src/main/res/drawable/ic_share.xml @@ -0,0 +1,26 @@ + + + + + diff --git a/app/src/main/res/drawable/ic_tabs.xml b/app/src/main/res/drawable/ic_tabs.xml new file mode 100644 index 000000000000..70e0b284a284 --- /dev/null +++ b/app/src/main/res/drawable/ic_tabs.xml @@ -0,0 +1,26 @@ + + + + + diff --git a/app/src/main/res/layout/include_omnibar_toolbar.xml b/app/src/main/res/layout/include_omnibar_toolbar.xml index a5de54c2242b..fe29078fa95e 100644 --- a/app/src/main/res/layout/include_omnibar_toolbar.xml +++ b/app/src/main/res/layout/include_omnibar_toolbar.xml @@ -98,7 +98,7 @@ android:paddingStart="8dp" android:paddingEnd="8dp" android:background="@drawable/omnibar_field_background" - android:fontFamily="sans-serif-medium" + android:fontFamily="sans-serif" android:hint="@string/omnibarInputHint" android:imeOptions="flagNoExtractUi|actionGo|flagNoPersonalizedLearning" android:inputType="textUri|textNoSuggestions" @@ -107,7 +107,7 @@ android:textColor="?attr/omnibarTextColor" android:textColorHint="?attr/omnibarHintColor" android:textCursorDrawable="@drawable/text_cursor" - android:textSize="13sp" + android:textSize="16sp" android:textStyle="normal" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toStartOf="@id/clearTextButton" diff --git a/app/src/main/res/layout/layout_bottom_navigation_bar.xml b/app/src/main/res/layout/layout_bottom_navigation_bar.xml index d60f4a0fbade..58f3ddb98c8a 100644 --- a/app/src/main/res/layout/layout_bottom_navigation_bar.xml +++ b/app/src/main/res/layout/layout_bottom_navigation_bar.xml @@ -36,7 +36,7 @@ android:layout_weight="1" android:background="?selectableItemBackgroundBorderless" android:contentDescription="@string/back" - android:src="@drawable/ic_bookmarks_black_24dp" /> + android:src="@drawable/ic_bottom_bar_bookmarks" /> + android:src="@drawable/ic_back" /> + android:src="@drawable/ic_forward" /> - + android:src="@drawable/ic_bottom_bar_refresh" /> + android:src="@drawable/ic_share" /> diff --git a/app/src/main/res/layout/popup_window_browser_menu.xml b/app/src/main/res/layout/popup_window_browser_menu.xml index cf30740ddd16..cc0bf509c63c 100644 --- a/app/src/main/res/layout/popup_window_browser_menu.xml +++ b/app/src/main/res/layout/popup_window_browser_menu.xml @@ -38,7 +38,7 @@ android:layout_height="wrap_content" android:layout_weight="1" android:contentDescription="@string/back" - android:src="@drawable/ic_arrow_back_24dp" /> + android:src="@drawable/ic_back" /> + android:src="@drawable/ic_forward" /> + android:src="@drawable/ic_bottom_bar_refresh" /> From 03826b005f02f12890dbbe904975c7b808307ccc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Gonz=C3=A1lez?= Date: Fri, 3 Apr 2020 15:15:16 +0200 Subject: [PATCH 027/104] popup menu now also respect light / dark theme --- .../main/java/com/duckduckgo/app/browser/BrowserPopupMenu.kt | 4 +--- app/src/main/res/drawable/ic_back.xml | 2 +- app/src/main/res/drawable/ic_bottom_bar_bookmarks.xml | 2 +- app/src/main/res/drawable/ic_bottom_bar_refresh.xml | 2 +- app/src/main/res/drawable/ic_fire_black_24dp.xml | 2 +- app/src/main/res/drawable/ic_forward.xml | 2 +- app/src/main/res/drawable/ic_overflow_bookmarks_24dp.xml | 2 +- app/src/main/res/drawable/ic_search_black_24dp.xml | 2 +- app/src/main/res/drawable/ic_share.xml | 2 +- app/src/main/res/layout/fragment_browser_tab.xml | 2 +- .../main/res/layout/popup_window_browser_bottom_tab_menu.xml | 3 +-- app/src/main/res/layout/popup_window_browser_menu.xml | 3 +-- app/src/main/res/values/styles.xml | 2 +- 13 files changed, 13 insertions(+), 17 deletions(-) diff --git a/app/src/main/java/com/duckduckgo/app/browser/BrowserPopupMenu.kt b/app/src/main/java/com/duckduckgo/app/browser/BrowserPopupMenu.kt index df2e397455b7..2b6b21a37006 100644 --- a/app/src/main/java/com/duckduckgo/app/browser/BrowserPopupMenu.kt +++ b/app/src/main/java/com/duckduckgo/app/browser/BrowserPopupMenu.kt @@ -62,9 +62,7 @@ class BrowserPopupMenu : PopupWindow { private const val margin = 30 fun inflate(layoutInflater: LayoutInflater, variant: Variant): View { - return inflateBottomBarWithSearchExperiment(layoutInflater) - - if (variant.hasFeature(VariantManager.VariantFeature.BottomBarWithSearchExperiment)){ + return if (variant.hasFeature(VariantManager.VariantFeature.BottomBarWithSearchExperiment)){ inflateBottomBarWithSearchExperiment(layoutInflater) } else { inflateToolbarOnlyExperiment(layoutInflater) diff --git a/app/src/main/res/drawable/ic_back.xml b/app/src/main/res/drawable/ic_back.xml index 1d48d2bedc38..04f12f5105df 100644 --- a/app/src/main/res/drawable/ic_back.xml +++ b/app/src/main/res/drawable/ic_back.xml @@ -21,5 +21,5 @@ android:viewportHeight="24"> + android:fillColor="?attr/toolbarIconColor"/> diff --git a/app/src/main/res/drawable/ic_bottom_bar_bookmarks.xml b/app/src/main/res/drawable/ic_bottom_bar_bookmarks.xml index b21ad2f25f1b..7b8c3e4f899e 100644 --- a/app/src/main/res/drawable/ic_bottom_bar_bookmarks.xml +++ b/app/src/main/res/drawable/ic_bottom_bar_bookmarks.xml @@ -21,6 +21,6 @@ android:viewportHeight="24"> diff --git a/app/src/main/res/drawable/ic_bottom_bar_refresh.xml b/app/src/main/res/drawable/ic_bottom_bar_refresh.xml index 98a71f5f56eb..9f790eaaeb31 100644 --- a/app/src/main/res/drawable/ic_bottom_bar_refresh.xml +++ b/app/src/main/res/drawable/ic_bottom_bar_refresh.xml @@ -21,5 +21,5 @@ android:viewportHeight="24"> + android:fillColor="?attr/toolbarIconColor"/> diff --git a/app/src/main/res/drawable/ic_fire_black_24dp.xml b/app/src/main/res/drawable/ic_fire_black_24dp.xml index f7b42ae701e3..2726e6a03516 100644 --- a/app/src/main/res/drawable/ic_fire_black_24dp.xml +++ b/app/src/main/res/drawable/ic_fire_black_24dp.xml @@ -20,6 +20,6 @@ android:viewportWidth="24" android:viewportHeight="24"> \ No newline at end of file diff --git a/app/src/main/res/drawable/ic_forward.xml b/app/src/main/res/drawable/ic_forward.xml index 5a10bc088f03..a0f76e510efc 100644 --- a/app/src/main/res/drawable/ic_forward.xml +++ b/app/src/main/res/drawable/ic_forward.xml @@ -21,5 +21,5 @@ android:viewportHeight="24"> + android:fillColor="?attr/toolbarIconColor"/> diff --git a/app/src/main/res/drawable/ic_overflow_bookmarks_24dp.xml b/app/src/main/res/drawable/ic_overflow_bookmarks_24dp.xml index 83ac3a8ec093..e13682fe200a 100644 --- a/app/src/main/res/drawable/ic_overflow_bookmarks_24dp.xml +++ b/app/src/main/res/drawable/ic_overflow_bookmarks_24dp.xml @@ -20,6 +20,6 @@ android:viewportWidth="24.0" android:viewportHeight="24.0"> diff --git a/app/src/main/res/drawable/ic_search_black_24dp.xml b/app/src/main/res/drawable/ic_search_black_24dp.xml index 57b7762c6332..4289c8f4a1ce 100644 --- a/app/src/main/res/drawable/ic_search_black_24dp.xml +++ b/app/src/main/res/drawable/ic_search_black_24dp.xml @@ -20,6 +20,6 @@ android:viewportWidth="24.0" android:viewportHeight="24.0"> diff --git a/app/src/main/res/drawable/ic_share.xml b/app/src/main/res/drawable/ic_share.xml index 85d63158e24f..ec43a54705d0 100644 --- a/app/src/main/res/drawable/ic_share.xml +++ b/app/src/main/res/drawable/ic_share.xml @@ -21,6 +21,6 @@ android:viewportHeight="24"> diff --git a/app/src/main/res/layout/fragment_browser_tab.xml b/app/src/main/res/layout/fragment_browser_tab.xml index 55dd5c3e00a0..1915b39845bd 100644 --- a/app/src/main/res/layout/fragment_browser_tab.xml +++ b/app/src/main/res/layout/fragment_browser_tab.xml @@ -28,7 +28,7 @@ android:layout_width="match_parent" android:layout_height="48dp" android:layout_gravity="bottom" - android:background="@color/white" + android:background="?attr/colorPrimary" android:elevation="8dp" android:gravity="center" android:orientation="horizontal" diff --git a/app/src/main/res/layout/popup_window_browser_bottom_tab_menu.xml b/app/src/main/res/layout/popup_window_browser_bottom_tab_menu.xml index 0a7664dbd8c8..79dac0416c1e 100644 --- a/app/src/main/res/layout/popup_window_browser_bottom_tab_menu.xml +++ b/app/src/main/res/layout/popup_window_browser_bottom_tab_menu.xml @@ -18,7 +18,7 @@ xmlns:app="http://schemas.android.com/apk/res-auto" android:layout_width="match_parent" android:layout_height="wrap_content" - android:background="@color/white"> + android:background="?attr/colorPrimary"> + android:background="?attr/colorPrimary"> normal match_parent wrap_content - @color/browser_menu_text + ?attr/omnibarTextColor ?attr/selectableItemBackground @color/browser_menu_text From 8c624e31668ecc3bafaef32398ed50054af72591 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Gonz=C3=A1lez?= Date: Fri, 3 Apr 2020 15:32:07 +0200 Subject: [PATCH 028/104] using new color attribute for dark / light theme --- .../color/bottom_bar_icon_color_selector.xml | 21 +++++++++++++++ app/src/main/res/drawable/ic_back.xml | 2 +- .../res/drawable/ic_bottom_bar_bookmarks.xml | 2 +- .../res/drawable/ic_bottom_bar_refresh.xml | 2 +- .../main/res/drawable/ic_fire_black_24dp.xml | 2 +- app/src/main/res/drawable/ic_forward.xml | 2 +- .../drawable/ic_overflow_bookmarks_24dp.xml | 2 +- app/src/main/res/drawable/ic_search.xml | 26 +++++++++++++++++++ .../res/drawable/ic_search_black_24dp.xml | 2 +- app/src/main/res/drawable/ic_share.xml | 2 +- .../layout/layout_bottom_navigation_bar.xml | 2 +- app/src/main/res/values/attrs.xml | 2 ++ app/src/main/res/values/themes.xml | 6 +++++ 13 files changed, 64 insertions(+), 9 deletions(-) create mode 100644 app/src/main/res/color/bottom_bar_icon_color_selector.xml create mode 100644 app/src/main/res/drawable/ic_search.xml diff --git a/app/src/main/res/color/bottom_bar_icon_color_selector.xml b/app/src/main/res/color/bottom_bar_icon_color_selector.xml new file mode 100644 index 000000000000..c3ed2581bcec --- /dev/null +++ b/app/src/main/res/color/bottom_bar_icon_color_selector.xml @@ -0,0 +1,21 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/ic_back.xml b/app/src/main/res/drawable/ic_back.xml index 04f12f5105df..ce34fa83272e 100644 --- a/app/src/main/res/drawable/ic_back.xml +++ b/app/src/main/res/drawable/ic_back.xml @@ -21,5 +21,5 @@ android:viewportHeight="24"> + android:fillColor="@color/bottom_bar_icon_color_selector"/> diff --git a/app/src/main/res/drawable/ic_bottom_bar_bookmarks.xml b/app/src/main/res/drawable/ic_bottom_bar_bookmarks.xml index 7b8c3e4f899e..8c4663b6fab6 100644 --- a/app/src/main/res/drawable/ic_bottom_bar_bookmarks.xml +++ b/app/src/main/res/drawable/ic_bottom_bar_bookmarks.xml @@ -21,6 +21,6 @@ android:viewportHeight="24"> diff --git a/app/src/main/res/drawable/ic_bottom_bar_refresh.xml b/app/src/main/res/drawable/ic_bottom_bar_refresh.xml index 9f790eaaeb31..d24b16a5d4a5 100644 --- a/app/src/main/res/drawable/ic_bottom_bar_refresh.xml +++ b/app/src/main/res/drawable/ic_bottom_bar_refresh.xml @@ -21,5 +21,5 @@ android:viewportHeight="24"> + android:fillColor="@color/bottom_bar_icon_color_selector"/> diff --git a/app/src/main/res/drawable/ic_fire_black_24dp.xml b/app/src/main/res/drawable/ic_fire_black_24dp.xml index 2726e6a03516..7811efe4484c 100644 --- a/app/src/main/res/drawable/ic_fire_black_24dp.xml +++ b/app/src/main/res/drawable/ic_fire_black_24dp.xml @@ -20,6 +20,6 @@ android:viewportWidth="24" android:viewportHeight="24"> \ No newline at end of file diff --git a/app/src/main/res/drawable/ic_forward.xml b/app/src/main/res/drawable/ic_forward.xml index a0f76e510efc..2ccd5ffe53e2 100644 --- a/app/src/main/res/drawable/ic_forward.xml +++ b/app/src/main/res/drawable/ic_forward.xml @@ -21,5 +21,5 @@ android:viewportHeight="24"> + android:fillColor="@color/bottom_bar_icon_color_selector"/> diff --git a/app/src/main/res/drawable/ic_overflow_bookmarks_24dp.xml b/app/src/main/res/drawable/ic_overflow_bookmarks_24dp.xml index e13682fe200a..bf80a21a811e 100644 --- a/app/src/main/res/drawable/ic_overflow_bookmarks_24dp.xml +++ b/app/src/main/res/drawable/ic_overflow_bookmarks_24dp.xml @@ -20,6 +20,6 @@ android:viewportWidth="24.0" android:viewportHeight="24.0"> diff --git a/app/src/main/res/drawable/ic_search.xml b/app/src/main/res/drawable/ic_search.xml new file mode 100644 index 000000000000..5b9324089eeb --- /dev/null +++ b/app/src/main/res/drawable/ic_search.xml @@ -0,0 +1,26 @@ + + + + + diff --git a/app/src/main/res/drawable/ic_search_black_24dp.xml b/app/src/main/res/drawable/ic_search_black_24dp.xml index 4289c8f4a1ce..ae26de2f1a9b 100644 --- a/app/src/main/res/drawable/ic_search_black_24dp.xml +++ b/app/src/main/res/drawable/ic_search_black_24dp.xml @@ -20,6 +20,6 @@ android:viewportWidth="24.0" android:viewportHeight="24.0"> diff --git a/app/src/main/res/drawable/ic_share.xml b/app/src/main/res/drawable/ic_share.xml index ec43a54705d0..a9265a9069bb 100644 --- a/app/src/main/res/drawable/ic_share.xml +++ b/app/src/main/res/drawable/ic_share.xml @@ -21,6 +21,6 @@ android:viewportHeight="24"> diff --git a/app/src/main/res/layout/layout_bottom_navigation_bar.xml b/app/src/main/res/layout/layout_bottom_navigation_bar.xml index 58f3ddb98c8a..86ecd424801e 100644 --- a/app/src/main/res/layout/layout_bottom_navigation_bar.xml +++ b/app/src/main/res/layout/layout_bottom_navigation_bar.xml @@ -26,7 +26,7 @@ android:layout_weight="1" android:background="?selectableItemBackgroundBorderless" android:contentDescription="@string/back" - android:src="@drawable/ic_search_black_24dp" /> + android:src="@drawable/ic_search" /> + + diff --git a/app/src/main/res/values/themes.xml b/app/src/main/res/values/themes.xml index b4290a7d1f16..02921c733545 100644 --- a/app/src/main/res/values/themes.xml +++ b/app/src/main/res/values/themes.xml @@ -80,6 +80,9 @@ @color/almostBlack @color/grayish + @color/white + @color/midGray + From 3a6bd90ed7c1c25b8e81bc0355b89bd28310c74f Mon Sep 17 00:00:00 2001 From: David Gonzalez Date: Thu, 9 Apr 2020 11:51:59 +0200 Subject: [PATCH 040/104] Update popup_window_browser_bottom_tab_menu.xml checkbox should also be tinted --- app/src/main/res/layout/popup_window_browser_bottom_tab_menu.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/app/src/main/res/layout/popup_window_browser_bottom_tab_menu.xml b/app/src/main/res/layout/popup_window_browser_bottom_tab_menu.xml index 75eed70b73d4..acc26b3a4ffb 100644 --- a/app/src/main/res/layout/popup_window_browser_bottom_tab_menu.xml +++ b/app/src/main/res/layout/popup_window_browser_bottom_tab_menu.xml @@ -73,6 +73,7 @@ android:drawablePadding="30dp" android:paddingStart="30dp" android:paddingEnd="0dp" + android:drawableTint="@color/browser_menu_icon" android:text="@string/requestDesktopSiteMenuTitle" /> Date: Thu, 9 Apr 2020 13:06:57 +0200 Subject: [PATCH 041/104] all toolbars should be the same --- .../app/about/AboutDuckDuckGoActivity.kt | 7 +------ .../app/bookmarks/ui/BookmarksActivity.kt | 8 +------- .../app/brokensite/BrokenSiteActivity.kt | 8 +------- .../app/feedback/ui/common/FeedbackActivity.kt | 7 +------ .../duckduckgo/app/global/DuckDuckGoActivity.kt | 7 +++++++ .../app/icon/ui/ChangeIconActivity.kt | 8 +------- .../app/privacy/ui/PrivacyDashboardActivity.kt | 7 +------ .../app/privacy/ui/PrivacyPracticesActivity.kt | 7 +------ .../app/privacy/ui/ScorecardActivity.kt | 8 +------- .../app/privacy/ui/TrackerNetworksActivity.kt | 7 +------ .../duckduckgo/app/settings/SettingsActivity.kt | 17 +---------------- .../app/tabs/ui/TabSwitcherActivity.kt | 9 +-------- 12 files changed, 18 insertions(+), 82 deletions(-) diff --git a/app/src/main/java/com/duckduckgo/app/about/AboutDuckDuckGoActivity.kt b/app/src/main/java/com/duckduckgo/app/about/AboutDuckDuckGoActivity.kt index a1067c2b4456..e895b6c4d78f 100644 --- a/app/src/main/java/com/duckduckgo/app/about/AboutDuckDuckGoActivity.kt +++ b/app/src/main/java/com/duckduckgo/app/about/AboutDuckDuckGoActivity.kt @@ -31,7 +31,7 @@ class AboutDuckDuckGoActivity : DuckDuckGoActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_about_duck_duck_go) - configureActionBar() + setupToolbar(toolbar) learnMoreLink.setOnClickListener { startActivity(BrowserActivity.intent(this, Url.ABOUT)) @@ -39,11 +39,6 @@ class AboutDuckDuckGoActivity : DuckDuckGoActivity() { } } - private fun configureActionBar() { - setSupportActionBar(toolbar) - supportActionBar?.setDisplayHomeAsUpEnabled(true) - } - companion object { fun intent(context: Context): Intent { return Intent(context, AboutDuckDuckGoActivity::class.java) diff --git a/app/src/main/java/com/duckduckgo/app/bookmarks/ui/BookmarksActivity.kt b/app/src/main/java/com/duckduckgo/app/bookmarks/ui/BookmarksActivity.kt index 877b3433ab1c..353cb5eb156c 100644 --- a/app/src/main/java/com/duckduckgo/app/bookmarks/ui/BookmarksActivity.kt +++ b/app/src/main/java/com/duckduckgo/app/bookmarks/ui/BookmarksActivity.kt @@ -59,7 +59,7 @@ class BookmarksActivity : DuckDuckGoActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_bookmarks) - setupActionBar() + setupToolbar(toolbar) setupBookmarksRecycler() observeViewModel() } @@ -72,12 +72,6 @@ class BookmarksActivity : DuckDuckGoActivity() { recycler.addItemDecoration(separator) } - private fun setupActionBar() { - setSupportActionBar(toolbar) - supportActionBar?.setDisplayHomeAsUpEnabled(true) - toolbar.setNavigationIcon(R.drawable.ic_back) - } - private fun observeViewModel() { viewModel.viewState.observe(this, Observer { viewState -> viewState?.let { diff --git a/app/src/main/java/com/duckduckgo/app/brokensite/BrokenSiteActivity.kt b/app/src/main/java/com/duckduckgo/app/brokensite/BrokenSiteActivity.kt index 9fc3e2d2a2e7..60dbfa5c4639 100644 --- a/app/src/main/java/com/duckduckgo/app/brokensite/BrokenSiteActivity.kt +++ b/app/src/main/java/com/duckduckgo/app/brokensite/BrokenSiteActivity.kt @@ -31,7 +31,6 @@ import kotlinx.android.synthetic.main.content_broken_sites.* import kotlinx.android.synthetic.main.include_toolbar.* import org.jetbrains.anko.longToast - class BrokenSiteActivity : DuckDuckGoActivity() { private val viewModel: BrokenSiteViewModel by bindViewModel() @@ -40,17 +39,12 @@ class BrokenSiteActivity : DuckDuckGoActivity() { setContentView(R.layout.activity_broken_site) configureListeners() configureObservers() - setupActionBar() + setupToolbar(toolbar) if (savedInstanceState == null) { consumeIntentExtra() } } - private fun setupActionBar() { - setSupportActionBar(toolbar) - supportActionBar?.setDisplayHomeAsUpEnabled(true) - } - private fun consumeIntentExtra() { val url = intent.getStringExtra(URL_EXTRA) val blockedTrackers = intent.getStringExtra(BLOCKED_TRACKERS_EXTRA) diff --git a/app/src/main/java/com/duckduckgo/app/feedback/ui/common/FeedbackActivity.kt b/app/src/main/java/com/duckduckgo/app/feedback/ui/common/FeedbackActivity.kt index e7720c971070..4dd644a7478c 100644 --- a/app/src/main/java/com/duckduckgo/app/feedback/ui/common/FeedbackActivity.kt +++ b/app/src/main/java/com/duckduckgo/app/feedback/ui/common/FeedbackActivity.kt @@ -54,15 +54,10 @@ class FeedbackActivity : DuckDuckGoActivity(), override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_feedback) - setupActionBar() + setupToolbar(toolbar) configureObservers() } - private fun setupActionBar() { - setSupportActionBar(toolbar) - supportActionBar?.setDisplayHomeAsUpEnabled(true) - } - private fun configureObservers() { viewModel.command.observe(this, Observer { it?.let { command -> processCommand(command) } diff --git a/app/src/main/java/com/duckduckgo/app/global/DuckDuckGoActivity.kt b/app/src/main/java/com/duckduckgo/app/global/DuckDuckGoActivity.kt index b3ae859b6c6d..2bd0499758fa 100644 --- a/app/src/main/java/com/duckduckgo/app/global/DuckDuckGoActivity.kt +++ b/app/src/main/java/com/duckduckgo/app/global/DuckDuckGoActivity.kt @@ -21,6 +21,7 @@ import android.content.BroadcastReceiver import android.os.Bundle import android.view.MenuItem import androidx.appcompat.app.AppCompatActivity +import androidx.appcompat.widget.Toolbar import androidx.lifecycle.ViewModel import androidx.lifecycle.ViewModelProviders import androidx.localbroadcastmanager.content.LocalBroadcastManager @@ -77,6 +78,12 @@ abstract class DuckDuckGoActivity : AppCompatActivity() { super.onDestroy() } + fun setupToolbar(toolbar: Toolbar) { + setSupportActionBar(toolbar) + supportActionBar?.setDisplayHomeAsUpEnabled(true) + toolbar.setNavigationIcon(R.drawable.ic_back) + } + protected inline fun bindViewModel() = lazy { ViewModelProviders.of(this, viewModelFactory).get(V::class.java) } } diff --git a/app/src/main/java/com/duckduckgo/app/icon/ui/ChangeIconActivity.kt b/app/src/main/java/com/duckduckgo/app/icon/ui/ChangeIconActivity.kt index 4192ca92e769..85da644eb39c 100644 --- a/app/src/main/java/com/duckduckgo/app/icon/ui/ChangeIconActivity.kt +++ b/app/src/main/java/com/duckduckgo/app/icon/ui/ChangeIconActivity.kt @@ -23,7 +23,6 @@ import androidx.appcompat.app.AlertDialog import androidx.lifecycle.Observer import androidx.recyclerview.widget.GridLayoutManager import com.duckduckgo.app.browser.R -import com.duckduckgo.app.fire.FireActivity import com.duckduckgo.app.global.DuckDuckGoActivity import kotlinx.android.synthetic.main.content_app_icons.appIconsList import kotlinx.android.synthetic.main.include_toolbar.toolbar @@ -44,17 +43,12 @@ class ChangeIconActivity : DuckDuckGoActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_app_icons) - setupActionBar() + setupToolbar(toolbar) configureRecycler() observeViewModel() } - private fun setupActionBar() { - setSupportActionBar(toolbar) - supportActionBar?.setDisplayHomeAsUpEnabled(true) - } - private fun configureRecycler() { appIconsList.layoutManager = GridLayoutManager(this, 4) appIconsList.addItemDecoration(ItemOffsetDecoration(this, R.dimen.changeAppIconListPadding)) diff --git a/app/src/main/java/com/duckduckgo/app/privacy/ui/PrivacyDashboardActivity.kt b/app/src/main/java/com/duckduckgo/app/privacy/ui/PrivacyDashboardActivity.kt index bc0686f7856d..4597f460e60a 100644 --- a/app/src/main/java/com/duckduckgo/app/privacy/ui/PrivacyDashboardActivity.kt +++ b/app/src/main/java/com/duckduckgo/app/privacy/ui/PrivacyDashboardActivity.kt @@ -55,7 +55,7 @@ class PrivacyDashboardActivity : DuckDuckGoActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_privacy_dashboard) - configureToolbar() + setupToolbar(toolbar) viewModel.viewState.observe(this, Observer { it?.let { render(it) } @@ -74,11 +74,6 @@ class PrivacyDashboardActivity : DuckDuckGoActivity() { } } - private fun configureToolbar() { - setSupportActionBar(toolbar) - supportActionBar?.setDisplayHomeAsUpEnabled(true) - } - private fun render(viewState: ViewState) { if (isFinishing) { return diff --git a/app/src/main/java/com/duckduckgo/app/privacy/ui/PrivacyPracticesActivity.kt b/app/src/main/java/com/duckduckgo/app/privacy/ui/PrivacyPracticesActivity.kt index 588a5097a063..f78507b757d6 100644 --- a/app/src/main/java/com/duckduckgo/app/privacy/ui/PrivacyPracticesActivity.kt +++ b/app/src/main/java/com/duckduckgo/app/privacy/ui/PrivacyPracticesActivity.kt @@ -47,7 +47,7 @@ class PrivacyPracticesActivity : DuckDuckGoActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_privacy_practices) - configureToolbar() + setupToolbar(toolbar) configureRecycler() viewModel.viewState.observe(this, Observer { @@ -59,11 +59,6 @@ class PrivacyPracticesActivity : DuckDuckGoActivity() { }) } - private fun configureToolbar() { - setSupportActionBar(toolbar) - supportActionBar?.setDisplayHomeAsUpEnabled(true) - } - private fun configureRecycler() { practicesList.layoutManager = LinearLayoutManager(this) practicesList.adapter = practicesAdapter diff --git a/app/src/main/java/com/duckduckgo/app/privacy/ui/ScorecardActivity.kt b/app/src/main/java/com/duckduckgo/app/privacy/ui/ScorecardActivity.kt index eece8050e2fb..3e5be9a6f0f1 100644 --- a/app/src/main/java/com/duckduckgo/app/privacy/ui/ScorecardActivity.kt +++ b/app/src/main/java/com/duckduckgo/app/privacy/ui/ScorecardActivity.kt @@ -47,7 +47,7 @@ class ScorecardActivity : DuckDuckGoActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_privacy_scorecard) - configureToolbar() + setupToolbar(toolbar) viewModel.viewState.observe(this, Observer { it?.let { render(it) } @@ -58,11 +58,6 @@ class ScorecardActivity : DuckDuckGoActivity() { }) } - private fun configureToolbar() { - setSupportActionBar(toolbar) - supportActionBar?.setDisplayHomeAsUpEnabled(true) - } - private fun render(viewState: ScorecardViewModel.ViewState) { privacyBanner.setImageResource(viewState.afterGrade.banner(viewState.privacyOn)) domain.text = viewState.domain @@ -105,5 +100,4 @@ class ScorecardActivity : DuckDuckGoActivity() { return intent } } - } \ No newline at end of file diff --git a/app/src/main/java/com/duckduckgo/app/privacy/ui/TrackerNetworksActivity.kt b/app/src/main/java/com/duckduckgo/app/privacy/ui/TrackerNetworksActivity.kt index 213c5838f418..7d0daeeed7a3 100644 --- a/app/src/main/java/com/duckduckgo/app/privacy/ui/TrackerNetworksActivity.kt +++ b/app/src/main/java/com/duckduckgo/app/privacy/ui/TrackerNetworksActivity.kt @@ -43,7 +43,7 @@ class TrackerNetworksActivity : DuckDuckGoActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_tracker_networks) - configureToolbar() + setupToolbar(toolbar) configureRecycler() viewModel.viewState.observe(this, Observer { @@ -55,11 +55,6 @@ class TrackerNetworksActivity : DuckDuckGoActivity() { }) } - private fun configureToolbar() { - setSupportActionBar(toolbar) - supportActionBar?.setDisplayHomeAsUpEnabled(true) - } - private fun configureRecycler() { networksList.layoutManager = LinearLayoutManager(this) networksList.adapter = networksAdapter diff --git a/app/src/main/java/com/duckduckgo/app/settings/SettingsActivity.kt b/app/src/main/java/com/duckduckgo/app/settings/SettingsActivity.kt index 3a27da52edaf..a7d438ee66a7 100644 --- a/app/src/main/java/com/duckduckgo/app/settings/SettingsActivity.kt +++ b/app/src/main/java/com/duckduckgo/app/settings/SettingsActivity.kt @@ -54,16 +54,7 @@ import kotlinx.android.synthetic.main.content_settings_other.version import kotlinx.android.synthetic.main.content_settings_privacy.automaticallyClearWhatSetting import kotlinx.android.synthetic.main.content_settings_privacy.automaticallyClearWhenSetting import kotlinx.android.synthetic.main.include_toolbar.toolbar -import kotlinx.android.synthetic.main.content_settings_general.autocompleteToggle -import kotlinx.android.synthetic.main.content_settings_general.lightThemeToggle import kotlinx.android.synthetic.main.content_settings_general.searchNotificationToggle -import kotlinx.android.synthetic.main.content_settings_general.setAsDefaultBrowserSetting -import kotlinx.android.synthetic.main.content_settings_other.about -import kotlinx.android.synthetic.main.content_settings_other.provideFeedback -import kotlinx.android.synthetic.main.content_settings_other.version -import kotlinx.android.synthetic.main.content_settings_privacy.automaticallyClearWhatSetting -import kotlinx.android.synthetic.main.content_settings_privacy.automaticallyClearWhenSetting -import kotlinx.android.synthetic.main.include_toolbar.toolbar import javax.inject.Inject class SettingsActivity : DuckDuckGoActivity(), SettingsAutomaticallyClearWhatFragment.Listener, SettingsAutomaticallyClearWhenFragment.Listener { @@ -90,7 +81,7 @@ class SettingsActivity : DuckDuckGoActivity(), SettingsAutomaticallyClearWhatFra override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_settings) - setupActionBar() + setupToolbar(toolbar) configureUiEventHandlers() observeViewModel() @@ -188,12 +179,6 @@ class SettingsActivity : DuckDuckGoActivity(), SettingsAutomaticallyClearWhatFra } } - private fun setupActionBar() { - setSupportActionBar(toolbar) - supportActionBar?.setDisplayHomeAsUpEnabled(true) - toolbar.setNavigationIcon(R.drawable.ic_back) - } - private fun launchFeedback() { val options = ActivityOptions.makeSceneTransitionAnimation(this).toBundle() startActivityForResult(Intent(FeedbackActivity.intent(this)), FEEDBACK_REQUEST_CODE, options) diff --git a/app/src/main/java/com/duckduckgo/app/tabs/ui/TabSwitcherActivity.kt b/app/src/main/java/com/duckduckgo/app/tabs/ui/TabSwitcherActivity.kt index 39b720cb985c..a1462be67cb5 100644 --- a/app/src/main/java/com/duckduckgo/app/tabs/ui/TabSwitcherActivity.kt +++ b/app/src/main/java/com/duckduckgo/app/tabs/ui/TabSwitcherActivity.kt @@ -38,7 +38,6 @@ import com.duckduckgo.app.tabs.model.TabEntity import com.duckduckgo.app.tabs.ui.TabSwitcherViewModel.Command import com.duckduckgo.app.tabs.ui.TabSwitcherViewModel.Command.Close import com.duckduckgo.app.tabs.ui.TabSwitcherViewModel.Command.DisplayMessage -import kotlinx.android.synthetic.main.include_toolbar.toolbar import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.SupervisorJob @@ -86,7 +85,7 @@ class TabSwitcherActivity : DuckDuckGoActivity(), TabSwitcherListener, Coroutine setContentView(R.layout.activity_tab_switcher) extractIntentExtras() configureViewReferences() - configureToolbar() + setupToolbar(toolbar) configureRecycler() configureObservers() } @@ -100,12 +99,6 @@ class TabSwitcherActivity : DuckDuckGoActivity(), TabSwitcherListener, Coroutine toolbar = findViewById(R.id.toolbar) } - private fun configureToolbar() { - setSupportActionBar(toolbar) - supportActionBar?.setDisplayHomeAsUpEnabled(true) - toolbar.setNavigationIcon(R.drawable.ic_back) - } - private fun configureRecycler() { val numberColumns = gridViewColumnCalculator.calculateNumberOfColumns(TAB_GRID_COLUMN_WIDTH_DP, TAB_GRID_MAX_COLUMN_COUNT) val layoutManager = GridLayoutManager(this, numberColumns) From 1e48c886cab316ef3fb99fda7e9c11e24805d851 Mon Sep 17 00:00:00 2001 From: David Gonzalez Date: Thu, 9 Apr 2020 14:17:48 +0200 Subject: [PATCH 042/104] ui tweaks with Robert --- .../TabSwitcherBottomBarExperimentActivity.kt | 1 + app/src/main/res/drawable/popup_menu_bg.xml | 20 ++++++++++++++++ .../res/layout/include_omnibar_toolbar.xml | 5 +--- .../item_autocomplete_search_suggestion.xml | 6 ++--- .../layout_tabs_bottom_navigation_bar.xml | 23 +++++++++++++++++++ .../popup_window_browser_bottom_tab_menu.xml | 17 +++++++------- .../res/layout/view_tab_switcher_button.xml | 3 +-- app/src/main/res/values/styles.xml | 4 ++-- 8 files changed, 60 insertions(+), 19 deletions(-) create mode 100644 app/src/main/res/drawable/popup_menu_bg.xml diff --git a/app/src/main/java/com/duckduckgo/app/tabs/ui/TabSwitcherBottomBarExperimentActivity.kt b/app/src/main/java/com/duckduckgo/app/tabs/ui/TabSwitcherBottomBarExperimentActivity.kt index fc8afdfb6a44..2dbb0d9b391b 100644 --- a/app/src/main/java/com/duckduckgo/app/tabs/ui/TabSwitcherBottomBarExperimentActivity.kt +++ b/app/src/main/java/com/duckduckgo/app/tabs/ui/TabSwitcherBottomBarExperimentActivity.kt @@ -230,6 +230,7 @@ class TabSwitcherBottomBarExperimentActivity : DuckDuckGoActivity(), TabSwitcher override fun finish() { clearObserversEarlyToStopViewUpdates() super.finish() + overridePendingTransition(R.anim.slide_from_bottom, R.anim.tab_anim_fade_out) } private fun clearObserversEarlyToStopViewUpdates() { diff --git a/app/src/main/res/drawable/popup_menu_bg.xml b/app/src/main/res/drawable/popup_menu_bg.xml new file mode 100644 index 000000000000..faaf444af467 --- /dev/null +++ b/app/src/main/res/drawable/popup_menu_bg.xml @@ -0,0 +1,20 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/include_omnibar_toolbar.xml b/app/src/main/res/layout/include_omnibar_toolbar.xml index 17e81870c8e3..f6c8e4a1ef9a 100644 --- a/app/src/main/res/layout/include_omnibar_toolbar.xml +++ b/app/src/main/res/layout/include_omnibar_toolbar.xml @@ -52,10 +52,7 @@ android:id="@+id/omniBarContainer" android:layout_width="match_parent" android:layout_height="match_parent" - android:layout_marginStart="5dp" - android:layout_marginTop="8dp" - android:layout_marginEnd="5dp" - android:layout_marginBottom="8dp" + android:layout_margin="8dp" android:background="@drawable/omnibar_field_background" android:paddingStart="6dp" android:paddingEnd="6dp"> diff --git a/app/src/main/res/layout/item_autocomplete_search_suggestion.xml b/app/src/main/res/layout/item_autocomplete_search_suggestion.xml index 3b2d66645321..b929cfa9d7bd 100644 --- a/app/src/main/res/layout/item_autocomplete_search_suggestion.xml +++ b/app/src/main/res/layout/item_autocomplete_search_suggestion.xml @@ -26,7 +26,7 @@ android:id="@+id/phraseOrUrlIndicator" android:layout_width="24dp" android:layout_height="24dp" - android:layout_marginStart="24dp" + android:layout_marginStart="18dp" android:importantForAccessibility="no" android:src="@drawable/ic_loupe_24dp" app:layout_constraintBottom_toBottomOf="parent" @@ -37,7 +37,7 @@ android:id="@+id/phrase" android:layout_width="0dp" android:layout_height="0dp" - android:layout_marginStart="16dp" + android:layout_marginStart="8dp" android:ellipsize="end" android:includeFontPadding="false" android:fontFamily="sans-serif" @@ -58,7 +58,7 @@ android:layout_height="wrap_content" android:padding="6dp" android:paddingStart="16dp" - android:paddingEnd="22dp" + android:paddingEnd="16dp" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintTop_toTopOf="parent"> diff --git a/app/src/main/res/layout/layout_tabs_bottom_navigation_bar.xml b/app/src/main/res/layout/layout_tabs_bottom_navigation_bar.xml index de3caa075915..ac6e55476990 100644 --- a/app/src/main/res/layout/layout_tabs_bottom_navigation_bar.xml +++ b/app/src/main/res/layout/layout_tabs_bottom_navigation_bar.xml @@ -28,6 +28,18 @@ android:contentDescription="@string/back" android:src="@drawable/ic_newtab" /> + + + + + + android:background="@drawable/popup_menu_bg"> + android:paddingBottom="16dp"> @@ -96,8 +96,9 @@ android:layout_height="50dp" android:gravity="center" android:orientation="horizontal" - android:paddingStart="18dp" - android:paddingEnd="18dp" + android:paddingStart="12dp" + android:paddingEnd="12dp" + android:paddingBottom="16dp" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" diff --git a/app/src/main/res/layout/view_tab_switcher_button.xml b/app/src/main/res/layout/view_tab_switcher_button.xml index 1cd7b2632027..6a6980cd6a0d 100644 --- a/app/src/main/res/layout/view_tab_switcher_button.xml +++ b/app/src/main/res/layout/view_tab_switcher_button.xml @@ -27,8 +27,7 @@ android:textAlignment="center" android:textColor="?toolbarIconColor" android:textSize="12sp" - android:textStyle="bold" - android:typeface="normal" + android:fontFamily="sans-serif-condensed-medium" android:gravity="center" android:background="@drawable/ic_tabs" tools:text="66" /> diff --git a/app/src/main/res/values/styles.xml b/app/src/main/res/values/styles.xml index f494c4da18e4..8e5c25b9e5e3 100644 --- a/app/src/main/res/values/styles.xml +++ b/app/src/main/res/values/styles.xml @@ -154,8 +154,8 @@ + + \ No newline at end of file diff --git a/app/src/main/res/values/styles.xml b/app/src/main/res/values/styles.xml index ed1908b4367d..61118ea7539b 100644 --- a/app/src/main/res/values/styles.xml +++ b/app/src/main/res/values/styles.xml @@ -150,7 +150,7 @@ 6dp 6dp ?selectableItemBackground - @color/browser_menu_icon + @color/bottom_bar_icon_color_selector_21 @@ -209,4 +209,9 @@ true + + From 349d300bd7f7c3d05ffe79ab290cc850ad1cb065 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Gonz=C3=A1lez?= Date: Wed, 22 Apr 2020 09:07:47 +0200 Subject: [PATCH 078/104] no need for this --- .../main/java/com/duckduckgo/app/browser/BrowserTabFragment.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/main/java/com/duckduckgo/app/browser/BrowserTabFragment.kt b/app/src/main/java/com/duckduckgo/app/browser/BrowserTabFragment.kt index 961d493254f8..64fbfd9fb513 100644 --- a/app/src/main/java/com/duckduckgo/app/browser/BrowserTabFragment.kt +++ b/app/src/main/java/com/duckduckgo/app/browser/BrowserTabFragment.kt @@ -1485,7 +1485,7 @@ class BrowserTabFragment : Fragment(), FindListener, CoroutineScope, DaxDialogLi fun animateTabsCount() { val tabsButton = tabsButton?.actionView as TabSwitcherButton - tabsButton?.animateCount() + tabsButton.animateCount() bottomBarTabsItem.animateCount() } } From 9b91ae77012563ca488d4c06a79e7bc707343195 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Gonz=C3=A1lez?= Date: Wed, 22 Apr 2020 11:26:59 +0200 Subject: [PATCH 079/104] cleaning up the toolbar, make sure we show the icons for both experiments --- .../app/browser/BrowserTabFragment.kt | 59 +++--- .../res/layout/include_omnibar_toolbar.xml | 194 +++++++++++------- .../main/res/menu/menu_browser_activity.xml | 34 --- 3 files changed, 146 insertions(+), 141 deletions(-) delete mode 100644 app/src/main/res/menu/menu_browser_activity.xml diff --git a/app/src/main/java/com/duckduckgo/app/browser/BrowserTabFragment.kt b/app/src/main/java/com/duckduckgo/app/browser/BrowserTabFragment.kt index 64fbfd9fb513..463c0ddfacb8 100644 --- a/app/src/main/java/com/duckduckgo/app/browser/BrowserTabFragment.kt +++ b/app/src/main/java/com/duckduckgo/app/browser/BrowserTabFragment.kt @@ -139,6 +139,7 @@ import kotlinx.android.synthetic.main.fragment_browser_tab.focusDummy import kotlinx.android.synthetic.main.fragment_browser_tab.rootView import kotlinx.android.synthetic.main.fragment_browser_tab.webViewContainer import kotlinx.android.synthetic.main.fragment_browser_tab.webViewFullScreenContainer +import kotlinx.android.synthetic.main.include_add_widget_instruction_buttons.view.closeButton import kotlinx.android.synthetic.main.include_cta_buttons.view.ctaDismissButton import kotlinx.android.synthetic.main.include_cta_buttons.view.ctaOkButton import kotlinx.android.synthetic.main.include_dax_dialog_cta.daxCtaContainer @@ -155,8 +156,9 @@ import kotlinx.android.synthetic.main.include_new_browser_tab.ddgLogo import kotlinx.android.synthetic.main.include_new_browser_tab.newTabLayout import kotlinx.android.synthetic.main.include_omnibar_toolbar.* import kotlinx.android.synthetic.main.include_omnibar_toolbar.view.browserMenu +import kotlinx.android.synthetic.main.include_omnibar_toolbar.view.fireIconMenu import kotlinx.android.synthetic.main.include_omnibar_toolbar.view.privacyGradeButton -import kotlinx.android.synthetic.main.include_top_cta.view.closeButton +import kotlinx.android.synthetic.main.include_omnibar_toolbar.view.tabsMenu import kotlinx.android.synthetic.main.layout_browser_bottom_navigation_bar.bottomBarBookmarksItemOne import kotlinx.android.synthetic.main.layout_browser_bottom_navigation_bar.bottomBarFireItem import kotlinx.android.synthetic.main.layout_browser_bottom_navigation_bar.bottomBarOverflowItem @@ -278,11 +280,11 @@ class BrowserTabFragment : Fragment(), FindListener, CoroutineScope, DaxDialogLi private val browserActivity get() = activity as? BrowserActivity - private val tabsButton: MenuItem? - get() = toolbar.menu.findItem(R.id.tabs) + private val tabsButton: TabSwitcherButton? + get() = appBarLayout.tabsMenu - private val fireMenuButton: MenuItem? - get() = toolbar.menu.findItem(R.id.fire) + private val fireMenuButton: ViewGroup? + get() = appBarLayout.fireIconMenu private val menuButton: ViewGroup? get() = appBarLayout.browserMenu @@ -476,7 +478,9 @@ class BrowserTabFragment : Fragment(), FindListener, CoroutineScope, DaxDialogLi private fun addTabsObserver() { viewModel.tabs.observe(viewLifecycleOwner, Observer> { - it?.let { renderer.renderTabIcon(it) } + it?.let { + decorator.renderTabIcon(it) + } }) } @@ -651,8 +655,7 @@ class BrowserTabFragment : Fragment(), FindListener, CoroutineScope, DaxDialogLi private fun openInNewBackgroundTab() { appBarLayout.setExpanded(true, true) viewModel.tabs.removeObservers(this) - val view = tabsButton?.actionView as TabSwitcherButton - view.increment { + tabsButton?.increment { addTabsObserver() } bottomBarTabsItem.increment { @@ -1321,17 +1324,13 @@ class BrowserTabFragment : Fragment(), FindListener, CoroutineScope, DaxDialogLi } private fun decorateAppBarWithToolbarOnly() { - toolbar.inflateMenu(R.menu.menu_browser_activity) - toolbar.setOnMenuItemClickListener { menuItem -> - when (menuItem.itemId) { - R.id.fire -> { - browserActivity?.launchFire() - pixel.fire(String.format(Locale.US, Pixel.PixelName.MENU_ACTION_FIRE_PRESSED.pixelName, variantManager.getVariant().key)) - return@setOnMenuItemClickListener true - } - else -> return@setOnMenuItemClickListener false - } + fireMenuButton?.show() + fireMenuButton?.setOnClickListener { + browserActivity?.launchFire() + pixel.fire(String.format(Locale.US, Pixel.PixelName.MENU_ACTION_FIRE_PRESSED.pixelName, variantManager.getVariant().key)) } + + tabsButton?.show() } private fun decorateAppBarWithBottomBar() { @@ -1458,7 +1457,7 @@ class BrowserTabFragment : Fragment(), FindListener, CoroutineScope, DaxDialogLi } private fun configureShowTabSwitcherListenerWithToolbarOnly() { - tabsButton?.actionView?.setOnClickListener { + tabsButton?.setOnClickListener { launch { viewModel.userLaunchingTabSwitcher() } } } @@ -1470,7 +1469,7 @@ class BrowserTabFragment : Fragment(), FindListener, CoroutineScope, DaxDialogLi } private fun configureLongClickOpensNewTabListenerWithToolbarOnly() { - tabsButton?.actionView?.setOnLongClickListener { + tabsButton?.setOnLongClickListener { launch { viewModel.userRequestedOpeningNewTab() } return@setOnLongClickListener true } @@ -1484,10 +1483,19 @@ class BrowserTabFragment : Fragment(), FindListener, CoroutineScope, DaxDialogLi } fun animateTabsCount() { - val tabsButton = tabsButton?.actionView as TabSwitcherButton - tabsButton.animateCount() + tabsButton?.animateCount() bottomBarTabsItem.animateCount() } + + fun renderTabIcon(tabs: List) { + context?.let { + tabsButton?.count = tabs.count() + tabsButton?.hasUnread = tabs.firstOrNull { !it.viewed } != null + + bottomBarTabsItem.count = tabs.count() + bottomBarTabsItem.hasUnread = tabs.firstOrNull { !it.viewed } != null + } + } } inner class BrowserTabFragmentRenderer { @@ -1696,13 +1704,6 @@ class BrowserTabFragment : Fragment(), FindListener, CoroutineScope, DaxDialogLi popupMenu.contentView.findInPageMenuItem?.isEnabled = viewState.canFindInPage } - fun renderTabIcon(tabs: List) { - context?.let { - bottomBarTabsItem.count = tabs.count() - bottomBarTabsItem.hasUnread = tabs.firstOrNull { !it.viewed } != null - } - } - fun renderCtaViewState(viewState: CtaViewState) { if (isHidden) { return diff --git a/app/src/main/res/layout/include_omnibar_toolbar.xml b/app/src/main/res/layout/include_omnibar_toolbar.xml index f6c8e4a1ef9a..5ebbcfd6fa1d 100644 --- a/app/src/main/res/layout/include_omnibar_toolbar.xml +++ b/app/src/main/res/layout/include_omnibar_toolbar.xml @@ -43,93 +43,131 @@ app:contentInsetEnd="0dp" app:contentInsetStart="0dp" app:layout_constraintBottom_toBottomOf="parent" - app:layout_constraintEnd_toStartOf="@id/browserMenu" + app:layout_constraintEnd_toStartOf="@id/fireIconMenu" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent" app:popupTheme="@style/AppTheme.Dark.PopupOverlay"> - - - - - - - - - - - - + android:layout_margin="8dp" + android:background="@drawable/omnibar_field_background" + android:paddingStart="6dp" + android:paddingEnd="6dp"> + + + + + + + + + + + + + + + + + + + + + tools:visibility="visible"> - - - - - - - - \ No newline at end of file From 890b3cd6d38590c934f2cac379df35c2cbfbf688 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Gonz=C3=A1lez?= Date: Wed, 22 Apr 2020 11:35:06 +0200 Subject: [PATCH 080/104] returning experiments back to original distibution --- .../com/duckduckgo/app/statistics/VariantManager.kt | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/app/src/main/java/com/duckduckgo/app/statistics/VariantManager.kt b/app/src/main/java/com/duckduckgo/app/statistics/VariantManager.kt index 8328bd9d9d14..effccb436a4e 100644 --- a/app/src/main/java/com/duckduckgo/app/statistics/VariantManager.kt +++ b/app/src/main/java/com/duckduckgo/app/statistics/VariantManager.kt @@ -44,18 +44,18 @@ interface VariantManager { val ACTIVE_VARIANTS = listOf( // SERP variants. "sc" may also be used as a shared control for mobile experiments in // the future if we can filter by app version - Variant(key = "sc", weight = 0.0, features = emptyList(), filterBy = { noFilter() }), - Variant(key = "se", weight = 0.0, features = emptyList(), filterBy = { noFilter() }), + Variant(key = "sc", weight = 1.0, features = emptyList(), filterBy = { noFilter() }), + Variant(key = "se", weight = 1.0, features = emptyList(), filterBy = { noFilter() }), // Quick Search Notification Experiment Variant( key = "mf", - weight = 0.0, + weight = 1.0, features = emptyList(), filterBy = { isEnglishLocale() }), Variant( key = "mg", - weight = 0.0, + weight = 1.0, features = listOf(StickySearchNotification), filterBy = { isEnglishLocale() }), @@ -67,7 +67,7 @@ interface VariantManager { filterBy = { noFilter() }), Variant( key = "mn", - weight = 0.0, + weight = 1.0, features = listOf(BottomBarNavigation), filterBy = { noFilter() }) From 240c3c04ee2dab52eeaa6afd71de20cea02c2595 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Gonz=C3=A1lez?= Date: Wed, 22 Apr 2020 11:38:44 +0200 Subject: [PATCH 081/104] hide new menu buttons when in bottomnav mode --- .../main/java/com/duckduckgo/app/browser/BrowserTabFragment.kt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/app/src/main/java/com/duckduckgo/app/browser/BrowserTabFragment.kt b/app/src/main/java/com/duckduckgo/app/browser/BrowserTabFragment.kt index 463c0ddfacb8..972a01561662 100644 --- a/app/src/main/java/com/duckduckgo/app/browser/BrowserTabFragment.kt +++ b/app/src/main/java/com/duckduckgo/app/browser/BrowserTabFragment.kt @@ -1335,6 +1335,8 @@ class BrowserTabFragment : Fragment(), FindListener, CoroutineScope, DaxDialogLi private fun decorateAppBarWithBottomBar() { menuButton?.gone() + tabsButton?.gone() + fireMenuButton?.gone() } private fun createPopupMenuWithToolbarOnly() { From 8e488ab2dd0c784103c4f5e94f68aa1fbacdc5b9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Gonz=C3=A1lez?= Date: Wed, 22 Apr 2020 11:49:46 +0200 Subject: [PATCH 082/104] no need for this selector because we use theming now --- .../res/color/checkbox_color_selector.xml | 21 ------------------- 1 file changed, 21 deletions(-) delete mode 100644 app/src/main/res/color/checkbox_color_selector.xml diff --git a/app/src/main/res/color/checkbox_color_selector.xml b/app/src/main/res/color/checkbox_color_selector.xml deleted file mode 100644 index d95ef54f2270..000000000000 --- a/app/src/main/res/color/checkbox_color_selector.xml +++ /dev/null @@ -1,21 +0,0 @@ - - - - - - - From bd3e2bfd06c918a0219537fa4c6858e1004c3e3b Mon Sep 17 00:00:00 2001 From: David Gonzalez Date: Thu, 23 Apr 2020 14:21:28 +0200 Subject: [PATCH 083/104] ensure the omnibar is using full width --- app/src/main/res/layout/include_omnibar_toolbar.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/src/main/res/layout/include_omnibar_toolbar.xml b/app/src/main/res/layout/include_omnibar_toolbar.xml index 5ebbcfd6fa1d..002ab3214c37 100644 --- a/app/src/main/res/layout/include_omnibar_toolbar.xml +++ b/app/src/main/res/layout/include_omnibar_toolbar.xml @@ -50,7 +50,7 @@ From 75daa9e3bbbac39f69df93c859e3f4393a8d9b9d Mon Sep 17 00:00:00 2001 From: David Gonzalez Date: Thu, 23 Apr 2020 15:08:14 +0200 Subject: [PATCH 084/104] ensure widget container is shown properly --- .../duckduckgo/app/browser/BrowserTabFragment.kt | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/app/src/main/java/com/duckduckgo/app/browser/BrowserTabFragment.kt b/app/src/main/java/com/duckduckgo/app/browser/BrowserTabFragment.kt index 972a01561662..f97d954656e8 100644 --- a/app/src/main/java/com/duckduckgo/app/browser/BrowserTabFragment.kt +++ b/app/src/main/java/com/duckduckgo/app/browser/BrowserTabFragment.kt @@ -973,7 +973,6 @@ class BrowserTabFragment : Fragment(), FindListener, CoroutineScope, DaxDialogLi } private fun bookmarkAdded(bookmarkId: Long, title: String?, url: String?) { - Snackbar.make(rootView, R.string.bookmarkEdited, Snackbar.LENGTH_LONG) .setAction(R.string.edit) { val addBookmarkDialog = EditBookmarkDialogFragment.instance(bookmarkId, title, url) @@ -1251,7 +1250,7 @@ class BrowserTabFragment : Fragment(), FindListener, CoroutineScope, DaxDialogLi .show() } - fun omnibarViews(): List = listOf(clearTextButton, omnibarTextInput, privacyGradeButton) + fun omnibarViews(): List = listOf(clearTextButton, omnibarTextInput, privacyGradeButton, searchIcon) companion object { private const val TAB_ID_ARG = "TAB_ID_ARG" @@ -1543,10 +1542,14 @@ class BrowserTabFragment : Fragment(), FindListener, CoroutineScope, DaxDialogLi } if (ctaContainer.isVisible) { - if (viewState.isEditing) { - ctaContainer.setPadding(0, 0, 0, 0) - } else { - ctaContainer.setPadding(0, 0, 0, 46.toPx()) + if (isBottomNavigationFeatureEnabled()) { + lastSeenOmnibarViewState?.let { + if (it.isEditing) { + ctaContainer.setPadding(0, 0, 0, 0) + } else { + ctaContainer.setPadding(0, 0, 0, 46.toPx()) + } + } ?: ctaContainer.setPadding(0, 0, 0, 46.toPx()) } } } From 6120a459d4dee1cd5802b51bfabfde8d5f019ed0 Mon Sep 17 00:00:00 2001 From: David Gonzalez Date: Thu, 23 Apr 2020 17:44:53 +0200 Subject: [PATCH 085/104] removing the behaviour so the omnibar is properly updated --- .../app/browser/BrowserTabFragment.kt | 20 ++++++++++++++++--- .../app/browser/BrowserTabViewModel.kt | 13 +++++------- .../browser/omnibar/KeyboardAwareEditText.kt | 7 ++++++- .../res/layout/include_omnibar_toolbar.xml | 6 +++--- 4 files changed, 31 insertions(+), 15 deletions(-) diff --git a/app/src/main/java/com/duckduckgo/app/browser/BrowserTabFragment.kt b/app/src/main/java/com/duckduckgo/app/browser/BrowserTabFragment.kt index f97d954656e8..4961307efc1e 100644 --- a/app/src/main/java/com/duckduckgo/app/browser/BrowserTabFragment.kt +++ b/app/src/main/java/com/duckduckgo/app/browser/BrowserTabFragment.kt @@ -65,6 +65,7 @@ import androidx.annotation.AnyThread import androidx.annotation.StringRes import androidx.appcompat.app.AlertDialog import androidx.constraintlayout.widget.ConstraintSet +import androidx.coordinatorlayout.widget.CoordinatorLayout import androidx.core.content.ContextCompat import androidx.core.content.pm.ShortcutManagerCompat import androidx.core.view.isEmpty @@ -409,7 +410,7 @@ class BrowserTabFragment : Fragment(), FindListener, CoroutineScope, DaxDialogLi override fun onResume() { super.onResume() - addTextChangedListeners() + appBarLayout.setExpanded(true) viewModel.onViewResumed() logoHidingListener.onResume() @@ -418,6 +419,8 @@ class BrowserTabFragment : Fragment(), FindListener, CoroutineScope, DaxDialogLi if (fragmentIsVisible()) { viewModel.onViewVisible() } + + addTextChangedListeners() } override fun onPause() { @@ -973,7 +976,7 @@ class BrowserTabFragment : Fragment(), FindListener, CoroutineScope, DaxDialogLi } private fun bookmarkAdded(bookmarkId: Long, title: String?, url: String?) { - Snackbar.make(rootView, R.string.bookmarkEdited, Snackbar.LENGTH_LONG) + Snackbar.make(browserLayout, R.string.bookmarkEdited, Snackbar.LENGTH_LONG) .setAction(R.string.edit) { val addBookmarkDialog = EditBookmarkDialogFragment.instance(bookmarkId, title, url) addBookmarkDialog.show(childFragmentManager, ADD_BOOKMARK_FRAGMENT_TAG) @@ -1312,6 +1315,7 @@ class BrowserTabFragment : Fragment(), FindListener, CoroutineScope, DaxDialogLi createPopupMenuWithToolbarOnly() configureShowTabSwitcherListenerWithToolbarOnly() configureLongClickOpensNewTabListenerWithToolbarOnly() + removeUnnecessaryLayoutBehaviour() } fun decorateWithBottomBarSearch() { @@ -1483,6 +1487,11 @@ class BrowserTabFragment : Fragment(), FindListener, CoroutineScope, DaxDialogLi } } + private fun removeUnnecessaryLayoutBehaviour() { + val params: CoordinatorLayout.LayoutParams = bottomNavigationBar.getLayoutParams() as CoordinatorLayout.LayoutParams + params.behavior = null + } + fun animateTabsCount() { tabsButton?.animateCount() bottomBarTabsItem.animateCount() @@ -1541,6 +1550,11 @@ class BrowserTabFragment : Fragment(), FindListener, CoroutineScope, DaxDialogLi decorator.updateBottomBarVisibility(!viewState.isEditing) } + lastSeenBrowserViewState?.let { + decorator.decorateToolbar(it) + renderToolbarMenus(it) + } + if (ctaContainer.isVisible) { if (isBottomNavigationFeatureEnabled()) { lastSeenOmnibarViewState?.let { @@ -1685,7 +1699,7 @@ class BrowserTabFragment : Fragment(), FindListener, CoroutineScope, DaxDialogLi clearTextButton?.isVisible = viewState.showClearButton searchIcon?.isVisible = viewState.showSearchIcon } else { - privacyGradeButton?.isInvisible = true + privacyGradeButton?.isVisible = false clearTextButton?.isVisible = viewState.showClearButton searchIcon?.isVisible = true } diff --git a/app/src/main/java/com/duckduckgo/app/browser/BrowserTabViewModel.kt b/app/src/main/java/com/duckduckgo/app/browser/BrowserTabViewModel.kt index ce613b350d73..c1e7def58933 100644 --- a/app/src/main/java/com/duckduckgo/app/browser/BrowserTabViewModel.kt +++ b/app/src/main/java/com/duckduckgo/app/browser/BrowserTabViewModel.kt @@ -486,12 +486,10 @@ class BrowserTabViewModel( buildSiteFactory(url, title) val currentOmnibarViewState = currentOmnibarViewState() - omnibarViewState.postValue(currentOmnibarViewState.copy(omnibarText = omnibarTextForUrl(url), shouldMoveCaretToEnd = false)) - + omnibarViewState.value = currentOmnibarViewState.copy(omnibarText = omnibarTextForUrl(url), shouldMoveCaretToEnd = false) val currentBrowserViewState = currentBrowserViewState() - findInPageViewState.postValue(FindInPageViewState(visible = false, canFindInPage = true)) - browserViewState.postValue( - currentBrowserViewState.copy( + findInPageViewState.value = FindInPageViewState(visible = false, canFindInPage = true) + browserViewState.value = currentBrowserViewState.copy( browserShowing = true, canAddBookmarks = true, addToHomeEnabled = true, @@ -500,7 +498,6 @@ class BrowserTabViewModel( showPrivacyGrade = true, canReportSite = true, showSearchIcon = false - ) ) if (duckDuckGoUrlDetector.isDuckDuckGoQueryUrl(url)) { @@ -667,8 +664,8 @@ class BrowserTabViewModel( val currentBrowserViewState = currentBrowserViewState() browserViewState.value = currentBrowserViewState.copy( - showPrivacyGrade = !hasFocus, - showSearchIcon = hasFocus, + showPrivacyGrade = !showClearButton, + showSearchIcon = showClearButton, showTabsButton = showControls, showFireButton = showControls, showMenuButton = showControls, diff --git a/app/src/main/java/com/duckduckgo/app/browser/omnibar/KeyboardAwareEditText.kt b/app/src/main/java/com/duckduckgo/app/browser/omnibar/KeyboardAwareEditText.kt index 61386985ccb4..7a2102b8fce4 100644 --- a/app/src/main/java/com/duckduckgo/app/browser/omnibar/KeyboardAwareEditText.kt +++ b/app/src/main/java/com/duckduckgo/app/browser/omnibar/KeyboardAwareEditText.kt @@ -33,8 +33,13 @@ class KeyboardAwareEditText : AppCompatEditText { constructor(context: Context, attrs: AttributeSet?) : this(context, attrs, 0) constructor(context: Context, attrs: AttributeSet?, defStyleAttr: Int) : super(context, attrs, defStyleAttr) + private var lastFocusValue = false + override fun onFocusChanged(focused: Boolean, direction: Int, previouslyFocusedRect: Rect?) { - super.onFocusChanged(focused, direction, previouslyFocusedRect) + if (focused != lastFocusValue){ + lastFocusValue = focused + super.onFocusChanged(focused, direction, previouslyFocusedRect) + } if (focused) { showKeyboard() diff --git a/app/src/main/res/layout/include_omnibar_toolbar.xml b/app/src/main/res/layout/include_omnibar_toolbar.xml index 002ab3214c37..2b1a247f76ee 100644 --- a/app/src/main/res/layout/include_omnibar_toolbar.xml +++ b/app/src/main/res/layout/include_omnibar_toolbar.xml @@ -59,7 +59,7 @@ @@ -98,7 +98,7 @@ android:imeOptions="flagNoExtractUi|actionGo|flagNoPersonalizedLearning" android:inputType="textUri|textNoSuggestions" android:maxLines="1" - android:paddingStart="5dp" + android:paddingStart="36dp" android:paddingEnd="8dp" android:selectAllOnFocus="true" android:textColor="?attr/omnibarTextColor" @@ -108,7 +108,7 @@ android:textStyle="normal" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toStartOf="@id/clearTextButton" - app:layout_constraintStart_toEndOf="@id/privacyGradeButton" + app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent" tools:text="https://duckduckgo.com/?q=areallylongexampleexample" /> From cd6dd49880ea1f58819b2730d9a3df8941bfbb8c Mon Sep 17 00:00:00 2001 From: David Gonzalez Date: Thu, 23 Apr 2020 17:51:28 +0200 Subject: [PATCH 086/104] revert this to what it was --- .../app/browser/omnibar/KeyboardAwareEditText.kt | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/app/src/main/java/com/duckduckgo/app/browser/omnibar/KeyboardAwareEditText.kt b/app/src/main/java/com/duckduckgo/app/browser/omnibar/KeyboardAwareEditText.kt index 7a2102b8fce4..b9f91e09a3a8 100644 --- a/app/src/main/java/com/duckduckgo/app/browser/omnibar/KeyboardAwareEditText.kt +++ b/app/src/main/java/com/duckduckgo/app/browser/omnibar/KeyboardAwareEditText.kt @@ -33,14 +33,8 @@ class KeyboardAwareEditText : AppCompatEditText { constructor(context: Context, attrs: AttributeSet?) : this(context, attrs, 0) constructor(context: Context, attrs: AttributeSet?, defStyleAttr: Int) : super(context, attrs, defStyleAttr) - private var lastFocusValue = false - override fun onFocusChanged(focused: Boolean, direction: Int, previouslyFocusedRect: Rect?) { - if (focused != lastFocusValue){ - lastFocusValue = focused - super.onFocusChanged(focused, direction, previouslyFocusedRect) - } - + super.onFocusChanged(focused, direction, previouslyFocusedRect) if (focused) { showKeyboard() } @@ -67,7 +61,5 @@ class KeyboardAwareEditText : AppCompatEditText { interface OnBackKeyListener { fun onBackKey(): Boolean - } - } From f924f806cd4fb670c0ff6236c1e19feee549a641 Mon Sep 17 00:00:00 2001 From: David Gonzalez Date: Thu, 23 Apr 2020 18:06:49 +0200 Subject: [PATCH 087/104] revert this to fix tests --- .../java/com/duckduckgo/app/browser/BrowserTabViewModel.kt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/src/main/java/com/duckduckgo/app/browser/BrowserTabViewModel.kt b/app/src/main/java/com/duckduckgo/app/browser/BrowserTabViewModel.kt index c1e7def58933..358426a47eea 100644 --- a/app/src/main/java/com/duckduckgo/app/browser/BrowserTabViewModel.kt +++ b/app/src/main/java/com/duckduckgo/app/browser/BrowserTabViewModel.kt @@ -664,8 +664,8 @@ class BrowserTabViewModel( val currentBrowserViewState = currentBrowserViewState() browserViewState.value = currentBrowserViewState.copy( - showPrivacyGrade = !showClearButton, - showSearchIcon = showClearButton, + showPrivacyGrade = !hasFocus, + showSearchIcon = hasFocus, showTabsButton = showControls, showFireButton = showControls, showMenuButton = showControls, From 6382a9d004e546c2e9fde319400b5b5531452b28 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Gonz=C3=A1lez?= Date: Fri, 24 Apr 2020 13:56:02 +0200 Subject: [PATCH 088/104] proper style for checkbox --- .../main/res/layout/popup_window_browser_menu.xml | 2 +- app/src/main/res/values/styles.xml | 13 +++++++++++++ app/src/main/res/values/themes.xml | 2 +- 3 files changed, 15 insertions(+), 2 deletions(-) diff --git a/app/src/main/res/layout/popup_window_browser_menu.xml b/app/src/main/res/layout/popup_window_browser_menu.xml index 5ec7188a745d..dc6d31acbf03 100644 --- a/app/src/main/res/layout/popup_window_browser_menu.xml +++ b/app/src/main/res/layout/popup_window_browser_menu.xml @@ -111,7 +111,7 @@ ?attr/selectableItemBackground + + From 49600fa3d62792952e080da4db067a3ae68a279c Mon Sep 17 00:00:00 2001 From: David Gonzalez Date: Mon, 27 Apr 2020 10:49:15 +0200 Subject: [PATCH 089/104] cleaning up state and visibility of the toolbar --- .../app/browser/BrowserTabViewModel.kt | 34 ++++++++----- .../res/layout/include_omnibar_toolbar.xml | 50 +++++++++++-------- 2 files changed, 52 insertions(+), 32 deletions(-) diff --git a/app/src/main/java/com/duckduckgo/app/browser/BrowserTabViewModel.kt b/app/src/main/java/com/duckduckgo/app/browser/BrowserTabViewModel.kt index 358426a47eea..e4e0735dd60c 100644 --- a/app/src/main/java/com/duckduckgo/app/browser/BrowserTabViewModel.kt +++ b/app/src/main/java/com/duckduckgo/app/browser/BrowserTabViewModel.kt @@ -195,7 +195,7 @@ class BrowserTabViewModel( object GenerateWebViewPreviewImage : Command() object LaunchTabSwitcher : Command() class ShowErrorWithAction(val action: () -> Unit) : Command() - sealed class DaxCommand: Command() { + sealed class DaxCommand : Command() { object FinishTrackerAnimation : DaxCommand() class HideDaxDialog(val cta: Cta) : DaxCommand() } @@ -490,16 +490,19 @@ class BrowserTabViewModel( val currentBrowserViewState = currentBrowserViewState() findInPageViewState.value = FindInPageViewState(visible = false, canFindInPage = true) browserViewState.value = currentBrowserViewState.copy( - browserShowing = true, - canAddBookmarks = true, - addToHomeEnabled = true, - addToHomeVisible = addToHomeCapabilityDetector.isAddToHomeSupported(), - canSharePage = true, - showPrivacyGrade = true, - canReportSite = true, - showSearchIcon = false + browserShowing = true, + canAddBookmarks = true, + addToHomeEnabled = true, + addToHomeVisible = addToHomeCapabilityDetector.isAddToHomeSupported(), + canSharePage = true, + showPrivacyGrade = true, + canReportSite = true, + showSearchIcon = false, + showClearButton = false ) + Timber.d("showPrivacyGrade=true, showSearchIcon=false, showClearButton=false") + if (duckDuckGoUrlDetector.isDuckDuckGoQueryUrl(url)) { statisticsUpdater.refreshSearchRetentionAtb() } @@ -535,8 +538,11 @@ class BrowserTabViewModel( addToHomeVisible = addToHomeCapabilityDetector.isAddToHomeSupported(), canSharePage = false, showPrivacyGrade = false, - canReportSite = false + canReportSite = false, + showSearchIcon = true, + showClearButton = true ) + Timber.d("showPrivacyGrade=false, showSearchIcon=true, showClearButton=true") } override fun pageRefreshed(refreshedUrl: String) { @@ -659,19 +665,23 @@ class BrowserTabViewModel( val showAutoCompleteSuggestions = hasFocus && query.isNotBlank() && hasQueryChanged && autoCompleteSuggestionsEnabled val showClearButton = hasFocus && query.isNotBlank() val showControls = !hasFocus || query.isBlank() + val showPrivacyGrade = !hasFocus + val showSearchIcon = hasFocus omnibarViewState.value = currentOmnibarViewState.copy(isEditing = hasFocus) val currentBrowserViewState = currentBrowserViewState() browserViewState.value = currentBrowserViewState.copy( - showPrivacyGrade = !hasFocus, - showSearchIcon = hasFocus, + showPrivacyGrade = showPrivacyGrade, + showSearchIcon = showSearchIcon, showTabsButton = showControls, showFireButton = showControls, showMenuButton = showControls, showClearButton = showClearButton ) + Timber.d("showPrivacyGrade=$showPrivacyGrade, showSearchIcon=$showSearchIcon, showClearButton=$showClearButton") + autoCompleteViewState.value = AutoCompleteViewState(showAutoCompleteSuggestions, autoCompleteSearchResults) if (hasQueryChanged && hasFocus && autoCompleteSuggestionsEnabled) { diff --git a/app/src/main/res/layout/include_omnibar_toolbar.xml b/app/src/main/res/layout/include_omnibar_toolbar.xml index 2b1a247f76ee..cd26d56e7ade 100644 --- a/app/src/main/res/layout/include_omnibar_toolbar.xml +++ b/app/src/main/res/layout/include_omnibar_toolbar.xml @@ -64,28 +64,38 @@ app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" /> - - - + app:layout_constraintTop_toTopOf="parent"> + + + + + + From b2c27178d4f237f84c69162d8241cb696b327079 Mon Sep 17 00:00:00 2001 From: David Gonzalez Date: Mon, 27 Apr 2020 14:24:43 +0200 Subject: [PATCH 090/104] updated etag for tests --- .../java/com/duckduckgo/app/trackerdetection/TdsTest.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/androidTest/java/com/duckduckgo/app/trackerdetection/TdsTest.kt b/app/src/androidTest/java/com/duckduckgo/app/trackerdetection/TdsTest.kt index 758c8bc0e536..252cb9068413 100644 --- a/app/src/androidTest/java/com/duckduckgo/app/trackerdetection/TdsTest.kt +++ b/app/src/androidTest/java/com/duckduckgo/app/trackerdetection/TdsTest.kt @@ -38,6 +38,6 @@ class TdsTest { } companion object { - private const val DEFAULT_TDS_HASH_VALUE = -1752095080 + private const val DEFAULT_TDS_HASH_VALUE = 671069862 } } \ No newline at end of file From 49d3629e42ca99ead44a3cd0b15dcdff5f164223 Mon Sep 17 00:00:00 2001 From: David Gonzalez Date: Mon, 27 Apr 2020 14:46:59 +0200 Subject: [PATCH 091/104] revert tdstest changes --- .../java/com/duckduckgo/app/trackerdetection/TdsTest.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/androidTest/java/com/duckduckgo/app/trackerdetection/TdsTest.kt b/app/src/androidTest/java/com/duckduckgo/app/trackerdetection/TdsTest.kt index 252cb9068413..758c8bc0e536 100644 --- a/app/src/androidTest/java/com/duckduckgo/app/trackerdetection/TdsTest.kt +++ b/app/src/androidTest/java/com/duckduckgo/app/trackerdetection/TdsTest.kt @@ -38,6 +38,6 @@ class TdsTest { } companion object { - private const val DEFAULT_TDS_HASH_VALUE = 671069862 + private const val DEFAULT_TDS_HASH_VALUE = -1752095080 } } \ No newline at end of file From b209a3c4178378c5ffd669a522dcadb1c097ffbe Mon Sep 17 00:00:00 2001 From: David Gonzalez Date: Mon, 27 Apr 2020 15:11:48 +0200 Subject: [PATCH 092/104] cleanup references --- .../main/java/com/duckduckgo/app/settings/SettingsActivity.kt | 1 - .../main/java/com/duckduckgo/app/statistics/VariantManager.kt | 1 - 2 files changed, 2 deletions(-) diff --git a/app/src/main/java/com/duckduckgo/app/settings/SettingsActivity.kt b/app/src/main/java/com/duckduckgo/app/settings/SettingsActivity.kt index 06c182470d0f..4e6026ed7ddb 100644 --- a/app/src/main/java/com/duckduckgo/app/settings/SettingsActivity.kt +++ b/app/src/main/java/com/duckduckgo/app/settings/SettingsActivity.kt @@ -52,7 +52,6 @@ import kotlinx.android.synthetic.main.content_settings_other.version import kotlinx.android.synthetic.main.content_settings_privacy.automaticallyClearWhatSetting import kotlinx.android.synthetic.main.content_settings_privacy.automaticallyClearWhenSetting import kotlinx.android.synthetic.main.include_toolbar.toolbar -import kotlinx.android.synthetic.main.content_settings_general.searchNotificationToggle import javax.inject.Inject class SettingsActivity : DuckDuckGoActivity(), SettingsAutomaticallyClearWhatFragment.Listener, SettingsAutomaticallyClearWhenFragment.Listener { diff --git a/app/src/main/java/com/duckduckgo/app/statistics/VariantManager.kt b/app/src/main/java/com/duckduckgo/app/statistics/VariantManager.kt index 673a87a858eb..1f6c337334d5 100644 --- a/app/src/main/java/com/duckduckgo/app/statistics/VariantManager.kt +++ b/app/src/main/java/com/duckduckgo/app/statistics/VariantManager.kt @@ -20,7 +20,6 @@ import androidx.annotation.WorkerThread import com.duckduckgo.app.statistics.VariantManager.Companion.DEFAULT_VARIANT import com.duckduckgo.app.statistics.VariantManager.Companion.referrerVariant import com.duckduckgo.app.statistics.VariantManager.VariantFeature.BottomBarNavigation -import com.duckduckgo.app.statistics.VariantManager.VariantFeature.StickySearchNotification import com.duckduckgo.app.statistics.store.StatisticsDataStore import timber.log.Timber import java.util.Locale From b2c55f6ab72bc66172b25299b5e88000f3d777c3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Gonz=C3=A1lez?= Date: Tue, 28 Apr 2020 10:08:34 +0200 Subject: [PATCH 093/104] add missing pixel after opening a new tab --- .../java/com/duckduckgo/app/browser/BrowserTabFragment.kt | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/app/src/main/java/com/duckduckgo/app/browser/BrowserTabFragment.kt b/app/src/main/java/com/duckduckgo/app/browser/BrowserTabFragment.kt index 4961307efc1e..7286f06e9e32 100644 --- a/app/src/main/java/com/duckduckgo/app/browser/BrowserTabFragment.kt +++ b/app/src/main/java/com/duckduckgo/app/browser/BrowserTabFragment.kt @@ -1390,7 +1390,10 @@ class BrowserTabFragment : Fragment(), FindListener, CoroutineScope, DaxDialogLi pixel.fire(String.format(Locale.US, Pixel.PixelName.MENU_ACTION_REFRESH_PRESSED.pixelName, variantManager.getVariant().key)) } onMenuItemClicked(view.sharePopupMenuItem) { viewModel.onShareSelected() } - onMenuItemClicked(view.newTabPopupMenuItem) { viewModel.userRequestedOpeningNewTab() } + onMenuItemClicked(view.newTabPopupMenuItem) { + viewModel.userRequestedOpeningNewTab() + pixel.fire(String.format(Locale.US, Pixel.PixelName.MENU_ACTION_NEW_TAB_PRESSED.pixelName, variantManager.getVariant().key)) + } onMenuItemClicked(view.addBookmarksPopupMenuItem) { launch { viewModel.onBookmarkAddRequested() } } onMenuItemClicked(view.findInPageMenuItem) { viewModel.onFindInPageSelected() } onMenuItemClicked(view.brokenSitePopupMenuItem) { viewModel.onBrokenSiteSelected() } From 50867954baa35e254521cf1b5d6d31a64f046f83 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Gonz=C3=A1lez?= Date: Tue, 28 Apr 2020 10:15:16 +0200 Subject: [PATCH 094/104] move this to the decorator --- .../app/browser/BrowserTabFragment.kt | 19 +++++++++++++------ build.gradle | 2 +- 2 files changed, 14 insertions(+), 7 deletions(-) diff --git a/app/src/main/java/com/duckduckgo/app/browser/BrowserTabFragment.kt b/app/src/main/java/com/duckduckgo/app/browser/BrowserTabFragment.kt index 7286f06e9e32..66967c099ae6 100644 --- a/app/src/main/java/com/duckduckgo/app/browser/BrowserTabFragment.kt +++ b/app/src/main/java/com/duckduckgo/app/browser/BrowserTabFragment.kt @@ -658,12 +658,7 @@ class BrowserTabFragment : Fragment(), FindListener, CoroutineScope, DaxDialogLi private fun openInNewBackgroundTab() { appBarLayout.setExpanded(true, true) viewModel.tabs.removeObservers(this) - tabsButton?.increment { - addTabsObserver() - } - bottomBarTabsItem.increment { - addTabsObserver() - } + decorator.incrementTabs() } private fun openExternalDialog(intent: Intent, fallbackUrl: String? = null, useFirstActivityFound: Boolean = true) { @@ -1509,6 +1504,18 @@ class BrowserTabFragment : Fragment(), FindListener, CoroutineScope, DaxDialogLi bottomBarTabsItem.hasUnread = tabs.firstOrNull { !it.viewed } != null } } + + fun incrementTabs() { + if (isBottomNavigationFeatureEnabled()){ + bottomBarTabsItem.increment { + addTabsObserver() + } + } else { + tabsButton?.increment { + addTabsObserver() + } + } + } } inner class BrowserTabFragmentRenderer { diff --git a/build.gradle b/build.gradle index 0822dc77e876..93bb5cb4166c 100644 --- a/build.gradle +++ b/build.gradle @@ -9,7 +9,7 @@ buildscript { jcenter() } dependencies { - classpath 'com.android.tools.build:gradle:3.6.3' + classpath 'com.android.tools.build:gradle:3.6.2' classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" classpath "com.android.tools.build.jetifier:jetifier-processor:$jetifier" From cbb947088cbf42736b951e5a66990e3307aa10fd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Gonz=C3=A1lez?= Date: Tue, 28 Apr 2020 10:15:35 +0200 Subject: [PATCH 095/104] duplicate call --- .../main/java/com/duckduckgo/app/browser/BrowserTabFragment.kt | 1 - 1 file changed, 1 deletion(-) diff --git a/app/src/main/java/com/duckduckgo/app/browser/BrowserTabFragment.kt b/app/src/main/java/com/duckduckgo/app/browser/BrowserTabFragment.kt index 66967c099ae6..fc3a623e5eb1 100644 --- a/app/src/main/java/com/duckduckgo/app/browser/BrowserTabFragment.kt +++ b/app/src/main/java/com/duckduckgo/app/browser/BrowserTabFragment.kt @@ -348,7 +348,6 @@ class BrowserTabFragment : Fragment(), FindListener, CoroutineScope, DaxDialogLi configureFindInPage() configureAutoComplete() configureKeyboardAwareLogoAnimation() - configureAppBar() decorateWithFeatures() From 6e471399ba2255dddc62496611b2f67d624f38b0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Gonz=C3=A1lez?= Date: Tue, 28 Apr 2020 10:19:41 +0200 Subject: [PATCH 096/104] better method naming --- .../java/com/duckduckgo/app/browser/BrowserTabFragment.kt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/src/main/java/com/duckduckgo/app/browser/BrowserTabFragment.kt b/app/src/main/java/com/duckduckgo/app/browser/BrowserTabFragment.kt index fc3a623e5eb1..b0213a4a7a46 100644 --- a/app/src/main/java/com/duckduckgo/app/browser/BrowserTabFragment.kt +++ b/app/src/main/java/com/duckduckgo/app/browser/BrowserTabFragment.kt @@ -341,7 +341,7 @@ class BrowserTabFragment : Fragment(), FindListener, CoroutineScope, DaxDialogLi super.onActivityCreated(savedInstanceState) configureObservers() - configureAppBar() + configurePrivacyGrade() configureWebView() viewModel.registerWebViewListener(webViewClient, webChromeClient) configureOmnibarTextInput() @@ -775,7 +775,7 @@ class BrowserTabFragment : Fragment(), FindListener, CoroutineScope, DaxDialogLi } } - private fun configureAppBar() { + private fun configurePrivacyGrade() { toolbar.privacyGradeButton.setOnClickListener { browserActivity?.launchPrivacyDashboard() } From 87341a5ce880f408b52365436cea671dbeb9c7af Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Gonz=C3=A1lez?= Date: Tue, 28 Apr 2020 10:34:53 +0200 Subject: [PATCH 097/104] remove duplicate call for this method --- .../java/com/duckduckgo/app/browser/BrowserTabFragment.kt | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/app/src/main/java/com/duckduckgo/app/browser/BrowserTabFragment.kt b/app/src/main/java/com/duckduckgo/app/browser/BrowserTabFragment.kt index b0213a4a7a46..27e89a1d8f22 100644 --- a/app/src/main/java/com/duckduckgo/app/browser/BrowserTabFragment.kt +++ b/app/src/main/java/com/duckduckgo/app/browser/BrowserTabFragment.kt @@ -1286,9 +1286,7 @@ class BrowserTabFragment : Fragment(), FindListener, CoroutineScope, DaxDialogLi inner class BrowserTabFragmentDecorator { fun decorateToolbar(viewState: BrowserViewState) { - if (variantManager.getVariant().hasFeature(VariantManager.VariantFeature.BottomBarNavigation)) { - decorator.hideToolbarMenu() - } else { + if (!variantManager.getVariant().hasFeature(VariantManager.VariantFeature.BottomBarNavigation)) { decorator.decorateToolbarActions(viewState) } } @@ -1299,10 +1297,6 @@ class BrowserTabFragment : Fragment(), FindListener, CoroutineScope, DaxDialogLi menuButton?.isVisible = viewState.showMenuButton } - private fun hideToolbarMenu() { - menuButton?.gone() - } - fun decorateWithToolbar() { hideBottomBar() decorateAppBarWithToolbarOnly() From 93b8a2820744b3c3d77a60229eeada6a2ba8eff3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Gonz=C3=A1lez?= Date: Tue, 28 Apr 2020 10:36:56 +0200 Subject: [PATCH 098/104] ensure bottombar is visible after opening a new tab --- .../main/java/com/duckduckgo/app/browser/BrowserTabFragment.kt | 1 + 1 file changed, 1 insertion(+) diff --git a/app/src/main/java/com/duckduckgo/app/browser/BrowserTabFragment.kt b/app/src/main/java/com/duckduckgo/app/browser/BrowserTabFragment.kt index 27e89a1d8f22..529644f17b3d 100644 --- a/app/src/main/java/com/duckduckgo/app/browser/BrowserTabFragment.kt +++ b/app/src/main/java/com/duckduckgo/app/browser/BrowserTabFragment.kt @@ -656,6 +656,7 @@ class BrowserTabFragment : Fragment(), FindListener, CoroutineScope, DaxDialogLi private fun openInNewBackgroundTab() { appBarLayout.setExpanded(true, true) + decorator.updateBottomBarVisibility(true, true) viewModel.tabs.removeObservers(this) decorator.incrementTabs() } From f07e7d737b67bdbdb9a654fb6fe335189c044788 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Gonz=C3=A1lez?= Date: Tue, 28 Apr 2020 10:40:03 +0200 Subject: [PATCH 099/104] another redundant call --- .../java/com/duckduckgo/app/browser/BrowserTabFragment.kt | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/app/src/main/java/com/duckduckgo/app/browser/BrowserTabFragment.kt b/app/src/main/java/com/duckduckgo/app/browser/BrowserTabFragment.kt index 529644f17b3d..424a2d2e1919 100644 --- a/app/src/main/java/com/duckduckgo/app/browser/BrowserTabFragment.kt +++ b/app/src/main/java/com/duckduckgo/app/browser/BrowserTabFragment.kt @@ -1308,6 +1308,7 @@ class BrowserTabFragment : Fragment(), FindListener, CoroutineScope, DaxDialogLi } fun decorateWithBottomBarSearch() { + bindBottomBarButtons() decorateBottomBarWithNavigationOnly() decorateAppBarWithBottomBar() createPopupMenuWithBottomBar() @@ -1397,10 +1398,6 @@ class BrowserTabFragment : Fragment(), FindListener, CoroutineScope, DaxDialogLi pixel.fire(String.format(Locale.US, Pixel.PixelName.MENU_ACTION_POPUP_OPENED.pixelName, variantManager.getVariant().key)) } - private fun decorateBottomBarWithNavigationOnly() { - bindBottomBarButtons() - } - private fun bindBottomBarButtons() { bottomNavigationBar.apply { onItemClicked(bottomBarFireItem) { @@ -1555,7 +1552,6 @@ class BrowserTabFragment : Fragment(), FindListener, CoroutineScope, DaxDialogLi } lastSeenBrowserViewState?.let { - decorator.decorateToolbar(it) renderToolbarMenus(it) } From e812c2fd3b443105aedb064f3b6c6b54d15edd76 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Gonz=C3=A1lez?= Date: Tue, 28 Apr 2020 10:48:12 +0200 Subject: [PATCH 100/104] renaming bottom bar only icons --- .../duckduckgo/app/tabs/ui/TabsPopupMenu.kt | 8 +++--- .../res/drawable/ic_bottom_bar_bookmarks.xml | 9 +++++++ ...c_search.xml => ic_botttom_bar_search.xml} | 0 .../res/drawable/ic_search_black_24dp.xml | 25 ------------------- .../layout_browser_bottom_navigation_bar.xml | 4 +-- 5 files changed, 14 insertions(+), 32 deletions(-) create mode 100644 app/src/main/res/drawable/ic_bottom_bar_bookmarks.xml rename app/src/main/res/drawable/{ic_search.xml => ic_botttom_bar_search.xml} (100%) delete mode 100644 app/src/main/res/drawable/ic_search_black_24dp.xml diff --git a/app/src/main/java/com/duckduckgo/app/tabs/ui/TabsPopupMenu.kt b/app/src/main/java/com/duckduckgo/app/tabs/ui/TabsPopupMenu.kt index 3fa79df9d16e..fab4fffac010 100644 --- a/app/src/main/java/com/duckduckgo/app/tabs/ui/TabsPopupMenu.kt +++ b/app/src/main/java/com/duckduckgo/app/tabs/ui/TabsPopupMenu.kt @@ -25,8 +25,6 @@ import android.view.View import android.view.ViewGroup.LayoutParams.WRAP_CONTENT import android.widget.PopupWindow import com.duckduckgo.app.browser.R -import com.duckduckgo.app.statistics.Variant -import com.duckduckgo.app.statistics.VariantManager class TabsPopupMenu(layoutInflater: LayoutInflater, view: View = inflate(layoutInflater, R.layout.popup_window_tabs_menu)) : PopupWindow(view, WRAP_CONTENT, WRAP_CONTENT, true) { @@ -55,14 +53,14 @@ class TabsPopupMenu(layoutInflater: LayoutInflater, view: View = inflate(layoutI fun show(rootView: View, anchorView: View) { val anchorLocation = IntArray(2) anchorView.getLocationOnScreen(anchorLocation) - val x = margin - val y = anchorLocation[1] + margin + val x = MARGIN + val y = anchorLocation[1] + MARGIN showAtLocation(rootView, Gravity.TOP or Gravity.END, x, y) } companion object { - private const val margin = 30 + private const val MARGIN = 30 fun inflate(layoutInflater: LayoutInflater, resourceId: Int): View { return layoutInflater.inflate(resourceId, null) diff --git a/app/src/main/res/drawable/ic_bottom_bar_bookmarks.xml b/app/src/main/res/drawable/ic_bottom_bar_bookmarks.xml new file mode 100644 index 000000000000..bface6f092e5 --- /dev/null +++ b/app/src/main/res/drawable/ic_bottom_bar_bookmarks.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_search.xml b/app/src/main/res/drawable/ic_botttom_bar_search.xml similarity index 100% rename from app/src/main/res/drawable/ic_search.xml rename to app/src/main/res/drawable/ic_botttom_bar_search.xml diff --git a/app/src/main/res/drawable/ic_search_black_24dp.xml b/app/src/main/res/drawable/ic_search_black_24dp.xml deleted file mode 100644 index ae26de2f1a9b..000000000000 --- a/app/src/main/res/drawable/ic_search_black_24dp.xml +++ /dev/null @@ -1,25 +0,0 @@ - - - - - diff --git a/app/src/main/res/layout/layout_browser_bottom_navigation_bar.xml b/app/src/main/res/layout/layout_browser_bottom_navigation_bar.xml index d62874e21c41..69faea48654f 100644 --- a/app/src/main/res/layout/layout_browser_bottom_navigation_bar.xml +++ b/app/src/main/res/layout/layout_browser_bottom_navigation_bar.xml @@ -26,7 +26,7 @@ android:layout_weight="1" android:background="?selectableItemBackgroundBorderless" android:contentDescription="@string/back" - android:src="@drawable/ic_bookmarks" /> + android:src="@drawable/ic_bottom_bar_bookmarks" /> + android:src="@drawable/ic_bottom_bar_search" /> Date: Tue, 28 Apr 2020 10:48:31 +0200 Subject: [PATCH 101/104] no longer used --- app/src/main/res/drawable/ic_bookmarks.xml | 9 --------- 1 file changed, 9 deletions(-) delete mode 100644 app/src/main/res/drawable/ic_bookmarks.xml diff --git a/app/src/main/res/drawable/ic_bookmarks.xml b/app/src/main/res/drawable/ic_bookmarks.xml deleted file mode 100644 index bface6f092e5..000000000000 --- a/app/src/main/res/drawable/ic_bookmarks.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - From d241ecb4412afd3d031a6e62f899c456c70e41dd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Gonz=C3=A1lez?= Date: Tue, 28 Apr 2020 10:53:02 +0200 Subject: [PATCH 102/104] proper icon name --- .../{ic_botttom_bar_search.xml => ic_bottom_bar_search.xml} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename app/src/main/res/drawable/{ic_botttom_bar_search.xml => ic_bottom_bar_search.xml} (100%) diff --git a/app/src/main/res/drawable/ic_botttom_bar_search.xml b/app/src/main/res/drawable/ic_bottom_bar_search.xml similarity index 100% rename from app/src/main/res/drawable/ic_botttom_bar_search.xml rename to app/src/main/res/drawable/ic_bottom_bar_search.xml From 2cd2d44abf322d89c472b8f857bc32c9fe05a1a9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Gonz=C3=A1lez?= Date: Tue, 28 Apr 2020 11:00:24 +0200 Subject: [PATCH 103/104] removing unnecessary method --- .../main/java/com/duckduckgo/app/browser/BrowserTabFragment.kt | 1 - 1 file changed, 1 deletion(-) diff --git a/app/src/main/java/com/duckduckgo/app/browser/BrowserTabFragment.kt b/app/src/main/java/com/duckduckgo/app/browser/BrowserTabFragment.kt index 424a2d2e1919..8d8c01ed1f53 100644 --- a/app/src/main/java/com/duckduckgo/app/browser/BrowserTabFragment.kt +++ b/app/src/main/java/com/duckduckgo/app/browser/BrowserTabFragment.kt @@ -1309,7 +1309,6 @@ class BrowserTabFragment : Fragment(), FindListener, CoroutineScope, DaxDialogLi fun decorateWithBottomBarSearch() { bindBottomBarButtons() - decorateBottomBarWithNavigationOnly() decorateAppBarWithBottomBar() createPopupMenuWithBottomBar() configureShowTabSwitcherListenerWithBottomBarNavigationOnly() From cc1327ea919554af05aa63afd57404ace7da20d0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Gonz=C3=A1lez?= Date: Tue, 28 Apr 2020 11:36:12 +0200 Subject: [PATCH 104/104] fix color reference pointing to wrong attribute --- app/src/main/res/values/themes.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/main/res/values/themes.xml b/app/src/main/res/values/themes.xml index 0f9d325bc199..ccdbb44764b8 100644 --- a/app/src/main/res/values/themes.xml +++ b/app/src/main/res/values/themes.xml @@ -220,7 +220,7 @@