forked from GitHub-Mirror/riotX-android
Content : make content url resolution aware of homeserver url
This commit is contained in:
parent
1d400180bc
commit
cc4c1cf308
@ -4,16 +4,13 @@ import android.widget.ImageView
|
|||||||
import androidx.core.content.ContextCompat
|
import androidx.core.content.ContextCompat
|
||||||
import com.amulyakhare.textdrawable.TextDrawable
|
import com.amulyakhare.textdrawable.TextDrawable
|
||||||
import com.bumptech.glide.request.RequestOptions
|
import com.bumptech.glide.request.RequestOptions
|
||||||
import im.vector.matrix.android.api.session.content.ContentUrlResolver
|
import im.vector.matrix.android.api.Matrix
|
||||||
import im.vector.matrix.android.api.session.room.model.RoomMember
|
import im.vector.matrix.android.api.session.room.model.RoomMember
|
||||||
import im.vector.matrix.android.api.session.room.model.RoomSummary
|
import im.vector.matrix.android.api.session.room.model.RoomSummary
|
||||||
import im.vector.riotredesign.R
|
import im.vector.riotredesign.R
|
||||||
import im.vector.riotredesign.core.extensions.firstCharAsString
|
import im.vector.riotredesign.core.extensions.firstCharAsString
|
||||||
import im.vector.riotredesign.core.glide.GlideApp
|
import im.vector.riotredesign.core.glide.GlideApp
|
||||||
|
|
||||||
private const val MEDIA_URL = "https://matrix.org/_matrix/media/v1/download/"
|
|
||||||
private const val MXC_PREFIX = "mxc://"
|
|
||||||
|
|
||||||
object AvatarRenderer {
|
object AvatarRenderer {
|
||||||
|
|
||||||
fun render(roomMember: RoomMember, imageView: ImageView) {
|
fun render(roomMember: RoomMember, imageView: ImageView) {
|
||||||
@ -28,7 +25,7 @@ object AvatarRenderer {
|
|||||||
if (name.isNullOrEmpty()) {
|
if (name.isNullOrEmpty()) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
val resolvedUrl = ContentUrlResolver.resolve(avatarUrl)
|
val resolvedUrl = Matrix.getInstance().currentSession.contentUrlResolver().resolveFullSize(avatarUrl)
|
||||||
val avatarColor = ContextCompat.getColor(imageView.context, R.color.pale_teal)
|
val avatarColor = ContextCompat.getColor(imageView.context, R.color.pale_teal)
|
||||||
val fallbackDrawable = TextDrawable.builder().buildRound(name.firstCharAsString().toUpperCase(), avatarColor)
|
val fallbackDrawable = TextDrawable.builder().buildRound(name.firstCharAsString().toUpperCase(), avatarColor)
|
||||||
|
|
||||||
|
@ -5,6 +5,7 @@ import android.graphics.Point
|
|||||||
import android.media.ExifInterface
|
import android.media.ExifInterface
|
||||||
import android.view.WindowManager
|
import android.view.WindowManager
|
||||||
import android.widget.ImageView
|
import android.widget.ImageView
|
||||||
|
import im.vector.matrix.android.api.Matrix
|
||||||
import im.vector.matrix.android.api.session.content.ContentUrlResolver
|
import im.vector.matrix.android.api.session.content.ContentUrlResolver
|
||||||
import im.vector.matrix.android.api.session.room.model.message.MessageImageContent
|
import im.vector.matrix.android.api.session.room.model.message.MessageImageContent
|
||||||
import im.vector.riotredesign.core.glide.GlideApp
|
import im.vector.riotredesign.core.glide.GlideApp
|
||||||
@ -48,12 +49,17 @@ object MessageImageRenderer {
|
|||||||
imageView.layoutParams.height = finalHeight
|
imageView.layoutParams.height = finalHeight
|
||||||
imageView.layoutParams.width = finalWidth
|
imageView.layoutParams.width = finalWidth
|
||||||
|
|
||||||
val resolvedUrl = ContentUrlResolver.resolve(messageContent.url) ?: return
|
val contentUrlResolver = Matrix.getInstance().currentSession.contentUrlResolver()
|
||||||
|
val resolvedUrl = contentUrlResolver.resolveThumbnail(
|
||||||
|
messageContent.url,
|
||||||
|
finalWidth,
|
||||||
|
finalHeight,
|
||||||
|
ContentUrlResolver.ThumbnailMethod.SCALE
|
||||||
|
) ?: return
|
||||||
|
|
||||||
GlideApp
|
GlideApp
|
||||||
.with(imageView)
|
.with(imageView)
|
||||||
.load(resolvedUrl)
|
.load(resolvedUrl)
|
||||||
.override(finalWidth, finalHeight)
|
|
||||||
.thumbnail(0.3f)
|
|
||||||
.into(imageView)
|
.into(imageView)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
package im.vector.matrix.android.api
|
package im.vector.matrix.android.api
|
||||||
|
|
||||||
import androidx.lifecycle.ProcessLifecycleOwner
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
|
import androidx.lifecycle.ProcessLifecycleOwner
|
||||||
import com.zhuinden.monarchy.Monarchy
|
import com.zhuinden.monarchy.Monarchy
|
||||||
import im.vector.matrix.android.api.auth.Authenticator
|
import im.vector.matrix.android.api.auth.Authenticator
|
||||||
import im.vector.matrix.android.api.session.Session
|
import im.vector.matrix.android.api.session.Session
|
||||||
|
@ -2,6 +2,7 @@ package im.vector.matrix.android.api.session
|
|||||||
|
|
||||||
import androidx.annotation.MainThread
|
import androidx.annotation.MainThread
|
||||||
import im.vector.matrix.android.api.auth.data.SessionParams
|
import im.vector.matrix.android.api.auth.data.SessionParams
|
||||||
|
import im.vector.matrix.android.api.session.content.ContentUrlResolver
|
||||||
import im.vector.matrix.android.api.session.group.GroupService
|
import im.vector.matrix.android.api.session.group.GroupService
|
||||||
import im.vector.matrix.android.api.session.room.RoomService
|
import im.vector.matrix.android.api.session.room.RoomService
|
||||||
|
|
||||||
@ -15,6 +16,8 @@ interface Session : RoomService, GroupService {
|
|||||||
@MainThread
|
@MainThread
|
||||||
fun close()
|
fun close()
|
||||||
|
|
||||||
|
fun contentUrlResolver(): ContentUrlResolver
|
||||||
|
|
||||||
fun addListener(listener: Listener)
|
fun addListener(listener: Listener)
|
||||||
|
|
||||||
fun removeListener(listener: Listener)
|
fun removeListener(listener: Listener)
|
||||||
|
@ -1,9 +1,32 @@
|
|||||||
|
/*
|
||||||
|
*
|
||||||
|
* * Copyright 2019 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.matrix.android.api.session.content
|
package im.vector.matrix.android.api.session.content
|
||||||
|
|
||||||
object ContentUrlResolver {
|
/**
|
||||||
|
* This interface defines methods for accessing content from the current session.
|
||||||
|
*/
|
||||||
|
interface ContentUrlResolver {
|
||||||
|
|
||||||
private const val MATRIX_CONTENT_URI_SCHEME = "mxc://"
|
enum class ThumbnailMethod(val value: String) {
|
||||||
private const val MEDIA_URL = "https://matrix.org/_matrix/media/v1/download/"
|
CROP("crop"),
|
||||||
|
SCALE("scale")
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the actual URL for accessing the full-size image of a Matrix media content URI.
|
* Get the actual URL for accessing the full-size image of a Matrix media content URI.
|
||||||
@ -11,21 +34,16 @@ object ContentUrlResolver {
|
|||||||
* @param contentUrl the Matrix media content URI (in the form of "mxc://...").
|
* @param contentUrl the Matrix media content URI (in the form of "mxc://...").
|
||||||
* @return the URL to access the described resource, or null if the url is invalid.
|
* @return the URL to access the described resource, or null if the url is invalid.
|
||||||
*/
|
*/
|
||||||
fun resolve(contentUrl: String?): String? {
|
fun resolveFullSize(contentUrl: String?): String?
|
||||||
if (contentUrl.isValidMatrixContentUrl()) {
|
|
||||||
return contentUrl?.replace(MATRIX_CONTENT_URI_SCHEME, MEDIA_URL)
|
|
||||||
}
|
|
||||||
return null
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check whether an url is a valid matrix content url.
|
* Get the actual URL for accessing the thumbnail image of a given Matrix media content URI.
|
||||||
*
|
*
|
||||||
* @param contentUrl the content URL (in the form of "mxc://...").
|
* @param contentUrl the Matrix media content URI (in the form of "mxc://...").
|
||||||
* @return true if contentUrl is valid.
|
* @param width the desired width
|
||||||
|
* @param height the desired height
|
||||||
|
* @param method the desired method (METHOD_CROP or METHOD_SCALE)
|
||||||
|
* @return the URL to access the described resource, or null if the url is invalid.
|
||||||
*/
|
*/
|
||||||
private fun String?.isValidMatrixContentUrl(): Boolean {
|
fun resolveThumbnail(contentUrl: String?, width: Int, height: Int, method: ThumbnailMethod): String?
|
||||||
return !this.isNullOrEmpty() && startsWith(MATRIX_CONTENT_URI_SCHEME)
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
@ -1,10 +1,11 @@
|
|||||||
package im.vector.matrix.android.internal.session
|
package im.vector.matrix.android.internal.session
|
||||||
|
|
||||||
import androidx.lifecycle.LiveData
|
|
||||||
import android.os.Looper
|
import android.os.Looper
|
||||||
import androidx.annotation.MainThread
|
import androidx.annotation.MainThread
|
||||||
|
import androidx.lifecycle.LiveData
|
||||||
import im.vector.matrix.android.api.auth.data.SessionParams
|
import im.vector.matrix.android.api.auth.data.SessionParams
|
||||||
import im.vector.matrix.android.api.session.Session
|
import im.vector.matrix.android.api.session.Session
|
||||||
|
import im.vector.matrix.android.api.session.content.ContentUrlResolver
|
||||||
import im.vector.matrix.android.api.session.group.Group
|
import im.vector.matrix.android.api.session.group.Group
|
||||||
import im.vector.matrix.android.api.session.group.GroupService
|
import im.vector.matrix.android.api.session.group.GroupService
|
||||||
import im.vector.matrix.android.api.session.group.model.GroupSummary
|
import im.vector.matrix.android.api.session.group.model.GroupSummary
|
||||||
@ -35,6 +36,7 @@ internal class DefaultSession(override val sessionParams: SessionParams) : Sessi
|
|||||||
private val roomService by inject<RoomService>()
|
private val roomService by inject<RoomService>()
|
||||||
private val groupService by inject<GroupService>()
|
private val groupService by inject<GroupService>()
|
||||||
private val syncThread by inject<SyncThread>()
|
private val syncThread by inject<SyncThread>()
|
||||||
|
private val contentUrlResolver by inject<ContentUrlResolver>()
|
||||||
private var isOpen = false
|
private var isOpen = false
|
||||||
|
|
||||||
@MainThread
|
@MainThread
|
||||||
@ -63,6 +65,10 @@ internal class DefaultSession(override val sessionParams: SessionParams) : Sessi
|
|||||||
isOpen = false
|
isOpen = false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun contentUrlResolver(): ContentUrlResolver {
|
||||||
|
return contentUrlResolver
|
||||||
|
}
|
||||||
|
|
||||||
override fun addListener(listener: Session.Listener) {
|
override fun addListener(listener: Session.Listener) {
|
||||||
sessionListeners.addListener(listener)
|
sessionListeners.addListener(listener)
|
||||||
}
|
}
|
||||||
|
@ -3,9 +3,11 @@ package im.vector.matrix.android.internal.session
|
|||||||
import android.content.Context
|
import android.content.Context
|
||||||
import com.zhuinden.monarchy.Monarchy
|
import com.zhuinden.monarchy.Monarchy
|
||||||
import im.vector.matrix.android.api.auth.data.SessionParams
|
import im.vector.matrix.android.api.auth.data.SessionParams
|
||||||
|
import im.vector.matrix.android.api.session.content.ContentUrlResolver
|
||||||
import im.vector.matrix.android.api.session.group.GroupService
|
import im.vector.matrix.android.api.session.group.GroupService
|
||||||
import im.vector.matrix.android.api.session.room.RoomService
|
import im.vector.matrix.android.api.session.room.RoomService
|
||||||
import im.vector.matrix.android.internal.database.LiveEntityObserver
|
import im.vector.matrix.android.internal.database.LiveEntityObserver
|
||||||
|
import im.vector.matrix.android.internal.session.content.DefaultContentUrlResolver
|
||||||
import im.vector.matrix.android.internal.session.group.DefaultGroupService
|
import im.vector.matrix.android.internal.session.group.DefaultGroupService
|
||||||
import im.vector.matrix.android.internal.session.group.GroupSummaryUpdater
|
import im.vector.matrix.android.internal.session.group.GroupSummaryUpdater
|
||||||
import im.vector.matrix.android.internal.session.room.DefaultRoomService
|
import im.vector.matrix.android.internal.session.room.DefaultRoomService
|
||||||
@ -78,6 +80,10 @@ internal class SessionModule(private val sessionParams: SessionParams) {
|
|||||||
SessionListeners()
|
SessionListeners()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
scope(DefaultSession.SCOPE) {
|
||||||
|
DefaultContentUrlResolver(sessionParams.homeServerConnectionConfig) as ContentUrlResolver
|
||||||
|
}
|
||||||
|
|
||||||
scope(DefaultSession.SCOPE) {
|
scope(DefaultSession.SCOPE) {
|
||||||
val roomSummaryUpdater = RoomSummaryUpdater(get(), get(), get(), get(), sessionParams.credentials)
|
val roomSummaryUpdater = RoomSummaryUpdater(get(), get(), get(), get(), sessionParams.credentials)
|
||||||
val groupSummaryUpdater = GroupSummaryUpdater(get())
|
val groupSummaryUpdater = GroupSummaryUpdater(get())
|
||||||
|
@ -0,0 +1,69 @@
|
|||||||
|
/*
|
||||||
|
*
|
||||||
|
* * Copyright 2019 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.matrix.android.internal.session.content
|
||||||
|
|
||||||
|
import im.vector.matrix.android.api.auth.data.HomeServerConnectionConfig
|
||||||
|
import im.vector.matrix.android.api.session.content.ContentUrlResolver
|
||||||
|
|
||||||
|
|
||||||
|
private const val MATRIX_CONTENT_URI_SCHEME = "mxc://"
|
||||||
|
private const val URI_PREFIX_CONTENT_API = "/_matrix/media/v1/"
|
||||||
|
|
||||||
|
internal class DefaultContentUrlResolver(private val homeServerConnectionConfig: HomeServerConnectionConfig) : ContentUrlResolver {
|
||||||
|
|
||||||
|
override fun resolveFullSize(contentUrl: String?): String? {
|
||||||
|
if (contentUrl?.isValidMatrixContentUrl() == true) {
|
||||||
|
val baseUrl = homeServerConnectionConfig.homeServerUri.toString()
|
||||||
|
val prefix = URI_PREFIX_CONTENT_API + "download/"
|
||||||
|
return resolve(baseUrl, contentUrl, prefix)
|
||||||
|
}
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun resolveThumbnail(contentUrl: String?, width: Int, height: Int, method: ContentUrlResolver.ThumbnailMethod): String? {
|
||||||
|
if (contentUrl?.isValidMatrixContentUrl() == true) {
|
||||||
|
val baseUrl = homeServerConnectionConfig.homeServerUri.toString()
|
||||||
|
val prefix = URI_PREFIX_CONTENT_API + "thumbnail/"
|
||||||
|
val params = "?width=$width&height=$height&method=${method.value}"
|
||||||
|
return resolve(baseUrl, contentUrl, prefix, params)
|
||||||
|
}
|
||||||
|
// do not allow non-mxc content URLs
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun resolve(baseUrl: String,
|
||||||
|
contentUrl: String,
|
||||||
|
prefix: String,
|
||||||
|
params: String? = null): String? {
|
||||||
|
|
||||||
|
var serverAndMediaId = contentUrl.removePrefix(MATRIX_CONTENT_URI_SCHEME)
|
||||||
|
val fragmentOffset = serverAndMediaId.indexOf("#")
|
||||||
|
var fragment = ""
|
||||||
|
if (fragmentOffset >= 0) {
|
||||||
|
fragment = serverAndMediaId.substring(fragmentOffset)
|
||||||
|
serverAndMediaId = serverAndMediaId.substring(0, fragmentOffset)
|
||||||
|
}
|
||||||
|
return baseUrl + prefix + serverAndMediaId + (params ?: "") + fragment
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun String.isValidMatrixContentUrl(): Boolean {
|
||||||
|
return startsWith(MATRIX_CONTENT_URI_SCHEME)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user