mirror of
https://github.com/SchildiChat/SchildiChat-android.git
synced 2024-11-22 17:35:54 +03:00
Start importing permalink classes from old SDK/Riot
This commit is contained in:
parent
39ad44e9aa
commit
58f60eaab4
5 changed files with 247 additions and 1 deletions
|
@ -0,0 +1,115 @@
|
||||||
|
package im.vector.matrix.android.api.permalinks
|
||||||
|
|
||||||
|
import java.util.*
|
||||||
|
import java.util.regex.Pattern
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This class contains pattern to match the different Matrix ids
|
||||||
|
*/
|
||||||
|
object MatrixPatterns {
|
||||||
|
|
||||||
|
// Note: TLD is not mandatory (localhost, IP address...)
|
||||||
|
private val DOMAIN_REGEX = ":[A-Z0-9.-]+(:[0-9]{2,5})?"
|
||||||
|
|
||||||
|
// regex pattern to find matrix user ids in a string.
|
||||||
|
// See https://matrix.org/speculator/spec/HEAD/appendices.html#historical-user-ids
|
||||||
|
private val MATRIX_USER_IDENTIFIER_REGEX = "@[A-Z0-9\\x21-\\x39\\x3B-\\x7F]+$DOMAIN_REGEX"
|
||||||
|
val PATTERN_CONTAIN_MATRIX_USER_IDENTIFIER = Pattern.compile(MATRIX_USER_IDENTIFIER_REGEX, Pattern.CASE_INSENSITIVE)
|
||||||
|
|
||||||
|
// regex pattern to find room ids in a string.
|
||||||
|
private val MATRIX_ROOM_IDENTIFIER_REGEX = "![A-Z0-9]+$DOMAIN_REGEX"
|
||||||
|
val PATTERN_CONTAIN_MATRIX_ROOM_IDENTIFIER = Pattern.compile(MATRIX_ROOM_IDENTIFIER_REGEX, Pattern.CASE_INSENSITIVE)
|
||||||
|
|
||||||
|
// regex pattern to find room aliases in a string.
|
||||||
|
private val MATRIX_ROOM_ALIAS_REGEX = "#[A-Z0-9._%#@=+-]+$DOMAIN_REGEX"
|
||||||
|
val PATTERN_CONTAIN_MATRIX_ALIAS = Pattern.compile(MATRIX_ROOM_ALIAS_REGEX, Pattern.CASE_INSENSITIVE)
|
||||||
|
|
||||||
|
// regex pattern to find message ids in a string.
|
||||||
|
private val MATRIX_EVENT_IDENTIFIER_REGEX = "\\$[A-Z0-9]+$DOMAIN_REGEX"
|
||||||
|
val PATTERN_CONTAIN_MATRIX_EVENT_IDENTIFIER = Pattern.compile(MATRIX_EVENT_IDENTIFIER_REGEX, Pattern.CASE_INSENSITIVE)
|
||||||
|
|
||||||
|
// regex pattern to find group ids in a string.
|
||||||
|
private val MATRIX_GROUP_IDENTIFIER_REGEX = "\\+[A-Z0-9=_\\-./]+$DOMAIN_REGEX"
|
||||||
|
val PATTERN_CONTAIN_MATRIX_GROUP_IDENTIFIER = Pattern.compile(MATRIX_GROUP_IDENTIFIER_REGEX, Pattern.CASE_INSENSITIVE)
|
||||||
|
|
||||||
|
// regex pattern to find permalink with message id.
|
||||||
|
// Android does not support in URL so extract it.
|
||||||
|
private val PERMALINK_BASE_REGEX = "https://matrix\\.to/#/"
|
||||||
|
private val APP_BASE_REGEX = "https://[A-Z0-9.-]+\\.[A-Z]{2,}/[A-Z]{3,}/#/room/"
|
||||||
|
private val SEP_REGEX = "/"
|
||||||
|
|
||||||
|
private val LINK_TO_ROOM_ID_REGEXP = PERMALINK_BASE_REGEX + MATRIX_ROOM_IDENTIFIER_REGEX + SEP_REGEX + MATRIX_EVENT_IDENTIFIER_REGEX
|
||||||
|
val PATTERN_CONTAIN_MATRIX_TO_PERMALINK_ROOM_ID = Pattern.compile(LINK_TO_ROOM_ID_REGEXP, Pattern.CASE_INSENSITIVE)
|
||||||
|
|
||||||
|
private val LINK_TO_ROOM_ALIAS_REGEXP = PERMALINK_BASE_REGEX + MATRIX_ROOM_ALIAS_REGEX + SEP_REGEX + MATRIX_EVENT_IDENTIFIER_REGEX
|
||||||
|
val PATTERN_CONTAIN_MATRIX_TO_PERMALINK_ROOM_ALIAS = Pattern.compile(LINK_TO_ROOM_ALIAS_REGEXP, Pattern.CASE_INSENSITIVE)
|
||||||
|
|
||||||
|
private val LINK_TO_APP_ROOM_ID_REGEXP = APP_BASE_REGEX + MATRIX_ROOM_IDENTIFIER_REGEX + SEP_REGEX + MATRIX_EVENT_IDENTIFIER_REGEX
|
||||||
|
val PATTERN_CONTAIN_APP_LINK_PERMALINK_ROOM_ID = Pattern.compile(LINK_TO_APP_ROOM_ID_REGEXP, Pattern.CASE_INSENSITIVE)
|
||||||
|
|
||||||
|
private val LINK_TO_APP_ROOM_ALIAS_REGEXP = APP_BASE_REGEX + MATRIX_ROOM_ALIAS_REGEX + SEP_REGEX + MATRIX_EVENT_IDENTIFIER_REGEX
|
||||||
|
val PATTERN_CONTAIN_APP_LINK_PERMALINK_ROOM_ALIAS = Pattern.compile(LINK_TO_APP_ROOM_ALIAS_REGEXP, Pattern.CASE_INSENSITIVE)
|
||||||
|
|
||||||
|
// list of patterns to find some matrix item.
|
||||||
|
val MATRIX_PATTERNS = Arrays.asList(
|
||||||
|
MatrixPatterns.PATTERN_CONTAIN_MATRIX_TO_PERMALINK_ROOM_ID,
|
||||||
|
MatrixPatterns.PATTERN_CONTAIN_MATRIX_TO_PERMALINK_ROOM_ALIAS,
|
||||||
|
MatrixPatterns.PATTERN_CONTAIN_APP_LINK_PERMALINK_ROOM_ID,
|
||||||
|
MatrixPatterns.PATTERN_CONTAIN_APP_LINK_PERMALINK_ROOM_ALIAS,
|
||||||
|
MatrixPatterns.PATTERN_CONTAIN_MATRIX_USER_IDENTIFIER,
|
||||||
|
MatrixPatterns.PATTERN_CONTAIN_MATRIX_ALIAS,
|
||||||
|
MatrixPatterns.PATTERN_CONTAIN_MATRIX_ROOM_IDENTIFIER,
|
||||||
|
MatrixPatterns.PATTERN_CONTAIN_MATRIX_EVENT_IDENTIFIER,
|
||||||
|
MatrixPatterns.PATTERN_CONTAIN_MATRIX_GROUP_IDENTIFIER
|
||||||
|
)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tells if a string is a valid user Id.
|
||||||
|
*
|
||||||
|
* @param str the string to test
|
||||||
|
* @return true if the string is a valid user id
|
||||||
|
*/
|
||||||
|
fun isUserId(str: String?): Boolean {
|
||||||
|
return str != null && PATTERN_CONTAIN_MATRIX_USER_IDENTIFIER.matcher(str).matches()
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tells if a string is a valid room id.
|
||||||
|
*
|
||||||
|
* @param str the string to test
|
||||||
|
* @return true if the string is a valid room Id
|
||||||
|
*/
|
||||||
|
fun isRoomId(str: String?): Boolean {
|
||||||
|
return str != null && PATTERN_CONTAIN_MATRIX_ROOM_IDENTIFIER.matcher(str).matches()
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tells if a string is a valid room alias.
|
||||||
|
*
|
||||||
|
* @param str the string to test
|
||||||
|
* @return true if the string is a valid room alias.
|
||||||
|
*/
|
||||||
|
fun isRoomAlias(str: String?): Boolean {
|
||||||
|
return str != null && PATTERN_CONTAIN_MATRIX_ALIAS.matcher(str).matches()
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tells if a string is a valid event id.
|
||||||
|
*
|
||||||
|
* @param str the string to test
|
||||||
|
* @return true if the string is a valid event id.
|
||||||
|
*/
|
||||||
|
fun isEventId(str: String?): Boolean {
|
||||||
|
return str != null && PATTERN_CONTAIN_MATRIX_EVENT_IDENTIFIER.matcher(str).matches()
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tells if a string is a valid group id.
|
||||||
|
*
|
||||||
|
* @param str the string to test
|
||||||
|
* @return true if the string is a valid group id.
|
||||||
|
*/
|
||||||
|
fun isGroupId(str: String?): Boolean {
|
||||||
|
return str != null && PATTERN_CONTAIN_MATRIX_GROUP_IDENTIFIER.matcher(str).matches()
|
||||||
|
}
|
||||||
|
}// Cannot be instantiated
|
|
@ -0,0 +1,18 @@
|
||||||
|
package im.vector.matrix.android.api.permalinks
|
||||||
|
|
||||||
|
import android.text.style.ClickableSpan
|
||||||
|
import android.view.View
|
||||||
|
|
||||||
|
class MatrixURLSpan(private val url: String,
|
||||||
|
private val callback: Callback? = null) : ClickableSpan() {
|
||||||
|
|
||||||
|
interface Callback {
|
||||||
|
fun onUrlClicked(url: String)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onClick(widget: View) {
|
||||||
|
callback?.onUrlClicked(url)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,35 @@
|
||||||
|
package im.vector.matrix.android.api.permalinks
|
||||||
|
|
||||||
|
import android.text.Spannable
|
||||||
|
import android.text.SpannableStringBuilder
|
||||||
|
|
||||||
|
object MatrixUrlLinkify {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Find the matrix spans i.e matrix id , user id ... to display them as URL.
|
||||||
|
*
|
||||||
|
* @param spannableStringBuilder the text in which the matrix items has to be clickable.
|
||||||
|
*/
|
||||||
|
fun addLinks(spannableStringBuilder: SpannableStringBuilder, callback: MatrixURLSpan.Callback?) {
|
||||||
|
// sanity checks
|
||||||
|
if (spannableStringBuilder.isEmpty()) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
val text = spannableStringBuilder.toString()
|
||||||
|
for (index in MatrixPatterns.MATRIX_PATTERNS.indices) {
|
||||||
|
val pattern = MatrixPatterns.MATRIX_PATTERNS[index]
|
||||||
|
val matcher = pattern.matcher(spannableStringBuilder)
|
||||||
|
while (matcher.find()) {
|
||||||
|
val startPos = matcher.start(0)
|
||||||
|
if (startPos == 0 || text[startPos - 1] != '/') {
|
||||||
|
val endPos = matcher.end(0)
|
||||||
|
val url = text.substring(matcher.start(0), matcher.end(0))
|
||||||
|
val span = MatrixURLSpan(url, callback)
|
||||||
|
spannableStringBuilder.setSpan(span, startPos, endPos, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,78 @@
|
||||||
|
package im.vector.matrix.android.api.permalinks
|
||||||
|
|
||||||
|
import android.text.TextUtils
|
||||||
|
import im.vector.matrix.android.api.session.events.model.Event
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Useful methods to deals with Matrix permalink
|
||||||
|
*/
|
||||||
|
object PermalinkUtils {
|
||||||
|
|
||||||
|
private val MATRIX_TO_URL_BASE = "https://matrix.to/#/"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a permalink for an event.
|
||||||
|
* Ex: "https://matrix.to/#/!nbzmcXAqpxBXjAdgoX:matrix.org/$1531497316352799BevdV:matrix.org"
|
||||||
|
*
|
||||||
|
* @param event the event
|
||||||
|
* @return the permalink, or null in case of error
|
||||||
|
*/
|
||||||
|
fun createPermalink(event: Event): String? {
|
||||||
|
if (event.roomId.isNullOrEmpty() || event.eventId.isNullOrEmpty()) {
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
return createPermalink(event.roomId, event.eventId)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a permalink for an id (can be a user Id, Room Id, etc.).
|
||||||
|
* Ex: "https://matrix.to/#/@benoit:matrix.org"
|
||||||
|
*
|
||||||
|
* @param id the id
|
||||||
|
* @return the permalink, or null in case of error
|
||||||
|
*/
|
||||||
|
fun createPermalink(id: String): String? {
|
||||||
|
return if (TextUtils.isEmpty(id)) {
|
||||||
|
null
|
||||||
|
} else MATRIX_TO_URL_BASE + escape(id)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a permalink for an event. If you have an event you can use [.createPermalink]
|
||||||
|
* Ex: "https://matrix.to/#/!nbzmcXAqpxBXjAdgoX:matrix.org/$1531497316352799BevdV:matrix.org"
|
||||||
|
*
|
||||||
|
* @param roomId the id of the room
|
||||||
|
* @param eventId the id of the event
|
||||||
|
* @return the permalink
|
||||||
|
*/
|
||||||
|
fun createPermalink(roomId: String, eventId: String): String {
|
||||||
|
return MATRIX_TO_URL_BASE + escape(roomId) + "/" + escape(eventId)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Extract the linked id from the universal link
|
||||||
|
*
|
||||||
|
* @param url the universal link, Ex: "https://matrix.to/#/@benoit:matrix.org"
|
||||||
|
* @return the id from the url, ex: "@benoit:matrix.org", or null if the url is not a permalink
|
||||||
|
*/
|
||||||
|
fun getLinkedId(url: String?): String? {
|
||||||
|
val isSupported = url != null && url.startsWith(MATRIX_TO_URL_BASE)
|
||||||
|
|
||||||
|
return if (isSupported) {
|
||||||
|
url!!.substring(MATRIX_TO_URL_BASE.length)
|
||||||
|
} else null
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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("/".toRegex(), "%2F")
|
||||||
|
}
|
||||||
|
}
|
|
@ -25,7 +25,7 @@ data class Event(
|
||||||
@Json(name = "origin_server_ts") val originServerTs: Long? = null,
|
@Json(name = "origin_server_ts") val originServerTs: Long? = null,
|
||||||
@Json(name = "sender") val sender: String? = null,
|
@Json(name = "sender") val sender: String? = null,
|
||||||
@Json(name = "state_key") val stateKey: String? = null,
|
@Json(name = "state_key") val stateKey: String? = null,
|
||||||
@Json(name = "room_id") var roomId: String? = null,
|
@Json(name = "room_id") val roomId: String? = null,
|
||||||
@Json(name = "unsigned") val unsignedData: UnsignedData? = null,
|
@Json(name = "unsigned") val unsignedData: UnsignedData? = null,
|
||||||
@Json(name = "redacts") val redacts: String? = null
|
@Json(name = "redacts") val redacts: String? = null
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue