Merge branch 'develop' into dla/feature/custom_room_notification_settings_list
This commit is contained in:
commit
6fa73963c1
16 changed files with 173 additions and 10 deletions
|
|
@ -65,10 +65,11 @@ import io.element.android.libraries.testtags.testTag
|
|||
import io.element.android.libraries.textcomposer.components.ComposerOptionsButton
|
||||
import io.element.android.libraries.textcomposer.components.DismissTextFormattingButton
|
||||
import io.element.android.libraries.textcomposer.components.RecordButton
|
||||
import io.element.android.libraries.textcomposer.components.VoiceMessagePreview
|
||||
import io.element.android.libraries.textcomposer.components.VoiceMessageRecording
|
||||
import io.element.android.libraries.textcomposer.components.SendButton
|
||||
import io.element.android.libraries.textcomposer.components.TextFormatting
|
||||
import io.element.android.libraries.textcomposer.components.VoiceMessageDeleteButton
|
||||
import io.element.android.libraries.textcomposer.components.VoiceMessagePreview
|
||||
import io.element.android.libraries.textcomposer.components.VoiceMessageRecording
|
||||
import io.element.android.libraries.textcomposer.components.textInputRoundedCornerShape
|
||||
import io.element.android.libraries.textcomposer.model.Message
|
||||
import io.element.android.libraries.textcomposer.model.MessageComposerMode
|
||||
|
|
@ -99,6 +100,7 @@ fun TextComposer(
|
|||
onDismissTextFormatting: () -> Unit = {},
|
||||
onVoiceRecordButtonEvent: (PressEvent) -> Unit = {},
|
||||
onSendVoiceMessage: () -> Unit = {},
|
||||
onDeleteVoiceMessage: () -> Unit = {},
|
||||
onError: (Throwable) -> Unit = {},
|
||||
) {
|
||||
val onSendClicked = {
|
||||
|
|
@ -176,7 +178,7 @@ fun TextComposer(
|
|||
}
|
||||
|
||||
val voiceRecording = @Composable {
|
||||
when(voiceMessageState) {
|
||||
when (voiceMessageState) {
|
||||
VoiceMessageState.Preview ->
|
||||
VoiceMessagePreview(isInteractive = true)
|
||||
VoiceMessageState.Sending ->
|
||||
|
|
@ -187,6 +189,16 @@ fun TextComposer(
|
|||
}
|
||||
}
|
||||
|
||||
val voiceDeleteButton = @Composable {
|
||||
val enabled = when (voiceMessageState) {
|
||||
VoiceMessageState.Preview -> true
|
||||
VoiceMessageState.Sending,
|
||||
is VoiceMessageState.Recording,
|
||||
VoiceMessageState.Idle -> false
|
||||
}
|
||||
VoiceMessageDeleteButton(enabled = enabled, onClick = onDeleteVoiceMessage)
|
||||
}
|
||||
|
||||
if (showTextFormatting) {
|
||||
TextFormattingLayout(
|
||||
modifier = layoutModifier,
|
||||
|
|
@ -206,6 +218,7 @@ fun TextComposer(
|
|||
textInput = textInput,
|
||||
endButton = sendOrRecordButton,
|
||||
voiceRecording = voiceRecording,
|
||||
voiceDeleteButton = voiceDeleteButton,
|
||||
)
|
||||
}
|
||||
|
||||
|
|
@ -225,6 +238,7 @@ private fun StandardLayout(
|
|||
textInput: @Composable () -> Unit,
|
||||
composerOptionsButton: @Composable () -> Unit,
|
||||
voiceRecording: @Composable () -> Unit,
|
||||
voiceDeleteButton: @Composable () -> Unit,
|
||||
endButton: @Composable () -> Unit,
|
||||
modifier: Modifier = Modifier,
|
||||
) {
|
||||
|
|
@ -233,9 +247,21 @@ private fun StandardLayout(
|
|||
verticalAlignment = Alignment.Bottom,
|
||||
) {
|
||||
if (enableVoiceMessages && voiceMessageState !is VoiceMessageState.Idle) {
|
||||
if (voiceMessageState is VoiceMessageState.Preview || voiceMessageState is VoiceMessageState.Sending) {
|
||||
Box(
|
||||
modifier = Modifier
|
||||
.padding(bottom = 5.dp, top = 5.dp, end = 3.dp, start = 3.dp)
|
||||
.size(48.dp.applyScaleUp()),
|
||||
contentAlignment = Alignment.Center,
|
||||
) {
|
||||
voiceDeleteButton()
|
||||
}
|
||||
} else {
|
||||
Spacer(modifier = Modifier.width(16.dp))
|
||||
}
|
||||
Box(
|
||||
modifier = Modifier
|
||||
.padding(start = 16.dp, bottom = 8.dp, top = 8.dp)
|
||||
.padding(bottom = 8.dp, top = 8.dp)
|
||||
.weight(1f)
|
||||
) {
|
||||
voiceRecording()
|
||||
|
|
|
|||
|
|
@ -0,0 +1,66 @@
|
|||
/*
|
||||
* Copyright (c) 2023 New Vector Ltd
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package io.element.android.libraries.textcomposer.components
|
||||
|
||||
import androidx.compose.foundation.layout.Row
|
||||
import androidx.compose.foundation.layout.size
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.unit.dp
|
||||
import io.element.android.libraries.designsystem.preview.ElementPreview
|
||||
import io.element.android.libraries.designsystem.preview.PreviewsDayNight
|
||||
import io.element.android.libraries.designsystem.text.applyScaleUp
|
||||
import io.element.android.libraries.designsystem.theme.components.Icon
|
||||
import io.element.android.libraries.designsystem.theme.components.IconButton
|
||||
import io.element.android.libraries.designsystem.utils.CommonDrawables
|
||||
import io.element.android.libraries.theme.ElementTheme
|
||||
import io.element.android.libraries.ui.strings.CommonStrings
|
||||
|
||||
@Composable
|
||||
fun VoiceMessageDeleteButton(
|
||||
enabled: Boolean,
|
||||
modifier: Modifier = Modifier,
|
||||
onClick: () -> Unit = {},
|
||||
) {
|
||||
IconButton(
|
||||
modifier = modifier
|
||||
.size(48.dp),
|
||||
enabled = enabled,
|
||||
onClick = onClick,
|
||||
) {
|
||||
Icon(
|
||||
modifier = Modifier.size(24.dp.applyScaleUp()),
|
||||
resourceId = CommonDrawables.ic_compound_delete,
|
||||
contentDescription = stringResource(CommonStrings.a11y_delete),
|
||||
tint = if (enabled) {
|
||||
ElementTheme.colors.iconCriticalPrimary
|
||||
} else {
|
||||
ElementTheme.colors.iconDisabled
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@PreviewsDayNight
|
||||
@Composable
|
||||
internal fun VoiceMessageDeleteButtonPreview() = ElementPreview {
|
||||
Row {
|
||||
VoiceMessageDeleteButton(enabled = true)
|
||||
VoiceMessageDeleteButton(enabled = false)
|
||||
}
|
||||
}
|
||||
|
|
@ -27,4 +27,5 @@ dependencies {
|
|||
implementation(projects.tests.testutils)
|
||||
|
||||
implementation(libs.coroutines.test)
|
||||
implementation(libs.test.truth)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@
|
|||
|
||||
package io.element.android.libraries.voicerecorder.test
|
||||
|
||||
import com.google.common.truth.Truth.assertThat
|
||||
import io.element.android.libraries.voicerecorder.api.VoiceRecorder
|
||||
import io.element.android.libraries.voicerecorder.api.VoiceRecorderState
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
|
|
@ -37,7 +38,12 @@ class FakeVoiceRecorder(
|
|||
|
||||
private var securityException: SecurityException? = null
|
||||
|
||||
private var startedCount = 0
|
||||
private var stoppedCount = 0
|
||||
private var deletedCount = 0
|
||||
|
||||
override suspend fun startRecord() {
|
||||
startedCount += 1
|
||||
val startedAt = timeSource.markNow()
|
||||
securityException?.let { throw it }
|
||||
|
||||
|
|
@ -55,6 +61,8 @@ class FakeVoiceRecorder(
|
|||
override suspend fun stopRecord(
|
||||
cancelled: Boolean
|
||||
) {
|
||||
stoppedCount++
|
||||
|
||||
if (cancelled) {
|
||||
deleteRecording()
|
||||
}
|
||||
|
|
@ -68,6 +76,7 @@ class FakeVoiceRecorder(
|
|||
}
|
||||
|
||||
override suspend fun deleteRecording() {
|
||||
deletedCount++
|
||||
curRecording = null
|
||||
|
||||
_state.emit(
|
||||
|
|
@ -75,6 +84,17 @@ class FakeVoiceRecorder(
|
|||
)
|
||||
}
|
||||
|
||||
|
||||
fun assertCalls(
|
||||
started: Int = 0,
|
||||
stopped: Int = 0,
|
||||
deleted: Int = 0,
|
||||
) {
|
||||
assertThat(startedCount).isEqualTo(started)
|
||||
assertThat(stoppedCount).isEqualTo(stopped)
|
||||
assertThat(deletedCount).isEqualTo(deleted)
|
||||
}
|
||||
|
||||
fun givenThrowsSecurityException(exception: SecurityException) {
|
||||
this.securityException = exception
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue