diff --git a/vector/src/main/java/im/vector/riotredesign/core/platform/VectorBaseActivity.kt b/vector/src/main/java/im/vector/riotredesign/core/platform/VectorBaseActivity.kt index 388d3425..20a2c091 100644 --- a/vector/src/main/java/im/vector/riotredesign/core/platform/VectorBaseActivity.kt +++ b/vector/src/main/java/im/vector/riotredesign/core/platform/VectorBaseActivity.kt @@ -32,6 +32,7 @@ import com.bumptech.glide.util.Util import com.google.android.material.snackbar.Snackbar import im.vector.riotredesign.BuildConfig 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.BugReporter import im.vector.riotredesign.features.rageshake.RageShake @@ -284,9 +285,9 @@ abstract class VectorBaseActivity : BaseMvRxActivity() { * PUBLIC METHODS * ========================================================================================== */ - protected fun showSnackbar(message: String) { + fun showSnackbar(message: String) { 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 * ========================================================================================== */ - protected fun notImplemented() { - showSnackbar(getString(R.string.not_implemented)) + fun notImplemented() { + toast(getString(R.string.not_implemented)) } } \ No newline at end of file diff --git a/vector/src/main/java/im/vector/riotredesign/features/home/room/detail/RoomDetailFragment.kt b/vector/src/main/java/im/vector/riotredesign/features/home/room/detail/RoomDetailFragment.kt index d3319b74..8a8ef50e 100644 --- a/vector/src/main/java/im/vector/riotredesign/features/home/room/detail/RoomDetailFragment.kt +++ b/vector/src/main/java/im/vector/riotredesign/features/home/room/detail/RoomDetailFragment.kt @@ -37,6 +37,8 @@ import com.otaliastudios.autocomplete.Autocomplete import com.otaliastudios.autocomplete.AutocompleteCallback import com.otaliastudios.autocomplete.CharPolicy 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.MessageVideoContent import im.vector.matrix.android.api.session.room.timeline.TimelineEvent @@ -371,7 +373,7 @@ class RoomDetailFragment : VectorBaseFragment(), TimelineEventController.Callbac .show() } -// TimelineEventController.Callback ************************************************************ + // TimelineEventController.Callback ************************************************************ override fun onUrlClicked(url: String) { homePermalinkHandler.launch(url) @@ -387,11 +389,18 @@ class RoomDetailFragment : VectorBaseFragment(), TimelineEventController.Callbac } override fun onVideoMessageClicked(messageVideoContent: MessageVideoContent, mediaData: ImageContentRenderer.Data, view: View) { - //TODO handle + vectorBaseActivity.notImplemented() } + override fun onFileMessageClicked(messageFileContent: MessageFileContent) { + vectorBaseActivity.notImplemented() + } -// AutocompleteUserPresenter.Callback + override fun onAudioMessageClicked(messageAudioContent: MessageAudioContent) { + vectorBaseActivity.notImplemented() + } + + // AutocompleteUserPresenter.Callback override fun onQueryUsers(query: CharSequence?) { textComposerViewModel.process(TextComposerActions.QueryUsers(query)) diff --git a/vector/src/main/java/im/vector/riotredesign/features/home/room/detail/timeline/TimelineEventController.kt b/vector/src/main/java/im/vector/riotredesign/features/home/room/detail/timeline/TimelineEventController.kt index b96ba1dd..67654861 100644 --- a/vector/src/main/java/im/vector/riotredesign/features/home/room/detail/timeline/TimelineEventController.kt +++ b/vector/src/main/java/im/vector/riotredesign/features/home/room/detail/timeline/TimelineEventController.kt @@ -25,6 +25,8 @@ import androidx.recyclerview.widget.RecyclerView import com.airbnb.epoxy.EpoxyController import com.airbnb.epoxy.EpoxyModel 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.MessageVideoContent 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 onImageMessageClicked(messageImageContent: MessageImageContent, 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>>() diff --git a/vector/src/main/java/im/vector/riotredesign/features/home/room/detail/timeline/factory/MessageItemFactory.kt b/vector/src/main/java/im/vector/riotredesign/features/home/room/detail/timeline/factory/MessageItemFactory.kt index 884e8c34..28bf49da 100644 --- a/vector/src/main/java/im/vector/riotredesign/features/home/room/detail/timeline/factory/MessageItemFactory.kt +++ b/vector/src/main/java/im/vector/riotredesign/features/home/room/detail/timeline/factory/MessageItemFactory.kt @@ -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.session.events.model.EventType 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.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.MessageNoticeContent 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.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.MessageInformationData @@ -95,10 +99,32 @@ class MessageItemFactory(private val colorProvider: ColorProvider, is MessageImageContent -> buildImageMessageItem(messageContent, informationData, callback) is MessageNoticeContent -> buildNoticeMessageItem(messageContent, informationData, callback) is MessageVideoContent -> buildVideoMessageItem(messageContent, informationData, callback) + is MessageFileContent -> buildFileMessageItem(messageContent, informationData, callback) + is MessageAudioContent -> buildAudioMessageItem(messageContent, informationData, callback) 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? { val text = "${messageContent.type} message events are not yet handled" return DefaultItem_().text(text) diff --git a/vector/src/main/java/im/vector/riotredesign/features/home/room/detail/timeline/item/MessageFileItem.kt b/vector/src/main/java/im/vector/riotredesign/features/home/room/detail/timeline/item/MessageFileItem.kt new file mode 100644 index 00000000..edd3c779 --- /dev/null +++ b/vector/src/main/java/im/vector/riotredesign/features/home/room/detail/timeline/item/MessageFileItem.kt @@ -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() { + + @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(R.id.messageAvatarImageView) + override val memberNameView by bind(R.id.messageMemberNameView) + override val timeView by bind(R.id.messageTimeView) + val fileLayout by bind(R.id.messageFileLayout) + val fileImageView by bind(R.id.messageFileImageView) + val filenameView by bind(R.id.messageFilenameView) + } + + +} \ No newline at end of file diff --git a/vector/src/main/res/layout/item_timeline_event_file_message.xml b/vector/src/main/res/layout/item_timeline_event_file_message.xml new file mode 100644 index 00000000..83bc4815 --- /dev/null +++ b/vector/src/main/res/layout/item_timeline_event_file_message.xml @@ -0,0 +1,135 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file