Timeline : start to handle video media. Probably to amend

This commit is contained in:
ganfra 2019-04-12 13:46:59 +02:00
parent 657f4d3e9c
commit 2c83ba0824
11 changed files with 202 additions and 19 deletions

View File

@ -24,8 +24,11 @@ import im.vector.matrix.android.api.session.content.ContentAttachmentData
import im.vector.matrix.android.api.session.events.model.Event
import im.vector.matrix.android.api.session.events.model.toContent
import im.vector.matrix.android.api.session.events.model.toModel
import im.vector.matrix.android.api.session.room.model.message.MessageAudioContent
import im.vector.matrix.android.api.session.room.model.message.MessageContent
import im.vector.matrix.android.api.session.room.model.message.MessageFileContent
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.internal.di.MatrixKoinComponent
import im.vector.matrix.android.internal.session.room.send.SendEventWorker
import im.vector.matrix.android.internal.util.WorkerParamsFactory
@ -69,6 +72,9 @@ internal class UploadContentWorker(context: Context, params: WorkerParameters)
val messageContent: MessageContent = event.content.toModel() ?: return event
val updatedContent = when (messageContent) {
is MessageImageContent -> messageContent.update(url)
is MessageVideoContent -> messageContent.update(url)
is MessageFileContent -> messageContent.update(url)
is MessageAudioContent -> messageContent.update(url)
else -> messageContent
}
return event.copy(content = updatedContent.toContent())
@ -78,6 +84,18 @@ internal class UploadContentWorker(context: Context, params: WorkerParameters)
return copy(url = url)
}

private fun MessageVideoContent.update(url: String): MessageVideoContent {
return copy(url = url)
}

private fun MessageFileContent.update(url: String): MessageFileContent {
return copy(url = url)
}

private fun MessageAudioContent.update(url: String): MessageAudioContent {
return copy(url = url)
}


}


View File

@ -187,6 +187,7 @@ dependencies {
implementation "com.github.piasy:GlideImageViewFactory:$big_image_viewer_version"
implementation "com.github.bumptech.glide:glide:$glide_version"
kapt "com.github.bumptech.glide:compiler:$glide_version"
implementation 'com.danikula:videocache:2.7.1'

// Badge for compatibility
implementation 'me.leolin:ShortcutBadger:1.1.2@aar'

View File

@ -29,7 +29,7 @@

<activity android:name=".features.home.HomeActivity" />
<activity android:name=".features.login.LoginActivity" />
<activity android:name=".features.media.MediaViewerActivity" />
<activity android:name=".features.media.ImageMediaViewerActivity" />
<activity
android:name=".features.rageshake.BugReportActivity"
android:label="@string/title_activity_bug_report" />
@ -37,6 +37,7 @@
android:name=".features.settings.VectorSettingsActivity"
android:label="@string/title_activity_settings"
android:windowSoftInputMode="adjustResize" />
<activity android:name=".features.media.VideoMediaViewerActivity" />

<service
android:name=".core.services.CallService"

View File

@ -70,7 +70,9 @@ import im.vector.riotredesign.features.home.room.detail.timeline.TimelineEventCo
import im.vector.riotredesign.features.home.room.detail.timeline.helper.EndlessRecyclerViewScrollListener
import im.vector.riotredesign.features.html.PillImageSpan
import im.vector.riotredesign.features.media.ImageContentRenderer
import im.vector.riotredesign.features.media.MediaViewerActivity
import im.vector.riotredesign.features.media.ImageMediaViewerActivity
import im.vector.riotredesign.features.media.VideoContentRenderer
import im.vector.riotredesign.features.media.VideoMediaViewerActivity
import kotlinx.android.parcel.Parcelize
import kotlinx.android.synthetic.main.fragment_room_detail.*
import org.koin.android.ext.android.inject
@ -384,12 +386,13 @@ class RoomDetailFragment : VectorBaseFragment(), TimelineEventController.Callbac
}

override fun onImageMessageClicked(messageImageContent: MessageImageContent, mediaData: ImageContentRenderer.Data, view: View) {
val intent = MediaViewerActivity.newIntent(vectorBaseActivity, mediaData)
val intent = ImageMediaViewerActivity.newIntent(vectorBaseActivity, mediaData)
startActivity(intent)
}

