Uploads: create extension
This commit is contained in:
parent
919225bdfd
commit
f7de2f0f13
@ -256,7 +256,11 @@ fun shareMedia(context: Context, file: File, mediaMimeType: String?) {
|
||||
sendIntent.type = mediaMimeType
|
||||
sendIntent.putExtra(Intent.EXTRA_STREAM, mediaUri)
|
||||
|
||||
context.startActivity(sendIntent)
|
||||
try {
|
||||
context.startActivity(sendIntent)
|
||||
} catch (activityNotFoundException: ActivityNotFoundException) {
|
||||
context.toast(R.string.error_no_external_application_found)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -17,11 +17,12 @@
|
||||
package im.vector.riotx.features.roomprofile.uploads
|
||||
|
||||
import im.vector.matrix.android.api.session.events.model.Event
|
||||
import im.vector.matrix.android.api.session.room.model.message.MessageWithAttachmentContent
|
||||
import im.vector.riotx.core.platform.VectorViewModelAction
|
||||
|
||||
sealed class RoomUploadsAction : VectorViewModelAction {
|
||||
data class Download(val event: Event) : RoomUploadsAction()
|
||||
data class Share(val event: Event) : RoomUploadsAction()
|
||||
data class Download(val event: Event, val messageContent: MessageWithAttachmentContent) : RoomUploadsAction()
|
||||
data class Share(val event: Event, val messageContent: MessageWithAttachmentContent) : RoomUploadsAction()
|
||||
|
||||
object Retry : RoomUploadsAction()
|
||||
object LoadMore : RoomUploadsAction()
|
||||
|
@ -18,14 +18,20 @@ package im.vector.riotx.features.roomprofile.uploads
|
||||
|
||||
import android.os.Bundle
|
||||
import android.view.View
|
||||
import android.widget.Toast
|
||||
import androidx.core.net.toUri
|
||||
import com.airbnb.mvrx.args
|
||||
import com.airbnb.mvrx.fragmentViewModel
|
||||
import com.airbnb.mvrx.withState
|
||||
import com.google.android.material.tabs.TabLayoutMediator
|
||||
import im.vector.matrix.android.api.util.toMatrixItem
|
||||
import im.vector.riotx.R
|
||||
import im.vector.riotx.core.extensions.exhaustive
|
||||
import im.vector.riotx.core.intent.getMimeTypeFromUri
|
||||
import im.vector.riotx.core.platform.VectorBaseFragment
|
||||
import im.vector.riotx.core.resources.StringProvider
|
||||
import im.vector.riotx.core.utils.saveMedia
|
||||
import im.vector.riotx.core.utils.shareMedia
|
||||
import im.vector.riotx.features.home.AvatarRenderer
|
||||
import im.vector.riotx.features.roomprofile.RoomProfileArgs
|
||||
import kotlinx.android.synthetic.main.fragment_room_uploads.*
|
||||
@ -58,7 +64,27 @@ class RoomUploadsFragment @Inject constructor(
|
||||
|
||||
setupToolbar(roomUploadsToolbar)
|
||||
|
||||
// Initialize your view, subscribe to viewModel...
|
||||
viewModel.observeViewEvents {
|
||||
when (it) {
|
||||
is RoomUploadsViewEvents.FileReadyForSharing -> {
|
||||
shareMedia(requireContext(), it.file, getMimeTypeFromUri(requireContext(), it.file.toUri()))
|
||||
}
|
||||
is RoomUploadsViewEvents.FileReadyForSaving -> {
|
||||
val saved = saveMedia(
|
||||
context = requireContext(),
|
||||
file = it.file,
|
||||
title = it.title,
|
||||
mediaMimeType = getMimeTypeFromUri(requireContext(), it.file.toUri())
|
||||
)
|
||||
if (saved) {
|
||||
Toast.makeText(requireContext(), R.string.media_file_added_to_gallery, Toast.LENGTH_LONG).show()
|
||||
} else {
|
||||
Toast.makeText(requireContext(), R.string.error_adding_media_file_to_gallery, Toast.LENGTH_LONG).show()
|
||||
}
|
||||
}
|
||||
is RoomUploadsViewEvents.Failure -> showFailure(it.throwable)
|
||||
}.exhaustive
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -0,0 +1,27 @@
|
||||
/*
|
||||
* 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.roomprofile.uploads
|
||||
|
||||
import im.vector.riotx.core.platform.VectorViewEvents
|
||||
import java.io.File
|
||||
|
||||
sealed class RoomUploadsViewEvents : VectorViewEvents {
|
||||
data class Failure(val throwable: Throwable) : RoomUploadsViewEvents()
|
||||
|
||||
data class FileReadyForSharing(val file: File) : RoomUploadsViewEvents()
|
||||
data class FileReadyForSaving(val file: File, val title: String) : RoomUploadsViewEvents()
|
||||
}
|
@ -30,20 +30,23 @@ import im.vector.matrix.android.api.session.Session
|
||||
import im.vector.matrix.android.api.session.events.model.EventType
|
||||
import im.vector.matrix.android.api.session.events.model.isPreviewableMessage
|
||||
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.getFileUrl
|
||||
import im.vector.matrix.android.api.session.room.uploads.GetUploadsResult
|
||||
import im.vector.matrix.android.internal.crypto.attachments.toElementToDecrypt
|
||||
import im.vector.matrix.android.internal.util.awaitCallback
|
||||
import im.vector.matrix.rx.rx
|
||||
import im.vector.matrix.rx.unwrap
|
||||
import im.vector.riotx.core.extensions.exhaustive
|
||||
import im.vector.riotx.core.platform.EmptyViewEvents
|
||||
import im.vector.riotx.core.platform.VectorViewModel
|
||||
import kotlinx.coroutines.launch
|
||||
import java.io.File
|
||||
|
||||
class RoomUploadsViewModel @AssistedInject constructor(
|
||||
@Assisted initialState: RoomUploadsViewState,
|
||||
private val session: Session
|
||||
) : VectorViewModel<RoomUploadsViewState, RoomUploadsAction, EmptyViewEvents>(initialState) {
|
||||
) : VectorViewModel<RoomUploadsViewState, RoomUploadsAction, RoomUploadsViewEvents>(initialState) {
|
||||
|
||||
@AssistedInject.Factory
|
||||
interface Factory {
|
||||
@ -123,10 +126,50 @@ class RoomUploadsViewModel @AssistedInject constructor(
|
||||
|
||||
override fun handle(action: RoomUploadsAction) {
|
||||
when (action) {
|
||||
is RoomUploadsAction.Download -> TODO()
|
||||
is RoomUploadsAction.Share -> TODO()
|
||||
is RoomUploadsAction.Download -> handleDownload(action)
|
||||
is RoomUploadsAction.Share -> handleShare(action)
|
||||
RoomUploadsAction.Retry -> handleLoadMore()
|
||||
RoomUploadsAction.LoadMore -> handleLoadMore()
|
||||
}.exhaustive
|
||||
}
|
||||
|
||||
private fun handleShare(action: RoomUploadsAction.Share) {
|
||||
viewModelScope.launch {
|
||||
try {
|
||||
val file = awaitCallback<File> {
|
||||
session.downloadFile(
|
||||
FileService.DownloadMode.FOR_EXTERNAL_SHARE,
|
||||
action.event.eventId ?: "",
|
||||
action.messageContent.body,
|
||||
action.messageContent.getFileUrl(),
|
||||
action.messageContent.encryptedFileInfo?.toElementToDecrypt(),
|
||||
it
|
||||
)
|
||||
}
|
||||
_viewEvents.post(RoomUploadsViewEvents.FileReadyForSharing(file))
|
||||
} catch (failure: Throwable) {
|
||||
_viewEvents.post(RoomUploadsViewEvents.Failure(failure))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun handleDownload(action: RoomUploadsAction.Download) {
|
||||
viewModelScope.launch {
|
||||
try {
|
||||
val file = awaitCallback<File> {
|
||||
session.downloadFile(
|
||||
FileService.DownloadMode.FOR_EXTERNAL_SHARE,
|
||||
action.event.eventId ?: "",
|
||||
action.messageContent.body,
|
||||
action.messageContent.getFileUrl(),
|
||||
action.messageContent.encryptedFileInfo?.toElementToDecrypt(),
|
||||
it)
|
||||
|
||||
}
|
||||
_viewEvents.post(RoomUploadsViewEvents.FileReadyForSaving(file, action.messageContent.body))
|
||||
} catch (failure: Throwable) {
|
||||
_viewEvents.post(RoomUploadsViewEvents.Failure(failure))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -21,6 +21,7 @@ import android.view.View
|
||||
import com.airbnb.mvrx.parentFragmentViewModel
|
||||
import com.airbnb.mvrx.withState
|
||||
import im.vector.matrix.android.api.session.events.model.Event
|
||||
import im.vector.matrix.android.api.session.room.model.message.MessageWithAttachmentContent
|
||||
import im.vector.riotx.R
|
||||
import im.vector.riotx.core.extensions.cleanup
|
||||
import im.vector.riotx.core.extensions.configureWith
|
||||
@ -54,7 +55,7 @@ class RoomUploadsFilesFragment @Inject constructor(
|
||||
}
|
||||
|
||||
override fun onOpenClicked(event: Event) {
|
||||
// TODO
|
||||
TODO()
|
||||
}
|
||||
|
||||
override fun onRetry() {
|
||||
@ -65,12 +66,12 @@ class RoomUploadsFilesFragment @Inject constructor(
|
||||
uploadsViewModel.handle(RoomUploadsAction.LoadMore)
|
||||
}
|
||||
|
||||
override fun onDownloadClicked(event: Event) {
|
||||
uploadsViewModel.handle(RoomUploadsAction.Download(event))
|
||||
override fun onDownloadClicked(event: Event, messageWithAttachmentContent: MessageWithAttachmentContent) {
|
||||
uploadsViewModel.handle(RoomUploadsAction.Download(event, messageWithAttachmentContent))
|
||||
}
|
||||
|
||||
override fun onShareClicked(event: Event) {
|
||||
uploadsViewModel.handle(RoomUploadsAction.Share(event))
|
||||
override fun onShareClicked(event: Event, messageWithAttachmentContent: MessageWithAttachmentContent) {
|
||||
uploadsViewModel.handle(RoomUploadsAction.Share(event, messageWithAttachmentContent))
|
||||
}
|
||||
|
||||
override fun invalidate() = withState(uploadsViewModel) { state ->
|
||||
|
@ -22,7 +22,11 @@ import com.airbnb.mvrx.Fail
|
||||
import com.airbnb.mvrx.Loading
|
||||
import com.airbnb.mvrx.Success
|
||||
import im.vector.matrix.android.api.session.events.model.Event
|
||||
import im.vector.matrix.android.api.session.events.model.toModel
|
||||
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.riotx.R
|
||||
import im.vector.riotx.core.date.VectorDateFormatter
|
||||
import im.vector.riotx.core.epoxy.errorWithRetryItem
|
||||
import im.vector.riotx.core.epoxy.loadingItem
|
||||
import im.vector.riotx.core.epoxy.noResultItem
|
||||
@ -33,15 +37,16 @@ import javax.inject.Inject
|
||||
|
||||
class UploadsFileController @Inject constructor(
|
||||
private val errorFormatter: ErrorFormatter,
|
||||
private val stringProvider: StringProvider
|
||||
private val stringProvider: StringProvider,
|
||||
private val dateFormatter: VectorDateFormatter
|
||||
) : TypedEpoxyController<RoomUploadsViewState>() {
|
||||
|
||||
interface Listener {
|
||||
fun onRetry()
|
||||
fun loadMore()
|
||||
fun onOpenClicked(event: Event)
|
||||
fun onDownloadClicked(event: Event)
|
||||
fun onShareClicked(event: Event)
|
||||
fun onDownloadClicked(event: Event, messageWithAttachmentContent: MessageWithAttachmentContent)
|
||||
fun onShareClicked(event: Event, messageWithAttachmentContent: MessageWithAttachmentContent)
|
||||
}
|
||||
|
||||
var listener: Listener? = null
|
||||
@ -100,21 +105,25 @@ class UploadsFileController @Inject constructor(
|
||||
|
||||
private fun buildFileItems(fileEvents: List<Event>) {
|
||||
fileEvents.forEach {
|
||||
val messageContent = it.getClearContent()?.toModel<MessageContent>() ?: return@forEach
|
||||
val messageWithAttachmentContent = (messageContent as? MessageWithAttachmentContent) ?: return@forEach
|
||||
|
||||
uploadsFileItem {
|
||||
id(it.eventId ?: "")
|
||||
title(it.getClearType())
|
||||
subtitle(it.getSenderKey())
|
||||
title(messageWithAttachmentContent.body)
|
||||
// TODO Resolve user displayName
|
||||
subtitle(stringProvider.getString(R.string.uploads_files_subtitle, it.senderId, dateFormatter.formatRelativeDateTime(it.originServerTs)))
|
||||
listener(object : UploadsFileItem.Listener {
|
||||
override fun onItemClicked() {
|
||||
listener?.onOpenClicked(it)
|
||||
}
|
||||
|
||||
override fun onDownloadClicked() {
|
||||
listener?.onDownloadClicked(it)
|
||||
listener?.onDownloadClicked(it, messageWithAttachmentContent)
|
||||
}
|
||||
|
||||
override fun onShareClicked() {
|
||||
listener?.onShareClicked(it)
|
||||
listener?.onShareClicked(it, messageWithAttachmentContent)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
@ -1791,6 +1791,8 @@ Not all features in Riot are implemented in RiotX yet. Main missing (and coming
|
||||
<string name="uploads_media_title">MEDIA</string>
|
||||
<string name="uploads_media_no_result">There is no media in this room</string>
|
||||
<string name="uploads_files_title">FILES</string>
|
||||
<!-- First parameter is a username and second is a date Example: "Matthew at 12:00 on 01/01/01" -->
|
||||
<string name="uploads_files_subtitle">%1$s at %2$s</string>
|
||||
<string name="uploads_files_no_result">There is no files in this room</string>
|
||||
|
||||
<string name="report_content_spam">"It's spam"</string>
|
||||
|
Loading…
x
Reference in New Issue
Block a user