From 869b5ad55b5a950034715fbe485209d38cfc11ff Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Wed, 24 Nov 2021 12:08:07 +0100 Subject: [PATCH] Analytics: add setting section --- .../analytics/impl/DefaultVectorAnalytics.kt | 3 ++ .../features/settings/VectorPreferences.kt | 23 -------- .../settings/VectorSettingsBaseFragment.kt | 7 ++- .../VectorSettingsSecurityPrivacyFragment.kt | 52 ++++++++++++++----- .../xml/vector_settings_security_privacy.xml | 5 +- 5 files changed, 51 insertions(+), 39 deletions(-) diff --git a/vector/src/main/java/im/vector/app/features/analytics/impl/DefaultVectorAnalytics.kt b/vector/src/main/java/im/vector/app/features/analytics/impl/DefaultVectorAnalytics.kt index 6164e2ded4..541c040ed0 100644 --- a/vector/src/main/java/im/vector/app/features/analytics/impl/DefaultVectorAnalytics.kt +++ b/vector/src/main/java/im/vector/app/features/analytics/impl/DefaultVectorAnalytics.kt @@ -24,6 +24,7 @@ import im.vector.app.features.analytics.VectorAnalytics import im.vector.app.features.analytics.store.AnalyticsStore import kotlinx.coroutines.GlobalScope import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.onEach import kotlinx.coroutines.launch import timber.log.Timber @@ -106,6 +107,7 @@ class DefaultVectorAnalytics @Inject constructor( posthog?.identify(it) } } + .launchIn(GlobalScope) } } @@ -115,6 +117,7 @@ class DefaultVectorAnalytics @Inject constructor( getUserConsent().onEach { userConsent = it } + .launchIn(GlobalScope) } } diff --git a/vector/src/main/java/im/vector/app/features/settings/VectorPreferences.kt b/vector/src/main/java/im/vector/app/features/settings/VectorPreferences.kt index 07cd9d6dac..6887a4f623 100755 --- a/vector/src/main/java/im/vector/app/features/settings/VectorPreferences.kt +++ b/vector/src/main/java/im/vector/app/features/settings/VectorPreferences.kt @@ -167,9 +167,6 @@ class VectorPreferences @Inject constructor(private val context: Context) { private const val SETTINGS_LABS_SHOW_COMPLETE_HISTORY_IN_ENCRYPTED_ROOM = "SETTINGS_LABS_SHOW_COMPLETE_HISTORY_IN_ENCRYPTED_ROOM" const val SETTINGS_LABS_UNREAD_NOTIFICATIONS_AS_TAB = "SETTINGS_LABS_UNREAD_NOTIFICATIONS_AS_TAB" - // analytics - const val SETTINGS_USE_ANALYTICS_KEY = "SETTINGS_USE_ANALYTICS_KEY" - // Rageshake const val SETTINGS_USE_RAGE_SHAKE_KEY = "SETTINGS_USE_RAGE_SHAKE_KEY" const val SETTINGS_RAGE_SHAKE_DETECTION_THRESHOLD_KEY = "SETTINGS_RAGE_SHAKE_DETECTION_THRESHOLD_KEY" @@ -821,15 +818,6 @@ class VectorPreferences @Inject constructor(private val context: Context) { } } - /** - * Tells if the analytics tracking is authorized (piwik, matomo, etc.). - * - * @return true if the analytics tracking is authorized - */ - fun useAnalytics(): Boolean { - return defaultPrefs.getBoolean(SETTINGS_USE_ANALYTICS_KEY, false) - } - /** * Tells if the user wants to see URL previews in the timeline * @@ -839,17 +827,6 @@ class VectorPreferences @Inject constructor(private val context: Context) { return defaultPrefs.getBoolean(SETTINGS_SHOW_URL_PREVIEW_KEY, true) } - /** - * Enable or disable the analytics tracking. - * - * @param useAnalytics true to enable the analytics tracking - */ - fun setUseAnalytics(useAnalytics: Boolean) { - defaultPrefs.edit { - putBoolean(SETTINGS_USE_ANALYTICS_KEY, useAnalytics) - } - } - /** * Tells if media should be previewed before sending * diff --git a/vector/src/main/java/im/vector/app/features/settings/VectorSettingsBaseFragment.kt b/vector/src/main/java/im/vector/app/features/settings/VectorSettingsBaseFragment.kt index 0a12a86ff0..c5786b44b0 100644 --- a/vector/src/main/java/im/vector/app/features/settings/VectorSettingsBaseFragment.kt +++ b/vector/src/main/java/im/vector/app/features/settings/VectorSettingsBaseFragment.kt @@ -21,6 +21,7 @@ import android.os.Bundle import android.view.View import androidx.annotation.CallSuper import androidx.preference.PreferenceFragmentCompat +import com.airbnb.mvrx.MavericksView import com.google.android.material.dialog.MaterialAlertDialogBuilder import im.vector.app.R import im.vector.app.core.error.ErrorFormatter @@ -30,7 +31,7 @@ import im.vector.app.core.utils.toast import org.matrix.android.sdk.api.session.Session import timber.log.Timber -abstract class VectorSettingsBaseFragment : PreferenceFragmentCompat() { +abstract class VectorSettingsBaseFragment : PreferenceFragmentCompat(), MavericksView { val vectorActivity: VectorBaseActivity<*> by lazy { activity as VectorBaseActivity<*> @@ -145,4 +146,8 @@ abstract class VectorSettingsBaseFragment : PreferenceFragmentCompat() { .setPositiveButton(R.string.ok, null) .show() } + + override fun invalidate() { + // No op by default + } } diff --git a/vector/src/main/java/im/vector/app/features/settings/VectorSettingsSecurityPrivacyFragment.kt b/vector/src/main/java/im/vector/app/features/settings/VectorSettingsSecurityPrivacyFragment.kt index 438382ab3c..f3a054d46d 100644 --- a/vector/src/main/java/im/vector/app/features/settings/VectorSettingsSecurityPrivacyFragment.kt +++ b/vector/src/main/java/im/vector/app/features/settings/VectorSettingsSecurityPrivacyFragment.kt @@ -23,6 +23,7 @@ import android.content.Intent import android.net.Uri import android.os.Bundle import android.view.LayoutInflater +import android.view.View import android.view.ViewGroup import androidx.core.content.ContextCompat import androidx.core.view.isVisible @@ -31,6 +32,7 @@ import androidx.preference.Preference import androidx.preference.PreferenceCategory import androidx.preference.SwitchPreference import androidx.recyclerview.widget.RecyclerView +import com.airbnb.mvrx.fragmentViewModel import com.google.android.material.dialog.MaterialAlertDialogBuilder import im.vector.app.R import im.vector.app.core.di.ActiveSessionHolder @@ -43,10 +45,15 @@ import im.vector.app.core.intent.getFilenameFromUri import im.vector.app.core.platform.SimpleTextWatcher import im.vector.app.core.preference.VectorPreference import im.vector.app.core.preference.VectorPreferenceCategory +import im.vector.app.core.preference.VectorSwitchPreference import im.vector.app.core.utils.copyToClipboard import im.vector.app.core.utils.openFileSelection import im.vector.app.core.utils.toast import im.vector.app.databinding.DialogImportE2eKeysBinding +import im.vector.app.features.analytics.AnalyticsConfig +import im.vector.app.features.analytics.ui.consent.AnalyticsConsentViewActions +import im.vector.app.features.analytics.ui.consent.AnalyticsConsentViewModel +import im.vector.app.features.analytics.ui.consent.AnalyticsConsentViewState import im.vector.app.features.crypto.keys.KeysExporter import im.vector.app.features.crypto.keys.KeysImporter import im.vector.app.features.crypto.keysbackup.settings.KeysBackupManageActivity @@ -71,7 +78,6 @@ import org.matrix.android.sdk.internal.crypto.model.rest.DevicesListResponse import javax.inject.Inject class VectorSettingsSecurityPrivacyFragment @Inject constructor( - private val vectorPreferences: VectorPreferences, private val activeSessionHolder: ActiveSessionHolder, private val pinCodeStore: PinCodeStore, private val keysExporter: KeysExporter, @@ -83,6 +89,8 @@ class VectorSettingsSecurityPrivacyFragment @Inject constructor( override var titleRes = R.string.settings_security_and_privacy override val preferenceXmlRes = R.xml.vector_settings_security_privacy + private val analyticsConsentViewModel: AnalyticsConsentViewModel by fragmentViewModel() + // cryptography private val mCryptographyCategory by lazy { findPreference(VectorPreferences.SETTINGS_CRYPTOGRAPHY_PREFERENCE_KEY)!! @@ -129,6 +137,14 @@ class VectorSettingsSecurityPrivacyFragment @Inject constructor( findPreference("SETTINGS_SECURITY_PIN")!! } + private val analyticsCategory by lazy { + findPreference("SETTINGS_ANALYTICS_PREFERENCE_KEY")!! + } + + private val analyticsConsent by lazy { + findPreference("SETTINGS_USER_ANALYTICS_CONSENT_KEY")!! + } + override fun onCreateRecyclerView(inflater: LayoutInflater?, parent: ViewGroup?, savedInstanceState: Bundle?): RecyclerView { return super.onCreateRecyclerView(inflater, parent, savedInstanceState).also { // Insert animation are really annoying the first time the list is shown @@ -238,18 +254,9 @@ class VectorSettingsSecurityPrivacyFragment @Inject constructor( refreshKeysManagementSection() // Analytics + setUpAnalytics() - // Analytics tracking management - findPreference(VectorPreferences.SETTINGS_USE_ANALYTICS_KEY)!!.let { - // On if the analytics tracking is activated - it.isChecked = vectorPreferences.useAnalytics() - - it.onPreferenceChangeListener = Preference.OnPreferenceChangeListener { _, newValue -> - vectorPreferences.setUseAnalytics(newValue as Boolean) - true - } - } - + // Pin code openPinCodeSettingsPref.setOnPreferenceClickListener { openPinCodePreferenceScreen() true @@ -274,6 +281,27 @@ class VectorSettingsSecurityPrivacyFragment @Inject constructor( } } + override fun onViewCreated(view: View, savedInstanceState: Bundle?) { + super.onViewCreated(view, savedInstanceState) + + observeAnalyticsState() + } + + private fun observeAnalyticsState() { + analyticsConsentViewModel.onEach(AnalyticsConsentViewState::shouldCheckTheBox) { + analyticsConsent.isChecked = it + } + } + + private fun setUpAnalytics() { + analyticsCategory.isVisible = AnalyticsConfig.isAnalyticsEnabled() + + analyticsConsent.setOnPreferenceClickListener { + analyticsConsentViewModel.handle(AnalyticsConsentViewActions.SetUserConsent(analyticsConsent.isChecked)) + true + } + } + // Todo this should be refactored and use same state as 4S section private fun refreshXSigningStatus() { val crossSigningKeys = session.cryptoService().crossSigningService().getMyCrossSigningKeys() diff --git a/vector/src/main/res/xml/vector_settings_security_privacy.xml b/vector/src/main/res/xml/vector_settings_security_privacy.xml index 5dfde2d1df..97ca51033e 100644 --- a/vector/src/main/res/xml/vector_settings_security_privacy.xml +++ b/vector/src/main/res/xml/vector_settings_security_privacy.xml @@ -104,12 +104,11 @@ + android:title="@string/settings_analytics">