From 95b3afd1488b046b3d36e99a8ed91d11a710778a Mon Sep 17 00:00:00 2001 From: ClaireG Date: Fri, 18 Feb 2022 16:45:01 +0100 Subject: [PATCH] #3771: When accepting an invite, expecting to see the room (#5247) Open the room when user accepts an invite from the room list --- changelog.d/3771.feature | 1 + .../home/room/detail/RoomDetailViewEvents.kt | 2 +- .../home/room/detail/RoomDetailViewState.kt | 2 ++ .../home/room/detail/TimelineFragment.kt | 8 +++++--- .../home/room/detail/TimelineViewModel.kt | 19 +++++++++++++++++-- .../room/detail/arguments/TimelineArgs.kt | 3 ++- .../home/room/list/RoomListFragment.kt | 6 +++--- .../home/room/list/RoomListViewEvents.kt | 2 +- .../home/room/list/RoomListViewModel.kt | 16 ++-------------- .../features/navigation/DefaultNavigator.kt | 5 +++-- .../app/features/navigation/Navigator.kt | 2 +- 11 files changed, 38 insertions(+), 28 deletions(-) create mode 100644 changelog.d/3771.feature diff --git a/changelog.d/3771.feature b/changelog.d/3771.feature new file mode 100644 index 0000000000..c480bb649d --- /dev/null +++ b/changelog.d/3771.feature @@ -0,0 +1 @@ +Open the room when user accepts an invite from the room list \ No newline at end of file diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/RoomDetailViewEvents.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/RoomDetailViewEvents.kt index 86240a5ffe..d08a27324c 100644 --- a/vector/src/main/java/im/vector/app/features/home/room/detail/RoomDetailViewEvents.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/detail/RoomDetailViewEvents.kt @@ -29,7 +29,7 @@ import java.io.File * Transient events for RoomDetail */ sealed class RoomDetailViewEvents : VectorViewEvents { - data class Failure(val throwable: Throwable) : RoomDetailViewEvents() + data class Failure(val throwable: Throwable, val showInDialog: Boolean = false) : RoomDetailViewEvents() data class OnNewTimelineEvents(val eventIds: List) : RoomDetailViewEvents() data class ActionSuccess(val action: RoomDetailAction) : RoomDetailViewEvents() diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/RoomDetailViewState.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/RoomDetailViewState.kt index 22d5fc2a77..71a299e11b 100644 --- a/vector/src/main/java/im/vector/app/features/home/room/detail/RoomDetailViewState.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/detail/RoomDetailViewState.kt @@ -49,6 +49,7 @@ data class JitsiState( data class RoomDetailViewState( val roomId: String, val eventId: String?, + val isInviteAlreadyAccepted: Boolean, val myRoomMember: Async = Uninitialized, val asyncInviter: Async = Uninitialized, val asyncRoomSummary: Async = Uninitialized, @@ -77,6 +78,7 @@ data class RoomDetailViewState( constructor(args: TimelineArgs) : this( roomId = args.roomId, eventId = args.eventId, + isInviteAlreadyAccepted = args.isInviteAlreadyAccepted, // Also highlight the target event, if any highlightedEventId = args.eventId, switchToParentSpace = args.switchToParentSpace, 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 ff392eaf1b..b6cbd538f3 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 @@ -448,7 +448,7 @@ class TimelineFragment @Inject constructor( timelineViewModel.observeViewEvents { when (it) { - is RoomDetailViewEvents.Failure -> showErrorInSnackbar(it.throwable) + is RoomDetailViewEvents.Failure -> displayErrorMessage(it) is RoomDetailViewEvents.OnNewTimelineEvents -> scrollOnNewMessageCallback.addNewTimelineEventIds(it.eventIds) is RoomDetailViewEvents.ActionSuccess -> displayRoomDetailActionSuccess(it) is RoomDetailViewEvents.ActionFailure -> displayRoomDetailActionFailure(it) @@ -623,6 +623,10 @@ class TimelineFragment @Inject constructor( ) } + private fun displayErrorMessage(error: RoomDetailViewEvents.Failure) { + if (error.showInDialog) displayErrorDialog(error.throwable) else showErrorInSnackbar(error.throwable) + } + private fun requestNativeWidgetPermission(it: RoomDetailViewEvents.RequestNativeWidgetPermission) { val tag = RoomWidgetPermissionBottomSheet::class.java.name val dFrag = childFragmentManager.findFragmentByTag(tag) as? RoomWidgetPermissionBottomSheet @@ -2374,12 +2378,10 @@ class TimelineFragment @Inject constructor( // VectorInviteView.Callback override fun onAcceptInvite() { - notificationDrawerManager.updateEvents { it.clearMemberShipNotificationForRoom(timelineArgs.roomId) } timelineViewModel.handle(RoomDetailAction.AcceptInvite) } override fun onRejectInvite() { - notificationDrawerManager.updateEvents { it.clearMemberShipNotificationForRoom(timelineArgs.roomId) } timelineViewModel.handle(RoomDetailAction.RejectInvite) } diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/TimelineViewModel.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/TimelineViewModel.kt index a404f9136b..0198c77280 100644 --- a/vector/src/main/java/im/vector/app/features/home/room/detail/TimelineViewModel.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/detail/TimelineViewModel.kt @@ -53,6 +53,7 @@ import im.vector.app.features.home.room.detail.sticker.StickerPickerActionHandle import im.vector.app.features.home.room.detail.timeline.factory.TimelineFactory import im.vector.app.features.home.room.detail.timeline.url.PreviewUrlRetriever import im.vector.app.features.home.room.typing.TypingHelper +import im.vector.app.features.notifications.NotificationDrawerManager import im.vector.app.features.powerlevel.PowerLevelsFlowFactory import im.vector.app.features.session.coroutineScope import im.vector.app.features.settings.VectorDataStore @@ -123,6 +124,7 @@ class TimelineViewModel @AssistedInject constructor( private val analyticsTracker: AnalyticsTracker, private val activeConferenceHolder: JitsiActiveConferenceHolder, private val decryptionFailureTracker: DecryptionFailureTracker, + private val notificationDrawerManager: NotificationDrawerManager, timelineFactory: TimelineFactory, appStateHandler: AppStateHandler ) : VectorViewModel(initialState), @@ -190,6 +192,11 @@ class TimelineViewModel @AssistedInject constructor( prepareForEncryption() } + // If the user had already accepted the invitation in the room list + if (initialState.isInviteAlreadyAccepted) { + handleAcceptInvite() + } + if (initialState.switchToParentSpace) { // We are coming from a notification, try to switch to the most relevant space // so that when hitting back the room will appear in the list @@ -800,16 +807,24 @@ class TimelineViewModel @AssistedInject constructor( } private fun handleRejectInvite() { + notificationDrawerManager.updateEvents { it.clearMemberShipNotificationForRoom(initialState.roomId) } viewModelScope.launch { - tryOrNull { session.leaveRoom(room.roomId) } + try { + session.leaveRoom(room.roomId) + } catch (throwable: Throwable) { + _viewEvents.post(RoomDetailViewEvents.Failure(throwable, showInDialog = true)) + } } } private fun handleAcceptInvite() { + notificationDrawerManager.updateEvents { it.clearMemberShipNotificationForRoom(initialState.roomId) } viewModelScope.launch { - tryOrNull { + try { session.joinRoom(room.roomId) analyticsTracker.capture(room.roomSummary().toAnalyticsJoinedRoom()) + } catch (throwable: Throwable) { + _viewEvents.post(RoomDetailViewEvents.Failure(throwable, showInDialog = true)) } } } diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/arguments/TimelineArgs.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/arguments/TimelineArgs.kt index f22fe1b7df..a21567acb1 100644 --- a/vector/src/main/java/im/vector/app/features/home/room/detail/arguments/TimelineArgs.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/detail/arguments/TimelineArgs.kt @@ -28,5 +28,6 @@ data class TimelineArgs( val sharedData: SharedData? = null, val openShareSpaceForId: String? = null, val threadTimelineArgs: ThreadTimelineArgs? = null, - val switchToParentSpace: Boolean = false + val switchToParentSpace: Boolean = false, + val isInviteAlreadyAccepted: Boolean = false ) : Parcelable diff --git a/vector/src/main/java/im/vector/app/features/home/room/list/RoomListFragment.kt b/vector/src/main/java/im/vector/app/features/home/room/list/RoomListFragment.kt index b023c26590..28849204c4 100644 --- a/vector/src/main/java/im/vector/app/features/home/room/list/RoomListFragment.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/list/RoomListFragment.kt @@ -121,7 +121,7 @@ class RoomListFragment @Inject constructor( when (it) { is RoomListViewEvents.Loading -> showLoading(it.message) is RoomListViewEvents.Failure -> showFailure(it.throwable) - is RoomListViewEvents.SelectRoom -> handleSelectRoom(it) + is RoomListViewEvents.SelectRoom -> handleSelectRoom(it, it.isInviteAlreadyAccepted) is RoomListViewEvents.Done -> Unit is RoomListViewEvents.NavigateToMxToBottomSheet -> handleShowMxToLink(it.link) }.exhaustive @@ -184,8 +184,8 @@ class RoomListFragment @Inject constructor( super.onDestroyView() } - private fun handleSelectRoom(event: RoomListViewEvents.SelectRoom) { - navigator.openRoom(requireActivity(), event.roomSummary.roomId) + private fun handleSelectRoom(event: RoomListViewEvents.SelectRoom, isInviteAlreadyAccepted: Boolean) { + navigator.openRoom(context = requireActivity(), roomId = event.roomSummary.roomId, isInviteAlreadyAccepted = isInviteAlreadyAccepted) } private fun setupCreateRoomButton() { diff --git a/vector/src/main/java/im/vector/app/features/home/room/list/RoomListViewEvents.kt b/vector/src/main/java/im/vector/app/features/home/room/list/RoomListViewEvents.kt index df2ff58da6..15e16c464f 100644 --- a/vector/src/main/java/im/vector/app/features/home/room/list/RoomListViewEvents.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/list/RoomListViewEvents.kt @@ -27,7 +27,7 @@ sealed class RoomListViewEvents : VectorViewEvents { data class Loading(val message: CharSequence? = null) : RoomListViewEvents() data class Failure(val throwable: Throwable) : RoomListViewEvents() - data class SelectRoom(val roomSummary: RoomSummary) : RoomListViewEvents() + data class SelectRoom(val roomSummary: RoomSummary, val isInviteAlreadyAccepted: Boolean = false) : RoomListViewEvents() object Done : RoomListViewEvents() data class NavigateToMxToBottomSheet(val link: String) : RoomListViewEvents() } diff --git a/vector/src/main/java/im/vector/app/features/home/room/list/RoomListViewModel.kt b/vector/src/main/java/im/vector/app/features/home/room/list/RoomListViewModel.kt index a5977501d2..4a81a8b526 100644 --- a/vector/src/main/java/im/vector/app/features/home/room/list/RoomListViewModel.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/list/RoomListViewModel.kt @@ -33,7 +33,6 @@ import im.vector.app.core.extensions.exhaustive import im.vector.app.core.platform.VectorViewModel import im.vector.app.core.resources.StringProvider import im.vector.app.features.analytics.AnalyticsTracker -import im.vector.app.features.analytics.extensions.toAnalyticsJoinedRoom import im.vector.app.features.displayname.getBestName import im.vector.app.features.invite.AutoAcceptInvites import im.vector.app.features.settings.VectorPreferences @@ -174,7 +173,7 @@ class RoomListViewModel @AssistedInject constructor( // PRIVATE METHODS ***************************************************************************** private fun handleSelectRoom(action: RoomListAction.SelectRoom) = withState { - _viewEvents.post(RoomListViewEvents.SelectRoom(action.roomSummary)) + _viewEvents.post(RoomListViewEvents.SelectRoom(action.roomSummary, false)) } private fun handleToggleSection(roomSection: RoomsSection) { @@ -208,6 +207,7 @@ class RoomListViewModel @AssistedInject constructor( Timber.w("Try to join an already joining room. Should not happen") return@withState } + _viewEvents.post(RoomListViewEvents.SelectRoom(action.roomSummary, true)) // quick echo setState { @@ -221,18 +221,6 @@ class RoomListViewModel @AssistedInject constructor( } ) } - - viewModelScope.launch { - try { - session.joinRoom(roomId) - analyticsTracker.capture(action.roomSummary.toAnalyticsJoinedRoom()) - // We do not update the joiningRoomsIds here, because, the room is not joined yet regarding the sync data. - // Instead, we wait for the room to be joined - } catch (failure: Throwable) { - // Notify the user - _viewEvents.post(RoomListViewEvents.Failure(failure)) - } - } } private fun handleRejectInvitation(action: RoomListAction.RejectInvitation) = withState { state -> diff --git a/vector/src/main/java/im/vector/app/features/navigation/DefaultNavigator.kt b/vector/src/main/java/im/vector/app/features/navigation/DefaultNavigator.kt index b521710c1e..cc02687d93 100644 --- a/vector/src/main/java/im/vector/app/features/navigation/DefaultNavigator.kt +++ b/vector/src/main/java/im/vector/app/features/navigation/DefaultNavigator.kt @@ -147,13 +147,14 @@ class DefaultNavigator @Inject constructor( context: Context, roomId: String, eventId: String?, - buildTask: Boolean + buildTask: Boolean, + isInviteAlreadyAccepted: Boolean ) { if (sessionHolder.getSafeActiveSession()?.getRoom(roomId) == null) { fatalError("Trying to open an unknown room $roomId", vectorPreferences.failFast()) return } - val args = TimelineArgs(roomId, eventId) + val args = TimelineArgs(roomId = roomId, eventId = eventId, isInviteAlreadyAccepted = isInviteAlreadyAccepted) val intent = RoomDetailActivity.newIntent(context, args) startActivity(context, intent, buildTask) } diff --git a/vector/src/main/java/im/vector/app/features/navigation/Navigator.kt b/vector/src/main/java/im/vector/app/features/navigation/Navigator.kt index b5e94241ce..a31dc8fb89 100644 --- a/vector/src/main/java/im/vector/app/features/navigation/Navigator.kt +++ b/vector/src/main/java/im/vector/app/features/navigation/Navigator.kt @@ -50,7 +50,7 @@ interface Navigator { fun softLogout(context: Context) - fun openRoom(context: Context, roomId: String, eventId: String? = null, buildTask: Boolean = false) + fun openRoom(context: Context, roomId: String, eventId: String? = null, buildTask: Boolean = false, isInviteAlreadyAccepted: Boolean = false) sealed class PostSwitchSpaceAction { object None : PostSwitchSpaceAction()