Skip to content

Commit f752147

Browse files
jmartinespElementBot
andauthored
Remove Element Call feature flag and revert base URL to call.element.io (#1809)
Co-authored-by: ElementBot <[email protected]>
1 parent a5bad53 commit f752147

File tree

25 files changed

+164
-191
lines changed

25 files changed

+164
-191
lines changed

appconfig/src/main/kotlin/io/element/android/appconfig/ElementCallConfig.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,5 +17,5 @@
1717
package io.element.android.appconfig
1818

1919
object ElementCallConfig {
20-
const val DEFAULT_BASE_URL = "https://call.element.dev"
20+
const val DEFAULT_BASE_URL = "https://call.element.io"
2121
}
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
Remove Element Call feature flag, it's not always enabled.
2+
3+
- Reverted the EC base URL to `https://call.element.io`.
4+
- Moved the option to override this URL to developer settings from advanced settings.

features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesPresenter.kt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -157,10 +157,10 @@ class MessagesPresenter @AssistedInject constructor(
157157
val enableTextFormatting by preferencesStore.isRichTextEditorEnabledFlow().collectAsState(initial = true)
158158

159159
var enableVoiceMessages by remember { mutableStateOf(false) }
160-
var enableInRoomCalls by remember { mutableStateOf(false) }
160+
// TODO add min power level to use this feature in the future?
161+
val enableInRoomCalls = true
161162
LaunchedEffect(featureFlagsService) {
162163
enableVoiceMessages = featureFlagsService.isFeatureEnabled(FeatureFlags.VoiceMessages)
163-
enableInRoomCalls = featureFlagsService.isFeatureEnabled(FeatureFlags.InRoomCalls)
164164
}
165165

166166
fun handleEvents(event: MessagesEvents) {

features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/advanced/AdvancedSettingsEvents.kt

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,5 +19,4 @@ package io.element.android.features.preferences.impl.advanced
1919
sealed interface AdvancedSettingsEvents {
2020
data class SetRichTextEditorEnabled(val enabled: Boolean) : AdvancedSettingsEvents
2121
data class SetDeveloperModeEnabled(val enabled: Boolean) : AdvancedSettingsEvents
22-
data class SetCustomElementCallBaseUrl(val baseUrl: String?) : AdvancedSettingsEvents
2322
}

features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/advanced/AdvancedSettingsPresenter.kt

Lines changed: 0 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -17,25 +17,16 @@
1717
package io.element.android.features.preferences.impl.advanced
1818

1919
import androidx.compose.runtime.Composable
20-
import androidx.compose.runtime.LaunchedEffect
2120
import androidx.compose.runtime.collectAsState
2221
import androidx.compose.runtime.getValue
23-
import androidx.compose.runtime.mutableStateOf
24-
import androidx.compose.runtime.remember
2522
import androidx.compose.runtime.rememberCoroutineScope
26-
import androidx.compose.runtime.setValue
27-
import io.element.android.appconfig.ElementCallConfig
2823
import io.element.android.features.preferences.api.store.PreferencesStore
2924
import io.element.android.libraries.architecture.Presenter
30-
import io.element.android.libraries.featureflag.api.FeatureFlagService
31-
import io.element.android.libraries.featureflag.api.FeatureFlags
3225
import kotlinx.coroutines.launch
33-
import java.net.URL
3426
import javax.inject.Inject
3527

3628
class AdvancedSettingsPresenter @Inject constructor(
3729
private val preferencesStore: PreferencesStore,
38-
private val featureFlagService: FeatureFlagService,
3930
) : Presenter<AdvancedSettingsState> {
4031

4132
@Composable
@@ -47,14 +38,6 @@ class AdvancedSettingsPresenter @Inject constructor(
4738
val isDeveloperModeEnabled by preferencesStore
4839
.isDeveloperModeEnabledFlow()
4940
.collectAsState(initial = false)
50-
val customElementCallBaseUrl by preferencesStore
51-
.getCustomElementCallBaseUrlFlow()
52-
.collectAsState(initial = null)
53-
54-
var canDisplayElementCallSettings by remember { mutableStateOf(false) }
55-
LaunchedEffect(Unit) {
56-
canDisplayElementCallSettings = featureFlagService.isFeatureEnabled(FeatureFlags.InRoomCalls)
57-
}
5841

5942
fun handleEvents(event: AdvancedSettingsEvents) {
6043
when (event) {
@@ -64,34 +47,13 @@ class AdvancedSettingsPresenter @Inject constructor(
6447
is AdvancedSettingsEvents.SetDeveloperModeEnabled -> localCoroutineScope.launch {
6548
preferencesStore.setDeveloperModeEnabled(event.enabled)
6649
}
67-
is AdvancedSettingsEvents.SetCustomElementCallBaseUrl -> localCoroutineScope.launch {
68-
// If the URL is either empty or the default one, we want to save 'null' to remove the custom URL
69-
val urlToSave = event.baseUrl.takeIf { !it.isNullOrEmpty() && it != ElementCallConfig.DEFAULT_BASE_URL }
70-
preferencesStore.setCustomElementCallBaseUrl(urlToSave)
71-
}
7250
}
7351
}
7452

7553
return AdvancedSettingsState(
7654
isRichTextEditorEnabled = isRichTextEditorEnabled,
7755
isDeveloperModeEnabled = isDeveloperModeEnabled,
78-
customElementCallBaseUrlState = if (canDisplayElementCallSettings) {
79-
CustomElementCallBaseUrlState(
80-
baseUrl = customElementCallBaseUrl,
81-
defaultUrl = ElementCallConfig.DEFAULT_BASE_URL,
82-
validator = ::customElementCallUrlValidator,
83-
)
84-
} else null,
8556
eventSink = { handleEvents(it) }
8657
)
8758
}
88-
89-
private fun customElementCallUrlValidator(url: String?): Boolean {
90-
return runCatching {
91-
if (url.isNullOrEmpty()) return@runCatching
92-
val parsedUrl = URL(url)
93-
if (parsedUrl.protocol !in listOf("http", "https")) error("Incorrect protocol")
94-
if (parsedUrl.host.isNullOrBlank()) error("Missing host")
95-
}.isSuccess
96-
}
9759
}

features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/advanced/AdvancedSettingsState.kt

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -19,12 +19,5 @@ package io.element.android.features.preferences.impl.advanced
1919
data class AdvancedSettingsState(
2020
val isRichTextEditorEnabled: Boolean,
2121
val isDeveloperModeEnabled: Boolean,
22-
val customElementCallBaseUrlState: CustomElementCallBaseUrlState?,
2322
val eventSink: (AdvancedSettingsEvents) -> Unit
2423
)
25-
26-
data class CustomElementCallBaseUrlState(
27-
val baseUrl: String?,
28-
val defaultUrl: String,
29-
val validator: (String?) -> Boolean,
30-
)

features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/advanced/AdvancedSettingsStateProvider.kt

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,17 +24,14 @@ open class AdvancedSettingsStateProvider : PreviewParameterProvider<AdvancedSett
2424
aAdvancedSettingsState(),
2525
aAdvancedSettingsState(isRichTextEditorEnabled = true),
2626
aAdvancedSettingsState(isDeveloperModeEnabled = true),
27-
aAdvancedSettingsState(customElementCallBaseUrl = "https://call.element.io"),
2827
)
2928
}
3029

3130
fun aAdvancedSettingsState(
3231
isRichTextEditorEnabled: Boolean = false,
3332
isDeveloperModeEnabled: Boolean = false,
34-
customElementCallBaseUrl: String? = null,
3533
) = AdvancedSettingsState(
3634
isRichTextEditorEnabled = isRichTextEditorEnabled,
3735
isDeveloperModeEnabled = isDeveloperModeEnabled,
38-
customElementCallBaseUrlState = customElementCallBaseUrl?.let { CustomElementCallBaseUrlState(it, "https://call.element.io") { true } },
3936
eventSink = {}
4037
)

features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/advanced/AdvancedSettingsView.kt

Lines changed: 0 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -16,16 +16,13 @@
1616

1717
package io.element.android.features.preferences.impl.advanced
1818

19-
import androidx.compose.foundation.text.KeyboardOptions
2019
import androidx.compose.runtime.Composable
2120
import androidx.compose.ui.Modifier
2221
import androidx.compose.ui.res.stringResource
23-
import androidx.compose.ui.text.input.KeyboardType
2422
import androidx.compose.ui.tooling.preview.PreviewParameter
2523
import io.element.android.features.preferences.impl.R
2624
import io.element.android.libraries.designsystem.components.preferences.PreferencePage
2725
import io.element.android.libraries.designsystem.components.preferences.PreferenceSwitch
28-
import io.element.android.libraries.designsystem.components.preferences.PreferenceTextField
2926
import io.element.android.libraries.designsystem.preview.ElementPreview
3027
import io.element.android.libraries.designsystem.preview.PreviewsDayNight
3128
import io.element.android.libraries.ui.strings.CommonStrings
@@ -36,11 +33,6 @@ fun AdvancedSettingsView(
3633
onBackPressed: () -> Unit,
3734
modifier: Modifier = Modifier,
3835
) {
39-
fun isUsingDefaultUrl(value: String?): Boolean {
40-
val defaultUrl = state.customElementCallBaseUrlState?.defaultUrl ?: return false
41-
return value.isNullOrEmpty() || value == defaultUrl
42-
}
43-
4436
PreferencePage(
4537
modifier = modifier,
4638
onBackPressed = onBackPressed,
@@ -58,23 +50,6 @@ fun AdvancedSettingsView(
5850
isChecked = state.isDeveloperModeEnabled,
5951
onCheckedChange = { state.eventSink(AdvancedSettingsEvents.SetDeveloperModeEnabled(it)) },
6052
)
61-
state.customElementCallBaseUrlState?.let { callUrlState ->
62-
val supportingText = if (isUsingDefaultUrl(callUrlState.baseUrl)) {
63-
stringResource(R.string.screen_advanced_settings_element_call_base_url_description)
64-
} else {
65-
callUrlState.baseUrl
66-
}
67-
PreferenceTextField(
68-
headline = stringResource(R.string.screen_advanced_settings_element_call_base_url),
69-
value = callUrlState.baseUrl ?: callUrlState.defaultUrl,
70-
supportingText = supportingText,
71-
validation = callUrlState.validator,
72-
onValidationErrorMessage = stringResource(R.string.screen_advanced_settings_element_call_base_url_validation_error),
73-
displayValue = { value -> !isUsingDefaultUrl(value) },
74-
keyboardOptions = KeyboardOptions.Default.copy(autoCorrect = false, keyboardType = KeyboardType.Uri),
75-
onChange = { state.eventSink(AdvancedSettingsEvents.SetCustomElementCallBaseUrl(it)) }
76-
)
77-
}
7853
}
7954
}
8055

features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/developer/DeveloperSettingsEvents.kt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,5 +20,6 @@ import io.element.android.libraries.featureflag.ui.model.FeatureUiModel
2020

2121
sealed interface DeveloperSettingsEvents {
2222
data class UpdateEnabledFeature(val feature: FeatureUiModel, val isEnabled: Boolean) : DeveloperSettingsEvents
23+
data class SetCustomElementCallBaseUrl(val baseUrl: String?) : DeveloperSettingsEvents
2324
data object ClearCache: DeveloperSettingsEvents
2425
}

features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/developer/DeveloperSettingsPresenter.kt

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,12 +19,16 @@ package io.element.android.features.preferences.impl.developer
1919
import androidx.compose.runtime.Composable
2020
import androidx.compose.runtime.LaunchedEffect
2121
import androidx.compose.runtime.MutableState
22+
import androidx.compose.runtime.collectAsState
23+
import androidx.compose.runtime.getValue
2224
import androidx.compose.runtime.key
2325
import androidx.compose.runtime.mutableStateMapOf
2426
import androidx.compose.runtime.mutableStateOf
2527
import androidx.compose.runtime.remember
2628
import androidx.compose.runtime.rememberCoroutineScope
2729
import androidx.compose.runtime.snapshots.SnapshotStateMap
30+
import io.element.android.appconfig.ElementCallConfig
31+
import io.element.android.features.preferences.api.store.PreferencesStore
2832
import io.element.android.features.preferences.impl.tasks.ClearCacheUseCase
2933
import io.element.android.features.preferences.impl.tasks.ComputeCacheSizeUseCase
3034
import io.element.android.features.rageshake.api.preferences.RageshakePreferencesPresenter
@@ -39,13 +43,15 @@ import io.element.android.libraries.featureflag.ui.model.FeatureUiModel
3943
import kotlinx.collections.immutable.toImmutableList
4044
import kotlinx.coroutines.CoroutineScope
4145
import kotlinx.coroutines.launch
46+
import java.net.URL
4247
import javax.inject.Inject
4348

4449
class DeveloperSettingsPresenter @Inject constructor(
4550
private val featureFlagService: FeatureFlagService,
4651
private val computeCacheSizeUseCase: ComputeCacheSizeUseCase,
4752
private val clearCacheUseCase: ClearCacheUseCase,
4853
private val rageshakePresenter: RageshakePreferencesPresenter,
54+
private val preferencesStore: PreferencesStore,
4955
) : Presenter<DeveloperSettingsState> {
5056

5157
@Composable
@@ -64,8 +70,12 @@ class DeveloperSettingsPresenter @Inject constructor(
6470
val clearCacheAction = remember {
6571
mutableStateOf<Async<Unit>>(Async.Uninitialized)
6672
}
73+
val customElementCallBaseUrl by preferencesStore
74+
.getCustomElementCallBaseUrlFlow()
75+
.collectAsState(initial = null)
76+
6777
LaunchedEffect(Unit) {
68-
FeatureFlags.values().forEach { feature ->
78+
FeatureFlags.entries.forEach { feature ->
6979
features[feature.key] = feature
7080
enabledFeatures[feature.key] = featureFlagService.isFeatureEnabled(feature)
7181
}
@@ -86,6 +96,11 @@ class DeveloperSettingsPresenter @Inject constructor(
8696
event.isEnabled,
8797
triggerClearCache = { handleEvents(DeveloperSettingsEvents.ClearCache) }
8898
)
99+
is DeveloperSettingsEvents.SetCustomElementCallBaseUrl -> coroutineScope.launch {
100+
// If the URL is either empty or the default one, we want to save 'null' to remove the custom URL
101+
val urlToSave = event.baseUrl.takeIf { !it.isNullOrEmpty() && it != ElementCallConfig.DEFAULT_BASE_URL }
102+
preferencesStore.setCustomElementCallBaseUrl(urlToSave)
103+
}
89104
DeveloperSettingsEvents.ClearCache -> coroutineScope.clearCache(clearCacheAction)
90105
}
91106
}
@@ -95,6 +110,11 @@ class DeveloperSettingsPresenter @Inject constructor(
95110
cacheSize = cacheSize.value,
96111
clearCacheAction = clearCacheAction.value,
97112
rageshakeState = rageshakeState,
113+
customElementCallBaseUrlState = CustomElementCallBaseUrlState(
114+
baseUrl = customElementCallBaseUrl,
115+
defaultUrl = ElementCallConfig.DEFAULT_BASE_URL,
116+
validator = ::customElementCallUrlValidator,
117+
),
98118
eventSink = ::handleEvents
99119
)
100120
}
@@ -145,5 +165,14 @@ class DeveloperSettingsPresenter @Inject constructor(
145165
}
146166
}
147167

168+
private fun customElementCallUrlValidator(url: String?): Boolean {
169+
return runCatching {
170+
if (url.isNullOrEmpty()) return@runCatching
171+
val parsedUrl = URL(url)
172+
if (parsedUrl.protocol !in listOf("http", "https")) error("Incorrect protocol")
173+
if (parsedUrl.host.isNullOrBlank()) error("Missing host")
174+
}.isSuccess
175+
}
176+
148177

149178

0 commit comments

Comments
 (0)