Skip to content

Commit 794168d

Browse files
committed
Merge remote-tracking branch 'origin/develop' into fetch-and-display-node-versions
# Conflicts: # features/cells/src/main/java/com/wire/android/feature/cells/ui/CellViewModel.kt # features/cells/src/main/res/values/strings.xml
2 parents 9e3644e + 258515f commit 794168d

File tree

10 files changed

+628
-4
lines changed

10 files changed

+628
-4
lines changed

app/src/main/kotlin/com/wire/android/di/accountScoped/DebugModule.kt

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,4 +77,9 @@ class DebugModule {
7777
@ViewModelScoped
7878
@Provides
7979
fun provideFeatureConfigUseCase(debugScope: DebugScope): GetFeatureConfigUseCase = debugScope.getFeatureConfig
80+
81+
@ViewModelScoped
82+
@Provides
83+
fun provideDebugFeedConversationUseCase(debugScope: DebugScope) =
84+
debugScope.debugFeedConversationUseCase
8085
}

app/src/main/kotlin/com/wire/android/ui/debug/conversation/DebugConversationScreen.kt

Lines changed: 148 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@ import androidx.compose.foundation.layout.Column
2222
import androidx.compose.foundation.layout.fillMaxSize
2323
import androidx.compose.foundation.layout.padding
2424
import androidx.compose.foundation.layout.wrapContentWidth
25+
import androidx.compose.foundation.rememberScrollState
26+
import androidx.compose.foundation.verticalScroll
2527
import androidx.compose.material.Text
2628
import androidx.compose.material3.MaterialTheme
2729
import androidx.compose.runtime.Composable
@@ -30,15 +32,21 @@ import androidx.compose.runtime.getValue
3032
import androidx.compose.ui.Modifier
3133
import androidx.compose.ui.platform.LocalClipboardManager
3234
import androidx.compose.ui.platform.LocalContext
35+
import androidx.compose.ui.res.stringResource
3336
import androidx.compose.ui.text.AnnotatedString
3437
import androidx.hilt.navigation.compose.hiltViewModel
38+
import com.wire.android.BuildConfig
3539
import com.wire.android.R
3640
import com.wire.android.model.Clickable
3741
import com.wire.android.navigation.Navigator
3842
import com.wire.android.navigation.annotation.app.WireDestination
3943
import com.wire.android.ui.common.HandleActions
44+
import com.wire.android.ui.common.WireDialog
45+
import com.wire.android.ui.common.WireDialogButtonProperties
46+
import com.wire.android.ui.common.WireDialogButtonType
4047
import com.wire.android.ui.common.rowitem.RowItemTemplate
4148
import com.wire.android.ui.common.button.WirePrimaryButton
49+
import com.wire.android.ui.common.button.WireSwitch
4250
import com.wire.android.ui.common.dimensions
4351
import com.wire.android.ui.common.scaffold.WireScaffold
4452
import com.wire.android.ui.common.topappbar.NavigationIconType
@@ -62,6 +70,7 @@ fun DebugConversationScreen(
6270
) {
6371

6472
val context = LocalContext.current
73+
val scrollState = rememberScrollState()
6574

6675
WireScaffold(
6776
topBar = {
@@ -86,6 +95,7 @@ fun DebugConversationScreen(
8695
Column(
8796
modifier = modifier
8897
.fillMaxSize()
98+
.verticalScroll(scrollState)
8999
.padding(paddingValues),
90100
) {
91101
SectionHeader("Conversation details")
@@ -102,6 +112,18 @@ fun DebugConversationScreen(
102112
onUpdate = { viewModel.updateConversation() },
103113
onReset = { viewModel.resetMLSConversation() },
104114
)
115+
if (BuildConfig.CONVERSATION_FEEDER_ENABLED) {
116+
SectionHeader("Feeders / performance config")
117+
ConversationFeedConfigView(
118+
config = state.feedConfig,
119+
onMessagesToggle = { enabled -> viewModel.onMessagesFeederToggle(enabled) },
120+
onReactionsToggle = { enabled -> viewModel.onReactionsFeederToggle(enabled) },
121+
onUnreadEventsToggle = { enabled -> viewModel.onUnreadEventsFeederToggle(enabled) },
122+
onMentionsToggle = { enabled -> viewModel.onMentionsFeederToggle(enabled) },
123+
onShowDialog = { show -> viewModel.showFeedersDialog(show) },
124+
onRunFeeders = { viewModel.runFeedersForConversation() }
125+
)
126+
}
105127
}
106128
}
107129
)
@@ -232,6 +254,132 @@ private fun MlsDetailsView(mlsProtocolInfo: Conversation.ProtocolInfo.MLS) {
232254
)
233255
}
234256

257+
@Composable
258+
private fun ConversationFeedConfigView(
259+
config: DebugFeedConfigUiState,
260+
onMessagesToggle: (Boolean) -> Unit,
261+
onReactionsToggle: (Boolean) -> Unit,
262+
onUnreadEventsToggle: (Boolean) -> Unit,
263+
onMentionsToggle: (Boolean) -> Unit,
264+
onShowDialog: (Boolean) -> Unit,
265+
onRunFeeders: () -> Unit,
266+
) {
267+
if (config.showDialog) {
268+
WireDialog(
269+
title = "Warning: Irreversible Debug Operation",
270+
text = "Using feeders will permanently modify this conversation’s data.\n" +
271+
"Synthetic messages, mentions, reactions or unread events cannot be undone.\n" +
272+
"\n" +
273+
"This action is for internal testing only. Do NOT use on real conversations.",
274+
onDismiss = {
275+
onShowDialog(false)
276+
},
277+
optionButton1Properties = WireDialogButtonProperties(
278+
onClick = {
279+
onShowDialog(false)
280+
},
281+
text = stringResource(R.string.label_cancel),
282+
type = WireDialogButtonType.Secondary,
283+
),
284+
optionButton2Properties = WireDialogButtonProperties(
285+
onClick = {
286+
onRunFeeders()
287+
},
288+
text = "Run feeders",
289+
loading = config.isProcessing,
290+
type = WireDialogButtonType.Primary,
291+
)
292+
)
293+
}
294+
295+
RowItemTemplate(
296+
title = {
297+
Text(
298+
text = "Feed messages",
299+
style = MaterialTheme.wireTypography.body01,
300+
color = MaterialTheme.wireColorScheme.onBackground,
301+
modifier = Modifier.padding(start = dimensions().spacing8x)
302+
)
303+
},
304+
actions = {
305+
WireSwitch(
306+
checked = config.messagesEnabled,
307+
onCheckedChange = onMessagesToggle
308+
)
309+
}
310+
)
311+
312+
RowItemTemplate(
313+
title = {
314+
Text(
315+
text = "Feed reactions",
316+
style = MaterialTheme.wireTypography.body01,
317+
color = MaterialTheme.wireColorScheme.onBackground,
318+
modifier = Modifier.padding(start = dimensions().spacing8x)
319+
)
320+
},
321+
actions = {
322+
WireSwitch(
323+
checked = config.reactionsEnabled,
324+
onCheckedChange = onReactionsToggle
325+
)
326+
}
327+
)
328+
329+
RowItemTemplate(
330+
title = {
331+
Text(
332+
text = "Feed unread events",
333+
style = MaterialTheme.wireTypography.body01,
334+
color = MaterialTheme.wireColorScheme.onBackground,
335+
modifier = Modifier.padding(start = dimensions().spacing8x)
336+
)
337+
},
338+
actions = {
339+
WireSwitch(
340+
checked = config.unreadEventsEnabled,
341+
onCheckedChange = onUnreadEventsToggle
342+
)
343+
}
344+
)
345+
346+
RowItemTemplate(
347+
title = {
348+
Text(
349+
text = "Feed mentions",
350+
style = MaterialTheme.wireTypography.body01,
351+
color = MaterialTheme.wireColorScheme.onBackground,
352+
modifier = Modifier.padding(start = dimensions().spacing8x)
353+
)
354+
},
355+
actions = {
356+
WireSwitch(
357+
checked = config.mentionsEnabled,
358+
onCheckedChange = onMentionsToggle
359+
)
360+
}
361+
)
362+
363+
RowItemTemplate(
364+
title = {
365+
Text(
366+
text = "Run selected feeders",
367+
style = MaterialTheme.wireTypography.body01,
368+
color = MaterialTheme.wireColorScheme.onBackground,
369+
modifier = Modifier.padding(start = dimensions().spacing8x)
370+
)
371+
},
372+
actions = {
373+
WirePrimaryButton(
374+
loading = config.isProcessing,
375+
onClick = { onShowDialog(true) },
376+
text = "Run feeders",
377+
fillMaxWidth = false
378+
)
379+
}
380+
)
381+
}
382+
235383
data class DebugConversationScreenNavArgs(
236384
val conversationId: ConversationId,
237385
)

app/src/main/kotlin/com/wire/android/ui/debug/conversation/DebugConversationViewModel.kt

Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,9 @@ import com.wire.kalium.logic.data.conversation.Conversation
2828
import com.wire.kalium.logic.data.conversation.FetchConversationUseCase
2929
import com.wire.kalium.logic.data.conversation.ResetMLSConversationUseCase
3030
import com.wire.kalium.logic.feature.conversation.ObserveConversationDetailsUseCase
31+
import com.wire.kalium.logic.feature.debug.DebugFeedConfig
32+
import com.wire.kalium.logic.feature.debug.DebugFeedConversationUseCase
33+
import com.wire.kalium.logic.feature.debug.DebugFeedResult
3134
import dagger.hilt.android.lifecycle.HiltViewModel
3235
import kotlinx.coroutines.flow.MutableStateFlow
3336
import kotlinx.coroutines.flow.asStateFlow
@@ -40,6 +43,7 @@ class DebugConversationViewModel @Inject constructor(
4043
private val conversationDetails: ObserveConversationDetailsUseCase,
4144
private val resetMLSConversation: ResetMLSConversationUseCase,
4245
private val fetchConversation: FetchConversationUseCase,
46+
private val feedConversation: DebugFeedConversationUseCase,
4347
savedStateHandle: SavedStateHandle,
4448
) : ActionsViewModel<DebugConversationScreenAction>() {
4549

@@ -90,6 +94,95 @@ class DebugConversationViewModel @Inject constructor(
9094
appLogger.e("MLS conversation fetch failed: $error")
9195
}
9296
}
97+
98+
/**
99+
* Toggle: enable/disable messages feeder for this conversation.
100+
*/
101+
fun onMessagesFeederToggle(enabled: Boolean) {
102+
_state.update { current ->
103+
current.copy(
104+
feedConfig = current.feedConfig.copy(messagesEnabled = enabled)
105+
)
106+
}
107+
}
108+
109+
/**
110+
* Toggle: enable/disable reactions feeder for this conversation.
111+
*/
112+
fun onReactionsFeederToggle(enabled: Boolean) {
113+
_state.update { current ->
114+
current.copy(
115+
feedConfig = current.feedConfig.copy(reactionsEnabled = enabled)
116+
)
117+
}
118+
}
119+
120+
/**
121+
* Toggle: enable/disable unread events feeder for this conversation.
122+
*/
123+
fun onUnreadEventsFeederToggle(enabled: Boolean) {
124+
_state.update { current ->
125+
current.copy(
126+
feedConfig = current.feedConfig.copy(unreadEventsEnabled = enabled)
127+
)
128+
}
129+
}
130+
131+
/**
132+
* Toggle: enable/disable mentions feeder for this conversation.
133+
*/
134+
fun onMentionsFeederToggle(enabled: Boolean) {
135+
_state.update { current ->
136+
current.copy(
137+
feedConfig = current.feedConfig.copy(mentionsEnabled = enabled)
138+
)
139+
}
140+
}
141+
142+
fun showFeedersDialog(show: Boolean) {
143+
_state.update { current ->
144+
current.copy(
145+
feedConfig = current.feedConfig.copy(showDialog = show)
146+
)
147+
}
148+
}
149+
150+
/**
151+
* Runs all selected feeders for the current conversation.
152+
*
153+
* This is debug-only: it can generate a lot of local data and should only be
154+
* triggered manually from the debug screen.
155+
*/
156+
fun runFeedersForConversation() = viewModelScope.launch {
157+
val uiConfig = state.value.feedConfig
158+
159+
// Map UI config -> domain config for the use case.
160+
val config = DebugFeedConfig(
161+
messages = uiConfig.messagesEnabled,
162+
reactions = uiConfig.reactionsEnabled,
163+
unreadEvents = uiConfig.unreadEventsEnabled,
164+
mentions = uiConfig.mentionsEnabled,
165+
)
166+
167+
_state.update {
168+
it.copy(feedConfig = it.feedConfig.copy(isProcessing = true))
169+
}
170+
when (val response = feedConversation(conversationId, config)) {
171+
is DebugFeedResult.Failure -> {
172+
_state.update {
173+
it.copy(feedConfig = DebugFeedConfigUiState())
174+
}
175+
sendAction(ShowMessage("Feeders failed: ${response.coreFailure}}"))
176+
}
177+
178+
DebugFeedResult.Success -> {
179+
_state.update {
180+
it.copy(feedConfig = DebugFeedConfigUiState())
181+
}
182+
sendAction(ShowMessage("Feeders executed successfully."))
183+
}
184+
}
185+
}
93186
}
94187

