Update plugin ktlint to v12.1.0 (#2200)

* Update plugin ktlint to v12.1.0

* Run `./gradlew ktlintFormat` and fix some issues manually.

* Fix other issues reproted by Ktlint

* Limit false positives, KtLint removes unnecessary curly brace in String templates.

* Remove useless Unit

* Minor improvements over ktlint changes

* Restore `AlertDialogContent` behaviour

* Update screenshots

---------

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: Benoit Marty <benoit@matrix.org>
Co-authored-by: Jorge Martín <jorgem@element.io>
Co-authored-by: ElementBot <benoitm+elementbot@element.io>
This commit is contained in:
renovate[bot] 2024-01-10 16:22:24 +01:00 committed by GitHub
parent 675cc525cf
commit 7e9cda3aa9
442 changed files with 1091 additions and 1081 deletions

View file

@ -17,7 +17,7 @@ ij_wrap_on_typing = false
# Ktlint rule, for more information see https://pinterest.github.io/ktlint/faq/#why-is-editorconfig-property-disabled_rules-deprecated-and-how-do-i-resolve-this # Ktlint rule, for more information see https://pinterest.github.io/ktlint/faq/#why-is-editorconfig-property-disabled_rules-deprecated-and-how-do-i-resolve-this
ktlint_standard_wrapping = disabled ktlint_standard_wrapping = disabled
ktlint_standard_trailing-comma-on-call-site = disabled ktlint_standard_trailing-comma-on-call-site = disabled
ktlint_standard_spacing-between-declarations-with-annotations = disabled
[*.java] [*.java]
ij_java_align_consecutive_assignments = false ij_java_align_consecutive_assignments = false

View file

@ -68,5 +68,4 @@ class MainNode(
@Parcelize @Parcelize
object RootNavTarget : Parcelable object RootNavTarget : Parcelable
} }

View file

@ -31,6 +31,9 @@ interface AppComponent : NodeFactoriesBindings {
@Component.Factory @Component.Factory
interface Factory { interface Factory {
fun create(@ApplicationContext @BindsInstance context: Context): AppComponent fun create(
@ApplicationContext @BindsInstance
context: Context
): AppComponent
} }
} }

View file

@ -40,4 +40,3 @@ fun <T : Any> BackStack<T>.removeLast(element: T) {
} ?: return } ?: return
accept(Remove(lastExpectedNavElement.key)) accept(Remove(lastExpectedNavElement.key))
} }

View file

@ -138,7 +138,7 @@ class LoggedInFlowNode @AssistedInject constructor(
}, },
onStop = { onStop = {
coroutineScope.launch { coroutineScope.launch {
//Counterpart startSync is done in observeSyncStateAndNetworkStatus method. // Counterpart startSync is done in observeSyncStateAndNetworkStatus method.
syncService.stopSync() syncService.stopSync()
} }
}, },

View file

@ -268,10 +268,9 @@ class RootFlowNode @AssistedInject constructor(
} }
private suspend fun attachSession(sessionId: SessionId): LoggedInAppScopeFlowNode { private suspend fun attachSession(sessionId: SessionId): LoggedInAppScopeFlowNode {
//TODO handle multi-session // TODO handle multi-session
return waitForChildAttached { navTarget -> return waitForChildAttached { navTarget ->
navTarget is NavTarget.LoggedInFlow && navTarget.sessionId == sessionId navTarget is NavTarget.LoggedInFlow && navTarget.sessionId == sessionId
} }
} }
} }

View file

@ -65,8 +65,9 @@ class MatrixClientsHolder @Inject constructor(private val authenticationService:
@Suppress("UNCHECKED_CAST") @Suppress("UNCHECKED_CAST")
fun restoreWithSavedState(state: SavedStateMap?) { fun restoreWithSavedState(state: SavedStateMap?) {
Timber.d("Restore state") Timber.d("Restore state")
if (state == null || sessionIdsToMatrixClient.isNotEmpty()) return Unit.also { if (state == null || sessionIdsToMatrixClient.isNotEmpty()) {
Timber.w("Restore with non-empty map") Timber.w("Restore with non-empty map")
return
} }
val sessionIds = state[SAVE_INSTANCE_KEY] as? Array<SessionId> val sessionIds = state[SAVE_INSTANCE_KEY] as? Array<SessionId>
Timber.d("Restore matrix session keys = ${sessionIds?.map { it.value }}") Timber.d("Restore matrix session keys = ${sessionIds?.map { it.value }}")

View file

@ -59,15 +59,15 @@ fun SyncStateView(
) { ) {
Row( Row(
modifier = Modifier modifier = Modifier
.background(color = ElementTheme.colors.bgSubtleSecondary) .background(color = ElementTheme.colors.bgSubtleSecondary)
.padding(horizontal = 24.dp, vertical = 10.dp), .padding(horizontal = 24.dp, vertical = 10.dp),
verticalAlignment = Alignment.CenterVertically, verticalAlignment = Alignment.CenterVertically,
horizontalArrangement = Arrangement.spacedBy(10.dp) horizontalArrangement = Arrangement.spacedBy(10.dp)
) { ) {
CircularProgressIndicator( CircularProgressIndicator(
modifier = Modifier modifier = Modifier
.progressSemantics() .progressSemantics()
.size(12.dp), .size(12.dp),
color = ElementTheme.colors.textPrimary, color = ElementTheme.colors.textPrimary,
strokeWidth = 1.5.dp, strokeWidth = 1.5.dp,
) )

View file

@ -136,4 +136,3 @@ class RoomFlowNode @AssistedInject constructor(
) )
} }
} }

View file

@ -31,22 +31,22 @@ class LoadingRoomStateFlowFactoryTest {
@Test @Test
fun `flow should emit Loading and then Loaded when there is a room in cache`() = runTest { fun `flow should emit Loading and then Loaded when there is a room in cache`() = runTest {
val room = FakeMatrixRoom(sessionId= A_SESSION_ID, roomId = A_ROOM_ID) val room = FakeMatrixRoom(sessionId = A_SESSION_ID, roomId = A_ROOM_ID)
val matrixClient = FakeMatrixClient(A_SESSION_ID).apply { val matrixClient = FakeMatrixClient(A_SESSION_ID).apply {
givenGetRoomResult(A_ROOM_ID, room) givenGetRoomResult(A_ROOM_ID, room)
} }
val flowFactory = LoadingRoomStateFlowFactory(matrixClient) val flowFactory = LoadingRoomStateFlowFactory(matrixClient)
flowFactory flowFactory
.create(this, A_ROOM_ID) .create(this, A_ROOM_ID)
.test { .test {
assertThat(awaitItem()).isEqualTo(LoadingRoomState.Loading) assertThat(awaitItem()).isEqualTo(LoadingRoomState.Loading)
assertThat(awaitItem()).isEqualTo(LoadingRoomState.Loaded(room)) assertThat(awaitItem()).isEqualTo(LoadingRoomState.Loaded(room))
} }
} }
@Test @Test
fun `flow should emit Loading and then Loaded when there is a room in cache after SS is loaded`() = runTest { fun `flow should emit Loading and then Loaded when there is a room in cache after SS is loaded`() = runTest {
val room = FakeMatrixRoom(sessionId= A_SESSION_ID, roomId = A_ROOM_ID) val room = FakeMatrixRoom(sessionId = A_SESSION_ID, roomId = A_ROOM_ID)
val roomListService = FakeRoomListService() val roomListService = FakeRoomListService()
val matrixClient = FakeMatrixClient(A_SESSION_ID, roomListService = roomListService) val matrixClient = FakeMatrixClient(A_SESSION_ID, roomListService = roomListService)
val flowFactory = LoadingRoomStateFlowFactory(matrixClient) val flowFactory = LoadingRoomStateFlowFactory(matrixClient)

View file

@ -216,13 +216,15 @@ subprojects {
if (project.findProperty("composeCompilerReports") == "true") { if (project.findProperty("composeCompilerReports") == "true") {
freeCompilerArgs += listOf( freeCompilerArgs += listOf(
"-P", "-P",
"plugin:androidx.compose.compiler.plugins.kotlin:reportsDestination=${project.layout.buildDirectory.asFile.get().absolutePath}/compose_compiler" "plugin:androidx.compose.compiler.plugins.kotlin:reportsDestination=" +
"${project.layout.buildDirectory.asFile.get().absolutePath}/compose_compiler"
) )
} }
if (project.findProperty("composeCompilerMetrics") == "true") { if (project.findProperty("composeCompilerMetrics") == "true") {
freeCompilerArgs += listOf( freeCompilerArgs += listOf(
"-P", "-P",
"plugin:androidx.compose.compiler.plugins.kotlin:metricsDestination=${project.layout.buildDirectory.asFile.get().absolutePath}/compose_compiler" "plugin:androidx.compose.compiler.plugins.kotlin:metricsDestination=" +
"${project.layout.buildDirectory.asFile.get().absolutePath}/compose_compiler"
) )
} }
} }

View file

@ -25,8 +25,8 @@ import io.element.android.features.analytics.api.AnalyticsOptInEvents
import io.element.android.features.analytics.api.R import io.element.android.features.analytics.api.R
import io.element.android.libraries.designsystem.components.LINK_TAG import io.element.android.libraries.designsystem.components.LINK_TAG
import io.element.android.libraries.designsystem.components.list.ListItemContent import io.element.android.libraries.designsystem.components.list.ListItemContent
import io.element.android.libraries.designsystem.preview.PreviewsDayNight
import io.element.android.libraries.designsystem.preview.ElementPreview import io.element.android.libraries.designsystem.preview.ElementPreview
import io.element.android.libraries.designsystem.preview.PreviewsDayNight
import io.element.android.libraries.designsystem.text.buildAnnotatedStringWithStyledPart import io.element.android.libraries.designsystem.text.buildAnnotatedStringWithStyledPart
import io.element.android.libraries.designsystem.theme.components.ListItem import io.element.android.libraries.designsystem.theme.components.ListItem
import io.element.android.libraries.designsystem.theme.components.ListSupportingText import io.element.android.libraries.designsystem.theme.components.ListSupportingText

View file

@ -19,8 +19,7 @@ package io.element.android.features.analytics.impl
import androidx.compose.ui.tooling.preview.PreviewParameterProvider import androidx.compose.ui.tooling.preview.PreviewParameterProvider
import javax.inject.Inject import javax.inject.Inject
open class AnalyticsOptInStateProvider @Inject constructor( open class AnalyticsOptInStateProvider @Inject constructor() : PreviewParameterProvider<AnalyticsOptInState> {
) : PreviewParameterProvider<AnalyticsOptInState> {
override val values: Sequence<AnalyticsOptInState> override val values: Sequence<AnalyticsOptInState>
get() = sequenceOf( get() = sequenceOf(
aAnalyticsOptInState(), aAnalyticsOptInState(),

View file

@ -70,4 +70,3 @@ class AnalyticsOptInPresenterTest {
} }
} }
} }

View file

@ -33,6 +33,7 @@ data class WidgetMessage(
enum class Direction { enum class Direction {
@SerialName("fromWidget") @SerialName("fromWidget")
FromWidget, FromWidget,
@SerialName("toWidget") @SerialName("toWidget")
ToWidget ToWidget
} }
@ -41,6 +42,7 @@ data class WidgetMessage(
enum class Action { enum class Action {
@SerialName("im.vector.hangup") @SerialName("im.vector.hangup")
HangUp, HangUp,
@SerialName("send_event") @SerialName("send_event")
SendEvent, SendEvent,
} }

View file

@ -224,6 +224,4 @@ class CallScreenPresenter @AssistedInject constructor(
navigator.close() navigator.close()
widgetDriver?.close() widgetDriver?.close()
} }
} }

View file

@ -56,7 +56,7 @@ class WebViewWidgetMessageInterceptor(
|| !message.data.response && message.data.api == "fromWidget") { || !message.data.response && message.data.api == "fromWidget") {
let json = JSON.stringify(event.data) let json = JSON.stringify(event.data)
${"console.log('message sent: ' + json);".takeIf { BuildConfig.DEBUG } } ${"console.log('message sent: ' + json);".takeIf { BuildConfig.DEBUG } }
${LISTENER_NAME}.postMessage(json); $LISTENER_NAME.postMessage(json);
} else { } else {
${"console.log('message received (ignored): ' + JSON.stringify(event.data));".takeIf { BuildConfig.DEBUG } } ${"console.log('message received (ignored): ' + JSON.stringify(event.data));".takeIf { BuildConfig.DEBUG } }
} }