override fun onVideoMessageClicked(messageVideoContent: MessageVideoContent, mediaData: ImageContentRenderer.Data, view: View) {
vectorBaseActivity.notImplemented()
override fun onVideoMessageClicked(messageVideoContent: MessageVideoContent, mediaData: VideoContentRenderer.Data, view: View) {
val intent = VideoMediaViewerActivity.newIntent(vectorBaseActivity, mediaData)
startActivity(intent)
}

override fun onFileMessageClicked(messageFileContent: MessageFileContent) {

View File

@ -42,6 +42,7 @@ import im.vector.riotredesign.features.home.room.detail.timeline.helper.Timeline
import im.vector.riotredesign.features.home.room.detail.timeline.helper.nextDisplayableEvent
import im.vector.riotredesign.features.home.room.detail.timeline.item.DaySeparatorItem_
import im.vector.riotredesign.features.media.ImageContentRenderer
import im.vector.riotredesign.features.media.VideoContentRenderer

class TimelineEventController(private val dateFormatter: TimelineDateFormatter,
private val timelineItemFactory: TimelineItemFactory,
@ -53,7 +54,7 @@ class TimelineEventController(private val dateFormatter: TimelineDateFormatter,
fun onEventVisible(event: TimelineEvent)
fun onUrlClicked(url: String)
fun onImageMessageClicked(messageImageContent: MessageImageContent, mediaData: ImageContentRenderer.Data, view: View)
fun onVideoMessageClicked(messageVideoContent: MessageVideoContent, mediaData: ImageContentRenderer.Data, view: View)
fun onVideoMessageClicked(messageVideoContent: MessageVideoContent, mediaData: VideoContentRenderer.Data, view: View)
fun onFileMessageClicked(messageFileContent: MessageFileContent)
fun onAudioMessageClicked(messageAudioContent: MessageAudioContent)
}

View File

@ -51,6 +51,7 @@ import im.vector.riotredesign.features.home.room.detail.timeline.item.MessageTex
import im.vector.riotredesign.features.home.room.detail.timeline.item.MessageTextItem_
import im.vector.riotredesign.features.html.EventHtmlRenderer
import im.vector.riotredesign.features.media.ImageContentRenderer
import im.vector.riotredesign.features.media.VideoContentRenderer
import me.gujun.android.span.span

class MessageItemFactory(private val colorProvider: ColorProvider,
@ -157,7 +158,7 @@ class MessageItemFactory(private val colorProvider: ColorProvider,
callback: TimelineEventController.Callback?): MessageImageVideoItem? {

val (maxWidth, maxHeight) = timelineMediaSizeProvider.getMaxSize()
val data = ImageContentRenderer.Data(
val thumbnailData = ImageContentRenderer.Data(
filename = messageContent.body,
url = messageContent.info?.thumbnailUrl,
height = messageContent.info?.height,
@ -165,11 +166,18 @@ class MessageItemFactory(private val colorProvider: ColorProvider,
width = messageContent.info?.width,
maxWidth = maxWidth
)

val videoData = VideoContentRenderer.Data(
filename = messageContent.body,
videoUrl = messageContent.url,
thumbnailMediaData = thumbnailData
)

return MessageImageVideoItem_()
.playable(true)
.informationData(informationData)
.mediaData(data)
.clickListener { view -> callback?.onVideoMessageClicked(messageContent, data, view) }
.mediaData(thumbnailData)
.clickListener { view -> callback?.onVideoMessageClicked(messageContent, videoData, view) }
}

private fun buildTextMessageItem(messageContent: MessageTextContent,

View File

@ -25,22 +25,22 @@ import androidx.appcompat.widget.Toolbar
import com.github.piasy.biv.indicator.progresspie.ProgressPieIndicator
import com.github.piasy.biv.view.GlideImageViewFactory
import im.vector.riotredesign.core.platform.VectorBaseActivity
import kotlinx.android.synthetic.main.activity_media_viewer.*
import kotlinx.android.synthetic.main.activity_image_media_viewer.*


class MediaViewerActivity : VectorBaseActivity() {
class ImageMediaViewerActivity : VectorBaseActivity() {

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(im.vector.riotredesign.R.layout.activity_media_viewer)
setContentView(im.vector.riotredesign.R.layout.activity_image_media_viewer)
val mediaData = intent.getParcelableExtra<ImageContentRenderer.Data>(EXTRA_MEDIA_DATA)
if (mediaData.url.isNullOrEmpty()) {
finish()
} else {
configureToolbar(mediaViewerToolbar, mediaData)
mediaViewerImageView.setImageViewFactory(GlideImageViewFactory())
mediaViewerImageView.setProgressIndicator(ProgressPieIndicator())
ImageContentRenderer.render(mediaData, mediaViewerImageView)
configureToolbar(imageMediaViewerToolbar, mediaData)
imageMediaViewerImageView.setImageViewFactory(GlideImageViewFactory())
imageMediaViewerImageView.setProgressIndicator(ProgressPieIndicator())
ImageContentRenderer.render(mediaData, imageMediaViewerImageView)
}
}

@ -58,7 +58,7 @@ class MediaViewerActivity : VectorBaseActivity() {
private const val EXTRA_MEDIA_DATA = "EXTRA_MEDIA_DATA"

fun newIntent(context: Context, mediaData: ImageContentRenderer.Data): Intent {
return Intent(context, MediaViewerActivity::class.java).apply {
return Intent(context, ImageMediaViewerActivity::class.java).apply {
putExtra(EXTRA_MEDIA_DATA, mediaData)
}
}

View File

@ -0,0 +1,41 @@
/*
* 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.riotredesign.features.media

import android.os.Parcelable
import android.widget.ImageView
import android.widget.VideoView
import im.vector.matrix.android.api.Matrix
import kotlinx.android.parcel.Parcelize

object VideoContentRenderer {

@Parcelize
data class Data(
val filename: String,
val videoUrl: String?,
val thumbnailMediaData: ImageContentRenderer.Data
) : Parcelable

fun render(data: Data, thumbnailView: ImageView, videoView: VideoView) {
val contentUrlResolver = Matrix.getInstance().currentSession!!.contentUrlResolver()
val resolvedUrl = contentUrlResolver.resolveFullSize(data.videoUrl)
videoView.setVideoPath(resolvedUrl)
videoView.start()
}

}

View File

@ -0,0 +1,62 @@
/*
* 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.riotredesign.features.media

import android.content.Context
import android.content.Intent
import android.os.Bundle
import androidx.appcompat.widget.Toolbar
import im.vector.riotredesign.core.platform.VectorBaseActivity
import kotlinx.android.synthetic.main.activity_video_media_viewer.*


class VideoMediaViewerActivity : VectorBaseActivity() {

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(im.vector.riotredesign.R.layout.activity_video_media_viewer)
val mediaData = intent.getParcelableExtra<VideoContentRenderer.Data>(EXTRA_MEDIA_DATA)
if (mediaData.videoUrl.isNullOrEmpty()) {
finish()
} else {
configureToolbar(videoMediaViewerToolbar, mediaData)
VideoContentRenderer.render(mediaData, videoMediaViewerThumbnailView, videoMediaViewerVideoView)
}
}

private fun configureToolbar(toolbar: Toolbar, mediaData: VideoContentRenderer.Data) {
setSupportActionBar(toolbar)
supportActionBar?.apply {
title = mediaData.filename
setHomeButtonEnabled(true)
setDisplayHomeAsUpEnabled(true)
}
}

companion object {

private const val EXTRA_MEDIA_DATA = "EXTRA_MEDIA_DATA"

fun newIntent(context: Context, mediaData: VideoContentRenderer.Data): Intent {
return Intent(context, VideoMediaViewerActivity::class.java).apply {
putExtra(EXTRA_MEDIA_DATA, mediaData)
}
}
}


}

View File

@ -6,7 +6,7 @@
android:orientation="vertical">

<androidx.appcompat.widget.Toolbar
android:id="@+id/mediaViewerToolbar"
android:id="@+id/imageMediaViewerToolbar"
style="@style/VectorToolbarStyle"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
@ -15,7 +15,7 @@
app:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar" />

<com.github.piasy.biv.view.BigImageView
android:id="@+id/mediaViewerImageView"
android:id="@+id/imageMediaViewerImageView"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:failureImageInitScaleType="center"

View File

@ -0,0 +1,48 @@
<?xml version="1.0" encoding="utf-8"?><!--
~ 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.
-->

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">

<androidx.appcompat.widget.Toolbar
android:id="@+id/videoMediaViewerToolbar"
style="@style/VectorToolbarStyle"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="?attr/colorPrimary"
app:popupTheme="@style/ThemeOverlay.AppCompat.Light"
app:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar" />

<FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent">

<ImageView
android:id="@+id/videoMediaViewerThumbnailView"
android:layout_width="match_parent"
android:layout_height="match_parent" />

<VideoView
android:id="@+id/videoMediaViewerVideoView"
android:layout_width="match_parent"
android:layout_height="match_parent" />

</FrameLayout>

</LinearLayout>