From 4dba8018aede4045cc578edf839fec83fda5ebad Mon Sep 17 00:00:00 2001 From: yostyle Date: Fri, 24 Feb 2023 18:27:30 +0100 Subject: [PATCH 1/7] create encrypted DM for user invite by email --- .../src/main/res/values/strings.xml | 2 + .../RoomDisplayNameFallbackProvider.kt | 2 +- .../room/create/CreateRoomBodyBuilder.kt | 4 +- .../membership/RoomDisplayNameResolver.kt | 2 +- .../createdirect/CreateDirectRoomViewModel.kt | 2 +- .../home/room/detail/TimelineFragment.kt | 6 +++ .../timeline/factory/EncryptionItemFactory.kt | 43 +++++++++++++------ .../timeline/item/MergedRoomCreationItem.kt | 33 +++++++++----- .../timeline/item/StatusTileTimelineItem.kt | 2 + .../VectorRoomDisplayNameFallbackProvider.kt | 4 +- 10 files changed, 68 insertions(+), 32 deletions(-) diff --git a/library/ui-strings/src/main/res/values/strings.xml b/library/ui-strings/src/main/res/values/strings.xml index 2ee623cf883..7990e1cf931 100644 --- a/library/ui-strings/src/main/res/values/strings.xml +++ b/library/ui-strings/src/main/res/values/strings.xml @@ -2561,6 +2561,8 @@ Messages in this room are end-to-end encrypted. Learn more & verify users in their profile. Messages in this chat are end-to-end encrypted. Messages in this chat will be end-to-end encrypted. + Waiting for users to join ${app_name} + Once all users invited have joined ${app_name}, you will able to chat and the room will be end to end encrypted. Encryption not enabled Encryption is misconfigured The encryption used by this room is not supported diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/provider/RoomDisplayNameFallbackProvider.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/provider/RoomDisplayNameFallbackProvider.kt index 37d9b46b0ba..a945c3da330 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/provider/RoomDisplayNameFallbackProvider.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/provider/RoomDisplayNameFallbackProvider.kt @@ -26,7 +26,7 @@ package org.matrix.android.sdk.api.provider */ interface RoomDisplayNameFallbackProvider { fun getNameForRoomInvite(): String - fun getNameForEmptyRoom(isDirect: Boolean, leftMemberNames: List): String + fun getNameForEmptyRoom(isDirect: Boolean, directUserId: String?, leftMemberNames: List): String fun getNameFor1member(name: String): String fun getNameFor2members(name1: String, name2: String): String fun getNameFor3members(name1: String, name2: String, name3: String): String diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/create/CreateRoomBodyBuilder.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/create/CreateRoomBodyBuilder.kt index 4105c77cc85..92081885af5 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/create/CreateRoomBodyBuilder.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/create/CreateRoomBodyBuilder.kt @@ -190,10 +190,8 @@ internal class CreateRoomBodyBuilder @Inject constructor( private suspend fun canEnableEncryption(params: CreateRoomParams): Boolean { return params.enableEncryptionIfInvitedUsersSupportIt && // Parity with web, enable if users have encryption ready devices - // for now remove checks on cross signing and 3pid invites + // for now remove checks on cross signing // && crossSigningService.isCrossSigningVerified() - params.invite3pids.isEmpty() && - params.invitedUserIds.isNotEmpty() && params.invitedUserIds.let { userIds -> val keys = deviceListManager.downloadKeys(userIds, forceDownload = false) diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/membership/RoomDisplayNameResolver.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/membership/RoomDisplayNameResolver.kt index 4645bb05ab3..5f28c581e25 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/membership/RoomDisplayNameResolver.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/membership/RoomDisplayNameResolver.kt @@ -115,7 +115,7 @@ internal class RoomDisplayNameResolver @Inject constructor( val leftMembersNames = roomMembers.queryLeftRoomMembersEvent() .findAll() .map { displayNameResolver.getBestName(it.toMatrixItem()) } - roomDisplayNameFallbackProvider.getNameForEmptyRoom(roomSummary?.isDirect.orFalse(), leftMembersNames) + roomDisplayNameFallbackProvider.getNameForEmptyRoom(roomSummary?.isDirect.orFalse(), roomSummary?.directUserId, leftMembersNames) } 1 -> { roomDisplayNameFallbackProvider.getNameFor1member( 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 3f67708a28f..dce1e63766e 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 @@ -124,7 +124,7 @@ class CreateDirectRoomViewModel @AssistedInject constructor( } val result = runCatchingToAsync { - if (vectorPreferences.isDeferredDmEnabled()) { + if (vectorPreferences.isDeferredDmEnabled() && roomParams.invite3pids.isEmpty()) { session.roomService().createLocalRoom(roomParams) } else { analyticsTracker.capture(CreatedRoom(isDM = roomParams.isDirect.orFalse())) diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/TimelineFragment.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/TimelineFragment.kt index 2bb6fdb3e6e..cf791242a4a 100644 --- a/vector/src/main/java/im/vector/app/features/home/room/detail/TimelineFragment.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/detail/TimelineFragment.kt @@ -75,6 +75,7 @@ import im.vector.app.core.extensions.containsRtLOverride import im.vector.app.core.extensions.ensureEndsLeftToRight import im.vector.app.core.extensions.filterDirectionOverrides import im.vector.app.core.extensions.hideKeyboard +import im.vector.app.core.extensions.isEmail import im.vector.app.core.extensions.registerStartForActivityResult import im.vector.app.core.extensions.setTextOrHide import im.vector.app.core.glide.GlideApp @@ -192,6 +193,7 @@ import kotlinx.coroutines.flow.onEach import kotlinx.coroutines.launch import kotlinx.coroutines.withContext import org.billcarsonfr.jsonviewer.JSonViewerDialog +import org.matrix.android.sdk.api.extensions.orFalse import org.matrix.android.sdk.api.session.Session import org.matrix.android.sdk.api.session.events.model.EventType import org.matrix.android.sdk.api.session.events.model.content.EncryptedEventContent @@ -1176,6 +1178,10 @@ class TimelineFragment : views.hideComposerViews() views.notificationAreaView.render(NotificationAreaView.State.Tombstone(mainState.tombstoneEvent)) } + + if (summary.isDirect && summary.isEncrypted && summary.joinedMembersCount == 1 && summary.invitedMembersCount == 0) { + views.hideComposerViews() + } } else if (summary?.membership == Membership.INVITE && inviter != null) { views.hideComposerViews() lazyLoadedViews.inviteView(true)?.apply { diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/factory/EncryptionItemFactory.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/factory/EncryptionItemFactory.kt index 69b4f6e039b..9d757a5f2ee 100644 --- a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/factory/EncryptionItemFactory.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/factory/EncryptionItemFactory.kt @@ -56,22 +56,37 @@ class EncryptionItemFactory @Inject constructor( val description: String val shield: StatusTileTimelineItem.ShieldUIState if (isSafeAlgorithm) { - val isDirect = session.getRoomSummary(event.root.roomId.orEmpty())?.isDirect.orFalse() - title = stringProvider.getString(R.string.encryption_enabled) - description = stringProvider.getString( + val roomSummary = session.getRoomSummary(event.root.roomId.orEmpty()) + val isDirect = roomSummary?.isDirect.orFalse() + val (resTitle, resDescription, resShield) = when { + isDirect -> { + val isWaitingUser = roomSummary?.isEncrypted.orFalse() && roomSummary?.joinedMembersCount == 1 && roomSummary.invitedMembersCount == 0 when { - isDirect && RoomLocalEcho.isLocalEchoId(event.root.roomId.orEmpty()) -> { - R.string.direct_room_encryption_enabled_tile_description_future - } - isDirect -> { - R.string.direct_room_encryption_enabled_tile_description - } - else -> { - R.string.encryption_enabled_tile_description - } + RoomLocalEcho.isLocalEchoId(event.root.roomId.orEmpty()) -> Triple( + R.string.encryption_enabled, + R.string.direct_room_encryption_enabled_tile_description_future, + StatusTileTimelineItem.ShieldUIState.BLACK + ) + isWaitingUser -> Triple( + R.string.direct_room_encryption_enabled_waiting_users, + R.string.direct_room_encryption_enabled_waiting_users_tile_description, + StatusTileTimelineItem.ShieldUIState.WAITING + ) + else -> Triple( + R.string.encryption_enabled, + R.string.direct_room_encryption_enabled_tile_description, + StatusTileTimelineItem.ShieldUIState.BLACK + ) } - ) - shield = StatusTileTimelineItem.ShieldUIState.BLACK + } + else -> { + Triple(R.string.encryption_enabled, R.string.encryption_enabled_tile_description, StatusTileTimelineItem.ShieldUIState.BLACK) + } + } + + title = stringProvider.getString(resTitle) + description = stringProvider.getString(resDescription) + shield = resShield } else { title = stringProvider.getString(R.string.encryption_misconfigured) description = stringProvider.getString(R.string.encryption_unknown_algorithm_tile_description) diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/item/MergedRoomCreationItem.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/item/MergedRoomCreationItem.kt index a5e2b0d0645..d8a91704024 100644 --- a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/item/MergedRoomCreationItem.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/item/MergedRoomCreationItem.kt @@ -40,6 +40,7 @@ import im.vector.app.features.home.room.detail.timeline.TimelineEventController import im.vector.app.features.home.room.detail.timeline.tools.linkify import im.vector.app.features.themes.ThemeUtils import me.gujun.android.span.span +import org.matrix.android.sdk.api.extensions.orFalse import org.matrix.android.sdk.api.session.room.model.RoomSummary import org.matrix.android.sdk.api.session.room.model.localecho.RoomLocalEcho import org.matrix.android.sdk.api.util.toMatrixItem @@ -127,26 +128,38 @@ abstract class MergedRoomCreationItem : BasedMergedItem { - if (attributes.isLocalRoom) { - resources.getString(R.string.direct_room_encryption_enabled_tile_description_future) - } else { - resources.getString(R.string.direct_room_encryption_enabled_tile_description) + val isWaitingUser = roomSummary?.isEncrypted.orFalse() && roomSummary?.joinedMembersCount == 1 && roomSummary?.invitedMembersCount == 0 + when { + attributes.isLocalRoom -> Triple( + R.string.encryption_enabled, + R.string.direct_room_encryption_enabled_tile_description_future, + R.drawable.ic_shield_black + ) + isWaitingUser -> Triple( + R.string.direct_room_encryption_enabled_waiting_users, + R.string.direct_room_encryption_enabled_waiting_users_tile_description, + R.drawable.ic_room_profile_member_list + ) + else -> Triple( + R.string.encryption_enabled, + R.string.direct_room_encryption_enabled_tile_description, + R.drawable.ic_shield_black + ) } } else -> { - resources.getString(R.string.encryption_enabled_tile_description) + Triple(R.string.encryption_enabled, R.string.encryption_enabled_tile_description, R.drawable.ic_shield_black) } } - holder.e2eTitleTextView.text = holder.expandView.resources.getString(R.string.encryption_enabled) + holder.e2eTitleTextView.text = holder.expandView.resources.getString(title) holder.e2eTitleTextView.setCompoundDrawablesWithIntrinsicBounds( - ContextCompat.getDrawable(holder.view.context, R.drawable.ic_shield_black), + ContextCompat.getDrawable(holder.view.context, drawable), null, null, null ) - holder.e2eTitleDescriptionView.text = description + holder.e2eTitleDescriptionView.text = holder.expandView.resources.getString(description) holder.e2eTitleDescriptionView.textAlignment = View.TEXT_ALIGNMENT_CENTER } diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/item/StatusTileTimelineItem.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/item/StatusTileTimelineItem.kt index 1e5bb0521d6..5a0c024ec88 100644 --- a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/item/StatusTileTimelineItem.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/item/StatusTileTimelineItem.kt @@ -57,6 +57,7 @@ abstract class StatusTileTimelineItem : AbsBaseMessageItem R.drawable.ic_shield_trusted ShieldUIState.BLACK -> R.drawable.ic_shield_black ShieldUIState.RED -> R.drawable.ic_shield_warning + ShieldUIState.WAITING -> R.drawable.ic_room_profile_member_list ShieldUIState.ERROR -> R.drawable.ic_warning_badge } @@ -101,6 +102,7 @@ abstract class StatusTileTimelineItem : AbsBaseMessageItem): String { + override fun getNameForEmptyRoom(isDirect: Boolean, directUserId: String?, leftMemberNames: List): String { return if (leftMemberNames.isEmpty()) { - context.getString(R.string.room_displayname_empty_room) + if (isDirect && directUserId != null) directUserId else context.getString(R.string.room_displayname_empty_room) } else { val was = when (val size = leftMemberNames.size) { 1 -> getNameFor1member(leftMemberNames[0]) From ff42a46a7fde59120c509872a9c97ff56b31b64f Mon Sep 17 00:00:00 2001 From: yostyle Date: Tue, 28 Feb 2023 01:45:41 +0100 Subject: [PATCH 2/7] Only invite one email at a time --- .../src/main/res/values/strings.xml | 1 + .../createdirect/CreateDirectRoomActivity.kt | 25 +++++++++++-------- .../userdirectory/UserListController.kt | 11 ++++++++ .../userdirectory/UserListFragment.kt | 3 +-- .../userdirectory/UserListFragmentArgs.kt | 1 + .../userdirectory/UserListViewModel.kt | 9 +++++-- .../userdirectory/UserListViewState.kt | 2 ++ 7 files changed, 38 insertions(+), 14 deletions(-) diff --git a/library/ui-strings/src/main/res/values/strings.xml b/library/ui-strings/src/main/res/values/strings.xml index 7990e1cf931..f093aec74dc 100644 --- a/library/ui-strings/src/main/res/values/strings.xml +++ b/library/ui-strings/src/main/res/values/strings.xml @@ -1817,6 +1817,7 @@ Add by QR code QR code "Creating room…" + You can only invite one email at a time Known Users Suggestions 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 acaf24dca74..4fecf352364 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 @@ -44,6 +44,7 @@ import im.vector.app.core.utils.registerForPermissionsResult import im.vector.app.features.analytics.plan.MobileScreen import im.vector.app.features.analytics.plan.ViewRoom import im.vector.app.features.contactsbook.ContactsBookFragment +import im.vector.app.features.homeserver.HomeServerCapabilitiesViewModel import im.vector.app.features.qrcode.QrCodeScannerEvents import im.vector.app.features.qrcode.QrCodeScannerFragment import im.vector.app.features.qrcode.QrCodeScannerViewModel @@ -63,6 +64,7 @@ class CreateDirectRoomActivity : SimpleFragmentActivity() { private val viewModel: CreateDirectRoomViewModel by viewModel() private val qrViewModel: QrCodeScannerViewModel by viewModel() + private val homeServerCapabilitiesViewModel: HomeServerCapabilitiesViewModel by viewModel() private lateinit var sharedActionViewModel: UserListSharedActionViewModel @@ -85,16 +87,19 @@ class CreateDirectRoomActivity : SimpleFragmentActivity() { } } .launchIn(lifecycleScope) - if (isFirstCreation()) { - addFragment( - views.container, - UserListFragment::class.java, - UserListFragmentArgs( - title = getString(R.string.fab_menu_create_chat), - menuResId = R.menu.vector_create_direct_room, - submitMenuItemId = R.id.action_create_direct_room, - ) - ) + homeServerCapabilitiesViewModel.onEach { + if (isFirstCreation()) { + addFragment( + views.container, + UserListFragment::class.java, + UserListFragmentArgs( + title = getString(R.string.fab_menu_create_chat), + menuResId = R.menu.vector_create_direct_room, + submitMenuItemId = R.id.action_create_direct_room, + isE2EByDefault = it.isE2EByDefault, + ) + ) + } } viewModel.onEach(CreateDirectRoomViewState::createAndInviteState) { renderCreateAndInviteState(it) diff --git a/vector/src/main/java/im/vector/app/features/userdirectory/UserListController.kt b/vector/src/main/java/im/vector/app/features/userdirectory/UserListController.kt index 2131eda60e4..5400fcc8580 100644 --- a/vector/src/main/java/im/vector/app/features/userdirectory/UserListController.kt +++ b/vector/src/main/java/im/vector/app/features/userdirectory/UserListController.kt @@ -25,12 +25,16 @@ import im.vector.app.R import im.vector.app.core.epoxy.errorWithRetryItem import im.vector.app.core.epoxy.loadingItem import im.vector.app.core.epoxy.noResultItem +import im.vector.app.core.epoxy.profiles.notifications.TextHeaderItem +import im.vector.app.core.epoxy.profiles.notifications.textHeaderItem import im.vector.app.core.error.ErrorFormatter +import im.vector.app.core.extensions.isEmail import im.vector.app.core.resources.ColorProvider import im.vector.app.core.resources.StringProvider import im.vector.app.core.ui.list.genericPillItem import im.vector.app.features.displayname.getBestName import im.vector.app.features.home.AvatarRenderer +import im.vector.app.features.home.room.detail.timeline.item.messageTextItem import im.vector.lib.core.utils.epoxy.charsequence.toEpoxyCharSequence import me.gujun.android.span.span import org.matrix.android.sdk.api.session.Session @@ -61,6 +65,13 @@ class UserListController @Inject constructor( val currentState = state ?: return val host = this + if (currentState.isE2EByDefault && currentState.pendingSelections.isNotEmpty()) { + textHeaderItem { + id("userListNotificationHeader") + textRes(R.string.direct_room_user_list_only_invite_one_email) + } + } + // Build generic items if (currentState.searchTerm.isBlank()) { if (currentState.showInviteActions()) { diff --git a/vector/src/main/java/im/vector/app/features/userdirectory/UserListFragment.kt b/vector/src/main/java/im/vector/app/features/userdirectory/UserListFragment.kt index fbb6a8ee147..abca808361f 100644 --- a/vector/src/main/java/im/vector/app/features/userdirectory/UserListFragment.kt +++ b/vector/src/main/java/im/vector/app/features/userdirectory/UserListFragment.kt @@ -63,7 +63,6 @@ class UserListFragment : private val args: UserListFragmentArgs by args() private val viewModel: UserListViewModel by activityViewModel() - private val homeServerCapabilitiesViewModel: HomeServerCapabilitiesViewModel by fragmentViewModel() private lateinit var sharedActionViewModel: UserListSharedActionViewModel override fun getBinding(inflater: LayoutInflater, container: ViewGroup?): FragmentUserListBinding { @@ -86,7 +85,7 @@ class UserListFragment : setupRecyclerView() setupSearchView() - homeServerCapabilitiesViewModel.onEach { + viewModel.onEach { views.userListE2EbyDefaultDisabled.isVisible = !it.isE2EByDefault } diff --git a/vector/src/main/java/im/vector/app/features/userdirectory/UserListFragmentArgs.kt b/vector/src/main/java/im/vector/app/features/userdirectory/UserListFragmentArgs.kt index d6e55c29ae7..9538b2974f2 100644 --- a/vector/src/main/java/im/vector/app/features/userdirectory/UserListFragmentArgs.kt +++ b/vector/src/main/java/im/vector/app/features/userdirectory/UserListFragmentArgs.kt @@ -26,6 +26,7 @@ data class UserListFragmentArgs( val submitMenuItemId: Int, val excludedUserIds: Set? = null, val singleSelection: Boolean = false, + val isE2EByDefault: Boolean = false, val showInviteActions: Boolean = true, val showContactBookAction: Boolean = true, val showToolbar: Boolean = true diff --git a/vector/src/main/java/im/vector/app/features/userdirectory/UserListViewModel.kt b/vector/src/main/java/im/vector/app/features/userdirectory/UserListViewModel.kt index 5a764f11fd5..4faffde707d 100644 --- a/vector/src/main/java/im/vector/app/features/userdirectory/UserListViewModel.kt +++ b/vector/src/main/java/im/vector/app/features/userdirectory/UserListViewModel.kt @@ -258,8 +258,13 @@ class UserListViewModel @AssistedInject constructor( } private fun handleSelectUser(action: UserListAction.AddPendingSelection) = withState { state -> - val selections = state.pendingSelections.toggle(action.pendingSelection, singleElement = state.singleSelection) - setState { copy(pendingSelections = selections) } + val canSelectUser = !state.isE2EByDefault || state.pendingSelections.isEmpty() || + (action.pendingSelection is PendingSelection.UserPendingSelection && + state.pendingSelections.last() is PendingSelection.UserPendingSelection) + if (canSelectUser) { + val selections = state.pendingSelections.toggle(action.pendingSelection, singleElement = state.singleSelection) + setState { copy(pendingSelections = selections) } + } } private fun handleRemoveSelectedUser(action: UserListAction.RemovePendingSelection) = withState { state -> diff --git a/vector/src/main/java/im/vector/app/features/userdirectory/UserListViewState.kt b/vector/src/main/java/im/vector/app/features/userdirectory/UserListViewState.kt index f91e273aeb6..6ceaf580faf 100644 --- a/vector/src/main/java/im/vector/app/features/userdirectory/UserListViewState.kt +++ b/vector/src/main/java/im/vector/app/features/userdirectory/UserListViewState.kt @@ -32,6 +32,7 @@ data class UserListViewState( val pendingSelections: Set = emptySet(), val searchTerm: String = "", val singleSelection: Boolean, + val isE2EByDefault: Boolean, val configuredIdentityServer: String? = null, private val showInviteActions: Boolean, val showContactBookAction: Boolean @@ -40,6 +41,7 @@ data class UserListViewState( constructor(args: UserListFragmentArgs) : this( excludedUserIds = args.excludedUserIds, singleSelection = args.singleSelection, + isE2EByDefault = args.isE2EByDefault, showInviteActions = args.showInviteActions, showContactBookAction = args.showContactBookAction ) From 71953e27877509f95481706064ce745ea6277355 Mon Sep 17 00:00:00 2001 From: yostyle Date: Tue, 28 Feb 2023 15:15:21 +0100 Subject: [PATCH 3/7] Fix multiple userlist fragments --- .../app/features/createdirect/CreateDirectRoomActivity.kt | 7 ++++--- 1 file changed, 4 insertions(+), 3 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 4fecf352364..bdd2b7bf20b 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 @@ -29,6 +29,7 @@ import com.airbnb.mvrx.Fail import com.airbnb.mvrx.Loading import com.airbnb.mvrx.Success import com.airbnb.mvrx.viewModel +import com.airbnb.mvrx.withState import com.google.android.material.dialog.MaterialAlertDialogBuilder import dagger.hilt.android.AndroidEntryPoint import im.vector.app.R @@ -87,8 +88,8 @@ class CreateDirectRoomActivity : SimpleFragmentActivity() { } } .launchIn(lifecycleScope) - homeServerCapabilitiesViewModel.onEach { - if (isFirstCreation()) { + if (isFirstCreation()) { + withState(homeServerCapabilitiesViewModel) { homeServerCapabilitiesViewState -> addFragment( views.container, UserListFragment::class.java, @@ -96,7 +97,7 @@ class CreateDirectRoomActivity : SimpleFragmentActivity() { title = getString(R.string.fab_menu_create_chat), menuResId = R.menu.vector_create_direct_room, submitMenuItemId = R.id.action_create_direct_room, - isE2EByDefault = it.isE2EByDefault, + isE2EByDefault = homeServerCapabilitiesViewState.isE2EByDefault, ) ) } From d6b59ea0946ba2d05ee7ddc292f1835a5a0958ee Mon Sep 17 00:00:00 2001 From: Yoan Pintas Date: Thu, 2 Mar 2023 15:56:20 +0000 Subject: [PATCH 4/7] Update waiting users description Co-authored-by: jonnyandrew --- library/ui-strings/src/main/res/values/strings.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/ui-strings/src/main/res/values/strings.xml b/library/ui-strings/src/main/res/values/strings.xml index f093aec74dc..1363432e3de 100644 --- a/library/ui-strings/src/main/res/values/strings.xml +++ b/library/ui-strings/src/main/res/values/strings.xml @@ -2563,7 +2563,7 @@ Messages in this chat are end-to-end encrypted. Messages in this chat will be end-to-end encrypted. Waiting for users to join ${app_name} - Once all users invited have joined ${app_name}, you will able to chat and the room will be end to end encrypted. + Once all invited users have joined ${app_name}, you will be able to chat and the room will be end to end encrypted Encryption not enabled Encryption is misconfigured The encryption used by this room is not supported From ef0a6addb8a3ebfa4962c68d8c5104b68fa6c09c Mon Sep 17 00:00:00 2001 From: yostyle Date: Fri, 3 Mar 2023 10:04:27 +0100 Subject: [PATCH 5/7] Fix PR comments --- .../src/main/res/values/strings.xml | 2 +- .../RoomDisplayNameFallbackProvider.kt | 2 +- .../membership/RoomDisplayNameResolver.kt | 7 +- .../app/core/di/MavericksViewModelModule.kt | 6 -- .../createdirect/CreateDirectRoomActivity.kt | 24 ++---- .../home/room/detail/TimelineFragment.kt | 2 - .../HomeServerCapabilitiesViewModel.kt | 83 ------------------- .../HomeServerCapabilitiesViewState.kt | 25 ------ .../VectorRoomDisplayNameFallbackProvider.kt | 4 +- .../userdirectory/UserListController.kt | 3 - .../userdirectory/UserListFragment.kt | 2 - .../userdirectory/UserListFragmentArgs.kt | 1 - .../userdirectory/UserListViewModel.kt | 22 +++++ .../userdirectory/UserListViewState.kt | 3 +- 14 files changed, 42 insertions(+), 144 deletions(-) delete mode 100644 vector/src/main/java/im/vector/app/features/homeserver/HomeServerCapabilitiesViewModel.kt delete mode 100644 vector/src/main/java/im/vector/app/features/homeserver/HomeServerCapabilitiesViewState.kt diff --git a/library/ui-strings/src/main/res/values/strings.xml b/library/ui-strings/src/main/res/values/strings.xml index 1363432e3de..62f061f009a 100644 --- a/library/ui-strings/src/main/res/values/strings.xml +++ b/library/ui-strings/src/main/res/values/strings.xml @@ -2563,7 +2563,7 @@ Messages in this chat are end-to-end encrypted. Messages in this chat will be end-to-end encrypted. Waiting for users to join ${app_name} - Once all invited users have joined ${app_name}, you will be able to chat and the room will be end to end encrypted + Once invited users have joined ${app_name}, you will be able to chat and the room will be end-to-end encrypted Encryption not enabled Encryption is misconfigured The encryption used by this room is not supported diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/provider/RoomDisplayNameFallbackProvider.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/provider/RoomDisplayNameFallbackProvider.kt index a945c3da330..37d9b46b0ba 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/provider/RoomDisplayNameFallbackProvider.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/provider/RoomDisplayNameFallbackProvider.kt @@ -26,7 +26,7 @@ package org.matrix.android.sdk.api.provider */ interface RoomDisplayNameFallbackProvider { fun getNameForRoomInvite(): String - fun getNameForEmptyRoom(isDirect: Boolean, directUserId: String?, leftMemberNames: List): String + fun getNameForEmptyRoom(isDirect: Boolean, leftMemberNames: List): String fun getNameFor1member(name: String): String fun getNameFor2members(name1: String, name2: String): String fun getNameFor3members(name1: String, name2: String, name3: String): String diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/membership/RoomDisplayNameResolver.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/membership/RoomDisplayNameResolver.kt index 5f28c581e25..e115a3b2289 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/membership/RoomDisplayNameResolver.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/membership/RoomDisplayNameResolver.kt @@ -115,7 +115,12 @@ internal class RoomDisplayNameResolver @Inject constructor( val leftMembersNames = roomMembers.queryLeftRoomMembersEvent() .findAll() .map { displayNameResolver.getBestName(it.toMatrixItem()) } - roomDisplayNameFallbackProvider.getNameForEmptyRoom(roomSummary?.isDirect.orFalse(), roomSummary?.directUserId, leftMembersNames) + val isDirect = roomSummary?.isDirect.orFalse() + if (isDirect && leftMembersNames.isEmpty()) { + roomSummary?.directUserId + } else { + roomDisplayNameFallbackProvider.getNameForEmptyRoom(isDirect, leftMembersNames) + } } 1 -> { roomDisplayNameFallbackProvider.getNameFor1member( diff --git a/vector/src/main/java/im/vector/app/core/di/MavericksViewModelModule.kt b/vector/src/main/java/im/vector/app/core/di/MavericksViewModelModule.kt index 27981c3d363..8b435c9e6cd 100644 --- a/vector/src/main/java/im/vector/app/core/di/MavericksViewModelModule.kt +++ b/vector/src/main/java/im/vector/app/core/di/MavericksViewModelModule.kt @@ -57,7 +57,6 @@ import im.vector.app.features.home.room.list.RoomListViewModel import im.vector.app.features.home.room.list.home.HomeRoomListViewModel import im.vector.app.features.home.room.list.home.invites.InvitesViewModel import im.vector.app.features.home.room.list.home.release.ReleaseNotesViewModel -import im.vector.app.features.homeserver.HomeServerCapabilitiesViewModel import im.vector.app.features.invite.InviteUsersToRoomViewModel import im.vector.app.features.location.LocationSharingViewModel import im.vector.app.features.location.live.map.LiveLocationMapViewModel @@ -500,11 +499,6 @@ interface MavericksViewModelModule { @MavericksViewModelKey(StartAppViewModel::class) fun startAppViewModelFactory(factory: StartAppViewModel.Factory): MavericksAssistedViewModelFactory<*, *> - @Binds - @IntoMap - @MavericksViewModelKey(HomeServerCapabilitiesViewModel::class) - fun homeServerCapabilitiesViewModelFactory(factory: HomeServerCapabilitiesViewModel.Factory): MavericksAssistedViewModelFactory<*, *> - @Binds @IntoMap @MavericksViewModelKey(InviteUsersToRoomViewModel::class) 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 bdd2b7bf20b..acaf24dca74 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 @@ -29,7 +29,6 @@ import com.airbnb.mvrx.Fail import com.airbnb.mvrx.Loading import com.airbnb.mvrx.Success import com.airbnb.mvrx.viewModel -import com.airbnb.mvrx.withState import com.google.android.material.dialog.MaterialAlertDialogBuilder import dagger.hilt.android.AndroidEntryPoint import im.vector.app.R @@ -45,7 +44,6 @@ import im.vector.app.core.utils.registerForPermissionsResult import im.vector.app.features.analytics.plan.MobileScreen import im.vector.app.features.analytics.plan.ViewRoom import im.vector.app.features.contactsbook.ContactsBookFragment -import im.vector.app.features.homeserver.HomeServerCapabilitiesViewModel import im.vector.app.features.qrcode.QrCodeScannerEvents import im.vector.app.features.qrcode.QrCodeScannerFragment import im.vector.app.features.qrcode.QrCodeScannerViewModel @@ -65,7 +63,6 @@ class CreateDirectRoomActivity : SimpleFragmentActivity() { private val viewModel: CreateDirectRoomViewModel by viewModel() private val qrViewModel: QrCodeScannerViewModel by viewModel() - private val homeServerCapabilitiesViewModel: HomeServerCapabilitiesViewModel by viewModel() private lateinit var sharedActionViewModel: UserListSharedActionViewModel @@ -89,18 +86,15 @@ class CreateDirectRoomActivity : SimpleFragmentActivity() { } .launchIn(lifecycleScope) if (isFirstCreation()) { - withState(homeServerCapabilitiesViewModel) { homeServerCapabilitiesViewState -> - addFragment( - views.container, - UserListFragment::class.java, - UserListFragmentArgs( - title = getString(R.string.fab_menu_create_chat), - menuResId = R.menu.vector_create_direct_room, - submitMenuItemId = R.id.action_create_direct_room, - isE2EByDefault = homeServerCapabilitiesViewState.isE2EByDefault, - ) - ) - } + addFragment( + views.container, + UserListFragment::class.java, + UserListFragmentArgs( + title = getString(R.string.fab_menu_create_chat), + menuResId = R.menu.vector_create_direct_room, + submitMenuItemId = R.id.action_create_direct_room, + ) + ) } viewModel.onEach(CreateDirectRoomViewState::createAndInviteState) { renderCreateAndInviteState(it) diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/TimelineFragment.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/TimelineFragment.kt index cf791242a4a..f363128ad5a 100644 --- a/vector/src/main/java/im/vector/app/features/home/room/detail/TimelineFragment.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/detail/TimelineFragment.kt @@ -75,7 +75,6 @@ import im.vector.app.core.extensions.containsRtLOverride import im.vector.app.core.extensions.ensureEndsLeftToRight import im.vector.app.core.extensions.filterDirectionOverrides import im.vector.app.core.extensions.hideKeyboard -import im.vector.app.core.extensions.isEmail import im.vector.app.core.extensions.registerStartForActivityResult import im.vector.app.core.extensions.setTextOrHide import im.vector.app.core.glide.GlideApp @@ -193,7 +192,6 @@ import kotlinx.coroutines.flow.onEach import kotlinx.coroutines.launch import kotlinx.coroutines.withContext import org.billcarsonfr.jsonviewer.JSonViewerDialog -import org.matrix.android.sdk.api.extensions.orFalse import org.matrix.android.sdk.api.session.Session import org.matrix.android.sdk.api.session.events.model.EventType import org.matrix.android.sdk.api.session.events.model.content.EncryptedEventContent diff --git a/vector/src/main/java/im/vector/app/features/homeserver/HomeServerCapabilitiesViewModel.kt b/vector/src/main/java/im/vector/app/features/homeserver/HomeServerCapabilitiesViewModel.kt deleted file mode 100644 index 1e4fccefd5f..00000000000 --- a/vector/src/main/java/im/vector/app/features/homeserver/HomeServerCapabilitiesViewModel.kt +++ /dev/null @@ -1,83 +0,0 @@ -/* - * Copyright (c) 2020 New Vector Ltd - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package im.vector.app.features.homeserver - -import com.airbnb.mvrx.MavericksViewModelFactory -import com.airbnb.mvrx.ViewModelContext -import dagger.assisted.Assisted -import dagger.assisted.AssistedFactory -import dagger.assisted.AssistedInject -import dagger.hilt.EntryPoints -import im.vector.app.core.di.MavericksAssistedViewModelFactory -import im.vector.app.core.di.SingletonEntryPoint -import im.vector.app.core.di.hiltMavericksViewModelFactory -import im.vector.app.core.platform.EmptyAction -import im.vector.app.core.platform.EmptyViewEvents -import im.vector.app.core.platform.VectorViewModel -import im.vector.app.features.raw.wellknown.getElementWellknown -import im.vector.app.features.raw.wellknown.isE2EByDefault -import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.launch -import org.matrix.android.sdk.api.extensions.tryOrNull -import org.matrix.android.sdk.api.raw.RawService -import org.matrix.android.sdk.api.session.Session -import org.matrix.android.sdk.api.session.homeserver.HomeServerCapabilities - -class HomeServerCapabilitiesViewModel @AssistedInject constructor( - @Assisted initialState: HomeServerCapabilitiesViewState, - private val session: Session, - private val rawService: RawService -) : VectorViewModel(initialState) { - - @AssistedFactory - interface Factory : MavericksAssistedViewModelFactory { - override fun create(initialState: HomeServerCapabilitiesViewState): HomeServerCapabilitiesViewModel - } - - companion object : MavericksViewModelFactory by hiltMavericksViewModelFactory() { - - override fun initialState(viewModelContext: ViewModelContext): HomeServerCapabilitiesViewState { - val session = EntryPoints.get(viewModelContext.app(), SingletonEntryPoint::class.java).activeSessionHolder().getSafeActiveSession() - return HomeServerCapabilitiesViewState( - capabilities = session?.homeServerCapabilitiesService()?.getHomeServerCapabilities() ?: HomeServerCapabilities() - ) - } - } - - init { - - initAdminE2eByDefault() - } - - private fun initAdminE2eByDefault() { - viewModelScope.launch(Dispatchers.IO) { - val adminE2EByDefault = tryOrNull { - rawService.getElementWellknown(session.sessionParams) - ?.isE2EByDefault() - ?: true - } ?: true - - setState { - copy( - isE2EByDefault = adminE2EByDefault - ) - } - } - } - - override fun handle(action: EmptyAction) {} -} diff --git a/vector/src/main/java/im/vector/app/features/homeserver/HomeServerCapabilitiesViewState.kt b/vector/src/main/java/im/vector/app/features/homeserver/HomeServerCapabilitiesViewState.kt deleted file mode 100644 index d7ced5e632f..00000000000 --- a/vector/src/main/java/im/vector/app/features/homeserver/HomeServerCapabilitiesViewState.kt +++ /dev/null @@ -1,25 +0,0 @@ -/* - * Copyright (c) 2020 New Vector Ltd - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package im.vector.app.features.homeserver - -import com.airbnb.mvrx.MavericksState -import org.matrix.android.sdk.api.session.homeserver.HomeServerCapabilities - -data class HomeServerCapabilitiesViewState( - val capabilities: HomeServerCapabilities = HomeServerCapabilities(), - val isE2EByDefault: Boolean = true -) : MavericksState diff --git a/vector/src/main/java/im/vector/app/features/room/VectorRoomDisplayNameFallbackProvider.kt b/vector/src/main/java/im/vector/app/features/room/VectorRoomDisplayNameFallbackProvider.kt index d7df4da5546..cfbc2748adf 100644 --- a/vector/src/main/java/im/vector/app/features/room/VectorRoomDisplayNameFallbackProvider.kt +++ b/vector/src/main/java/im/vector/app/features/room/VectorRoomDisplayNameFallbackProvider.kt @@ -29,9 +29,9 @@ class VectorRoomDisplayNameFallbackProvider @Inject constructor( return context.getString(R.string.room_displayname_room_invite) } - override fun getNameForEmptyRoom(isDirect: Boolean, directUserId: String?, leftMemberNames: List): String { + override fun getNameForEmptyRoom(isDirect: Boolean, leftMemberNames: List): String { return if (leftMemberNames.isEmpty()) { - if (isDirect && directUserId != null) directUserId else context.getString(R.string.room_displayname_empty_room) + context.getString(R.string.room_displayname_empty_room) } else { val was = when (val size = leftMemberNames.size) { 1 -> getNameFor1member(leftMemberNames[0]) diff --git a/vector/src/main/java/im/vector/app/features/userdirectory/UserListController.kt b/vector/src/main/java/im/vector/app/features/userdirectory/UserListController.kt index 5400fcc8580..003d022c8f8 100644 --- a/vector/src/main/java/im/vector/app/features/userdirectory/UserListController.kt +++ b/vector/src/main/java/im/vector/app/features/userdirectory/UserListController.kt @@ -25,16 +25,13 @@ import im.vector.app.R import im.vector.app.core.epoxy.errorWithRetryItem import im.vector.app.core.epoxy.loadingItem import im.vector.app.core.epoxy.noResultItem -import im.vector.app.core.epoxy.profiles.notifications.TextHeaderItem import im.vector.app.core.epoxy.profiles.notifications.textHeaderItem import im.vector.app.core.error.ErrorFormatter -import im.vector.app.core.extensions.isEmail import im.vector.app.core.resources.ColorProvider import im.vector.app.core.resources.StringProvider import im.vector.app.core.ui.list.genericPillItem import im.vector.app.features.displayname.getBestName import im.vector.app.features.home.AvatarRenderer -import im.vector.app.features.home.room.detail.timeline.item.messageTextItem import im.vector.lib.core.utils.epoxy.charsequence.toEpoxyCharSequence import me.gujun.android.span.span import org.matrix.android.sdk.api.session.Session diff --git a/vector/src/main/java/im/vector/app/features/userdirectory/UserListFragment.kt b/vector/src/main/java/im/vector/app/features/userdirectory/UserListFragment.kt index abca808361f..6447452e5b2 100644 --- a/vector/src/main/java/im/vector/app/features/userdirectory/UserListFragment.kt +++ b/vector/src/main/java/im/vector/app/features/userdirectory/UserListFragment.kt @@ -27,7 +27,6 @@ import androidx.core.view.isVisible import androidx.lifecycle.lifecycleScope import com.airbnb.mvrx.activityViewModel import com.airbnb.mvrx.args -import com.airbnb.mvrx.fragmentViewModel import com.airbnb.mvrx.withState import com.google.android.material.chip.Chip import dagger.hilt.android.AndroidEntryPoint @@ -42,7 +41,6 @@ import im.vector.app.core.utils.DimensionConverter import im.vector.app.core.utils.showIdentityServerConsentDialog import im.vector.app.core.utils.startSharePlainTextIntent import im.vector.app.databinding.FragmentUserListBinding -import im.vector.app.features.homeserver.HomeServerCapabilitiesViewModel import im.vector.app.features.settings.VectorSettingsActivity import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.onEach diff --git a/vector/src/main/java/im/vector/app/features/userdirectory/UserListFragmentArgs.kt b/vector/src/main/java/im/vector/app/features/userdirectory/UserListFragmentArgs.kt index 9538b2974f2..d6e55c29ae7 100644 --- a/vector/src/main/java/im/vector/app/features/userdirectory/UserListFragmentArgs.kt +++ b/vector/src/main/java/im/vector/app/features/userdirectory/UserListFragmentArgs.kt @@ -26,7 +26,6 @@ data class UserListFragmentArgs( val submitMenuItemId: Int, val excludedUserIds: Set? = null, val singleSelection: Boolean = false, - val isE2EByDefault: Boolean = false, val showInviteActions: Boolean = true, val showContactBookAction: Boolean = true, val showToolbar: Boolean = true diff --git a/vector/src/main/java/im/vector/app/features/userdirectory/UserListViewModel.kt b/vector/src/main/java/im/vector/app/features/userdirectory/UserListViewModel.kt index 4faffde707d..f2739cc8975 100644 --- a/vector/src/main/java/im/vector/app/features/userdirectory/UserListViewModel.kt +++ b/vector/src/main/java/im/vector/app/features/userdirectory/UserListViewModel.kt @@ -31,6 +31,9 @@ import im.vector.app.core.extensions.toggle import im.vector.app.core.platform.VectorViewModel import im.vector.app.core.resources.StringProvider import im.vector.app.features.discovery.fetchIdentityServerWithTerms +import im.vector.app.features.raw.wellknown.getElementWellknown +import im.vector.app.features.raw.wellknown.isE2EByDefault +import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.debounce import kotlinx.coroutines.flow.filter @@ -41,6 +44,7 @@ import kotlinx.coroutines.flow.sample import kotlinx.coroutines.launch import org.matrix.android.sdk.api.MatrixPatterns import org.matrix.android.sdk.api.extensions.tryOrNull +import org.matrix.android.sdk.api.raw.RawService import org.matrix.android.sdk.api.session.Session import org.matrix.android.sdk.api.session.identity.IdentityServiceError import org.matrix.android.sdk.api.session.identity.IdentityServiceListener @@ -57,6 +61,7 @@ data class ThreePidUser( class UserListViewModel @AssistedInject constructor( @Assisted initialState: UserListViewState, private val stringProvider: StringProvider, + private val rawService: RawService, private val session: Session ) : VectorViewModel(initialState) { @@ -84,6 +89,7 @@ class UserListViewModel @AssistedInject constructor( } init { + initAdminE2eByDefault() observeUsers() setState { copy( @@ -93,6 +99,22 @@ class UserListViewModel @AssistedInject constructor( session.identityService().addListener(identityServerListener) } + private fun initAdminE2eByDefault() { + viewModelScope.launch(Dispatchers.IO) { + val adminE2EByDefault = tryOrNull { + rawService.getElementWellknown(session.sessionParams) + ?.isE2EByDefault() + ?: true + } ?: true + + setState { + copy( + isE2EByDefault = adminE2EByDefault + ) + } + } + } + private fun cleanISURL(url: String?): String? { return url?.removePrefix("https://") } diff --git a/vector/src/main/java/im/vector/app/features/userdirectory/UserListViewState.kt b/vector/src/main/java/im/vector/app/features/userdirectory/UserListViewState.kt index 6ceaf580faf..c41c15e3ef6 100644 --- a/vector/src/main/java/im/vector/app/features/userdirectory/UserListViewState.kt +++ b/vector/src/main/java/im/vector/app/features/userdirectory/UserListViewState.kt @@ -32,7 +32,7 @@ data class UserListViewState( val pendingSelections: Set = emptySet(), val searchTerm: String = "", val singleSelection: Boolean, - val isE2EByDefault: Boolean, + val isE2EByDefault: Boolean = false, val configuredIdentityServer: String? = null, private val showInviteActions: Boolean, val showContactBookAction: Boolean @@ -41,7 +41,6 @@ data class UserListViewState( constructor(args: UserListFragmentArgs) : this( excludedUserIds = args.excludedUserIds, singleSelection = args.singleSelection, - isE2EByDefault = args.isE2EByDefault, showInviteActions = args.showInviteActions, showContactBookAction = args.showContactBookAction ) From 35878f70071ed15e7801cd05fc6b871ffd7e5280 Mon Sep 17 00:00:00 2001 From: yostyle Date: Fri, 3 Mar 2023 18:35:14 +0100 Subject: [PATCH 6/7] Add single 3pid user selection for DM creation --- .../session/room/membership/RoomDisplayNameResolver.kt | 8 ++++---- .../app/features/createdirect/CreateDirectRoomActivity.kt | 1 + .../app/features/userdirectory/UserListController.kt | 2 +- .../app/features/userdirectory/UserListFragmentArgs.kt | 1 + .../app/features/userdirectory/UserListViewModel.kt | 2 +- .../app/features/userdirectory/UserListViewState.kt | 2 ++ 6 files changed, 10 insertions(+), 6 deletions(-) diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/membership/RoomDisplayNameResolver.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/membership/RoomDisplayNameResolver.kt index e115a3b2289..7497ecf21b6 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/membership/RoomDisplayNameResolver.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/membership/RoomDisplayNameResolver.kt @@ -115,11 +115,11 @@ internal class RoomDisplayNameResolver @Inject constructor( val leftMembersNames = roomMembers.queryLeftRoomMembersEvent() .findAll() .map { displayNameResolver.getBestName(it.toMatrixItem()) } - val isDirect = roomSummary?.isDirect.orFalse() - if (isDirect && leftMembersNames.isEmpty()) { - roomSummary?.directUserId + val directUserId = roomSummary?.directUserId + if (!directUserId.isNullOrBlank() && leftMembersNames.isEmpty()) { + directUserId } else { - roomDisplayNameFallbackProvider.getNameForEmptyRoom(isDirect, leftMembersNames) + roomDisplayNameFallbackProvider.getNameForEmptyRoom(roomSummary?.isDirect.orFalse(), leftMembersNames) } } 1 -> { 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 acaf24dca74..fbddf815c6f 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 @@ -93,6 +93,7 @@ class CreateDirectRoomActivity : SimpleFragmentActivity() { title = getString(R.string.fab_menu_create_chat), menuResId = R.menu.vector_create_direct_room, submitMenuItemId = R.id.action_create_direct_room, + single3pidSelection = true, ) ) } diff --git a/vector/src/main/java/im/vector/app/features/userdirectory/UserListController.kt b/vector/src/main/java/im/vector/app/features/userdirectory/UserListController.kt index 003d022c8f8..54e43038b16 100644 --- a/vector/src/main/java/im/vector/app/features/userdirectory/UserListController.kt +++ b/vector/src/main/java/im/vector/app/features/userdirectory/UserListController.kt @@ -62,7 +62,7 @@ class UserListController @Inject constructor( val currentState = state ?: return val host = this - if (currentState.isE2EByDefault && currentState.pendingSelections.isNotEmpty()) { + if (currentState.isE2EByDefault && currentState.single3pidSelection && currentState.pendingSelections.isNotEmpty()) { textHeaderItem { id("userListNotificationHeader") textRes(R.string.direct_room_user_list_only_invite_one_email) diff --git a/vector/src/main/java/im/vector/app/features/userdirectory/UserListFragmentArgs.kt b/vector/src/main/java/im/vector/app/features/userdirectory/UserListFragmentArgs.kt index d6e55c29ae7..0a0ae8127a6 100644 --- a/vector/src/main/java/im/vector/app/features/userdirectory/UserListFragmentArgs.kt +++ b/vector/src/main/java/im/vector/app/features/userdirectory/UserListFragmentArgs.kt @@ -26,6 +26,7 @@ data class UserListFragmentArgs( val submitMenuItemId: Int, val excludedUserIds: Set? = null, val singleSelection: Boolean = false, + val single3pidSelection: Boolean = false, val showInviteActions: Boolean = true, val showContactBookAction: Boolean = true, val showToolbar: Boolean = true diff --git a/vector/src/main/java/im/vector/app/features/userdirectory/UserListViewModel.kt b/vector/src/main/java/im/vector/app/features/userdirectory/UserListViewModel.kt index f2739cc8975..ae28ff020d6 100644 --- a/vector/src/main/java/im/vector/app/features/userdirectory/UserListViewModel.kt +++ b/vector/src/main/java/im/vector/app/features/userdirectory/UserListViewModel.kt @@ -280,7 +280,7 @@ class UserListViewModel @AssistedInject constructor( } private fun handleSelectUser(action: UserListAction.AddPendingSelection) = withState { state -> - val canSelectUser = !state.isE2EByDefault || state.pendingSelections.isEmpty() || + val canSelectUser = !state.isE2EByDefault || state.pendingSelections.isEmpty() || !state.single3pidSelection || (action.pendingSelection is PendingSelection.UserPendingSelection && state.pendingSelections.last() is PendingSelection.UserPendingSelection) if (canSelectUser) { diff --git a/vector/src/main/java/im/vector/app/features/userdirectory/UserListViewState.kt b/vector/src/main/java/im/vector/app/features/userdirectory/UserListViewState.kt index c41c15e3ef6..ec932a2a575 100644 --- a/vector/src/main/java/im/vector/app/features/userdirectory/UserListViewState.kt +++ b/vector/src/main/java/im/vector/app/features/userdirectory/UserListViewState.kt @@ -32,6 +32,7 @@ data class UserListViewState( val pendingSelections: Set = emptySet(), val searchTerm: String = "", val singleSelection: Boolean, + val single3pidSelection: Boolean, val isE2EByDefault: Boolean = false, val configuredIdentityServer: String? = null, private val showInviteActions: Boolean, @@ -41,6 +42,7 @@ data class UserListViewState( constructor(args: UserListFragmentArgs) : this( excludedUserIds = args.excludedUserIds, singleSelection = args.singleSelection, + single3pidSelection = args.single3pidSelection, showInviteActions = args.showInviteActions, showContactBookAction = args.showContactBookAction ) From 2e71730ab1af34fab2d0d99e0f7a2d69ba411425 Mon Sep 17 00:00:00 2001 From: yostyle Date: Mon, 6 Mar 2023 12:15:18 +0100 Subject: [PATCH 7/7] Add changelog --- changelog.d/6912.misc | 1 + 1 file changed, 1 insertion(+) create mode 100644 changelog.d/6912.misc diff --git a/changelog.d/6912.misc b/changelog.d/6912.misc new file mode 100644 index 00000000000..c43830e9022 --- /dev/null +++ b/changelog.d/6912.misc @@ -0,0 +1 @@ +Direct Message: Manage encrypted DM in case of invite by email