Analytics: add setting section

This commit is contained in:
Benoit Marty 2021-11-24 12:08:07 +01:00 committed by Benoit Marty
parent 4c7ccfb438
commit 869b5ad55b
5 changed files with 51 additions and 39 deletions

View File

@ -24,6 +24,7 @@ import im.vector.app.features.analytics.VectorAnalytics
import im.vector.app.features.analytics.store.AnalyticsStore import im.vector.app.features.analytics.store.AnalyticsStore
import kotlinx.coroutines.GlobalScope import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.onEach import kotlinx.coroutines.flow.onEach
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import timber.log.Timber import timber.log.Timber
@ -106,6 +107,7 @@ class DefaultVectorAnalytics @Inject constructor(
posthog?.identify(it) posthog?.identify(it)
} }
} }
.launchIn(GlobalScope)
} }
} }
@ -115,6 +117,7 @@ class DefaultVectorAnalytics @Inject constructor(
getUserConsent().onEach { getUserConsent().onEach {
userConsent = it userConsent = it
} }
.launchIn(GlobalScope)
} }
} }

View File

@ -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" 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" 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 // Rageshake
const val SETTINGS_USE_RAGE_SHAKE_KEY = "SETTINGS_USE_RAGE_SHAKE_KEY" 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" 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 * 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) 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 * Tells if media should be previewed before sending
* *

View File

