Permalink handling for thread events

This commit is contained in:
ariskotsomitopoulos 2021-11-29 18:08:16 +00:00
parent 2a83e93265
commit 53ca86dc6c
8 changed files with 89 additions and 27 deletions

View file

@ -556,7 +556,7 @@ class HomeActivity :
return true
}
override fun navToRoom(roomId: String?, eventId: String?, deepLink: Uri?): Boolean {
override fun navToRoom(roomId: String?, eventId: String?, deepLink: Uri?, rootThreadEventId: String?): Boolean {
if (roomId == null) return false
MatrixToBottomSheet.withLink(deepLink.toString())
.show(supportFragmentManager, "HA#MatrixToBottomSheet")

View file

@ -984,7 +984,12 @@ class TimelineFragment @Inject constructor(
true
}
R.id.menu_thread_timeline_copy_link -> {
requireActivity().toast("menu_thread_timeline_copy_link")
getRootThreadEventId()?.let {
val permalink = session.permalinkService().createPermalink(timelineArgs.roomId, it)
copyToClipboard(requireContext(), permalink, false)
showSnackWithMessage(getString(R.string.copied_to_clipboard))
}
true
}
R.id.menu_thread_timeline_view_in_room -> {
@ -992,7 +997,10 @@ class TimelineFragment @Inject constructor(
true
}
R.id.menu_thread_timeline_share -> {
requireActivity().toast("menu_thread_timeline_share")
getRootThreadEventId()?.let {
val permalink = session.permalinkService().createPermalink(timelineArgs.roomId, it)
shareText(requireContext(), permalink)
}
true
}
else -> super.onOptionsItemSelected(item)
@ -1649,20 +1657,36 @@ class TimelineFragment @Inject constructor(
viewLifecycleOwner.lifecycleScope.launch {
val isManaged = permalinkHandler
.launch(requireActivity(), url, object : NavigationInterceptor {
override fun navToRoom(roomId: String?, eventId: String?, deepLink: Uri?): Boolean {
override fun navToRoom(roomId: String?, eventId: String?, deepLink: Uri?, rootThreadEventId: String?): Boolean {
// Same room?
if (roomId == timelineArgs.roomId) {
// Navigation to same room
if (eventId == null) {
if (roomId != timelineArgs.roomId) return false
// Navigation to same room
if (!isThreadTimeLine()) {
if (rootThreadEventId != null) {
// Thread link, so PermalinkHandler will handle the navigation
return false
}
return if (eventId == null) {
showSnackWithMessage(getString(R.string.navigate_to_room_when_already_in_the_room))
true
} else {
// Highlight and scroll to this event
roomDetailViewModel.handle(RoomDetailAction.NavigateToEvent(eventId, true))
true
}
} else {
return if (rootThreadEventId == getRootThreadEventId() && eventId == null) {
showSnackWithMessage(getString(R.string.navigate_to_thread_when_already_in_the_thread))
true
} else if (rootThreadEventId == getRootThreadEventId() && eventId != null) {
// we are in the same thread
roomDetailViewModel.handle(RoomDetailAction.NavigateToEvent(eventId, true))
true
} else {
false
}
return true
}
// Not handled
return false
}
override fun navToMemberProfile(userId: String, deepLink: Uri): Boolean {
@ -1816,7 +1840,6 @@ class TimelineFragment @Inject constructor(
}
}
override fun onAvatarClicked(informationData: MessageInformationData) {
// roomDetailViewModel.handle(RoomDetailAction.RequestVerification(informationData.userId))
openRoomMemberProfile(informationData.senderId)
@ -1862,7 +1885,7 @@ class TimelineFragment @Inject constructor(
viewLifecycleOwner.lifecycleScope.launchWhenResumed {
permalinkHandler
.launch(requireContext(), url, object : NavigationInterceptor {
override fun navToRoom(roomId: String?, eventId: String?, deepLink: Uri?): Boolean {
override fun navToRoom(roomId: String?, eventId: String?, deepLink: Uri?, rootThreadEventId: String?): Boolean {
requireActivity().finish()
return false
}

View file

@ -94,6 +94,7 @@ class ThreadsActivity : VectorBaseActivity<ActivityThreadsBinding>(), ToolbarCon
TimelineFragment::class.java,
TimelineArgs(
roomId = threadTimelineArgs.roomId,
eventId = getEventIdToNavigate(),
threadTimelineArgs = threadTimelineArgs
))
@ -141,15 +142,23 @@ class ThreadsActivity : VectorBaseActivity<ActivityThreadsBinding>(), ToolbarCon
private fun getThreadTimelineArgs(): ThreadTimelineArgs? = intent?.extras?.getParcelable(THREAD_TIMELINE_ARGS)
private fun getThreadListArgs(): ThreadListArgs? = intent?.extras?.getParcelable(THREAD_LIST_ARGS)
private fun getEventIdToNavigate(): String? = intent?.extras?.getString(THREAD_EVENT_ID_TO_NAVIGATE)
companion object {
// private val FRAGMENT_TAG = RoomThreadDetailFragment::class.simpleName
const val THREAD_TIMELINE_ARGS = "THREAD_TIMELINE_ARGS"
const val THREAD_EVENT_ID_TO_NAVIGATE = "THREAD_EVENT_ID_TO_NAVIGATE"
const val THREAD_LIST_ARGS = "THREAD_LIST_ARGS"
fun newIntent(context: Context, threadTimelineArgs: ThreadTimelineArgs?, threadListArgs: ThreadListArgs?): Intent {
fun newIntent(
context: Context,
threadTimelineArgs: ThreadTimelineArgs?,
threadListArgs: ThreadListArgs?,
eventIdToNavigate: String? = null
): Intent {
return Intent(context, ThreadsActivity::class.java).apply {
putExtra(THREAD_TIMELINE_ARGS, threadTimelineArgs)
putExtra(THREAD_EVENT_ID_TO_NAVIGATE, eventIdToNavigate)
putExtra(THREAD_LIST_ARGS, threadListArgs)
}

View file

@ -116,7 +116,12 @@ class DefaultNavigator @Inject constructor(
context.startActivity(intent)
}
override fun openRoom(context: Context, roomId: String, eventId: String?, buildTask: Boolean) {
override fun openRoom(
context: Context,
roomId: String,
eventId: String?,
buildTask: Boolean
) {
if (sessionHolder.getSafeActiveSession()?.getRoom(roomId) == null) {
fatalError("Trying to open an unknown room $roomId", vectorPreferences.failFast())
return
@ -511,16 +516,19 @@ class DefaultNavigator @Inject constructor(
}
}
override fun openThread(context: Context, threadTimelineArgs: ThreadTimelineArgs) {
override fun openThread(context: Context, threadTimelineArgs: ThreadTimelineArgs, eventIdToNavigate: String?) {
context.startActivity(ThreadsActivity.newIntent(
context = context,
threadTimelineArgs = threadTimelineArgs,
threadListArgs =null))
threadTimelineArgs = threadTimelineArgs,
threadListArgs = null,
eventIdToNavigate = eventIdToNavigate
))
}
override fun openThreadList(context: Context, threadTimelineArgs: ThreadTimelineArgs) {
context.startActivity(ThreadsActivity.newIntent(
context = context,
threadTimelineArgs = null,
threadTimelineArgs = null,
threadListArgs = ThreadListArgs(
roomId = threadTimelineArgs.roomId,
displayName = threadTimelineArgs.displayName,

View file

@ -142,7 +142,7 @@ interface Navigator {
fun openCallTransfer(context: Context, callId: String)
fun openThread(context: Context, threadTimelineArgs: ThreadTimelineArgs)
fun openThread(context: Context, threadTimelineArgs: ThreadTimelineArgs, eventIdToNavigate: String? = null)
fun openThreadList(context: Context, threadTimelineArgs: ThreadTimelineArgs)

View file

@ -21,12 +21,14 @@ import android.net.Uri
import im.vector.app.R
import im.vector.app.core.di.ActiveSessionHolder
import im.vector.app.core.utils.toast
import im.vector.app.features.home.room.threads.arguments.ThreadTimelineArgs
import im.vector.app.features.navigation.Navigator
import im.vector.app.features.roomdirectory.roompreview.RoomPreviewData
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
import org.matrix.android.sdk.api.extensions.orFalse
import org.matrix.android.sdk.api.extensions.tryOrNull
import org.matrix.android.sdk.api.session.events.model.getRootThreadEventId
import org.matrix.android.sdk.api.session.permalinks.PermalinkData
import org.matrix.android.sdk.api.session.permalinks.PermalinkParser
import org.matrix.android.sdk.api.session.permalinks.PermalinkService
@ -74,13 +76,27 @@ class PermalinkHandler @Inject constructor(private val activeSessionHolder: Acti
return when (permalinkData) {
is PermalinkData.RoomLink -> {
val roomId = permalinkData.getRoomId()
if (navigationInterceptor?.navToRoom(roomId, permalinkData.eventId, rawLink) != true) {
val session = activeSessionHolder.getSafeActiveSession()
val rootThreadEventId = permalinkData.eventId?.let { eventId ->
val room = roomId?.let { session?.getRoom(it) }
// Root thread will be opened in timeline
// if(room?.getTimeLineEvent(eventId)?.root?.threadDetails?.isRootThread == true){
// room.getTimeLineEvent(eventId)?.root?.eventId
// }else{
room?.getTimeLineEvent(eventId)?.root?.getRootThreadEventId()
// }
}
if (navigationInterceptor?.navToRoom(roomId, permalinkData.eventId, rawLink, rootThreadEventId) != true) {
openRoom(
context = context,
roomId = roomId,
permalinkData = permalinkData,
rawLink = rawLink,
buildTask = buildTask
buildTask = buildTask,
rootThreadEventId = rootThreadEventId
)
}
true
@ -115,8 +131,8 @@ class PermalinkHandler @Inject constructor(private val activeSessionHolder: Acti
private fun isPermalinkSupported(context: Context, url: String): Boolean {
return url.startsWith(PermalinkService.MATRIX_TO_URL_BASE) ||
context.resources.getStringArray(R.array.permalink_supported_hosts).any {
url.startsWith(it)
}
url.startsWith(it)
}
}
private suspend fun PermalinkData.RoomLink.getRoomId(): String? {
@ -145,7 +161,8 @@ class PermalinkHandler @Inject constructor(private val activeSessionHolder: Acti
roomId: String?,
permalinkData: PermalinkData.RoomLink,
rawLink: Uri,
buildTask: Boolean
buildTask: Boolean,
rootThreadEventId: String? =null
) {
val session = activeSessionHolder.getSafeActiveSession() ?: return
if (roomId == null) {
@ -155,6 +172,7 @@ class PermalinkHandler @Inject constructor(private val activeSessionHolder: Acti
val roomSummary = session.getRoomSummary(roomId)
val membership = roomSummary?.membership
val eventId = permalinkData.eventId
// val roomAlias = permalinkData.getRoomAliasOrNull()
val isSpace = roomSummary?.roomType == RoomType.SPACE
return when {
@ -162,7 +180,10 @@ class PermalinkHandler @Inject constructor(private val activeSessionHolder: Acti
membership?.isActive().orFalse() -> {
if (!isSpace && membership == Membership.JOIN) {
// If it's a room you're in, let's just open it, you can tap back if needed
navigator.openRoom(context, roomId, eventId, buildTask)
rootThreadEventId?.let {
val threadTimelineArgs = ThreadTimelineArgs(roomId, displayName = roomSummary.displayName, roomSummary.avatarUrl, it)
navigator.openThread(context, threadTimelineArgs, eventId)
} ?: navigator.openRoom(context, roomId, eventId, buildTask)
} else {
// maybe open space preview navigator.openSpacePreview(context, roomId)? if already joined?
navigator.openMatrixToBottomSheet(context, rawLink.toString())
@ -187,7 +208,7 @@ interface NavigationInterceptor {
/**
* Return true if the navigation has been intercepted
*/
fun navToRoom(roomId: String?, eventId: String?, deepLink: Uri? = null): Boolean {
fun navToRoom(roomId: String?, eventId: String?, deepLink: Uri? = null, rootThreadEventId: String? = null): Boolean {
return false
}

View file

@ -130,7 +130,7 @@ class PublicRoomsFragment @Inject constructor(
val permalink = session.permalinkService().createPermalink(roomIdOrAlias)
val isHandled = permalinkHandler
.launch(requireContext(), permalink, object : NavigationInterceptor {
override fun navToRoom(roomId: String?, eventId: String?, deepLink: Uri?): Boolean {
override fun navToRoom(roomId: String?, eventId: String?, deepLink: Uri?, rootThreadEventId: String?): Boolean {
requireActivity().finish()
return false
}

View file

@ -2259,6 +2259,7 @@
<string name="settings_sdk_version">Matrix SDK Version</string>
<string name="settings_other_third_party_notices">Other third party notices</string>
<string name="navigate_to_room_when_already_in_the_room">You are already viewing this room!</string>
<string name="navigate_to_thread_when_already_in_the_thread">You are already viewing this thread!</string>
<string name="quick_reactions">Quick Reactions</string>