View file

@ -191,7 +191,7 @@ class CallScreenPresenterTest {
moleculeFlow(RecompositionMode.Immediate) { moleculeFlow(RecompositionMode.Immediate) {
presenter.present() presenter.present()
}.test { }.test {
consumeItemsUntilTimeout() consumeItemsUntilTimeout()
assertThat(matrixClient.syncService().syncState.value).isEqualTo(SyncState.Running) assertThat(matrixClient.syncService().syncState.value).isEqualTo(SyncState.Running)

View file

@ -17,10 +17,10 @@
package io.element.android.features.call.ui package io.element.android.features.call.ui
class FakeCallScreenNavigator : CallScreenNavigator { class FakeCallScreenNavigator : CallScreenNavigator {
var closeCalled = false var closeCalled = false
private set private set
override fun close() { override fun close() {
closeCalled = true closeCalled = true
}
} }
}

View file

@ -117,7 +117,7 @@ class CallIntentDataParserTest {
@Test @Test
fun `Element Call url with url extra param appPrompt gets url extracted`() { fun `Element Call url with url extra param appPrompt gets url extracted`() {
doTest( doTest(
url = "${VALID_CALL_URL_WITH_PARAM}&appPrompt=true", url = "$VALID_CALL_URL_WITH_PARAM&appPrompt=true",
expectedResult = "$VALID_CALL_URL_WITH_PARAM#?$EXTRA_PARAMS" expectedResult = "$VALID_CALL_URL_WITH_PARAM#?$EXTRA_PARAMS"
) )
} }
@ -125,7 +125,7 @@ class CallIntentDataParserTest {
@Test @Test
fun `Element Call url with url extra param in fragment appPrompt gets url extracted`() { fun `Element Call url with url extra param in fragment appPrompt gets url extracted`() {
doTest( doTest(
url = "${VALID_CALL_URL_WITH_PARAM}#?appPrompt=true", url = "$VALID_CALL_URL_WITH_PARAM#?appPrompt=true",
expectedResult = "$VALID_CALL_URL_WITH_PARAM#?appPrompt=false&confineToRoom=true" expectedResult = "$VALID_CALL_URL_WITH_PARAM#?appPrompt=false&confineToRoom=true"
) )
} }
@ -133,7 +133,7 @@ class CallIntentDataParserTest {
@Test @Test
fun `Element Call url with url extra param in fragment appPrompt and other gets url extracted`() { fun `Element Call url with url extra param in fragment appPrompt and other gets url extracted`() {
doTest( doTest(
url = "${VALID_CALL_URL_WITH_PARAM}#?appPrompt=true&otherParam=maybe", url = "$VALID_CALL_URL_WITH_PARAM#?appPrompt=true&otherParam=maybe",
expectedResult = "$VALID_CALL_URL_WITH_PARAM#?appPrompt=false&otherParam=maybe&confineToRoom=true" expectedResult = "$VALID_CALL_URL_WITH_PARAM#?appPrompt=false&otherParam=maybe&confineToRoom=true"
) )
} }
@ -141,7 +141,7 @@ class CallIntentDataParserTest {
@Test @Test
fun `Element Call url with url extra param confineToRoom gets url extracted`() { fun `Element Call url with url extra param confineToRoom gets url extracted`() {
doTest( doTest(
url = "${VALID_CALL_URL_WITH_PARAM}&confineToRoom=false", url = "$VALID_CALL_URL_WITH_PARAM&confineToRoom=false",
expectedResult = "$VALID_CALL_URL_WITH_PARAM#?$EXTRA_PARAMS" expectedResult = "$VALID_CALL_URL_WITH_PARAM#?$EXTRA_PARAMS"
) )
} }
@ -149,7 +149,7 @@ class CallIntentDataParserTest {
@Test @Test
fun `Element Call url with url extra param in fragment confineToRoom gets url extracted`() { fun `Element Call url with url extra param in fragment confineToRoom gets url extracted`() {
doTest( doTest(
url = "${VALID_CALL_URL_WITH_PARAM}#?confineToRoom=false", url = "$VALID_CALL_URL_WITH_PARAM#?confineToRoom=false",
expectedResult = "$VALID_CALL_URL_WITH_PARAM#?confineToRoom=true&appPrompt=false" expectedResult = "$VALID_CALL_URL_WITH_PARAM#?confineToRoom=true&appPrompt=false"
) )
} }
@ -157,7 +157,7 @@ class CallIntentDataParserTest {
@Test @Test
fun `Element Call url with url extra param in fragment confineToRoom and more gets url extracted`() { fun `Element Call url with url extra param in fragment confineToRoom and more gets url extracted`() {
doTest( doTest(
url = "${VALID_CALL_URL_WITH_PARAM}#?confineToRoom=false&otherParam=maybe", url = "$VALID_CALL_URL_WITH_PARAM#?confineToRoom=false&otherParam=maybe",
expectedResult = "$VALID_CALL_URL_WITH_PARAM#?confineToRoom=true&otherParam=maybe&appPrompt=false" expectedResult = "$VALID_CALL_URL_WITH_PARAM#?confineToRoom=true&otherParam=maybe&appPrompt=false"
) )
} }
@ -165,7 +165,7 @@ class CallIntentDataParserTest {
@Test @Test
fun `Element Call url with url fragment gets url extracted`() { fun `Element Call url with url fragment gets url extracted`() {
doTest( doTest(
url = "${VALID_CALL_URL_WITH_PARAM}#fragment", url = "$VALID_CALL_URL_WITH_PARAM#fragment",
expectedResult = "$VALID_CALL_URL_WITH_PARAM#fragment?$EXTRA_PARAMS" expectedResult = "$VALID_CALL_URL_WITH_PARAM#fragment?$EXTRA_PARAMS"
) )
} }
@ -173,7 +173,7 @@ class CallIntentDataParserTest {
@Test @Test
fun `Element Call url with url fragment with params gets url extracted`() { fun `Element Call url with url fragment with params gets url extracted`() {
doTest( doTest(
url = "${VALID_CALL_URL_WITH_PARAM}#fragment?otherParam=maybe", url = "$VALID_CALL_URL_WITH_PARAM#fragment?otherParam=maybe",
expectedResult = "$VALID_CALL_URL_WITH_PARAM#fragment?otherParam=maybe&$EXTRA_PARAMS" expectedResult = "$VALID_CALL_URL_WITH_PARAM#fragment?otherParam=maybe&$EXTRA_PARAMS"
) )
} }
@ -181,7 +181,7 @@ class CallIntentDataParserTest {
@Test @Test
fun `Element Call url with url fragment with other params gets url extracted`() { fun `Element Call url with url fragment with other params gets url extracted`() {
doTest( doTest(
url = "${VALID_CALL_URL_WITH_PARAM}#?otherParam=maybe", url = "$VALID_CALL_URL_WITH_PARAM#?otherParam=maybe",
expectedResult = "$VALID_CALL_URL_WITH_PARAM#?otherParam=maybe&$EXTRA_PARAMS" expectedResult = "$VALID_CALL_URL_WITH_PARAM#?otherParam=maybe&$EXTRA_PARAMS"
) )
} }
@ -189,7 +189,7 @@ class CallIntentDataParserTest {
@Test @Test
fun `Element Call url with empty fragment`() { fun `Element Call url with empty fragment`() {
doTest( doTest(
url = "${VALID_CALL_URL_WITH_PARAM}#", url = "$VALID_CALL_URL_WITH_PARAM#",
expectedResult = "$VALID_CALL_URL_WITH_PARAM#?$EXTRA_PARAMS" expectedResult = "$VALID_CALL_URL_WITH_PARAM#?$EXTRA_PARAMS"
) )
} }
@ -197,7 +197,7 @@ class CallIntentDataParserTest {
@Test @Test
fun `Element Call url with empty fragment query`() { fun `Element Call url with empty fragment query`() {
doTest( doTest(
url = "${VALID_CALL_URL_WITH_PARAM}#?", url = "$VALID_CALL_URL_WITH_PARAM#?",
expectedResult = "$VALID_CALL_URL_WITH_PARAM#?$EXTRA_PARAMS" expectedResult = "$VALID_CALL_URL_WITH_PARAM#?$EXTRA_PARAMS"
) )
} }

View file

@ -24,19 +24,19 @@ import io.element.android.libraries.matrix.test.widget.FakeWidgetDriver
class FakeCallWidgetProvider( class FakeCallWidgetProvider(
private val widgetDriver: FakeWidgetDriver = FakeWidgetDriver(), private val widgetDriver: FakeWidgetDriver = FakeWidgetDriver(),
private val url: String = "https://call.element.io", private val url: String = "https://call.element.io",
) : CallWidgetProvider { ) : CallWidgetProvider {
var getWidgetCalled = false var getWidgetCalled = false
private set private set
override suspend fun getWidget( override suspend fun getWidget(
sessionId: SessionId, sessionId: SessionId,
roomId: RoomId, roomId: RoomId,
clientId: String, clientId: String,
languageTag: String?, languageTag: String?,
theme: String? theme: String?
): Result<Pair<MatrixWidgetDriver, String>> { ): Result<Pair<MatrixWidgetDriver, String>> {
getWidgetCalled = true getWidgetCalled = true
return Result.success(widgetDriver to url) return Result.success(widgetDriver to url)
}
} }
}

View file

@ -19,15 +19,15 @@ package io.element.android.features.call.utils
import kotlinx.coroutines.flow.MutableSharedFlow import kotlinx.coroutines.flow.MutableSharedFlow
class FakeWidgetMessageInterceptor : WidgetMessageInterceptor { class FakeWidgetMessageInterceptor : WidgetMessageInterceptor {
val sentMessages = mutableListOf<String>() val sentMessages = mutableListOf<String>()
override val interceptedMessages = MutableSharedFlow<String>(extraBufferCapacity = 1) override val interceptedMessages = MutableSharedFlow<String>(extraBufferCapacity = 1)
override fun sendMessage(message: String) { override fun sendMessage(message: String) {
sentMessages += message sentMessages += message
}
fun givenInterceptedMessage(message: String) {
interceptedMessages.tryEmit(message)
}
} }
fun givenInterceptedMessage(message: String) {
interceptedMessages.tryEmit(message)
}
}

View file

@ -29,7 +29,6 @@ import javax.inject.Inject
class DefaultCreateRoomEntryPoint @Inject constructor() : CreateRoomEntryPoint { class DefaultCreateRoomEntryPoint @Inject constructor() : CreateRoomEntryPoint {
override fun nodeBuilder(parentNode: Node, buildContext: BuildContext): CreateRoomEntryPoint.NodeBuilder { override fun nodeBuilder(parentNode: Node, buildContext: BuildContext): CreateRoomEntryPoint.NodeBuilder {
val plugins = ArrayList<Plugin>() val plugins = ArrayList<Plugin>()
return object : CreateRoomEntryPoint.NodeBuilder { return object : CreateRoomEntryPoint.NodeBuilder {

View file

@ -45,4 +45,3 @@ class AddPeoplePresenter @Inject constructor(
return userListPresenter.present() return userListPresenter.present()
} }
} }

View file

@ -37,11 +37,13 @@ open class AddPeopleUserListStateProvider : PreviewParameterProvider<UserListSta
selectionMode = SelectionMode.Multiple, selectionMode = SelectionMode.Multiple,
), ),
aUserListState().copy( aUserListState().copy(
searchResults = SearchBarResultState.Results(aMatrixUserList() searchResults = SearchBarResultState.Results(
.mapIndexed { index, matrixUser -> aMatrixUserList()
UserSearchResult(matrixUser, index % 2 == 0) .mapIndexed { index, matrixUser ->
} UserSearchResult(matrixUser, index % 2 == 0)
.toImmutableList()), }
.toImmutableList()
),
selectedUsers = aListOfSelectedUsers(), selectedUsers = aListOfSelectedUsers(),
isSearchActive = true, isSearchActive = true,
selectionMode = SelectionMode.Multiple, selectionMode = SelectionMode.Multiple,

View file

@ -29,14 +29,14 @@ import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.semantics.Role import androidx.compose.ui.semantics.Role
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import io.element.android.compound.theme.ElementTheme
import io.element.android.features.createroom.impl.configureroom.RoomPrivacyItem import io.element.android.features.createroom.impl.configureroom.RoomPrivacyItem
import io.element.android.features.createroom.impl.configureroom.roomPrivacyItems import io.element.android.features.createroom.impl.configureroom.roomPrivacyItems
import io.element.android.libraries.designsystem.preview.PreviewsDayNight
import io.element.android.libraries.designsystem.preview.ElementPreview import io.element.android.libraries.designsystem.preview.ElementPreview
import io.element.android.libraries.designsystem.preview.PreviewsDayNight
import io.element.android.libraries.designsystem.theme.components.Icon import io.element.android.libraries.designsystem.theme.components.Icon
import io.element.android.libraries.designsystem.theme.components.RadioButton import io.element.android.libraries.designsystem.theme.components.RadioButton
import io.element.android.libraries.designsystem.theme.components.Text import io.element.android.libraries.designsystem.theme.components.Text
import io.element.android.compound.theme.ElementTheme
@Composable @Composable
fun RoomPrivacyOption( fun RoomPrivacyOption(

View file

@ -19,8 +19,8 @@ package io.element.android.features.createroom.impl.configureroom
import androidx.annotation.DrawableRes import androidx.annotation.DrawableRes
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.ui.res.stringResource import androidx.compose.ui.res.stringResource
import io.element.android.libraries.designsystem.icons.CompoundDrawables
import io.element.android.features.createroom.impl.R import io.element.android.features.createroom.impl.R
import io.element.android.libraries.designsystem.icons.CompoundDrawables
import kotlinx.collections.immutable.ImmutableList import kotlinx.collections.immutable.ImmutableList
import kotlinx.collections.immutable.toImmutableList import kotlinx.collections.immutable.toImmutableList

View file

@ -19,7 +19,6 @@ package io.element.android.features.createroom.impl.root
import androidx.compose.ui.tooling.preview.PreviewParameterProvider import androidx.compose.ui.tooling.preview.PreviewParameterProvider
import io.element.android.features.createroom.impl.userlist.aUserListState import io.element.android.features.createroom.impl.userlist.aUserListState
import io.element.android.libraries.architecture.AsyncAction import io.element.android.libraries.architecture.AsyncAction
import io.element.android.libraries.designsystem.theme.components.SearchBarResultState import io.element.android.libraries.designsystem.theme.components.SearchBarResultState
import io.element.android.libraries.matrix.ui.components.aMatrixUser import io.element.android.libraries.matrix.ui.components.aMatrixUser
import io.element.android.libraries.usersearch.api.UserSearchResult import io.element.android.libraries.usersearch.api.UserSearchResult

View file

@ -106,7 +106,7 @@ fun CreateRoomRootView(
onRetry = { onRetry = {
state.userListState.selectedUsers.firstOrNull() state.userListState.selectedUsers.firstOrNull()
?.let { state.eventSink(CreateRoomRootEvents.StartDM(it)) } ?.let { state.eventSink(CreateRoomRootEvents.StartDM(it)) }
// Cancel start DM if there is no more selected user (should not happen) // Cancel start DM if there is no more selected user (should not happen)
?: state.eventSink(CreateRoomRootEvents.CancelStartDM) ?: state.eventSink(CreateRoomRootEvents.CancelStartDM)
}, },
onErrorDismiss = { state.eventSink(CreateRoomRootEvents.CancelStartDM) }, onErrorDismiss = { state.eventSink(CreateRoomRootEvents.CancelStartDM) },

View file

@ -80,7 +80,6 @@ class CreateRoomRootPresenterTests {
awaitItem().also { state -> awaitItem().also { state ->
assertThat(state.startDmAction).isEqualTo(startDMSuccessResult) assertThat(state.startDmAction).isEqualTo(startDMSuccessResult)
} }
} }
} }

View file

@ -50,5 +50,6 @@ fun MigrationScreenView(
internal fun MigrationViewPreview() = ElementPreview { internal fun MigrationViewPreview() = ElementPreview {
MigrationScreenView( MigrationScreenView(
migrationState = MigrationScreenState(isMigrating = true), migrationState = MigrationScreenState(isMigrating = true),
onMigrationFinished = {}) onMigrationFinished = {}
)
} }

View file

@ -58,4 +58,3 @@ class SharedPrefsMigrationScreenStore @Inject constructor(
private const val IS_MIGRATION_SCREEN_SHOWN_PREFIX = "is_migration_screen_shown_" private const val IS_MIGRATION_SCREEN_SHOWN_PREFIX = "is_migration_screen_shown_"
} }
} }

View file

@ -77,8 +77,8 @@ class NotificationsOptInPresenter @AssistedInject constructor(
} }
LaunchedEffect(notificationsPermissionsState) { LaunchedEffect(notificationsPermissionsState) {
if (notificationsPermissionsState.permissionGranted if (notificationsPermissionsState.permissionGranted ||
|| notificationsPermissionsState.permissionAlreadyDenied) { notificationsPermissionsState.permissionAlreadyDenied) {
callback.onNotificationsOptInFinished() callback.onNotificationsOptInFinished()
} }
} }

View file

@ -40,7 +40,7 @@ import javax.inject.Inject
@ContributesBinding(SessionScope::class) @ContributesBinding(SessionScope::class)
class DefaultFtueState @Inject constructor( class DefaultFtueState @Inject constructor(
private val sdkVersionProvider: BuildVersionSdkIntProvider, private val sdkVersionProvider: BuildVersionSdkIntProvider,
private val coroutineScope: CoroutineScope, coroutineScope: CoroutineScope,
private val analyticsService: AnalyticsService, private val analyticsService: AnalyticsService,
private val welcomeScreenState: WelcomeScreenState, private val welcomeScreenState: WelcomeScreenState,
private val migrationScreenStore: MigrationScreenStore, private val migrationScreenStore: MigrationScreenStore,
@ -68,21 +68,31 @@ class DefaultFtueState @Inject constructor(
fun getNextStep(currentStep: FtueStep? = null): FtueStep? = fun getNextStep(currentStep: FtueStep? = null): FtueStep? =
when (currentStep) { when (currentStep) {
null -> if (shouldDisplayMigrationScreen()) FtueStep.MigrationScreen else getNextStep( null -> if (shouldDisplayMigrationScreen()) {
FtueStep.MigrationScreen FtueStep.MigrationScreen
) } else {
FtueStep.MigrationScreen -> if (shouldDisplayWelcomeScreen()) FtueStep.WelcomeScreen else getNextStep( getNextStep(FtueStep.MigrationScreen)
}
FtueStep.MigrationScreen -> if (shouldDisplayWelcomeScreen()) {
FtueStep.WelcomeScreen FtueStep.WelcomeScreen
) } else {
FtueStep.WelcomeScreen -> if (shouldAskNotificationPermissions()) FtueStep.NotificationsOptIn else getNextStep( getNextStep(FtueStep.WelcomeScreen)
}
FtueStep.WelcomeScreen -> if (shouldAskNotificationPermissions()) {
FtueStep.NotificationsOptIn FtueStep.NotificationsOptIn
) } else {
FtueStep.NotificationsOptIn -> if (shouldDisplayLockscreenSetup()) FtueStep.LockscreenSetup else getNextStep( getNextStep(FtueStep.NotificationsOptIn)
}
FtueStep.NotificationsOptIn -> if (shouldDisplayLockscreenSetup()) {
FtueStep.LockscreenSetup FtueStep.LockscreenSetup
) } else {
FtueStep.LockscreenSetup -> if (needsAnalyticsOptIn()) FtueStep.AnalyticsOptIn else getNextStep( getNextStep(FtueStep.LockscreenSetup)
}
FtueStep.LockscreenSetup -> if (needsAnalyticsOptIn()) {
FtueStep.AnalyticsOptIn FtueStep.AnalyticsOptIn
) } else {
getNextStep(FtueStep.AnalyticsOptIn)
}
FtueStep.AnalyticsOptIn -> null FtueStep.AnalyticsOptIn -> null
} }
@ -115,7 +125,9 @@ class DefaultFtueState @Inject constructor(
val isPermissionDenied = runBlocking { permissionStateProvider.isPermissionDenied(permission).first() } val isPermissionDenied = runBlocking { permissionStateProvider.isPermissionDenied(permission).first() }
val isPermissionGranted = permissionStateProvider.isPermissionGranted(permission) val isPermissionGranted = permissionStateProvider.isPermissionGranted(permission)
!isPermissionGranted && !isPermissionDenied !isPermissionGranted && !isPermissionDenied
} else false } else {
false
}
} }
private fun shouldDisplayLockscreenSetup(): Boolean { private fun shouldDisplayLockscreenSetup(): Boolean {

View file

@ -50,5 +50,4 @@ class WelcomeNode @AssistedInject constructor(
modifier = modifier modifier = modifier
) )
} }
} }

View file

@ -37,4 +37,3 @@ interface InviteListEntryPoint : FeatureEntryPoint {
fun onInviteAccepted(roomId: RoomId) fun onInviteAccepted(roomId: RoomId)
} }
} }

View file

@ -34,7 +34,6 @@ import javax.inject.Inject
private val Context.dataStore: DataStore<Preferences> by preferencesDataStore(name = "elementx_seeninvites") private val Context.dataStore: DataStore<Preferences> by preferencesDataStore(name = "elementx_seeninvites")
private val seenInvitesKey = stringSetPreferencesKey("seenInvites") private val seenInvitesKey = stringSetPreferencesKey("seenInvites")
@ContributesBinding(SessionScope::class) @ContributesBinding(SessionScope::class)
class DefaultSeenInvitesStore @Inject constructor( class DefaultSeenInvitesStore @Inject constructor(
@ApplicationContext context: Context @ApplicationContext context: Context
@ -55,5 +54,4 @@ class DefaultSeenInvitesStore @Inject constructor(
prefs[seenInvitesKey] = roomIds.map { it.value }.toSet() prefs[seenInvitesKey] = roomIds.map { it.value }.toSet()
} }
} }
} }

View file

@ -22,9 +22,9 @@ sealed interface InviteListEvents {
data class AcceptInvite(val invite: InviteListInviteSummary) : InviteListEvents data class AcceptInvite(val invite: InviteListInviteSummary) : InviteListEvents
data class DeclineInvite(val invite: InviteListInviteSummary) : InviteListEvents data class DeclineInvite(val invite: InviteListInviteSummary) : InviteListEvents
data object ConfirmDeclineInvite: InviteListEvents data object ConfirmDeclineInvite : InviteListEvents
data object CancelDeclineInvite: InviteListEvents data object CancelDeclineInvite : InviteListEvents
data object DismissAcceptError: InviteListEvents data object DismissAcceptError : InviteListEvents
data object DismissDeclineError: InviteListEvents data object DismissDeclineError : InviteListEvents
} }

View file

@ -159,25 +159,27 @@ class InviteListPresenter @Inject constructor(
private fun RoomSummary.Filled.toInviteSummary(seen: Boolean) = details.run { private fun RoomSummary.Filled.toInviteSummary(seen: Boolean) = details.run {
val i = inviter val i = inviter
val avatarData = if (isDirect && i != null) val avatarData = if (isDirect && i != null) {
AvatarData( AvatarData(
id = i.userId.value, id = i.userId.value,
name = i.displayName, name = i.displayName,
url = i.avatarUrl, url = i.avatarUrl,
size = AvatarSize.RoomInviteItem, size = AvatarSize.RoomInviteItem,
) )
else } else {
AvatarData( AvatarData(
id = roomId.value, id = roomId.value,
name = name, name = name,
url = avatarURLString, url = avatarURLString,
size = AvatarSize.RoomInviteItem, size = AvatarSize.RoomInviteItem,
) )
}
val alias = if (isDirect) val alias = if (isDirect) {
inviter?.userId?.value inviter?.userId?.value
else } else {
canonicalAlias canonicalAlias
}
InviteListInviteSummary( InviteListInviteSummary(
roomId = roomId, roomId = roomId,
@ -186,18 +188,20 @@ class InviteListPresenter @Inject constructor(
roomAvatarData = avatarData, roomAvatarData = avatarData,
isDirect = isDirect, isDirect = isDirect,
isNew = !seen, isNew = !seen,
sender = if (isDirect) null else inviter?.run { sender = inviter
InviteSender( ?.takeIf { !isDirect }
userId = userId, ?.run {
displayName = displayName ?: "", InviteSender(
avatarData = AvatarData( userId = userId,
id = userId.value, displayName = displayName ?: "",
name = displayName, avatarData = AvatarData(
url = avatarUrl, id = userId.value,
size = AvatarSize.InviteSender, name = displayName,
), url = avatarUrl,
) size = AvatarSize.InviteSender,
}, ),
)
},
) )
} }
} }

View file

@ -69,15 +69,17 @@ fun InviteListView(
) )
if (state.declineConfirmationDialog is InviteDeclineConfirmationDialog.Visible) { if (state.declineConfirmationDialog is InviteDeclineConfirmationDialog.Visible) {
val contentResource = if (state.declineConfirmationDialog.isDirect) val contentResource = if (state.declineConfirmationDialog.isDirect) {
R.string.screen_invites_decline_direct_chat_message R.string.screen_invites_decline_direct_chat_message
else } else {
R.string.screen_invites_decline_chat_message R.string.screen_invites_decline_chat_message
}
val titleResource = if (state.declineConfirmationDialog.isDirect) val titleResource = if (state.declineConfirmationDialog.isDirect) {
R.string.screen_invites_decline_direct_chat_title R.string.screen_invites_decline_direct_chat_title
else } else {
R.string.screen_invites_decline_chat_title R.string.screen_invites_decline_chat_title
}
ConfirmationDialog( ConfirmationDialog(
content = stringResource(contentResource, state.declineConfirmationDialog.name), content = stringResource(contentResource, state.declineConfirmationDialog.name),

View file

@ -39,6 +39,7 @@ import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.tooling.preview.PreviewParameter import androidx.compose.ui.tooling.preview.PreviewParameter
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import io.element.android.compound.theme.ElementTheme
import io.element.android.features.invitelist.impl.R import io.element.android.features.invitelist.impl.R
import io.element.android.features.invitelist.impl.model.InviteListInviteSummary import io.element.android.features.invitelist.impl.model.InviteListInviteSummary
import io.element.android.features.invitelist.impl.model.InviteListInviteSummaryProvider import io.element.android.features.invitelist.impl.model.InviteListInviteSummaryProvider
@ -51,7 +52,6 @@ import io.element.android.libraries.designsystem.theme.components.Button
import io.element.android.libraries.designsystem.theme.components.ButtonSize import io.element.android.libraries.designsystem.theme.components.ButtonSize
import io.element.android.libraries.designsystem.theme.components.OutlinedButton import io.element.android.libraries.designsystem.theme.components.OutlinedButton
import io.element.android.libraries.designsystem.theme.components.Text import io.element.android.libraries.designsystem.theme.components.Text
import io.element.android.compound.theme.ElementTheme
import io.element.android.libraries.ui.strings.CommonStrings import io.element.android.libraries.ui.strings.CommonStrings
private val minHeight = 72.dp private val minHeight = 72.dp

View file

@ -27,8 +27,8 @@ import androidx.compose.ui.unit.dp
import io.element.android.libraries.designsystem.components.ProgressDialog import io.element.android.libraries.designsystem.components.ProgressDialog
import io.element.android.libraries.designsystem.components.dialogs.ConfirmationDialog import io.element.android.libraries.designsystem.components.dialogs.ConfirmationDialog
import io.element.android.libraries.designsystem.components.dialogs.ErrorDialog import io.element.android.libraries.designsystem.components.dialogs.ErrorDialog
import io.element.android.libraries.designsystem.preview.PreviewsDayNight
import io.element.android.libraries.designsystem.preview.ElementPreview import io.element.android.libraries.designsystem.preview.ElementPreview
import io.element.android.libraries.designsystem.preview.PreviewsDayNight
import io.element.android.libraries.matrix.api.core.RoomId import io.element.android.libraries.matrix.api.core.RoomId
import io.element.android.libraries.ui.strings.CommonStrings import io.element.android.libraries.ui.strings.CommonStrings

View file

@ -65,7 +65,7 @@ internal class MapTilerStaticMapUrlBuilder(
// image smaller than the available space in pixels. // image smaller than the available space in pixels.
// The resulting image will have to be scaled to fit the available space in order // The resulting image will have to be scaled to fit the available space in order
// to keep the perceived content size constant at the expense of sharpness. // to keep the perceived content size constant at the expense of sharpness.
return "$MAPTILER_BASE_URL/${mapId}/static/${lon},${lat},${finalZoom}/${finalWidth}x${finalHeight}${scale}.webp?key=${apiKey}&attribution=bottomleft" return "$MAPTILER_BASE_URL/$mapId/static/$lon,$lat,$finalZoom/${finalWidth}x${finalHeight}$scale.webp?key=$apiKey&attribution=bottomleft"
} }
} }

View file

@ -34,6 +34,6 @@ internal class MapTilerTileServerStyleUriBuilder(
override fun build(darkMode: Boolean): String { override fun build(darkMode: Boolean): String {
val mapId = if (darkMode) darkMapId else lightMapId val mapId = if (darkMode) darkMapId else lightMapId
return "${MAPTILER_BASE_URL}/${mapId}/style.json?key=${apiKey}" return "$MAPTILER_BASE_URL/$mapId/style.json?key=$apiKey"
} }
} }

View file

@ -78,7 +78,7 @@ internal class LocationKtTest {
@Test @Test
fun `encode geoUri - returns geoUri from a Location`() { fun `encode geoUri - returns geoUri from a Location`() {
assertThat(Location(1.0,2.0,3.0f).toGeoUri()) assertThat(Location(1.0, 2.0, 3.0f).toGeoUri())
.isEqualTo("geo:1.0,2.0;u=3.0") .isEqualTo("geo:1.0,2.0;u=3.0")
} }
} }

View file

@ -27,6 +27,7 @@ import javax.inject.Inject
@ContributesBinding(AppScope::class) @ContributesBinding(AppScope::class)
class SendLocationEntryPointImpl @Inject constructor() : SendLocationEntryPoint { class SendLocationEntryPointImpl @Inject constructor() : SendLocationEntryPoint {
override fun createNode( override fun createNode(
parentNode: Node, buildContext: BuildContext parentNode: Node,
buildContext: BuildContext
): SendLocationNode = parentNode.createNode(buildContext) ): SendLocationNode = parentNode.createNode(buildContext)
} }

View file

@ -55,8 +55,11 @@ class SendLocationPresenter @Inject constructor(
val permissionsState: PermissionsState = permissionsPresenter.present() val permissionsState: PermissionsState = permissionsPresenter.present()
var mode: SendLocationState.Mode by remember { var mode: SendLocationState.Mode by remember {
mutableStateOf( mutableStateOf(
if (permissionsState.isAnyGranted) SendLocationState.Mode.SenderLocation if (permissionsState.isAnyGranted) {
else SendLocationState.Mode.PinLocation SendLocationState.Mode.SenderLocation
} else {
SendLocationState.Mode.PinLocation
}
) )
} }
val appName by remember { derivedStateOf { buildMeta.applicationName } } val appName by remember { derivedStateOf { buildMeta.applicationName } }

View file

@ -75,7 +75,6 @@ class SendLocationPresenterTest {
moleculeFlow(RecompositionMode.Immediate) { moleculeFlow(RecompositionMode.Immediate) {
sendLocationPresenter.present() sendLocationPresenter.present()
}.test { }.test {
val initialState = awaitItem() val initialState = awaitItem()
assertThat(initialState.permissionDialog).isEqualTo(SendLocationState.Dialog.None) assertThat(initialState.permissionDialog).isEqualTo(SendLocationState.Dialog.None)
assertThat(initialState.mode).isEqualTo(SendLocationState.Mode.SenderLocation) assertThat(initialState.mode).isEqualTo(SendLocationState.Mode.SenderLocation)
@ -102,7 +101,6 @@ class SendLocationPresenterTest {
moleculeFlow(RecompositionMode.Immediate) { moleculeFlow(RecompositionMode.Immediate) {
sendLocationPresenter.present() sendLocationPresenter.present()
}.test { }.test {
val initialState = awaitItem() val initialState = awaitItem()
assertThat(initialState.permissionDialog).isEqualTo(SendLocationState.Dialog.None) assertThat(initialState.permissionDialog).isEqualTo(SendLocationState.Dialog.None)
assertThat(initialState.mode).isEqualTo(SendLocationState.Mode.SenderLocation) assertThat(initialState.mode).isEqualTo(SendLocationState.Mode.SenderLocation)
@ -381,7 +379,9 @@ class SendLocationPresenterTest {
) )
fakeMessageComposerContext.apply { fakeMessageComposerContext.apply {
composerMode = MessageComposerMode.Edit( composerMode = MessageComposerMode.Edit(
eventId = null, defaultContent = "", transactionId = null eventId = null,
defaultContent = "",
transactionId = null
) )
} }
@ -427,7 +427,9 @@ class SendLocationPresenterTest {
) )
fakeMessageComposerContext.apply { fakeMessageComposerContext.apply {
composerMode = MessageComposerMode.Edit( composerMode = MessageComposerMode.Edit(
eventId = null, defaultContent = "", transactionId = null eventId = null,
defaultContent = "",
transactionId = null
) )
} }

View file

@ -28,7 +28,6 @@ import javax.inject.Inject
class DefaultLockScreenEntryPoint @Inject constructor() : LockScreenEntryPoint { class DefaultLockScreenEntryPoint @Inject constructor() : LockScreenEntryPoint {
override fun nodeBuilder(parentNode: Node, buildContext: BuildContext): LockScreenEntryPoint.NodeBuilder { override fun nodeBuilder(parentNode: Node, buildContext: BuildContext): LockScreenEntryPoint.NodeBuilder {
var innerTarget: LockScreenEntryPoint.Target = LockScreenEntryPoint.Target.Unlock var innerTarget: LockScreenEntryPoint.Target = LockScreenEntryPoint.Target.Unlock
val callbacks = mutableListOf<LockScreenEntryPoint.Callback>() val callbacks = mutableListOf<LockScreenEntryPoint.Callback>()

View file

@ -95,7 +95,7 @@ class DefaultLockScreenService @Inject constructor(
override suspend fun onSessionCreated(userId: String) = Unit override suspend fun onSessionCreated(userId: String) = Unit
override suspend fun onSessionDeleted(userId: String) { override suspend fun onSessionDeleted(userId: String) {
//TODO handle multi session at some point // TODO handle multi session at some point
pinCodeManager.deletePinCode() pinCodeManager.deletePinCode()
} }
}) })

View file

@ -66,15 +66,15 @@ class DefaultBiometricUnlockManager @Inject constructor(
* Returns true if a weak biometric method (i.e.: some face or iris unlock implementations) can be used. * Returns true if a weak biometric method (i.e.: some face or iris unlock implementations) can be used.
*/ */
private val canUseWeakBiometricAuth: Boolean private val canUseWeakBiometricAuth: Boolean
get() = lockScreenConfig.isWeakBiometricsEnabled get() = lockScreenConfig.isWeakBiometricsEnabled &&
&& biometricManager.canAuthenticate(BiometricManager.Authenticators.BIOMETRIC_WEAK) == BiometricManager.BIOMETRIC_SUCCESS biometricManager.canAuthenticate(BiometricManager.Authenticators.BIOMETRIC_WEAK) == BiometricManager.BIOMETRIC_SUCCESS
/** /**
* Returns true if a strong biometric method (i.e.: fingerprint, some face or iris unlock implementations) can be used. * Returns true if a strong biometric method (i.e.: fingerprint, some face or iris unlock implementations) can be used.
*/ */
private val canUseStrongBiometricAuth: Boolean private val canUseStrongBiometricAuth: Boolean
get() = lockScreenConfig.isStrongBiometricsEnabled get() = lockScreenConfig.isStrongBiometricsEnabled &&
&& biometricManager.canAuthenticate(BiometricManager.Authenticators.BIOMETRIC_STRONG) == BiometricManager.BIOMETRIC_SUCCESS biometricManager.canAuthenticate(BiometricManager.Authenticators.BIOMETRIC_STRONG) == BiometricManager.BIOMETRIC_SUCCESS
/** /**
* Returns true if any biometric method (weak or strong) can be used. * Returns true if any biometric method (weak or strong) can be used.

View file

@ -34,12 +34,12 @@ import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.text.input.KeyboardType import androidx.compose.ui.text.input.KeyboardType
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import io.element.android.compound.theme.ElementTheme
import io.element.android.features.lockscreen.impl.pin.model.PinDigit import io.element.android.features.lockscreen.impl.pin.model.PinDigit
import io.element.android.features.lockscreen.impl.pin.model.PinEntry import io.element.android.features.lockscreen.impl.pin.model.PinEntry
import io.element.android.libraries.designsystem.preview.ElementPreview import io.element.android.libraries.designsystem.preview.ElementPreview
import io.element.android.libraries.designsystem.preview.PreviewsDayNight import io.element.android.libraries.designsystem.preview.PreviewsDayNight
import io.element.android.libraries.designsystem.theme.pinDigitBg import io.element.android.libraries.designsystem.theme.pinDigitBg
import io.element.android.compound.theme.ElementTheme
@Composable @Composable
fun PinEntryTextField( fun PinEntryTextField(
@ -100,7 +100,7 @@ private fun PinDigitView(
.then(appearanceModifier), .then(appearanceModifier),
contentAlignment = Alignment.Center, contentAlignment = Alignment.Center,
) { ) {
if (digit is PinDigit.Filled) { if (digit is PinDigit.Filled) {
val text = if (isSecured) { val text = if (isSecured) {
"" ""
@ -112,7 +112,6 @@ private fun PinDigitView(
style = ElementTheme.typography.fontHeadingMdBold style = ElementTheme.typography.fontHeadingMdBold
) )
} }
} }
} }

View file

@ -125,7 +125,6 @@ class LockScreenSettingsFlowNode @AssistedInject constructor(
createNode<LockScreenSettingsNode>(buildContext, plugins = listOf(callback)) createNode<LockScreenSettingsNode>(buildContext, plugins = listOf(callback))
} }
NavTarget.Unknown -> node(buildContext) { } NavTarget.Unknown -> node(buildContext) { }
} }
} }

View file

@ -20,6 +20,7 @@ import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.res.stringResource import androidx.compose.ui.res.stringResource
import androidx.compose.ui.tooling.preview.PreviewParameter import androidx.compose.ui.tooling.preview.PreviewParameter
import io.element.android.compound.theme.ElementTheme
import io.element.android.features.lockscreen.impl.R import io.element.android.features.lockscreen.impl.R
import io.element.android.libraries.designsystem.components.dialogs.ConfirmationDialog import io.element.android.libraries.designsystem.components.dialogs.ConfirmationDialog
import io.element.android.libraries.designsystem.components.preferences.PreferenceCategory import io.element.android.libraries.designsystem.components.preferences.PreferenceCategory
@ -29,7 +30,6 @@ import io.element.android.libraries.designsystem.components.preferences.Preferen
import io.element.android.libraries.designsystem.components.preferences.PreferenceText import io.element.android.libraries.designsystem.components.preferences.PreferenceText
import io.element.android.libraries.designsystem.preview.ElementPreview import io.element.android.libraries.designsystem.preview.ElementPreview
import io.element.android.libraries.designsystem.preview.PreviewsDayNight import io.element.android.libraries.designsystem.preview.PreviewsDayNight
import io.element.android.compound.theme.ElementTheme
@Composable @Composable
fun LockScreenSettingsView( fun LockScreenSettingsView(
@ -79,7 +79,8 @@ fun LockScreenSettingsView(
}, },
onDismiss = { onDismiss = {
state.eventSink(LockScreenSettingsEvents.CancelRemovePin) state.eventSink(LockScreenSettingsEvents.CancelRemovePin)
}) }
)
} }
} }

View file

@ -33,7 +33,6 @@ class SetupBiometricPresenter @Inject constructor(
@Composable @Composable
override fun present(): SetupBiometricState { override fun present(): SetupBiometricState {
var isBiometricSetupDone by remember { var isBiometricSetupDone by remember {
mutableStateOf(false) mutableStateOf(false)
} }

View file

@ -97,4 +97,3 @@ internal fun SetupBiometricViewPreview(@PreviewParameter(SetupBiometricStateProv
) )
} }
} }

View file

@ -58,4 +58,3 @@ fun aSetupPinState(
appName = "Element", appName = "Element",
eventSink = {} eventSink = {}
) )

View file

@ -42,5 +42,4 @@ interface EncryptedPinCodeStorage {
* Returns whether the PIN code is stored or not. * Returns whether the PIN code is stored or not.
*/ */
fun hasPinCode(): Flow<Boolean> fun hasPinCode(): Flow<Boolean>
} }

View file

@ -38,9 +38,9 @@ data class PinUnlockState(
} }
val biometricUnlockErrorMessage = when { val biometricUnlockErrorMessage = when {
biometricUnlockResult is BiometricUnlock.AuthenticationResult.Failure biometricUnlockResult is BiometricUnlock.AuthenticationResult.Failure &&
&& biometricUnlockResult.error is BiometricUnlockError biometricUnlockResult.error is BiometricUnlockError &&
&& biometricUnlockResult.error.isAuthDisabledError -> { biometricUnlockResult.error.isAuthDisabledError -> {
biometricUnlockResult.error.message biometricUnlockResult.error.message
} }
else -> null else -> null

View file

@ -14,7 +14,6 @@
* limitations under the License. * limitations under the License.
*/ */
package io.element.android.features.lockscreen.impl.unlock package io.element.android.features.lockscreen.impl.unlock
import androidx.compose.foundation.background import androidx.compose.foundation.background
@ -51,6 +50,7 @@ import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.tooling.preview.PreviewParameter import androidx.compose.ui.tooling.preview.PreviewParameter
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import androidx.lifecycle.Lifecycle import androidx.lifecycle.Lifecycle
import io.element.android.compound.theme.ElementTheme
import io.element.android.features.lockscreen.impl.R import io.element.android.features.lockscreen.impl.R
import io.element.android.features.lockscreen.impl.components.PinEntryTextField import io.element.android.features.lockscreen.impl.components.PinEntryTextField
import io.element.android.features.lockscreen.impl.pin.model.PinDigit import io.element.android.features.lockscreen.impl.pin.model.PinDigit
@ -68,7 +68,6 @@ import io.element.android.libraries.designsystem.theme.components.Surface
import io.element.android.libraries.designsystem.theme.components.Text import io.element.android.libraries.designsystem.theme.components.Text
import io.element.android.libraries.designsystem.theme.components.TextButton import io.element.android.libraries.designsystem.theme.components.TextButton
import io.element.android.libraries.designsystem.utils.OnLifecycleEvent import io.element.android.libraries.designsystem.utils.OnLifecycleEvent
import io.element.android.compound.theme.ElementTheme
import io.element.android.libraries.ui.strings.CommonStrings import io.element.android.libraries.ui.strings.CommonStrings
@Composable @Composable
@ -378,4 +377,3 @@ internal fun PinUnlockDefaultViewPreview(@PreviewParameter(PinUnlockStateProvide
) )
} }
} }

View file

@ -41,11 +41,11 @@ import androidx.compose.ui.unit.coerceAtMost
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp import androidx.compose.ui.unit.sp
import androidx.compose.ui.unit.times import androidx.compose.ui.unit.times
import io.element.android.compound.theme.ElementTheme
import io.element.android.libraries.designsystem.preview.ElementPreview import io.element.android.libraries.designsystem.preview.ElementPreview
import io.element.android.libraries.designsystem.preview.PreviewsDayNight import io.element.android.libraries.designsystem.preview.PreviewsDayNight
import io.element.android.libraries.designsystem.text.toSp import io.element.android.libraries.designsystem.text.toSp
import io.element.android.libraries.designsystem.theme.components.Icon import io.element.android.libraries.designsystem.theme.components.Icon
import io.element.android.compound.theme.ElementTheme
import kotlinx.collections.immutable.ImmutableList import kotlinx.collections.immutable.ImmutableList
import kotlinx.collections.immutable.persistentListOf import kotlinx.collections.immutable.persistentListOf
@ -210,5 +210,3 @@ internal fun PinKeypadPreview() {
} }
} }
} }

