forked from GitHub-Mirror/riotX-android
Room update: start handling tombstone and room create events [WIP]
This commit is contained in:
@ -244,7 +244,8 @@ class RoomDetailFragment :
|
||||
composerLayout.collapse()
|
||||
}
|
||||
|
||||
private fun enterSpecialMode(event: TimelineEvent, @DrawableRes iconRes: Int, useText: Boolean) {
|
||||
private fun enterSpecialMode(event: TimelineEvent, @DrawableRes
|
||||
iconRes: Int, useText: Boolean) {
|
||||
commandAutocompletePolicy.enabled = false
|
||||
//switch to expanded bar
|
||||
composerLayout.composerRelatedMessageTitle.apply {
|
||||
@ -533,7 +534,13 @@ class RoomDetailFragment :
|
||||
} else if (state.asyncInviter.complete) {
|
||||
vectorBaseActivity.finish()
|
||||
}
|
||||
composerLayout.setRoomEncrypted(state.isEncrypted)
|
||||
if (state.tombstoneContent == null) {
|
||||
composerLayout.visibility = View.VISIBLE
|
||||
composerLayout.setRoomEncrypted(state.isEncrypted)
|
||||
} else {
|
||||
composerLayout.visibility = View.GONE
|
||||
showSnackWithMessage("TOMBSTONED", duration = Snackbar.LENGTH_INDEFINITE)
|
||||
}
|
||||
}
|
||||
|
||||
private fun renderRoomSummary(state: RoomDetailViewState) {
|
||||
|
@ -30,12 +30,14 @@ import com.squareup.inject.assisted.AssistedInject
|
||||
import im.vector.matrix.android.api.MatrixCallback
|
||||
import im.vector.matrix.android.api.session.Session
|
||||
import im.vector.matrix.android.api.session.content.ContentAttachmentData
|
||||
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.file.FileService
|
||||
import im.vector.matrix.android.api.session.room.model.Membership
|
||||
import im.vector.matrix.android.api.session.room.model.message.MessageContent
|
||||
import im.vector.matrix.android.api.session.room.model.message.MessageType
|
||||
import im.vector.matrix.android.api.session.room.model.message.getFileUrl
|
||||
import im.vector.matrix.android.api.session.room.model.tombstone.RoomTombstoneContent
|
||||
import im.vector.matrix.android.api.session.room.timeline.TimelineEvent
|
||||
import im.vector.matrix.android.internal.crypto.attachments.toElementToDecrypt
|
||||
import im.vector.matrix.android.internal.crypto.model.event.EncryptedEventContent
|
||||
@ -94,7 +96,7 @@ class RoomDetailViewModel @AssistedInject constructor(@Assisted initialState: Ro
|
||||
init {
|
||||
observeRoomSummary()
|
||||
observeEventDisplayedActions()
|
||||
observeInvitationState()
|
||||
observeSummaryState()
|
||||
cancelableBag += room.loadRoomMembersIfNeeded()
|
||||
timeline.start()
|
||||
setState { copy(timeline = this@RoomDetailViewModel.timeline) }
|
||||
@ -547,7 +549,7 @@ class RoomDetailViewModel @AssistedInject constructor(@Assisted initialState: Ro
|
||||
}
|
||||
}
|
||||
|
||||
private fun observeInvitationState() {
|
||||
private fun observeSummaryState() {
|
||||
asyncSubscribe(RoomDetailViewState::asyncRoomSummary) { summary ->
|
||||
if (summary.membership == Membership.INVITE) {
|
||||
summary.latestEvent?.root?.senderId?.let { senderId ->
|
||||
@ -556,6 +558,13 @@ class RoomDetailViewModel @AssistedInject constructor(@Assisted initialState: Ro
|
||||
setState { copy(asyncInviter = Success(it)) }
|
||||
}
|
||||
}
|
||||
if (summary.isVersioned) {
|
||||
room.getStateEvent(EventType.STATE_ROOM_TOMBSTONE)
|
||||
?.getClearContent()
|
||||
?.toModel<RoomTombstoneContent>()?.also {
|
||||
setState { copy(tombstoneContent = it) }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -20,6 +20,7 @@ import com.airbnb.mvrx.Async
|
||||
import com.airbnb.mvrx.MvRxState
|
||||
import com.airbnb.mvrx.Uninitialized
|
||||
import im.vector.matrix.android.api.session.room.model.RoomSummary
|
||||
import im.vector.matrix.android.api.session.room.model.tombstone.RoomTombstoneContent
|
||||
import im.vector.matrix.android.api.session.room.timeline.Timeline
|
||||
import im.vector.matrix.android.api.session.room.timeline.TimelineEvent
|
||||
import im.vector.matrix.android.api.session.user.model.User
|
||||
@ -46,7 +47,8 @@ data class RoomDetailViewState(
|
||||
val asyncInviter: Async<User> = Uninitialized,
|
||||
val asyncRoomSummary: Async<RoomSummary> = Uninitialized,
|
||||
val sendMode: SendMode = SendMode.REGULAR,
|
||||
val isEncrypted: Boolean = false
|
||||
val isEncrypted: Boolean = false,
|
||||
val tombstoneContent: RoomTombstoneContent? = null
|
||||
) : MvRxState {
|
||||
|
||||
constructor(args: RoomDetailArgs) : this(roomId = args.roomId, eventId = args.eventId)
|
||||
|
@ -0,0 +1,61 @@
|
||||
/*
|
||||
*
|
||||
* * 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.riotx.features.home.room.detail.timeline.factory
|
||||
|
||||
import im.vector.matrix.android.api.permalinks.MatrixPermalinkSpan
|
||||
import im.vector.matrix.android.api.permalinks.PermalinkFactory
|
||||
import im.vector.matrix.android.api.session.events.model.toModel
|
||||
import im.vector.matrix.android.api.session.room.model.create.RoomCreateContent
|
||||
import im.vector.matrix.android.api.session.room.timeline.TimelineEvent
|
||||
import im.vector.riotx.R
|
||||
import im.vector.riotx.core.resources.ColorProvider
|
||||
import im.vector.riotx.core.resources.StringProvider
|
||||
import im.vector.riotx.features.home.room.detail.timeline.TimelineEventController
|
||||
import im.vector.riotx.features.home.room.detail.timeline.item.RoomCreateItem
|
||||
import im.vector.riotx.features.home.room.detail.timeline.item.RoomCreateItem_
|
||||
import me.gujun.android.span.span
|
||||
import javax.inject.Inject
|
||||
|
||||
class RoomCreateItemFactory @Inject constructor(private val colorProvider: ColorProvider,
|
||||
private val stringProvider: StringProvider) {
|
||||
|
||||
fun create(event: TimelineEvent, callback: TimelineEventController.Callback?): RoomCreateItem? {
|
||||
val createRoomContent = event.root.getClearContent().toModel<RoomCreateContent>()
|
||||
?: return null
|
||||
val predecessor = createRoomContent.predecessor ?: return null
|
||||
val roomLink = PermalinkFactory.createPermalink(predecessor.roomId) ?: return null
|
||||
val urlSpan = MatrixPermalinkSpan(roomLink, object : MatrixPermalinkSpan.Callback {
|
||||
override fun onUrlClicked(url: String) {
|
||||
callback?.onUrlClicked(roomLink)
|
||||
}
|
||||
})
|
||||
val textColorInt = colorProvider.getColor(R.color.riot_primary_text_color_light)
|
||||
val text = span {
|
||||
text = stringProvider.getString(R.string.room_tombstone_continuation_description)
|
||||
append("\n")
|
||||
append(
|
||||
stringProvider.getString(R.string.room_tombstone_predecessor_link)
|
||||
)
|
||||
}
|
||||
return RoomCreateItem_()
|
||||
.text(text)
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -33,6 +33,7 @@ class TimelineItemFactory @Inject constructor(private val messageItemFactory: Me
|
||||
private val encryptedItemFactory: EncryptedItemFactory,
|
||||
private val noticeItemFactory: NoticeItemFactory,
|
||||
private val defaultItemFactory: DefaultItemFactory,
|
||||
private val roomCreateItemFactory: RoomCreateItemFactory,
|
||||
private val avatarRenderer: AvatarRenderer) {
|
||||
|
||||
fun create(event: TimelineEvent,
|
||||
@ -45,6 +46,7 @@ class TimelineItemFactory @Inject constructor(private val messageItemFactory: Me
|
||||
when (event.root.getClearType()) {
|
||||
EventType.MESSAGE -> messageItemFactory.create(event, nextEvent, highlight, callback)
|
||||
// State and call
|
||||
EventType.STATE_ROOM_TOMBSTONE,
|
||||
EventType.STATE_ROOM_NAME,
|
||||
EventType.STATE_ROOM_TOPIC,
|
||||
EventType.STATE_ROOM_MEMBER,
|
||||
@ -52,7 +54,8 @@ class TimelineItemFactory @Inject constructor(private val messageItemFactory: Me
|
||||
EventType.CALL_INVITE,
|
||||
EventType.CALL_HANGUP,
|
||||
EventType.CALL_ANSWER -> noticeItemFactory.create(event, highlight, callback)
|
||||
|
||||
// State room create
|
||||
EventType.STATE_ROOM_CREATE -> roomCreateItemFactory.create(event, callback)
|
||||
// Crypto
|
||||
EventType.ENCRYPTION -> encryptionItemFactory.create(event, highlight, callback)
|
||||
EventType.ENCRYPTED -> {
|
||||
@ -66,8 +69,7 @@ class TimelineItemFactory @Inject constructor(private val messageItemFactory: Me
|
||||
|
||||
// Unhandled event types (yet)
|
||||
EventType.STATE_ROOM_THIRD_PARTY_INVITE,
|
||||
EventType.STICKER,
|
||||
EventType.STATE_ROOM_CREATE -> defaultItemFactory.create(event, highlight)
|
||||
EventType.STICKER -> defaultItemFactory.create(event, highlight)
|
||||
|
||||
else -> {
|
||||
//These are just for debug to display hidden event, they should be filtered out in normal mode
|
||||
|
@ -22,6 +22,7 @@ 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.*
|
||||
import im.vector.matrix.android.api.session.room.model.call.CallInviteContent
|
||||
import im.vector.matrix.android.api.session.room.model.tombstone.RoomTombstoneContent
|
||||
import im.vector.matrix.android.api.session.room.timeline.TimelineEvent
|
||||
import im.vector.riotx.R
|
||||
import im.vector.riotx.core.resources.StringProvider
|
||||
@ -37,6 +38,7 @@ class NoticeEventFormatter @Inject constructor(private val stringProvider: Strin
|
||||
EventType.STATE_ROOM_TOPIC -> formatRoomTopicEvent(timelineEvent.root, timelineEvent.getDisambiguatedDisplayName())
|
||||
EventType.STATE_ROOM_MEMBER -> formatRoomMemberEvent(timelineEvent.root, timelineEvent.senderName())
|
||||
EventType.STATE_HISTORY_VISIBILITY -> formatRoomHistoryVisibilityEvent(timelineEvent.root, timelineEvent.getDisambiguatedDisplayName())
|
||||
EventType.STATE_ROOM_TOMBSTONE -> formatRoomTombstoneEvent(timelineEvent.root, timelineEvent.getDisambiguatedDisplayName())
|
||||
EventType.CALL_INVITE,
|
||||
EventType.CALL_HANGUP,
|
||||
EventType.CALL_ANSWER -> formatCallEvent(timelineEvent.root, timelineEvent.getDisambiguatedDisplayName())
|
||||
@ -56,6 +58,7 @@ class NoticeEventFormatter @Inject constructor(private val stringProvider: Strin
|
||||
EventType.CALL_INVITE,
|
||||
EventType.CALL_HANGUP,
|
||||
EventType.CALL_ANSWER -> formatCallEvent(event, senderName)
|
||||
EventType.STATE_ROOM_TOMBSTONE -> formatRoomTombstoneEvent(event, senderName)
|
||||
else -> {
|
||||
Timber.v("Type $type not handled by this formatter")
|
||||
null
|
||||
@ -72,6 +75,10 @@ class NoticeEventFormatter @Inject constructor(private val stringProvider: Strin
|
||||
}
|
||||
}
|
||||
|
||||
private fun formatRoomTombstoneEvent(event: Event, senderName: String?): CharSequence? {
|
||||
return stringProvider.getString(R.string.notice_room_update, senderName)
|
||||
}
|
||||
|
||||
private fun formatRoomTopicEvent(event: Event, senderName: String?): CharSequence? {
|
||||
val content = event.getClearContent().toModel<RoomTopicContent>() ?: return null
|
||||
return if (content.topic.isNullOrEmpty()) {
|
||||
|
@ -39,7 +39,8 @@ object TimelineDisplayableEvents {
|
||||
EventType.ENCRYPTION,
|
||||
EventType.STATE_ROOM_THIRD_PARTY_INVITE,
|
||||
EventType.STICKER,
|
||||
EventType.STATE_ROOM_CREATE
|
||||
EventType.STATE_ROOM_CREATE,
|
||||
EventType.STATE_ROOM_TOMBSTONE
|
||||
)
|
||||
|
||||
val DEBUG_DISPLAYABLE_TYPES = DISPLAYABLE_TYPES + listOf(
|
||||
|
@ -0,0 +1,41 @@
|
||||
/*
|
||||
*
|
||||
* * 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.riotx.features.home.room.detail.timeline.item
|
||||
|
||||
import android.widget.TextView
|
||||
import com.airbnb.epoxy.EpoxyAttribute
|
||||
import com.airbnb.epoxy.EpoxyModelClass
|
||||
import com.airbnb.epoxy.EpoxyModelWithHolder
|
||||
import im.vector.riotx.R
|
||||
import im.vector.riotx.core.epoxy.VectorEpoxyHolder
|
||||
import im.vector.riotx.core.epoxy.VectorEpoxyModel
|
||||
|
||||
@EpoxyModelClass(layout = R.layout.item_timeline_event_create)
|
||||
abstract class RoomCreateItem : VectorEpoxyModel<RoomCreateItem.Holder>() {
|
||||
|
||||
@EpoxyAttribute lateinit var text: CharSequence
|
||||
|
||||
override fun bind(holder: Holder) {
|
||||
holder.description.text = text
|
||||
}
|
||||
|
||||
class Holder : VectorEpoxyHolder() {
|
||||
val description by bind<TextView>(R.id.roomCreateItemDescription)
|
||||
}
|
||||
}
|
@ -101,4 +101,5 @@
|
||||
app:layout_constraintTop_toBottomOf="@+id/roomToolbar"
|
||||
tools:visibility="visible" />
|
||||
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
24
vector/src/main/res/layout/item_timeline_event_create.xml
Normal file
24
vector/src/main/res/layout/item_timeline_event_create.xml
Normal file
@ -0,0 +1,24 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<FrameLayout 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">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/roomCreateItemDescription"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="16dp"
|
||||
android:layout_marginLeft="16dp"
|
||||
android:layout_marginTop="16dp"
|
||||
android:layout_marginBottom="16dp"
|
||||
android:background="@drawable/bg_tombstone_predecessor"
|
||||
android:drawableStart="@drawable/error"
|
||||
android:drawableLeft="@drawable/error"
|
||||
android:drawablePadding="16dp"
|
||||
android:gravity="center|start"
|
||||
android:minHeight="80dp"
|
||||
android:padding="16dp"
|
||||
tools:text="This room is continuation…" />
|
||||
|
||||
</FrameLayout>
|
Reference in New Issue
Block a user