From dc26134665beb194b7e6a666a1931a5ed7307234 Mon Sep 17 00:00:00 2001 From: Craig Russell Date: Mon, 3 Sep 2018 09:46:36 +0100 Subject: [PATCH 1/7] Reduce boilerplate in each Activity in the way the ViewModel is obtained (#341) --- .../duckduckgo/app/bookmarks/ui/BookmarksActivity.kt | 9 +-------- .../java/com/duckduckgo/app/browser/BrowserActivity.kt | 9 +-------- .../com/duckduckgo/app/feedback/ui/FeedbackActivity.kt | 10 +--------- .../main/java/com/duckduckgo/app/fire/FireActivity.kt | 10 +--------- .../com/duckduckgo/app/global/DuckDuckGoActivity.kt | 8 ++++++++ .../java/com/duckduckgo/app/launch/LaunchActivity.kt | 10 +--------- .../duckduckgo/app/onboarding/ui/OnboardingActivity.kt | 9 +-------- .../app/privacy/ui/PrivacyDashboardActivity.kt | 8 +------- .../app/privacy/ui/PrivacyPracticesActivity.kt | 9 +-------- .../com/duckduckgo/app/privacy/ui/ScorecardActivity.kt | 9 ++------- .../app/privacy/ui/TrackerNetworksActivity.kt | 7 +------ .../com/duckduckgo/app/settings/SettingsActivity.kt | 10 +--------- .../com/duckduckgo/app/tabs/ui/TabSwitcherActivity.kt | 10 ++-------- 13 files changed, 22 insertions(+), 96 deletions(-) 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 24009de25885..4017c874a8ca 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 @@ -18,7 +18,6 @@ package com.duckduckgo.app.bookmarks.ui import android.app.AlertDialog import android.arch.lifecycle.Observer -import android.arch.lifecycle.ViewModelProviders import android.content.Context import android.content.Intent import android.net.Uri @@ -35,7 +34,6 @@ import com.duckduckgo.app.bookmarks.db.BookmarkEntity import com.duckduckgo.app.browser.BrowserActivity import com.duckduckgo.app.browser.R import com.duckduckgo.app.global.DuckDuckGoActivity -import com.duckduckgo.app.global.ViewModelFactory import com.duckduckgo.app.global.baseHost import com.duckduckgo.app.global.faviconLocation import com.duckduckgo.app.global.image.GlideApp @@ -46,18 +44,13 @@ import kotlinx.android.synthetic.main.include_toolbar.* import kotlinx.android.synthetic.main.view_bookmark_entry.view.* import org.jetbrains.anko.alert import timber.log.Timber -import javax.inject.Inject class BookmarksActivity : DuckDuckGoActivity() { - @Inject - lateinit var viewModelFactory: ViewModelFactory lateinit var adapter: BookmarksAdapter private var deleteDialog: AlertDialog? = null - private val viewModel: BookmarksViewModel by lazy { - ViewModelProviders.of(this, viewModelFactory).get(BookmarksViewModel::class.java) - } + private val viewModel: BookmarksViewModel by bindViewModel() override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) 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 cd05c16962fa..5ab309bed7c8 100644 --- a/app/src/main/java/com/duckduckgo/app/browser/BrowserActivity.kt +++ b/app/src/main/java/com/duckduckgo/app/browser/BrowserActivity.kt @@ -17,7 +17,6 @@ package com.duckduckgo.app.browser import android.arch.lifecycle.Observer -import android.arch.lifecycle.ViewModelProviders import android.content.Context import android.content.Intent import android.content.Intent.EXTRA_TEXT @@ -29,7 +28,6 @@ import com.duckduckgo.app.browser.BrowserViewModel.Command.Query import com.duckduckgo.app.browser.BrowserViewModel.Command.Refresh import com.duckduckgo.app.feedback.ui.FeedbackActivity import com.duckduckgo.app.global.DuckDuckGoActivity -import com.duckduckgo.app.global.ViewModelFactory import com.duckduckgo.app.global.intentText import com.duckduckgo.app.global.view.ClearPersonalDataAction import com.duckduckgo.app.global.view.FireDialog @@ -46,9 +44,6 @@ import javax.inject.Inject class BrowserActivity : DuckDuckGoActivity() { - @Inject - lateinit var viewModelFactory: ViewModelFactory - @Inject lateinit var clearPersonalDataAction: ClearPersonalDataAction @@ -57,9 +52,7 @@ class BrowserActivity : DuckDuckGoActivity() { private var currentTab: BrowserTabFragment? = null - private val viewModel: BrowserViewModel by lazy { - ViewModelProviders.of(this, viewModelFactory).get(BrowserViewModel::class.java) - } + private val viewModel: BrowserViewModel by bindViewModel() override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) diff --git a/app/src/main/java/com/duckduckgo/app/feedback/ui/FeedbackActivity.kt b/app/src/main/java/com/duckduckgo/app/feedback/ui/FeedbackActivity.kt index 78945057bb04..45b035bd3dc8 100644 --- a/app/src/main/java/com/duckduckgo/app/feedback/ui/FeedbackActivity.kt +++ b/app/src/main/java/com/duckduckgo/app/feedback/ui/FeedbackActivity.kt @@ -17,7 +17,6 @@ package com.duckduckgo.app.feedback.ui import android.arch.lifecycle.Observer -import android.arch.lifecycle.ViewModelProviders import android.content.Context import android.content.Intent import android.os.Bundle @@ -28,21 +27,14 @@ import com.duckduckgo.app.browser.R import com.duckduckgo.app.feedback.ui.FeedbackViewModel.Command import com.duckduckgo.app.feedback.ui.FeedbackViewModel.ViewState import com.duckduckgo.app.global.DuckDuckGoActivity -import com.duckduckgo.app.global.ViewModelFactory import com.duckduckgo.app.global.view.TextChangedWatcher import kotlinx.android.synthetic.main.activity_feedback.* import org.jetbrains.anko.longToast -import javax.inject.Inject class FeedbackActivity : DuckDuckGoActivity() { - @Inject - lateinit var viewModelFactory: ViewModelFactory - - private val viewModel: FeedbackViewModel by lazy { - ViewModelProviders.of(this, viewModelFactory).get(FeedbackViewModel::class.java) - } + private val viewModel: FeedbackViewModel by bindViewModel() override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) 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 36f9b4a3d3c0..f34c271deba9 100644 --- a/app/src/main/java/com/duckduckgo/app/fire/FireActivity.kt +++ b/app/src/main/java/com/duckduckgo/app/fire/FireActivity.kt @@ -21,7 +21,6 @@ import android.animation.AnimatorListenerAdapter import android.app.Activity import android.app.ActivityManager import android.arch.lifecycle.Observer -import android.arch.lifecycle.ViewModelProviders import android.content.Context import android.content.Intent import android.os.Bundle @@ -30,9 +29,7 @@ import android.support.v4.app.ActivityOptionsCompat import com.duckduckgo.app.browser.BrowserActivity import com.duckduckgo.app.browser.R import com.duckduckgo.app.global.DuckDuckGoActivity -import com.duckduckgo.app.global.ViewModelFactory import kotlinx.android.synthetic.main.activity_fire.* -import javax.inject.Inject /** * Activity which is responsible for killing the main process and restarting it. This Activity will automatically finish itself after a brief time. @@ -49,12 +46,7 @@ import javax.inject.Inject */ class FireActivity : DuckDuckGoActivity() { - @Inject - lateinit var viewModelFactory: ViewModelFactory - - private val viewModel: FireViewModel by lazy { - ViewModelProviders.of(this, viewModelFactory).get(FireViewModel::class.java) - } + private val viewModel: FireViewModel by bindViewModel() override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) 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 02522e8ba162..7202b629a4b2 100644 --- a/app/src/main/java/com/duckduckgo/app/global/DuckDuckGoActivity.kt +++ b/app/src/main/java/com/duckduckgo/app/global/DuckDuckGoActivity.kt @@ -16,14 +16,20 @@ package com.duckduckgo.app.global +import android.arch.lifecycle.ViewModel +import android.arch.lifecycle.ViewModelProviders import android.os.Bundle import android.support.v7.app.AppCompatActivity import android.view.MenuItem import dagger.android.AndroidInjection +import javax.inject.Inject abstract class DuckDuckGoActivity : AppCompatActivity() { + @Inject + lateinit var viewModelFactory: ViewModelFactory + override fun onCreate(savedInstanceState: Bundle?) { AndroidInjection.inject(this) super.onCreate(savedInstanceState) @@ -38,4 +44,6 @@ abstract class DuckDuckGoActivity : AppCompatActivity() { } return super.onOptionsItemSelected(item) } + + protected inline fun bindViewModel() = lazy { ViewModelProviders.of(this, viewModelFactory).get(V::class.java) } } \ No newline at end of file diff --git a/app/src/main/java/com/duckduckgo/app/launch/LaunchActivity.kt b/app/src/main/java/com/duckduckgo/app/launch/LaunchActivity.kt index 72e9bb3aefc1..21dcc9e537e6 100644 --- a/app/src/main/java/com/duckduckgo/app/launch/LaunchActivity.kt +++ b/app/src/main/java/com/duckduckgo/app/launch/LaunchActivity.kt @@ -17,24 +17,16 @@ package com.duckduckgo.app.launch import android.arch.lifecycle.Observer -import android.arch.lifecycle.ViewModelProviders import android.os.Bundle import com.duckduckgo.app.browser.BrowserActivity import com.duckduckgo.app.browser.R import com.duckduckgo.app.global.DuckDuckGoActivity -import com.duckduckgo.app.global.ViewModelFactory import com.duckduckgo.app.onboarding.ui.OnboardingActivity -import javax.inject.Inject class LaunchActivity : DuckDuckGoActivity() { - @Inject - lateinit var viewModelFactory: ViewModelFactory - - private val viewModel: LaunchViewModel by lazy { - ViewModelProviders.of(this, viewModelFactory).get(LaunchViewModel::class.java) - } + private val viewModel: LaunchViewModel by bindViewModel() override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) diff --git a/app/src/main/java/com/duckduckgo/app/onboarding/ui/OnboardingActivity.kt b/app/src/main/java/com/duckduckgo/app/onboarding/ui/OnboardingActivity.kt index 11ed807f7264..511ea2c8b35c 100644 --- a/app/src/main/java/com/duckduckgo/app/onboarding/ui/OnboardingActivity.kt +++ b/app/src/main/java/com/duckduckgo/app/onboarding/ui/OnboardingActivity.kt @@ -16,7 +16,6 @@ package com.duckduckgo.app.onboarding.ui -import android.arch.lifecycle.ViewModelProviders import android.content.Context import android.content.Intent import android.os.Build @@ -27,7 +26,6 @@ import android.support.v4.content.ContextCompat import android.view.View import com.duckduckgo.app.browser.R import com.duckduckgo.app.global.DuckDuckGoActivity -import com.duckduckgo.app.global.ViewModelFactory import com.duckduckgo.app.global.view.ColorCombiner import com.duckduckgo.app.global.view.launchDefaultAppActivity import com.duckduckgo.app.onboarding.ui.ColorChangingPageListener.NewColorListener @@ -37,17 +35,12 @@ import javax.inject.Inject class OnboardingActivity : DuckDuckGoActivity() { - @Inject - lateinit var viewModelFactory: ViewModelFactory - @Inject lateinit var colorCombiner: ColorCombiner private lateinit var viewPageAdapter: PagerAdapter - private val viewModel: OnboardingViewModel by lazy { - ViewModelProviders.of(this, viewModelFactory).get(OnboardingViewModel::class.java) - } + private val viewModel: OnboardingViewModel by bindViewModel() override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) 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 e1002e286aff..2ceba4d4ceed 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 @@ -18,7 +18,6 @@ package com.duckduckgo.app.privacy.ui import android.app.Activity import android.arch.lifecycle.Observer -import android.arch.lifecycle.ViewModelProviders import android.content.Context import android.content.Intent import android.os.Bundle @@ -26,7 +25,6 @@ import android.support.v4.content.ContextCompat import android.view.View import com.duckduckgo.app.browser.R import com.duckduckgo.app.global.DuckDuckGoActivity -import com.duckduckgo.app.global.ViewModelFactory import com.duckduckgo.app.global.model.Site import com.duckduckgo.app.global.view.hide import com.duckduckgo.app.global.view.html @@ -44,8 +42,6 @@ import javax.inject.Inject class PrivacyDashboardActivity : DuckDuckGoActivity() { - @Inject - lateinit var viewModelFactory: ViewModelFactory @Inject lateinit var repository: TabRepository @Inject @@ -54,9 +50,7 @@ class PrivacyDashboardActivity : DuckDuckGoActivity() { private val trackersRenderer = TrackersRenderer() private val upgradeRenderer = PrivacyUpgradeRenderer() - private val viewModel: PrivacyDashboardViewModel by lazy { - ViewModelProviders.of(this, viewModelFactory).get(PrivacyDashboardViewModel::class.java) - } + private val viewModel: PrivacyDashboardViewModel by bindViewModel() override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) 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 fccb298614c8..58f78a580cb3 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 @@ -17,7 +17,6 @@ package com.duckduckgo.app.privacy.ui import android.arch.lifecycle.Observer -import android.arch.lifecycle.ViewModelProviders import android.content.Context import android.content.Intent import android.os.Bundle @@ -27,7 +26,6 @@ import com.duckduckgo.app.browser.BrowserActivity import com.duckduckgo.app.browser.R import com.duckduckgo.app.global.AppUrl.Url import com.duckduckgo.app.global.DuckDuckGoActivity -import com.duckduckgo.app.global.ViewModelFactory import com.duckduckgo.app.global.model.Site import com.duckduckgo.app.privacy.renderer.banner import com.duckduckgo.app.privacy.renderer.text @@ -39,17 +37,12 @@ import javax.inject.Inject class PrivacyPracticesActivity : DuckDuckGoActivity() { - @Inject - lateinit var viewModelFactory: ViewModelFactory - @Inject lateinit var repository: TabRepository private val practicesAdapter = PrivacyPracticesAdapter() - private val viewModel: PrivacyPracticesViewModel by lazy { - ViewModelProviders.of(this, viewModelFactory).get(PrivacyPracticesViewModel::class.java) - } + private val viewModel: PrivacyPracticesViewModel by bindViewModel() override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) 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 bdf5718245ce..55efc5cd6c8f 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 @@ -17,7 +17,6 @@ package com.duckduckgo.app.privacy.ui import android.arch.lifecycle.Observer -import android.arch.lifecycle.ViewModelProviders import android.content.Context import android.content.Intent import android.os.Bundle @@ -26,9 +25,8 @@ import android.view.View import android.widget.TextView import com.duckduckgo.app.browser.R import com.duckduckgo.app.global.DuckDuckGoActivity -import com.duckduckgo.app.global.ViewModelFactory -import com.duckduckgo.app.global.view.html import com.duckduckgo.app.global.model.Site +import com.duckduckgo.app.global.view.html import com.duckduckgo.app.privacy.renderer.* import com.duckduckgo.app.tabs.model.TabRepository import com.duckduckgo.app.tabs.tabId @@ -39,14 +37,11 @@ import javax.inject.Inject class ScorecardActivity : DuckDuckGoActivity() { - @Inject lateinit var viewModelFactory: ViewModelFactory @Inject lateinit var repository: TabRepository private val trackersRenderer = TrackersRenderer() private val upgradeRenderer = PrivacyUpgradeRenderer() - private val viewModel: ScorecardViewModel by lazy { - ViewModelProviders.of(this, viewModelFactory).get(ScorecardViewModel::class.java) - } + private val viewModel: ScorecardViewModel by bindViewModel() override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) 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 a31b25a1c323..2f6ef2f8b721 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 @@ -17,14 +17,12 @@ package com.duckduckgo.app.privacy.ui import android.arch.lifecycle.Observer -import android.arch.lifecycle.ViewModelProviders import android.content.Context import android.content.Intent import android.os.Bundle import android.support.v7.widget.LinearLayoutManager import com.duckduckgo.app.browser.R import com.duckduckgo.app.global.DuckDuckGoActivity -import com.duckduckgo.app.global.ViewModelFactory import com.duckduckgo.app.global.model.Site import com.duckduckgo.app.privacy.renderer.TrackersRenderer import com.duckduckgo.app.tabs.model.TabRepository @@ -35,14 +33,11 @@ import javax.inject.Inject class TrackerNetworksActivity : DuckDuckGoActivity() { - @Inject lateinit var viewModelFactory: ViewModelFactory @Inject lateinit var repository: TabRepository private val trackersRenderer = TrackersRenderer() private val networksAdapter = TrackerNetworksAdapter() - private val viewModel: TrackerNetworksViewModel by lazy { - ViewModelProviders.of(this, viewModelFactory).get(TrackerNetworksViewModel::class.java) - } + private val viewModel: TrackerNetworksViewModel by bindViewModel() override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) 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 ba20062465bd..bb8841a326f4 100644 --- a/app/src/main/java/com/duckduckgo/app/settings/SettingsActivity.kt +++ b/app/src/main/java/com/duckduckgo/app/settings/SettingsActivity.kt @@ -17,7 +17,6 @@ package com.duckduckgo.app.settings import android.arch.lifecycle.Observer -import android.arch.lifecycle.ViewModelProviders import android.content.Context import android.content.Intent import android.os.Build @@ -29,21 +28,14 @@ import com.duckduckgo.app.about.AboutDuckDuckGoActivity import com.duckduckgo.app.browser.R import com.duckduckgo.app.feedback.ui.FeedbackActivity import com.duckduckgo.app.global.DuckDuckGoActivity -import com.duckduckgo.app.global.ViewModelFactory import com.duckduckgo.app.global.view.launchDefaultAppActivity import com.duckduckgo.app.onboarding.ui.OnboardingActivity import kotlinx.android.synthetic.main.content_settings.* import kotlinx.android.synthetic.main.include_toolbar.* -import javax.inject.Inject class SettingsActivity : DuckDuckGoActivity() { - @Inject - lateinit var viewModelFactory: ViewModelFactory - - private val viewModel: SettingsViewModel by lazy { - ViewModelProviders.of(this, viewModelFactory).get(SettingsViewModel::class.java) - } + private val viewModel: SettingsViewModel by bindViewModel() private val defaultBrowserChangeListener = OnCheckedChangeListener { _, _ -> launchDefaultAppScreen() } 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 088902d31c17..814f857fb174 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 @@ -17,7 +17,6 @@ package com.duckduckgo.app.tabs.ui import android.arch.lifecycle.Observer -import android.arch.lifecycle.ViewModelProviders import android.content.Context import android.content.Intent import android.os.Bundle @@ -26,7 +25,6 @@ import android.view.Menu import android.view.MenuItem import com.duckduckgo.app.browser.R import com.duckduckgo.app.global.DuckDuckGoActivity -import com.duckduckgo.app.global.ViewModelFactory import com.duckduckgo.app.global.view.ClearPersonalDataAction import com.duckduckgo.app.global.view.FireDialog import com.duckduckgo.app.statistics.pixels.Pixel @@ -41,18 +39,14 @@ import javax.inject.Inject class TabSwitcherActivity : DuckDuckGoActivity(), TabSwitcherAdapter.TabSwitchedListener { - @Inject - lateinit var viewModelFactory: ViewModelFactory - @Inject lateinit var clearPersonalDataAction: ClearPersonalDataAction @Inject lateinit var pixel: Pixel - private val viewModel: TabSwitcherViewModel by lazy { - ViewModelProviders.of(this, viewModelFactory).get(TabSwitcherViewModel::class.java) - } + private val viewModel: TabSwitcherViewModel by bindViewModel() + private val tabsAdapter = TabSwitcherAdapter(this, this) override fun onCreate(savedInstanceState: Bundle?) { From 79d22662008b612189edb306e9759ec25633df5c Mon Sep 17 00:00:00 2001 From: Craig Russell Date: Mon, 3 Sep 2018 17:12:58 +0100 Subject: [PATCH 2/7] Add new items to the Tab Switcher's overflow menu (#343) --- .../com/duckduckgo/app/tabs/ui/TabSwitcherActivity.kt | 8 +++++++- app/src/main/res/menu/menu_tab_switcher_activity.xml | 10 ++++++++++ 2 files changed, 17 insertions(+), 1 deletion(-) 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 814f857fb174..3e029927d637 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 @@ -27,6 +27,7 @@ import com.duckduckgo.app.browser.R import com.duckduckgo.app.global.DuckDuckGoActivity import com.duckduckgo.app.global.view.ClearPersonalDataAction import com.duckduckgo.app.global.view.FireDialog +import com.duckduckgo.app.settings.SettingsActivity import com.duckduckgo.app.statistics.pixels.Pixel import com.duckduckgo.app.tabs.model.TabEntity import com.duckduckgo.app.tabs.ui.TabSwitcherViewModel.Command @@ -98,8 +99,9 @@ class TabSwitcherActivity : DuckDuckGoActivity(), TabSwitcherAdapter.TabSwitched override fun onOptionsItemSelected(item: MenuItem): Boolean { when (item.itemId) { R.id.fire -> onFire() - R.id.newTab -> onNewTabRequested() + R.id.newTab, R.id.newTabOverflow -> onNewTabRequested() R.id.closeAllTabs -> closeAllTabs() + R.id.settings -> showSettings() } return super.onOptionsItemSelected(item) } @@ -129,6 +131,10 @@ class TabSwitcherActivity : DuckDuckGoActivity(), TabSwitcherAdapter.TabSwitched } } + private fun showSettings() { + startActivity(SettingsActivity.intent(this)) + } + override fun finish() { clearObserversEarlyToStopViewUpdates() super.finish() diff --git a/app/src/main/res/menu/menu_tab_switcher_activity.xml b/app/src/main/res/menu/menu_tab_switcher_activity.xml index a2108cbb2f39..1b605ac5747f 100644 --- a/app/src/main/res/menu/menu_tab_switcher_activity.xml +++ b/app/src/main/res/menu/menu_tab_switcher_activity.xml @@ -31,9 +31,19 @@ android:title="@string/newTabMenuItem" app:showAsAction="always" /> + + + + From 89d49d461d3ffee8e4639f9f7ffa06014d52d947 Mon Sep 17 00:00:00 2001 From: Craig Russell Date: Mon, 3 Sep 2018 17:33:17 +0100 Subject: [PATCH 3/7] Remove onboarding as an experimental feature (#344) --- .../onboarding/ui/OnboardingViewModelTest.kt | 22 ++----------------- .../duckduckgo/app/global/ViewModelFactory.kt | 2 +- .../app/onboarding/ui/OnboardingViewModel.kt | 11 ++-------- .../app/statistics/VariantManager.kt | 1 - 4 files changed, 5 insertions(+), 31 deletions(-) diff --git a/app/src/androidTest/java/com/duckduckgo/app/onboarding/ui/OnboardingViewModelTest.kt b/app/src/androidTest/java/com/duckduckgo/app/onboarding/ui/OnboardingViewModelTest.kt index e8c098e57833..070090d8fd6d 100644 --- a/app/src/androidTest/java/com/duckduckgo/app/onboarding/ui/OnboardingViewModelTest.kt +++ b/app/src/androidTest/java/com/duckduckgo/app/onboarding/ui/OnboardingViewModelTest.kt @@ -19,9 +19,7 @@ package com.duckduckgo.app.onboarding.ui import android.arch.core.executor.testing.InstantTaskExecutorRule import com.duckduckgo.app.browser.defaultBrowsing.DefaultBrowserDetector import com.duckduckgo.app.onboarding.store.OnboardingStore -import com.duckduckgo.app.statistics.Variant import com.duckduckgo.app.statistics.VariantManager -import com.duckduckgo.app.statistics.VariantManager.VariantFeature.DefaultBrowserFeature.ShowInOnboarding import com.nhaarman.mockito_kotlin.mock import com.nhaarman.mockito_kotlin.never import com.nhaarman.mockito_kotlin.verify @@ -43,7 +41,7 @@ class OnboardingViewModelTest { private var variantManager: VariantManager = mock() private val testee: OnboardingViewModel by lazy { - OnboardingViewModel(onboardingStore, mockDefaultBrowserDetector, variantManager) + OnboardingViewModel(onboardingStore, mockDefaultBrowserDetector) } @Test @@ -66,33 +64,17 @@ class OnboardingViewModelTest { } @Test - fun whenThirdPageRequestedWithFeatureEnabledAndDefaultBrowserCapableThenDefaultBrowserPageReturned() { - whenever(variantManager.getVariant()).thenReturn(variantWithOnboardingEnabled()) + fun whenThirdPageRequestedWithDefaultBrowserCapableThenDefaultBrowserPageReturned() { whenever(mockDefaultBrowserDetector.deviceSupportsDefaultBrowserConfiguration()).thenReturn(true) val page = testee.getItem(2) assertTrue(page is OnboardingPageFragment.DefaultBrowserPage) } - @Test - fun whenThirdPageRequestedWithFeatureDisabledAndDefaultBrowserCapableThenNoPageReturned() { - whenever(variantManager.getVariant()).thenReturn(variantWithOnboardingDisabled()) - whenever(mockDefaultBrowserDetector.deviceSupportsDefaultBrowserConfiguration()).thenReturn(true) - val page = testee.getItem(2) - assertNull(page) - } - @Test fun whenThirdPageRequestedButDefaultBrowserNotCapableThenNoPageReturned() { - whenever(variantManager.getVariant()).thenReturn(variantWithOnboardingEnabled()) whenever(mockDefaultBrowserDetector.deviceSupportsDefaultBrowserConfiguration()).thenReturn(false) val page = testee.getItem(2) assertNull(page) } - private fun variantWithOnboardingEnabled(): Variant = - Variant("", 0.0, listOf(ShowInOnboarding)) - - private fun variantWithOnboardingDisabled(): Variant = - Variant("", 0.0, listOf()) - } \ No newline at end of file diff --git a/app/src/main/java/com/duckduckgo/app/global/ViewModelFactory.kt b/app/src/main/java/com/duckduckgo/app/global/ViewModelFactory.kt index 19811686d995..296db7d2c1e6 100644 --- a/app/src/main/java/com/duckduckgo/app/global/ViewModelFactory.kt +++ b/app/src/main/java/com/duckduckgo/app/global/ViewModelFactory.kt @@ -81,7 +81,7 @@ class ViewModelFactory @Inject constructor( with(modelClass) { when { isAssignableFrom(LaunchViewModel::class.java) -> LaunchViewModel(onboaringStore) - isAssignableFrom(OnboardingViewModel::class.java) -> OnboardingViewModel(onboaringStore, defaultBrowserDetector, variantManager) + isAssignableFrom(OnboardingViewModel::class.java) -> OnboardingViewModel(onboaringStore, defaultBrowserDetector) isAssignableFrom(BrowserViewModel::class.java) -> BrowserViewModel(tabRepository, queryUrlConverter) isAssignableFrom(BrowserTabViewModel::class.java) -> browserTabViewModel() isAssignableFrom(TabSwitcherViewModel::class.java) -> TabSwitcherViewModel(tabRepository, webViewSessionStorage) diff --git a/app/src/main/java/com/duckduckgo/app/onboarding/ui/OnboardingViewModel.kt b/app/src/main/java/com/duckduckgo/app/onboarding/ui/OnboardingViewModel.kt index 945d98d56dab..96a310126598 100644 --- a/app/src/main/java/com/duckduckgo/app/onboarding/ui/OnboardingViewModel.kt +++ b/app/src/main/java/com/duckduckgo/app/onboarding/ui/OnboardingViewModel.kt @@ -19,13 +19,10 @@ package com.duckduckgo.app.onboarding.ui import android.arch.lifecycle.ViewModel import com.duckduckgo.app.browser.defaultBrowsing.DefaultBrowserDetector import com.duckduckgo.app.onboarding.store.OnboardingStore -import com.duckduckgo.app.statistics.VariantManager -import com.duckduckgo.app.statistics.VariantManager.VariantFeature.DefaultBrowserFeature class OnboardingViewModel( private val onboardingStore: OnboardingStore, - private val defaultWebBrowserCapability: DefaultBrowserDetector, - private val variantManager: VariantManager + private val defaultWebBrowserCapability: DefaultBrowserDetector ) : ViewModel() { fun pageCount(): Int { @@ -50,10 +47,6 @@ class OnboardingViewModel( } private fun shouldShowDefaultBrowserPage(): Boolean { - val deviceSupported = - defaultWebBrowserCapability.deviceSupportsDefaultBrowserConfiguration() - val featureEnabled = variantManager.getVariant().hasFeature(DefaultBrowserFeature.ShowInOnboarding) - - return deviceSupported && featureEnabled + return defaultWebBrowserCapability.deviceSupportsDefaultBrowserConfiguration() } } 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 fce1b0b55606..8940e53f424c 100644 --- a/app/src/main/java/com/duckduckgo/app/statistics/VariantManager.kt +++ b/app/src/main/java/com/duckduckgo/app/statistics/VariantManager.kt @@ -30,7 +30,6 @@ interface VariantManager { sealed class VariantFeature { sealed class DefaultBrowserFeature : VariantFeature() { - object ShowInOnboarding : DefaultBrowserFeature() object ShowBanner : DefaultBrowserFeature() object ShowHomeScreenCallToActionSimpleButton : DefaultBrowserFeature() object ShowHomeScreenCallToActionBottomSheet : DefaultBrowserFeature() From 4396167554bbd3dc4540f01ad5369a17e42a7d86 Mon Sep 17 00:00:00 2001 From: Craig Russell Date: Mon, 3 Sep 2018 17:37:45 +0100 Subject: [PATCH 4/7] Feature/remove closed experiments (#345) * Remove onboarding as an experimental feature * Remove variants which have ended --- .../app/browser/BrowserTabViewModelTest.kt | 17 +-- .../DefaultBrowserBannerNotificationTest.kt | 98 -------------- ...efaultBrowserHomeScreenCallToActionTest.kt | 83 ------------ .../com/duckduckgo/app/di/TestAppComponent.kt | 2 - .../AppInstallSharedPreferencesTest.kt | 25 ---- .../app/statistics/VariantManagerTest.kt | 28 +--- .../app/browser/BrowserTabFragment.kt | 114 ----------------- .../app/browser/BrowserTabViewModel.kt | 46 ------- .../defaultBrowsing/DefaultBrowserDetector.kt | 14 +- .../DefaultBrowserNotification.kt | 121 ------------------ .../app/browser/di/BrowserModule.kt | 5 +- .../app/browser/di/DefaultBrowserModule.kt | 30 ----- .../com/duckduckgo/app/di/AppComponent.kt | 2 - .../duckduckgo/app/global/ViewModelFactory.kt | 5 - .../app/global/install/AppInstallStore.kt | 26 ---- .../app/statistics/VariantManager.kt | 13 -- .../main/res/layout/fragment_browser_tab.xml | 6 +- .../layout/include_banner_notification.xml | 110 ---------------- ..._screen_default_browser_call_to_action.xml | 82 ------------ ...lt_browser_call_to_action_bottom_sheet.xml | 118 ----------------- 20 files changed, 7 insertions(+), 938 deletions(-) delete mode 100644 app/src/androidTest/java/com/duckduckgo/app/browser/defaultBrowsing/DefaultBrowserBannerNotificationTest.kt delete mode 100644 app/src/androidTest/java/com/duckduckgo/app/browser/defaultBrowsing/DefaultBrowserHomeScreenCallToActionTest.kt delete mode 100644 app/src/main/java/com/duckduckgo/app/browser/defaultBrowsing/DefaultBrowserNotification.kt delete mode 100644 app/src/main/java/com/duckduckgo/app/browser/di/DefaultBrowserModule.kt delete mode 100644 app/src/main/res/layout/include_banner_notification.xml delete mode 100644 app/src/main/res/layout/include_home_screen_default_browser_call_to_action.xml delete mode 100644 app/src/main/res/layout/include_home_screen_default_browser_call_to_action_bottom_sheet.xml diff --git a/app/src/androidTest/java/com/duckduckgo/app/browser/BrowserTabViewModelTest.kt b/app/src/androidTest/java/com/duckduckgo/app/browser/BrowserTabViewModelTest.kt index 89d8aa92b5bc..1fdbbb9d90ab 100644 --- a/app/src/androidTest/java/com/duckduckgo/app/browser/BrowserTabViewModelTest.kt +++ b/app/src/androidTest/java/com/duckduckgo/app/browser/BrowserTabViewModelTest.kt @@ -32,8 +32,6 @@ import com.duckduckgo.app.browser.BrowserTabViewModel.Command.DisplayMessage import com.duckduckgo.app.browser.BrowserTabViewModel.Command.Navigate import com.duckduckgo.app.browser.LongPressHandler.RequiredAction.DownloadFile import com.duckduckgo.app.browser.LongPressHandler.RequiredAction.OpenInNewTab -import com.duckduckgo.app.browser.defaultBrowsing.DefaultBrowserDetector -import com.duckduckgo.app.browser.defaultBrowsing.DefaultBrowserNotification import com.duckduckgo.app.browser.favicon.FaviconDownloader import com.duckduckgo.app.browser.omnibar.OmnibarEntryConverter import com.duckduckgo.app.browser.session.WebViewSessionStorage @@ -47,7 +45,6 @@ import com.duckduckgo.app.privacy.db.SiteVisitedEntity import com.duckduckgo.app.privacy.model.PrivacyGrade import com.duckduckgo.app.privacy.store.TermsOfServiceStore import com.duckduckgo.app.settings.db.SettingsDataStore -import com.duckduckgo.app.statistics.VariantManager import com.duckduckgo.app.statistics.api.StatisticsUpdater import com.duckduckgo.app.tabs.model.TabRepository import com.duckduckgo.app.trackerdetection.model.TrackerNetwork @@ -104,21 +101,12 @@ class BrowserTabViewModelTest { @Mock private lateinit var mockOmnibarConverter: OmnibarEntryConverter - @Mock - private lateinit var mockDefaultBrowserDetector: DefaultBrowserDetector - - @Mock - private lateinit var mockDefaultBrowserNotification: DefaultBrowserNotification - @Mock private lateinit var mockTabsRepository: TabRepository @Mock private lateinit var webViewSessionStorage: WebViewSessionStorage - @Mock - private lateinit var variantManager: VariantManager - @Mock private lateinit var mockFaviconDownloader: FaviconDownloader @@ -154,14 +142,11 @@ class BrowserTabViewModelTest { autoCompleteApi = mockAutoCompleteApi, appSettingsPreferencesStore = mockSettingsStore, bookmarksDao = bookmarksDao, - defaultBrowserNotification = mockDefaultBrowserNotification, - defaultBrowserDetector = mockDefaultBrowserDetector, longPressHandler = mockLongPressHandler, appConfigurationDao = appConfigurationDao, webViewSessionStorage = webViewSessionStorage, specialUrlDetector = SpecialUrlDetector(), - faviconDownloader = mockFaviconDownloader, - variantManager = variantManager + faviconDownloader = mockFaviconDownloader ) testee.loadData("abc", null) diff --git a/app/src/androidTest/java/com/duckduckgo/app/browser/defaultBrowsing/DefaultBrowserBannerNotificationTest.kt b/app/src/androidTest/java/com/duckduckgo/app/browser/defaultBrowsing/DefaultBrowserBannerNotificationTest.kt deleted file mode 100644 index de51b2457c05..000000000000 --- a/app/src/androidTest/java/com/duckduckgo/app/browser/defaultBrowsing/DefaultBrowserBannerNotificationTest.kt +++ /dev/null @@ -1,98 +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.defaultBrowsing - -import com.duckduckgo.app.global.install.AppInstallStore -import com.duckduckgo.app.statistics.Variant -import com.duckduckgo.app.statistics.VariantManager -import com.duckduckgo.app.statistics.VariantManager.VariantFeature.DefaultBrowserFeature.ShowBanner -import com.nhaarman.mockito_kotlin.mock -import com.nhaarman.mockito_kotlin.whenever -import org.junit.Assert.assertFalse -import org.junit.Assert.assertTrue -import org.junit.Before -import org.junit.Test -import java.util.concurrent.TimeUnit - -class DefaultBrowserBannerNotificationTest { - - private lateinit var testee: DefaultBrowserTimeBasedNotification - - private val mockDetector: DefaultBrowserDetector = mock() - private val appInstallStore: AppInstallStore = mock() - private val variantManager: VariantManager = mock() - - @Before - fun setup() { - testee = DefaultBrowserTimeBasedNotification(mockDetector, appInstallStore, variantManager) - } - - @Test - fun whenDefaultBrowserNotSupportedByDeviceThenNotificationNotShown() { - configureEnvironment(false, true, true, false) - assertFalse(testee.shouldShowBannerNotification(browserShowing = true)) - } - - @Test - fun whenDefaultBrowserFeatureNotSupportedThenNotificationNotShown() { - configureEnvironment(true, false, true, false) - assertFalse(testee.shouldShowBannerNotification(browserShowing = true)) - } - - @Test - fun whenNoAppInstallTimeRecordedThenNotificationNotShown() { - configureEnvironment(true, true, false, false) - assertFalse(testee.shouldShowBannerNotification(browserShowing = true)) - } - - @Test - fun whenUserDeclinedPreviouslyThenNotificationNotShown() { - configureEnvironment(true, true, true, true) - assertFalse(testee.shouldShowBannerNotification(browserShowing = true)) - } - - @Test - fun whenNotEnoughTimeHasPassedSinceInstallThenNotificationNotShown() { - configureEnvironment(true, true, true, false) - whenever(appInstallStore.installTimestamp).thenReturn(0) - assertFalse(testee.shouldShowBannerNotification(browserShowing = true, timeNow = TimeUnit.SECONDS.toMillis(10))) - } - - @Test - fun whenEnoughTimeHasPassedSinceInstallThenNotificationShown() { - configureEnvironment(true, true, true, false) - whenever(appInstallStore.installTimestamp).thenReturn(0) - assertTrue(testee.shouldShowBannerNotification(browserShowing = true, timeNow = TimeUnit.DAYS.toMillis(100))) - } - - @Test - fun whenUserDeclinedHomeScreenCallToActionPreviouslyThenNotificationStillShown() { - configureEnvironment(true, true, true, false) - whenever(appInstallStore.hasUserDeclinedDefaultBrowserHomeScreenCallToActionPreviously()).thenReturn(true) - assertTrue(testee.shouldShowBannerNotification(browserShowing = true)) - } - - private fun configureEnvironment(deviceSupported: Boolean, featureEnabled: Boolean, timestampRecorded: Boolean, previousDecline: Boolean) { - whenever(mockDetector.deviceSupportsDefaultBrowserConfiguration()).thenReturn(deviceSupported) - whenever(variantManager.getVariant()).thenReturn(if (featureEnabled) variantWithFeatureEnabled() else variantWithFeatureDisabled()) - whenever(appInstallStore.hasInstallTimestampRecorded()).thenReturn(timestampRecorded) - whenever(appInstallStore.hasUserDeclinedDefaultBrowserBannerPreviously()).thenReturn(previousDecline) - } - - private fun variantWithFeatureEnabled() = Variant("", 0.0, listOf(ShowBanner)) - private fun variantWithFeatureDisabled() = Variant("", 0.0, listOf()) -} \ No newline at end of file diff --git a/app/src/androidTest/java/com/duckduckgo/app/browser/defaultBrowsing/DefaultBrowserHomeScreenCallToActionTest.kt b/app/src/androidTest/java/com/duckduckgo/app/browser/defaultBrowsing/DefaultBrowserHomeScreenCallToActionTest.kt deleted file mode 100644 index 7c82e1ff0e22..000000000000 --- a/app/src/androidTest/java/com/duckduckgo/app/browser/defaultBrowsing/DefaultBrowserHomeScreenCallToActionTest.kt +++ /dev/null @@ -1,83 +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.defaultBrowsing - -import com.duckduckgo.app.global.install.AppInstallStore -import com.duckduckgo.app.statistics.Variant -import com.duckduckgo.app.statistics.VariantManager -import com.duckduckgo.app.statistics.VariantManager.VariantFeature.DefaultBrowserFeature.ShowHomeScreenCallToActionSimpleButton -import com.nhaarman.mockito_kotlin.mock -import com.nhaarman.mockito_kotlin.whenever -import org.junit.Assert.assertFalse -import org.junit.Assert.assertTrue -import org.junit.Before -import org.junit.Test - -class DefaultBrowserHomeScreenCallToActionTest { - - private lateinit var testee: DefaultBrowserTimeBasedNotification - - private val mockDetector: DefaultBrowserDetector = mock() - private val appInstallStore: AppInstallStore = mock() - private val variantManager: VariantManager = mock() - - @Before - fun setup() { - testee = DefaultBrowserTimeBasedNotification(mockDetector, appInstallStore, variantManager) - } - - @Test - fun whenDefaultBrowserNotSupportedByDeviceThenCallToActionNotShown() { - configureEnvironment(false, true, true, false) - assertFalse(testee.shouldShowHomeScreenCallToActionNotification()) - } - - @Test - fun whenDefaultBrowserFeatureNotSupportedThenCallToActionNotShown() { - configureEnvironment(true, false, true, false) - assertFalse(testee.shouldShowHomeScreenCallToActionNotification( )) - } - - @Test - fun whenNoAppInstallTimeRecordedThenCallToActionNotShown() { - configureEnvironment(true, true, false, false) - assertFalse(testee.shouldShowHomeScreenCallToActionNotification( )) - } - - @Test - fun whenUserDeclinedPreviouslyThenCallToActionNotShown() { - configureEnvironment(true, true, true, true) - assertFalse(testee.shouldShowHomeScreenCallToActionNotification( )) - } - - @Test - fun whenAllOtherConditionsPassThenCallToActionShown() { - configureEnvironment(true, true, true, false) - whenever(appInstallStore.installTimestamp).thenReturn(0) - assertTrue(testee.shouldShowHomeScreenCallToActionNotification()) - } - - private fun configureEnvironment(deviceSupported: Boolean, featureEnabled: Boolean, timestampRecorded: Boolean, previousDecline: Boolean) { - whenever(mockDetector.deviceSupportsDefaultBrowserConfiguration()).thenReturn(deviceSupported) - whenever(variantManager.getVariant()).thenReturn(if (featureEnabled) variantWithFeatureEnabled() else variantWithFeatureDisabled()) - whenever(appInstallStore.hasInstallTimestampRecorded()).thenReturn(timestampRecorded) - whenever(appInstallStore.hasUserDeclinedDefaultBrowserHomeScreenCallToActionPreviously()).thenReturn(previousDecline) - } - - private fun variantWithFeatureEnabled() = Variant("", 0.0, listOf(ShowHomeScreenCallToActionSimpleButton)) - private fun variantWithFeatureDisabled() = Variant("", 0.0, listOf()) -} \ No newline at end of file diff --git a/app/src/androidTest/java/com/duckduckgo/app/di/TestAppComponent.kt b/app/src/androidTest/java/com/duckduckgo/app/di/TestAppComponent.kt index 0f786424fa6f..ff1b527fa62a 100644 --- a/app/src/androidTest/java/com/duckduckgo/app/di/TestAppComponent.kt +++ b/app/src/androidTest/java/com/duckduckgo/app/di/TestAppComponent.kt @@ -20,7 +20,6 @@ import android.app.Application import com.duckduckgo.app.TestApplication import com.duckduckgo.app.browser.autoComplete.BrowserAutoCompleteModule import com.duckduckgo.app.browser.di.BrowserModule -import com.duckduckgo.app.browser.di.DefaultBrowserModule import com.duckduckgo.app.browser.favicon.FaviconModule import com.duckduckgo.app.httpsupgrade.di.HttpsUpgraderModule import com.duckduckgo.app.onboarding.di.OnboardingModule @@ -55,7 +54,6 @@ import javax.inject.Singleton ResourceSurrogateModule::class, TrackerDetectionModule::class, NotificationModule::class, - DefaultBrowserModule::class, OnboardingModule::class, VariantModule::class, FaviconModule::class diff --git a/app/src/androidTest/java/com/duckduckgo/app/global/install/AppInstallSharedPreferencesTest.kt b/app/src/androidTest/java/com/duckduckgo/app/global/install/AppInstallSharedPreferencesTest.kt index 71a69b1a766a..7ba678a7f7e1 100644 --- a/app/src/androidTest/java/com/duckduckgo/app/global/install/AppInstallSharedPreferencesTest.kt +++ b/app/src/androidTest/java/com/duckduckgo/app/global/install/AppInstallSharedPreferencesTest.kt @@ -35,16 +35,6 @@ class AppInstallSharedPreferencesTest { testee = AppInstallSharedPreferences(context) } - @Test - fun whenInitializedThenUserHasNotBeenMarkedAsHavingPreviouslyDeclinedBanner() { - assertFalse(testee.hasUserDeclinedDefaultBrowserBannerPreviously()) - } - - @Test - fun whenInitializedThenUserHasNotBeenMarkedAsHavingPreviouslyDeclinedHomeScreenCallToAction() { - assertFalse(testee.hasUserDeclinedDefaultBrowserHomeScreenCallToActionPreviously()) - } - @Test fun whenInitializedThenInstallTimestampNotYetRecorded() { assertFalse(testee.hasInstallTimestampRecorded()) @@ -63,19 +53,4 @@ class AppInstallSharedPreferencesTest { testee.installTimestamp = timestamp assertEquals(timestamp, testee.installTimestamp) } - - @Test - fun whenUserPreviouslyDeclinedBannerThenThatIsReturnedWhenQueried() { - val timestamp = 1L - testee.recordUserDeclinedBannerToSetDefaultBrowser(timestamp) - assertTrue(testee.hasUserDeclinedDefaultBrowserBannerPreviously()) - } - - @Test - fun whenUserPreviouslyDeclinedHomeScreenCallToActionThenThatIsReturnedWhenQueried() { - val timestamp = 1L - testee.recordUserDeclinedHomeScreenCallToActionToSetDefaultBrowser(timestamp) - assertTrue(testee.hasUserDeclinedDefaultBrowserHomeScreenCallToActionPreviously()) - } - } \ No newline at end of file diff --git a/app/src/androidTest/java/com/duckduckgo/app/statistics/VariantManagerTest.kt b/app/src/androidTest/java/com/duckduckgo/app/statistics/VariantManagerTest.kt index 514d8c387a3b..9abca16331f6 100644 --- a/app/src/androidTest/java/com/duckduckgo/app/statistics/VariantManagerTest.kt +++ b/app/src/androidTest/java/com/duckduckgo/app/statistics/VariantManagerTest.kt @@ -16,38 +16,14 @@ package com.duckduckgo.app.statistics -import com.duckduckgo.app.statistics.VariantManager.VariantFeature.DefaultBrowserFeature.ShowHomeScreenCallToActionBottomSheet -import com.duckduckgo.app.statistics.VariantManager.VariantFeature.DefaultBrowserFeature.ShowHomeScreenCallToActionSimpleButton -import org.junit.Assert.* +import org.junit.Assert.assertEquals +import org.junit.Assert.fail import org.junit.Test class VariantManagerTest { private val variants = VariantManager.ACTIVE_VARIANTS - @Test - fun homeScreenCallToActionButtonVariantConfiguredCorrectly() { - val variant = variants.firstOrNull { it.key == "mq" } - assertEqualsDouble(1.0, variant!!.weight) - assertTrue(variant.hasFeature(ShowHomeScreenCallToActionSimpleButton)) - assertEquals(1, variant.features.size) - } - - @Test - fun homeScreenCallToActionBottomSheetVariantConfiguredCorrectly() { - val variant = variants.firstOrNull { it.key == "mp" } - assertEqualsDouble(1.0, variant!!.weight) - assertTrue(variant.hasFeature(ShowHomeScreenCallToActionBottomSheet)) - assertEquals(1, variant.features.size) - } - - @Test - fun controlVariantConfiguredCorrectly() { - val variant = variants.firstOrNull { it.key == "mr" } - assertEqualsDouble(1.0, variant!!.weight) - assertEquals(0, variant.features.size) - } - @Test fun serpVariantAConfiguredCorrectly() { val variant = variants.firstOrNull { it.key == "sa" } 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 b3cf2abff21d..8c298ca59054 100644 --- a/app/src/main/java/com/duckduckgo/app/browser/BrowserTabFragment.kt +++ b/app/src/main/java/com/duckduckgo/app/browser/BrowserTabFragment.kt @@ -21,7 +21,6 @@ import android.animation.LayoutTransition.CHANGING import android.animation.LayoutTransition.DISAPPEARING import android.annotation.SuppressLint import android.app.Activity.RESULT_OK -import android.app.ActivityOptions import android.arch.lifecycle.Observer import android.arch.lifecycle.ViewModelProviders import android.content.Context @@ -34,7 +33,6 @@ import android.os.Bundle import android.os.Environment import android.support.annotation.AnyThread import android.support.annotation.StringRes -import android.support.constraint.ConstraintSet import android.support.design.widget.Snackbar import android.support.v4.app.Fragment import android.support.v4.content.ContextCompat @@ -57,7 +55,6 @@ import androidx.core.view.postDelayed import com.duckduckgo.app.bookmarks.ui.SaveBookmarkDialogFragment import com.duckduckgo.app.browser.BrowserTabViewModel.* import com.duckduckgo.app.browser.autoComplete.BrowserAutoCompleteSuggestionsAdapter -import com.duckduckgo.app.browser.defaultBrowsing.DefaultBrowserInfoActivity import com.duckduckgo.app.browser.downloader.FileDownloadNotificationManager import com.duckduckgo.app.browser.downloader.FileDownloader import com.duckduckgo.app.browser.downloader.FileDownloader.PendingFileDownload @@ -73,9 +70,7 @@ import com.duckduckgo.app.privacy.renderer.icon import com.duckduckgo.app.tabs.model.TabEntity import dagger.android.support.AndroidSupportInjection import kotlinx.android.synthetic.main.fragment_browser_tab.* -import kotlinx.android.synthetic.main.include_banner_notification.* import kotlinx.android.synthetic.main.include_find_in_page.* -import kotlinx.android.synthetic.main.include_home_screen_default_browser_call_to_action.* 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.* @@ -86,9 +81,6 @@ import timber.log.Timber import java.io.File import javax.inject.Inject import kotlin.concurrent.thread -import kotlinx.android.synthetic.main.include_home_screen_default_browser_call_to_action_bottom_sheet.homeScreenCallToActionContainer as bottomSheetExperimentContainer -import kotlinx.android.synthetic.main.include_home_screen_default_browser_call_to_action_bottom_sheet.homeScreenCallToActionDismissButton as bottomSheetExperimentDismissButton -import kotlinx.android.synthetic.main.include_home_screen_default_browser_call_to_action_bottom_sheet.launchSettingsButton as bottomSheetExperimentLaunchSettingsButton class BrowserTabFragment : Fragment(), FindListener { @@ -171,8 +163,6 @@ class BrowserTabFragment : Fragment(), FindListener { private val logoHidingLayoutChangeListener by lazy { LogoHidingLayoutChangeListener(ddgLogo) } - private val callToActionConfigurator = CallToActionConfigurator() - override fun onAttach(context: Context?) { AndroidSupportInjection.inject(this) super.onAttach(context) @@ -192,7 +182,6 @@ class BrowserTabFragment : Fragment(), FindListener { createPopupMenu() configureObservers() configureToolbar() - configureBannerNotification() configureWebView() viewModel.registerWebViewListener(webViewClient, webChromeClient) configureOmnibarTextInput() @@ -265,10 +254,6 @@ class BrowserTabFragment : Fragment(), FindListener { it?.let { renderer.renderBrowserViewState(it) } }) - viewModel.defaultBrowserViewState.observe(this, Observer { - it?.let { renderer.renderDefaultBrowserBanner(it) } - }) - viewModel.loadingViewState.observe(this, Observer { it?.let { renderer.renderLoadingIndicator(it) } }) @@ -370,12 +355,6 @@ class BrowserTabFragment : Fragment(), FindListener { addHomeShortcut(it, context) } } - is Command.InflateCallToActionBottomSheet -> { - callToActionConfigurator.configureBottomSheetCallToAction() - } - is Command.InflateCallToActionSimpleButton -> { - callToActionConfigurator.configureButtonCallToAction() - } is Command.HandleExternalAppLink -> { externalAppLinkClicked(it) } } } @@ -493,15 +472,6 @@ class BrowserTabFragment : Fragment(), FindListener { }) } - private fun configureBannerNotification() { - dismissBannerButton.setOnClickListener { - viewModel.userDeclinedBannerToSetAsDefaultBrowser() - } - bannerNotification.setOnClickListener { - launchDefaultAppSystemSettingsFromBanner() - } - } - private fun configureFindInPage() { findInPageInput.setOnFocusChangeListener { _, hasFocus -> if (hasFocus && findInPageInput.text.toString() != viewModel.findInPageViewState.value?.searchTerm) { @@ -621,21 +591,6 @@ class BrowserTabFragment : Fragment(), FindListener { activity?.share(url, "") } - private fun launchDefaultAppSystemSettingsFromBanner() { - activity?.let { - val options = ActivityOptions.makeSceneTransitionAnimation(it, bannerNotification, "defaultBrowserBannerTransition") - val intent = DefaultBrowserInfoActivity.intent(it) - startActivity(intent, options.toBundle()) - } - } - - private fun launchDefaultAppSystemSettingsFromCallToActionButton() { - activity?.let { - val intent = DefaultBrowserInfoActivity.intent(it) - startActivity(intent) - } - } - private fun addBookmark() { val addBookmarkDialog = SaveBookmarkDialogFragment.createDialogCreationMode( existingTitle = webView?.title, @@ -851,29 +806,8 @@ class BrowserTabFragment : Fragment(), FindListener { private var lastSeenFindInPageViewState: FindInPageViewState? = null private var lastSeenBrowserViewState: BrowserViewState? = null private var lastSeenGlobalViewState: GlobalLayoutViewState? = null - private var lastSeenDefaultBrowserViewState: DefaultBrowserViewState? = null private var lastSeenAutoCompleteViewState: AutoCompleteViewState? = null - fun renderDefaultBrowserBanner(viewState: DefaultBrowserViewState) { - renderIfChanged(viewState, lastSeenDefaultBrowserViewState) { - lastSeenDefaultBrowserViewState = viewState - - if (viewState.showDefaultBrowserBanner) { - bannerNotification.show() - } else { - bannerNotification.gone() - } - - if (viewState.showHomeScreenCallToActionButton) { - homeScreenCallToActionContainer?.show() - } else { - homeScreenCallToActionContainer?.gone() - } - - logoHidingLayoutChangeListener.update() - } - } - fun renderAutocomplete(viewState: AutoCompleteViewState) { renderIfChanged(viewState, lastSeenAutoCompleteViewState) { lastSeenAutoCompleteViewState = viewState @@ -1056,52 +990,4 @@ class BrowserTabFragment : Fragment(), FindListener { private fun shouldUpdateOmnibarTextInput(viewState: OmnibarViewState, omnibarInput: String?) = !viewState.isEditing && omnibarTextInput.isDifferent(omnibarInput) } - - private inner class CallToActionConfigurator { - - fun configureBottomSheetCallToAction() { - if (callToActionStub == null) return - - callToActionStub.layoutResource = R.layout.include_home_screen_default_browser_call_to_action_bottom_sheet - val container = callToActionStub.inflate() - - adjustLogoConstraintsForCallToAction(container) - - bottomSheetExperimentLaunchSettingsButton.setOnClickListener { launchDefaultAppSystemSettingsFromCallToActionButton() } - bottomSheetExperimentDismissButton.setOnClickListener { viewModel.userDeclinedHomeScreenCallToActionToSetAsDefaultBrowser() } - } - - fun configureButtonCallToAction() { - if (callToActionStub == null) return - - callToActionStub.layoutResource = R.layout.include_home_screen_default_browser_call_to_action - val container = callToActionStub.inflate() - - adjustLogoConstraintsForCallToAction(container) - - val set = ConstraintSet() - set.clone(newTabLayout) - set.constrainPercentWidth(container.id, 0.9f) - set.connect(container.id, ConstraintSet.BOTTOM, ConstraintSet.PARENT_ID, ConstraintSet.BOTTOM, 10.toPx()) - set.applyTo(newTabLayout) - - homeScreenCallToActionContainer.setOnClickListener { launchDefaultAppSystemSettingsFromCallToActionButton() } - homeScreenCallToActionDismissButton.setOnClickListener { viewModel.userDeclinedHomeScreenCallToActionToSetAsDefaultBrowser() } - } - - /** - * We want to center logo in space available above call to action, but c2a isn't in original view hierarchy. - * After appropriate c2a is loaded, we programmatically apply ConstraintLayout constraints to position logo - */ - private fun adjustLogoConstraintsForCallToAction(callToActionContainer: View) { - - logoHidingLayoutChangeListener.callToActionButton = callToActionContainer - - ConstraintSet().also { - it.clone(newTabLayout) - it.connect(ddgLogo.id, ConstraintSet.BOTTOM, callToActionContainer.id, ConstraintSet.TOP, 0) - it.applyTo(newTabLayout) - } - } - } } 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 887acd2be40d..752753b04a19 100644 --- a/app/src/main/java/com/duckduckgo/app/browser/BrowserTabViewModel.kt +++ b/app/src/main/java/com/duckduckgo/app/browser/BrowserTabViewModel.kt @@ -40,8 +40,6 @@ import com.duckduckgo.app.bookmarks.ui.SaveBookmarkDialogFragment.SaveBookmarkLi import com.duckduckgo.app.browser.BrowserTabViewModel.Command.* import com.duckduckgo.app.browser.LongPressHandler.RequiredAction import com.duckduckgo.app.browser.SpecialUrlDetector.UrlType.IntentType -import com.duckduckgo.app.browser.defaultBrowsing.DefaultBrowserDetector -import com.duckduckgo.app.browser.defaultBrowsing.DefaultBrowserNotification import com.duckduckgo.app.browser.favicon.FaviconDownloader import com.duckduckgo.app.browser.omnibar.OmnibarEntryConverter import com.duckduckgo.app.browser.session.WebViewSessionStorage @@ -59,9 +57,6 @@ import com.duckduckgo.app.privacy.db.SiteVisitedEntity import com.duckduckgo.app.privacy.model.PrivacyGrade import com.duckduckgo.app.privacy.model.improvedGrade import com.duckduckgo.app.settings.db.SettingsDataStore -import com.duckduckgo.app.statistics.VariantManager -import com.duckduckgo.app.statistics.VariantManager.VariantFeature.DefaultBrowserFeature.ShowHomeScreenCallToActionBottomSheet -import com.duckduckgo.app.statistics.VariantManager.VariantFeature.DefaultBrowserFeature.ShowHomeScreenCallToActionSimpleButton import com.duckduckgo.app.statistics.api.StatisticsUpdater import com.duckduckgo.app.tabs.model.TabEntity import com.duckduckgo.app.tabs.model.TabRepository @@ -82,12 +77,9 @@ class BrowserTabViewModel( private val bookmarksDao: BookmarksDao, private val autoCompleteApi: AutoCompleteApi, private val appSettingsPreferencesStore: SettingsDataStore, - private val defaultBrowserDetector: DefaultBrowserDetector, - private val defaultBrowserNotification: DefaultBrowserNotification, private val longPressHandler: LongPressHandler, private val webViewSessionStorage: WebViewSessionStorage, private val specialUrlDetector: SpecialUrlDetector, - private val variantManager: VariantManager, private val faviconDownloader: FaviconDownloader, appConfigurationDao: AppConfigurationDao ) : WebViewClientListener, SaveBookmarkListener, ViewModel() { @@ -136,11 +128,6 @@ class BrowserTabViewModel( val searchResults: AutoCompleteResult = AutoCompleteResult("", emptyList()) ) - data class DefaultBrowserViewState( - val showDefaultBrowserBanner: Boolean = false, - val showHomeScreenCallToActionButton: Boolean = false - ) - sealed class Command { object LandingPage : Command() object Refresh : Command() @@ -162,8 +149,6 @@ class BrowserTabViewModel( class ShowFileChooser(val filePathCallback: ValueCallback>, val fileChooserParams: WebChromeClient.FileChooserParams) : Command() class HandleExternalAppLink(val appLink: IntentType) : Command() class AddHomeShortcut(val title: String, val url: String, val icon: Bitmap?= null) : Command() - object InflateCallToActionBottomSheet : Command() - object InflateCallToActionSimpleButton : Command() } val autoCompleteViewState: MutableLiveData = MutableLiveData() @@ -171,7 +156,6 @@ class BrowserTabViewModel( val globalLayoutState: MutableLiveData = MutableLiveData() val loadingViewState: MutableLiveData = MutableLiveData() val omnibarViewState: MutableLiveData = MutableLiveData() - val defaultBrowserViewState: MutableLiveData = MutableLiveData() val findInPageViewState: MutableLiveData = MutableLiveData() val tabs: LiveData> = tabRepository.liveTabs @@ -249,20 +233,6 @@ class BrowserTabViewModel( fun onViewVisible() { command.value = if (url.value == null) ShowKeyboard else Command.HideKeyboard - - val showBanner = defaultBrowserNotification.shouldShowBannerNotification(currentBrowserViewState().browserShowing) - val showCallToAction = defaultBrowserNotification.shouldShowHomeScreenCallToActionNotification() - - if (showCallToAction) { - val variant = variantManager.getVariant() - if (variant.hasFeature(ShowHomeScreenCallToActionBottomSheet)) { - command.value = InflateCallToActionBottomSheet - } else if (variant.hasFeature(ShowHomeScreenCallToActionSimpleButton)) { - command.value = InflateCallToActionSimpleButton - } - } - - defaultBrowserViewState.value = DefaultBrowserViewState(showBanner, showCallToAction) } fun onUserSubmittedQuery(input: String) { @@ -383,8 +353,6 @@ class BrowserTabViewModel( ) if (duckDuckGoUrlDetector.isDuckDuckGoQueryUrl(url)) { - val shouldShowBanner = defaultBrowserNotification.shouldShowBannerNotification(currentBrowserViewState.browserShowing) - defaultBrowserViewState.value = currentDefaultBrowserViewState().copy(showDefaultBrowserBanner = shouldShowBanner) statisticsUpdater.refreshRetentionAtb() } @@ -436,7 +404,6 @@ class BrowserTabViewModel( private fun currentFindInPageViewState(): FindInPageViewState = findInPageViewState.value!! private fun currentOmnibarViewState(): OmnibarViewState = omnibarViewState.value!! private fun currentLoadingViewState(): LoadingViewState = loadingViewState.value!! - private fun currentDefaultBrowserViewState(): DefaultBrowserViewState = defaultBrowserViewState.value!! fun onOmnibarInputStateChanged(query: String, hasFocus: Boolean) { @@ -582,7 +549,6 @@ class BrowserTabViewModel( private fun initializeViewStates() { globalLayoutState.value = GlobalLayoutViewState() - defaultBrowserViewState.value = DefaultBrowserViewState(showHomeScreenCallToActionButton = defaultBrowserNotification.shouldShowHomeScreenCallToActionNotification()) browserViewState.value = BrowserViewState() loadingViewState.value = LoadingViewState() autoCompleteViewState.value = AutoCompleteViewState() @@ -596,18 +562,6 @@ class BrowserTabViewModel( } } - fun userDeclinedBannerToSetAsDefaultBrowser() { - defaultBrowserDetector.userDeclinedBannerToSetAsDefaultBrowser() - val currentDefaultBrowserViewState = currentDefaultBrowserViewState() - defaultBrowserViewState.value = currentDefaultBrowserViewState.copy(showDefaultBrowserBanner = false) - } - - fun userDeclinedHomeScreenCallToActionToSetAsDefaultBrowser() { - defaultBrowserDetector.userDeclinedHomeScreenCallToActionToSetAsDefaultBrowser() - val currentDefaultBrowserViewState = currentDefaultBrowserViewState() - defaultBrowserViewState.value = currentDefaultBrowserViewState.copy(showHomeScreenCallToActionButton = false) - } - fun saveWebViewState(webView: WebView?, tabId: String) { webViewSessionStorage.saveSession(webView, tabId) } diff --git a/app/src/main/java/com/duckduckgo/app/browser/defaultBrowsing/DefaultBrowserDetector.kt b/app/src/main/java/com/duckduckgo/app/browser/defaultBrowsing/DefaultBrowserDetector.kt index e8888f5192d1..fb6be5602e33 100644 --- a/app/src/main/java/com/duckduckgo/app/browser/defaultBrowsing/DefaultBrowserDetector.kt +++ b/app/src/main/java/com/duckduckgo/app/browser/defaultBrowsing/DefaultBrowserDetector.kt @@ -24,19 +24,15 @@ import android.content.pm.ResolveInfo import android.net.Uri import android.os.Build import com.duckduckgo.app.browser.BuildConfig -import com.duckduckgo.app.global.install.AppInstallStore import timber.log.Timber import javax.inject.Inject interface DefaultBrowserDetector { fun deviceSupportsDefaultBrowserConfiguration(): Boolean fun isCurrentlyConfiguredAsDefaultBrowser(): Boolean - fun userDeclinedBannerToSetAsDefaultBrowser(timestamp: Long = System.currentTimeMillis()) - fun userDeclinedHomeScreenCallToActionToSetAsDefaultBrowser(timestamp: Long = System.currentTimeMillis()) } -class AndroidDefaultBrowserDetector @Inject constructor(private val context: Context, private val appInstallStore: AppInstallStore) : - DefaultBrowserDetector { +class AndroidDefaultBrowserDetector @Inject constructor(private val context: Context) : DefaultBrowserDetector { override fun deviceSupportsDefaultBrowserConfiguration(): Boolean { return Build.VERSION.SDK_INT >= Build.VERSION_CODES.N @@ -50,12 +46,4 @@ class AndroidDefaultBrowserDetector @Inject constructor(private val context: Con Timber.i("Default browser identified as ${resolutionInfo?.activityInfo?.packageName}") return defaultAlready } - - override fun userDeclinedBannerToSetAsDefaultBrowser(timestamp: Long) { - appInstallStore.recordUserDeclinedBannerToSetDefaultBrowser(timestamp) - } - - override fun userDeclinedHomeScreenCallToActionToSetAsDefaultBrowser(timestamp: Long) { - appInstallStore.recordUserDeclinedHomeScreenCallToActionToSetDefaultBrowser(timestamp) - } } \ No newline at end of file diff --git a/app/src/main/java/com/duckduckgo/app/browser/defaultBrowsing/DefaultBrowserNotification.kt b/app/src/main/java/com/duckduckgo/app/browser/defaultBrowsing/DefaultBrowserNotification.kt deleted file mode 100644 index 64642113ac5e..000000000000 --- a/app/src/main/java/com/duckduckgo/app/browser/defaultBrowsing/DefaultBrowserNotification.kt +++ /dev/null @@ -1,121 +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.defaultBrowsing - -import com.duckduckgo.app.browser.BuildConfig -import com.duckduckgo.app.global.install.AppInstallStore -import com.duckduckgo.app.statistics.VariantManager -import com.duckduckgo.app.statistics.VariantManager.VariantFeature.DefaultBrowserFeature -import com.duckduckgo.app.statistics.VariantManager.VariantFeature.DefaultBrowserFeature.ShowBanner -import com.duckduckgo.app.statistics.VariantManager.VariantFeature.DefaultBrowserFeature.ShowHomeScreenCallToActionSimpleButton -import java.util.concurrent.TimeUnit -import javax.inject.Inject - - -interface DefaultBrowserNotification { - fun shouldShowBannerNotification( - browserShowing: Boolean, - timeNow: Long = System.currentTimeMillis() - ): Boolean - - fun shouldShowHomeScreenCallToActionNotification(): Boolean -} - -class DefaultBrowserTimeBasedNotification @Inject constructor( - private val defaultBrowserDetector: DefaultBrowserDetector, - private val appInstallStore: AppInstallStore, - private val variantManager: VariantManager -) : DefaultBrowserNotification { - - override fun shouldShowBannerNotification(browserShowing: Boolean, timeNow: Long): Boolean { - - if (!browserShowing) { - return false - } - - if (!isDeviceCapable()) { - return false - } - - if (!isFeatureEnabled(ShowBanner)) { - return false - } - - if (isAlreadyDefaultBrowser()) { - return false - } - - if (appInstallStore.hasUserDeclinedDefaultBrowserBannerPreviously()) { - return false - } - - return hasEnoughTimeElapsed(timeNow) - } - - override fun shouldShowHomeScreenCallToActionNotification(): Boolean { - - if (!isDeviceCapable()) { - return false - } - - if (!isFeatureEnabled(ShowHomeScreenCallToActionSimpleButton) && !isFeatureEnabled(DefaultBrowserFeature.ShowHomeScreenCallToActionBottomSheet)) { - return false - } - - if (isAlreadyDefaultBrowser()) { - return false - } - - if (appInstallStore.hasUserDeclinedDefaultBrowserHomeScreenCallToActionPreviously()) { - return false - } - - return true - } - - private fun isDeviceCapable(): Boolean { - return defaultBrowserDetector.deviceSupportsDefaultBrowserConfiguration() && appInstallStore.hasInstallTimestampRecorded() - } - - private fun isFeatureEnabled(feature: DefaultBrowserFeature): Boolean { - return variantManager.getVariant().hasFeature(feature) - } - - private fun isAlreadyDefaultBrowser(): Boolean { - return defaultBrowserDetector.isCurrentlyConfiguredAsDefaultBrowser() - } - - private fun hasEnoughTimeElapsed(now: Long): Boolean { - val elapsed = calculateElapsedTime(now) - - return elapsed >= ELAPSED_TIME_THRESHOLD_MS - } - - private fun calculateElapsedTime(now: Long): Long { - return now - appInstallStore.installTimestamp - } - - companion object { - - // time period to wait after first launch before showing notification banner - set much shorter for DEBUG builds so it can be tested - private val ELAPSED_TIME_THRESHOLD_PRODUCTION = TimeUnit.DAYS.toMillis(3) - private val ELAPSED_TIME_THRESHOLD_DEBUG = TimeUnit.SECONDS.toMillis(20) - - private val ELAPSED_TIME_THRESHOLD_MS = if (BuildConfig.DEBUG) ELAPSED_TIME_THRESHOLD_DEBUG else ELAPSED_TIME_THRESHOLD_PRODUCTION - } - -} \ No newline at end of file diff --git a/app/src/main/java/com/duckduckgo/app/browser/di/BrowserModule.kt b/app/src/main/java/com/duckduckgo/app/browser/di/BrowserModule.kt index 4260223f1da8..489b1a350376 100644 --- a/app/src/main/java/com/duckduckgo/app/browser/di/BrowserModule.kt +++ b/app/src/main/java/com/duckduckgo/app/browser/di/BrowserModule.kt @@ -23,7 +23,6 @@ import com.duckduckgo.app.browser.defaultBrowsing.DefaultBrowserDetector import com.duckduckgo.app.browser.session.WebViewSessionInMemoryStorage import com.duckduckgo.app.browser.session.WebViewSessionStorage import com.duckduckgo.app.global.AppUrl -import com.duckduckgo.app.global.install.AppInstallStore import com.duckduckgo.app.statistics.VariantManager import com.duckduckgo.app.statistics.pixels.Pixel import com.duckduckgo.app.statistics.store.StatisticsDataStore @@ -49,8 +48,8 @@ class BrowserModule { } @Provides - fun defaultWebBrowserCapability(context: Context, appInstallStore: AppInstallStore): DefaultBrowserDetector { - return AndroidDefaultBrowserDetector(context, appInstallStore) + fun defaultWebBrowserCapability(context: Context): DefaultBrowserDetector { + return AndroidDefaultBrowserDetector(context) } @Singleton diff --git a/app/src/main/java/com/duckduckgo/app/browser/di/DefaultBrowserModule.kt b/app/src/main/java/com/duckduckgo/app/browser/di/DefaultBrowserModule.kt deleted file mode 100644 index ea89a055cdcb..000000000000 --- a/app/src/main/java/com/duckduckgo/app/browser/di/DefaultBrowserModule.kt +++ /dev/null @@ -1,30 +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.di - -import com.duckduckgo.app.browser.defaultBrowsing.DefaultBrowserNotification -import com.duckduckgo.app.browser.defaultBrowsing.DefaultBrowserTimeBasedNotification -import dagger.Binds -import dagger.Module - - -@Module -abstract class DefaultBrowserModule { - - @Binds - abstract fun defaultBrowserNotification(defaultBrowserNotification: DefaultBrowserTimeBasedNotification): DefaultBrowserNotification -} \ No newline at end of file diff --git a/app/src/main/java/com/duckduckgo/app/di/AppComponent.kt b/app/src/main/java/com/duckduckgo/app/di/AppComponent.kt index 5a06bcc5200f..c12bd0610d36 100644 --- a/app/src/main/java/com/duckduckgo/app/di/AppComponent.kt +++ b/app/src/main/java/com/duckduckgo/app/di/AppComponent.kt @@ -20,7 +20,6 @@ package com.duckduckgo.app.di import android.app.Application import com.duckduckgo.app.browser.autoComplete.BrowserAutoCompleteModule import com.duckduckgo.app.browser.di.BrowserModule -import com.duckduckgo.app.browser.di.DefaultBrowserModule import com.duckduckgo.app.browser.favicon.FaviconModule import com.duckduckgo.app.global.DuckDuckGoApplication import com.duckduckgo.app.httpsupgrade.di.HttpsUpgraderModule @@ -52,7 +51,6 @@ import javax.inject.Singleton ResourceSurrogateModule::class, TrackerDetectionModule::class, NotificationModule::class, - DefaultBrowserModule::class, OnboardingModule::class, VariantModule::class, FaviconModule::class diff --git a/app/src/main/java/com/duckduckgo/app/global/ViewModelFactory.kt b/app/src/main/java/com/duckduckgo/app/global/ViewModelFactory.kt index 296db7d2c1e6..da5b5a81c128 100644 --- a/app/src/main/java/com/duckduckgo/app/global/ViewModelFactory.kt +++ b/app/src/main/java/com/duckduckgo/app/global/ViewModelFactory.kt @@ -23,7 +23,6 @@ import com.duckduckgo.app.bookmarks.db.BookmarksDao import com.duckduckgo.app.bookmarks.ui.BookmarksViewModel import com.duckduckgo.app.browser.* import com.duckduckgo.app.browser.defaultBrowsing.DefaultBrowserDetector -import com.duckduckgo.app.browser.defaultBrowsing.DefaultBrowserNotification import com.duckduckgo.app.browser.favicon.FaviconDownloader import com.duckduckgo.app.browser.omnibar.QueryUrlConverter import com.duckduckgo.app.browser.session.WebViewSessionStorage @@ -65,7 +64,6 @@ class ViewModelFactory @Inject constructor( private val bookmarksDao: BookmarksDao, private val autoCompleteApi: AutoCompleteApi, private val appSettingsPreferencesStore: SettingsDataStore, - private val defaultBrowserNotification: DefaultBrowserNotification, private val webViewLongPressHandler: LongPressHandler, private val defaultBrowserDetector: DefaultBrowserDetector, private val variantManager: VariantManager, @@ -110,12 +108,9 @@ class ViewModelFactory @Inject constructor( networkLeaderboardDao = networkLeaderboardDao, bookmarksDao = bookmarksDao, appSettingsPreferencesStore = appSettingsPreferencesStore, - defaultBrowserDetector = defaultBrowserDetector, - defaultBrowserNotification = defaultBrowserNotification, appConfigurationDao = appConfigurationDao, longPressHandler = webViewLongPressHandler, webViewSessionStorage = webViewSessionStorage, - variantManager = variantManager, autoCompleteApi = autoCompleteApi, specialUrlDetector = specialUrlDetector, faviconDownloader = faviconDownloader diff --git a/app/src/main/java/com/duckduckgo/app/global/install/AppInstallStore.kt b/app/src/main/java/com/duckduckgo/app/global/install/AppInstallStore.kt index bb4cda8d129b..c9fde1e63041 100644 --- a/app/src/main/java/com/duckduckgo/app/global/install/AppInstallStore.kt +++ b/app/src/main/java/com/duckduckgo/app/global/install/AppInstallStore.kt @@ -27,10 +27,6 @@ interface AppInstallStore { var installTimestamp: Long fun hasInstallTimestampRecorded() : Boolean - fun recordUserDeclinedBannerToSetDefaultBrowser(timestamp: Long = System.currentTimeMillis()) - fun recordUserDeclinedHomeScreenCallToActionToSetDefaultBrowser(timestamp: Long = System.currentTimeMillis()) - fun hasUserDeclinedDefaultBrowserBannerPreviously(): Boolean - fun hasUserDeclinedDefaultBrowserHomeScreenCallToActionPreviously(): Boolean } class AppInstallSharedPreferences @Inject constructor(private val context: Context) : AppInstallStore { @@ -40,26 +36,6 @@ class AppInstallSharedPreferences @Inject constructor(private val context: Conte override fun hasInstallTimestampRecorded(): Boolean = preferences.contains(KEY_TIMESTAMP_UTC) - override fun recordUserDeclinedBannerToSetDefaultBrowser(timestamp: Long) { - preferences.edit { - putLong(KEY_TIMESTAMP_USER_DECLINED_BANNER_DEFAULT_BROWSER, timestamp) - } - } - - override fun recordUserDeclinedHomeScreenCallToActionToSetDefaultBrowser(timestamp: Long) { - preferences.edit { - putLong(KEY_TIMESTAMP_USER_DECLINED_CALL_TO_ACTION_DEFAULT_BROWSER, timestamp) - } - } - - override fun hasUserDeclinedDefaultBrowserBannerPreviously(): Boolean { - return preferences.contains(KEY_TIMESTAMP_USER_DECLINED_BANNER_DEFAULT_BROWSER) - } - - override fun hasUserDeclinedDefaultBrowserHomeScreenCallToActionPreviously(): Boolean { - return preferences.contains(KEY_TIMESTAMP_USER_DECLINED_CALL_TO_ACTION_DEFAULT_BROWSER) - } - private val preferences: SharedPreferences get() = context.getSharedPreferences(FILENAME, Context.MODE_PRIVATE) @@ -68,7 +44,5 @@ class AppInstallSharedPreferences @Inject constructor(private val context: Conte @VisibleForTesting const val FILENAME = "com.duckduckgo.app.install.settings" const val KEY_TIMESTAMP_UTC = "INSTALL_TIMESTAMP_UTC" - const val KEY_TIMESTAMP_USER_DECLINED_BANNER_DEFAULT_BROWSER = "USER_DECLINED_DEFAULT_BROWSER_TIMESTAMP_UTC" - const val KEY_TIMESTAMP_USER_DECLINED_CALL_TO_ACTION_DEFAULT_BROWSER = "USER_DECLINED_DEFAULT_BROWSER_CALL_TO_ACTION_TIMESTAMP_UTC" } } \ 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 8940e53f424c..98127a4c45e0 100644 --- a/app/src/main/java/com/duckduckgo/app/statistics/VariantManager.kt +++ b/app/src/main/java/com/duckduckgo/app/statistics/VariantManager.kt @@ -19,8 +19,6 @@ package com.duckduckgo.app.statistics import android.os.Build import android.support.annotation.WorkerThread import com.duckduckgo.app.statistics.VariantManager.Companion.DEFAULT_VARIANT -import com.duckduckgo.app.statistics.VariantManager.VariantFeature.DefaultBrowserFeature.ShowHomeScreenCallToActionBottomSheet -import com.duckduckgo.app.statistics.VariantManager.VariantFeature.DefaultBrowserFeature.ShowHomeScreenCallToActionSimpleButton import com.duckduckgo.app.statistics.store.StatisticsDataStore import timber.log.Timber @@ -29,11 +27,6 @@ interface VariantManager { sealed class VariantFeature { - sealed class DefaultBrowserFeature : VariantFeature() { - object ShowBanner : DefaultBrowserFeature() - object ShowHomeScreenCallToActionSimpleButton : DefaultBrowserFeature() - object ShowHomeScreenCallToActionBottomSheet : DefaultBrowserFeature() - } } companion object { @@ -42,12 +35,6 @@ interface VariantManager { val DEFAULT_VARIANT = Variant(key = "", features = emptyList()) val ACTIVE_VARIANTS = listOf( - Variant(key = "mp", weight = 1.0, features = listOf(ShowHomeScreenCallToActionBottomSheet)), - Variant(key = "mq", weight = 1.0, features = listOf(ShowHomeScreenCallToActionSimpleButton)), - - // control group - Variant(key = "mr", weight = 1.0, features = emptyList()), - // SERP variants - do not remove Variant(key = "sa", weight = 1.0, features = emptyList()), Variant(key = "sb", weight = 1.0, features = emptyList()) diff --git a/app/src/main/res/layout/fragment_browser_tab.xml b/app/src/main/res/layout/fragment_browser_tab.xml index 2d01af870076..fcf7243c9a26 100644 --- a/app/src/main/res/layout/fragment_browser_tab.xml +++ b/app/src/main/res/layout/fragment_browser_tab.xml @@ -72,13 +72,9 @@ app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" - app:layout_constraintTop_toBottomOf="@id/bannerNotification" + app:layout_constraintTop_toTopOf="parent" tools:background="#4F00" /> - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/app/src/main/res/layout/include_home_screen_default_browser_call_to_action.xml b/app/src/main/res/layout/include_home_screen_default_browser_call_to_action.xml deleted file mode 100644 index d8e8c02ce4c2..000000000000 --- a/app/src/main/res/layout/include_home_screen_default_browser_call_to_action.xml +++ /dev/null @@ -1,82 +0,0 @@ - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/app/src/main/res/layout/include_home_screen_default_browser_call_to_action_bottom_sheet.xml b/app/src/main/res/layout/include_home_screen_default_browser_call_to_action_bottom_sheet.xml deleted file mode 100644 index 8b569a889dca..000000000000 --- a/app/src/main/res/layout/include_home_screen_default_browser_call_to_action_bottom_sheet.xml +++ /dev/null @@ -1,118 +0,0 @@ - - - - - - - - - - - -