Lifting debug overrides to their own abstraction (#5361)

* separating the debug overrides to their own abstraction
- rather than sharing the user facing vector data store

* inlining the debug flow getters and declarations
- also replaces funs with vals as the references are immutable

* adding changelog entry
This commit is contained in:
Adam Brown 2022-03-02 10:08:43 +00:00 committed by GitHub
parent 1c94a7ddc7
commit 0c628905de
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 124 additions and 39 deletions

1
changelog.d/5361.misc Normal file
View File

@ -0,0 +1 @@
Creates dedicated VectorOverrides for forcing behaviour for local testing/development

View File

@ -23,8 +23,11 @@ import dagger.Provides
import dagger.hilt.InstallIn
import dagger.hilt.components.SingletonComponent
import im.vector.app.features.DefaultVectorFeatures
import im.vector.app.features.DefaultVectorOverrides
import im.vector.app.features.VectorFeatures
import im.vector.app.features.VectorOverrides
import im.vector.app.features.debug.features.DebugVectorFeatures
import im.vector.app.features.debug.features.DebugVectorOverrides
@InstallIn(SingletonComponent::class)
@Module
@ -33,6 +36,9 @@ interface FeaturesModule {
@Binds
fun bindFeatures(debugFeatures: DebugVectorFeatures): VectorFeatures
@Binds
fun bindOverrides(debugOverrides: DebugVectorOverrides): VectorOverrides
companion object {
@Provides
@ -44,5 +50,15 @@ interface FeaturesModule {
fun providesDebugVectorFeatures(context: Context, defaultVectorFeatures: DefaultVectorFeatures): DebugVectorFeatures {
return DebugVectorFeatures(context, defaultVectorFeatures)
}
@Provides
fun providesDefaultVectorOverrides(): DefaultVectorOverrides {
return DefaultVectorOverrides()
}
@Provides
fun providesDebugVectorOverrides(context: Context): DebugVectorOverrides {
return DebugVectorOverrides(context)
}
}
}

View File

@ -0,0 +1,54 @@
/*
* Copyright (c) 2022 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.debug.features
import android.content.Context
import androidx.datastore.core.DataStore
import androidx.datastore.preferences.core.Preferences
import androidx.datastore.preferences.core.booleanPreferencesKey
import androidx.datastore.preferences.core.edit
import androidx.datastore.preferences.preferencesDataStore
import im.vector.app.features.VectorOverrides
import kotlinx.coroutines.flow.map
import org.matrix.android.sdk.api.extensions.orFalse
private val Context.dataStore: DataStore<Preferences> by preferencesDataStore(name = "vector_overrides")
private val keyForceDialPadDisplay = booleanPreferencesKey("force_dial_pad_display")
private val keyForceLoginFallback = booleanPreferencesKey("force_login_fallback")
class DebugVectorOverrides(private val context: Context) : VectorOverrides {
override val forceDialPad = context.dataStore.data.map { preferences ->
preferences[keyForceDialPadDisplay].orFalse()
}
override val forceLoginFallback = context.dataStore.data.map { preferences ->
preferences[keyForceLoginFallback].orFalse()
}
suspend fun setForceDialPadDisplay(force: Boolean) {
context.dataStore.edit { settings ->
settings[keyForceDialPadDisplay] = force
}
}
suspend fun setForceLoginFallback(force: Boolean) {
context.dataStore.edit { settings ->
settings[keyForceLoginFallback] = force
}
}
}

View File

@ -24,12 +24,12 @@ import im.vector.app.core.di.MavericksAssistedViewModelFactory
import im.vector.app.core.di.hiltMavericksViewModelFactory
import im.vector.app.core.platform.EmptyViewEvents
import im.vector.app.core.platform.VectorViewModel
import im.vector.app.features.settings.VectorDataStore
import im.vector.app.features.debug.features.DebugVectorOverrides
import kotlinx.coroutines.launch
class DebugPrivateSettingsViewModel @AssistedInject constructor(
@Assisted initialState: DebugPrivateSettingsViewState,
private val vectorDataStore: VectorDataStore
private val debugVectorOverrides: DebugVectorOverrides
) : VectorViewModel<DebugPrivateSettingsViewState, DebugPrivateSettingsViewActions, EmptyViewEvents>(initialState) {
@AssistedFactory
@ -44,11 +44,12 @@ class DebugPrivateSettingsViewModel @AssistedInject constructor(
}
private fun observeVectorDataStore() {
vectorDataStore.forceDialPadDisplayFlow.setOnEach {
copy(dialPadVisible = it)
debugVectorOverrides.forceDialPad.setOnEach {
copy(
dialPadVisible = it
)
}
vectorDataStore.forceLoginFallbackFlow.setOnEach {
debugVectorOverrides.forceLoginFallback.setOnEach {
copy(forceLoginFallback = it)
}
}
@ -62,13 +63,13 @@ class DebugPrivateSettingsViewModel @AssistedInject constructor(
private fun handleSetDialPadVisibility(action: DebugPrivateSettingsViewActions.SetDialPadVisibility) {
viewModelScope.launch {
vectorDataStore.setForceDialPadDisplay(action.force)
debugVectorOverrides.setForceDialPadDisplay(action.force)
}
}
private fun handleSetForceLoginFallbackEnabled(action: DebugPrivateSettingsViewActions.SetForceLoginFallbackEnabled) {
viewModelScope.launch {
vectorDataStore.setForceLoginFallbackFlow(action.force)
debugVectorOverrides.setForceLoginFallback(action.force)
}
}
}

View File

@ -0,0 +1,30 @@
/*
* Copyright (c) 2022 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
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.flowOf
interface VectorOverrides {
val forceDialPad: Flow<Boolean>
val forceLoginFallback: Flow<Boolean>
}
class DefaultVectorOverrides : VectorOverrides {
override val forceDialPad = flowOf(false)
override val forceLoginFallback = flowOf(false)
}

View File

@ -28,6 +28,7 @@ import im.vector.app.core.di.MavericksAssistedViewModelFactory
import im.vector.app.core.di.hiltMavericksViewModelFactory
import im.vector.app.core.extensions.singletonEntryPoint
import im.vector.app.core.platform.VectorViewModel
import im.vector.app.features.VectorOverrides
import im.vector.app.features.call.dialpad.DialPadLookup
import im.vector.app.features.call.lookup.CallProtocolsChecker
import im.vector.app.features.call.webrtc.WebRtcCallManager
@ -67,7 +68,8 @@ class HomeDetailViewModel @AssistedInject constructor(
private val callManager: WebRtcCallManager,
private val directRoomHelper: DirectRoomHelper,
private val appStateHandler: AppStateHandler,
private val autoAcceptInvites: AutoAcceptInvites
private val autoAcceptInvites: AutoAcceptInvites,
private val vectorOverrides: VectorOverrides
) : VectorViewModel<HomeDetailViewState, HomeDetailAction, HomeDetailViewEvents>(initialState),
CallProtocolsChecker.Listener {
@ -106,8 +108,7 @@ class HomeDetailViewModel @AssistedInject constructor(
pushCounter = nbOfPush
)
}
vectorDataStore.forceDialPadDisplayFlow.setOnEach { force ->
vectorOverrides.forceDialPad.setOnEach { force ->
copy(
forceDialPadTab = force
)

View File

@ -37,6 +37,7 @@ import im.vector.app.core.platform.VectorViewModel
import im.vector.app.core.resources.StringProvider
import im.vector.app.core.utils.ensureTrailingSlash
import im.vector.app.features.VectorFeatures
import im.vector.app.features.VectorOverrides
import im.vector.app.features.analytics.AnalyticsTracker
import im.vector.app.features.analytics.extensions.toTrackingValue
import im.vector.app.features.analytics.plan.UserProperties
@ -81,6 +82,7 @@ class OnboardingViewModel @AssistedInject constructor(
private val vectorFeatures: VectorFeatures,
private val analyticsTracker: AnalyticsTracker,
private val vectorDataStore: VectorDataStore,
private val vectorOverrides: VectorOverrides
) : VectorViewModel<OnboardingViewState, OnboardingAction, OnboardingViewEvents>(initialState) {
@AssistedFactory
@ -102,7 +104,7 @@ class OnboardingViewModel @AssistedInject constructor(
}
private fun observeDataStore() = viewModelScope.launch {
vectorDataStore.forceLoginFallbackFlow.setOnEach { isForceLoginFallbackEnabled ->
vectorOverrides.forceLoginFallback.setOnEach { isForceLoginFallbackEnabled ->
copy(isForceLoginFallbackEnabled = isForceLoginFallbackEnabled)
}
}

View File

@ -19,13 +19,11 @@ package im.vector.app.features.settings
import android.content.Context
import androidx.datastore.core.DataStore
import androidx.datastore.preferences.core.Preferences
import androidx.datastore.preferences.core.booleanPreferencesKey
import androidx.datastore.preferences.core.edit
import androidx.datastore.preferences.core.intPreferencesKey
import androidx.datastore.preferences.preferencesDataStore
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.map
import org.matrix.android.sdk.api.extensions.orFalse
import javax.inject.Inject
private val Context.dataStore: DataStore<Preferences> by preferencesDataStore(name = "vector_settings")
@ -46,29 +44,4 @@ class VectorDataStore @Inject constructor(
settings[pushCounter] = currentCounterValue + 1
}
}
// For debug only
private val forceDialPadDisplay = booleanPreferencesKey("force_dial_pad_display")
val forceDialPadDisplayFlow: Flow<Boolean> = context.dataStore.data.map { preferences ->
preferences[forceDialPadDisplay].orFalse()
}
suspend fun setForceDialPadDisplay(force: Boolean) {
context.dataStore.edit { settings ->
settings[forceDialPadDisplay] = force
}
}
private val forceLoginFallback = booleanPreferencesKey("force_login_fallback")
val forceLoginFallbackFlow: Flow<Boolean> = context.dataStore.data.map { preferences ->
preferences[forceLoginFallback].orFalse()
}
suspend fun setForceLoginFallbackFlow(force: Boolean) {
context.dataStore.edit { settings ->
settings[forceLoginFallback] = force
}
}
}

View File

@ -21,7 +21,9 @@ import dagger.Provides
import dagger.hilt.InstallIn
import dagger.hilt.components.SingletonComponent
import im.vector.app.features.DefaultVectorFeatures
import im.vector.app.features.DefaultVectorOverrides
import im.vector.app.features.VectorFeatures
import im.vector.app.features.VectorOverrides
@InstallIn(SingletonComponent::class)
@Module
@ -31,4 +33,9 @@ object FeaturesModule {
fun providesFeatures(): VectorFeatures {
return DefaultVectorFeatures()
}
@Provides
fun providesOverrides(): VectorOverrides {
return DefaultVectorOverrides()
}
}