View file

@ -116,7 +116,7 @@ class SetupPinPresenterTest {
} }
} }
private fun SetupPinState.onPinEntryChanged(pinEntry: String){ private fun SetupPinState.onPinEntryChanged(pinEntry: String) {
eventSink(SetupPinEvents.OnPinEntryChanged(pinEntry, isConfirmationStep)) eventSink(SetupPinEvents.OnPinEntryChanged(pinEntry, isConfirmationStep))
} }

View file

@ -25,8 +25,7 @@ import kotlinx.coroutines.flow.asStateFlow
import javax.inject.Inject import javax.inject.Inject
@SingleIn(AppScope::class) @SingleIn(AppScope::class)
class AccountProviderDataSource @Inject constructor( class AccountProviderDataSource @Inject constructor() {
) {
private val accountProvider: MutableStateFlow<AccountProvider> = MutableStateFlow( private val accountProvider: MutableStateFlow<AccountProvider> = MutableStateFlow(
defaultAccountProvider defaultAccountProvider
) )

View file

@ -50,9 +50,11 @@ fun AccountProviderView(
modifier: Modifier = Modifier, modifier: Modifier = Modifier,
onClick: () -> Unit, onClick: () -> Unit,
) { ) {
Column(modifier = modifier Column(
.fillMaxWidth() modifier = modifier
.clickable { onClick() }) { .fillMaxWidth()
.clickable { onClick() }
) {
HorizontalDivider() HorizontalDivider()
Column( Column(
modifier = Modifier modifier = Modifier

View file

@ -54,9 +54,11 @@ fun ChangeServerView(
onLearnMoreClicked = { onLearnMoreClicked = {
onLearnMoreClicked() onLearnMoreClicked()
eventSink.invoke(ChangeServerEvents.ClearError) eventSink.invoke(ChangeServerEvents.ClearError)
}, onDismiss = { },
eventSink.invoke(ChangeServerEvents.ClearError) onDismiss = {
}) eventSink.invoke(ChangeServerEvents.ClearError)
}
)
} }
} }
} }

