forked from GitHub-Mirror/riotX-android
Media upload: handle local echo by pinning at the bottom... will probably be changed
This commit is contained in:
@ -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()
|
||||
|
@ -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()
|
||||
}
|
||||
|
||||
}
|
@ -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)
|
||||
|
@ -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)
|
||||
|
@ -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) {
|
||||
|
@ -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" />
|
||||
|
||||
|
@ -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>
|
||||
|
Reference in New Issue
Block a user