Skip to content

Commit 2ddac13

Browse files
committed
Merge branch 'release/5.209.0' into main
2 parents 7bb62c4 + 0c3b5c3 commit 2ddac13

File tree

208 files changed

+7889
-722
lines changed

Some content is hidden

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

208 files changed

+7889
-722
lines changed

app-tracking-protection/vpn-impl/src/main/java/com/duckduckgo/mobile/android/vpn/apps/ui/ManageRecentAppsProtectionActivity.kt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -243,6 +243,7 @@ class ManageRecentAppsProtectionActivity :
243243
}
244244

245245
override fun onBackPressed() {
246+
super.onBackPressed()
246247
onSupportNavigateUp()
247248
}
248249

app-tracking-protection/vpn-impl/src/main/java/com/duckduckgo/mobile/android/vpn/apps/ui/TrackingProtectionExclusionListActivity.kt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -274,6 +274,7 @@ class TrackingProtectionExclusionListActivity :
274274
}
275275

276276
override fun onBackPressed() {
277+
super.onBackPressed()
277278
onSupportNavigateUp()
278279
}
279280

app-tracking-protection/vpn-impl/src/main/java/com/duckduckgo/mobile/android/vpn/breakage/ReportBreakageAppListActivity.kt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,7 @@ class ReportBreakageAppListActivity : DuckDuckGoActivity(), ReportBreakageAppLis
117117
}
118118

119119
override fun onBackPressed() {
120+
super.onBackPressed()
120121
onSupportNavigateUp()
121122
}
122123

app-tracking-protection/vpn-impl/src/main/java/com/duckduckgo/mobile/android/vpn/bugreport/DeviceInfoCollector.kt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ class DeviceInfoCollector @Inject constructor(
4444
put("buildFlavor", appBuildConfig.flavor.toString())
4545
put("os", appBuildConfig.sdkInt)
4646
put("batteryOptimizations", (!isIgnoringBatteryOptimizations.get()).toString())
47+
put("man", appBuildConfig.manufacturer)
4748
}
4849
}
4950
}

app-tracking-protection/vpn-impl/src/main/java/com/duckduckgo/mobile/android/vpn/pixels/DeviceShieldPixelNames.kt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -226,5 +226,8 @@ enum class DeviceShieldPixelNames(override val pixelName: String, val enqueue: B
226226
VPN_START_ATTEMPT("m_vpn_ev_start_attempt_c", enqueue = true),
227227
VPN_START_ATTEMPT_SUCCESS("m_vpn_ev_start_attempt_success_c", enqueue = true),
228228
VPN_START_ATTEMPT_FAILURE("m_vpn_ev_start_attempt_failure_c", enqueue = true),
229+
230+
NEW_TAB_SECTION_TOGGLED_OFF("m_new_tab_page_customize_section_off_appTP"),
231+
NEW_TAB_SECTION_TOGGLED_ON("m_new_tab_page_customize_section_on_appTP"),
229232
;
230233
}

app-tracking-protection/vpn-impl/src/main/java/com/duckduckgo/mobile/android/vpn/pixels/DeviceShieldPixels.kt

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -363,6 +363,9 @@ interface DeviceShieldPixels {
363363
fun reportVpnStartAttempt()
364364

365365
fun reportVpnStartAttemptSuccess()
366+
367+
// New Tab Engagement pixels https://app.asana.com/0/72649045549333/1207667088727866/f
368+
fun reportNewTabSectionToggled(enabled: Boolean)
366369
}
367370

368371
@ContributesBinding(AppScope::class)
@@ -827,6 +830,14 @@ class RealDeviceShieldPixels @Inject constructor(
827830
tryToFireDailyPixel(String.format(Locale.US, DeviceShieldPixelNames.REPORT_TLS_PARSING_ERROR_CODE_DAILY.pixelName, errorCode))
828831
}
829832

