mirror of
https://github.com/SchildiChat/SchildiChat-android.git
synced 2025-02-09 00:29:00 +01:00
Timeline : handle file/audio message
This commit is contained in:
parent
9c9c09db2b
commit
657f4d3e9c
@ -32,6 +32,7 @@ import com.bumptech.glide.util.Util
|
|||||||
import com.google.android.material.snackbar.Snackbar
|
import com.google.android.material.snackbar.Snackbar
|
||||||
import im.vector.riotredesign.BuildConfig
|
import im.vector.riotredesign.BuildConfig
|
||||||
import im.vector.riotredesign.R
|
import im.vector.riotredesign.R
|
||||||
|
import im.vector.riotredesign.core.utils.toast
|
||||||
import im.vector.riotredesign.features.rageshake.BugReportActivity
|
import im.vector.riotredesign.features.rageshake.BugReportActivity
|
||||||
import im.vector.riotredesign.features.rageshake.BugReporter
|
import im.vector.riotredesign.features.rageshake.BugReporter
|
||||||
import im.vector.riotredesign.features.rageshake.RageShake
|
import im.vector.riotredesign.features.rageshake.RageShake
|
||||||
@ -284,9 +285,9 @@ abstract class VectorBaseActivity : BaseMvRxActivity() {
|
|||||||
* PUBLIC METHODS
|
* PUBLIC METHODS
|
||||||
* ========================================================================================== */
|
* ========================================================================================== */
|
||||||
|
|
||||||
protected fun showSnackbar(message: String) {
|
fun showSnackbar(message: String) {
|
||||||
coordinatorLayout?.let {
|
coordinatorLayout?.let {
|
||||||
Snackbar.make(it, message, Snackbar.LENGTH_SHORT)
|
Snackbar.make(it, message, Snackbar.LENGTH_SHORT).show()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -294,8 +295,8 @@ abstract class VectorBaseActivity : BaseMvRxActivity() {
|
|||||||
* Temporary method
|
* Temporary method
|
||||||
* ========================================================================================== */
|
* ========================================================================================== */
|
||||||
|
|
||||||
protected fun notImplemented() {
|
fun notImplemented() {
|
||||||
showSnackbar(getString(R.string.not_implemented))
|
toast(getString(R.string.not_implemented))
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
@ -37,6 +37,8 @@ import com.otaliastudios.autocomplete.Autocomplete
|
|||||||
import com.otaliastudios.autocomplete.AutocompleteCallback
|
import com.otaliastudios.autocomplete.AutocompleteCallback
|
||||||
import com.otaliastudios.autocomplete.CharPolicy
|
import com.otaliastudios.autocomplete.CharPolicy
|
||||||
import im.vector.matrix.android.api.session.Session
|
import im.vector.matrix.android.api.session.Session
|
||||||
|
import im.vector.matrix.android.api.session.room.model.message.MessageAudioContent
|
||||||
|
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.MessageImageContent
|
||||||
import im.vector.matrix.android.api.session.room.model.message.MessageVideoContent
|
import im.vector.matrix.android.api.session.room.model.message.MessageVideoContent
|
||||||
import im.vector.matrix.android.api.session.room.timeline.TimelineEvent
|
import im.vector.matrix.android.api.session.room.timeline.TimelineEvent
|
||||||
@ -387,9 +389,16 @@ class RoomDetailFragment : VectorBaseFragment(), TimelineEventController.Callbac
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun onVideoMessageClicked(messageVideoContent: MessageVideoContent, mediaData: ImageContentRenderer.Data, view: View) {
|
override fun onVideoMessageClicked(messageVideoContent: MessageVideoContent, mediaData: ImageContentRenderer.Data, view: View) {
|
||||||
//TODO handle
|
vectorBaseActivity.notImplemented()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun onFileMessageClicked(messageFileContent: MessageFileContent) {
|
||||||
|
vectorBaseActivity.notImplemented()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onAudioMessageClicked(messageAudioContent: MessageAudioContent) {
|
||||||
|
vectorBaseActivity.notImplemented()
|
||||||
|
}
|
||||||
|
|
||||||
// AutocompleteUserPresenter.Callback
|
// AutocompleteUserPresenter.Callback
|
||||||
|
|
||||||
|
@ -25,6 +25,8 @@ import androidx.recyclerview.widget.RecyclerView
|
|||||||
import com.airbnb.epoxy.EpoxyController
|
import com.airbnb.epoxy.EpoxyController
|
||||||
import com.airbnb.epoxy.EpoxyModel
|
import com.airbnb.epoxy.EpoxyModel
|
||||||
import com.airbnb.epoxy.VisibilityState
|
import com.airbnb.epoxy.VisibilityState
|
||||||
|
import im.vector.matrix.android.api.session.room.model.message.MessageAudioContent
|
||||||
|
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.MessageImageContent
|
||||||
import im.vector.matrix.android.api.session.room.model.message.MessageVideoContent
|
import im.vector.matrix.android.api.session.room.model.message.MessageVideoContent
|
||||||
import im.vector.matrix.android.api.session.room.timeline.Timeline
|
import im.vector.matrix.android.api.session.room.timeline.Timeline
|
||||||
@ -52,6 +54,8 @@ class TimelineEventController(private val dateFormatter: TimelineDateFormatter,
|
|||||||
fun onUrlClicked(url: String)
|
fun onUrlClicked(url: String)
|
||||||
fun onImageMessageClicked(messageImageContent: MessageImageContent, mediaData: ImageContentRenderer.Data, view: View)
|
fun onImageMessageClicked(messageImageContent: MessageImageContent, mediaData: ImageContentRenderer.Data, view: View)
|
||||||
fun onVideoMessageClicked(messageVideoContent: MessageVideoContent, mediaData: ImageContentRenderer.Data, view: View)
|
fun onVideoMessageClicked(messageVideoContent: MessageVideoContent, mediaData: ImageContentRenderer.Data, view: View)
|
||||||
|
fun onFileMessageClicked(messageFileContent: MessageFileContent)
|
||||||
|
fun onAudioMessageClicked(messageAudioContent: MessageAudioContent)
|
||||||
}
|
}
|
||||||
|
|
||||||
private val modelCache = arrayListOf<List<EpoxyModel<*>>>()
|
private val modelCache = arrayListOf<List<EpoxyModel<*>>>()
|
||||||
|
@ -23,8 +23,10 @@ import im.vector.matrix.android.api.permalinks.MatrixLinkify
|
|||||||
import im.vector.matrix.android.api.permalinks.MatrixPermalinkSpan
|
import im.vector.matrix.android.api.permalinks.MatrixPermalinkSpan
|
||||||
import im.vector.matrix.android.api.session.events.model.EventType
|
import im.vector.matrix.android.api.session.events.model.EventType
|
||||||
import im.vector.matrix.android.api.session.events.model.toModel
|
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.MessageContent
|
||||||
import im.vector.matrix.android.api.session.room.model.message.MessageEmoteContent
|
import im.vector.matrix.android.api.session.room.model.message.MessageEmoteContent
|
||||||
|
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.MessageImageContent
|
||||||
import im.vector.matrix.android.api.session.room.model.message.MessageNoticeContent
|
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.model.message.MessageTextContent
|
||||||
@ -40,6 +42,8 @@ import im.vector.riotredesign.features.home.room.detail.timeline.helper.Timeline
|
|||||||
import im.vector.riotredesign.features.home.room.detail.timeline.helper.TimelineMediaSizeProvider
|
import im.vector.riotredesign.features.home.room.detail.timeline.helper.TimelineMediaSizeProvider
|
||||||
import im.vector.riotredesign.features.home.room.detail.timeline.item.DefaultItem
|
import im.vector.riotredesign.features.home.room.detail.timeline.item.DefaultItem
|
||||||
import im.vector.riotredesign.features.home.room.detail.timeline.item.DefaultItem_
|
import im.vector.riotredesign.features.home.room.detail.timeline.item.DefaultItem_
|
||||||
|
import im.vector.riotredesign.features.home.room.detail.timeline.item.MessageFileItem
|
||||||
|
import im.vector.riotredesign.features.home.room.detail.timeline.item.MessageFileItem_
|
||||||
import im.vector.riotredesign.features.home.room.detail.timeline.item.MessageImageVideoItem
|
import im.vector.riotredesign.features.home.room.detail.timeline.item.MessageImageVideoItem
|
||||||
import im.vector.riotredesign.features.home.room.detail.timeline.item.MessageImageVideoItem_
|
import im.vector.riotredesign.features.home.room.detail.timeline.item.MessageImageVideoItem_
|
||||||
import im.vector.riotredesign.features.home.room.detail.timeline.item.MessageInformationData
|
import im.vector.riotredesign.features.home.room.detail.timeline.item.MessageInformationData
|
||||||
@ -95,10 +99,32 @@ class MessageItemFactory(private val colorProvider: ColorProvider,
|
|||||||
is MessageImageContent -> buildImageMessageItem(messageContent, informationData, callback)
|
is MessageImageContent -> buildImageMessageItem(messageContent, informationData, callback)
|
||||||
is MessageNoticeContent -> buildNoticeMessageItem(messageContent, informationData, callback)
|
is MessageNoticeContent -> buildNoticeMessageItem(messageContent, informationData, callback)
|
||||||
is MessageVideoContent -> buildVideoMessageItem(messageContent, informationData, callback)
|
is MessageVideoContent -> buildVideoMessageItem(messageContent, informationData, callback)
|
||||||
|
is MessageFileContent -> buildFileMessageItem(messageContent, informationData, callback)
|
||||||
|
is MessageAudioContent -> buildAudioMessageItem(messageContent, informationData, callback)
|
||||||
else -> buildNotHandledMessageItem(messageContent)
|
else -> buildNotHandledMessageItem(messageContent)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun buildAudioMessageItem(messageContent: MessageAudioContent,
|
||||||
|
informationData: MessageInformationData,
|
||||||
|
callback: TimelineEventController.Callback?): MessageFileItem? {
|
||||||
|
return MessageFileItem_()
|
||||||
|
.informationData(informationData)
|
||||||
|
.filename(messageContent.body)
|
||||||
|
.iconRes(R.drawable.filetype_audio)
|
||||||
|
.clickListener { _ -> callback?.onAudioMessageClicked(messageContent) }
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun buildFileMessageItem(messageContent: MessageFileContent,
|
||||||
|
informationData: MessageInformationData,
|
||||||
|
callback: TimelineEventController.Callback?): MessageFileItem? {
|
||||||
|
return MessageFileItem_()
|
||||||
|
.informationData(informationData)
|
||||||
|
.filename(messageContent.body)
|
||||||
|
.iconRes(R.drawable.filetype_attachment)
|
||||||
|
.clickListener { _ -> callback?.onFileMessageClicked(messageContent) }
|
||||||
|
}
|
||||||
|
|
||||||
private fun buildNotHandledMessageItem(messageContent: MessageContent): DefaultItem? {
|
private fun buildNotHandledMessageItem(messageContent: MessageContent): DefaultItem? {
|
||||||
val text = "${messageContent.type} message events are not yet handled"
|
val text = "${messageContent.type} message events are not yet handled"
|
||||||
return DefaultItem_().text(text)
|
return DefaultItem_().text(text)
|
||||||
|
@ -0,0 +1,57 @@
|
|||||||
|
/*
|
||||||
|
* 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.home.room.detail.timeline.item
|
||||||
|
|
||||||
|
import android.graphics.Paint
|
||||||
|
import android.view.View
|
||||||
|
import android.view.ViewGroup
|
||||||
|
import android.widget.ImageView
|
||||||
|
import android.widget.TextView
|
||||||
|
import androidx.annotation.DrawableRes
|
||||||
|
import com.airbnb.epoxy.EpoxyAttribute
|
||||||
|
import com.airbnb.epoxy.EpoxyModelClass
|
||||||
|
import im.vector.riotredesign.R
|
||||||
|
|
||||||
|
@EpoxyModelClass(layout = R.layout.item_timeline_event_file_message)
|
||||||
|
abstract class MessageFileItem : AbsMessageItem<MessageFileItem.Holder>() {
|
||||||
|
|
||||||
|
@EpoxyAttribute var filename: CharSequence = ""
|
||||||
|
@EpoxyAttribute @DrawableRes var iconRes: Int = 0
|
||||||
|
@EpoxyAttribute override lateinit var informationData: MessageInformationData
|
||||||
|
@EpoxyAttribute var clickListener: View.OnClickListener? = null
|
||||||
|
|
||||||
|
override fun bind(holder: Holder) {
|
||||||
|
super.bind(holder)
|
||||||
|
holder.fileLayout.renderSendState()
|
||||||
|
holder.filenameView.text = filename
|
||||||
|
holder.fileImageView.setImageResource(iconRes)
|
||||||
|
holder.filenameView.setOnClickListener(clickListener)
|
||||||
|
holder.filenameView.paintFlags = (holder.filenameView.paintFlags or Paint.UNDERLINE_TEXT_FLAG)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
class Holder : AbsMessageItem.Holder() {
|
||||||
|
override val avatarImageView by bind<ImageView>(R.id.messageAvatarImageView)
|
||||||
|
override val memberNameView by bind<TextView>(R.id.messageMemberNameView)
|
||||||
|
override val timeView by bind<TextView>(R.id.messageTimeView)
|
||||||
|
val fileLayout by bind<ViewGroup>(R.id.messageFileLayout)
|
||||||
|
val fileImageView by bind<ImageView>(R.id.messageFileImageView)
|
||||||
|
val filenameView by bind<TextView>(R.id.messageFilenameView)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
135
vector/src/main/res/layout/item_timeline_event_file_message.xml
Normal file
135
vector/src/main/res/layout/item_timeline_event_file_message.xml
Normal file
@ -0,0 +1,135 @@
|
|||||||
|
<?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.
|
||||||
|
-->
|
||||||
|
|
||||||
|
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:paddingLeft="16dp"
|
||||||
|
android:paddingRight="16dp">
|
||||||
|
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:id="@+id/messageAvatarImageView"
|
||||||
|
android:layout_width="@dimen/chat_avatar_size"
|
||||||
|
android:layout_height="@dimen/chat_avatar_size"
|
||||||
|
android:layout_marginTop="8dp"
|
||||||
|
android:layout_marginBottom="8dp"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintTop_toTopOf="parent"
|
||||||
|
tools:src="@tools:sample/avatars" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/messageMemberNameView"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginStart="64dp"
|
||||||
|
android:layout_marginLeft="64dp"
|
||||||
|
android:layout_marginTop="8dp"
|
||||||
|
android:layout_marginEnd="8dp"
|
||||||
|
android:layout_marginRight="8dp"
|
||||||
|
android:ellipsize="end"
|
||||||
|
android:maxLines="1"
|
||||||
|
android:textSize="15sp"
|
||||||
|
app:layout_constraintEnd_toStartOf="@+id/messageTimeView"
|
||||||
|
app:layout_constraintHorizontal_bias="0.0"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintTop_toTopOf="parent"
|
||||||
|
tools:text="@tools:sample/full_names" />
|
||||||
|
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/messageTimeView"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginStart="8dp"
|
||||||
|
android:layout_marginLeft="8dp"
|
||||||
|
android:duplicateParentState="true"
|
||||||
|
android:textColor="@color/brown_grey"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintHorizontal_bias="0.0"
|
||||||
|
app:layout_constraintTop_toTopOf="@id/messageMemberNameView"
|
||||||
|
tools:text="@tools:sample/date/hhmm" />
|
||||||
|
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:id="@+id/messageFileLayout"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
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:duplicateParentState="true"
|
||||||
|
android:orientation="horizontal"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintHorizontal_bias="0"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintTop_toBottomOf="@+id/messageMemberNameView">
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:id="@+id/messageFilee2eIcon"
|
||||||
|
android:layout_width="14dp"
|
||||||
|
android:layout_height="14dp"
|
||||||
|
android:src="@drawable/e2e_verified"
|
||||||
|
android:visibility="gone" />
|
||||||
|
|
||||||
|
<!-- the media type -->
|
||||||
|
<ImageView
|
||||||
|
android:id="@+id/messageFileImageView"
|
||||||
|
android:layout_width="@dimen/chat_avatar_size"
|
||||||
|
android:layout_height="@dimen/chat_avatar_size"
|
||||||
|
android:layout_marginStart="4dp"
|
||||||
|
android:layout_marginLeft="4dp"
|
||||||
|
android:src="@drawable/filetype_image" />
|
||||||
|
|
||||||
|
<!-- the media -->
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/messageFilenameView"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="@dimen/chat_avatar_size"
|
||||||
|
android:layout_marginStart="4dp"
|
||||||
|
android:layout_marginLeft="4dp"
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:autoLink="none"
|
||||||
|
android:gravity="center_vertical"
|
||||||
|
tools:text="A filename here" />
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
|
||||||
|
<include
|
||||||
|
android:id="@+id/messageMediaUploadProgressLayout"
|
||||||
|
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="parent"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintTop_toBottomOf="@+id/messageFileLayout"
|
||||||
|
tools:visibility="visible" />
|
||||||
|
|
||||||
|
|
||||||
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
Loading…
x
Reference in New Issue
Block a user