forked from GitHub-Mirror/riotX-android
Compare commits
1 Commits
develop
...
feature/do
Author | SHA1 | Date | |
---|---|---|---|
|
4a754166df |
@ -208,6 +208,7 @@ class MessageItemFactory @Inject constructor(
|
|||||||
|
|
||||||
val (maxWidth, maxHeight) = timelineMediaSizeProvider.getMaxSize()
|
val (maxWidth, maxHeight) = timelineMediaSizeProvider.getMaxSize()
|
||||||
val data = ImageContentRenderer.Data(
|
val data = ImageContentRenderer.Data(
|
||||||
|
eventId = informationData.eventId,
|
||||||
filename = messageContent.body,
|
filename = messageContent.body,
|
||||||
url = messageContent.getFileUrl(),
|
url = messageContent.getFileUrl(),
|
||||||
elementToDecrypt = messageContent.encryptedFileInfo?.toElementToDecrypt(),
|
elementToDecrypt = messageContent.encryptedFileInfo?.toElementToDecrypt(),
|
||||||
@ -251,6 +252,7 @@ class MessageItemFactory @Inject constructor(
|
|||||||
|
|
||||||
val (maxWidth, maxHeight) = timelineMediaSizeProvider.getMaxSize()
|
val (maxWidth, maxHeight) = timelineMediaSizeProvider.getMaxSize()
|
||||||
val thumbnailData = ImageContentRenderer.Data(
|
val thumbnailData = ImageContentRenderer.Data(
|
||||||
|
eventId = informationData.eventId,
|
||||||
filename = messageContent.body,
|
filename = messageContent.body,
|
||||||
url = messageContent.videoInfo?.thumbnailFile?.url
|
url = messageContent.videoInfo?.thumbnailFile?.url
|
||||||
?: messageContent.videoInfo?.thumbnailUrl,
|
?: messageContent.videoInfo?.thumbnailUrl,
|
||||||
|
@ -42,6 +42,7 @@ class ImageContentRenderer @Inject constructor(private val activeSessionHolder:
|
|||||||
|
|
||||||
@Parcelize
|
@Parcelize
|
||||||
data class Data(
|
data class Data(
|
||||||
|
val eventId: String,
|
||||||
val filename: String,
|
val filename: String,
|
||||||
val url: String?,
|
val url: String?,
|
||||||
val elementToDecrypt: ElementToDecrypt?,
|
val elementToDecrypt: ElementToDecrypt?,
|
||||||
|
@ -21,6 +21,8 @@ import android.content.Intent
|
|||||||
import android.graphics.drawable.Drawable
|
import android.graphics.drawable.Drawable
|
||||||
import android.os.Build
|
import android.os.Build
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
|
import android.view.Menu
|
||||||
|
import android.view.MenuItem
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.ViewTreeObserver
|
import android.view.ViewTreeObserver
|
||||||
import androidx.annotation.RequiresApi
|
import androidx.annotation.RequiresApi
|
||||||
@ -36,6 +38,7 @@ import com.bumptech.glide.request.RequestListener
|
|||||||
import com.bumptech.glide.request.target.Target
|
import com.bumptech.glide.request.target.Target
|
||||||
import com.github.piasy.biv.indicator.progresspie.ProgressPieIndicator
|
import com.github.piasy.biv.indicator.progresspie.ProgressPieIndicator
|
||||||
import com.github.piasy.biv.view.GlideImageViewFactory
|
import com.github.piasy.biv.view.GlideImageViewFactory
|
||||||
|
import im.vector.riotx.R
|
||||||
import im.vector.riotx.core.di.ScreenComponent
|
import im.vector.riotx.core.di.ScreenComponent
|
||||||
import im.vector.riotx.core.glide.GlideApp
|
import im.vector.riotx.core.glide.GlideApp
|
||||||
import im.vector.riotx.core.platform.VectorBaseActivity
|
import im.vector.riotx.core.platform.VectorBaseActivity
|
||||||
@ -47,17 +50,20 @@ import javax.inject.Inject
|
|||||||
class ImageMediaViewerActivity : VectorBaseActivity() {
|
class ImageMediaViewerActivity : VectorBaseActivity() {
|
||||||
|
|
||||||
@Inject lateinit var imageContentRenderer: ImageContentRenderer
|
@Inject lateinit var imageContentRenderer: ImageContentRenderer
|
||||||
|
@Inject lateinit var mediaDownloadHelper: MediaDownloadHelper
|
||||||
|
|
||||||
lateinit var mediaData: ImageContentRenderer.Data
|
lateinit var mediaData: ImageContentRenderer.Data
|
||||||
|
|
||||||
|
override fun getMenuRes() = R.menu.image_media_viewer
|
||||||
|
|
||||||
override fun injectWith(injector: ScreenComponent) {
|
override fun injectWith(injector: ScreenComponent) {
|
||||||
injector.inject(this)
|
injector.inject(this)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
super.onCreate(savedInstanceState)
|
super.onCreate(savedInstanceState)
|
||||||
setContentView(im.vector.riotx.R.layout.activity_image_media_viewer)
|
setContentView(R.layout.activity_image_media_viewer)
|
||||||
mediaData = intent.getParcelableExtra<ImageContentRenderer.Data>(EXTRA_MEDIA_DATA)
|
mediaData = intent.getParcelableExtra(EXTRA_MEDIA_DATA)
|
||||||
intent.extras.getString(EXTRA_SHARED_TRANSITION_NAME)?.let {
|
intent.extras.getString(EXTRA_SHARED_TRANSITION_NAME)?.let {
|
||||||
ViewCompat.setTransitionName(imageTransitionView, it)
|
ViewCompat.setTransitionName(imageTransitionView, it)
|
||||||
}
|
}
|
||||||
@ -105,6 +111,29 @@ class ImageMediaViewerActivity : VectorBaseActivity() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun onPrepareOptionsMenu(menu: Menu): Boolean {
|
||||||
|
val downloadItem = menu.findItem(R.id.download_image)
|
||||||
|
downloadItem.isVisible = !mediaData.isLocalFile()
|
||||||
|
return super.onPrepareOptionsMenu(menu)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onOptionsItemSelected(item: MenuItem): Boolean {
|
||||||
|
when (item.itemId) {
|
||||||
|
R.id.download_image -> mediaDownloadHelper.checkPermissionAndDownload(
|
||||||
|
mediaData.eventId,
|
||||||
|
mediaData.filename,
|
||||||
|
mediaData.url,
|
||||||
|
mediaData.elementToDecrypt
|
||||||
|
)
|
||||||
|
}
|
||||||
|
return super.onOptionsItemSelected(item)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<out String>, grantResults: IntArray) {
|
||||||
|
mediaDownloadHelper.onRequestPermissionsResult(requestCode, permissions, grantResults)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
private fun configureToolbar(toolbar: Toolbar, mediaData: ImageContentRenderer.Data) {
|
private fun configureToolbar(toolbar: Toolbar, mediaData: ImageContentRenderer.Data) {
|
||||||
setSupportActionBar(toolbar)
|
setSupportActionBar(toolbar)
|
||||||
supportActionBar?.apply {
|
supportActionBar?.apply {
|
||||||
|
@ -0,0 +1,84 @@
|
|||||||
|
/*
|
||||||
|
|
||||||
|
* 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.riotx.features.media
|
||||||
|
|
||||||
|
import androidx.appcompat.app.AppCompatActivity
|
||||||
|
import im.vector.matrix.android.api.MatrixCallback
|
||||||
|
import im.vector.matrix.android.api.session.Session
|
||||||
|
import im.vector.matrix.android.api.session.file.FileService
|
||||||
|
import im.vector.matrix.android.internal.crypto.attachments.ElementToDecrypt
|
||||||
|
import im.vector.riotx.R
|
||||||
|
import im.vector.riotx.core.error.ErrorFormatter
|
||||||
|
import im.vector.riotx.core.resources.StringProvider
|
||||||
|
import im.vector.riotx.core.utils.*
|
||||||
|
import java.io.File
|
||||||
|
import javax.inject.Inject
|
||||||
|
|
||||||
|
class MediaDownloadHelper @Inject constructor(private val activity: AppCompatActivity,
|
||||||
|
private val session: Session,
|
||||||
|
private val stringProvider: StringProvider,
|
||||||
|
private val errorFormatter: ErrorFormatter) {
|
||||||
|
|
||||||
|
private data class PendingData(
|
||||||
|
val id: String,
|
||||||
|
val filename: String,
|
||||||
|
val url: String,
|
||||||
|
val elementToDecrypt: ElementToDecrypt?
|
||||||
|
)
|
||||||
|
|
||||||
|
private var pendingData: PendingData? = null
|
||||||
|
|
||||||
|
fun checkPermissionAndDownload(id: String, filename: String, url: String?, elementToDecrypt: ElementToDecrypt?) {
|
||||||
|
if (url.isNullOrEmpty()) {
|
||||||
|
activity.toast(stringProvider.getString(R.string.unexpected_error))
|
||||||
|
} else if (checkPermissions(PERMISSIONS_FOR_WRITING_FILES, activity, PERMISSION_REQUEST_CODE_DOWNLOAD_FILE)) {
|
||||||
|
downloadFile(id, filename, url, elementToDecrypt)
|
||||||
|
} else {
|
||||||
|
pendingData = PendingData(id, filename, url, elementToDecrypt)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun onRequestPermissionsResult(requestCode: Int, permissions: Array<out String>, grantResults: IntArray) {
|
||||||
|
if (allGranted(grantResults) && requestCode == PERMISSION_REQUEST_CODE_DOWNLOAD_FILE) {
|
||||||
|
pendingData?.also {
|
||||||
|
downloadFile(it.id, it.filename, it.url, it.elementToDecrypt)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun downloadFile(id: String, filename: String, url: String, elementToDecrypt: ElementToDecrypt?) {
|
||||||
|
session.downloadFile(
|
||||||
|
FileService.DownloadMode.TO_EXPORT,
|
||||||
|
id,
|
||||||
|
filename,
|
||||||
|
url,
|
||||||
|
elementToDecrypt,
|
||||||
|
object : MatrixCallback<File> {
|
||||||
|
override fun onSuccess(data: File) {
|
||||||
|
activity.toast(stringProvider.getString(R.string.downloaded_file, data.path))
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onFailure(failure: Throwable) {
|
||||||
|
activity.toast(errorFormatter.toHumanReadable(failure))
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
@ -43,7 +43,13 @@ class VideoContentRenderer @Inject constructor(private val activeSessionHolder:
|
|||||||
val url: String?,
|
val url: String?,
|
||||||
val elementToDecrypt: ElementToDecrypt?,
|
val elementToDecrypt: ElementToDecrypt?,
|
||||||
val thumbnailMediaData: ImageContentRenderer.Data
|
val thumbnailMediaData: ImageContentRenderer.Data
|
||||||
) : Parcelable
|
) : Parcelable {
|
||||||
|
|
||||||
|
fun isLocalFile(): Boolean {
|
||||||
|
return url != null && File(url).exists()
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
fun render(data: Data,
|
fun render(data: Data,
|
||||||
thumbnailView: ImageView,
|
thumbnailView: ImageView,
|
||||||
|
@ -19,7 +19,10 @@ package im.vector.riotx.features.media
|
|||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
|
import android.view.Menu
|
||||||
|
import android.view.MenuItem
|
||||||
import androidx.appcompat.widget.Toolbar
|
import androidx.appcompat.widget.Toolbar
|
||||||
|
import im.vector.riotx.R
|
||||||
import im.vector.riotx.core.di.ScreenComponent
|
import im.vector.riotx.core.di.ScreenComponent
|
||||||
import im.vector.riotx.core.platform.VectorBaseActivity
|
import im.vector.riotx.core.platform.VectorBaseActivity
|
||||||
import kotlinx.android.synthetic.main.activity_video_media_viewer.*
|
import kotlinx.android.synthetic.main.activity_video_media_viewer.*
|
||||||
@ -30,6 +33,10 @@ class VideoMediaViewerActivity : VectorBaseActivity() {
|
|||||||
|
|
||||||
@Inject lateinit var imageContentRenderer: ImageContentRenderer
|
@Inject lateinit var imageContentRenderer: ImageContentRenderer
|
||||||
@Inject lateinit var videoContentRenderer: VideoContentRenderer
|
@Inject lateinit var videoContentRenderer: VideoContentRenderer
|
||||||
|
@Inject lateinit var mediaDownloadHelper: MediaDownloadHelper
|
||||||
|
lateinit var mediaData: VideoContentRenderer.Data
|
||||||
|
|
||||||
|
override fun getMenuRes() = R.menu.video_media_viewer
|
||||||
|
|
||||||
override fun injectWith(injector: ScreenComponent) {
|
override fun injectWith(injector: ScreenComponent) {
|
||||||
injector.inject(this)
|
injector.inject(this)
|
||||||
@ -37,9 +44,12 @@ class VideoMediaViewerActivity : VectorBaseActivity() {
|
|||||||
|
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
super.onCreate(savedInstanceState)
|
super.onCreate(savedInstanceState)
|
||||||
setContentView(im.vector.riotx.R.layout.activity_video_media_viewer)
|
setContentView(R.layout.activity_video_media_viewer)
|
||||||
val mediaData = intent.getParcelableExtra<VideoContentRenderer.Data>(EXTRA_MEDIA_DATA)
|
mediaData = intent.getParcelableExtra(EXTRA_MEDIA_DATA)
|
||||||
|
if (mediaData.url.isNullOrEmpty()) {
|
||||||
|
finish()
|
||||||
|
return
|
||||||
|
}
|
||||||
configureToolbar(videoMediaViewerToolbar, mediaData)
|
configureToolbar(videoMediaViewerToolbar, mediaData)
|
||||||
imageContentRenderer.render(mediaData.thumbnailMediaData, ImageContentRenderer.Mode.FULL_SIZE, videoMediaViewerThumbnailView)
|
imageContentRenderer.render(mediaData.thumbnailMediaData, ImageContentRenderer.Mode.FULL_SIZE, videoMediaViewerThumbnailView)
|
||||||
videoContentRenderer.render(mediaData, videoMediaViewerThumbnailView, videoMediaViewerLoading, videoMediaViewerVideoView, videoMediaViewerErrorView)
|
videoContentRenderer.render(mediaData, videoMediaViewerThumbnailView, videoMediaViewerLoading, videoMediaViewerVideoView, videoMediaViewerErrorView)
|
||||||
@ -54,6 +64,28 @@ class VideoMediaViewerActivity : VectorBaseActivity() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun onPrepareOptionsMenu(menu: Menu): Boolean {
|
||||||
|
val downloadItem = menu.findItem(R.id.download_video)
|
||||||
|
downloadItem.isVisible = !mediaData.isLocalFile()
|
||||||
|
return super.onPrepareOptionsMenu(menu)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onOptionsItemSelected(item: MenuItem): Boolean {
|
||||||
|
when (item.itemId) {
|
||||||
|
R.id.download_video -> mediaDownloadHelper.checkPermissionAndDownload(
|
||||||
|
mediaData.eventId,
|
||||||
|
mediaData.filename,
|
||||||
|
mediaData.url,
|
||||||
|
mediaData.elementToDecrypt
|
||||||
|
)
|
||||||
|
}
|
||||||
|
return super.onOptionsItemSelected(item)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<out String>, grantResults: IntArray) {
|
||||||
|
mediaDownloadHelper.onRequestPermissionsResult(requestCode, permissions, grantResults)
|
||||||
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
|
|
||||||
private const val EXTRA_MEDIA_DATA = "EXTRA_MEDIA_DATA"
|
private const val EXTRA_MEDIA_DATA = "EXTRA_MEDIA_DATA"
|
||||||
|
11
vector/src/main/res/menu/image_media_viewer.xml
Normal file
11
vector/src/main/res/menu/image_media_viewer.xml
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<menu xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto">
|
||||||
|
|
||||||
|
<item
|
||||||
|
android:id="@+id/download_image"
|
||||||
|
android:title="@string/download"
|
||||||
|
android:visible="true"
|
||||||
|
app:showAsAction="never" />
|
||||||
|
|
||||||
|
</menu>
|
12
vector/src/main/res/menu/video_media_viewer.xml
Normal file
12
vector/src/main/res/menu/video_media_viewer.xml
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<menu xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto">
|
||||||
|
|
||||||
|
<item
|
||||||
|
android:id="@+id/download_video"
|
||||||
|
android:title="@string/download"
|
||||||
|
android:visible="true"
|
||||||
|
app:showAsAction="never" />
|
||||||
|
|
||||||
|
|
||||||
|
</menu>
|
Loading…
Reference in New Issue
Block a user