From af8487b9a3462b65eb21107d79142cb4636a65da Mon Sep 17 00:00:00 2001 From: Mohamad Jaara Date: Mon, 27 Jan 2025 19:53:11 +0100 Subject: [PATCH 01/12] feat: enter to send --- .../wire/android/datastore/GlobalDataStore.kt | 6 ++ .../ui/common/textfield/WireTextField.kt | 20 +++++- .../conversations/MessageComposerViewState.kt | 3 +- .../composer/MessageComposerViewModel.kt | 12 ++++ .../messagecomposer/EnabledMessageComposer.kt | 62 ++++++++++++++++++- .../messagecomposer/MessageComposerInput.kt | 47 +++++++++----- kalium | 2 +- 7 files changed, 133 insertions(+), 19 deletions(-) diff --git a/app/src/main/kotlin/com/wire/android/datastore/GlobalDataStore.kt b/app/src/main/kotlin/com/wire/android/datastore/GlobalDataStore.kt index b9fa7463f57..6b2d23c3a37 100644 --- a/app/src/main/kotlin/com/wire/android/datastore/GlobalDataStore.kt +++ b/app/src/main/kotlin/com/wire/android/datastore/GlobalDataStore.kt @@ -57,6 +57,7 @@ class GlobalDataStore @Inject constructor(@ApplicationContext private val contex booleanPreferencesKey("is_encrypted_proteus_storage_enabled") private val APP_LOCK_PASSCODE = stringPreferencesKey("app_lock_passcode") private val APP_LOCK_SOURCE = intPreferencesKey("app_lock_source") + private val ENTER_TO_SENT = booleanPreferencesKey("enter_to_sent") val APP_THEME_OPTION = stringPreferencesKey("app_theme_option") val RECORD_AUDIO_EFFECTS_CHECKBOX = booleanPreferencesKey("record_audio_effects_checkbox") @@ -244,4 +245,9 @@ class GlobalDataStore @Inject constructor(@ApplicationContext private val contex fun selectedThemeOptionFlow(): Flow = getStringPreference(APP_THEME_OPTION, ThemeOption.SYSTEM.toString()) .map { ThemeOption.valueOf(it) } + + fun enterToSendFlow(): Flow = getBooleanPreference(ENTER_TO_SENT, false) + suspend fun setEnterToSend(enabled: Boolean) { + context.dataStore.edit { it[ENTER_TO_SENT] = enabled } + } } diff --git a/app/src/main/kotlin/com/wire/android/ui/common/textfield/WireTextField.kt b/app/src/main/kotlin/com/wire/android/ui/common/textfield/WireTextField.kt index 0bf843388d9..e50889c5706 100644 --- a/app/src/main/kotlin/com/wire/android/ui/common/textfield/WireTextField.kt +++ b/app/src/main/kotlin/com/wire/android/ui/common/textfield/WireTextField.kt @@ -157,7 +157,7 @@ internal fun WireTextField( textState, onSelectedLineIndexChanged, onLineBottomYCoordinateChanged - ) + ), ) } ) @@ -185,6 +185,24 @@ val KeyboardOptions.Companion.DefaultText: KeyboardOptions capitalization = KeyboardCapitalization.Sentences, ) +@Stable +val KeyboardOptions.Companion.MessageComposerEnterToSend: KeyboardOptions + get() = Default.copy( + keyboardType = KeyboardType.Text, + imeAction = ImeAction.Send, + autoCorrectEnabled = true, + capitalization = KeyboardCapitalization.Sentences, + ) + +@Stable +val KeyboardOptions.Companion.MessageComposerDefault: KeyboardOptions + get() = Default.copy( + keyboardType = KeyboardType.Text, + imeAction = ImeAction.None, + autoCorrectEnabled = true, + capitalization = KeyboardCapitalization.Sentences, + ) + @Stable val KeyboardOptions.Companion.DefaultEmailDone: KeyboardOptions get() = defaultEmail(ImeAction.Done) diff --git a/app/src/main/kotlin/com/wire/android/ui/home/conversations/MessageComposerViewState.kt b/app/src/main/kotlin/com/wire/android/ui/home/conversations/MessageComposerViewState.kt index 44fff2ef166..5e2850a7620 100644 --- a/app/src/main/kotlin/com/wire/android/ui/home/conversations/MessageComposerViewState.kt +++ b/app/src/main/kotlin/com/wire/android/ui/home/conversations/MessageComposerViewState.kt @@ -30,7 +30,8 @@ data class MessageComposerViewState( val isFileSharingEnabled: Boolean = true, val interactionAvailability: InteractionAvailability = InteractionAvailability.ENABLED, val mentionSearchResult: List = listOf(), - val mentionSearchQuery: String = String.EMPTY + val mentionSearchQuery: String = String.EMPTY, + val enterToSend: Boolean = false, ) sealed class AssetTooLargeDialogState { diff --git a/app/src/main/kotlin/com/wire/android/ui/home/conversations/composer/MessageComposerViewModel.kt b/app/src/main/kotlin/com/wire/android/ui/home/conversations/composer/MessageComposerViewModel.kt index 7cd872f01ec..d221c26fc51 100644 --- a/app/src/main/kotlin/com/wire/android/ui/home/conversations/composer/MessageComposerViewModel.kt +++ b/app/src/main/kotlin/com/wire/android/ui/home/conversations/composer/MessageComposerViewModel.kt @@ -24,6 +24,7 @@ import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.setValue import androidx.lifecycle.SavedStateHandle import androidx.lifecycle.viewModelScope +import com.wire.android.datastore.GlobalDataStore import com.wire.android.mapper.ContactMapper import com.wire.android.navigation.SavedStateViewModel import com.wire.android.ui.home.conversations.ConversationNavArgs @@ -56,6 +57,7 @@ import com.wire.kalium.logic.feature.session.CurrentSessionResult import com.wire.kalium.logic.feature.user.IsFileSharingEnabledUseCase import dagger.hilt.android.lifecycle.HiltViewModel import kotlinx.coroutines.flow.collectLatest +import kotlinx.coroutines.flow.first import kotlinx.coroutines.flow.flatMapLatest import kotlinx.coroutines.flow.flowOf import kotlinx.coroutines.flow.mapLatest @@ -80,6 +82,7 @@ class MessageComposerViewModel @Inject constructor( private val fileManager: FileManager, private val kaliumFileSystem: KaliumFileSystem, private val currentSessionFlowUseCase: CurrentSessionFlowUseCase, + private val globalDataStore: GlobalDataStore, ) : SavedStateViewModel(savedStateHandle) { var messageComposerViewState = mutableStateOf(MessageComposerViewState()) @@ -107,6 +110,15 @@ class MessageComposerViewModel @Inject constructor( initTempWritableImageUri() observeIsTypingAvailable() setFileSharingStatus() + getEnterToSendState() + } + + private fun getEnterToSendState() { + viewModelScope.launch(dispatchers.io()) { + globalDataStore.enterToSendFlow().first().also { + messageComposerViewState.value = messageComposerViewState.value.copy(enterToSend = it) + } + } } private fun initTempWritableVideoUri() { diff --git a/app/src/main/kotlin/com/wire/android/ui/home/messagecomposer/EnabledMessageComposer.kt b/app/src/main/kotlin/com/wire/android/ui/home/messagecomposer/EnabledMessageComposer.kt index f1b64a76de9..92ce54316a5 100644 --- a/app/src/main/kotlin/com/wire/android/ui/home/messagecomposer/EnabledMessageComposer.kt +++ b/app/src/main/kotlin/com/wire/android/ui/home/messagecomposer/EnabledMessageComposer.kt @@ -44,9 +44,12 @@ import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.wrapContentHeight import androidx.compose.foundation.layout.wrapContentSize import androidx.compose.foundation.shape.GenericShape +import androidx.compose.foundation.text.KeyboardOptions +import androidx.compose.foundation.text.input.KeyboardActionHandler import androidx.compose.material3.Surface import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect +import androidx.compose.runtime.derivedStateOf import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember @@ -65,6 +68,12 @@ import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.Path import androidx.compose.ui.graphics.drawscope.Fill import androidx.compose.ui.graphics.drawscope.Stroke +import androidx.compose.ui.input.key.Key +import androidx.compose.ui.input.key.KeyEventType +import androidx.compose.ui.input.key.isShiftPressed +import androidx.compose.ui.input.key.key +import androidx.compose.ui.input.key.onPreviewKeyEvent +import androidx.compose.ui.input.key.type import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.platform.LocalDensity import androidx.compose.ui.unit.Density @@ -77,6 +86,8 @@ import com.wire.android.ui.common.banner.SecurityClassificationBannerForConversa import com.wire.android.ui.common.bottombar.bottomNavigationBarHeight import com.wire.android.ui.common.colorsScheme import com.wire.android.ui.common.dimensions +import com.wire.android.ui.common.textfield.MessageComposerDefault +import com.wire.android.ui.common.textfield.MessageComposerEnterToSend import com.wire.android.ui.home.conversations.ConversationActionPermissionType import com.wire.android.ui.home.conversations.UsersTypingIndicatorForConversation import com.wire.android.ui.home.conversations.model.UriAsset @@ -209,10 +220,39 @@ fun EnabledMessageComposer( Box(fillRemainingSpaceOrWrapContent, contentAlignment = Alignment.BottomCenter) { var currentSelectedLineIndex by remember { mutableStateOf(0) } var cursorCoordinateY by remember { mutableStateOf(0F) } + val canSendMessage by remember { + derivedStateOf { + messageCompositionInputStateHolder.inputType is InputType.Composing && + (messageCompositionInputStateHolder.inputType as InputType.Composing).isSendButtonEnabled + } + } + val keyboardOptions by remember { + derivedStateOf { + if (messageComposerStateHolder.messageComposerViewState.value.enterToSend) { + KeyboardOptions.Companion.MessageComposerEnterToSend + } else { + KeyboardOptions.Companion.MessageComposerDefault + } + } + } + val keyboardActionHandler by remember { + derivedStateOf { + KeyboardActionHandler { + if (canSendMessage) { + onSendButtonClicked() + } else { + Unit + } + } + } + } ActiveMessageComposerInput( conversationId = conversationId, messageComposition = messageComposition.value, + keyboardOptions = keyboardOptions, + onKeyboardAction = keyboardActionHandler, + canSendMessage = canSendMessage, messageTextState = inputStateHolder.messageTextState, isTextExpanded = inputStateHolder.isTextExpanded, inputType = messageCompositionInputStateHolder.inputType, @@ -270,7 +310,27 @@ fun EnabledMessageComposer( transferableContent } } - ), + ) + .onPreviewKeyEvent { keyEvent -> + if (keyEvent.type != KeyEventType.KeyDown) { + return@onPreviewKeyEvent false + } + if (keyEvent.isShiftPressed && keyEvent.key == Key.Enter) { + messageComposerStateHolder.messageCompositionInputStateHolder.messageTextState.edit { + append("\n") + } + true + } else if (keyEvent.key == Key.Enter) { + if (canSendMessage) { + onSendButtonClicked() + } else { + Unit + } + true + } else { + false + } + }, ) val mentionSearchResult = messageComposerViewState.value.mentionSearchResult diff --git a/app/src/main/kotlin/com/wire/android/ui/home/messagecomposer/MessageComposerInput.kt b/app/src/main/kotlin/com/wire/android/ui/home/messagecomposer/MessageComposerInput.kt index 9eeed0f3439..db8e7aaa575 100644 --- a/app/src/main/kotlin/com/wire/android/ui/home/messagecomposer/MessageComposerInput.kt +++ b/app/src/main/kotlin/com/wire/android/ui/home/messagecomposer/MessageComposerInput.kt @@ -30,6 +30,8 @@ import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.size import androidx.compose.foundation.layout.wrapContentHeight import androidx.compose.foundation.text.KeyboardOptions +import androidx.compose.foundation.text.input.KeyboardActionHandler +import androidx.compose.foundation.text.input.TextFieldLineLimits import androidx.compose.foundation.text.input.TextFieldState import androidx.compose.material3.HorizontalDivider import androidx.compose.material3.Icon @@ -51,7 +53,6 @@ import androidx.compose.ui.input.key.nativeKeyCode import androidx.compose.ui.input.key.onPreInterceptKeyBeforeSoftKeyboard import androidx.compose.ui.res.painterResource import androidx.compose.ui.res.stringResource -import androidx.compose.ui.text.input.ImeAction import androidx.compose.ui.unit.dp import androidx.constraintlayout.compose.ConstraintLayout import androidx.constraintlayout.compose.Dimension @@ -61,7 +62,7 @@ import com.wire.android.di.hiltViewModelScoped import com.wire.android.ui.common.colorsScheme import com.wire.android.ui.common.dimensions import com.wire.android.ui.common.spacers.VerticalSpace -import com.wire.android.ui.common.textfield.DefaultText +import com.wire.android.ui.common.textfield.MessageComposerDefault import com.wire.android.ui.common.textfield.WireTextField import com.wire.android.ui.common.textfield.WireTextFieldColors import com.wire.android.ui.common.textfield.WireTextFieldState @@ -88,6 +89,9 @@ fun ActiveMessageComposerInput( isTextExpanded: Boolean, inputType: InputType, focusRequester: FocusRequester, + keyboardOptions: KeyboardOptions, + onKeyboardAction: KeyboardActionHandler?, + canSendMessage: Boolean, onSendButtonClicked: () -> Unit, onEditButtonClicked: () -> Unit, onChangeSelfDeletionClicked: (currentlySelected: SelfDeletionTimer) -> Unit, @@ -101,7 +105,7 @@ fun ActiveMessageComposerInput( showOptions: Boolean, optionsSelected: Boolean, onPlusClick: () -> Unit, - modifier: Modifier = Modifier + modifier: Modifier = Modifier, ) { Column( modifier = modifier @@ -132,6 +136,9 @@ fun ActiveMessageComposerInput( inputType = inputType, focusRequester = focusRequester, onSendButtonClicked = onSendButtonClicked, + keyboardOptions = keyboardOptions, + onKeyboardAction = onKeyboardAction, + canSendMessage = canSendMessage, onChangeSelfDeletionClicked = onChangeSelfDeletionClicked, onFocused = onFocused, onSelectedLineIndexChanged = onSelectedLineIndexChanged, @@ -168,6 +175,9 @@ private fun InputContent( isTextExpanded: Boolean, inputType: InputType, focusRequester: FocusRequester, + keyboardOptions: KeyboardOptions, + onKeyboardAction: KeyboardActionHandler?, + canSendMessage: Boolean, onSendButtonClicked: () -> Unit, onChangeSelfDeletionClicked: (currentlySelected: SelfDeletionTimer) -> Unit, onFocused: () -> Unit, @@ -214,6 +224,8 @@ private fun InputContent( onSelectedLineIndexChanged = onSelectedLineIndexChanged, onLineBottomYCoordinateChanged = onLineBottomYCoordinateChanged, onTextCollapse = onTextCollapse, + keyboardOptions = keyboardOptions, + onKeyBoardAction = onKeyboardAction, modifier = Modifier .fillMaxWidth() .constrainAs(input) { @@ -246,15 +258,13 @@ private fun InputContent( UsersTypingIndicatorForConversation(conversationId = conversationId) } } - if (inputType is InputType.Composing && (showOptions || inputType.isSendButtonEnabled)) { - MessageSendActions( - onSendButtonClicked = onSendButtonClicked, - sendButtonEnabled = inputType.isSendButtonEnabled, - selfDeletionTimer = viewModel.state(), - onChangeSelfDeletionClicked = onChangeSelfDeletionClicked, - modifier = Modifier.padding(end = dimensions().spacing8x) - ) - } + MessageSendActions( + onSendButtonClicked = onSendButtonClicked, + sendButtonEnabled = canSendMessage, + selfDeletionTimer = viewModel.state(), + onChangeSelfDeletionClicked = onChangeSelfDeletionClicked, + modifier = Modifier.padding(end = dimensions().spacing8x) + ) } } } @@ -269,9 +279,11 @@ private fun MessageComposerTextInput( placeHolderText: String, onTextCollapse: () -> Unit, onFocused: () -> Unit, + keyboardOptions: KeyboardOptions, + onKeyBoardAction: KeyboardActionHandler?, modifier: Modifier = Modifier, onSelectedLineIndexChanged: (Int) -> Unit = { }, - onLineBottomYCoordinateChanged: (Float) -> Unit = { } + onLineBottomYCoordinateChanged: (Float) -> Unit = { }, ) { val interactionSource = remember { MutableInteractionSource() } val isPressed by interactionSource.collectIsPressedAsState() @@ -289,7 +301,8 @@ private fun MessageComposerTextInput( // Add an extra space so that the cursor is placed one space before "Type a message" placeholderText = " $placeHolderText", state = WireTextFieldState.Default, - keyboardOptions = KeyboardOptions.DefaultText.copy(imeAction = ImeAction.None), + keyboardOptions = keyboardOptions, + onKeyboardAction = onKeyBoardAction, modifier = modifier .focusable(true) .focusRequester(focusRequester) @@ -312,7 +325,8 @@ private fun MessageComposerTextInput( }, interactionSource = interactionSource, onSelectedLineIndexChanged = onSelectedLineIndexChanged, - onLineBottomYCoordinateChanged = onLineBottomYCoordinateChanged + onLineBottomYCoordinateChanged = onLineBottomYCoordinateChanged, + lineLimits = TextFieldLineLimits.MultiLine() ) } @@ -354,6 +368,9 @@ private fun PreviewActiveMessageComposerInput(inputType: InputType, isTextExpand messageTextState = TextFieldState(""), isTextExpanded = isTextExpanded, inputType = inputType, + keyboardOptions = KeyboardOptions.Companion.MessageComposerDefault, + onKeyboardAction = null, + canSendMessage = true, focusRequester = FocusRequester(), onSendButtonClicked = {}, onEditButtonClicked = {}, diff --git a/kalium b/kalium index 7456f22fa05..70bb4ca7b8f 160000 --- a/kalium +++ b/kalium @@ -1 +1 @@ -Subproject commit 7456f22fa052bda1988aaea526109e229c52b458 +Subproject commit 70bb4ca7b8f7d5a5eae20665ea84ff819adbb032 From b43c002538d1236a3f933782806b0025a591b65f Mon Sep 17 00:00:00 2001 From: Mohamad Jaara Date: Mon, 27 Jan 2025 20:00:12 +0100 Subject: [PATCH 02/12] kalium --- kalium | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kalium b/kalium index eb886e214a1..e21b0a87e27 160000 --- a/kalium +++ b/kalium @@ -1 +1 @@ -Subproject commit eb886e214a1346a65f65ade4f5163fb560793284 +Subproject commit e21b0a87e2763187d2773652b0cb3992b45e7bc2 From 4b8c395d29321ad964125b63759177ac18080a8c Mon Sep 17 00:00:00 2001 From: Mohamad Jaara Date: Mon, 27 Jan 2025 22:19:49 +0100 Subject: [PATCH 03/12] detekt --- .../android/ui/home/messagecomposer/MessageComposerInput.kt | 1 - .../composer/MessageComposerViewModelArrangement.kt | 6 ++++++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/app/src/main/kotlin/com/wire/android/ui/home/messagecomposer/MessageComposerInput.kt b/app/src/main/kotlin/com/wire/android/ui/home/messagecomposer/MessageComposerInput.kt index e31f6e058a8..078894c21e4 100644 --- a/app/src/main/kotlin/com/wire/android/ui/home/messagecomposer/MessageComposerInput.kt +++ b/app/src/main/kotlin/com/wire/android/ui/home/messagecomposer/MessageComposerInput.kt @@ -32,7 +32,6 @@ import androidx.compose.foundation.layout.wrapContentHeight import androidx.compose.foundation.text.KeyboardOptions import androidx.compose.foundation.text.input.TextFieldLineLimits import androidx.compose.foundation.text.input.KeyboardActionHandler -import androidx.compose.foundation.text.input.TextFieldLineLimits import androidx.compose.foundation.text.input.TextFieldState import androidx.compose.material3.HorizontalDivider import androidx.compose.material3.Icon diff --git a/app/src/test/kotlin/com/wire/android/ui/home/conversations/composer/MessageComposerViewModelArrangement.kt b/app/src/test/kotlin/com/wire/android/ui/home/conversations/composer/MessageComposerViewModelArrangement.kt index c3d49835c84..d13a5151eb5 100644 --- a/app/src/test/kotlin/com/wire/android/ui/home/conversations/composer/MessageComposerViewModelArrangement.kt +++ b/app/src/test/kotlin/com/wire/android/ui/home/conversations/composer/MessageComposerViewModelArrangement.kt @@ -22,6 +22,7 @@ import android.net.Uri import androidx.lifecycle.SavedStateHandle import com.wire.android.config.TestDispatcherProvider import com.wire.android.config.mockUri +import com.wire.android.datastore.GlobalDataStore import com.wire.android.framework.FakeKaliumFileSystem import com.wire.android.framework.TestConversation import com.wire.android.framework.TestUser @@ -97,6 +98,7 @@ internal class MessageComposerViewModelArrangement { coEvery { currentSessionFlowUseCase() } returns flowOf(CurrentSessionResult.Success(AccountInfo.Valid(TestUser.USER_ID))) + coEvery { globalDataStore.enterToSendFlow() } returns flowOf(false) } @MockK @@ -144,6 +146,9 @@ internal class MessageComposerViewModelArrangement { @MockK lateinit var currentSessionFlowUseCase: CurrentSessionFlowUseCase + @MockK + lateinit var globalDataStore: GlobalDataStore + private val fakeKaliumFileSystem = FakeKaliumFileSystem() private val viewModel by lazy { @@ -162,6 +167,7 @@ internal class MessageComposerViewModelArrangement { kaliumFileSystem = fakeKaliumFileSystem, fileManager = fileManager, currentSessionFlowUseCase = currentSessionFlowUseCase, + globalDataStore = globalDataStore, ) } From 01d8e190555dc0a95fb76c3575dc5570cad98a3a Mon Sep 17 00:00:00 2001 From: Mohamad Jaara Date: Tue, 28 Jan 2025 15:32:07 +0100 Subject: [PATCH 04/12] feat: add ui for press enter to send --- .../android/ui/common/WireLabelledCheckbox.kt | 2 +- ...aranceScreen.kt => CustomizationScreen.kt} | 45 +++++++++++++++---- ...pearanceState.kt => CustomizationState.kt} | 3 +- ...ViewModel.kt => CustomizationViewModel.kt} | 15 ++++++- app/src/main/res/values/strings.xml | 2 + ...lTest.kt => CustomizationViewModelTest.kt} | 4 +- 6 files changed, 57 insertions(+), 14 deletions(-) rename app/src/main/kotlin/com/wire/android/ui/home/settings/appearance/{AppearanceScreen.kt => CustomizationScreen.kt} (84%) rename app/src/main/kotlin/com/wire/android/ui/home/settings/appearance/{AppearanceState.kt => CustomizationState.kt} (91%) rename app/src/main/kotlin/com/wire/android/ui/home/settings/appearance/{AppearanceViewModel.kt => CustomizationViewModel.kt} (79%) rename app/src/test/kotlin/com/wire/android/ui/home/settings/appearance/{AppearanceViewModelTest.kt => CustomizationViewModelTest.kt} (94%) diff --git a/app/src/main/kotlin/com/wire/android/ui/common/WireLabelledCheckbox.kt b/app/src/main/kotlin/com/wire/android/ui/common/WireLabelledCheckbox.kt index 4576a436043..a33f8336b0d 100644 --- a/app/src/main/kotlin/com/wire/android/ui/common/WireLabelledCheckbox.kt +++ b/app/src/main/kotlin/com/wire/android/ui/common/WireLabelledCheckbox.kt @@ -90,8 +90,8 @@ fun WireLabelledCheckbox( fun WireCheckbox( checked: Boolean, onCheckedChange: ((Boolean) -> Unit)?, - enabled: Boolean = true, modifier: Modifier = Modifier, + enabled: Boolean = true ) { Checkbox( checked = checked, diff --git a/app/src/main/kotlin/com/wire/android/ui/home/settings/appearance/AppearanceScreen.kt b/app/src/main/kotlin/com/wire/android/ui/home/settings/appearance/CustomizationScreen.kt similarity index 84% rename from app/src/main/kotlin/com/wire/android/ui/home/settings/appearance/AppearanceScreen.kt rename to app/src/main/kotlin/com/wire/android/ui/home/settings/appearance/CustomizationScreen.kt index 8c818bf3c8d..e89a2ad8058 100644 --- a/app/src/main/kotlin/com/wire/android/ui/home/settings/appearance/AppearanceScreen.kt +++ b/app/src/main/kotlin/com/wire/android/ui/home/settings/appearance/CustomizationScreen.kt @@ -48,6 +48,9 @@ import com.wire.android.ui.common.dimensions import com.wire.android.ui.common.scaffold.WireScaffold import com.wire.android.ui.common.selectableBackground import com.wire.android.ui.common.topappbar.WireCenterAlignedTopAppBar +import com.wire.android.ui.home.conversationslist.common.FolderHeader +import com.wire.android.ui.home.settings.SettingsItem +import com.wire.android.ui.home.settings.SwitchState import com.wire.android.ui.theme.ThemeData import com.wire.android.ui.theme.ThemeOption import com.wire.android.ui.theme.wireColorScheme @@ -58,24 +61,26 @@ import com.wire.android.util.ui.PreviewMultipleThemes @RootNavGraph @WireDestination @Composable -fun AppearanceScreen( +fun CustomizationScreen( navigator: Navigator, - viewModel: AppearanceViewModel = hiltViewModel() + viewModel: CustomizationViewModel = hiltViewModel() ) { val lazyListState: LazyListState = rememberLazyListState() - AppearanceScreenContent( + CustomizationScreenContent( lazyListState = lazyListState, state = viewModel.state, onThemeOptionChanged = viewModel::selectThemeOption, - onBackPressed = navigator::navigateBack + onBackPressed = navigator::navigateBack, + onEnterToSendClicked = TODO(), ) } @Composable -fun AppearanceScreenContent( - state: AppearanceState, +fun CustomizationScreenContent( + state: CustomizationState, onThemeOptionChanged: (ThemeOption) -> Unit, onBackPressed: () -> Unit, + onEnterToSendClicked: () -> Unit, modifier: Modifier = Modifier, lazyListState: LazyListState = rememberLazyListState() ) { @@ -105,10 +110,34 @@ fun AppearanceScreenContent( }, onItemClicked = onThemeOptionChanged ) + item { + CustomizationOptionsContent( + + ) + } + } } } +@Composable +fun CustomizationOptionsContent( + enterToSendState: Boolean, + enterToSendClicked: (Boolean) -> Unit, + modifier: Modifier = Modifier, +) { + FolderHeader("Options") + SettingsItem( + title = stringResource(R.string.press_enter_to_send_title), + text = stringResource(R.string.press_enter_to_send_text), + switchState = SwitchState.Enabled( + isOnOffVisible = true, + value = enterToSendState, + onCheckedChange = enterToSendClicked + ) + ) +} + private fun LazyListScope.folderWithElements( header: String, items: List, @@ -167,8 +196,8 @@ fun ThemeOptionItem( @PreviewMultipleThemes @Composable fun PreviewSettingsScreen() { - AppearanceScreenContent( - AppearanceState(), + CustomizationScreenContent( + CustomizationState(), {}, {}, ) diff --git a/app/src/main/kotlin/com/wire/android/ui/home/settings/appearance/AppearanceState.kt b/app/src/main/kotlin/com/wire/android/ui/home/settings/appearance/CustomizationState.kt similarity index 91% rename from app/src/main/kotlin/com/wire/android/ui/home/settings/appearance/AppearanceState.kt rename to app/src/main/kotlin/com/wire/android/ui/home/settings/appearance/CustomizationState.kt index 2c5be7a8415..21df95bc4b0 100644 --- a/app/src/main/kotlin/com/wire/android/ui/home/settings/appearance/AppearanceState.kt +++ b/app/src/main/kotlin/com/wire/android/ui/home/settings/appearance/CustomizationState.kt @@ -19,6 +19,7 @@ package com.wire.android.ui.home.settings.appearance import com.wire.android.ui.theme.ThemeOption -data class AppearanceState( +data class CustomizationState( val selectedThemeOption: ThemeOption = ThemeOption.SYSTEM, + val pressEnterToSentState: Boolean = false, ) diff --git a/app/src/main/kotlin/com/wire/android/ui/home/settings/appearance/AppearanceViewModel.kt b/app/src/main/kotlin/com/wire/android/ui/home/settings/appearance/CustomizationViewModel.kt similarity index 79% rename from app/src/main/kotlin/com/wire/android/ui/home/settings/appearance/AppearanceViewModel.kt rename to app/src/main/kotlin/com/wire/android/ui/home/settings/appearance/CustomizationViewModel.kt index 4ca0993902f..223280d358e 100644 --- a/app/src/main/kotlin/com/wire/android/ui/home/settings/appearance/AppearanceViewModel.kt +++ b/app/src/main/kotlin/com/wire/android/ui/home/settings/appearance/CustomizationViewModel.kt @@ -30,13 +30,24 @@ import kotlinx.coroutines.launch import javax.inject.Inject @HiltViewModel -class AppearanceViewModel @Inject constructor( +class CustomizationViewModel @Inject constructor( private val globalDataStore: GlobalDataStore, ) : ViewModel() { - var state by mutableStateOf(AppearanceState()) + var state by mutableStateOf(CustomizationState()) private set init { + observeThemeState() + observePressEnterToSendState() + } + + private fun observePressEnterToSendState() { + viewModelScope.launch { + globalDataStore.enterToSendFlow().collect { state = state.copy(pressEnterToSentState = it) } + } + } + + private fun observeThemeState() { viewModelScope.launch { globalDataStore.selectedThemeOptionFlow().collect { option -> state = state.copy(selectedThemeOption = option) } } diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index ff56f4feeaa..ae4175802de 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -1695,5 +1695,7 @@ In group conversations, the group admin can overwrite this setting. Please enter folder name. Minimum of 1 and maximum of 64 characters “%1$s” folder could not be added + Press Enter to send + If this is on, messages can be sent with the Enter key on the Keyboard diff --git a/app/src/test/kotlin/com/wire/android/ui/home/settings/appearance/AppearanceViewModelTest.kt b/app/src/test/kotlin/com/wire/android/ui/home/settings/appearance/CustomizationViewModelTest.kt similarity index 94% rename from app/src/test/kotlin/com/wire/android/ui/home/settings/appearance/AppearanceViewModelTest.kt rename to app/src/test/kotlin/com/wire/android/ui/home/settings/appearance/CustomizationViewModelTest.kt index 3c1f8626e98..fdc5dc8748d 100644 --- a/app/src/test/kotlin/com/wire/android/ui/home/settings/appearance/AppearanceViewModelTest.kt +++ b/app/src/test/kotlin/com/wire/android/ui/home/settings/appearance/CustomizationViewModelTest.kt @@ -31,7 +31,7 @@ import org.junit.jupiter.api.Test import org.junit.jupiter.api.extension.ExtendWith @ExtendWith(CoroutineTestExtension::class) -class AppearanceViewModelTest { +class CustomizationViewModelTest { @Test fun `given theme option, when changing it, then should update global data store`() = runTest { @@ -53,7 +53,7 @@ class AppearanceViewModelTest { every { globalDataStore.selectedThemeOptionFlow() } returns flowOf(ThemeOption.DARK) } - private val viewModel = AppearanceViewModel(globalDataStore) + private val viewModel = CustomizationViewModel(globalDataStore) fun arrange() = this to viewModel } From 35042f44631a411b9bea5d46e7577cedf7f5691c Mon Sep 17 00:00:00 2001 From: Mohamad Jaara Date: Tue, 28 Jan 2025 18:03:12 +0100 Subject: [PATCH 05/12] add enter to send to the settings screen --- .../composer/MessageComposerViewModel.kt | 3 +- .../messagecomposer/EnabledMessageComposer.kt | 3 +- .../android/ui/home/settings/SettingsItem.kt | 10 +++--- .../ui/home/settings/SettingsScreen.kt | 2 +- .../appearance/CustomizationScreen.kt | 33 +++++++++++-------- .../appearance/CustomizationViewModel.kt | 6 ++++ app/src/main/res/values-de/strings.xml | 1 - app/src/main/res/values-hu/strings.xml | 1 - app/src/main/res/values-it/strings.xml | 1 - app/src/main/res/values-ru/strings.xml | 1 - app/src/main/res/values-si/strings.xml | 1 - app/src/main/res/values-sv/strings.xml | 1 - app/src/main/res/values/strings.xml | 4 +-- 13 files changed, 38 insertions(+), 29 deletions(-) diff --git a/app/src/main/kotlin/com/wire/android/ui/home/conversations/composer/MessageComposerViewModel.kt b/app/src/main/kotlin/com/wire/android/ui/home/conversations/composer/MessageComposerViewModel.kt index d221c26fc51..f60ab59935e 100644 --- a/app/src/main/kotlin/com/wire/android/ui/home/conversations/composer/MessageComposerViewModel.kt +++ b/app/src/main/kotlin/com/wire/android/ui/home/conversations/composer/MessageComposerViewModel.kt @@ -24,6 +24,7 @@ import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.setValue import androidx.lifecycle.SavedStateHandle import androidx.lifecycle.viewModelScope +import com.wire.android.appLogger import com.wire.android.datastore.GlobalDataStore import com.wire.android.mapper.ContactMapper import com.wire.android.navigation.SavedStateViewModel @@ -114,7 +115,7 @@ class MessageComposerViewModel @Inject constructor( } private fun getEnterToSendState() { - viewModelScope.launch(dispatchers.io()) { + viewModelScope.launch { globalDataStore.enterToSendFlow().first().also { messageComposerViewState.value = messageComposerViewState.value.copy(enterToSend = it) } diff --git a/app/src/main/kotlin/com/wire/android/ui/home/messagecomposer/EnabledMessageComposer.kt b/app/src/main/kotlin/com/wire/android/ui/home/messagecomposer/EnabledMessageComposer.kt index 92ce54316a5..63783995160 100644 --- a/app/src/main/kotlin/com/wire/android/ui/home/messagecomposer/EnabledMessageComposer.kt +++ b/app/src/main/kotlin/com/wire/android/ui/home/messagecomposer/EnabledMessageComposer.kt @@ -228,13 +228,14 @@ fun EnabledMessageComposer( } val keyboardOptions by remember { derivedStateOf { - if (messageComposerStateHolder.messageComposerViewState.value.enterToSend) { + if (messageComposerViewState.value.enterToSend) { KeyboardOptions.Companion.MessageComposerEnterToSend } else { KeyboardOptions.Companion.MessageComposerDefault } } } + val keyboardActionHandler by remember { derivedStateOf { KeyboardActionHandler { diff --git a/app/src/main/kotlin/com/wire/android/ui/home/settings/SettingsItem.kt b/app/src/main/kotlin/com/wire/android/ui/home/settings/SettingsItem.kt index d90df2654e4..eadf9709828 100644 --- a/app/src/main/kotlin/com/wire/android/ui/home/settings/SettingsItem.kt +++ b/app/src/main/kotlin/com/wire/android/ui/home/settings/SettingsItem.kt @@ -46,7 +46,7 @@ import com.wire.android.ui.common.clickable import com.wire.android.ui.common.dimensions import com.wire.android.ui.destinations.AboutThisAppScreenDestination import com.wire.android.ui.destinations.AppSettingsScreenDestination -import com.wire.android.ui.destinations.AppearanceScreenDestination +import com.wire.android.ui.destinations.CustomizationScreenDestination import com.wire.android.ui.destinations.BackupAndRestoreScreenDestination import com.wire.android.ui.destinations.DebugScreenDestination import com.wire.android.ui.destinations.DependenciesScreenDestination @@ -157,10 +157,10 @@ sealed class SettingsItem(open val id: String, open val title: UIText) { direction = MyAccountScreenDestination ) - data object Appearance : DirectionItem( - id = "appearance_settings", - title = UIText.StringResource(R.string.settings_appearance_label), - direction = AppearanceScreenDestination + data object Customization : DirectionItem( + id = "customization_settings", + title = UIText.StringResource(R.string.settings_customization_label), + direction = CustomizationScreenDestination ) data object NetworkSettings : DirectionItem( diff --git a/app/src/main/kotlin/com/wire/android/ui/home/settings/SettingsScreen.kt b/app/src/main/kotlin/com/wire/android/ui/home/settings/SettingsScreen.kt index 10afe2caad6..203b617728a 100644 --- a/app/src/main/kotlin/com/wire/android/ui/home/settings/SettingsScreen.kt +++ b/app/src/main/kotlin/com/wire/android/ui/home/settings/SettingsScreen.kt @@ -98,7 +98,6 @@ fun SettingsScreenContent( header = context.getString(R.string.settings_account_settings_label), items = buildList { add(SettingsItem.YourAccount) - add(SettingsItem.Appearance) add(SettingsItem.PrivacySettings) add(SettingsItem.ManageDevices) if (BackUpSettings) { @@ -117,6 +116,7 @@ fun SettingsScreenContent( folderWithElements( header = context.getString(R.string.app_settings_screen_title), items = buildList { + add(SettingsItem.Customization) if (AppSettings) { add(SettingsItem.AppSettings) } diff --git a/app/src/main/kotlin/com/wire/android/ui/home/settings/appearance/CustomizationScreen.kt b/app/src/main/kotlin/com/wire/android/ui/home/settings/appearance/CustomizationScreen.kt index e89a2ad8058..a53e7cc6eec 100644 --- a/app/src/main/kotlin/com/wire/android/ui/home/settings/appearance/CustomizationScreen.kt +++ b/app/src/main/kotlin/com/wire/android/ui/home/settings/appearance/CustomizationScreen.kt @@ -19,6 +19,7 @@ package com.wire.android.ui.home.settings.appearance import androidx.compose.foundation.background +import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxWidth @@ -48,6 +49,8 @@ import com.wire.android.ui.common.dimensions import com.wire.android.ui.common.scaffold.WireScaffold import com.wire.android.ui.common.selectableBackground import com.wire.android.ui.common.topappbar.WireCenterAlignedTopAppBar +import com.wire.android.ui.home.conversations.details.options.ArrowType +import com.wire.android.ui.home.conversations.details.options.GroupConversationOptionsItem import com.wire.android.ui.home.conversationslist.common.FolderHeader import com.wire.android.ui.home.settings.SettingsItem import com.wire.android.ui.home.settings.SwitchState @@ -71,7 +74,7 @@ fun CustomizationScreen( state = viewModel.state, onThemeOptionChanged = viewModel::selectThemeOption, onBackPressed = navigator::navigateBack, - onEnterToSendClicked = TODO(), + onEnterToSendClicked = viewModel::selectPressEnterToSendOption, ) } @@ -80,7 +83,7 @@ fun CustomizationScreenContent( state: CustomizationState, onThemeOptionChanged: (ThemeOption) -> Unit, onBackPressed: () -> Unit, - onEnterToSendClicked: () -> Unit, + onEnterToSendClicked: (Boolean) -> Unit, modifier: Modifier = Modifier, lazyListState: LazyListState = rememberLazyListState() ) { @@ -91,7 +94,7 @@ fun CustomizationScreenContent( WireCenterAlignedTopAppBar( onNavigationPressed = onBackPressed, elevation = 0.dp, - title = stringResource(id = R.string.settings_appearance_label) + title = stringResource(id = R.string.settings_customization_label) ) } ) { internalPadding -> @@ -112,7 +115,8 @@ fun CustomizationScreenContent( ) item { CustomizationOptionsContent( - + enterToSendState = state.pressEnterToSentState, + enterToSendClicked = onEnterToSendClicked ) } @@ -126,16 +130,18 @@ fun CustomizationOptionsContent( enterToSendClicked: (Boolean) -> Unit, modifier: Modifier = Modifier, ) { - FolderHeader("Options") - SettingsItem( - title = stringResource(R.string.press_enter_to_send_title), - text = stringResource(R.string.press_enter_to_send_text), - switchState = SwitchState.Enabled( - isOnOffVisible = true, - value = enterToSendState, - onCheckedChange = enterToSendClicked + Column( + modifier = modifier + .fillMaxWidth() + ) { + FolderHeader("Options") + GroupConversationOptionsItem( + title = stringResource(R.string.press_enter_to_send_title), + switchState = SwitchState.Enabled(value = enterToSendState, onCheckedChange = enterToSendClicked), + arrowType = ArrowType.NONE, + subtitle = stringResource(id = R.string.press_enter_to_send_text) ) - ) + } } private fun LazyListScope.folderWithElements( @@ -200,5 +206,6 @@ fun PreviewSettingsScreen() { CustomizationState(), {}, {}, + {}, ) } diff --git a/app/src/main/kotlin/com/wire/android/ui/home/settings/appearance/CustomizationViewModel.kt b/app/src/main/kotlin/com/wire/android/ui/home/settings/appearance/CustomizationViewModel.kt index 223280d358e..0557bc0a4ae 100644 --- a/app/src/main/kotlin/com/wire/android/ui/home/settings/appearance/CustomizationViewModel.kt +++ b/app/src/main/kotlin/com/wire/android/ui/home/settings/appearance/CustomizationViewModel.kt @@ -53,6 +53,12 @@ class CustomizationViewModel @Inject constructor( } } + fun selectPressEnterToSendOption(option: Boolean) { + viewModelScope.launch { + globalDataStore.setEnterToSend(option) + } + } + fun selectThemeOption(option: ThemeOption) { viewModelScope.launch { globalDataStore.setThemeOption(option) diff --git a/app/src/main/res/values-de/strings.xml b/app/src/main/res/values-de/strings.xml index af4c4053903..0087c4920ef 100644 --- a/app/src/main/res/values-de/strings.xml +++ b/app/src/main/res/values-de/strings.xml @@ -1012,7 +1012,6 @@ Verbessern Sie den Empfang von Benachrichtigungen, indem Sie eine ständige Verbindung zu %1$s aufrechterhalten. Es ersetzt die Benachrichtigungsdienste, wenn die Google-Dienste auf Ihrem Gerät nicht verfügbar sind. Dienst wird ausgeführt - Erscheinungsbild Hintergrund Mit Systemeinstellungen synchronisieren (Standard) diff --git a/app/src/main/res/values-hu/strings.xml b/app/src/main/res/values-hu/strings.xml index 62dc757df88..df30a081969 100644 --- a/app/src/main/res/values-hu/strings.xml +++ b/app/src/main/res/values-hu/strings.xml @@ -1068,7 +1068,6 @@ Javítson az értesítések fogadásán a(z) %1$s szolgáltatáshoz való állandó kapcsolattal. Ez helyettesíti az értesítési szolgáltatásokat, ha a Google-szolgáltatások nem elérhetők az eszközén. szolgáltatás fut - Megjelenés Téma Rendszerbeállítások használata (Alapértelmezett) diff --git a/app/src/main/res/values-it/strings.xml b/app/src/main/res/values-it/strings.xml index 643ac1310fb..97c0cd37f28 100644 --- a/app/src/main/res/values-it/strings.xml +++ b/app/src/main/res/values-it/strings.xml @@ -884,7 +884,6 @@ Rispondendo qui, verrà riagganciata l\'altra chiamata. Migliora la ricezione di notifiche mantenendo una costante connessione a %1$s. Questo servizio sostituirà i servizi di notifica se Google Services non sono disponibili sul tuo dispositivo. il servizio è in esecuzione - Aspetto Tema Sincronizza con le impostazioni di sistema (Predefinito) diff --git a/app/src/main/res/values-ru/strings.xml b/app/src/main/res/values-ru/strings.xml index 1ef56d7ed7e..26bded16404 100644 --- a/app/src/main/res/values-ru/strings.xml +++ b/app/src/main/res/values-ru/strings.xml @@ -1103,7 +1103,6 @@ Позволяет оптимизировать получение уведомлений, поддерживая постоянное соединение с %1$s. Эта опция заменит службу уведомлений, если Google Services недоступны на устройстве. активен - Внешний вид Тема Как в системе (По умолчанию) diff --git a/app/src/main/res/values-si/strings.xml b/app/src/main/res/values-si/strings.xml index c6a7341bf0b..b07e18c2d88 100644 --- a/app/src/main/res/values-si/strings.xml +++ b/app/src/main/res/values-si/strings.xml @@ -895,7 +895,6 @@ %1$s වෙත ස්ථායී සම්බන්ධතාවයක් පවත්වා ගැනීමෙන් දැනුම්දීම් ලැබීම වැඩි දියුණු කරගන්න. ඔබගේ උපාංගයේ ගූගල් සේවා නැති නම් දැනුම්දීමේ සේවා සඳහා විසඳුමක් වේ. සේවාව ධාවනය වෙමින් - පෙනුම තේමාව පද්ධතියේ සැකසුම් සමඟ සමමුහූර්තය (පෙරනිමි) diff --git a/app/src/main/res/values-sv/strings.xml b/app/src/main/res/values-sv/strings.xml index 0c77f7c169b..6b8946f4055 100644 --- a/app/src/main/res/values-sv/strings.xml +++ b/app/src/main/res/values-sv/strings.xml @@ -505,7 +505,6 @@ Nätverksinställningar Hantera dina enheter - Utseende Tema (Standard) Ljust läge diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index ae4175802de..b5b0bb93658 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -1108,7 +1108,7 @@ Improve receiving notifications by keeping a constant connection to %1$s. It will replace notification services if Google Services are not available on your device. service is running - Appearance + Customization Theme Sync with system settings (Default) @@ -1688,7 +1688,7 @@ In group conversations, the group admin can overwrite this setting. “%1$s” was moved to “%2$s” “%1$s” could not be moved “%1$s” was removed from “%2$s” - “%1$s” could not be removed + “%1$s” could no`t be removed FOLDER NAME Create Folder A folder with this name already exists. Please choose another name. From 2b47153b75e03b61c966fa561e9149cb898c2dd7 Mon Sep 17 00:00:00 2001 From: Mohamad Jaara Date: Tue, 28 Jan 2025 18:05:42 +0100 Subject: [PATCH 06/12] detekt --- .../ui/home/conversations/composer/MessageComposerViewModel.kt | 1 - .../android/ui/home/settings/appearance/CustomizationScreen.kt | 2 -- 2 files changed, 3 deletions(-) diff --git a/app/src/main/kotlin/com/wire/android/ui/home/conversations/composer/MessageComposerViewModel.kt b/app/src/main/kotlin/com/wire/android/ui/home/conversations/composer/MessageComposerViewModel.kt index f60ab59935e..60daf40c4c8 100644 --- a/app/src/main/kotlin/com/wire/android/ui/home/conversations/composer/MessageComposerViewModel.kt +++ b/app/src/main/kotlin/com/wire/android/ui/home/conversations/composer/MessageComposerViewModel.kt @@ -24,7 +24,6 @@ import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.setValue import androidx.lifecycle.SavedStateHandle import androidx.lifecycle.viewModelScope -import com.wire.android.appLogger import com.wire.android.datastore.GlobalDataStore import com.wire.android.mapper.ContactMapper import com.wire.android.navigation.SavedStateViewModel diff --git a/app/src/main/kotlin/com/wire/android/ui/home/settings/appearance/CustomizationScreen.kt b/app/src/main/kotlin/com/wire/android/ui/home/settings/appearance/CustomizationScreen.kt index a53e7cc6eec..1f04ed8be59 100644 --- a/app/src/main/kotlin/com/wire/android/ui/home/settings/appearance/CustomizationScreen.kt +++ b/app/src/main/kotlin/com/wire/android/ui/home/settings/appearance/CustomizationScreen.kt @@ -52,7 +52,6 @@ import com.wire.android.ui.common.topappbar.WireCenterAlignedTopAppBar import com.wire.android.ui.home.conversations.details.options.ArrowType import com.wire.android.ui.home.conversations.details.options.GroupConversationOptionsItem import com.wire.android.ui.home.conversationslist.common.FolderHeader -import com.wire.android.ui.home.settings.SettingsItem import com.wire.android.ui.home.settings.SwitchState import com.wire.android.ui.theme.ThemeData import com.wire.android.ui.theme.ThemeOption @@ -119,7 +118,6 @@ fun CustomizationScreenContent( enterToSendClicked = onEnterToSendClicked ) } - } } } From 15ac8c895ed1ce1ed4a391188e91f7ef7a52f6e3 Mon Sep 17 00:00:00 2001 From: Mohamad Jaara Date: Wed, 29 Jan 2025 09:34:27 +0100 Subject: [PATCH 07/12] tests --- .../MessageComposerViewModelArrangement.kt | 5 +++- .../composer/MessageComposerViewModelTest.kt | 25 +++++++++++++++++++ 2 files changed, 29 insertions(+), 1 deletion(-) diff --git a/app/src/test/kotlin/com/wire/android/ui/home/conversations/composer/MessageComposerViewModelArrangement.kt b/app/src/test/kotlin/com/wire/android/ui/home/conversations/composer/MessageComposerViewModelArrangement.kt index d13a5151eb5..db63ce1058c 100644 --- a/app/src/test/kotlin/com/wire/android/ui/home/conversations/composer/MessageComposerViewModelArrangement.kt +++ b/app/src/test/kotlin/com/wire/android/ui/home/conversations/composer/MessageComposerViewModelArrangement.kt @@ -171,7 +171,9 @@ internal class MessageComposerViewModelArrangement { ) } - fun withSuccessfulViewModelInit() = apply { + fun withSuccessfulViewModelInit( + enterToSend: Boolean = false, + ) = apply { coEvery { isFileSharingEnabledUseCase() } returns FileSharingStatus(FileSharingStatus.Value.EnabledAll, null) coEvery { observeOngoingCallsUseCase() } returns emptyFlow() coEvery { observeEstablishedCallsUseCase() } returns emptyFlow() @@ -180,6 +182,7 @@ internal class MessageComposerViewModelArrangement { InteractionAvailability.ENABLED ) ) + coEvery { globalDataStore.enterToSendFlow() } returns flowOf(enterToSend) } fun withSaveDraftMessage() = apply { diff --git a/app/src/test/kotlin/com/wire/android/ui/home/conversations/composer/MessageComposerViewModelTest.kt b/app/src/test/kotlin/com/wire/android/ui/home/conversations/composer/MessageComposerViewModelTest.kt index 8c643a426c4..bd174a62594 100644 --- a/app/src/test/kotlin/com/wire/android/ui/home/conversations/composer/MessageComposerViewModelTest.kt +++ b/app/src/test/kotlin/com/wire/android/ui/home/conversations/composer/MessageComposerViewModelTest.kt @@ -31,6 +31,7 @@ import kotlinx.coroutines.flow.flowOf import kotlinx.coroutines.test.advanceUntilIdle import kotlinx.coroutines.test.runTest import org.amshove.kluent.internal.assertEquals +import org.junit.jupiter.api.Assertions.assertTrue import org.junit.jupiter.api.Test import org.junit.jupiter.api.extension.ExtendWith @@ -94,4 +95,28 @@ class MessageComposerViewModelTest { // then assertEquals(InteractionAvailability.DISABLED, viewModel.messageComposerViewState.value.interactionAvailability) } + + @Test + fun `given enter to send is enabled, when init, then update state`() = runTest { + // given + val (_, viewModel) = MessageComposerViewModelArrangement() + .withSuccessfulViewModelInit(enterToSend = true) + .arrange() + // when + + // then + assertTrue(viewModel.messageComposerViewState.value.enterToSend) + } + + @Test + fun `given enter to send is disabled, when init, then update state`() = runTest { + // given + val (_, viewModel) = MessageComposerViewModelArrangement() + .withSuccessfulViewModelInit(enterToSend = false) + .arrange() + // when + + // then + assertTrue(!viewModel.messageComposerViewState.value.enterToSend) + } } From 63a237403c967169e09d8b5b7c0f35bc40de4fff Mon Sep 17 00:00:00 2001 From: Mohamad Jaara Date: Wed, 5 Feb 2025 11:32:52 +0100 Subject: [PATCH 08/12] pr comment --- app/src/main/res/values/strings.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 0c95b231c38..dab263d79f9 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -1689,7 +1689,7 @@ In group conversations, the group admin can overwrite this setting. “%1$s” was moved to “%2$s” “%1$s” could not be moved “%1$s” was removed from “%2$s” - “%1$s” could no`t be removed + “%1$s” could not be removed FOLDER NAME Create Folder A folder with this name already exists. Please choose another name. From 7a70a5430f2332aa877d3dc9f2729d3af0ccfebd Mon Sep 17 00:00:00 2001 From: Mohamad Jaara Date: Wed, 5 Feb 2025 11:34:32 +0100 Subject: [PATCH 09/12] formating --- .../kotlin/com/wire/android/ui/common/WireLabelledCheckbox.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/main/kotlin/com/wire/android/ui/common/WireLabelledCheckbox.kt b/app/src/main/kotlin/com/wire/android/ui/common/WireLabelledCheckbox.kt index a33f8336b0d..7d4fd19eb47 100644 --- a/app/src/main/kotlin/com/wire/android/ui/common/WireLabelledCheckbox.kt +++ b/app/src/main/kotlin/com/wire/android/ui/common/WireLabelledCheckbox.kt @@ -91,7 +91,7 @@ fun WireCheckbox( checked: Boolean, onCheckedChange: ((Boolean) -> Unit)?, modifier: Modifier = Modifier, - enabled: Boolean = true + enabled: Boolean = true, ) { Checkbox( checked = checked, From 82187187646226aa8d19eb15f40f677fbe9ed7e3 Mon Sep 17 00:00:00 2001 From: Mohamad Jaara Date: Wed, 5 Feb 2025 12:43:50 +0100 Subject: [PATCH 10/12] tests --- ...odelTest.kt => AppearanceViewModelTest.kt} | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) rename app/src/test/kotlin/com/wire/android/ui/home/settings/appearance/{CustomizationViewModelTest.kt => AppearanceViewModelTest.kt} (76%) diff --git a/app/src/test/kotlin/com/wire/android/ui/home/settings/appearance/CustomizationViewModelTest.kt b/app/src/test/kotlin/com/wire/android/ui/home/settings/appearance/AppearanceViewModelTest.kt similarity index 76% rename from app/src/test/kotlin/com/wire/android/ui/home/settings/appearance/CustomizationViewModelTest.kt rename to app/src/test/kotlin/com/wire/android/ui/home/settings/appearance/AppearanceViewModelTest.kt index fdc5dc8748d..c53390e13f7 100644 --- a/app/src/test/kotlin/com/wire/android/ui/home/settings/appearance/CustomizationViewModelTest.kt +++ b/app/src/test/kotlin/com/wire/android/ui/home/settings/appearance/AppearanceViewModelTest.kt @@ -25,17 +25,19 @@ import io.mockk.coEvery import io.mockk.coVerify import io.mockk.every import io.mockk.impl.annotations.MockK +import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.flowOf import kotlinx.coroutines.test.runTest import org.junit.jupiter.api.Test import org.junit.jupiter.api.extension.ExtendWith @ExtendWith(CoroutineTestExtension::class) -class CustomizationViewModelTest { +class AppearanceViewModelTest { @Test fun `given theme option, when changing it, then should update global data store`() = runTest { val (arrangement, viewModel) = Arrangement() + .withEnterToSend(flowOf(false)) .arrange() viewModel.selectThemeOption(ThemeOption.DARK) @@ -43,6 +45,17 @@ class CustomizationViewModelTest { coVerify(exactly = 1) { arrangement.globalDataStore.setThemeOption(ThemeOption.DARK) } } + @Test + fun `given enter to send option, when changing it, then should update global data store`() = runTest { + val (arrangement, viewModel) = Arrangement() + .withEnterToSend(flowOf(true)) + .arrange() + + viewModel.selectPressEnterToSendOption(false) + + coVerify(exactly = 1) { arrangement.globalDataStore.setEnterToSend(false) } + } + private class Arrangement { @MockK lateinit var globalDataStore: GlobalDataStore @@ -53,6 +66,10 @@ class CustomizationViewModelTest { every { globalDataStore.selectedThemeOptionFlow() } returns flowOf(ThemeOption.DARK) } + fun withEnterToSend(result: Flow) = apply { + every { globalDataStore.enterToSendFlow() } returns result + } + private val viewModel = CustomizationViewModel(globalDataStore) fun arrange() = this to viewModel From bb92dd653b466b5920cfa3a1077ee3af2e839c6b Mon Sep 17 00:00:00 2001 From: Mohamad Jaara Date: Wed, 5 Feb 2025 14:35:52 +0100 Subject: [PATCH 11/12] pr comments --- .../android/ui/home/settings/appearance/CustomizationScreen.kt | 2 +- app/src/main/res/values/strings.xml | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/app/src/main/kotlin/com/wire/android/ui/home/settings/appearance/CustomizationScreen.kt b/app/src/main/kotlin/com/wire/android/ui/home/settings/appearance/CustomizationScreen.kt index 1f04ed8be59..8e5a1805e72 100644 --- a/app/src/main/kotlin/com/wire/android/ui/home/settings/appearance/CustomizationScreen.kt +++ b/app/src/main/kotlin/com/wire/android/ui/home/settings/appearance/CustomizationScreen.kt @@ -132,7 +132,7 @@ fun CustomizationOptionsContent( modifier = modifier .fillMaxWidth() ) { - FolderHeader("Options") + FolderHeader(stringResource(R.string.custimization_options_header_title)) GroupConversationOptionsItem( title = stringResource(R.string.press_enter_to_send_title), switchState = SwitchState.Enabled(value = enterToSendState, onCheckedChange = enterToSendClicked), diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index dab263d79f9..943109205a4 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -1698,5 +1698,6 @@ In group conversations, the group admin can overwrite this setting. “%1$s” folder could not be added Press Enter to send If this is on, messages can be sent with the Enter key on the Keyboard + Options From d5711fdd2e352f0fae7bd49542fa5648c50512d8 Mon Sep 17 00:00:00 2001 From: Mohamad Jaara Date: Wed, 5 Feb 2025 15:39:14 +0100 Subject: [PATCH 12/12] test --- .../ui/home/settings/appearance/AppearanceViewModelTest.kt | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/app/src/test/kotlin/com/wire/android/ui/home/settings/appearance/AppearanceViewModelTest.kt b/app/src/test/kotlin/com/wire/android/ui/home/settings/appearance/AppearanceViewModelTest.kt index c53390e13f7..eb2761c3002 100644 --- a/app/src/test/kotlin/com/wire/android/ui/home/settings/appearance/AppearanceViewModelTest.kt +++ b/app/src/test/kotlin/com/wire/android/ui/home/settings/appearance/AppearanceViewModelTest.kt @@ -70,8 +70,6 @@ class AppearanceViewModelTest { every { globalDataStore.enterToSendFlow() } returns result } - private val viewModel = CustomizationViewModel(globalDataStore) - - fun arrange() = this to viewModel + fun arrange() = this to CustomizationViewModel(globalDataStore) } }