mirror of
https://github.com/element-hq/element-android
synced 2024-11-27 20:06:51 +03:00
Merge pull request #134 from vector-im/feature/refactor_timeline_layouts
Refactoring / Use view ViewStub to avoid layout xml duplication
This commit is contained in:
commit
8929898397
23 changed files with 492 additions and 388 deletions
|
@ -20,6 +20,7 @@ import android.content.Context
|
||||||
import android.graphics.drawable.Drawable
|
import android.graphics.drawable.Drawable
|
||||||
import android.widget.ImageView
|
import android.widget.ImageView
|
||||||
import androidx.annotation.AnyThread
|
import androidx.annotation.AnyThread
|
||||||
|
import androidx.annotation.ColorRes
|
||||||
import androidx.annotation.UiThread
|
import androidx.annotation.UiThread
|
||||||
import androidx.core.content.ContextCompat
|
import androidx.core.content.ContextCompat
|
||||||
import com.amulyakhare.textdrawable.TextDrawable
|
import com.amulyakhare.textdrawable.TextDrawable
|
||||||
|
@ -77,31 +78,35 @@ object AvatarRenderer {
|
||||||
|
|
||||||
@AnyThread
|
@AnyThread
|
||||||
fun getPlaceholderDrawable(context: Context, identifier: String, text: String): Drawable {
|
fun getPlaceholderDrawable(context: Context, identifier: String, text: String): Drawable {
|
||||||
val avatarColor = ContextCompat.getColor(context, getAvatarColor(identifier))
|
val avatarColor = ContextCompat.getColor(context, getColorFromUserId(identifier))
|
||||||
return if (text.isEmpty()) {
|
return if (text.isEmpty()) {
|
||||||
TextDrawable.builder().buildRound("", avatarColor)
|
TextDrawable.builder().buildRound("", avatarColor)
|
||||||
} else {
|
} else {
|
||||||
val isUserId = MatrixPatterns.isUserId(text)
|
val isUserId = MatrixPatterns.isUserId(text)
|
||||||
val firstLetterIndex = if (isUserId) 1 else 0
|
val firstLetterIndex = if (isUserId) 1 else 0
|
||||||
val firstLetter = text[firstLetterIndex].toString().toUpperCase()
|
val firstLetter = text[firstLetterIndex].toString().toUpperCase()
|
||||||
TextDrawable.builder().buildRound(firstLetter, avatarColor)
|
TextDrawable.builder()
|
||||||
|
.beginConfig()
|
||||||
|
.bold()
|
||||||
|
.endConfig()
|
||||||
|
.buildRound(firstLetter, avatarColor)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// PRIVATE API *********************************************************************************
|
// PRIVATE API *********************************************************************************
|
||||||
|
|
||||||
|
|
||||||
private fun getAvatarColor(text: String? = null): Int {
|
// private fun getAvatarColor(text: String? = null): Int {
|
||||||
var colorIndex: Long = 0
|
// var colorIndex: Long = 0
|
||||||
if (!text.isNullOrEmpty()) {
|
// if (!text.isNullOrEmpty()) {
|
||||||
var sum: Long = 0
|
// var sum: Long = 0
|
||||||
for (i in 0 until text.length) {
|
// for (i in 0 until text.length) {
|
||||||
sum += text[i].toLong()
|
// sum += text[i].toLong()
|
||||||
}
|
// }
|
||||||
colorIndex = sum % AVATAR_COLOR_LIST.size
|
// colorIndex = sum % AVATAR_COLOR_LIST.size
|
||||||
}
|
// }
|
||||||
return AVATAR_COLOR_LIST[colorIndex.toInt()]
|
// return AVATAR_COLOR_LIST[colorIndex.toInt()]
|
||||||
}
|
// }
|
||||||
|
|
||||||
private fun buildGlideRequest(glideRequest: GlideRequests, avatarUrl: String?): GlideRequest<Drawable> {
|
private fun buildGlideRequest(glideRequest: GlideRequests, avatarUrl: String?): GlideRequest<Drawable> {
|
||||||
val resolvedUrl = Matrix.getInstance().currentSession!!.contentUrlResolver()
|
val resolvedUrl = Matrix.getInstance().currentSession!!.contentUrlResolver()
|
||||||
|
@ -112,4 +117,32 @@ object AvatarRenderer {
|
||||||
.apply(RequestOptions.circleCropTransform())
|
.apply(RequestOptions.circleCropTransform())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//Based on riot-web implementation
|
||||||
|
@ColorRes
|
||||||
|
fun getColorFromUserId(sender: String): Int {
|
||||||
|
var hash = 0
|
||||||
|
var i = 0
|
||||||
|
var chr: Char
|
||||||
|
if (sender.isEmpty()) {
|
||||||
|
return R.color.username_1
|
||||||
|
}
|
||||||
|
while (i < sender.length) {
|
||||||
|
chr = sender[i]
|
||||||
|
hash = (hash shl 5) - hash + chr.toInt()
|
||||||
|
hash = hash or 0
|
||||||
|
i++
|
||||||
|
}
|
||||||
|
val cI = Math.abs(hash) % 8 + 1
|
||||||
|
return when (cI) {
|
||||||
|
1 -> R.color.username_1
|
||||||
|
2 -> R.color.username_2
|
||||||
|
3 -> R.color.username_3
|
||||||
|
4 -> R.color.username_4
|
||||||
|
5 -> R.color.username_5
|
||||||
|
6 -> R.color.username_6
|
||||||
|
7 -> R.color.username_7
|
||||||
|
else -> R.color.username_8
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -32,6 +32,7 @@ import im.vector.riotredesign.core.extensions.localDateTime
|
||||||
import im.vector.riotredesign.core.linkify.VectorLinkify
|
import im.vector.riotredesign.core.linkify.VectorLinkify
|
||||||
import im.vector.riotredesign.core.resources.ColorProvider
|
import im.vector.riotredesign.core.resources.ColorProvider
|
||||||
import im.vector.riotredesign.core.utils.DebouncedClickListener
|
import im.vector.riotredesign.core.utils.DebouncedClickListener
|
||||||
|
import im.vector.riotredesign.features.home.AvatarRenderer
|
||||||
import im.vector.riotredesign.features.home.room.detail.timeline.TimelineEventController
|
import im.vector.riotredesign.features.home.room.detail.timeline.TimelineEventController
|
||||||
import im.vector.riotredesign.features.home.room.detail.timeline.helper.TimelineDateFormatter
|
import im.vector.riotredesign.features.home.room.detail.timeline.helper.TimelineDateFormatter
|
||||||
import im.vector.riotredesign.features.home.room.detail.timeline.helper.TimelineMediaSizeProvider
|
import im.vector.riotredesign.features.home.room.detail.timeline.helper.TimelineMediaSizeProvider
|
||||||
|
@ -70,7 +71,7 @@ class MessageItemFactory(private val colorProvider: ColorProvider,
|
||||||
val avatarUrl = event.senderAvatar
|
val avatarUrl = event.senderAvatar
|
||||||
val memberName = event.senderName ?: event.root.sender ?: ""
|
val memberName = event.senderName ?: event.root.sender ?: ""
|
||||||
val formattedMemberName = span(memberName) {
|
val formattedMemberName = span(memberName) {
|
||||||
textColor = colorProvider.getColor(getColorFor(event.root.sender ?: ""))
|
textColor = colorProvider.getColor(AvatarRenderer.getColorFromUserId(event.root.sender ?: ""))
|
||||||
}
|
}
|
||||||
val informationData = MessageInformationData(eventId = eventId,
|
val informationData = MessageInformationData(eventId = eventId,
|
||||||
senderId = event.root.sender ?: "",
|
senderId = event.root.sender ?: "",
|
||||||
|
|
|
@ -19,13 +19,12 @@ package im.vector.riotredesign.features.home.room.detail.timeline.item
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.widget.ImageView
|
import android.widget.ImageView
|
||||||
import android.widget.TextView
|
import android.widget.TextView
|
||||||
|
import im.vector.riotredesign.R
|
||||||
import com.airbnb.epoxy.EpoxyAttribute
|
import com.airbnb.epoxy.EpoxyAttribute
|
||||||
import com.jakewharton.rxbinding2.view.RxView
|
|
||||||
import im.vector.riotredesign.core.epoxy.VectorEpoxyHolder
|
|
||||||
import im.vector.riotredesign.core.epoxy.VectorEpoxyModel
|
|
||||||
import im.vector.riotredesign.features.home.AvatarRenderer
|
import im.vector.riotredesign.features.home.AvatarRenderer
|
||||||
|
|
||||||
abstract class AbsMessageItem<H : AbsMessageItem.Holder> : VectorEpoxyModel<H>() {
|
|
||||||
|
abstract class AbsMessageItem<H : AbsMessageItem.Holder> : BaseEventItem<H>() {
|
||||||
|
|
||||||
abstract val informationData: MessageInformationData
|
abstract val informationData: MessageInformationData
|
||||||
|
|
||||||
|
@ -41,6 +40,13 @@ abstract class AbsMessageItem<H : AbsMessageItem.Holder> : VectorEpoxyModel<H>()
|
||||||
override fun bind(holder: H) {
|
override fun bind(holder: H) {
|
||||||
super.bind(holder)
|
super.bind(holder)
|
||||||
if (informationData.showInformation) {
|
if (informationData.showInformation) {
|
||||||
|
|
||||||
|
holder.avatarImageView.layoutParams = holder.avatarImageView.layoutParams?.apply {
|
||||||
|
val size = dpToPx(avatarStyle.avatarSizeDP, holder.view.context)
|
||||||
|
height = size
|
||||||
|
width = size
|
||||||
|
}
|
||||||
|
|
||||||
holder.avatarImageView.visibility = View.VISIBLE
|
holder.avatarImageView.visibility = View.VISIBLE
|
||||||
holder.avatarImageView.setOnClickListener(avatarClickListener)
|
holder.avatarImageView.setOnClickListener(avatarClickListener)
|
||||||
holder.memberNameView.visibility = View.VISIBLE
|
holder.memberNameView.visibility = View.VISIBLE
|
||||||
|
@ -63,10 +69,11 @@ abstract class AbsMessageItem<H : AbsMessageItem.Holder> : VectorEpoxyModel<H>()
|
||||||
alpha = if (informationData.sendState.isSent()) 1f else 0.5f
|
alpha = if (informationData.sendState.isSent()) 1f else 0.5f
|
||||||
}
|
}
|
||||||
|
|
||||||
abstract class Holder : VectorEpoxyHolder() {
|
abstract class Holder : BaseHolder() {
|
||||||
abstract val avatarImageView: ImageView
|
|
||||||
abstract val memberNameView: TextView
|
val avatarImageView by bind<ImageView>(R.id.messageAvatarImageView)
|
||||||
abstract val timeView: TextView
|
val memberNameView by bind<TextView>(R.id.messageMemberNameView)
|
||||||
|
val timeView by bind<TextView>(R.id.messageTimeView)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
|
@ -0,0 +1,82 @@
|
||||||
|
/*
|
||||||
|
* 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.content.Context
|
||||||
|
import android.util.TypedValue
|
||||||
|
import android.view.View
|
||||||
|
import android.view.ViewStub
|
||||||
|
import androidx.annotation.IdRes
|
||||||
|
import androidx.constraintlayout.widget.Guideline
|
||||||
|
import im.vector.riotredesign.R
|
||||||
|
import im.vector.riotredesign.core.epoxy.VectorEpoxyHolder
|
||||||
|
import im.vector.riotredesign.core.epoxy.VectorEpoxyModel
|
||||||
|
|
||||||
|
abstract class BaseEventItem<H : BaseEventItem.BaseHolder> : VectorEpoxyModel<H>() {
|
||||||
|
|
||||||
|
var avatarStyle: AvatarStyle = Companion.AvatarStyle.SMALL
|
||||||
|
|
||||||
|
override fun bind(holder: H) {
|
||||||
|
super.bind(holder)
|
||||||
|
//optimize?
|
||||||
|
val px = dpToPx(avatarStyle.avatarSizeDP, holder.view.context)
|
||||||
|
holder.leftGuideline.setGuidelineBegin(px)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
override fun getViewType(): Int {
|
||||||
|
return getStubType()
|
||||||
|
}
|
||||||
|
|
||||||
|
abstract fun getStubType(): Int
|
||||||
|
|
||||||
|
|
||||||
|
abstract class BaseHolder : VectorEpoxyHolder() {
|
||||||
|
|
||||||
|
val leftGuideline by bind<Guideline>(R.id.messageStartGuideline)
|
||||||
|
|
||||||
|
@IdRes
|
||||||
|
abstract fun getStubId(): Int
|
||||||
|
|
||||||
|
override fun bindView(itemView: View) {
|
||||||
|
super.bindView(itemView)
|
||||||
|
inflateStub()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun inflateStub() {
|
||||||
|
view.findViewById<ViewStub>(getStubId()).inflate()
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
|
||||||
|
enum class AvatarStyle(val avatarSizeDP: Int) {
|
||||||
|
BIG(50),
|
||||||
|
MEDIUM(40),
|
||||||
|
SMALL(30),
|
||||||
|
NONE(0)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun dpToPx(dp: Int, context: Context): Int {
|
||||||
|
return TypedValue.applyDimension(
|
||||||
|
TypedValue.COMPLEX_UNIT_DIP,
|
||||||
|
dp.toFloat(),
|
||||||
|
context.resources.displayMetrics
|
||||||
|
).toInt()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -20,19 +20,26 @@ import android.widget.TextView
|
||||||
import com.airbnb.epoxy.EpoxyAttribute
|
import com.airbnb.epoxy.EpoxyAttribute
|
||||||
import com.airbnb.epoxy.EpoxyModelClass
|
import com.airbnb.epoxy.EpoxyModelClass
|
||||||
import im.vector.riotredesign.R
|
import im.vector.riotredesign.R
|
||||||
import im.vector.riotredesign.core.epoxy.VectorEpoxyHolder
|
|
||||||
import im.vector.riotredesign.core.epoxy.VectorEpoxyModel
|
|
||||||
|
|
||||||
@EpoxyModelClass(layout = R.layout.item_timeline_event_default)
|
@EpoxyModelClass(layout = R.layout.item_timeline_event_base_noinfo)
|
||||||
abstract class DefaultItem : VectorEpoxyModel<DefaultItem.Holder>() {
|
abstract class DefaultItem : BaseEventItem<DefaultItem.Holder>() {
|
||||||
|
|
||||||
@EpoxyAttribute var text: CharSequence? = null
|
@EpoxyAttribute
|
||||||
|
var text: CharSequence? = null
|
||||||
|
|
||||||
override fun bind(holder: Holder) {
|
override fun bind(holder: Holder) {
|
||||||
holder.messageView.text = text
|
holder.messageView.text = text
|
||||||
}
|
}
|
||||||
|
|
||||||
class Holder : VectorEpoxyHolder() {
|
override fun getStubType(): Int = STUB_ID
|
||||||
|
|
||||||
|
class Holder : BaseHolder() {
|
||||||
|
override fun getStubId(): Int = STUB_ID
|
||||||
|
|
||||||
val messageView by bind<TextView>(R.id.stateMessageView)
|
val messageView by bind<TextView>(R.id.stateMessageView)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
private val STUB_ID = R.id.messageContentDefaultStub
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -24,15 +24,14 @@ import android.widget.ImageView
|
||||||
import android.widget.TextView
|
import android.widget.TextView
|
||||||
import androidx.core.view.children
|
import androidx.core.view.children
|
||||||
import im.vector.riotredesign.R
|
import im.vector.riotredesign.R
|
||||||
import im.vector.riotredesign.core.epoxy.VectorEpoxyHolder
|
|
||||||
import im.vector.riotredesign.core.epoxy.VectorEpoxyModel
|
|
||||||
import im.vector.riotredesign.features.home.AvatarRenderer
|
import im.vector.riotredesign.features.home.AvatarRenderer
|
||||||
|
|
||||||
|
|
||||||
data class MergedHeaderItem(private val isCollapsed: Boolean,
|
data class MergedHeaderItem(private val isCollapsed: Boolean,
|
||||||
private val mergeId: String,
|
private val mergeId: String,
|
||||||
private val mergeData: List<Data>,
|
private val mergeData: List<Data>,
|
||||||
private val onCollapsedStateChanged: (Boolean) -> Unit
|
private val onCollapsedStateChanged: (Boolean) -> Unit
|
||||||
) : VectorEpoxyModel<MergedHeaderItem.Holder>() {
|
) : BaseEventItem<MergedHeaderItem.Holder>() {
|
||||||
|
|
||||||
private val distinctMergeData = mergeData.distinctBy { it.userId }
|
private val distinctMergeData = mergeData.distinctBy { it.userId }
|
||||||
|
|
||||||
|
@ -41,13 +40,15 @@ data class MergedHeaderItem(private val isCollapsed: Boolean,
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getDefaultLayout(): Int {
|
override fun getDefaultLayout(): Int {
|
||||||
return R.layout.item_timeline_event_merged_header
|
return R.layout.item_timeline_event_base_noinfo
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun createNewHolder(): Holder {
|
override fun createNewHolder(): Holder {
|
||||||
return Holder()
|
return Holder()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun getStubType(): Int = STUB_ID
|
||||||
|
|
||||||
override fun bind(holder: Holder) {
|
override fun bind(holder: Holder) {
|
||||||
super.bind(holder)
|
super.bind(holder)
|
||||||
holder.expandView.setOnClickListener {
|
holder.expandView.setOnClickListener {
|
||||||
|
@ -84,11 +85,17 @@ data class MergedHeaderItem(private val isCollapsed: Boolean,
|
||||||
val avatarUrl: String?
|
val avatarUrl: String?
|
||||||
)
|
)
|
||||||
|
|
||||||
class Holder : VectorEpoxyHolder() {
|
class Holder : BaseHolder() {
|
||||||
|
override fun getStubId(): Int = STUB_ID
|
||||||
|
|
||||||
val expandView by bind<TextView>(R.id.itemMergedExpandTextView)
|
val expandView by bind<TextView>(R.id.itemMergedExpandTextView)
|
||||||
val summaryView by bind<TextView>(R.id.itemMergedSummaryTextView)
|
val summaryView by bind<TextView>(R.id.itemMergedSummaryTextView)
|
||||||
val separatorView by bind<View>(R.id.itemMergedSeparatorView)
|
val separatorView by bind<View>(R.id.itemMergedSeparatorView)
|
||||||
val avatarListView by bind<ViewGroup>(R.id.itemMergedAvatarListView)
|
val avatarListView by bind<ViewGroup>(R.id.itemMergedAvatarListView)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
private val STUB_ID = R.id.messageContentMergedheaderStub
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -26,13 +26,18 @@ import com.airbnb.epoxy.EpoxyAttribute
|
||||||
import com.airbnb.epoxy.EpoxyModelClass
|
import com.airbnb.epoxy.EpoxyModelClass
|
||||||
import im.vector.riotredesign.R
|
import im.vector.riotredesign.R
|
||||||
|
|
||||||
@EpoxyModelClass(layout = R.layout.item_timeline_event_file_message)
|
@EpoxyModelClass(layout = R.layout.item_timeline_event_base)
|
||||||
abstract class MessageFileItem : AbsMessageItem<MessageFileItem.Holder>() {
|
abstract class MessageFileItem : AbsMessageItem<MessageFileItem.Holder>() {
|
||||||
|
|
||||||
@EpoxyAttribute var filename: CharSequence = ""
|
@EpoxyAttribute
|
||||||
@EpoxyAttribute @DrawableRes var iconRes: Int = 0
|
var filename: CharSequence = ""
|
||||||
@EpoxyAttribute override lateinit var informationData: MessageInformationData
|
@EpoxyAttribute
|
||||||
@EpoxyAttribute var clickListener: View.OnClickListener? = null
|
@DrawableRes
|
||||||
|
var iconRes: Int = 0
|
||||||
|
@EpoxyAttribute
|
||||||
|
override lateinit var informationData: MessageInformationData
|
||||||
|
@EpoxyAttribute
|
||||||
|
var clickListener: View.OnClickListener? = null
|
||||||
|
|
||||||
override fun bind(holder: Holder) {
|
override fun bind(holder: Holder) {
|
||||||
super.bind(holder)
|
super.bind(holder)
|
||||||
|
@ -43,15 +48,19 @@ abstract class MessageFileItem : AbsMessageItem<MessageFileItem.Holder>() {
|
||||||
holder.filenameView.paintFlags = (holder.filenameView.paintFlags or Paint.UNDERLINE_TEXT_FLAG)
|
holder.filenameView.paintFlags = (holder.filenameView.paintFlags or Paint.UNDERLINE_TEXT_FLAG)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun getStubType(): Int = STUB_ID
|
||||||
|
|
||||||
class Holder : AbsMessageItem.Holder() {
|
class Holder : AbsMessageItem.Holder() {
|
||||||
override val avatarImageView by bind<ImageView>(R.id.messageAvatarImageView)
|
override fun getStubId(): Int = STUB_ID
|
||||||
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 fileLayout by bind<ViewGroup>(R.id.messageFileLayout)
|
||||||
val fileImageView by bind<ImageView>(R.id.messageFileImageView)
|
val fileImageView by bind<ImageView>(R.id.messageFileImageView)
|
||||||
val filenameView by bind<TextView>(R.id.messageFilenameView)
|
val filenameView by bind<TextView>(R.id.messageFilenameView)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
private val STUB_ID = R.id.messageContentFileStub
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
|
@ -19,20 +19,23 @@ package im.vector.riotredesign.features.home.room.detail.timeline.item
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
import android.widget.ImageView
|
import android.widget.ImageView
|
||||||
import android.widget.TextView
|
|
||||||
import com.airbnb.epoxy.EpoxyAttribute
|
import com.airbnb.epoxy.EpoxyAttribute
|
||||||
import com.airbnb.epoxy.EpoxyModelClass
|
import com.airbnb.epoxy.EpoxyModelClass
|
||||||
import im.vector.riotredesign.R
|
import im.vector.riotredesign.R
|
||||||
import im.vector.riotredesign.features.home.room.detail.timeline.helper.ContentUploadStateTrackerBinder
|
import im.vector.riotredesign.features.home.room.detail.timeline.helper.ContentUploadStateTrackerBinder
|
||||||
import im.vector.riotredesign.features.media.ImageContentRenderer
|
import im.vector.riotredesign.features.media.ImageContentRenderer
|
||||||
|
|
||||||
@EpoxyModelClass(layout = R.layout.item_timeline_event_image_video_message)
|
@EpoxyModelClass(layout = R.layout.item_timeline_event_base)
|
||||||
abstract class MessageImageVideoItem : AbsMessageItem<MessageImageVideoItem.Holder>() {
|
abstract class MessageImageVideoItem : AbsMessageItem<MessageImageVideoItem.Holder>() {
|
||||||
|
|
||||||
@EpoxyAttribute lateinit var mediaData: ImageContentRenderer.Data
|
@EpoxyAttribute
|
||||||
@EpoxyAttribute override lateinit var informationData: MessageInformationData
|
lateinit var mediaData: ImageContentRenderer.Data
|
||||||
@EpoxyAttribute var playable: Boolean = false
|
@EpoxyAttribute
|
||||||
@EpoxyAttribute var clickListener: View.OnClickListener? = null
|
override lateinit var informationData: MessageInformationData
|
||||||
|
@EpoxyAttribute
|
||||||
|
var playable: Boolean = false
|
||||||
|
@EpoxyAttribute
|
||||||
|
var clickListener: View.OnClickListener? = null
|
||||||
|
|
||||||
override fun bind(holder: Holder) {
|
override fun bind(holder: Holder) {
|
||||||
super.bind(holder)
|
super.bind(holder)
|
||||||
|
@ -49,13 +52,21 @@ abstract class MessageImageVideoItem : AbsMessageItem<MessageImageVideoItem.Hold
|
||||||
super.unbind(holder)
|
super.unbind(holder)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun getStubType(): Int = STUB_ID
|
||||||
|
|
||||||
class Holder : AbsMessageItem.Holder() {
|
class Holder : AbsMessageItem.Holder() {
|
||||||
override val avatarImageView by bind<ImageView>(R.id.messageAvatarImageView)
|
|
||||||
override val memberNameView by bind<TextView>(R.id.messageMemberNameView)
|
override fun getStubId(): Int = STUB_ID
|
||||||
override val timeView by bind<TextView>(R.id.messageTimeView)
|
|
||||||
val progressLayout by bind<ViewGroup>(R.id.messageMediaUploadProgressLayout)
|
val progressLayout by bind<ViewGroup>(R.id.messageMediaUploadProgressLayout)
|
||||||
val imageView by bind<ImageView>(R.id.messageThumbnailView)
|
val imageView by bind<ImageView>(R.id.messageThumbnailView)
|
||||||
val playContentView by bind<ImageView>(R.id.messageMediaPlayView)
|
val playContentView by bind<ImageView>(R.id.messageMediaPlayView)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
private val STUB_ID = R.id.messageContentMediaStub
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
|
@ -16,6 +16,7 @@
|
||||||
|
|
||||||
package im.vector.riotredesign.features.home.room.detail.timeline.item
|
package im.vector.riotredesign.features.home.room.detail.timeline.item
|
||||||
|
|
||||||
|
import android.text.Spannable
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.widget.ImageView
|
import android.widget.ImageView
|
||||||
import android.widget.TextView
|
import android.widget.TextView
|
||||||
|
@ -33,7 +34,7 @@ import kotlinx.coroutines.GlobalScope
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import kotlinx.coroutines.withContext
|
import kotlinx.coroutines.withContext
|
||||||
|
|
||||||
@EpoxyModelClass(layout = R.layout.item_timeline_event_text_message)
|
@EpoxyModelClass(layout = R.layout.item_timeline_event_base)
|
||||||
abstract class MessageTextItem : AbsMessageItem<MessageTextItem.Holder>() {
|
abstract class MessageTextItem : AbsMessageItem<MessageTextItem.Holder>() {
|
||||||
|
|
||||||
@EpoxyAttribute
|
@EpoxyAttribute
|
||||||
|
@ -67,12 +68,12 @@ abstract class MessageTextItem : AbsMessageItem<MessageTextItem.Holder>() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun getStubType(): Int = R.id.messageContentTextStub
|
||||||
|
|
||||||
class Holder : AbsMessageItem.Holder() {
|
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 messageView by bind<AppCompatTextView>(R.id.messageTextView)
|
val messageView by bind<AppCompatTextView>(R.id.messageTextView)
|
||||||
|
override fun getStubId(): Int = R.id.messageContentTextStub
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
|
@ -22,30 +22,41 @@ import android.widget.TextView
|
||||||
import com.airbnb.epoxy.EpoxyAttribute
|
import com.airbnb.epoxy.EpoxyAttribute
|
||||||
import com.airbnb.epoxy.EpoxyModelClass
|
import com.airbnb.epoxy.EpoxyModelClass
|
||||||
import im.vector.riotredesign.R
|
import im.vector.riotredesign.R
|
||||||
import im.vector.riotredesign.core.epoxy.VectorEpoxyHolder
|
|
||||||
import im.vector.riotredesign.core.epoxy.VectorEpoxyModel
|
|
||||||
import im.vector.riotredesign.features.home.AvatarRenderer
|
import im.vector.riotredesign.features.home.AvatarRenderer
|
||||||
|
|
||||||
@EpoxyModelClass(layout = R.layout.item_timeline_event_notice)
|
@EpoxyModelClass(layout = R.layout.item_timeline_event_base_noinfo)
|
||||||
abstract class NoticeItem : VectorEpoxyModel<NoticeItem.Holder>() {
|
abstract class NoticeItem : BaseEventItem<NoticeItem.Holder>() {
|
||||||
|
|
||||||
@EpoxyAttribute var noticeText: CharSequence? = null
|
@EpoxyAttribute
|
||||||
@EpoxyAttribute var avatarUrl: String? = null
|
var noticeText: CharSequence? = null
|
||||||
@EpoxyAttribute var userId: String = ""
|
@EpoxyAttribute
|
||||||
@EpoxyAttribute var memberName: CharSequence? = null
|
var avatarUrl: String? = null
|
||||||
|
@EpoxyAttribute
|
||||||
|
var userId: String = ""
|
||||||
|
@EpoxyAttribute
|
||||||
|
var memberName: CharSequence? = null
|
||||||
|
|
||||||
|
|
||||||
@EpoxyAttribute
|
@EpoxyAttribute
|
||||||
var longClickListener: View.OnLongClickListener? = null
|
var longClickListener: View.OnLongClickListener? = null
|
||||||
|
|
||||||
override fun bind(holder: Holder) {
|
override fun bind(holder: Holder) {
|
||||||
|
super.bind(holder)
|
||||||
holder.noticeTextView.text = noticeText
|
holder.noticeTextView.text = noticeText
|
||||||
AvatarRenderer.render(avatarUrl, userId, memberName?.toString(), holder.avatarImageView)
|
AvatarRenderer.render(avatarUrl, userId, memberName?.toString(), holder.avatarImageView)
|
||||||
holder.view.setOnLongClickListener(longClickListener)
|
holder.view.setOnLongClickListener(longClickListener)
|
||||||
}
|
}
|
||||||
|
|
||||||
class Holder : VectorEpoxyHolder() {
|
override fun getStubType(): Int = STUB_ID
|
||||||
|
|
||||||
|
class Holder : BaseHolder() {
|
||||||
|
override fun getStubId(): Int = STUB_ID
|
||||||
|
|
||||||
val avatarImageView by bind<ImageView>(R.id.itemNoticeAvatarView)
|
val avatarImageView by bind<ImageView>(R.id.itemNoticeAvatarView)
|
||||||
val noticeTextView by bind<TextView>(R.id.itemNoticeTextView)
|
val noticeTextView by bind<TextView>(R.id.itemNoticeTextView)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
private val STUB_ID = R.id.messageContentNoticeStub
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -4,37 +4,44 @@
|
||||||
xmlns:tools="http://schemas.android.com/tools"
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:background="?attr/selectableItemBackground"
|
|
||||||
android:addStatesFromChildren="true"
|
android:addStatesFromChildren="true"
|
||||||
android:paddingLeft="16dp"
|
android:background="?attr/selectableItemBackground"
|
||||||
android:paddingRight="16dp">
|
android:paddingLeft="8dp"
|
||||||
|
android:paddingRight="8dp">
|
||||||
|
|
||||||
|
|
||||||
<ImageView
|
<ImageView
|
||||||
android:id="@+id/messageAvatarImageView"
|
android:id="@+id/messageAvatarImageView"
|
||||||
android:layout_width="44dp"
|
android:layout_width="44dp"
|
||||||
android:layout_height="44dp"
|
android:layout_height="44dp"
|
||||||
android:layout_marginTop="8dp"
|
android:layout_marginTop="4dp"
|
||||||
android:layout_marginBottom="8dp"
|
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
app:layout_constraintTop_toTopOf="parent"
|
app:layout_constraintTop_toTopOf="parent"
|
||||||
tools:src="@tools:sample/avatars" />
|
tools:src="@tools:sample/avatars" />
|
||||||
|
|
||||||
|
<androidx.constraintlayout.widget.Guideline
|
||||||
|
android:id="@+id/messageStartGuideline"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:orientation="vertical"
|
||||||
|
tools:layout_constraintGuide_begin="44dp" />
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/messageMemberNameView"
|
android:id="@+id/messageMemberNameView"
|
||||||
android:layout_width="0dp"
|
android:layout_width="0dp"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginStart="56dp"
|
android:layout_marginStart="8dp"
|
||||||
android:layout_marginLeft="56dp"
|
android:layout_marginLeft="8dp"
|
||||||
android:layout_marginTop="8dp"
|
android:layout_marginTop="4dp"
|
||||||
android:layout_marginEnd="8dp"
|
android:layout_marginEnd="4dp"
|
||||||
android:layout_marginRight="8dp"
|
android:layout_marginRight="8dp"
|
||||||
android:ellipsize="end"
|
android:ellipsize="end"
|
||||||
android:maxLines="1"
|
android:maxLines="1"
|
||||||
android:textSize="15sp"
|
android:textSize="15sp"
|
||||||
|
android:textStyle="bold"
|
||||||
app:layout_constraintEnd_toStartOf="@+id/messageTimeView"
|
app:layout_constraintEnd_toStartOf="@+id/messageTimeView"
|
||||||
app:layout_constraintHorizontal_bias="0.0"
|
app:layout_constraintHorizontal_bias="0.0"
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
app:layout_constraintStart_toEndOf="@id/messageStartGuideline"
|
||||||
app:layout_constraintTop_toTopOf="parent"
|
app:layout_constraintTop_toTopOf="parent"
|
||||||
tools:text="@tools:sample/full_names" />
|
tools:text="@tools:sample/full_names" />
|
||||||
|
|
||||||
|
@ -51,21 +58,26 @@
|
||||||
app:layout_constraintTop_toTopOf="@id/messageMemberNameView"
|
app:layout_constraintTop_toTopOf="@id/messageMemberNameView"
|
||||||
tools:text="@tools:sample/date/hhmm" />
|
tools:text="@tools:sample/date/hhmm" />
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/messageTextView"
|
<ViewStub
|
||||||
android:layout_width="0dp"
|
android:id="@+id/messageContentTextStub"
|
||||||
android:layout_height="wrap_content"
|
style="@style/TimelineContentStubLayoutParams"
|
||||||
android:layout_marginStart="56dp"
|
android:inflatedId="@id/messageTextView"
|
||||||
android:layout_marginLeft="56dp"
|
android:layout="@layout/item_timeline_event_text_message_stub"
|
||||||
android:layout_marginBottom="8dp"
|
tools:ignore="MissingConstraints"
|
||||||
android:clickable="true"
|
tools:visibility="visible" />
|
||||||
android:textColor="@color/dark_grey"
|
|
||||||
android:textSize="14sp"
|
<ViewStub
|
||||||
app:layout_constraintBottom_toBottomOf="parent"
|
android:id="@+id/messageContentMediaStub"
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
style="@style/TimelineContentStubLayoutParams"
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
android:layout="@layout/item_timeline_event_media_message_stub"
|
||||||
app:layout_constraintTop_toBottomOf="@+id/messageMemberNameView"
|
tools:ignore="MissingConstraints" />
|
||||||
tools:text="Alright finished work, heading there in about 20 mins…
Ping me when you’re outside" />
|
|
||||||
|
<ViewStub
|
||||||
|
android:id="@+id/messageContentFileStub"
|
||||||
|
style="@style/TimelineContentStubLayoutParams"
|
||||||
|
android:layout="@layout/item_timeline_event_file_stub"
|
||||||
|
tools:ignore="MissingConstraints" />
|
||||||
|
|
||||||
|
|
||||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
|
@ -0,0 +1,44 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:addStatesFromChildren="true"
|
||||||
|
android:paddingLeft="8dp"
|
||||||
|
android:paddingRight="8dp">
|
||||||
|
|
||||||
|
<androidx.constraintlayout.widget.Guideline
|
||||||
|
android:id="@+id/messageStartGuideline"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:orientation="vertical"
|
||||||
|
tools:layout_constraintGuide_begin="44dp" />
|
||||||
|
|
||||||
|
<ViewStub
|
||||||
|
android:id="@+id/messageContentNoticeStub"
|
||||||
|
style="@style/TimelineContentStubNoInfoLayoutParams"
|
||||||
|
android:layout="@layout/item_timeline_event_notice_stub"
|
||||||
|
tools:ignore="MissingConstraints"
|
||||||
|
tools:visibility="visible" />
|
||||||
|
|
||||||
|
<ViewStub
|
||||||
|
android:id="@+id/messageContentDefaultStub"
|
||||||
|
style="@style/TimelineContentStubNoInfoLayoutParams"
|
||||||
|
android:inflatedId="@+id/stateMessageView"
|
||||||
|
android:layout="@layout/item_timeline_event_default_stub"
|
||||||
|
tools:ignore="MissingConstraints" />
|
||||||
|
|
||||||
|
<ViewStub
|
||||||
|
android:id="@+id/messageContentBlankStub"
|
||||||
|
style="@style/TimelineContentStubNoInfoLayoutParams"
|
||||||
|
android:layout="@layout/item_timeline_event_blank_stub"
|
||||||
|
tools:ignore="MissingConstraints" />
|
||||||
|
|
||||||
|
<ViewStub
|
||||||
|
android:id="@+id/messageContentMergedheaderStub"
|
||||||
|
style="@style/TimelineContentStubNoInfoLayoutParams"
|
||||||
|
android:layout="@layout/item_timeline_event_merged_header_stub"
|
||||||
|
tools:ignore="MissingConstraints" />
|
||||||
|
|
||||||
|
|
||||||
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
|
@ -4,10 +4,8 @@
|
||||||
android:id="@+id/stateMessageView"
|
android:id="@+id/stateMessageView"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginStart="64dp"
|
|
||||||
android:layout_marginLeft="64dp"
|
|
||||||
android:gravity="center_vertical"
|
android:gravity="center_vertical"
|
||||||
android:padding="16dp"
|
android:padding="8dp"
|
||||||
android:textColor="?attr/colorAccent"
|
android:textColor="?attr/colorAccent"
|
||||||
android:textSize="14sp"
|
android:textSize="14sp"
|
||||||
android:textStyle="italic"
|
android:textStyle="italic"
|
|
@ -1,134 +0,0 @@
|
||||||
<?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:addStatesFromChildren="true"
|
|
||||||
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: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: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>
|
|
67
vector/src/main/res/layout/item_timeline_event_file_stub.xml
Normal file
67
vector/src/main/res/layout/item_timeline_event_file_stub.xml
Normal file
|
@ -0,0 +1,67 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<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="match_parent">
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:id="@+id/messageFileLayout"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
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_toTopOf="parent">
|
||||||
|
|
||||||
|
<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_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>
|
|
@ -1,117 +0,0 @@
|
||||||
<?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:background="?attr/selectableItemBackground"
|
|
||||||
android:paddingLeft="16dp"
|
|
||||||
android:addStatesFromChildren="true"
|
|
||||||
android:paddingRight="16dp">
|
|
||||||
|
|
||||||
|
|
||||||
<ImageView
|
|
||||||
android:id="@+id/messageAvatarImageView"
|
|
||||||
android:layout_width="44dp"
|
|
||||||
android:layout_height="44dp"
|
|
||||||
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="56dp"
|
|
||||||
android:layout_marginLeft="56dp"
|
|
||||||
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: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" />
|
|
||||||
|
|
||||||
<ImageView
|
|
||||||
android:id="@+id/messageThumbnailView"
|
|
||||||
android:layout_width="0dp"
|
|
||||||
android:layout_height="0dp"
|
|
||||||
android:layout_marginStart="64dp"
|
|
||||||
android:layout_marginLeft="64dp"
|
|
||||||
android:layout_marginTop="8dp"
|
|
||||||
android:layout_marginEnd="32dp"
|
|
||||||
android:layout_marginRight="32dp"
|
|
||||||
android:foreground="?attr/selectableItemBackground"
|
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
|
||||||
app:layout_constraintHorizontal_bias="0"
|
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
|
||||||
app:layout_constraintTop_toBottomOf="@+id/messageMemberNameView"
|
|
||||||
tools:layout_height="300dp"
|
|
||||||
tools:srcCompat="@tools:sample/backgrounds/scenic" />
|
|
||||||
|
|
||||||
<ImageView
|
|
||||||
android:id="@+id/messageMediaPlayView"
|
|
||||||
android:layout_width="40dp"
|
|
||||||
android:layout_height="40dp"
|
|
||||||
android:src="@drawable/ic_material_play_circle"
|
|
||||||
android:visibility="gone"
|
|
||||||
app:layout_constraintBottom_toBottomOf="@id/messageThumbnailView"
|
|
||||||
app:layout_constraintEnd_toEndOf="@id/messageThumbnailView"
|
|
||||||
app:layout_constraintStart_toStartOf="@id/messageThumbnailView"
|
|
||||||
app:layout_constraintTop_toTopOf="@id/messageThumbnailView"
|
|
||||||
tools:visibility="visible" />
|
|
||||||
|
|
||||||
|
|
||||||
<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/messageThumbnailView"
|
|
||||||
tools:visibility="visible" />
|
|
||||||
|
|
||||||
|
|
||||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
|
|
@ -0,0 +1,47 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<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">
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:id="@+id/messageThumbnailView"
|
||||||
|
android:layout_width="375dp"
|
||||||
|
android:layout_height="0dp"
|
||||||
|
android:layout_marginEnd="32dp"
|
||||||
|
android:layout_marginRight="32dp"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintHorizontal_bias="0"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintTop_toTopOf="parent"
|
||||||
|
tools:layout_height="300dp" />
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:id="@+id/messageMediaPlayView"
|
||||||
|
android:layout_width="40dp"
|
||||||
|
android:layout_height="40dp"
|
||||||
|
android:src="@drawable/ic_material_play_circle"
|
||||||
|
android:visibility="gone"
|
||||||
|
app:layout_constraintBottom_toBottomOf="@id/messageThumbnailView"
|
||||||
|
app:layout_constraintEnd_toEndOf="@id/messageThumbnailView"
|
||||||
|
app:layout_constraintStart_toStartOf="@id/messageThumbnailView"
|
||||||
|
app:layout_constraintTop_toTopOf="@id/messageThumbnailView"
|
||||||
|
tools:visibility="visible" />
|
||||||
|
|
||||||
|
|
||||||
|
<include
|
||||||
|
android:id="@+id/messageMediaUploadProgressLayout"
|
||||||
|
layout="@layout/media_upload_download_progress_layout"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="46dp"
|
||||||
|
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/messageThumbnailView"
|
||||||
|
tools:visibility="visible" />
|
||||||
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
|
@ -3,8 +3,6 @@
|
||||||
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
xmlns:tools="http://schemas.android.com/tools"
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
android:paddingLeft="16dp"
|
|
||||||
android:paddingRight="16dp"
|
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content">
|
android:layout_height="wrap_content">
|
||||||
|
|
||||||
|
@ -13,8 +11,6 @@
|
||||||
layout="@layout/vector_message_merge_avatar_list"
|
layout="@layout/vector_message_merge_avatar_list"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginStart="64dp"
|
|
||||||
android:layout_marginLeft="64dp"
|
|
||||||
android:layout_marginTop="8dp"
|
android:layout_marginTop="8dp"
|
||||||
android:layout_marginEnd="16dp"
|
android:layout_marginEnd="16dp"
|
||||||
android:layout_marginRight="16dp"
|
android:layout_marginRight="16dp"
|
|
@ -1,38 +0,0 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
|
|
||||||
<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/itemNoticeAvatarView"
|
|
||||||
android:layout_width="24dp"
|
|
||||||
android:layout_height="24dp"
|
|
||||||
android:layout_marginStart="56dp"
|
|
||||||
android:layout_marginLeft="56dp"
|
|
||||||
android:layout_marginTop="8dp"
|
|
||||||
android:layout_marginBottom="8dp"
|
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
|
||||||
app:layout_constraintTop_toTopOf="parent" />
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/itemNoticeTextView"
|
|
||||||
android:layout_width="0dp"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginStart="8dp"
|
|
||||||
android:layout_marginTop="2dp"
|
|
||||||
android:layout_marginEnd="8dp"
|
|
||||||
android:layout_marginBottom="8dp"
|
|
||||||
android:textColor="@color/slate_grey"
|
|
||||||
android:textSize="14sp"
|
|
||||||
android:textStyle="italic"
|
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
|
||||||
app:layout_constraintStart_toEndOf="@+id/itemNoticeAvatarView"
|
|
||||||
app:layout_constraintTop_toTopOf="@+id/itemNoticeAvatarView"
|
|
||||||
tools:text="Mon item" />
|
|
||||||
|
|
||||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
|
|
@ -0,0 +1,30 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<LinearLayout 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:orientation="horizontal"
|
||||||
|
android:layout_height="wrap_content">
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:id="@+id/itemNoticeAvatarView"
|
||||||
|
android:layout_width="24dp"
|
||||||
|
android:layout_height="24dp"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintTop_toTopOf="parent"
|
||||||
|
tools:srcCompat="@tools:sample/avatars" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_gravity="top"
|
||||||
|
android:id="@+id/itemNoticeTextView"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginStart="8dp"
|
||||||
|
android:layout_marginEnd="8dp"
|
||||||
|
android:layout_marginBottom="8dp"
|
||||||
|
android:textColor="@color/slate_grey"
|
||||||
|
android:textSize="14sp"
|
||||||
|
android:textStyle="italic"
|
||||||
|
tools:text="Jhon doe changed their avatar" />
|
||||||
|
|
||||||
|
</LinearLayout>
|
|
@ -0,0 +1,9 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
|
android:id="@+id/messageTextView"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:textColor="@color/dark_grey"
|
||||||
|
android:textSize="14sp"
|
||||||
|
tools:text="Alright finished work, heading there in about 20 mins…
Ping me when you’re outside" />
|
|
@ -246,4 +246,25 @@
|
||||||
<item name="android:textColorTertiary">@color/riot_tertiary_text_color_status</item>
|
<item name="android:textColorTertiary">@color/riot_tertiary_text_color_status</item>
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
|
|
||||||
|
<style name="TimelineContentStubBaseParams">
|
||||||
|
<item name="android:layout_width">0dp</item>
|
||||||
|
<item name="android:layout_height">wrap_content</item>
|
||||||
|
<item name="android:layout_marginStart">8dp</item>
|
||||||
|
<item name="android:layout_marginLeft">8dp</item>
|
||||||
|
<item name="android:layout_marginBottom">8dp</item>
|
||||||
|
<item name="android:layout_marginTop">4dp</item>
|
||||||
|
<item name="layout_constraintBottom_toBottomOf">parent</item>
|
||||||
|
<item name="layout_constraintEnd_toEndOf">parent</item>
|
||||||
|
<item name="layout_constraintStart_toEndOf">@id/messageStartGuideline</item>
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<style name="TimelineContentStubNoInfoLayoutParams" parent="TimelineContentStubBaseParams">
|
||||||
|
<item name="layout_constraintTop_toTopOf">parent</item>
|
||||||
|
</style>
|
||||||
|
|
||||||
|
|
||||||
|
<style name="TimelineContentStubLayoutParams" parent="TimelineContentStubBaseParams">
|
||||||
|
<item name="layout_constraintTop_toBottomOf">@id/messageMemberNameView</item>
|
||||||
|
</style>
|
||||||
</resources>
|
</resources>
|
Loading…
Reference in a new issue