Skip to content

Commit 78eb66c

Browse files
committed
Add user toggle to control tracker animation
1 parent 42191d1 commit 78eb66c

12 files changed

Lines changed: 219 additions & 3 deletions

File tree

app/src/androidTest/java/com/duckduckgo/app/browser/BrowserTabViewModelTest.kt

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4256,6 +4256,45 @@ class BrowserTabViewModelTest {
42564256
assertFalse(loadingViewState().trackersAnimationEnabled)
42574257
}
42584258

4259+
@Test
4260+
fun whenUserPreferenceDisabledThenTrackersAnimationDisabled() {
4261+
whenever(mockSettingsDataStore.showTrackersCountInAddressBar).thenReturn(false)
4262+
loadUrl("https://example.com")
4263+
assertFalse(loadingViewState().trackersAnimationEnabled)
4264+
}
4265+
4266+
@Test
4267+
fun whenUserPreferenceEnabledAndPrivacyProtectionActiveThenTrackersAnimationEnabled() {
4268+
whenever(mockSettingsDataStore.showTrackersCountInAddressBar).thenReturn(true)
4269+
whenever(mockContentBlocking.isAnException("example.com")).thenReturn(false)
4270+
loadUrl("https://example.com")
4271+
assertTrue(loadingViewState().trackersAnimationEnabled)
4272+
}
4273+
4274+
@Test
4275+
fun whenUserPreferenceDisabledEvenWithPrivacyProtectionActiveThenTrackersAnimationDisabled() {
4276+
whenever(mockSettingsDataStore.showTrackersCountInAddressBar).thenReturn(false)
4277+
whenever(mockContentBlocking.isAnException("example.com")).thenReturn(false)
4278+
loadUrl("https://example.com")
4279+
assertFalse(loadingViewState().trackersAnimationEnabled)
4280+
}
4281+
4282+
@Test
4283+
fun whenUserPreferenceEnabledButPrivacyProtectionDisabledThenTrackersAnimationDisabled() {
4284+
whenever(mockSettingsDataStore.showTrackersCountInAddressBar).thenReturn(true)
4285+
whenever(mockContentBlocking.isAnException("example.com")).thenReturn(true)
4286+
loadUrl("https://example.com")
4287+
assertFalse(loadingViewState().trackersAnimationEnabled)
4288+
}
4289+
4290+
@Test
4291+
fun whenUserPreferenceDisabledAndPrivacyProtectionDisabledThenTrackersAnimationDisabled() {
4292+
whenever(mockSettingsDataStore.showTrackersCountInAddressBar).thenReturn(false)
4293+
whenever(mockContentBlocking.isAnException("example.com")).thenReturn(true)
4294+
loadUrl("https://example.com")
4295+
assertFalse(loadingViewState().trackersAnimationEnabled)
4296+
}
4297+
42594298
@Test
42604299
fun whenEditBookmarkRequestedThenRepositoryIsNotUpdated() =
42614300
runTest {

app/src/main/java/com/duckduckgo/app/appearance/AppearanceActivity.kt

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,11 @@ class AppearanceActivity : DuckDuckGoActivity() {
100100
viewModel.onShowTrackersCountInTabSwitcherChanged(isChecked)
101101
}
102102

103+
private val showTrackersCountInAddressBar =
104+
CompoundButton.OnCheckedChangeListener { _, isChecked ->
105+
viewModel.onShowTrackersCountInAddressBarChanged(isChecked)
106+
}
107+
103108
private val changeIconFlow =
104109
registerForActivityResult(ChangeIconContract()) { resultOk ->
105110
if (resultOk) {
@@ -173,6 +178,12 @@ class AppearanceActivity : DuckDuckGoActivity() {
173178
viewState.isTrackersCountInTabSwitcherEnabled,
174179
showTrackersCountInTabSwitcher,
175180
)
181+
binding.showTrackersCountInAddressBar.isVisible = viewState.shouldShowTrackersCountInAddressBar
182+
binding.trackersCountInAddressBarDivider.isVisible = viewState.shouldShowTrackersCountInAddressBar
183+
binding.showTrackersCountInAddressBar.quietlySetIsChecked(
184+
viewState.isTrackersCountInAddressBarEnabled,
185+
showTrackersCountInAddressBar,
186+
)
176187
configureOmnibarSettings(it)
177188
}
178189
}.launchIn(lifecycleScope)

app/src/main/java/com/duckduckgo/app/appearance/AppearanceViewModel.kt

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ import androidx.lifecycle.ViewModel
2020
import androidx.lifecycle.viewModelScope
2121
import androidx.webkit.WebViewFeature
2222
import com.duckduckgo.anvil.annotations.ContributesViewModel
23+
import com.duckduckgo.app.browser.animations.AddressBarTrackersAnimationManager
2324
import com.duckduckgo.app.browser.api.OmnibarRepository
2425
import com.duckduckgo.app.browser.omnibar.OmnibarType
2526
import com.duckduckgo.app.browser.urldisplay.UrlDisplayRepository
@@ -58,6 +59,7 @@ class AppearanceViewModel @Inject constructor(
5859
private val pixel: Pixel,
5960
private val dispatcherProvider: DispatcherProvider,
6061
private val tabSwitcherDataStore: TabSwitcherDataStore,
62+
private val addressBarTrackersAnimationManager: AddressBarTrackersAnimationManager,
6163
omnibarRepository: OmnibarRepository,
6264
) : ViewModel() {
6365
data class ViewState(
@@ -69,6 +71,8 @@ class AppearanceViewModel @Inject constructor(
6971
val omnibarType: OmnibarType = OmnibarType.SINGLE_TOP,
7072
val isFullUrlEnabled: Boolean = true,
7173
val isTrackersCountInTabSwitcherEnabled: Boolean = true,
74+
val isTrackersCountInAddressBarEnabled: Boolean = true,
75+
val shouldShowTrackersCountInAddressBar: Boolean = false,
7276
val shouldShowSplitOmnibarSettings: Boolean = false,
7377
)
7478

@@ -95,6 +99,7 @@ class AppearanceViewModel @Inject constructor(
9599
supportsForceDarkMode = WebViewFeature.isFeatureSupported(WebViewFeature.ALGORITHMIC_DARKENING),
96100
omnibarType = settingsDataStore.omnibarType,
97101
shouldShowSplitOmnibarSettings = omnibarRepository.isSplitOmnibarAvailable,
102+
isTrackersCountInAddressBarEnabled = settingsDataStore.showTrackersCountInAddressBar,
98103
),
99104
)
100105

@@ -103,9 +108,11 @@ class AppearanceViewModel @Inject constructor(
103108
urlDisplayRepository.isFullUrlEnabled,
104109
tabSwitcherDataStore.isTrackersAnimationInfoTileHidden(),
105110
) { currentViewState, isFullUrlEnabled, isTrackersAnimationTileHidden ->
111+
val isFeatureEnabled = addressBarTrackersAnimationManager.isFeatureEnabled()
106112
currentViewState.copy(
107113
isTrackersCountInTabSwitcherEnabled = !isTrackersAnimationTileHidden,
108114
isFullUrlEnabled = isFullUrlEnabled,
115+
shouldShowTrackersCountInAddressBar = isFeatureEnabled,
109116
)
110117
}.stateIn(viewModelScope, SharingStarted.Lazily, viewState.value)
111118

@@ -194,4 +201,14 @@ class AppearanceViewModel @Inject constructor(
194201
pixel.fire(AppPixelName.SETTINGS_APPEARANCE_IS_TRACKER_COUNT_IN_TAB_SWITCHER_TOGGLED, params)
195202
}
196203
}
204+
205+
fun onShowTrackersCountInAddressBarChanged(checked: Boolean) {
206+
viewModelScope.launch(dispatcherProvider.io()) {
207+
settingsDataStore.showTrackersCountInAddressBar = checked
208+
viewState.update { it.copy(isTrackersCountInAddressBarEnabled = checked) }
209+
210+
val params = mapOf(Pixel.PixelParameter.IS_ENABLED to checked.toString())
211+
pixel.fire(AppPixelName.SETTINGS_APPEARANCE_IS_TRACKER_COUNT_IN_ADDRESS_BAR_TOGGLED, params)
212+
}
213+
}
197214
}

