From 9f2994ae36b4c88109adebba83c33774841e6bb5 Mon Sep 17 00:00:00 2001 From: Cristian Monforte Date: Wed, 17 Feb 2021 22:21:16 +0100 Subject: [PATCH 01/44] add checkpoints to report startup times --- .../app/browser/BrowserTabFragment.kt | 20 ++++-- .../app/global/DuckDuckGoApplication.kt | 61 +++++++++++++++++ .../duckduckgo/app/global/NextDrawListener.kt | 67 +++++++++++++++++++ .../app/global/WindowDelegateCallback.kt | 62 +++++++++++++++++ 4 files changed, 206 insertions(+), 4 deletions(-) create mode 100644 app/src/main/java/com/duckduckgo/app/global/NextDrawListener.kt create mode 100644 app/src/main/java/com/duckduckgo/app/global/WindowDelegateCallback.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 7487cba2ed2d..0cf1762a92dc 100644 --- a/app/src/main/java/com/duckduckgo/app/browser/BrowserTabFragment.kt +++ b/app/src/main/java/com/duckduckgo/app/browser/BrowserTabFragment.kt @@ -28,10 +28,7 @@ import android.content.pm.PackageManager import android.content.res.Configuration import android.media.MediaScannerConnection import android.net.Uri -import android.os.Bundle -import android.os.Environment -import android.os.Handler -import android.os.Message +import android.os.* import android.provider.Settings import android.text.Editable import android.view.* @@ -92,6 +89,7 @@ import com.duckduckgo.app.browser.useragent.UserAgentProvider import com.duckduckgo.app.cta.ui.* import com.duckduckgo.app.fire.fireproofwebsite.data.FireproofWebsiteEntity import com.duckduckgo.app.fire.fireproofwebsite.data.website +import com.duckduckgo.app.global.DuckDuckGoApplication import com.duckduckgo.app.global.ViewModelFactory import com.duckduckgo.app.global.model.orderedTrackingEntities import com.duckduckgo.app.global.view.* @@ -277,6 +275,10 @@ class BrowserTabFragment : private val pulseAnimation: PulseAnimation = PulseAnimation(this) + var activityOnCreateMs: Long = 0 + var activityOnCreatedMs: Long = 0 + var activityOnResumeMs: Long = 0 + override fun onAttach(context: Context) { AndroidSupportInjection.inject(this) super.onAttach(context) @@ -284,6 +286,8 @@ class BrowserTabFragment : override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) + activityOnCreateMs = SystemClock.uptimeMillis() + removeDaxDialogFromActivity() renderer = BrowserTabFragmentRenderer() decorator = BrowserTabFragmentDecorator() @@ -325,6 +329,7 @@ class BrowserTabFragment : } } }) + activityOnCreatedMs = SystemClock.uptimeMillis() } private fun getDaxDialogFromActivity(): Fragment? = activity?.supportFragmentManager?.findFragmentByTag(DAX_DIALOG_DIALOG_TAG) @@ -374,6 +379,8 @@ class BrowserTabFragment : } addTextChangedListeners() + + activityOnResumeMs = SystemClock.uptimeMillis() } override fun onPause() { @@ -1463,6 +1470,11 @@ class BrowserTabFragment : private fun decorateToolbarWithButtons() { fireMenuButton?.show() fireMenuButton?.setOnClickListener { + val appMS = (activity!!.application as DuckDuckGoApplication).applicationOnCreateMs + val frameMS = (activity!!.application as DuckDuckGoApplication).firstFrameDoneMs + val drawMS = (activity!!.application as DuckDuckGoApplication).firstDrawMs + Timber.i("PROFILING: $appMS / $frameMS / $drawMS") + Timber.i("PROFILING: $activityOnCreateMs / $activityOnCreatedMs / $activityOnResumeMs") browserActivity?.launchFire() pixel.fire( Pixel.PixelName.MENU_ACTION_FIRE_PRESSED.pixelName, diff --git a/app/src/main/java/com/duckduckgo/app/global/DuckDuckGoApplication.kt b/app/src/main/java/com/duckduckgo/app/global/DuckDuckGoApplication.kt index 21444cc81a98..556fb87d855b 100644 --- a/app/src/main/java/com/duckduckgo/app/global/DuckDuckGoApplication.kt +++ b/app/src/main/java/com/duckduckgo/app/global/DuckDuckGoApplication.kt @@ -16,9 +16,15 @@ package com.duckduckgo.app.global +import android.app.Activity import android.app.Application import android.content.IntentFilter import android.os.Build +import android.os.Bundle +import android.os.Handler +import android.os.SystemClock +import android.view.Choreographer +import android.view.View import androidx.lifecycle.Lifecycle import androidx.lifecycle.LifecycleObserver import androidx.lifecycle.OnLifecycleEvent @@ -31,7 +37,9 @@ import com.duckduckgo.app.browser.shortcut.ShortcutReceiver import com.duckduckgo.app.di.AppComponent import com.duckduckgo.app.di.DaggerAppComponent import com.duckduckgo.app.fire.* +import com.duckduckgo.app.global.NextDrawListener.Companion.onNextDraw import com.duckduckgo.app.global.Theming.initializeTheme +import com.duckduckgo.app.global.WindowDelegateCallback.Companion.onDecorViewReady import com.duckduckgo.app.global.initialization.AppDataLoader import com.duckduckgo.app.global.install.AppInstallStore import com.duckduckgo.app.global.rating.AppEnjoymentLifecycleObserver @@ -179,8 +187,61 @@ open class DuckDuckGoApplication : HasAndroidInjector, Application(), LifecycleO open lateinit var daggerAppComponent: AppComponent + var applicationOnCreateMs: Long = 0 + var firstFrameDoneMs: Long = 0 + var firstDrawMs: Long = 0 + override fun onCreate() { super.onCreate() + var firstDraw = false + val handler = Handler() + + applicationOnCreateMs = SystemClock.uptimeMillis() + + registerActivityLifecycleCallbacks( + object : ActivityLifecycleCallbacks { + override fun onActivityCreated(activity: Activity, savedInstanceState: Bundle?) { + if (firstDraw) return + val window = activity.window + window.onDecorViewReady { + window.decorView.onNextDraw { + if (firstDraw) return@onNextDraw + firstDraw = true + handler.postAtFrontOfQueue { + firstDrawMs = SystemClock.uptimeMillis() + } + } + } + } + + override fun onActivityStarted(activity: Activity) { + + } + + override fun onActivityResumed(activity: Activity) { + } + + override fun onActivityPaused(activity: Activity) { + + } + + override fun onActivityStopped(activity: Activity) { + + } + + override fun onActivitySaveInstanceState(activity: Activity, outState: Bundle) { + + } + + override fun onActivityDestroyed(activity: Activity) { + + } + } + ) + + Choreographer.getInstance().postFrameCallback { + firstFrameDoneMs = SystemClock.uptimeMillis() + } configureLogging() configureDependencyInjection() diff --git a/app/src/main/java/com/duckduckgo/app/global/NextDrawListener.kt b/app/src/main/java/com/duckduckgo/app/global/NextDrawListener.kt new file mode 100644 index 000000000000..aa0afbbe0a5b --- /dev/null +++ b/app/src/main/java/com/duckduckgo/app/global/NextDrawListener.kt @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2021 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.global + +import android.os.Handler +import android.os.Looper +import android.view.View +import android.view.ViewTreeObserver + +class NextDrawListener( + val view: View, + val onDrawCallback: () -> Unit +) : ViewTreeObserver.OnDrawListener { + + val handler = Handler(Looper.getMainLooper()) + var invoked = false + + override fun onDraw() { + if (invoked) return + invoked = true + onDrawCallback() + handler.post { + if (view.viewTreeObserver.isAlive) { + view.viewTreeObserver.removeOnDrawListener(this) + } + } + } + + companion object { + fun View.onNextDraw(onDrawCallback: () -> Unit) { + if (viewTreeObserver.isAlive && isAttachedToWindow) { + addNextDrawListener(onDrawCallback) + } else { + // Wait until attached + addOnAttachStateChangeListener( + object : View.OnAttachStateChangeListener { + override fun onViewAttachedToWindow(v: View) { + addNextDrawListener(onDrawCallback) + removeOnAttachStateChangeListener(this) + } + + override fun onViewDetachedFromWindow(v: View) = Unit + }) + } + } + + private fun View.addNextDrawListener(callback: () -> Unit) { + viewTreeObserver.addOnDrawListener( + NextDrawListener(this, callback) + ) + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/duckduckgo/app/global/WindowDelegateCallback.kt b/app/src/main/java/com/duckduckgo/app/global/WindowDelegateCallback.kt new file mode 100644 index 000000000000..d94c8e0626aa --- /dev/null +++ b/app/src/main/java/com/duckduckgo/app/global/WindowDelegateCallback.kt @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2021 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.global + +import android.view.Window + +class WindowDelegateCallback constructor( + private val delegate: Window.Callback +) : Window.Callback by delegate { + + val onContentChangedCallbacks = mutableListOf<() -> Boolean>() + + override fun onContentChanged() { + onContentChangedCallbacks.removeAll { callback -> + !callback() + } + delegate.onContentChanged() + } + + companion object { + fun Window.onDecorViewReady(callback: () -> Unit) { + if (peekDecorView() == null) { + onContentChanged { + callback() + return@onContentChanged false + } + } else { + callback() + } + } + + fun Window.onContentChanged(block: () -> Boolean) { + val callback = wrapCallback() + callback.onContentChangedCallbacks += block + } + + private fun Window.wrapCallback(): WindowDelegateCallback { + val currentCallback = callback + return if (currentCallback is WindowDelegateCallback) { + currentCallback + } else { + val newCallback = WindowDelegateCallback(currentCallback) + callback = newCallback + newCallback + } + } + } +} \ No newline at end of file From 188979d1c9f9f6c973ade62b16c80701fca39a02 Mon Sep 17 00:00:00 2001 From: Cristian Monforte Date: Fri, 19 Feb 2021 15:35:13 +0100 Subject: [PATCH 02/44] code to trace app start --- app/build.gradle | 1 + app/src/main/AndroidManifest.xml | 5 ++ .../app/browser/BrowserTabFragment.kt | 2 + .../duckduckgo/app/global/AppStartListener.kt | 57 +++++++++++++++++++ 4 files changed, 65 insertions(+) create mode 100644 app/src/main/java/com/duckduckgo/app/global/AppStartListener.kt diff --git a/app/build.gradle b/app/build.gradle index 94a012305303..f4f2a66332af 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -53,6 +53,7 @@ android { ] } release { + debuggable true minifyEnabled false proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' signingConfig signingConfigs.release diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 193cef9f5e8f..c85b38d46eed 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -43,6 +43,11 @@ android:resource="@xml/provider_paths"/> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file From 23cdcdbf5884f68b135926b10c62024b4c0531a4 Mon Sep 17 00:00:00 2001 From: Cristian Monforte Date: Sun, 21 Feb 2021 14:51:45 +0100 Subject: [PATCH 04/44] unnecessary element in layout --- app/src/main/res/layout/fragment_browser_tab.xml | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/app/src/main/res/layout/fragment_browser_tab.xml b/app/src/main/res/layout/fragment_browser_tab.xml index 7efa36945dcb..ccd51d5cfd42 100644 --- a/app/src/main/res/layout/fragment_browser_tab.xml +++ b/app/src/main/res/layout/fragment_browser_tab.xml @@ -23,16 +23,6 @@ - - Date: Sun, 21 Feb 2021 14:52:37 +0100 Subject: [PATCH 05/44] replace contraintlayout for framelayout, optimization --- app/src/main/res/layout/activity_launch.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/src/main/res/layout/activity_launch.xml b/app/src/main/res/layout/activity_launch.xml index 3329cbe44848..40ad31eed98e 100644 --- a/app/src/main/res/layout/activity_launch.xml +++ b/app/src/main/res/layout/activity_launch.xml @@ -14,12 +14,12 @@ ~ limitations under the License. --> - - + From c607ee93d8192bc777756d934e24812d5decf477 Mon Sep 17 00:00:00 2001 From: Cristian Monforte Date: Sun, 21 Feb 2021 14:53:55 +0100 Subject: [PATCH 06/44] replace contraintlayout for framelayout --- app/src/main/res/layout/activity_browser.xml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/app/src/main/res/layout/activity_browser.xml b/app/src/main/res/layout/activity_browser.xml index fb9271a2f609..dce433d92e8c 100644 --- a/app/src/main/res/layout/activity_browser.xml +++ b/app/src/main/res/layout/activity_browser.xml @@ -16,7 +16,7 @@ ~ limitations under the License. --> - - + + From fd3c8b64be4156205e09ffdde74e8c23d03b226c Mon Sep 17 00:00:00 2001 From: Cristian Monforte Date: Sun, 21 Feb 2021 14:54:15 +0100 Subject: [PATCH 07/44] replace contraintlayout for framelayout --- app/src/main/res/layout/activity_browser.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/main/res/layout/activity_browser.xml b/app/src/main/res/layout/activity_browser.xml index dce433d92e8c..f27ee208a4f0 100644 --- a/app/src/main/res/layout/activity_browser.xml +++ b/app/src/main/res/layout/activity_browser.xml @@ -22,7 +22,7 @@ android:layout_height="match_parent" tools:context="com.duckduckgo.app.browser.BrowserActivity"> - From bb3e86c19280a26a25d3d77dfee6afe574ed383c Mon Sep 17 00:00:00 2001 From: Cristian Monforte Date: Sun, 21 Feb 2021 14:54:33 +0100 Subject: [PATCH 08/44] show mockup toolbar in browseractivity --- app/src/main/res/layout/activity_browser.xml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/app/src/main/res/layout/activity_browser.xml b/app/src/main/res/layout/activity_browser.xml index f27ee208a4f0..3df72a13464e 100644 --- a/app/src/main/res/layout/activity_browser.xml +++ b/app/src/main/res/layout/activity_browser.xml @@ -22,6 +22,8 @@ android:layout_height="match_parent" tools:context="com.duckduckgo.app.browser.BrowserActivity"> + + Date: Mon, 22 Feb 2021 17:25:47 +0100 Subject: [PATCH 09/44] make errorSnackbar lazy --- .../duckduckgo/app/browser/BrowserTabFragment.kt | 14 +++++++++----- 1 file changed, 9 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 27e43b5f9836..19b41662d6ad 100644 --- a/app/src/main/java/com/duckduckgo/app/browser/BrowserTabFragment.kt +++ b/app/src/main/java/com/duckduckgo/app/browser/BrowserTabFragment.kt @@ -246,7 +246,7 @@ class BrowserTabFragment : private var webView: DuckDuckGoWebView? = null - private val errorSnackbar: Snackbar by lazy { + private val errorSnackbar = lazy { Snackbar.make(browserLayout, R.string.crashedWebViewErrorMessage, Snackbar.LENGTH_INDEFINITE) .setBehavior(NonDismissibleBehavior()) } @@ -495,7 +495,9 @@ class BrowserTabFragment : } private fun showHome() { - errorSnackbar.dismiss() + if (errorSnackbar.isInitialized()) { + errorSnackbar.value.dismiss() + } newTabLayout.show() appBarLayout.setExpanded(true) webView?.onPause() @@ -703,9 +705,11 @@ class BrowserTabFragment : private fun showErrorSnackbar(command: Command.ShowErrorWithAction) { // Snackbar is global and it should appear only the foreground fragment - if (!errorSnackbar.view.isAttachedToWindow && isVisible) { - errorSnackbar.setText(command.textResId) - errorSnackbar.setAction(R.string.crashedWebViewErrorAction) { command.action() }.show() + with(errorSnackbar.value) { + if (!view.isAttachedToWindow && isVisible) { + setText(command.textResId) + setAction(R.string.crashedWebViewErrorAction) { command.action() }.show() + } } } From 48b15f485d7dbdcdaca3b9accd506948fbef6c21 Mon Sep 17 00:00:00 2001 From: Cristian Monforte Date: Mon, 22 Feb 2021 17:26:11 +0100 Subject: [PATCH 10/44] delay popupbrowsermenu creation until requested --- .../com/duckduckgo/app/browser/BrowserTabFragment.kt | 12 ++++++++++-- 1 file changed, 10 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 19b41662d6ad..2aa7bc8e0ec5 100644 --- a/app/src/main/java/com/duckduckgo/app/browser/BrowserTabFragment.kt +++ b/app/src/main/java/com/duckduckgo/app/browser/BrowserTabFragment.kt @@ -1447,7 +1447,7 @@ class BrowserTabFragment : fun decorateWithFeatures() { decorateToolbarWithButtons() - createPopupMenu() + setListenerPopupMenu() configureShowTabSwitcherListener() configureLongClickOpensNewTabListener() } @@ -1492,6 +1492,8 @@ class BrowserTabFragment : } private fun createPopupMenu() { + if(this@BrowserTabFragment::popupMenu.isInitialized) return + popupMenu = BrowserPopupMenu(layoutInflater, variantManager.getVariant()) val view = popupMenu.contentView popupMenu.apply { @@ -1547,7 +1549,11 @@ class BrowserTabFragment : viewModel.onPinPageToHomeSelected() } } + } + + private fun setListenerPopupMenu() { browserMenu.setOnClickListener { + createPopupMenu() hideKeyboardImmediately() launchTopAnchoredPopupMenu() } @@ -1769,6 +1775,8 @@ class BrowserTabFragment : } private fun renderPopupMenus(browserShowing: Boolean, viewState: BrowserViewState) { + if(!this@BrowserTabFragment::popupMenu.isInitialized) return + popupMenu.contentView.apply { backPopupMenuItem.isEnabled = viewState.canGoBack forwardPopupMenuItem.isEnabled = viewState.canGoForward @@ -1821,7 +1829,7 @@ class BrowserTabFragment : hideFindInPage() } - popupMenu.contentView.findInPageMenuItem?.isEnabled = viewState.canFindInPage + //popupMenu.contentView.findInPageMenuItem?.isEnabled = viewState.canFindInPage } fun renderCtaViewState(viewState: CtaViewState) { From b0b617083e95f1d2973c39a8cbe2db3c45636817 Mon Sep 17 00:00:00 2001 From: Cristian Monforte Date: Mon, 22 Feb 2021 17:27:00 +0100 Subject: [PATCH 11/44] replace contraintlayout from popup menu by linearlayout --- .../res/layout/popup_window_browser_menu.xml | 25 +++++-------------- 1 file changed, 6 insertions(+), 19 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 13e294a039bd..b7e0959d5027 100644 --- a/app/src/main/res/layout/popup_window_browser_menu.xml +++ b/app/src/main/res/layout/popup_window_browser_menu.xml @@ -14,21 +14,18 @@ ~ limitations under the License. --> - + android:orientation="horizontal"> - - + android:layout_height="wrap_content"> - - \ No newline at end of file + \ No newline at end of file From 89051286e6aa337c295d31ea32a1c3deba9eb38b Mon Sep 17 00:00:00 2001 From: Cristian Monforte Date: Wed, 24 Feb 2021 14:16:05 +0100 Subject: [PATCH 12/44] disable including url mockup in browseractivity --- app/src/main/res/layout/activity_browser.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/main/res/layout/activity_browser.xml b/app/src/main/res/layout/activity_browser.xml index 3df72a13464e..9033930f41b9 100644 --- a/app/src/main/res/layout/activity_browser.xml +++ b/app/src/main/res/layout/activity_browser.xml @@ -22,7 +22,7 @@ android:layout_height="match_parent" tools:context="com.duckduckgo.app.browser.BrowserActivity"> - + Date: Wed, 24 Feb 2021 14:36:58 +0100 Subject: [PATCH 13/44] remove top_cta from layout. It will never appear based on our current logic. --- app/src/main/res/layout/include_new_browser_tab.xml | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/app/src/main/res/layout/include_new_browser_tab.xml b/app/src/main/res/layout/include_new_browser_tab.xml index f6c9bfe78b18..9c7652863be9 100644 --- a/app/src/main/res/layout/include_new_browser_tab.xml +++ b/app/src/main/res/layout/include_new_browser_tab.xml @@ -26,17 +26,6 @@ tools:context="com.duckduckgo.app.browser.BrowserActivity" tools:showIn="@layout/fragment_browser_tab"> - - Date: Wed, 24 Feb 2021 14:37:54 +0100 Subject: [PATCH 14/44] set all views gone to avoid rendering them when view inflated --- app/src/main/res/layout/include_new_browser_tab.xml | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/app/src/main/res/layout/include_new_browser_tab.xml b/app/src/main/res/layout/include_new_browser_tab.xml index 9c7652863be9..ca7fdf47588c 100644 --- a/app/src/main/res/layout/include_new_browser_tab.xml +++ b/app/src/main/res/layout/include_new_browser_tab.xml @@ -38,8 +38,9 @@ app:layout_constraintEnd_toEndOf="parent" app:layout_constraintHeight_max="180dp" app:layout_constraintStart_toStartOf="parent" - app:layout_constraintTop_toBottomOf="@id/ctaTopContainer" - app:layout_constraintWidth_max="180dp" /> + app:layout_constraintTop_toTopOf="parent" + app:layout_constraintWidth_max="180dp" + android:visibility="gone"/> + app:layout_constraintWidth_max="600dp" + android:visibility="gone"/> Date: Wed, 24 Feb 2021 14:38:15 +0100 Subject: [PATCH 15/44] remove constraint layout from find_in_page layout --- .../main/res/layout/include_find_in_page.xml | 80 ++++++------------- 1 file changed, 24 insertions(+), 56 deletions(-) diff --git a/app/src/main/res/layout/include_find_in_page.xml b/app/src/main/res/layout/include_find_in_page.xml index 0477d991d45a..f01c2d3d7b01 100644 --- a/app/src/main/res/layout/include_find_in_page.xml +++ b/app/src/main/res/layout/include_find_in_page.xml @@ -14,7 +14,7 @@ ~ limitations under the License. --> - @@ -29,6 +30,7 @@ android:id="@+id/findInPageInput" android:layout_width="0dp" android:layout_height="match_parent" + android:layout_weight="1" android:layout_marginStart="12dp" android:layout_marginEnd="12dp" android:background="?attr/colorPrimary" @@ -53,64 +55,30 @@ android:layout_height="wrap_content" android:layout_marginEnd="10dp" android:textColor="?attr/omnibarTextColor" - app:layout_constraintBottom_toBottomOf="parent" - app:layout_constraintEnd_toStartOf="@id/findInPageControlButtons" - app:layout_constraintStart_toEndOf="@id/findInPageInput" - app:layout_constraintTop_toTopOf="parent" - app:layout_constraintVertical_bias="0.5" tools:text="1/10" /> - - - - - - + android:layout_marginStart="6dp" + android:contentDescription="@string/previousSearchTermDescription" + android:src="@drawable/ic_keyboard_arrow_up_24dp"/> - - - + + - \ No newline at end of file + \ No newline at end of file From b629123d14b3c30fcec4686ee9e4d64f6daaa681 Mon Sep 17 00:00:00 2001 From: Cristian Monforte Date: Wed, 24 Feb 2021 14:38:40 +0100 Subject: [PATCH 16/44] Simplify toolbar_mockup layout --- .../layout/include_omnibar_toolbar_mockup.xml | 186 +++++++----------- 1 file changed, 75 insertions(+), 111 deletions(-) diff --git a/app/src/main/res/layout/include_omnibar_toolbar_mockup.xml b/app/src/main/res/layout/include_omnibar_toolbar_mockup.xml index b1281bd04369..13f9f49a98ed 100644 --- a/app/src/main/res/layout/include_omnibar_toolbar_mockup.xml +++ b/app/src/main/res/layout/include_omnibar_toolbar_mockup.xml @@ -30,126 +30,90 @@ android:background="?toolbarBgColor" android:theme="@style/AppTheme.Dark.AppBarOverlay"> - + - - - - - - - - - - - + android:contentDescription="@string/privacyGradeContentDescription" + android:gravity="center" + android:padding="4dp" + android:src="@drawable/ic_loupe_24dp" /> + + - - + - + android:layout_gravity="center" + android:background="?attr/selectableItemBackgroundBorderless" + android:contentDescription="@string/browserPopupMenu" + android:padding="3dp" + android:src="@drawable/ic_fire" /> + - + + + - + - + \ No newline at end of file From e7642f7e26756b5c99e09182bffca93d15889317 Mon Sep 17 00:00:00 2001 From: Cristian Monforte Date: Wed, 24 Feb 2021 14:39:03 +0100 Subject: [PATCH 17/44] Remove unnecessary contraintlayouts --- .../main/res/layout/fragment_browser_tab.xml | 27 +++++++------------ 1 file changed, 10 insertions(+), 17 deletions(-) diff --git a/app/src/main/res/layout/fragment_browser_tab.xml b/app/src/main/res/layout/fragment_browser_tab.xml index ccd51d5cfd42..2ab4b117b23e 100644 --- a/app/src/main/res/layout/fragment_browser_tab.xml +++ b/app/src/main/res/layout/fragment_browser_tab.xml @@ -44,16 +44,14 @@ android:clipToPadding="false" android:elevation="4dp" app:layout_behavior="@string/appbar_scrolling_view_behavior" - app:layout_constraintEnd_toEndOf="parent" - app:layout_constraintStart_toStartOf="parent" - app:layout_constraintTop_toTopOf="parent" tools:itemCount="3" tools:listitem="@layout/item_autocomplete_search_suggestion" tools:visibility="visible" /> - + - - + @@ -85,6 +79,5 @@ android:layout_height="match_parent" android:focusableInTouchMode="true" /> - - + \ No newline at end of file From 1c7ab6653fb14a991ecb1c4efcc51c43d0142629 Mon Sep 17 00:00:00 2001 From: Cristian Monforte Date: Wed, 24 Feb 2021 15:50:33 +0100 Subject: [PATCH 18/44] animate fragment from bottom after clearing data --- app/src/main/java/com/duckduckgo/app/browser/BrowserActivity.kt | 1 + 1 file changed, 1 insertion(+) diff --git a/app/src/main/java/com/duckduckgo/app/browser/BrowserActivity.kt b/app/src/main/java/com/duckduckgo/app/browser/BrowserActivity.kt index c1dc7e50da22..9a35bc99a511 100644 --- a/app/src/main/java/com/duckduckgo/app/browser/BrowserActivity.kt +++ b/app/src/main/java/com/duckduckgo/app/browser/BrowserActivity.kt @@ -148,6 +148,7 @@ class BrowserActivity : DuckDuckGoActivity(), CoroutineScope by MainScope() { val transaction = supportFragmentManager.beginTransaction() val tab = currentTab if (tab == null) { + transaction.setCustomAnimations(R.anim.slide_from_bottom, 0) transaction.replace(R.id.fragmentContainer, fragment, tabId) } else { transaction.hide(tab) From 50abe497a93303287ee7fde57958c6f41a595895 Mon Sep 17 00:00:00 2001 From: Cristian Monforte Date: Mon, 1 Mar 2021 11:13:08 +0100 Subject: [PATCH 19/44] Refactor DDGLogoListener to just hide-show background image --- .../app/browser/BrowserTabFragment.kt | 19 ++-- .../app/browser/HomeBackgroundLogo.kt | 66 +++++++++++ ...LogoHidingLayoutChangeLifecycleListener.kt | 107 ------------------ .../res/layout/include_new_browser_tab.xml | 6 +- 4 files changed, 75 insertions(+), 123 deletions(-) create mode 100644 app/src/main/java/com/duckduckgo/app/browser/HomeBackgroundLogo.kt delete mode 100644 app/src/main/java/com/duckduckgo/app/browser/LogoHidingLayoutChangeLifecycleListener.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 2aa7bc8e0ec5..f6a9815bba50 100644 --- a/app/src/main/java/com/duckduckgo/app/browser/BrowserTabFragment.kt +++ b/app/src/main/java/com/duckduckgo/app/browser/BrowserTabFragment.kt @@ -263,7 +263,7 @@ class BrowserTabFragment : } } - private val logoHidingListener by lazy { LogoHidingLayoutChangeLifecycleListener(ddgLogo) } + private val homeBackgroundLogo by lazy { HomeBackgroundLogo(ddgLogo) } private val ctaViewStateObserver = Observer { it?.let { renderer.renderCtaViewState(it) } @@ -371,7 +371,6 @@ class BrowserTabFragment : appBarLayout.setExpanded(true) viewModel.onViewResumed() - logoHidingListener.onResume() // onResume can be called for a hidden/backgrounded fragment, ensure this tab is visible. if (fragmentIsVisible()) { @@ -386,7 +385,6 @@ class BrowserTabFragment : } override fun onPause() { - logoHidingListener.onPause() dismissDownloadFragment() dismissAuthenticationDialog() super.onPause() @@ -503,7 +501,7 @@ class BrowserTabFragment : webView?.onPause() webView?.hide() omnibarScrolling.disableOmnibarScrolling(toolbarContainer) - logoHidingListener.onReadyToShowLogo() + homeBackgroundLogo.showLogo() } private fun showBrowser() { @@ -511,6 +509,7 @@ class BrowserTabFragment : webView?.show() webView?.onResume() omnibarScrolling.enableOmnibarScrolling(toolbarContainer) + homeBackgroundLogo.hideLogo() } fun submitQuery(query: String) { @@ -954,7 +953,6 @@ class BrowserTabFragment : disableTransitionType(DISAPPEARING) setDuration(LAYOUT_TRANSITION_MS) } - rootView.addOnLayoutChangeListener(logoHidingListener) } private fun userSelectedAutocomplete(suggestion: AutoCompleteSuggestion) { @@ -1838,8 +1836,6 @@ class BrowserTabFragment : } renderIfChanged(viewState, lastSeenCtaViewState) { - - ddgLogo.show() lastSeenCtaViewState = viewState removeNewTabLayoutClickListener() if (viewState.cta != null) { @@ -1880,7 +1876,7 @@ class BrowserTabFragment : } private fun showDaxCta(configuration: DaxBubbleCta) { - ddgLogo.hide() + homeBackgroundLogo.hideLogo() hideHomeCta() hideHomeTopCta() configuration.showCta(daxCtaContainer) @@ -1895,7 +1891,7 @@ class BrowserTabFragment : hideDaxCta() hideHomeCta() - logoHidingListener.callToActionView = ctaTopContainer + /*logoHidingListener.callToActionView = ctaTopContainer configuration.showCta(ctaTopContainer) ctaTopContainer.setOnClickListener { @@ -1903,7 +1899,7 @@ class BrowserTabFragment : } ctaTopContainer.closeButton.setOnClickListener { viewModel.onUserDismissedCta() - } + }*/ } private fun showHomeCta(configuration: HomePanelCta) { @@ -1914,6 +1910,7 @@ class BrowserTabFragment : } else { configuration.showCta(ctaContainer) } + homeBackgroundLogo.showLogo() } private fun hideDaxCta() { @@ -1937,13 +1934,11 @@ class BrowserTabFragment : ctaContainer.removeAllViews() inflate(context, R.layout.include_cta, ctaContainer) - logoHidingListener.callToActionView = ctaContainer configuration.showCta(ctaContainer) ctaContainer.ctaOkButton.setOnClickListener { viewModel.onUserClickCtaOkButton() } - ctaContainer.ctaDismissButton.setOnClickListener { viewModel.onUserDismissedCta() } diff --git a/app/src/main/java/com/duckduckgo/app/browser/HomeBackgroundLogo.kt b/app/src/main/java/com/duckduckgo/app/browser/HomeBackgroundLogo.kt new file mode 100644 index 000000000000..b37e281c5893 --- /dev/null +++ b/app/src/main/java/com/duckduckgo/app/browser/HomeBackgroundLogo.kt @@ -0,0 +1,66 @@ +/* + * 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.view.View +import android.view.animation.AccelerateInterpolator +import com.duckduckgo.app.global.view.hide +import com.duckduckgo.app.global.view.show +import timber.log.Timber + +class HomeBackgroundLogo(private var ddgLogoView: View) { + + private var readyToShowLogo = false + + fun showLogo() { + this.readyToShowLogo = true + update() + } + + fun hideLogo() { + readyToShowLogo = false + update() + } + + private fun update() { + if (readyToShowLogo) { + fadeLogoIn() + } else { + fadeLogoOut() + } + } + + private fun fadeLogoIn() { + Timber.v("showLogo") + ddgLogoView.animate().apply { + duration = FADE_IN_DURATION + interpolator = AccelerateInterpolator() + alpha(1f) + ddgLogoView.show() + } + } + + private fun fadeLogoOut() { + Timber.v("hideLogo") + ddgLogoView.hide() + + } + + companion object { + private const val FADE_IN_DURATION = 50L + } +} diff --git a/app/src/main/java/com/duckduckgo/app/browser/LogoHidingLayoutChangeLifecycleListener.kt b/app/src/main/java/com/duckduckgo/app/browser/LogoHidingLayoutChangeLifecycleListener.kt deleted file mode 100644 index d890203d7740..000000000000 --- a/app/src/main/java/com/duckduckgo/app/browser/LogoHidingLayoutChangeLifecycleListener.kt +++ /dev/null @@ -1,107 +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.graphics.Rect -import android.view.View -import android.view.animation.AccelerateInterpolator -import androidx.core.view.isGone -import androidx.core.view.isVisible -import com.duckduckgo.app.global.view.toDp -import timber.log.Timber - -class LogoHidingLayoutChangeLifecycleListener(private var ddgLogoView: View) : View.OnLayoutChangeListener { - - var callToActionView: View? = null - - private var readyToShowLogo = false - - fun onReadyToShowLogo() { - readyToShowLogo = true - update() - } - - override fun onLayoutChange(view: View, left: Int, top: Int, right: Int, bottom: Int, oldLeft: Int, oldTop: Int, oldRight: Int, oldBottom: Int) { - update() - } - - fun onResume() { - update() - } - - fun onPause() { - hideLogo() - } - - private fun update() { - val heightDp = getHeightDp() - Timber.v("App height now: $heightDp dp, call to action button showing: ${callToActionView?.isVisible}") - if (readyToShowLogo && enoughRoomForLogo(heightDp)) { - fadeLogoIn() - } else { - fadeLogoOut() - } - } - - private fun fadeLogoIn() { - ddgLogoView.animate().apply { - duration = FADE_IN_DURATION - interpolator = AccelerateInterpolator() - alpha(1f) - } - } - - private fun fadeLogoOut() { - ddgLogoView.animate().apply { - duration = FADE_OUT_DURATION - interpolator = AccelerateInterpolator() - alpha(0f) - } - } - - private fun hideLogo() { - ddgLogoView.alpha = 0f - } - - private fun getHeightDp(): Int { - val r = Rect() - ddgLogoView.getWindowVisibleDisplayFrame(r) - return r.height().toDp() - } - - private fun enoughRoomForLogo(heightDp: Int): Boolean { - - val isCallToActionHidden = callToActionView?.isGone ?: true - if (isCallToActionHidden) { - return true - } - val callToActionButtonHeightDp = callToActionView?.measuredHeight?.toDp() ?: 0 - val heightMinusCallToAction = heightDp - callToActionButtonHeightDp - if (heightMinusCallToAction >= MINIMUM_AVAILABLE_HEIGHT_REQUIRED_TO_SHOW_LOGO) { - return true - } - - return false - } - - companion object { - private const val MINIMUM_AVAILABLE_HEIGHT_REQUIRED_TO_SHOW_LOGO = 220 - private const val FADE_IN_DURATION = 300L - private const val FADE_OUT_DURATION = 300L - } - -} diff --git a/app/src/main/res/layout/include_new_browser_tab.xml b/app/src/main/res/layout/include_new_browser_tab.xml index ca7fdf47588c..73066712ca84 100644 --- a/app/src/main/res/layout/include_new_browser_tab.xml +++ b/app/src/main/res/layout/include_new_browser_tab.xml @@ -21,7 +21,6 @@ android:layout_width="match_parent" android:layout_height="match_parent" android:layout_marginTop="?attr/actionBarSize" - android:animateLayoutChanges="true" android:foreground="@android:color/transparent" tools:context="com.duckduckgo.app.browser.BrowserActivity" tools:showIn="@layout/fragment_browser_tab"> @@ -29,15 +28,14 @@ From 20f69a33d960a1c1e8f23f693d201365554894ca Mon Sep 17 00:00:00 2001 From: Cristian Monforte Date: Mon, 1 Mar 2021 11:16:07 +0100 Subject: [PATCH 20/44] leave a comment to document why animation is in place --- .../main/java/com/duckduckgo/app/browser/HomeBackgroundLogo.kt | 1 + 1 file changed, 1 insertion(+) diff --git a/app/src/main/java/com/duckduckgo/app/browser/HomeBackgroundLogo.kt b/app/src/main/java/com/duckduckgo/app/browser/HomeBackgroundLogo.kt index b37e281c5893..9d30696c693b 100644 --- a/app/src/main/java/com/duckduckgo/app/browser/HomeBackgroundLogo.kt +++ b/app/src/main/java/com/duckduckgo/app/browser/HomeBackgroundLogo.kt @@ -46,6 +46,7 @@ class HomeBackgroundLogo(private var ddgLogoView: View) { private fun fadeLogoIn() { Timber.v("showLogo") + //To avoid glitches when calling show/hide logo within a small amount of time we keep this 50ms animation ddgLogoView.animate().apply { duration = FADE_IN_DURATION interpolator = AccelerateInterpolator() From 52d06764065d9c032d3499068e68da8c61060441 Mon Sep 17 00:00:00 2001 From: Cristian Monforte Date: Mon, 1 Mar 2021 11:17:00 +0100 Subject: [PATCH 21/44] remove debuggable flag (used to measure performance, not needed anymore) --- app/build.gradle | 1 - 1 file changed, 1 deletion(-) diff --git a/app/build.gradle b/app/build.gradle index f4f2a66332af..94a012305303 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -53,7 +53,6 @@ android { ] } release { - debuggable true minifyEnabled false proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' signingConfig signingConfigs.release From 4e3db9128fc38765e96cbf1516d20379906ceb52 Mon Sep 17 00:00:00 2001 From: Cristian Monforte Date: Mon, 1 Mar 2021 11:18:46 +0100 Subject: [PATCH 22/44] Remove logic used to measure performance --- app/src/main/AndroidManifest.xml | 5 -- .../app/browser/BrowserTabFragment.kt | 2 +- .../duckduckgo/app/global/AppStartListener.kt | 57 ------------------- 3 files changed, 1 insertion(+), 63 deletions(-) delete mode 100644 app/src/main/java/com/duckduckgo/app/global/AppStartListener.kt diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index c85b38d46eed..193cef9f5e8f 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -43,11 +43,6 @@ android:resource="@xml/provider_paths"/> - - (KEY_RESTART_INTENTS) - startActivity(intent, fadeTransitionConfig()) - finish() - killProcess() + Timber.i("FireActivity") + setContentView(R.layout.activity_fire_activity) + Handler().postDelayed({ + finish() + killProcess() + }, 3000L) + } + + override fun onPostCreate(savedInstanceState: Bundle?) { + super.onPostCreate(savedInstanceState) + intent = intent.getParcelableExtra(KEY_RESTART_INTENTS) + startActivity(intent) } override fun onBackPressed() { @@ -70,8 +80,7 @@ class FireActivity : DuckDuckGoActivity() { } private fun getRestartIntent(context: Context): Intent { - val intent = BrowserActivity.intent(context, launchedFromFireAction = true) - intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK) + val intent = Intent(context, LaunchBridgeActivity2::class.java) return intent } diff --git a/app/src/main/java/com/duckduckgo/app/launch/LaunchBridgeActivity2.kt b/app/src/main/java/com/duckduckgo/app/launch/LaunchBridgeActivity2.kt new file mode 100644 index 000000000000..1a439c44b0ba --- /dev/null +++ b/app/src/main/java/com/duckduckgo/app/launch/LaunchBridgeActivity2.kt @@ -0,0 +1,52 @@ +/* + * 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.launch + +import android.content.Intent +import android.os.Bundle +import android.os.Handler +import androidx.appcompat.app.AppCompatActivity +import com.duckduckgo.app.browser.BrowserActivity +import com.duckduckgo.app.global.events.db.UserEventKey +import com.duckduckgo.app.global.events.db.UserEventsStore +import dagger.android.AndroidInjection +import kotlinx.coroutines.runBlocking +import timber.log.Timber +import javax.inject.Inject + +class LaunchBridgeActivity2 : AppCompatActivity() { + + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + Timber.i("LaunchBridgeActivity2") + } + + override fun onPostCreate(savedInstanceState: Bundle?) { + super.onPostCreate(savedInstanceState) + Timber.i("LaunchBridgeActivity2: showHome ") + showHome() + } + + private fun showHome() { + val intent = BrowserActivity.intent(this, launchedFromFireAction = true) + intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK) + startActivity(intent) + overridePendingTransition(0, 0) + finish() + } +} diff --git a/app/src/main/res/layout/activity_fire_activity.xml b/app/src/main/res/layout/activity_fire_activity.xml new file mode 100644 index 000000000000..c778e91ab2c1 --- /dev/null +++ b/app/src/main/res/layout/activity_fire_activity.xml @@ -0,0 +1,30 @@ + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/values/themes.xml b/app/src/main/res/values/themes.xml index 831cec4502cc..d0e1a579409a 100644 --- a/app/src/main/res/values/themes.xml +++ b/app/src/main/res/values/themes.xml @@ -108,6 +108,15 @@ true + + + - From 6c41d4d6715a94b08cf6ca4784196f08dbc1c6b3 Mon Sep 17 00:00:00 2001 From: Cristian Monforte Date: Tue, 2 Mar 2021 12:15:29 +0100 Subject: [PATCH 26/44] no transitions to smooth process restart --- .../main/java/com/duckduckgo/app/browser/BrowserActivity.kt | 2 +- .../java/com/duckduckgo/app/launch/LaunchBridgeActivity.kt | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/app/src/main/java/com/duckduckgo/app/browser/BrowserActivity.kt b/app/src/main/java/com/duckduckgo/app/browser/BrowserActivity.kt index 9a35bc99a511..9a48a7de4169 100644 --- a/app/src/main/java/com/duckduckgo/app/browser/BrowserActivity.kt +++ b/app/src/main/java/com/duckduckgo/app/browser/BrowserActivity.kt @@ -147,8 +147,8 @@ class BrowserActivity : DuckDuckGoActivity(), CoroutineScope by MainScope() { val fragment = BrowserTabFragment.newInstance(tabId, url, skipHome) val transaction = supportFragmentManager.beginTransaction() val tab = currentTab + //transaction.setCustomAnimations(R.anim.slide_from_bottom, R.anim.fragment_fade_exit) if (tab == null) { - transaction.setCustomAnimations(R.anim.slide_from_bottom, 0) transaction.replace(R.id.fragmentContainer, fragment, tabId) } else { transaction.hide(tab) diff --git a/app/src/main/java/com/duckduckgo/app/launch/LaunchBridgeActivity.kt b/app/src/main/java/com/duckduckgo/app/launch/LaunchBridgeActivity.kt index a98cfd19a0c3..2c12014a7f58 100644 --- a/app/src/main/java/com/duckduckgo/app/launch/LaunchBridgeActivity.kt +++ b/app/src/main/java/com/duckduckgo/app/launch/LaunchBridgeActivity.kt @@ -25,6 +25,7 @@ import com.duckduckgo.app.onboarding.ui.OnboardingActivity import com.duckduckgo.app.statistics.VariantManager import kotlinx.coroutines.MainScope import kotlinx.coroutines.launch +import timber.log.Timber import javax.inject.Inject class LaunchBridgeActivity : DuckDuckGoActivity() { @@ -36,6 +37,7 @@ class LaunchBridgeActivity : DuckDuckGoActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) + Timber.i("LaunchBridgeActivity") setContentView(R.layout.activity_launch) configureObservers() @@ -70,6 +72,7 @@ class LaunchBridgeActivity : DuckDuckGoActivity() { private fun showHome() { startActivity(BrowserActivity.intent(this)) + overridePendingTransition(0, 0) finish() } } From 65353bff9fd4e9836de14f4b80f6700eb275a5c7 Mon Sep 17 00:00:00 2001 From: Cristian Monforte Date: Wed, 3 Mar 2021 15:09:48 +0100 Subject: [PATCH 27/44] Remove Toast from BrowserActivity --- .../main/java/com/duckduckgo/app/browser/BrowserActivity.kt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/app/src/main/java/com/duckduckgo/app/browser/BrowserActivity.kt b/app/src/main/java/com/duckduckgo/app/browser/BrowserActivity.kt index 9a48a7de4169..0075a4e17b75 100644 --- a/app/src/main/java/com/duckduckgo/app/browser/BrowserActivity.kt +++ b/app/src/main/java/com/duckduckgo/app/browser/BrowserActivity.kt @@ -39,8 +39,10 @@ import com.duckduckgo.app.fire.DataClearer import com.duckduckgo.app.fire.DataClearerForegroundAppRestartPixel import com.duckduckgo.app.global.ApplicationClearDataState import com.duckduckgo.app.global.DuckDuckGoActivity +import com.duckduckgo.app.global.events.db.UserEventKey import com.duckduckgo.app.global.events.db.UserEventsStore import com.duckduckgo.app.global.intentText +import com.duckduckgo.app.global.sendThemeChangedBroadcast import com.duckduckgo.app.global.view.* import com.duckduckgo.app.location.ui.LocationPermissionsActivity import com.duckduckgo.app.onboarding.ui.page.DefaultBrowserPage @@ -214,7 +216,6 @@ class BrowserActivity : DuckDuckGoActivity(), CoroutineScope by MainScope() { if (intent.getBooleanExtra(LAUNCHED_FROM_FIRE_EXTRA, false)) { Timber.i("Launched from fire") - Toast.makeText(applicationContext, R.string.fireDataCleared, Toast.LENGTH_LONG).show() } if (launchNewSearch(intent)) { From e1beaa81b18bcbda8f7c8235401057fac27ead72 Mon Sep 17 00:00:00 2001 From: Cristian Monforte Date: Wed, 3 Mar 2021 15:12:33 +0100 Subject: [PATCH 28/44] Don't show data cleared test in black restart screen --- .../java/com/duckduckgo/app/fire/FireActivity.kt | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/app/src/main/java/com/duckduckgo/app/fire/FireActivity.kt b/app/src/main/java/com/duckduckgo/app/fire/FireActivity.kt index 30207f89013d..fba0d058b17e 100644 --- a/app/src/main/java/com/duckduckgo/app/fire/FireActivity.kt +++ b/app/src/main/java/com/duckduckgo/app/fire/FireActivity.kt @@ -24,9 +24,12 @@ import android.os.Bundle import android.os.Handler import android.os.Process import androidx.appcompat.app.AppCompatActivity +import com.duckduckgo.app.browser.BrowserActivity import com.duckduckgo.app.browser.R import com.duckduckgo.app.global.view.fadeTransitionConfig import com.duckduckgo.app.launch.LaunchBridgeActivity2 +import org.jetbrains.anko.longToast +import org.jetbrains.anko.toast import timber.log.Timber /** @@ -43,17 +46,14 @@ class FireActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) Timber.i("FireActivity") - setContentView(R.layout.activity_fire_activity) - Handler().postDelayed({ - finish() - killProcess() - }, 3000L) } override fun onPostCreate(savedInstanceState: Bundle?) { super.onPostCreate(savedInstanceState) - intent = intent.getParcelableExtra(KEY_RESTART_INTENTS) + intent = intent.getParcelableExtra(KEY_RESTART_INTENTS) startActivity(intent) + finish() + killProcess() } override fun onBackPressed() { @@ -80,7 +80,7 @@ class FireActivity : AppCompatActivity() { } private fun getRestartIntent(context: Context): Intent { - val intent = Intent(context, LaunchBridgeActivity2::class.java) + val intent = BrowserActivity.intent(context, launchedFromFireAction = true) return intent } From d1253e8e2b7b4ebffe8a968c7a2bdc8f02f6db61 Mon Sep 17 00:00:00 2001 From: Cristian Monforte Date: Wed, 3 Mar 2021 15:13:30 +0100 Subject: [PATCH 29/44] Avoid to initialise dependency injection when process restarting due to clear data --- .../duckduckgo/app/global/DuckDuckGoApplication.kt | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/app/src/main/java/com/duckduckgo/app/global/DuckDuckGoApplication.kt b/app/src/main/java/com/duckduckgo/app/global/DuckDuckGoApplication.kt index 556fb87d855b..4fdeee5036c2 100644 --- a/app/src/main/java/com/duckduckgo/app/global/DuckDuckGoApplication.kt +++ b/app/src/main/java/com/duckduckgo/app/global/DuckDuckGoApplication.kt @@ -25,12 +25,14 @@ import android.os.Handler import android.os.SystemClock import android.view.Choreographer import android.view.View +import android.widget.Toast import androidx.lifecycle.Lifecycle import androidx.lifecycle.LifecycleObserver import androidx.lifecycle.OnLifecycleEvent import androidx.lifecycle.ProcessLifecycleOwner import androidx.work.WorkerFactory import com.duckduckgo.app.browser.BuildConfig +import com.duckduckgo.app.browser.R import com.duckduckgo.app.browser.defaultbrowsing.DefaultBrowserObserver import com.duckduckgo.app.browser.shortcut.ShortcutBuilder import com.duckduckgo.app.browser.shortcut.ShortcutReceiver @@ -244,12 +246,16 @@ open class DuckDuckGoApplication : HasAndroidInjector, Application(), LifecycleO } configureLogging() - configureDependencyInjection() - configureUncaughtExceptionHandler() + Timber.i("Application Started") + if (appIsRestarting()){ + + return + } Timber.i("Creating DuckDuckGoApplication") + configureDependencyInjection() + configureUncaughtExceptionHandler() - if (appIsRestarting()) return ProcessLifecycleOwner.get().lifecycle.also { it.addObserver(this) From 422441361f226b70f019ec33575accf7a4f35277 Mon Sep 17 00:00:00 2001 From: Cristian Monforte Date: Wed, 3 Mar 2021 15:14:21 +0100 Subject: [PATCH 30/44] temp commit (WIP views that will inflate later should not be accessible without checkin nullability) --- .../java/com/duckduckgo/app/browser/BrowserTabFragment.kt | 7 +++---- 1 file changed, 3 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 5d0514bfb858..a2221e737eb1 100644 --- a/app/src/main/java/com/duckduckgo/app/browser/BrowserTabFragment.kt +++ b/app/src/main/java/com/duckduckgo/app/browser/BrowserTabFragment.kt @@ -109,7 +109,6 @@ 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_add_widget_instruction_buttons.view.* import kotlinx.android.synthetic.main.include_cta_buttons.view.* import kotlinx.android.synthetic.main.include_dax_dialog_cta.* import kotlinx.android.synthetic.main.include_dax_dialog_cta.view.* @@ -368,7 +367,7 @@ class BrowserTabFragment : override fun onResume() { super.onResume() - + Timber.i("BrowserTabFragment onResume") appBarLayout.setExpanded(true) viewModel.onViewResumed() @@ -1226,7 +1225,7 @@ class BrowserTabFragment : pulseAnimation.stop() animatorHelper.removeListener() supervisorJob.cancel() - popupMenu.dismiss() + //popupMenu.dismiss() loginDetectionDialog?.dismiss() destroyWebView() super.onDestroy() @@ -1923,7 +1922,7 @@ class BrowserTabFragment : } private fun hideHomeTopCta() { - ctaTopContainer.gone() + //ctaTopContainer.gone() } fun renderHomeCta() { From 31f5c853b069a1c7179df1003a0d1b1679f6d2dd Mon Sep 17 00:00:00 2001 From: Cristian Monforte Date: Mon, 8 Mar 2021 12:56:44 +0100 Subject: [PATCH 31/44] Remove code related to measure performance, spotlessApply, unused classes --- app/src/main/AndroidManifest.xml | 11 --- .../duckduckgo/app/browser/BrowserActivity.kt | 4 -- .../app/browser/BrowserTabFragment.kt | 30 ++------ .../app/browser/HomeBackgroundLogo.kt | 2 +- .../com/duckduckgo/app/fire/FireActivity.kt | 13 +--- .../app/global/DuckDuckGoApplication.kt | 69 +------------------ .../duckduckgo/app/global/NextDrawListener.kt | 67 ------------------ .../app/global/WindowDelegateCallback.kt | 62 ----------------- .../app/launch/LaunchBridgeActivity.kt | 2 - .../app/launch/LaunchBridgeActivity2.kt | 52 -------------- .../res/layout/activity_fire_activity.xml | 30 -------- app/src/main/res/values/themes.xml | 9 --- 12 files changed, 11 insertions(+), 340 deletions(-) delete mode 100644 app/src/main/java/com/duckduckgo/app/global/NextDrawListener.kt delete mode 100644 app/src/main/java/com/duckduckgo/app/global/WindowDelegateCallback.kt delete mode 100644 app/src/main/java/com/duckduckgo/app/launch/LaunchBridgeActivity2.kt delete mode 100644 app/src/main/res/layout/activity_fire_activity.xml diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 76d21e9322dd..193cef9f5e8f 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -51,17 +51,6 @@ android:name="android.webkit.WebView.EnableSafeBrowsing" android:value="false" /> - - - - - - (KEY_RESTART_INTENTS) startActivity(intent) finish() killProcess() @@ -81,6 +71,7 @@ class FireActivity : AppCompatActivity() { private fun getRestartIntent(context: Context): Intent { val intent = BrowserActivity.intent(context, launchedFromFireAction = true) + intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK) return intent } diff --git a/app/src/main/java/com/duckduckgo/app/global/DuckDuckGoApplication.kt b/app/src/main/java/com/duckduckgo/app/global/DuckDuckGoApplication.kt index db35dadd1ea5..36c27cb63cc3 100644 --- a/app/src/main/java/com/duckduckgo/app/global/DuckDuckGoApplication.kt +++ b/app/src/main/java/com/duckduckgo/app/global/DuckDuckGoApplication.kt @@ -16,31 +16,21 @@ package com.duckduckgo.app.global -import android.app.Activity import android.app.Application import android.content.IntentFilter import android.os.Build -import android.os.Bundle -import android.os.Handler -import android.os.SystemClock -import android.view.Choreographer -import android.view.View -import android.widget.Toast import androidx.lifecycle.Lifecycle import androidx.lifecycle.LifecycleObserver import androidx.lifecycle.OnLifecycleEvent import androidx.lifecycle.ProcessLifecycleOwner import com.duckduckgo.app.browser.BuildConfig -import com.duckduckgo.app.browser.R import com.duckduckgo.app.browser.defaultbrowsing.DefaultBrowserObserver import com.duckduckgo.app.browser.shortcut.ShortcutBuilder import com.duckduckgo.app.browser.shortcut.ShortcutReceiver import com.duckduckgo.app.di.AppComponent import com.duckduckgo.app.di.DaggerAppComponent import com.duckduckgo.app.fire.* -import com.duckduckgo.app.global.NextDrawListener.Companion.onNextDraw import com.duckduckgo.app.global.Theming.initializeTheme -import com.duckduckgo.app.global.WindowDelegateCallback.Companion.onDecorViewReady import com.duckduckgo.app.global.initialization.AppDataLoader import com.duckduckgo.app.global.install.AppInstallStore import com.duckduckgo.app.global.rating.AppEnjoymentLifecycleObserver @@ -165,74 +155,17 @@ open class DuckDuckGoApplication : HasAndroidInjector, Application(), LifecycleO open lateinit var daggerAppComponent: AppComponent - var applicationOnCreateMs: Long = 0 - var firstFrameDoneMs: Long = 0 - var firstDrawMs: Long = 0 - override fun onCreate() { super.onCreate() - var firstDraw = false - val handler = Handler() - - applicationOnCreateMs = SystemClock.uptimeMillis() - - registerActivityLifecycleCallbacks( - object : ActivityLifecycleCallbacks { - override fun onActivityCreated(activity: Activity, savedInstanceState: Bundle?) { - if (firstDraw) return - val window = activity.window - window.onDecorViewReady { - window.decorView.onNextDraw { - if (firstDraw) return@onNextDraw - firstDraw = true - handler.postAtFrontOfQueue { - firstDrawMs = SystemClock.uptimeMillis() - } - } - } - } - - override fun onActivityStarted(activity: Activity) { - - } - - override fun onActivityResumed(activity: Activity) { - } - - override fun onActivityPaused(activity: Activity) { - - } - - override fun onActivityStopped(activity: Activity) { - - } - - override fun onActivitySaveInstanceState(activity: Activity, outState: Bundle) { - - } - - override fun onActivityDestroyed(activity: Activity) { - - } - } - ) - - Choreographer.getInstance().postFrameCallback { - firstFrameDoneMs = SystemClock.uptimeMillis() - } configureLogging() Timber.i("Application Started") - if (appIsRestarting()){ - - return - } + if (appIsRestarting()) return Timber.i("Creating DuckDuckGoApplication") configureDependencyInjection() configureUncaughtExceptionHandler() - ProcessLifecycleOwner.get().lifecycle.also { it.addObserver(this) it.addObserver(dataClearer) diff --git a/app/src/main/java/com/duckduckgo/app/global/NextDrawListener.kt b/app/src/main/java/com/duckduckgo/app/global/NextDrawListener.kt deleted file mode 100644 index aa0afbbe0a5b..000000000000 --- a/app/src/main/java/com/duckduckgo/app/global/NextDrawListener.kt +++ /dev/null @@ -1,67 +0,0 @@ -/* - * Copyright (c) 2021 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.global - -import android.os.Handler -import android.os.Looper -import android.view.View -import android.view.ViewTreeObserver - -class NextDrawListener( - val view: View, - val onDrawCallback: () -> Unit -) : ViewTreeObserver.OnDrawListener { - - val handler = Handler(Looper.getMainLooper()) - var invoked = false - - override fun onDraw() { - if (invoked) return - invoked = true - onDrawCallback() - handler.post { - if (view.viewTreeObserver.isAlive) { - view.viewTreeObserver.removeOnDrawListener(this) - } - } - } - - companion object { - fun View.onNextDraw(onDrawCallback: () -> Unit) { - if (viewTreeObserver.isAlive && isAttachedToWindow) { - addNextDrawListener(onDrawCallback) - } else { - // Wait until attached - addOnAttachStateChangeListener( - object : View.OnAttachStateChangeListener { - override fun onViewAttachedToWindow(v: View) { - addNextDrawListener(onDrawCallback) - removeOnAttachStateChangeListener(this) - } - - override fun onViewDetachedFromWindow(v: View) = Unit - }) - } - } - - private fun View.addNextDrawListener(callback: () -> Unit) { - viewTreeObserver.addOnDrawListener( - NextDrawListener(this, callback) - ) - } - } -} \ No newline at end of file diff --git a/app/src/main/java/com/duckduckgo/app/global/WindowDelegateCallback.kt b/app/src/main/java/com/duckduckgo/app/global/WindowDelegateCallback.kt deleted file mode 100644 index d94c8e0626aa..000000000000 --- a/app/src/main/java/com/duckduckgo/app/global/WindowDelegateCallback.kt +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Copyright (c) 2021 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.global - -import android.view.Window - -class WindowDelegateCallback constructor( - private val delegate: Window.Callback -) : Window.Callback by delegate { - - val onContentChangedCallbacks = mutableListOf<() -> Boolean>() - - override fun onContentChanged() { - onContentChangedCallbacks.removeAll { callback -> - !callback() - } - delegate.onContentChanged() - } - - companion object { - fun Window.onDecorViewReady(callback: () -> Unit) { - if (peekDecorView() == null) { - onContentChanged { - callback() - return@onContentChanged false - } - } else { - callback() - } - } - - fun Window.onContentChanged(block: () -> Boolean) { - val callback = wrapCallback() - callback.onContentChangedCallbacks += block - } - - private fun Window.wrapCallback(): WindowDelegateCallback { - val currentCallback = callback - return if (currentCallback is WindowDelegateCallback) { - currentCallback - } else { - val newCallback = WindowDelegateCallback(currentCallback) - callback = newCallback - newCallback - } - } - } -} \ No newline at end of file diff --git a/app/src/main/java/com/duckduckgo/app/launch/LaunchBridgeActivity.kt b/app/src/main/java/com/duckduckgo/app/launch/LaunchBridgeActivity.kt index 2c12014a7f58..b8990d756479 100644 --- a/app/src/main/java/com/duckduckgo/app/launch/LaunchBridgeActivity.kt +++ b/app/src/main/java/com/duckduckgo/app/launch/LaunchBridgeActivity.kt @@ -25,7 +25,6 @@ import com.duckduckgo.app.onboarding.ui.OnboardingActivity import com.duckduckgo.app.statistics.VariantManager import kotlinx.coroutines.MainScope import kotlinx.coroutines.launch -import timber.log.Timber import javax.inject.Inject class LaunchBridgeActivity : DuckDuckGoActivity() { @@ -37,7 +36,6 @@ class LaunchBridgeActivity : DuckDuckGoActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) - Timber.i("LaunchBridgeActivity") setContentView(R.layout.activity_launch) configureObservers() diff --git a/app/src/main/java/com/duckduckgo/app/launch/LaunchBridgeActivity2.kt b/app/src/main/java/com/duckduckgo/app/launch/LaunchBridgeActivity2.kt deleted file mode 100644 index 1a439c44b0ba..000000000000 --- a/app/src/main/java/com/duckduckgo/app/launch/LaunchBridgeActivity2.kt +++ /dev/null @@ -1,52 +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.launch - -import android.content.Intent -import android.os.Bundle -import android.os.Handler -import androidx.appcompat.app.AppCompatActivity -import com.duckduckgo.app.browser.BrowserActivity -import com.duckduckgo.app.global.events.db.UserEventKey -import com.duckduckgo.app.global.events.db.UserEventsStore -import dagger.android.AndroidInjection -import kotlinx.coroutines.runBlocking -import timber.log.Timber -import javax.inject.Inject - -class LaunchBridgeActivity2 : AppCompatActivity() { - - - override fun onCreate(savedInstanceState: Bundle?) { - super.onCreate(savedInstanceState) - Timber.i("LaunchBridgeActivity2") - } - - override fun onPostCreate(savedInstanceState: Bundle?) { - super.onPostCreate(savedInstanceState) - Timber.i("LaunchBridgeActivity2: showHome ") - showHome() - } - - private fun showHome() { - val intent = BrowserActivity.intent(this, launchedFromFireAction = true) - intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK) - startActivity(intent) - overridePendingTransition(0, 0) - finish() - } -} diff --git a/app/src/main/res/layout/activity_fire_activity.xml b/app/src/main/res/layout/activity_fire_activity.xml deleted file mode 100644 index c778e91ab2c1..000000000000 --- a/app/src/main/res/layout/activity_fire_activity.xml +++ /dev/null @@ -1,30 +0,0 @@ - - - - - - - - \ No newline at end of file diff --git a/app/src/main/res/values/themes.xml b/app/src/main/res/values/themes.xml index d0e1a579409a..831cec4502cc 100644 --- a/app/src/main/res/values/themes.xml +++ b/app/src/main/res/values/themes.xml @@ -108,15 +108,6 @@ true - - - - - - - - - - - - \ No newline at end of file diff --git a/app/src/main/res/values/attrs.xml b/app/src/main/res/values/attrs.xml index a96851ddc505..79f18f6b0334 100644 --- a/app/src/main/res/values/attrs.xml +++ b/app/src/main/res/values/attrs.xml @@ -65,8 +65,6 @@ - - diff --git a/app/src/main/res/values/themes.xml b/app/src/main/res/values/themes.xml index 831cec4502cc..5294b42db226 100644 --- a/app/src/main/res/values/themes.xml +++ b/app/src/main/res/values/themes.xml @@ -85,8 +85,6 @@ @color/greyishBrownTwo @color/warGreyTwo @color/white - @color/grayish - @color/greyishBrownTwo @color/grayish @color/almostBlack @@ -164,8 +162,6 @@ @color/subtleGrayTwo @color/white @color/subtleGrayTwo - @color/almostBlackDark - @color/white @color/warmerGray @color/whiteFive