View file

@ -20,6 +20,6 @@ import io.element.android.features.login.api.oidc.OidcAction
sealed interface OidcEvents { sealed interface OidcEvents {
data object Cancel : OidcEvents data object Cancel : OidcEvents
data class OidcActionEvent(val oidcAction: OidcAction): OidcEvents data class OidcActionEvent(val oidcAction: OidcAction) : OidcEvents
data object ClearError : OidcEvents data object ClearError : OidcEvents
} }

View file

@ -90,9 +90,9 @@ class HomeserverResolver @Inject constructor(
if (data.contains(".")) { if (data.contains(".")) {
// TLD detected? // TLD detected?
} else { } else {
add("${data}.org") add("$data.org")
add("${data}.com") add("$data.com")
add("${data}.io") add("$data.io")
} }
// Always try what the user has entered // Always try what the user has entered
add(data) add(data)

View file

@ -30,6 +30,6 @@ import kotlinx.serialization.Serializable
*/ */
@Serializable @Serializable
data class WellKnownBaseConfig( data class WellKnownBaseConfig(
@SerialName("base_url") @SerialName("base_url")
val baseURL: String? = null val baseURL: String? = null
) )

View file

@ -21,6 +21,6 @@ import kotlinx.serialization.Serializable
@Serializable @Serializable
data class WellKnownSlidingSyncConfig( data class WellKnownSlidingSyncConfig(
@SerialName("url") @SerialName("url")
val url: String? = null, val url: String? = null,
) )

View file

@ -220,7 +220,9 @@ private fun LoginForm(
Icon(imageVector = CompoundIcons.Close, contentDescription = stringResource(CommonStrings.action_clear)) Icon(imageVector = CompoundIcons.Close, contentDescription = stringResource(CommonStrings.action_clear))
} }
} }
} else null, } else {
null
},
) )
var passwordVisible by remember { mutableStateOf(false) } var passwordVisible by remember { mutableStateOf(false) }

