Skip to content

Commit 5fd75af

Browse files
committed
Add attributed metrics internal dev settings
1 parent 0602cd7 commit 5fd75af

File tree

12 files changed

+482
-0
lines changed

12 files changed

+482
-0
lines changed

app/build.gradle

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -411,6 +411,7 @@ dependencies {
411411

412412
implementation project(':attributed-metrics-api')
413413
implementation project(':attributed-metrics-impl')
414+
internalImplementation project(':attributed-metrics-internal')
414415

415416
implementation project(':breakage-reporting-impl')
416417

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
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.statistics
18+
19+
import android.content.Context
20+
import android.view.View
21+
import com.duckduckgo.app.attributed.metrics.internal.ui.AttributedMetricsSettingPlugin
22+
import com.duckduckgo.di.scopes.ActivityScope
23+
import com.squareup.anvil.annotations.ContributesMultibinding
24+
import javax.inject.Inject
25+
26+
@ContributesMultibinding(ActivityScope::class)
27+
class StatisticsAttributedMetricsPlugin @Inject constructor() : AttributedMetricsSettingPlugin {
28+
29+
override fun getView(context: Context): View {
30+
return StatisticsInternalInfoView(context)
31+
}
32+
}
Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
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.statistics
18+
19+
import android.content.Context
20+
import android.util.AttributeSet
21+
import android.widget.LinearLayout
22+
import android.widget.Toast
23+
import com.duckduckgo.anvil.annotations.InjectWith
24+
import com.duckduckgo.app.browser.databinding.ViewStatisticsAttributedMetricsBinding
25+
import com.duckduckgo.app.global.install.AppInstallStore
26+
import com.duckduckgo.app.referral.AppReferrerDataStore
27+
import com.duckduckgo.app.statistics.store.StatisticsDataStore
28+
import com.duckduckgo.common.ui.viewbinding.viewBinding
29+
import com.duckduckgo.di.scopes.ViewScope
30+
import dagger.android.support.AndroidSupportInjection
31+
import java.text.SimpleDateFormat
32+
import java.util.*
33+
import javax.inject.Inject
34+
35+
@InjectWith(ViewScope::class)
36+
class StatisticsInternalInfoView @JvmOverloads constructor(
37+
context: Context,
38+
attrs: AttributeSet? = null,
39+
defStyle: Int = 0,
40+
) : LinearLayout(context, attrs, defStyle) {
41+
42+
@Inject lateinit var store: StatisticsDataStore
43+
44+
@Inject lateinit var referrerDataStore: AppReferrerDataStore
45+
46+
@Inject lateinit var appInstallStore: AppInstallStore
47+
48+
private val binding: ViewStatisticsAttributedMetricsBinding by viewBinding()
49+
50+
private val dateETFormat = SimpleDateFormat("yyyy-MM-dd", Locale.US).apply {
51+
timeZone = TimeZone.getTimeZone("US/Eastern")
52+
}
53+
override fun onAttachedToWindow() {
54+
AndroidSupportInjection.inject(this)
55+
super.onAttachedToWindow()
56+
57+
binding.searchAtb.apply {
58+
text = store.searchRetentionAtb ?: "unknown"
59+
}
60+
61+
binding.searchAtbSave.setOnClickListener {
62+
store.searchRetentionAtb?.let {
63+
store.searchRetentionAtb = binding.searchAtb.text
64+
}
65+
Toast.makeText(this.context, "Search Atb updated", Toast.LENGTH_SHORT).show()
66+
}
67+
68+
binding.originInput.apply {
69+
text = referrerDataStore.utmOriginAttributeCampaign ?: "unknown"
70+
}
71+
72+
binding.originInputSave.setOnClickListener {
73+
referrerDataStore.utmOriginAttributeCampaign = binding.originInput.text.toString()
74+
Toast.makeText(this.context, "Origin updated", Toast.LENGTH_SHORT).show()
75+
}
76+
77+
binding.installDateInput.apply {
78+
val timestamp = appInstallStore.installTimestamp
79+
text = dateETFormat.format(Date(timestamp))
80+
}
81+
82+
binding.installDateSave.setOnClickListener {
83+
try {
84+
val date = dateETFormat.parse(binding.installDateInput.text)
85+
if (date != null) {
86+
appInstallStore.installTimestamp = date.time
87+
Toast.makeText(this.context, "Install date updated", Toast.LENGTH_SHORT).show()
88+
} else {
89+
Toast.makeText(this.context, "Invalid date format. Use yyyy-MM-dd", Toast.LENGTH_SHORT).show()
90+
}
91+
} catch (e: Exception) {
92+
Toast.makeText(this.context, "Invalid date format. Use yyyy-MM-dd", Toast.LENGTH_SHORT).show()
93+
}
94+
}
95+
}
96+
}
Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
<?xml version="1.0" encoding="utf-8"?><!--
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+
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
18+
xmlns:app="http://schemas.android.com/apk/res-auto"
19+
android:layout_width="match_parent"
20+
android:layout_height="wrap_content"
21+
android:orientation="vertical"
22+
android:padding="16dp">
23+
24+
<com.duckduckgo.common.ui.view.text.DaxTextInput
25+
android:id="@+id/searchAtb"
26+
android:layout_width="match_parent"
27+
android:layout_height="wrap_content"
28+
android:layout_marginHorizontal="16dp"
29+
android:hint="Search Atb"
30+
app:endIcon="@drawable/ic_copy_24" />
31+
32+
<com.duckduckgo.common.ui.view.button.DaxButtonPrimary
33+
android:id="@+id/searchAtbSave"
34+
android:layout_width="wrap_content"
35+
android:layout_height="wrap_content"
36+
android:layout_marginHorizontal="16dp"
37+
android:layout_gravity="end"
38+
android:text="Save" />
39+
40+
<com.duckduckgo.common.ui.view.text.DaxTextInput
41+
android:id="@+id/originInput"
42+
android:layout_width="match_parent"
43+
android:layout_height="wrap_content"
44+
android:layout_marginHorizontal="16dp"
45+
android:hint="Origin"
46+
app:endIcon="@drawable/ic_copy_24" />
47+
48+
<com.duckduckgo.common.ui.view.button.DaxButtonPrimary
49+
android:id="@+id/originInputSave"
50+
android:layout_width="wrap_content"
51+
android:layout_height="wrap_content"
52+
android:layout_marginHorizontal="16dp"
53+
android:layout_gravity="end"
54+
android:text="Save" />
55+
56+
<com.duckduckgo.common.ui.view.text.DaxTextInput
57+
android:id="@+id/installDateInput"
58+
android:layout_width="match_parent"
59+
android:layout_height="wrap_content"
60+
android:layout_marginHorizontal="16dp"
61+
android:hint="Installation Date (ET time)"
62+
app:endIcon="@drawable/ic_copy_24" />
63+
64+
<com.duckduckgo.common.ui.view.button.DaxButtonPrimary
65+
android:id="@+id/installDateSave"
66+
android:layout_width="wrap_content"
67+
android:layout_height="wrap_content"
68+
android:layout_marginHorizontal="16dp"
69+
android:layout_gravity="end"
70+
android:text="Save" />
71+
</LinearLayout>
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
plugins {
2+
id 'com.android.library'
3+
id 'kotlin-android'
4+
id 'com.squareup.anvil'
5+
id 'com.google.devtools.ksp'
6+
}
7+
8+
apply from: "$rootProject.projectDir/gradle/android-library.gradle"
9+
10+
android {
11+
anvil {
12+
generateDaggerFactories = true // default is false
13+
}
14+
namespace 'com.duckduckgo.attributed.metrics.internal'
15+
testOptions {
16+
unitTests {
17+
includeAndroidResources = true
18+
}
19+
}
20+
}
21+
22+
dependencies {
23+
anvil project(':anvil-compiler')
24+
implementation project(':anvil-annotations')
25+
implementation project(':attributed-metrics-api')
26+
implementation project(':attributed-metrics-impl')
27+
implementation project(':di')
28+
implementation project(':internal-features-api')
29+
implementation project(':navigation-api')
30+
implementation project(':common-utils')
31+
implementation project(':design-system')
32+
33+
implementation AndroidX.appCompat
34+
implementation AndroidX.constraintLayout
35+
implementation Google.android.material
36+
implementation Google.dagger
37+
38+
testImplementation project(path: ':common-test')
39+
testImplementation "org.mockito.kotlin:mockito-kotlin:_"
40+
testImplementation Testing.junit4
41+
}
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<issues format="6" by="lint 8.8.2" type="baseline" client="gradle" dependencies="false" name="AGP (8.7.3)" variant="all" version="8.8.2">
3+
4+
</issues>
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
3+
4+
<application>
5+
<activity
6+
android:name="com.duckduckgo.app.attributed.metrics.internal.ui.AttributedMetricsDevSettingsActivity"
7+
android:label="Attributed Metrics Dev Settings"
8+
android:exported="false" />
9+
</application>
10+
11+
</manifest>
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
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.app.attributed.metrics.internal
18+
19+
import android.content.Context
20+
import com.duckduckgo.anvil.annotations.PriorityKey
21+
import com.duckduckgo.app.attributed.metrics.internal.ui.MainAttributedMetricsSettings
22+
import com.duckduckgo.di.scopes.AppScope
23+
import com.duckduckgo.internal.features.api.InternalFeaturePlugin
24+
import com.duckduckgo.navigation.api.GlobalActivityStarter
25+
import com.squareup.anvil.annotations.ContributesMultibinding
26+
import javax.inject.Inject
27+
28+
@ContributesMultibinding(AppScope::class)
29+
@PriorityKey(InternalFeaturePlugin.ATTRIBUTED_METRICS_SETTINGS_PRIO_KEY)
30+
class AttributedMetricsDevSettingsFeatures @Inject constructor(
31+
private val globalActivityStarter: GlobalActivityStarter,
32+
) : InternalFeaturePlugin {
33+
override fun internalFeatureTitle(): String {
34+
return "Attributed Metrics Settings"
35+
}
36+
37+
override fun internalFeatureSubtitle(): String {
38+
return "Attributed Metrics Dev Settings for internal users"
39+
}
40+
41+
override fun onInternalFeatureClicked(activityContext: Context) {
42+
globalActivityStarter.start(activityContext, MainAttributedMetricsSettings)
43+
}
44+
}

0 commit comments

Comments
 (0)