mirror of
https://github.com/element-hq/element-android
synced 2024-11-24 18:35:40 +03:00
Create a PermalinkFactory to avoid injecting the service in SDK classes
This commit is contained in:
parent
2c90e33ceb
commit
fde2bdf304
3 changed files with 130 additions and 80 deletions
|
@ -19,44 +19,26 @@ package org.matrix.android.sdk.internal.session.permalinks
|
|||
import org.matrix.android.sdk.api.session.events.model.Event
|
||||
import org.matrix.android.sdk.api.session.permalinks.PermalinkService
|
||||
import org.matrix.android.sdk.api.session.permalinks.PermalinkService.Companion.MATRIX_TO_URL_BASE
|
||||
import org.matrix.android.sdk.api.session.room.members.roomMemberQueryParams
|
||||
import org.matrix.android.sdk.api.session.room.model.Membership
|
||||
import org.matrix.android.sdk.internal.di.UserId
|
||||
import org.matrix.android.sdk.internal.session.room.RoomGetter
|
||||
import java.net.URLEncoder
|
||||
import javax.inject.Inject
|
||||
import javax.inject.Provider
|
||||
|
||||
internal class DefaultPermalinkService @Inject constructor(
|
||||
@UserId
|
||||
private val userId: String,
|
||||
// Use a provider to fix circular Dagger dependency
|
||||
private val roomGetterProvider: Provider<RoomGetter>
|
||||
private val permalinkFactory: PermalinkFactory
|
||||
) : PermalinkService {
|
||||
|
||||
override fun createPermalink(event: Event): String? {
|
||||
if (event.roomId.isNullOrEmpty() || event.eventId.isNullOrEmpty()) {
|
||||
return null
|
||||
}
|
||||
return createPermalink(event.roomId, event.eventId)
|
||||
return permalinkFactory.createPermalink(event)
|
||||
}
|
||||
|
||||
override fun createPermalink(id: String): String? {
|
||||
return if (id.isEmpty()) {
|
||||
null
|
||||
} else MATRIX_TO_URL_BASE + escape(id)
|
||||
return permalinkFactory.createPermalink(id)
|
||||
}
|
||||
|
||||
override fun createRoomPermalink(roomId: String): String? {
|
||||
return if (roomId.isEmpty()) {
|
||||
null
|
||||
} else {
|
||||
MATRIX_TO_URL_BASE + escape(roomId) + computeViaParams(userId, roomId)
|
||||
}
|
||||
return permalinkFactory.createRoomPermalink(roomId)
|
||||
}
|
||||
|
||||
override fun createPermalink(roomId: String, eventId: String): String {
|
||||
return MATRIX_TO_URL_BASE + escape(roomId) + "/" + escape(eventId) + computeViaParams(userId, roomId)
|
||||
return permalinkFactory.createPermalink(roomId, eventId)
|
||||
}
|
||||
|
||||
override fun getLinkedId(url: String): String? {
|
||||
|
@ -66,54 +48,4 @@ internal class DefaultPermalinkService @Inject constructor(
|
|||
url.substring(MATRIX_TO_URL_BASE.length)
|
||||
} else null
|
||||
}
|
||||
|
||||
/**
|
||||
* Compute the via parameters.
|
||||
* Take up to 3 homeserver domains, taking the most representative one regarding room members and including the
|
||||
* current user one.
|
||||
*/
|
||||
private fun computeViaParams(userId: String, roomId: String): String {
|
||||
val userHomeserver = userId.substringAfter(":")
|
||||
return getUserIdsOfJoinedMembers(roomId)
|
||||
.map { it.substringAfter(":") }
|
||||
.groupBy { it }
|
||||
.mapValues { it.value.size }
|
||||
.toMutableMap()
|
||||
// Ensure the user homeserver will be included
|
||||
.apply { this[userHomeserver] = Int.MAX_VALUE }
|
||||
.let { map -> map.keys.sortedByDescending { map[it] } }
|
||||
.take(3)
|
||||
.joinToString(prefix = "?via=", separator = "&via=") { URLEncoder.encode(it, "utf-8") }
|
||||
}
|
||||
|
||||
/**
|
||||
* Escape '/' in id, because it is used as a separator
|
||||
*
|
||||
* @param id the id to escape
|
||||
* @return the escaped id
|
||||
*/
|
||||
private fun escape(id: String): String {
|
||||
return id.replace("/", "%2F")
|
||||
}
|
||||
|
||||
/**
|
||||
* Unescape '/' in id
|
||||
*
|
||||
* @param id the id to escape
|
||||
* @return the escaped id
|
||||
*/
|
||||
private fun unescape(id: String): String {
|
||||
return id.replace("%2F", "/")
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a set of userIds of joined members of a room
|
||||
*/
|
||||
private fun getUserIdsOfJoinedMembers(roomId: String): Set<String> {
|
||||
return roomGetterProvider.get().getRoom(roomId)
|
||||
?.getRoomMembers(roomMemberQueryParams { memberships = listOf(Membership.JOIN) })
|
||||
?.map { it.userId }
|
||||
.orEmpty()
|
||||
.toSet()
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,118 @@
|
|||
/*
|
||||
* 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 org.matrix.android.sdk.internal.session.permalinks
|
||||
|
||||
import org.matrix.android.sdk.api.session.events.model.Event
|
||||
import org.matrix.android.sdk.api.session.permalinks.PermalinkService.Companion.MATRIX_TO_URL_BASE
|
||||
import org.matrix.android.sdk.api.session.room.members.roomMemberQueryParams
|
||||
import org.matrix.android.sdk.api.session.room.model.Membership
|
||||
import org.matrix.android.sdk.internal.di.UserId
|
||||
import org.matrix.android.sdk.internal.session.room.RoomGetter
|
||||
import java.net.URLEncoder
|
||||
import javax.inject.Inject
|
||||
import javax.inject.Provider
|
||||
|
||||
internal class PermalinkFactory @Inject constructor(
|
||||
@UserId
|
||||
private val userId: String,
|
||||
// Use a provider to fix circular Dagger dependency
|
||||
private val roomGetterProvider: Provider<RoomGetter>
|
||||
) {
|
||||
|
||||
fun createPermalink(event: Event): String? {
|
||||
if (event.roomId.isNullOrEmpty() || event.eventId.isNullOrEmpty()) {
|
||||
return null
|
||||
}
|
||||
return createPermalink(event.roomId, event.eventId)
|
||||
}
|
||||
|
||||
fun createPermalink(id: String): String? {
|
||||
return if (id.isEmpty()) {
|
||||
null
|
||||
} else MATRIX_TO_URL_BASE + escape(id)
|
||||
}
|
||||
|
||||
fun createRoomPermalink(roomId: String): String? {
|
||||
return if (roomId.isEmpty()) {
|
||||
null
|
||||
} else {
|
||||
MATRIX_TO_URL_BASE + escape(roomId) + computeViaParams(userId, roomId)
|
||||
}
|
||||
}
|
||||
|
||||
fun createPermalink(roomId: String, eventId: String): String {
|
||||
return MATRIX_TO_URL_BASE + escape(roomId) + "/" + escape(eventId) + computeViaParams(userId, roomId)
|
||||
}
|
||||
|
||||
fun getLinkedId(url: String): String? {
|
||||
val isSupported = url.startsWith(MATRIX_TO_URL_BASE)
|
||||
|
||||
return if (isSupported) {
|
||||
url.substring(MATRIX_TO_URL_BASE.length)
|
||||
} else null
|
||||
}
|
||||
|
||||
/**
|
||||
* Compute the via parameters.
|
||||
* Take up to 3 homeserver domains, taking the most representative one regarding room members and including the
|
||||
* current user one.
|
||||
*/
|
||||
private fun computeViaParams(userId: String, roomId: String): String {
|
||||
val userHomeserver = userId.substringAfter(":")
|
||||
return getUserIdsOfJoinedMembers(roomId)
|
||||
.map { it.substringAfter(":") }
|
||||
.groupBy { it }
|
||||
.mapValues { it.value.size }
|
||||
.toMutableMap()
|
||||
// Ensure the user homeserver will be included
|
||||
.apply { this[userHomeserver] = Int.MAX_VALUE }
|
||||
.let { map -> map.keys.sortedByDescending { map[it] } }
|
||||
.take(3)
|
||||
.joinToString(prefix = "?via=", separator = "&via=") { URLEncoder.encode(it, "utf-8") }
|
||||
}
|
||||
|
||||
/**
|
||||
* Escape '/' in id, because it is used as a separator
|
||||
*
|
||||
* @param id the id to escape
|
||||
* @return the escaped id
|
||||
*/
|
||||
private fun escape(id: String): String {
|
||||
return id.replace("/", "%2F")
|
||||
}
|
||||
|
||||
/**
|
||||
* Unescape '/' in id
|
||||
*
|
||||
* @param id the id to escape
|
||||
* @return the escaped id
|
||||
*/
|
||||
private fun unescape(id: String): String {
|
||||
return id.replace("%2F", "/")
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a set of userIds of joined members of a room
|
||||
*/
|
||||
private fun getUserIdsOfJoinedMembers(roomId: String): Set<String> {
|
||||
return roomGetterProvider.get().getRoom(roomId)
|
||||
?.getRoomMembers(roomMemberQueryParams { memberships = listOf(Membership.JOIN) })
|
||||
?.map { it.userId }
|
||||
.orEmpty()
|
||||
.toSet()
|
||||
}
|
||||
}
|
|
@ -30,7 +30,6 @@ import org.matrix.android.sdk.api.session.events.model.LocalEcho
|
|||
import org.matrix.android.sdk.api.session.events.model.RelationType
|
||||
import org.matrix.android.sdk.api.session.events.model.UnsignedData
|
||||
import org.matrix.android.sdk.api.session.events.model.toContent
|
||||
import org.matrix.android.sdk.api.session.permalinks.PermalinkService
|
||||
import org.matrix.android.sdk.api.session.room.model.message.AudioInfo
|
||||
import org.matrix.android.sdk.api.session.room.model.message.FileInfo
|
||||
import org.matrix.android.sdk.api.session.room.model.message.ImageInfo
|
||||
|
@ -59,6 +58,7 @@ import org.matrix.android.sdk.api.session.room.timeline.getLastMessageContent
|
|||
import org.matrix.android.sdk.api.session.room.timeline.isReply
|
||||
import org.matrix.android.sdk.internal.di.UserId
|
||||
import org.matrix.android.sdk.internal.session.content.ThumbnailExtractor
|
||||
import org.matrix.android.sdk.internal.session.permalinks.PermalinkFactory
|
||||
import org.matrix.android.sdk.internal.session.room.send.pills.TextPillsUtils
|
||||
import org.matrix.android.sdk.internal.util.StringProvider
|
||||
import javax.inject.Inject
|
||||
|
@ -79,7 +79,7 @@ internal class LocalEchoEventFactory @Inject constructor(
|
|||
private val markdownParser: MarkdownParser,
|
||||
private val textPillsUtils: TextPillsUtils,
|
||||
private val localEchoRepository: LocalEchoRepository,
|
||||
private val permalinkService: PermalinkService
|
||||
private val permalinkFactory: PermalinkFactory
|
||||
) {
|
||||
fun createTextEvent(roomId: String, msgType: String, text: CharSequence, autoMarkdown: Boolean): Event {
|
||||
if (msgType == MessageType.MSGTYPE_TEXT || msgType == MessageType.MSGTYPE_EMOTE) {
|
||||
|
@ -168,8 +168,8 @@ internal class LocalEchoEventFactory @Inject constructor(
|
|||
newBodyAutoMarkdown: Boolean,
|
||||
msgType: String,
|
||||
compatibilityText: String): Event {
|
||||
val permalink = permalinkService.createPermalink(roomId, originalEvent.root.eventId ?: "")
|
||||
val userLink = originalEvent.root.senderId?.let { permalinkService.createPermalink(it) } ?: ""
|
||||
val permalink = permalinkFactory.createPermalink(roomId, originalEvent.root.eventId ?: "")
|
||||
val userLink = originalEvent.root.senderId?.let { permalinkFactory.createPermalink(it) } ?: ""
|
||||
|
||||
val body = bodyForReply(originalEvent.getLastMessageContent(), originalEvent.isReply())
|
||||
val replyFormatted = REPLY_PATTERN.format(
|
||||
|
@ -205,7 +205,7 @@ internal class LocalEchoEventFactory @Inject constructor(
|
|||
ContentAttachmentData.Type.IMAGE -> createImageEvent(roomId, attachment)
|
||||
ContentAttachmentData.Type.VIDEO -> createVideoEvent(roomId, attachment)
|
||||
ContentAttachmentData.Type.AUDIO -> createAudioEvent(roomId, attachment)
|
||||
ContentAttachmentData.Type.FILE -> createFileEvent(roomId, attachment)
|
||||
ContentAttachmentData.Type.FILE -> createFileEvent(roomId, attachment)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -365,9 +365,9 @@ internal class LocalEchoEventFactory @Inject constructor(
|
|||
autoMarkdown: Boolean): Event? {
|
||||
// Fallbacks and event representation
|
||||
// TODO Add error/warning logs when any of this is null
|
||||
val permalink = permalinkService.createPermalink(eventReplied.root) ?: return null
|
||||
val permalink = permalinkFactory.createPermalink(eventReplied.root) ?: return null
|
||||
val userId = eventReplied.root.senderId ?: return null
|
||||
val userLink = permalinkService.createPermalink(userId) ?: return null
|
||||
val userLink = permalinkFactory.createPermalink(userId) ?: return null
|
||||
|
||||
val body = bodyForReply(eventReplied.getLastMessageContent(), eventReplied.isReply())
|
||||
val replyFormatted = REPLY_PATTERN.format(
|
||||
|
|
Loading…
Reference in a new issue