app/src/main/java/com/duckduckgo/app/browser/BrowserTabViewModel.kt

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1753,7 +1753,8 @@ class BrowserTabViewModel @Inject constructor(
17531753
withContext(dispatchers.main()) {
17541754
loadingViewState.value =
17551755
currentLoadingViewState().copy(
1756-
trackersAnimationEnabled = !(privacyProtectionDisabled || currentBrowserViewState().maliciousSiteBlocked),
1756+
trackersAnimationEnabled = !(privacyProtectionDisabled || currentBrowserViewState().maliciousSiteBlocked)
1757+
&& settingsDataStore.showTrackersCountInAddressBar,
17571758
url = site?.url ?: "",
17581759
)
17591760
}
@@ -2151,7 +2152,7 @@ class BrowserTabViewModel @Inject constructor(
21512152
loadingViewState.value =
21522153
currentLoadingViewState().copy(
21532154
isLoading = true,
2154-
trackersAnimationEnabled = true,
2155+
trackersAnimationEnabled = settingsDataStore.showTrackersCountInAddressBar,
21552156
/*We set the progress to 20 so the omnibar starts animating and the user knows we are loading the page.
21562157
* We don't show the browser until the page actually starts loading, to prevent previous sites from briefly
21572158
* showing in case the URL was blocked locally and therefore never started to show*/

app/src/main/java/com/duckduckgo/app/browser/omnibar/OmnibarLayoutViewModel.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -903,7 +903,7 @@ class OmnibarLayoutViewModel @Inject constructor(
903903
Command.StartTrackersAnimation(
904904
entities = decoration.entities,
905905
isCustomTab = viewState.value.viewMode is CustomTab,
906-
isAddressBarTrackersAnimationEnabled = addressBarTrackersAnimationManager.isFeatureEnabled(),
906+
isAddressBarTrackersAnimationEnabled = viewState.value.isAddressBarTrackersAnimationEnabled,
907907
),
908908
)
909909
}

app/src/main/java/com/duckduckgo/app/global/api/PixelParamRemovalInterceptor.kt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,7 @@ object PixelInterceptorPixelsRequiringDataCleaning : PixelParamRemovalPlugin {
127127
AppPixelName.SEARCH_WIDGET_ADDED.pixelName to PixelParameter.removeAtb(),
128128
AppPixelName.SEARCH_WIDGET_DELETED.pixelName to PixelParameter.removeAtb(),
129129
AppPixelName.SETTINGS_APPEARANCE_IS_TRACKER_COUNT_IN_TAB_SWITCHER_TOGGLED.pixelName to PixelParameter.removeAll(),
130+
AppPixelName.SETTINGS_APPEARANCE_IS_TRACKER_COUNT_IN_ADDRESS_BAR_TOGGLED.pixelName to PixelParameter.removeAll(),
130131
AppPixelName.TIMEOUT_WAITING_FOR_APP_REFERRER.pixelName to PixelParameter.removeAtb(),
131132
AppPixelName.PRODUCT_TELEMETRY_SURFACE_LANDSCAPE_ORIENTATION_USED.pixelName to PixelParameter.removeAtb(),
132133
AppPixelName.PRODUCT_TELEMETRY_SURFACE_LANDSCAPE_ORIENTATION_USED_DAILY.pixelName to PixelParameter.removeAtb(),

app/src/main/java/com/duckduckgo/app/pixels/AppPixelName.kt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -143,6 +143,7 @@ enum class AppPixelName(override val pixelName: String) : Pixel.PixelName {
143143
SETTINGS_APPEARANCE_IS_FULL_URL_OPTION_TOGGLED("m_appearance_settings_is_full_url_option_toggled"),
144144
APPEARANCE_SETTINGS_IS_FULL_URL_ENABLED_DAILY("m_appearance_settings_is_full_url_enabled_daily"),
145145
SETTINGS_APPEARANCE_IS_TRACKER_COUNT_IN_TAB_SWITCHER_TOGGLED("m_appearance_settings_is_tracker_count_in_tab_switcher_toggled"),
146+
SETTINGS_APPEARANCE_IS_TRACKER_COUNT_IN_ADDRESS_BAR_TOGGLED("m_appearance_settings_is_tracker_count_in_address_bar_toggled"),
146147
SETTINGS_APP_ICON_PRESSED("ms_app_icon_setting_pressed"),
147148
SETTINGS_ADDRESS_BAR_POSITION_PRESSED("ms_address_bar_position_setting_pressed"),
148149
SETTINGS_ADDRESS_BAR_POSITION_SELECTED_TOP("ms_address_bar_position_setting_selected_top"),

app/src/main/java/com/duckduckgo/app/settings/db/SettingsDataStore.kt

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,7 @@ interface SettingsDataStore {
105105
*/
106106
var urlPreferenceSetByUser: Boolean
107107
var clearDuckAiData: Boolean
108+
var showTrackersCountInAddressBar: Boolean
108109

109110
/**
110111
* Check if a value has been set to the URL display preference.
@@ -267,6 +268,10 @@ class SettingsSharedPreferences @Inject constructor(
267268
get() = preferences.getBoolean(KEY_CLEAR_DUCK_AI_DATA, false)
268269
set(enabled) = preferences.edit { putBoolean(KEY_CLEAR_DUCK_AI_DATA, enabled) }
269270

271+
override var showTrackersCountInAddressBar: Boolean
272+
get() = preferences.getBoolean(KEY_SHOW_TRACKERS_COUNT_IN_ADDRESS_BAR, true)
273+
set(enabled) = preferences.edit { putBoolean(KEY_SHOW_TRACKERS_COUNT_IN_ADDRESS_BAR, enabled) }
274+
270275
override fun hasBackgroundTimestampRecorded(): Boolean = preferences.contains(KEY_APP_BACKGROUNDED_TIMESTAMP)
271276

272277
override fun clearAppBackgroundTimestamp() = preferences.edit { remove(KEY_APP_BACKGROUNDED_TIMESTAMP) }
@@ -345,6 +350,7 @@ class SettingsSharedPreferences @Inject constructor(
345350
const val URL_PREFERENCE_MIGRATED = "URL_PREFERENCE_MIGRATED"
346351
const val URL_PREFERENCE_SET_BY_USER = "URL_PREFERENCE_SET_BY_USER"
347352
const val KEY_CLEAR_DUCK_AI_DATA = "KEY_CLEAR_DUCK_AI_DATA"
353+
const val KEY_SHOW_TRACKERS_COUNT_IN_ADDRESS_BAR = "KEY_SHOW_TRACKERS_COUNT_IN_ADDRESS_BAR"
348354
}
349355

350356
private class FireAnimationPrefsMapper {

app/src/main/res/layout/activity_appearance.xml

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -274,6 +274,20 @@
274274
app:primaryTextTruncated="false"
275275
app:showSwitch="true" />
276276

277+
<com.duckduckgo.common.ui.view.divider.HorizontalDivider
278+
android:id="@+id/trackersCountInAddressBarDivider"
279+
android:layout_width="match_parent"
280+
android:layout_height="wrap_content"
281+
android:paddingBottom="0dp" />
282+
283+
<com.duckduckgo.common.ui.view.listitem.OneLineListItem
284+
android:id="@+id/showTrackersCountInAddressBar"
285+
android:layout_width="match_parent"
286+
android:layout_height="wrap_content"
287+
app:primaryText="@string/showTrackerCountInAddressBar"
288+
app:primaryTextTruncated="false"
289+
app:showSwitch="true" />
290+
277291
<com.duckduckgo.common.ui.view.divider.HorizontalDivider
278292
android:id="@+id/trackersAnimationSettingDivider"
279293
android:layout_width="match_parent"

app/src/main/res/values/strings.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -893,6 +893,7 @@
893893

894894
<!--TabSwitcher Trackers Animation-->
895895
<string name="showTrackerCountInTabSwitcher">Show Tracker Count in Tab Switcher</string>
896+
<string name="showTrackerCountInAddressBar">Show Trackers Blocked Animation </string>
896897
<string name="tabSwitcherAnimationTileRemovalDialogTitle" instruction="A title for a dialog that shows when a user clicks a tile that shows them their current blocked tracker count">Hide tracker count?</string>
897898
<string name="tabSwitcherAnimationTileRemovalDialogBody" instruction="A message for a dialog that shows when a user clicks a tile that shows them their current blocked tracker count">You can turn this back on in Settings > Appearance.</string>
898899
<string name="tabSwitcherAnimationTileRemovalDialogPositiveButton">Hide</string>

0 commit comments

Comments
 (0)