mirror of
https://github.com/element-hq/element-android
synced 2024-12-11 20:52:35 +03:00
Permalink handling for thread events
This commit is contained in:
parent
2a83e93265
commit
53ca86dc6c
8 changed files with 89 additions and 27 deletions
|
@ -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")
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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)
|
||||
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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>
|
||||
|
||||
|
|
Loading…
Reference in a new issue