Improve API and documentation

This commit is contained in:
Benoit Marty 2025-10-21 11:53:36 +02:00
parent 0f3858649c
commit 64b5b53510
9 changed files with 22 additions and 15 deletions

@ -1 +1 @@
Subproject commit f9178b5a11cda8d91ae5d62d6ad66ae8a6b3081e Subproject commit f662f079f911b728e5769d10268e2c2775d7287a

View file

@ -21,9 +21,10 @@ interface EnterpriseService {
/** /**
* Override the brand color. * Override the brand color.
* @param sessionId the session to override the brand color for, or null to set the brand color to use when there is no session.
* @param brandColor the color in hex format (#RRGGBBAA or #RRGGBB), or null to reset to default. * @param brandColor the color in hex format (#RRGGBBAA or #RRGGBB), or null to reset to default.
*/ */
suspend fun overrideBrandColor(brandColor: String?) suspend fun overrideBrandColor(sessionId: SessionId?, brandColor: String?)
@Composable @Composable
fun semanticColorsLight(): State<SemanticColors> fun semanticColorsLight(): State<SemanticColors>

View file

@ -32,7 +32,7 @@ class DefaultEnterpriseService : EnterpriseService {
override fun defaultHomeserverList(): List<String> = emptyList() override fun defaultHomeserverList(): List<String> = emptyList()
override suspend fun isAllowedToConnectToHomeserver(homeserverUrl: String) = true override suspend fun isAllowedToConnectToHomeserver(homeserverUrl: String) = true
override suspend fun overrideBrandColor(brandColor: String?) = Unit override suspend fun overrideBrandColor(sessionId: SessionId?, brandColor: String?) = Unit
@Composable @Composable
override fun semanticColorsLight(): State<SemanticColors> { override fun semanticColorsLight(): State<SemanticColors> {

View file

@ -51,7 +51,7 @@ class DefaultEnterpriseServiceTest {
}.test { }.test {
val initialState = awaitItem() val initialState = awaitItem()
assertThat(initialState).isEqualTo(compoundColorsLight) assertThat(initialState).isEqualTo(compoundColorsLight)
defaultEnterpriseService.overrideBrandColor("#87654321") defaultEnterpriseService.overrideBrandColor(A_SESSION_ID, "#87654321")
expectNoEvents() expectNoEvents()
} }
} }
@ -64,7 +64,7 @@ class DefaultEnterpriseServiceTest {
}.test { }.test {
val initialState = awaitItem() val initialState = awaitItem()
assertThat(initialState).isEqualTo(compoundColorsDark) assertThat(initialState).isEqualTo(compoundColorsDark)
defaultEnterpriseService.overrideBrandColor("#87654321") defaultEnterpriseService.overrideBrandColor(A_SESSION_ID, "#87654321")
expectNoEvents() expectNoEvents()
} }
} }

View file

@ -26,7 +26,7 @@ class FakeEnterpriseService(
private val isAllowedToConnectToHomeserverResult: (String) -> Boolean = { lambdaError() }, private val isAllowedToConnectToHomeserverResult: (String) -> Boolean = { lambdaError() },
private val semanticColorsLightResult: () -> State<SemanticColors> = { lambdaError() }, private val semanticColorsLightResult: () -> State<SemanticColors> = { lambdaError() },
private val semanticColorsDarkResult: () -> State<SemanticColors> = { lambdaError() }, private val semanticColorsDarkResult: () -> State<SemanticColors> = { lambdaError() },
private val overrideBrandColorResult: (String?) -> Unit = { lambdaError() }, private val overrideBrandColorResult: (SessionId?, String?) -> Unit = { _, _ -> lambdaError() },
private val firebasePushGatewayResult: () -> String? = { lambdaError() }, private val firebasePushGatewayResult: () -> String? = { lambdaError() },
private val unifiedPushDefaultPushGatewayResult: () -> String? = { lambdaError() }, private val unifiedPushDefaultPushGatewayResult: () -> String? = { lambdaError() },
) : EnterpriseService { ) : EnterpriseService {
@ -42,8 +42,8 @@ class FakeEnterpriseService(
isAllowedToConnectToHomeserverResult(homeserverUrl) isAllowedToConnectToHomeserverResult(homeserverUrl)
} }
override suspend fun overrideBrandColor(brandColor: String?) = simulateLongTask { override suspend fun overrideBrandColor(sessionId: SessionId?, brandColor: String?) = simulateLongTask {
overrideBrandColorResult(brandColor) overrideBrandColorResult(sessionId, brandColor)
} }
@Composable @Composable