View file

@ -144,7 +144,9 @@ fun SearchAccountProviderView(
) )
} }
} }
} else null, } else {
null
},
supportingText = { supportingText = {
Text(text = stringResource(id = R.string.screen_account_provider_form_notice), color = MaterialTheme.colorScheme.secondary) Text(text = stringResource(id = R.string.screen_account_provider_form_notice), color = MaterialTheme.colorScheme.secondary)
} }

View file

@ -140,7 +140,6 @@ private fun OverallContent(
.padding(bottom = 8.dp), .padding(bottom = 8.dp),
) )
} }
} }
} }

View file

@ -43,4 +43,3 @@ class DefaultLogoutEntryPoint @Inject constructor() : LogoutEntryPoint {
} }
} }
} }

View file

@ -25,8 +25,8 @@ import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberCoroutineScope import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.runtime.setValue import androidx.compose.runtime.setValue
import io.element.android.libraries.architecture.AsyncData
import io.element.android.libraries.architecture.AsyncAction import io.element.android.libraries.architecture.AsyncAction
import io.element.android.libraries.architecture.AsyncData
import io.element.android.libraries.architecture.Presenter import io.element.android.libraries.architecture.Presenter
import io.element.android.libraries.architecture.runCatchingUpdatingState import io.element.android.libraries.architecture.runCatchingUpdatingState
import io.element.android.libraries.core.bool.orTrue import io.element.android.libraries.core.bool.orTrue

