mirror of
https://github.com/element-hq/element-android
synced 2024-11-25 02:45:37 +03:00
Merge pull request #891 from vector-im/feature/event-unknown
Feature/event unknown
This commit is contained in:
commit
e12de3fba0
10 changed files with 133 additions and 67 deletions
|
@ -46,17 +46,14 @@ class MessageActionsEpoxyController @Inject constructor(
|
||||||
|
|
||||||
override fun buildModels(state: MessageActionState) {
|
override fun buildModels(state: MessageActionState) {
|
||||||
// Message preview
|
// Message preview
|
||||||
val body = state.messageBody
|
bottomSheetMessagePreviewItem {
|
||||||
if (body != null) {
|
id("preview")
|
||||||
bottomSheetMessagePreviewItem {
|
avatarRenderer(avatarRenderer)
|
||||||
id("preview")
|
matrixItem(state.informationData.matrixItem)
|
||||||
avatarRenderer(avatarRenderer)
|
movementMethod(createLinkMovementMethod(listener))
|
||||||
matrixItem(state.informationData.matrixItem)
|
userClicked { listener?.didSelectMenuAction(EventSharedAction.OpenUserProfile(state.informationData.senderId)) }
|
||||||
movementMethod(createLinkMovementMethod(listener))
|
body(state.messageBody.linkify(listener))
|
||||||
userClicked { listener?.didSelectMenuAction(EventSharedAction.OpenUserProfile(state.informationData.senderId)) }
|
time(state.time())
|
||||||
body(body.linkify(listener))
|
|
||||||
time(state.time())
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Send state
|
// Send state
|
||||||
|
|
|
@ -15,7 +15,12 @@
|
||||||
*/
|
*/
|
||||||
package im.vector.riotx.features.home.room.detail.timeline.action
|
package im.vector.riotx.features.home.room.detail.timeline.action
|
||||||
|
|
||||||
import com.airbnb.mvrx.*
|
import com.airbnb.mvrx.Async
|
||||||
|
import com.airbnb.mvrx.FragmentViewModelContext
|
||||||
|
import com.airbnb.mvrx.MvRxState
|
||||||
|
import com.airbnb.mvrx.MvRxViewModelFactory
|
||||||
|
import com.airbnb.mvrx.Uninitialized
|
||||||
|
import com.airbnb.mvrx.ViewModelContext
|
||||||
import com.squareup.inject.assisted.Assisted
|
import com.squareup.inject.assisted.Assisted
|
||||||
import com.squareup.inject.assisted.AssistedInject
|
import com.squareup.inject.assisted.AssistedInject
|
||||||
import dagger.Lazy
|
import dagger.Lazy
|
||||||
|
@ -45,7 +50,8 @@ import im.vector.riotx.features.html.VectorHtmlCompressor
|
||||||
import im.vector.riotx.features.reactions.data.EmojiDataSource
|
import im.vector.riotx.features.reactions.data.EmojiDataSource
|
||||||
import im.vector.riotx.features.settings.VectorPreferences
|
import im.vector.riotx.features.settings.VectorPreferences
|
||||||
import java.text.SimpleDateFormat
|
import java.text.SimpleDateFormat
|
||||||
import java.util.*
|
import java.util.Date
|
||||||
|
import java.util.Locale
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Quick reactions state
|
* Quick reactions state
|
||||||
|
@ -60,7 +66,7 @@ data class MessageActionState(
|
||||||
val eventId: String,
|
val eventId: String,
|
||||||
val informationData: MessageInformationData,
|
val informationData: MessageInformationData,
|
||||||
val timelineEvent: Async<TimelineEvent> = Uninitialized,
|
val timelineEvent: Async<TimelineEvent> = Uninitialized,
|
||||||
val messageBody: CharSequence? = null,
|
val messageBody: CharSequence = "",
|
||||||
// For quick reactions
|
// For quick reactions
|
||||||
val quickStates: Async<List<ToggleState>> = Uninitialized,
|
val quickStates: Async<List<ToggleState>> = Uninitialized,
|
||||||
// For actions
|
// For actions
|
||||||
|
@ -155,13 +161,16 @@ class MessageActionsViewModel @AssistedInject constructor(@Assisted
|
||||||
|
|
||||||
private fun observeTimelineEventState() {
|
private fun observeTimelineEventState() {
|
||||||
asyncSubscribe(MessageActionState::timelineEvent) { timelineEvent ->
|
asyncSubscribe(MessageActionState::timelineEvent) { timelineEvent ->
|
||||||
val computedMessage = computeMessageBody(timelineEvent)
|
setState {
|
||||||
val actions = actionsForEvent(timelineEvent)
|
copy(
|
||||||
setState { copy(messageBody = computedMessage, actions = actions) }
|
messageBody = computeMessageBody(timelineEvent),
|
||||||
|
actions = actionsForEvent(timelineEvent)
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun computeMessageBody(timelineEvent: TimelineEvent): CharSequence? {
|
private fun computeMessageBody(timelineEvent: TimelineEvent): CharSequence {
|
||||||
return when (timelineEvent.root.getClearType()) {
|
return when (timelineEvent.root.getClearType()) {
|
||||||
EventType.MESSAGE,
|
EventType.MESSAGE,
|
||||||
EventType.STICKER -> {
|
EventType.STICKER -> {
|
||||||
|
@ -189,7 +198,7 @@ class MessageActionsViewModel @AssistedInject constructor(@Assisted
|
||||||
noticeEventFormatter.format(timelineEvent)
|
noticeEventFormatter.format(timelineEvent)
|
||||||
}
|
}
|
||||||
else -> null
|
else -> null
|
||||||
}
|
} ?: ""
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun actionsForEvent(timelineEvent: TimelineEvent): List<EventSharedAction> {
|
private fun actionsForEvent(timelineEvent: TimelineEvent): List<EventSharedAction> {
|
||||||
|
|
|
@ -16,10 +16,13 @@
|
||||||
|
|
||||||
package im.vector.riotx.features.home.room.detail.timeline.factory
|
package im.vector.riotx.features.home.room.detail.timeline.factory
|
||||||
|
|
||||||
|
import android.view.View
|
||||||
import im.vector.matrix.android.api.session.room.timeline.TimelineEvent
|
import im.vector.matrix.android.api.session.room.timeline.TimelineEvent
|
||||||
import im.vector.riotx.features.home.room.detail.timeline.helper.AvatarSizeProvider
|
import im.vector.riotx.R
|
||||||
|
import im.vector.riotx.core.resources.StringProvider
|
||||||
import im.vector.riotx.features.home.AvatarRenderer
|
import im.vector.riotx.features.home.AvatarRenderer
|
||||||
import im.vector.riotx.features.home.room.detail.timeline.TimelineEventController
|
import im.vector.riotx.features.home.room.detail.timeline.TimelineEventController
|
||||||
|
import im.vector.riotx.features.home.room.detail.timeline.helper.AvatarSizeProvider
|
||||||
import im.vector.riotx.features.home.room.detail.timeline.helper.MessageInformationDataFactory
|
import im.vector.riotx.features.home.room.detail.timeline.helper.MessageInformationDataFactory
|
||||||
import im.vector.riotx.features.home.room.detail.timeline.item.DefaultItem
|
import im.vector.riotx.features.home.room.detail.timeline.item.DefaultItem
|
||||||
import im.vector.riotx.features.home.room.detail.timeline.item.DefaultItem_
|
import im.vector.riotx.features.home.room.detail.timeline.item.DefaultItem_
|
||||||
|
@ -28,20 +31,26 @@ import javax.inject.Inject
|
||||||
|
|
||||||
class DefaultItemFactory @Inject constructor(private val avatarSizeProvider: AvatarSizeProvider,
|
class DefaultItemFactory @Inject constructor(private val avatarSizeProvider: AvatarSizeProvider,
|
||||||
private val avatarRenderer: AvatarRenderer,
|
private val avatarRenderer: AvatarRenderer,
|
||||||
|
private val stringProvider: StringProvider,
|
||||||
private val informationDataFactory: MessageInformationDataFactory) {
|
private val informationDataFactory: MessageInformationDataFactory) {
|
||||||
|
|
||||||
fun create(text: String,
|
fun create(text: String,
|
||||||
informationData: MessageInformationData,
|
informationData: MessageInformationData,
|
||||||
highlight: Boolean,
|
highlight: Boolean,
|
||||||
callback: TimelineEventController.Callback?): DefaultItem {
|
callback: TimelineEventController.Callback?): DefaultItem {
|
||||||
|
val attributes = DefaultItem.Attributes(
|
||||||
|
avatarRenderer = avatarRenderer,
|
||||||
|
informationData = informationData,
|
||||||
|
text = text,
|
||||||
|
itemLongClickListener = View.OnLongClickListener { view ->
|
||||||
|
callback?.onEventLongClicked(informationData, null, view) ?: false
|
||||||
|
},
|
||||||
|
readReceiptsCallback = callback
|
||||||
|
)
|
||||||
return DefaultItem_()
|
return DefaultItem_()
|
||||||
.leftGuideline(avatarSizeProvider.leftGuideline)
|
.leftGuideline(avatarSizeProvider.leftGuideline)
|
||||||
.highlighted(highlight)
|
.highlighted(highlight)
|
||||||
.text(text)
|
.attributes(attributes)
|
||||||
.avatarRenderer(avatarRenderer)
|
|
||||||
.informationData(informationData)
|
|
||||||
.baseCallback(callback)
|
|
||||||
.readReceiptsCallback(callback)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fun create(event: TimelineEvent,
|
fun create(event: TimelineEvent,
|
||||||
|
@ -49,9 +58,9 @@ class DefaultItemFactory @Inject constructor(private val avatarSizeProvider: Ava
|
||||||
callback: TimelineEventController.Callback?,
|
callback: TimelineEventController.Callback?,
|
||||||
throwable: Throwable? = null): DefaultItem {
|
throwable: Throwable? = null): DefaultItem {
|
||||||
val text = if (throwable == null) {
|
val text = if (throwable == null) {
|
||||||
"${event.root.getClearType()} events are not yet handled"
|
stringProvider.getString(R.string.rendering_event_error_type_of_event_not_handled, event.root.getClearType())
|
||||||
} else {
|
} else {
|
||||||
"an exception occurred when rendering the event ${event.root.eventId}"
|
stringProvider.getString(R.string.rendering_event_error_exception, event.root.eventId)
|
||||||
}
|
}
|
||||||
val informationData = informationDataFactory.create(event, null)
|
val informationData = informationDataFactory.create(event, null)
|
||||||
return create(text, informationData, highlight, callback)
|
return create(text, informationData, highlight, callback)
|
||||||
|
|
|
@ -26,7 +26,16 @@ import android.view.View
|
||||||
import dagger.Lazy
|
import dagger.Lazy
|
||||||
import im.vector.matrix.android.api.session.events.model.RelationType
|
import im.vector.matrix.android.api.session.events.model.RelationType
|
||||||
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.*
|
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.MessageImageInfoContent
|
||||||
|
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.MessageType
|
||||||
|
import im.vector.matrix.android.api.session.room.model.message.MessageVideoContent
|
||||||
|
import im.vector.matrix.android.api.session.room.model.message.getFileUrl
|
||||||
import im.vector.matrix.android.api.session.room.timeline.TimelineEvent
|
import im.vector.matrix.android.api.session.room.timeline.TimelineEvent
|
||||||
import im.vector.matrix.android.api.session.room.timeline.getLastMessageContent
|
import im.vector.matrix.android.api.session.room.timeline.getLastMessageContent
|
||||||
import im.vector.matrix.android.internal.crypto.attachments.toElementToDecrypt
|
import im.vector.matrix.android.internal.crypto.attachments.toElementToDecrypt
|
||||||
|
@ -40,8 +49,24 @@ import im.vector.riotx.core.utils.DimensionConverter
|
||||||
import im.vector.riotx.core.utils.containsOnlyEmojis
|
import im.vector.riotx.core.utils.containsOnlyEmojis
|
||||||
import im.vector.riotx.core.utils.isLocalFile
|
import im.vector.riotx.core.utils.isLocalFile
|
||||||
import im.vector.riotx.features.home.room.detail.timeline.TimelineEventController
|
import im.vector.riotx.features.home.room.detail.timeline.TimelineEventController
|
||||||
import im.vector.riotx.features.home.room.detail.timeline.helper.*
|
import im.vector.riotx.features.home.room.detail.timeline.helper.AvatarSizeProvider
|
||||||
import im.vector.riotx.features.home.room.detail.timeline.item.*
|
import im.vector.riotx.features.home.room.detail.timeline.helper.ContentUploadStateTrackerBinder
|
||||||
|
import im.vector.riotx.features.home.room.detail.timeline.helper.MessageInformationDataFactory
|
||||||
|
import im.vector.riotx.features.home.room.detail.timeline.helper.MessageItemAttributesFactory
|
||||||
|
import im.vector.riotx.features.home.room.detail.timeline.helper.TimelineMediaSizeProvider
|
||||||
|
import im.vector.riotx.features.home.room.detail.timeline.item.AbsMessageItem
|
||||||
|
import im.vector.riotx.features.home.room.detail.timeline.item.DefaultItem
|
||||||
|
import im.vector.riotx.features.home.room.detail.timeline.item.MessageBlockCodeItem
|
||||||
|
import im.vector.riotx.features.home.room.detail.timeline.item.MessageBlockCodeItem_
|
||||||
|
import im.vector.riotx.features.home.room.detail.timeline.item.MessageFileItem
|
||||||
|
import im.vector.riotx.features.home.room.detail.timeline.item.MessageFileItem_
|
||||||
|
import im.vector.riotx.features.home.room.detail.timeline.item.MessageImageVideoItem
|
||||||
|
import im.vector.riotx.features.home.room.detail.timeline.item.MessageImageVideoItem_
|
||||||
|
import im.vector.riotx.features.home.room.detail.timeline.item.MessageInformationData
|
||||||
|
import im.vector.riotx.features.home.room.detail.timeline.item.MessageTextItem
|
||||||
|
import im.vector.riotx.features.home.room.detail.timeline.item.MessageTextItem_
|
||||||
|
import im.vector.riotx.features.home.room.detail.timeline.item.RedactedMessageItem
|
||||||
|
import im.vector.riotx.features.home.room.detail.timeline.item.RedactedMessageItem_
|
||||||
import im.vector.riotx.features.home.room.detail.timeline.tools.createLinkMovementMethod
|
import im.vector.riotx.features.home.room.detail.timeline.tools.createLinkMovementMethod
|
||||||
import im.vector.riotx.features.home.room.detail.timeline.tools.linkify
|
import im.vector.riotx.features.home.room.detail.timeline.tools.linkify
|
||||||
import im.vector.riotx.features.html.CodeVisitor
|
import im.vector.riotx.features.html.CodeVisitor
|
||||||
|
@ -153,7 +178,7 @@ class MessageItemFactory @Inject constructor(
|
||||||
informationData: MessageInformationData,
|
informationData: MessageInformationData,
|
||||||
highlight: Boolean,
|
highlight: Boolean,
|
||||||
callback: TimelineEventController.Callback?): DefaultItem? {
|
callback: TimelineEventController.Callback?): DefaultItem? {
|
||||||
val text = "${messageContent.type} message events are not yet handled"
|
val text = stringProvider.getString(R.string.rendering_event_error_type_of_message_not_handled, messageContent.type)
|
||||||
return defaultItemFactory.create(text, informationData, highlight, callback)
|
return defaultItemFactory.create(text, informationData, highlight, callback)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -18,6 +18,7 @@ package im.vector.riotx.features.home.room.detail.timeline.item
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.ViewStub
|
import android.view.ViewStub
|
||||||
import android.widget.RelativeLayout
|
import android.widget.RelativeLayout
|
||||||
|
import androidx.annotation.CallSuper
|
||||||
import androidx.annotation.IdRes
|
import androidx.annotation.IdRes
|
||||||
import androidx.core.view.updateLayoutParams
|
import androidx.core.view.updateLayoutParams
|
||||||
import com.airbnb.epoxy.EpoxyAttribute
|
import com.airbnb.epoxy.EpoxyAttribute
|
||||||
|
@ -42,6 +43,7 @@ abstract class BaseEventItem<H : BaseEventItem.BaseHolder> : VectorEpoxyModel<H>
|
||||||
@EpoxyAttribute
|
@EpoxyAttribute
|
||||||
lateinit var dimensionConverter: DimensionConverter
|
lateinit var dimensionConverter: DimensionConverter
|
||||||
|
|
||||||
|
@CallSuper
|
||||||
override fun bind(holder: H) {
|
override fun bind(holder: H) {
|
||||||
super.bind(holder)
|
super.bind(holder)
|
||||||
holder.leftGuideline.updateLayoutParams<RelativeLayout.LayoutParams> {
|
holder.leftGuideline.updateLayoutParams<RelativeLayout.LayoutParams> {
|
||||||
|
|
|
@ -17,6 +17,7 @@
|
||||||
package im.vector.riotx.features.home.room.detail.timeline.item
|
package im.vector.riotx.features.home.room.detail.timeline.item
|
||||||
|
|
||||||
import android.view.View
|
import android.view.View
|
||||||
|
import android.widget.ImageView
|
||||||
import android.widget.TextView
|
import android.widget.TextView
|
||||||
import com.airbnb.epoxy.EpoxyAttribute
|
import com.airbnb.epoxy.EpoxyAttribute
|
||||||
import com.airbnb.epoxy.EpoxyModelClass
|
import com.airbnb.epoxy.EpoxyModelClass
|
||||||
|
@ -29,42 +30,39 @@ import im.vector.riotx.features.home.room.detail.timeline.TimelineEventControlle
|
||||||
abstract class DefaultItem : BaseEventItem<DefaultItem.Holder>() {
|
abstract class DefaultItem : BaseEventItem<DefaultItem.Holder>() {
|
||||||
|
|
||||||
@EpoxyAttribute
|
@EpoxyAttribute
|
||||||
lateinit var informationData: MessageInformationData
|
lateinit var attributes: Attributes
|
||||||
@EpoxyAttribute
|
|
||||||
lateinit var avatarRenderer: AvatarRenderer
|
|
||||||
@EpoxyAttribute
|
|
||||||
var baseCallback: TimelineEventController.BaseCallback? = null
|
|
||||||
|
|
||||||
private var longClickListener = View.OnLongClickListener {
|
|
||||||
return@OnLongClickListener baseCallback?.onEventLongClicked(informationData, null, it) == true
|
|
||||||
}
|
|
||||||
|
|
||||||
@EpoxyAttribute
|
|
||||||
var readReceiptsCallback: TimelineEventController.ReadReceiptsCallback? = null
|
|
||||||
|
|
||||||
private val _readReceiptsClickListener = DebouncedClickListener(View.OnClickListener {
|
private val _readReceiptsClickListener = DebouncedClickListener(View.OnClickListener {
|
||||||
readReceiptsCallback?.onReadReceiptsClicked(informationData.readReceipts)
|
attributes.readReceiptsCallback?.onReadReceiptsClicked(attributes.informationData.readReceipts)
|
||||||
})
|
})
|
||||||
|
|
||||||
@EpoxyAttribute
|
|
||||||
var text: CharSequence? = null
|
|
||||||
|
|
||||||
override fun bind(holder: Holder) {
|
override fun bind(holder: Holder) {
|
||||||
holder.messageView.text = text
|
super.bind(holder)
|
||||||
holder.view.setOnLongClickListener(longClickListener)
|
holder.messageTextView.text = attributes.text
|
||||||
holder.readReceiptsView.render(informationData.readReceipts, avatarRenderer, _readReceiptsClickListener)
|
attributes.avatarRenderer.render(attributes.informationData.matrixItem, holder.avatarImageView)
|
||||||
|
holder.view.setOnLongClickListener(attributes.itemLongClickListener)
|
||||||
|
holder.readReceiptsView.render(attributes.informationData.readReceipts, attributes.avatarRenderer, _readReceiptsClickListener)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getEventIds(): List<String> {
|
override fun getEventIds(): List<String> {
|
||||||
return listOf(informationData.eventId)
|
return listOf(attributes.informationData.eventId)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getViewType() = STUB_ID
|
override fun getViewType() = STUB_ID
|
||||||
|
|
||||||
class Holder : BaseHolder(STUB_ID) {
|
class Holder : BaseHolder(STUB_ID) {
|
||||||
val messageView by bind<TextView>(R.id.stateMessageView)
|
val avatarImageView by bind<ImageView>(R.id.itemDefaultAvatarView)
|
||||||
|
val messageTextView by bind<TextView>(R.id.itemDefaultTextView)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
data class Attributes(
|
||||||
|
val avatarRenderer: AvatarRenderer,
|
||||||
|
val informationData: MessageInformationData,
|
||||||
|
val text: CharSequence,
|
||||||
|
val itemLongClickListener: View.OnLongClickListener? = null,
|
||||||
|
val readReceiptsCallback: TimelineEventController.ReadReceiptsCallback? = null
|
||||||
|
)
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
private const val STUB_ID = R.id.messageContentDefaultStub
|
private const val STUB_ID = R.id.messageContentDefaultStub
|
||||||
}
|
}
|
||||||
|
|
|
@ -36,8 +36,9 @@
|
||||||
<ViewStub
|
<ViewStub
|
||||||
android:id="@+id/messageContentDefaultStub"
|
android:id="@+id/messageContentDefaultStub"
|
||||||
style="@style/TimelineContentStubBaseParams"
|
style="@style/TimelineContentStubBaseParams"
|
||||||
android:inflatedId="@+id/stateMessageView"
|
android:layout="@layout/item_timeline_event_default_stub"
|
||||||
android:layout="@layout/item_timeline_event_default_stub" />
|
tools:layout_marginTop="80dp"
|
||||||
|
tools:visibility="visible" />
|
||||||
|
|
||||||
<ViewStub
|
<ViewStub
|
||||||
android:id="@+id/messageContentBlankStub"
|
android:id="@+id/messageContentBlankStub"
|
||||||
|
@ -49,7 +50,9 @@
|
||||||
<ViewStub
|
<ViewStub
|
||||||
android:id="@+id/messageContentMergedHeaderStub"
|
android:id="@+id/messageContentMergedHeaderStub"
|
||||||
style="@style/TimelineContentStubBaseParams"
|
style="@style/TimelineContentStubBaseParams"
|
||||||
android:layout="@layout/item_timeline_event_merged_header_stub" />
|
android:layout="@layout/item_timeline_event_merged_header_stub"
|
||||||
|
tools:layout_marginTop="160dp"
|
||||||
|
tools:visibility="visible" />
|
||||||
|
|
||||||
</FrameLayout>
|
</FrameLayout>
|
||||||
|
|
||||||
|
|
|
@ -1,12 +1,31 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
|
<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"
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
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:gravity="center_vertical"
|
android:orientation="horizontal">
|
||||||
android:padding="8dp"
|
|
||||||
android:textColor="?attr/colorAccent"
|
<ImageView
|
||||||
android:textSize="14sp"
|
android:id="@+id/itemDefaultAvatarView"
|
||||||
android:textStyle="italic"
|
android:layout_width="24dp"
|
||||||
tools:text="Mon item" />
|
android:layout_height="24dp"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintTop_toTopOf="parent"
|
||||||
|
tools:srcCompat="@tools:sample/avatars" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/itemDefaultTextView"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_gravity="top"
|
||||||
|
android:layout_marginStart="8dp"
|
||||||
|
android:layout_marginEnd="8dp"
|
||||||
|
android:layout_marginBottom="8dp"
|
||||||
|
android:textColor="?attr/colorAccent"
|
||||||
|
android:textSize="14sp"
|
||||||
|
android:textStyle="italic"
|
||||||
|
tools:text="@string/rendering_event_error_type_of_event_not_handled" />
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
|
|
@ -3,8 +3,8 @@
|
||||||
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:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:orientation="horizontal"
|
android:layout_height="wrap_content"
|
||||||
android:layout_height="wrap_content">
|
android:orientation="horizontal">
|
||||||
|
|
||||||
<ImageView
|
<ImageView
|
||||||
android:id="@+id/itemNoticeAvatarView"
|
android:id="@+id/itemNoticeAvatarView"
|
||||||
|
@ -15,16 +15,16 @@
|
||||||
tools:srcCompat="@tools:sample/avatars" />
|
tools:srcCompat="@tools:sample/avatars" />
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:layout_gravity="top"
|
|
||||||
android:id="@+id/itemNoticeTextView"
|
android:id="@+id/itemNoticeTextView"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_gravity="top"
|
||||||
android:layout_marginStart="8dp"
|
android:layout_marginStart="8dp"
|
||||||
android:layout_marginEnd="8dp"
|
android:layout_marginEnd="8dp"
|
||||||
android:layout_marginBottom="8dp"
|
android:layout_marginBottom="8dp"
|
||||||
android:textColor="?riotx_text_secondary"
|
android:textColor="?riotx_text_secondary"
|
||||||
android:textSize="14sp"
|
android:textSize="14sp"
|
||||||
android:textStyle="italic"
|
android:textStyle="italic"
|
||||||
tools:text="John doe changed their avatar" />
|
tools:text="@string/notice_avatar_url_changed" />
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
|
@ -32,6 +32,10 @@
|
||||||
|
|
||||||
<string name="room_member_jump_to_read_receipt">Jump to read receipt</string>
|
<string name="room_member_jump_to_read_receipt">Jump to read receipt</string>
|
||||||
|
|
||||||
|
<string name="rendering_event_error_type_of_event_not_handled">"RiotX does not handle events of type '%1$s' (yet)"</string>
|
||||||
|
<string name="rendering_event_error_type_of_message_not_handled">"RiotX does not handle message of type '%1$s' (yet)"</string>
|
||||||
|
<string name="rendering_event_error_exception">"RiotX encountered an issue when rendering content of event with id '%1$s'"</string>
|
||||||
|
|
||||||
<string name="unignore">Unignore</string>
|
<string name="unignore">Unignore</string>
|
||||||
|
|
||||||
<string name="room_list_sharing_header_recent_rooms">Recent rooms</string>
|
<string name="room_list_sharing_header_recent_rooms">Recent rooms</string>
|
||||||
|
|
Loading…
Reference in a new issue