Browse Source

Delete cached avatar URI

feature/jme/open-room-member-details-when-clicking-on-user-data
Florian Renaud 1 year ago
parent
commit
929ebc79c5
  1. 3
      features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/CreateRoomConfig.kt
  2. 12
      features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/CreateRoomDataStore.kt
  3. 21
      features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/configureroom/ConfigureRoomPresenter.kt
  4. 3
      features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/configureroom/ConfigureRoomView.kt
  5. 21
      features/createroom/impl/src/test/kotlin/io/element/android/features/createroom/impl/configureroom/ConfigureRoomPresenterTests.kt

3
features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/CreateRoomConfig.kt

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

12
features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/CreateRoomDataStore.kt

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

21
features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/configureroom/ConfigureRoomPresenter.kt

@ -56,20 +56,21 @@ class ConfigureRoomPresenter @Inject constructor(
} }
} }
val cameraPhotoPicker = mediaPickerProvider.registerCameraPhotoPicker(onResult = { uri -> val cameraPhotoPicker = mediaPickerProvider.registerCameraPhotoPicker(
if (uri != null) dataStore.setAvatarUrl(uri.toString()) onResult = { uri -> if (uri != null) dataStore.setAvatarUri(uri = uri, cached = true) },
}) deleteAfter = false,
val galleryImagePicker = mediaPickerProvider.registerGalleryImagePicker(onResult = { uri -> )
if (uri != null) dataStore.setAvatarUrl(uri.toString()) 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 { derivedStateOf {
mutableListOf( mutableListOf(
AvatarAction.TakePhoto, AvatarAction.TakePhoto,
AvatarAction.ChoosePhoto, AvatarAction.ChoosePhoto,
).apply { ).apply {
if (createRoomConfig.value.avatarUrl != null) { if (createRoomConfig.value.avatarUri != null) {
add(AvatarAction.Remove) add(AvatarAction.Remove)
} }
}.toImmutableList() }.toImmutableList()
@ -95,7 +96,7 @@ class ConfigureRoomPresenter @Inject constructor(
when (event.action) { when (event.action) {
AvatarAction.ChoosePhoto -> galleryImagePicker.launch() AvatarAction.ChoosePhoto -> galleryImagePicker.launch()
AvatarAction.TakePhoto -> cameraPhotoPicker.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, visibility = if (config.privacy == RoomPrivacy.Public) RoomVisibility.PUBLIC else RoomVisibility.PRIVATE,
preset = if (config.privacy == RoomPrivacy.Public) RoomPreset.PUBLIC_CHAT else RoomPreset.PRIVATE_CHAT, preset = if (config.privacy == RoomPrivacy.Public) RoomPreset.PUBLIC_CHAT else RoomPreset.PRIVATE_CHAT,
invite = config.invites.map { it.userId }, invite = config.invites.map { it.userId },
avatar = config.avatarUrl, avatar = config.avatarUri?.toString(),
) )
matrixClient.createRoom(params).getOrThrow() matrixClient.createRoom(params).getOrThrow()
}.execute(createRoomAction) }.execute(createRoomAction)

3
features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/configureroom/ConfigureRoomView.kt

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

21
features/createroom/impl/src/test/kotlin/io/element/android/features/createroom/impl/configureroom/ConfigureRoomPresenterTests.kt

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

Loading…
Cancel
Save