Delete cached avatar URI
This commit is contained in:
parent
554ce9f650
commit
a38fbb3419
5 changed files with 40 additions and 20 deletions
|
|
@ -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,
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -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?) {
|
||||||
|
|
|
||||||
|
|
@ -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)
|
||||||
|
|
|
||||||
|
|
@ -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)) },
|
||||||
|
|
|
||||||
|
|
@ -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…
Add table
Add a link
Reference in a new issue