View file

@ -213,4 +213,3 @@ class LogoutPresenterTest {
featureFlagService = FakeFeatureFlagService(mapOf(FeatureFlags.SecureStorage.key to true)), featureFlagService = FakeFeatureFlagService(mapOf(FeatureFlags.SecureStorage.key to true)),
) )
} }

View file

@ -194,4 +194,3 @@ class DefaultDirectLogoutPresenterTest {
featureFlagService = FakeFeatureFlagService(mapOf(FeatureFlags.SecureStorage.key to true)), featureFlagService = FakeFeatureFlagService(mapOf(FeatureFlags.SecureStorage.key to true)),
) )
} }

View file

@ -152,7 +152,8 @@ internal fun ExpandableBottomSheetScaffold(
top.place(x = 0, y = 0) top.place(x = 0, y = 0)
} }
}, },
content = { sheetContent(false) }) content = { sheetContent(false) }
)
}, sheetDragHandle, peekHeight) }, sheetDragHandle, peekHeight)
}.map { measurable: Measurable -> }.map { measurable: Measurable ->
measurable.measure(constraints) measurable.measure(constraints)
@ -161,7 +162,8 @@ internal fun ExpandableBottomSheetScaffold(
layout(constraints.maxWidth, constraints.maxHeight) { layout(constraints.maxWidth, constraints.maxHeight) {
scaffoldPlaceable.place(0, 0) scaffoldPlaceable.place(0, 0)
} }
}) }
)
} }
private fun CustomSheetState.getIntOffset(): Int? = try { private fun CustomSheetState.getIntOffset(): Int? = try {

View file

@ -32,13 +32,13 @@ import io.element.android.features.messages.impl.timeline.di.LocalTimelineItemPr
import io.element.android.features.messages.impl.timeline.di.TimelineItemPresenterFactories import io.element.android.features.messages.impl.timeline.di.TimelineItemPresenterFactories
import io.element.android.features.messages.impl.timeline.model.TimelineItem import io.element.android.features.messages.impl.timeline.model.TimelineItem
import io.element.android.libraries.core.bool.orFalse import io.element.android.libraries.core.bool.orFalse
import io.element.android.libraries.mediaplayer.api.MediaPlayer
import io.element.android.libraries.di.RoomScope import io.element.android.libraries.di.RoomScope
import io.element.android.libraries.matrix.api.core.EventId import io.element.android.libraries.matrix.api.core.EventId
import io.element.android.libraries.matrix.api.core.RoomId import io.element.android.libraries.matrix.api.core.RoomId
import io.element.android.libraries.matrix.api.core.UserId import io.element.android.libraries.matrix.api.core.UserId
import io.element.android.libraries.matrix.api.room.MatrixRoom import io.element.android.libraries.matrix.api.room.MatrixRoom
import io.element.android.libraries.matrix.api.timeline.item.TimelineItemDebugInfo import io.element.android.libraries.matrix.api.timeline.item.TimelineItemDebugInfo
import io.element.android.libraries.mediaplayer.api.MediaPlayer
import io.element.android.services.analytics.api.AnalyticsService import io.element.android.services.analytics.api.AnalyticsService
import io.element.android.services.analytics.api.extensions.toAnalyticsViewRoom import io.element.android.services.analytics.api.extensions.toAnalyticsViewRoom
import kotlinx.collections.immutable.ImmutableList import kotlinx.collections.immutable.ImmutableList

View file

@ -172,9 +172,10 @@ private fun SheetContent(
item { item {
Column { Column {
MessageSummary( MessageSummary(
event = target.event, modifier = Modifier event = target.event,
.fillMaxWidth() modifier = Modifier
.padding(horizontal = 16.dp) .fillMaxWidth()
.padding(horizontal = 16.dp)
) )
Spacer(modifier = Modifier.height(14.dp)) Spacer(modifier = Modifier.height(14.dp))
HorizontalDivider() HorizontalDivider()
@ -299,7 +300,11 @@ private fun EmojiReactionsRow(
) { ) {
// TODO use most recently used emojis here when available from the Rust SDK // TODO use most recently used emojis here when available from the Rust SDK
val defaultEmojis = sequenceOf( val defaultEmojis = sequenceOf(
"👍️", "👎️", "🔥", "❤️", "👏" "👍️",
"👎️",
"🔥",
"❤️",
"👏"
) )
for (emoji in defaultEmojis) { for (emoji in defaultEmojis) {
val isHighlighted = highlightedEmojis.contains(emoji) val isHighlighted = highlightedEmojis.contains(emoji)

View file

@ -48,7 +48,6 @@ class AttachmentsPreviewPresenter @AssistedInject constructor(
@Composable @Composable
override fun present(): AttachmentsPreviewState { override fun present(): AttachmentsPreviewState {
val coroutineScope = rememberCoroutineScope() val coroutineScope = rememberCoroutineScope()
val sendActionState = remember { val sendActionState = remember {

View file

@ -34,4 +34,3 @@ sealed interface SendActionState {
data class Failure(val error: Throwable) : SendActionState data class Failure(val error: Throwable) : SendActionState
data object Done : SendActionState data object Done : SendActionState
} }

View file

@ -36,7 +36,8 @@ open class AttachmentsPreviewStateProvider : PreviewParameterProvider<Attachment
fun anAttachmentsPreviewState( fun anAttachmentsPreviewState(
mediaInfo: MediaInfo = anImageInfo(), mediaInfo: MediaInfo = anImageInfo(),
sendActionState: SendActionState = SendActionState.Idle) = AttachmentsPreviewState( sendActionState: SendActionState = SendActionState.Idle
) = AttachmentsPreviewState(
attachment = Attachment.Media( attachment = Attachment.Media(
localMedia = LocalMedia("file://path".toUri(), mediaInfo), localMedia = LocalMedia("file://path".toUri(), mediaInfo),
compressIfPossible = true compressIfPossible = true

View file

@ -48,7 +48,6 @@ fun AttachmentsPreviewView(
onDismiss: () -> Unit, onDismiss: () -> Unit,
modifier: Modifier = Modifier, modifier: Modifier = Modifier,
) { ) {
fun postSendAttachment() { fun postSendAttachment() {
state.eventSink(AttachmentsPreviewEvents.SendAttachment) state.eventSink(AttachmentsPreviewEvents.SendAttachment)
} }
@ -88,7 +87,6 @@ private fun AttachmentSendStateView(
onDismissClicked: () -> Unit, onDismissClicked: () -> Unit,
onRetryClicked: () -> Unit onRetryClicked: () -> Unit
) { ) {
when (sendActionState) { when (sendActionState) {
is SendActionState.Sending -> { is SendActionState.Sending -> {
ProgressDialog( ProgressDialog(

View file

@ -88,8 +88,8 @@ object MentionSuggestionsProcessor {
} }
fun memberMatchesQuery(member: RoomMember, query: String): Boolean { fun memberMatchesQuery(member: RoomMember, query: String): Boolean {
return member.userId.value.contains(query, ignoreCase = true) return member.userId.value.contains(query, ignoreCase = true) ||
|| member.displayName?.contains(query, ignoreCase = true) == true member.displayName?.contains(query, ignoreCase = true) == true
} }
val matchingMembers = roomMembers val matchingMembers = roomMembers

View file

@ -62,12 +62,12 @@ internal fun AttachmentsBottomSheet(
} }
LaunchedEffect(state.showAttachmentSourcePicker) { LaunchedEffect(state.showAttachmentSourcePicker) {
if (state.showAttachmentSourcePicker) { isVisible = if (state.showAttachmentSourcePicker) {
// We need to use this instead of `LocalFocusManager.clearFocus()` to hide the keyboard when focus is on an Android View // We need to use this instead of `LocalFocusManager.clearFocus()` to hide the keyboard when focus is on an Android View
localView.hideKeyboard() localView.hideKeyboard()
isVisible = true true
} else { } else {
isVisible = false false
} }
} }
// Send 'DismissAttachmentMenu' event when the bottomsheet was just hidden // Send 'DismissAttachmentMenu' event when the bottomsheet was just hidden
@ -122,7 +122,7 @@ private fun AttachmentSourcePickerMenu(
) )
ListItem( ListItem(
modifier = Modifier.clickable { state.eventSink(MessageComposerEvents.PickAttachmentSource.PhotoFromCamera) }, modifier = Modifier.clickable { state.eventSink(MessageComposerEvents.PickAttachmentSource.PhotoFromCamera) },
leadingContent = ListItemContent.Icon(IconSource.Resource(CommonDrawables.ic_take_photo_camera, )), leadingContent = ListItemContent.Icon(IconSource.Resource(CommonDrawables.ic_take_photo_camera)),
headlineContent = { Text(stringResource(R.string.screen_room_attachment_source_camera_photo)) }, headlineContent = { Text(stringResource(R.string.screen_room_attachment_source_camera_photo)) },
style = ListItemStyle.Primary, style = ListItemStyle.Primary,
) )

View file

@ -456,4 +456,3 @@ class MessageComposerPresenter @Inject constructor(
} }
} }
} }

View file

@ -35,4 +35,3 @@ class DefaultRichTextEditorStateFactory @Inject constructor() : RichTextEditorSt
return rememberRichTextEditorState() return rememberRichTextEditorState()
} }
} }

View file

@ -39,7 +39,7 @@ import javax.inject.Inject
@ContributesBinding(SessionScope::class) @ContributesBinding(SessionScope::class)
@SingleIn(SessionScope::class) @SingleIn(SessionScope::class)
class DefaultHtmlConverterProvider @Inject constructor(): HtmlConverterProvider { class DefaultHtmlConverterProvider @Inject constructor() : HtmlConverterProvider {
private val htmlConverter: MutableState<HtmlConverter?> = mutableStateOf(null) private val htmlConverter: MutableState<HtmlConverter?> = mutableStateOf(null)
@ -67,7 +67,7 @@ class DefaultHtmlConverterProvider @Inject constructor(): HtmlConverterProvider
return TextDisplay.Custom(mentionSpanProvider.getMentionSpanFor(text, url)) return TextDisplay.Custom(mentionSpanProvider.getMentionSpanFor(text, url))
} }
}, },
isMention = { _, url -> mentionDetector?.isMention(url).orFalse() } isMention = { _, url -> mentionDetector?.isMention(url).orFalse() }
).apply { ).apply {
configureWith(editorStyle) configureWith(editorStyle)
} }

View file

@ -179,7 +179,9 @@ internal fun aTimelineItemDebugInfo(
originalJson: String? = null, originalJson: String? = null,
latestEditedJson: String? = null, latestEditedJson: String? = null,
) = TimelineItemDebugInfo( ) = TimelineItemDebugInfo(
model, originalJson, latestEditedJson model,
originalJson,
latestEditedJson
) )
internal fun aTimelineItemReadReceipts(): TimelineItemReadReceipts { internal fun aTimelineItemReadReceipts(): TimelineItemReadReceipts {

View file

@ -120,8 +120,8 @@ fun TimelineView(
timelineItem = timelineItem, timelineItem = timelineItem,
timelineRoomInfo = state.timelineRoomInfo, timelineRoomInfo = state.timelineRoomInfo,
showReadReceipts = state.showReadReceipts, showReadReceipts = state.showReadReceipts,
isLastOutgoingMessage = (timelineItem as? TimelineItem.Event)?.isMine == true isLastOutgoingMessage = (timelineItem as? TimelineItem.Event)?.isMine == true &&
&& state.timelineItems.first().identifier() == timelineItem.identifier(), state.timelineItems.first().identifier() == timelineItem.identifier(),
highlightedItem = state.highlightedEventId?.value, highlightedItem = state.highlightedEventId?.value,
onClick = onMessageClicked, onClick = onMessageClicked,
onLongClick = onMessageLongClicked, onLongClick = onMessageLongClicked,

View file

@ -165,8 +165,7 @@ private fun ReactionContent(
model = MediaRequestData(MediaSource(reaction.key), MediaRequestData.Kind.Content), model = MediaRequestData(MediaSource(reaction.key), MediaRequestData.Kind.Content),
contentDescription = null contentDescription = null
) )
} } else {
else {
Text( Text(
text = reaction.displayKey, text = reaction.displayKey,
style = ElementTheme.typography.fontBodyMdRegular.copy( style = ElementTheme.typography.fontBodyMdRegular.copy(
@ -225,4 +224,3 @@ internal fun MessagesReactionExtraButtonsPreview() = ElementPreview {
) )
} }
} }

View file

@ -25,8 +25,8 @@ import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.graphicsLayer import androidx.compose.ui.graphics.graphicsLayer
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import io.element.android.libraries.designsystem.preview.PreviewsDayNight
import io.element.android.libraries.designsystem.preview.ElementPreview import io.element.android.libraries.designsystem.preview.ElementPreview
import io.element.android.libraries.designsystem.preview.PreviewsDayNight
import io.element.android.libraries.designsystem.theme.components.Icon import io.element.android.libraries.designsystem.theme.components.Icon
import io.element.android.libraries.designsystem.utils.CommonDrawables import io.element.android.libraries.designsystem.utils.CommonDrawables

View file

@ -419,7 +419,6 @@ private fun MessageEventBubbleContent(
@Suppress("ModifierNaming") @Suppress("ModifierNaming")
bubbleModifier: Modifier = Modifier, // need to rename this modifier to prevent linter false positives bubbleModifier: Modifier = Modifier, // need to rename this modifier to prevent linter false positives
) { ) {
// Long clicks are not not automatically propagated from a `clickable` // Long clicks are not not automatically propagated from a `clickable`
// to its `combinedClickable` parent so we do it manually // to its `combinedClickable` parent so we do it manually
fun onTimestampLongClick() = onMessageLongClick() fun onTimestampLongClick() = onMessageLongClick()
@ -578,7 +577,6 @@ private fun MessageEventBubbleContent(
.clip(RoundedCornerShape(6.dp)) .clip(RoundedCornerShape(6.dp))
.clickable(enabled = true, onClick = inReplyToClick), .clickable(enabled = true, onClick = inReplyToClick),
) )
} }
if (inReplyToDetails != null) { if (inReplyToDetails != null) {
// Use SubComposeLayout only if necessary as it can have consequences on the performance. // Use SubComposeLayout only if necessary as it can have consequences on the performance.
@ -669,7 +667,7 @@ internal fun TimelineItemEventRowPreview() = ElementPreview {
isMine = it, isMine = it,
content = aTimelineItemTextContent().copy( content = aTimelineItemTextContent().copy(
body = "A long text which will be displayed on several lines and" + body = "A long text which will be displayed on several lines and" +
" hopefully can be manually adjusted to test different behaviors." " hopefully can be manually adjusted to test different behaviors."
), ),
groupPosition = TimelineItemGroupPosition.First, groupPosition = TimelineItemGroupPosition.First,
), ),

View file

@ -59,4 +59,3 @@ internal fun TimelineItemEventRowForDirectRoomPreview() = ElementPreview {
} }
} }
} }

View file

@ -42,4 +42,3 @@ internal fun TimelineItemEventRowWithManyReactionsPreview() = ElementPreview {
} }
} }
} }

