Commit c936a4ab authored by Wilko Manger's avatar Wilko Manger

Show membership changes in chat list

Also remove duplicated handling of events
parent 258ac852
Pipeline #254 passed with stage
in 2 minutes and 55 seconds
......@@ -69,84 +69,12 @@ class ChatEventRemoteSource(private val matrix: Matrix,
if (response != null) {
for (event in response.chunk) {
val json = event.contentAsJsonObject
val id = event.eventId
val sentAt = Date(event.originServerTs)
val sender = User(event.sender,
room.getMember(event.sender)?.name ?: event.sender)
val text = json?.get("formatted_body")?.asString
?: json?.get("body")?.asString
?: ""
val chatEvent = when (event.type) {
EVENT_TYPE_MESSAGE -> {
val msgtype = json?.get("msgtype")?.asString
when (msgtype) {
"m.room.message" -> {
ChatMessage(
id = id,
sentAt = sentAt,
sender = sender,
text = text
)
}
"m.notice" -> {
ChatNotice(
id = id,
sentAt = sentAt,
sender = sender,
text = text
)
}
// TODO: Add yet unhandled cases.
else -> {
ChatMessage(
id = id,
sentAt = sentAt,
sender = sender,
text = text
)
}
}
}
EVENT_TYPE_STATE_ROOM_MEMBER -> {
val membership = json?.get("membership")?.asString
val type = when (membership) {
"invite" -> MemberChangeType.INVITE
"join" -> MemberChangeType.JOIN
"leave" -> MemberChangeType.LEAVE
"ban" -> MemberChangeType.BAN
"knock" -> MemberChangeType.KNOCK
else -> MemberChangeType.KNOCK
}
val subject = User(event.stateKey,
json?.get("displayname")?.asString ?: "")
MemberChangeEvent(
id = id,
sentAt = sentAt,
sender = sender,
subject = subject,
type = type
)
}
else -> {
// TODO: Don't handle
// everything as a message
ChatMessage(
id = id,
sentAt = sentAt,
sender = sender,
text = text
)
}
val chatEvent = event.toChatEvent(room)
if (chatEvent != null) {
it.onNext(chatEvent)
}
it.onNext(chatEvent)
}
} else {
throw NullPointerException("chunk is null")
......@@ -171,15 +99,11 @@ class ChatEventRemoteSource(private val matrix: Matrix,
roomState: RoomState?) {
if (event != null && roomState?.roomId == chatId) {
val message = ChatMessage(
id = event.eventId,
sentAt = Date(event.originServerTs),
sender = User(event.sender,
room.getMember(event.sender)?.name ?: event.sender),
text = event.contentAsJsonObject?.get("body")?.asString ?: ""
)
it.onNext(message)
val chatEvent = event.toChatEvent(room)
if (chatEvent != null) {
it.onNext(chatEvent)
}
}
}
......
......@@ -20,7 +20,9 @@ package im.pattle.app.data.chat.event.model
import im.pattle.app.data.chat.overview.ChatOverview
import im.pattle.app.data.user.User
import org.matrix.androidsdk.data.Room
import org.matrix.androidsdk.data.cryptostore.db.hash
import org.matrix.androidsdk.rest.model.Event
import java.util.*
abstract class ChatEvent {
......@@ -38,4 +40,111 @@ abstract class ChatEvent {
override fun hashCode(): Int {
return id.hashCode()
}
}
/**
* Convert an SDK event to an [ChatEvent].
*/
fun Event.toChatEvent(room: Room): ChatEvent? {
val json = this.contentAsJsonObject
val id = this.eventId
val sentAt = Date(this.originServerTs)
val sender = User(this.sender,
room.getMember(this.sender)?.name ?: this.sender)
val text = json?.get("formatted_body")?.asString
?: json?.get("body")?.asString
?: ""
return when (type) {
Event.EVENT_TYPE_MESSAGE -> {
val msgtype = json?.get("msgtype")?.asString
when (msgtype) {
"m.room.message" -> {
ChatMessage(
id = id,
sentAt = sentAt,
sender = sender,
text = text
)
}
"m.notice" -> {
ChatNotice(
id = id,
sentAt = sentAt,
sender = sender,
text = text
)
}
// TODO: Add yet unhandled cases.
else -> {
ChatMessage(
id = id,
sentAt = sentAt,
sender = sender,
text = text
)
}
}
}
Event.EVENT_TYPE_STATE_ROOM_MEMBER -> {
val membership = json?.get("membership")?.asString
val type = when (membership) {
"invite" -> MemberChangeType.INVITE
"join" -> MemberChangeType.JOIN
"leave" -> MemberChangeType.LEAVE
"ban" -> MemberChangeType.BAN
"knock" -> MemberChangeType.KNOCK
else -> MemberChangeType.KNOCK
}
val subject = User(this.stateKey,
json?.get("displayname")?.asString ?: "")
MemberChangeEvent(
id = id,
sentAt = sentAt,
sender = sender,
subject = subject,
type = type
)
}
Event.EVENT_TYPE_TYPING -> {
val userIds = contentAsJsonObject
?.getAsJsonArray("user_ids")
val users = mutableListOf<User>()
if (userIds != null) {
for (userId in userIds) {
val id = userId.asString
users.add(User(
id,
name = room.getMember(id)?.name ?: id)
)
}
TypingEvent(users)
} else {
null
}
}
Event.EVENT_TYPE_MESSAGE_ENCRYPTED -> {
EncryptedChatMessage(
id = eventId,
sentAt = sentAt,
sender = sender
)
}
else -> {
object : ChatEvent() {
override val id = eventId
override val sentAt = sentAt
override val sender = sender
}
}
}
}
\ No newline at end of file
......@@ -20,10 +20,7 @@ package im.pattle.app.data.chat.overview
import android.content.Context
import android.util.Log
import im.pattle.app.data.chat.event.model.ChatEvent
import im.pattle.app.data.chat.event.model.TypingEvent
import im.pattle.app.data.chat.event.model.ChatMessage
import im.pattle.app.data.chat.event.model.EncryptedChatMessage
import im.pattle.app.data.chat.event.model.*
import im.pattle.app.data.sync.SyncManager
import im.pattle.app.data.user.User
import im.pattle.app.sdk.Matrix
......@@ -46,68 +43,6 @@ class ChatOverviewRemoteSource(private val matrix: Matrix,
return matrix.waitForInitialSync().andThen(
Flowable.create<ChatOverview>({
/**
* Convert an SDK event to an [ChatOverviewEvent].
*/
fun Event.toChatEvent(): ChatEvent? {
val room = matrix.dataHandler.store.getRoom(roomId)
val sentAt = Date(originServerTs)
val sender = this.sender ?: this.userId
val user = if (sender != null) User(sender,
room.getMember(sender)?.name
?: sender)
else null
val json = contentAsJsonObject
val body = json?.get("formatted_body")?.asString
?: json?.get("body")?.asString
?: ""
return when (type) {
Event.EVENT_TYPE_MESSAGE -> ChatMessage(
id = eventId,
sentAt = sentAt,
sender = user!!,
text = body)
Event.EVENT_TYPE_TYPING -> {
val userIds = contentAsJsonObject
?.getAsJsonArray("user_ids")
val users = mutableListOf<User>()
if (userIds != null) {
for (userId in userIds) {
val id = userId.asString
users.add(User(
id,
name = room.getMember(id)?.name ?: id)
)
}
TypingEvent(users)
} else {
null
}
}
Event.EVENT_TYPE_MESSAGE_ENCRYPTED -> {
EncryptedChatMessage(
id = eventId,
sentAt = sentAt,
sender = user!!
)
}
else -> {
object : ChatEvent() {
override val id = eventId
override val sentAt = sentAt
override val sender = user
}
}
}
}
for (room in matrix.dataHandler.store.rooms) {
if (!room.isEncrypted) {
......@@ -117,7 +52,7 @@ class ChatOverviewRemoteSource(private val matrix: Matrix,
val unreadCount = room.notificationCount
val latestRoomEvent = room.roomSummary?.latestReceivedEvent
val lastEvent = latestRoomEvent?.toChatEvent()
val lastEvent = latestRoomEvent?.toChatEvent(room)
val chat = ChatOverview(
id = id,
......@@ -137,7 +72,7 @@ class ChatOverviewRemoteSource(private val matrix: Matrix,
if (event != null && roomState != null) {
val room = matrix.dataHandler.getRoom(roomState?.roomId)
val lastEvent = event.toChatEvent()
val lastEvent = event.toChatEvent(room)
val overview = roomState.toChatOverview(lastEvent, room.isDirect)
......
......@@ -140,29 +140,7 @@ class ChatEventAdapter(private val isDirect: Boolean,
is MemberChangeEvent -> {
holder as InfoHolder
val text = when(item.type) {
MemberChangeType.INVITE -> {
context.getString(R.string.invited,
item.sender.toString(),
item.subject.toString())
}
MemberChangeType.JOIN -> {
context.getString(R.string.has_joined,
item.subject.toString())
}
MemberChangeType.LEAVE -> {
context.getString(R.string.has_left,
item.subject.toString())
}
MemberChangeType.BAN -> {
context.getString(R.string.banned,
item.subject.toString(),
item.sender.toString())
}
MemberChangeType.KNOCK -> "Knock, knock."
}
holder.layout.title.text = text
holder.layout.title.text = item.displayString(context)
}
// TODO: Remove pasted code
......
......@@ -33,12 +33,10 @@ import im.pattle.app.R
import im.pattle.app.data.chat.event.model.TypingEvent
import im.pattle.app.data.chat.event.model.ChatMessage
import im.pattle.app.data.chat.event.model.EncryptedChatMessage
import im.pattle.app.data.chat.event.model.MemberChangeEvent
import im.pattle.app.data.chat.overview.ChatOverview
import im.pattle.app.data.user.User
import im.pattle.app.ui.util.ChangeableAdapter
import im.pattle.app.ui.util.ImageLoader
import im.pattle.app.ui.util.formatAsListItem
import im.pattle.app.ui.util.fromHtml
import im.pattle.app.ui.util.*
import kotlinx.android.synthetic.main.list_item_chat_overview.view.*
import org.jetbrains.anko.sdk25.coroutines.onClick
import java.util.*
......@@ -146,6 +144,9 @@ class ChatOverviewAdapter(private val onClick: (ChatOverview) -> Unit,
0)
holder.layout.subtitle.text = span
}
is MemberChangeEvent -> {
holder.layout.subtitle.text = chat.lastEvent.displayString(context)
}
else -> {
// TODO: Actually handle this
holder.layout.subtitle.text = chat.lastEvent.id
......
package im.pattle.app.ui.util
import android.content.Context
import im.pattle.app.R
import im.pattle.app.data.chat.event.model.MemberChangeEvent
import im.pattle.app.data.chat.event.model.MemberChangeType
/**
* File for determining UI strings for models.
*/
/**
* Get string to display a [MemberChangeEvent] in the UI.
*/
fun MemberChangeEvent.displayString(context: Context): String {
return when(type) {
MemberChangeType.INVITE -> {
context.getString(R.string.invited,
sender.toString(),
subject.toString())
}
MemberChangeType.JOIN -> {
context.getString(R.string.has_joined,
subject.toString())
}
MemberChangeType.LEAVE -> {
context.getString(R.string.has_left,
subject.toString())
}
MemberChangeType.BAN -> {
context.getString(R.string.banned,
subject.toString(),
sender.toString())
}
MemberChangeType.KNOCK -> "Knock, knock."
}
}
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment