mirror of
https://github.com/SchildiChat/SchildiChat-android.git
synced 2024-11-25 10:55:55 +03:00
Support open from upload media tab
This commit is contained in:
parent
e38cb7c1a6
commit
195e2703b9
10 changed files with 455 additions and 187 deletions
|
@ -0,0 +1,148 @@
|
||||||
|
/*
|
||||||
|
* 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 im.vector.riotx.features.media
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import android.graphics.drawable.Drawable
|
||||||
|
import android.view.View
|
||||||
|
import android.widget.ImageView
|
||||||
|
import com.bumptech.glide.request.target.CustomViewTarget
|
||||||
|
import com.bumptech.glide.request.transition.Transition
|
||||||
|
import im.vector.matrix.android.api.MatrixCallback
|
||||||
|
import im.vector.matrix.android.api.session.file.FileService
|
||||||
|
import im.vector.riotx.attachmentviewer.AttachmentInfo
|
||||||
|
import im.vector.riotx.attachmentviewer.AttachmentSourceProvider
|
||||||
|
import im.vector.riotx.attachmentviewer.ImageLoaderTarget
|
||||||
|
import im.vector.riotx.attachmentviewer.VideoLoaderTarget
|
||||||
|
import java.io.File
|
||||||
|
|
||||||
|
abstract class BaseAttachmentProvider(val imageContentRenderer: ImageContentRenderer, val fileService: FileService) : AttachmentSourceProvider {
|
||||||
|
|
||||||
|
interface InteractionListener {
|
||||||
|
fun onDismissTapped()
|
||||||
|
fun onShareTapped()
|
||||||
|
fun onPlayPause(play: Boolean)
|
||||||
|
fun videoSeekTo(percent: Int)
|
||||||
|
}
|
||||||
|
|
||||||
|
var interactionListener: InteractionListener? = null
|
||||||
|
|
||||||
|
protected var overlayView: AttachmentOverlayView? = null
|
||||||
|
|
||||||
|
override fun overlayViewAtPosition(context: Context, position: Int): View? {
|
||||||
|
if (position == -1) return null
|
||||||
|
if (overlayView == null) {
|
||||||
|
overlayView = AttachmentOverlayView(context)
|
||||||
|
overlayView?.onBack = {
|
||||||
|
interactionListener?.onDismissTapped()
|
||||||
|
}
|
||||||
|
overlayView?.onShareCallback = {
|
||||||
|
interactionListener?.onShareTapped()
|
||||||
|
}
|
||||||
|
overlayView?.onPlayPause = { play ->
|
||||||
|
interactionListener?.onPlayPause(play)
|
||||||
|
}
|
||||||
|
overlayView?.videoSeekTo = { percent ->
|
||||||
|
interactionListener?.videoSeekTo(percent)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return overlayView
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun loadImage(target: ImageLoaderTarget, info: AttachmentInfo.Image) {
|
||||||
|
(info.data as? ImageContentRenderer.Data)?.let {
|
||||||
|
imageContentRenderer.render(it, target.contextView(), object : CustomViewTarget<ImageView, Drawable>(target.contextView()) {
|
||||||
|
override fun onLoadFailed(errorDrawable: Drawable?) {
|
||||||
|
target.onLoadFailed(info.uid, errorDrawable)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onResourceCleared(placeholder: Drawable?) {
|
||||||
|
target.onResourceCleared(info.uid, placeholder)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onResourceReady(resource: Drawable, transition: Transition<in Drawable>?) {
|
||||||
|
target.onResourceReady(info.uid, resource)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun loadImage(target: ImageLoaderTarget, info: AttachmentInfo.AnimatedImage) {
|
||||||
|
(info.data as? ImageContentRenderer.Data)?.let {
|
||||||
|
imageContentRenderer.render(it, target.contextView(), object : CustomViewTarget<ImageView, Drawable>(target.contextView()) {
|
||||||
|
override fun onLoadFailed(errorDrawable: Drawable?) {
|
||||||
|
target.onLoadFailed(info.uid, errorDrawable)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onResourceCleared(placeholder: Drawable?) {
|
||||||
|
target.onResourceCleared(info.uid, placeholder)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onResourceReady(resource: Drawable, transition: Transition<in Drawable>?) {
|
||||||
|
target.onResourceReady(info.uid, resource)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun loadVideo(target: VideoLoaderTarget, info: AttachmentInfo.Video) {
|
||||||
|
val data = info.data as? VideoContentRenderer.Data ?: return
|
||||||
|
// videoContentRenderer.render(data,
|
||||||
|
// holder.thumbnailImage,
|
||||||
|
// holder.loaderProgressBar,
|
||||||
|
// holder.videoView,
|
||||||
|
// holder.errorTextView)
|
||||||
|
imageContentRenderer.render(data.thumbnailMediaData, target.contextView(), object : CustomViewTarget<ImageView, Drawable>(target.contextView()) {
|
||||||
|
override fun onLoadFailed(errorDrawable: Drawable?) {
|
||||||
|
target.onThumbnailLoadFailed(info.uid, errorDrawable)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onResourceCleared(placeholder: Drawable?) {
|
||||||
|
target.onThumbnailResourceCleared(info.uid, placeholder)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onResourceReady(resource: Drawable, transition: Transition<in Drawable>?) {
|
||||||
|
target.onThumbnailResourceReady(info.uid, resource)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
target.onVideoFileLoading(info.uid)
|
||||||
|
fileService.downloadFile(
|
||||||
|
downloadMode = FileService.DownloadMode.FOR_INTERNAL_USE,
|
||||||
|
id = data.eventId,
|
||||||
|
mimeType = data.mimeType,
|
||||||
|
elementToDecrypt = data.elementToDecrypt,
|
||||||
|
fileName = data.filename,
|
||||||
|
url = data.url,
|
||||||
|
callback = object : MatrixCallback<File> {
|
||||||
|
override fun onSuccess(data: File) {
|
||||||
|
target.onVideoFileReady(info.uid, data)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onFailure(failure: Throwable) {
|
||||||
|
target.onVideoFileLoadFailed(info.uid)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun clear(id: String) {
|
||||||
|
// TODO("Not yet implemented")
|
||||||
|
}
|
||||||
|
|
||||||
|
abstract fun getFileForSharing(position: Int, callback: ((File?) -> Unit))
|
||||||
|
}
|
|
@ -0,0 +1,112 @@
|
||||||
|
/*
|
||||||
|
* 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 im.vector.riotx.features.media
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import android.view.View
|
||||||
|
import androidx.core.view.isVisible
|
||||||
|
import im.vector.matrix.android.api.MatrixCallback
|
||||||
|
import im.vector.matrix.android.api.session.events.model.isVideoMessage
|
||||||
|
import im.vector.matrix.android.api.session.file.FileService
|
||||||
|
import im.vector.matrix.android.api.session.room.Room
|
||||||
|
import im.vector.riotx.attachmentviewer.AttachmentInfo
|
||||||
|
import im.vector.riotx.core.date.VectorDateFormatter
|
||||||
|
import im.vector.riotx.core.extensions.localDateTime
|
||||||
|
import java.io.File
|
||||||
|
|
||||||
|
class DataAttachmentRoomProvider(
|
||||||
|
private val attachments: List<AttachmentData>,
|
||||||
|
private val room: Room?,
|
||||||
|
private val initialIndex: Int,
|
||||||
|
imageContentRenderer: ImageContentRenderer,
|
||||||
|
private val dateFormatter: VectorDateFormatter,
|
||||||
|
fileService: FileService) : BaseAttachmentProvider(imageContentRenderer, fileService) {
|
||||||
|
|
||||||
|
override fun getItemCount(): Int = attachments.size
|
||||||
|
|
||||||
|
override fun getAttachmentInfoAt(position: Int): AttachmentInfo {
|
||||||
|
return attachments[position].let {
|
||||||
|
when (it) {
|
||||||
|
is ImageContentRenderer.Data -> {
|
||||||
|
if (it.mimeType == "image/gif") {
|
||||||
|
AttachmentInfo.AnimatedImage(
|
||||||
|
uid = it.eventId,
|
||||||
|
url = it.url ?: "",
|
||||||
|
data = it
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
AttachmentInfo.Image(
|
||||||
|
uid = it.eventId,
|
||||||
|
url = it.url ?: "",
|
||||||
|
data = it
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
is VideoContentRenderer.Data -> {
|
||||||
|
AttachmentInfo.Video(
|
||||||
|
uid = it.eventId,
|
||||||
|
url = it.url ?: "",
|
||||||
|
data = it,
|
||||||
|
thumbnail = AttachmentInfo.Image(
|
||||||
|
uid = it.eventId,
|
||||||
|
url = it.thumbnailMediaData.url ?: "",
|
||||||
|
data = it.thumbnailMediaData
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
else -> throw IllegalArgumentException()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun overlayViewAtPosition(context: Context, position: Int): View? {
|
||||||
|
super.overlayViewAtPosition(context, position)
|
||||||
|
val item = attachments[position]
|
||||||
|
val timeLineEvent = room?.getTimeLineEvent(item.eventId)
|
||||||
|
if (timeLineEvent != null) {
|
||||||
|
val dateString = timeLineEvent.root.localDateTime().let {
|
||||||
|
"${dateFormatter.formatMessageDay(it)} at ${dateFormatter.formatMessageHour(it)} "
|
||||||
|
}
|
||||||
|
overlayView?.updateWith("${position + 1} of ${attachments.size}", "${timeLineEvent.senderInfo.displayName} $dateString")
|
||||||
|
overlayView?.videoControlsGroup?.isVisible = timeLineEvent.root.isVideoMessage()
|
||||||
|
} else {
|
||||||
|
overlayView?.updateWith("", "")
|
||||||
|
}
|
||||||
|
return overlayView
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getFileForSharing(position: Int, callback: (File?) -> Unit) {
|
||||||
|
val item = attachments[position]
|
||||||
|
fileService.downloadFile(
|
||||||
|
downloadMode = FileService.DownloadMode.FOR_EXTERNAL_SHARE,
|
||||||
|
id = item.eventId,
|
||||||
|
fileName = item.filename,
|
||||||
|
mimeType = item.mimeType,
|
||||||
|
url = item.url ?: "",
|
||||||
|
elementToDecrypt = item.elementToDecrypt,
|
||||||
|
callback = object : MatrixCallback<File> {
|
||||||
|
override fun onSuccess(data: File) {
|
||||||
|
callback(data)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onFailure(failure: Throwable) {
|
||||||
|
callback(null)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
|
@ -17,17 +17,14 @@
|
||||||
package im.vector.riotx.features.media
|
package im.vector.riotx.features.media
|
||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.graphics.drawable.Drawable
|
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.widget.ImageView
|
|
||||||
import androidx.core.view.isVisible
|
import androidx.core.view.isVisible
|
||||||
import com.bumptech.glide.request.target.CustomViewTarget
|
|
||||||
import com.bumptech.glide.request.transition.Transition
|
|
||||||
import im.vector.matrix.android.api.MatrixCallback
|
import im.vector.matrix.android.api.MatrixCallback
|
||||||
import im.vector.matrix.android.api.session.Session
|
import im.vector.matrix.android.api.session.Session
|
||||||
import im.vector.matrix.android.api.session.events.model.isVideoMessage
|
import im.vector.matrix.android.api.session.events.model.isVideoMessage
|
||||||
import im.vector.matrix.android.api.session.events.model.toModel
|
import im.vector.matrix.android.api.session.events.model.toModel
|
||||||
import im.vector.matrix.android.api.session.file.FileService
|
import im.vector.matrix.android.api.session.file.FileService
|
||||||
|
import im.vector.matrix.android.api.session.room.Room
|
||||||
import im.vector.matrix.android.api.session.room.model.message.MessageContent
|
import im.vector.matrix.android.api.session.room.model.message.MessageContent
|
||||||
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.matrix.android.api.session.room.model.message.MessageVideoContent
|
import im.vector.matrix.android.api.session.room.model.message.MessageVideoContent
|
||||||
|
@ -36,33 +33,18 @@ import im.vector.matrix.android.api.session.room.model.message.getFileUrl
|
||||||
import im.vector.matrix.android.api.session.room.timeline.TimelineEvent
|
import im.vector.matrix.android.api.session.room.timeline.TimelineEvent
|
||||||
import im.vector.matrix.android.internal.crypto.attachments.toElementToDecrypt
|
import im.vector.matrix.android.internal.crypto.attachments.toElementToDecrypt
|
||||||
import im.vector.riotx.attachmentviewer.AttachmentInfo
|
import im.vector.riotx.attachmentviewer.AttachmentInfo
|
||||||
import im.vector.riotx.attachmentviewer.AttachmentSourceProvider
|
|
||||||
import im.vector.riotx.attachmentviewer.ImageLoaderTarget
|
|
||||||
import im.vector.riotx.attachmentviewer.VideoLoaderTarget
|
|
||||||
import im.vector.riotx.core.date.VectorDateFormatter
|
import im.vector.riotx.core.date.VectorDateFormatter
|
||||||
import im.vector.riotx.core.extensions.localDateTime
|
import im.vector.riotx.core.extensions.localDateTime
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
class RoomAttachmentProvider(
|
class RoomEventsAttachmentProvider(
|
||||||
private val attachments: List<TimelineEvent>,
|
private val attachments: List<TimelineEvent>,
|
||||||
private val initialIndex: Int,
|
private val initialIndex: Int,
|
||||||
private val imageContentRenderer: ImageContentRenderer,
|
imageContentRenderer: ImageContentRenderer,
|
||||||
private val videoContentRenderer: VideoContentRenderer,
|
|
||||||
private val dateFormatter: VectorDateFormatter,
|
private val dateFormatter: VectorDateFormatter,
|
||||||
private val fileService: FileService
|
fileService: FileService
|
||||||
) : AttachmentSourceProvider {
|
) : BaseAttachmentProvider(imageContentRenderer, fileService) {
|
||||||
|
|
||||||
interface InteractionListener {
|
|
||||||
fun onDismissTapped()
|
|
||||||
fun onShareTapped()
|
|
||||||
fun onPlayPause(play: Boolean)
|
|
||||||
fun videoSeekTo(percent: Int)
|
|
||||||
}
|
|
||||||
|
|
||||||
var interactionListener: InteractionListener? = null
|
|
||||||
|
|
||||||
private var overlayView: AttachmentOverlayView? = null
|
|
||||||
|
|
||||||
override fun getItemCount(): Int {
|
override fun getItemCount(): Int {
|
||||||
return attachments.size
|
return attachments.size
|
||||||
|
@ -139,99 +121,8 @@ class RoomAttachmentProvider(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun loadImage(target: ImageLoaderTarget, info: AttachmentInfo.Image) {
|
|
||||||
(info.data as? ImageContentRenderer.Data)?.let {
|
|
||||||
imageContentRenderer.render(it, target.contextView(), object : CustomViewTarget<ImageView, Drawable>(target.contextView()) {
|
|
||||||
override fun onLoadFailed(errorDrawable: Drawable?) {
|
|
||||||
target.onLoadFailed(info.uid, errorDrawable)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onResourceCleared(placeholder: Drawable?) {
|
|
||||||
target.onResourceCleared(info.uid, placeholder)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onResourceReady(resource: Drawable, transition: Transition<in Drawable>?) {
|
|
||||||
target.onResourceReady(info.uid, resource)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun loadImage(target: ImageLoaderTarget, info: AttachmentInfo.AnimatedImage) {
|
|
||||||
(info.data as? ImageContentRenderer.Data)?.let {
|
|
||||||
imageContentRenderer.render(it, target.contextView(), object : CustomViewTarget<ImageView, Drawable>(target.contextView()) {
|
|
||||||
override fun onLoadFailed(errorDrawable: Drawable?) {
|
|
||||||
target.onLoadFailed(info.uid, errorDrawable)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onResourceCleared(placeholder: Drawable?) {
|
|
||||||
target.onResourceCleared(info.uid, placeholder)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onResourceReady(resource: Drawable, transition: Transition<in Drawable>?) {
|
|
||||||
target.onResourceReady(info.uid, resource)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun loadVideo(target: VideoLoaderTarget, info: AttachmentInfo.Video) {
|
|
||||||
val data = info.data as? VideoContentRenderer.Data ?: return
|
|
||||||
// videoContentRenderer.render(data,
|
|
||||||
// holder.thumbnailImage,
|
|
||||||
// holder.loaderProgressBar,
|
|
||||||
// holder.videoView,
|
|
||||||
// holder.errorTextView)
|
|
||||||
imageContentRenderer.render(data.thumbnailMediaData, target.contextView(), object : CustomViewTarget<ImageView, Drawable>(target.contextView()) {
|
|
||||||
override fun onLoadFailed(errorDrawable: Drawable?) {
|
|
||||||
target.onThumbnailLoadFailed(info.uid, errorDrawable)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onResourceCleared(placeholder: Drawable?) {
|
|
||||||
target.onThumbnailResourceCleared(info.uid, placeholder)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onResourceReady(resource: Drawable, transition: Transition<in Drawable>?) {
|
|
||||||
target.onThumbnailResourceReady(info.uid, resource)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
target.onVideoFileLoading(info.uid)
|
|
||||||
fileService.downloadFile(
|
|
||||||
downloadMode = FileService.DownloadMode.FOR_INTERNAL_USE,
|
|
||||||
id = data.eventId,
|
|
||||||
mimeType = data.mimeType,
|
|
||||||
elementToDecrypt = data.elementToDecrypt,
|
|
||||||
fileName = data.filename,
|
|
||||||
url = data.url,
|
|
||||||
callback = object : MatrixCallback<File> {
|
|
||||||
override fun onSuccess(data: File) {
|
|
||||||
target.onVideoFileReady(info.uid, data)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onFailure(failure: Throwable) {
|
|
||||||
target.onVideoFileLoadFailed(info.uid)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun overlayViewAtPosition(context: Context, position: Int): View? {
|
override fun overlayViewAtPosition(context: Context, position: Int): View? {
|
||||||
if (overlayView == null) {
|
super.overlayViewAtPosition(context, position)
|
||||||
overlayView = AttachmentOverlayView(context)
|
|
||||||
overlayView?.onBack = {
|
|
||||||
interactionListener?.onDismissTapped()
|
|
||||||
}
|
|
||||||
overlayView?.onShareCallback = {
|
|
||||||
interactionListener?.onShareTapped()
|
|
||||||
}
|
|
||||||
overlayView?.onPlayPause = { play ->
|
|
||||||
interactionListener?.onPlayPause(play)
|
|
||||||
}
|
|
||||||
overlayView?.videoSeekTo = { percent ->
|
|
||||||
interactionListener?.videoSeekTo(percent)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
val item = attachments[position]
|
val item = attachments[position]
|
||||||
val dateString = item.root.localDateTime().let {
|
val dateString = item.root.localDateTime().let {
|
||||||
"${dateFormatter.formatMessageDay(it)} at ${dateFormatter.formatMessageHour(it)} "
|
"${dateFormatter.formatMessageDay(it)} at ${dateFormatter.formatMessageHour(it)} "
|
||||||
|
@ -241,19 +132,44 @@ class RoomAttachmentProvider(
|
||||||
return overlayView
|
return overlayView
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun clear(id: String) {
|
override fun getFileForSharing(position: Int, callback: (File?) -> Unit) {
|
||||||
// TODO("Not yet implemented")
|
attachments[position].let { timelineEvent ->
|
||||||
|
|
||||||
|
val messageContent = timelineEvent.root.getClearContent().toModel<MessageContent>()
|
||||||
|
as? MessageWithAttachmentContent
|
||||||
|
?: return@let
|
||||||
|
fileService.downloadFile(
|
||||||
|
downloadMode = FileService.DownloadMode.FOR_EXTERNAL_SHARE,
|
||||||
|
id = timelineEvent.eventId,
|
||||||
|
fileName = messageContent.body,
|
||||||
|
mimeType = messageContent.mimeType,
|
||||||
|
url = messageContent.getFileUrl(),
|
||||||
|
elementToDecrypt = messageContent.encryptedFileInfo?.toElementToDecrypt(),
|
||||||
|
callback = object : MatrixCallback<File> {
|
||||||
|
override fun onSuccess(data: File) {
|
||||||
|
callback(data)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onFailure(failure: Throwable) {
|
||||||
|
callback(null)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class RoomAttachmentProviderFactory @Inject constructor(
|
class AttachmentProviderFactory @Inject constructor(
|
||||||
private val imageContentRenderer: ImageContentRenderer,
|
private val imageContentRenderer: ImageContentRenderer,
|
||||||
private val vectorDateFormatter: VectorDateFormatter,
|
private val vectorDateFormatter: VectorDateFormatter,
|
||||||
private val videoContentRenderer: VideoContentRenderer,
|
|
||||||
private val session: Session
|
private val session: Session
|
||||||
) {
|
) {
|
||||||
|
|
||||||
fun createProvider(attachments: List<TimelineEvent>, initialIndex: Int): RoomAttachmentProvider {
|
fun createProvider(attachments: List<TimelineEvent>, initialIndex: Int): RoomEventsAttachmentProvider {
|
||||||
return RoomAttachmentProvider(attachments, initialIndex, imageContentRenderer, videoContentRenderer, vectorDateFormatter, session.fileService())
|
return RoomEventsAttachmentProvider(attachments, initialIndex, imageContentRenderer, vectorDateFormatter, session.fileService())
|
||||||
|
}
|
||||||
|
|
||||||
|
fun createProvider(attachments: List<AttachmentData>, room: Room?, initialIndex: Int): DataAttachmentRoomProvider {
|
||||||
|
return DataAttachmentRoomProvider(attachments, room, initialIndex, imageContentRenderer, vectorDateFormatter, session.fileService())
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -30,14 +30,6 @@ import androidx.core.view.isInvisible
|
||||||
import androidx.core.view.isVisible
|
import androidx.core.view.isVisible
|
||||||
import androidx.lifecycle.Lifecycle
|
import androidx.lifecycle.Lifecycle
|
||||||
import androidx.transition.Transition
|
import androidx.transition.Transition
|
||||||
import im.vector.matrix.android.api.MatrixCallback
|
|
||||||
import im.vector.matrix.android.api.session.events.model.toModel
|
|
||||||
import im.vector.matrix.android.api.session.file.FileService
|
|
||||||
import im.vector.matrix.android.api.session.room.model.message.MessageContent
|
|
||||||
import im.vector.matrix.android.api.session.room.model.message.MessageWithAttachmentContent
|
|
||||||
import im.vector.matrix.android.api.session.room.model.message.getFileUrl
|
|
||||||
import im.vector.matrix.android.api.session.room.timeline.TimelineEvent
|
|
||||||
import im.vector.matrix.android.internal.crypto.attachments.toElementToDecrypt
|
|
||||||
import im.vector.riotx.R
|
import im.vector.riotx.R
|
||||||
import im.vector.riotx.attachmentviewer.AttachmentCommands
|
import im.vector.riotx.attachmentviewer.AttachmentCommands
|
||||||
import im.vector.riotx.attachmentviewer.AttachmentViewerActivity
|
import im.vector.riotx.attachmentviewer.AttachmentViewerActivity
|
||||||
|
@ -52,11 +44,10 @@ import im.vector.riotx.features.themes.ActivityOtherThemes
|
||||||
import im.vector.riotx.features.themes.ThemeUtils
|
import im.vector.riotx.features.themes.ThemeUtils
|
||||||
import kotlinx.android.parcel.Parcelize
|
import kotlinx.android.parcel.Parcelize
|
||||||
import timber.log.Timber
|
import timber.log.Timber
|
||||||
import java.io.File
|
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
import kotlin.system.measureTimeMillis
|
import kotlin.system.measureTimeMillis
|
||||||
|
|
||||||
class VectorAttachmentViewerActivity : AttachmentViewerActivity(), RoomAttachmentProvider.InteractionListener {
|
class VectorAttachmentViewerActivity : AttachmentViewerActivity(), BaseAttachmentProvider.InteractionListener {
|
||||||
|
|
||||||
@Parcelize
|
@Parcelize
|
||||||
data class Args(
|
data class Args(
|
||||||
|
@ -69,7 +60,7 @@ class VectorAttachmentViewerActivity : AttachmentViewerActivity(), RoomAttachmen
|
||||||
lateinit var sessionHolder: ActiveSessionHolder
|
lateinit var sessionHolder: ActiveSessionHolder
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
lateinit var dataSourceFactory: RoomAttachmentProviderFactory
|
lateinit var dataSourceFactory: AttachmentProviderFactory
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
lateinit var imageContentRenderer: ImageContentRenderer
|
lateinit var imageContentRenderer: ImageContentRenderer
|
||||||
|
@ -78,7 +69,8 @@ class VectorAttachmentViewerActivity : AttachmentViewerActivity(), RoomAttachmen
|
||||||
|
|
||||||
private var initialIndex = 0
|
private var initialIndex = 0
|
||||||
private var isAnimatingOut = false
|
private var isAnimatingOut = false
|
||||||
private var eventList: List<TimelineEvent>? = null
|
|
||||||
|
var currentSourceProvider: BaseAttachmentProvider? = null
|
||||||
|
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
super.onCreate(savedInstanceState)
|
super.onCreate(savedInstanceState)
|
||||||
|
@ -92,13 +84,6 @@ class VectorAttachmentViewerActivity : AttachmentViewerActivity(), RoomAttachmen
|
||||||
ThemeUtils.setActivityTheme(this, getOtherThemes())
|
ThemeUtils.setActivityTheme(this, getOtherThemes())
|
||||||
|
|
||||||
val args = args() ?: throw IllegalArgumentException("Missing arguments")
|
val args = args() ?: throw IllegalArgumentException("Missing arguments")
|
||||||
val session = sessionHolder.getSafeActiveSession() ?: return Unit.also { finish() }
|
|
||||||
|
|
||||||
val room = args.roomId?.let { session.getRoom(it) }
|
|
||||||
val events = room?.getAttachmentMessages() ?: emptyList()
|
|
||||||
eventList = events
|
|
||||||
val index = events.indexOfFirst { it.eventId == args.eventId }
|
|
||||||
initialIndex = index
|
|
||||||
|
|
||||||
if (savedInstanceState == null && addTransitionListener()) {
|
if (savedInstanceState == null && addTransitionListener()) {
|
||||||
args.sharedTransitionName?.let {
|
args.sharedTransitionName?.let {
|
||||||
|
@ -127,14 +112,41 @@ class VectorAttachmentViewerActivity : AttachmentViewerActivity(), RoomAttachmen
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
val sourceProvider = dataSourceFactory.createProvider(events, index)
|
val session = sessionHolder.getSafeActiveSession() ?: return Unit.also { finish() }
|
||||||
sourceProvider.interactionListener = this
|
|
||||||
setSourceProvider(sourceProvider)
|
val room = args.roomId?.let { session.getRoom(it) }
|
||||||
if (savedInstanceState == null) {
|
|
||||||
pager2.setCurrentItem(index, false)
|
val inMemoryData = intent.getParcelableArrayListExtra<AttachmentData>(EXTRA_IN_MEMORY_DATA)
|
||||||
// The page change listener is not notified of the change...
|
if (inMemoryData != null) {
|
||||||
pager2.post {
|
val sourceProvider = dataSourceFactory.createProvider(inMemoryData, room, initialIndex)
|
||||||
onSelectedPositionChanged(index)
|
val index = inMemoryData.indexOfFirst { it.eventId == args.eventId }
|
||||||
|
initialIndex = index
|
||||||
|
sourceProvider.interactionListener = this
|
||||||
|
setSourceProvider(sourceProvider)
|
||||||
|
this.currentSourceProvider = sourceProvider
|
||||||
|
if (savedInstanceState == null) {
|
||||||
|
pager2.setCurrentItem(index, false)
|
||||||
|
// The page change listener is not notified of the change...
|
||||||
|
pager2.post {
|
||||||
|
onSelectedPositionChanged(index)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
val events = room?.getAttachmentMessages()
|
||||||
|
?: emptyList()
|
||||||
|
val index = events.indexOfFirst { it.eventId == args.eventId }
|
||||||
|
initialIndex = index
|
||||||
|
|
||||||
|
val sourceProvider = dataSourceFactory.createProvider(events, index)
|
||||||
|
sourceProvider.interactionListener = this
|
||||||
|
setSourceProvider(sourceProvider)
|
||||||
|
this.currentSourceProvider = sourceProvider
|
||||||
|
if (savedInstanceState == null) {
|
||||||
|
pager2.setCurrentItem(index, false)
|
||||||
|
// The page change listener is not notified of the change...
|
||||||
|
pager2.post {
|
||||||
|
onSelectedPositionChanged(index)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -228,14 +240,19 @@ class VectorAttachmentViewerActivity : AttachmentViewerActivity(), RoomAttachmen
|
||||||
|
|
||||||
const val EXTRA_ARGS = "EXTRA_ARGS"
|
const val EXTRA_ARGS = "EXTRA_ARGS"
|
||||||
const val EXTRA_IMAGE_DATA = "EXTRA_IMAGE_DATA"
|
const val EXTRA_IMAGE_DATA = "EXTRA_IMAGE_DATA"
|
||||||
|
const val EXTRA_IN_MEMORY_DATA = "EXTRA_IN_MEMORY_DATA"
|
||||||
|
|
||||||
fun newIntent(context: Context,
|
fun newIntent(context: Context,
|
||||||
mediaData: AttachmentData,
|
mediaData: AttachmentData,
|
||||||
roomId: String?,
|
roomId: String?,
|
||||||
eventId: String,
|
eventId: String,
|
||||||
|
inMemoryData: List<AttachmentData>?,
|
||||||
sharedTransitionName: String?) = Intent(context, VectorAttachmentViewerActivity::class.java).also {
|
sharedTransitionName: String?) = Intent(context, VectorAttachmentViewerActivity::class.java).also {
|
||||||
it.putExtra(EXTRA_ARGS, Args(roomId, eventId, sharedTransitionName))
|
it.putExtra(EXTRA_ARGS, Args(roomId, eventId, sharedTransitionName))
|
||||||
it.putExtra(EXTRA_IMAGE_DATA, mediaData)
|
it.putExtra(EXTRA_IMAGE_DATA, mediaData)
|
||||||
|
if (inMemoryData != null) {
|
||||||
|
it.putParcelableArrayListExtra(EXTRA_IN_MEMORY_DATA, ArrayList(inMemoryData))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -252,27 +269,10 @@ class VectorAttachmentViewerActivity : AttachmentViewerActivity(), RoomAttachmen
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onShareTapped() {
|
override fun onShareTapped() {
|
||||||
// Share
|
this.currentSourceProvider?.getFileForSharing(currentPosition) { data ->
|
||||||
eventList?.get(currentPosition)?.let { timelineEvent ->
|
if (data != null && lifecycle.currentState.isAtLeast(Lifecycle.State.RESUMED)) {
|
||||||
|
shareMedia(this@VectorAttachmentViewerActivity, data, getMimeTypeFromUri(this@VectorAttachmentViewerActivity, data.toUri()))
|
||||||
val messageContent = timelineEvent.root.getClearContent().toModel<MessageContent>()
|
}
|
||||||
as? MessageWithAttachmentContent
|
|
||||||
?: return@let
|
|
||||||
sessionHolder.getSafeActiveSession()?.fileService()?.downloadFile(
|
|
||||||
downloadMode = FileService.DownloadMode.FOR_EXTERNAL_SHARE,
|
|
||||||
id = timelineEvent.eventId,
|
|
||||||
fileName = messageContent.body,
|
|
||||||
mimeType = messageContent.mimeType,
|
|
||||||
url = messageContent.getFileUrl(),
|
|
||||||
elementToDecrypt = messageContent.encryptedFileInfo?.toElementToDecrypt(),
|
|
||||||
callback = object : MatrixCallback<File> {
|
|
||||||
override fun onSuccess(data: File) {
|
|
||||||
if (lifecycle.currentState.isAtLeast(Lifecycle.State.RESUMED)) {
|
|
||||||
shareMedia(this@VectorAttachmentViewerActivity, data, getMimeTypeFromUri(this@VectorAttachmentViewerActivity, data.toUri()))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -246,20 +246,25 @@ class DefaultNavigator @Inject constructor(
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun openImageViewer(activity: Activity,
|
override fun openImageViewer(activity: Activity,
|
||||||
roomId: String?,
|
roomId: String,
|
||||||
mediaData: AttachmentData,
|
mediaData: AttachmentData,
|
||||||
view: View,
|
view: View,
|
||||||
|
inMemory: List<AttachmentData>?,
|
||||||
options: ((MutableList<Pair<View, String>>) -> Unit)?) {
|
options: ((MutableList<Pair<View, String>>) -> Unit)?) {
|
||||||
VectorAttachmentViewerActivity.newIntent(activity, mediaData, roomId, mediaData.eventId, ViewCompat.getTransitionName(view)).let { intent ->
|
VectorAttachmentViewerActivity.newIntent(activity,
|
||||||
|
mediaData,
|
||||||
|
roomId,
|
||||||
|
mediaData.eventId,
|
||||||
|
inMemory,
|
||||||
|
ViewCompat.getTransitionName(view)).let { intent ->
|
||||||
val pairs = ArrayList<Pair<View, String>>()
|
val pairs = ArrayList<Pair<View, String>>()
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
|
activity.window.decorView.findViewById<View>(android.R.id.statusBarBackground)?.let {
|
||||||
activity.window.decorView.findViewById<View>(android.R.id.statusBarBackground)?.let {
|
pairs.add(Pair(it, Window.STATUS_BAR_BACKGROUND_TRANSITION_NAME))
|
||||||
pairs.add(Pair(it, Window.STATUS_BAR_BACKGROUND_TRANSITION_NAME))
|
|
||||||
}
|
|
||||||
activity.window.decorView.findViewById<View>(android.R.id.navigationBarBackground)?.let {
|
|
||||||
pairs.add(Pair(it, Window.NAVIGATION_BAR_BACKGROUND_TRANSITION_NAME))
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
activity.window.decorView.findViewById<View>(android.R.id.navigationBarBackground)?.let {
|
||||||
|
pairs.add(Pair(it, Window.NAVIGATION_BAR_BACKGROUND_TRANSITION_NAME))
|
||||||
|
}
|
||||||
|
|
||||||
pairs.add(Pair(view, ViewCompat.getTransitionName(view) ?: ""))
|
pairs.add(Pair(view, ViewCompat.getTransitionName(view) ?: ""))
|
||||||
options?.invoke(pairs)
|
options?.invoke(pairs)
|
||||||
|
|
||||||
|
@ -284,12 +289,18 @@ class DefaultNavigator @Inject constructor(
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun openVideoViewer(activity: Activity,
|
override fun openVideoViewer(activity: Activity,
|
||||||
roomId: String?, mediaData: VideoContentRenderer.Data,
|
roomId: String, mediaData: VideoContentRenderer.Data,
|
||||||
view: View,
|
view: View,
|
||||||
|
inMemory: List<AttachmentData>?,
|
||||||
options: ((MutableList<Pair<View, String>>) -> Unit)?) {
|
options: ((MutableList<Pair<View, String>>) -> Unit)?) {
|
||||||
// val intent = VideoMediaViewerActivity.newIntent(activity, mediaData)
|
// val intent = VideoMediaViewerActivity.newIntent(activity, mediaData)
|
||||||
// activity.startActivity(intent)
|
// activity.startActivity(intent)
|
||||||
VectorAttachmentViewerActivity.newIntent(activity, mediaData, roomId, mediaData.eventId, ViewCompat.getTransitionName(view)).let { intent ->
|
VectorAttachmentViewerActivity.newIntent(activity,
|
||||||
|
mediaData,
|
||||||
|
roomId,
|
||||||
|
mediaData.eventId,
|
||||||
|
inMemory,
|
||||||
|
ViewCompat.getTransitionName(view)).let { intent ->
|
||||||
val pairs = ArrayList<Pair<View, String>>()
|
val pairs = ArrayList<Pair<View, String>>()
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
|
||||||
activity.window.decorView.findViewById<View>(android.R.id.statusBarBackground)?.let {
|
activity.window.decorView.findViewById<View>(android.R.id.statusBarBackground)?.let {
|
||||||
|
|
|
@ -92,13 +92,15 @@ interface Navigator {
|
||||||
fun openRoomWidget(context: Context, roomId: String, widget: Widget)
|
fun openRoomWidget(context: Context, roomId: String, widget: Widget)
|
||||||
|
|
||||||
fun openImageViewer(activity: Activity,
|
fun openImageViewer(activity: Activity,
|
||||||
roomId: String?,
|
roomId: String,
|
||||||
mediaData: AttachmentData,
|
mediaData: AttachmentData,
|
||||||
view: View,
|
view: View,
|
||||||
|
inMemory: List<AttachmentData>? = null,
|
||||||
options: ((MutableList<Pair<View, String>>) -> Unit)?)
|
options: ((MutableList<Pair<View, String>>) -> Unit)?)
|
||||||
|
|
||||||
fun openVideoViewer(activity: Activity,
|
fun openVideoViewer(activity: Activity,
|
||||||
roomId: String?, mediaData: VideoContentRenderer.Data,
|
roomId: String, mediaData: VideoContentRenderer.Data,
|
||||||
view: View,
|
view: View,
|
||||||
|
inMemory: List<AttachmentData>? = null,
|
||||||
options: ((MutableList<Pair<View, String>>) -> Unit)?)
|
options: ((MutableList<Pair<View, String>>) -> Unit)?)
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,23 +20,34 @@ import android.os.Bundle
|
||||||
import android.util.DisplayMetrics
|
import android.util.DisplayMetrics
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import androidx.core.content.ContextCompat
|
import androidx.core.content.ContextCompat
|
||||||
|
import androidx.core.util.Pair
|
||||||
|
import androidx.core.view.ViewCompat
|
||||||
import androidx.recyclerview.widget.GridLayoutManager
|
import androidx.recyclerview.widget.GridLayoutManager
|
||||||
import com.airbnb.mvrx.Fail
|
import com.airbnb.mvrx.Fail
|
||||||
import com.airbnb.mvrx.Loading
|
import com.airbnb.mvrx.Loading
|
||||||
import com.airbnb.mvrx.Success
|
import com.airbnb.mvrx.Success
|
||||||
import com.airbnb.mvrx.parentFragmentViewModel
|
import com.airbnb.mvrx.parentFragmentViewModel
|
||||||
import com.airbnb.mvrx.withState
|
import com.airbnb.mvrx.withState
|
||||||
|
import com.google.android.material.appbar.AppBarLayout
|
||||||
|
import im.vector.matrix.android.api.session.room.model.message.MessageImageContent
|
||||||
|
import im.vector.matrix.android.api.session.room.model.message.MessageVideoContent
|
||||||
|
import im.vector.matrix.android.api.session.room.model.message.getFileUrl
|
||||||
|
import im.vector.matrix.android.internal.crypto.attachments.toElementToDecrypt
|
||||||
import im.vector.riotx.R
|
import im.vector.riotx.R
|
||||||
import im.vector.riotx.core.extensions.cleanup
|
import im.vector.riotx.core.extensions.cleanup
|
||||||
import im.vector.riotx.core.extensions.trackItemsVisibilityChange
|
import im.vector.riotx.core.extensions.trackItemsVisibilityChange
|
||||||
import im.vector.riotx.core.platform.StateView
|
import im.vector.riotx.core.platform.StateView
|
||||||
import im.vector.riotx.core.platform.VectorBaseFragment
|
import im.vector.riotx.core.platform.VectorBaseFragment
|
||||||
import im.vector.riotx.core.utils.DimensionConverter
|
import im.vector.riotx.core.utils.DimensionConverter
|
||||||
|
import im.vector.riotx.features.media.AttachmentData
|
||||||
import im.vector.riotx.features.media.ImageContentRenderer
|
import im.vector.riotx.features.media.ImageContentRenderer
|
||||||
import im.vector.riotx.features.media.VideoContentRenderer
|
import im.vector.riotx.features.media.VideoContentRenderer
|
||||||
import im.vector.riotx.features.roomprofile.uploads.RoomUploadsAction
|
import im.vector.riotx.features.roomprofile.uploads.RoomUploadsAction
|
||||||
|
import im.vector.riotx.features.roomprofile.uploads.RoomUploadsFragment
|
||||||
import im.vector.riotx.features.roomprofile.uploads.RoomUploadsViewModel
|
import im.vector.riotx.features.roomprofile.uploads.RoomUploadsViewModel
|
||||||
|
import im.vector.riotx.features.roomprofile.uploads.RoomUploadsViewState
|
||||||
import kotlinx.android.synthetic.main.fragment_generic_state_view_recycler.*
|
import kotlinx.android.synthetic.main.fragment_generic_state_view_recycler.*
|
||||||
|
import kotlinx.android.synthetic.main.fragment_room_uploads.*
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
class RoomUploadsMediaFragment @Inject constructor(
|
class RoomUploadsMediaFragment @Inject constructor(
|
||||||
|
@ -76,13 +87,75 @@ class RoomUploadsMediaFragment @Inject constructor(
|
||||||
controller.listener = null
|
controller.listener = null
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onOpenImageClicked(view: View, mediaData: ImageContentRenderer.Data) {
|
// It's very strange i can't just access
|
||||||
navigator.openImageViewer(requireActivity(), null, mediaData, view, null)
|
// the app bar using find by id...
|
||||||
|
private fun trickFindAppBar() : AppBarLayout? {
|
||||||
|
return activity?.supportFragmentManager?.fragments
|
||||||
|
?.filterIsInstance<RoomUploadsFragment>()
|
||||||
|
?.firstOrNull()
|
||||||
|
?.roomUploadsAppBar
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onOpenVideoClicked(view: View, mediaData: VideoContentRenderer.Data) {
|
override fun onOpenImageClicked(view: View, mediaData: ImageContentRenderer.Data) = withState(uploadsViewModel) { state ->
|
||||||
// TODO
|
|
||||||
// navigator.openVideoViewer(requireActivity(), mediaData, null, )
|
val inMemory = getItemsArgs(state)
|
||||||
|
navigator.openImageViewer(requireActivity(), state.roomId, mediaData, view, inMemory) { pairs ->
|
||||||
|
trickFindAppBar()?.let {
|
||||||
|
pairs.add(Pair(it, ViewCompat.getTransitionName(it) ?: ""))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun getItemsArgs(state: RoomUploadsViewState): List<AttachmentData> {
|
||||||
|
return state.mediaEvents.mapNotNull {
|
||||||
|
when (val content = it.contentWithAttachmentContent) {
|
||||||
|
is MessageImageContent -> {
|
||||||
|
ImageContentRenderer.Data(
|
||||||
|
eventId = it.eventId,
|
||||||
|
filename = content.body,
|
||||||
|
mimeType = content.mimeType,
|
||||||
|
url = content.getFileUrl(),
|
||||||
|
elementToDecrypt = content.encryptedFileInfo?.toElementToDecrypt(),
|
||||||
|
maxHeight = -1,
|
||||||
|
maxWidth = -1,
|
||||||
|
width = null,
|
||||||
|
height = null
|
||||||
|
)
|
||||||
|
}
|
||||||
|
is MessageVideoContent -> {
|
||||||
|
val thumbnailData = ImageContentRenderer.Data(
|
||||||
|
eventId = it.eventId,
|
||||||
|
filename = content.body,
|
||||||
|
mimeType = content.mimeType,
|
||||||
|
url = content.videoInfo?.thumbnailFile?.url
|
||||||
|
?: content.videoInfo?.thumbnailUrl,
|
||||||
|
elementToDecrypt = content.videoInfo?.thumbnailFile?.toElementToDecrypt(),
|
||||||
|
height = content.videoInfo?.height,
|
||||||
|
maxHeight = -1,
|
||||||
|
width = content.videoInfo?.width,
|
||||||
|
maxWidth = -1
|
||||||
|
)
|
||||||
|
VideoContentRenderer.Data(
|
||||||
|
eventId = it.eventId,
|
||||||
|
filename = content.body,
|
||||||
|
mimeType = content.mimeType,
|
||||||
|
url = content.getFileUrl(),
|
||||||
|
elementToDecrypt = content.encryptedFileInfo?.toElementToDecrypt(),
|
||||||
|
thumbnailMediaData = thumbnailData
|
||||||
|
)
|
||||||
|
}
|
||||||
|
else -> null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onOpenVideoClicked(view: View, mediaData: VideoContentRenderer.Data) = withState(uploadsViewModel) { state ->
|
||||||
|
val inMemory = getItemsArgs(state)
|
||||||
|
navigator.openVideoViewer(requireActivity(), state.roomId, mediaData, view, inMemory) { pairs ->
|
||||||
|
trickFindAppBar()?.let {
|
||||||
|
pairs.add(Pair(it, ViewCompat.getTransitionName(it) ?: ""))
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun loadMore() {
|
override fun loadMore() {
|
||||||
|
|
|
@ -18,6 +18,7 @@ package im.vector.riotx.features.roomprofile.uploads.media
|
||||||
|
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.widget.ImageView
|
import android.widget.ImageView
|
||||||
|
import androidx.core.view.ViewCompat
|
||||||
import com.airbnb.epoxy.EpoxyAttribute
|
import com.airbnb.epoxy.EpoxyAttribute
|
||||||
import com.airbnb.epoxy.EpoxyModelClass
|
import com.airbnb.epoxy.EpoxyModelClass
|
||||||
import im.vector.riotx.R
|
import im.vector.riotx.R
|
||||||
|
@ -37,6 +38,7 @@ abstract class UploadsImageItem : VectorEpoxyModel<UploadsImageItem.Holder>() {
|
||||||
super.bind(holder)
|
super.bind(holder)
|
||||||
holder.view.setOnClickListener { listener?.onItemClicked(holder.imageView, data) }
|
holder.view.setOnClickListener { listener?.onItemClicked(holder.imageView, data) }
|
||||||
imageContentRenderer.render(data, holder.imageView, IMAGE_SIZE_DP)
|
imageContentRenderer.render(data, holder.imageView, IMAGE_SIZE_DP)
|
||||||
|
ViewCompat.setTransitionName(holder.imageView, "imagePreview_${id()}")
|
||||||
}
|
}
|
||||||
|
|
||||||
class Holder : VectorEpoxyHolder() {
|
class Holder : VectorEpoxyHolder() {
|
||||||
|
|
|
@ -18,6 +18,7 @@ package im.vector.riotx.features.roomprofile.uploads.media
|
||||||
|
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.widget.ImageView
|
import android.widget.ImageView
|
||||||
|
import androidx.core.view.ViewCompat
|
||||||
import com.airbnb.epoxy.EpoxyAttribute
|
import com.airbnb.epoxy.EpoxyAttribute
|
||||||
import com.airbnb.epoxy.EpoxyModelClass
|
import com.airbnb.epoxy.EpoxyModelClass
|
||||||
import im.vector.riotx.R
|
import im.vector.riotx.R
|
||||||
|
@ -38,6 +39,7 @@ abstract class UploadsVideoItem : VectorEpoxyModel<UploadsVideoItem.Holder>() {
|
||||||
super.bind(holder)
|
super.bind(holder)
|
||||||
holder.view.setOnClickListener { listener?.onItemClicked(holder.imageView, data) }
|
holder.view.setOnClickListener { listener?.onItemClicked(holder.imageView, data) }
|
||||||
imageContentRenderer.render(data.thumbnailMediaData, holder.imageView, IMAGE_SIZE_DP)
|
imageContentRenderer.render(data.thumbnailMediaData, holder.imageView, IMAGE_SIZE_DP)
|
||||||
|
ViewCompat.setTransitionName(holder.imageView, "videoPreview_${id()}")
|
||||||
}
|
}
|
||||||
|
|
||||||
class Holder : VectorEpoxyHolder() {
|
class Holder : VectorEpoxyHolder() {
|
||||||
|
|
|
@ -8,6 +8,8 @@
|
||||||
|
|
||||||
<com.google.android.material.appbar.AppBarLayout
|
<com.google.android.material.appbar.AppBarLayout
|
||||||
style="@style/VectorAppBarLayoutStyle"
|
style="@style/VectorAppBarLayoutStyle"
|
||||||
|
android:id="@+id/roomUploadsAppBar"
|
||||||
|
android:transitionName="toolbar"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:elevation="4dp">
|
android:elevation="4dp">
|
||||||
|
|
Loading…
Reference in a new issue