Delete cached avatar URI

This commit is contained in:
Florian Renaud
2023-05-10 11:08:43 +02:00
parent 554ce9f650
commit a38fbb3419
5 changed files with 40 additions and 20 deletions

View File

@@ -16,6 +16,7 @@
package io.element.android.features.createroom.impl
import android.net.Uri
import io.element.android.features.createroom.impl.configureroom.RoomPrivacy
import io.element.android.libraries.matrix.api.user.MatrixUser
import kotlinx.collections.immutable.ImmutableList
@@ -24,7 +25,7 @@ import kotlinx.collections.immutable.persistentListOf
data class CreateRoomConfig(
val roomName: String? = null,
val topic: String? = null,
val avatarUrl: String? = null,
val avatarUri: Uri? = null,
val invites: ImmutableList<MatrixUser> = persistentListOf(),
val privacy: RoomPrivacy? = null,
)

View File

@@ -16,6 +16,7 @@
package io.element.android.features.createroom.impl
import android.net.Uri
import io.element.android.features.createroom.impl.configureroom.RoomPrivacy
import io.element.android.features.createroom.impl.di.CreateRoomScope
import io.element.android.features.userlist.api.UserListDataStore
@@ -24,6 +25,7 @@ import kotlinx.collections.immutable.toImmutableList
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.combine
import java.io.File
import javax.inject.Inject
@SingleIn(CreateRoomScope::class)
@@ -32,6 +34,11 @@ class CreateRoomDataStore @Inject constructor(
) {
private val createRoomConfigFlow: MutableStateFlow<CreateRoomConfig> = MutableStateFlow(CreateRoomConfig())
private var cachedAvatarUri: Uri? = null
set(value) {
field?.path?.let { File(it) }?.delete()
field = value
}
fun getCreateRoomConfig(): Flow<CreateRoomConfig> = combine(
selectedUserListDataStore.selectedUsers(),
@@ -48,8 +55,9 @@ class CreateRoomDataStore @Inject constructor(
createRoomConfigFlow.tryEmit(createRoomConfigFlow.value.copy(topic = topic?.takeIf { it.isNotEmpty() }))
}
fun setAvatarUrl(avatarUrl: String?) {
createRoomConfigFlow.tryEmit(createRoomConfigFlow.value.copy(avatarUrl = avatarUrl))
fun setAvatarUri(uri: Uri?, cached: Boolean = false) {
cachedAvatarUri = uri.takeIf { cached }
createRoomConfigFlow.tryEmit(createRoomConfigFlow.value.copy(avatarUri = uri))
}
fun setPrivacy(privacy: RoomPrivacy?) {

View File

@@ -56,20 +56,21 @@ class ConfigureRoomPresenter @Inject constructor(
}
}
val cameraPhotoPicker = mediaPickerProvider.registerCameraPhotoPicker(onResult = { uri ->
if (uri != null) dataStore.setAvatarUrl(uri.toString())
})
val galleryImagePicker = mediaPickerProvider.registerGalleryImagePicker(onResult = { uri ->
if (uri != null) dataStore.setAvatarUrl(uri.toString())
})
val cameraPhotoPicker = mediaPickerProvider.registerCameraPhotoPicker(
onResult = { uri -> if (uri != null) dataStore.setAvatarUri(uri = uri, cached = true) },
deleteAfter = false,
)
val galleryImagePicker = mediaPickerProvider.registerGalleryImagePicker(
onResult = { uri -> if (uri != null) dataStore.setAvatarUri(uri = uri) }
)
val avatarActions by remember(createRoomConfig.value.avatarUrl) {
val avatarActions by remember(createRoomConfig.value.avatarUri) {
derivedStateOf {
mutableListOf(
AvatarAction.TakePhoto,
AvatarAction.ChoosePhoto,
).apply {
if (createRoomConfig.value.avatarUrl != null) {
if (createRoomConfig.value.avatarUri != null) {
add(AvatarAction.Remove)
}
}.toImmutableList()
@@ -95,7 +96,7 @@ class ConfigureRoomPresenter @Inject constructor(
when (event.action) {
AvatarAction.ChoosePhoto -> galleryImagePicker.launch()
AvatarAction.TakePhoto -> cameraPhotoPicker.launch()
AvatarAction.Remove -> dataStore.setAvatarUrl(null)
AvatarAction.Remove -> dataStore.setAvatarUri(uri = null)
}
}
@@ -122,7 +123,7 @@ 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.avatarUrl,
avatar = config.avatarUri?.toString(),
)
matrixClient.createRoom(params).getOrThrow()
}.execute(createRoomAction)

View File

@@ -41,7 +41,6 @@ import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.tooling.preview.PreviewParameter
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import androidx.core.net.toUri
import io.element.android.features.createroom.impl.R
import io.element.android.features.createroom.impl.components.Avatar
import io.element.android.features.createroom.impl.components.LabelledTextField
@@ -104,7 +103,7 @@ fun ConfigureRoomView(
) {
RoomNameWithAvatar(
modifier = Modifier.padding(horizontal = 16.dp),
avatarUri = state.config.avatarUrl?.toUri(),
avatarUri = state.config.avatarUri,
roomName = state.config.roomName.orEmpty(),
onAvatarClick = ::onAvatarClicked,
onRoomNameChanged = { state.eventSink(ConfigureRoomEvents.RoomNameChanged(it)) },

View File

@@ -25,6 +25,7 @@ import app.cash.turbine.test
import com.google.common.truth.Truth.assertThat
import io.element.android.features.createroom.impl.CreateRoomConfig
import io.element.android.features.createroom.impl.CreateRoomDataStore
import io.element.android.features.createroom.impl.configureroom.avatar.AvatarAction
import io.element.android.features.userlist.api.UserListDataStore
import io.element.android.libraries.architecture.Async
import io.element.android.libraries.matrix.api.core.RoomId
@@ -34,6 +35,7 @@ import io.element.android.libraries.matrix.test.A_ROOM_NAME
import io.element.android.libraries.matrix.test.A_THROWABLE
import io.element.android.libraries.matrix.test.FakeMatrixClient
import io.element.android.libraries.matrix.ui.components.aMatrixUser
import io.element.android.libraries.mediapickers.PickerProvider
import kotlinx.collections.immutable.persistentListOf
import kotlinx.collections.immutable.toImmutableList
import kotlinx.coroutines.ExperimentalCoroutinesApi
@@ -48,15 +50,18 @@ class ConfigureRoomPresenterTests {
private lateinit var presenter: ConfigureRoomPresenter
private lateinit var userListDataStore: UserListDataStore
private lateinit var createRoomDataStore: CreateRoomDataStore
private lateinit var fakeMatrixClient: FakeMatrixClient
@Before
fun setup() {
fakeMatrixClient = FakeMatrixClient()
userListDataStore = UserListDataStore()
createRoomDataStore = CreateRoomDataStore(userListDataStore)
presenter = ConfigureRoomPresenter(
dataStore = CreateRoomDataStore(userListDataStore),
matrixClient = fakeMatrixClient
dataStore = createRoomDataStore,
matrixClient = fakeMatrixClient,
mediaPickerProvider = PickerProvider(isInTest = true),
)
}
@@ -70,7 +75,7 @@ class ConfigureRoomPresenterTests {
assertThat(initialState.config.roomName).isNull()
assertThat(initialState.config.topic).isNull()
assertThat(initialState.config.invites).isEmpty()
assertThat(initialState.config.avatarUrl).isNull()
assertThat(initialState.config.avatarUri).isNull()
assertThat(initialState.config.privacy).isNull()
}
}
@@ -139,10 +144,16 @@ class ConfigureRoomPresenterTests {
assertThat(newState.config).isEqualTo(expectedConfig)
// Room avatar
// Add
val anUri = Uri.parse(AN_AVATAR_URL)
newState.eventSink(ConfigureRoomEvents.AvatarUriChanged(anUri))
createRoomDataStore.setAvatarUri(anUri)
newState = awaitItem()
expectedConfig = expectedConfig.copy(avatarUrl = anUri.toString())
expectedConfig = expectedConfig.copy(avatarUri = anUri)
assertThat(newState.config).isEqualTo(expectedConfig)
// Remove
newState.eventSink(ConfigureRoomEvents.HandleAvatarAction(AvatarAction.Remove))
newState = awaitItem()
expectedConfig = expectedConfig.copy(avatarUri = null)
assertThat(newState.config).isEqualTo(expectedConfig)
// Room privacy