View file

@ -38,6 +38,7 @@ import io.element.android.libraries.core.meta.BuildType
import io.element.android.libraries.featureflag.api.FeatureFlagService import io.element.android.libraries.featureflag.api.FeatureFlagService
import io.element.android.libraries.featureflag.api.FeatureFlags import io.element.android.libraries.featureflag.api.FeatureFlags
import io.element.android.libraries.featureflag.ui.model.FeatureUiModel import io.element.android.libraries.featureflag.ui.model.FeatureUiModel
import io.element.android.libraries.matrix.api.core.SessionId
import io.element.android.libraries.preferences.api.store.AppPreferencesStore import io.element.android.libraries.preferences.api.store.AppPreferencesStore
import kotlinx.collections.immutable.ImmutableList import kotlinx.collections.immutable.ImmutableList
import kotlinx.collections.immutable.persistentListOf import kotlinx.collections.immutable.persistentListOf
@ -50,6 +51,7 @@ import java.net.URL
@Inject @Inject
class DeveloperSettingsPresenter( class DeveloperSettingsPresenter(
private val sessionId: SessionId,
private val featureFlagService: FeatureFlagService, private val featureFlagService: FeatureFlagService,
private val computeCacheSizeUseCase: ComputeCacheSizeUseCase, private val computeCacheSizeUseCase: ComputeCacheSizeUseCase,
private val clearCacheUseCase: ClearCacheUseCase, private val clearCacheUseCase: ClearCacheUseCase,
@ -138,7 +140,7 @@ class DeveloperSettingsPresenter(
is DeveloperSettingsEvents.ChangeBrandColor -> coroutineScope.launch { is DeveloperSettingsEvents.ChangeBrandColor -> coroutineScope.launch {
showColorPicker = false showColorPicker = false
val color = event.color?.value?.toHexString(HexFormat.UpperCase)?.substring(2, 8) val color = event.color?.value?.toHexString(HexFormat.UpperCase)?.substring(2, 8)
enterpriseService.overrideBrandColor(color) enterpriseService.overrideBrandColor(sessionId, color)
} }
is DeveloperSettingsEvents.SetShowColorPicker -> { is DeveloperSettingsEvents.SetShowColorPicker -> {
showColorPicker = event.show showColorPicker = event.show

View file

@ -25,6 +25,8 @@ import io.element.android.libraries.featureflag.api.Feature
import io.element.android.libraries.featureflag.api.FeatureFlags import io.element.android.libraries.featureflag.api.FeatureFlags
import io.element.android.libraries.featureflag.test.FakeFeature import io.element.android.libraries.featureflag.test.FakeFeature
import io.element.android.libraries.featureflag.test.FakeFeatureFlagService import io.element.android.libraries.featureflag.test.FakeFeatureFlagService
import io.element.android.libraries.matrix.api.core.SessionId
import io.element.android.libraries.matrix.test.A_SESSION_ID
import io.element.android.libraries.matrix.test.core.aBuildMeta import io.element.android.libraries.matrix.test.core.aBuildMeta
import io.element.android.libraries.preferences.test.InMemoryAppPreferencesStore import io.element.android.libraries.preferences.test.InMemoryAppPreferencesStore
import io.element.android.tests.testutils.WarmUpRule import io.element.android.tests.testutils.WarmUpRule
@ -184,7 +186,7 @@ class DeveloperSettingsPresenterTest {
@Test @Test
fun `present - enterprise build can change the brand color`() = runTest { fun `present - enterprise build can change the brand color`() = runTest {
val overrideBrandColorResult = lambdaRecorder<String?, Unit> { } val overrideBrandColorResult = lambdaRecorder<SessionId?, String?, Unit> { _, _ -> }
val presenter = createDeveloperSettingsPresenter( val presenter = createDeveloperSettingsPresenter(
enterpriseService = FakeEnterpriseService( enterpriseService = FakeEnterpriseService(
isEnterpriseBuild = true, isEnterpriseBuild = true,
@ -205,11 +207,12 @@ class DeveloperSettingsPresenterTest {
assertThat(awaitItem().showColorPicker).isFalse() assertThat(awaitItem().showColorPicker).isFalse()
skipItems(1) skipItems(1)
overrideBrandColorResult.assertions().isCalledOnce() overrideBrandColorResult.assertions().isCalledOnce()
.with(value("00FF00")) .with(value(A_SESSION_ID), value("00FF00"))
} }
} }
private fun createDeveloperSettingsPresenter( private fun createDeveloperSettingsPresenter(
sessionId: SessionId = A_SESSION_ID,
featureFlagService: FakeFeatureFlagService = FakeFeatureFlagService( featureFlagService: FakeFeatureFlagService = FakeFeatureFlagService(
getAvailableFeaturesResult = { _, _ -> getAvailableFeaturesResult = { _, _ ->
listOf( listOf(
@ -228,6 +231,7 @@ class DeveloperSettingsPresenterTest {
enterpriseService: EnterpriseService = FakeEnterpriseService(), enterpriseService: EnterpriseService = FakeEnterpriseService(),
): DeveloperSettingsPresenter { ): DeveloperSettingsPresenter {
return DeveloperSettingsPresenter( return DeveloperSettingsPresenter(
sessionId = sessionId,
featureFlagService = featureFlagService, featureFlagService = featureFlagService,
computeCacheSizeUseCase = cacheSizeUseCase, computeCacheSizeUseCase = cacheSizeUseCase,
clearCacheUseCase = clearCacheUseCase, clearCacheUseCase = clearCacheUseCase,

View file

@ -36,7 +36,7 @@ import io.element.android.libraries.matrix.api.core.UserId
import io.element.android.libraries.matrix.api.tracing.TracingService import io.element.android.libraries.matrix.api.tracing.TracingService
import io.element.android.libraries.network.useragent.UserAgentProvider import io.element.android.libraries.network.useragent.UserAgentProvider
import io.element.android.libraries.sessionstorage.api.SessionStore import io.element.android.libraries.sessionstorage.api.SessionStore
import io.element.android.libraries.sessionstorage.api.userIdFlow import io.element.android.libraries.sessionstorage.api.sessionIdFlow
import kotlinx.coroutines.CancellationException import kotlinx.coroutines.CancellationException
import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.flow.distinctUntilChanged import kotlinx.coroutines.flow.distinctUntilChanged
@ -107,7 +107,7 @@ class DefaultBugReporter(
sessionStore.getLatestSession() sessionStore.getLatestSession()
}?.userId?.let(::UserId)?.domainName }?.userId?.let(::UserId)?.domainName
setCurrentLogDirectory(logSubfolder) setCurrentLogDirectory(logSubfolder)
sessionStore.userIdFlow() sessionStore.sessionIdFlow()
.map { .map {
it?.let(::UserId)?.domainName it?.let(::UserId)?.domainName
} }

View file

@ -75,9 +75,9 @@ fun Flow<List<SessionData>>.toUserListFlow(): Flow<List<String>> {
} }
/** /**
* @return a flow emitting the userId of the latest session if logged in, null otherwise. * @return a flow emitting the sessionId of the latest session if logged in, null otherwise.
*/ */
fun SessionStore.userIdFlow(): Flow<String?> { fun SessionStore.sessionIdFlow(): Flow<String?> {
return loggedInStateFlow().map { return loggedInStateFlow().map {
when (it) { when (it) {
is LoggedInState.LoggedIn -> it.sessionId is LoggedInState.LoggedIn -> it.sessionId