upload avatar within the room creation
This commit is contained in:
parent
17dd489e6a
commit
27f6f5cd3b
5 changed files with 44 additions and 15 deletions
|
|
@ -47,6 +47,7 @@ dependencies {
|
|||
implementation(projects.libraries.uiStrings)
|
||||
implementation(projects.features.userlist.api)
|
||||
implementation(projects.libraries.mediapickers.api)
|
||||
implementation(projects.libraries.mediaupload.api)
|
||||
implementation(libs.coil.compose)
|
||||
api(projects.features.createroom.api)
|
||||
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@
|
|||
|
||||
package io.element.android.features.createroom.impl.configureroom
|
||||
|
||||
import android.net.Uri
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.MutableState
|
||||
import androidx.compose.runtime.collectAsState
|
||||
|
|
@ -30,12 +31,16 @@ import io.element.android.features.createroom.impl.configureroom.avatar.AvatarAc
|
|||
import io.element.android.libraries.architecture.Async
|
||||
import io.element.android.libraries.architecture.Presenter
|
||||
import io.element.android.libraries.architecture.execute
|
||||
import io.element.android.libraries.core.mimetype.MimeTypes
|
||||
import io.element.android.libraries.matrix.api.MatrixClient
|
||||
import io.element.android.libraries.matrix.api.core.RoomId
|
||||
import io.element.android.libraries.matrix.api.createroom.CreateRoomParameters
|
||||
import io.element.android.libraries.matrix.api.createroom.RoomPreset
|
||||
import io.element.android.libraries.matrix.api.createroom.RoomVisibility
|
||||
import io.element.android.libraries.mediapickers.api.PickerProvider
|
||||
import io.element.android.libraries.mediaupload.api.MediaPreProcessor
|
||||
import io.element.android.libraries.mediaupload.api.MediaType
|
||||
import io.element.android.libraries.mediaupload.api.MediaUploadInfo
|
||||
import kotlinx.collections.immutable.toImmutableList
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.launch
|
||||
|
|
@ -45,6 +50,7 @@ class ConfigureRoomPresenter @Inject constructor(
|
|||
private val dataStore: CreateRoomDataStore,
|
||||
private val matrixClient: MatrixClient,
|
||||
private val mediaPickerProvider: PickerProvider,
|
||||
private val mediaPreProcessor: MediaPreProcessor,
|
||||
) : Presenter<ConfigureRoomState> {
|
||||
|
||||
@Composable
|
||||
|
|
@ -112,9 +118,12 @@ class ConfigureRoomPresenter @Inject constructor(
|
|||
)
|
||||
}
|
||||
|
||||
private fun CoroutineScope.createRoom(config: CreateRoomConfig, createRoomAction: MutableState<Async<RoomId>>) = launch {
|
||||
private fun CoroutineScope.createRoom(
|
||||
config: CreateRoomConfig,
|
||||
createRoomAction: MutableState<Async<RoomId>>
|
||||
) = launch {
|
||||
val mxc = config.avatarUri?.let { uploadAvatar(it) }
|
||||
suspend {
|
||||
// TODO pre-process and upload the avatar before creating the room
|
||||
val params = CreateRoomParameters(
|
||||
name = config.roomName,
|
||||
topic = config.topic,
|
||||
|
|
@ -123,9 +132,15 @@ class ConfigureRoomPresenter @Inject constructor(
|
|||
visibility = if (config.privacy == RoomPrivacy.Public) RoomVisibility.PUBLIC else RoomVisibility.PRIVATE,
|
||||
preset = if (config.privacy == RoomPrivacy.Public) RoomPreset.PUBLIC_CHAT else RoomPreset.PRIVATE_CHAT,
|
||||
invite = config.invites.map { it.userId },
|
||||
avatar = config.avatarUri?.toString(),
|
||||
avatar = mxc,
|
||||
)
|
||||
matrixClient.createRoom(params).getOrThrow()
|
||||
}.execute(createRoomAction)
|
||||
}
|
||||
|
||||
private suspend fun uploadAvatar(avatarUri: Uri): String? {
|
||||
val preprocessed = mediaPreProcessor.process(avatarUri, MediaType.Image).getOrThrow() as? MediaUploadInfo.Image
|
||||
val byteArray = preprocessed?.file?.readBytes()
|
||||
return byteArray?.let { matrixClient.uploadMedia(MimeTypes.Jpeg, it) }?.getOrThrow()
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -42,6 +42,7 @@ interface MatrixClient : Closeable {
|
|||
suspend fun createRoom(createRoomParams: CreateRoomParameters): Result<RoomId>
|
||||
suspend fun createDM(userId: UserId): Result<RoomId>
|
||||
suspend fun getProfile(userId: UserId): Result<MatrixUser>
|
||||
suspend fun searchUsers(searchTerm: String, limit: Long): Result<MatrixSearchUserResults>
|
||||
fun startSync()
|
||||
fun stopSync()
|
||||
fun mediaResolver(): MediaResolver
|
||||
|
|
@ -58,9 +59,10 @@ interface MatrixClient : Closeable {
|
|||
height: Long
|
||||
): Result<ByteArray>
|
||||
|
||||
suspend fun uploadMedia(mimeType: String, data: ByteArray): Result<String>
|
||||
|
||||
fun onSlidingSyncUpdate()
|
||||
|
||||
fun roomMembershipObserver(): RoomMembershipObserver
|
||||
|
||||
suspend fun searchUsers(searchTerm: String, limit: Long): Result<MatrixSearchUserResults>
|
||||
}
|
||||
|
|
|
|||
|
|
@ -280,6 +280,13 @@ class RustMatrixClient constructor(
|
|||
}
|
||||
}
|
||||
|
||||
override suspend fun searchUsers(searchTerm: String, limit: Long): Result<MatrixSearchUserResults> =
|
||||
withContext(dispatchers.io) {
|
||||
runCatching {
|
||||
client.searchUsers(searchTerm, limit.toULong()).let(UserSearchResultMapper::map)
|
||||
}
|
||||
}
|
||||
|
||||
override fun mediaResolver(): MediaResolver = mediaResolver
|
||||
|
||||
override fun sessionVerificationService(): SessionVerificationService = verificationService
|
||||
|
|
@ -368,6 +375,13 @@ class RustMatrixClient constructor(
|
|||
}
|
||||
}
|
||||
|
||||
@OptIn(ExperimentalUnsignedTypes::class)
|
||||
override suspend fun uploadMedia(mimeType: String, data: ByteArray): Result<String> = withContext(dispatchers.io) {
|
||||
runCatching {
|
||||
client.uploadMedia(mimeType, data.toUByteArray().toList())
|
||||
}
|
||||
}
|
||||
|
||||
override fun onSlidingSyncUpdate() {
|
||||
if (!verificationService.isReady.value) {
|
||||
try {
|
||||
|
|
@ -380,13 +394,6 @@ class RustMatrixClient constructor(
|
|||
|
||||
override fun roomMembershipObserver(): RoomMembershipObserver = roomMembershipObserver
|
||||
|
||||
override suspend fun searchUsers(searchTerm: String, limit: Long): Result<MatrixSearchUserResults> =
|
||||
withContext(dispatchers.io) {
|
||||
runCatching {
|
||||
client.searchUsers(searchTerm, limit.toULong()).let(UserSearchResultMapper::map)
|
||||
}
|
||||
}
|
||||
|
||||
private fun File.deleteSessionDirectory(userID: String): Boolean {
|
||||
// Rust sanitises the user ID replacing invalid characters with an _
|
||||
val sanitisedUserID = userID.replace(":", "_")
|
||||
|
|
|
|||
|
|
@ -91,6 +91,10 @@ class FakeMatrixClient(
|
|||
return getProfileResults[userId] ?: Result.failure(IllegalStateException("No profile found for $userId"))
|
||||
}
|
||||
|
||||
override suspend fun searchUsers(searchTerm: String, limit: Long): Result<MatrixSearchUserResults> {
|
||||
return searchUserResults[searchTerm] ?: Result.failure(IllegalStateException("No response defined for $searchTerm"))
|
||||
}
|
||||
|
||||
override fun startSync() = Unit
|
||||
|
||||
override fun stopSync() = Unit
|
||||
|
|
@ -122,6 +126,10 @@ class FakeMatrixClient(
|
|||
return Result.success(ByteArray(0))
|
||||
}
|
||||
|
||||
override suspend fun uploadMedia(mimeType: String, data: ByteArray): Result<String> {
|
||||
return Result.success("")
|
||||
}
|
||||
|
||||
override fun sessionVerificationService(): SessionVerificationService = sessionVerificationService
|
||||
|
||||
override fun pushersService(): PushersService = pushersService
|
||||
|
|
@ -134,10 +142,6 @@ class FakeMatrixClient(
|
|||
return RoomMembershipObserver()
|
||||
}
|
||||
|
||||
override suspend fun searchUsers(searchTerm: String, limit: Long): Result<MatrixSearchUserResults> {
|
||||
return searchUserResults[searchTerm] ?: Result.failure(IllegalStateException("No response defined for $searchTerm"))
|
||||
}
|
||||
|
||||
// Mocks
|
||||
|
||||
fun givenLogoutError(failure: Throwable?) {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue