Media upload: handle local echo by pinning at the bottom... will probably be changed

This commit is contained in:
ganfra
2019-04-09 19:57:43 +02:00
parent c9658918ed
commit 0225fc7120
25 changed files with 462 additions and 152 deletions

View File

@ -23,7 +23,6 @@ import android.os.Parcelable
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.appcompat.app.AlertDialog
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import com.airbnb.epoxy.EpoxyVisibilityTracker
@ -34,7 +33,6 @@ import com.jaiselrahman.filepicker.model.MediaFile
import im.vector.matrix.android.api.session.room.timeline.TimelineEvent
import im.vector.riotredesign.R
import im.vector.riotredesign.core.dialogs.DialogListItem
import im.vector.riotredesign.core.dialogs.DialogSendItemAdapter
import im.vector.riotredesign.core.epoxy.LayoutManagerStateRestorer
import im.vector.riotredesign.core.platform.RiotFragment
import im.vector.riotredesign.core.platform.ToolbarConfigurable
@ -155,15 +153,24 @@ class RoomDetailFragment : RiotFragment(), TimelineEventController.Callback {
private fun setupAttachmentButton() {
attachmentButton.setOnClickListener {
val intent = Intent(requireContext(), FilePickerActivity::class.java)
intent.putExtra(FilePickerActivity.CONFIGS, Configurations.Builder()
.setCheckPermission(true)
.setShowFiles(true)
.setShowAudios(true)
.setSkipZeroSizeFiles(true)
.build())
startActivityForResult(intent, REQUEST_FILES_REQUEST_CODE)
/*
val items = ArrayList<DialogListItem>()
// Send file
items.add(DialogListItem.SendFile)
// Send voice
/*
if (PreferencesManager.isSendVoiceFeatureEnabled(this)) {
items.add(DialogListItem.SendVoice.INSTANCE)
}
*/
// Send sticker
//items.add(DialogListItem.SendSticker)
@ -182,6 +189,7 @@ class RoomDetailFragment : RiotFragment(), TimelineEventController.Callback {
}
.setNegativeButton(R.string.cancel, null)
.show()
*/
}
}
@ -189,12 +197,7 @@ class RoomDetailFragment : RiotFragment(), TimelineEventController.Callback {
Timber.v("On send choice clicked: $dialogListItem")
when (dialogListItem) {
is DialogListItem.SendFile -> {
val intent = Intent(requireContext(), FilePickerActivity::class.java)
intent.putExtra(FilePickerActivity.CONFIGS, Configurations.Builder()
.setCheckPermission(true)
.setSkipZeroSizeFiles(true)
.build())
startActivityForResult(intent, REQUEST_FILES_REQUEST_CODE)
// launchFileIntent
}
is DialogListItem.SendVoice -> {
//launchAudioRecorderIntent()

View File

@ -21,7 +21,6 @@ import com.airbnb.mvrx.ViewModelContext
import com.jakewharton.rxrelay2.BehaviorRelay
import im.vector.matrix.android.api.MatrixCallback
import im.vector.matrix.android.api.session.Session
import im.vector.matrix.android.api.session.events.model.Event
import im.vector.matrix.android.api.session.content.ContentAttachmentData
import im.vector.matrix.rx.rx
import im.vector.riotredesign.core.platform.RiotViewModel
@ -75,25 +74,24 @@ class RoomDetailViewModel(initialState: RoomDetailViewState,
// PRIVATE METHODS *****************************************************************************
private fun handleSendMessage(action: RoomDetailActions.SendMessage) {
room.sendTextMessage(action.text, callback = object : MatrixCallback<Event> {})
room.sendTextMessage(action.text)
}
private fun handleSendMedia(action: RoomDetailActions.SendMedia) {
val attachment = action.mediaFiles.firstOrNull()
?.let {
ContentAttachmentData(
it.size,
it.duration,
it.date,
it.height,
it.width,
it.name,
it.path,
it.mimeType
)
}
?: return
room.sendMedia(attachment, callback = object : MatrixCallback<Event> {})
val attachments = action.mediaFiles.map {
ContentAttachmentData(
size = it.size,
duration = it.duration,
date = it.date,
height = it.height,
width = it.width,
name = it.name,
path = it.path,
mimeType = it.mimeType,
type = ContentAttachmentData.Type.values()[it.mediaType]
)
}
room.sendMedias(attachments)
}
private fun handleEventDisplayed(action: RoomDetailActions.EventDisplayed) {
@ -134,4 +132,5 @@ class RoomDetailViewModel(initialState: RoomDetailViewState,
timeline.dispose()
super.onCleared()
}
}

View File

@ -28,6 +28,7 @@ import im.vector.matrix.android.api.session.room.model.message.MessageEmoteConte
import im.vector.matrix.android.api.session.room.model.message.MessageImageContent
import im.vector.matrix.android.api.session.room.model.message.MessageNoticeContent
import im.vector.matrix.android.api.session.room.model.message.MessageTextContent
import im.vector.matrix.android.api.session.room.send.SendState
import im.vector.matrix.android.api.session.room.timeline.TimelineEvent
import im.vector.riotredesign.R
import im.vector.riotredesign.core.epoxy.RiotEpoxyModel
@ -79,7 +80,7 @@ class MessageItemFactory(private val colorProvider: ColorProvider,
val informationData = MessageInformationData(time, avatarUrl, memberName, showInformation)
return when (messageContent) {
is MessageTextContent -> buildTextMessageItem(messageContent, informationData, callback)
is MessageTextContent -> buildTextMessageItem(event.sendState, messageContent, informationData, callback)
is MessageImageContent -> buildImageMessageItem(eventId, messageContent, informationData, callback)
is MessageEmoteContent -> buildEmoteMessageItem(messageContent, informationData, callback)
is MessageNoticeContent -> buildNoticeMessageItem(messageContent, informationData, callback)
@ -115,17 +116,24 @@ class MessageItemFactory(private val colorProvider: ColorProvider,
.clickListener { view -> callback?.onMediaClicked(data, view) }
}
private fun buildTextMessageItem(messageContent: MessageTextContent,
private fun buildTextMessageItem(sendState: SendState,
messageContent: MessageTextContent,
informationData: MessageInformationData,
callback: TimelineEventController.Callback?): MessageTextItem? {
val bodyToUse = messageContent.formattedBody
?.let {
htmlRenderer.render(it)
}
?: messageContent.body
val bodyToUse = messageContent.formattedBody?.let {
htmlRenderer.render(it)
} ?: messageContent.body
val linkifiedBody = linkifyBody(bodyToUse, callback)
val textColor = if (sendState.isSent()) {
R.color.dark_grey
} else {
R.color.brown_grey
}
val formattedBody = span(bodyToUse) {
this.textColor = colorProvider.getColor(textColor)
}
val linkifiedBody = linkifyBody(formattedBody, callback)
return MessageTextItem_()
.message(linkifiedBody)
.informationData(informationData)

View File

@ -25,15 +25,20 @@ import android.widget.TextView
import im.vector.matrix.android.api.Matrix
import im.vector.matrix.android.api.session.content.ContentUploadStateTracker
import im.vector.riotredesign.R
import im.vector.riotredesign.features.media.MediaContentRenderer
import java.io.File
object ContentUploadStateTrackerBinder {
private val updateListeners = mutableMapOf<String, ContentUploadStateTracker.UpdateListener>()
fun bind(eventId: String, progressLayout: ViewGroup) {
fun bind(eventId: String,
mediaData: MediaContentRenderer.Data,
progressLayout: ViewGroup) {
Matrix.getInstance().currentSession?.also { session ->
val uploadStateTracker = session.contentUploadProgressTracker()
val updateListener = ContentMediaProgressUpdater(progressLayout)
val updateListener = ContentMediaProgressUpdater(progressLayout, mediaData)
updateListeners[eventId] = updateListener
uploadStateTracker.track(eventId, updateListener)
}
@ -50,22 +55,40 @@ object ContentUploadStateTrackerBinder {
}
private class ContentMediaProgressUpdater(private val progressLayout: ViewGroup) : ContentUploadStateTracker.UpdateListener {
private class ContentMediaProgressUpdater(private val progressLayout: ViewGroup,
private val mediaData: MediaContentRenderer.Data) : ContentUploadStateTracker.UpdateListener {
override fun onUpdate(state: ContentUploadStateTracker.State) {
when (state) {
is ContentUploadStateTracker.State.Idle,
is ContentUploadStateTracker.State.Failure,
is ContentUploadStateTracker.State.Success -> hideProgress()
is ContentUploadStateTracker.State.ProgressData -> showProgress(state)
is ContentUploadStateTracker.State.Idle -> handleIdle(state)
is ContentUploadStateTracker.State.Failure -> handleFailure(state)
is ContentUploadStateTracker.State.Success -> handleSuccess(state)
is ContentUploadStateTracker.State.ProgressData -> handleProgress(state)
}
}
private fun hideProgress() {
progressLayout.visibility = View.GONE
private fun handleIdle(state: ContentUploadStateTracker.State.Idle) {
if (mediaData.isLocalFile()) {
val file = File(mediaData.url)
progressLayout.visibility = View.VISIBLE
val progressBar = progressLayout.findViewById<ProgressBar>(R.id.mediaProgressBar)
val progressTextView = progressLayout.findViewById<TextView>(R.id.mediaProgressTextView)
progressBar?.progress = 0
progressTextView?.text = formatStats(progressLayout.context, 0L, file.length())
} else {
progressLayout.visibility = View.GONE
}
}
private fun showProgress(state: ContentUploadStateTracker.State.ProgressData) {
private fun handleFailure(state: ContentUploadStateTracker.State.Failure) {
}
private fun handleSuccess(state: ContentUploadStateTracker.State.Success) {
}
private fun handleProgress(state: ContentUploadStateTracker.State.ProgressData) {
progressLayout.visibility = View.VISIBLE
val percent = 100L * (state.current.toFloat() / state.total.toFloat())
val progressBar = progressLayout.findViewById<ProgressBar>(R.id.mediaProgressBar)

View File

@ -37,8 +37,10 @@ abstract class MessageImageItem : AbsMessageItem<MessageImageItem.Holder>() {
override fun bind(holder: Holder) {
super.bind(holder)
MediaContentRenderer.render(mediaData, MediaContentRenderer.Mode.THUMBNAIL, holder.imageView)
ContentUploadStateTrackerBinder.bind(eventId, holder.progressLayout)
ContentUploadStateTrackerBinder.bind(eventId, mediaData, holder.progressLayout)
holder.imageView.setOnClickListener(clickListener)
holder.imageView.isEnabled = !mediaData.isLocalFile()
holder.imageView.alpha = if (mediaData.isLocalFile()) 0.5f else 1f
}
override fun unbind(holder: Holder) {

View File

@ -69,11 +69,15 @@
layout="@layout/media_upload_download_progress_layout"
android:layout_width="0dp"
android:layout_height="46dp"
android:layout_marginStart="64dp"
android:layout_marginLeft="64dp"
android:layout_marginTop="8dp"
android:layout_marginEnd="32dp"
android:layout_marginRight="32dp"
android:layout_marginBottom="8dp"
android:visibility="gone"
app:layout_constraintEnd_toEndOf="@+id/messageImageView"
app:layout_constraintStart_toStartOf="@+id/messageImageView"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/messageImageView"
tools:visibility="visible" />

View File

@ -114,7 +114,8 @@
<item name="vctr_tabbar_background">@drawable/vector_tabbar_background_light</item>
<item name="vctr_pill_background_user_id">@drawable/pill_background_user_id_light</item>
<item name="vctr_pill_background_room_alias">@drawable/pill_background_room_alias_light</item>
<item name="vctr_pill_background_room_alias">@drawable/pill_background_room_alias_light
</item>
<item name="vctr_pill_text_color_user_id">@color/riot_primary_text_color_light</item>
<item name="vctr_pill_text_color_room_alias">@android:color/white</item>
@ -261,6 +262,11 @@
<item name="actionBarTabStyle">@style/Vector.TabView.Group</item>
</style>
<style name="AppTheme.AppBarOverlay" parent="ThemeOverlay.AppCompat">
<item name="titleTextColor">?attr/actionMenuTextColor</item>
<item name="android:background">?attr/colorPrimary</item>
</style>
<style name="AppTheme.Dialog.Light" parent="Theme.AppCompat.Light.Dialog.Alert" />
</resources>