From e7714da8e8f65b8764daf762f9e3b9d4cf2df04a Mon Sep 17 00:00:00 2001 From: Onuray Sahin Date: Wed, 4 Nov 2020 16:32:25 +0300 Subject: [PATCH 1/3] Navigate to an existing DM instead of creating a new one. --- CHANGES.md | 1 + .../createdirect/CreateDirectRoomViewModel.kt | 26 ++++++++++++++++++- 2 files changed, 26 insertions(+), 1 deletion(-) diff --git a/CHANGES.md b/CHANGES.md index 79ea40de59..31dd8388e0 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -39,6 +39,7 @@ Improvements 🙌: - Add graphic resources for F-Droid (#812, #2220) - Highlight text in the body of the displayed result (#2200) - Considerably faster QR-code bitmap generation (#2331) + - Open an existing DM instead of creating a new one (#2319) Bugfix 🐛: - Fixed ringtone handling (#2100 & #2246) diff --git a/vector/src/main/java/im/vector/app/features/createdirect/CreateDirectRoomViewModel.kt b/vector/src/main/java/im/vector/app/features/createdirect/CreateDirectRoomViewModel.kt index c42e10686f..7d8b8c0c82 100644 --- a/vector/src/main/java/im/vector/app/features/createdirect/CreateDirectRoomViewModel.kt +++ b/vector/src/main/java/im/vector/app/features/createdirect/CreateDirectRoomViewModel.kt @@ -19,6 +19,7 @@ package im.vector.app.features.createdirect import androidx.lifecycle.viewModelScope import com.airbnb.mvrx.ActivityViewModelContext import com.airbnb.mvrx.MvRxViewModelFactory +import com.airbnb.mvrx.Success import com.airbnb.mvrx.ViewModelContext import com.squareup.inject.assisted.Assisted import com.squareup.inject.assisted.AssistedInject @@ -56,10 +57,33 @@ class CreateDirectRoomViewModel @AssistedInject constructor(@Assisted override fun handle(action: CreateDirectRoomAction) { when (action) { - is CreateDirectRoomAction.CreateRoomAndInviteSelectedUsers -> createRoomAndInviteSelectedUsers(action.invitees) + is CreateDirectRoomAction.CreateRoomAndInviteSelectedUsers -> onSubmitInvitees(action.invitees) } } + /** + * If users already have a DM room then navigate to it instead of creating a new room. + */ + private fun onSubmitInvitees(invitees: Set) { + invitees + .takeIf { it.size == 1 } + ?.first() + ?.let { invitee -> + when (invitee) { + is PendingInvitee.UserPendingInvitee -> session.getExistingDirectRoomWithUser(invitee.user.userId) + is PendingInvitee.ThreePidPendingInvitee -> null + }.exhaustive + } + ?.let { roomId -> + setState { + copy(createAndInviteState = Success(roomId)) + } + } + ?: run { + createRoomAndInviteSelectedUsers(invitees) + } + } + private fun createRoomAndInviteSelectedUsers(invitees: Set) { viewModelScope.launch(Dispatchers.IO) { val adminE2EByDefault = rawService.getElementWellknown(session.myUserId) From 458b4259fe0950c4c14734113292eebcfa627798 Mon Sep 17 00:00:00 2001 From: Onuray Sahin Date: Wed, 4 Nov 2020 17:51:31 +0300 Subject: [PATCH 2/3] Change menu action title for existing rooms. --- .../createdirect/CreateDirectRoomActivity.kt | 3 ++- .../userdirectory/KnownUsersFragment.kt | 3 +++ .../userdirectory/KnownUsersFragmentArgs.kt | 3 ++- .../userdirectory/UserDirectoryViewModel.kt | 27 +++++++++++++++++-- .../userdirectory/UserDirectoryViewState.kt | 3 ++- 5 files changed, 34 insertions(+), 5 deletions(-) diff --git a/vector/src/main/java/im/vector/app/features/createdirect/CreateDirectRoomActivity.kt b/vector/src/main/java/im/vector/app/features/createdirect/CreateDirectRoomActivity.kt index a1bb12a84b..3dfd93bea7 100644 --- a/vector/src/main/java/im/vector/app/features/createdirect/CreateDirectRoomActivity.kt +++ b/vector/src/main/java/im/vector/app/features/createdirect/CreateDirectRoomActivity.kt @@ -91,7 +91,8 @@ class CreateDirectRoomActivity : SimpleFragmentActivity() { KnownUsersFragment::class.java, KnownUsersFragmentArgs( title = getString(R.string.fab_menu_create_chat), - menuResId = R.menu.vector_create_direct_room + menuResId = R.menu.vector_create_direct_room, + isCreatingRoom = true ) ) } diff --git a/vector/src/main/java/im/vector/app/features/userdirectory/KnownUsersFragment.kt b/vector/src/main/java/im/vector/app/features/userdirectory/KnownUsersFragment.kt index c832fe4833..17e619d990 100644 --- a/vector/src/main/java/im/vector/app/features/userdirectory/KnownUsersFragment.kt +++ b/vector/src/main/java/im/vector/app/features/userdirectory/KnownUsersFragment.kt @@ -91,6 +91,9 @@ class KnownUsersFragment @Inject constructor( val showMenuItem = it.pendingInvitees.isNotEmpty() menu.forEach { menuItem -> menuItem.isVisible = showMenuItem + if (args.isCreatingRoom) { + menuItem.setTitle(if (it.isThereAnExistingRoom) R.string.action_open else R.string.create_room_action_create) + } } } super.onPrepareOptionsMenu(menu) diff --git a/vector/src/main/java/im/vector/app/features/userdirectory/KnownUsersFragmentArgs.kt b/vector/src/main/java/im/vector/app/features/userdirectory/KnownUsersFragmentArgs.kt index 65fd6681bf..c20aedb803 100644 --- a/vector/src/main/java/im/vector/app/features/userdirectory/KnownUsersFragmentArgs.kt +++ b/vector/src/main/java/im/vector/app/features/userdirectory/KnownUsersFragmentArgs.kt @@ -23,5 +23,6 @@ import kotlinx.android.parcel.Parcelize data class KnownUsersFragmentArgs( val title: String, val menuResId: Int, - val excludedUserIds: Set? = null + val excludedUserIds: Set? = null, + val isCreatingRoom: Boolean = false ) : Parcelable diff --git a/vector/src/main/java/im/vector/app/features/userdirectory/UserDirectoryViewModel.kt b/vector/src/main/java/im/vector/app/features/userdirectory/UserDirectoryViewModel.kt index b8c42a0f08..a924280da3 100644 --- a/vector/src/main/java/im/vector/app/features/userdirectory/UserDirectoryViewModel.kt +++ b/vector/src/main/java/im/vector/app/features/userdirectory/UserDirectoryViewModel.kt @@ -87,14 +87,37 @@ class UserDirectoryViewModel @AssistedInject constructor(@Assisted private fun handleRemoveSelectedUser(action: UserDirectoryAction.RemovePendingInvitee) = withState { state -> val selectedUsers = state.pendingInvitees.minus(action.pendingInvitee) - setState { copy(pendingInvitees = selectedUsers) } + setState { + copy( + pendingInvitees = selectedUsers, + isThereAnExistingRoom = isThereAnExistingRoom(selectedUsers) + ) + } } private fun handleSelectUser(action: UserDirectoryAction.SelectPendingInvitee) = withState { state -> // Reset the filter asap directoryUsersSearch.accept("") val selectedUsers = state.pendingInvitees.toggle(action.pendingInvitee) - setState { copy(pendingInvitees = selectedUsers) } + setState { + copy( + pendingInvitees = selectedUsers, + isThereAnExistingRoom = isThereAnExistingRoom(selectedUsers) + ) + } + } + + private fun isThereAnExistingRoom(selectedUsers: Set): Boolean { + return selectedUsers + .takeIf { it.size == 1 } + ?.firstOrNull() + ?.let { invitee -> + return when (invitee) { + is PendingInvitee.UserPendingInvitee -> session.getExistingDirectRoomWithUser(invitee.user.userId) != null + is PendingInvitee.ThreePidPendingInvitee -> false + }.exhaustive + } + ?: false } private fun observeDirectoryUsers() = withState { state -> diff --git a/vector/src/main/java/im/vector/app/features/userdirectory/UserDirectoryViewState.kt b/vector/src/main/java/im/vector/app/features/userdirectory/UserDirectoryViewState.kt index 8bb555e0fa..3d2cd0c1b4 100644 --- a/vector/src/main/java/im/vector/app/features/userdirectory/UserDirectoryViewState.kt +++ b/vector/src/main/java/im/vector/app/features/userdirectory/UserDirectoryViewState.kt @@ -30,7 +30,8 @@ data class UserDirectoryViewState( val pendingInvitees: Set = emptySet(), val createAndInviteState: Async = Uninitialized, val directorySearchTerm: String = "", - val filterKnownUsersValue: Option = Option.empty() + val filterKnownUsersValue: Option = Option.empty(), + val isThereAnExistingRoom: Boolean = false ) : MvRxState { constructor(args: KnownUsersFragmentArgs) : this(excludedUserIds = args.excludedUserIds) From 12d8bd17433bd2248408f12db989592eb650019b Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Thu, 5 Nov 2020 17:34:10 +0100 Subject: [PATCH 3/3] Cleanup after rebase - avoid computing twice the existing roomId --- CHANGES.md | 3 +- .../createdirect/CreateDirectRoomAction.kt | 5 ++- .../createdirect/CreateDirectRoomActivity.kt | 5 ++- .../createdirect/CreateDirectRoomViewModel.kt | 32 +++++++------------ .../userdirectory/KnownUsersFragment.kt | 8 +++-- .../UserDirectorySharedAction.kt | 4 ++- .../userdirectory/UserDirectoryViewModel.kt | 15 +++------ .../userdirectory/UserDirectoryViewState.kt | 2 +- 8 files changed, 36 insertions(+), 38 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index 31dd8388e0..fa30acabd5 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -5,7 +5,7 @@ Features ✨: - Improvements 🙌: - - + - Open an existing DM instead of creating a new one (#2319) Bugfix 🐛: - Fix issue when updating the avatar of a room @@ -39,7 +39,6 @@ Improvements 🙌: - Add graphic resources for F-Droid (#812, #2220) - Highlight text in the body of the displayed result (#2200) - Considerably faster QR-code bitmap generation (#2331) - - Open an existing DM instead of creating a new one (#2319) Bugfix 🐛: - Fixed ringtone handling (#2100 & #2246) diff --git a/vector/src/main/java/im/vector/app/features/createdirect/CreateDirectRoomAction.kt b/vector/src/main/java/im/vector/app/features/createdirect/CreateDirectRoomAction.kt index f6fc3fed5b..ce91761fdd 100644 --- a/vector/src/main/java/im/vector/app/features/createdirect/CreateDirectRoomAction.kt +++ b/vector/src/main/java/im/vector/app/features/createdirect/CreateDirectRoomAction.kt @@ -20,5 +20,8 @@ import im.vector.app.core.platform.VectorViewModelAction import im.vector.app.features.userdirectory.PendingInvitee sealed class CreateDirectRoomAction : VectorViewModelAction { - data class CreateRoomAndInviteSelectedUsers(val invitees: Set) : CreateDirectRoomAction() + data class CreateRoomAndInviteSelectedUsers( + val invitees: Set, + val existingDmRoomId: String? + ) : CreateDirectRoomAction() } diff --git a/vector/src/main/java/im/vector/app/features/createdirect/CreateDirectRoomActivity.kt b/vector/src/main/java/im/vector/app/features/createdirect/CreateDirectRoomActivity.kt index 3dfd93bea7..10ab1673e4 100644 --- a/vector/src/main/java/im/vector/app/features/createdirect/CreateDirectRoomActivity.kt +++ b/vector/src/main/java/im/vector/app/features/createdirect/CreateDirectRoomActivity.kt @@ -122,7 +122,10 @@ class CreateDirectRoomActivity : SimpleFragmentActivity() { private fun onMenuItemSelected(action: UserDirectorySharedAction.OnMenuItemSelected) { if (action.itemId == R.id.action_create_direct_room) { - viewModel.handle(CreateDirectRoomAction.CreateRoomAndInviteSelectedUsers(action.invitees)) + viewModel.handle(CreateDirectRoomAction.CreateRoomAndInviteSelectedUsers( + action.invitees, + action.existingDmRoomId + )) } } diff --git a/vector/src/main/java/im/vector/app/features/createdirect/CreateDirectRoomViewModel.kt b/vector/src/main/java/im/vector/app/features/createdirect/CreateDirectRoomViewModel.kt index 7d8b8c0c82..be9449b77a 100644 --- a/vector/src/main/java/im/vector/app/features/createdirect/CreateDirectRoomViewModel.kt +++ b/vector/src/main/java/im/vector/app/features/createdirect/CreateDirectRoomViewModel.kt @@ -57,31 +57,23 @@ class CreateDirectRoomViewModel @AssistedInject constructor(@Assisted override fun handle(action: CreateDirectRoomAction) { when (action) { - is CreateDirectRoomAction.CreateRoomAndInviteSelectedUsers -> onSubmitInvitees(action.invitees) - } + is CreateDirectRoomAction.CreateRoomAndInviteSelectedUsers -> onSubmitInvitees(action) + }.exhaustive } /** * If users already have a DM room then navigate to it instead of creating a new room. */ - private fun onSubmitInvitees(invitees: Set) { - invitees - .takeIf { it.size == 1 } - ?.first() - ?.let { invitee -> - when (invitee) { - is PendingInvitee.UserPendingInvitee -> session.getExistingDirectRoomWithUser(invitee.user.userId) - is PendingInvitee.ThreePidPendingInvitee -> null - }.exhaustive - } - ?.let { roomId -> - setState { - copy(createAndInviteState = Success(roomId)) - } - } - ?: run { - createRoomAndInviteSelectedUsers(invitees) - } + private fun onSubmitInvitees(action: CreateDirectRoomAction.CreateRoomAndInviteSelectedUsers) { + if (action.existingDmRoomId != null) { + // Do not create a new DM, just tell that the creation is successful by passing the existing roomId + setState { + copy(createAndInviteState = Success(action.existingDmRoomId)) + } + } else { + // Create the DM + createRoomAndInviteSelectedUsers(action.invitees) + } } private fun createRoomAndInviteSelectedUsers(invitees: Set) { diff --git a/vector/src/main/java/im/vector/app/features/userdirectory/KnownUsersFragment.kt b/vector/src/main/java/im/vector/app/features/userdirectory/KnownUsersFragment.kt index 17e619d990..0ca46cd154 100644 --- a/vector/src/main/java/im/vector/app/features/userdirectory/KnownUsersFragment.kt +++ b/vector/src/main/java/im/vector/app/features/userdirectory/KnownUsersFragment.kt @@ -92,7 +92,7 @@ class KnownUsersFragment @Inject constructor( menu.forEach { menuItem -> menuItem.isVisible = showMenuItem if (args.isCreatingRoom) { - menuItem.setTitle(if (it.isThereAnExistingRoom) R.string.action_open else R.string.create_room_action_create) + menuItem.setTitle(if (it.existingDmRoomId != null) R.string.action_open else R.string.create_room_action_create) } } } @@ -100,7 +100,11 @@ class KnownUsersFragment @Inject constructor( } override fun onOptionsItemSelected(item: MenuItem): Boolean = withState(viewModel) { - sharedActionViewModel.post(UserDirectorySharedAction.OnMenuItemSelected(item.itemId, it.pendingInvitees)) + sharedActionViewModel.post(UserDirectorySharedAction.OnMenuItemSelected( + item.itemId, + it.pendingInvitees, + it.existingDmRoomId + )) return@withState true } diff --git a/vector/src/main/java/im/vector/app/features/userdirectory/UserDirectorySharedAction.kt b/vector/src/main/java/im/vector/app/features/userdirectory/UserDirectorySharedAction.kt index a4ae0d1be2..14daa67f25 100644 --- a/vector/src/main/java/im/vector/app/features/userdirectory/UserDirectorySharedAction.kt +++ b/vector/src/main/java/im/vector/app/features/userdirectory/UserDirectorySharedAction.kt @@ -23,5 +23,7 @@ sealed class UserDirectorySharedAction : VectorSharedAction { object OpenPhoneBook : UserDirectorySharedAction() object Close : UserDirectorySharedAction() object GoBack : UserDirectorySharedAction() - data class OnMenuItemSelected(val itemId: Int, val invitees: Set) : UserDirectorySharedAction() + data class OnMenuItemSelected(val itemId: Int, + val invitees: Set, + val existingDmRoomId: String?) : UserDirectorySharedAction() } diff --git a/vector/src/main/java/im/vector/app/features/userdirectory/UserDirectoryViewModel.kt b/vector/src/main/java/im/vector/app/features/userdirectory/UserDirectoryViewModel.kt index a924280da3..0a24b85ce2 100644 --- a/vector/src/main/java/im/vector/app/features/userdirectory/UserDirectoryViewModel.kt +++ b/vector/src/main/java/im/vector/app/features/userdirectory/UserDirectoryViewModel.kt @@ -90,7 +90,7 @@ class UserDirectoryViewModel @AssistedInject constructor(@Assisted setState { copy( pendingInvitees = selectedUsers, - isThereAnExistingRoom = isThereAnExistingRoom(selectedUsers) + existingDmRoomId = getExistingDmRoomId(selectedUsers) ) } } @@ -102,22 +102,17 @@ class UserDirectoryViewModel @AssistedInject constructor(@Assisted setState { copy( pendingInvitees = selectedUsers, - isThereAnExistingRoom = isThereAnExistingRoom(selectedUsers) + existingDmRoomId = getExistingDmRoomId(selectedUsers) ) } } - private fun isThereAnExistingRoom(selectedUsers: Set): Boolean { + private fun getExistingDmRoomId(selectedUsers: Set): String? { return selectedUsers .takeIf { it.size == 1 } + ?.filterIsInstance(PendingInvitee.UserPendingInvitee::class.java) ?.firstOrNull() - ?.let { invitee -> - return when (invitee) { - is PendingInvitee.UserPendingInvitee -> session.getExistingDirectRoomWithUser(invitee.user.userId) != null - is PendingInvitee.ThreePidPendingInvitee -> false - }.exhaustive - } - ?: false + ?.let { invitee -> session.getExistingDirectRoomWithUser(invitee.user.userId) } } private fun observeDirectoryUsers() = withState { state -> diff --git a/vector/src/main/java/im/vector/app/features/userdirectory/UserDirectoryViewState.kt b/vector/src/main/java/im/vector/app/features/userdirectory/UserDirectoryViewState.kt index 3d2cd0c1b4..fe79a8ab37 100644 --- a/vector/src/main/java/im/vector/app/features/userdirectory/UserDirectoryViewState.kt +++ b/vector/src/main/java/im/vector/app/features/userdirectory/UserDirectoryViewState.kt @@ -31,7 +31,7 @@ data class UserDirectoryViewState( val createAndInviteState: Async = Uninitialized, val directorySearchTerm: String = "", val filterKnownUsersValue: Option = Option.empty(), - val isThereAnExistingRoom: Boolean = false + val existingDmRoomId: String? = null ) : MvRxState { constructor(args: KnownUsersFragmentArgs) : this(excludedUserIds = args.excludedUserIds)