95188
sealed interface DebugConversationScreenAction
@@ -99,4 +192,14 @@ data class DebugConversationViewState(
99192
val conversationName: String? = null,
100193
val teamId: String? = null,
101194
val mlsProtocolInfo: Conversation.ProtocolInfo.MLS? = null,
195+
val feedConfig: DebugFeedConfigUiState = DebugFeedConfigUiState(),
196+
)
197+
198+
data class DebugFeedConfigUiState(
199+
val messagesEnabled: Boolean = false,
200+
val reactionsEnabled: Boolean = false,
201+
val unreadEventsEnabled: Boolean = false,
202+
val mentionsEnabled: Boolean = false,
203+
val isProcessing: Boolean = false,
204+
val showDialog: Boolean = false
102205
)

buildSrc/src/main/kotlin/customization/FeatureConfigs.kt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,7 @@ enum class FeatureConfigs(val value: String, val configType: ConfigType) {
8484

8585
URL_SUPPORT("url_support", ConfigType.STRING),
8686
URL_RSS_RELEASE_NOTES("url_rss_release_notes", ConfigType.STRING),
87+
CONVERSATION_FEEDER_ENABLED("conversation_feeder_enabled", ConfigType.BOOLEAN),
8788

8889
/**
8990
* In runtime, will use these values to determine which backend to use.

default.json

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,8 @@
3535
"enable_new_registration": true,
3636
"channels_history_options_enabled": true,
3737
"meetings_enabled": true,
38-
"use_async_flush_logging" : true,
38+
"use_async_flush_logging": true,
39+
"conversation_feeder_enabled": true,
3940
"secure_public_link_settings": true,
4041
"collabora_integration": true
4142
},
@@ -71,7 +72,7 @@
7172
"analytics_app_key": "8ffae535f1836ed5f58fd5c8a11c00eca07c5438",
7273
"analytics_server_url": "https://wire.count.ly/",
7374
"enable_new_registration": true,
74-
"use_async_flush_logging" : true,
75+
"use_async_flush_logging": true,
7576
"secure_public_link_settings": true
7677
},
7778
"internal": {
@@ -85,7 +86,8 @@
8586
"analytics_server_url": "https://wire.count.ly/",
8687
"enable_new_registration": true,
8788
"use_strict_mls_filter": false,
88-
"use_async_flush_logging" : true,
89+
"use_async_flush_logging": true,
90+
"conversation_feeder_enabled": true,
8991
"background_notification_retry_enabled": true,
9092
"background_notification_stay_alive_seconds": 5,
9193
"secure_public_link_settings": true
@@ -151,7 +153,7 @@
151153
"paginated_conversation_list_enabled": true,
152154
"should_display_release_notes": true,
153155
"public_channels_enabled": false,
154-
"use_async_flush_logging" : false,
156+
"use_async_flush_logging": false,
155157
"channels_history_options_enabled": false,
156158
"use_new_login_for_default_backend": true,
157159
"enable_crossplatform_backup": true,
@@ -160,6 +162,7 @@
160162
"use_strict_mls_filter": false,
161163
"meetings_enabled": false,
162164
"emm_support_enabled": true,
165+
"conversation_feeder_enabled": false,
163166
"background_notification_retry_enabled": false,
164167
"background_notification_stay_alive_seconds": 1,
165168
"is_bubble_ui_enabled": true,

0 commit comments

Comments
 (0)