833+
override fun reportNewTabSectionToggled(enabled: Boolean) {
834+
if (enabled) {
835+
firePixel(DeviceShieldPixelNames.NEW_TAB_SECTION_TOGGLED_ON)
836+
} else {
837+
firePixel(DeviceShieldPixelNames.NEW_TAB_SECTION_TOGGLED_OFF)
838+
}
839+
}
840+
830841
private fun firePixel(
831842
p: DeviceShieldPixelNames,
832843
payload: Map<String, String> = emptyMap(),
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,119 @@
1+
/*
2+
* Copyright (c) 2024 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.mobile.android.vpn.ui.newtab
18+
19+
import android.annotation.SuppressLint
20+
import android.content.Context
21+
import android.util.AttributeSet
22+
import android.view.View
23+
import android.widget.LinearLayout
24+
import androidx.lifecycle.ViewModelProvider
25+
import androidx.lifecycle.findViewTreeLifecycleOwner
26+
import androidx.lifecycle.findViewTreeViewModelStoreOwner
27+
import com.duckduckgo.anvil.annotations.ContributesRemoteFeature
28+
import com.duckduckgo.anvil.annotations.InjectWith
29+
import com.duckduckgo.anvil.annotations.PriorityKey
30+
import com.duckduckgo.common.ui.viewbinding.viewBinding
31+
import com.duckduckgo.common.utils.ViewViewModelFactory
32+
import com.duckduckgo.di.scopes.ActivityScope
33+
import com.duckduckgo.di.scopes.AppScope
34+
import com.duckduckgo.di.scopes.ViewScope
35+
import com.duckduckgo.feature.toggles.api.Toggle
36+
import com.duckduckgo.mobile.android.vpn.databinding.ViewApptpSettingsItemBinding
37+
import com.duckduckgo.mobile.android.vpn.feature.removal.VpnFeatureRemover
38+
import com.duckduckgo.mobile.android.vpn.ui.newtab.AppTrackingProtectionNewTabSettingsViewModel.ViewState
39+
import com.duckduckgo.mobile.android.vpn.ui.onboarding.VpnStore
40+
import com.duckduckgo.newtabpage.api.NewTabPageSection
41+
import com.duckduckgo.newtabpage.api.NewTabPageSectionSettingsPlugin
42+
import com.squareup.anvil.annotations.ContributesMultibinding
43+
import dagger.android.support.AndroidSupportInjection
44+
import javax.inject.Inject
45+
import kotlinx.coroutines.CoroutineScope
46+
import kotlinx.coroutines.Dispatchers
47+
import kotlinx.coroutines.SupervisorJob
48+
import kotlinx.coroutines.flow.launchIn
49+
import kotlinx.coroutines.flow.onEach
50+
51+
@InjectWith(ViewScope::class)
52+
class AppTrackingProtectionNewTabSettingView @JvmOverloads constructor(
53+
context: Context,
54+
attrs: AttributeSet? = null,
55+
defStyle: Int = 0,
56+
) : LinearLayout(context, attrs, defStyle) {
57+
58+
@Inject
59+
lateinit var viewModelFactory: ViewViewModelFactory
60+
61+
private val binding: ViewApptpSettingsItemBinding by viewBinding()
62+
63+
private var coroutineScope: CoroutineScope? = null
64+
65+
private val viewModel: AppTrackingProtectionNewTabSettingsViewModel by lazy {
66+
ViewModelProvider(findViewTreeViewModelStoreOwner()!!, viewModelFactory)[AppTrackingProtectionNewTabSettingsViewModel::class.java]
67+
}
68+
69+
override fun onAttachedToWindow() {
70+
AndroidSupportInjection.inject(this)
71+
super.onAttachedToWindow()
72+
findViewTreeLifecycleOwner()?.lifecycle?.addObserver(viewModel)
73+
74+
@SuppressLint("NoHardcodedCoroutineDispatcher")
75+
coroutineScope = CoroutineScope(SupervisorJob() + Dispatchers.Main)
76+
77+
viewModel.viewState
78+
.onEach { render(it) }
79+
.launchIn(coroutineScope!!)
80+
}
81+
82+
private fun render(viewState: ViewState) {
83+
binding.root.quietlySetIsChecked(viewState.enabled) { _, enabled ->
84+
viewModel.onSettingEnabled(enabled)
85+
}
86+
}
87+
}
88+
89+
@ContributesMultibinding(scope = ActivityScope::class)
90+
@PriorityKey(NewTabPageSectionSettingsPlugin.APP_TRACKING_PROTECTION)
91+
class AppTrackingProtectionNewTabSettingViewPlugin @Inject constructor(
92+
private val vpnStore: VpnStore,
93+
private val vpnFeatureRemover: VpnFeatureRemover,
94+
) : NewTabPageSectionSettingsPlugin {
95+
override val name = NewTabPageSection.APP_TRACKING_PROTECTION.name
96+
97+
override fun getView(context: Context): View {
98+
return AppTrackingProtectionNewTabSettingView(context)
99+
}
100+
101+
override suspend fun isActive(): Boolean {
102+
if (vpnFeatureRemover.isFeatureRemoved()) {
103+
return false
104+
}
105+
return vpnStore.didShowOnboarding()
106+
}
107+
}
108+
109+
/**
110+
* Local feature/settings - they will never be in remote config
111+
*/
112+
@ContributesRemoteFeature(
113+
scope = AppScope::class,
114+
featureName = "newTabAppTPSectionSetting",
115+
)
116+
interface NewTabAppTrackingProtectionSectionSetting {
117+
@Toggle.DefaultValue(true)
118+
fun self(): Toggle
119+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
/*
2+
* Copyright (c) 2024 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.mobile.android.vpn.ui.newtab
18+
19+
import android.annotation.SuppressLint
20+
import androidx.lifecycle.DefaultLifecycleObserver
21+
import androidx.lifecycle.LifecycleOwner
22+
import androidx.lifecycle.ViewModel
23+
import androidx.lifecycle.viewModelScope
24+
import com.duckduckgo.anvil.annotations.ContributesViewModel
25+
import com.duckduckgo.common.utils.DispatcherProvider
26+
import com.duckduckgo.di.scopes.ViewScope
27+
import com.duckduckgo.feature.toggles.api.Toggle.State
28+
import com.duckduckgo.mobile.android.vpn.pixels.DeviceShieldPixels
29+
import javax.inject.Inject
30+
import kotlinx.coroutines.flow.MutableStateFlow
31+
import kotlinx.coroutines.flow.asStateFlow
32+
import kotlinx.coroutines.flow.update
33+
import kotlinx.coroutines.launch
34+
import kotlinx.coroutines.withContext
35+
36+
@SuppressLint("NoLifecycleObserver") // we don't observe app lifecycle
37+
@ContributesViewModel(ViewScope::class)
38+
class AppTrackingProtectionNewTabSettingsViewModel @Inject constructor(
39+
private val dispatchers: DispatcherProvider,
40+
private val setting: NewTabAppTrackingProtectionSectionSetting,
41+
private val pixel: DeviceShieldPixels,
42+
) : ViewModel(), DefaultLifecycleObserver {
43+
44+
private val _viewState = MutableStateFlow(ViewState(true))
45+
val viewState = _viewState.asStateFlow()
46+
47+
data class ViewState(val enabled: Boolean)
48+
49+
override fun onCreate(owner: LifecycleOwner) {
50+
super.onCreate(owner)
51+
52+
viewModelScope.launch(dispatchers.io()) {
53+
val isEnabled = setting.self().isEnabled()
54+
withContext(dispatchers.main()) {
55+
_viewState.update { ViewState(isEnabled) }
56+
}
57+
}
58+
}
59+
60+
fun onSettingEnabled(enabled: Boolean) {
61+
setting.self().setEnabled(State(enabled))
62+
pixel.reportNewTabSectionToggled(enabled)
63+
}
64+
}
Lines changed: 25 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2021 DuckDuckGo
2+
* Copyright (c) 2024 DuckDuckGo
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -14,7 +14,7 @@
1414
* limitations under the License.
1515
*/
1616

17-
package com.duckduckgo.mobile.android.vpn.ui.report
17+
package com.duckduckgo.mobile.android.vpn.ui.newtab
1818

1919
import android.annotation.SuppressLint
2020
import android.content.Context
@@ -33,9 +33,13 @@ import com.duckduckgo.di.scopes.AppScope
3333
import com.duckduckgo.di.scopes.ViewScope
3434
import com.duckduckgo.mobile.android.vpn.R
3535
import com.duckduckgo.mobile.android.vpn.databinding.FragmentDeviceShieldCtaBinding
36+
import com.duckduckgo.mobile.android.vpn.feature.removal.VpnFeatureRemover
3637
import com.duckduckgo.mobile.android.vpn.pixels.DeviceShieldPixels
3738
import com.duckduckgo.mobile.android.vpn.state.VpnStateMonitor.VpnRunningState.ENABLED
3839
import com.duckduckgo.mobile.android.vpn.state.VpnStateMonitor.VpnStopReason.REVOKED
40+
import com.duckduckgo.mobile.android.vpn.ui.onboarding.VpnStore
41+
import com.duckduckgo.mobile.android.vpn.ui.report.PrivacyReportViewModel
42+
import com.duckduckgo.mobile.android.vpn.ui.report.PrivacyReportViewModel.PrivacyReportView.TrackersBlocked
3943
import com.duckduckgo.mobile.android.vpn.ui.report.PrivacyReportViewModel.PrivacyReportView.ViewState
4044
import com.duckduckgo.mobile.android.vpn.ui.tracker_activity.DeviceShieldTrackerActivity
4145
import com.duckduckgo.newtabpage.api.NewTabPageSection
@@ -128,7 +132,7 @@ class AppTrackingProtectionStateView @JvmOverloads constructor(
128132
binding.deviceShieldCtaImage.setImageResource(R.drawable.ic_apptp_warning)
129133
}
130134

131-
private fun renderTrackersBlockedWhenEnabled(trackerBlocked: PrivacyReportViewModel.PrivacyReportView.TrackersBlocked) {
135+
private fun renderTrackersBlockedWhenEnabled(trackerBlocked: TrackersBlocked) {
132136
val trackersBlocked = trackerBlocked.trackers
133137
val lastTrackingApp = trackerBlocked.latestApp
134138
val otherApps = trackerBlocked.otherAppsSize
@@ -185,11 +189,28 @@ class AppTrackingProtectionStateView @JvmOverloads constructor(
185189
@ContributesActivePlugin(
186190
AppScope::class,
187191
boundType = NewTabPageSectionPlugin::class,
192+
priority = 2,
188193
)
189-
class AppTrackingProtectionNewTabPageSectionPlugin @Inject constructor() : NewTabPageSectionPlugin {
194+
class AppTrackingProtectionNewTabPageSectionPlugin @Inject constructor(
195+
private val vpnStore: VpnStore,
196+
private val vpnFeatureRemover: VpnFeatureRemover,
197+
private val setting: NewTabAppTrackingProtectionSectionSetting,
198+
) : NewTabPageSectionPlugin {
190199
override val name = NewTabPageSection.APP_TRACKING_PROTECTION.name
191200

192201
override fun getView(context: Context): View {
193202
return AppTrackingProtectionStateView(context)
194203
}
204+
205+
override suspend fun isUserEnabled(): Boolean {
206+
if (vpnFeatureRemover.isFeatureRemoved()) {
207+
return false
208+
}
209+
210+
return if (vpnStore.didShowOnboarding()) {
211+
setting.self().isEnabled()
212+
} else {
213+
false
214+
}
215+
}
195216
}

app-tracking-protection/vpn-impl/src/main/java/com/duckduckgo/mobile/android/vpn/ui/onboarding/VpnOnboardingActivity.kt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -170,6 +170,7 @@ class VpnOnboardingActivity : DuckDuckGoActivity() {
170170
}
171171

172172
override fun onBackPressed() {
173+
super.onBackPressed()
173174
// go back to previous screen or get out if first page
174175
onSupportNavigateUp()
175176
}

0 commit comments

Comments
 (0)