@ -21,6 +21,7 @@ import android.os.Bundle
import android.view.View import android.view.View
import androidx.annotation.CallSuper import androidx.annotation.CallSuper
import androidx.preference.PreferenceFragmentCompat import androidx.preference.PreferenceFragmentCompat
import com.airbnb.mvrx.MavericksView
import com.google.android.material.dialog.MaterialAlertDialogBuilder import com.google.android.material.dialog.MaterialAlertDialogBuilder
import im.vector.app.R import im.vector.app.R
import im.vector.app.core.error.ErrorFormatter 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 org.matrix.android.sdk.api.session.Session
import timber.log.Timber import timber.log.Timber
abstract class VectorSettingsBaseFragment : PreferenceFragmentCompat() { abstract class VectorSettingsBaseFragment : PreferenceFragmentCompat(), MavericksView {
val vectorActivity: VectorBaseActivity<*> by lazy { val vectorActivity: VectorBaseActivity<*> by lazy {
activity as VectorBaseActivity<*> activity as VectorBaseActivity<*>
@ -145,4 +146,8 @@ abstract class VectorSettingsBaseFragment : PreferenceFragmentCompat() {
.setPositiveButton(R.string.ok, null) .setPositiveButton(R.string.ok, null)
.show() .show()
} }
override fun invalidate() {
// No op by default
}
} }

View File

@ -23,6 +23,7 @@ import android.content.Intent
import android.net.Uri import android.net.Uri
import android.os.Bundle import android.os.Bundle
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import androidx.core.content.ContextCompat import androidx.core.content.ContextCompat
import androidx.core.view.isVisible import androidx.core.view.isVisible
@ -31,6 +32,7 @@ import androidx.preference.Preference
import androidx.preference.PreferenceCategory import androidx.preference.PreferenceCategory
import androidx.preference.SwitchPreference import androidx.preference.SwitchPreference
import androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.RecyclerView
import com.airbnb.mvrx.fragmentViewModel
import com.google.android.material.dialog.MaterialAlertDialogBuilder import com.google.android.material.dialog.MaterialAlertDialogBuilder
import im.vector.app.R import im.vector.app.R
import im.vector.app.core.di.ActiveSessionHolder 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.platform.SimpleTextWatcher
import im.vector.app.core.preference.VectorPreference import im.vector.app.core.preference.VectorPreference
import im.vector.app.core.preference.VectorPreferenceCategory 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.copyToClipboard
import im.vector.app.core.utils.openFileSelection import im.vector.app.core.utils.openFileSelection
import im.vector.app.core.utils.toast import im.vector.app.core.utils.toast
import im.vector.app.databinding.DialogImportE2eKeysBinding 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.KeysExporter
import im.vector.app.features.crypto.keys.KeysImporter import im.vector.app.features.crypto.keys.KeysImporter
import im.vector.app.features.crypto.keysbackup.settings.KeysBackupManageActivity 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 import javax.inject.Inject
class VectorSettingsSecurityPrivacyFragment @Inject constructor( class VectorSettingsSecurityPrivacyFragment @Inject constructor(
private val vectorPreferences: VectorPreferences,
private val activeSessionHolder: ActiveSessionHolder, private val activeSessionHolder: ActiveSessionHolder,
private val pinCodeStore: PinCodeStore, private val pinCodeStore: PinCodeStore,
private val keysExporter: KeysExporter, private val keysExporter: KeysExporter,
@ -83,6 +89,8 @@ class VectorSettingsSecurityPrivacyFragment @Inject constructor(
override var titleRes = R.string.settings_security_and_privacy override var titleRes = R.string.settings_security_and_privacy
override val preferenceXmlRes = R.xml.vector_settings_security_privacy override val preferenceXmlRes = R.xml.vector_settings_security_privacy
private val analyticsConsentViewModel: AnalyticsConsentViewModel by fragmentViewModel()
// cryptography // cryptography
private val mCryptographyCategory by lazy { private val mCryptographyCategory by lazy {
findPreference<PreferenceCategory>(VectorPreferences.SETTINGS_CRYPTOGRAPHY_PREFERENCE_KEY)!! findPreference<PreferenceCategory>(VectorPreferences.SETTINGS_CRYPTOGRAPHY_PREFERENCE_KEY)!!
@ -129,6 +137,14 @@ class VectorSettingsSecurityPrivacyFragment @Inject constructor(
findPreference<VectorPreference>("SETTINGS_SECURITY_PIN")!! findPreference<VectorPreference>("SETTINGS_SECURITY_PIN")!!
} }
private val analyticsCategory by lazy {
findPreference<VectorPreferenceCategory>("SETTINGS_ANALYTICS_PREFERENCE_KEY")!!
}
private val analyticsConsent by lazy {
findPreference<VectorSwitchPreference>("SETTINGS_USER_ANALYTICS_CONSENT_KEY")!!
}
override fun onCreateRecyclerView(inflater: LayoutInflater?, parent: ViewGroup?, savedInstanceState: Bundle?): RecyclerView { override fun onCreateRecyclerView(inflater: LayoutInflater?, parent: ViewGroup?, savedInstanceState: Bundle?): RecyclerView {
return super.onCreateRecyclerView(inflater, parent, savedInstanceState).also { return super.onCreateRecyclerView(inflater, parent, savedInstanceState).also {
// Insert animation are really annoying the first time the list is shown // Insert animation are really annoying the first time the list is shown
@ -238,18 +254,9 @@ class VectorSettingsSecurityPrivacyFragment @Inject constructor(
refreshKeysManagementSection() refreshKeysManagementSection()
// Analytics // Analytics
setUpAnalytics()
// Analytics tracking management // Pin code
findPreference<SwitchPreference>(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
}
}
openPinCodeSettingsPref.setOnPreferenceClickListener { openPinCodeSettingsPref.setOnPreferenceClickListener {
openPinCodePreferenceScreen() openPinCodePreferenceScreen()
true 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 // Todo this should be refactored and use same state as 4S section
private fun refreshXSigningStatus() { private fun refreshXSigningStatus() {
val crossSigningKeys = session.cryptoService().crossSigningService().getMyCrossSigningKeys() val crossSigningKeys = session.cryptoService().crossSigningService().getMyCrossSigningKeys()

View File

@ -104,12 +104,11 @@
<im.vector.app.core.preference.VectorPreferenceCategory <im.vector.app.core.preference.VectorPreferenceCategory
android:key="SETTINGS_ANALYTICS_PREFERENCE_KEY" android:key="SETTINGS_ANALYTICS_PREFERENCE_KEY"
android:title="@string/settings_analytics" android:title="@string/settings_analytics">
app:isPreferenceVisible="@bool/false_not_implemented">
<im.vector.app.core.preference.VectorSwitchPreference <im.vector.app.core.preference.VectorSwitchPreference
android:defaultValue="false" android:defaultValue="false"
android:key="SETTINGS_USE_ANALYTICS_KEY" android:key="SETTINGS_USER_ANALYTICS_CONSENT_KEY"
android:summary="@string/settings_opt_in_of_analytics_summary" android:summary="@string/settings_opt_in_of_analytics_summary"
android:title="@string/settings_opt_in_of_analytics" /> android:title="@string/settings_opt_in_of_analytics" />