mirror of
https://github.com/element-hq/element-android
synced 2024-11-24 18:35:40 +03:00
Analytics: ask user consent at startup (we may iterate later)
This commit is contained in:
parent
b68e9e1f7f
commit
5606a5bfe7
7 changed files with 174 additions and 1 deletions
|
@ -20,6 +20,7 @@ import dagger.Binds
|
|||
import dagger.Module
|
||||
import dagger.hilt.InstallIn
|
||||
import dagger.multibindings.IntoMap
|
||||
import im.vector.app.features.analytics.ui.consent.AnalyticsConsentViewModel
|
||||
import im.vector.app.features.auth.ReAuthViewModel
|
||||
import im.vector.app.features.call.VectorCallViewModel
|
||||
import im.vector.app.features.call.conference.JitsiCallViewModel
|
||||
|
@ -454,6 +455,11 @@ interface MavericksViewModelModule {
|
|||
@MavericksViewModelKey(LoginViewModel::class)
|
||||
fun loginViewModelFactory(factory: LoginViewModel.Factory): MavericksAssistedViewModelFactory<*, *>
|
||||
|
||||
@Binds
|
||||
@IntoMap
|
||||
@MavericksViewModelKey(AnalyticsConsentViewModel::class)
|
||||
fun analyticsConsentViewModelFactory(factory: AnalyticsConsentViewModel.Factory): MavericksAssistedViewModelFactory<*, *>
|
||||
|
||||
@Binds
|
||||
@IntoMap
|
||||
@MavericksViewModelKey(HomeServerCapabilitiesViewModel::class)
|
||||
|
|
|
@ -0,0 +1,24 @@
|
|||
/*
|
||||
* Copyright (c) 2021 New Vector Ltd
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package im.vector.app.features.analytics.ui.consent
|
||||
|
||||
import im.vector.app.core.platform.VectorViewModelAction
|
||||
|
||||
sealed class AnalyticsConsentViewActions : VectorViewModelAction {
|
||||
data class SetUserConsent(val userConsent: Boolean) : AnalyticsConsentViewActions()
|
||||
object OnGetStarted : AnalyticsConsentViewActions()
|
||||
}
|
|
@ -0,0 +1,79 @@
|
|||
/*
|
||||
* Copyright (c) 2021 New Vector Ltd
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package im.vector.app.features.analytics.ui.consent
|
||||
|
||||
import com.airbnb.mvrx.MavericksViewModelFactory
|
||||
import dagger.assisted.Assisted
|
||||
import dagger.assisted.AssistedFactory
|
||||
import dagger.assisted.AssistedInject
|
||||
import im.vector.app.core.di.MavericksAssistedViewModelFactory
|
||||
import im.vector.app.core.di.hiltMavericksViewModelFactory
|
||||
import im.vector.app.core.extensions.exhaustive
|
||||
import im.vector.app.core.platform.EmptyViewEvents
|
||||
import im.vector.app.core.platform.VectorViewModel
|
||||
import im.vector.app.features.analytics.VectorAnalytics
|
||||
import kotlinx.coroutines.launch
|
||||
|
||||
class AnalyticsConsentViewModel @AssistedInject constructor(
|
||||
@Assisted initialState: AnalyticsConsentViewState,
|
||||
private val analytics: VectorAnalytics
|
||||
) : VectorViewModel<AnalyticsConsentViewState, AnalyticsConsentViewActions, EmptyViewEvents>(initialState) {
|
||||
|
||||
@AssistedFactory
|
||||
interface Factory : MavericksAssistedViewModelFactory<AnalyticsConsentViewModel, AnalyticsConsentViewState> {
|
||||
override fun create(initialState: AnalyticsConsentViewState): AnalyticsConsentViewModel
|
||||
}
|
||||
|
||||
companion object : MavericksViewModelFactory<AnalyticsConsentViewModel, AnalyticsConsentViewState> by hiltMavericksViewModelFactory()
|
||||
|
||||
init {
|
||||
observeAnalytics()
|
||||
}
|
||||
|
||||
private fun observeAnalytics() {
|
||||
analytics.didAskUserConsent().setOnEach {
|
||||
copy(didAskUserConsent = it)
|
||||
}
|
||||
analytics.getUserConsent().setOnEach {
|
||||
copy(userConsent = it)
|
||||
}
|
||||
}
|
||||
|
||||
override fun handle(action: AnalyticsConsentViewActions) {
|
||||
when (action) {
|
||||
is AnalyticsConsentViewActions.SetUserConsent -> handleSetUserConsent(action)
|
||||
AnalyticsConsentViewActions.OnGetStarted -> handleOnScreenLeft()
|
||||
}.exhaustive
|
||||
}
|
||||
|
||||
private fun handleSetUserConsent(action: AnalyticsConsentViewActions.SetUserConsent) {
|
||||
viewModelScope.launch {
|
||||
analytics.setUserConsent(action.userConsent)
|
||||
if (!action.userConsent) {
|
||||
// User explicitly changed the default value, let's avoid reverting to the default value
|
||||
analytics.setDidAskUserConsent(true)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun handleOnScreenLeft() {
|
||||
// Whatever the state of the box, consider the user acknowledge it
|
||||
viewModelScope.launch {
|
||||
analytics.setDidAskUserConsent(true)
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,32 @@
|
|||
/*
|
||||
* Copyright (c) 2021 New Vector Ltd
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package im.vector.app.features.analytics.ui.consent
|
||||
|
||||
import com.airbnb.mvrx.MavericksState
|
||||
|
||||
data class AnalyticsConsentViewState(
|
||||
val userConsent: Boolean = false,
|
||||
val didAskUserConsent: Boolean = false
|
||||
) : MavericksState {
|
||||
val shouldCheckTheBox: Boolean =
|
||||
if (didAskUserConsent) {
|
||||
userConsent
|
||||
} else {
|
||||
// default value
|
||||
true
|
||||
}
|
||||
}
|
|
@ -22,10 +22,14 @@ import android.view.LayoutInflater
|
|||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.core.view.isVisible
|
||||
import com.airbnb.mvrx.fragmentViewModel
|
||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||
import im.vector.app.BuildConfig
|
||||
import im.vector.app.R
|
||||
import im.vector.app.databinding.FragmentLoginSplashBinding
|
||||
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.settings.VectorPreferences
|
||||
import org.matrix.android.sdk.api.failure.Failure
|
||||
import java.net.UnknownHostException
|
||||
|
@ -38,6 +42,8 @@ class LoginSplashFragment @Inject constructor(
|
|||
private val vectorPreferences: VectorPreferences
|
||||
) : AbstractLoginFragment<FragmentLoginSplashBinding>() {
|
||||
|
||||
private val analyticsConsentViewModel: AnalyticsConsentViewModel by fragmentViewModel()
|
||||
|
||||
override fun getBinding(inflater: LayoutInflater, container: ViewGroup?): FragmentLoginSplashBinding {
|
||||
return FragmentLoginSplashBinding.inflate(inflater, container, false)
|
||||
}
|
||||
|
@ -46,10 +52,23 @@ class LoginSplashFragment @Inject constructor(
|
|||
super.onViewCreated(view, savedInstanceState)
|
||||
|
||||
setupViews()
|
||||
observeAnalyticsState()
|
||||
}
|
||||
|
||||
private fun observeAnalyticsState() {
|
||||
analyticsConsentViewModel.onEach(AnalyticsConsentViewState::shouldCheckTheBox) {
|
||||
views.loginSplashAnalyticsConsent.isChecked = it
|
||||
}
|
||||
}
|
||||
|
||||
private fun setupViews() {
|
||||
views.loginSplashSubmit.debouncedClicks { getStarted() }
|
||||
// setOnCheckedChangeListener is to annoying since it does not distinguish user changes and code changes
|
||||
views.loginSplashAnalyticsConsent.setOnClickListener {
|
||||
analyticsConsentViewModel.handle(AnalyticsConsentViewActions.SetUserConsent(
|
||||
views.loginSplashAnalyticsConsent.isChecked
|
||||
))
|
||||
}
|
||||
|
||||
if (BuildConfig.DEBUG || vectorPreferences.developerMode()) {
|
||||
views.loginSplashVersion.isVisible = true
|
||||
|
@ -61,6 +80,7 @@ class LoginSplashFragment @Inject constructor(
|
|||
}
|
||||
|
||||
private fun getStarted() {
|
||||
analyticsConsentViewModel.handle(AnalyticsConsentViewActions.OnGetStarted)
|
||||
loginViewModel.handle(LoginAction.OnGetStarted(resetLoginConfig = false))
|
||||
}
|
||||
|
||||
|
|
|
@ -204,9 +204,18 @@
|
|||
android:layout_height="wrap_content"
|
||||
android:textColor="?vctr_content_secondary"
|
||||
android:visibility="gone"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintBottom_toTopOf="@id/loginSplashAnalyticsConsent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
tools:text="@string/settings_version"
|
||||
tools:visibility="visible" />
|
||||
|
||||
<CheckBox
|
||||
android:id="@+id/loginSplashAnalyticsConsent"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/analytics_consent_splash"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
|
|
|
@ -1377,6 +1377,9 @@
|
|||
<string name="template_settings_opt_in_of_analytics_prompt">Please enable analytics to help us improve ${app_name}.</string>
|
||||
<string name="settings_opt_in_of_analytics_ok">Yes, I want to help!</string>
|
||||
|
||||
<!-- analytics v2 -->
|
||||
<string name="analytics_consent_splash">Send anonymous usage data to element.io</string>
|
||||
|
||||
<string name="settings_data_save_mode">Data save mode</string>
|
||||
<string name="settings_data_save_mode_summary">Data save mode applies a specific filter so presence updates and typing notifications are filtered out.</string>
|
||||
|
||||
|
|
Loading…
Reference in a new issue