mirror of
https://github.com/vector-im/element-android.git
synced 2024-11-15 01:35:07 +08:00
Implement "Jump to read receipt" and "Mention" actions on the room member profile screen
This commit is contained in:
parent
1fd24e746c
commit
7952e205b9
@ -15,6 +15,7 @@ Improvements 🙌:
|
||||
- Add a menu item in the timeline as a shortcut to invite user (#2171)
|
||||
- Drawer: move settings access and add sign out action (#2171)
|
||||
- Filter room member (and banned users) by name (#2184)
|
||||
- Implement "Jump to read receipt" and "Mention" actions on the room member profile screen
|
||||
|
||||
Bugfix 🐛:
|
||||
- Improve support for image/audio/video/file selection with intent changes (#1376)
|
||||
|
@ -63,6 +63,14 @@ interface ReadService {
|
||||
*/
|
||||
fun getMyReadReceiptLive(): LiveData<Optional<String>>
|
||||
|
||||
/**
|
||||
* Get the eventId where the read receipt for the provided user is
|
||||
* @param otherUserId the userId param to look for
|
||||
*
|
||||
* @return the eventId where the read receipt for the provided user is attached, or null if not found
|
||||
*/
|
||||
fun getUserReadReceipt(otherUserId: String): String?
|
||||
|
||||
/**
|
||||
* Returns a live list of read receipts for a given event
|
||||
* @param eventId: the event
|
||||
|
@ -107,6 +107,16 @@ internal class DefaultReadService @AssistedInject constructor(
|
||||
}
|
||||
}
|
||||
|
||||
override fun getUserReadReceipt(otherUserId: String): String? {
|
||||
var eventId: String? = null
|
||||
monarchy.doWithRealm {
|
||||
eventId = ReadReceiptEntity.where(it, roomId = roomId, userId = otherUserId)
|
||||
.findFirst()
|
||||
?.eventId
|
||||
}
|
||||
return eventId
|
||||
}
|
||||
|
||||
override fun getEventReadReceiptsLive(eventId: String): LiveData<List<ReadReceipt>> {
|
||||
val liveRealmData = monarchy.findAllMappedWithChanges(
|
||||
{ ReadReceiptsSummaryEntity.where(it, eventId) },
|
||||
|
@ -36,6 +36,7 @@ import im.vector.app.features.crypto.verification.IncomingVerificationRequestHan
|
||||
import im.vector.app.features.grouplist.SelectedGroupDataSource
|
||||
import im.vector.app.features.home.AvatarRenderer
|
||||
import im.vector.app.features.home.HomeRoomListDataSource
|
||||
import im.vector.app.features.home.room.detail.RoomDetailPendingActionStore
|
||||
import im.vector.app.features.home.room.detail.timeline.helper.MatrixItemColorProvider
|
||||
import im.vector.app.features.html.EventHtmlRenderer
|
||||
import im.vector.app.features.html.VectorHtmlCompressor
|
||||
@ -114,6 +115,8 @@ interface VectorComponent {
|
||||
|
||||
fun selectedGroupStore(): SelectedGroupDataSource
|
||||
|
||||
fun roomDetailPendingActionStore(): RoomDetailPendingActionStore
|
||||
|
||||
fun activeSessionObservableStore(): ActiveSessionDataSource
|
||||
|
||||
fun incomingVerificationRequestHandler(): IncomingVerificationRequestHandler
|
||||
|
@ -23,6 +23,7 @@ const val THREE_MINUTES = 3 * 60_000L
|
||||
|
||||
/**
|
||||
* Store an object T for a specific period of time
|
||||
* @param delay delay to keep the data, in millis
|
||||
*/
|
||||
open class TemporaryStore<T>(private val delay: Long = THREE_MINUTES) {
|
||||
|
||||
@ -30,14 +31,16 @@ open class TemporaryStore<T>(private val delay: Long = THREE_MINUTES) {
|
||||
|
||||
var data: T? = null
|
||||
set(value) {
|
||||
field = value
|
||||
timer?.cancel()
|
||||
timer = Timer().also {
|
||||
it.schedule(object : TimerTask() {
|
||||
override fun run() {
|
||||
field = null
|
||||
}
|
||||
}, delay)
|
||||
field = value
|
||||
if (value != null) {
|
||||
timer = Timer().also {
|
||||
it.schedule(object : TimerTask() {
|
||||
override fun run() {
|
||||
field = null
|
||||
}
|
||||
}, delay)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -88,4 +88,6 @@ sealed class RoomDetailAction : VectorViewModelAction {
|
||||
data class EnsureNativeWidgetAllowed(val widget: Widget,
|
||||
val userJustAccepted: Boolean,
|
||||
val grantedEvents: RoomDetailViewEvents) : RoomDetailAction()
|
||||
|
||||
data class JumpToReadReceipt(val userId: String) : RoomDetailAction()
|
||||
}
|
||||
|
@ -216,7 +216,8 @@ class RoomDetailFragment @Inject constructor(
|
||||
private val notificationUtils: NotificationUtils,
|
||||
private val webRtcPeerConnectionManager: WebRtcPeerConnectionManager,
|
||||
private val matrixItemColorProvider: MatrixItemColorProvider,
|
||||
private val imageContentRenderer: ImageContentRenderer
|
||||
private val imageContentRenderer: ImageContentRenderer,
|
||||
private val roomDetailPendingActionStore: RoomDetailPendingActionStore
|
||||
) :
|
||||
VectorBaseFragment(),
|
||||
TimelineEventController.Callback,
|
||||
@ -878,6 +879,17 @@ class RoomDetailFragment @Inject constructor(
|
||||
override fun onResume() {
|
||||
super.onResume()
|
||||
notificationDrawerManager.setCurrentRoom(roomDetailArgs.roomId)
|
||||
roomDetailPendingActionStore.data?.let { handlePendingAction(it) }
|
||||
roomDetailPendingActionStore.data = null
|
||||
}
|
||||
|
||||
private fun handlePendingAction(roomDetailPendingAction: RoomDetailPendingAction) {
|
||||
when (roomDetailPendingAction) {
|
||||
is RoomDetailPendingAction.JumpToReadReceipt ->
|
||||
roomDetailViewModel.handle(RoomDetailAction.JumpToReadReceipt(roomDetailPendingAction.userId))
|
||||
is RoomDetailPendingAction.MentionUser ->
|
||||
insertUserDisplayNameInTextEditor(roomDetailPendingAction.userId)
|
||||
}.exhaustive
|
||||
}
|
||||
|
||||
override fun onPause() {
|
||||
|
@ -0,0 +1,22 @@
|
||||
/*
|
||||
* 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.home.room.detail
|
||||
|
||||
sealed class RoomDetailPendingAction {
|
||||
data class JumpToReadReceipt(val userId: String) : RoomDetailPendingAction()
|
||||
data class MentionUser(val userId: String) : RoomDetailPendingAction()
|
||||
}
|
@ -0,0 +1,25 @@
|
||||
/*
|
||||
* 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.home.room.detail
|
||||
|
||||
import im.vector.app.core.utils.TemporaryStore
|
||||
import javax.inject.Inject
|
||||
import javax.inject.Singleton
|
||||
|
||||
// Store to keep a pending action from sub screen of a room detail
|
||||
@Singleton
|
||||
class RoomDetailPendingActionStore @Inject constructor() : TemporaryStore<RoomDetailPendingAction>(10_000)
|
@ -274,9 +274,15 @@ class RoomDetailViewModel @AssistedInject constructor(
|
||||
is RoomDetailAction.RemoveWidget -> handleDeleteWidget(action.widgetId)
|
||||
is RoomDetailAction.EnsureNativeWidgetAllowed -> handleCheckWidgetAllowed(action)
|
||||
is RoomDetailAction.CancelSend -> handleCancel(action)
|
||||
is RoomDetailAction.JumpToReadReceipt -> handleJumpToReadReceipt(action)
|
||||
}.exhaustive
|
||||
}
|
||||
|
||||
private fun handleJumpToReadReceipt(action: RoomDetailAction.JumpToReadReceipt) {
|
||||
room.getUserReadReceipt(action.userId)
|
||||
?.let { handleNavigateToEvent(RoomDetailAction.NavigateToEvent(it, true)) }
|
||||
}
|
||||
|
||||
private fun handleSendSticker(action: RoomDetailAction.SendSticker) {
|
||||
room.sendEvent(EventType.STICKER, action.stickerContent.toContent())
|
||||
}
|
||||
|
@ -43,6 +43,8 @@ import im.vector.app.core.platform.VectorBaseFragment
|
||||
import im.vector.app.core.utils.startSharePlainTextIntent
|
||||
import im.vector.app.features.crypto.verification.VerificationBottomSheet
|
||||
import im.vector.app.features.home.AvatarRenderer
|
||||
import im.vector.app.features.home.room.detail.RoomDetailPendingAction
|
||||
import im.vector.app.features.home.room.detail.RoomDetailPendingActionStore
|
||||
import im.vector.app.features.roommemberprofile.devices.DeviceListBottomSheet
|
||||
import im.vector.app.features.roommemberprofile.powerlevel.EditPowerLevelDialogs
|
||||
import kotlinx.android.parcel.Parcelize
|
||||
@ -61,7 +63,8 @@ data class RoomMemberProfileArgs(
|
||||
class RoomMemberProfileFragment @Inject constructor(
|
||||
val viewModelFactory: RoomMemberProfileViewModel.Factory,
|
||||
private val roomMemberProfileController: RoomMemberProfileController,
|
||||
private val avatarRenderer: AvatarRenderer
|
||||
private val avatarRenderer: AvatarRenderer,
|
||||
private val roomDetailPendingActionStore: RoomDetailPendingActionStore
|
||||
) : VectorBaseFragment(), RoomMemberProfileController.Callback {
|
||||
|
||||
private val fragmentArgs: RoomMemberProfileArgs by args()
|
||||
@ -276,11 +279,13 @@ class RoomMemberProfileFragment @Inject constructor(
|
||||
}
|
||||
|
||||
override fun onJumpToReadReceiptClicked() {
|
||||
vectorBaseActivity.notImplemented("Jump to read receipts")
|
||||
roomDetailPendingActionStore.data = RoomDetailPendingAction.JumpToReadReceipt(fragmentArgs.userId)
|
||||
vectorBaseActivity.finish()
|
||||
}
|
||||
|
||||
override fun onMentionClicked() {
|
||||
vectorBaseActivity.notImplemented("Mention")
|
||||
roomDetailPendingActionStore.data = RoomDetailPendingAction.MentionUser(fragmentArgs.userId)
|
||||
vectorBaseActivity.finish()
|
||||
}
|
||||
|
||||
private fun handleShareRoomMemberProfile(permalink: String) {
|
||||
|
@ -36,6 +36,7 @@ import im.vector.app.core.extensions.cleanup
|
||||
import im.vector.app.core.extensions.configureWith
|
||||
import im.vector.app.core.platform.VectorBaseFragment
|
||||
import im.vector.app.features.home.AvatarRenderer
|
||||
import im.vector.app.features.home.room.detail.RoomDetailPendingActionStore
|
||||
import im.vector.app.features.roomprofile.RoomProfileArgs
|
||||
import kotlinx.android.synthetic.main.fragment_room_setting_generic.*
|
||||
import javax.inject.Inject
|
||||
@ -43,7 +44,8 @@ import javax.inject.Inject
|
||||
class RoomMemberListFragment @Inject constructor(
|
||||
val viewModelFactory: RoomMemberListViewModel.Factory,
|
||||
private val roomMemberListController: RoomMemberListController,
|
||||
private val avatarRenderer: AvatarRenderer
|
||||
private val avatarRenderer: AvatarRenderer,
|
||||
private val roomDetailPendingActionStore: RoomDetailPendingActionStore
|
||||
) : VectorBaseFragment(), RoomMemberListController.Callback {
|
||||
|
||||
private val viewModel: RoomMemberListViewModel by fragmentViewModel()
|
||||
@ -96,6 +98,13 @@ class RoomMemberListFragment @Inject constructor(
|
||||
})
|
||||
}
|
||||
|
||||
override fun onResume() {
|
||||
super.onResume()
|
||||
if (roomDetailPendingActionStore.data != null) {
|
||||
vectorBaseActivity.finish()
|
||||
}
|
||||
}
|
||||
|
||||
override fun onDestroyView() {
|
||||
recyclerView.cleanup()
|
||||
super.onDestroyView()
|
||||
|
Loading…
Reference in New Issue
Block a user