Skip to content

Commit 678c492

Browse files
LukasPaczosdaxmobilemarcosholgado
authored
Add option to clear data in Data Clearing settings (#7096)
Task/Issue URL: https://app.asana.com/1/137249556945/project/1208671518894266/task/1211878032869780?focus=true ### Description Adds a new fire button to the Data Clearing settings screen. :warning: This is ready for review but will need to wait for translations before merging. ### Steps to test this PR - [x] Go to Settings → Data Clearing. - [x] Try the new fire button. - [x] Open Duck.ai (from anywhere). - [x] Go to Settings → Data Clearing. - [x] See the option to clear Duck.ai chats and enable it. - [x] See how the copy on the fire button and confirmation button changes. ### UI changes | Before | After | | ------ | ----- | <img width="480" height="1071" alt="clear_data_and_chat_light_before" src="https://github.com/user-attachments/assets/b97652c9-c3f6-44f6-b74e-dade70cb7fb9" />|<img width="480" height="1071" alt="clear_data_and_chat_light" src="https://github.com/user-attachments/assets/4597987a-4b55-48c8-a3f5-8d33c8b06ed1" />| --------- Co-authored-by: Dax The Translator <daxmobile@duckduckgo.com> Co-authored-by: Marcos <marcosh@duckduckgo.com>
1 parent 094c5fa commit 678c492

File tree

56 files changed

+295
-154
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

56 files changed

+295
-154
lines changed

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

Lines changed: 6 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ import androidx.webkit.ServiceWorkerClientCompat
5050
import androidx.webkit.ServiceWorkerControllerCompat
5151
import androidx.webkit.WebViewFeature
5252
import com.duckduckgo.anvil.annotations.InjectWith
53+
import com.duckduckgo.app.browser.BrowserActivity.Companion.DUCK_AI_ANIM_READY_DELAY_MS
5354
import com.duckduckgo.app.browser.BrowserViewModel.Command
5455
import com.duckduckgo.app.browser.animations.slideAndFadeInFromLeft
5556
import com.duckduckgo.app.browser.animations.slideAndFadeInFromRight
@@ -73,27 +74,22 @@ import com.duckduckgo.app.downloads.DownloadsScreens.DownloadsScreenNoParams
7374
import com.duckduckgo.app.feedback.ui.common.FeedbackActivity
7475
import com.duckduckgo.app.fire.DataClearer
7576
import com.duckduckgo.app.fire.DataClearerForegroundAppRestartPixel
76-
import com.duckduckgo.app.firebutton.FireButtonStore
7777
import com.duckduckgo.app.global.ApplicationClearDataState
78-
import com.duckduckgo.app.global.events.db.UserEventsStore
7978
import com.duckduckgo.app.global.intentText
8079
import com.duckduckgo.app.global.rating.PromptCount
8180
import com.duckduckgo.app.global.sanitize
8281
import com.duckduckgo.app.global.view.ClearDataAction
83-
import com.duckduckgo.app.global.view.FireDialog
82+
import com.duckduckgo.app.global.view.FireDialogProvider
8483
import com.duckduckgo.app.global.view.renderIfChanged
8584
import com.duckduckgo.app.onboarding.ui.page.DefaultBrowserPage
86-
import com.duckduckgo.app.onboardingdesignexperiment.OnboardingDesignExperimentManager
8785
import com.duckduckgo.app.pixels.AppPixelName
8886
import com.duckduckgo.app.pixels.AppPixelName.FIRE_DIALOG_CANCEL
89-
import com.duckduckgo.app.settings.clear.OnboardingExperimentFireAnimationHelper
9087
import com.duckduckgo.app.settings.db.SettingsDataStore
9188
import com.duckduckgo.app.statistics.pixels.Pixel
9289
import com.duckduckgo.app.statistics.pixels.Pixel.PixelParameter
9390
import com.duckduckgo.app.tabs.model.TabEntity
9491
import com.duckduckgo.app.tabs.ui.DefaultSnackbar
9592
import com.duckduckgo.app.tabs.ui.TabSwitcherActivity
96-
import com.duckduckgo.appbuildconfig.api.AppBuildConfig
9793
import com.duckduckgo.autofill.api.emailprotection.EmailProtectionLinkVerifier
9894
import com.duckduckgo.browser.api.ui.BrowserScreens.BookmarksScreenNoParams
9995
import com.duckduckgo.browser.api.ui.BrowserScreens.SettingsScreenNoParams
@@ -158,9 +154,6 @@ open class BrowserActivity : DuckDuckGoActivity() {
158154
@Inject
159155
lateinit var dataClearerForegroundAppRestartPixel: DataClearerForegroundAppRestartPixel
160156

161-
@Inject
162-
lateinit var userEventsStore: UserEventsStore
163-
164157
@Inject
165158
lateinit var serviceWorkerClientCompat: ServiceWorkerClientCompat
166159

@@ -176,15 +169,9 @@ open class BrowserActivity : DuckDuckGoActivity() {
176169

177170
@Inject lateinit var dispatcherProvider: DispatcherProvider
178171

179-
@Inject
180-
lateinit var fireButtonStore: FireButtonStore
181-
182172
@Inject
183173
lateinit var externalIntentProcessingState: ExternalIntentProcessingState
184174

185-
@Inject
186-
lateinit var appBuildConfig: AppBuildConfig
187-
188175
@Inject
189176
lateinit var swipingTabsFeature: SwipingTabsFeatureProvider
190177

@@ -200,18 +187,15 @@ open class BrowserActivity : DuckDuckGoActivity() {
200187
@Inject
201188
lateinit var syncUrlIdentifier: SyncUrlIdentifier
202189

203-
@Inject
204-
lateinit var onboardingDesignExperimentManager: OnboardingDesignExperimentManager
205-
206-
@Inject
207-
lateinit var onboardingExperimentFireAnimationHelper: OnboardingExperimentFireAnimationHelper
208-
209190
@Inject
210191
lateinit var omnibarEntryConverter: OmnibarEntryConverter
211192

212193
@Inject
213194
lateinit var newAddressBarOptionManager: NewAddressBarOptionManager
214195

196+
@Inject
197+
lateinit var fireDialogProvider: FireDialogProvider
198+
215199
private val lastActiveTabs = TabList()
216200

217201
private var duckAiFragment: DuckChatWebViewFragment? = null
@@ -804,20 +788,7 @@ open class BrowserActivity : DuckDuckGoActivity() {
804788
val params = mapOf(PixelParameter.FROM_FOCUSED_NTP to launchedFromFocusedNtp.toString())
805789
pixel.fire(AppPixelName.FORGET_ALL_PRESSED_BROWSING, params)
806790

807-
val dialog =
808-
FireDialog(
809-
context = this,
810-
clearPersonalDataAction = clearPersonalDataAction,
811-
pixel = pixel,
812-
settingsDataStore = settingsDataStore,
813-
userEventsStore = userEventsStore,
814-
appCoroutineScope = appCoroutineScope,
815-
dispatcherProvider = dispatcherProvider,
816-
fireButtonStore = fireButtonStore,
817-
appBuildConfig = appBuildConfig,
818-
onboardingDesignExperimentManager = onboardingDesignExperimentManager,
819-
onboardingExperimentFireAnimationHelper = onboardingExperimentFireAnimationHelper,
820-
)
791+
val dialog = fireDialogProvider.createFireDialog(context = this)
821792
dialog.setOnShowListener { currentTab?.onFireDialogVisibilityChanged(isVisible = true) }
822793
dialog.setOnCancelListener {
823794
pixel.fire(FIRE_DIALOG_CANCEL)

app/src/main/java/com/duckduckgo/app/firebutton/FireButtonActivity.kt

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ import com.duckduckgo.app.browser.databinding.ActivityDataClearingBinding
3232
import com.duckduckgo.app.fire.fireproofwebsite.ui.FireproofWebsitesActivity
3333
import com.duckduckgo.app.firebutton.FireButtonViewModel.AutomaticallyClearData
3434
import com.duckduckgo.app.firebutton.FireButtonViewModel.Command
35+
import com.duckduckgo.app.global.view.FireDialogProvider
3536
import com.duckduckgo.app.pixels.AppPixelName
3637
import com.duckduckgo.app.settings.FireAnimationActivity
3738
import com.duckduckgo.app.settings.clear.ClearWhatOption
@@ -61,6 +62,9 @@ class FireButtonActivity : DuckDuckGoActivity() {
6162
@Inject
6263
lateinit var appBuildConfig: AppBuildConfig
6364

65+
@Inject
66+
lateinit var fireDialogProvider: FireDialogProvider
67+
6468
private val viewModel: FireButtonViewModel by bindViewModel()
6569
private val binding: ActivityDataClearingBinding by viewBinding()
6670

@@ -86,6 +90,7 @@ class FireButtonActivity : DuckDuckGoActivity() {
8690
automaticallyClearWhenSetting.setClickListener { viewModel.onAutomaticallyClearWhenClicked() }
8791
selectedFireAnimationSetting.setClickListener { viewModel.userRequestedToChangeFireAnimation() }
8892
clearDuckAiDataSetting.setOnCheckedChangeListener { _, isChecked -> viewModel.onClearDuckAiDataToggled(isChecked) }
93+
clearDataAction.setClickListener { viewModel.onClearDataActionClicked() }
8994
}
9095
}
9196

@@ -97,6 +102,7 @@ class FireButtonActivity : DuckDuckGoActivity() {
97102
updateAutomaticClearDataOptions(it.automaticallyClearData, it.clearDuckAiData)
98103
updateSelectedFireAnimation(it.selectedFireAnimation)
99104
updateClearDuckAiDataSetting(it.clearDuckAiData, it.showClearDuckAiDataSetting)
105+
updateClearDataAction(it.clearDuckAiData)
100106
}
101107
}.launchIn(lifecycleScope)
102108

@@ -133,12 +139,23 @@ class FireButtonActivity : DuckDuckGoActivity() {
133139
binding.clearDuckAiDataSetting.visibility = if (isVisible) View.VISIBLE else View.GONE
134140
}
135141

142+
private fun updateClearDataAction(clearDuckAiData: Boolean) {
143+
if (clearDuckAiData) {
144+
binding.clearDataAction.setPrimaryText(resources.getString(R.string.fireClearAllPlusDuckChats))
145+
binding.clearDataAction.setSecondaryText(resources.getString(R.string.settingsClearDataActionPlusDuckChatsSecondaryText))
146+
} else {
147+
binding.clearDataAction.setPrimaryText(resources.getString(R.string.fireClearAll))
148+
binding.clearDataAction.setSecondaryText(resources.getString(R.string.settingsClearDataActionSecondaryText))
149+
}
150+
}
151+
136152
private fun processCommand(it: Command) {
137153
when (it) {
138154
is Command.LaunchFireproofWebsites -> launchFireproofWebsites()
139155
is Command.ShowClearWhatDialog -> launchAutomaticallyClearWhatDialog(it.option, it.clearDuckAi)
140156
is Command.ShowClearWhenDialog -> launchAutomaticallyClearWhenDialog(it.option)
141157
is Command.LaunchFireAnimationSettings -> launchFireAnimationSelector(it.animation)
158+
is Command.LaunchFireDialog -> launchFireDialog()
142159
}
143160
}
144161

@@ -270,6 +287,11 @@ class FireButtonActivity : DuckDuckGoActivity() {
270287
.show()
271288
}
272289

290+
private fun launchFireDialog() {
291+
val dialog = fireDialogProvider.createFireDialog(context = this)
292+
dialog.show()
293+
}
294+
273295
companion object {
274296
const val LAUNCH_FROM_NOTIFICATION_PIXEL_NAME = "LAUNCH_FROM_NOTIFICATION_PIXEL_NAME"
275297

app/src/main/java/com/duckduckgo/app/firebutton/FireButtonViewModel.kt

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@ class FireButtonViewModel @Inject constructor(
5858
val selectedFireAnimation: FireAnimation = FireAnimation.HeroFire,
5959
val clearDuckAiData: Boolean = false,
6060
val showClearDuckAiDataSetting: Boolean = false,
61+
val clerDataWithDuckAiChats: Boolean = false,
6162
)
6263

6364
data class AutomaticallyClearData(
@@ -75,6 +76,7 @@ class FireButtonViewModel @Inject constructor(
7576

7677
data class ShowClearWhenDialog(val option: ClearWhenOption) : Command()
7778
data class LaunchFireAnimationSettings(val animation: FireAnimation) : Command()
79+
data object LaunchFireDialog : Command()
7880
}
7981

8082
private val viewState = MutableStateFlow(ViewState())
@@ -213,6 +215,10 @@ class FireButtonViewModel @Inject constructor(
213215
}
214216
}
215217

218+
fun onClearDataActionClicked() {
219+
viewModelScope.launch { command.send(Command.LaunchFireDialog) }
220+
}
221+
216222
private fun ClearWhatOption.pixelEvent(): Pixel.PixelName {
217223
return when (this) {
218224
ClearWhatOption.CLEAR_NONE -> AppPixelName.AUTOMATIC_CLEAR_DATA_WHAT_OPTION_NONE
Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
/*
2+
* Copyright (c) 2025 DuckDuckGo
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package com.duckduckgo.app.global.view
18+
19+
import android.content.Context
20+
import com.duckduckgo.app.di.AppCoroutineScope
21+
import com.duckduckgo.app.firebutton.FireButtonStore
22+
import com.duckduckgo.app.global.events.db.UserEventsStore
23+
import com.duckduckgo.app.onboardingdesignexperiment.OnboardingDesignExperimentManager
24+
import com.duckduckgo.app.settings.clear.OnboardingExperimentFireAnimationHelper
25+
import com.duckduckgo.app.settings.db.SettingsDataStore
26+
import com.duckduckgo.app.statistics.pixels.Pixel
27+
import com.duckduckgo.appbuildconfig.api.AppBuildConfig
28+
import com.duckduckgo.common.utils.DispatcherProvider
29+
import com.duckduckgo.di.scopes.AppScope
30+
import com.squareup.anvil.annotations.ContributesBinding
31+
import dagger.SingleInstanceIn
32+
import kotlinx.coroutines.CoroutineScope
33+
import javax.inject.Inject
34+
35+
interface FireDialogProvider {
36+
fun createFireDialog(context: Context): FireDialog
37+
}
38+
39+
@ContributesBinding(scope = AppScope::class)
40+
@SingleInstanceIn(scope = AppScope::class)
41+
class FireDialogLauncherImpl @Inject constructor() : FireDialogProvider {
42+
43+
@Inject
44+
lateinit var clearPersonalDataAction: ClearDataAction
45+
46+
@Inject
47+
lateinit var pixel: Pixel
48+
49+
@Inject
50+
lateinit var settingsDataStore: SettingsDataStore
51+
52+
@Inject
53+
lateinit var userEventsStore: UserEventsStore
54+
55+
@AppCoroutineScope
56+
@Inject
57+
lateinit var appCoroutineScope: CoroutineScope
58+
59+
@Inject
60+
lateinit var dispatcherProvider: DispatcherProvider
61+
62+
@Inject
63+
lateinit var fireButtonStore: FireButtonStore
64+
65+
@Inject
66+
lateinit var appBuildConfig: AppBuildConfig
67+
68+
@Inject
69+
lateinit var onboardingDesignExperimentManager: OnboardingDesignExperimentManager
70+
71+
@Inject
72+
lateinit var onboardingExperimentFireAnimationHelper: OnboardingExperimentFireAnimationHelper
73+
74+
override fun createFireDialog(context: Context): FireDialog = FireDialog(
75+
context = context,
76+
clearPersonalDataAction = clearPersonalDataAction,
77+
pixel = pixel,
78+
settingsDataStore = settingsDataStore,
79+
userEventsStore = userEventsStore,
80+
appCoroutineScope = appCoroutineScope,
81+
dispatcherProvider = dispatcherProvider,
82+
fireButtonStore = fireButtonStore,
83+
appBuildConfig = appBuildConfig,
84+
onboardingDesignExperimentManager = onboardingDesignExperimentManager,
85+
onboardingExperimentFireAnimationHelper = onboardingExperimentFireAnimationHelper,
86+
)
87+
}

app/src/main/java/com/duckduckgo/app/tabs/ui/TabSwitcherActivity.kt

Lines changed: 3 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -47,15 +47,9 @@ import com.duckduckgo.app.browser.navigation.bar.view.BrowserNavigationBarObserv
4747
import com.duckduckgo.app.browser.navigation.bar.view.BrowserNavigationBarView
4848
import com.duckduckgo.app.browser.omnibar.OmnibarType
4949
import com.duckduckgo.app.browser.tabpreview.WebViewPreviewPersister
50-
import com.duckduckgo.app.di.AppCoroutineScope
5150
import com.duckduckgo.app.downloads.DownloadsActivity
52-
import com.duckduckgo.app.firebutton.FireButtonStore
53-
import com.duckduckgo.app.global.events.db.UserEventsStore
54-
import com.duckduckgo.app.global.view.ClearDataAction
55-
import com.duckduckgo.app.global.view.FireDialog
56-
import com.duckduckgo.app.onboardingdesignexperiment.OnboardingDesignExperimentManager
51+
import com.duckduckgo.app.global.view.FireDialogProvider
5752
import com.duckduckgo.app.settings.SettingsActivity
58-
import com.duckduckgo.app.settings.clear.OnboardingExperimentFireAnimationHelper
5953
import com.duckduckgo.app.settings.db.SettingsDataStore
6054
import com.duckduckgo.app.statistics.pixels.Pixel
6155
import com.duckduckgo.app.tabs.TabManagerFeatureFlags
@@ -77,7 +71,6 @@ import com.duckduckgo.app.tabs.ui.TabSwitcherViewModel.Command.ShowUndoBookmarkM
7771
import com.duckduckgo.app.tabs.ui.TabSwitcherViewModel.Command.ShowUndoDeleteTabsMessage
7872
import com.duckduckgo.app.tabs.ui.TabSwitcherViewModel.ViewState.Mode
7973
import com.duckduckgo.app.tabs.ui.TabSwitcherViewModel.ViewState.Mode.Selection
80-
import com.duckduckgo.appbuildconfig.api.AppBuildConfig
8174
import com.duckduckgo.common.ui.DuckDuckGoActivity
8275
import com.duckduckgo.common.ui.menu.PopupMenu
8376
import com.duckduckgo.common.ui.view.button.ButtonType
@@ -101,7 +94,6 @@ import kotlinx.coroutines.launch
10194
import logcat.LogPriority.WARN
10295
import logcat.asLog
10396
import logcat.logcat
104-
import java.util.ArrayList
10597
import javax.inject.Inject
10698
import kotlin.coroutines.CoroutineContext
10799
import kotlin.math.max
@@ -120,9 +112,6 @@ class TabSwitcherActivity :
120112
@Inject
121113
lateinit var settingsDataStore: SettingsDataStore
122114

123-
@Inject
124-
lateinit var clearPersonalDataAction: ClearDataAction
125-
126115
@Inject
127116
lateinit var gridViewColumnCalculator: GridViewColumnCalculator
128117

@@ -135,22 +124,6 @@ class TabSwitcherActivity :
135124
@Inject
136125
lateinit var faviconManager: FaviconManager
137126

138-
@Inject
139-
lateinit var userEventsStore: UserEventsStore
140-
141-
@Inject
142-
@AppCoroutineScope
143-
lateinit var appCoroutineScope: CoroutineScope
144-
145-
@Inject
146-
lateinit var dispatcherProvider: DispatcherProvider
147-
148-
@Inject
149-
lateinit var fireButtonStore: FireButtonStore
150-
151-
@Inject
152-
lateinit var appBuildConfig: AppBuildConfig
153-
154127
@Inject
155128
lateinit var duckChat: DuckChat
156129

@@ -161,10 +134,7 @@ class TabSwitcherActivity :
161134
lateinit var tabManagerFeatureFlags: TabManagerFeatureFlags
162135

163136
@Inject
164-
lateinit var onboardingDesignExperimentManager: OnboardingDesignExperimentManager
165-
166-
@Inject
167-
lateinit var onboardingExperimentFireAnimationHelper: OnboardingExperimentFireAnimationHelper
137+
lateinit var fireDialogProvider: FireDialogProvider
168138

169139
@Inject
170140
lateinit var omnibarRepository: OmnibarRepository
@@ -655,20 +625,7 @@ class TabSwitcherActivity :
655625
}
656626

657627
private fun onFireButtonClicked() {
658-
val dialog =
659-
FireDialog(
660-
context = this,
661-
clearPersonalDataAction = clearPersonalDataAction,
662-
pixel = pixel,
663-
settingsDataStore = settingsDataStore,
664-
userEventsStore = userEventsStore,
665-
appCoroutineScope = appCoroutineScope,
666-
dispatcherProvider = dispatcherProvider,
667-
fireButtonStore = fireButtonStore,
668-
appBuildConfig = appBuildConfig,
669-
onboardingDesignExperimentManager = onboardingDesignExperimentManager,
670-
onboardingExperimentFireAnimationHelper = onboardingExperimentFireAnimationHelper,
671-
)
628+
val dialog = fireDialogProvider.createFireDialog(context = this)
672629
dialog.show()
673630
}
674631

0 commit comments

Comments
 (0)