View file

@ -24,8 +24,8 @@ import androidx.compose.runtime.saveable.rememberSaveable
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.res.pluralStringResource import androidx.compose.ui.res.pluralStringResource
import io.element.android.features.messages.impl.R import io.element.android.features.messages.impl.R
import io.element.android.features.messages.impl.timeline.TimelineRoomInfo
import io.element.android.features.messages.impl.timeline.TimelineEvents import io.element.android.features.messages.impl.timeline.TimelineEvents
import io.element.android.features.messages.impl.timeline.TimelineRoomInfo
import io.element.android.features.messages.impl.timeline.aGroupedEvents import io.element.android.features.messages.impl.timeline.aGroupedEvents
import io.element.android.features.messages.impl.timeline.aTimelineRoomInfo import io.element.android.features.messages.impl.timeline.aTimelineRoomInfo
import io.element.android.features.messages.impl.timeline.components.group.GroupHeaderView import io.element.android.features.messages.impl.timeline.components.group.GroupHeaderView

View file

@ -117,7 +117,7 @@ fun TimelineItemReactionsLayout(
return rows return rows
} }
/// Given a list of rows place them in the layout. // Given a list of rows place them in the layout.
fun layoutRows(rows: List<List<Placeable>>): MeasureResult { fun layoutRows(rows: List<List<Placeable>>): MeasureResult {
var width = 0 var width = 0
var height = 0 var height = 0

Some files were not shown because too many files have changed in this diff Show more